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
@@ -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 ✓