Control planeLicensing

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

  1. Mint. An admin calls POST /license/keys with a customerId and tier. The plaintext key is returned once.
  2. Activate. The box calls POST /license/activate with the key. It receives a short-lived RS256 activation token, the entitled package set, and the registry URL.
  3. Install. The CLI uses the activation token as the registry auth token. The registry serves only entitled packages.
  4. 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:

FieldNotes
keyThe credential (hashed at rest)
customerIdOpaque customer identifier
tierbasic / growth / enterprise
activeInactive keys fail activation with a uniform error
expiresAtOptional 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 (default 3600).
  • Issuer: LICENSE_JWT_ISSUER (default withpotter-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

EnvironmentBehavior
ProductionReads LICENSE_JWT_PRIVATE_KEY + LICENSE_JWT_PUBLIC_KEY (PEM). Both required.
Dev / demoGenerates 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.