fix(web): /register reachable for bootstrap admin (closes #376) #32

Merged
bvandeusen merged 262 commits from dev into main 2026-05-08 18:01:39 -04:00
bvandeusen commented 2026-05-08 18:00:09 -04:00 (Migrated from git.fabledsword.com)

Summary

Production deploy hit a chicken-and-egg bootstrap blocker: the +layout.svelte auth guard only treated /login as a public route, so any unauthenticated visit to /register got bounced to /login?returnTo=%2Fregister and the "Register" link on the login page looped back to itself. The first-user-becomes-admin path (handleRegister + CreateUserFirstAdminRace) was therefore unreachable without direct DB surgery.

This PR adds /register to the public-route allowlist and closes the last gap on user-mgmt umbrella #376.

Changes

  • New web/src/lib/auth/publicRoutes.tsisPublicRoute() helper with /login + /register as the public set. Single source of truth so future auth-guard changes don't require touching +layout.svelte.
  • Updated web/src/routes/+layout.svelte — guard now calls isPublicRoute(path) instead of an inline path === '/login' check.
  • New web/src/lib/auth/publicRoutes.test.ts — six unit tests, including an explicit comment-tagged regression guard for the /register case so this can't silently regress.

Test plan

  • CI runs vitest on publicRoutes.test.ts
  • Operator: pull the resulting image, browse to https://minstrel.fabledsword.com/register while logged out, register a fresh user, confirm is_admin = true on first user
  • Operator: with a session, browse to /register and confirm the redirect to / still fires (authenticated user shouldn't see the form)

Notes

  • Production also needs HTTPS (or localhost) for the SPA to load at all — crypto.randomUUID is gated to secure contexts and SvelteKit's client runtime calls it. Operator already moved minstrel.fabledsword.com behind TLS while diagnosing this; documenting here for the next operator.
  • Fable #376 marked done with closeout notes covering shipped surface, the SMTP-blocked forgot-password carve-out, and this regression.
## Summary Production deploy hit a chicken-and-egg bootstrap blocker: the `+layout.svelte` auth guard only treated `/login` as a public route, so any unauthenticated visit to `/register` got bounced to `/login?returnTo=%2Fregister` and the "Register" link on the login page looped back to itself. The first-user-becomes-admin path (`handleRegister` + `CreateUserFirstAdminRace`) was therefore unreachable without direct DB surgery. This PR adds `/register` to the public-route allowlist and closes the last gap on user-mgmt umbrella **#376**. ## Changes - **New** `web/src/lib/auth/publicRoutes.ts` — `isPublicRoute()` helper with `/login` + `/register` as the public set. Single source of truth so future auth-guard changes don't require touching `+layout.svelte`. - **Updated** `web/src/routes/+layout.svelte` — guard now calls `isPublicRoute(path)` instead of an inline `path === '/login'` check. - **New** `web/src/lib/auth/publicRoutes.test.ts` — six unit tests, including an explicit comment-tagged regression guard for the `/register` case so this can't silently regress. ## Test plan - [x] CI runs vitest on `publicRoutes.test.ts` - [ ] Operator: pull the resulting image, browse to `https://minstrel.fabledsword.com/register` while logged out, register a fresh user, confirm `is_admin = true` on first user - [ ] Operator: with a session, browse to `/register` and confirm the redirect to `/` still fires (authenticated user shouldn't see the form) ## Notes - Production also needs HTTPS (or `localhost`) for the SPA to load at all — `crypto.randomUUID` is gated to secure contexts and SvelteKit's client runtime calls it. Operator already moved `minstrel.fabledsword.com` behind TLS while diagnosing this; documenting here for the next operator. - Fable #376 marked done with closeout notes covering shipped surface, the SMTP-blocked forgot-password carve-out, and this regression.
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: bvandeusen/minstrel#32