104 lines
4.2 KiB
Markdown
104 lines
4.2 KiB
Markdown
|
|
# Path D — `kind = 'Wasm`
|
||
|
|
|
||
|
|
Phase B per ADR-030 — **declarable today, executive backend deferred**.
|
||
|
|
The op body is a WASM component implementing a WIT-typed interface; the
|
||
|
|
daemon (when built with `--features wasm`) hosts it via `wasmtime`
|
||
|
|
inside an explicit capability sandbox.
|
||
|
|
|
||
|
|
## Files
|
||
|
|
|
||
|
|
| File | Purpose |
|
||
|
|
| --- | --- |
|
||
|
|
| [`render_provisioning_report.ncl`](render_provisioning_report.ncl) | Catalog declaration with `kind = 'Wasm` and a fully-populated `body` |
|
||
|
|
| [`render_provisioning_report.wit`](render_provisioning_report.wit) | WIT interface — the host/guest contract |
|
||
|
|
|
||
|
|
## What the `body` declares
|
||
|
|
|
||
|
|
| Field | Value | Meaning |
|
||
|
|
| --- | --- | --- |
|
||
|
|
| `module_path` | `.ontoref/catalog/wasm/render_provisioning_report.wasm` | Built WASM artefact, project-relative |
|
||
|
|
| `export_name` | `ontoref:catalog/op#render` | Exported function the host calls |
|
||
|
|
| `capabilities` | `["fs:read:.ontology/provisioning/", "fs:read:.ontoref/catalog/", "net:none"]` | Explicit grant set — anything else traps |
|
||
|
|
|
||
|
|
## Today's runtime behaviour
|
||
|
|
|
||
|
|
Dispatching against a stock daemon returns:
|
||
|
|
|
||
|
|
```
|
||
|
|
HTTP/1.1 501 Not Implemented
|
||
|
|
{
|
||
|
|
"error": "missing_executive_backend",
|
||
|
|
"kind": "Wasm",
|
||
|
|
"op_id": "render_provisioning_report",
|
||
|
|
"hint": "rebuild ontoref-daemon --features wasm (awaiting ADR-030 T3/T4/T5 trigger)"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
This is intentional per ADR-034 constraint
|
||
|
|
`non-rust-kinds-declarable-not-executable-without-flag`. The op
|
||
|
|
declaration is a first-class catalog entry that consumers can read
|
||
|
|
cross-project via ADR-028 content-addressing right now.
|
||
|
|
|
||
|
|
## Building the WASM artefact (when the executive backend lands)
|
||
|
|
|
||
|
|
```sh
|
||
|
|
# 1. Author the implementation against the WIT interface — any source
|
||
|
|
# language that supports the component model: Rust, AssemblyScript,
|
||
|
|
# Go (with tinygo), Zig, Python (via Pyodide), …
|
||
|
|
|
||
|
|
# 2. For a Rust implementation:
|
||
|
|
cargo build -p render-provisioning-report --target wasm32-unknown-unknown --release
|
||
|
|
|
||
|
|
# 3. Convert the core wasm to a component:
|
||
|
|
wasm-tools component new \
|
||
|
|
target/wasm32-unknown-unknown/release/render_provisioning_report.wasm \
|
||
|
|
-o .ontoref/catalog/wasm/render_provisioning_report.wasm
|
||
|
|
```
|
||
|
|
|
||
|
|
## Why WASM is Phase B (deferred)
|
||
|
|
|
||
|
|
Per ADR-030 the WASM backend awaits one of:
|
||
|
|
|
||
|
|
- **T3** — cross-instance ops dispatch becomes the bottleneck (HTTP IPC
|
||
|
|
chain in Path B Sidecar exceeds acceptable latency)
|
||
|
|
- **T4** — toolchain divergence — an instance wants ops in
|
||
|
|
Go / Python / AssemblyScript and dynlib is too brittle
|
||
|
|
- **T5** — untrusted ops authors — the deployment must sandbox ops from
|
||
|
|
outside the instance's control
|
||
|
|
|
||
|
|
None of these have fired empirically. Path B (Sidecar) covers the
|
||
|
|
shared-domain near-term case at ~80 LOC of daemon proxy; WASM lands
|
||
|
|
when concrete pressure justifies the wasmtime dependency.
|
||
|
|
|
||
|
|
## Key properties
|
||
|
|
|
||
|
|
- **`evaluate_ondaod` is mandatory** — the host invokes ondaod
|
||
|
|
discipline BEFORE entering the sandbox. The WASM module cannot reach
|
||
|
|
the ondaod context.
|
||
|
|
- **Witness honesty** — `payload_kind = "wasm_call_envelope"`. The
|
||
|
|
daemon's Ed25519 signature attests the inputs it passed and the
|
||
|
|
outputs it received; it does NOT claim to attest the WASM-internal
|
||
|
|
computation (the sandbox is honest about being a black box).
|
||
|
|
- **Capability sandbox** — every fs/net interaction must be in the
|
||
|
|
`capabilities` list. Anything else returns a wasmtime host trap.
|
||
|
|
Designed for the T5 untrusted-author case.
|
||
|
|
- **wasmtime is NOT in the default daemon build** — ADR-034 constraint
|
||
|
|
`wasmtime-not-in-default-daemon-build`. Honours `protocol-not-runtime`
|
||
|
|
axiom (invariant=true).
|
||
|
|
|
||
|
|
## When NOT to use
|
||
|
|
|
||
|
|
- Your op is part of the ontoref piloto → Path A `'Rust`.
|
||
|
|
- Your project is a shared-domain instance and the bottleneck is
|
||
|
|
process management overhead, not the IPC boundary → Path B
|
||
|
|
`'Sidecar` is the right Phase A answer.
|
||
|
|
- The op is a trivial NCL data-transform → Path C `'NclTransform`
|
||
|
|
(lower complexity than WASM, no wasmtime needed).
|
||
|
|
|
||
|
|
## References
|
||
|
|
|
||
|
|
- [ADR-034 — Catalog extensibility beyond Rust](../../../.ontoref/adrs/adr-034-catalog-extensibility-beyond-rust.ncl)
|
||
|
|
- [ADR-030 mechanism #3 — WasmComponents](../../../.ontoref/adrs/adr-030-catalog-discovery-cross-project.ncl)
|
||
|
|
- [`schema-future.ncl::WasmBody`](../schema-future.ncl)
|
||
|
|
- [WIT component model spec](https://component-model.bytecodealliance.org/design/wit.html)
|