Plan: WASI Host Adapter
Overview
Implementation track for the WASI host adapter sketched in
docs/proposals/wasi-host-adapter-proposal.md. The proposal’s Phase W.0
through W.8 decomposition is the source of truth; each task below maps to
one phase. This plan is ad-hoc until selected, and the v0 phases (W.1 and
W.2) are parallel-safe with the kernel-core selected milestone because
they touch only new userspace crates, demos, manifests, and Makefile
targets. Preview 2 / Component Model phases (W.7 onward) will touch
schema/capos.capnp and must serialise with other schema-touching plans
per docs/plans/README.md Concurrency Notes.
Conflict Surface
Owned by this plan:
capos-wasm/(NEW crate, standalone likeinit/andcapos-rt/, built for thetargets/x86_64-unknown-capos.jsonuserspace target).vendor/wasmi-no_std/(NEW vendored runtime if upstreamno_stdflag is insufficient; otherwise acargo-vendor-style mirror).demos/wasi-hello-rust/,demos/wasi-hello-c/,demos/wasi-cli-args/,demos/wasi-random/,demos/wasi-fs/,demos/wasi-net/,demos/wasi-component-bridge/,demos/wasi-cue-evaluator/(NEW per-phase smoke binaries).Makefile(newwasm-host-build,run-wasm-host,wasm-hello-rust-build,wasm-hello-c-build,run-wasi-hello-rust,run-wasi-hello-c, and successorrun-wasi-*targets).- Repo-root
system-wasm-host.cueand per-phasesystem-wasi-*.cuefocused-proof manifests. docs/proposals/wasi-host-adapter-proposal.md(status updates, closeout stamps, phase progress).docs/plans/wasi-host-adapter.md(this file).docs/programming-languages.mdWASI row updates as phases land.docs/proposals/userspace-binaries-proposal.mdPart 5 status note (cross-link only; the full proposal lives elsewhere).docs/proposals/index.mdFuture Architecture row for the new proposal.WORKPLAN.mdad-hoc track bullet update.docs/plans/README.mdTrack Map row update.
Do not touch from this plan:
- Kernel-core cap tables, scheduler, device manager, or the existing
userspace runtime (
capos-rt/). tools/remote-session-client/(owned by remote-session plan).- Any other proposal/plan file that does not directly cross-reference this track.
docs/topics.md(auto-regenerated; never edit manually).schema/capos.capnpuntil Phase W.7. When that phase begins, queue on the shared serial surface perdocs/plans/README.mdConcurrency Notes.
Validation Commands
make fmt-checkmake generated-code-checkcargo build --features qemucargo test-configcargo test-libcargo build-demos-caposmake capos-rt-checkmake run-smoke- Per-phase smoke targets (added as the matching task lands):
- W.1:
make run-wasm-host - W.2:
make run-wasi-hello-rust,make run-wasi-hello-c - W.3:
make run-wasi-cli-args - W.4:
make run-wasi-random - W.5:
make run-wasi-fs - W.6:
make run-wasi-net - W.7:
make run-wasi-component-bridge - W.8:
make run-wasi-cue-evaluator
- W.1:
Treat the matching make run-wasi-* target for the most recent phase
as required for any iteration that touches this plan’s owned files.
Success Criteria
Each landed phase must keep its make run-wasi-* target green, leave
unrelated make run-* targets unaffected, and stamp the phase closeout
in docs/proposals/wasi-host-adapter-proposal.md with commit hash and
minute-precision timestamp. The track is recorded done when Phase W.6 is
green (Preview 1 surface complete against the available cap surfaces);
W.7 and W.8 are layered milestones that close independently when their
dependencies land.
Task 1: Phase W.0 — Decision and host runtime selection (planning)
- Decide runtime: wasmi for v0; WAMR / wasmtime as W.7+ migration
targets. Captured in
docs/proposals/wasi-host-adapter-proposal.mdRuntime Selection. - Land
docs/proposals/wasi-host-adapter-proposal.mdwith the capability-mapping surface, phase decomposition, runtime survey, and open questions. - Land this plan file as the ralphex-shaped task list.
- Resolve the cross-cutting open questions §1 (per-instance vs
per-process), §3 (
poll_oneoffsemantics), §6 (environ_getsource), §7 (args_getsource), and §8 (vendoring posture for wasmi) before W.1 starts. The vendoring decision in §8 gates the W.1 scaffold because Task 2 vendors wasmi and the fork-vs-mirror shape determines the directory layout. Working answers are captured in the proposal; promote each to a final decision when W.1 begins.
Task 2: Phase W.1 — capos-wasm host process scaffold
- Create the
capos-wasm/standalone userspace crate built oncapos-rt. - Vendor wasmi at a pinned tag with
default-features = false. If upstreamno_stdis insufficient, fork intovendor/wasmi-no_std/with the dependency-trim patches noted in the proposal. - Embed one hand-written empty
.wasmblob in.rodataand compile/instantiate it with no imports; run_start; exit cleanly. - Add
system-wasm-host.cue(its own distinct CUE package; imports the sharedcapos.local/cue/defaultspackage per the slice-3 defaults pattern). - Add
make run-wasm-hosttarget. Smoke must print[wasm-host] empty module instantiated and exitedand exit cleanly under QEMU. - Update
docs/programming-languages.mdWASI row to note Phase W.1 landed. - Stamp the phase closeout in
docs/proposals/wasi-host-adapter-proposal.mdwith commit hash and minute-precision timestamp.
Task 3: Phase W.2 — WASI Preview 1 stdout-only
- Add
capos-wasm/src/wasi/(Preview 1 import resolver). - Implement
args_get,args_sizes_get,environ_get,environ_sizes_get(all return empty),clock_time_get(MONOTONIC)viaTimer.now(),proc_exit,random_get(gated on the in-treeEntropySourcecap; refuse withERRNO_NOSYSif absent),fd_write(1, …)via host’sConsole.write_line,fd_write(2, …)via the same or a separate log cap. - Stub everything else as
ERRNO_NOSYS. Verify a probe module receivesERRNO_NOSYSfor each unimplemented import. - Add
demos/wasi-hello-rust/built forwasm32-wasip1anddemos/wasi-hello-c/built withclang --target=wasm32-wasi(or wasi-sdk if available). Both must printHello from WASI on capOSand exit cleanly. - Add
system-wasi-hello-rust.cueandsystem-wasi-hello-c.cuemanifests; embed the produced.wasmblob bytes inline (no capnp schema change). - Add
make run-wasi-hello-rustandmake run-wasi-hello-ctargets. - Update
docs/programming-languages.mdWASI row to note Phase W.2 landed: C runs on capOS without anylibcapos/POSIX work in tree. - Stamp the phase closeout in the proposal.
Task 4: Phase W.3 — Per-instance CapSet plumbing + LaunchParameters
- Define how the host adapter receives per-instance grants from the
manifest. Extend the wasm-host CUE shape so each entry lists
{ binary, args, caps: { console, timer, random, preopens } }. - Cross-cutting: until a capOS
LaunchParameterssurface exists, ship a bounded text grant in the host adapter manifest as the v0 argv source. Document the migration path so the futureLaunchParameterssurface replaces the bounded text grant when it lands. - Add
demos/wasi-cli-args/smoke that readsargv[1]and prints it back; assert the printed value matches the manifest grant. - Add
system-wasi-cli-args.cueandmake run-wasi-cli-argstarget. - Update the proposal Open Question §5 / §6 / §7 status as each is decided.
- Stamp the phase closeout in the proposal.
Task 5: Phase W.4 — WASI Preview 1 random + clocks production-ready
- Wire the in-tree kernel
EntropySourcecap through the host adapter sorandom_getreturns cryptographically-sourced bytes when the instance was granted entropy authority. - Document wall-clock support as deferred until capOS has a
wall-clock cap;
clock_time_get(REALTIME)returns the documented sentinel error. - Add
demos/wasi-random/smoke that reads N random bytes through the host’s grantedEntropySourcecap and asserts entropy bounds; ungranted manifest variant proves refusal. - Add
system-wasi-random.cueandmake run-wasi-randomtarget. - Stamp the phase closeout in the proposal.
Task 6: Phase W.5 — WASI Preview 1 filesystem (gated on Namespace/File caps)
- Map preopened-dir fds to
Namespacecaps from the manifest. Implementpath_open,fd_read,fd_write,fd_seek,fd_close,fd_filestat_get,fd_prestat_get,fd_prestat_dir_nameagainst the availableNamespace/File/Storecap surface. - Add
demos/wasi-fs/smoke that reads and writes a file inside a preopened capOS namespace; assert ungranted-namespace path-open attempts returnERRNO_BADF/ERRNO_ACCES. - Add
system-wasi-fs.cueandmake run-wasi-fstarget. - Blocked until the Namespace/File cap surface exists. Note the block in the proposal status header until storage proposals land.
- Stamp the phase closeout in the proposal once unblocked.
Task 7: Phase W.6 — WASI Preview 1 sockets (gated on userspace network stack)
- Implement
sock_send,sock_recv,sock_shutdownagainstTcpSocket/UdpSocketcaps once the userspace network stack lands. Until then, ship an HTTP client overFetch/HttpEndpointas the v0 networking shim and document the migration path. - Add
demos/wasi-net/smoke that serves an HTTP response or drives an HTTP request inside a capOS process; assert ungranted-socket attempts fail closed. - Add
system-wasi-net.cueandmake run-wasi-nettarget. - Blocked until the userspace network stack (or the
Fetch/HttpEndpointv0 shim) lands. - Stamp the phase closeout in the proposal once unblocked.
Task 8: Phase W.7 — Move to wasmtime or migrate to WASI Preview 2 / Component Model
- Decide between (a) swapping wasmi for wasmtime once capOS
userspace gains
stdand a futures executor, or (b) promoting wasmi to wasip2 / Component Model support once that maturity arrives. Capture the decision in the proposal. - Map WIT resources to typed
OwnedCapability<T>slots in the host adapter. Capability transfer between wasm components becomes a host-mediated resource handoff. - Add
schema/capos.capnpvariants needed for Component Model resource bridging. Schema serial-surface coordination required: queue on the sharedschema/capos.capnpserial surface perdocs/plans/README.mdConcurrency Notes; only one plan at a time may add or change interfaces inschema/capos.capnp. Runmake generated-code-checkbefore downstream Cargo builds. - Add
demos/wasi-component-bridge/smoke proving a wasm component exports a typed interface that a native capOS process invokes. - Add
system-wasi-component-bridge.cueandmake run-wasi-component-bridgetarget. - Blocked on the std-userspace decision (same blocker as the capnp-rpc rewrite in the remote-session plan).
- Stamp the phase closeout in the proposal once unblocked.
Task 9: Phase W.8 — TinyGo / Go-on-WASI integration for CUE
- Build a CUE evaluator binary against TinyGo or upstream Go’s
GOOS=wasip1. Run it in the host adapter against a CUE source blob granted as a futureScriptPackagecap (same shape as the plannedLaunchParameterswork). - Add
demos/wasi-cue-evaluator/smoke that evaluates a small CUE expression and prints the canonicalised result. - Add
system-wasi-cue-evaluator.cueandmake run-wasi-cue-evaluatortarget. - Cross-link the bridge to native
GOOS=caposplanning indocs/proposals/go-runtime-proposal.md: WASI is the v0 path for CUE evaluation; native Go remains the path for full Go runtime semantics. - Stamp the phase closeout in the proposal.