# auth.md — Bog Cloud authentication

This is a prototype. During this preview, the existing chat owner credential may remain enabled for the legacy workspace only; it cannot access new personal workspaces or manage memberships.

GitHub sign-in at /auth/login proves identity. Bog owns sessions, memberships and credentials. No repository scopes are requested. Your personal workspace is created once. Logout ends only the local Bog session.

For agents, POST /auth/device with JSON {"name":"My agent"}. Keep device_code private in memory. Show the user only verification_uri and user_code. The human signs in, reviews the name/access, and explicitly approves or denies. Poll POST /auth/device/token with JSON {"device_code":"<private code>"} at intervals of at least 5 seconds. Grants expire after 10 minutes and are lost on server restart. Errors: authorization_pending (keep waiting), slow_down (for polling, wait at least 5 seconds; request and approval limits require a 10-minute wait, then a new request if the grant expired), expired_token (start again), access_denied (stop). Successful polling returns access_token exactly once, token_type Bearer, expires_in 2592000. Never put credentials in chat, URLs, logs or browser storage.

Alternatively, a signed-in human creates/revokes named agent credentials in /console or uses GET/POST /v1/agent-tokens and DELETE /v1/agent-tokens/{id}. Writes require the session cookie, exact Origin and x-csrf-token from /console-session. Only humans can manage account credentials. Tokens expire in 30 days; revocation and account suspension are immediate.

MCP tool results, including structuredContent, may enter model context, chat transcripts or client logs. Structured output is not a private credential channel. For app credentials, prefer prepare_app_access and the /bog-app-access.py helper or an explicit console download. The helper writes directly to a private file with owner-only permissions, without printing it. Keep compatibility issue_token out of ordinary tool conversations. Configure the client from that file privately; never paste its contents into a conversation. This applies to device-token responses, account credentials and scoped app credentials.

Use Authorization: Bearer <Bog credential> for REST and bearer-capable MCP clients at /mcp. Select workspace_id explicitly; omission selects personal. Agents can create Bogs and issue scoped app credentials, but cannot manage members, delete Bogs or mint account credentials. App credentials remain restricted to one Bog. Membership is checked on every request. GitHub access tokens are never Bog API credentials. OAuth-capable MCP clients can discover the self-hosted authorization server and request bog:read or bog:write. GitHub remains the identity provider; there is no paid authentication intermediary. See /v1 for creation requirements and /v1/templates for templates.

## OAuth 2.0 for MCP clients

REST OAuth clients use this service origin (without a trailing slash) as their resource and discover /.well-known/oauth-protected-resource. Origin-bound tokens work only on REST; MCP keeps its distinct /mcp resource. The authorization and token requests must name the identical resource. Existing /mcp-bound credentials retain their REST compatibility.

Read /connect for client connection guidance. Discover /.well-known/oauth-protected-resource/mcp (resource is this origin plus /mcp), then /.well-known/oauth-authorization-server. Register a public client at POST /oauth/register with application/json, client_name, redirect_uris, and token_endpoint_auth_method "none". Registration lasts 30 days. HTTPS redirects match exactly. Desktop client metadata may use a temporary port on an otherwise matching HTTP loopback callback (127.0.0.1, [::1], or localhost); the literal host, path and query must match. Dynamically registered redirects still match exactly. HTTPS Client ID Metadata Documents are supported alongside dynamic registration. The document client_id must exactly match its HTTPS URL and the redirect must match its declared redirect_uris. Metadata fetches are bounded and restricted to public addresses without redirects. Refresh tokens, OIDC ID tokens, and the separate Auth.md identity-assertion registration protocol are not implemented.

