Skip to content

Commit 02996c1

Browse files
ci(fleet-write): the advisory mint comment names its five write rows and both read rows (#31468)
<!-- claude-projects-attribution: {"github_login":"os-project-manager"} --> _Requested by **Leehom** · [project thread](https://claude.ai/code/project/chan_01TenzsRopZj4jMbvjX8uz1X?thread=cmsg_01TenzsRopZj4jMbvjX8uz1X6dgL2t8w3ZnGzrj82kZCCo)_ domain:devx#3 · os-project-manager · session_01FEkQ5okxtTf6xn1wgra68y Fixes #31447 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:`.github/workflows/fleet-write.yml` 里 `permission-repository-advisories` 上方的注释块,只改文字。读权限的消费者从只写 `advisory_read` 改为点名两个:`advisory_read`(单条 advisory 的 GET)和 `advisory_list`(集合 GET,即列表),各自单独成笔。 - 顺带核正:写权限消费者不是卡上说的 FOUR,而是 FIVE。`advisory_versions`(#30135)在 #29620 写这段注释之后才落地,也走同一个 `write` 授权,注释漏了它。 - 风险与回滚:不改任何键、值、`permissions:`、`if:`、`run:` 或步骤,行为不变;回滚即还原本 PR。唯一读这段注释原文的 pin(`validate.mjs` 要求出现 `Unexpected input(s) 'permission-repository-advisories'`)那一行没动。 - 先看:`.github/workflows/fleet-write.yml` 约 154–162 行这一个 hunk。 - 两分钟验证:`node scripts/pm/fleet-write/validate.mjs --self-test`,预期 361 条全绿。 - 需要你做的:受管面 Tier H(`.github/workflows/**`):由你合并,或授权账号 APPROVED 后由席位落地。 ## What changes `.github/workflows/fleet-write.yml`, the comment block above `permission-repository-advisories` in the mint step (L154–L161 on this head), text only: - **Write consumers: FOUR → FIVE.** The list now names `advisory_versions` beside `advisory_report`, `advisory_create`, `advisory_collaborators_add` and `advisory_state`. The card says "FOUR" and that the write count is still right; the order said to recount, and the recount on `origin/main` a40eb02 is five (see Why). - **Read consumers: one → TWO.** The block now names `advisory_read` (one advisory's GET) and `advisory_list` (the collection's GET, the listing), each travelling alone, each minted `permission_repository_advisories=read`, never `write`. - The measurement sentence (2026-11-02, run 41415522766), the ⚠️ EXPECTED warning paragraph and the ⛔ refused-mint sentence are unchanged, only re-wrapped where the line above them moved. - No change to any key, value, `permissions:`, `if:`, `run:` or step. ## Why Each claim in the new comment, checked against `origin/main` a40eb02: | Claim | Code | |---|---| | Five rows write through this grant, each alone | `scripts/pm/fleet-write/ops.mjs` rows `advisory_report` L2502, `advisory_create` L2520, `advisory_collaborators_add` L2542, `advisory_versions` L2554, `advisory_state` L2572: each `permission: 'repository-advisories'`, `alone: true`, no `grant`, so the level is `PERMISSIONS['repository-advisories']` = `'write'` (L2110) through `levelOf` (`validate.mjs` L514). Self-test: `ADVISORY_OPS` (`validate.mjs` L1736) and the "fence grant, accepted side" case mint `write` for all five rows' strokes. | | `advisory_collaborators_add`, `advisory_versions` and `advisory_state` are one advisory's PATCH | `ops.mjs` L2547, L2561–L2562, L2577: `verb: 'PATCH'` on `/repos/${repo}/security-advisories/${a.ghsa_id}`. | | Two rows read through it, each alone, at `read` | `ops.mjs` `advisory_read` L2584 (`grant: 'read'` L2586, `GET .../security-advisories/${a.ghsa_id}` L2591) and `advisory_list` L2598 (`grant: 'read'` L2600, `GET .../security-advisories` L2605); both `alone: true`. | | The validator writes `permission_repository_advisories=read` for either's stroke, never `write` | `validate.mjs` header L132–L136; self-test cases at L2003 (a read's stroke) and L2085 (a listing's stroke), both asserting `permission_repository_advisories=read`. | | An EMPTY value for every other stroke | `validate.mjs` "fence grant, refused side" case (L1863). | When the count was written: #29620 (d280265, 2026-11-02) wrote "FOUR write consumers"; `advisory_versions` landed after it in #30135 (6d1dc7f). `advisory_list` landed in #31418 (efc5e0a, 2026-11-08). ## Tests None owed: workflow comment only, no behaviour changed, so no new test and no ablation. ## Acceptance notes - **Readers of the comment text.** `git grep` on `scripts/**` for every sentence changed (`FOUR write consumers`, `one advisory's GET`, `advisory_read` in the workflow) finds no pin or census reading them. The readers of `fleet-write.yml`'s text in `validate.mjs` (L1304–L1309, L1429, L1599–L1601, L1709–L1715, L1866–L1869) read non-comment `permission-*`, `repositories:`, `owner:`, `run:` and `uses:` lines, the absence of `run_rerun_failed` / `rerun-failed-jobs`, and the literal `Unexpected input(s) 'permission-repository-advisories'`, which stays byte-for-byte. `validate.mjs --self-test` is green on this head. - **Observed, not changed (out of this card's file surface).** `validate.mjs` L578–L583, `tokenPermissionsOf`'s doc comment, still names `advisory_read` alone as adding `repository-advisories: read`; `advisory_list` does too. Same drift as this card, in a file the order kept out of scope. class: observation · reach: none (a doc comment, nothing reads it) · carrier: none. - **Observed, not changed.** The comment above `permission-actions` (L145) says "ONE consumer: the `workflow_dispatch` row", but `run_rerun_failed` (`ops.mjs` L2489, `permission: 'actions'`, `alone: true`) spends the same input. A self-test pin (`validate.mjs` L1601, "ruling 3, no workflow edit") keeps the workflow from naming that op or its path, so any fix would have to count it without naming it. class: observation · reach: none · carrier: none. - **Governed surface.** `node scripts/pm/check-governed-merges.mjs --branch HEAD` on head fcee8b8, exit 3: ```text governed-surface predicate: 1 of 1 path(s) hit the register (13 surfaces govern objectstack). ⛔ GOVERNED — a human merge is the review record for this PR (#9495 regime). ⚖️ landing tier: H(人合) — the maintainer's hand, or an authorized APPROVED review (GOVERNED_APPROVERS) and then the owning seat lands it. .github/workflows/** ×1 — CI, deploy and release workflows: what runs on every push, what deploys, what gates the queue - .github/workflows/fleet-write.yml ⚠️ head repo: NOT MEASURED — this verdict cannot tell a fork PR from an internal one; `--pr <n>` reads it. size: 17 changed line(s) (+9 / -8) ≤ 3000 — under the human-merge threshold (generated files included in the count). ``` - `node scripts/pm/dispatch-gates.mjs --tier`: "Model tier — no path-derived mandate: the surface hits none of the 4 declared glob(s)". ## Verification Gate union derived by `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (37 families for this diff), run on head `fcee8b840`, each exit code captured before any pipe: - **37 run, exit 0 each**, `pnpm check:pm-dispatch-gates` among them (fast tier, 2205 cases). `--ran`: "37 derived famil(ies) accounted for — 37 run, 0 NOT-MEASURED". - Also run, outside the derivation: `node scripts/pm/fleet-write/validate.mjs --self-test` exit 0 (361 cases, 18 batteries), `execute.mjs --self-test` exit 0 (306 cases), `ops.mjs --self-test` exit 0, and a YAML parse of the workflow, exit 0. - `pnpm lint`: the diff touches no package, so there is no scoped package lint; eslint does not read workflow YAML. - CI families are read from this PR's check-runs, not re-run here. `skip-changeset`: a workflow file, published by no package. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01FEkQ5okxtTf6xn1wgra68y Co-authored-by: Claude <noreply@anthropic.com>
1 parent e115841 commit 02996c1

1 file changed

Lines changed: 9 additions & 8 deletions

File tree

‎.github/workflows/fleet-write.yml‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -151,14 +151,15 @@ jobs:
151151
# also reaches cancel, re-run, delete, cache and artifact endpoints; the op table has no
152152
# row for any of them, and `validate.mjs --self-test` pins that none is reachable.
153153
permission-actions: ${{ steps.validate.outputs.permission_actions }}
154-
# FOUR write consumers, one at a time: the advisory rows — `advisory_report` (one private report),
155-
# `advisory_create` (one draft advisory), `advisory_collaborators_add` and `advisory_state` (one
156-
# advisory's PATCH). Minted ONLY for a stroke carrying one of them, which travels alone, the same
157-
# way as `permission-actions`: the validator writes `permission_repository_advisories=write` for it
158-
# and an EMPTY value for every other stroke. Separately, `advisory_read` (one advisory's GET, also
159-
# alone) gets a READ-ONLY mint through this same input: the validator writes
160-
# `permission_repository_advisories=read` for its stroke, never `write`. Measured 2026-11-02 with
161-
# this action and a control token minted without the grant
154+
# FIVE write consumers, one at a time: the advisory rows — `advisory_report` (one private report),
155+
# `advisory_create` (one draft advisory), `advisory_collaborators_add`, `advisory_versions` and
156+
# `advisory_state` (one advisory's PATCH). Minted ONLY for a stroke carrying one of them, which
157+
# travels alone, the same way as `permission-actions`: the validator writes
158+
# `permission_repository_advisories=write` for it and an EMPTY value for every other stroke.
159+
# Separately, TWO read consumers, each also alone, get a READ-ONLY mint through this same input:
160+
# `advisory_read` (one advisory's GET) and `advisory_list` (the collection's GET, the listing). The
161+
# validator writes `permission_repository_advisories=read` for either's stroke, never `write`.
162+
# Measured 2026-11-02 with this action and a control token minted without the grant
162163
# (run 41415522766): the narrowed mint succeeds, and the grant opens an advisory's read and PATCH.
163164
# ⚠️ EXPECTED: such a run warns "Unexpected input(s) 'permission-repository-advisories'", because
164165
# the action's `action.yml` does not declare the input; its `lib/get-permissions-from-inputs.js`

0 commit comments

Comments
 (0)