Stratify
Legal and compliance

Secure SDLC & Code-Review Gate Procedure

docs/compliance/isms/procedures/PRO-04-secure-sdlc-gate.md

Source updated 03. Aug. 2026

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:

JobWhat it runsFailure mode if the script is missing
staticpnpm run lint, pnpm run typecheckWarns and passes (DOS §12) if no script defined — does not silently skip without a visible warning
testpnpm run testSame warn-and-pass pattern if no test script
secret-scangitleaks detect against the PR diff (base..HEAD), fails the job (--exit-code 1) on any matchHard fail, no bypass
buildpnpm run buildWarn-and-pass if no build script
verifyneeds: [static, test, secret-scan, build] — the single required status checkFails 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

  1. Author opens a PR against `main`. Trunk-based, per CONTRIBUTING.md — branches are

short-lived (feature/…, fix/…, chore/…, spike/…).

  1. `dos-ci.yml` runs automatically. No manual trigger needed; pull_request, merge_group,

and workflow_dispatch events all fire it.

  1. Each of `static`, `test`, `secret-scan`, `build` must pass for verify to succeed.
  2. 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.

  1. 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:

  1. Add a new job to dos-ci.yml, e.g. sca, running pnpm audit --audit-level high (matches the

existing job pattern — checkout, pnpm/action-setup, setup-node, pnpm install --frozen-lockfile, then the audit command).

  1. Add sca to verify's needs: [...] list so a high/critical finding blocks merge the same

way a failing test does today.

  1. In parallel or as a follow-up, enable Dependabot (a .github/dependabot.yml config is enough

to start — no code change required) for automated version-bump PRs, which the sca job above would then also gate.

  1. Once wired, the sca job'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 verify check'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.