# Lakefront Agent Registration (auth.md)

Lakefront is a cloud-agnostic deploy platform. Agents can register to act **on behalf of a Lakefront
user**. An agent never exceeds the permissions of the user it acts for, and every action it takes is
attributed and independently revocable.

## Step 1: Discovery

Fetch the protected-resource metadata:

```
GET https://lakefront.sh/.well-known/oauth-protected-resource
```

The `agent_auth` block lists the supported flows, scopes, and endpoint URLs. Unauthenticated API calls
also return `401` with `WWW-Authenticate: Bearer resource_metadata="https://lakefront.sh/.well-known/oauth-protected-resource"`.

## Step 2: Choose a registration method

- **identity_assertion** (agent-verified): you are a trusted agent provider and can present a signed
  ID-JAG (`typ: oauth-id-jag+jwt`) asserting a verified user. Synchronous, no human step.
- **user_claimed**: no provider integration. You register with the user's email; that user approves
  the agent in the Lakefront dashboard, then you poll for the credential.

## Step 3: Register

```
POST https://lakefront.sh/api/agent-auth
Content-Type: application/json
```

Agent-verified:

```json
{ "type": "identity_assertion", "idjag": "<JWT>", "requested_scopes": ["deployments:read"] }
```

The ID-JAG must be signed by a registered trusted provider, have `aud: "https://lakefront.sh/"`, `typ:
oauth-id-jag+jwt`, and assert `email_verified: true` for an address in one of the provider's allowed
email domains. Response (`200`):

```json
{ "credential": "lf_agent_…", "credential_type": "api_key", "expires_at": null, "scopes": ["deployments:read"], "agent_id": "…" }
```

User-claimed:

```json
{ "type": "user_claimed", "email": "user@example.com", "label": "My Agent", "requested_scopes": ["deployments:read"] }
```

Response (`201`):

```json
{ "status": "pending_claim", "claim_token": "…", "claim_url": "https://lakefront.sh/settings/agents", "agent_id": "…" }
```

## Step 4: Claim ceremony (user_claimed only)

Direct the user whose email you registered with to `https://lakefront.sh/settings/agents` to approve the pending
agent and confirm its scopes — only that user can approve it. Then poll:

```
POST https://lakefront.sh/api/agent-auth/claim/complete
{ "claim_token": "…" }
```

`202 { "status": "pending_claim" }` until approved; `200` with the `credential` once approved (returned
exactly once). `403` if the request was denied; `400 expired_token` if it was not approved and
collected within 7 days of registering (register again).

## Step 5: Use the credential

Send it as a bearer token on API calls:

```
Authorization: Bearer lf_agent_…
```

The credential authenticates you as the bound user, capped to your granted scopes.

### Scopes

Request only what you need. The human approving you sees the list, and a shorter one is approved more
often. Scopes are granted independently: holding `services:write` does not imply `services:read`.

#### Apps & environments

What is deployed, and where it runs.

- `projects:read`: View projects
- `services:read`: View services & their configuration
- `services:write`: Create, update & delete services
- `environments:read`: View environments & preview environments
- `environments:write`: Create & update environments, their variables and preview settings
- `profiles:read`: View deploy profiles
- `profiles:write`: Create, update & delete deploy profiles

#### Source & shipping

Connecting repositories, building them, and rolling releases out.

- `repos:read`: View connected repositories & what they deploy
- `repos:write`: Connect repositories and change what they deploy
- `deployments:read`: View builds, deployments & their status
- `deployments:write`: Trigger deploys, rollbacks, retries & scaling
- `logs:read`: View build & runtime logs

#### Data & secrets

Managed databases, object storage and queues, and the secrets services read at deploy time. Secret access lets the agent reveal stored values.

- `databases:read`: View managed databases & connection info
- `databases:write`: Provision, bind, back up & delete managed databases
- `storage:read`: View managed storage, browse objects & connection info
- `storage:write`: Provision, bind & delete managed storage
- `queues:read`: View managed queues, their depth, dead letters & alert rules
- `queues:write`: Provision, bind, send to, redrive, purge & delete managed queues; set their alerts
- `secrets:read`: Read & reveal secrets
- `secrets:write`: Create, update & rotate secrets

#### Domains

Custom hostnames and their DNS. Buying a domain is separate because it spends money and cannot be undone.

- `domains:read`: View custom domains & their DNS status
- `domains:write`: Add, verify, attach & remove custom domains
- `domains:purchase`: Buy domains and change auto-renew (spends money)

#### Observability

Metrics, alerts, status pages, notification channels, spend and the activity log.

