The token.* family (6 verbs). Every verb enters through the one front door: it is capability-checked, permission-checked, scope-checked and audited before it runs (see Security & permissions). Each entry below lists its capability, risk class (which fixes the minimum autonomy level), the minimum caller permission, its availability tier, whether it is idempotent, and any outbound egress.
Consumetoken.consume
| Property | Value |
|---|---|
| Capability | token.consume |
| Risk class | Sensitive - autonomy L2 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
A THIN wrapper over the shared consume_token validation core (ADR-0040 step 4): the verb and the
TokenIdentityProvider resolver call the SAME path, so the token’s three revocation axes are
enforced in exactly ONE place (steering #1 - one validation path, never a second hand-rolled one).
The verb adds only the JSON-shaping the front doors expect; all seven fail-closed checks + the
atomic single-use spend live in consume_token.
Input { secret, scopeRef?, presentedEmail?, via?, fromBrowser? } (fields ending in ? are optional)
Call POST /v/token.consume with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool token.consume.
Gettoken.get
| Property | Value |
|---|---|
| Capability | token.read |
| Risk class | Read - autonomy L0 |
| Min. permission | Admin |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
| Render schema | Yes - drives an inline chat artefact and a GUI panel |
One token’s metadata (kind+scope+status+expiry+consume-history + lastAccessAt). NEVER the hash or the plaintext (C12). IDOR-scoped to the caller workspace.
Input { tokenId } (fields ending in ? are optional)
Call POST /v/token.get with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool token.get.
Listtoken.list
| Property | Value |
|---|---|
| Capability | token.read |
| Risk class | Read - autonomy L0 |
| Min. permission | Admin |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
| Render schema | Yes - drives an inline chat artefact and a GUI panel |
Returns outstanding tokens filtered by scope/status. The response carries ONLY kind+scope+status+expiry+consume-history metadata - never the hash or the plaintext (C12). IDOR-scoped: a token row from workspace B is never enumerable (the verb filters on workspace_id).
Input { scopeRef?, status? } (fields ending in ? are optional)
Call POST /v/token.list with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool token.list.
Minttoken.mint
| Property | Value |
|---|---|
| Capability | token.write |
| Risk class | Sensitive - autonomy L2 |
| Min. permission | Admin |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Returns { tokenId, secret, ... } - the secret is the ONLY time the
plaintext is ever returned. The DB stores only its sha256 hash + an explicit scheme (C12).
Input { kind, scopeRef, purpose?, expiresInSecs?, allowedClickerEmails?, boundActorId?, requireBrowser? } (fields ending in ? are optional)
Call POST /v/token.mint with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool token.mint.
Revoketoken.revoke
| Property | Value |
|---|---|
| Capability | token.write |
| Risk class | Sensitive - autonomy L2 |
| Min. permission | Admin |
| Availability | On demand (MCP tier 2) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
Atomic guard: a non-terminal token → REVOKED; a re-revoke of a terminal token is a no-op-conflict (idempotent terminal). A later consume of a REVOKED token is refused (410-equivalent).
Input { tokenId } (fields ending in ? are optional)
Call POST /v/token.revoke with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool token.revoke.
Revoke scopetoken.revoke-scope
| Property | Value |
|---|---|
| Capability | token.write |
| Risk class | Sensitive - autonomy L2 |
| Min. permission | Admin |
| Availability | On demand (MCP tier 2) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
Bumps the scope-version counter so EVERY outstanding token in the scope fan is
invalidated at next consume (one call kills the whole fan, any flavour). This is the generalised
accessVersion axis - the SAME mechanism EPIC-PORTAL’s bump-access-version rides (consolidation).
Input { scopeRef } (fields ending in ? are optional)
Call POST /v/token.revoke-scope with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool token.revoke-scope.