Skip to content

Scoped API keys and the durable-key model

The durable, account-scoped key a tenant mints for an end user — how it stays live, the two tiers, inquiry-key export, Cold Vault accounts, capacity eviction, and coarse revocation.

Updated View as Markdown

A scoped API key is a single opaque string a tenant mints for one end user, bound to one account — or one wallet within it. Unlike a workspace token, it is durable: it keeps working, and keeps its account unlocked, until the service restarts. The end user holds the one string (for example in localStorage) and never sees the workspace password.

The canonical flow is a tenant minting a key for an end user who later redeems a key export against it — the workspace password never leaving the tenant’s side:

sequenceDiagram
autonumber
actor U as End user
participant T as Tenant backend
participant S as TEE Docker
U->>U: generate an X25519 keypair, keep the private half
U->>T: ask for access, hand over the inquiry public key
T->>S: POST /v1/auth/api-key — tier unlimited, inquiryKey, accountPassword if Cold Vault
Note over S: the account is unlocked and pinned open inside the enclave
S-->>T: 201 — one durable scoped-key string
T-->>U: the scoped key, kept in the browser
Note over U,S: later — the workspace password is never shared
U->>S: POST /v1/accounts/slug/wallets/id/export?vm=evm — Bearer scoped key
S-->>U: a blob sealed to the inquiry key
U->>U: unseal with the private half to recover the private key
The end user generates a keypair, the tenant mints a scoped key bound to their inquiry key, and later the user exports a key that only their private half can open.

The endpoint shapes for minting and introspection are on API keys; this page is the model behind them.

Durable, and in memory

A live key is stay-exposed: while it exists it pins its workspace and its bound account open, so the idle, absolute, and account-custody timers do not apply to it. All of that state — the binding, the tier, the inquiry key — lives in memory only. Nothing about a scoped key is written to disk, and a restart voids every key. “Durable” means “until the process restarts,” not “forever on disk.”

Nothing decrypted is persisted to achieve this: the never-lock behaviour comes from keeping an already-unsealed session alive in the enclave, never from storing a re-unlock secret. No workspace or account password is ever held at rest.

Two tiers

A key is minted at one of two fixed tiers, expressed as its scopes:

Tier Scopes What a scoped key can reach (this release)
basic (default) read, write Read its bound account, wallets, and addresses
unlimited read, write, sign, export The above, plus sealed export (with a live inquiry key)

The write and sign scopes sit on the lease but are not reachable by a scoped key: it is confined to its bound account’s read routes plus export. Signing and account/wallet management require a workspace token, so unlimited over basic buys a scoped key only sealed export. Mint it deliberately, for users who need export. See Scopes and tiers.

Export needs an inquiry key

Export is the highest-consequence operation, so it is never sealed to an operator key. The end user generates their own X25519 keypair, keeps the private half, and gives the tenant only the public inquiry key at mint. Every export the key performs is sealed to it, and opens only for the holder of the private half.

  • The inquiry key unlocks a small functionality list — today just export.
  • It is time-boxed by validationDuration (default four hours). After it lapses the base key keeps working, but export locks again.
  • Without an inquiry key, export is refused even on an Unlimited key.

The client-side unseal is in Export key material.

Cold Vault accounts

An account may carry its own password — an extra secret beyond the workspace password. Such an account can still be minted for: the tenant relays that password as accountPassword at mint, the service unlocks the account, and the durable key keeps it open. The password is used once and never stored.

Capacity and eviction

A durable key holds a decrypted workspace handle in memory until restart, so handle capacity is finite. When admitting a new key would exceed a tenant’s capacity, the tenant’s least-recently-used durable key is evicted to make room. An evicted key’s next request fails exactly as after a restart — re-mint it. Each use touches the key’s recency, and every eviction is recorded in the audit log so an evicted client knows to re-mint.

Revocation is coarse

There is no per-key revoke. DELETE /v1/auth/token is accepted for a scoped key but does nothing — a restart (or an eviction) is what ends it. Plan to re-mint after a restart rather than to revoke, and keep the blast radius of any one key small by scoping it to a single account or wallet.

Identity binding

A key is bound to its account by the account’s slug (and to a wallet by its stable id). A slug can be reused after an account is deleted, so deleting an account that a live key is bound to is recorded in the audit log — a later account created with the same slug would otherwise inherit that key’s authority.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close