One static binary that replaces Temporal + Kratos + Hydra + Keto.
Workflow engine + full IdP (passkey, OIDC, biscuit, Zanzibar) in
assay-engine. Lua 5.5 runtime with 51 stdlib modules
(Kubernetes, Prometheus, Vault, GitHub, Gmail, OpenClaw…) in
assay. PG18 + SQLite. Linux, macOS, Docker,
Rust crate.
Core Capabilities
Auth & IdP v0.2.0
Full Ory replacement in the same binary as the workflow engine. Passkey (WebAuthn) + Argon2 password login, full OIDC provider (Hydra-equivalent: /authorize, /token, /userinfo, JWKS rotation, RFC 7009 revoke, RFC 7662 introspect, back-channel logout), OIDC client (federate via Google/Apple/GitHub/etc.), biscuit capability tokens (Datalog-attenuable, always-on — Ory has nothing equivalent), Zanzibar ReBAC (Keto/SpiceDB-equivalent, recursive-CTE walk on PG18 + SQLite), session manager (cookie + CSRF), JWT/JWKS rotation, admin HTTP API + dashboard panes for users / sessions / OIDC clients / upstream providers / Zanzibar / keys / audit. Module enable/disable is runtime, not compile-time.
local auth = require("assay.auth")
local c = auth.client({ engine_url = url })
local sess = c:login(email, password)
local me = c:whoami()
local ok = c.zanzibar:check(
"doc", "doc-42", "viewer",
"user", me.id)
Workflow Engine v0.2.0
Native durable workflow engine — full Temporal replacement — with deterministic-replay runtime. Activities (sequential + parallel), signals (with optional timeout), durable timers, child workflows, side effects, live state via ctx:register_query, self-initiated cancel via ctx:cancel, search attributes, namespace-scoped workers + workflows, optional S3 archival, and dashboard whitelabel (ASSAY_WHITELABEL_* env vars to rebrand the embedded /workflow UI per deployment — including brand mark, subtitle, and a "Powered by" attribution when customised). Crash-safe by replay — workers can die mid-flight without losing work or duplicating side effects.
workflow.define("Deploy", function(ctx, in)
local img = ctx:execute_activity("build", in)
ctx:wait_for_signal("approve")
return ctx:execute_activity("deploy", img)
end)
workflow.listen({ queue = "deploys" })
HTTP Server & SSE
Build web services with async route handlers. Handlers can call http.get, sleep, and any async builtin. SSE streaming built in. Header values can be arrays for multiple Set-Cookie, Link, etc.
http.serve(8080, {
GET = {
["/login"] = function(req)
return {
status = 200,
headers = {
["Set-Cookie"] = {
"session=abc; Path=/",
"csrf=xyz; Path=/",
},
},
json = { ok = true },
}
end
}
})
Kubernetes & GitOps
30+ K8s resource types, ArgoCD, Kargo, Flux, Traefik. In-cluster and cross-cluster auth.
local k8s = require("assay.k8s")
local pods = k8s.list("default", "pod")
local argo = require("assay.argocd")
local c = argo.client(url, {token=t})
local apps = c.apps:list()
AI Agent Integration
OpenClaw platform tools, GitHub PRs/issues, Gmail, Google Calendar. Build AI-powered workflows.
local oc = require("assay.openclaw")
local c = oc.client()
c:send("discord", "#ops", "Done!")
local r = c:llm_task("Summarize")
c:state_set("key", {v="1.2"})
Monitoring & Observability
Prometheus, Grafana, Loki, Alertmanager. Query metrics, push logs, manage alerts and dashboards.
local prom = require("assay.prometheus")
local c = prom.client(url)
local r = c.queries:instant("up")
assert.gt(#r, 0, "No targets")
Security & Secrets
Vault, cert-manager, ESO, Dex, Zitadel. JWT signing, OIDC, secret management.
local vault = require("assay.vault")
local c = vault.client(url, {token=t})
local s = c:kv_get("my/secret")
local jwt = crypto.jwt_sign(
{sub="svc"}, key, "HS256")
Infrastructure Testing
Builtin assertions, structured YAML checks with retry and backoff. Verify deployments, health endpoints, and service readiness.
# checks.yaml — retry + backoff
checks:
- name: api-healthy
type: http
url: http://api:8080/health
retries: 5
backoff: 3s
expect:
status: 200
9 MB static binary — FROM scratch, 5 ms cold start, 14x smaller than postman/newman.
See full size & speed comparison →
Two Modes
Auto-detected by file extension:
Lua Scripts (.lua)
#!/usr/bin/assay
local prom = require("assay.prometheus")
local c = prom.client("http://prom:9090")
local result = c.queries:instant("up")
assert.gt(#result, 0, "No targets up")
log.info("Targets up: " .. #result)
YAML Checks (.yaml)
timeout: 120s
retries: 3
backoff: 5s
checks:
- name: grafana-healthy
type: http
url: http://grafana:80/api/health
expect:
status: 200
json: ".database == \"ok\""
Container Image Size
FROM scratch — no shell, no package manager, just the static binary:
| Runtime | Compressed | vs Assay |
|---|---|---|
| Assay | 9 MB | 1x |
| alpine/python | 17 MB | 2x |
| bitnami/kubectl | 35 MB | 4x |
| Node.js alpine | 57 MB | 6x |
| alpine/k8s | 60 MB | 7x |
Install
Pre-built Binaries
# Linux (x86_64, static) — both binaries
curl -L -o assay https://github.com/developerinlondon/assay/releases/latest/download/assay-linux-x86_64
curl -L -o assay-engine https://github.com/developerinlondon/assay/releases/latest/download/assay-engine-linux-x86_64
chmod +x assay assay-engine && sudo mv assay assay-engine /usr/local/bin/
# macOS (Apple Silicon)
curl -L -o assay https://github.com/developerinlondon/assay/releases/latest/download/assay-darwin-aarch64
curl -L -o assay-engine https://github.com/developerinlondon/assay/releases/latest/download/assay-engine-darwin-aarch64
chmod +x assay assay-engine && sudo mv assay assay-engine /usr/local/bin/
Docker
docker pull ghcr.io/developerinlondon/assay:latest # runtime
docker pull ghcr.io/developerinlondon/assay-engine:latest # workflow + auth + dashboard server
Cargo / Rust Library
# Lua runtime CLI (no embedded engine — talks to assay-engine over HTTP)
cargo install assay-lua
# Workflow + auth + dashboard server
cargo install assay-engine
# As a Rust dependency
# Cargo.toml: assay-engine = { version = "0.2", features = ["auth", "backend-postgres", "backend-sqlite"] }
mise
# .mise.toml
"github:developerinlondon/assay" = "v0.12.1"