[luv-340] fix: regenerate OpenCode dev shim + handler-side canonicalization for OpenCode/Pi#340
[luv-340] fix: regenerate OpenCode dev shim + handler-side canonicalization for OpenCode/Pi#340NiveditJain merged 2 commits intomainfrom
Conversation
…calization for OpenCode/Pi Two-layer fix for `block-read-outside-cwd` silently no-op'ing on OpenCode inside this repo. PR #337 added `OPENCODE_TOOL_INPUT_MAP` to the production shim template at `src/hooks/integrations.ts:buildOpenCodePluginShim`, but the dev shim at `.opencode/plugins/failproofai.mjs` is hand-maintained and was never regenerated, so contributors running `opencode` from inside this repo could still read paths outside the repo cwd — `getFilePath()` returned "" (camelCase `filePath` didn't match the policy's snake_case `file_path` lookup) and the target-empty short-circuit at `src/hooks/builtin-policies.ts:799` returned allow. Layer 1 (dev shim): regenerate `.opencode/plugins/failproofai.mjs` to mirror the production template — `TOOL_NAME_MAP` + `TOOL_INPUT_MAP` + idempotent `canonicalizeTool` / `canonicalizeToolInput`. Also pick up the `applyDecision` async-await change from #318 that the dev shim had been missing, so Stop / SubagentStop force-retry actually awaits the SDK call before the plugin handler returns. Layer 2 (handler): add per-CLI canonicalization for OpenCode + Pi in `src/hooks/handler.ts` as defense-in-depth, so a user-scope shim that pre-dates #337 automatically starts enforcing the moment failproofai upgrades — without forcing a `failproofai policies --install --cli opencode` re-run. The shim canonicalization stays in place; both passes are idempotent because the per-CLI maps key on camelCase / Pi-shape and don't match already-canonical snake_case input. New `canonicalizeToolInput` helper is gated by `cli === "opencode" / "pi"` so Claude / Codex / Cursor / Copilot / Gemini sessions are unaffected. New unit tests in `__tests__/hooks/handler.test.ts` cover: - Stale-shim shapes (`read` + `filePath` for OpenCode, `read` + `path` for Pi) - Per-CLI map coverage parity (12 OpenCode + 6 Pi tool names, four Edit keys) - Idempotency (handler doesn't corrupt fresh-shim shapes) - Unknown-tool passthrough (MCP `mcp_*` tool names + args) - Per-CLI gate (Claude payloads with literal `filePath` keys are not rewritten) Smoke-tested against the exact pattern from the bug report: an opencode `read` with a camelCase `filePath` pointing outside the repo cwd is now blocked with a clear `Access outside project directory blocked` deny reason. In-cwd reads still pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThis PR implements defense-in-depth tool-name and tool-input canonicalization for OpenCode and Pi CLIs. The handler canonicalizes incoming hook payloads to canonical PascalCase tool IDs and snake_case input keys before policy evaluation. The OpenCode plugin shim includes parallel canonicalization and refactors ChangesTool-Name and Tool-Input Canonicalization
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@CHANGELOG.md`:
- Line 3: Update the CHANGELOG.md entry for version "0.0.10-beta.11" so the date
matches today's date (change "2026-05-09" to "2026-05-10") and ensure the
heading remains formatted as "## 0.0.10-beta.11 — 2026-05-10" to comply with the
guideline that changelog entries use the package.json version with today's date.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 71068430-d140-4125-a11b-dee6064b7019
📒 Files selected for processing (4)
.opencode/plugins/failproofai.mjsCHANGELOG.md__tests__/hooks/handler.test.tssrc/hooks/handler.ts
…tion CodeRabbit flagged the freshly-added section heading dated 2026-05-09 while the PR was opened at 2026-05-10T02:26Z UTC. Bump the date so the heading is internally consistent with the prior `## 0.0.10-beta.10 — 2026-05-10` section and with the GH server clock that downstream release tooling reads. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Summary
Two-layer fix for
block-read-outside-cwdsilently no-op'ing on OpenCodereadcalls inside this repo. Surfaced when an opencode session running from this repo couldreadpaths outside the repo cwd (e.g./home/<user>/<other-folder>) without any deny.OPENCODE_TOOL_INPUT_MAPto the production shim template atsrc/hooks/integrations.ts:buildOpenCodePluginShim, but the dev shim at.opencode/plugins/failproofai.mjsis hand-maintained and was never regenerated. With camelCasefilePathreaching the binary unchanged,getFilePath()returned"", the target-empty short-circuit atsrc/hooks/builtin-policies.ts:799returned allow, and the policy silently no-op'd..opencode/plugins/failproofai.mjsto mirror the production template (TOOL_NAME_MAP+TOOL_INPUT_MAP+ idempotentcanonicalizeTool/canonicalizeToolInput). Also picked up theapplyDecisionasync-await change from [luv-319] fix: enforce Stop hook on Cursor Agent CLI + cut 0.0.10-beta.6 #318 the dev shim had been missing, so Stop / SubagentStop force-retry actually awaits the SDK call.src/hooks/handler.tsso user-scope shims that pre-date [luv-338] fix: canonicalize OpenCode + Pi tool-input arg keys #337 automatically start enforcing the moment failproofai upgrades — nofailproofai policies --install --cli opencodere-run required. NewcanonicalizeToolInputhelper gated bycli === "opencode" / "pi"; idempotent because the per-CLI maps key on camelCase / Pi-shape and don't match already-canonical snake_case input. Claude / Codex / Cursor / Copilot / Gemini sessions are unaffected.Smoke-tested against the exact bug-report shape: an opencode
readwith a camelCasefilePathpointing outside the repo cwd is now blocked withAccess outside project directory blocked. In-cwd reads still pass; idempotent for already-canonical input; Pipathshape also blocked.Test plan
bun run test:run— 1596 / 1596 passingbun run lint— only an unrelated<img>warning inapp/components/log-viewer/tool-input-output.tsxbunx tsc --noEmit— cleanbun run build— Next.js + dist bundle build cleanlytool_name: "read",tool_input: {filePath: "<outside-cwd>"},--cli opencode) →permissionDecision: "deny"withAccess outside project directory blockedreasontool_name: "Read",tool_input: {file_path: "<outside-cwd>"}) → blocked (idempotent — handler doesn't corrupt fresh-shim shape)tool_name: "read",tool_input: {path: "<outside-cwd>"},--cli pi) → blocked with Pi-flat{permission: "deny", reason}shapetool_input: {filePath: "<cwd>/package.json"}) → exit 0, no stdout (allow)__tests__/hooks/handler.test.tscover stale-shim shapes, full per-CLI map coverage parity (12 OpenCode + 6 Pi tool names, four Edit keys), idempotency, MCP passthrough, and the per-CLI gate (Claude payloads with literalfilePathkeys are NOT rewritten)🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Behavior
Tests