Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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 like init/ and capos-rt/, built for the targets/x86_64-unknown-capos.json userspace target).
  • vendor/wasmi-no_std/ (NEW vendored runtime if upstream no_std flag is insufficient; otherwise a cargo-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 (new wasm-host-build, run-wasm-host, wasm-hello-rust-build, wasm-hello-c-build, run-wasi-hello-rust, run-wasi-hello-c, and successor run-wasi-* targets).
  • Repo-root system-wasm-host.cue and per-phase system-wasi-*.cue focused-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.md WASI row updates as phases land.
  • docs/proposals/userspace-binaries-proposal.md Part 5 status note (cross-link only; the full proposal lives elsewhere).
  • docs/proposals/index.md Future Architecture row for the new proposal.
  • WORKPLAN.md ad-hoc track bullet update.
  • docs/plans/README.md Track 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.capnp until Phase W.7. When that phase begins, queue on the shared serial surface per docs/plans/README.md Concurrency Notes.

Validation Commands

  • make fmt-check
  • make generated-code-check
  • cargo build --features qemu
  • cargo test-config
  • cargo test-lib
  • cargo build-demos-capos
  • make capos-rt-check
  • make 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

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.md Runtime Selection.
  • Land docs/proposals/wasi-host-adapter-proposal.md with 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_oneoff semantics), §6 (environ_get source), §7 (args_get source), 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 on capos-rt.
  • Vendor wasmi at a pinned tag with default-features = false. If upstream no_std is insufficient, fork into vendor/wasmi-no_std/ with the dependency-trim patches noted in the proposal.
  • Embed one hand-written empty .wasm blob in .rodata and compile/instantiate it with no imports; run _start; exit cleanly.
  • Add system-wasm-host.cue (its own distinct CUE package; imports the shared capos.local/cue/defaults package per the slice-3 defaults pattern).
  • Add make run-wasm-host target. Smoke must print [wasm-host] empty module instantiated and exited and exit cleanly under QEMU.
  • Update docs/programming-languages.md WASI row to note Phase W.1 landed.
  • Stamp the phase closeout in docs/proposals/wasi-host-adapter-proposal.md with 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) via Timer.now(), proc_exit, random_get (gated on the in-tree EntropySource cap; refuse with ERRNO_NOSYS if absent), fd_write(1, …) via host’s Console.write_line, fd_write(2, …) via the same or a separate log cap.
  • Stub everything else as ERRNO_NOSYS. Verify a probe module receives ERRNO_NOSYS for each unimplemented import.
  • Add demos/wasi-hello-rust/ built for wasm32-wasip1 and demos/wasi-hello-c/ built with clang --target=wasm32-wasi (or wasi-sdk if available). Both must print Hello from WASI on capOS and exit cleanly.
  • Add system-wasi-hello-rust.cue and system-wasi-hello-c.cue manifests; embed the produced .wasm blob bytes inline (no capnp schema change).
  • Add make run-wasi-hello-rust and make run-wasi-hello-c targets.
  • Update docs/programming-languages.md WASI row to note Phase W.2 landed: C runs on capOS without any libcapos/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 LaunchParameters surface exists, ship a bounded text grant in the host adapter manifest as the v0 argv source. Document the migration path so the future LaunchParameters surface replaces the bounded text grant when it lands.
  • Add demos/wasi-cli-args/ smoke that reads argv[1] and prints it back; assert the printed value matches the manifest grant.
  • Add system-wasi-cli-args.cue and make run-wasi-cli-args target.
  • 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 EntropySource cap through the host adapter so random_get returns 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 granted EntropySource cap and asserts entropy bounds; ungranted manifest variant proves refusal.
  • Add system-wasi-random.cue and make run-wasi-random target.
  • 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 Namespace caps from the manifest. Implement path_open, fd_read, fd_write, fd_seek, fd_close, fd_filestat_get, fd_prestat_get, fd_prestat_dir_name against the available Namespace/File/Store cap surface.
  • Add demos/wasi-fs/ smoke that reads and writes a file inside a preopened capOS namespace; assert ungranted-namespace path-open attempts return ERRNO_BADF / ERRNO_ACCES.
  • Add system-wasi-fs.cue and make run-wasi-fs target.
  • 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_shutdown against TcpSocket / UdpSocket caps once the userspace network stack lands. Until then, ship an HTTP client over Fetch/HttpEndpoint as 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.cue and make run-wasi-net target.
  • Blocked until the userspace network stack (or the Fetch/HttpEndpoint v0 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 std and 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.capnp variants needed for Component Model resource bridging. Schema serial-surface coordination required: queue on the shared schema/capos.capnp serial surface per docs/plans/README.md Concurrency Notes; only one plan at a time may add or change interfaces in schema/capos.capnp. Run make generated-code-check before 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.cue and make run-wasi-component-bridge target.
  • 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 future ScriptPackage cap (same shape as the planned LaunchParameters work).
  • Add demos/wasi-cue-evaluator/ smoke that evaluates a small CUE expression and prints the canonicalised result.
  • Add system-wasi-cue-evaluator.cue and make run-wasi-cue-evaluator target.
  • Cross-link the bridge to native GOOS=capos planning in docs/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.