@drm3/sdk
v0.4.2
Published
The DRM3 network SDK. One package to integrate an app or agent with DRM3: identity (offline SSO verify), the user's credit balance, a cross-app switcher, cross-app alerts, an in-browser receipt viewer, partner key management (the key lives with the partne
Maintainers
Readme
What it is
The one package to put an app or an agent on the DRM3 network. Add an account, a credit balance, x402 payments, partner keys, and provenance receipts to the code you already have, then ship.
@drm3/sdk is a thin, typed client. Identity checks, x402 payments, and receipt chains verify
locally with Web Crypto; everything else is a plain HTTPS call to a DRM3 surface. There is no
service to host, no daemon, and no sidecar. It ships compiled and typed, and it carries the drm3
CLI for key operations in a terminal. Import a subpath into your code, or run npx drm3. That is the
whole SDK.
Install
npm install @drm3/sdk # or: pnpm add @drm3/sdk · yarn add @drm3/sdk · bun add @drm3/sdkTypeScript types are bundled, and the drm3 CLI installs alongside the library.
What you need
- The library: a JS runtime with
fetchand Web Crypto (crypto.subtle, Ed25519). Every current runtime has both: browsers, Node 20+, Deno, Bun, and edge or serverless runtimes including Cloudflare Workers, Vercel Edge, and Fly or Docker containers. - The
drm3CLI: Node 20 or newer. - One runtime dependency:
@noble/curvesand@noble/hashes(audited, zero-dependency crypto). Nothing else.
Install works the same on Windows, macOS, and Linux: it is a normal npm package, so if npm
runs, it installs. Module format is ESM with subpath exports and sideEffects: false, so a bundler
ships only the code you import.
What is in it
Each capability has its own subpath. A server never pulls the browser UI; a browser never pulls the Postgres driver.
| Import | What it does | Runs in |
|--------|--------------|---------|
| @drm3/sdk | Sign-in URLs, the live app catalog, the user's credit balance, Data Passport writes | server or browser |
| @drm3/sdk/sso | Verify the DRM3 identity token locally, per-app launch tokens, a revocation gate | server |
| @drm3/sdk/x402 | The x402 "exact" payment gateway: verify a signed payment, build the 402 offer | server |
| @drm3/sdk/meter | LedgerMeterClient: charge any kind of usage to the DRM3 ledger with your service key. Plus the ledger engine itself (authorize / capture / void / settle, a multi-bucket wallet) for a ledger you run | server |
| @drm3/sdk/extract | Read lakehouse data through the signed Data Extract API, no service account: pull verified keyset pages, materialize-first | server or agent |
| @drm3/sdk/ingest | Write raw rows through the signed Ingest door, no service account: idempotent on your insertId, returns a verified batch receipt | server or agent |
| @drm3/sdk/keys | Partner signing keys: generate, build a CSR, verify a receipt chain to the DRM3 Root, bring-your-own seed helpers | server or browser |
| @drm3/sdk/keys/home | The partner's home (~/.drm3/<tenant>/): read the key the CLI wrote, from your own service | server (Node) |
| @drm3/sdk/switcher | The cross-app switcher tile grid, one call | browser |
| @drm3/sdk/alerts | The cross-app alerts bell, one call | browser |
| @drm3/sdk/receipts | The in-browser provenance receipt viewer and a verify button | browser |
| drm3 (CLI) | init a home, generate or import keys, submit a CSR, poll for the certificate, register a SKU, verify receipts | terminal (Node 20+) |
Prebuilt browser bundles ship at @drm3/sdk/receipts/global and @drm3/sdk/alerts/global for a plain
<script> tag, no bundler required.
The CLI
The drm3 CLI is the terminal half of the SDK: the same signing discipline, for a human or an agent
at a prompt. Zero install with npx drm3. It makes an Ed25519 keypair locally (the private key never
leaves your machine), builds and submits a CSR, saves the certificate when DRM3 issues it, registers
a SKU signed with the same key, verifies a receipt chain to the DRM3 Root, and reads live fleet and
registry status.
The key lives with you. drm3 init <tenant> makes ~/.drm3/<tenant>/ and every later command
defaults to it: signing-key.json (mode 0600, the only place the private half is ever written),
config.json (your subject, the CA, the doors), csr.json, cert.json. DRM3_HOME replaces
~/.drm3; --tenant NAME or DRM3_TENANT picks the tenant. Bring your own key from openssl or an
HSM with drm3 keys import. The format and the fields are in docs/keys.md.
npx drm3 init my-app # ~/.drm3/my-app/config.json; my-app is your CA subject
npx drm3 keys generate # -> ~/.drm3/my-app/signing-key.json, mode 0600
npx drm3 keys submit # the CSR: your PUBLIC key, self-signed. Nothing else leaves.
npx drm3 keys status --wait # polls; saves cert.json and prints the Root fingerprint
npx drm3 registry submit --file sku.json # register your app, signed with the same key
npx drm3 keys verify receipt.json
npx drm3 statusThe flag form still works everywhere: drm3 keys generate --out FILE, drm3 keys submit --subject
NAME --key FILE, drm3 partner status --subject NAME.
The DRM3 surfaces it talks to
Four surfaces. Most of the SDK runs locally; the network calls are few and cacheable.
| Surface | Host | Used for |
|---------|------|----------|
| Account hub | drm3.network | sign in/out, credit balance, alerts, Passport writes, the revocation feed |
| Registry + CA | status.drm3.network | the app catalog, the public key registry, CSR submit and certificate issuance |
| The ledger | ledger.drm3.network | the meter: every kind of usage is charged here with your service key |
| Metered inference | queue.drm3.network | the shared inference queue (it charges the ledger too) |
| Base chain | USDC on Base | where an x402 payment settles, out of band. The SDK never touches it. |
Architecture
The app or agent is the center. It verifies identity, payments, and receipts locally, and makes a handful of cacheable calls to the DRM3 surfaces. It never holds a wallet key and never settles money.
The interactions
Every flow, its exact endpoint, and what stays local. Each diagram reads top to bottom.
Sign in
The user authenticates once at the hub and comes back with a drm3_sso token. Your app verifies that
token locally on every request after that, with no further call to the hub.
import { createRevocationGate, verifyActiveSsoToken } from "@drm3/sdk/sso";
const gate = createRevocationGate({ url: "https://drm3.network/api/sso/revocations" });
const claims = await verifyActiveSsoToken(process.env.DRM3_SSO_SECRET!, token, gate);
if (!claims) return new Response("unauthorized", { status: 401 }); // signature, expiry, revocation, all localSign out
One redirect clears the shared session across every DRM3 app, not just yours.
Generate a signing key
Fully local. The private key is created on your machine and never leaves it. DRM3 is not contacted.
npx drm3 init my-app
npx drm3 keys generate # -> ~/.drm3/my-app/signing-key.json (0600); --out FILE to put it elsewhereAlready have a key? drm3 keys import --pem key.pem (openssl PKCS8), --seed FILE (the raw 32-byte
seed), or --public FILE when the private half stays in your HSM and you sign the CSR yourself.
Get your key certified
You send a self-signed CSR carrying only your public key. A DRM3 operator approves it and the Root signs an attestation. DRM3 never sees your private key.
npx drm3 keys submit # flag-less once the home exists
npx drm3 keys status --wait # polls GET /v1/ca/cert/my-app; saves ~/.drm3/my-app/cert.json on approvalkeys status verifies the attestation's signature and checks its issuer against the Root the public
registry publishes before it saves anything, then prints that Root fingerprint. The same key then
signs your SKU registration: drm3 registry submit --file sku.json (registry status to follow it).
Verify a key or a receipt chain
Anyone can do this. Fetch the public key registry once, then verify the Ed25519 chain locally: a receipt links to its issuer attestation, which links to the DRM3 Root.
npx drm3 keys verify receipt.jsonRead the credit balance
A single call to the hub with the user's identity token.
Meter usage
Two halves. Charging the DRM3 ledger is what an app or service on the network does: one client,
your own service key as the Bearer, any kind of usage (tokens, actions, rows, bytes,
queries, jobs), idempotent on idem_key, the ledger prices it. A delegating app names the user
it bills with on_behalf_of.
import { LedgerMeterClient } from "@drm3/sdk/meter";
const meter = new LedgerMeterClient({ bearer: process.env.DRM3_SERVICE_KEY! });
const who = await meter.resolve(consumerKey); // sends the key's SHA-256, never the key
if (!who.active) return new Response("unauthenticated", { status: 401 });
const r = await meter.charge({ kind: "actions", action: "myapp_export", count: 1, idem_key: jobId, on_behalf_of: who.tenant! });
// r.charged, r.available, r.replay (a retry debits once); r.priced is false for a kind the ledger does not price yetRunning a ledger of your own is the engine underneath (SQLite / D1 or Postgres). authorize
reserves credits and cannot overdraft; capture settles the real cost and releases the rest.
import { CreditsClient, InMemoryAdapter } from "@drm3/sdk/meter";
const credits = new CreditsClient({ adapter: new InMemoryAdapter() }); // or a D1 / Postgres adapter
const auth = await credits.authorize({ tenant: claims.sub, maxCredits: 100n });
if (!auth.ok) return new Response("payment required", { status: 402 });
await credits.capture(auth.reservation.id, { credits: 84n });Alerts
Read the user's cross-app alerts and mark them read. The same bell mounts in any DRM3 app.
Data access (Passport)
The user grants your app a Passport token at the hub's consent screen. Your app then writes into its own namespace under the user's record. The hub re-checks the token audience on every write.
x402 payment
Your app answers 402 with an offer. The agent signs an EIP-3009 authorization to payTo and retries.
verifyX402Payment checks the signature locally: it holds no key and broadcasts nothing. Settlement
is out of band - the signed authorization is submitted on-chain by the caller or a facilitator, which
moves USDC directly to payTo. The SDK does not settle and never custodies funds.
import { verifyX402Payment, x402Body } from "@drm3/sdk/x402";
const cfg = { payTo: process.env.X402_PAY_TO!, priceAtomic: 10_000n }; // 0.01 USDC on Base
const header = req.headers.get("x-payment");
if (!header) return Response.json(x402Body(cfg, { resource: "/answer", description: "One answer" }), { status: 402 });
const result = verifyX402Payment(header, cfg); // pure, holds no key
if (!result.ok) return new Response(result.error, { status: 402 });
// result.payer is recovered from the signature. Run your nonce-replay gate, then serve.Offers
x402Body builds the 402 menu. accepts is the machine-payable x402 requirement; offers and
hint are additive extras for humans and apps, and x402 clients ignore them.
Browser drop-ins
Three one-call widgets. Mount them into an element and they render, fetch, and stay in sync.
import { mountAppSwitcher } from "@drm3/sdk/switcher";
import { mountAlertsBell } from "@drm3/sdk/alerts";
import { mountVerifyButton } from "@drm3/sdk/receipts";
mountAppSwitcher(document.getElementById("switcher"));
mountAlertsBell(document.getElementById("bell"));
mountVerifyButton(document.getElementById("verify"), { receiptId });For agents and LLMs
An agent puts itself on the network the same way an app does: npm install @drm3/sdk, then import the
one subpath it needs. For keys, run npx drm3 keys generate --out signing.key (the private key stays
local) and verify receipt chains with npx drm3 keys verify. To pay an x402-gated endpoint, sign an
EIP-3009 authorization to the offer's payTo and retry with the X-PAYMENT header.
A machine-readable summary of the package, its subpaths, the CLI, and the DRM3 surfaces lives in
llms.txt.
Feedback and submissions
We do not accept pull requests or code contributions: the SDK is source-managed by DRM3 Labs Corp. so every app and agent on the network shares one signed, tested surface. We do want your ideas, feature requests, and bug reports. Open a GitHub issue on this repository, or email [email protected]. See CONTRIBUTING.md.
License
Free to use, including in commercial products. Use @drm3/sdk and the drm3 CLI to build and
ship your own apps and agents on the DRM3 network. No fee, no signup, no agreement to sign, and the
grant is not revoked as long as you play by the rules.
It is not open source: the SDK is DRM3 Labs Corp. property, so you cannot repackage or resell the SDK on its own, reverse-engineer it, or use it to build a competing network. Build anything you want on DRM3 with it; just do not clone or resell the SDK itself. Full terms in LICENSE. Questions: [email protected].
