@elacity-js/ddrm-reader-backend
v0.2.4
Published
Express-like backend: wallet handshake, ECDH WebSocket channel, CEK recovery, ddrm-decrypt.wasm, render-layer. Plaintext/CEK never leave here.
Readme
@elacity-js/ddrm-reader-backend
The dDRM reader backend — wallet handshake, ECDH WebSocket channel, CEK recovery (Lit Action), ddrm-decrypt.wasm, and the render layer. It can run as a standalone service or be embedded as a library in your own Node app.
Prime directive: the encrypted file bytes and the recovered Content Encryption Key never leave this process. The client only ever receives a decoded render-IR over the ECDH-encrypted channel; plaintext and CEK are zeroized after use, on every path.
Workflow role
client: gen session key → wallet signs challenge ──▶ verify sig, ECDH channel
Lit Action → CEK [on-chain gate]
fetch encrypted bytes (IPFS)
ddrm-decrypt.wasm: CEK+bytes → plaintext
DecoderRegistry: plaintext → render-IR
client: render IR ◀── stream IR frames (encrypted) ── zeroize plaintext + CEKThe server core imports no decoder — content types are injected through a DecoderRegistry. This package's main.ts is the composition root (the only file naming concrete decoders); the published library exposes the building blocks so you can assemble your own.
Install
pnpm add @elacity-js/ddrm-reader-backendRequires Node ≥ 20, ESM.
Embed as a library
import {
createServer,
DecoderRegistry,
imageDecoder,
createTextDecoder,
} from "@elacity-js/ddrm-reader-backend";
const server = await createServer({
port: 8787,
wasm: {
wasmUrl: process.env.DDRM_WASM_URL!, // pinned GitHub release URL / file:// / path
sha256: process.env.DDRM_WASM_SHA256!, // verified before instantiation
},
decoders: new DecoderRegistry([imageDecoder, createTextDecoder()]),
chainId: 8453,
gateways: ["https://ipfs.ela.city/ipfs/"],
lit: {
proxyUrl: "https://europe-west1-elacity.cloudfunctions.net/chipotle-proxy",
decryptCid: "Qm…",
pkpId: "0x…",
authority: "0x…",
chain: "base",
chainId: 8453,
rpc: "https://mainnet.base.org",
},
});
// GET /health + WS /channelAlso exported: decryptAndRender (the pipeline), createSessionManager, and loadDdrmRuntime (the wasm loader) for finer-grained composition.
Run as a service
The package's composition root registers every decoder and reads config from env (and two CLI overrides):
# env-driven
DDRM_WASM_URL=… DDRM_WASM_SHA256=… node dist/main.js
# CLI flags take precedence over the env vars
node dist/main.js --ddrm:wasm-url <url> --ddrm:wasm-hash256 <sha256>See .env.example for the full config surface (PORT, IPFS_GATEWAYS, the LIT_* Lit Action settings, optional self-hosted DDRM_KROKI_URL).
Docker
A multi-stage Dockerfile and a repo-root docker-compose.yml are provided:
docker compose up --build