Secure SDLC & Code-Review Gate Procedure
The real, current gate
Every pull request against main triggers .github/workflows/dos-ci.yml — this is not a target process, it is what already runs on every PR today. Four jobs, gated behind one required check:
| Job | What it runs | Failure mode if the script is missing |
|---|---|---|
static | pnpm run lint, pnpm run typecheck | Warns and passes (DOS §12) if no script defined — does not silently skip without a visible warning |
test | pnpm run test | Same warn-and-pass pattern if no test script |
secret-scan | gitleaks detect against the PR diff (base..HEAD), fails the job (--exit-code 1) on any match | Hard fail, no bypass |
build | pnpm run build | Warn-and-pass if no build script |
verify | needs: [static, test, secret-scan, build] — the single required status check | Fails if any dependency job fails |
verify is the check branch protection is expected to require (CONTRIBUTING.md:14-19,56-63 describes this; branch-protection/ruleset configuration itself is a GitHub-side setting, not a repo file, so it isn't independently verifiable from the repo — note that as a limitation of this procedure's own evidence trail, not assume it's enforced without confirming it in GitHub's settings periodically).
Steps — what happens on every PR
- Author opens a PR against `main`. Trunk-based, per
CONTRIBUTING.md— branches are
short-lived (feature/…, fix/…, chore/…, spike/…).
- `dos-ci.yml` runs automatically. No manual trigger needed;
pull_request,merge_group,
and workflow_dispatch events all fire it.
- Each of `static`, `test`, `secret-scan`, `build` must pass for
verifyto succeed. - Merge is blocked until `verify` passes. At Stratify's current "Tier 1 (solo)" process
level, 0 human approvals are required (CONTRIBUTING.md:37-42) — the mandated review is an AI-agent /code-review run in a fresh context, not a second human reviewer. This is a real, current segregation-of-duties gap (Annex A 5.3), already tracked as RISK-002 in register/risks.yaml and documented honestly in GOV-03's RACI — this procedure does not pretend a human-review gate exists where it doesn't.
- Squash-merge to `main`. The merged commit is what the deploy timer picks up — see PRO-05.
Local pre-commit hooks — mirror, not the gate
.pre-commit-config.yaml runs gitleaks, detect-private-key, and a large-file check locally on commit. These exist to give fast local feedback and keep obvious secrets out of history before a push even happens, but they are explicitly bypassable via git commit --no-verify, and the file says so in its own header comment ("Fast feedback, bypassable by design"). CI is the actual non-bypassable gate — a developer who skips the local hook still hits secret-scan in dos-ci.yml on the PR, which has no bypass flag. Do not treat local hook coverage as equivalent to CI coverage when reasoning about what's actually enforced.
The real, current gap: no dependency/SCA scanning
Confirmed absent (register/facts.md, RISK-003): neither dos-ci.yml nor the vestigial Jenkinsfile runs pnpm audit, Dependabot, or Renovate. A known-vulnerable npm/pnpm dependency can ship to production today with nothing in CI to catch it. This is not a hypothetical future-hardening item — it is an open gap in the running gate described above, and closing it is the immediate next action for this procedure, cross-referenced to GOV-08 objective 1 ("Close the dependency/SCA scanning gap in CI," target 2026-11-01).
Concrete remediation steps:
- Add a new job to
dos-ci.yml, e.g.sca, runningpnpm audit --audit-level high(matches the
existing job pattern — checkout, pnpm/action-setup, setup-node, pnpm install --frozen-lockfile, then the audit command).
- Add
scatoverify'sneeds: [...]list so a high/critical finding blocks merge the same
way a failing test does today.
- In parallel or as a follow-up, enable Dependabot (a
.github/dependabot.ymlconfig is enough
to start — no code change required) for automated version-bump PRs, which the sca job above would then also gate.
- Once wired, the
scajob's run history becomes part of this procedure's evidence trail (see
below) — no separate tracking mechanism needed beyond CI run history.
Until this is wired, this procedure's own coverage of Annex A 8.8 (management of technical vulnerabilities) is honestly partial — the gate exists for code correctness and secrets, not yet for known-vulnerable dependencies. See PRO-06 for the fuller vulnerability/patch-management procedure this gap feeds into.
Evidence produced
- CI run history on GitHub Actions for every PR — pass/fail status per job, timestamped,
tied to a commit SHA. This is the primary evidence artifact for this procedure; no separate log needs to be kept by hand.
- The
verifycheck's pass/fail state as recorded against the merge commit. - Once the SCA job lands: its run history and any findings, feeding into PRO-06's triage process.
Review
Reviewed whenever dos-ci.yml changes (a new required job added or removed), and otherwise annually. The SCA-scanning gap above should be re-checked at every review until it's closed.