Lets the photographer edit config/site.json from /dashboard instead
of SSHing in and hand-editing the file. Two tiers:
- Quick-edit form for the fields actually touched day to day (site
title/tagline/hero, photographer bio, contact/social, Venmo
username, session pricing, theme colors)
- Raw JSON textarea for everything else (portfolio categories,
locations, session types, Immich settings) - the form's fields are
a subset of this, not a separate source of truth
Backend: GET/PUT /api/admin/config, gated by the existing requireAdmin
middleware (OIDC admin session or legacy ADMIN_SECRET). PUT validates
the body is an object with the required top-level sections, writes
atomically (temp file + rename), and keeps one prior version as
site.json.bak before overwriting.
Required a docker-compose.yml change: the api service had no volume
mount for config/ at all before this (only portfolio/nginx did, and
read-only) - added a read-write mount so the API can actually write
the file the live site reads.
- api/auth.js: zero-dep OIDC authorization-code flow with PKCE against
Authentik; HMAC-signed HttpOnly session cookies (SESSION_SECRET)
- requireAdmin now accepts an OIDC session in the admin group; legacy
ADMIN_SECRET bearer kept for n8n and scripts
- New client endpoints: GET /api/my-bookings, owner-gated contract download
- Bookings created while signed in are bound to the client's OIDC sub
- Dashboard: "Sign in with SSO" alongside passphrase fallback
- New /my-bookings portal page (nginx route + themed page)
- Fix booking modal: content area now scrolls; nav no longer overlaps the
calendar on short viewports (was swallowing clicks on date cells)
- 10 new Playwright tests; suite green at 67
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>