Skip to content

wasm

import "github.com/stablekernel/crucible/wasm"

Package wasm runs Crucible behaviors authored as WebAssembly modules, invoked over a serializable JSON ABI through the pure-Go wazero runtime (no CGo). It is the polyglot binding path: a guard (and later a service) can be implemented in any language that compiles to WebAssembly, and the host calls it with a JSON request and reads a JSON response.

The module lives apart from the kernel so the wazero dependency never enters the stdlib-only core. The ABI is core WebAssembly plus two exported functions — alloc and eval — over the guest’s linear memory; it is not the WebAssembly Component Model (which would require a CGo runtime), trading that for a pure-Go host.

func Guard[S comparable, C any](reg *state.Registry[C], name string, mod *Module) state.GuardNode[S]

Guard registers a WebAssembly-backed guard under name in reg and returns the rich IR node that references it. The module is already compiled (Compile); Guard only binds it, so a JSON-authored machine that Provides reg resolves the guard to the WASM evaluator. The returned node composes like any named-ref guard: drop it into a transition with WhenExpr, or combine it with And/Or/Not. It is tagged rich so analysis knows its truth lives in the module rather than the kernel’s tree.

CompileOption configures Compile. New capabilities arrive as additional options, so the signature never breaks. No option changes the default behavior; each is additive.

type CompileOption func(*compileConfig)

func WithRuntimeConfig(cfg wazero.RuntimeConfig) CompileOption

WithRuntimeConfig overrides the wazero RuntimeConfig the module is built with, for hosts that need to tune compilation (interpreter vs compiler), memory limits, or other wazero knobs. The default already closes a running guest when the call context is done, so a caller that supplies its own config should retain WithCloseOnContextDone(true) to keep timeout/cancellation working.

Module is a compiled and instantiated WebAssembly behavior module exposing the Crucible JSON ABI. A guest exports:

alloc(size uint32) uint32 — reserve size bytes, return the pointer
eval(ptr uint32, size uint32) uint64 — evaluate the JSON request at [ptr,ptr+size),
return packed (outPtr<<32 | outLen)

One Module owns one linear memory, so Eval serializes concurrent calls behind a mutex. Close releases the runtime.

type Module struct {
// contains filtered or unexported fields
}

func Compile(ctx context.Context, wasmBytes []byte, opts ...CompileOption) (*Module, error)

Compile instantiates a behavior module from its WebAssembly bytes and resolves its ABI exports. The bytes are a wasip1 module (a Go //go:wasmexport guest, or any language’s equivalent); WASI preview 1 is provided for the Go runtime’s needs.

The runtime is built with WithCloseOnContextDone(true), so a guest that runs away (an infinite loop, a pathological input) is interrupted when the context passed to Eval / Compile is canceled or hits its deadline: the call returns an error rather than blocking the host indefinitely. Pass a per-call timeout context to bound a guest’s execution.

func (m *Module) Close(ctx context.Context) error

Close releases the underlying runtime and its instances.

func (m *Module) Eval(ctx context.Context, request []byte) ([]byte, error)

Eval sends the JSON request to the guest and returns its JSON response. It allocates input space in the guest, writes the request there, calls eval, and reads the response back from the returned pointer. Calls are serialized.

Generated by gomarkdoc