docs(16-01): complete boot-guard plan — add SUMMARY, advance state to plan 2
This commit is contained in:
@@ -328,7 +328,7 @@ Plans:
|
|||||||
Plans:
|
Plans:
|
||||||
**Wave 1**
|
**Wave 1**
|
||||||
|
|
||||||
- [ ] 16-01-PLAN.md — Image-hygiene runtime: bake NODE_ENV=production + boot-time refuse-to-boot guard (IMG-01)
|
- [x] 16-01-PLAN.md — Image-hygiene runtime: bake NODE_ENV=production + boot-time refuse-to-boot guard (IMG-01)
|
||||||
- [ ] 16-02-PLAN.md — pnpm audit gate + waiver allowlist + advisory-only tiered outdated report (DEP-01, DEP-02)
|
- [ ] 16-02-PLAN.md — pnpm audit gate + waiver allowlist + advisory-only tiered outdated report (DEP-01, DEP-02)
|
||||||
- [ ] 16-03-PLAN.md — Fold eslint-plugin-security into the lint gate as blocking errors + triage (SEC-02)
|
- [ ] 16-03-PLAN.md — Fold eslint-plugin-security into the lint gate as blocking errors + triage (SEC-02)
|
||||||
- [ ] 16-04-PLAN.md — gitleaks config + full-history baseline + .dockerignore (SEC-01, IMG-02)
|
- [ ] 16-04-PLAN.md — gitleaks config + full-history baseline + .dockerignore (SEC-01, IMG-02)
|
||||||
@@ -359,7 +359,7 @@ Plans:
|
|||||||
| 13. Real Lint Gate (ESLint) | v1.1 | 3/3 | Complete | 2026-06-12 |
|
| 13. Real Lint Gate (ESLint) | v1.1 | 3/3 | Complete | 2026-06-12 |
|
||||||
| 14. Desktop E2E Coverage | v1.1 | 1/1 | Complete | 2026-06-12 |
|
| 14. Desktop E2E Coverage | v1.1 | 1/1 | Complete | 2026-06-12 |
|
||||||
| 15. Doc-Only CI Skip + MD Lint | v1.1 | 3/3 | Complete | 2026-06-12 |
|
| 15. Doc-Only CI Skip + MD Lint | v1.1 | 3/3 | Complete | 2026-06-12 |
|
||||||
| 16. CI Dep Audit, Sec & Img Hyg | v1.1 | 0/6 | Not started | - |
|
| 16. CI Dep Audit, Sec & Img Hyg | v1.1 | 1/6 | In Progress| |
|
||||||
|
|
||||||
## Backlog
|
## Backlog
|
||||||
|
|
||||||
@@ -367,7 +367,7 @@ Plans:
|
|||||||
|
|
||||||
**Goal:** [Captured for future planning] Abstract the calendar backend behind a provider interface so Fastmail/CalDAV is one implementation among potentially many. Shipping with a single provider is fine, but the broker, sync, and event-expansion layers should be structured so additional providers (e.g. other CalDAV hosts, Google Calendar, generic ICS feeds) can be added without rework. Captures the "provider" seam as an explicit architectural concern.
|
**Goal:** [Captured for future planning] Abstract the calendar backend behind a provider interface so Fastmail/CalDAV is one implementation among potentially many. Shipping with a single provider is fine, but the broker, sync, and event-expansion layers should be structured so additional providers (e.g. other CalDAV hosts, Google Calendar, generic ICS feeds) can be added without rework. Captures the "provider" seam as an explicit architectural concern.
|
||||||
**Requirements:** TBD
|
**Requirements:** TBD
|
||||||
**Plans:** 2/2 plans complete
|
**Plans:** 1/6 plans executed
|
||||||
|
|
||||||
Plans:
|
Plans:
|
||||||
|
|
||||||
|
|||||||
+15
-12
@@ -3,14 +3,14 @@ gsd_state_version: 1.0
|
|||||||
milestone: v1.1
|
milestone: v1.1
|
||||||
milestone_name: Operability & Polish
|
milestone_name: Operability & Polish
|
||||||
status: executing
|
status: executing
|
||||||
stopped_at: Phase 16 context gathered
|
stopped_at: Completed 16-01-PLAN.md
|
||||||
last_updated: "2026-06-13T03:25:36.437Z"
|
last_updated: "2026-06-13T09:15:26.256Z"
|
||||||
last_activity: 2026-06-13 -- Phase 16 planning complete
|
last_activity: 2026-06-13 -- Phase 16 execution started
|
||||||
progress:
|
progress:
|
||||||
total_phases: 19
|
total_phases: 19
|
||||||
completed_phases: 6
|
completed_phases: 6
|
||||||
total_plans: 17
|
total_plans: 23
|
||||||
completed_plans: 17
|
completed_plans: 18
|
||||||
percent: 32
|
percent: 32
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -21,14 +21,14 @@ progress:
|
|||||||
See: .planning/PROJECT.md (updated 2026-06-10)
|
See: .planning/PROJECT.md (updated 2026-06-10)
|
||||||
|
|
||||||
**Core value:** One color-coded family calendar (shared + personal) and shared lists from a single low-friction PWA — cross-ecosystem, no app store
|
**Core value:** One color-coded family calendar (shared + personal) and shared lists from a single low-friction PWA — cross-ecosystem, no app store
|
||||||
**Current focus:** Phase 09 — faster-write-back
|
**Current focus:** Phase 16 — ci-dependency-audit-and-security-checks
|
||||||
|
|
||||||
## Current Position
|
## Current Position
|
||||||
|
|
||||||
Phase: 13
|
Phase: 16 (ci-dependency-audit-and-security-checks) — EXECUTING
|
||||||
Plan: Not started
|
Plan: 2 of 6
|
||||||
Status: Ready to execute
|
Status: Ready to execute
|
||||||
Last activity: 2026-06-13 -- Phase 16 planning complete
|
Last activity: 2026-06-13 -- Phase 16 execution started
|
||||||
|
|
||||||
### Deferred Checkpoint — Phase 15 Plan 15-03 Task 2 (human-action)
|
### Deferred Checkpoint — Phase 15 Plan 15-03 Task 2 (human-action)
|
||||||
|
|
||||||
@@ -103,6 +103,7 @@ _Updated after each plan completion_
|
|||||||
| Phase 13-real-lint-gate-eslint P02 | 90 | 2 tasks | 31 files |
|
| Phase 13-real-lint-gate-eslint P02 | 90 | 2 tasks | 31 files |
|
||||||
| Phase 13-real-lint-gate-eslint P03 | 10 | 3 tasks | 399 files |
|
| Phase 13-real-lint-gate-eslint P03 | 10 | 3 tasks | 399 files |
|
||||||
| Phase 09-faster-write-back P01 | 341 | 3 tasks | 3 files |
|
| Phase 09-faster-write-back P01 | 341 | 3 tasks | 3 files |
|
||||||
|
| Phase 16 P01 | 188 | 3 tasks | 4 files |
|
||||||
|
|
||||||
## Accumulated Context
|
## Accumulated Context
|
||||||
|
|
||||||
@@ -164,6 +165,8 @@ Recent decisions affecting current work:
|
|||||||
- [Phase ?]: D-04-SCHEDULE-X-LOCATOR: Used .sx-react-calendar-wrapper CSS class to assert Schedule-X grid — no semantic role on outer wrapper div
|
- [Phase ?]: D-04-SCHEDULE-X-LOCATOR: Used .sx-react-calendar-wrapper CSS class to assert Schedule-X grid — no semantic role on outer wrapper div
|
||||||
- [Phase ?]: D-04-EMPTY-NETWORK-SIM: Lists empty state simulated via page.route to 200 empty array — preserves seeded DB for parallel workers (D-06 / T-07-11)
|
- [Phase ?]: D-04-EMPTY-NETWORK-SIM: Lists empty state simulated via page.route to 200 empty array — preserves seeded DB for parallel workers (D-06 / T-07-11)
|
||||||
- [Phase ?]: D-13-08: Prettier reformat committed as isolated mechanical diff; CI Format check step added to fast-checks job
|
- [Phase ?]: D-13-08: Prettier reformat committed as isolated mechanical diff; CI Format check step added to fast-checks job
|
||||||
|
- [Phase ?]: D-07 (16-01): ENV NODE_ENV=production baked into production Dockerfile stage — engages devBypass.ts hard guard so DEV_AUTH_BYPASS never injects in production
|
||||||
|
- [Phase ?]: D-08 (16-01): assertNotDevBypassInProduction() boot guard — first statement in isMainModule(), exits non-zero when NODE_ENV=production AND DEV_AUTH_BYPASS=true; unit-tested
|
||||||
|
|
||||||
### Roadmap Evolution
|
### Roadmap Evolution
|
||||||
|
|
||||||
@@ -228,9 +231,9 @@ Recent decisions affecting current work:
|
|||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-06-13T02:50:57.477Z
|
Last session: 2026-06-13T09:15:26.245Z
|
||||||
Stopped at: Phase 16 context gathered
|
Stopped at: Completed 16-01-PLAN.md
|
||||||
Resume file: .planning/phases/16-ci-dependency-audit-and-security-checks/16-CONTEXT.md
|
Resume file: None
|
||||||
|
|
||||||
## Operator Next Steps
|
## Operator Next Steps
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
---
|
||||||
|
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
|
||||||
Reference in New Issue
Block a user