Capability tokens
A capability token is the bearer credential that proves you hold a lease. Programs carry tokens; data-plane operations present tokens; cells verify tokens before serving any byte. Without a valid token there is no access.
If you’ve used Macaroons, the model is similar: short-TTL, signed by the cell that issued the lease, attenuable by caveats that tighten what the token grants.
Why bearer credentials and not ACLs
Two reasons.
First, the data plane is hot — RDMA QPs, NVMe ops, GPU submissions. Checking a centralized ACL on every op would dominate latency. Instead, the cell issues a token at lease time, the program presents it on every op, and the cell verifies the signature locally and the lease state locally. No round-trip to the controller.
Second, leases are short-lived and revocable. A long-lived ACL would have to be invalidated explicitly. With short-TTL tokens, the worst-case window after revocation is a few seconds: the cell drops the token at revoke time, in-flight ops with the old token fail closed, the program asks for a renewal and gets a fresh token only if the lease is still valid.
Anatomy of a token
A token is a signed structure carrying:
| Field | What it is |
|---|---|
tenant_id | Tenant the token was issued to. |
resource_id | The leased resource the token grants access to. |
lease_id + generation | Which specific lease and at which generation. Renewing a lease bumps the generation; old tokens become invalid. |
expires_at | Wall-clock TTL. Default max 300s; renewal cadence is faster. |
audience | The cell that issued + must verify. Tokens are not transferable across cells. |
caveats | Zero or more attenuations (see below). |
signature | Issuing cell’s signature over the above. |
The token never leaves the program’s process unencrypted. It rides on the inside of capability-bound calls; the data-plane ops carry the token in their headers but the underlying transport is mTLS or fabricBIOS-protected RDMA.
The wire format is in /spec/fabricbios-wire-encoding-v0 under the Token section, and a minimal no_std implementation is in crates/fabricbios-core/src/cap_token.rs.
Caveats — narrowing what a token grants
A caveat is a clause attached to the token that further restricts what it can do. The cell verifies every caveat on every op; failing any caveat fails closed.
Caveat kinds today (see crates/fabricbios-core/src/token.rs):
program_path— token is only valid for tasklets whose path/SHA-256 matches. Stops a malicious co-tenant from stealing a token and using it from a different tasklet.expires_before— narrower TTL than the lease itself; useful for issuing per-op tokens with sub-second lifetimes.isolation— token requires the running cell to provide certain isolation guarantees (StrictIsolated,WholeCore,WholeCard). Tied to/spec/resource-isolation-and-exclusivity.attestation— token requires the cell to have a verified attestation digest (TEE, secure boot). Falls closed if the cell didn’t produce a matching attestation at last announce.
You attenuate by adding caveats. You cannot remove a caveat the issuing cell put on the token.
Token lifecycle
- Mint at lease creation. When
LEASE_ALLOCsucceeds, the cell’s CapBroker mints a token and returns it to the requester. Token TTL ≤ lease TTL. - Use on every op. Every data-plane op (memory read/write, block I/O, GPU submission, etc.) presents the token. The cell verifies signature → audience → expiry → caveats → lease state, in that order, on every op. Verification before decompression, by spec.
- Refresh near expiry. Programs use
grafos-leasekitto refresh tokens before they expire. The new token has a fresh signature and a newexpires_at; the old token is invalidated immediately. - Discard at revoke. When the cell revokes a lease (operator action, fence, partition), it invalidates all tokens for that lease. Programs see typed
LeaseRevokedevents.
What can go wrong
- Token replay. A token signed for one tenant cannot be reused by another tenant —
tenant_idis in the signed payload, the cell verifies it. - Token forwarding. A valid token for cell A cannot be presented at cell B;
audiencebinds the token to one cell. - Token theft within the program. If a malicious co-tasklet on the same cell can read your memory, it can steal your token. Use
program_pathcaveats so a stolen token is useless to a different tasklet. - Stale renewal. If you renew a lease and the new token doesn’t propagate to all the threads using it, those threads fail with
stale_token. The SDK wrappers handle this with a retry loop; if you wrote raw token-using code, you handle it yourself. - Attestation drift. A cell that loses its attestation (key compromise, soft reset of TPM) fails any token with an
attestationcaveat. New leases ride on a fresh attestation digest after re-attest.
Where to next
- Trust model — how tokens fit into the larger signed-everything story.
/spec/fabricbios-wire-encoding-v0— token wire format bytes.grafos-leasekit— the SDK wrapper that refreshes tokens for you.