Roles and guards
Three layers decide whether a button works: your role (permissions), step-up (a second factor verified in the last five minutes), and dual control (a second, different person). An API key has the first layer only, and only for a subset.
Roles and permissions
| Permission | owner / admin | approver | analyst | developer | viewer |
|---|---|---|---|---|---|
All reads (payments:read, trust:read, cases:read, policies:read, connections:read, webhooks:read, recon:read, insights:read, team:read) | ✓ | ✓ | ✓ | ✓ | ✓ |
audit:read | ✓ | ✓ | ✓ | ||
payments:write, refunds:write, orders:write | ✓ | ✓ | |||
trust:write, beneficiary_changes:request, payouts:write | ✓ | ✓ | |||
connections:write ⚡ | ✓ | ✓ | |||
webhooks:write | ✓ | ✓ | |||
api_keys:manage ⚡ | ✓ | ✓ | |||
cases:write | ✓ | ✓ | ✓ | ||
policies:write, insights:write, recon:write | ✓ | ✓ | |||
policies:approve | ✓ | ✓ | |||
policies:publish ⚡ | ✓ | ✓ | |||
beneficiary_changes:approve ⚡ | ✓ | ✓ | |||
payouts:approve ⚡, payouts:release ⚡ | ✓ | ✓ | |||
appeals:decide | ✓ | ✓ | |||
team:write ⚡ | ✓ | ||||
entitlement:request ⚡ | ✓ |
⚡ = needs a fresh second factor as well.
Step-up
Eight permissions require a second factor verified within the last five minutes: connections:write, api_keys:manage, team:write, policies:publish, payouts:approve, payouts:release, beneficiary_changes:approve, entitlement:request. The dashboard asks inline; the API answers 403 step_up_required with the freshness window in details. A TOTP code works once per 30-second step.
Dual control
| Action | Bound to | Who approves |
|---|---|---|
| Publish a policy | Definition hash and lock version | Someone else with policies:approve |
| Roll back a policy | From and to versions | Someone else with policies:approve |
| Approve a beneficiary change | Seller, old and new beneficiary | Someone else with beneficiary_changes:approve, after cooling-off |
| Approve a payout above the threshold | Instruction content and version | Someone else with payouts:approve |
| Create a live connection | Credential fingerprint | Someone else with connections:write |
| Grant a live entitlement | Evidence references and caps | A second platform administrator |
Rules that apply to all of them: the approver must differ from the requester (approver_must_differ); any change to the bound content between request and execution makes the approval stale (approval_stale); approvals expire after 24 hours; an approval completed by someone else cannot be completed again.
The account-takeover rule
A user who changed credentials in the last 24 hours (including enrolling a second factor) can neither request nor approve a beneficiary change: ato_session_blocked.
API keys
A key carries a subset of permissions, chosen at mint time from these fourteen: payments:read, payments:write, refunds:write, orders:write, trust:read, trust:write, beneficiary_changes:request, payouts:write, cases:read, cases:write, webhooks:read, insights:read, policies:read, recon:read.
No step-up permission is grantable to a key. A key cannot approve, release, publish, mint keys, manage the team, request Live, or seed a demo. It is bound to one environment and can only be revoked from that environment.
Platform administrators
A separate axis from workspace roles. They see the read-only Platform screen, resolve payouts stuck in MANUAL_REVIEW, record operator attestations, and grant or revoke live entitlement under dual control. None of those are dashboard buttons.