Skip to content

fix(approvals): fail closed plugin tool gates#103932

Merged
steipete merged 1 commit into
codex/durable-approval-registryfrom
codex/approval-fail-closed-tools
Jul 12, 2026
Merged

fix(approvals): fail closed plugin tool gates#103932
steipete merged 1 commit into
codex/durable-approval-registryfrom
codex/approval-fail-closed-tools

Conversation

@steipete

Copy link
Copy Markdown
Contributor

Related to #103505.

Stacked on #103921; review only the final commit in this PR.

What Problem This Solves

Plugin tool gates still had three ways to hand out execution authority without a valid, bound approval:

  • the legacy timeoutBehavior: "allow" option could execute after a timeout or unavailable reviewer;
  • a trusted but malformed or request-disallowed verdict could be treated as approval;
  • the node policy runtime returned allow-once without atomically consuming that one-shot authority.

The file-transfer plugin also treated approval results too loosely at its final dispatch boundary.

Why This Change Was Made

The durable approval lifecycle needs a strict final invariant: only an exact allow-once or allow-always verdict, permitted by the request and bound to the parked approval ID, may release a tool gate.

This change therefore:

  • fails closed for timeout, missing, malformed, mismatched, and request-disallowed plugin decisions in Gateway and embedded modes;
  • retains timeoutBehavior as a deprecated plugin API field but ignores it at runtime;
  • binds plugin.approval.waitDecision results to the requested approval ID;
  • consumes node-policy allow-once before returning execution authority;
  • makes file-transfer approval parsing exact while preserving one approval for the logical preflight plus final invoke operation;
  • updates plugin documentation, the approval design note, and the changelog.

The exec-host askFallback cutover is intentionally not included. PR #103515 is concurrently refactoring that authorization transaction boundary; the strict exec delta should follow after that work lands rather than duplicate or conflict with it.

User Impact

Unanswered, unavailable, malformed, stale, or mismatched plugin approvals no longer execute tools. Existing plugins may continue sending the legacy timeoutBehavior field, but setting it to allow no longer grants authority after timeout. Explicit permitted approvals continue to work, and file-transfer allow-always persistence is unchanged.

Evidence

  • Blacksmith Testbox tbx_01kx6r6jmg877rbq9wmyhmdfn7:
    • corepack pnpm test src/agents/agent-tools.before-tool-call.e2e.test.ts src/agents/agent-tools.before-tool-call.embedded-mode.test.ts src/gateway/node-invoke-plugin-policy.test.ts extensions/file-transfer/src/shared/node-invoke-policy.test.ts
    • 173 focused tests passed across four Vitest projects: 82 agent E2E, 18 embedded, 48 Gateway matrix, 25 file-transfer.
    • corepack pnpm tsgo:core
    • corepack pnpm tsgo:test:src
    • corepack pnpm docs:check-mdx — 705 files passed.
  • Source-blind behavior validation against the production file-transfer policy: 7/7 contract checks and 3/3 path-variation probes passed; deny, null/timeout, missing, and malformed verdicts made zero node calls.
  • Targeted oxlint and git diff --check passed.
  • Fresh committed-tree autoreview against codex/approval-ancestor-propagation: no actionable findings, confidence 0.86.

No screenshots or transcript logs attached.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation gateway Gateway runtime agents Agent runtime and tooling plugin: file-transfer size: M maintainer Maintainer-authored PR labels Jul 10, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P0 Emergency: data loss, security bypass, crash loop, or unusable core runtime. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. labels Jul 10, 2026
@clawsweeper

clawsweeper Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 11, 2026, 10:31 PM ET / July 12, 2026, 02:31 UTC.

Summary
The PR makes plugin and native approval gates reject unresolved, malformed, disallowed, or mismatched decisions, consumes one-shot node-policy approvals before releasing execution authority, and tightens file-transfer approval parsing.

PR surface: Source +43, Tests +409, Docs +8, Generated 0. Total +460 across 16 files.

