VibeAI Virtual Hosts
A Wasm runtime platform where the sandbox never touches the host
wasm-box runs WebAssembly modules the way Docker runs containers — daemon, registry, CLI, dashboard — but isolation comes from the Wasm memory model and a capability firewall instead of kernel namespaces. Every number below is from a real run on this machine.
The capability pipeline
The load-bearing idea, formalized from the original sketch: a module sees only its Context; every request crosses the Firewall; only the Host Machine Interface touches anything real. Reading right to left is the guest's view of the world.
WASM module
- linear memory only, hard-capped
- fuel-metered CPU, per-message refill
- imports: WASI + vibeai ABI
- no sockets, no host fs, no env
Context
- data: fs preopens, db, cache buckets
- network: policy + allowlist
- argv, env, stdin — explicit only
- declared in vhost.toml / flags
Firewall
- data layer registration check
- network layer registration check
- allow -> forward to HMI
- deny -> reason back to guest
- JSONL audit log of every attempt
Host Machine Interface
- data: per-module SQLite, cache, folders
- network: HTTP client, size-capped
- planned: APIs, models, DNS, services
Host machine
- never sees the guest
- daemon socket chmod 600
System overview
Three tiers. Clients speak JSON to the daemon; the daemon owns policy and state; the engine executes. The daemon runs as a standalone service — no frontend needs to exist for it to work.
Sandbox guarantees
Each threat maps to a specific enforcement mechanism, and each one has been exercised with a hostile test module.
Message flows
Three ways data moves at runtime. The daemon routes every hop, so inter-module traffic stays observable and policeable in one place.
Service lifecycle & supervision
A service instance is owned by a supervisor task for its whole life. Restart policy decides what happens when it stops; explicit stop always wins.
| transition | trigger | what happens |
|---|---|---|
| running -> exited | guest returns / proc_exit | outcome + log tail recorded; on-failure with exit 0 rests, always restarts |
| running -> failed | trap, fuel exhausted | error recorded; on-failure and always go to backoff |
| failed -> backoff -> running | restart policy | 1s doubling to 30s; a healthy 60s resets the clock; restart count on the record |
| running -> stopped | wasm-box stop | stop flag set, inbox closes, guest's next_msg_len returns -1, loop exits clean — never restarted, desired state cleared |
| daemon restart | crash or upgrade | runs.json survives; anything running is marked failed with a reason; always-services relaunch from services.json |
vhost.toml — the virtual host definition
One file declares a named set of modules with their capabilities and budgets — the platform's Dockerfile and compose in one. wasm-box up makes it real.
[host] name = "my-app" [modules.api] module = "api" # registry tag or ./path.wasm service = true # long-running, message inbox restart = "always" # survives crashes AND daemon restarts [modules.api.data] db = true # private sqlite, module-scoped cache = ["session"] # named buckets, per-module [[modules.api.dirs]] host = "./data" guest = "/data" writable = true [modules.api.network] policy = "allowlist" allow = ["api.example.com"] [modules.api.limits] memory_mb = 64 fuel_per_message = 5000000
On-disk layout
Everything the platform knows lives under one data directory (default ~/.wasm-box) — trivially backed up, inspected, or wiped.
~/.wasm-box/ |- blobs/<sha256>.wasm immutable module bytes, deduplicated by digest |- index.json tag -> digest, size, created (the "images" list) |- runs.json run history — survives daemon restarts |- services.json desired state: always-restart services to relaunch |- firewall.log JSONL audit: every network attempt, every denial `- moduledb/<module>.sqlite3 private per-module databases, isolation by construction
CLI surface
# modules (the "images" workflow) wasm-box load app.wasm --name app wasm-box modules wasm-box rm app # batch runs echo '{"q":"hi"}' | wasm-box run app --stdin --db --allow-net api.example.com # services wasm-box start app --restart always --fuel-per-msg 5000000 --cache session wasm-box send 3 "payload" wasm-box logs 3 wasm-box stop 3 # fleet wasm-box up # reads vhost.toml wasm-box ps # status, restarts, fuel, duration
Full specs live in the repo: ARCHITECTURE.md, docs/COMMUNICATION.md, docs/DIAGRAMS.md (Mermaid sources for every diagram here).