Repository navigation
Releases: sideeffffect/dapr-wasm-components
Release list
v0.7.4 — one OCI namespace for all modules
Packaging release: all modules now publish under one OCI namespace. The WIT interfaces have not changed since 0.7.1. Only the package version moves to 0.7.4, because the release tag must match it. Apps do not change.
New OCI names
Every module is now ghcr.io/sideeffffect/dapr-wasm-components/<module>:
| Before (last version 0.7.3) | Now |
|---|---|
dapr-wasm-components-interfaces |
dapr-wasm-components/interfaces |
dapr-wasm-components-wasi-http-outbound |
dapr-wasm-components/wasi-http-outbound |
dapr-wasm-components-wasi-http-inbound |
dapr-wasm-components/wasi-http-inbound |
dapr-wasm-components-wasi-grpc-outbound |
dapr-wasm-components/wasi-grpc-outbound |
dapr-wasm-components-wasi-grpc-inbound |
dapr-wasm-components/wasi-grpc-inbound |
dapr-wasm-components-go-outbound |
dapr-wasm-components/go-outbound |
dapr-wasm-components-go-inbound |
dapr-wasm-components/go-inbound |
dapr-wasm-components/interfacesis the namewkg wit fetchresolves (seewkg-config.toml). It now also has thelatesttag. wkg ignores non-semver tags, solatestdoes not change dependency resolution (wkg prints one harmless warning about it).- The flat
dapr-wasm-components-*packages are removed from ghcr. All their versions (0.6.0 – 0.7.3) were copied byte for byte to the new names first, so old versions stay available: e.g.dapr-wasm-components/wasi-http-outbound:0.6.0. Updatewkg oci pullreferences to the new names.
Breaking for consumers of the OCI artifacts only: change the pull references. The WIT, the SDK and the apps do not change.
v0.7.3 — wstd gRPC transport, go family app channel without HTTP
Provider-internals release: a new gRPC transport and a new app channel for the go family. The WIT interfaces have not changed since 0.7.1. Only the package version moves to 0.7.3, because the release tag must match it. Apps do not change.
wasi-gRPC: wstd transport, tonic 0.14 (#14)
wasi-grpc-outboundnow sends tonic requests through a smalltower::Serviceoverwstd'swasi:httpclient. It is the same stack aswasi-http-outbound.wasi-grpc,wasi-hyperiumandspin-executorare removed. The artifact has no Spin crate dependency.- HTTP/2 is still the host's job. Spin ≥ 3.4 still needs
SPIN_OUTBOUND_H2C_PRIOR_KNOWLEDGE. wasmCloud v2 sends everyapplication/grpcrequest over HTTP/2, so it can now run the provider too (no E2E yet). - tonic/prost 0.13 → 0.14 for both gRPC providers. The checked-in codegen is regenerated.
go family: the runtime reaches the app with Go calls (#15)
- The embedded Dapr runtime no longer talks to the app over HTTP on an in-memory pipe. It runs in gRPC app-protocol mode with two in-process objects: an
AppCallback"connection" for pub/sub, bulk pub/sub, input bindings and subscription lists, and an app channel for invocation, jobs, actors and health. - No HTTP encoding, JSON or CloudEvent re-encoding on delivery. The 700-line HTTP router is gone.
- Input-binding replies now work in the go family: Dapr applies
to,dataandconcurrencyfrom the reply. - No Dapr patch: the objects are wired in after
runtime.FromConfig, with startup checks against the pinned Dapr version. - Caveats: at most 100 concurrent
AppCallbackcalls; Dapr's app HTTP middleware and app API token no longer apply.
Docs and repo
- README: wasmCloud v2 as a possible gRPC host; actor hosting and input-binding replies in the go family; three real-Dapr E2Es.
- Wiki: who-is-who of wasi-grpc, wstd, Spin and wasmCloud; gRPC in both directions per host.
- Generated code is marked
linguist-generated, and generated Go has the standard generated-code header.
v0.7.2 — outbound provider fixes for daprd 1.17/1.18
Bug-fix release for the outbound providers, found by dapr4s's import probe against daprd 1.17.7 and 1.18.7. The WIT interfaces have not changed since 0.7.1. Only the package version moves to 0.7.2, because the release tag must match it.
Fixes
conversation.converseno longer traps when the answer reports usage (wasi-http). daprd writes 64-bit integers as JSON strings, for example"totalTokens":"4". Token counts and the choice index now accept either a string or a number. The gRPC and go providers read protobuf, so they were never affected.- Jobs work on daprd 1.17 (wasi-http and wasi-gRPC).
- Up to 1.17, daprd serves jobs only at
/v1.0-alpha1/jobs/{name}over HTTP and as*JobAlpha1over gRPC. - Before this fix,
schedulefailed andgetreported a 404 as "job not found". - Both providers now use the alpha1 API, which also works on 1.18, where it is a deprecated alias.
- Up to 1.17, daprd serves jobs only at
actors.register-timerreturns a typed error instead of trapping (all three providers). When the actor type is not hosted, daprd answers with a generic 500 (ERR_ACTOR_TIMER_CREATE … actor type not registered). This is nowactors-error.permission-denied, the same answer daprd gives (403) for reminders. Any other timer failure still traps.- Error payloads (wasi-http): the string in a setup error case (
store-not-found,permission-denied, …) is now daprd's message, as on the gRPC provider. Before, it was"HTTP 400: {raw JSON}". The rule is documented intypes.wit, the README andINTERFACES.md. compose.shexits 0 on success and no longer leaks temp directories.
Build and CI
- New unit tests in CI: the wasi-gRPC provider tests (run under wasmtime) and the go
daprerrtests. - Publishing: releases publish the WIT package with
wkg publishunder the namewkg wit fetchresolves (ghcr.io/sideeffffect/dapr-wasm-components/interfaces). Copywkg-config.tomlto consume it.
Docs
- README limitation notes on the jobs alpha1 API and on how the timer error maps.
- Corrected the jobs version map in the wiki: jobs moved to
/v1.0only in daprd 1.18.
v0.7.1 — go provider family: Dapr embedded, no sidecar
A third provider family: Dapr itself, embedded in the component. No sidecar, and no HTTP or gRPC between the app and Dapr. The dapr-wasm-components:interfaces WIT package does not change since v0.7.0; the version moves to 0.7.1 only to tag this release. Apps need no change.
New
dapr-wasm-components-go-outbound(Go, built withcomponentize-go). It contains the Dapr runtime that daprd runs (github.com/dapr/daprv1.18.7). Every building block is a direct call into that runtime. Configure it with daprd's own flags as the program arguments.dapr-wasm-components-go-inbound(Rust, 117 KB). A small loop (wasi:cli/run) that takes Dapr's deliveries fromgo-outboundand calls the app's*-callbackexports. The two components are a pair; the composed app has one Go runtime and one Dapr runtime.compose.sh --out gocomposes the pair. Run the result withwasmtime run -S inherit-network -S tcp -S allow-ip-name-lookup ... composed.wasm --app-id my-app --resources-path /resources.- Values are raw bytes, so binary state roundtrips byte-exact.
e2e/tests/go.rsruns the same real-Dapr scenario as the sidecar suites (two runtimes, Redis pub/sub, Consul name resolution). CI runs it in the newgo-e2ejob.
Limits
- Self-invocation does not work. The app is one long-running instance, so it cannot receive a call while it handles another. Invoking its own app id fails at once with
app-unreachable. A call cycle A → B → A hangs unless you set a Dapr resiliency timeout. - Size:
go-outboundis about 264 MB (the Dapr runtime plus component SDKs). The first wasmtime compile takes about 30 s. - Name resolution: mDNS cannot work in Wasm (no UDP multicast). Use Consul (or another resolver) and set
DAPR_HOST_IP. - Dapr's
HotReloadfeature is off: WASI cannot watch files. - Not every Dapr component is included: sqlite, Pulsar, Dubbo and some Azure components do not build for Wasm.
- Actors, workflow and jobs are implemented but not yet covered by the real-Dapr test (it does not start placement and scheduler).
v0.7.0 — authority-split interfaces, subscription resource, typed workflow status
Interfaces split by authority, configuration subscriptions as a resource, and typed workflow status. This release has breaking changes to the dapr-wasm-components:interfaces WIT package since v0.6.0. Motivation: dapr4s Wasm components proposal.
Breaking
- Read interfaces split out (W1). Five interfaces now have a read-only twin that owns the shared types:
state-read:get,get-bulk,query.state:save,delete,execute-transaction.secrets-read:get-secret.secrets:get-bulk-secret.configuration-read:get.configuration:subscribe.jobs-read:get.jobs:schedule,delete.workflow-read:get.workflow:start,terminate,raise-event,pause,resume,purge.- Update imports and
usepaths.dapr-appre-exports both halves.
- Configuration subscription is a resource (W2).
subscribereturns asubscriptionhandle withid(). Dropping it unsubscribes. The freeunsubscribefunction andunsubscribe-errorare gone. - Typed
workflow-instance(W3). New fields:workflow-name,runtime-status(enum),input,output,failure. These keys are removed fromproperties. - No
workflow-componentparameter (W4). Providers always usedapr.workflow-error.component-not-foundnow means "workflow engine not available".
New
- The import list is the authority list. A component imports only the interfaces and functions it calls. An app that only reads state imports
state-readwith onlyget. CI checks this ine2e/tests/authority.rs.- Every app also imports
state-readandconfiguration-readwith no functions, because the callback exports use their types. These give no authority.
- Every app also imports
runtime-statusenum. It has daprd's 8 statuses, includingcanceled, plusunknown. Matching ignores case. Forunknown, the raw string stays inproperties["dapr.workflow.runtime_status"].
Fixes and notes
- If unsubscribe fails when a
subscriptionis dropped, the HTTP provider logs it and does not trap. - The gRPC provider still does not support
subscribe. - The subscription resource and typed workflow
getare tested against the mock sidecar only. Real-Dapr coverage is on the ROADMAP.
v0.6.0 — pub/sub routing + bulk, streaming crypto, error model
Pub/sub routing and bulk subscribe, streaming crypto, and the error-model redesign. This release has breaking changes to the dapr-wasm-components:interfaces WIT package since v0.4.0. It includes the 0.5.0 changes, which had no GitHub release of their own.
Breaking
- Error model redesign (0.5.0). There is no longer one shared 7-case
errorvariant.- Each interface now has its own
variants for errors you can recover from, sometimes per function. Example:state.save→write-error { etag-mismatch, … }. - A missing value is now an error case such as
key-not-found. It is no longeroptionin the success type. - Infrastructure failures, such as the sidecar being down, a 5xx or a timeout, now trap instead of being typed.
- Inbound callbacks use
types.app-error.
- Each interface now has its own
topic-subscriptionhas new fields. If you build the record literally, addroutes: none, bulk-subscribe: none. You can also use the newdapr-appbuilder:TopicSubscription::new(pubsub, topic).- New export
pubsub-callback.on-bulk-topic-event. Apps built on thedapr-appSDK get a default implementation. Apps that implement the WIT directly must add it.
New
- Pub/sub CEL routing rules.
topic-subscription.routes { rules: [{match, path}], default }. daprd evaluates the rules, and the matched route arrives intopic-event.path. SDK:.with_rule(cel, path).with_default_route(path). - Pub/sub bulk subscribe.
- Turn it on with
.with_bulk_subscribe(max_count, max_await_ms). Batches arrive aton-bulk-topic-event, with a status for each entry (SUCCESS / RETRY / DROP). - The SDK default passes each entry to
on_topic_event. - You can use it together with routing rules.
- gRPC inbound serves
OnBulkTopicEventand the olderOnBulkTopicEventAlpha1.
- Turn it on with
- Streaming crypto with sync WIT resources (no WASI 0.3).
- Use
encryptor/decryptor:writethe input in chunks, callfinish, then read the output in chunks fromcrypto-output. The SDK wraps these asstd::iotypes indapr_app::crypto_io. wasi-http-outboundstreams both HTTP bodies. daprd v1.18 still buffers the output and limits the input to--max-body-size(default 4Mi).wasi-grpc-outboundbuffers the data in provider memory, and payloads over 4Mi work.
- Use
Fixes
- Secrets. A missing secret now returns
secret-not-foundon both providers. Before, it trapped against a real daprd, because daprd reports a missing secret asERR_SECRET_GET. - Crypto. "Component not found" now maps to
component-not-found.
Findings (documented, no API change)
- Input-binding reply. daprd ignores the input-binding reply. On the HTTP app channel it ignores the reply completely. On the gRPC channel it uses only
to/data/concurrency. The E2E records this behaviour, so we will notice if daprd changes it. - Workflow. Only the HTTP workflow API is deprecated. The gRPC provider uses the
*WorkflowBeta1RPCs, which are not deprecated. - Actor hosting with gRPC outbound. Compose
--out grpc --in httpand run daprd with--app-protocol http.
Tooling
- wasmtime 49, wit-bindgen 0.62, wac-graph 0.12
- CI runs Spin v4.2.2, wkg 0.16.1 and daprd 1.18.7
Full changelog: v0.4.0...v0.6.0
v0.4.0 — Bare provider world names
Bare provider world names. One breaking change to the dapr-wasm-components:interfaces WIT package since v0.3.0.
Breaking
- Provider WIT worlds renamed:
dapr-outbound→outbound,dapr-inbound→inbound. The application worldappis unchanged.- The
dapr-prefix was redundant inside thedapr-wasm-components:interfacespackage (it said "dapr" twice) and now matches the baredapr:outbound/dapr:inboundpackage aliases already used incompose.wac. - If you target a provider world by name in
wit_bindgen::generate!orwasmtime::component::bindgen!: renamedapr-outbound→outbound,dapr-inbound→inbound(and the derived structDaprOutbound→Outbound). - Composition via
wac/compose.shis unaffected — it matches interface identifiers, not world names.
- The
No interface (building-block / callback) shapes changed in this release — it is purely the world rename.
Full changelog: v0.3.0...v0.4.0
v0.3.0 — HTTP-API-faithful interfaces
HTTP-API-faithful interfaces. Breaking changes to the dapr-wasm-components:interfaces WIT package since v0.2.0.
Breaking
- API-faithfulness pass — WIT shapes now mirror the Dapr HTTP API exactly, even where the gRPC proto differs (each outbound provider maps its own transport):
- State: bulk-get items use
value; query results usedata— now separate recordsbulk-state-item/query-state-item. - Secrets:
get-secretreturnsoption(HTTP204→none; the gRPC provider never yieldsnone). - State transactions:
transaction-requestis flattened withvalue: option(omitted for deletes) instead of reusing the save-shapedstate-item. - Pub/sub:
publish'sdata-content-typeis nowoption(absent → the sidecar default). - Conversation: models the full alpha2 surface (was a text subset);
conversereturns the faithfuloutputs → choicesstructure (was a flattened list).
- State: bulk-get items use
- OCI artifact renamed: the interface package is published as
dapr-wasm-components-interfaces(was…-interface). Update your pull references.
Added / improved
- Inbound: Dapr configuration-update pushes are delivered to
on-configuration-event. wasi-grpc-inbound: CloudEvent extensions are mapped from the protoStruct.compose.sh: one-liner wrapper aroundwac composefor composing app + outbound + inbound providers.
Verified against docs.dapr.io v1.18 and cross-checked against the vendored gRPC protos; mirrored across both outbound providers and the e2e mock/tests.
Provider worlds in 0.3.0 are still
dapr-outbound/dapr-inbound(renamed tooutbound/inboundin v0.4.0).
Full changelog: v0.2.0...v0.3.0
v0.2.0 — two typed directions
A Dapr application is now pure typed domain logic — it never touches HTTP or gRPC in either direction. The provider components translate the wire on both sides.
Highlights
- Typed inbound (Dapr → app). Seven
*-callbackinterfaces (named after Dapr'sAppCallback): service invocation, pub/sub, input bindings, jobs, actor hosting, configuration updates, health. Previously only outbound was typed. - App-side SDK
dapr-app. Implement theDaprApptrait (every callback defaulted — override only what you use) andexport_app!; call Dapr through re-exported typed interfaces. - Providers split per direction × transport (4 components).
wasi-http-outbound/wasi-http-inbound/wasi-grpc-outbound/wasi-grpc-inbound. Splitting outbound from inbound keeps the composition graphoutbound → app → inboundacyclic (a single bidirectional provider would form an illegalapp ↔ providerinstantiation cycle). The two directions are independent, so transports mix (e.g. gRPC out + HTTP in). wasi-grpc-inboundhand-rolls Dapr'sAppCallbackgRPC server overwasi:http/incoming-handler(verified over Spin h2c withgrpcurl).- Outbound additions:
configuration.subscribe/unsubscribe. compose.wac— awac composerecipe for the acyclic three-component graph.
Published modules (ghcr.io/sideeffffect)
dapr-wasm-components-interface, -wasi-http-outbound, -wasi-http-inbound, -wasi-grpc-outbound, -wasi-grpc-inbound — tag 0.2.0.
Notes
Follow-ups (incl. an automated daprd --app-protocol grpc E2E) are tracked in ROADMAP.md. Breaking vs 0.1.0: the WIT worlds are now app / dapr-outbound / dapr-inbound (the dapr-client / dapr-server worlds were removed).
v0.1.0
First release of the pure-wasm Dapr component modules:
- dapr-wasm-components-interface — WIT package
dapr-wasm-components:interfaces@0.1.0: synchronous interfaces for all Dapr building blocks (state incl. transactions/query, pub/sub incl. bulk publish, bindings, secrets, configuration, service invocation, distributed lock, workflow, jobs, cryptography, conversation, actors, runtime metadata/health). - dapr-wasm-components-wasi-http — pure-wasm implementation over
wasi:http, talking to the Dapr sidecar's HTTP API. Compose with your app viawac plugand run on any WASI 0.2 runtime.
OCI artifacts: ghcr.io/sideeffffect/dapr-wasm-components-interface:0.1.0 and ghcr.io/sideeffffect/dapr-wasm-components-wasi-http:0.1.0.