greentic-interfaces
Define the WebAssembly interface types shared by Greentic component modules and their hosts. The WIT files under wit/ are versioned by package name to enable additive evolution without breaking existing components.
Package overview
greentic:component@0.3.0exposes the original contract used by early components. Hosts provide atenant-ctxand receive a JSON payload or plain string error. Streaming and lifecycle hooks are not available.greentic:component@0.4.0adds structured execution context, explicit error envelopes, and streaming progress. Components surface cooperative control via thecontrolinterface and may opt into lifecycle hooks (on-start,on-stop).
Usage
Add the crate to your Wasmtime host:
[]
= "0.1"
= { = "21", = ["component-model"] }
Then wire the bindings into a component host:
use ;
use ;
use ;
use ;
;
type HostFuture<'a, T> = ;
let mut config = new;
config.wasm_component_model;
let engine = new?;
let mut linker = new;
add_control_to_linker?;
let component = from_file?;
let mut store = new;
let = instantiate_async.await?;
let node = bindings.exports.greentic_component_node?;
let ctx = ExecCtx ;
let result = node.invoke.await?;
The helper HostFuture alias keeps the trait signatures readable; the generated bindings expect pinned Futures.
At build time, ensure scripts/validate-wit.sh runs so the packaged WIT stays well-formed.
Mapping to greentic-types
Rust type (greentic-types) |
WIT type |
|---|---|
TenantCtx |
node::tenant-ctx |
ExecCtx |
node::exec-ctx |
InvokeResult |
node::invoke-result |
StreamEvent |
node::stream-event |
NodeError |
node::node-error |
LifecycleStatus (newtype) |
node::lifecycle-status |
All structured payloads are JSON strings (type json = string) to stay language-agnostic. Components should deserialize into native types as needed.
Version negotiation
Hosts should enumerate supported packages in descending order and attempt to instantiate the highest version offered by the component module. When a module only implements component@0.3.0, the host must fall back to the legacy interface and avoid calling lifecycle or streaming APIs. When both parties expose component@0.4.0, hosts are expected to:
- Bind the
controlinterface (if the component imports it) to cooperate with cancellation and scheduling. - Invoke lifecycle hooks opportunistically. Components that do not need them must still export the functions but may return
Ok(())immediately. - Prefer
invoke-streamwhen progressive updates are desired; otherwise callinvoke.
Consumers should document the chosen version in their manifest to simplify future migrations.
Error semantics
invokereturnsinvoke-result. A successful execution wraps the JSON payload inok(json).- Recoverable failures surface as
err(node-error)withretryable = trueand an optionalbackoff-mshint. - Non-retryable errors set
retryable = false. Hosts may surfacemessagedirectly to operators. invoke-streamis expected to end with eitherstream-event::doneorstream-event::error. Specific progress updates usestream-event::progresswith values from0to100.on-start/on-stopreturnlifecycle-status::okwhen the hook succeeds andErrwith a descriptive string otherwise.
Legacy component@0.3.0 continues to use result<json, string> for synchronous replies; hosts should translate that into invoke-result::ok or a generic node-error when bridging between versions.
Rust bindings
src/component_v0_3.rs and src/component_v0_4.rs expose wasmtime::component::bindgen! output to make hosting components easy:
component_v0_3::Componentprovides strongly‑typed access to the@0.3.0exports.component_v0_4::Componentdoes the same for@0.4.0, andcomponent_v0_4::add_control_to_linkerwraps the generated helper so hosts can wire thecontrolinterface into awasmtime::component::Linker.
The generated modules follow Wasmtime defaults: identifiers with hyphens in WIT are mapped to snake_case in Rust (tenant-ctx → TenantCtx).
Publishing
crates.io
- Run
cargo fmt,cargo test, andcargo check(orcargo publish --dry-run) to make sure the crate builds cleanly. - Update
CHANGELOG.md(if applicable) and bump the version inCargo.toml. - Authenticate with crates.io using
cargo login. - Execute
cargo publishfrom the repository root.
The include section in Cargo.toml restricts the published archive to source code, scripts, README, and license.
wa.dev (WIT packages)
-
Install wasm-tools and the warg CLI. Both are available via
cargo install wasm-tools warg-cli. -
Encode each WIT package into its binary form (required by warg registries). The repository includes
scripts/package-wit.shto automate this:# Produces target/wit-packages/greentic-component-0.3.0.wasm etc. -
Authenticate with wa.dev:
warg login --registry https://registry.wa.dev/v1. -
Initialize the package namespace on the registry (one-time):
-
Release both versions so hosts can negotiate:
-
Tag the release (
git tag v0.4.0 && git push --tags).
As part of CI, run bash scripts/validate-wit.sh to catch schema regressions before publishing. Use wasm-tools component wit --out-dir during review if you need to diff the resolved package graph.
Validation
Run scripts/validate-wit.sh (once wit-bindgen is installed) to lint the interface definitions:
License
MIT