Defense-in-depth check that fails the build (and the local pre-push
workflow) if a server secret value is assigned to a NEXT_PUBLIC_*
variable — those get bundled into the browser by Next.js.
- scripts/check-no-secret-leak.mjs: git grep for the assignment shape,
excluding lockfiles and the script itself
- package.json: pnpm check:no-secret-leak
- .github/workflows/ci.yml: run the guard right after install, before
format/lint/typecheck/build
- docs/threat-model.md: close the last Unresolved item
- Phase 5 imaging: keep, pin numbers — 200 KB/image, 1h signed-URL TTL,
7-day retention window (PLAN.md §4 Phase 5)
- Phase 7 reminders: keep QStash (free tier 1000 msgs/day covers
clinic-scale); document signature + Zod + DB-invariant validation
plan in threat-model R8
- sb_secret_* / sb_publishable_* rotation: event-driven only for the
current educational scope (solo author, no real users); switch to
quarterly when any real user exists
- threat-model Unresolved: drop the three items above; CI grep for
sb_secret_ in NEXT_PUBLIC_* lines remains the only open question