Tags: rivet-dev/secure-exec
Tags
fix(registry): wasm vim raw-mode input as a shell child wasm-runner treats kernel-managed stdio as authoritative TTY for fd 0/1/2 and routes fd 1/2 writes through the PTY; vim bridge overrides __isatty as well as isatty and links termios_bridge.o directly. vim launched from the shell now enters raw mode and receives keystrokes.
fix(agent-adapters): robustness fixes to pi + claude ACP adapters
Five verified fixes to the Pi and Claude ACP agent adapters (each with a unit
test), found via a multi-agent review:
- claude: tool-permission handler no longer auto-resolves on a 2s timer (was
fail-open: ran the guest's tool without host consent); host is authoritative.
- claude: partial tool input attributed by streaming content-block index, not
Map insertion order.
- claude: a dead query reader marks the session closed so the next prompt()
fails fast instead of hanging to the ACP timeout.
- pi: live session subscription is torn down on replace + conn.closed;
editSnapshots cleared per turn + on cancel.
- pi + claude: failed session/update writes are logged to stderr instead of
silently swallowed (emit chain kept alive).
Tests: registry/agent/{claude,pi}/tests/adapter.test.mjs. No auto-resolve on
timeout remains in any adapter.
fix(sidecar): classify new limit constants, tolerate stale sidecar re… …sponses, fix service-test build (#133) Fixes surfaced while syncing agent-os against latest secure-exec main: 1. limits: classify DEFAULT_WASM_RUNNER_HEAP_LIMIT_MB (#129) and MAX_TIMER_DELAY_MS (#131) — both added without inventory entries, so limits_audit failed on main. 2. sidecar: accept_sidecar_response drops a stale sidecar_response with no matching pending request (UnmatchedResponse) or already completed (DuplicateResponse) instead of failing the whole sidecar — a per-VM callback can be answered by the host after that VM is disposed on the shared sidecar process. Real protocol violations stay fatal. 3. tests: re-export crate::EventSinkTransport into the source-included service test crate (#132 added the use in src/service.rs without the matching test re-export, breaking 'cargo test -p secure-exec-sidecar --test service' compilation). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix: repair main after #124 merge (rustfmt 1.96.0 + userland_code tes… …t ctors + clippy) (#127) #124 (perf: agent-SDK heap snapshot) landed while its CI was red, leaving main failing on fmt, clippy, and 13 missing-field/unused test-compile errors. Repair: - rustfmt 1.96.0: reformat embedded_runtime.rs, snapshot.rs, sidecar/execution.rs, javascript_v8.rs (chain/closure collapse the pinned toolchain expects). - userland_code: add the WarmSnapshot/Execute snapshot field (#124) to 11 ipc_binary BinaryFrame test constructors + 2 embedded_runtime_session frames (empty = bridge-only, the documented default); update the hand-built WarmSnapshot trailing-byte test for the new 2-field wire layout. - clippy -D warnings: checked_div in queue_tracker, is_multiple_of in sidecar/execution, while-let in the js backpressure test, and allow(dead_code) on the host_dir test's source-included module (SessionModuleReader is used elsewhere in the crate). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(v8-bridge): yield a macrotask between bridge socket reads (#122) _pumpBridgeReads drained the synchronous _netSocketReadRaw in a tight loop and emitted readable/data for an entire HTTP response in one synchronous burst. That collapses the event-loop turn boundaries undici's keep-alive socket recycling depends on: onMessageComplete resolves the caller's fetch synchronously and only defers reuse via setImmediate(client[kResume]), so the caller's microtask dispatches the next request before kResume runs. Every Client stays kNeedDrain, the pool allocates a fresh Client+socket per request, and each registers EventEmitter listeners until the in-VM Node process dies (MaxListenersExceededWarning + unbounded memory / OOM). Await a setImmediate-backed macrotask yield before delivering each payload so socket bytes surface across distinct event-loop turns, exactly as they do on real Node where each readable arrives in its own I/O callback. This lets setImmediate(kResume) clear kNeedDrain before the next dispatch, so the pool reuses one keep-alive socket. Empirically: 40 sequential requests went from 40 sockets / 41 Clients to 1 socket / 2 Clients. Adds a deterministic regression test (javascript_v8 suite) that scripts two socket chunks over the mocked net bridge and asserts a setImmediate scheduled when the first chunk lands interleaves before the second chunk. It fails on the synchronous-burst trace (data:chunk-1,data:chunk-2,immediate) and passes on the fixed trace (data:chunk-1,immediate,data:chunk-2). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
test+docs: host-mounted node_modules resolution (#109) (#113) Add a sidecar integration test that mirrors NodeRuntime.create({ nodeModules }): project a host node_modules at guest /tmp/node_modules via the host_dir mount plugin, run a guest program under /tmp, and assert a bare import resolves the projected package. A missing package reproduces the exact 0.3.0 symptom ('_resolveModule returned non-string'); a present one resolves and runs. Package resolution through a host-mounted node_modules was broken in 0.3.0 and is fixed on main by the VFS refactor; this locks the end-to-end behavior in. Docs: make explicit that 'nodeModules' is a convenience for a read-only host-directory mount (the same machinery as 'mounts', defaulting to guest /tmp/node_modules). State it in features/module-loading and add it to the features/filesystem 'at a glance' list, which previously omitted it. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
test+docs: host-mounted node_modules resolution (#109) (#113) Add a sidecar integration test that mirrors NodeRuntime.create({ nodeModules }): project a host node_modules at guest /tmp/node_modules via the host_dir mount plugin, run a guest program under /tmp, and assert a bare import resolves the projected package. A missing package reproduces the exact 0.3.0 symptom ('_resolveModule returned non-string'); a present one resolves and runs. Package resolution through a host-mounted node_modules was broken in 0.3.0 and is fixed on main by the VFS refactor; this locks the end-to-end behavior in. Docs: make explicit that 'nodeModules' is a convenience for a read-only host-directory mount (the same machinery as 'mounts', defaulting to guest /tmp/node_modules). State it in features/module-loading and add it to the features/filesystem 'at a glance' list, which previously omitted it. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
release: bundle WASM commands into @secure-exec/core tarball The kernel needs guest sh + coreutils to spawn any process, so a fresh `npm install secure-exec` must ship them. Vendor the WASM command binaries into packages/core/commands via copy-wasm-commands.mjs (dereferencing the build's alias symlinks to real files, since npm pack drops symlinks), list `commands` in files, and guard pack with a prepack --require hook so a tarball is never published without them. CI (publish.yaml): new build-commands job builds the wasm32-wasip1 command set and uploads it; publish-npm restores the artifact and verifies sh before packing. Fetch wasm-opt as a prebuilt binary (taiki-e/install-action) instead of compiling it from source. Fix a latent wasm build break: registry/native/.cargo/config.toml (the cargo source-replacement that points at the patched vendor/ tree) is gitignored, so a fresh CI checkout had none and cargo built crates straight from the crates.io cache, silently ignoring every patches/crates/*.patch wasi fix (e.g. uu_tac's mmap-on-stdin guard) and failing to compile for wasm32-wasip1. The Makefile vendor target now writes that config from `cargo vendor` output so the patched sources are always used. Verified: cmd-tac compiles for wasm32-wasip1 from a wiped vendor/, and a fresh out-of-repo `npm install secure-exec` boots, execs, and spawns shell commands.
PreviousNext