---
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*
