Auth boundary: public reads, owner mutations, admin API tier #12

Merged
arne merged 18 commits from auth-admin-htmx-roadmap into main 2026-04-13 13:35:09 +02:00
Owner

Summary

First of three roadmap changes (auth boundary, admin API, htmx). Splits the site into five auth tiers:

  • visitor — library, book detail, author, series are now public
  • user — any OIDC-authenticated identity can download /file/{uuid}
  • owner — shelve/edit/delete/upload/errata require the owner sub
  • kobo — existing token-in-URL flow untouched
  • admin — new /api/admin/* surface behind Authorization: Bearer $BOOKS_ADMIN_TOKEN (placeholder endpoints; real operations land in spec 2)

Specs and roadmap notes live in docs/superpowers/.

Test plan

  • Visit https://books.fismen.no in a private window → library loads without login
  • Log in and confirm shelf, edit, upload, delete still work
  • curl /api/admin/books → 401
  • curl -H "Authorization: Bearer \$BOOKS_ADMIN" /api/admin/books → 404 (placeholder)
## Summary First of three roadmap changes (auth boundary, admin API, htmx). Splits the site into five auth tiers: - **visitor** — library, book detail, author, series are now public - **user** — any OIDC-authenticated identity can download `/file/{uuid}` - **owner** — shelve/edit/delete/upload/errata require the owner sub - **kobo** — existing token-in-URL flow untouched - **admin** — new `/api/admin/*` surface behind `Authorization: Bearer $BOOKS_ADMIN_TOKEN` (placeholder endpoints; real operations land in spec 2) Specs and roadmap notes live in `docs/superpowers/`. ## Test plan - [ ] Visit https://books.fismen.no in a private window → library loads without login - [ ] Log in and confirm shelf, edit, upload, delete still work - [ ] `curl /api/admin/books` → 401 - [ ] `curl -H "Authorization: Bearer \$BOOKS_ADMIN" /api/admin/books` → 404 (placeholder)
arne added 18 commits 2026-04-13 13:35:05 +02:00
Captures the three intersecting ideas — auth boundary redesign, admin
API, htmx migration — and the order they'll be tackled in. Each gets
its own spec; this note just keeps them from being lost.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
First of three roadmap specs. Defines five auth tiers (visitor, user,
owner, kobo, admin), classifies every route, and specifies the
middleware, viewer plumbing, and rollout for splitting public read
access from owner-only mutations and a bearer-token admin path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
14 tasks covering: config rename, Viewer + tier-specific middleware,
template gating, 403 page, per-tier integration tests, and the
production deploy with env updates.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaces AllowedSub with OwnerSub for owner-level access control in middleware.
Adds AdminToken field for /api/admin/* bearer token auth. Removes subject check
from ExchangeCode (any verified OIDC subject is allowed); tier resolution now
happens in middleware. Updates User struct with IsOwner field set in middleware.
Updates test helper newTestAuth and patches temporary references in middleware.go
and main.go for bridging during this refactor phase.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- RequireOwner now stores Viewer in context before invoking the
  forbidden handler, so InstallForbiddenHandler doesn't redo the
  session lookup.
- TestRoutes_AuthTier now exercises two owner POST routes with a
  matching Origin header, so RequireOwner cannot silently regress to
  CSRF-only protection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
arne merged commit 442b6363a6 into main 2026-04-13 13:35:09 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
arne/books!12
No description provided.