Reproducibility: yes. at source level: current main honors timeout allow, leaves sibling waiter results unbound to their originating approval ID, and returns node-policy allow-once without consuming it.

Review metrics: 1 noteworthy metric.

  • Plugin API behavior: 1 deprecated field retained, 1 runtime behavior changed. The field remains accepted, but its allow value no longer grants execution after timeout.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #103505
Summary: This PR is the fail-closed tool-gate implementation slice of the durable approvals program.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦞 diamond lobster
Proof: 🦞 diamond lobster
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Risk before merge

  • [P1] Existing plugins that rely on requireApproval.timeoutBehavior:"allow" will deny after upgrade even though the field remains accepted for one deprecation release train.
  • [P1] The stacked parent currently fails lint and mobile protocol-event coverage, so this exact stack cannot merge until those parent-owned gates are corrected.

Maintainer options:

  1. Approve the fail-closed release cutover (recommended)
    Accept the legacy plugin behavior break and merge once the exact stacked head has green required checks.
  2. Stage compatibility first
    Preserve timeout allow until a separately reviewed strict-mode or migration path is ready.
  3. Pause the stack
    Defer this slice if the approval security transition should land with the remaining exec timeout work.

Next step before merge

  • [P2] A human must accept the immediate plugin compatibility and security-boundary cutover; the stacked parent must also clear its existing gates before merge.

Maintainer decision needed

  • Question: Should unresolved plugin approvals fail closed immediately even for plugins that still set the accepted legacy timeoutBehavior:"allow" field?
  • Rationale: The implementation closes an execution-authorization gap but deliberately removes authority from an accepted plugin API behavior, so release compatibility intent must be explicit.
  • Likely owner: steipete — Recent merged approval work and the current stacked implementation make this the strongest history-backed owner for the cutover decision.
  • Options:
    • Accept fail-closed cutover (recommended): Keep the field parse-compatible for one release train while making every unresolved approval deny immediately.
    • Stage strict semantics: Preserve timeout allow temporarily and introduce a separately approved strict transition path.
    • Pause for combined transition: Defer this slice until the remaining exec timeout cutover can be reviewed as one authorization release change.

Security
Cleared: The patch narrows execution authority and adds no secrets, permissions, dependencies, downloads, or new third-party execution path.

Review details

Best possible solution:

Keep the strict fail-closed implementation, retain the legacy field only for one documented deprecation train, and land after explicit owner acceptance and green exact-stack gates.

Do we have a high-confidence way to reproduce the issue?

Yes at source level: current main honors timeout allow, leaves sibling waiter results unbound to their originating approval ID, and returns node-policy allow-once without consuming it.

Is this the best way to solve the issue?

Yes technically: the patch enforces strict verdict parsing at final gate boundaries and consumes one-shot authority where it is handed to plugin policy code; the release cutover remains a human compatibility and security choice.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 01fc1ed02a50.

Label changes

Label justifications:

  • P0: Current behavior can release plugin-gated tool execution without a valid resolved approval, which is an authorization-boundary bypass.
  • merge-risk: 🚨 compatibility: Existing plugins relying on timeoutBehavior:"allow" will deny after upgrade despite the field remaining accepted.
  • merge-risk: 🚨 security-boundary: The PR changes the final condition that releases tool-execution authority and consumes one-shot approvals.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): Source-blind production-policy validation and focused Testbox runtime output show invalid decisions produce zero node dispatches.
  • proof: sufficient: Contributor real behavior proof is sufficient. Source-blind production-policy validation and focused Testbox runtime output show invalid decisions produce zero node dispatches.
Evidence reviewed

PR surface:

Source +43, Tests +409, Docs +8, Generated 0. Total +460 across 16 files.

View PR surface stats
Area Files Added Removed Net
Source 6 94 51 +43
Tests 6 443 34 +409
Docs 3 16 8 +8
Config 0 0 0 0
Generated 1 2 2 0
Other 0 0 0 0
Total 16 555 95 +460

What I checked:

