0025. Risky actions need an approval in id, bound to the action
Status: accepted, 2026-10-21
Context
A person's API token, CLI sign-in or panel session carries their whole role, for 15 minutes to 30 days, and
the platform is about to be driven by agents (Claude Code through MCP), the assistant, Telegram and phones. A
stolen or prompt-injected credential could then delete a database or reveal production secrets, and nothing
can ask the person "did you mean this?". Protected environments (ADR 0005) are guarded by role only; the
only confirmations are dialogs in panels, and each new surface would invent its own.
Decision
- Operations carry a risk:
none, low, medium, high, critical (x-xvii-risk in each service's
API contract; base/protected when it depends on the target environment). Risk is independent of scope.
- Every token says how it was obtained (
via: panel, app, cli, token, ci, agent, assistant, telegram,
service) and which sign-in it belongs to (sid). Calls through MCP, and requests an agent marks, count as
agent; agents get sign-ins and tokens of their own.
- A policy by via and risk says whether a person must approve and how:
none, confirm (a tap in a
surface bound to the person), passkey (a passkey at id, or a native app's approve key behind
biometrics, rooted in a passkey), or refuse. id holds it: an instance matrix with floors in code,
strict environments, four eyes per environment. Defaults: critical needs a passkey from every caller but
services; high needs one from agents, the assistant and Telegram.
- The service that owns the operation enforces it through kit before acting, and writes what the person
will read from its own data. It asks id, which records the approval, has notify deliver it, and runs the
passkey ceremony on its own page (passkeys stay at id, ADR 0006).
- An approval is bound to the service, operation, resource, parameters and requester, and is used once:
the requester repeats its request, and the service gets a single-use action token from id. Panels and
apps step up through the same approval and then go five minutes without another passkey; an approver may
allow a kind of action for a few hours, never a critical one.
- The requester's side never approves: API tokens, CLI sign-ins, CI, agents and delegated tokens can't
decide. Decisions happen at id, in the hub, the native apps, the ai chat or the person's bound Telegram
chat.
- Fail closed: without id, gated actions stop; everything else goes on.
- Approvals never grant a role. Doing more than one's role allows would need its own ADR.
Consequences
- One mechanism replaces per-surface confirmations; agents ask instead of being refused, and the person's
phone is where production changes are confirmed.
- Every service declares the risk of its operations and gates the risky ones; kit and the API contracts make
that a declaration, with a test that lists operations that forgot.
- id is now in the path of risky actions; the break-glass path stays
xvii-node recover.
- Design:
superpowers/specs/2026-10-21-approvals-design.md in this repository.