reference: fabro-sandbox-forkd JSON-RPC plugin (feedback on the provider-plugin sketch) - #20
Draft
zenprocess wants to merge 4 commits into
Draft
reference: fabro-sandbox-forkd JSON-RPC plugin (feedback on the provider-plugin sketch)#20zenprocess wants to merge 4 commits into
zenprocess wants to merge 4 commits into
Conversation
WIP commit before adding the protocol dispatcher, main.rs, and tests. Includes: Cargo.toml, lib.rs (JSON-RPC envelope + Plugin + PluginState), capabilities.rs (honest initialize payload), gaps.rs (gap 1/2/3 prose), forkd.rs (async ForkdClient trait + reqwest-backed HttpClient). Not yet wired into the workspace; not yet buildable.
JSON-RPC 2.0 stdio plugin subprocess for the forkd microVM controller. Implements initialize (honest capabilities: exec streaming false, fs native false, snapshots dockerfile false) plus the create/exec/delete handlers. sandbox/delete is idempotent on unknown id (test covers it). Unsupported capabilities return the spec's literal error string. The three capability gaps that forkd's microVM shape exposes (vs the container-centric sketch) are marked in code at the friction site: - GAP 1 src/capabilities.rs:71 (SnapshotCapability::dockerfile) + src/protocol.rs:90 (sandbox_create) — microVM snapshot/COW-branch - GAP 2 src/protocol.rs:97 (sandbox_create) — guest RAM/vCPU sizing - GAP 3 src/protocol.rs:266 (exec result) — ran/infra outcome distinction Verified: cargo build, cargo nextest (7/7), cargo fmt --check, and clippy -p fabro-sandbox-forkd --no-deps --tests -D warnings are all clean for this crate alone. No live forkd calls in tests; mock HTTP responder only.
No internal hostnames, tokens, or private URLs. Every method/field name verified against the design doc rather than paraphrased. Three proposals: - GAP 1: snapshots.dockerfile is too narrow; add microvm/branch/register - GAP 2: SandboxSpec has no memory/cpu knob; add resources block - GAP 3: termination cannot carry ran/infra; add outcomeKind + stage Drafted for public posting; operator reviews before upstream contact.
zenprocess
marked this pull request as draft
July 25, 2026 19:53
PR #20 added `httpmock 0.8` as a dev-dependency of the new fabro-sandbox-forkd crate but never committed the resulting root Cargo.lock update (+40 lines). Found during the adversarial review pass: running the crate's tests dirties Cargo.lock, which means every contributor and every CI run would regenerate it as an uncommitted change. No source change — lockfile only. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes fabro-sh#567
Reference implementation + concrete feedback on the provider-plugin sketch
This PR ships a reference implementation of the JSON-RPC 2.0 over stdio provider-plugin half of the upstream sketch (PR #567), built against a genuinely different sandbox shape (a Firecracker microVM, via forkd). Its purpose is to validate the design against a non-container backend and to surface three concrete capability gaps the container-centric sketch misses.
The plugin is the subprocess half only — the upstream
Sandboxtrait split /PluginProviderhost-side wiring is deliberately out of scope (separate concern, separate PR). The reference is wired into a workingfabro-sandbox-forkdcrate, the wire protocol is end-to-end with the host, and all tests pass against a mock HTTP responder — no live forkd controller call.Resources
~/.ao/data/aofactory/UPSTREAM-SANDBOX-PLUGIN-DESIGN.mddocs/internal/upstream-proposal-pr567.mdWhat the implementation demonstrates
initializereturns the honest forkd capability payload:exec.streaming: false(forkd is buffered),fs.native: false(host derives from exec),snapshots.dockerfile: false,network.modes: [allow_all, block, cidr_allow_list],clone.github: true.sandbox/create→POST /v1/sandboxes,sandbox/delete→DELETE(idempotent on unknown id, per spec),exec→POST /v1/sandboxes/{id}/exec.streaming:false),sandbox/deleteidempotency on unknown id, and the unsupported-method error shape.Three capability gaps the microVM shape exposes (each marked in code)
snapshots: { dockerfile }; forkd needsregister-snapshot/branch-from-snapshot(copy-on-write reflink off a read-only golden rootfs). Marker:lib/components/fabro-sandbox-forkd/src/capabilities.rs:73andlib/components/fabro-sandbox-forkd/src/protocol.rs:96.SandboxSpec. forkd needs--mem-size-miband vCPU count at create time. A 512 MiB guest silently OOM-killed our test suites; the fix was a host-side resize the wire protocol cannot currently express. Marker:lib/components/fabro-sandbox-forkd/src/protocol.rs:103.{termination}. forkd distinguishesran(real code verdict) frominfra(sandbox could not be created/reached/exec'd/torn down) with astage: boot | exec | teardown. Conflating them turns infrastructure faults into code failures, which are sticky and poison downstream labels. Marker:lib/components/fabro-sandbox-forkd/src/protocol.rs:236.What is NOT implemented (and why)
Sandboxtrait split /SandboxProviderRegistrywiring /PluginProviderhost side. That is the other half of the sketch and a prerequisite refactor; this PR is deliberately just the plugin subprocess half.exec/stream,exec/outputnotifications). forkd is buffered; the plugin declaresstreaming:falseand returns the spec's unsupported error if asked.fs/*handlers. Declarednative:false; the host derives read/write/list/grep/glob from exec (base64 cat/tee + POSIX grep/find).Verification (scoped to this crate, not the full workspace)
The full-workspace
cargo buildis intentionally not run on the development Mac (a hook blocks it because it pins the machine); the authoritative build runs in PR CI. This crate alone passes the four gates above.Tone
This is a collaborative PR. The sketch works for our needs modulo the three gaps above; the diff is small; the test suite is honest; the gap markers are the actual code path of friction, not prose. Reviewer feedback welcome — happy to iterate.
🤖 Generated with Claude Code