Likely related people:

  • steipete: Recent merged cross-surface approval work and the current approval-stack history connect this handle to the affected gateway, agent, and plugin authorization paths. (role: recent approval feature owner; confidence: high; commits: 7a456e362d0b, 2e3be08653d9; files: src/agents/agent-tools.before-tool-call.ts, src/gateway/node-invoke-plugin-policy.ts, extensions/codex/src/app-server/plugin-approval-roundtrip.ts)
  • Brian Mendonca: The existing consumeAllowOnce replay-protection invariant appears to date to this contributor's approval-manager change. (role: introduced one-shot consumption behavior; confidence: medium; commits: 3f5e7f815668; files: src/gateway/exec-approval-manager.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (4 earlier review cycles)
  • reviewed 2026-07-10T20:47:56.096Z sha 5acd4de :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-11T14:53:14.553Z sha b9780e2 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-12T01:03:09.931Z sha 7682980 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-12T01:32:47.453Z sha a8b493f :: needs maintainer review before merge. :: none

@steipete
steipete force-pushed the codex/approval-ancestor-propagation branch from 0077d9e to 1ec7715 Compare July 11, 2026 14:24
@steipete
steipete force-pushed the codex/approval-fail-closed-tools branch from 5acd4de to 7e84b46 Compare July 11, 2026 14:24
@steipete
steipete force-pushed the codex/approval-ancestor-propagation branch from 1ec7715 to 593e3ab Compare July 11, 2026 14:31
@steipete
steipete force-pushed the codex/approval-fail-closed-tools branch from 7e84b46 to 1053f33 Compare July 11, 2026 14:31
@steipete

Copy link
Copy Markdown
Contributor Author

Land-ready update: rebased through the reconciled stack; slice review clean ("consistently fails closed for missing, malformed, mismatched, timed-out, and disallowed plugin approval decisions", 0.95).

