Licensing Overview
Quick summary
Two licensing paths exist: a legacy key lookup and a PoP security plane with device proof and short-lived entitlements. They are not interchangeable.
Choose your backend first: Worker security-plane routes require an explicit feature flag; Axum supports the legacy subset.
Two license planes coexist — know which one you are on:
| Plane | Where | Model |
|---|---|---|
| Legacy records | both backends (be/, be-cloudflare) | lic_… rows + NG-… keys, activations_json device records, public /licenses/verify lookup — no PoP, no entitlement |
| Security plane (PoP) | be-cloudflare only, behind LICENSE_SECURITY_ENABLED (else the routes 404, including preflight) | entitlement JWS + DPoP-style proof + license_bindings + one-time capabilities |
The Axum backend has no PoP entitlement plane — it neither issues nor verifies these claims. The @yetdapay/license-* SDKs can also run a fully self-hosted (BYOS) enforcement server with the same wire format.
Lifecycle
purchase / seller issue POST /licenses (seller) or checkout batch
│ → lic_… row + NG-… key
▼
activation POST /licenses/activate {key, product_id, public_jwk}
│ → device slot bound to jkt → {entitlement, expires_in:120, features}
▼
entitlement use Authorization: Entitlement <jws> + DPoP: <proof>
│ → GET /licenses/status, POST /licenses/capability
▼
capability + execute POST /licenses/capability {feature} → {cap_id}
POST /licenses/execute {feature,input,cap_id}
│ → atomic consume; reuse → 409 CAPABILITY_CONSUMED
▼
revocation / expiry PATCH /licenses/:id status
→ live row re-queried on every guarded call2
3
4
5
6
7
8
9
10
11
12
13
14
15
Key identifiers & wire elements
jkt—sha256(sha256(RFC 7638 JWK thumbprint))— the DevPay-specific double-hash, not the RFC 9449 thumbprint. Entitlements carryjkt_boundcnf.jkt(same value).
htu— same-originpathname + query(not a full URI).h—base64url(sha256(raw request body)).- TTLs — entitlement
120 s· proofiat±60 s· capability60 s· nonce600 s.
Contract authority
The interface contract matrix is the single normative reference for claims, error codes, and activation paths across Worker / SDK-default / SDK-worker-preset. This section summarizes; the matrix adjudicates. Wire contract: v1, implicit — no version field or negotiation exists (versioning).
Feature flag
All PoP endpoints are gated behind LICENSE_SECURITY_ENABLED=true (exact match) on the Worker — unset → 404, including CORS preflight. It is absent from wrangler.toml today, so all PoP evidence is loopback (limitations §1.3).