[plugin sdk] Allow declared installed trusted hooks#90004
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 10, 2026, 1:24 AM ET / 05:24 UTC. Summary PR surface: Source +222, Tests +797, Docs +31, Other +1. Total +1051 across 28 files. Reproducibility: yes. Current main source directly rejects non-bundled registrations on both requested paths, and the linked Tokenjuice issue provides concrete external-install evidence; I did not run a live repro in this read-only review. Review metrics: 1 noteworthy metric.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Accept or reject the manifest-gated installed trusted-hook boundary explicitly; if accepted, keep the explicit enablement, bundled-first ordering, inspect/docs visibility, and regression coverage together. Do we have a high-confidence way to reproduce the issue? Yes. Current main source directly rejects non-bundled registrations on both requested paths, and the linked Tokenjuice issue provides concrete external-install evidence; I did not run a live repro in this read-only review. Is this the best way to solve the issue? Unclear until maintainers accept the trust model. Given that decision, the PR's manifest declaration plus explicit enablement is the narrowest implementation shape I found for the existing plugin-contract architecture. AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against 69a73b6278b5. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +222, Tests +797, Docs +31, Other +1. Total +1051 across 28 files. View PR surface stats
Security concerns:
What I checked:
Likely related people:
What the crustacean ranks mean
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
|
d6d393b to
90707e6
Compare
90707e6 to
b274fb8
Compare
b274fb8 to
532ac36
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Addressed the latest ClawSweeper rank-up items in commit 0f1b93d:
Validation run locally:
I did not trigger a manual ClawSweeper re-review. |
|
Follow-up after Codex review: commit 53cfdda fixes the remaining middleware-loader gap. Codex review found that installed tool-result middleware could still be skipped when bundled middleware was already active for the same runtime. I accepted that finding and fixed the loader to load only missing manifest owners, then return active handlers plus newly loaded missing handlers. Added a regression covering active bundled middleware plus lazy installed middleware, proving both handlers run. Additional validation after the fix:
No manual ClawSweeper re-review was triggered. |
|
Additional Testbox / changed-gate proof for the rank-up request:
env OPENCLAW_CHECK_CHANGED_REMOTE_CHILD=1 OPENCLAW_CHANGED_LANES_RAW_SYNC=1 CI=1 corepack pnpm check:changedResult: passed with Note: the local Windows Crabbox/Blacksmith wrapper path hit worktree/key-permission issues, so I ran the same approved changed gate directly on the warmed Blacksmith Testbox over SSH. No production/VPS OpenClaw state or user secrets were touched. |
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
amknight
left a comment
There was a problem hiding this comment.
Overall LGTM after fixing the prior issue. Given plugin SDK changes it would still be good to get @vincentkoc @steipete approval.
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
/clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
/clawsweeper re-review |
|
🦞👀 Command router queued. I will update this comment with the next step. Re-review progress:
|
|
Land-ready proof checked before merge. Local proof already run on this branch: Additional runtime proof: That proof loaded temporary installed plugins through the real loader and verified: Live PR state before merge: Known proof gap: Clawsweeper-until-clean did not complete because repeated Clawsweeper/Codex execution runs failed before producing a code finding. No actionable Clawsweeper code finding was observed. |
Summary
api.registerAgentToolResultMiddleware(...)when their manifest declares the targeted runtimes incontracts.agentToolResultMiddleware.contracts.trustedToolPolicies[]so installed plugins can opt into named trusted pre-tool policies while undeclared policy ids still fail closed.contracts.trustedToolPoliciesthrough official external catalog contract merges.Closes #87735.
Current-Main Source Evidence
Current main still has the bundled-only gates that the canonical issue reports:
src/plugins/registry.tsrejects installed/non-bundledapi.registerAgentToolResultMiddleware(...)registrations withonly bundled plugins can register agent tool result middleware.src/plugins/registry.tsrejects installed/non-bundledapi.registerTrustedToolPolicy(...)registrations withonly bundled plugins can register trusted tool policies.src/plugins/agent-tool-result-middleware-loader.tsskips every manifest record whererecord.origin !== "bundled", so installed plugins declaringcontracts.agentToolResultMiddlewarecannot be lazy-loaded as middleware owners.2026.5.28showing this bundled-only middleware gate is exposed as a broken official-plugin install flow.Security / Trust Posture
openclaw.plugin.jsonbefore registration is accepted.Real Behavior Proof
bundled.tbx_01ktm4xc6e4yqawy9wck02f46nusingenv OPENCLAW_CHECK_CHANGED_REMOTE_CHILD=1 OPENCLAW_CHANGED_LANES_RAW_SYNC=1 CI=1 corepack pnpm check:changed.node --import tsx src/entry.ts plugins inspect ... --runtime --jsonruns showed installed/official Tokenjuice loaded from both npm and ClawHub withenabled: true,imported: true,trustedOfficialInstall: true,diagnostics: [], andcontracts.agentToolResultMiddleware: ["openclaw", "codex"]. The isolated installed-plugin proof also retainedcontracts.trustedToolPolicies: ["issue-87735-proof-policy"]withdiagnostics: []. The Blacksmith Testbox changed gate completed ontbx_01ktm4xc6e4yqawy9wck02f46nwithTESTBOX_EXIT=0; warmup Actions run: https://github.com/openclaw/openclaw/actions/runs/27155636123. PR headf990ec4fcf3d390740dd48b30adbb767dc94d9bcis a no-op CI requeue commit on the same tree as the tested53cfddad43c7a16cd461289588af86b5c5c4507bhead.pnpm checkwas not run. The final review used focused runtime/plugin/Codex middleware gates, Blacksmith Testboxcheck:changed, ClawSweeper review, and manual diff review.Isolated installed-plugin command:
The isolated installed-plugin inspect command reported the installed plugin as loaded/imported with no diagnostics and retained the trusted-surface contracts:
{ "contracts": { "agentToolResultMiddleware": ["codex"], "trustedToolPolicies": ["issue-87735-proof-policy"] }, "diagnostics": [] }NPM Tokenjuice package command:
NPM Tokenjuice runtime inspect reported
install.source: "npm",trustedOfficialInstall: true,enabled: true,explicitlyEnabled: true,status: "loaded",imported: true,diagnostics: [], andcontracts.agentToolResultMiddleware: ["openclaw", "codex"].ClawHub Tokenjuice package command:
ClawHub Tokenjuice runtime inspect reported
install.source: "clawhub",clawhubChannel: "official",trustedOfficialInstall: true,enabled: true,explicitlyEnabled: true,status: "loaded",imported: true,diagnostics: [], andcontracts.agentToolResultMiddleware: ["openclaw", "codex"].Maintainer-review follow-up: after maintainer review pointed out that an installed plugin could register a built-in trusted policy id before the bundled policy and win the duplicate check, PR head
b2677eef2cremoved the earlier installed registration when the later registration is bundled, logs/records a warning for the displaced plugin, and keeps the bundled policy as the only active policy for that id. The focused regressionlets bundled trusted policies replace declared external policies with the same idproves the installed fake policy is displaced and the bundled policy blocks the tool call.Verification
Original PR validation:
NODE_OPTIONS=--max-old-space-size=8192 node scripts/run-vitest.mjs src/agents/codex-app-server.extensions.test.ts src/plugins/contracts/host-hooks.contract.test.ts src/plugins/manifest-registry.test.tscorepack pnpm build:plugin-sdk:strict-smokecorepack pnpm tsgo:prodcorepack pnpm check:test-typescorepack pnpm lint --threads=8corepack pnpm exec oxfmt --check src/plugins/manifest.ts src/plugins/registry.ts src/plugins/agent-tool-result-middleware-loader.ts src/plugins/types.ts src/plugins/registry-types.ts src/agents/codex-app-server.extensions.test.ts src/plugins/contracts/host-hooks.contract.test.ts src/plugins/manifest-registry.test.tscorepack pnpm exec oxfmt --check docs/plugins/sdk-overview.md docs/plugins/sdk-agent-harness.md docs/plugins/hooks.md docs/plugins/manifest.md docs/plugins/building-plugins.md docs/cli/plugins.mdcorepack pnpm docs:check-mdxcorepack pnpm docs:check-i18n-glossarycorepack pnpm docs:check-linksgit diff --check6ea717e3572ba4a9f0ab370202ae4c8835cadb5a.Maintainer-review follow-up validation on PR head
b2677eef2c:node scripts/run-vitest.mjs run --config test/vitest/vitest.contracts-plugin.config.ts src/plugins/contracts/host-hooks.contract.test.ts -t "lets bundled trusted"node scripts/run-vitest.mjs run --config test/vitest/vitest.contracts-plugin.config.ts src/plugins/contracts/host-hooks.contract.test.tsNODE_OPTIONS=--max-old-space-size=8192 pnpm tsgo:corepnpm exec oxlint src/plugins/registry.ts src/plugins/contracts/host-hooks.contract.test.tsgit diff --checkAdditional follow-up validation on PR head
53cfddad43c7a16cd461289588af86b5c5c4507b:node scripts/run-vitest.mjs src/plugins/loader.test.ts -t "rolls back trusted policies when plugin register fails"node scripts/run-vitest.mjs test/scripts/kitchen-sink-plugin-assertions.test.ts -t "accepts" --reporter=verbosenode scripts/run-vitest.mjs src/plugins/loader.test.ts src/plugins/contracts/host-hooks.contract.test.ts src/agents/codex-app-server.extensions.test.tsnode scripts/run-vitest.mjs src/agents/codex-app-server.extensions.test.ts -t "loads missing installed middleware" --reporter=verbosepnpm exec oxlinton focused plugin, loader, host-hook, Codex middleware, and kitchen-sink filesNODE_OPTIONS=--max-old-space-size=8192 pnpm tsgo:coregit diff --checkcodex-review --mode branchthrough the local codex-review helper: clean; no accepted/actionable findings.Blacksmith/Testbox changed gate:
53cfddad43c7a16cd461289588af86b5c5c4507bf990ec4fcf3d390740dd48b30adbb767dc94d9bc(no-op CI requeue commit on the same tree)tbx_01ktm4xc6e4yqawy9wck02f46nResult: passed with
TESTBOX_EXIT=0.