Commit Graph

799 Commits

Author SHA1 Message Date
8636dfedb9 Replace go-imap library with custom IMAP client, simplify CV layout styles, bump vite, move SEED_DB to backend
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 5m19s
- Rewrite email_imap.go to use a minimal hand-rolled IMAP client instead of go-imap/go-message,
  for better compatibility with Outlook's non-standard responses
- Consolidate and simplify CVLayout.vue CSS overrides
- Bump vite from 7.1.11 to 7.3.2
- Move SEED_DB env var from nginx to backend in dev compose
- Add /app/src/wasm volume exclusion in dev compose

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-18 08:53:34 +01:00
c20b1c2691 Fix CV layout colors: force transparent bg on links, inherit color on td/textarea
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 11m24s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-18 08:14:47 +01:00
0b6ffedb70 Add padding below headers in Listening/Steam and adjust layout sizing
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 27s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 02:57:54 +01:00
a14b78a1b9 Add CreateBookmark form with toggle in Bookmarks header
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 25s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 02:51:51 +01:00
254541a370 Center ToggleHeader button vertically in LinkTable
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 20s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 02:49:38 +01:00
f390bf82cc Resize bookmark headers
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 20s
2026-04-16 00:42:53 +01:00
b96b7d7a93 Split schema.graphql and schema.resolvers.go into per-domain files
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m36s
Move Query/Mutation field declarations from the monolithic schema.graphql
into each domain's .graphql file using extend type, so gqlgen places
resolvers in the matching *.resolvers.go files. Extract helper functions
into *_helpers.go files to prevent gqlgen from commenting them out.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 18:57:23 +01:00
37171478b1 refactored code, removed *_helper.go files and placed them in *.resolvers.go files for uniformity
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m23s
2026-04-15 18:33:19 +01:00
00364aca23 Fix nginx stale DNS caching causing backend to appear down after restarts
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 22s
Use Docker's embedded DNS resolver (127.0.0.11) with nginx variables in
proxy_pass directives so upstream hostnames are re-resolved at runtime
instead of being cached forever at startup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 16:29:50 +01:00
3d97ccf38c Switch IMAP library from go-imap/v2 to v1 for Outlook compatibility
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 4m16s
go-imap/v2's strict wire parser rejects Outlook's non-standard IMAP
login responses. v1 is more lenient and handles these gracefully.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 14:16:04 +01:00
1e22bacdc9 Add email sync service for automated job application tracking
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 4m40s
Background poller fetches emails via IMAP or Microsoft Graph API,
classifies them with Claude Haiku, and creates/updates JobApplication
records automatically. Includes manual sync endpoint and OAuth callback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 13:59:24 +01:00
8d10f75f2b Move bookmarks to home folder, reduce header size and fix import link
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 28s
2026-04-14 17:31:53 +01:00
68dca953f2 Restore JS scroll animations, move WASM AutoScroll to util/wasm/
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 17s
Revert AutoScroll and Headline components to their original JS
requestAnimationFrame implementations. Keep the WASM-based AutoScroll
as an alternative at util/wasm/AutoScroll.vue.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 16:53:32 +01:00
c684fcb858 Reduce toggle button size by half
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 22s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 16:49:37 +01:00
2b5745b946 Move scroll animations to Rust/WASM, enable Hasura, and move bookmarks to home sidebar
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 12m7s
Port AutoScroll and Headline scroll logic from Vue/JS to Rust compiled
to WASM via wasm-pack. Add multi-stage Docker build for WASM compilation,
Vite WASM plugins, and top-level await for WASM init. Enable Hasura
service in docker-compose. Move bookmarks from a separate route to an
inline sidebar component on the home page. Fix ToggleHeader click
propagation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 16:34:24 +01:00
b56f8253d9 Harden backend against critical and high security vulnerabilities
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m51s
- Fix WebSocket CheckOrigin to use proper url.Parse instead of string stripping
- Add admin auth checks to Users/User GraphQL queries
- Remove GraphQL GET transport to prevent CSRF via cross-site links
- Add application-level IP-based login rate limiting (5 attempts/min)
- Add path traversal bounds check on radio file upload
- Require DEV_MODE for GraphQL introspection and playground
- Move notes backend endpoint behind admin middleware
- Add dedicated Nginx rate limit zone for GraphQL (10r/s)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 13:27:33 +01:00
798c8e7f50 Fix horizontal scrollbar and style slim themed scrollbars for Chrome/Edge
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 22s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 13:18:13 +01:00
0e7f34edc7 Update README with recent features and route changes
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m34s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 11:08:42 +01:00
7aff171ef8 Remove REST handlers superseded by GraphQL resolvers
Some checks failed
Deploy with Docker Compose / deploy (push) Has been cancelled
Deleted handle_activity.go, handle_favorites.go, handle_post.go, and
handle_user.go — all logic already exists in schema.resolvers.go.
Removed corresponding REST routes from main.go. Moved UserCredentials
struct (used by Login handler) into handle_auth.go.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 11:08:09 +01:00
cc6a423ef0 Add backend healthcheck and autoheal for automatic restart
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 19s
Adds a Docker healthcheck to the backend service (polling GET / every 30s)
and the willfarrell/autoheal container to automatically restart any unhealthy containers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 10:59:48 +01:00
759614e92d Add job application quick reference for storing profile links and experience
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m34s
Auth-protected CRUD for personal info (LinkedIn, GitHub, etc.) and
experience entries, stored in the database so nothing sensitive is in
the public repo. Displayed as a categorized panel on the Job Applications page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 12:38:53 +01:00
81c5684102 Fix appliedAt date format to RFC3339 for GraphQL mutations
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 15s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 12:34:12 +01:00
a911e6ca69 Add inline admin create forms to home page components
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 28s
Lazy-load create forms (Post, Activity, Favorite, Rowing) directly
into their corresponding home components with an admin-only toggle
button, replacing the need to navigate to the admin page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 12:13:13 +01:00
66f32cdbd2 Add database-backed bookmarks via GraphQL
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m47s
Replace hardcoded bookmarks in the frontend with a GORM-backed Bookmark
model exposed through GraphQL query and admin-only create/delete mutations.
Frontend groups bookmarks by category dynamically from the store.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 12:04:13 +01:00
390f69858c Redirect to original URL after admin login
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m49s
Pass the requested URI as ?redirect= when nginx denies access, so the
login page can forward the user to their intended destination on success.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 11:55:42 +01:00
c3db00abf2 Fix logout not clearing cookies due to missing path and domain
Some checks failed
Deploy with Docker Compose / deploy (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 11:53:42 +01:00
4a0300d4b4 Fix auth guard watcher to use Vue 3 watch instead of $watch
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 19s
$watch is a Vue 2 instance method not available on Pinia stores.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 11:48:27 +01:00
18b50f1ce6 Split admin login into its own route and add auth guard to /admin
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 28s
- Add /admin/login route for Login.vue as a standalone page
- Add requiresAdmin guard to /admin route
- Update auth guard redirect to /admin/login with redirect query param
- Update nginx @auth_denied to redirect to /admin/login
- Remove Login component from Admin.vue; drop v-if auth checks (guard handles access)
- Remove stale view files from old views/ structure (moved in prior commit)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 11:19:10 +01:00
4d154ff837 Reorganise views/ directory structure to match routes
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 16s
Move shrines and bookmarks under home/, landing and 404 into own
subdirectories, and retire Notes.vue (served by external service).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 11:15:46 +01:00
869d9a168e Move admin auth guard to Vue Router
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 24s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 11:09:12 +01:00
fc9d3c97bf Add Jobs link to CV and fix auth race on job applications page
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 19s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 11:03:00 +01:00
0dc1c278c2 Move job applications to /cv/jobs route and add layout system
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m41s
- Add DefaultLayout and CVLayout with nested routing
- Job applications is now a standalone page at /cv/jobs with a back link
- Remove JobApplications embed from CV.vue

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 10:09:22 +01:00
a0f99d9fba Add CSV export to job applications tracker
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m29s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 09:53:30 +01:00
8f3c369ed8 Add job application tracker (admin-only)
Some checks failed
Deploy with Docker Compose / deploy (push) Has been cancelled
Full CRUD GraphQL API for tracking job applications with status workflow.
Frontend component in CV view, hidden from print. Login now redirects to
intended route after auth via query param.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 09:51:31 +01:00
81f5fafb61 Redirect auth-denied users to /admin login page instead of homepage
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 23s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 22:05:22 +01:00
c335bf14d6 Add token refresh to ValidateAdmin for seamless session renewal
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m55s
When the access token is missing or expired, the handler now falls back
to the refresh token, verifies the user is still admin via DB lookup,
and issues fresh cookies in the subrequest response.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 21:35:45 +01:00
d344497393 Gate searxng, notes, and hasura behind admin auth via nginx auth_request
Some checks failed
Deploy with Docker Compose / deploy (push) Has been cancelled
Add ValidateAdmin endpoint that checks JWT admin claim for use as an
nginx auth_request subrequest. Widen cookie path from backend endpoint
to "/" so the access_token is sent on all paths. Extend access token
lifetime from 24h to 7 days. Disable hasura service by default via
Docker profile.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 21:33:41 +01:00
ee97ec9b23 Pin app-network subnet to match trusted proxy CIDR
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 38s
Gin's trusted proxies list is hardcoded to 172.28.0.0/16, but Docker was
assigning the bridge network whatever subnet was free, so c.ClientIP()
often returned nginx's container IP instead of the real client.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 00:43:29 +01:00
34934e7d13 Enable gin release mode outside dev
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m53s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 00:38:44 +01:00
1d472d382b Remove padding beneath header
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 15s
2026-04-08 01:33:26 +01:00
4ebe886579 Remove padding beneath header
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 24s
2026-04-08 01:32:02 +01:00
dd5412cb79 Fix sidebar on mobile
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 15s
2026-04-08 01:30:03 +01:00
4000baf755 Fix mobile heights
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 20s
2026-04-08 01:26:00 +01:00
a15aa040f4 Remove horizontal side-scrolling on Home page
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 5m35s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 00:35:17 +01:00
a03cce3e04 Comment on AI slop and fix ai slop
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 7s
2026-04-07 16:46:31 +01:00
400d100426 Consolidate readme.md and README.md into single comprehensive README
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 7s
Merges both files and adds full endpoint reference, .env variable table,
setup guides (Spotify, Certbot, Obsidian/Quartz, Icecast), deprecated
endpoint notes, and updated architecture with all services.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 16:16:37 +01:00
7afd1be81b Add Gitea entrypoint to generate app.ini from template on startup
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 6s
Since app.ini is gitignored, the container needs to create it at
runtime. The entrypoint copies the template on first start, then
Gitea's env var overrides handle secrets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 14:40:38 +01:00
cdcef5ba96 Gitignore gitea app.ini and remove INTERNAL_TOKEN from template
Runtime config (app.ini) should not be tracked since secrets are
injected via env vars in docker-compose. The template remains as
source of truth. INTERNAL_TOKEN is removed from the template as
it is set exclusively via GITEA__security__INTERNAL_TOKEN env var.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 14:37:30 +01:00
494f61f9c6 Reduce secret syncing to just .env
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 7s
Strip hardcoded secrets from gitea/config/app.ini (already injected
via GITEA__ env vars) and commit it to git. Add download.sh to fetch
the act_runner binary on demand instead of syncing it. Everything else
(searxng settings, certbot certs, runner registration, Spotify tokens)
is generated at runtime.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 14:22:50 +01:00
67771777cd Fix searxng upstream entrypoint path
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 10s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 14:11:39 +01:00