Additions since the last head: plugin.approval.waitDecision replies are now bound to the requested approval id at the two sibling waiters the original PR missed — the native hook relay and the Codex plugin approval roundtrip (verified against the sibling codex-rs app-server protocol: a mismatched reply maps to a protocol-valid decline, mirroring Codex's own TimedOut → Decline); a once-per-plugin runtime warning fires when the deprecated timeoutBehavior: "allow" arrives, and its JSDoc names the removal train. Follow-up filed for the strict exec askFallback cutover now that #103515 has merged.

Validation: relay-binding, embedded-mode, and gateway matrix suites green on Testbox (tbx_01kx8r0r4g46agd58kdt2rqbfg); structured Codex reviews of both fix commits clean.

@steipete
steipete force-pushed the codex/approval-ancestor-propagation branch from 593e3ab to be22413 Compare July 11, 2026 14:34
@steipete
steipete force-pushed the codex/approval-fail-closed-tools branch from 1053f33 to b9780e2 Compare July 11, 2026 14:34
@steipete
steipete marked this pull request as ready for review July 11, 2026 14:38
@clawsweeper clawsweeper Bot removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 11, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. labels Jul 11, 2026
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels Jul 12, 2026
@steipete
steipete force-pushed the codex/approval-ancestor-propagation branch from 9e904ef to 678f238 Compare July 12, 2026 01:23
steipete added a commit that referenced this pull request Jul 12, 2026
Squash-rebased #103932 segment onto the ancestor-propagation tip on
current main. Plugin node.invoke approvals claim a one-shot allow-once
decision before handing execution authority to the policy, so observation
or retry cannot replay a consumed approval; sibling tool gates bind
approval ids to their originating reviewer identity.

(cherry picked from commit 122df0d75281f572c012b6484ed5daf085d1d577)
(cherry picked from commit f23d8ac240a8dcf2a42c4daaae962263975a0ae8)
(cherry picked from commit 8632fb6436a224dac7a9a9ef0216884530de2c24)
(cherry picked from commit d9fe2dd5c53665e5732f5f3da5ed1907a686ade8)
(cherry picked from commit bb139f2c8aa36ddad70413e1ef79ff491a6f2ecd)
(cherry picked from commit 9b3e056b68ea515c7d4baef269289b6670570480)
(cherry picked from commit b11e66b59a7af1f3b08712de06864aed64d349e4)
(cherry picked from commit a12916ee592d03dfa35e86a2aaede4476a5d4e5d)
(cherry picked from commit d699de840fc8346892b9ae244fe3c3e8c4413032)
(cherry picked from commit 9b7e5a9)
(cherry picked from commit 4b507593f1b2f10b4496984c84a2803b853e5c5e)
(cherry picked from commit 56408a186733c4eeb5aa76bd5907cde7b0cd3d5b)
(cherry picked from commit a4051d6d8353d39d6fa0b5d69c36e06c3cd3e796)
(cherry picked from commit 7682980)
@steipete
steipete force-pushed the codex/approval-fail-closed-tools branch from 7682980 to a8b493f Compare July 12, 2026 01:23
@clawsweeper clawsweeper Bot added rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Jul 12, 2026
@steipete
steipete force-pushed the codex/approval-ancestor-propagation branch from 678f238 to 72842e5 Compare July 12, 2026 02:08
steipete added a commit that referenced this pull request Jul 12, 2026
Squash-rebased #103932 segment onto the ancestor-propagation tip on
current main. Plugin node.invoke approvals claim a one-shot allow-once
decision before handing execution authority to the policy, so observation
or retry cannot replay a consumed approval; sibling tool gates bind
approval ids to their originating reviewer identity.

(cherry picked from commit 122df0d75281f572c012b6484ed5daf085d1d577)
(cherry picked from commit f23d8ac240a8dcf2a42c4daaae962263975a0ae8)
(cherry picked from commit 8632fb6436a224dac7a9a9ef0216884530de2c24)
(cherry picked from commit d9fe2dd5c53665e5732f5f3da5ed1907a686ade8)
(cherry picked from commit bb139f2c8aa36ddad70413e1ef79ff491a6f2ecd)
(cherry picked from commit 9b3e056b68ea515c7d4baef269289b6670570480)
(cherry picked from commit b11e66b59a7af1f3b08712de06864aed64d349e4)
(cherry picked from commit a12916ee592d03dfa35e86a2aaede4476a5d4e5d)
(cherry picked from commit d699de840fc8346892b9ae244fe3c3e8c4413032)
(cherry picked from commit 9b7e5a9)
(cherry picked from commit 4b507593f1b2f10b4496984c84a2803b853e5c5e)
(cherry picked from commit 56408a186733c4eeb5aa76bd5907cde7b0cd3d5b)
(cherry picked from commit a4051d6d8353d39d6fa0b5d69c36e06c3cd3e796)
(cherry picked from commit 7682980)
(cherry picked from commit a8b493f)
@steipete
steipete force-pushed the codex/approval-fail-closed-tools branch from a8b493f to aceb990 Compare July 12, 2026 02:08
steipete added a commit that referenced this pull request Jul 12, 2026
Squash-rebased #103932 segment onto the ancestor-propagation tip on
current main. Plugin node.invoke approvals claim a one-shot allow-once
decision before handing execution authority to the policy, so observation
or retry cannot replay a consumed approval; sibling tool gates bind
approval ids to their originating reviewer identity.

(cherry picked from commit 122df0d75281f572c012b6484ed5daf085d1d577)
(cherry picked from commit f23d8ac240a8dcf2a42c4daaae962263975a0ae8)
(cherry picked from commit 8632fb6436a224dac7a9a9ef0216884530de2c24)
(cherry picked from commit d9fe2dd5c53665e5732f5f3da5ed1907a686ade8)
(cherry picked from commit bb139f2c8aa36ddad70413e1ef79ff491a6f2ecd)
(cherry picked from commit 9b3e056b68ea515c7d4baef269289b6670570480)
(cherry picked from commit b11e66b59a7af1f3b08712de06864aed64d349e4)
(cherry picked from commit a12916ee592d03dfa35e86a2aaede4476a5d4e5d)
(cherry picked from commit d699de840fc8346892b9ae244fe3c3e8c4413032)
(cherry picked from commit 9b7e5a9)
(cherry picked from commit 4b507593f1b2f10b4496984c84a2803b853e5c5e)
(cherry picked from commit 56408a186733c4eeb5aa76bd5907cde7b0cd3d5b)
(cherry picked from commit a4051d6d8353d39d6fa0b5d69c36e06c3cd3e796)
(cherry picked from commit 7682980)
(cherry picked from commit a8b493f)
(cherry picked from commit aceb990)
@steipete
steipete force-pushed the codex/approval-ancestor-propagation branch from 72842e5 to be74c25 Compare July 12, 2026 02:16
@steipete
steipete force-pushed the codex/approval-fail-closed-tools branch from aceb990 to a29b0e7 Compare July 12, 2026 02:16
Squash-rebased #103932 segment onto the ancestor-propagation tip on
current main. Plugin node.invoke approvals claim a one-shot allow-once
decision before handing execution authority to the policy, so observation
or retry cannot replay a consumed approval; sibling tool gates bind
approval ids to their originating reviewer identity.

(cherry picked from commit 122df0d75281f572c012b6484ed5daf085d1d577)
(cherry picked from commit f23d8ac240a8dcf2a42c4daaae962263975a0ae8)
(cherry picked from commit 8632fb6436a224dac7a9a9ef0216884530de2c24)
(cherry picked from commit d9fe2dd5c53665e5732f5f3da5ed1907a686ade8)
(cherry picked from commit bb139f2c8aa36ddad70413e1ef79ff491a6f2ecd)
(cherry picked from commit 9b3e056b68ea515c7d4baef269289b6670570480)
(cherry picked from commit b11e66b59a7af1f3b08712de06864aed64d349e4)
(cherry picked from commit a12916ee592d03dfa35e86a2aaede4476a5d4e5d)
(cherry picked from commit d699de840fc8346892b9ae244fe3c3e8c4413032)
(cherry picked from commit 9b7e5a9)
(cherry picked from commit 4b507593f1b2f10b4496984c84a2803b853e5c5e)
(cherry picked from commit 56408a186733c4eeb5aa76bd5907cde7b0cd3d5b)
(cherry picked from commit a4051d6d8353d39d6fa0b5d69c36e06c3cd3e796)
(cherry picked from commit 7682980)
(cherry picked from commit a8b493f)
(cherry picked from commit aceb990)
(cherry picked from commit a29b0e7)
@steipete
steipete force-pushed the codex/approval-ancestor-propagation branch from be74c25 to 93ba8c4 Compare July 12, 2026 02:18
@steipete
steipete force-pushed the codex/approval-fail-closed-tools branch from a29b0e7 to 2e3be08 Compare July 12, 2026 02:18
Base automatically changed from codex/approval-ancestor-propagation to codex/durable-approval-registry July 12, 2026 02:35
@steipete
steipete merged commit 2e3be08 into codex/durable-approval-registry Jul 12, 2026
79 of 81 checks passed
@steipete
steipete deleted the codex/approval-fail-closed-tools branch July 12, 2026 02:35
w3evolutions pushed a commit to W3EvolutionsLLC/openclaw that referenced this pull request Jul 12, 2026
Squash-rebased openclaw#103932 segment onto the ancestor-propagation tip on
current main. Plugin node.invoke approvals claim a one-shot allow-once
decision before handing execution authority to the policy, so observation
or retry cannot replay a consumed approval; sibling tool gates bind
approval ids to their originating reviewer identity.

(cherry picked from commit 122df0d75281f572c012b6484ed5daf085d1d577)
(cherry picked from commit f23d8ac240a8dcf2a42c4daaae962263975a0ae8)
(cherry picked from commit 8632fb6436a224dac7a9a9ef0216884530de2c24)
(cherry picked from commit d9fe2dd5c53665e5732f5f3da5ed1907a686ade8)
(cherry picked from commit bb139f2c8aa36ddad70413e1ef79ff491a6f2ecd)
(cherry picked from commit 9b3e056b68ea515c7d4baef269289b6670570480)
(cherry picked from commit b11e66b59a7af1f3b08712de06864aed64d349e4)
(cherry picked from commit a12916ee592d03dfa35e86a2aaede4476a5d4e5d)
(cherry picked from commit d699de840fc8346892b9ae244fe3c3e8c4413032)
(cherry picked from commit 9b7e5a9)
(cherry picked from commit 4b507593f1b2f10b4496984c84a2803b853e5c5e)
(cherry picked from commit 56408a186733c4eeb5aa76bd5907cde7b0cd3d5b)
(cherry picked from commit a4051d6d8353d39d6fa0b5d69c36e06c3cd3e796)
(cherry picked from commit 7682980)
(cherry picked from commit a8b493f)
(cherry picked from commit aceb990)
(cherry picked from commit a29b0e7)
(cherry picked from commit 2e3be08)
steipete added a commit that referenced this pull request Jul 12, 2026
… gates

Squash of the remaining stack (#103912 native clients, #103921 ancestor
propagation, #103932 fail-closed gates — merged into this branch) plus the
main-gate repairs (hermetic model discovery via the provider-runtime
boundary, usage-cost settle-budget contract assertion, control-ui raw-copy
baseline, docs map, native i18n inventory, session.approval protocol
coverage allowlist, plugin-sdk DTS budget for approval wire types, Android
createdAtMs capture for canonical approval readback).
steipete added a commit that referenced this pull request Jul 12, 2026
… gates

Squash of the remaining stack (#103912 native clients, #103921 ancestor
propagation, #103932 fail-closed gates — merged into this branch) plus the
main-gate repairs (hermetic model discovery via the provider-runtime
boundary, usage-cost settle-budget contract assertion, control-ui raw-copy
baseline, docs map, native i18n inventory, session.approval protocol
coverage allowlist, plugin-sdk DTS budget for approval wire types, Android
createdAtMs capture for canonical approval readback).
steipete added a commit that referenced this pull request Jul 12, 2026
… gates

Squash of the remaining stack (#103912 native clients, #103921 ancestor
propagation, #103932 fail-closed gates — merged into this branch) plus the
main-gate repairs (hermetic model discovery via the provider-runtime
boundary, usage-cost settle-budget contract assertion, control-ui raw-copy
baseline, docs map, native i18n inventory, session.approval protocol
coverage allowlist, plugin-sdk DTS budget for approval wire types, Android
createdAtMs capture for canonical approval readback).
steipete added a commit that referenced this pull request Jul 12, 2026
Squash-rebased #103932 segment onto the ancestor-propagation tip on
current main. Plugin node.invoke approvals claim a one-shot allow-once
decision before handing execution authority to the policy, so observation
or retry cannot replay a consumed approval; sibling tool gates bind
approval ids to their originating reviewer identity.

(cherry picked from commit 122df0d75281f572c012b6484ed5daf085d1d577)
(cherry picked from commit f23d8ac240a8dcf2a42c4daaae962263975a0ae8)
(cherry picked from commit 8632fb6436a224dac7a9a9ef0216884530de2c24)
(cherry picked from commit d9fe2dd5c53665e5732f5f3da5ed1907a686ade8)
(cherry picked from commit bb139f2c8aa36ddad70413e1ef79ff491a6f2ecd)
(cherry picked from commit 9b3e056b68ea515c7d4baef269289b6670570480)
(cherry picked from commit b11e66b59a7af1f3b08712de06864aed64d349e4)
(cherry picked from commit a12916ee592d03dfa35e86a2aaede4476a5d4e5d)
(cherry picked from commit d699de840fc8346892b9ae244fe3c3e8c4413032)
(cherry picked from commit 9b7e5a9)
(cherry picked from commit 4b507593f1b2f10b4496984c84a2803b853e5c5e)
(cherry picked from commit 56408a186733c4eeb5aa76bd5907cde7b0cd3d5b)
(cherry picked from commit a4051d6d8353d39d6fa0b5d69c36e06c3cd3e796)
(cherry picked from commit 7682980)
(cherry picked from commit a8b493f)
(cherry picked from commit aceb990)
(cherry picked from commit a29b0e7)
(cherry picked from commit 2e3be08)
(cherry picked from commit c9ae3d7)
steipete added a commit that referenced this pull request Jul 12, 2026
Squash-rebased #103932 segment onto the ancestor-propagation tip on
current main. Plugin node.invoke approvals claim a one-shot allow-once
decision before handing execution authority to the policy, so observation
or retry cannot replay a consumed approval; sibling tool gates bind
approval ids to their originating reviewer identity.

(cherry picked from commit 122df0d75281f572c012b6484ed5daf085d1d577)
(cherry picked from commit f23d8ac240a8dcf2a42c4daaae962263975a0ae8)
(cherry picked from commit 8632fb6436a224dac7a9a9ef0216884530de2c24)
(cherry picked from commit d9fe2dd5c53665e5732f5f3da5ed1907a686ade8)
(cherry picked from commit bb139f2c8aa36ddad70413e1ef79ff491a6f2ecd)
(cherry picked from commit 9b3e056b68ea515c7d4baef269289b6670570480)
(cherry picked from commit b11e66b59a7af1f3b08712de06864aed64d349e4)
(cherry picked from commit a12916ee592d03dfa35e86a2aaede4476a5d4e5d)
(cherry picked from commit d699de840fc8346892b9ae244fe3c3e8c4413032)
(cherry picked from commit 9b7e5a9)
(cherry picked from commit 4b507593f1b2f10b4496984c84a2803b853e5c5e)
(cherry picked from commit 56408a186733c4eeb5aa76bd5907cde7b0cd3d5b)
(cherry picked from commit a4051d6d8353d39d6fa0b5d69c36e06c3cd3e796)
(cherry picked from commit 7682980)
(cherry picked from commit a8b493f)
(cherry picked from commit aceb990)
(cherry picked from commit a29b0e7)
(cherry picked from commit 2e3be08)
(cherry picked from commit c9ae3d7)
steipete added a commit that referenced this pull request Jul 12, 2026
Squash-rebased #103932 segment onto the ancestor-propagation tip on
current main. Plugin node.invoke approvals claim a one-shot allow-once
decision before handing execution authority to the policy, so observation
or retry cannot replay a consumed approval; sibling tool gates bind
approval ids to their originating reviewer identity.

(cherry picked from commit 122df0d75281f572c012b6484ed5daf085d1d577)
(cherry picked from commit f23d8ac240a8dcf2a42c4daaae962263975a0ae8)
(cherry picked from commit 8632fb6436a224dac7a9a9ef0216884530de2c24)
(cherry picked from commit d9fe2dd5c53665e5732f5f3da5ed1907a686ade8)
(cherry picked from commit bb139f2c8aa36ddad70413e1ef79ff491a6f2ecd)
(cherry picked from commit 9b3e056b68ea515c7d4baef269289b6670570480)
(cherry picked from commit b11e66b59a7af1f3b08712de06864aed64d349e4)
(cherry picked from commit a12916ee592d03dfa35e86a2aaede4476a5d4e5d)
(cherry picked from commit d699de840fc8346892b9ae244fe3c3e8c4413032)
(cherry picked from commit 9b7e5a9)
(cherry picked from commit 4b507593f1b2f10b4496984c84a2803b853e5c5e)
(cherry picked from commit 56408a186733c4eeb5aa76bd5907cde7b0cd3d5b)
(cherry picked from commit a4051d6d8353d39d6fa0b5d69c36e06c3cd3e796)
(cherry picked from commit 7682980)
(cherry picked from commit a8b493f)
(cherry picked from commit aceb990)
(cherry picked from commit a29b0e7)
(cherry picked from commit 2e3be08)
(cherry picked from commit c9ae3d7)
steipete added a commit that referenced this pull request Jul 12, 2026
Squash-rebased #103932 segment onto the ancestor-propagation tip on
current main. Plugin node.invoke approvals claim a one-shot allow-once
decision before handing execution authority to the policy, so observation
or retry cannot replay a consumed approval; sibling tool gates bind
approval ids to their originating reviewer identity.

(cherry picked from commit 122df0d75281f572c012b6484ed5daf085d1d577)
(cherry picked from commit f23d8ac240a8dcf2a42c4daaae962263975a0ae8)
(cherry picked from commit 8632fb6436a224dac7a9a9ef0216884530de2c24)
(cherry picked from commit d9fe2dd5c53665e5732f5f3da5ed1907a686ade8)
(cherry picked from commit bb139f2c8aa36ddad70413e1ef79ff491a6f2ecd)
(cherry picked from commit 9b3e056b68ea515c7d4baef269289b6670570480)
(cherry picked from commit b11e66b59a7af1f3b08712de06864aed64d349e4)
(cherry picked from commit a12916ee592d03dfa35e86a2aaede4476a5d4e5d)
(cherry picked from commit d699de840fc8346892b9ae244fe3c3e8c4413032)
(cherry picked from commit 9b7e5a9)
(cherry picked from commit 4b507593f1b2f10b4496984c84a2803b853e5c5e)
(cherry picked from commit 56408a186733c4eeb5aa76bd5907cde7b0cd3d5b)
(cherry picked from commit a4051d6d8353d39d6fa0b5d69c36e06c3cd3e796)
(cherry picked from commit 7682980)
(cherry picked from commit a8b493f)
(cherry picked from commit aceb990)
(cherry picked from commit a29b0e7)
(cherry picked from commit 2e3be08)
(cherry picked from commit c9ae3d7)
steipete added a commit that referenced this pull request Jul 12, 2026
Squash-rebased #103932 segment onto the ancestor-propagation tip on
current main. Plugin node.invoke approvals claim a one-shot allow-once
decision before handing execution authority to the policy, so observation
or retry cannot replay a consumed approval; sibling tool gates bind
approval ids to their originating reviewer identity.

(cherry picked from commit 122df0d75281f572c012b6484ed5daf085d1d577)
(cherry picked from commit f23d8ac240a8dcf2a42c4daaae962263975a0ae8)
(cherry picked from commit 8632fb6436a224dac7a9a9ef0216884530de2c24)
(cherry picked from commit d9fe2dd5c53665e5732f5f3da5ed1907a686ade8)
(cherry picked from commit bb139f2c8aa36ddad70413e1ef79ff491a6f2ecd)
(cherry picked from commit 9b3e056b68ea515c7d4baef269289b6670570480)
(cherry picked from commit b11e66b59a7af1f3b08712de06864aed64d349e4)
(cherry picked from commit a12916ee592d03dfa35e86a2aaede4476a5d4e5d)
(cherry picked from commit d699de840fc8346892b9ae244fe3c3e8c4413032)
(cherry picked from commit 9b7e5a9)
(cherry picked from commit 4b507593f1b2f10b4496984c84a2803b853e5c5e)
(cherry picked from commit 56408a186733c4eeb5aa76bd5907cde7b0cd3d5b)
(cherry picked from commit a4051d6d8353d39d6fa0b5d69c36e06c3cd3e796)
(cherry picked from commit 7682980)
(cherry picked from commit a8b493f)
(cherry picked from commit aceb990)
(cherry picked from commit a29b0e7)
(cherry picked from commit 2e3be08)
(cherry picked from commit c9ae3d7)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling docs Improvements or additions to documentation extensions: codex gateway Gateway runtime maintainer Maintainer-authored PR merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P0 Emergency: data loss, security bypass, crash loop, or unusable core runtime. plugin: file-transfer proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. size: L status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant