Repository navigation
Description
Raised by the dev seat on #10243 / PR #11660 as an open question, and filed here rather than ridden
into that PR: it is a user-visible copy change the maintainer's ruling did not ask for, and the
ruling was specifically "one predicate, no new capability name". Filed unassigned.
What a caller sees after #10243
POST /api/v1/automation/:name/toggle now requires manage_metadata (maintainer ruling on #10243,
option A). A caller without it is refused with the shared constant:
Authoring automation flows requires the \manage_metadata` capability.`
They were disabling a flow, not authoring one. The sentence is accurate about the policy — the
ruling classified toggle into the authoring write set — but it names a verb the caller did not use.
Why it was not fixed in #11660, and why that was right
- The ruling authorized one arm on one predicate. A second refusal constant is new surface, however
small, and fix(runtime): POST /automation/:name/toggle joins the manage_metadata write set #11660 was already carrying a breaking change (200 → 403) plus seven moved surfaces. - The message satisfies The runtime dispatcher serialises a PermissionDeniedError's
detailsto the client, sopositions/permissionSetsreach the browser on the/datatransport #7450's actual requirement: it names the capability that would admit the
caller. It is unhelpful, not wrong, and not a security defect.
The shape, if this is graded as work
The dev seat laid out three and recommended keeping A for that PR:
| option | cost | |
|---|---|---|
| A | keep the single shared message (shipped in #11660) | zero; one predicate, one refusal vocabulary |
| B | a toggle-specific sentence with the same code and status | one constant + one arm in refuseUngrantedFlowWrite |
| C | reword the shared message to cover both ("Authoring or enabling …") | one edit, but slightly degrades the message for the three definition writes |
⭐ B has an in-domain precedent one screen over: SCREEN_READ_DENY_MESSAGE sits beside
RUN_READ_DENY_MESSAGE in this very file (#7968) — a different question asked, a different sentence
returned. That is the argument for B being the long-term shape rather than a nicety.
⛔ Whichever way this is graded, the code and status must not move. PERMISSION_DENIED / 403 is
what #11660's pins and the ADR-0112 vocabulary assert; only the human-readable prose is in question.
Related
- Decide whether POST /api/v1/automation/:name/toggle belongs in the manage_metadata write set — it mutates flow enablement with no authoring capability #10243 — the ruling and the capability change.
- PR fix(runtime): POST /automation/:name/toggle joins the manage_metadata write set #11660 — where the shared message is now reached by the toggle path.
- finding:
GET /automation/:name/runs/:runId/screenstill discloses record-derived values to any authenticated caller who knows a run id #7968 — the precedent for a per-question refusal sentence in the same file. - The runtime dispatcher serialises a PermissionDeniedError's
detailsto the client, sopositions/permissionSetsreach the browser on the/datatransport #7450 — the requirement the current message already satisfies (name what would admit the caller).
Activity
claude commentedon Aug 25, 2026
Concentrated triage batch:
finding→pm:queue+domain:cli, Task. Premise re-verified: the shared constant (automation.ts:297) is still the only refusal string, so a refused toggle is told it was "authoring". Scope ruled at grading: add a second refusal constant for the enable/disable arm naming the operation actually attempted (same capability name, same status, same #7450 compliance — copy only, no policy change; the #10243 ruling's policy classification is untouched). Size: S.Generated by Claude Code
fix(runtime): the enablement door refuses in its own words (objectsta…
fix(runtime): the resume door checks WHO is resuming — the run's star…