Something went wrong. Try again.
Flatpak-style launcher for sandboxed WebAssembly tools. Install, verify, and run .wasm binaries with explicit capability grants. Single binary, local-first, zero telemetry. wasmbox.orbiter.website
wasm rust wasmbox
Something went wrong. Try again.
15 kB · 239 lines
HTML
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240<!doctype html><html lang="en" data-theme="dark"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="generated" content="2026-05-19T19:41:01Z"><title>WasmBox — Plan</title><style>:root { --bg:#0a0a0a; --fg:#e8e8e8; --muted:#888; --accent:#7dd3fc; --code-bg:#141414; --border:#222; --mono:ui-monospace,SFMono-Regular,Menlo,monospace; --sans:system-ui,-apple-system,sans-serif; --ok:#86efac; --warn:#fde047; --bad:#fca5a5; }@media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) { --bg:#fafafa; --fg:#111; --muted:#555; --accent:#0369a1; --code-bg:#f0f0f0; --border:#ddd; --ok:#16a34a; --warn:#a16207; --bad:#b91c1c; } }html { background: var(--bg); color: var(--fg); font-family: var(--sans); }body { max-width: 1100px; margin: 0 auto; padding: 2rem 1.5rem 6rem; line-height: 1.6; }header { display:flex; justify-content:space-between; align-items:baseline; border-bottom:1px solid var(--border); padding-bottom:1rem; margin-bottom:2rem; }header nav a { color: var(--muted); text-decoration: none; margin-right: 1rem; }header nav a:hover { color: var(--fg); }h1,h2,h3 { font-weight:600; line-height:1.2; }h1 { font-size:2rem; margin:0 0 0.5rem; }h2 { font-size:1.4rem; margin-top:3rem; border-bottom:1px solid var(--border); padding-bottom:0.4rem; }h2 a.anchor { color:var(--muted); text-decoration:none; opacity:0; margin-left:0.5rem; font-size:0.85em; }h2:hover a.anchor { opacity:1; }h3 { font-size:1.1rem; margin-top:2rem; color:var(--accent); }a { color: var(--accent); }code, pre { font-family: var(--mono); font-size: 0.9em; }pre { background:var(--code-bg); border:1px solid var(--border); padding:1rem; overflow-x:auto; border-radius:4px; }code:not(pre code) { background:var(--code-bg); padding:0.1em 0.4em; border-radius:3px; }mark { background:#fde047; color:#000; padding:0.1em 0.4em; }table { border-collapse:collapse; width:100%; margin:1rem 0; }th, td { text-align:left; padding:0.6rem 0.8rem; border-bottom:1px solid var(--border); vertical-align:top; }th { color:var(--muted); font-weight:500; font-size:0.85em; text-transform:uppercase; letter-spacing:0.05em; }footer { margin-top:6rem; padding-top:1rem; border-top:1px solid var(--border); color:var(--muted); font-size:0.85em; }#toc { background:var(--code-bg); border-left:2px solid var(--accent); padding:0.8rem 1.2rem; margin:2rem 0; }#toc ol { margin:0; padding-left:1.2rem; }#toc a { color:var(--fg); text-decoration:none; }.diagram { background:var(--code-bg); border:1px solid var(--border); padding:1rem; margin:1rem 0; }.diagram svg { display:block; max-width:100%; height:auto; }.pill { display:inline-block; font-size:0.75em; padding:0.1em 0.5em; border-radius:10px; font-family:var(--mono); }.pill.ok { background:rgba(134,239,172,0.15); color:var(--ok); }.pill.wip { background:rgba(125,211,252,0.15); color:var(--accent); }.pill.todo { background:rgba(136,136,136,0.15); color:var(--muted); }.pill.warn { background:rgba(253,224,71,0.15); color:var(--warn); }.pill.bad { background:rgba(252,165,165,0.15); color:var(--bad); }dl.qa dt { font-weight:600; color:var(--accent); margin-top:1rem; }dl.qa dd { margin:0.3rem 0 0 0; color:var(--muted); }</style></head><body><header> <nav> <a href="./index.html">WasmBox</a> <span style="color:var(--muted)">/ plan</span> </nav> <button onclick="document.documentElement.dataset.theme = document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark'" style="background:none;border:1px solid var(--border);color:var(--fg);padding:0.3em 0.6em;cursor:pointer;border-radius:3px;font-size:0.8em">theme</button></header>
<h1>Plan</h1><p style="color:var(--muted)">Scope, milestones, risks, mockups, open questions.</p>
<nav id="toc"> <ol> <li><a href="#goals">Goals</a></li> <li><a href="#non-goals">Non-goals</a></li> <li><a href="#milestones">Milestones</a></li> <li><a href="#risks">Risks</a></li> <li><a href="#mockups">Mockups</a></li> <li><a href="#questions">Open questions</a></li> </ol></nav>
<h2 id="goals">Goals <a class="anchor" href="#goals">#</a></h2><p>WasmBox exists because installing desktop tools means trusting binaries with full system access, and existing sandboxes (Flatpak, Snap) ship heavy runtimes with OS-level integration. The goal is a single static binary that runs <code>wasm32-wasip2</code> tools with zero ambient authority, verifiable hashes, and a registry protocol so trivial any static file host counts as one. It must be useful for humans piping JSON through <code>jfmt</code> <em>and</em> for AI agents that need a deterministic, sandboxed, auditable tool surface — both audiences are treated as first-class.</p>
<p>Concretely, the v0.3 line ships three things: the runtime + CLI (v0.1), agent-first manifest plus discoverable skill files (v0.2), and a compliance layer — run log, declarative policy, signed audit export — that turns WasmBox into provable evidence under EU AI Act Article 14 (v0.3). The runtime stays MIT; only the compliance crate is FSL.</p>
<h2 id="non-goals">Non-goals <a class="anchor" href="#non-goals">#</a></h2><p>WasmBox is not a container runtime. It does not virtualise the kernel, manage cgroups, or run native binaries. It is not a package manager for system tools — it cannot replace <code>apt</code>, <code>brew</code>, or even <code>cargo install</code> for things that need raw OS access. It is not a hosted marketplace; there is no account system, no centralised registry, no payment rails, and there will never be telemetry. Auto-update is explicitly forbidden — every hash change goes through user-visible confirmation.</p>
<h2 id="milestones">Milestones <a class="anchor" href="#milestones">#</a></h2><table> <thead><tr><th>Version</th><th>Scope</th><th>Status</th></tr></thead> <tbody> <tr> <td><code>0.1</code></td> <td>Wasmtime runtime, CLI (install/run/list/search/info/verify/update/remove/permissions/audit/registry/hash), capability grants, SHA-256 verify, registry protocol, integration tests with wiremock + fixture wasm.</td> <td><span class="pill ok">shipped</span></td> </tr> <tr> <td><code>0.2</code></td> <td>Agent-first manifest section, machine-readable skill files (<code>tools/<name>.md</code>), <code>--json</code> on every command, demo registry with ten tools (jfmt, secretscan, compact, b64, errparse, hashit, epoch, yamlfmt, diffsummary, worldid-verify).</td> <td><span class="pill ok">shipped</span></td> </tr> <tr> <td><code>0.3.0</code></td> <td>EU AI Act Article 14 layer: append-only run log, declarative policy with enforce/warn/disabled modes, signed Ed25519 audit export, agent shell wrapper that blocks raw <code>jq</code>/<code>base64</code>/<code>sha256sum</code> and redirects to sandboxed equivalents.</td> <td><span class="pill ok">shipped</span></td> </tr> <tr> <td><code>0.3.2</code></td> <td>WASI HTTP outbound with per-host filtering — manifests declare <code>network = ["api.example.com", ...]</code> and the runtime rejects requests to any other host before they leave the sandbox.</td> <td><span class="pill ok">shipped (current)</span></td> </tr> <tr> <td><code>0.4</code></td> <td>Leptos web dashboard as a WasmBox tool itself. Local HTTP server crate (<code>crates/server</code>) for web-UI tools. Spin integration for backend tools needing persistent KV.</td> <td><span class="pill todo">planned</span></td> </tr> <tr> <td><code>0.5</code></td> <td>Optional Ed25519 publisher signatures on manifests (separate from audit-export signing). Cross-compile to <code>x86_64-unknown-linux-musl</code> for fully static Linux binary; binary size under 20MB via LTO + strip.</td> <td><span class="pill todo">planned</span></td> </tr> </tbody></table>
<h2 id="risks">Risks <a class="anchor" href="#risks">#</a></h2><table> <thead><tr><th>Risk</th><th>Likelihood</th><th>Mitigation</th></tr></thead> <tbody> <tr> <td>Wasmtime engine creation cost dominates short-lived tool runs.</td> <td><span class="pill warn">medium</span></td> <td>Engine is built once per <code>wasmbox run</code> invocation, not per call. Module cache deliberately invalidated on version change (no stale compile artifacts).</td> </tr> <tr> <td>WASI Preview 2 outbound HTTP shape still evolving across Wasmtime releases.</td> <td><span class="pill warn">medium</span></td> <td>Pinned to <code>wasmtime = "42"</code> in workspace. Per-host filter is enforced by WasmBox in <code>crates/runtime</code>, so even an upstream API change cannot widen the allow-list silently.</td> </tr> <tr> <td>Binary size (~26MB unstripped) too large for casual install.</td> <td><span class="pill warn">medium</span></td> <td>v0.5 goal: under 20MB via LTO + strip. Wasmtime is the dominant cost. Track via <code>du -sh target/release/wasmbox</code> in CI.</td> </tr> <tr> <td>FSL licensing on the compliance crate confuses contributors who assume MIT for the whole workspace.</td> <td><span class="pill warn">medium</span></td> <td>License clearly stated in README, in <code>crates/compliance/Cargo.toml</code>, and in the audit page footer. Conversion to Apache 2.0 after two years.</td> </tr> <tr> <td>Registry-protocol minimalism (plain HTTPS, no auth) means a hijacked registry can serve malicious manifests.</td> <td><span class="pill bad">high impact</span></td> <td>SHA-256 in manifest is the trust anchor — if a hijacker swaps a binary they must also rewrite the hash in the JSON, which is then visibly different on next <code>wasmbox update</code>. v0.5 publisher signatures add a second factor.</td> </tr> <tr> <td>Agents bypass sandboxed tools and call raw system commands anyway.</td> <td><span class="pill warn">medium</span></td> <td>v0.3 agent shell wrapper blocks <code>jq</code>, <code>yq</code>, <code>base64</code>, <code>sha256sum</code>, <code>date</code>, <code>trufflehog</code>, <code>python -c</code>, <code>node -e</code> and redirects. Every block logged to <code>run.log</code> for audit evidence.</td> </tr> </tbody></table>
<h2 id="mockups">Mockups <a class="anchor" href="#mockups">#</a></h2>
<h3>Install + run flow</h3><div class="diagram"><svg viewBox="0 0 760 280" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Install and run flow diagram"> <defs> <marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"> <path d="M0,0 L10,5 L0,10 z" fill="#7dd3fc"/> </marker> </defs> <style> .b { fill: #141414; stroke: #444; stroke-width: 1; } .t { fill: #e8e8e8; font: 13px ui-monospace, Menlo, monospace; } .l { stroke: #7dd3fc; stroke-width: 1.5; fill: none; } .m { fill: #888; font: 11px ui-monospace, Menlo, monospace; } </style> <rect class="b" x="20" y="20" width="140" height="60" rx="4"/> <text class="t" x="90" y="50" text-anchor="middle">user</text> <text class="m" x="90" y="68" text-anchor="middle">$ wasmbox install</text>
<rect class="b" x="220" y="20" width="140" height="60" rx="4"/> <text class="t" x="290" y="50" text-anchor="middle">CLI</text> <text class="m" x="290" y="68" text-anchor="middle">crates/cli</text>
<rect class="b" x="420" y="20" width="140" height="60" rx="4"/> <text class="t" x="490" y="50" text-anchor="middle">registry client</text> <text class="m" x="490" y="68" text-anchor="middle">reqwest + rustls</text>
<rect class="b" x="600" y="20" width="140" height="60" rx="4"/> <text class="t" x="670" y="50" text-anchor="middle">registry</text> <text class="m" x="670" y="68" text-anchor="middle">static HTTPS</text>
<line class="l" x1="160" y1="50" x2="215" y2="50" marker-end="url(#arr)"/> <line class="l" x1="360" y1="50" x2="415" y2="50" marker-end="url(#arr)"/> <line class="l" x1="560" y1="50" x2="595" y2="50" marker-end="url(#arr)"/>
<rect class="b" x="220" y="120" width="140" height="60" rx="4"/> <text class="t" x="290" y="150" text-anchor="middle">verify</text> <text class="m" x="290" y="168" text-anchor="middle">sha256 (subtle)</text>
<rect class="b" x="420" y="120" width="140" height="60" rx="4"/> <text class="t" x="490" y="150" text-anchor="middle">permissions</text> <text class="m" x="490" y="168" text-anchor="middle">prompt + store</text>
<rect class="b" x="220" y="220" width="340" height="40" rx="4"/> <text class="t" x="390" y="245" text-anchor="middle">~/.wasmbox/{cache,permissions.toml,run.log}</text>
<line class="l" x1="290" y1="80" x2="290" y2="115" marker-end="url(#arr)"/> <line class="l" x1="290" y1="180" x2="290" y2="215" marker-end="url(#arr)"/> <line class="l" x1="490" y1="80" x2="490" y2="115" marker-end="url(#arr)"/> <line class="l" x1="490" y1="180" x2="490" y2="215" marker-end="url(#arr)"/></svg></div>
<h3>First-run capability prompt</h3><pre>$ wasmbox run crypts
crypts v0.2.0 — File encryption tool Author: Aunova | License: MIT Hash: sha256:a1b2c3d4... [VERIFIED]
Requested capabilities: stdin: yes stdout: yes filesystem: ~/Documents (read+write) network: []
Allow? [Y/n]</pre>
<p>The prompt is rendered by <code>crates/permissions</code> and skipped only when stdin is non-TTY <em>and</em> <code>--allow-all</code> was passed. Otherwise the run exits with code 2 (permission denied).</p>
<h2 id="questions">Open questions <a class="anchor" href="#questions">#</a></h2><dl class="qa"> <dt>Should the Leptos dashboard ship as its own <code>.wasm</code> tool consumable through the same registry, or as a built-in subcommand?</dt> <dd>Leaning toward dogfooding it as a tool — proves the web-UI capability path end to end and keeps the core binary small. <mark>TODO: decide before v0.4 cut.</mark></dd>
<dt>Should publisher signatures on manifests be mandatory at v1.0 or remain optional?</dt> <dd>Mandatory adds friction for hobby publishers; optional keeps adoption easy but weakens trust. <mark>TODO: revisit after first community tool author submits.</mark></dd>
<dt>Is the FSL/MIT split sustainable, or should compliance be a paid SaaS layer instead?</dt> <dd>FSL satisfies "free for individuals and small teams, paid above 5 users" without losing the source-available promise. Re-evaluate if revenue from FSL conversions is meaningful by end of 2026.</dd></dl>
<footer> <time datetime="2026-05-19T19:41:01Z">2026-05-19</time> · WasmBox · <code>f36febc</code></footer></body></html>