Provider SDK
A provider is a wasm32-wasip2 component that teaches omnifs how one system appears as paths. The host owns FUSE, credentials, cache, and callouts. Your provider owns routes, object identity, and rendering.
Provider shape
Section titled “Provider shape”A provider has:
- a config type,
- a state type,
- a
#[omnifs_sdk::provider]impl, - route registrations in
start, - handlers for files, directories, tree refs, or object leaves,
- an
omnifs.provider.jsonmanifest.
Workspace providers use one top-level provider impl:
use omnifs_sdk::prelude::*;
struct DbProvider;
#[omnifs_sdk::provider(metadata = "omnifs.provider.json")]impl DbProvider { type Config = Config; type State = State;
fn start(config: Config, r: &mut Router<State>) -> Result<State> { let state = State::open(config)?;
r.dir("/tables").handler(tables_list)?; r.file("/tables/{table}/schema.sql").handler(table_schema_sql)?;
Ok(state) }}There is no #[dir] or #[file] route attribute. Routes are registered imperatively.
Config
Section titled “Config”Use #[omnifs_sdk::config] for the Rust config type. The macro wires deserialization for provider startup. The public schema is still authored in omnifs.provider.json.
#[omnifs_sdk::config]struct Config { path: String, sample_limit: Option<u32>,}Do not rely on Rust config structs to generate the manifest schema. Keep the manifest explicit.
Routes
Section titled “Routes”Use the router methods that exist in the current SDK:
| Method | Use |
|---|---|
r.dir(path).handler(handler) | directory listing and lookup behavior |
r.file(path).handler(handler) | file bytes |
r.treeref(path).handler(handler) | hand off a real backing tree, such as a cloned repo |
| `r.object:: | o |
| `r.file_object:: | o |
r.attach(path, &subtree) | attach a detached object subtree |
Variable segments use {name} captures. Capture field types parse with FromStr; malformed captures remove that route from candidacy.
Objects
Section titled “Objects”Object-shaped providers declare canonical resources once and render leaves from them. A fresh load can store canonical upstream bytes and materialized view leaves. A warm read can render from host-pushed canonical bytes.
The route block is only half of an object route:
r.object::<TableDoc>("/tables/{table}", |o| { o.representations("table", ())?; o.file("schema.sql").handler(table_schema_sql)?; o.file("schema.json").handler(table_schema_json)?; o.file("count.txt").handler(table_count_txt)?; o.file("sample.json").handler(table_sample)?; Ok(())})?;The object type still needs an object declaration, a typed key, and a Key::load implementation. That load function is where the provider returns Fresh, Unchanged, or NotFound and supplies canonical bytes for the object cache.
Use object routes when several files describe the same upstream resource. Use plain file routes for independent leaves.
Macro resources and manifest
Section titled “Macro resources and manifest”The provider macro can declare compile-time resources used by typed endpoints and git handoffs:
#[omnifs_sdk::provider( metadata = "omnifs.provider.json", resources(endpoints = [api::GitHubApi], git = true))]impl GitHubProvider { /* ... */}The manifest declares package metadata, default mount name, capabilities, auth, and config schema.
{ "id": "example", "displayName": "Example", "provider": "omnifs_provider_example.wasm", "defaultMount": "example", "capabilities": [ { "kind": "domain", "value": "api.example.com", "why": "Fetch Example API resources." }, { "kind": "memoryMb", "value": 64, "why": "Declare the provider's expected memory need." } ]}Add auth only when the provider needs credentials. Add a preopened path only when the provider needs a local file capability.
Validation loop
Section titled “Validation loop”During SDK work, validate the provider as code and as a filesystem surface:
just providers-checkcargo check -p omnifs-provider-db --target wasm32-wasip2cargo test -p omnifs-provider-db --target wasm32-wasip2 --no-runomnifs dev -yomnifs shellInside the shell, test with ls, cat, jq, find, and grep. A provider is not done when the handler compiles. It is done when normal tools can traverse the path surface without special knowledge.