# Keys and scopes

## Facts about a key

- Format: `anlyon_live_` plus 32 characters. The prefix is the same in every environment.
- A key belongs to one environment, chosen at creation. It cannot see another environment's actions, secrets, invocations or approvals: a resource "missing" with a valid key usually lives in another environment.
- Scopes are fixed at creation. To change them, create a new key and revoke the old one.
- Sent as `Authorization: Bearer <key>`. The SDKs do this.
- `GET /api/v2/auth/identity` (`client.auth.identity()`) returns the caller's own credential type, key id, workspace, environment, scopes and expiry. It never returns a secret.

## Presets

| Preset | Holds | Use for |
| --- | --- | --- |
| Standard (default) | Every current scope except the privileged ones | Agent keys |
| Read only | Every `:read` scope | Dashboards, monitoring |
| Full access | Every scope, privileged included | Rarely. Prefer Standard plus a separate operator key |

## Privileged scopes (never in the agent's key)

The main ones are below. The full list also includes `integrations:*`, `secret-stores:*`, `functions:*`, `messages:ingest` and `notifications:manage`; the console marks every privileged scope.

| Scope | Allows |
| --- | --- |
| `secrets:read`, `secrets:write` | Manage vault secrets, and reference one from an action definition. No scope returns a secret's value |
| `approvals:decide` | Approve or deny without a person clicking approve |
| `policies:read`, `policies:write` | Read and change approval policies |
| `impact-limits:write` | Create, change, archive impact limits |
| `actions:govern` | Change whether an action requires approval, and change or remove a governed action's declarations |
| `actions:resolve` | Record the real outcome of an `unknown` invocation |
| `environments:halt` | Halt and resume the environment |
| `budgets:read`, `budgets:write` | Per-key caps on Anlyon operations |
| `end-users:read` | List end users and their connections |
| `end-users:write` | Connect links and their confirmation, store an end user's key, disconnect, erase, mint session tokens |
| `end-users:approvals` | List and decide the approvals an end user decides in your app |
| `audit:read` | Read and export audit records |

`actions:write` is in Standard, but a definition that references `{{secret:NAME}}` also needs `secrets:read`.

## Typical sets

- **Agent:** Standard. Check with `requireScopes(['actions:invoke'], { forbidden: ['secrets:write', 'policies:write', 'approvals:decide'] })`.
- **Operator (setup scripts, CI):** `secrets:write`, `secrets:read`, `actions:write`, plus `policies:write`, `impact-limits:write` and `actions:govern` when the script manages those.
- **Product server acting for users:** Standard + `end-users:read` + `end-users:write` + `end-users:approvals`, **Require a user** on (`"endUserRequired": true`). Such a key refuses an action call without `Anlyon-End-User` (`400 END_USER_REQUIRED`), never uses the workspace's own connections, and reads only the named user's invocations, receipts and approvals. Keep a second key without it for admin reads.
- **Reviewer tooling:** `approvals:read` + `approvals:decide`, on a different credential from the one that requests approvals. A key or app can never decide an approval it requested (`403 AUTHORIZATION_ERROR`), and a person cannot decide what their own agent requested (`403 SELF_APPROVAL_NOT_ALLOWED`).

## Plans

Actions run on a plan. A workspace without one answers `402 PAYMENT_REQUIRED` on invoke. An admin starts a trial or a plan under **Settings → Plan & billing**. See https://docs.anlyon.com/account/billing.md.
