Repository navigation
Conversation
…s and read the draft without it Each Configuration save authorizes Secret operate on every Secret it binds, so a member with Configuration update but no Secret operate on the bound Slack tokens met enabled Channel Secrets pickers whose Save answered 403. The Agent caller-permissions answer gains configurationSecretsOperate: Secret operate on every Secret the Agent's Configuration binds, answered only to a caller with Configuration read and update. The console treats false like a missing Configuration update: the Configuration, Channels and Channel Secrets views are read-only and say which grant is missing.
… its bound Secrets; add the editor-without-operate story
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: needs changes before merge. What this changesThis PR makes Configuration editing read-only when the caller cannot operate every currently bound Secret. Example: A member has Configuration read and update, but lacks Secret operate on the bound SLACK_APP_TOKEN and SLACK_BOT_TOKEN.
Review scores
ProductKind: Bug fix · Worth it: Yes · Fix scope: Complete Merge readiness⛔ Needs changes before merge - 2 items remain Keep open: this is a useful, maintainer-directed fix for a permission mismatch still present on main. Priority: P2 Before merge
Findings
Tests
Agent review detailsHow this fits togetherThe Console consumes an Agent permission summary from Fastify; OCC reads bound Secret references, and the selected IAM Driver supplies advisory decisions while save operations retain their own authorization. flowchart TB
Member[Namespace member] --> Console[Agent Console]
Console --> API[Permission summary API]
API --> OCC[OCC Configuration metadata]
OCC --> Bindings[Bound Secret references]
API --> IAM[Selected IAM Driver]
IAM --> API
API --> Console
Technical reviewBest possible solution: Keep the accepted advisory gate, add actionable access-recovery guidance, and update the existing Agent-editing flow. Do we have a high-confidence way to reproduce the issue? The current-main editor gate ignores Secret operate, while updateConfiguration authorizes every retained binding; the supplied browser case covers that exact persona, but no tests were run during this read-only review. Is this the best way to solve the issue? The existing permission-summary owner is an appropriate place for this advisory answer, and the maintainer explicitly accepts its conservative treatment of replacement bindings. Full review comments:
Overall correctness: patch is correct AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against c000db1d561d. Provenance checked
TestingProof path: in-process harness. SecurityNone. EvidenceAcceptance criteria:
What I checked:
LabelsLabel changes:
Label justifications:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior. WorkflowClawSweeper edits this one comment on every review. Comment Reviewed October 25, 2026, 6:22 AM ET / 10:22 UTC. |
# Conflicts: # tests/browser/console-agent-detail.test.mjs
… and matches a real save Bind a second Secret (and the first under two names), grant operate on only one, and expect configurationSecretsOperate false; an 'any' check instead of 'every' now fails. A resave of the same values as that caller answers 403, and 200 once operate covers both.
…say why the provisioning guard is skipped
…cs: a missing bound Secret operate makes the draft read-only
Problem
Dogfood finding D707: a member with Configuration
updatebut no Secretoperategot enabled Channel Secrets pickers and an enabled Save channel Secrets. The save then answered403(PATCH Configuration).The gap is wider than Channel Secrets.
updateConfigurationauthorizes Secretoperateon every Secret the saved Configuration binds, including bindings the request leaves unchanged. So for this member, every Configuration save fails while the Configuration binds a Secret they cannot operate: the JSON editor, the Channels drawer and Channel Secrets. The caller-permissions answer from #3600 reports only Configurationupdate, so the console could not tell.Change
API (additive):
GET /namespaces/{namespaceId}/agents/{agentId}/permissionsaddsconfigurationSecretsOperate.truewhen the IAM Driver allows Secretoperateon every Secret the Agent's Configuration binds now, andtruewhen the Configuration binds none.readandupdate; anyone else getsfalse.getConfigurationSecretSources, returns the distinct bound Secret references from the Configuration record (a Secret bound under two names is one IAM check). It requires Configurationreadand does not read the document through the Configuration Driver. UnlikegetConfigurationit skips the provisioning guard: saves are refused while an Agent is provisioning, so the answer enables nothing then, and the guard's409would fail the whole permissions answer.docs/reference/api.mdand the console guide.Console:
configurationSecretsOperate: falsemakes the draft's Configuration, Channels and Channel Secrets read-only, the same views #3600 made followconfigurationUpdate. Each one names the missing grant: "Saving this Configuration needs Secret operate on each Secret it binds, which your access does not include." Server authorization is unchanged. The Channel Secrets read-only texts have one copy incredentials.mts. The console flow doc (agent-editing.md) says a missing bound Secretoperatealso makes the draft read-only.Why this answer and not the other options
read), and with Configurationupdateany save attempt reports the same decision.Verification
tests/integration/console-api.test.mjs, "caller permission summaries…", covers the answer per persona:true.false.false.false.operateon one of the two bound Secrets:false(an "any instead of every" mutant now fails here), and a resave of the same values as that caller answers403.operateon both:true, and the same resave answers200.tests/browser/console-agent-detail.test.mjs, "a Configuration editor without Secret operate on its bound Secrets reads them". On a Slack Agent with both tokens bound:db913e95e8). Two mutants also fail them: the server answeringtrueregardless of the bound Secrets, and the console ignoring the bit.console-apiandgenerated-api-referencepassed 333/333. The browser files are detail, detail-2, save refusals, saves, channels, runtime credentials, agents and agents-2.configurationSecretsOperate: false, and fix(console): show plugin selections and the current version read-only to a reader #3608's "Edit current Configuration" / "Open version draft" entry follows the new bit.console-apipasses 10/10 and its permission test pinned 20/20 at 2 CPUs; the seven Configuration access browser tests pinned 20/20 at 2 CPUs; thechecks-browserlane passed on a remote test VM.agent-editing.mdis 2,489 words by the repo's counter.pnpm openapi:checkequivalent is current.tsc --build, eslint and prettier are clean on the touched files.Screenshots are from the console test fixture at 1440 px: a member with Configuration read+update and Secret read, no Secret operate, on a Slack Agent with both tokens bound. They are simulated UI proof. The picker hint text is fixed separately in #3609.
Risks
operateon the bound Secrets.operate).operateon each Secret the Configuration binds. A caller with Agentupdateand Configurationreadbut nooperateon a bound Secret still gets enabled plugin, authentication and repository editors whose Save answers403. This bit is answered only with Configurationupdate, so the console cannot reuse it for those saves; tracked separately.