Skip to content

Releases: sideeffffect/dapr-wasm-components

v0.7.4 — one OCI namespace for all modules

Choose a tag to compare

@sideeffffect sideeffffect released this 15 Oct 07:13

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/interfaces is the name wkg wit fetch resolves (see wkg-config.toml). It now also has the latest tag. wkg ignores non-semver tags, so latest does 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. Update wkg oci pull references 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

Choose a tag to compare

@sideeffffect sideeffffect released this 15 Oct 00:36

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-outbound now sends tonic requests through a small tower::Service over wstd's wasi:http client. It is the same stack as wasi-http-outbound.
  • wasi-grpc, wasi-hyperium and spin-executor are 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 every application/grpc request 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, data and concurrency from 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 AppCallback calls; 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

Choose a tag to compare

@sideeffffect sideeffffect released this 13 Oct 17:36

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.converse no 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 *JobAlpha1 over gRPC.
    • Before this fix, schedule failed and get reported 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.
  • actors.register-timer returns 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 now actors-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 in types.wit, the README and INTERFACES.md.
  • compose.sh exits 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 daprerr tests.
  • Publishing: releases publish the WIT package with wkg publish under the name wkg wit fetch resolves (ghcr.io/sideeffffect/dapr-wasm-components/interfaces). Copy wkg-config.toml to 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.0 only in daprd 1.18.

v0.7.1 — go provider family: Dapr embedded, no sidecar

Choose a tag to compare

@sideeffffect sideeffffect released this 13 Oct 01:25

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 with componentize-go). It contains the Dapr runtime that daprd runs (github.com/dapr/dapr v1.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 from go-outbound and calls the app's *-callback exports. The two components are a pair; the composed app has one Go runtime and one Dapr runtime.
  • compose.sh --out go composes the pair. Run the result with wasmtime 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.rs runs the same real-Dapr scenario as the sidecar suites (two runtimes, Redis pub/sub, Consul name resolution). CI runs it in the new go-e2e job.

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-outbound is 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 HotReload feature 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).

Details: README, wiki, PR #12.

v0.7.0 — authority-split interfaces, subscription resource, typed workflow status

Choose a tag to compare

@sideeffffect sideeffffect released this 12 Oct 17:06
9df43ce

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 use paths. dapr-app re-exports both halves.
  • Configuration subscription is a resource (W2). subscribe returns a subscription handle with id(). Dropping it unsubscribes. The free unsubscribe function and unsubscribe-error are gone.
  • Typed workflow-instance (W3). New fields: workflow-name, runtime-status (enum), input, output, failure. These keys are removed from properties.
  • No workflow-component parameter (W4). Providers always use dapr. workflow-error.component-not-found now 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-read with only get. CI checks this in e2e/tests/authority.rs.
    • Every app also imports state-read and configuration-read with no functions, because the callback exports use their types. These give no authority.
  • runtime-status enum. It has daprd's 8 statuses, including canceled, plus unknown. Matching ignores case. For unknown, the raw string stays in properties["dapr.workflow.runtime_status"].

Fixes and notes

  • If unsubscribe fails when a subscription is dropped, the HTTP provider logs it and does not trap.
  • The gRPC provider still does not support subscribe.
  • The subscription resource and typed workflow get are tested against the mock sidecar only. Real-Dapr coverage is on the ROADMAP.

v0.6.0 — pub/sub routing + bulk, streaming crypto, error model

Choose a tag to compare

@sideeffffect sideeffffect released this 10 Oct 16:02
83561cc

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 error variant.
    • 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 longer option in 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.
  • topic-subscription has new fields. If you build the record literally, add routes: none, bulk-subscribe: none. You can also use the new dapr-app builder: TopicSubscription::new(pubsub, topic).
  • New export pubsub-callback.on-bulk-topic-event. Apps built on the dapr-app SDK 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 in topic-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 at on-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 OnBulkTopicEvent and the older OnBulkTopicEventAlpha1.
  • Streaming crypto with sync WIT resources (no WASI 0.3).
    • Use encryptor / decryptor: write the input in chunks, call finish, then read the output in chunks from crypto-output. The SDK wraps these as std::io types in dapr_app::crypto_io.
    • wasi-http-outbound streams both HTTP bodies. daprd v1.18 still buffers the output and limits the input to --max-body-size (default 4Mi).
    • wasi-grpc-outbound buffers the data in provider memory, and payloads over 4Mi work.

Fixes

  • Secrets. A missing secret now returns secret-not-found on both providers. Before, it trapped against a real daprd, because daprd reports a missing secret as ERR_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 *WorkflowBeta1 RPCs, which are not deprecated.
  • Actor hosting with gRPC outbound. Compose --out grpc --in http and 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

Choose a tag to compare

@sideeffffect sideeffffect released this 13 Jun 22:44

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 world app is unchanged.
    • The dapr- prefix was redundant inside the dapr-wasm-components:interfaces package (it said "dapr" twice) and now matches the bare dapr:outbound / dapr:inbound package aliases already used in compose.wac.
    • If you target a provider world by name in wit_bindgen::generate! or wasmtime::component::bindgen!: rename dapr-outbound → outbound, dapr-inbound → inbound (and the derived struct DaprOutbound → Outbound).
    • Composition via wac / compose.sh is unaffected — it matches interface identifiers, not world names.

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

Choose a tag to compare

@sideeffffect sideeffffect released this 13 Jun 22:44

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 use data — now separate records bulk-state-item / query-state-item.
    • Secrets: get-secret returns option (HTTP 204 → none; the gRPC provider never yields none).
    • State transactions: transaction-request is flattened with value: option (omitted for deletes) instead of reusing the save-shaped state-item.
    • Pub/sub: publish's data-content-type is now option (absent → the sidecar default).
    • Conversation: models the full alpha2 surface (was a text subset); converse returns the faithful outputs → choices structure (was a flattened list).
  • 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 proto Struct.
  • compose.sh: one-liner wrapper around wac compose for 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 to outbound / inbound in v0.4.0).

Full changelog: v0.2.0...v0.3.0

v0.2.0 — two typed directions

Choose a tag to compare

@sideeffffect sideeffffect released this 13 Jun 12:49

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 *-callback interfaces (named after Dapr's AppCallback): service invocation, pub/sub, input bindings, jobs, actor hosting, configuration updates, health. Previously only outbound was typed.
  • App-side SDK dapr-app. Implement the DaprApp trait (every callback defaulted — override only what you use) and export_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 graph outbound → app → inbound acyclic (a single bidirectional provider would form an illegal app ↔ provider instantiation cycle). The two directions are independent, so transports mix (e.g. gRPC out + HTTP in).
  • wasi-grpc-inbound hand-rolls Dapr's AppCallback gRPC server over wasi:http/incoming-handler (verified over Spin h2c with grpcurl).
  • Outbound additions: configuration.subscribe / unsubscribe.
  • compose.wac — a wac compose recipe 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

Choose a tag to compare

@sideeffffect sideeffffect released this 11 Jun 21:56

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 via wac plug and 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.