feat(caprock): add ocap proxy plugin#953
Conversation
…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>
Adds @ocap/kernel-tui with an Ink/React terminal UI for interactive session authorization. Adds the `ocap modal <sid>` command to kernel-cli that spawns the TUI binary with the resolved channel URL. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ports the old ephemeral kernel-tui components (files, objects, invoke, log) to work against the daemon via makeDaemonKernelApi, which calls kernel RPC methods over the UNIX socket. Adds a sessions view that polls all sessions and their pending authorization requests with keyboard approve/reject. Adds `ocap-tui tui` command alongside the existing `modal` command. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
exactOptionalPropertyTypes rejects color={undefined} on ink's Text component.
Use spread to conditionally apply focused styles.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds `ocap tui` to kernel-cli for convenient TUI launch (mirrors `ocap modal`). Sessions view now shows a helpful hint when the daemon lacks session RPCs (i.e. is running from main rather than the sessions branch). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…uest from kernel-utils Removes locally-defined SessionSummary, PendingRequest, and the explicit session method declarations from KernelApi, replacing them with the shared types from @metamask/kernel-utils/session. Drops the unused @metamask/utils runtime dependency. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add overflow=hidden to content box and cap object registry promises at 20 rows to prevent the view from overflowing the terminal - Remove VIEW_LABELS title box from tui.tsx root — FileBrowser, InvokeView, and ObjectRegistryView already render their own headers, so the extra box was causing duplicate titles - Add Sessions title to SessionsView to match the other views - Clear screen before rendering and constrain root height to terminal rows via useTerminalSize to prevent rendering artifacts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- sessions-view: replace flat request list with per-session cursor; right arrow drills into a session's detail view; left arrow returns - session-detail-view: new component showing session history entries with authorization status, timestamps, and descriptions - use-kernel: add listHistory to KernelApi, expose SessionHistoryEntry - types: expand listSessions return type to include cwd/startedAt Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New requests arriving while inspecting a session were invisible until the user navigated away and back. Add a POLL_INTERVAL_MS interval tied to detailSession so refreshDetail runs automatically while the detail view is active. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ta hook SessionsView previously owned polling intervals, all fetch callbacks, loading/ error state, and detail-open state alongside its render logic. Move all of that into a useSessionData hook so the component owns only cursor position. - hooks/use-session-data.ts: new hook — owns refresh/refreshDetail intervals, openDetail/closeDetail, onDecided, loading, error, sessions, detailHistory - sessions-view.tsx: consumes useSessionData; only local state is cursor; extract sessionMetaSuffix helper to keep render logic readable Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…SessionData hook - session-registry.test.ts: 11 tests for listHistory(), authorizeRequest() (including timeout), createSession() with cwd/startedAt - rpc-socket-server.test.ts: 9 integration tests for session.history, session.authorize, and updated session.create/list/get responses - use-session-data.test.ts: 9 hook tests covering loading state, session fetch, error handling, openDetail, closeDetail, and polling Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Bash commands - Show most-recent history entries at the top of the detail view - Expand entries by rendering prettified JSON with description(params) format - Split compound shell commands on &&, |, ; into list segments for readability Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…t/reject keybinds - Replace numeric cursor index with token-based focus in SessionDetailView so new requests arriving above the cursor no longer shift what's highlighted - Show oldest pending request expanded at the session list level; 1/3 decide without drilling into the detail view - Change accept/reject keybinds from a/r to 1/3 throughout (status bar updated) - Export formatExpandedContent and parseDescription for reuse across views Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Migrates the standalone `pola` plugin into the monorepo as `@ocap/caprock`. The plugin routes every Claude Code tool invocation through an ocap-kernel permission vat (POLA enforcement), blocking for a TUI decision on first use of any (tool, input-hash) pair not yet in the allow-set. Key factoring decisions made visible by co-location: - `sendCommand`/`getSocketPath` imported from `@metamask/kernel-node-runtime` - `Decision` type imported from `@metamask/kernel-utils/session` - `getOcapHome` imported from `@metamask/kernel-utils/nodejs` - Vat bundle built at `build` time via `ocap bundle` (no committed artifact) Includes 62 unit tests covering `decompose()` (bash parser security logic) and `session.ts` persistence round-trips. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sorts candidates ascending by numeric `authority` metadata, so the most- restricted matching section is tried first. Candidates without an authority entry default to 0.5 (midpoint). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds ArgPattern / InvocationPattern / Provision types and the full algebra: interval builders (pathInterval, trivialInterval, argInterval), matchArg / matchPattern / matchProvision, argPatternLe, compareInvocationPatterns / compareProvisions, computeAuthority (midpoint-embedding of the partial order into (0,1)), and invocationToProvision. Adds provision? to Decision and SessionApi.decide so approved provisions can flow from the TUI through the RPC layer to the hook. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rewrites the permission-tracker vat to use the real sheaf machinery:
each Provision becomes a Provider<{authority,idx}> with an M.eq guard
for the tool name and an identity handler that throws on pattern
mismatch. leastAuthority drives the dispatch so the most-restricted
matching section wins.
The idx field in metadata prevents collapseEquivalent from merging
distinct providers that share the same authority value (incomparable
provisions).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the old vatCheck/vatGrant SHA-based API with invocation-aware
routing. buildInvocations parses Bash via decompose() and falls back to
[{name: tool, argv: stringFields}] for other tools. On a pre-tool-use
accept the hook records the approved provision (or constructs an exact
one via invocationToProvision). On post-tool-use it always records an
exact provision for the completed invocation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Passes the optional provision from the TUI's decide call through the RPC socket layer to the kernel session, so the permission-tracker vat can record whatever provision the user approved. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…hority noopPolicy takes one argument; passing context caused a TS2554 build error. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The hook process must not run SES lockdown because full lockdown freezes native prototypes and breaks tree-sitter's C++ bindings. @Endo modules call harden() and assert() at module-evaluation time, so any transitive import of @endo/* would crash the hook with 'harden is not defined' or 'Cannot initialize @endo/errors'. - Add harden-shim.ts: installs a no-op identity harden before any @Endo import can evaluate (ESM depth-first import order guarantees this runs first) - Inline sendCommand/readLine/writeLine/connectSocket into rpc.ts using only node:crypto and node:net, removing the import of @metamask/kernel-node-runtime/daemon which transitively pulled in @endo/promise-kit and @endo/errors - Add kernel-utils/session/provision lockdown-free subpath that re-exports only from types.ts and provision.ts (no channel.ts, no @endo/promise-kit); hook.ts imports from this subpath - Remove @metamask/kernel-node-runtime from caprock dependencies and tsconfig references - Fix hooks.json and scripts to use dist/bin/hook.mjs (ts-bridge with rootDir:. outputs bin/ under dist/bin/) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Carries parsed command invocations from the hook call-site through
the session registry and channel to TUI history entries, enabling
the provision editor to show per-arg pattern controls.
- Move ParsedInvocation type to session/types.ts to avoid circular deps
- Add invocations? to SectionNotification and SessionHistoryEntry
- Change authorizeRequest signature to an options bag
{ reason?, timeoutMs?, invocations? } for extensibility
- channel.listAll() includes invocations via ifDefined in both the
pending and decided entry paths
- rpc-socket-server session.authorize handler extracts invocations
from JSON-RPC params and forwards to session.authorizeRequest
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a '2' keybind on pending session-detail entries that opens an interactive provision editor before granting a standing provision. The editor flattens all invocation args into a navigable list. Each arg cycles through its pattern interval (exact → prefix levels → wildcard) via ↑/↓; ←/→ moves between args. Enter submits the shaped Provision; Esc cancels back to the normal view. Falls back to a tool-level wildcard provision when invocations data is unavailable (unparseable command or old daemon). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Spawns dist/bin/hook.mjs as a child process and asserts it exits cleanly without @endo/SES missing-globals errors. Builds the binary in beforeAll so the test is always self-contained and never silently skips due to a stale or missing dist/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add a 'provisioned' status for auto-accepted requests and expose the standing provision that was set by the user when accepting with keybind 2. - `SessionHistoryEntry` gains status 'provisioned' and optional `provision` field - `Channel.record()` inserts a pre-decided entry without blocking subscribers - `Session.recordProvisioned()` records an auto-accepted request synchronously - `session.record` RPC dispatches to `recordProvisioned` in the daemon - hook fires-and-forgets `recordProvisioned` when the vat returns 'allow' - TUI: ◆ for user-accepted-with-provision, → for auto-provisioned - TUI: expanded view shows provision patterns; provisioned entries show '→ standing provision' instead of decided time Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…anel Tweak 1 — show which provision auto-accepted a request: - Add findMatch(tool, invocations) and listProvisions() to permission-tracker vat - Hook calls vatFindMatch after vatRoute returns 'allow' and passes the result to recordProvisioned, threading it through rpc.ts → session.record RPC → channel.record() → HistoryEntry.provision - TUI: provisioned entries show '→ by provision: git log * | head *' (compact one-liner) instead of '→ standing provision'; detailed pattern block reserved for user-accepted-with-provision (◆) entries Tweak 2 — active-provisions panel (P keybind): - ProvisionsPanel component derives unique active provisions from session history - Press P in session detail view to open; Esc to close - Lists each provision as '◆ tool name arg1 arg2 | name2 arg1' - Status bar hint updated Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@endo/marshal smallcaps encoding prefixes strings starting with sigil characters (like `-` for negative floats) with `!`. Shell flags such as `--oneline` or `-l` were rendered as `!--oneline` and `!-l` in the TUI because vatFindMatch decoded only the outer CapData wrapper, leaving nested strings un-unescaped. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Caution MetaMask internal reviewing guidelines:
|
WIP