> ## Documentation Index
> Fetch the complete documentation index at: https://docs.omegas.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Operator: authentication and scopes

> One credential, a scope table with no surprises left in it, and the credential-custody rules that keep a key out of your logs.

One credential: an API key on the `Authorization` header.

```text theme={null}
Authorization: Bearer omg_operator_<env>_<key_id>_<secret>
```

Keys are minted by the Ωmegas team and shown exactly once. The TypeScript
client reads `OMEGAS_OPERATOR_API_KEY` from the environment; over raw HTTP you
send the header yourself.

```sh theme={null}
curl https://api.omegas.dev/v1/whoami \
  -H "Authorization: Bearer $OMEGAS_OPERATOR_API_KEY"
```

`GET /v1/whoami` answers with the key's identity and is the cheapest way to
check a credential without touching anything.

## Scopes

A key carries scopes and, optionally, a list of Spaces. Missing either is
`403 insufficient_scope`.

| Scope                       | What it unlocks                                                                 |
| --------------------------- | ------------------------------------------------------------------------------- |
| `operator:devices:read`     | list and get devices                                                            |
| `operator:devices:write`    | create, sleep, wake, delete                                                     |
| `operator:tasks:read`       | get and list tasks, stream events                                               |
| `operator:tasks:write`      | submit, cancel                                                                  |
| `operator:sessions:write`   | mint, read, and revoke live-view sessions                                       |
| `operator:sessions:control` | additionally required to mint a `control` session, to take over, and to release |
| `operator:usage:read`       | `GET /v1/usage`                                                                 |
| `operator:audit:read`       | read the audit trail at `GET /v1/audit`                                         |
| `operator:webhooks:read`    | list and get webhook endpoints                                                  |
| `operator:webhooks:write`   | create, update, delete endpoints                                                |
| `operator:escalations:read` | list and get human escalations                                                  |

Two rows deserve emphasis:

* `operator:sessions:control` is separate on purpose. A key issued for
  monitoring cannot be turned into a key that types into a logged-in browser.
* `GET /v1/audit` reads with `operator:audit:read`. Keys minted before that
  scope existed carried `operator:webhooks:read` for the audit route, and the
  historical scope is still accepted there, so an existing key keeps working.

A **Space-scoped** key must name a Space it holds on every list; an org-wide
key may omit it and sees the whole organization.

## A credential must not reach a URL

A URL is a publishing surface: access logs, span fields, error reporters,
proxies, `Referer` headers. This product has already had one credential leak
that way, which is why the client refuses to let it happen again rather than
asking integrators to be careful:

* The key is wrapped in a `Credential` whose `toString`, `toJSON` and
  inspection output all return `omg_operator_<env>_<key_id>_***`. The only
  function that reveals the secret returns an `Authorization` header.
* Query strings are scanned for credential-shaped values and the request
  throws before it is sent.
* Live-view session tokens ride the `Sec-WebSocket-Protocol` header
  (`omega.operator.v1, omega.token.<ops_…>`), never a query parameter, and the
  server-supplied `ws_url` must match the API origin and must be `wss:`.
* Redirects are refused outright; following one would replay the
  `Authorization` header at a host nobody validated.

If you integrate over raw HTTP, adopt the same rules. They are cheap before a
leak and expensive after one.
