--- phase: 16-ci-dependency-audit-and-security-checks plan: "01" subsystem: api-security tags: [security, boot-guard, docker, tdd] dependency_graph: requires: [] provides: [assertNotDevBypassInProduction, bootGuards.ts, ENV NODE_ENV=production] affects: [apps/api/src/index.ts, apps/api/Dockerfile] tech_stack: added: [] patterns: [TDD RED/GREEN, process.exit spy, boot-time guard] key_files: created: - apps/api/src/lib/bootGuards.ts - apps/api/tests/lib/bootGuards.test.ts modified: - apps/api/src/index.ts - apps/api/Dockerfile decisions: - "D-07: ENV NODE_ENV=production baked into production Dockerfile stage — engages devBypass.ts hard guard at image build time, not at runtime" - "D-08: assertNotDevBypassInProduction() placed as first statement in isMainModule() — boot-time refuse-to-boot guard converts silent misconfig into loud exit(1)" - "Guard evaluated at call time (not import time) — allows unit tests to set env vars before calling without module cache manipulation" metrics: duration_seconds: 188 completed_date: "2026-06-13" tasks_completed: 3 files_changed: 4 --- # Phase 16 Plan 01: Boot-time Dev-Bypass Guard Summary **One-liner:** Boot-time refuse-to-boot guard (`assertNotDevBypassInProduction`) plus `ENV NODE_ENV=production` baked into the production Dockerfile stage, turning a silent auth-bypass misconfiguration into an immediate non-zero exit. ## What Was Built ### Task 1 — RED (test commit 8414e89) Created `apps/api/tests/lib/bootGuards.test.ts` with 3 test cases: 1. `NODE_ENV=production` + `DEV_AUTH_BYPASS=true` → `process.exit(1)` is called (spy throws to make it observable) 2. `NODE_ENV=development` + `DEV_AUTH_BYPASS=true` → no `process.exit` 3. `NODE_ENV=production` + `DEV_AUTH_BYPASS` unset → no `process.exit` Suite failed with `Cannot find module '../../src/lib/bootGuards.js'` — RED state confirmed. ### Task 2 — GREEN (feat commit c2ffd1c) - Created `apps/api/src/lib/bootGuards.ts` exporting `assertNotDevBypassInProduction(): void` - JSDoc documents D-08, call-time env evaluation, and required placement rule - Added import to `apps/api/src/index.ts` - Added call as the **first** statement in `isMainModule()` block (before VAPID config, workers, serve()) - 3/3 unit tests pass, `pnpm typecheck` green ### Task 3 — Dockerfile ENV (chore commit 5b4f32a) - Added `ENV NODE_ENV=production` to the `production` stage in `apps/api/Dockerfile` - Placed between `WORKDIR /app/apps/api` and `COPY --from=pwa-builder` (exactly as specified) - Comment references D-07 - Exactly 1 occurrence; no other stage is affected ## Deviations from Plan None — plan executed exactly as written. ## TDD Gate Compliance - RED gate commit: `8414e89` — `test(16-01): add failing tests for boot-time dev-bypass guard` - GREEN gate commit: `c2ffd1c` — `feat(16-01): add boot-time refuse-to-boot guard for dev-bypass in production` - REFACTOR: not needed — implementation was clean on first pass ## Threat Surface Scan No new network endpoints, auth paths, file access patterns, or schema changes introduced. The boot guard adds a startup-time process.exit — no new externally-reachable surface. ## Known Stubs None. ## Self-Check: PASSED - `apps/api/src/lib/bootGuards.ts` — FOUND - `apps/api/tests/lib/bootGuards.test.ts` — FOUND - `apps/api/src/index.ts` modified — assertNotDevBypassInProduction() called at line 115 - `apps/api/Dockerfile` — `ENV NODE_ENV=production` present in production stage Commits: - `8414e89` — test(16-01): add failing tests for boot-time dev-bypass guard - `c2ffd1c` — feat(16-01): add boot-time refuse-to-boot guard for dev-bypass in production - `5b4f32a` — chore(16-01): bake ENV NODE_ENV=production into production Dockerfile stage