# auth.md

You are an agent. This document tells you how to authenticate with Cachely's
protected APIs. Cachely is a remote build cache for Nx, Lerna, Turborepo, Gradle, and
Bazel. Prefer the machine-readable discovery documents below; this file is the
human- and agent-readable companion to them.

## Audiences

Cachely exposes two protected surfaces:

- **MCP server** - `https://app.cachely.dev/mcp`. A Streamable HTTP Model
  Context Protocol endpoint (workspaces, insights, plan usage). Authenticated
  with OAuth 2.1. An agent can register and obtain credentials on its own.
- **Remote cache API** - `https://remote.cachely.dev` (Nx `/v1/cache`,
  Turborepo `/v8/artifacts`, Gradle `/v1/gradle`, Bazel `/v1/bazel`).
  Authenticated with a workspace bearer token that a human provisions in the
  dashboard. Agents cannot self-register for this surface.

## Discovery

- Protected Resource Metadata (RFC 9728):
  https://cachely.dev/.well-known/oauth-protected-resource
- Authorization Server Metadata (RFC 8414), including the `agent_auth` block:
  https://cachely.dev/.well-known/oauth-authorization-server
  (the authoritative same-origin copy is
  https://app.cachely.dev/.well-known/oauth-authorization-server)
- MCP Server Card (SEP-1649):
  https://cachely.dev/.well-known/mcp/server-card.json

The apex PRM names `https://cachely.dev` as its resource and points
`authorization_servers[0]` at `https://app.cachely.dev`, which exactly matches
the AS metadata issuer.

## MCP server - OAuth 2.1 (agent self-serve)

This is the supported path for an autonomous agent. It is standard OAuth 2.1
with dynamic client registration and PKCE - no Cachely-specific grant.

1. **Discover.** Fetch the Authorization Server Metadata above. Read `issuer`,
   `authorization_endpoint`, `token_endpoint`, `registration_endpoint`, and the
   `agent_auth` block (`register_uri`, `credential_types_supported`, and
   `registration_methods`).
2. **Register (RFC 7591).** `POST` your client metadata (including
   `redirect_uris`) to `https://app.cachely.dev/api/auth/mcp/register` to obtain
   a `client_id` (and `client_secret` for confidential clients).
3. **Authorize (authorization code + PKCE, S256).** Send the user to
   `https://app.cachely.dev/api/auth/mcp/authorize` with a `code_challenge`.
   The user signs in with Google or GitHub. You receive an authorization `code` at your
   redirect URI.
4. **Exchange.** `POST` the `code` and `code_verifier` to
   `https://app.cachely.dev/api/auth/mcp/token` to receive an
   `oauth2_access_token` (and a `refresh_token`).
5. **Call the API.** Send `Authorization: Bearer <access_token>` to
   `https://app.cachely.dev/mcp`. Refresh with the `refresh_token` when the
   access token expires.

## Remote cache API - bearer token (human-provisioned)

Agents cannot register here. A human owner creates a workspace token in the
dashboard (`https://app.cachely.dev`) and gives it to the build tool or CI.

- Send it as `Authorization: Bearer <token>`. Gradle and Bazel HTTP caches may
  send it as the HTTP Basic password instead (any username; the token is the
  password).
- The token is scoped to one workspace and is subject to that workspace's plan
  quota. Read-only tokens are recommended for developer machines and untrusted
  CI (on Bazel, pair them with `build --remote_upload_local_results=false`).

## Credential use

- Treat every token as a secret. Send it only over HTTPS in the `Authorization`
  header. Never log it, embed it in URLs, or commit it to source control.
- Prefer the shortest-lived credential that works: the OAuth access token for
  MCP (refreshable), a scoped workspace token for the cache API.

## Identity and registration methods

- Supported: OAuth 2.1 authorization code with PKCE, backed by Google or GitHub sign-in,
  via RFC 7591 dynamic client registration (MCP); human-provisioned bearer
  tokens (remote cache API).
- The agent acts as a user-authorized delegate: it obtains credentials only
  after the user approves the OAuth authorization request. Cachely advertises no
  `identity_types_supported` because the auth.md profile's canonical identity
  types (`anonymous`, `identity_assertion`, `service_auth`) do not apply.
- Not supported: ID-JAG identity assertions
  (`urn:ietf:params:oauth:token-type:id-jag`), verified-email assertions, and
  anonymous claim ceremonies. Cachely runs no `/agent/identity`, claim, or
  revocation endpoint, so those URLs are intentionally absent from metadata.
