feat(caprock): add ocap proxy plugin#953
Conversation
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Caution MetaMask internal reviewing guidelines:
|
ba12dbe to
01db469
Compare
…ives Adds two new capabilities needed by the modal authorization flow: NodeSocketDuplexStream (@metamask/streams): A duplex stream over a Node net.Socket. Reads NDJSON lines inbound, writes NDJSON lines outbound. Reader/writer cross-terminate on end. Exported via the streams package barrel. Session channel (kernel-utils/session): makeChannel() — a broadcast channel that fans SectionNotification messages to all connected ModalStream subscribers and resolves a Decision promise back to the broadcaster. New subscribers receive a replay of all currently-pending (undecided) notifications. SectionRequest / SectionNotification / Decision wire types. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…onApi types Transport-agnostic user-facing types used by both the TUI and the browser extension Authorization panel. Placing them in kernel-utils/session makes them available to any package without a node-runtime dependency. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ket server Adds ChannelFactory exo (kernel service), SessionRegistry, StreamSocketServer, and DaemonClient to support CLI-driven authorization session management. The daemon now exposes session RPC methods and a persistent stream socket for TUI subscriber connections. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- channel: track queuedAt timestamp, record history log with listAll() - session-registry: add startedAt/cwd, add listHistory() and authorizeRequest() - rpc-socket-server: add session.history and session.authorize RPC methods; include cwd/startedAt in session.create/list/get responses Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds ocap session create/list/requests/queue/approve/reject subcommands. Refactors daemon-client to delegate socket/RPC helpers to kernel-node-runtime, and extracts session command builder into session.ts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… timeline entries Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…erators Split bash commands joined by &&/||/; into independent clauses, each routed separately through the permission sheaf. A compound command is auto-accepted only when every clause has a covering provision. The TUI provision editor shows one pattern-tuning block per clause and creates one Provision per clause on submit. Migrates provision?:Provision → provisions?:Provision[] throughout the session layer (Decision, SessionHistoryEntry, Channel.record, etc.). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ropertyTypes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…decomposition Pipeline stages wrapped in a redirected_statement (e.g. `cmd 2>&1 | tail -30`) were silently dropped, causing only the tail end of the pipeline to appear as an invocation. A provision on `tail *` would then incorrectly auto-accept the entire command. Now all stages are collected regardless of redirect wrappers. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extends path detection to bare relative forms like `src/foo.ts` and `app/scripts/foo.ts` (word-char-prefixed segments containing a separator), not just absolute or `./`/`../`-prefixed paths. Provision routing was treating these as non-path args, which mis-matched commands that take relative project paths as the natural argument shape. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two observability additions to the caprock hook, prerequisite to the audit CLI but independently useful for transcript-driven inspection. - Reads `permissions.deny` from each watched settings file (in addition to the existing allow list) and captures it on the session state as `settingsDenySnapshot`, so the at-start view of authority is complete. - Records a `provision_match` event in the session log whenever a PreToolUse routing succeeds, naming the matched provisions. This makes "which provision authorized this tool use" inspectable from the event stream rather than only from the in-vat ledger. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds an `audit` CLI that reports which permission rules and provisions
were exercised in a given Claude session, plus SKILL.md manifests so
`audit`, `setup`, and `status` are reachable as slash commands from
Claude Code.
- `bin/audit.ts` + `scripts/audit.sh`: cross-references the transcript's
tool uses against the session-state allow/deny lists and the in-vat
provision ledger (via the new `listVatProvisions` RPC), and prints a
per-tool breakdown of which standing provisions were activated.
- `skills/{audit,setup,status}/SKILL.md`: thin wrappers that invoke the
corresponding `dist/bin/*.mjs` entry points. `setup` and `status`
existed as scripts; this is the slash-command surface.
- `src/rpc.ts:listVatProvisions`: queries the permission-tracker vat for
its current provisions list, decoded back to JS values.
- `package.json`: includes `skills/` in published files so the plugin
install ships the manifests.
- `bin/hook.ts:registerSkillPermissions`: adds the `audit.sh` entry to
the auto-registered Bash permissions.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Lift collectClauses into a SAFETY_FRAGMENT map (node kind → handler) so unknown node types refuse with unsupported_construct + node-kind detail instead of falling through to a permissive walk. Adds subshell and compound_statement as transparent grouping; moves hasCurlPipeShell ahead of clause collection so the security deny still fires when nested in an unsupported construct. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Descriptive overview of how the plugin is laid out: the hook subprocess, the src library (with bash.ts as the AST entry point), the in-kernel permission-tracker vat, and the communication boundary between them. Complements the forward-looking pipeline-rewrite-plan. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Define structs in `src/structs.ts` for the daemon responses caprock consumes (Provision, Decision, kernel session, launchSubcluster) plus a `Verdict = 'allow' | 'ask'` literal type, and use `superstruct.assert` at every `response.result` access in `src/rpc.ts`. The vat operations (`vatRoute`, `vatAddSection`, `vatFindMatch`, `vatSize`, `launchPermissionVat`) move from `bin/hook.ts` into `src/rpc.ts` so the whole RPC surface lives in one validated place, and `RpcClient` / `defaultRpcClient` are exported as the injection seam for handlers. `vatRoute` is now typed `Promise<Verdict>` instead of `Promise<string>`, so misshapen daemon responses fail loudly rather than silently flowing through as bogus strings.
`bin/audit.ts` and `bin/hook.ts` each had their own copy of "turn a tool invocation into clause arrays" — identical apart from the input type they accepted. Pull both into `src/clauses.ts` as one `buildClauses` that takes `(toolName, toolInput)`, plus a `routeAllClauses` helper for the cosheaf semantics (all clauses must independently match) and the small `inputSha` event-log key derivation. The audit binary switches to the shared helper here. The hook keeps its inline duplicate for now; that goes away in the handlers split.
…ed deps Each PreToolUse/PostToolUse/Permission*/FileChanged/SessionStart/SessionEnd handler moves into its own file under `src/handlers/`, taking a `HookDeps` bag (RPC client, session store, clock, stdout/stderr sinks, startup helpers) instead of reaching into module globals. `bin/hook.ts` becomes a thin shim: read stdin, build the production deps bag, hand off to `dispatch()`. The duplicated session-init paths in the old `onSessionStart` and `getOrInitSession` collapse into a single `initFreshSession`. The hook's inline `buildClauses` and `inputSha` are replaced with the shared `src/clauses.ts` exports from the prior commit. Decision flow is now unit-testable in milliseconds via the `HookDeps` fakes in `test/handler-fakes.ts` — no process spawning. The existing `bin/hook.test.ts` smoke test stays as the SES-lockdown regression check.
The daemon's `session.create` response includes `cwd?` and `startedAt`, and `launchSubcluster` includes `bootstrapResult` — fields the strict `KernelSessionStruct` and `LaunchSubclusterStruct` rejected with `Expected a value of type \`never\``. SessionStart threw inside the dispatcher, never persisted state, and every later PermissionRequest hook bailed at the missing-state check — leaving Claude Code's native permission prompt to handle everything. Add the missing fields as `optional` so the validators tolerate the real response shape. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The list rendered in daemon insertion order, which on long-lived daemons put the active session at the bottom and pushed it off-screen. Sort by `startedAt` descending so the most recent session is always visible; sessions without `startedAt` sort last. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Tree-sitter-bash parses `a && b 2>&1 | tail` as `pipeline → [redirected_statement → list (a, b), file_redirect], command (tail)` — the && chain is pulled inside the pipeline's first stage. The walker treated the redirected_statement as a single pipeline stage and silently dropped the list, so a compound command like `cd /tmp && yarn build 2>&1 | tail -40` decomposed to just `tail -40` and the provision editor only let the user widen `tail`. When a pipeline's stage is a `redirected_statement → list`, lift the non-final list commands out as their own clauses (matching bash's actual `a && (b 2>&1 | tail)` precedence) and keep the final list command — with the redirect attached — as the pipeline's first stage. Same fix at the top level: `cmd1 && cmd2 2>&1` (no pipeline) now splits into two clauses with the redirect bound to cmd2 only. Tests cover the regression command, the n-ary && chain (`a && b && c 2>&1 | tail`), and the no-pipeline variant. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
WIP