WebAssembly SDK contract
This document defines the Application Binary Interface (ABI) and host capabilities that you need to build a custom fluxrig WebAssembly (Wasm) Gear. fluxrig relies on a language-agnostic Wasm execution environment (Wazero). You can author your business logic in any language that compiles to wasm32-freestanding or wasm32-wasi. Examples are Zig, Rust, C++, Go, and AssemblyScript. Adhere to this contract.
Filter architecture & implicit ports
NOTE
Current topology role: The project currently implements the Wasm gear strictly as a Filter gear (1-to-1 or 1-to-0). It receives exactly one input message, processes it synchronously, and returns exactly one output message (or drops it).
Because of this strict filter pattern, the Wasm gear uses implicit ports. You do not need to define a ports block in its configuration.
- Input (
.in): The router automatically routes incoming messages to the gear's.inport, which triggers the Wasmprocess()function. - Output (
.out): The gear automatically emits the result thatprocess()returns on the.outport.
(The project plans support for Source/Split Wasm gears that generate spontaneous messages via env.emit for a future release).
The memory interface
WebAssembly restricts execution to an isolated linear memory sandbox. To pass data between the fluxrig host (the Rack) and the Wasm guest (your Gear), you must export basic memory allocation functions.
Required exports
Your Wasm module must export the following three functions:
alloc
alloc(len: i32) -> i32
The host calls it to allocate memory inside the guest's linear memory.
len: The number of bytes the guest allocates.- Returns: It returns an
i32pointer to the allocated memory block.
free
free(ptr: i32, len: i32)
The host calls it to free memory that the guest previously allocated.
ptr: It gives the starting pointer of the memory block.len: It gives the length of the memory block in bytes.
process
process(ptr: i32, len: i32) -> i64
The main execution entrypoint. The host calls it when a new message arrives at the Gear.
ptr: A pointer to the CBOR-encodedfluxMsgpayload that the host already wrote to guest memory.len: It gives the length of the CBOR payload in bytes.- Returns: It returns a packed 64-bit integer (
i64). The host uses bitwise shifting to unpack this into two 32-bit integers:- High 32 bits: It gives the return pointer to the modified CBOR payload.
- Low 32 bits: It gives the return length of the modified payload.
If you wish to drop a message, return 0.
Host imports (capabilities)
To interact with the host system (e.g., logging or state access), the host exposes a set of functions under the env namespace. You must import these explicitly in your language.
env.log
env.log(level: i32, ptr: i32, len: i32)
It emits a structured log message to the Rack's central telemetry stream.
level: It gives the severity level (e.g.,1=Debug,2=Info,3=Warn,4=Error).ptr: It gives the pointer to the UTF-8 encoded log message.len: It gives the length of the log message.
env.emit [Roadmap / Future]
env.emit(ptr: i32, len: i32)
(The project plans it for a future release). It allows the Wasm gear to spontaneously generate new messages or split a single message into multiple messages (Fan-out). The Wasm module allocates memory, writes the CBOR payload, and calls env.emit. The host reads the memory and pushes the message to the wire asynchronously.
(The host will also expose future capabilities like flux_kv_get or flux_req_http under the env module, and scenario-level permissions will govern them).
Signal format (CBOR)
For performance, the fluxrig host does not pass strings or JSON. Input payloads are CBOR encoded (RFC 8949) representations of the fluxMsg struct.
Your module must:
- Decode the CBOR payload from the input pointer.
- Apply business logic to the
fluxMsgfields (e.g., routing headers, raw payload, metadata). - Encode the modified data back into CBOR.
- Allocate space for the new CBOR data.
- Return the packed pointer/length.
Memory lifecycle
- Host receives a message on the bus.
- Host calls
alloc(len)on the guest to reserve space. - Host writes the CBOR payload into guest memory at the returned pointer.
- Host calls
process(ptr, len). - Guest processes the message, allocates new memory for the result, writes the new CBOR, and returns the packed
u64. - Host reads the new CBOR from the returned pointer.
- Host calls
freeon both the original input pointer and the new output pointer to prevent memory leaks.