Open /oauth/authorize with response_type=code, client_id, redirect_uri, resource, scope, state, code_challenge and code_challenge_method=S256. The human signs in through GitHub and explicitly approves or denies the named client and callback destination. Check state and the returned iss before exchanging the code. Exchange within 60 seconds at POST /oauth/token using application/x-www-form-urlencoded: grant_type=authorization_code, code, code_verifier, client_id, the exact redirect_uri and resource. Codes are one-use; pending requests expire after ten minutes and are lost on server restart. Access tokens persist across restart, expire after 30 days, and remain subject to current membership and account suspension.

Scopes: bog:read reads accessible Bogs, records, workspace and credential metadata; it cannot create, write, or issue credentials. bog:write includes reads, Bog creation, record writes, and single-Bog app credential issuance/revocation. Neither scope permits Bog deletion, organization/membership administration, platform controls or account credential issuance. Request the least access needed; the default is bog:read. Both HTTP and MCP share this permission boundary. For a deployed app, use a single-Bog read or write credential instead of an account-wide OAuth credential.

Revoke an OAuth connection through Agents in /console, or POST /oauth/revoke using application/x-www-form-urlencoded with token and client_id. Revocation is immediate, including for pending change waits. Invalid or already-revoked tokens also receive HTTP 200. There are no refresh tokens: reconnect with a new human approval after expiry. Keep access tokens out of model context, URLs, logs, and chat; the client handles the short-lived authorization code and PKCE verifier privately.

## Free self-serve access

GitHub signup is open. No payment card, sales contact, organization setup or manual key approval is required. The free prototype allowance is three Bogs per ordinary workspace, 16 MiB each, subject to shared host capacity. Approved accounts or organizations can have an uncapped Bog allowance; per-Bog storage and host capacity still apply. Device approval or OAuth gets an agent started; /console provides self-serve credential creation and revocation. Test in a disposable Bog in your workspace; there is no separate sandbox environment.

## Agent context and private app installation

Start with get_current_context and list_templates. Omitted workspace_id means your personal workspace; always pass workspace_id for shared workspaces. Create with a name and stable idempotency_key; reuse the identical key/body on retries. Wait for ready status before using records. If startup reports failed with a capacity error, retain the returned Bog ID and retry creation with the SAME name, idempotency_key and body after active operations finish. Unused warm workers are automatically reclaimed when another Bog needs capacity. This retries startup of the same Bog; do not create new names or keys to recover. A record/view request can also start that same Bog once capacity is available; describe alone does not restart it. Read bounded pages (default 100, max 1000, offset max 10000). wait_for_change takes timeout 0–25 and an opaque cursor; refetch on changed or reset, with no event replay. Use prepare_app_access for a single-Bog app credential delivered privately by the helper or an explicit console download. Never put secrets in prompts, URLs, or logs. For diagnosis use bog_metrics (window 5m or 1h): it does not wake a sleeping Bog. Check window_complete, truncated, and observed_since before comparing counts; latencies are bounded recent samples, not a complete history. Workspace members can read bog_events for bounded operational history; app credentials see only their own traffic and cannot read events. Events never contain record changes. Agents cannot manage membership or delete Bogs.

GitHub identity determines your account, and current membership determines workspace access. Personal is the default; shared workspace selection must be explicit. bog:read reads existing Bogs; bog:write also permits creation, record writes and issuing single-Bog app credentials. Broader scope cannot grant missing membership. App credentials cannot provision, mint credentials, or access another Bog. Owners manage membership and Bog deletion through the console. Removal and revocation take effect on subsequent requests. Pending private handoffs last ten minutes, require the initiating account at redemption, and expire on server restart. The handoff reference is nonsecret and safe in tool results or conversation; it grants no access by itself. An authorized agent may run the private helper using the helper's own authorization cache, without reading another client's credentials or exposing the installed file. If approval is needed, the human must explicitly approve the separate device request; console download also requires explicit human action. issue_token remains compatible but returns a secret in its result; prefer prepare_app_access.

Download /bog-app-access.py and follow the installation command returned by prepare_app_access. The helper may require a separate device approval; it never reads client credential stores.
