Phase 16: CI Dependency Audit, Security Checks & Image Hygiene - Discussion Log
Audit trail only. Do not use as input to planning, research, or execution agents.
Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
Date: 2026-06-12
Phase: 16-ci-dependency-audit-and-security-checks
Areas discussed: Security-check baseline, Audit + outdated policy, Image-hygiene enforcement (999.17), Gating & noise posture
Security-Check Baseline
Which checks form the baseline (multiSelect)
| Option |
Description |
Selected |
| Secret scan on diff |
gitleaks/trufflehog scans the PR diff for committed secrets |
✓ |
| Static security lint |
eslint-plugin-security or CodeQL |
✓ |
| Trivy image scan |
scan built production image for OS/package CVEs |
✗ (later dropped) |
| Dependency-review action |
GitHub's PR action — depends on GitHub API, not on Gitea |
|
User's choice: Secret scan + static security lint + (initially) trivy — then dropped trivy in the follow-up.
Secret-scan scope
| Option |
Description |
Selected |
| Diff + one full-history scan |
per-PR diff + a one-time full-history baseline |
✓ |
| PR diff only |
only changed commits |
|
| Full tree every run |
whole repo every PR |
|
Trivy gate
| Option |
Description |
Selected |
| Publish-time, advisory |
scan image, never block |
|
| Publish-time, block on CRITICAL |
fail publish on CRITICAL |
|
| Per-PR (build image in PR) |
earliest feedback |
|
User's choice: "Drop Trivy for now. I don't want it in the backlog, but it can be some future thing if we need it." → Trivy removed from scope entirely.
Static security lint severity
| Option |
Description |
Selected |
| Warn (advisory) |
surfaced but non-blocking |
|
| Error (blocking) |
fails the lint gate |
✓ |
Notes: User accepts that blocking eslint-plugin-security will require triaging/disabling existing heuristic findings to reach green.
Audit + Outdated Policy
pnpm audit severity threshold
| Option |
Description |
Selected |
| High + Critical |
fail on high/critical |
✓ |
| Critical only |
fail only on critical |
|
| Moderate+ |
fail on moderate and above |
|
Waiver mechanism
| Option |
Description |
Selected |
| Allowlist file in repo |
committed advisory-ID list + reason + reviewer |
✓ |
| pnpm overrides / config |
auditConfig.ignore* in package.json |
|
| No waiver mechanism yet |
deal with it if/when it blocks |
|
Outdated reporting vs intentional pins
| Option |
Description |
Selected |
| Advisory PR comment, never gates |
pnpm outdated -r as PR comment |
|
| Advisory, job-log only |
print to job log |
|
| Skip outdated entirely |
rely on audit only |
|
User's choice: Deferred to researcher (OQ-01). "Version pins are fine but if there's an issue with them or if they are too far behind there should be a balance here." Outcome locked: advisory, never gates; researcher designs the "dangerously behind / pinned-version-has-advisory" flagging.
Image-Hygiene Enforcement (999.17)
Enforcement mechanism (multiSelect)
| Option |
Description |
Selected |
| Bake NODE_ENV=production into image |
engages devBypass hard guard in shipped image |
✓ |
| Boot-time refuse-to-boot |
throw + non-zero exit on prod + dev-bypass |
✓ |
| Build-time abort |
fail build/publish on dev target/arg |
|
Notes: publish.yml already pins --target production; the static CI assertion covers "stays that way."
CI assertion depth
| Option |
Description |
Selected |
| Static + boot smoke |
.dockerignore + --target assertion + run image with dangerous combo, assert refuses to boot |
✓ |
| Full filesystem forensics |
export image fs, grep for secrets/seed/.git |
|
| Static checks only |
no container built/run |
|
.dockerignore scope
| Option |
Description |
Selected |
| Secrets + dev + bulk |
.env*, seed-credential.mjs, .git, node_modules, dist, tests, e2e, .planning, *.sql, playwright artifacts |
✓ |
| Secrets-only minimal |
only secret/seed/data files |
|
| Researcher proposes the list |
capture intent, enumerate later |
|
Gating & Noise Posture
Job layout
| Option |
Description |
Selected |
| New 'security' job, parallel |
gitleaks+audit+outdated parallel to fast-checks |
|
| Fold into fast-checks |
steps in existing job |
|
| Researcher decides layout |
pick against runner constraints |
✓ |
Notes: Recommendation surfaced (dedicated parallel security job) but final decomposition left to researcher/planner.
Doc-only PR behavior
| Option |
Description |
Selected |
| Secret scan always; audit/outdated code-only |
gitleaks universal, audit/outdated behind changes filter |
✓ |
| All new checks code-only |
whole security job skips doc-only |
|
| All new checks always run |
run on every PR |
|
Result surfacing
| Option |
Description |
Selected |
| Job-log summary only |
advisory output to job log |
✓ |
| PR comment via Gitea API |
step posts/updates a PR comment |
|
Renovate / Dependabot
| Option |
Description |
Selected |
| Defer |
out of scope; capture as deferred |
✓ |
| In scope |
add upgrade-bot config this phase |
|
Claude's Discretion
- Job decomposition for the new PR-time checks (D-15) — researcher/planner.
- Exact secret-scan tool (gitleaks vs trufflehog) and exact
.dockerignore line list — researcher confirms.
Deferred Ideas
- Renovate / Dependabot automated dependency upgrades — future phase/backlog.
- Trivy / image CVE scanning — dropped, not backlogged (revisit only if needed).
- PR-comment surfacing of advisory results — deferred in favor of job-log-only.
- Stale pending todo
2026-06-10-gitea-ci-regression-and-docker-publish.md — already delivered in Phase 8; should be archived.