- `metrics:read`: View runtime metrics (CPU, memory, requests, latency)
- `costs:read`: View cost breakdowns & spend
- `alerts:read`: View alert rules & alert history
- `alerts:write`: Create, update & delete alert rules
- `status:read`: View status pages & incidents
- `status:write`: Publish status pages & write incidents
- `notifications:read`: View notification channels & their delivery history
- `notifications:write`: Create, update, test & delete notification channels
- `audit:read`: View the organization activity log

#### Backups & failover

Recovery plans, snapshots and drills — and, with write access, moving traffic between regions.

- `recovery:read`: View backup & disaster-recovery plans and drills
- `recovery:write`: Edit recovery plans, take snapshots, run drills & fail over

#### Context

Read-only visibility into the cloud accounts, people and AI proposals the agent works alongside.

- `connections:read`: View cloud connections
- `access:read`: View members, teams & who can access what
- `ai:read`: View AI configuration proposals
- `ai:write`: Accept or reject AI configuration proposals

### Common sets

If you are unsure what to ask for, these are the sets the approval dialog offers in one click:

- **Read-only**: Can see everything it is shown, and change nothing.

  `projects:read environments:read services:read deployments:read repos:read logs:read databases:read storage:read queues:read secrets:read domains:read metrics:read alerts:read status:read notifications:read costs:read audit:read recovery:read connections:read access:read profiles:read ai:read`
- **Ship code**: Everything read-only, plus connecting repositories, defining services and deploying them. No access to secrets, data stores or domains.

  `projects:read environments:read services:read deployments:read repos:read logs:read databases:read storage:read queues:read secrets:read domains:read metrics:read alerts:read status:read notifications:read costs:read audit:read recovery:read connections:read access:read profiles:read ai:read repos:write services:write environments:write deployments:write profiles:write`
- **Run the app**: Everything an engineer on call would do: ship, provision data stores, manage secrets and domains, and respond to incidents. Cannot buy domains.

  `projects:read environments:read environments:write services:read services:write deployments:read deployments:write repos:read repos:write logs:read databases:read databases:write storage:read storage:write queues:read queues:write secrets:read secrets:write domains:read domains:write metrics:read alerts:read alerts:write status:read status:write notifications:read notifications:write costs:read audit:read recovery:read recovery:write connections:read access:read profiles:read profiles:write ai:read ai:write`
- **Everything available to agents**: Every scope, including buying domains. Still cannot manage members, roles, billing, cloud connections or other agents — no scope grants those.

  `projects:read environments:read environments:write services:read services:write deployments:read deployments:write repos:read repos:write logs:read databases:read databases:write storage:read storage:write queues:read queues:write secrets:read secrets:write domains:read domains:write domains:purchase metrics:read alerts:read alerts:write status:read status:write notifications:read notifications:write costs:read audit:read recovery:read recovery:write connections:read access:read profiles:read profiles:write ai:read ai:write`

### What no scope grants

These are refused to every agent, whatever it holds, because each one changes who is trusted rather
than what is running, and an attenuated credential that could perform them could widen itself:

- Inviting, removing or changing members, teams and roles
- Activating a just-in-time role, or approving anyone else’s activation
- Approving, denying or revoking agents, or curating trusted agent providers
- Connecting, re-verifying, renaming or revoking a cloud account
- Billing, plans and payment methods
- Creating, renaming or deleting organizations and enterprise accounts
- Anything reserved for platform operators

## What you can actually do

An agent reaches the same API the dashboard does, so the whole deploy lifecycle is available: connect a
repository and deploy it from source, or deploy a prebuilt image; set environment variables; provision
managed databases, object storage and secrets and bind them to an environment; attach domains; read
builds, runtime logs, metrics and cost; wire alerts and notification channels; write incidents and
status pages; run backups, drills and failover.

Two things worth knowing about the git surface specifically:

- `github.connectRepo` connects a repository; `github.deploy` builds and deploys its production
  branch. Pushes deploy automatically after that.
- `github.adoptService` connects a repository to a service that is **already running** from a prebuilt
  image, in place: same stack, same hostname, same variables, nothing recreated. Use it instead of
  connecting the repository separately, which would stand a second copy of the app up beside the first.
  `github.serviceGitLink` tells you which of the two a service is.

The same flows are in the CLI: `lakefront git connect`, `lakefront git link <service> --repo …`,
`lakefront git deploy`.

## Errors

Errors return `{ "error": "…", "error_description": "…" }`. Common codes: `invalid_request`,
`invalid_grant`, `untrusted_issuer`, `unverified_user`, `user_not_found`, `access_denied`.

## Revocation

A user can revoke an agent anytime from `https://lakefront.sh/settings/agents`. You (or your provider) may also
revoke a credential:

```
POST https://lakefront.sh/api/agent-auth/revoke
{ "credential": "lf_agent_…" }
```

After revocation, API calls return `401`. Re-register to recover.
