From c363fcffb7e4933c1474d696f6119688d5d1ff72 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" Date: Sun, 20 Sep 2026 22:54:15 +0000 Subject: [PATCH] fix(rulesets): retire the four constraints in the canon template; correct the O5 row --- config/README.adoc | 50 +++++++++++++++++++++-------- config/rulesets/Optimus-Extras.json | 6 +--- config/rulesets/README.adoc | 48 +++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 19 deletions(-) create mode 100644 config/rulesets/README.adoc diff --git a/config/README.adoc b/config/README.adoc index 2c82d1e21..24a390f1e 100644 --- a/config/README.adoc +++ b/config/README.adoc @@ -175,20 +175,42 @@ REST API. standing push right. | Integration ids 56611 (codacy), 827041 (gitar-bot), 254 (codecov), 2740 (renovate), 57789 (advanced-security), 1561, 85455, 946600 -| R1/R4 removals, advanced-security needs no bypass. Scanned 2026-09-20: all - 1,026 rulesets over all 453 repos in both estates. No active ruleset grants bypass to - any uninstalled app. 1561, 85455 and 946600 (Codex MCP) each appear exactly once, all - on one *disabled* ruleset — `hyperpolymath/anvomidaviser` id 14968878 `Optimus-Branch`, - which also still grants `always` bypass to RepositoryRole 2 (maintain) and keeps - `code_coverage` / `required_deployments` / `copilot_code_review`, the set §7.3 retired; - delete it rather than re-enabling it. O5 closes for 1561/85455 (no such app, no active - grant) and stays open for 946600. An earlier draft of this row quoted 96-repo sample - counts, including "67 repo rulesets" for 946600, and read this table as if it listed live - grants; both are superseded by the scan above. - Same scan: the only integration bypasses on *active* repo rulesets are oikosbot (6) and - claude (2). Dependabot, github-actions, gitguardian, sonarqubecloud and coderabbitai hold - none — so installing CodeRabbit also means adding its bypass actor to the estate ruleset, - or its auto-fix and commit-queue pushes cannot reach a protected branch. +| R1/R4 removals, advanced-security needs no bypass. + *This row was wrong twice and is now cut from a complete scan: 1,036 rulesets over all 453 + repos, every ruleset fetched individually.* `GET /repos/{o}/{r}/rulesets` omits `rules` and + `bypass_actors` from the objects it lists, so a list-only sweep reports 1,026 rulesets with + empty arrays and finds nothing — which is precisely the "no active ruleset grants bypass to + any uninstalled app" sentence that stood here, and it was false. Read per-ruleset instead. + *Live, active, 2026-09-20:* *gitar-bot (827041) holds `always` bypass on the + `metadatastician` org ruleset `EstateBranching` (id 18225024)*, i.e. on all 43 repos — + `always` defeats `required_signatures` and the PR requirement on every default branch, for an + app that is not installed. 946600 sits on the same org ruleset plus 13 active repo rulesets + (56 in total); 1561 and 85455 on 9 each. RepositoryRole 2 (maintain) with `always` is on 53 + active rulesets, so "the maintain role is dropped" is not yet true. codecov 254, codacy 56611, + renovate 2740 and advanced-security 57789: zero grants — those four are genuinely clear. + *Retired constraints still enforced:* `code_coverage` 130 rulesets (120 repos; the + `minimum_coverage: 95, max_coverage_drop: 3` gate that keeps pushing repos toward an external + coverage uploader), `code_quality` 137, `copilot_code_review` 162, `required_deployments` 78, + `update` 430 (only 11 admit the planner's precondition). `code_scanning` is kept: GitHub-native, + no third-party app behind it. + *Not applied, and not applicable by CI:* ruleset *writes* are refused for this estate's + fine-grained PAT — `PATCH`/`PUT` → 404 while `GET` → 200 and `POST`/`DELETE` are accepted + (measured on `marches`, `standards`, `anvomidaviser` 2026-09-20; `POST` created a probe + ruleset that was deleted again, so treat that capability as real and dangerous). Remediation + therefore ships as reviewable PUT bodies, in the shape + `scripts/plan-ruleset-constraint-repair.rb` already + intends: 96 repo rulesets + the one org ruleset, dry-run validated, each body guarded by a + re-read of live state so a concurrent owner edit is skipped rather than overwritten. + `anvomidaviser/Optimus-Branch` (14968878) is *disabled*, so it fails that planner's + active-only precondition: delete it outright rather than repairing it. + *Still unresolved by design:* 1561 / 85455 / 946600 (`/user/installations` → 403, marketplace + index → 404, no `GET /apps/{slug}` candidate reproduces them), plus two ids this scan is new + to — 262318 and 1658531 — which hold `always` bypass on `EstateBranching`. Unidentified + standing push rights on every default branch in the org; resolve in Settings → Applications + before assuming they are wanted. O5 stays open for all five. + *Keep-list note, still valid:* on active *repo* rulesets the only integration bypasses are + oikosbot (6) and claude (2), so installing CodeRabbit also means adding `coderabbitai` + (347564) to the estate ruleset or its auto-fix pushes cannot reach a protected branch. Note `123` (codecov PR gate) was never a bypass actor — it only ever appears as a jtv-lang required-check context, which is the §11.3 hand-typed-context bug. |=== diff --git a/config/rulesets/Optimus-Extras.json b/config/rulesets/Optimus-Extras.json index 694f63114..13c6904a4 100644 --- a/config/rulesets/Optimus-Extras.json +++ b/config/rulesets/Optimus-Extras.json @@ -12,10 +12,6 @@ { "actor_id": 5, "actor_type": "RepositoryRole", "bypass_mode": "pull_request" } ], "rules": [ - { "type": "code_scanning", "parameters": { "code_scanning_tools": [] } }, - { "type": "required_deployments", "parameters": { "required_deployment_environments": [] } }, - { "type": "code_quality" }, - { "type": "code_coverage" }, - { "type": "copilot_code_review" } + { "type": "code_scanning", "parameters": { "code_scanning_tools": [] } } ] } diff --git a/config/rulesets/README.adoc b/config/rulesets/README.adoc new file mode 100644 index 000000000..1c18925df --- /dev/null +++ b/config/rulesets/README.adoc @@ -0,0 +1,48 @@ += config/rulesets — canonical protection definitions +:toc: + +These files are the estate's intended ruleset state. `base.json` is the default-branch +baseline; `Optimus-Extras.json` carries the extras for repos on the Optimus profile; +`gates-only.json` / `gates.json` describe which workflow files become required contexts; +`immutable-tags.json` is the tag canon. + +== Nothing here is applied automatically + +`scripts/apply-tag-ruleset-canon.sh` converges *only* the tag ruleset, and its own header +records the consequence: after the 2026-09-11 deployment wave the branch-side remediation was +"manual per-repo `gh api` PUTs, because no committed script in this repository globs +`config/rulesets/`". That gap is why `Optimus-Extras.json` could keep four constraints §7.3 +retired (`code_coverage`, `code_quality`, `required_deployments`, `copilot_code_review`) and +re-add them on the next manual convergence, on 120-162 active rulesets estate-wide. The file is +now trimmed; the propagation mechanism is still missing by design, and this note is the +reminder that a template fix without an applier is a half fix. + +`scripts/plan-ruleset-constraint-repair.rb` is the sanctioned planner: it emits a reviewable PUT +body for exactly those retired constraints, optionally dropping one integration's bypass once +GitHub has rejected that app as no longer installed. It never calls GitHub. + +== What a repository token can do + +Measured 2026-09-20 with the estate's fine-grained PAT: + +|=== +| operation | result + +| `GET /repos/OWNER/REPO/rulesets`, `GET .../rulesets/ID` +| 200 — readable, but the list payload omits `rules` and `bypass_actors`; fetch each id + individually or you will conclude the estate is clean when it is not. + +| `PATCH` / `PUT .../rulesets/ID` +| 404 — updates refused, so no workflow or PR can converge protection. + +| `POST .../rulesets`, `DELETE .../rulesets/ID` +| accepted. Treat as a live capability: an over-eager applier can drop a ruleset and leave the + default branch unprotected in the gap, which is worse than the drift it set out to fix. + +| `PATCH /orgs/ORG/rulesets/ID` +| 404 (no `admin:org`), and org rulesets are not writable through the repo endpoint either — + only readable. The `metadatastician` `EstateBranching` fix must be run by an owner session. +|=== + +Consequence for any future applier: PUT-by-id against the live object, never +delete-then-create, and re-read before writing so a concurrent owner edit is skipped.