diff --git a/DEPLOY.md b/DEPLOY.md new file mode 100644 index 0000000..725bce0 --- /dev/null +++ b/DEPLOY.md @@ -0,0 +1,70 @@ +# Deploying docs.saturday.fit + +Operator runbook for the documentation site: hostnames, DNS, rebuilds, site configuration, and where the machine-readable files come from. Mintlify serves only the pages listed in `docs.json` navigation, so nothing in this file reaches the site. This repository is public, so keep secrets out of it all the same. + +## Hostnames + +| Host | What it serves | +|------|----------------| +| `docs.saturday.fit` | The documentation site, hosted on Mintlify | +| `api.saturday.fit` | The API itself, including the MCP endpoint at `/mcp` | + +The sandbox base URL is issued with each `sk_test_` key. Requesting a docs path on `api.saturday.fit` returns the API's `404`, not a page. `GET https://api.saturday.fit/v1/` is the discovery index and its `documentation` link points at this site. + +## DNS + +| Record type | Name | Target | Proxy | +|------------|------|--------|-------| +| CNAME | `docs` | `cname.mintlify-dns.com` | DNS only (grey cloud) | + +Cloudflare proxy stays disabled on the Mintlify CNAME. Mintlify terminates SSL and needs direct DNS resolution. + +To verify a DNS change: `dig docs.saturday.fit CNAME` answers `cname.mintlify-dns.com.`, `https://docs.saturday.fit` loads the site, and Mintlify issues the certificate. + +## Deploying + +Mintlify deploys from Git: a merge to `main` rebuilds the site. A rebuild can also be triggered by hand from [dashboard.mintlify.com](https://dashboard.mintlify.com) on the Saturday API project. + +Two checks run on every pull request from `.github/workflows/`. Engine Constants (GitHub-hosted) fails the PR if a page prints an engine value. Docs Drift asks for the self-hosted runner, which does not accept jobs from a public repository, so it queues until it is cancelled: run it locally instead (README, "Local checks") and cancel the queued run. The fuel-backend copy of the same check runs on backend pull requests and catches the other direction. + +## Site configuration + +`docs.json` at the repository root configures the site, against the [Mintlify `docs.json` schema](https://mintlify.com/docs.json). + +| Setting | Value | +|---------|-------| +| Theme | `mint` | +| Primary color | `#1aabb8` (Saturday teal) | +| Light / dark accent | `#8FC5CE` / `#0e7e8a` | +| Tabs | Coaching, API Guides | +| Contextual actions | Copy, view, open in Claude, open in Cursor | +| Feedback | Thumbs rating, suggest edit, raise issue (the last two open against this public repository) | + +Moving or renaming a page needs a `redirects` entry in `docs.json` so the old URL keeps resolving. `npx mint@latest broken-links --check-anchors` catches an internal link or anchor that no longer resolves. + +## Content structure + +``` +docs/ + docs.json # Site configuration and navigation + llms.txt # Hand-curated LLM index + introduction.mdx # Landing page + access.mdx # Getting a key + quickstart.mdx + authentication.mdx + error-handling.mdx + rate-limiting.mdx + coaching/ # Coaching tab: onboarding, billing, roster, team, nutrition + guides/ # API Guides tab: core, integration, coach API, platform + snippets/ # Shared JSX components + images/ # Logos, favicon, brand marks + scripts/ # Local checks (README) +``` + +## Machine-readable files + +| URL | Source | +|-----|--------| +| `https://docs.saturday.fit/llms.txt` | `llms.txt` in this repository, hand-curated | +| `https://docs.saturday.fit/llms-full.txt` | Generated by Mintlify from the MDX corpus on every build. Never commit one; it would shadow the generator | +| `https://api.saturday.fit/mcp` | Served by the API (fuel-backend `cmd/partner-api`), not by this site | diff --git a/README.md b/README.md index 332b606..416cb51 100644 --- a/README.md +++ b/README.md @@ -17,3 +17,7 @@ npx mint@latest validate ``` The response-example check executes the published Python and TypeScript display snippets with local fixtures. It requires Python and Node.js and makes no HTTP requests. The drift check needs a current `fuel-backend` checkout; set `--backend` to its path when using worktrees. + +## Deploying + +DNS, Cloudflare, Mintlify rebuilds, and site configuration: [DEPLOY.md](DEPLOY.md). diff --git a/docs.json b/docs.json index 6961245..dbde08a 100644 --- a/docs.json +++ b/docs.json @@ -114,7 +114,7 @@ "guides/attribution", "guides/feature-gates", "guides/data-policy", - "guides/deployment" + "guides/documentation" ] } ] @@ -174,6 +174,10 @@ { "source": "/webhooks", "destination": "/guides/webhooks" + }, + { + "source": "/guides/deployment", + "destination": "/guides/documentation" } ], "navbar": { diff --git a/guides/coach-api.mdx b/guides/coach-api.mdx index 5e22d8d..eb8c640 100644 --- a/guides/coach-api.mdx +++ b/guides/coach-api.mdx @@ -38,16 +38,31 @@ OAuth2 coaches use the [connector OAuth flow](/guides/oauth2) with coach scopes ## Scopes and capabilities -The coach's token or key carries scopes that map to capabilities. A route is reachable only when the token confers the matching capability; otherwise it returns the uniform `404`. - -| Capability | OAuth scope | API-key scope | Grants | -|------------|-------------|---------------|--------| -| Read roster + rollups + sessions | `coach:roster` | `roster:read`, `roster:write`, `org:read`, `org:write` | `GET /v1/coach/roster`, `…/fueling-rollup`, `…/sessions/…` | -| Read reports + digest | `coach:reports` | `org:read`, `org:write` | `…/report`, `/v1/coach/roster/digest` | -| Write alert + report config | `coach:alerts` | `roster:write`, `org:write` | `/v1/coach/config/*` | -| Manage webhooks | `coach:webhooks` | `webhooks:manage` | `/v1/coach/webhooks/*` | - -The two vocabularies are unioned, never translated, so a key keeps exactly the reach its scopes confer. `roster:read` alone does not open the report routes; pick `org:read` or higher when a key needs reports. Keys minted before scoped keys existed carry a single `*` scope and hold all four capabilities. +A coach token or key carries scopes, and each scope confers one or more of four capabilities. A route is reachable only when the credential confers the capability it requires; otherwise it returns the uniform `404`. + +| Capability | OAuth scope | Endpoints | +|------------|-------------|-----------| +| Read roster | `coach:roster` | `GET /v1/coach/roster`, `GET /v1/coach/athletes/{athlete_uid}/fueling-rollup`, `GET /v1/coach/athletes/{athlete_uid}/sessions/{activity_id}` | +| Read reports | `coach:reports` | `GET /v1/coach/roster/digest`, `GET /v1/coach/athletes/{athlete_uid}/report` | +| Configure alerts and reports | `coach:alerts` | `GET` and `PUT /v1/coach/config/notification-rules`, `POST /v1/coach/config/preset`, `GET` and `PUT /v1/coach/config/report-settings` | +| Manage webhooks | `coach:webhooks` | `GET` and `POST /v1/coach/webhooks`, `DELETE /v1/coach/webhooks/{id}`, `POST /v1/coach/webhooks/{id}/disable`, `POST /v1/coach/webhooks/{id}/enable` | + +Reading config takes the same capability as writing it: a credential without it gets `404` from `GET /v1/coach/config/notification-rules` as well as from `PUT`. + +An API key's scopes, chosen when the key is minted in the portal, map onto the same four capabilities: + +| API-key scope | Read roster | Read reports | Configure alerts and reports | Manage webhooks | +|---------------|-------------|--------------|------------------------------|-----------------| +| `roster:read` | Yes | | | | +| `roster:write` | Yes | | Yes | | +| `reports:read` | | Yes | | | +| `org:read` | Yes | Yes | | | +| `org:write` | Yes | Yes | Yes | | +| `org:admin` | Yes | Yes | Yes | Yes | +| `webhooks:manage` | | | | Yes | +| `*` (keys minted before scoped keys existed) | Yes | Yes | Yes | Yes | + +Scopes union: a key with several scopes holds every capability any of them confers, and nothing more. `roster:write` also reads the roster, since configuring alerts against a roster means seeing it. `roster:read` alone does not open the report routes; add `reports:read`, or pick `org:read` or higher. **Roster confinement.** Every `{athlete_uid}` you pass is checked against your roster. An athlete who isn't on your roster, and an athlete who doesn't exist, both return `404 resource_not_found`. The two cases are indistinguishable, so the API never reveals whether an athlete exists. diff --git a/guides/deployment.mdx b/guides/deployment.mdx deleted file mode 100644 index db99bca..0000000 --- a/guides/deployment.mdx +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: 'Deployment & Configuration' -description: 'Where the docs and the API live, and the machine-readable endpoints for AI agents' -sidebarTitle: 'Deployment' -icon: 'globe' ---- - -# Deployment & Configuration - -The API and its documentation are served from two hostnames. This page says which is which, and lists the machine-readable endpoints an agent can fetch. - -## The two hostnames - -| Host | What it serves | -|------|----------------| -| `docs.saturday.fit` | This documentation site, hosted on Mintlify | -| `api.saturday.fit` | The API itself, including the MCP endpoint | - -The sandbox base URL is issued with each `sk_test_` key; see [Authentication](/authentication#environments). Requesting a docs path on `api.saturday.fit` returns the API's `404`, not a page. `GET https://api.saturday.fit/v1/` returns a discovery document whose `documentation` link points back here. - -### DNS - -| Record type | Name | Target | Proxy | -|------------|------|--------|-------| -| CNAME | `docs` | `cname.mintlify-dns.com` | DNS only (no proxy) | - - - Cloudflare proxy stays **disabled** (DNS only, grey cloud) on the Mintlify CNAME. Mintlify terminates SSL and needs direct DNS resolution. - - -To verify a DNS change: `dig docs.saturday.fit CNAME` should answer `cname.mintlify-dns.com.`, `https://docs.saturday.fit` should load this site, and Mintlify issues the certificate. - -## Deploying documentation updates - -Mintlify deploys from Git. Push to the `docs` repository's default branch and the site rebuilds. - -A rebuild can also be triggered by hand from [dashboard.mintlify.com](https://dashboard.mintlify.com) on the Saturday API project. - -## Machine-readable endpoints - -### llms.txt - -``` -https://docs.saturday.fit/llms.txt -``` - -A short index of the API: what Saturday does, how authentication works, the core endpoints, the safety model, and a link to the full documentation. Follows the [llms.txt standard](https://llmstxt.org/). It is hand-curated in the docs repository. - -### llms-full.txt - -``` -https://docs.saturday.fit/llms-full.txt -``` - -The whole documentation corpus as one text file, for loading into an LLM context window. Mintlify generates it from the MDX sources on every build, so it is never edited or committed by hand. - -### MCP server - -``` -https://api.saturday.fit/mcp -``` - -The Model Context Protocol endpoint. It accepts `POST` only; a `GET` answers `405`. See [MCP Integration](/guides/mcp-integration) for setup, and the [Claude Connector](/guides/coach-connector) for the hosted connector. - -## Site configuration - -The site is configured by `docs.json` at the root of the docs repository, against the [Mintlify `docs.json` schema](https://mintlify.com/docs.json). - -| Setting | Value | -|---------|-------| -| Theme | `mint` | -| Primary color | `#1aabb8` (Saturday teal) | -| Light / dark accent | `#8FC5CE` / `#0e7e8a` | -| Tabs | Coaching, API Guides | -| Contextual actions | Copy, view, open in Claude, open in Cursor | - -## Content structure - -``` -docs/ - docs.json # Site configuration and navigation - llms.txt # Hand-curated LLM index - introduction.mdx # Landing page - access.mdx # Getting a key - quickstart.mdx - authentication.mdx - error-handling.mdx - rate-limiting.mdx - coaching/ # Coaching tab: onboarding, billing, roster, team, nutrition - guides/ # API Guides tab: core, integration, coach API, platform - snippets/ # Shared JSX components - images/ # Logos, favicon, brand marks -``` - -## Incidents - -Report an outage or incident to [api@saturday.fit](mailto:api@saturday.fit). diff --git a/guides/documentation.mdx b/guides/documentation.mdx new file mode 100644 index 0000000..b972c05 --- /dev/null +++ b/guides/documentation.mdx @@ -0,0 +1,10 @@ +--- +title: 'About This Documentation' +description: 'Where these docs live, what they describe, and how to report an error in them' +sidebarTitle: 'About the Docs' +icon: 'book' +--- + +# About This Documentation + +These pages are published at `docs.saturday.fit` from the public [SaturdayInc/docs](https://github.com/SaturdayInc/docs) repository. They describe the current `/v1` API at `https://api.saturday.fit`, and the API's discovery document at `GET https://api.saturday.fit/v1/` links back here. Agents can read the same content as [llms.txt and llms-full.txt](/guides/mcp-integration#llm-discoverability); the MCP endpoint is covered in [MCP Integration](/guides/mcp-integration). To report an error in the documentation, [open an issue](https://github.com/SaturdayInc/docs/issues/new) or write to [api@saturday.fit](mailto:api@saturday.fit). API outages and incidents go to the same address.