ReviewOS

also looking at this

stacks/postline

Single-user auth: login, first-run registration, page + API gates

#11
Merged glennmichael123 wants to merge feat/auth into main
9 files +254 -22
8 days ago

Summary

Postline was fully open — every page and /postline API route. This gates the whole app behind a single-user account, making it deployable.

Flow

  • First run: /login offers "Create the workspace account" → RegisterFirstUserAction creates the one account and returns a token. The endpoint returns 403 forever after, so strangers can't register on a deployed instance.
  • Sign in: POST /login (framework LoginAction, declared in routes/api.ts since the framework's copy lives in the feature-gated dashboard bundle this app doesn't load). The token is stored in the auth-token cookie.
  • Sign out: button on Settings clears the cookie.

Enforcement

  • Pages: stx-serve protectedPaths server-redirects queue/timeline/analytics/accounts/settings to /login; a client-side layout guard covers / (a / prefix rule would also match /login and loop). The public blog stays open.
  • API: auth middleware on every /postline route except the LinkedIn/Instagram/Threads OAuth redirect endpoints (hit by providers without a bearer).
  • Bridge: the frontend's /api proxy injects Authorization: Bearer <cookie> when absent, so all existing client fetches work unchanged — no Authorization plumbing in page scripts. The API remains the security boundary.

Fixes along the way

  • users table migration (was missing entirely)
  • @stacksjs/auth build emitted declarations under dist/src/ leaving no dist/index.d.ts (TS7016 for any consumer) — dts root now matches the other packages; auth added to the framework-types build list

Verification (browser + curl, end to end)

  • Unauthenticated / and /queue → redirect to /login; API unauthenticated → 401
  • First-run register → lands authenticated, provider toggles load through the cookie→bearer bridge
  • Second register attempt → 403 "workspace already has an account"
  • Sign in with correct password → token pair; wrong password → 401; sign out → gates re-engage
  • pickier clean, tsc --noEmit exit 0
  • Test account removed afterward — the DB ships in first-run state

9 changed files on the files tab, with 0 review threads.

Sign in to comment on this pull request.