Online Activation

Online activation is an optional convenience for internet-connected deployments. Instead of distributing an offline .license file, your own code (or the Bitruvius SDK) trades an API key for a short-lived, signed lease and writes it to disk. The codec then validates that lease file locally, exactly like any other license.

Crucially, the codec never touches the network. It embeds no HTTP client and makes no activation calls and no per-image calls. Fetching the lease is something your application code, or the SDK, does out-of-band — the codec only ever reads and verifies a file on disk.

It runs alongside the offline signed-file path — it does not replace it. If you operate air-gapped, keep using offline .license files; see Air-gapped deployment. A valid offline file always takes precedence over a lease.

Who does what

StepWhoNetwork?
Hold the API key and call the activation serviceyour code / the SDKyes — once per lease window
Write the returned lease into ~/.bitruvius/your code / the SDKno
Read the lease file and verify it on every encodethe codecnever

The codec is byte-for-byte the same as the air-gapped build: it validates a signed file on disk. Whether that file is an offline .license you copied in or a lease your code fetched makes no difference to the codec, and no difference to the encode hot path.

No per-image network calls

Activation is not a per-operation license check. Your code (or the SDK) fetches a lease at most once per lease window; the codec then verifies the file offline on every call, exactly like an offline .license file. There is no DNS, HTTPS, or telemetry on the encode/decode hot path — and no network code inside the codec at all.

  • One activation request per lease window — never per image.
  • The lease is verified locally by the codec; the network is never on the encode path.
  • The codec embeds no HTTP client; only your code or the SDK reaches the activation service.
  • Decoders are unlicensed and make no network calls of any kind.

The lease vs. offline trade-off

Offline .license fileOnline lease
Runtime network (codec)none, evernone, ever
Lease acquisitionyou copy the file inyour code / the SDK fetches it, once per window
Validitylong-lived, uncappedshort-lived, capped at 30 days
Best forair-gapped / SCIF / DoDCI runners, autoscaling fleets, dev laptops

Online leases are deliberately a separate, lower-trust class than offline files. The verifier hard-caps any lease at 30 days and rejects never-expiring leases, so a lease can never become a long-lived entitlement.

API keys

Create and manage keys in the portal at API keys (org admins only). A key looks like btr_live_<keyid>_<secret>.

  • The secret is shown once. Store it in your secret manager immediately; it cannot be retrieved again. Rotate or revoke from the same page.
  • A key is scoped to one or more product or suite ids. A suite scope (e.g. 3d-suite) automatically expands to the suite’s current members.
  • The scope picker only offers entitlements provisioned for online activation. Entitlements your org receives as a signed offline license file are delivered that way instead, and don’t appear here — there’s nothing for an online key to activate. Your dashboard tags each entitlement with its delivery method.
  • We store only a peppered hash of the secret — never the secret itself.

Treat the key like any other production credential: one per environment, least scope, rotate on a schedule. The key lives in your application/SDK environment, not in the codec — the codec never sees it.

Locking down API keys

When you create a key you can attach up to three optional, opt-in restrictions. Leave them blank and the key is unrestricted — exactly the default behavior. Set them from the Restrictions (optional) panel of the create-key dialog at API keys (org admins; staff can also view and set them from your org’s admin page).

All three are enforced only at the activation endpoint — at the moment a key is exchanged for a lease (POST https://activation.bitruvius.com/activate), after the key’s signature and status are checked and before a lease is minted. They are never evaluated per image. Once a lease is issued the codec validates it offline as usual, so restrictions add zero runtime cost to the encode path. A violation returns HTTP 403 with a clear message and no lease.

Allowed IPs / CIDRs — a real network boundary

Provide one or more CIDR ranges (IPv4 or IPv6; a bare address is treated as a /32 or /128). The key will only mint a lease when the caller’s IP falls inside one of the allowed ranges. The client IP is the edge-observed peer address (resolved from CloudFront-Viewer-Address, falling back to X-Forwarded-For), not a client-supplied value, so this is a genuine boundary. Ideal for server-side integrations with known egress IPs (CI runners behind a NAT, a fixed render-farm range). A caller outside every allowed range is rejected with “API key is not permitted from this network address”.

Allowed origins — browser / WASM only

List the exact browser origins permitted to use the key, e.g. https://app.example.com. This is intended for browser / WASM integrations: the activation API enforces the Origin header and speaks CORS (it echoes allowlisted origins back in Access-Control-Allow-Origin and answers the preflight), so a real browser on a disallowed origin is blocked before the request even reaches your key.

Be aware that Origin is a client-settable header. It is therefore advisory for non-browser / server-side clients — a custom HTTP client can send any Origin it likes, so an origin allowlist is not a security boundary against server callers (use the IP allowlist for that). An origin-restricted key is effectively browser-only: a request that arrives with no Origin, or a disallowed one, is rejected with “API key is not permitted from this origin”. Do not set an origin restriction on a key your server code uses — its requests carry no Origin and will be refused.

Max machines — a seat / device cap

Cap the number of distinct device fingerprints that may activate the key. Once that many distinct devices have activated, a new device is rejected with “device limit reached for this API key”, while already-seen devices keep re-activating freely (refreshing their leases is never blocked). This is a seat limit layered on top of the lease’s existing per-machine fingerprint binding and short TTL — it bounds how many machines a single key can spread to.

Fetching a lease

The Bitruvius SDK ships an ActivationClient (the activation feature of the bitruvius-license crate) that your build links — the codecs themselves do not. It accepts the key programmatically or reads it from the environment:

VarPurpose
BITRUVIUS_API_KEYYour btr_live_… key.
BITRUVIUS_ACTIVATION_ENDPOINTThe activation service URL (e.g. https://activation.bitruvius.com/activate).
// In YOUR application code (or the SDK) — never inside the codec:
let client = ActivationClient::from_env()?;        // reads BITRUVIUS_API_KEY + endpoint
// or pass them in directly:
// let client = ActivationClient::new(api_key, endpoint);
client.ensure_fresh(product, fingerprint)?;        // one POST per window → ~/.bitruvius/lease.license

ensure_fresh writes the lease to ~/.bitruvius/lease.license and refreshes it out-of-band at the midpoint of the lease window, so a transient network blip never interrupts encoding. The codec, running separately, simply reads that file and validates it offline on every call.

Prefer not to take the SDK dependency? Call POST $BITRUVIUS_ACTIVATION_ENDPOINT yourself with Authorization: Bearer $BITRUVIUS_API_KEY, write the returned lease into ~/.bitruvius/, and skip the client entirely. The codec only cares that a valid lease file is on disk.

Revocation SLA

Refreshing a lease is gated by the key’s and contract’s status, so revoking a key (or letting it expire) stops the next refresh. Active leases keep working until they expire; the maximum exposure after revocation is one TTL (default ~7 days, capped at 30). For an immediate cutoff, set a short lease_ttl_secs when you create the key.

Usage visibility

Activation calls let us report adoption and seat counts to your account team. These metrics are computed only on our backend from the activation requests — never on your machines, neither in the SDK nor in the codec. Air-gapped customers, who never activate online, are reported from license issuance instead.