Repository navigation
perf(security-issue-sync): decide bulk mode, guardrails, drafting, GHSA routing and the push flow as code - #1710
Merged
Merged
Conversation
… and guardrails as code A new issue-sync family in tools/security-management takes the rules of security-issue-sync's bulk mode and its rule-shaped single-tracker steps: the selector and its gh reads, the resolved set, the batched pre-flight read and the no-op rule table, the CVE-impact buckets, the single and bulk confirmation forms, a Guardrails check over the proposal's surfaces, and the Step 6 recap. Gathering state, mining signals and writing comments and drafts stay with the model. The step-bulk-selectors, step-bulk-orchestration, step-3-confirm, step-6-recap and step-guardrails suites become pytest cases named after each former case (86 -> 67 model cases). Behaviour changes: - A malformed CVE token stops the whole selector before any search, and a CVE search keeps only trackers whose CVE tool link field names it (read through github-body-field, not a body regex). - A bulk reply naming an unknown tracker or item, two dispositions for one tracker, or force-sync of a tracker that was not skipped applies nothing. - The Guardrails check flags a reporter CVSS score outside the observed state, another ASF project's name, a bare CVE ID on a markdown surface, the CVE-tool URL in a reporter email and a bare #NNN, per passage. Part of #1672 Generated-by: Claude Opus 5
…GHSA routing and push flow as code Four more rules of security-issue-sync move into the issue-sync family: - security-cc: the security CC of every draft through the project, organization and framework layers, each key from the first layer that declares it (shared.recipients), per the mail-source contract; - draft-backend: Gmail or Maildir, the person over the project, then the Gmail backend (shared.drafting.choose); - ghsa-route: the operator's advisory access tier and how a field edit, collaborator change, state change or reporter reply is delivered; - push-decision: the Step 5b flow — skip, the seven pre-push gates, the session probe, the push and the state verification — checking the title, upgrade-target and CWE long-form gates on the JSON and taking the four judgement gates as the model's verdicts. The step-security-cc, step-draft-backend, step-ghsa-access-tier and step-5b-push-decision suites become pytest cases named after each former case; a new step-5b-judged-gates model suite covers the four gates the model still judges (67 -> 38 model cases for the skill). Behaviour changes: - An explicit null or blank fallback address in the project layer disables the organization's, and the draft is blocked. - An admin-only advisory change after a 403 is never retried and is always a draft relay, never a tracker comment. - A judged gate with no verdict is asked for before the push, never assumed to pass. - The title cascade also strips a bracketed [GHSA-...] ID. - A CVE ID that is not CVE-YYYY-NNNNN never reaches a printed command: push-decision and the deduplicate apply plan refuse it, and quote it. Part of #1672 Generated-by: Claude Opus 5
…he guardrail check CodeQL read `"cveprocess.apache.org" in sentence` as an incomplete URL substring sanitization (py/incomplete-url-substring-sanitization). The check scans proposal text for the CVE-tool URL in a reporter email; it sanitises nothing. A host-anchored pattern says so and keeps the same cases flagged. Generated-by: Claude Opus 5
potiuk
added a commit
that referenced
this pull request
Oct 19, 2026
Hand-sync of tools/spec-loop/specs/ with the functionality that landed between ccb53a3 and 03c15a6. Specs changed: - security-issue-lifecycle: the tools/security-management shared library gains drafting, recipients and numbered; the package reuses github-body-field, generate-cve-json and magpie-vcs (the embargo scrub); every skill of the family now has its CLI family, completing the deep split (#1672); the Validation block runs its pytest suite. - .last-sync bumped to 03c15a6. No spec change needed (specs already updated in the commit itself): 03c15a6 (#1712), c819c90 (#1711), dacf00a (#1710), cb6bb8b (#1705). Exempt: aee01bf (the previous sync), 0bd021f (npm pin bump in prek hooks). Generated-by: Claude Opus 5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Layer 4b (part 1) of the security-family deep split (#1672), after #1705 (cve-allocate) and #1707 (deduplicate): the rule-shaped parts of
security-issue-syncmove into anissue-syncfamily oftools/security-management. Mining signals, thesignals-to-actionstable and the gather recipe stay with the model and follow in part 2.What moves to code
selector,resolveghreads (a malformedCVE-…token stops it before any search); the resolved set (ledger dropped, closedannouncedcut to 90 days, a CVE matched only in its CVE tool link field, capped lists flagged) and the echopreflight-query,preflightbucket,parse-bulk-replyallocated → review-readypush rides the latter), walk order; the merged confirmation syntaxparse-replyshared.numbered)check#NNNsecurity-cc,draft-backendshared.recipients); Gmail or Maildir, then the Gmail backend (shared.drafting.choose)ghsa-routepush-decisionrender-recapNine eval suites become pytest cases named after each former case (
tests/test_issue_sync.py,tests/test_issue_sync_rules.py):step-bulk-selectors,step-bulk-orchestration,step-3-confirm,step-6-recap,step-guardrails,step-security-cc,step-draft-backend,step-ghsa-access-tier,step-5b-push-decision. A newstep-5b-judged-gatesmodel suite covers the four gates the model still judges, and passes 2/2. The skill's model cases go from 86 to 38.SKILL.mdgrows slightly (7,006 → 7,282 tokens): this part adds the router lines but moves no large section out yet;gather.mdandsignals-to-actions.md, the bulk of the skill, are part 2.Behaviour changes
force-syncof a tracker that was not skipped applies nothing.403is never retried, and is always a draft relay, never a tracker comment.[GHSA-…]ID.CVE-YYYY-NNNNNnever reaches a printed command:push-decisionand the deduplicate apply plan (from perf(security-issue-deduplicate): decide and render the merge as code #1707) refuse it, and quote it.Spec
security-issue-lifecycledescribes the new family.Part of #1672
Generative AI disclosure
Drafted with Claude Code (Claude Opus 5) and reviewed by the author.
🤖 Generated with Claude Code