# Aetherya authentication

Aetherya is an auth.md service for external agents acting on behalf of a signed-in human. Discovery comes first; legacy API keys remain available for existing integrations.

## Discover

- Protected resource metadata: `/.well-known/oauth-protected-resource`
- Authorization server metadata: `/.well-known/oauth-authorization-server`
- JSON Web Key Set: `/.well-known/jwks.json`
- Registration: `POST /agent/identity`
- Token exchange and claim polling: `POST /oauth2/token`
- Revocation: `POST /oauth2/revoke`

When an API request needs authentication, follow the `resource_metadata` URL in the `WWW-Authenticate` header. Do not guess or hard-code a different issuer.

## Register

For a verified human email, send a `service_auth` registration with a normalized `login_hint`. For a headless first run, send `anonymous`. The service returns a short-lived claim secret and, where required, a verification URL. Never log or forward claim tokens, attempt tokens, or user codes.

Open the verification URL in a human browser. The user signs in with Aetherya's normal Clerk flow, reviews the exact organization/workspace and requested capabilities at `/claim`, and enters the six-digit code. Aetherya binds the registration to one user and workspace only after confirmation.

## Scopes

Phase 1 capability scopes are explicit and deny-by-default:

- `workspace.read`, `audiences.read`, `audits.read`, `usage.read`
- `surveys.read`, `posts.read`
- `audits.run`, `surveys.run`, `posts.run` (billable; rollout-gated)

Agent credentials cannot access admin, billing, organization membership, API-key management, approvals, connections, memory, internal employee-agent identity, or internal routes. Unknown routes are denied.

## Use and refresh

Exchange the service-signed `identity_assertion` at the discovered token endpoint using the JWT-bearer grant. Send the resulting short-lived `access_token` as `Authorization: Bearer <token>`. The token is bound to the approved workspace; do not override it with a different workspace header. Re-exchange the assertion to refresh. A refresh token is never issued.

Legacy `aeth_live_` API keys continue to work for existing clients and may require `x-aetherya-workspace-id`. Prefer delegated auth for new agent integrations.

## Revoke and errors

Revoke an individual access token with RFC 7009 `POST /oauth2/revoke`. A human can revoke the whole registration from Settings → API & agent access; revocation takes effect on the next request. Treat `401` as a signal to rediscover metadata and restart the claim flow when the assertion is expired or revoked. Respect `Retry-After` and `slow_down` responses while polling.
