You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: .claude/rules/09-ci-cd-efficiency-governance.md
+6-8Lines changed: 6 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -28,7 +28,7 @@ This repo is a single-package npm TypeScript CLI/library with private local Pyth
28
28
29
29
## Workflow map
30
30
31
-
The complete public CI surface is the seven tracked workflows under `.github/workflows/`:
31
+
The complete public CI surface is the six tracked workflows under `.github/workflows/`:
32
32
33
33
-`ci.yml` — the pull-request and `main`-push gate. Three jobs:
34
34
-`quality` (matrix `node-version: [22, 24]`, no database): `npm ci`, `npm audit signatures`, `npm run build`, `npm run lint:ci` (Biome `biome ci .`), `npm run typecheck`, `npm run guard`, `npm run check:schema`, `npm run check:package`, then packs the tarball and smoke-tests `npx supaschema --version|diff|check`. On Node 22 only, CI prepares the alternate consumer package managers required by Rule 13, runs `npm run package:smoke`, and runs the shipped `examples/` render+check plus `npm run test:examples`.
@@ -39,14 +39,13 @@ The complete public CI surface is the seven tracked workflows under `.github/wor
39
39
-`codeql.yml` — CodeQL static analysis matrix (`actions`, `javascript-typescript`) with the `security-and-quality` query suite and explicit no-build mode, on push/PR to `main` and a weekly schedule. These lanes have no dependency install.
-`docs.yml` — path-filtered (`docs/**`, `package.json`, `package-lock.json`, the workflow itself) Mintlify validation via `npm run docs:check`.
42
-
-`ci-failure-report.yml` — pull-request DX reporter. It runs after every completed `workflow_run` for `CI`, `Docs`, `CodeQL`, and `Dependency Review` when the source event was `pull_request`. Failed source workflows write or update one trusted PR marker comment for local Claude/Codex inbox hooks to read, including workflow-level failures when failed job details are unavailable. Successful and other non-failure source workflows clear only the matching current-head workflow marker so unrelated failures remain visible.
43
42
44
43
## Hard rules
45
44
46
45
- Every workflow declares a top-level least-privilege `permissions:` block, defaulting to `contents: read` (or `read-all`). A job elevates only the exact scopes it needs: `release.yml`'s `publish` job adds `contents: write` for GitHub Release/tag creation plus `id-token: write` and `attestations: write` for trusted publishing/provenance; `codeql.yml`/`scorecard.yml` add `security-events: write` (+ `id-token: write` for Scorecard). Never grant write at the top level.
47
46
- All `uses:` refs are pinned to full-length commit SHAs with an adjacent version comment (for example `# v6.0.3`) for Dependabot readability. The executable ref must be immutable — never a tag or branch. This is the OpenSSF Scorecard "Pinned-Dependencies" check and a STOP condition if violated.
48
-
-`actions/checkout` uses `persist-credentials: false` on every tracked workflow's checkout (`ci.yml`, `dependency-review.yml`, `scorecard.yml`, `release.yml`, `codeql.yml`, `docs.yml`, `ci-failure-report.yml`); release re-supplies an explicit `GH_TOKEN`/`registry-url` only where a step needs it.
49
-
- Every job declares a `timeout-minutes` ceiling so no lane can hang at the 360-minute default — least of all the privileged `release.yml``publish` job (`ci.yml` 20/30/20, `dependency-review.yml` 10, `release.yml` 30, `codeql.yml`/`scorecard.yml` 20, `docs.yml` 15, `ci-failure-report.yml` 10).
47
+
-`actions/checkout` uses `persist-credentials: false` on every tracked workflow's checkout (`ci.yml`, `dependency-review.yml`, `scorecard.yml`, `release.yml`, `codeql.yml`, `docs.yml`); release re-supplies an explicit `GH_TOKEN`/`registry-url` only where a step needs it.
48
+
- Every job declares a `timeout-minutes` ceiling so no lane can hang at the 360-minute default — least of all the privileged `release.yml``publish` job (`ci.yml` 20/30/20, `dependency-review.yml` 10, `release.yml` 30, `codeql.yml`/`scorecard.yml` 20, `docs.yml` 15).
50
49
- The privileged `release.yml``publish` job runs `step-security/harden-runner` for egress monitoring. It ships in `egress-policy: audit` with the candidate `allowed-endpoints` list commented inline; tightening to `egress-policy: block` happens only after reviewing a real run's network insights. Do not remove harden-runner from the OIDC-holding job.
51
50
- Releases publish through npm OIDC trusted publishing, not a stored npm token: the job runs on a GitHub-hosted runner with Node 24, asserts `npm >= 11.5.1`, sets `registry-url: https://registry.npmjs.org`, disables package-manager caching on the privileged publish path, and runs `npm publish "$SUPASCHEMA_TARBALL" --access public --provenance`. npm trusted publishing already generates provenance; `--provenance` remains explicit repo policy. Tarball provenance is attested with `actions/attest@v4`. Do not reintroduce a long-lived `NPM_TOKEN`/`NODE_AUTH_TOKEN` secret.
52
51
-`main` is the npm and GitHub release source. `release.yml` must not publish from GitHub Release events or `workflow_run` because release must not wait on the full CI workflow. It publishes from direct `push` to `main`, with manual dispatch limited to `refs/heads/main`. The preflight script must fail closed when `package.json`, `package-lock.json`, the lockfile root package version, or the top `CHANGELOG.md` release entry disagree; when a GitHub Release exists but npm is missing; or when an existing GitHub tag points away from the release commit. Same-version reruns are idempotent: if npm exists and the GitHub Release exists, the workflow exits cleanly; if npm exists and the GitHub Release is missing, the workflow repairs the GitHub Release from `CHANGELOG.md` without republishing npm.
@@ -58,7 +57,6 @@ The complete public CI surface is the seven tracked workflows under `.github/wor
58
57
- Each `supaschema diff --out` render in a workflow writes to its own output subdirectory. supaschema treats the `--out` file's parent directory as the migrations dir for the lineage chain gate, so two renders sharing one directory — for example the `quality` lane's tarball smoke and examples smoke both writing into `$RUNNER_TEMP` — make the first render look like a pending migration the second must continue, a false `SUPA_DIFF_LINEAGE_BROKEN`. Give each render an isolated `--out` directory (supaschema auto-creates the parent).
59
58
- Concurrency is declared in each PR-facing workflow (`ci.yml`, `dependency-review.yml`) as `group: "${{ github.workflow }}-${{ github.ref }}"` with `cancel-in-progress: true`, so superseded PR runs are cancelled. `release.yml` is not cancel-on-new; it uses `group: release-npm` with `queue: max` and must never set `cancel-in-progress: true` on the publish path.
60
59
- Path-filtered workflows (`docs.yml`) gate on their owned trees plus their own workflow file and the lockfile inputs that affect them. These are independent advisory workflows, not required checks short-circuited by `paths-ignore`; do not convert a required gate (`ci.yml`) into a path-skipped check.
61
-
-`ci-failure-report.yml` is a reporter, not a required gate. It MUST keep top-level read-only permissions, elevate only its report job to `actions: read`, `checks: read`, `contents: read`, `pull-requests: read`, and `issues: write`, and MUST NOT checkout, build, test, or execute pull-request code. It may only run `scripts/github/report-ci-failure.mjs` from the default-branch checkout to update the single `<!-- supaschema:ci-failure-report -->` PR comment.
62
60
- CI/docs Node lanes use `actions/setup-node` with npm caching where appropriate; the privileged release job disables package-manager caching to avoid unnecessary package-manager side effects on the OIDC publish path. There is no external/remote build cache in this repo.
63
61
- CodeQL MUST cover `actions` and `javascript-typescript`, use `queries: security-and-quality`, and use no-build analysis for these interpreted/action languages. Do not use the deprecated CodeQL dependency installer input.
64
62
- Supply-chain scanning is layered and must stay wired: `npm audit signatures` (registry signature check) in `quality` and `release`, `actions/dependency-review-action` on PRs, CodeQL static analysis, and OpenSSF Scorecard. Do not remove a public scanner to make a run green.
@@ -69,13 +67,13 @@ The complete public CI surface is the seven tracked workflows under `.github/wor
69
67
## Enforced by
70
68
71
69
-`npm run guard` (`scripts/guards/check-all.mjs`) — repository invariants (tooling stack, canonical surfaces, agent surfaces, dependency catalog, Code Atlas, LSP coverage), run inside `ci.yml`'s `quality` job. Public guard scans over agents, skills, rules, and policy files MUST derive their file lists from `git ls-files --cached`, not raw filesystem directory walks, so ignored local DX cannot satisfy or break CI-only requirements. It MUST run a second targeted public-checkout pass for local-only maintainer surfaces with `SUPASCHEMA_PUBLIC_CHECKOUT=1` and emit `PUBLIC_CHECKOUT_GUARDS_OK`, so ignored local files cannot mask clean GitHub checkout failures.
72
-
- `npm run guard:ci` (`scripts/guards/check-ci-governance.mjs`, part of `npm run guard`) — parses every tracked `.github/workflows/*.yml` with the `yaml` dependency (AST/structured walk, Rule 07) and asserts this rule's STOP invariants deterministically: top-level least-privilege permissions, full-SHA action pins, `actions/checkout` `persist-credentials: false`, no stored npm token, the release workflow's direct `push` trigger on `main`, no `workflow_run` release dependency, main-scoped manual dispatch, queued non-canceling publish concurrency, GitHub-hosted Ubuntu Node 24 trusted-publishing lane, harden-runner + OIDC `id-token: write` + `npm publish "$SUPASCHEMA_TARBALL" --access public --provenance`, `actions/attest@v4`, GitHub Release/tag creation from `scripts/release/changelog-notes.mjs` with `--notes-file`, exact `github.sha` checkout, release preflight, no database service or benchmark on the publish job, no benchmark gate in `ci.yml`, the Node/Postgres/OS matrix lanes, the single-owner examples lane, matrix-focused test scripts, the CodeQL `actions`/`javascript-typescript` matrix, the `ci-failure-report.yml` completed-PR reporter shape that can clear current-head markers after non-failure reruns, and the requirement that `python.yml` stay private with the FastMCP service.
70
+
- `npm run guard:ci` (`scripts/guards/check-ci-governance.mjs`, part of `npm run guard`) — parses every tracked `.github/workflows/*.yml` with the `yaml` dependency (AST/structured walk, Rule 07) and asserts this rule's STOP invariants deterministically: top-level least-privilege permissions, full-SHA action pins, `actions/checkout` `persist-credentials: false`, no stored npm token, the release workflow's direct `push` trigger on `main`, no `workflow_run` release dependency, main-scoped manual dispatch, queued non-canceling publish concurrency, GitHub-hosted Ubuntu Node 24 trusted-publishing lane, harden-runner + OIDC `id-token: write` + `npm publish "$SUPASCHEMA_TARBALL" --access public --provenance`, `actions/attest@v4`, GitHub Release/tag creation from `scripts/release/changelog-notes.mjs` with `--notes-file`, exact `github.sha` checkout, release preflight, no database service or benchmark on the publish job, no benchmark gate in `ci.yml`, the Node/Postgres/OS matrix lanes, the single-owner examples lane, matrix-focused test scripts, the CodeQL `actions`/`javascript-typescript` matrix, and the requirement that `python.yml` stay private with the FastMCP service.
73
71
-`npm run lint:ci` (Biome `biome ci .`), `npm run typecheck`, `npm run build`, `npm run check:schema`, `npm run check:package`, and `npm run package:smoke` — the static and packaging gates the `quality` matrix runs (lint/format ownership is Rule 08; toolchain is Rule 06; the npm package boundary is Rule 13).
74
72
-`npm run test:matrix`, `npm run test:matrix:coverage`, `npm run fixture:verify`, and `npm run corpus:check` — the database-backed replay-safety proofs the `check` matrix runs.
75
-
- The seven workflow files themselves under `.github/workflows/`, plus `.github/dependabot.yml`.
73
+
- The six workflow files themselves under `.github/workflows/`, plus `.github/dependabot.yml`.
76
74
-`lefthook.yml` for local pre-commit hooks that mirror the lint/format gates before code reaches CI.
77
75
78
-
STOP if a tracked workflow grants top-level write permissions, unpins an action from its full-length commit SHA, drops `persist-credentials: false` on a job that does not need persisted credentials, removes harden-runner from the OIDC publish job, replaces OIDC trusted publishing with a stored npm token, moves the publish job off GitHub-hosted Ubuntu/Node 24 or drops the npm `>=11.5.1` assertion, drops `actions/attest@v4`, publishes from GitHub Release events or waits for `workflow_run`, lets a non-main manual dispatch publish, drops the release version preflight, publishes anything other than the smoked tarball, drops GitHub Release/tag creation, creates a GitHub Release with auto-generated notes instead of the extracted `CHANGELOG.md` entry, uploads extra GitHub Release artifacts, runs benchmarks in a required CI/release workflow, removes a supported Node/Postgres/OS matrix lane, drops a public CodeQL language lane (`actions`, `javascript-typescript`), makes `python.yml` public while `services/agent-mcp` stays private, moves database-backed proofs out of the `postgres`-service `check` job, duplicates examples tests across DB or OS matrix axes, removes concurrency cancellation from a PR-facing workflow, disables a public supply-chain scanner (`npm audit signatures`, dependency-review, CodeQL, or Scorecard), makes `ci-failure-report.yml` run on non-PR source events, execute PR code, or grant permissions beyond the reporter scopes, moves a bash-only construct into a step or npm script the `check-os` (Windows/macOS) lane runs, or shares one `--out` directory across multiple `supaschema diff` renders in a workflow.
76
+
STOP if a tracked workflow grants top-level write permissions, unpins an action from its full-length commit SHA, drops `persist-credentials: false` on a job that does not need persisted credentials, removes harden-runner from the OIDC publish job, replaces OIDC trusted publishing with a stored npm token, moves the publish job off GitHub-hosted Ubuntu/Node 24 or drops the npm `>=11.5.1` assertion, drops `actions/attest@v4`, publishes from GitHub Release events or waits for `workflow_run`, lets a non-main manual dispatch publish, drops the release version preflight, publishes anything other than the smoked tarball, drops GitHub Release/tag creation, creates a GitHub Release with auto-generated notes instead of the extracted `CHANGELOG.md` entry, uploads extra GitHub Release artifacts, runs benchmarks in a required CI/release workflow, removes a supported Node/Postgres/OS matrix lane, drops a public CodeQL language lane (`actions`, `javascript-typescript`), makes `python.yml` public while `services/agent-mcp` stays private, moves database-backed proofs out of the `postgres`-service `check` job, duplicates examples tests across DB or OS matrix axes, removes concurrency cancellation from a PR-facing workflow, disables a public supply-chain scanner (`npm audit signatures`, dependency-review, CodeQL, or Scorecard), moves a bash-only construct into a step or npm script the `check-os` (Windows/macOS) lane runs, or shares one `--out` directory across multiple `supaschema diff` renders in a workflow.
79
77
80
78
STOP if anyone reintroduces Turborepo / remote-cache / `--affected` / maintainer pnpm/Yarn/Bun install workflows / Vercel / Render deploy machinery into the CI surface or into this rule. The isolated package-smoke lane is the only CI exception for alternate package managers.
0 commit comments