Issue #108 WebAssembly interface prototype review
Date: 2026-09-28
Status: review requested; documents only
Decision owner: Gabriel / Muse maintainers
Related issue: #108 — safe independently owned executable domain plugins
Why this document exists
Gabriel approved a prototype with:
looks good. prototype it. I'm interested to see the webassembly interface.
VideoFactory has now completed a local prototype of the call surface. This document presents that interface for Muse review. It does not add executable code to Muse, create a package, or change MuseHub behavior.
Executive summary
The prototype wraps the existing host-neutral video_timeline engine without
changing the engine. It targets wasm32-unknown-unknown, has no host imports,
and exposes five first-release domain operations:
validatesnapshotdiffmergemigrate
The module was exercised locally through an empty wasmi linker against public
fixtures. Native and guest results agreed. Invalid configuration and malformed
input refused closed.
This is a call-surface prototype. It is not the final Muse guest ABI, a Muse package, a package identity, a signature, an installation, a registry row, a MuseHub upload, or a deployment. MuseHub remains non-executing in v1.
Interface shown
The prototype identity is the exact 37-byte UTF-8 string:
video_timeline.wasm_iface/prototype-1
That string is not the future package name, package digest, or real ABI version.
The module exports linear memory and these eight functions:
| Export | Purpose |
|---|---|
vt_prototype_id |
Return the prototype identity |
vt_alloc |
Allocate an input or output buffer in guest memory |
vt_free |
Release a guest buffer |
vt_validate |
Validate a versioned candidate |
vt_snapshot |
Produce canonical state bytes and digest |
vt_diff |
Produce the engine's semantic-diff summary |
vt_merge |
Produce a merged result or structured conflicts |
vt_migrate |
Perform an explicit supported migration or refuse |
Inputs and outputs are length-delimited buffers in guest linear memory. Domain
results are deterministic JSON envelopes. Status 0 means success, status 1
means a domain/prototype refusal with a refusal envelope, and status 2 means
an envelope or allocation failure that could not write a body.
apply, drift, and schema are deliberately absent from the first-release
guest operations. Installation, signing, registry, and process-control
functions are also absent.
Configuration and capability rule
The accepted configuration bytes are only:
- zero bytes; or
- the exact two bytes
7b 7d({}).
Every other configuration refuses class capability before an engine call.
Configuration is not a capability channel.
The guest has no WASI and no filesystem, environment, clock, random, network, socket, process, or dynamic-module imports. The demonstrated module had no import section.
Memory and envelope boundary
- Each document buffer is limited to 16 MiB.
- Live guest allocations are limited to 32 MiB.
- Output envelopes are limited to 16 MiB.
- The host selects and copies exact in-memory inputs; the guest does not select repository paths, object-store identifiers, files, or URLs.
- A path list, URL list, or multi-file input set refuses class
envelope. - Output buffers are guest allocated, copied by the host, and then released
through
vt_free.
Refusal classes
The closed refusal-class set is:
parse
schema
validation
limit
digest
migration
extent
envelope
capability
The first seven preserve the existing timeline engine's refusal text.
envelope and capability are raised by the prototype before an engine call.
Demonstration evidence
The following whole-file SHA-256 values identify the frozen VideoFactory-local evidence. They are evidence pins, not package identities:
| Evidence | SHA-256 | Result |
|---|---|---|
| Prototype-boundary freeze | 9b1b43b0c85c55ec1a3c36e26ce0a5ae9aac1c959361e9c2094ea5087964f91e |
Frozen |
| Independent review of those exact freeze bytes | fd132ff86be3c91e058011ebcf538421dff894bcd0090a0cf3f9a9b720217fe1 |
PASS |
| Local demonstration record | 86249a13659b53645f2576905b071958a6c967cde2d374d58a425aa629cee8fc |
PASS |
| Independent build verification | 6ae93f79d48d6bda40826b6035cc775c2570f34fbc7733beab5755b40153b70c |
PASS |
The demonstrated local module was 968,524 bytes with SHA-256
e6d9c3110fb9960f8e221812e140623b401c93de6be3616f3a9da3424653ac00.
That digest identifies one local demonstration build only. The generated module
has not been uploaded, signed, packaged, installed, or registered.
The adapter verification covered:
- the closed function-export set plus linear memory;
- the empty host-import table;
- all five operations against public fixtures;
- native/guest result agreement;
- accepted and refused configuration bytes;
- input, output, and allocation limits;
- deterministic bodies from fresh processes;
- 1,000 repeated snapshot calls without retained project state; and
- failed linking for synthetic WASI, clock, random, filesystem, network, and process imports.
The prototype source remains in VideoFactory custody. No video_timeline source
or executable module has been copied into Muse by this review document.
What this proves—and what remains
This demonstrates that the existing timeline engine can be called through a small WebAssembly ABI without ambient host imports.
It is not yet the production isolation boundary. A production Muse runner still needs:
- explicit fuel or execution deadlines;
- runtime memory, stack, and table limits;
- a fresh-instance or worker-process lifecycle;
- cancellation and crash containment;
- strict input-handle brokering and output validation;
- deterministic runtime-version rules; and
- isolation, interruption, resource-exhaustion, and canary-secret tests.
The platform also still needs the package descriptor and identity, canonical signing payload, publisher-key and update rules, exact digest/history binding, install/activate/remove semantics, compatibility negotiation, registry row, private access, revocation, rollback, and staging qualification.
Decisions requested from Gabriel
Please confirm or redirect these points before the Muse/MuseHub contract is frozen:
- Keep a raw linear-memory ABI for v1, or move the contract to WIT/the component model?
- Keep the
vt_*export names, or rename them for the real versioned guest ABI? - Confirm the first release has exactly
validate,snapshot,diff,merge, andmigrate; no guestapply,drift, orschemaoperation. - Confirm MuseHub v1 stores, indexes, authorizes, and serves packages but never instantiates, links, or executes them.
- Authorize a documents-only contract freeze covering package identity, canonical signing, publisher authorization, exact digest/history binding, lifecycle commands, registry shape, compatibility, and capability refusals.
Questions 1–4 review the interface. Question 5 authorizes specification and independent review of the missing platform contract. It does not authorize a package, signature, installation, catalog entry, deployment, or production change.
Gated path after review
- Freeze and independently review the Muse/MuseHub ABI and package contract.
- Adapt the VideoFactory wrapper to the approved ABI and complete the production isolation proof without redesigning the timeline engine.
- After that build verification passes, produce a reproducible signed package and local Muse install/activation proof.
- Implement MuseHub's non-executing immutable package storage, publisher and access controls, registry metadata, and generic viewer.
- Run staging proofs for exact retrieval, signature/digest verification, local Muse execution, history binding, refusal, revocation, rollback, and mixed versions.
Each gate requires its own review. This document does not start those gates.