/modules/ · The field

A module is a crate that runs on anyone's Harness.

It implements the Module trait, ships its own migrations, asks for ports by name, and passes the conformance kit. Nothing in it knows which cloud it is on. Two modules ship today; the rest are listed with their status.

Shippingin the repo Designedpublic issues, unbuilt Plannednamed, unspecified

email-signupShipping

Double opt-in email capture with signed confirmation links and CSV export.

Database · Mailer · Captcha · RateLimiter · Signer
waitlistShipping

Per-product waitlists with position, referral-free by design, admin export.

Database · Mailer · RateLimiter · Signer
authDesigned

Passkeys, Google, Apple, Meta, password, magic links, OAuth 2.1 + PKCE, ES256 JWTs with JWKS.

Database · Mailer · Signer · KeyValue · Clock
secretsDesigned

Two-tier secrets with envelope encryption, KMS trait, tamper-evident audit log.

Database · Signer · Clock
conformance-kitShipping

The shared test suite every module must pass; run it in your own crate.

test harness
fzShipping

CLI: scaffold a venture, run migrations, build for wasm32, run the kit.

tool

Writing one

Implement the trait. Pass the kit.

The conformance kit runs every module against the same contract: problem+json errors, rate-limit headers, request-id propagation, concurrent-request safety, migration idempotency. A module that passes on SQLite runs unchanged on D1. Crates are not yet published to crates.io; today you depend on the git repository.

  1. 01Depend on harness-core from the git repository. Crates are not on crates.io yet.
  2. 02Implement Module. name(), requires(), migrations(), router(). Ask for ports by name; never import an adapter.
  3. 03Write migrations in the portable SQL subset. Forward-only, include_str!, numbered. The kit checks idempotency.
  4. 04Run the conformance kit. Concurrent requests, problem+json, rate-limit headers, request-id propagation.
  5. 05Add it to a composition and build for wasm32. If it pulls tokio, mio or std::fs, the build fails. That is the point.

Two mounts Designed

Your module. Your Worker. Your source.

A module can be mounted two ways, and the caller cannot tell which. Compiled in is the default: the crate is linked into the worker alongside every other module. Sidecar is the other: the module is its own worker, compiled on its own, reached over a service binding and mounted at the same /v1/<name> path. Both workers live in the same account, which in the default mode is yours. The platform runs them on the same thread of the same server, so the hop costs no measurable latency and nothing extra to run.

The reason it matters is not performance. A sidecar is built and deployed by whoever owns it, which means a module you will not share can run inside your backend without the source ever reaching us. It binds the same database as everything else, so it is a real module with real ports, not a webhook. It does not get the same secrets: a module we did not build never holds the key that signs the rest of your backend’s links. It is provisioned its own.

This is designed, not built. The decision record and the nine issues that implement it are open in the harness repository.

Want a module that does not exist yet? Tell us what you are running today.