docs(16-02): complete dependency-audit-gate plan — add SUMMARY, advance state to plan 3

This commit is contained in:
Lucas Berger
2026-06-13 05:20:43 -04:00
parent baf2e3ad1b
commit 069fe53523
3 changed files with 100 additions and 7 deletions
+3 -3
View File
@@ -329,7 +329,7 @@ Plans:
**Wave 1**
- [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)
- [x] 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-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 |
| 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 |
| 16. CI Dep Audit, Sec & Img Hyg | v1.1 | 1/6 | In Progress| |
| 16. CI Dep Audit, Sec & Img Hyg | v1.1 | 2/6 | In Progress| |
## 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.
**Requirements:** TBD
**Plans:** 1/6 plans executed
**Plans:** 2/6 plans executed
Plans:
+5 -4
View File
@@ -4,13 +4,13 @@ milestone: v1.1
milestone_name: Operability & Polish
status: executing
stopped_at: Completed 16-01-PLAN.md
last_updated: "2026-06-13T09:15:26.256Z"
last_updated: "2026-06-13T09:20:23.640Z"
last_activity: 2026-06-13 -- Phase 16 execution started
progress:
total_phases: 19
completed_phases: 6
total_plans: 23
completed_plans: 18
completed_plans: 19
percent: 32
---
@@ -26,7 +26,7 @@ See: .planning/PROJECT.md (updated 2026-06-10)
## Current Position
Phase: 16 (ci-dependency-audit-and-security-checks) — EXECUTING
Plan: 2 of 6
Plan: 3 of 6
Status: Ready to execute
Last activity: 2026-06-13 -- Phase 16 execution started
@@ -104,6 +104,7 @@ _Updated after each plan completion_
| Phase 13-real-lint-gate-eslint P03 | 10 | 3 tasks | 399 files |
| Phase 09-faster-write-back P01 | 341 | 3 tasks | 3 files |
| Phase 16 P01 | 188 | 3 tasks | 4 files |
| Phase 16-ci-dependency-audit-and-security-checks P02 | 25 | 3 tasks | 5 files |
## Accumulated Context
@@ -231,7 +232,7 @@ Recent decisions affecting current work:
## Session Continuity
Last session: 2026-06-13T09:15:26.245Z
Last session: 2026-06-13T09:20:23.627Z
Stopped at: Completed 16-01-PLAN.md
Resume file: None
@@ -0,0 +1,92 @@
---
phase: 16-ci-dependency-audit-and-security-checks
plan: "02"
subsystem: ci-security
tags: [dependency-audit, pnpm-audit, pnpm-outdated, allowlist, tdd]
dependency_graph:
requires: []
provides: [scripts/check-audit.mjs, scripts/audit-allowlist.json, scripts/check-outdated.mjs, scripts/outdated-pins.json]
affects: [16-05-ci-security-job]
tech_stack:
added: []
patterns: [node-wrapper-script, tdd-red-green, audit-allowlist-pattern]
key_files:
created:
- scripts/check-audit.mjs
- scripts/audit-allowlist.json
- scripts/check-outdated.mjs
- scripts/outdated-pins.json
- scripts/__tests__/check-audit.test.mjs
modified: []
decisions:
- "D-04/D-05: Audit wrapper uses committed allowlist (audit-allowlist.json) with reason+reviewer+expiry per GHSA; Option B over native pnpm.auditConfig.ignoreGhsas (no accountability metadata in native approach)"
- "D-06: check-outdated.mjs always exits 0; tiered report never gates"
- "Pitfall 1 honored: pnpm audit --json with NO --audit-level flag"
- "TDD gate: test(16-02) RED commit precedes feat(16-02) GREEN commit"
metrics:
duration: 25
completed: "2026-06-13"
tasks: 3
files: 5
---
# Phase 16 Plan 02: Dependency Audit Gate + Outdated Report Summary
**One-liner:** pnpm audit blocking wrapper with committed GHSA allowlist (esbuild waiver pre-seeded) plus tiered outdated report — both as standalone Node.js scripts, TDD-verified.
## What Was Built
### Task 1 — Audit allowlist + pin reasons (chore, `0f101bd`)
- `scripts/audit-allowlist.json`: committed GHSA waiver map. Seeded with `GHSA-gv7w-rqvm-qjhr` (esbuild High advisory, transitive dev-only via drizzle-kit/vitest/vite, not in production image). Each entry carries `reason`, `reviewer`, and `expires` fields for auditability.
- `scripts/outdated-pins.json`: flat package→reason map for four intentional pins: eslint (ESLint 10 breaks eslint-plugin-react), @eslint/js (same), zod (v4 breaking API), @types/node (Node 22 LTS types).
### Task 2 — check-audit.mjs blocking wrapper, TDD (`7ac8b19` RED → `6eb5107` GREEN)
- `scripts/check-audit.mjs`: exports two pure functions (`selectBlocking`, `partitionAdvisories`) for unit testing. Main body runs only when invoked directly (import.meta.url guard). Uses `pnpm audit --json` with no `--audit-level` (Pitfall 1 honored). Exits 1 on unwaived High/Critical; exits 0 with advisory report for moderate/low.
- `scripts/__tests__/check-audit.test.mjs`: 5 cases via `node:test` + `node:assert` (no extra deps). Covers: unwaived High → blocking; waived High → not blocking; moderate/low only → not blocking; no advisories → not blocking; mixed → correct partition.
- All 5 tests green.
### Task 3 — check-outdated.mjs tiered report (`baf2e3a`)
- `scripts/check-outdated.mjs`: classifies outdated packages into four tiers (AUDIT-ADVISORY > MAJOR-BEHIND-INTENTIONAL > MAJOR-BEHIND-UNPINNED > ROUTINE-DRIFT). Cross-checks `pnpm audit --json` to surface pinned-but-vulnerable packages under AUDIT-ADVISORY. Reads `outdated-pins.json` to label intentional pins with their reason. Always `process.exit(0)` — never gates (D-06).
- Live run output: eslint/@eslint/js/zod/@types/node correctly under INTENTIONAL, @vitejs/plugin-react/jsdom/typescript under UNPINNED, hono/mysql2/@types/react under ROUTINE-DRIFT.
## Verification Results
- `node --test scripts/__tests__/check-audit.test.mjs` → 5/5 pass
- `node scripts/check-outdated.mjs` → exit 0, tiered report printed
- `node -e "require('./scripts/audit-allowlist.json')['GHSA-gv7w-rqvm-qjhr']"` → defined
- `grep "execSync" scripts/check-audit.mjs``pnpm audit --json` (no `--audit-level`)
- `grep -c "process.exit(0)" scripts/check-outdated.mjs` → 1
- `grep "process.exit(1)" scripts/check-outdated.mjs` → absent
## TDD Gate Compliance
| Gate | Commit | Message |
|------|--------|---------|
| RED | 7ac8b19 | test(16-02): add failing tests for check-audit.mjs filter logic |
| GREEN | 6eb5107 | feat(16-02): add check-audit.mjs blocking wrapper + unit tests |
TDD gate sequence correct: test commit precedes implementation commit.
## Deviations from Plan
None — plan executed exactly as written.
## Known Stubs
None. All scripts are fully functional with live data.
## Threat Flags
No new threat surface introduced. Files created are scripts (no network endpoints, no auth paths, no schema changes).
## Self-Check: PASSED
- `scripts/check-audit.mjs` — exists ✓
- `scripts/audit-allowlist.json` — exists ✓ (GHSA-gv7w-rqvm-qjhr present)
- `scripts/check-outdated.mjs` — exists ✓
- `scripts/outdated-pins.json` — exists ✓
- `scripts/__tests__/check-audit.test.mjs` — exists ✓
- Commits 0f101bd, 7ac8b19, 6eb5107, baf2e3a — all present in git log ✓