Authorization middleware with explicit public allowlist (#10) #36
No reviewers
Labels
No labels
area:auth
area:ci
area:db
area:infra
area:native
area:pwa
area:service
epic
feature
foundation
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
james/carol!36
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "10-authorization-middleware"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #10.
Summary
middleware.tsat the project root — rejects every request without a session, except routes in the public allowlist.lib/auth/public-routes.ts— the single source of truth for what's reachable without auth./api/healthis the only exact public route;/api/auth/*is pre-registered for #12's OAuth callbacks. Adding a new public route is a one-file change that has to go through PR review.lib/auth/session.ts— placeholder session check (presence ofcarol_sessioncookie). Real validation lands with #11; the function is the only place that needs to change at that point.tests/middleware.test.tscovering both the policy (middleware()returns 401 / passes through) and the allowlist matcher (isPublicRouteexact + prefix semantics).Two stack choices worth flagging
middleware.tstriggers Next.js to compile for the edge runtime, which can't resolvefs/paththatpguses transitively viainstrumentation.ts → db. Carol is a self-hosted Node service — edge runtime buys nothing for a single-instance deployment. Enabledexperimental.nodeMiddleware: trueinnext.config.mjsandruntime: "nodejs"in the middleware config. Experimental flag, but Next.js's intent is to graduate it.@/*path alias. New tests import from@/lib/auth/...; vitest doesn't read tsconfig paths by default, so added a matchingresolve.aliasinvitest.config.ts. Existing tests using relative imports continue to work.End-to-end verification (production standalone server)
GET /api/healthGET /(no session){"error":"Unauthorized"}GET /(carol_session=...)GET /api/some-thing(no session)GET /api/auth/callback/github(no session)Out of scope
UI-friendly redirect-to-login. There is no sign-in page until #11, so a redirect target doesn't exist. The middleware returns JSON 401 for both API and UI requests today; swapping in a redirect is a one-line change when the page arrives.
Test plan
npm run lint/typecheck/build— cleannpm test— 25 pass, 5 skip (the Postgres-skip is unrelated to this PR).next/standalone/server.js— every row in the table above