v1.1.0: session guard on all game routes + register + sign-in screen (ISS-107) #152

Merged
kamilkrzywda merged 2 commits from feat/multiplayer-auth-guard into master 2026-09-26 17:43:19 +02:00
Owner

Multiplayer step 3/12 (ISS-107).

  • lib/auth.ts: shared guards — requireAuth(req) (X-Flight-Session header) and requireAuthSse(req) (header OR ?session=, since EventSource cannot set headers). Returns {ok, inst, user, player} or a ready-made 401/500; joins players on username (seeded admin → local row), missing players row → 500.
  • Guarded: /api/state, all eight action routes via one performAction(req, fn) call site in lib/game/actions.ts, and the SSE stream (connect-time validation).
  • Exempt by design: version/openapi/airports/login/register/logout/me, admin CRUD (own guard), all /api/test/* hooks.
  • New POST /api/register: strict body validation, username lowercased + [a-z0-9_-]{3,20}, password ≥8, 409 taken; creates users+players rows sharing one UUID with the starter economy and mints a session immediately (no second round-trip).
  • UI: new components/SignInScreen.tsx (sign in / create account); app/page.tsx gates the shell on it — unauthenticated browsers never poll /api/state. New client module lib/authClient.ts owns the localStorage key + header; every app fetch carries X-Flight-Session. Admin logout drops back to sign-in via a new onLogout prop.
  • E2E: new test-only POST /api/test/mint-player-session (FLIGHT_TEST_HOOKS=1, idempotent); e2e/auth.ts mints+applies per test; all guarded-route specs authenticate in beforeEach; events.spec uses the real ?session= path; api/openapi tests track the 18th endpoint; admin spec reworked for the sign-in gate.
  • Tests: new lib/auth.test.ts, register + mint-hook route tests; existing state/events/action route tests mint a session in beforeAll. OpenAPI documents /api/register (RegisterRequest schema).

Local verification: tsc --noEmit clean · vitest run 426/426 · playwright test --list 64 specs compile.

Multiplayer step 3/12 (ISS-107). - `lib/auth.ts`: shared guards — `requireAuth(req)` (X-Flight-Session header) and `requireAuthSse(req)` (header OR ?session=, since EventSource cannot set headers). Returns `{ok, inst, user, player}` or a ready-made 401/500; joins players on username (seeded admin → local row), missing players row → 500. - Guarded: `/api/state`, all eight action routes via one `performAction(req, fn)` call site in `lib/game/actions.ts`, and the SSE stream (connect-time validation). - Exempt by design: version/openapi/airports/login/register/logout/me, admin CRUD (own guard), all /api/test/* hooks. - New POST `/api/register`: strict body validation, username lowercased + `[a-z0-9_-]{3,20}`, password ≥8, 409 taken; creates users+players rows sharing one UUID with the starter economy and mints a session immediately (no second round-trip). - UI: new `components/SignInScreen.tsx` (sign in / create account); `app/page.tsx` gates the shell on it — unauthenticated browsers never poll `/api/state`. New client module `lib/authClient.ts` owns the localStorage key + header; every app fetch carries X-Flight-Session. Admin logout drops back to sign-in via a new onLogout prop. - E2E: new test-only POST /api/test/mint-player-session (FLIGHT_TEST_HOOKS=1, idempotent); `e2e/auth.ts` mints+applies per test; all guarded-route specs authenticate in beforeEach; events.spec uses the real ?session= path; api/openapi tests track the 18th endpoint; admin spec reworked for the sign-in gate. - Tests: new lib/auth.test.ts, register + mint-hook route tests; existing state/events/action route tests mint a session in beforeAll. OpenAPI documents /api/register (RegisterRequest schema). Local verification: `tsc --noEmit` clean · `vitest run` 426/426 · `playwright test --list` 64 specs compile.
kamilkrzywda added 1 commit 2026-09-26 16:41:33 +02:00
kamilkrzywda scheduled this pull request to auto merge when all checks succeed 2026-09-26 16:42:55 +02:00
kamilkrzywda added 1 commit 2026-09-26 17:28:56 +02:00
fix: add missing sign-in input testids (ISS-107) CI
CI / build + unit + e2e (pull_request) Successful in 14m20s
81ba642ec5
kamilkrzywda merged commit ba2c36a3f8 into master 2026-09-26 17:43:19 +02:00
kamilkrzywda deleted branch feat/multiplayer-auth-guard 2026-09-26 17:43:19 +02:00
Sign in to join this conversation.