CI workflow — security job added; gate aggregator updated
D-12: gitleaks always runs on every PR via unconditional steps (no job-level if:); only pnpm audit/outdated are code-gated at step level
D-14/D-15: security wired into gate with individual needs.security.result check — must be 'success', not 'success-or-skipped', because gitleaks always runs
A2/OQ-1: base.sha probe step with git merge-base fallback guards against empty base.sha on some Gitea versions
duration
completed
tasks_completed
files_modified
7
2026-06-13T12:23:36Z
2
1
Phase 16 Plan 05: CI Security Job — Summary
One-liner: Dedicated security CI job (gitleaks always + audit/outdated code-gated) wired into the gate aggregator with an individual needs.security.result success check.
What Was Built
A new security job was added to .gitea/workflows/ci.yml, placed between harness and gate in the file order (runs in parallel with fast-checks). The job:
Runs on every PR (if: github.event_name == 'pull_request'), needs: [changes]
Uses actions/checkout@v4 with fetch-depth: 0 (Pitfall 3 — base.sha must be locally present)
Has a "Probe PR base/head SHA" step that reads github.event.pull_request.base.sha and falls back to git merge-base origin/${{ github.base_ref }} HEAD if empty (Assumption A2 / OQ-1), exporting BASE_SHA and HEAD_SHA to $GITHUB_ENV
Installs gitleaks v8.30.1 from GitHub releases (pinned, no actions/cache per D-PROBE-04), then runs gitleaks git --log-opts="--no-merges ${BASE_SHA}..${HEAD_SHA}" --config .gitleaks.toml --baseline-path scripts/gitleaks-baseline.json --exit-code 1 — both gitleaks steps have no if: (D-12: blocking on every PR)
The pnpm setup-node / corepack / install / check-audit / check-outdated steps each carry if: needs.changes.outputs.code == 'true' (step-level, so gitleaks still runs on doc-only PRs)
The gate aggregator was updated:
needs: expanded to [fast-checks, changes, api, harness, security]
An individual if [ "${{ needs.security.result }}" != "success" ] check was inserted between the fast-checks check and the api/harness for loop
Security is not folded into the for loop — it must always succeed (cannot be skipped)
The task described a "Probe PR base/head SHA" step as a separate explicit step (per PLAN.md acceptance criteria A2/OQ-1). This matches the PLAN.md requirement and was implemented accordingly. The PATTERNS.md skeleton showed a simpler inline version; the PLAN.md explicitly required the probe step with fallback, so the PLAN.md was authoritative.
Threat Coverage
Threat
Mitigation
Status
T-16-15 — secret introduced in PR diff
gitleaks runs unconditionally, gate blocks on non-success
Mitigated
T-16-16 — unwaived High/Critical advisory merges to main