--- phase: 16-ci-dependency-audit-and-security-checks plan: "04" subsystem: infra tags: [gitleaks, secret-scanning, dockerignore, image-hygiene, security, ci] requires: - phase: 16-ci-dependency-audit-and-security-checks provides: Phase context, CI workflow, security check baseline strategy provides: - .gitleaks.toml — default ruleset + 4 allowlists (VAPID fixture, .env.example, .env.spike, crypto.test.ts AES fixture) - scripts/gitleaks-baseline.json — committed empty-array full-history baseline (613 commits, 23 MB, zero findings) - .dockerignore — excludes secrets/dev/bulk from Docker build context while preserving apps/api/src and workspace manifests affects: - 16-05 (gitleaks PR-diff scan CI job — consumes .gitleaks.toml + --baseline-path scripts/gitleaks-baseline.json) - 16-06 (static .dockerignore assertion — greps the exclusion patterns added here) tech-stack: added: - gitleaks v8.30.1 (secret scanner — used locally to generate baseline; CI binary installed in 16-05) patterns: - gitleaks allowlist-by-path pattern for known test fixtures (paths regex array in [[allowlists]] blocks) - Full-history baseline committed as empty JSON; PR-diff scan uses --baseline-path to ignore pre-existing known-safe history key-files: created: - .gitleaks.toml - scripts/gitleaks-baseline.json - .dockerignore modified: [] key-decisions: - "D-04-ALLOWLIST: crypto.test.ts TEST_KEY allowlisted by path — human-verified Vitest beforeAll synthetic AES-256-GCM fixture, not a real credential; 4th [[allowlists]] block added after human approval at the Task 3 checkpoint" - "D-04-BASELINE: baseline is empty JSON array after allowlisting; all 613 commits scanned clean; PR-diff scans in 16-05 start from provably clean history" patterns-established: - "gitleaks allowlist block structure: [[allowlists]] with description + paths (raw TOML string regex) — match existing block style when adding future fixture paths" requirements-completed: [SEC-01, IMG-02] duration: 45min completed: 2026-06-13 --- # Phase 16 Plan 04: Gitleaks Config, Full-History Baseline, and .dockerignore Summary **gitleaks config (4 path allowlists) + committed empty baseline (613 commits clean) + .dockerignore keeping secrets/dev/bulk out of Docker build context** ## Performance - **Duration:** ~45 min - **Started:** 2026-06-13 - **Completed:** 2026-06-13 - **Tasks:** 3 (Tasks 1-2 by prior executor; Task 3 checkpoint + continuation by this executor) - **Files modified:** 3 created + 1 extended (.gitleaks.toml 4th allowlist) ## Accomplishments - `.gitleaks.toml` authored with `[extend] useDefault = true` inheriting the full default ruleset, plus 4 `[[allowlists]]` blocks covering the VAPID test fixture, .env.example, .env.spike, and the synthetic AES-256-GCM key in crypto.test.ts - `scripts/gitleaks-baseline.json` regenerated after allowlisting the crypto.test.ts fixture — 613 commits scanned, ~23 MB of git history, zero findings; baseline is an empty JSON array `[]`, giving 16-05's PR-diff scan a provably clean starting state - `.dockerignore` created, excluding `.env`, `node_modules`, `.git`, `.planning/`, `apps/api/tests/`, `apps/pwa/e2e/`, seed scripts, and bulk artifacts while preserving `apps/api/src` (required by the builder stage's `COPY apps/api ./apps/api`), `apps/pwa/src`, workspace manifests, and all `package.json`/`tsconfig.json` files ## Task Commits 1. **Task 1: .gitleaks.toml with default ruleset + fixture/env allowlists** - `2f1592c` (chore) 2. **Task 2: .dockerignore (secrets/dev/bulk, preserve builder inputs)** - `5819247` (chore) 3. **Task 3 (post-checkpoint): allowlist crypto.test.ts in .gitleaks.toml** - `fba22b4` (chore) 4. **Task 3 (post-checkpoint): regenerate clean full-history baseline** - `bc83495` (chore) ## Files Created/Modified - `.gitleaks.toml` — gitleaks config: useDefault=true + 4 path-based allowlists (VAPID fixture, .env.example, .env.spike, crypto.test.ts AES fixture) - `scripts/gitleaks-baseline.json` — committed full-history baseline: empty `[]` (613 commits clean) - `.dockerignore` — Docker build context filter: excludes secrets/dev/bulk, preserves builder-stage inputs ## Decisions Made - **D-04-ALLOWLIST:** The Task 3 human-verify checkpoint surfaced one baseline finding: `TEST_KEY` at `apps/api/tests/broker/crypto.test.ts:15`, a synthetic AES-256-GCM key assigned to `process.env.APP_PASSWORD_ENCRYPTION_KEY` in a Vitest `beforeAll`. Human verified it is a test fixture. Operator approved adding a 4th `[[allowlists]]` block for `apps/api/tests/broker/crypto\.test\.ts` so future PR-diff scans also suppress it by path. Allowlist added, baseline regenerated — result is zero findings. - **D-04-BASELINE:** Empty baseline `[]` is the correct output when all known fixtures are properly allowlisted. The 16-05 gitleaks workflow will pass `--baseline-path scripts/gitleaks-baseline.json` so PR-diff scans only alert on new findings introduced in the PR, not pre-existing allowlisted history. ## Deviations from Plan The original plan had Tasks 1-2 as `type="auto"` and Task 3 as a `type="checkpoint:human-verify"`. The continuation task (adding the 4th allowlist and regenerating the baseline) was triggered by the human-verified finding at the checkpoint — this is expected flow, not a deviation. The 4th allowlist block was added per the operator's "Approve + allowlist it" decision. None - plan executed exactly as specified; the checkpoint and human-directed allowlist addition are the intended workflow. ## Issues Encountered None — gitleaks scan completed cleanly in 3 seconds; zero unexpected findings after allowlisting the known test fixture. ## Threat Surface Scan No new network endpoints, auth paths, file access patterns, or schema changes introduced by this plan. All changes are static config files (`.gitleaks.toml`, `.dockerignore`) and a JSON report artifact (`scripts/gitleaks-baseline.json`). ## User Setup Required None — no external service configuration required. The gitleaks binary is installed in CI via the 16-05 workflow step, not checked in. ## Next Phase Readiness - `16-05` (gitleaks PR-diff scan CI job): `.gitleaks.toml` and `scripts/gitleaks-baseline.json` are in place — 16-05 can wire the `gitleaks git --config .gitleaks.toml --baseline-path scripts/gitleaks-baseline.json` CI step immediately - `16-06` (static .dockerignore assertion): `.dockerignore` contains all patterns the static assertion greps for; `apps/api/src` exclusion is verified absent --- *Phase: 16-ci-dependency-audit-and-security-checks* *Completed: 2026-06-13*