ci(security-review): adopt always-report shape — paths input replaces workflow-level filter - #825
Conversation
… workflow-level filter Drop the workflow-level `on.pull_request.paths` filter and pass the same 26 security-sensitive patterns as the reusable workflow's new `paths` input (ci-workflows#189, re-pinned to its merge SHA). The reusable workflow's job-level gate now decides relevance: a not-applicable PR yields a name-stable skipped `security-review / security-review` check that a required-check ruleset reads as success, instead of a Pending wedge. ADR 0002 gains an ordering-correction addendum (ci-workflows-first; a caller-side `if:` on the `uses:` job registers a different check name when skipped — community discussion 72708 — and caller-first on the old pin would have run a full pass on every prose PR). Roadmap PLAN Phase II tagged DOING with the matching scope-change note; step 0 results recorded there (sole consumer = this caller; captured context unchanged). Prepares Phase II step 3: the github-iac ruleset flip stays LAST and user-gated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Claude finished @kyle-sexton's task in 2m 20s —— View job PR Review: ci(security-review) always-report shape adoptionTasks
SummaryClean, well-scoped Phase II step 2. No blocking findings. The core mechanics are correct and the documentation is thorough. Notes below.
|
…ths input (#229) ## What Add the reviewed runner-input contract for `melodic-software/ci-workflows/.github/workflows/claude-security-review.yml@99cb082ebb942b9da08e8345a851be5bf252ad79` (the ci-workflows#189 squash-merge SHA): `allowedInputs` gains `paths`; routing (`runner-input`), secret mapping (`CLAUDE_CODE_OAUTH_TOKEN`), and `allowedCallerPermissions` are identical to the reviewed `0a5fd4c` entry, which stays until the last caller re-pins and can then be retired. ## Why The runner-policy gate correctly declined auto-approval on claude-code-plugins#825 ("inputs changed since the previously reviewed ...@0a5fd4c"): the new pin's input surface grew by `paths` — the always-report shape's relevance-scope input (job-level gate inside the reusable workflow; a not-applicable PR yields a name-stable skipped check a required-check ruleset reads as success). This is the reviewed-contract update that gate exists to force. Context: claude-code-plugins ADR 0002 addenda (#509 enforcement ruling + ordering correction), ladder-climb roadmap Phase II. ## Verification - `npm run lint:runner-policy` — Runner policy passed. - `npm run test:runner-policy` — 227 pass / 0 fail (one EBUSY temp-dir teardown flake on first Windows run, clean on rerun). - `check-jsonschema --schemafile components/runner-policy/policy.schema.json components/runner-policy/policy.json` — ok. No linked issue (reviewed-contract update; the enforcement-rail issue lives in claude-code-plugins). ## Related - melodic-software/ci-workflows#189 (merged, `99cb082`) - melodic-software/claude-code-plugins#825 (blocked on this sync) - melodic-software/claude-code-plugins#509 — enforcement rail 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…ways-report-caller
|
Claude finished @kyle-sexton's task in 2m 28s —— View job Tasks
PR Review: ci(security-review) always-report shape adoptionVerdict: approve with one observation and one nit. The core mechanics are correct, the security surface is preserved, and the documentation trail is solid.
|
| # | Pattern |
|---|---|
| 1–3 | .github/**, .claude/**, scripts/** |
| 4–9 | plugins/*/hooks/** through plugins/*/commands/** |
| 10–13 | .claude-plugin/**, REVIEW.md, CLAUDE.md, AGENTS.md |
| 14–15 | plugins/*/src/**, plugins/*/dist/** |
| 16–22 | **/*.sh, **/*.ps1, **/*.mjs, **/*.ts, **/*.js, **/*.cjs, **/.mcp.json |
| 23–26 | **/mcp.json, **/package.json, **/package-lock.json, plugins/*/.claude-plugin/plugin.json |
The format change from YAML-quoted list items (".github/**") to unquoted multiline block scalar (|) is correct — with: inputs accept newline-separated strings, not YAML sequence syntax, and the reusable workflow receives these as a single multiline string.
SHA pin — correct. 99cb082 matches ci-workflows#189's merge SHA. Short-SHA inline comment matches the full SHA. ✓
Security posture — unchanged and correct:
secrets: inheritnot used ✓- Single named secret (
CLAUDE_CODE_OAUTH_TOKEN) ✓ - Workflow-level
permissions: contents: readas a least-privilege default; job-level permissions add only what the security-review job needs (pull-requests: write,id-token: write) ✓ cancel-in-progress: falsepreserved ✓
Header comment accurately describes the deliberate absence of a workflow-level path filter and the wedge risk. Good for future maintainers who might otherwise "restore" the filter.
Observation — billing posture change (expected, justified, but worth noting explicitly):
The old workflow-level paths filter prevented GitHub Actions from allocating a run for non-security-relevant PRs entirely — zero minutes consumed. Now every PR allocates a workflow run; the filtering happens inside the reusable workflow. The trade-off (token overhead on every run vs. name-stable SKIPPED check enabling required-check enforcement) is correctly justified in the PR body and header comment. This is not a concern to block on — just flagging the change for the step-3 required-check cost model.
docs/adr/0002-default-on-ai-review-advisory-with-earned-promotion.md
The ordering correction addendum is logically tight. The key claim — that a skipped uses: job registers a different check name, leaving the child context "Expected" and wedging prose PRs — is cited to community discussion 72708 and corroborated by the GitHub troubleshooting link. The causal chain (ci-workflows-first → caller adoption → ruleset flip) follows directly.
Nit: ADR Decision §1 (line 29) still reads "a PATH FILTER over security-sensitive surfaces" — now a paths input evaluated inside the reusable workflow, not a caller-side filter. ADR immutability convention means the original decision text is appropriately left in place, and the addenda capture the evolution. A future reader reading Decision → Addendum 1 → Addendum 2 in order gets the full picture. No change needed, but awareness: if someone reads only the Decision section they'll see the old framing.
docs/topics/ladder-climb-roadmap/PLAN.md
[DOING] tag and the scope-change note are correct. The note captures the causal constraint ("caller-side if: on the uses: job registers a different check name") and cross-references the ADR addendum. The step-0 outcome (sole consumer = this repo's caller; captured context security-review / security-review) is recorded inline.
Nit (same as prior review): The numbered step list under Phase II still reflects the original ordering (caller first, ci-workflows second). The scope-change prose block above the list corrects this, but a reader skimming the list sees the old order. Adding a (done — ci-workflows#189) annotation to the ci-workflows step and a (this PR) to the caller step would make the list self-documenting without requiring a cross-read. Suggestion only — the prose block is sufficient.
Verification deferred (correct call)
The docs-only skip path (not-applicable verdict → name-stable security-review / security-review conclusion=skipped reads as Success under the required check) is deferred to a follow-up test PR before the step-3 ruleset gate. That's the right sequencing — empirical confirmation before flipping the ruleset.
Overall: Correct implementation. Pattern migration complete, security posture maintained, documentation trail sound. The billing observation is the only new item vs. the prior review; both nits are carry-forwards. Ready to merge once the skip-path verification PR passes.
## What Append the Phase II status line to the roadmap PLAN scope-change note: steps 1–2 landed (ci-workflows#189, standards#229 + sync #827, #825). ## Why This PR is ALSO the plan's step-1 sanity check: it is docs-only (matches none of the caller's 26 security-sensitive patterns), so it must show `security-review / changes` = pass and `security-review / security-review` = skipped (name-stable not-applicable verdict — not Pending, not absent). That observed result gets cited at the step-3 user gate before the ruleset PR opens. No linked issue (status note; #509 completes at step 3). ## Related - #509 — enforcement rail - #825, melodic-software/ci-workflows#189, melodic-software/standards#229 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…4c (#234) ## What Remove the reviewed runner-input contract for `claude-security-review.yml@0a5fd4c` — superseded by the `99cb082` entry (#229). The sole caller re-pinned in claude-code-plugins#825 (merged); `pull_request` runs evaluate the caller from the merge ref, so no open PR resolves the old pin. ## Verification `npm run lint:runner-policy` passed; `npm run test:runner-policy` — first run hit the known Windows EBUSY temp-dir teardown flake (1 fail), three consecutive reruns 227 pass / 0 fail; Linux CI is authoritative. No linked issue. ## Related - #229 (added the 99cb082 entry; recorded this retirement as follow-up) - melodic-software/claude-code-plugins#825 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…-actor exception (#858) ## What - ADR 0002 step-3 addendum: `security-review-gate` org ruleset ACTIVE (github-iac#193 ruleset + #194 App-grant widening, production deploy verified: `security-review / security-review` in `required_status_checks` on this repo's main); operator-ratified skip-actor exception (dependabot[bot], melodic-standards-sync[bot]) with rationale and bounds; the PR-branch caller-file bound stated plainly. New revisit trigger: any skip-actors addition re-opens the exception. - Roadmap PLAN: Phase II [DONE] + step-3 status note. Closes #509. ## Related - ci-workflows#189, standards#229/#234, #825, #828, github-iac#193/#194 - Deploy run: https://github.com/melodic-software/github-iac/actions/runs/29822200383 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
What
Phase II steps 1–2 caller adoption (enforcement rail, #509 — not closed here; step 3 remains):
.github/workflows/claude-security-review.yml: drop the workflow-levelon.pull_request.pathsfilter; pass the same 26 security-sensitive patterns as the reusable workflow's newpathsinput; re-pin to the ci-workflows#189 merge SHA (99cb082). The workflow now triggers on every PR; the reusable workflow'schangesjob decides relevance and a not-applicable PR yields a name-stable SKIPPEDsecurity-review / security-reviewcheck a required-check ruleset reads as success.docs/adr/0002: ordering-correction addendum — ci-workflows-first, because a caller-sideif:on theuses:job registers a DIFFERENT check name when skipped (community discussion 72708: child context stays "Expected" and wedges prose PRs), and caller-first against the old pin would run a full security pass on every prose PR in the interim. Ruleset flip stays LAST (unchanged constraint).docs/topics/ladder-climb-roadmap/PLAN.md: Phase II tagged DOING + dated scope-change note.Phase II step 0 record (per plan sanity check)
gh search codereturned a false empty and was not trusted) — exactly one consumer of the reusable security workflow: this repo's caller. Full sweep archived in session records.security-review / security-review; caller job id and reusable job id unchanged by this PR, so the context is stable pre/post restructure.security-review / security-reviewconclusion=skipped).Verification on THIS PR
This PR touches
.github/**and docs: expectsecurity-review / changesto run andsecurity-review / security-reviewto run a real review (relevant=true). The docs-only skip path gets verified by a follow-up test PR before the step-3 ruleset gate.No linked issue (this PR closes nothing; #509 completes at step 3).
Related
99cb082)🤖 Generated with Claude Code