Licensing
Licensing is how a box proves what it is entitled to install. A license is minted once, activated repeatedly, and verified by the gated registry on every package download.
Lifecycle
- Mint. An admin calls
POST /license/keyswith acustomerIdandtier. The plaintext key is returned once. - Activate. The box calls
POST /license/activatewith the key. It receives a short-lived RS256 activation token, the entitled package set, and the registry URL. - Install. The CLI uses the activation token as the registry auth token. The registry serves only entitled packages.
- Renew. Activation tokens are short-lived (default
3600s). Re-activate to get a fresh token; the license key itself does not change.
License record
A license key resolves to a record with:
| Field | Notes |
|---|---|
key | The credential (hashed at rest) |
customerId | Opaque customer identifier |
tier | basic / growth / enterprise |
active | Inactive keys fail activation with a uniform error |
expiresAt | Optional expiry |
There is intentionally no version field on a license today — a license
gates which packages a box may install, not which versions. Freezing a box
to a platform version is a separate, proposed capability (see the
VERSION_FREEZE_LTS_PLAN RFC).
Activation token (JWT)
The activation token is an RS256 JWT. Its claims:
interface LicenseClaims {
sub: string // customerId
tier: Tier // 'basic' | 'growth' | 'enterprise'
pkgs: string[] // dependency-closed entitled package set
}- Algorithm: RS256 (2048-bit RSA).
- TTL:
LICENSE_JWT_TTL_SECONDS(default3600). - Issuer:
LICENSE_JWT_ISSUER(defaultwithpotter-control-plane).
The pkgs claim is the closed set — every dependency of every entitled
leaf package — so the registry never has to re-resolve closures at download time.
See Plans & tiers for how the set is built.
Signing keys
| Environment | Behavior |
|---|---|
| Production | Reads LICENSE_JWT_PRIVATE_KEY + LICENSE_JWT_PUBLIC_KEY (PEM). Both required. |
| Dev / demo | Generates an ephemeral keypair at boot. Tokens do not survive a restart. |
Verification: GET /license/jwks
The control plane publishes its public key at GET /license/jwks. The gated
registry fetches and caches it, then verifies every activation token presented as
a registry credential — checking the signature, issuer, and expiry before reading
the pkgs claim. Because verification is asymmetric, no secret is shared with
boxes or the registry.
Telemetry
After each download decision, the registry calls
POST /telemetry/download with the
package name and an allowed / denied outcome. This is fire-and-forget
(202) and never blocks an install.