9 Commits
Author SHA1 Message Date
Lucas Berger 1f94dc5eb7 feat(19-05): global-setup local_credentials seed + login.spec.ts + CI harness env
- global-setup.ts: TRUNCATE local_credentials + seed devuser/devpass (PHC scrypt inline)
- Create login.spec.ts: real-login-form e2e (gate redirect, wrong-password error, correct login)
- ci.yml: add LOCAL_SESSION_SECRET dev value + local_credentials seed step in harness job
- Fix all test mocks: add devSessionCookieMiddleware no-op to vi.mock(devBypass.js) blocks
  in admin/setup/push/lists/localAuth/authMode/requireAdmin tests (Rule 1 - Bug: missing export)
- Full API suite: 446/446 tests pass; pnpm typecheck: exit 0
2026-06-17 17:21:05 -04:00
Lucas BergerandClaude Opus 4.8 a193bc8236 fix(12): satisfy CI fast-checks — lint unused vars, typed contract-test body, prettier
CI / changes (pull_request) Successful in 3s
CI / fast-checks (pull_request) Successful in 2m16s
CI / api (pull_request) Failing after 1m37s
CI / harness (pull_request) Failing after 1h3m45s
CI / security (pull_request) Failing after 11s
CI / gate (pull_request) Failing after 1s
- Remove unused 'res'/'container' assignments (no-unused-vars)
- setupClient.contract.test.ts: typed parseSentBody helper + non-async json mock
  (no-unsafe-*/require-await)
- Prettier format 7 setup files

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 16:53:14 -04:00
Lucas Berger fbd3b77bde feat(12-06): expose non-secret DB name via GET /api/setup/status (gap 3)
- status returns { setupComplete, dbName } from process.env.DB_NAME (null fallback)
- only the DB name; never DB_HOST/DB_USER/DB_PASSWORD
- SetupStatusResponse carries dbName?: string | null for the PWA read-only field
2026-06-15 21:13:47 -04:00
Lucas Berger e9d07b38fb test(12-06): add failing tests for vapid public-key equality assertion (gap 2)
- mismatched submitted key (BH123) → 400, no VAPID_PRIVATE_KEY leak
- absent app_config.vapid_public_key row → 400
- happy path seeds matching app_config row
2026-06-15 21:11:41 -04:00
Lucas BergerandClaude Sonnet 4.6 687f9dc9fa fix(12): WR-01 narrow TOCTOU guard and set claimed=true for OIDC inserts
- apps/api/src/auth/user.ts: upsertUser step-5 insert now sets claimed=true
  for all OIDC-created users. An identity-bound OIDC user is never a pending
  wizard bootstrap user; explicit claimed=true prevents ambiguity with the
  (oidcIss IS NULL AND claimed=false) sentinel used by the TOCTOU guard and
  isSetupLocked. First-login-claims path is unaffected (it updates a
  pre-existing oidcIss=null row; this change only touches the fresh insert).

- apps/api/src/routes/setup.ts: TOCTOU guard in POST /credential now queries
  WHERE oidc_iss IS NULL AND claimed = false FOR UPDATE, matching the exact
  definition of a pending wizard bootstrap user. This provides defense-in-depth
  against any future path that could produce claimed=false OIDC rows.

- apps/api/tests/auth/user.test.ts: new WR-01 test asserts that the fresh
  OIDC insert sets claimed=true in the values passed to db.insert().

- apps/api/tests/routes/setup.test.ts: new WR-01 integration test seeds an
  OIDC user with claimed=false (oidcIss NOT NULL) and verifies POST /credential
  still succeeds (guard ignores the OIDC row, only counts local wizard rows).

All 402 API tests, 253 PWA tests, and typecheck pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 16:46:41 -04:00
Lucas BergerandClaude Sonnet 4.6 61a869ca7d fix(12): CR-01 guard effective-config branch during wizard in-progress
isSetupLocked() now checks for an unclaimed local wizard user
(oidcIss IS NULL, claimed=false) before firing the effective-config
branch. During the credential→complete window, this sentinel prevents
a production container with VAPID env set from blocking POST /complete
with 423. The explicit setup_complete flag (Check 1) still locks
unconditionally once written. Adds regression test that sets VAPID env
explicitly (no beforeEach clearing) to reproduce the production scenario.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 16:36:52 -04:00
Lucas BergerandClaude Sonnet 4.6 3babbfa20e fix(12): IN-02 guard /setup/complete against skipping the credential step
Without a prerequisite check, an operator could call POST /api/setup/complete
directly, setting setup_complete=true with no admin user or credential row,
leaving no recovery path without manual DB surgery.

Add an inner join check for an unclaimed user with an associated credential;
return 422 if absent. Update /complete tests to seed the prerequisite for
the success path and add an explicit 422 regression test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 16:20:55 -04:00
Lucas Berger 4748d578e7 test(12-02): isSetupLocked() real impl + RED-first setup route tests
- Implement real isSetupLocked() in setupGuard.ts: reads app_config.setup_complete
  (returns true if value==='true'); else checks member_credentials row + VAPID env
  for effective-config branch (D-10)
- Re-queries DB fresh every call — no module-level cache (D-10/Pitfall 8)
- Convert Wave-0 it.todo() scaffolds into real integration tests (17 tests RED)
- RED-first 423 guard test: POST /complete twice → first 200, second 423 (Pitfall 8)
- D-10 effective-config tests: 423 when credRow AND VAPID env; NOT 423 otherwise
- 2 'does NOT return 423' tests pass (404 ≠ 423); all others RED pending Task 2 router
2026-06-15 13:53:53 -04:00
Lucas Berger e098be3929 test(12-01): Wave-0 test scaffolds — setup.test.ts + user.test.ts (RED)
- Add apps/api/tests/routes/setup.test.ts with it.todo() scaffolds for:
  SETUP-01 (GET /api/setup/status), SETUP-02 (validate/vapid + validate/oidc),
  SETUP-01 (POST /api/setup/credential), SETUP-04 (POST /api/setup/complete
  × 2 → first 200, second 423), D-10 effective-config 423 guard.
  All 15 cases RED (it.todo) so Plan 02 implements against real failing tests.
- Extend apps/api/tests/auth/user.test.ts with D-08 first-login-claims describe
  block (5 it.todo() cases): unclaimed user bind, is_admin preservation,
  setup_complete=false fallthrough, no unclaimed fallthrough, no email lookup (D-10)
- Suite collects clean: 375 passed | 20 todo — no import errors
2026-06-15 13:43:47 -04:00