diff --git a/.agents/skills/ask-the-docs/SKILL.md b/.agents/skills/ask-the-docs/SKILL.md index f7ed9c49fa4b1..3f87e86fefca9 100644 --- a/.agents/skills/ask-the-docs/SKILL.md +++ b/.agents/skills/ask-the-docs/SKILL.md @@ -125,7 +125,10 @@ write it down. - [`pm-the-docs`](../pm-the-docs/SKILL.md) — audience, stage, and cross-cutting scope calls (Frame stage of the "Write the docs" checklist, - mirrored in `pm-the-docs`'s reference file). + mirrored in `pm-the-docs`'s reference file). Cross-repo **product** lookup + (universe) lives there, not in this skill. +- [`test-the-docs`](../test-the-docs/SKILL.md) — execute docs snippets against a + Docker-isolated local stack; verification report. - [`work-linear-issue`](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/work-linear-issue/SKILL.md) — implementing assigned DOCS-\* tickets. - [`review-the-docs`](../review-the-docs/SKILL.md) — reviewing open docs diff --git a/.agents/skills/ask-the-docs/reference/federated-docs.md b/.agents/skills/ask-the-docs/reference/federated-docs.md index 07c4c993083b4..988a8922d4e68 100644 --- a/.agents/skills/ask-the-docs/reference/federated-docs.md +++ b/.agents/skills/ask-the-docs/reference/federated-docs.md @@ -93,17 +93,17 @@ flowchart TB ## Federated sources (inventory) -| Local path | Source repo | Ref / branch | Pattern | -| ---------------------------------------- | -------------------------------------- | ------------------------------ | ------------------------------------------------- | -| `/guides/graphql/*` | `supabase/pg_graphql` | `master` | Fully federated; `pageMap` per page | -| `/guides/ai/python/*` | `supabase/vecs` | `main` | Fully federated | -| `/guides/deployment/ci/*` | `supabase/setup-cli` | `gh-pages` | Fully federated | -| `/guides/deployment/terraform/*` | `supabase/terraform-provider-supabase` | branch in `terraformConstants` | Federated prose pages | -| `/guides/deployment/terraform/reference` | same | same | Federated **JSON schema** (not MDX) | -| `/guides/database/extensions/wrappers/*` | `supabase/wrappers` | **release tag** `docs_v*.*.*` | **Hybrid** — local MDX + federated catalog | -| `/guides/database/database-advisors` | `supabase/splinter` | `main` | **Dynamic listing** — all `docs/*.md` files | -| AI Skills index | `supabase/agent-skills` | `main` | Lists `skills/*/SKILL.md` at runtime | -| `$CodeSample` directive | various | commit SHA only | Snippets via `getGitHubFileContentsImmutableOnly` | +| Local path | Source repo | Ref / branch | Pattern | +| ------------------------------------------- | -------------------------------------- | ------------------------------ | ------------------------------------------------- | +| `/guides/graphql/*` | `supabase/pg_graphql` | `master` | Fully federated; `pageMap` per page | +| `/guides/ai/python/*` | `supabase/vecs` | `main` | Fully federated | +| `/guides/deployment/ci/*` | `supabase/setup-cli` | `gh-pages` | Fully federated | +| `/guides/deployment/terraform/*` | `supabase/terraform-provider-supabase` | branch in `terraformConstants` | Federated prose pages | +| `/guides/deployment/terraform/reference` | same | same | Federated **JSON schema** (not MDX) | +| `/guides/database/extensions/wrappers/*` | `supabase/wrappers` | **release tag** `docs_v*.*.*` | **Hybrid** — local MDX + federated catalog | +| `/guides/monitoring-and-debugging/advisors` | `supabase/splinter` | `main` | **Dynamic listing** — all `docs/*.md` files | +| AI Skills index | `supabase/agent-skills` | `main` | Lists `skills/*/SKILL.md` at runtime | +| `$CodeSample` directive | various | commit SHA only | Snippets via `getGitHubFileContentsImmutableOnly` | ### Related patterns (not quite "federated docs") diff --git a/.agents/skills/pm-the-docs/SKILL.md b/.agents/skills/pm-the-docs/SKILL.md index 3d3d2a4867b20..d17a30cab7093 100644 --- a/.agents/skills/pm-the-docs/SKILL.md +++ b/.agents/skills/pm-the-docs/SKILL.md @@ -3,10 +3,12 @@ name: pm-the-docs description: >- Docs-PM decision support for the "Write the docs" authoring process — makes audience, stage, and cross-cutting scope calls during the Frame - and Shape stages, and helps decide when a docs question needs to - self-serve vs. escalate to a docs PM. Use when framing a new docs page - or launch, deciding what product stage or audience a feature targets, - or judging whether a docs question needs PM sign-off. + and Shape stages (including cross-repo product lookup via universe when + accessible, else the public OSS path), and helps decide when a docs + question needs to self-serve vs. escalate to a docs PM. Use when framing + a new docs page or launch, deciding what product stage or audience a + feature targets, judging whether a docs question needs PM sign-off, or + confirming which product repos a launch spans. --- # PM the docs @@ -17,17 +19,26 @@ Backs the Frame and Shape stages of the "Write the docs" checklist (mirrored in - Starting a new docs page or launch and need to state the product stage, audience, and "why" before drafting (Frame). - Deciding content type, IA placement, or prerequisites for a page (Shape). +- Judging whether a launch spans multiple product repos (CLI, Auth, migrations, platform, …) — see [reference/universe-lookup.md](reference/universe-lookup.md). - Unsure whether a docs question is self-serve or needs a docs PM's sign-off. -**Not for** drafting content itself (see [`write-the-docs`](../write-the-docs/SKILL.md)), restructuring existing pages (see [`edit-the-docs`](../edit-the-docs/SKILL.md)), or docs-app architecture/IA placement mechanics (see [`ask-the-docs`](../ask-the-docs/SKILL.md)). +**Not for** drafting content itself (see [`write-the-docs`](../write-the-docs/SKILL.md)), restructuring existing pages (see [`edit-the-docs`](../edit-the-docs/SKILL.md)), running snippets (see [`test-the-docs`](../test-the-docs/SKILL.md)), or docs-app architecture/IA placement mechanics (see [`ask-the-docs`](../ask-the-docs/SKILL.md)). + +## Reference files + +| File | What's inside | +| ------------------------------------------------------------------------------ | -------------------------------------------------------------------------- | +| [reference/write-the-docs-checklist.md](reference/write-the-docs-checklist.md) | Six-stage authoring checklist mirror | +| [reference/universe-lookup.md](reference/universe-lookup.md) | Cross-repo product lookup: capability gate, universe accelerator, OSS path | ## Answering a scope/stage/audience question 1. Read the relevant stage in [reference/write-the-docs-checklist.md](reference/write-the-docs-checklist.md) — its checkboxes state exactly what needs deciding. 2. Read whatever context exists for the feature: the linked issue/project, the PRD, the shipped code or PR. When code and PRD disagree, the code wins for behavior claims. -3. Answer the checklist's questions directly: product stage, audience and job-to-be-done, the one-line "why," content type, IA placement, prerequisites. -4. Distinguish **confirmed fact** (stated in the ticket/PRD/code) from **inference** (your best read) — flag inference explicitly rather than presenting it as settled. -5. If a decision is genuinely open at the org level (not a docs authoring call), say so and name who should decide instead of inventing an answer to look complete. +3. When scope may span services (CLI, Auth, migrations, Dashboard, platform, …), follow [reference/universe-lookup.md](reference/universe-lookup.md) **capability gate** before settling Frame/Shape; use universe only if accessible, otherwise the OSS path. Record which repos you searched. +4. Answer the checklist's questions directly: product stage, audience and job-to-be-done, the one-line "why," content type, IA placement, prerequisites. +5. Distinguish **confirmed fact** (stated in the ticket/PRD/code) from **inference** (your best read) — flag inference explicitly rather than presenting it as settled. +6. If a decision is genuinely open at the org level (not a docs authoring call), say so and name who should decide instead of inventing an answer to look complete. ## Self-serve vs. escalate @@ -37,7 +48,8 @@ Escalate to your docs team's PM when scope or stage is unclear, you need a revie ## Related skills -- [`ask-the-docs`](../ask-the-docs/SKILL.md) — IA placement and docs-app architecture (Shape stage) +- [`ask-the-docs`](../ask-the-docs/SKILL.md) — IA placement and docs-app architecture (Shape stage). Cross-repo **product** lookup lives here in `universe-lookup.md`, not in `ask-the-docs`. - [`write-the-docs`](../write-the-docs/SKILL.md) — drafting once Frame/Shape are settled +- [`test-the-docs`](../test-the-docs/SKILL.md) — run snippets against a Docker-isolated local stack; verification report - [`edit-the-docs`](../edit-the-docs/SKILL.md) — restructure and improve existing pages - [`review-the-docs`](../review-the-docs/SKILL.md) — self-review and PR review stages diff --git a/.agents/skills/pm-the-docs/reference/universe-lookup.md b/.agents/skills/pm-the-docs/reference/universe-lookup.md new file mode 100644 index 0000000000000..0ee205b50eb07 --- /dev/null +++ b/.agents/skills/pm-the-docs/reference/universe-lookup.md @@ -0,0 +1,96 @@ +# Cross-repo product lookup + +Cross-repo product search for Frame/Shape when a feature may span services. Use during `/pm-the-docs`, not `/ask-the-docs` (`ask-the-docs` stays on `apps/docs` architecture). + +**Cross-repo confirmation is required for everyone.** [`supabase/universe`](https://github.com/supabase/universe) is an optional accelerator when you have Supabase org access to that private meta-repo (and ideally a local clone). Contributors without that access use the OSS path below — that is a successful outcome, not a failure. + +## Capability gate + +Run this gate before any universe clone or submodule command. + +```mermaid +flowchart TD + start[Cross-repo grounding needed] + clone{"Local universe root exists?"} + ghApi{"gh api repos/supabase/universe succeeds?"} + useUniverse[Use universe clone + rg in repos/] + ossPath[OSS path: public gh search + linked product repos] + start --> clone + clone -->|yes| useUniverse + clone -->|no| ghApi + ghApi -->|yes Supabase org access| useUniverse + ghApi -->|no 404/403| ossPath +``` + +### 1. Local clone? + +Resolve the universe root in order (do not hardcode machine-specific absolute paths in committed files): + +1. `$SUPABASE_UNIVERSE_ROOT` (if set) +2. `$HOME/GitHub/supabase/universe` + +```bash +UNIVERSE_ROOT="${SUPABASE_UNIVERSE_ROOT:-$HOME/GitHub/supabase/universe}" +[[ -d "$UNIVERSE_ROOT/.git" || -f "$UNIVERSE_ROOT/.git" ]] && echo "local universe ok" +``` + +If that checkout exists → **accelerator path** (skip the `gh api` probe). + +### 2. Else probe org access (read-only, no clone) + +```bash +gh api repos/supabase/universe -q .full_name +``` + +| Result | Next step | +| ------ | --------- | +| Success (`supabase/universe`) | Accelerator path: you **may** clone with `--recurse-submodules` (or ask the user to), then search | +| 404, 403, or other failure | **OSS path only** — do **not** run `git clone` or `git submodule update` against universe | + +## OSS path (always valid) + +When the gate says universe is unavailable: + +- Search public code: `gh search code --owner supabase ''` (plus other public owners named in the ticket) +- Read any product repo already checked out or linked from Linear / the PR +- Prefer `supabase/supabase` in-tree sources when that is enough +- In the Frame/Shape summary, record `universe: unavailable (OSS)` and list the public sources used + +Never treat missing universe access as a blocker or an incomplete Frame/Shape. + +## Accelerator: universe (when accessible) + +Prefer an existing local clone. Only init or update submodules after the gate succeeds: + +```bash +cd "$UNIVERSE_ROOT" +git submodule update --init --recursive +``` + +Private submodules (`platform`, `branching`) may need a PAT. If those fail, note the gap and continue with public submodules plus the OSS search path. + +### Where to look + +Start from the universe README "Finding your way around" table, then `rg` inside the relevant submodule: + +| Looking for… | Start in | +| ------------ | -------- | +| Schema, extensions, RLS | `repos/postgres/`, `repos/postgrest/`, `repos/pg-toolbelt/` | +| Auth flows | `repos/auth/`, `auth-js` under `repos/supabase-js/` | +| Realtime / Storage / Edge Functions | `repos/realtime/`, `repos/storage/`, `repos/edge-runtime/` | +| Dashboard / Studio | `repos/supabase/apps/studio` | +| Management API / hosted infra | `repos/platform/` (private) | +| CLI, local dev, `config.toml` | `repos/cli/` | +| Docs & self-hosting Compose | `repos/supabase/` (`apps/docs`, `docker/`) | + +When scope is unknown, search initialized `repos/**` with a tight pattern rather than reading entire trees. + +## How to use in Frame / Shape + +1. Name the product surfaces the launch might touch (CLI, Auth, migrations, Dashboard, …). +2. Run the **capability gate**. +3. Resolve surfaces to repos (universe submodules **or** public search / linked checkouts). +4. Confirm with a short search whether behavior lives in one repo or several. +5. Record in the Frame/Shape summary: gate result (`universe: available` or `universe: unavailable (OSS)`), repos consulted, cross-cutting vs single-repo, and any gaps. + +Always distinguish confirmed fact from inference. diff --git a/.agents/skills/pm-the-docs/reference/write-the-docs-checklist.md b/.agents/skills/pm-the-docs/reference/write-the-docs-checklist.md index 5bffc867c62be..afe39dc5a9dfd 100644 --- a/.agents/skills/pm-the-docs/reference/write-the-docs-checklist.md +++ b/.agents/skills/pm-the-docs/reference/write-the-docs-checklist.md @@ -1,61 +1,71 @@ # Write the docs -> Mirrors Supabase's proposed "Write the docs" process as of 2026-08-10. Process specifics may still evolve. - A practical six-stage checklist and quality standard for planning, drafting, and reviewing product documentation. +**P** = Product +**E** = Engineering +**Docs** = Docs team + +## Authoring + +Six short stages. Keep it lightweight; the point is to make good docs the default, not to add ceremony. + +_Self-serve first ([agent skills](../../../../apps/docs/CONTRIBUTING.md#ai-agent-skills-for-docs-authoring)), ask your docs team's PM as needed._ + ## What good looks like - The **why** is explicit: a reader learns what problem this solves and when to reach for it, not only the steps. -- The **content type is deliberate** and consistent within the page. +- The content **type is deliberate** and consistent within the page. - **Audience and prerequisites** are stated up front. -- At least one **example is runnable and has been run** (commands, code, expected result). -- **Correct stage** is stated; limitations are named honestly. +- **Examples are runnable and have been tested** (commands, code, expected result) — verify with `/test-the-docs` against a Docker-isolated local stack, not production. +- **Correct stage** like GA is stated; limitations are named honestly. - The page **lives in the right place** in the IA and links to and from related pages. -- Terminology and formatting match existing docs (defer to the style guide once one lands). +- Terminology and formatting match existing docs (and style guide once it lands). -## 1. Frame +### 1. Frame -_Skills:_ `ask-the-docs` to see how the surface works today; `pm-the-docs` for audience, stage, and cross-cutting scope calls. +_Skills:_ `/ask-the-docs` for how the docs surface works today; `/pm-the-docs` for audience, stage, and cross-cutting scope (cross-repo span via universe when accessible — see [universe-lookup.md](universe-lookup.md)). - [ ] P: State the product stage (private/public alpha, beta, GA) - [ ] P: Name the audience and the job they are trying to do - [ ] P: Write one line on _why_ the feature exists (the problem it solves), not only what it does -## 2. Shape +### 2. Shape -_Skill:_ `ask-the-docs` for IA placement, architecture, and where content lives. +_Skill:_ `/ask-the-docs` for IA placement, architecture, and where content lives. - [ ] P: Pick the content type(s): tutorial (learning), how-to (a task), reference (lookup), explanation (the why). Do not mix types on one page (refer to [Diátaxis](https://diataxis.fr/)) - [ ] P: Decide where the page lives in the existing IA and what links in and out (avoid orphan pages) - [ ] P: List prerequisites and assumed knowledge up front -## 3. Draft +### 3. Draft -_Skill:_ `write-the-docs` to draft net-new content grounded in Linear and the code. +_Skill:_ `/write-the-docs` to draft net-new content grounded in Linear and the code (`/pm-the-docs` → universe when accessible, else public search / named product repos). - [ ] P: Lead with the why and the outcome, then the how/what (product story first) -- [ ] P: Include at least one runnable, copy-pasteable example that you have actually run +- [ ] P: Include at least one runnable, copy-pasteable example that you have actually run (or will run in Self-review via `/test-the-docs`) +- [ ] P/E: Cross-repo behavior confirmed via universe when accessible, else public `gh search` / named product repos when the feature is not confined to `supabase/supabase` (lookup via `/pm-the-docs`, not `/ask-the-docs`) - [ ] E: Contribute technical depth and verify accuracy (APIs, limits, edge cases) - [ ] P: Call out the current stage inline and any known limitations -When the work is improving an existing page (restructure, reorder, connective text, brevity) rather than authoring net-new content, use `edit-the-docs` instead of `write-the-docs`. +When the work is improving an existing page (restructure, reorder, connective text, brevity) rather than authoring net-new content, use `/edit-the-docs` instead of `/write-the-docs`. -## 4. Self-review against the bar +### 4. Self-review against the bar -_Skill:_ `review-the-docs` — [Local self-review](../../review-the-docs/SKILL.md#local-self-review-no-open-pr) on your own branch before opening the PR. +_Skills:_ `/review-the-docs` for [local self-review](../../review-the-docs/SKILL.md#local-self-review-no-open-pr) before opening the PR; `/test-the-docs` to run snippets and produce a verification report. - [ ] P/E: Check the draft against "What good looks like" above before opening the PR -- [ ] P/E: Follow authoring-experience standards and tooling when available +- [ ] P/E: `/test-the-docs` run; verification report ready for the PR body +- [ ] P/E: Follow Authoring Experience standards and tooling when available -## 5. PR review +### 5. PR review -_Skill:_ `review-the-docs` to triage, classify, verify the build, and report. +_Skill:_ `/review-the-docs` to triage, classify, verify the build, and report. - [ ] P/E: Open the PR and request review per the rules of engagement - [ ] Docs: Review against the published bar -## 6. Keep it honest +### 6. Keep it honest - [ ] P: Keep the product launch checklist's "start on day 1" docs gate honest through ship (update as stage or behavior changes) @@ -63,17 +73,12 @@ _Skill:_ `review-the-docs` to triage, classify, verify the build, and report. **Self-serve when:** the checklist above is clear, standards exist, and you know the product stage and audience. -**Ask when:** scope or stage is unclear, you need a review path, the bar is ambiguous, or the launch docs touch cross-cutting surfaces (quickstarts, API keys, tutorials, onboarding, platform concepts). +**Ask when:** scope or stage is unclear, you need a review path, the bar is ambiguous, or the launch docs touch cross-cutting surfaces (quick starts, API keys, tutorials, onboarding, platform concepts). -**What to expect:** the docs PM is the point of contact for questions and review against the bar. +**What to expect:** the docs PM is the point of contact for questions, skills enablement, and review against the bar. **Where to ping:** your team's PR-review channel and current docs PM — check your contributor guide for who that is today. -## Reference - -Role prefixes: +## Resources -- **P** = Product. The product lead / area PM who writes the docs. -- **E** = Engineering. Contributes technical depth and verifies accuracy. -- **P/E** = Product and Engineering together. -- **Docs** = Docs team, the reviewer. +Skills for this checklist: [AI agent skills for docs authoring](../../../../apps/docs/CONTRIBUTING.md#ai-agent-skills-for-docs-authoring) (`/pm-the-docs`, `/ask-the-docs`, `/write-the-docs`, `/edit-the-docs`, `/test-the-docs`, `/review-the-docs`). diff --git a/.agents/skills/review-the-docs/SKILL.md b/.agents/skills/review-the-docs/SKILL.md index 2b42ac33c50ce..0316e3fc613f2 100644 --- a/.agents/skills/review-the-docs/SKILL.md +++ b/.agents/skills/review-the-docs/SKILL.md @@ -69,7 +69,8 @@ pnpm build:reference-markdown # when reference pipeline changed ``` 4. Spot-check frontmatter, internal links, and nav wiring for content changes. -5. Write a short **self-review note** (blockers vs nits) suitable to paste into the future PR body under a "Self-review" heading. +5. **Offer runnable verification** — for content/tutorial PRs with new or changed procedural fenced blocks, ask whether to run [`test-the-docs`](../test-the-docs/SKILL.md). Prerequisites are class-specific (Docker Compose stack profile for DB/API; examples profile for `example-app`). If accepted, include the verification report; if declined or a required prerequisite for that class is missing, record credible `deferred` reasons for those artifacts only. Do not reimplement sandbox execution here. +6. Write a short **self-review note** (blockers vs nits) suitable to paste into the future PR body under a "Self-review" heading. Then open the PR and continue with open-PR review if a second pass is needed. @@ -216,6 +217,7 @@ Checklist: - [ ] `$CodeSample` paths match existing example directories - [ ] Admonitions, tabs, and partial includes render sensibly in PR preview - [ ] No accidental whitespace-only or empty sections where components were removed +- [ ] Offered [`test-the-docs`](../test-the-docs/SKILL.md) for new/changed procedural snippets; verification report present or credible `deferred` reasons recorded Compare PR preview URL (from Vercel/deployment comment) against production for visual regressions when layout components are involved. @@ -239,6 +241,7 @@ Checklist: - [ ] MDX steps match example code after `pnpm codegen:examples` (if `$CodeSample` used) - [ ] Env var names and Supabase client setup match current `@supabase/ssr` patterns - [ ] Example pins catalog versions — no `"latest"` for in-repo packages +- [ ] Offered [`test-the-docs`](../test-the-docs/SKILL.md) for procedural tutorial steps (or `deferred` with reason) - [ ] **Platform E2E** (when auth involved): SQL migration applied, auth flow walked, profiles verified — see `work-linear-issue` Phase 3 --- diff --git a/.agents/skills/test-the-docs/SKILL.md b/.agents/skills/test-the-docs/SKILL.md new file mode 100644 index 0000000000000..1261958ff9576 --- /dev/null +++ b/.agents/skills/test-the-docs/SKILL.md @@ -0,0 +1,96 @@ +--- +name: test-the-docs +description: >- + Execute runnable docs snippets and examples inside a disposable Docker Compose + sandbox (runner container + local Supabase stack via `supabase start`). Use + after Draft or during Self-review when asked to test the docs, fact-check + CLI/SQL/code samples, or produce a verification report for a docs PR. + Complements review-the-docs lint/build checks; does not replace them. +--- + +# Test the docs + +Runs procedural docs content **inside disposable containers**, not on the host shell and not against production. Produces a verification report for the PR body / self-review note. + +For lint, markdown rebuilds, example-app triage, and PR review, use [`review-the-docs`](../review-the-docs/SKILL.md). For Frame/Shape and cross-repo product lookup, use [`pm-the-docs`](../pm-the-docs/SKILL.md). + +## When to invoke + +- After Draft, before or during Self-review (checklist Stage 4). +- Standalone: "test the docs", "fact-check these snippets", "run the examples". +- Content or tutorial PRs that add or change procedural fenced blocks. + +**Not for:** generated reference pages, docs-app architecture questions, or hosted/production projects. + +## Core rules + +1. **Never run against production.** Local stack or temp dir only. +2. **Never run MDX fences on the host shell.** Use the Compose sandbox — see [reference/sandbox-setup.md](reference/sandbox-setup.md) and [`sandbox/run.sh`](sandbox/run.sh). +3. **Proportional:** Tier A (one end-to-end path) is required; Tier B spot-checks new/changed procedural blocks, not every fence on every page. +4. **Product bugs** found while testing get linked or filed separately; fix docs only when the docs are wrong. + +## Phases + +### 1. Scope + +From explicit MDX paths, or: + +```bash +git diff --name-only master...HEAD -- 'apps/docs/content/**' +``` + +Skip generated reference output under `features/docs/generated/`. + +### 2. Extract + +List runnable artifacts from changed MDX: + +- Fenced blocks: `bash`, `sh`, `sql`, `javascript`, `typescript`, `tsx`, `jsx` +- `$CodeSample` paths → treat as `example-app` (build under `examples/`) +- Skip: `mermaid`, incomplete illustrative fragments, partial-only includes + +### 3. Classify + +Assign each artifact a class per [reference/snippet-classes.md](reference/snippet-classes.md): + +| Class | Action | +| --------------------- | ---------------------------------------------- | +| `runnable-local` | Run in temp stack / temp dir | +| `runnable-with-setup` | Run after documented setup (migrations, seed) | +| `example-app` | `npm install && npm run build` in `examples/…` | +| `illustrative-only` | No run required | +| `deferred` | Record reason; do not silently skip | + +### 4. Sandbox setup + +Follow [reference/sandbox-setup.md](reference/sandbox-setup.md) and drive lifecycle with [`sandbox/run.sh`](sandbox/run.sh): + +1. Refuse if the **host** is running as root. +2. Require `docker` + `docker info` + `docker compose` on the host for any in-container run. +3. Gate profiles **per artifact class**: + - `runnable-local` / `runnable-with-setup` that need DB/API: `./sandbox/run.sh up-stack` (DinD + runner → `supabase init` / `supabase start` in `/work`). + - CLI-only blocks with no DB: still use a runner profile so fences stay off-host; skip `supabase start` when unused. + - `example-app`: `TTD_EXAMPLE_DIR=/examples/ ./sandbox/run.sh up-examples` (Node in runner; **no** DinD). Do **not** defer solely because the host lacks a global Supabase CLI. +4. Always `./sandbox/run.sh down` when finished (cleanup trap on the host session). +5. Capture connection **URLs only** inside the runner; never paste credential fields into notes or logs. + +If a **required** prerequisite for that artifact is unavailable, mark that artifact `deferred` with the specific reason — never silent skip, and do not defer unrelated classes. + +### 5. Execute + +- **Tier A:** one copy-pasteable end-to-end path from the page. +- **Tier B:** each new/changed block classified `runnable-*` **or** `example-app` (build and record the result). +- Run every fence via `./sandbox/run.sh exec` or `exec-timeout` (never a bare host shell). +- Bound every artifact: default **60s** for shell / SQL / JS / TypeScript / `tsx` / `jsx`; allow longer for `example-app` install/build (e.g. **5m**). On timeout, kill the process **group** inside the runner, then record `fail` or `deferred` with reason. +- `curl` / `wget` only to filtered stack URLs (or page-documented local endpoints). `npm` / `npx` / `node` only for mounted `example-app` builds. +- Capture exit code, stdout/stderr (redact secrets), and observed vs expected behavior. + +### 6. Report + +Write a verification report per [reference/verification-report.md](reference/verification-report.md) for the PR body / self-review note. + +## Related skills + +- [`write-the-docs`](../write-the-docs/SKILL.md) — Draft; hands off here before PR +- [`review-the-docs`](../review-the-docs/SKILL.md) — lint/build/classify; consumes verification report +- [`pm-the-docs`](../pm-the-docs/SKILL.md) — Frame/Shape; universe for cross-repo product lookup diff --git a/.agents/skills/test-the-docs/reference/sandbox-setup.md b/.agents/skills/test-the-docs/reference/sandbox-setup.md new file mode 100644 index 0000000000000..647d9840076c2 --- /dev/null +++ b/.agents/skills/test-the-docs/reference/sandbox-setup.md @@ -0,0 +1,83 @@ +# Sandbox setup + +Containerized local execution for `/test-the-docs`. The **host** only starts Docker Compose and tears it down. Every MDX fence (shell, SQL, JS/TS, example-app builds) runs **inside** the disposable `runner` container — never as a host shell. + +Assets live in [`../sandbox/`](../sandbox/): `compose.yaml`, `Dockerfile`, `run.sh`. + +## Threat model and guardrails + +| Layer | What it does | +| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Host | `docker compose` lifecycle only (`run.sh up-*` / `down`). No fence execution. | +| Runner container | Executes fences as non-root `runner` (uid 1001). No `$HOME` mount. Work dir is `/work`; optional read-only `/examples`. | +| DinD (`stack` profile) | Privileged `docker:dind` runs an isolated Docker daemon. `supabase start` creates stack containers **inside DinD**. The runner shares DinD’s network namespace (`network_mode: service:dind`) so `127.0.0.1` healthchecks and client URLs work. Residual risk: privileged DinD; mitigate with ephemeral project names and `run.sh down`. | +| Examples profile | No DinD and no docker.sock — Node-only builds. | + +This skill is for docs authors and reviewers verifying intended content. It is not unattended CI over arbitrary hostile input. + +Guardrails: + +- **Fences in-container only.** Never run MDX fences on the host shell. Use `./sandbox/run.sh exec` or `exec-timeout`. +- **Local stack only.** Reject snippets that target hosted or production Supabase projects. +- **No secrets in notes.** Never paste `PUBLISHABLE_KEY`, `SECRET_KEY`, `JWT_SECRET`, `ANON_KEY`, `SERVICE_ROLE_KEY`, `S3_PROTOCOL_ACCESS_KEY_ID`, `S3_PROTOCOL_ACCESS_KEY_SECRET`, or other keys into the verification report, PR body, or chat logs. Capture **URLs only** from `supabase status -o env`. +- **`curl` / `wget`.** Only to URLs from the filtered status capture (`API_URL`, `DB_URL`, `DATABASE_URL`), or to local endpoints the page under test documents. Mark other targets `deferred`. +- **`npm` / `npx` / `node`.** Only for `example-app` artifacts. Mount the app read-only at `/examples`, copy into `/work/example`, then `npm install && npm run build` (or the page’s documented build). Arbitrary `node -e`, remote `npx`, or Node from unrelated bash fences → `deferred`. +- **Prefer page commands.** Run documented steps from the MDX under test. +- **Fail closed** when Docker/Compose prerequisites for that artifact class are missing (see skill Phase 4). + +## Host prerequisites (fail closed) + +```bash +if [[ "$(id -u)" = "0" ]]; then + echo "error: refuse to run as root" >&2 + exit 1 +fi +command -v docker >/dev/null || { echo "error: docker not found" >&2; exit 1; } +docker info >/dev/null 2>&1 || { echo "error: Docker is not running" >&2; exit 1; } +docker compose version >/dev/null || { echo "error: docker compose not available" >&2; exit 1; } +``` + +The host does **not** need a global `supabase` CLI or Node for stack/example runs; those tools live in the runner image. If Docker/Compose is unavailable, mark artifacts that need the runner `deferred`. + +`run.sh` creates temp work/output dirs world-writable (`chmod 0777`) so the non-root runner (`uid 1001`) can write into the host bind mounts. + +## Lifecycle (`run.sh`) + +From `.agents/skills/test-the-docs/sandbox/`: + +```bash +# Optional: pin dirs / project name for the session +eval "$(./run.sh env)" + +# Stack profile: DinD + runner → supabase init/start inside /work +./run.sh up-stack + +# Capture URLs only inside the runner (never log credential fields) +./run.sh exec -- bash -lc ' + eval "$(supabase status -o env | grep -E "^(API_URL|DB_URL|DATABASE_URL)=")" + echo "API_URL is set (value omitted from logs)" +' + +# Run a fence with a deadline (process group killed on timeout) +./run.sh exec-timeout 60 -- bash -lc 'eval "$(supabase status -o env | grep -E "^(API_URL|DB_URL|DATABASE_URL)=")"; psql "$DB_URL" -c "select 1"' + +# Examples profile (no DinD): mount the app, then build +TTD_EXAMPLE_DIR=/path/to/repo/examples/auth/hono ./run.sh up-examples +./run.sh exec-timeout 300 -- bash -lc 'cd /work/example && npm install && npm run build' + +# Always tear down +./run.sh down +``` + +## Profiles + +| Profile | Services | Isolation | Use when | +| ---------- | ----------------------- | -------------------------------- | --------------------------------------------- | +| `stack` | `dind` + `runner-stack` | Privileged DinD; fences off-host | SQL, CLI, client calls against local Supabase | +| `examples` | `runner` | No Docker daemon in-sandbox | `example-app` install/build only | + +Do not start the stack unless the artifact needs it. + +## Teardown + +Always `./run.sh down` (stops `supabase` project containers when possible, `compose down -v`, removes temp work/output dirs). Leave Docker Desktop running for the next session. diff --git a/.agents/skills/test-the-docs/reference/snippet-classes.md b/.agents/skills/test-the-docs/reference/snippet-classes.md new file mode 100644 index 0000000000000..5823c9e9988ad --- /dev/null +++ b/.agents/skills/test-the-docs/reference/snippet-classes.md @@ -0,0 +1,28 @@ +# Snippet classes + +Classify each extracted artifact before running it. + +| Class | Meaning | Run? | +| --------------------- | -------------------------------------------------------------------------------- | -------------------------------------- | +| `runnable-local` | Complete CLI, SQL, or script that works against a local stack or temp dir | Yes | +| `runnable-with-setup` | Needs migrations, seed data, `.env`, or prior steps from the same page | Yes, after setup | +| `example-app` | `$CodeSample` or path under `examples/` | Build (`npm install && npm run build`) | +| `illustrative-only` | Incomplete on purpose, omits required context, or is conceptual | No | +| `deferred` | Needs production, paid feature, destructive op, or missing required prerequisite | No — record reason | + +## Safety + +- Prefer read-only SQL and non-destructive CLI flags. +- Never target a linked hosted/production project from this skill. +- Do not print secrets (service role keys, PATs) into Verification notes or logs. +- Mark incomplete copy-paste blocks `illustrative-only` rather than forcing a run that cannot succeed. +- Execute fences only inside the Compose runner per [sandbox-setup.md](sandbox-setup.md). Restrict `curl`/`wget` to filtered stack URLs; restrict `npm`/`npx`/`node` to `example-app` mounts. Mark out-of-policy fences `deferred`. + +## Language heuristics + +| Fence | Typical class | +| ------------------------------------------- | --------------------------------------------------------------------------- | +| `sql` | `runnable-local` or `runnable-with-setup` if ordered migrations | +| `bash` / `sh` | `runnable-local` if self-contained; else `deferred` / `illustrative-only` | +| `javascript` / `typescript` / `tsx` / `jsx` | Often `illustrative-only` unless a full runnable script or example-app path | +| `mermaid` | Skip (not executable) | diff --git a/.agents/skills/test-the-docs/reference/verification-report.md b/.agents/skills/test-the-docs/reference/verification-report.md new file mode 100644 index 0000000000000..0d19fd3209309 --- /dev/null +++ b/.agents/skills/test-the-docs/reference/verification-report.md @@ -0,0 +1,38 @@ +# Verification report + +Paste into the PR body or self-review note under a **Verification** heading. + +## Template + +```markdown +## Verification (`/test-the-docs`) + +| Snippet / step | Class | Sandbox | Result | Notes | +| ----------------------------- | -------------- | --------------------------------- | -------- | ------------------------ | +| e.g. `create type …` SQL | runnable-local | Compose runner + `supabase start` | pass | | +| e.g. `supabase db diff` | runnable-local | Compose runner + local stack | fail | product bug → link issue | +| e.g. paid Dashboard-only step | deferred | — | deferred | needs hosted project | + +**Tier A path:** + +**Environment:** Docker Desktop ; compose sandbox (`sandbox/run.sh`); fences in-container only +``` + +Do **not** put secrets (`JWT_SECRET`, `ANON_KEY`, `SERVICE_ROLE_KEY`, access tokens) in Notes or Environment. + +## Results + +| Result | Meaning | +| ---------- | -------------------------------------------------------------------- | +| `pass` | Command exited 0 and matched expected behavior | +| `fail` | Ran but wrong output / non-zero exit — docs wrong **or** product bug | +| `deferred` | Not run; reason required in Notes | +| `skipped` | Out of scope (`illustrative-only`) | + +## Product bugs + +If the snippet matches the code and still fails: + +1. Prefer linking an existing issue in the owning repo. +2. Otherwise note the repro in the PR and file/follow up with the product owner. +3. Do not "fix" the docs to hide a real platform bug without calling it out. diff --git a/.agents/skills/test-the-docs/sandbox/.empty/.keep b/.agents/skills/test-the-docs/sandbox/.empty/.keep new file mode 100644 index 0000000000000..9c664e38e3760 --- /dev/null +++ b/.agents/skills/test-the-docs/sandbox/.empty/.keep @@ -0,0 +1 @@ +# Keep empty bind-mount target for compose when no example is mounted. diff --git a/.agents/skills/test-the-docs/sandbox/.gitignore b/.agents/skills/test-the-docs/sandbox/.gitignore new file mode 100644 index 0000000000000..6d9a510bfea4d --- /dev/null +++ b/.agents/skills/test-the-docs/sandbox/.gitignore @@ -0,0 +1,2 @@ +.state/ +!.empty/.keep diff --git a/.agents/skills/test-the-docs/sandbox/Dockerfile b/.agents/skills/test-the-docs/sandbox/Dockerfile new file mode 100644 index 0000000000000..87e003adaa05a --- /dev/null +++ b/.agents/skills/test-the-docs/sandbox/Dockerfile @@ -0,0 +1,34 @@ +# Runner for /test-the-docs: executes MDX fences inside the container. +FROM node:22-bookworm-slim + +ARG TARGETARCH +ARG SUPABASE_CLI_VERSION=2.39.2 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + postgresql-client \ + && rm -rf /var/lib/apt/lists/* + +# Docker CLI only (daemon is DinD over TCP for stack profile) +COPY --from=docker:27-cli /usr/local/bin/docker /usr/local/bin/docker + +RUN set -eux; \ + arch="${TARGETARCH}"; \ + case "${arch}" in \ + amd64) cli_arch=amd64 ;; \ + arm64) cli_arch=arm64 ;; \ + *) cli_arch=amd64 ;; \ + esac; \ + curl -fsSL "https://github.com/supabase/cli/releases/download/v${SUPABASE_CLI_VERSION}/supabase_linux_${cli_arch}.tar.gz" \ + | tar -xz -C /usr/local/bin supabase; \ + chmod +x /usr/local/bin/supabase; \ + supabase --version + +RUN useradd --create-home --uid 1001 --shell /bin/bash runner \ + && mkdir -p /work /output /examples \ + && chown -R runner:runner /work /output /examples + +USER runner +WORKDIR /work +CMD ["bash"] diff --git a/.agents/skills/test-the-docs/sandbox/compose.yaml b/.agents/skills/test-the-docs/sandbox/compose.yaml new file mode 100644 index 0000000000000..00d24f3b73c74 --- /dev/null +++ b/.agents/skills/test-the-docs/sandbox/compose.yaml @@ -0,0 +1,81 @@ +# Disposable compose project for /test-the-docs. +# Host only starts/stops this project; MDX fences run inside the runner. +# +# Profiles: +# stack — privileged DinD + runner sharing DinD network (supabase start uses 127.0.0.1) +# examples — runner only; copies /examples into /work/example for npm install (no DinD) + +services: + dind: + image: docker:27-dind + privileged: true + environment: + DOCKER_TLS_CERTDIR: '' + command: ['dockerd', '--host=tcp://0.0.0.0:2375', '--host=unix:///var/run/docker.sock'] + healthcheck: + test: ['CMD', 'docker', 'info'] + interval: 2s + timeout: 5s + retries: 30 + start_period: 5s + profiles: + - stack + + runner: + build: + context: . + dockerfile: Dockerfile + working_dir: /work + user: '1001:1001' + environment: + TTD_IN_CONTAINER: '1' + command: ['sleep', 'infinity'] + volumes: + - type: bind + source: ${TTD_WORK_DIR:?set TTD_WORK_DIR} + target: /work + - type: bind + source: ${TTD_OUTPUT_DIR:?set TTD_OUTPUT_DIR} + target: /output + - type: bind + source: ${TTD_EXAMPLE_DIR:-./.empty} + target: /examples + read_only: true + networks: + - ttd + profiles: + - examples + + runner-stack: + build: + context: . + dockerfile: Dockerfile + working_dir: /work + user: '1001:1001' + # Share DinD's network namespace so supabase healthchecks on 127.0.0.1 succeed + network_mode: 'service:dind' + environment: + TTD_IN_CONTAINER: '1' + DOCKER_HOST: tcp://127.0.0.1:2375 + command: ['sleep', 'infinity'] + volumes: + - type: bind + source: ${TTD_WORK_DIR:?set TTD_WORK_DIR} + target: /work + - type: bind + source: ${TTD_OUTPUT_DIR:?set TTD_OUTPUT_DIR} + target: /output + - type: bind + source: ${TTD_EXAMPLE_DIR:-./.empty} + target: /examples + read_only: true + depends_on: + dind: + condition: service_healthy + profiles: + - stack + +networks: + ttd: + driver: bridge + name: ${TTD_NETWORK_NAME:-ttd-sandbox} diff --git a/.agents/skills/test-the-docs/sandbox/run.sh b/.agents/skills/test-the-docs/sandbox/run.sh new file mode 100755 index 0000000000000..85fd7c235cbce --- /dev/null +++ b/.agents/skills/test-the-docs/sandbox/run.sh @@ -0,0 +1,189 @@ +#!/usr/bin/env bash +# Host-side lifecycle for /test-the-docs sandbox. +# Starts a disposable compose project and execs fences inside the runner container. +# Usage: +# eval "$(./run.sh env)" # export TTD_* for the session +# ./run.sh up-stack # DinD + runner; supabase init/start in /work +# ./run.sh up-examples # runner only (no DinD); example-app builds in /work/example +# ./run.sh exec -- # run a command in the active runner +# ./run.sh exec-timeout 60 -- +# ./run.sh down # compose down -v and remove work/output dirs created by this script +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +COMPOSE_FILE="${SCRIPT_DIR}/compose.yaml" + +die() { + echo "error: $*" >&2 + exit 1 +} + +require_host_prereqs() { + if [[ "$(id -u)" = "0" ]]; then + die "refuse to run as root on the host" + fi + command -v docker >/dev/null || die "docker not found — install Docker Desktop" + docker info >/dev/null 2>&1 || die "Docker is not running — start Docker Desktop" + docker compose version >/dev/null 2>&1 || die "docker compose not available" +} + +compose() { + docker compose -p "${TTD_PROJECT_NAME}" -f "${COMPOSE_FILE}" "$@" +} + +runner_service() { + case "${TTD_PROFILE:-}" in + stack) echo runner-stack ;; + examples) echo runner ;; + *) die "TTD_PROFILE unset; run up-stack or up-examples first" ;; + esac +} + +ensure_state_dir() { + mkdir -p "${SCRIPT_DIR}/.state" +} + +write_env_file() { + ensure_state_dir + cat >"${SCRIPT_DIR}/.state/current.env" </dev/null 2>&1; then + break + fi + sleep 1 + done + docker info >/dev/null + cd /work + if [[ ! -f supabase/config.toml ]]; then + printf 'n\nn\n' | supabase init + fi + supabase start + ' + echo "sandbox ready: project=${TTD_PROJECT_NAME} work=${TTD_WORK_DIR} profile=stack (DinD)" >&2 +} + +cmd_up_examples() { + prepare_exports + export TTD_PROFILE=examples + write_env_file + compose --profile examples build runner + compose --profile examples up -d --remove-orphans runner + # Copy read-only mount into writable /work so npm can install without mutating the repo + compose --profile examples exec -T runner \ + bash -lc 'rm -rf /work/example && mkdir -p /work/example && cp -a /examples/. /work/example/' + echo "sandbox ready: project=${TTD_PROJECT_NAME} work=${TTD_WORK_DIR} profile=examples (build in /work/example)" >&2 +} + +cmd_exec() { + load_env_file + local svc + svc="$(runner_service)" + compose --profile "${TTD_PROFILE}" exec -T "${svc}" "$@" +} + +cmd_exec_timeout() { + load_env_file + local secs="$1" + shift + if [[ "${1:-}" == "--" ]]; then + shift + fi + local svc + svc="$(runner_service)" + compose --profile "${TTD_PROFILE}" exec -T "${svc}" \ + timeout --foreground --signal=TERM --kill-after=5s "${secs}s" "$@" +} + +cmd_down() { + if [[ -f "${SCRIPT_DIR}/.state/current.env" ]]; then + # shellcheck disable=SC1091 + source "${SCRIPT_DIR}/.state/current.env" + else + die "no active sandbox state" + fi + if [[ "${TTD_PROFILE:-}" == "stack" ]]; then + compose --profile stack exec -T runner-stack bash -lc 'cd /work && supabase stop 2>/dev/null || true' 2>/dev/null || true + fi + compose --profile "${TTD_PROFILE:-stack}" down -v --remove-orphans 2>/dev/null || true + rm -rf "${TTD_WORK_DIR:-}" "${TTD_OUTPUT_DIR:-}" 2>/dev/null || true + rm -f "${SCRIPT_DIR}/.state/current.env" + echo "sandbox torn down: ${TTD_PROJECT_NAME:-unknown}" >&2 +} + +usage() { + sed -n '2,10p' "$0" | sed 's/^# //; s/^#//' +} + +main() { + local cmd="${1:-}" + shift || true + case "${cmd}" in + env) cmd_env "$@" ;; + up-stack) cmd_up_stack "$@" ;; + up-examples) cmd_up_examples "$@" ;; + exec) + if [[ "${1:-}" == "--" ]]; then shift; fi + cmd_exec "$@" + ;; + exec-timeout) cmd_exec_timeout "$@" ;; + down) cmd_down "$@" ;; + -h | --help | help | "") usage ;; + *) die "unknown command: ${cmd}" ;; + esac +} + +main "$@" diff --git a/.agents/skills/write-the-docs/SKILL.md b/.agents/skills/write-the-docs/SKILL.md index 8380bd4c03e3c..80b892e4feeee 100644 --- a/.agents/skills/write-the-docs/SKILL.md +++ b/.agents/skills/write-the-docs/SKILL.md @@ -28,7 +28,7 @@ Four inputs, read in this sequence (sequence, not priority; Linear remains the p 1. **Style guide — voice/terminology reference.** Start with [`apps/docs/CONTRIBUTING.md`](../../../apps/docs/CONTRIBUTING.md) and [`apps/docs/WORD_LIST.md`](../../../apps/docs/WORD_LIST.md) for voice, structure, and terminology. If those don't cover the case, fall back to the nearest comparable existing page under `apps/docs/content/` and say explicitly: _"no dedicated style guide yet — following the precedent of ``."_ See [reference/style-fallback.md](reference/style-fallback.md). 2. **Linear — the ticket and its product context.** Linear is an internal Supabase tool: preferred when available, not required for open-source contributors. When a Linear issue is available, pull it, then its parent project/initiative description too (PRD, PRFAQ, RFC, or initiative narrative) and any PM comments. Product framing/positioning language usually lives one level up from the ticket, in the parent project or initiative description rather than the ticket body. Distinguish scope the ticket actually commits to from aspirational language in the PRD. If there is no Linear issue and no prior Frame/Shape product-intent output, stop drafting: ask internal authors for a Linear URL, otherwise hand off to [`pm-the-docs`](../pm-the-docs/SKILL.md) (Frame) and [`ask-the-docs`](../ask-the-docs/SKILL.md) when Shape/IA is unsettled. Resume only after product intent exists — never invent positioning, and never run Frame/Shape inside this Draft skill. -3. **Code.** Read the actual implementation before writing a single behavior claim — the PRD describes intent, the code describes what shipped. Check the Linear issue/project first for a linked `supabase/supabase` PR — its diff and description are the most precise "what actually shipped" source, more precise than a general codebase read. If no PR is linked, locate the feature directly in `supabase/supabase` (or the product's own repo), and apply [`ask-the-docs`](../ask-the-docs/SKILL.md)'s reuse/minimalism lens: understand what exists before describing it. If code and PRD disagree, the code wins for behavior claims — flag the mismatch rather than silently picking one. +3. **Code.** Read the actual implementation before writing a single behavior claim — the PRD describes intent, the code describes what shipped. Check the Linear issue/project first for a linked `supabase/supabase` PR — its diff and description are the most precise "what actually shipped" source, more precise than a general codebase read. If no PR is linked, locate the feature directly in `supabase/supabase` (or the product's own repo), and apply [`ask-the-docs`](../ask-the-docs/SKILL.md)'s reuse/minimalism lens: understand what exists before describing it. When behavior spans services (CLI, Auth, migrations, platform, …), follow [`pm-the-docs`](../pm-the-docs/SKILL.md) → [universe-lookup](../pm-the-docs/reference/universe-lookup.md) **capability gate** (universe when accessible, else OSS public search / linked repos — not `ask-the-docs`). If code and PRD disagree, the code wins for behavior claims — flag the mismatch rather than silently picking one. 4. **Whatever else the author supplies.** Screenshots, example projects, related pages, Slack threads, a specific voice sample. Screenshots are for more than general context — use them to verify the _exact_ button/menu/field labels before writing instructional steps that reference them; a mismatched UI label is one of the easiest, most avoidable errors in a draft. Ask for these when the feature's user-facing shape is still unclear after 1–3, rather than guessing. Summarize all four back to the requester before drafting: what's confirmed, what's product intent vs. shipped behavior, what's still a gap. Stop and ask if a real gap would change the draft's structure or scope. @@ -67,6 +67,7 @@ Before handing off, confirm: - [ ] Content type confirmed as Guide/Troubleshooting (not something that belongs in generated Reference instead) - [ ] Nav placement and nav enablement both wired, not just the placement - [ ] Internal links resolve; first-use of new terms/acronyms is defined +- [ ] If the draft has procedural snippets (CLI, SQL, client code, or example apps), **offered** to run [`test-the-docs`](../test-the-docs/SKILL.md) (optional; Docker Compose sandbox — stack profile for DB/API, examples profile for `example-app`) - [ ] Future promises minimized where possible (timeless documentation principle) - [ ] No unnecessary redundancy (same point restated multiple ways) - [ ] Single-item lists avoided unless there's a specific reason @@ -86,6 +87,8 @@ Re-read [`apps/docs/CONTRIBUTING.md`](../../../apps/docs/CONTRIBUTING.md) and [` This skill stops at a reviewable draft. It does not open worktrees or PRs itself: +- **Offer** [`test-the-docs`](../test-the-docs/SKILL.md) when the draft includes runnable procedural snippets. Ask before starting verification. Gate prerequisites **per artifact class** (Docker Compose stack profile for DB/API artifacts; examples profile / Node in-runner for `example-app`). If declined, or a required prerequisite for that class is missing, record `deferred` for those artifacts only and continue. When accepted, attach the verification report to the PR body / self-review note. +- Then run [`review-the-docs`](../review-the-docs/SKILL.md) local self-review (lint/build/classify). - Hand off to [`create-pull-request`](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/create-pull-request/SKILL.md) (and [`work-linear-issue`](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/work-linear-issue/SKILL.md) if the ticket needs a full worktree+PR flow) for the actual PR mechanics. Carry the Phase 1/2 flagged-assumptions list forward explicitly into that handoff — it belongs in the PR description (e.g. a "needs review" section) so a reviewer sees it, not just as an inline comment buried in the draft. - If the feature is UI-driven and the PR will need screenshots/GIFs, flag [`proof-it-works`](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/proof-it-works/SKILL.md) as the next step rather than capturing evidence here. - Before opening the PR, run [`review-the-docs`](../review-the-docs/SKILL.md) local self-review: `pnpm lint:mdx`, `pnpm build:guides-markdown` where applicable, and anchor checks per [reference/drafting-mechanics.md](reference/drafting-mechanics.md). @@ -98,6 +101,8 @@ This skill stops at a reviewable draft. It does not open worktrees or PRs itself - Content-type gate detail: [reference/content-type-gate.md](reference/content-type-gate.md) - Existing-page restructure/clarity: [`edit-the-docs`](../edit-the-docs/SKILL.md) - "Write the docs" checklist (Draft stage): [`pm-the-docs`](../pm-the-docs/SKILL.md)'s [reference/write-the-docs-checklist.md](../pm-the-docs/reference/write-the-docs-checklist.md) +- Cross-repo product lookup: [`pm-the-docs`](../pm-the-docs/SKILL.md) → [universe-lookup](../pm-the-docs/reference/universe-lookup.md) +- Runnable verification: [`test-the-docs`](../test-the-docs/SKILL.md) - Docs-app architecture/placement: [`ask-the-docs`](../ask-the-docs/SKILL.md), [`audit-docs-ia`](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/audit-docs-ia/SKILL.md) - PR mechanics: [`create-pull-request`](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/create-pull-request/SKILL.md), [`work-linear-issue`](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/work-linear-issue/SKILL.md) - Screenshots/proof: [`proof-it-works`](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/proof-it-works/SKILL.md) diff --git a/apps/design-system/content/docs/copywriting.mdx b/apps/design-system/content/docs/copywriting.mdx index 4709faa48feb7..2e8fe0b71c854 100644 --- a/apps/design-system/content/docs/copywriting.mdx +++ b/apps/design-system/content/docs/copywriting.mdx @@ -226,6 +226,10 @@ Use a fragment with no trailing period, and prefer declarative over instructiona | "Handle errors" | "View and resolve errors" | | "Work with data" | "Query and update data" | +## Authentication terminology + +Use **Sign in**, **Sign out**, and **Sign up** for button and menu labels. Keep `login`, `logout`, and `logOut` in code, routes, URL slugs, and CLI commands only when they match existing implementation names. + ## Capitalization - **Sentence case** for all UI text (buttons, labels, section headings) diff --git a/apps/design-system/registry/default/example/button-as-child.tsx b/apps/design-system/registry/default/example/button-as-child.tsx index 4a7cdfcdb07df..8d8909cdb50b6 100644 --- a/apps/design-system/registry/default/example/button-as-child.tsx +++ b/apps/design-system/registry/default/example/button-as-child.tsx @@ -4,7 +4,7 @@ import { Button } from 'ui' export default function ButtonAsChild() { return ( ) } diff --git a/apps/design-system/registry/default/example/button-with-icon.tsx b/apps/design-system/registry/default/example/button-with-icon.tsx index 70d24d18310b4..54ebaab7968e4 100644 --- a/apps/design-system/registry/default/example/button-with-icon.tsx +++ b/apps/design-system/registry/default/example/button-with-icon.tsx @@ -2,5 +2,5 @@ import { Mail } from 'lucide-react' import { Button } from 'ui' export default function ButtonWithIcon() { - return + return } diff --git a/apps/design-system/registry/default/example/dropdown-menu-demo.tsx b/apps/design-system/registry/default/example/dropdown-menu-demo.tsx index 40ca46ba1d3dd..c67490d0ad6ec 100644 --- a/apps/design-system/registry/default/example/dropdown-menu-demo.tsx +++ b/apps/design-system/registry/default/example/dropdown-menu-demo.tsx @@ -112,7 +112,7 @@ export default function DropdownMenuDemo() { - Log out + Sign out ⇧⌘Q diff --git a/apps/docs/CONTRIBUTING.md b/apps/docs/CONTRIBUTING.md index 42e465763e6fe..8ad5a85dd76a4 100644 --- a/apps/docs/CONTRIBUTING.md +++ b/apps/docs/CONTRIBUTING.md @@ -23,14 +23,15 @@ To make docs as clear as possible: If you're using an AI coding agent (Claude Code, Codex, or anything else that reads `.agents/skills/`), this repo ships skills that back the [Write the docs](../../.agents/skills/pm-the-docs/reference/write-the-docs-checklist.md) authoring checklist. -Ask your agent for a skill by name (`write-the-docs`, `edit-the-docs`, `ask-the-docs`, `pm-the-docs`, `review-the-docs`); in Claude Code these are also available as `/name` slash commands. +Ask your agent for a skill by name (`pm-the-docs`, `ask-the-docs`, `write-the-docs`, `edit-the-docs`, `test-the-docs`, `review-the-docs`); in Claude Code these are also available as `/name` slash commands. | Skill | Checklist stage | Use for | | --- | --- | --- | -| [`pm-the-docs`](../../.agents/skills/pm-the-docs/SKILL.md) | Frame / Shape | Audience, product-stage, and cross-cutting scope calls | +| [`pm-the-docs`](../../.agents/skills/pm-the-docs/SKILL.md) | Frame / Shape | Audience, product-stage, and cross-cutting scope calls (universe when you have Supabase org access, else OSS path) | | [`ask-the-docs`](../../.agents/skills/ask-the-docs/SKILL.md) | Frame / Shape | `apps/docs` architecture, IA placement, and where content lives | | [`write-the-docs`](../../.agents/skills/write-the-docs/SKILL.md) | Draft | Drafting net-new content grounded in the code | | [`edit-the-docs`](../../.agents/skills/edit-the-docs/SKILL.md) | Edit | Restructure and improve existing pages | +| [`test-the-docs`](../../.agents/skills/test-the-docs/SKILL.md) | Draft / Self-review | Execute docs snippets in a Docker-isolated local stack; verification report | | [`review-the-docs`](../../.agents/skills/review-the-docs/SKILL.md) | Self-review / PR review | Checking a draft and PR triage/verification | The canonical files live in `.agents/skills/`; `.claude/skills` is a Git symlink to that directory so Claude Code discovers them too. diff --git a/apps/docs/WORD_LIST.md b/apps/docs/WORD_LIST.md index 8fb46f2b22d81..e3ee4af18cc16 100644 --- a/apps/docs/WORD_LIST.md +++ b/apps/docs/WORD_LIST.md @@ -473,11 +473,8 @@ Write _lifecycle_, not _life cycle_ or _life-cycle_. ### login and log in -Use _login_ as a noun or adjective and _log in_ as a verb. Follow the terminology -in the product UI when it uses _sign in_. - -- Recommended: Open the login page, and then log in. -- Not recommended: Login to the Dashboard. +Don't use _login_ or _log in_ in prose. Use _sign in_. See +[sign in and sign-in](#sign-in-and-sign-in). ## M @@ -655,6 +652,16 @@ Use _setup_ as a noun or adjective and _set up_ as a verb. - Recommended: Complete the setup to set up authentication. - Not recommended: Setup authentication. +### sign in and sign-in + +Use _sign in_, _sign out_, and _sign up_ as verbs. Use the hyphenated forms +_sign-in_, _sign-out_, and _sign-up_ as nouns or adjectives. Match the product UI +labels **Sign in**, **Sign out**, and **Sign up**. + +Keep _login_, _log in_, _logout_, _log out_, and `logOut` when quoting +third-party UI or when they are part of code, routes, URL slugs, CLI commands, or +established feature names such as _social login_. + ### singular they Use _they_, _them_, and _their_ as gender-neutral singular pronouns. Don't use diff --git a/apps/docs/app/guides/database/database-advisors/page.tsx b/apps/docs/app/guides/database/database-advisors/page.tsx deleted file mode 100644 index 302cd6e4d0964..0000000000000 --- a/apps/docs/app/guides/database/database-advisors/page.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { GuideTemplate } from '~/features/docs/GuidesMdx.template' -import { genGuideMeta, getGuidesMarkdown } from '~/features/docs/GuidesMdx.utils' - -const DatabaseAdvisorDocs = async () => { - const data = await getGuidesMarkdown(['database', 'database-advisors']) - - return -} - -const generateMetadata = genGuideMeta(() => getGuidesMarkdown(['database', 'database-advisors'])) - -export default DatabaseAdvisorDocs -export { generateMetadata } diff --git a/apps/docs/app/guides/monitoring-and-debugging/[[...slug]]/page.tsx b/apps/docs/app/guides/observability/[[...slug]]/page.tsx similarity index 58% rename from apps/docs/app/guides/monitoring-and-debugging/[[...slug]]/page.tsx rename to apps/docs/app/guides/observability/[[...slug]]/page.tsx index 94df4a9b279a6..d9feda758919f 100644 --- a/apps/docs/app/guides/monitoring-and-debugging/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/observability/[[...slug]]/page.tsx @@ -9,20 +9,18 @@ import { IS_DEV } from '~/lib/constants' type Params = { slug?: string[] } -const MonitoringTroubleshootingGuidePage = async (props: { params: Promise }) => { +const ObservabilityGuidePage = async (props: { params: Promise }) => { const params = await props.params - const slug = ['monitoring-and-debugging', ...(params.slug ?? [])] + const slug = ['observability', ...(params.slug ?? [])] const data = await getGuidesMarkdown(slug) return } -const generateStaticParams = !IS_DEV - ? genGuidesStaticParams('monitoring-and-debugging') - : getEmptyArray +const generateStaticParams = !IS_DEV ? genGuidesStaticParams('observability') : getEmptyArray const generateMetadata = genGuideMeta((params: { slug?: string[] }) => - getGuidesMarkdown(['monitoring-and-debugging', ...(params.slug ?? [])]) + getGuidesMarkdown(['observability', ...(params.slug ?? [])]) ) -export default MonitoringTroubleshootingGuidePage +export default ObservabilityGuidePage export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/monitoring-and-debugging/layout.tsx b/apps/docs/app/guides/observability/layout.tsx similarity index 100% rename from apps/docs/app/guides/monitoring-and-debugging/layout.tsx rename to apps/docs/app/guides/observability/layout.tsx diff --git a/apps/docs/app/guides/troubleshooting/page.tsx b/apps/docs/app/guides/troubleshooting/page.tsx index 66d34249eb9d5..7d3bdfeb2b760 100644 --- a/apps/docs/app/guides/troubleshooting/page.tsx +++ b/apps/docs/app/guides/troubleshooting/page.tsx @@ -16,6 +16,8 @@ import { PROD_URL } from '~/lib/constants' import { getCustomContent } from '~/lib/custom-content/getCustomContent' import { mdAlternate } from '~/lib/md-alternates' import { type Metadata } from 'next' +import Link from 'next/link' +import { Admonition } from 'ui-patterns/Admonition' const { metadataTitle } = getCustomContent(['metadata:title']) @@ -32,6 +34,76 @@ export default async function GlobalTroubleshootingPage() {

Search or browse our troubleshooting guides for solutions to common Supabase issues.

+

+ Don't have a specific error yet? Start with{' '} + + Detecting + {' '} + to pick up a signal first. If you already have one, confirm one cause before you change + anything: +

+
    +
  1. + Capture the exact HTTP status, error code, and message. A 401 is not a{' '} + 403; PGRST002 is not PGRST106. If you use{' '} + supabase-js, errors are returned in {'{ data, error }'}, not + thrown. Inspect error; ignoring it hides the failure. +
  2. +
  3. + Query the{' '} + + log source + {' '} + for that layer. When two layers could fit, start closer to the database. +
  4. +
  5. + Search below for that error. Each article confirms one cause, applies one fix, and tells + you how to verify it. +
  6. +
  7. + Re-run the failing operation. Keep the change only when the original symptom is gone. If + verification fails, reverse the change and look again. +
  8. +
+

+ For client-side or local debugging, see{' '} + + Auth error codes + + ,{' '} + + Storage logs + + , and{' '} + + Edge Functions debugging tools + + . +

+ + Deleting data, disabling row-level security, weakening a policy, or terminating a database + process can cause data loss or a security incident. Do not let an automated routine + perform these changes. + +

+ Escalate to{' '} + + Support + {' '} + when you cannot access the diagnostic source, the evidence points to a platform failure, + or a safe fix needs a permission you do not have. Include the project reference, timestamp + with time zone, error code, request ID, and sanitized evidence. Do not include passwords, + API keys, or personal data. +


)} + {item.subtitle && ( + {item.subtitle} + )} {item.description} diff --git a/apps/docs/components/MetricsStackCards.data.ts b/apps/docs/components/MetricsStackCards.data.ts index 04c76f26e0267..a3f0a88cdb306 100644 --- a/apps/docs/components/MetricsStackCards.data.ts +++ b/apps/docs/components/MetricsStackCards.data.ts @@ -13,7 +13,7 @@ export const metricsStackOptions: MetricsStackOption[] = [ title: 'Grafana Cloud (SaaS)', description: 'Use Grafana Cloud’s managed Prometheus (works on Free + Pro tiers) and import the Supabase dashboard without running any infrastructure.', - href: '/guides/monitoring-and-debugging/metrics/grafana-cloud', + href: '/guides/observability/metrics/grafana-cloud', iconKind: 'grafana', iconColor: '#F05A28', iconBg: 'rgba(240,90,40,0.1)', @@ -23,7 +23,7 @@ export const metricsStackOptions: MetricsStackOption[] = [ title: 'Grafana + self-hosted Prometheus', description: 'Run Prometheus yourself following the official installation guidance and pair it with Grafana plus our dashboard JSON and alert pack.', - href: '/guides/monitoring-and-debugging/metrics/grafana-self-hosted', + href: '/guides/observability/metrics/grafana-self-hosted', iconKind: 'grafana', iconColor: '#F05A28', iconBg: 'rgba(240,90,40,0.1)', @@ -53,7 +53,7 @@ export const metricsStackOptions: MetricsStackOption[] = [ title: 'Vendor-agnostic / BYO Prometheus', description: 'Connect AWS AMP, Grafana Mimir, VictoriaMetrics, or any Prometheus-compatible SaaS with the same scrape job pattern.', - href: '/guides/monitoring-and-debugging/metrics/vendor-agnostic', + href: '/guides/observability/metrics/vendor-agnostic', iconKind: 'flame', iconColor: '#0BA678', iconBg: 'rgba(11,166,120,0.1)', diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index 2bf96f1082661..c0982f9a99d0c 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -210,17 +210,11 @@ export const GLOBAL_MENU_ITEMS: GlobalMenuItems = [ level: 'security', }, { - label: 'Monitoring and Debugging', + label: 'Observability', icon: 'telemetry', - href: '/guides/monitoring-and-debugging' as `/${string}`, + href: '/guides/observability' as `/${string}`, level: 'telemetry', }, - { - label: 'Troubleshooting', - icon: 'troubleshooting', - href: '/guides/troubleshooting' as `/${string}`, - level: 'troubleshooting', - }, ], ], }, @@ -1161,7 +1155,7 @@ export const database: NavMenuConstant = { }, { name: 'Database Advisors', - url: '/guides/database/database-advisors' as `/${string}`, + url: '/guides/observability/advisors' as `/${string}`, }, { name: 'Testing your database', url: '/guides/database/testing' }, { @@ -1179,8 +1173,8 @@ export const database: NavMenuConstant = { url: '/guides/database/postgres/timeouts' as `/${string}`, }, { - name: 'Debugging and monitoring', - url: '/guides/database/inspect' as `/${string}`, + name: 'Inspect the database', + url: '/guides/observability/inspect' as `/${string}`, }, { name: 'Debugging performance issues', @@ -3021,81 +3015,147 @@ export const platform: NavMenuConstant = { export const telemetry: NavMenuConstant = { icon: 'telemetry', - title: 'Monitoring and Debugging', - url: '/guides/monitoring-and-debugging', + title: 'Observability', + url: '/guides/observability', items: [ - { name: 'Overview', url: '/guides/monitoring-and-debugging' }, - { - name: 'Debugging', - url: undefined, - items: [ - { - name: 'Debugging guide', - url: '/guides/monitoring-and-debugging/debugging' as `/${string}`, - }, - { - name: 'Logging', - url: '/guides/monitoring-and-debugging/logs' as `/${string}`, - }, - { - name: 'Advanced log filtering', - url: '/guides/monitoring-and-debugging/advanced-log-filtering' as `/${string}`, - }, - { - name: 'Logs field reference', - url: '/guides/monitoring-and-debugging/log-field-reference' as `/${string}`, - }, - ], - }, + { name: 'Overview', url: '/guides/observability' }, { - name: 'Monitoring', - url: undefined, + name: 'Observe the data', + url: '/guides/observability/access-data' as `/${string}`, items: [ { - name: 'Log drains', - url: '/guides/monitoring-and-debugging/log-drains' as `/${string}`, - }, - { - name: 'Reports', - url: '/guides/monitoring-and-debugging/reports' as `/${string}`, - }, - { - name: 'Metrics', - url: '/guides/monitoring-and-debugging/metrics' as `/${string}`, + name: 'Logs', + url: '/guides/observability/advanced-log-filtering' as `/${string}`, items: [ { - name: 'Overview', - url: '/guides/monitoring-and-debugging/metrics' as `/${string}`, + name: 'Query and filter logs', + url: '/guides/observability/advanced-log-filtering' as `/${string}`, }, + { + name: 'Sources', + url: '/guides/observability/advanced-log-filtering#logs-explorer' as `/${string}`, + }, + { + name: 'Logs field reference', + url: '/guides/observability/log-field-reference' as `/${string}`, + }, + { + name: 'Logs in Studio', + url: '/guides/observability/logs' as `/${string}`, + }, + ], + }, + { + name: 'Metrics API', + url: '/guides/observability/metrics' as `/${string}`, + items: [ { name: 'Grafana Cloud', - url: '/guides/monitoring-and-debugging/metrics/grafana-cloud' as `/${string}`, + url: '/guides/observability/metrics/grafana-cloud' as `/${string}`, }, { name: 'Grafana self-hosted', - url: '/guides/monitoring-and-debugging/metrics/grafana-self-hosted' as `/${string}`, + url: '/guides/observability/metrics/grafana-self-hosted' as `/${string}`, }, { name: 'Datadog', - url: 'https://docs.datadoghq.com/integrations/supabase/' as `/${string}`, + url: 'https://docs.datadoghq.com/integrations/supabase/', }, { name: 'Elastic', - url: 'https://www.elastic.co/docs/reference/integrations/supabase' as `/${string}`, + url: 'https://www.elastic.co/docs/reference/integrations/supabase', }, { name: 'Vendor-agnostic setup', - url: '/guides/monitoring-and-debugging/metrics/vendor-agnostic' as `/${string}`, + url: '/guides/observability/metrics/vendor-agnostic' as `/${string}`, }, ], }, { - name: 'Sentry integration', - url: '/guides/monitoring-and-debugging/sentry-monitoring' as `/${string}`, + name: 'Database', + url: '/guides/observability/inspect' as `/${string}`, + items: [ + { + name: 'CLI commands', + url: '/guides/observability/inspect#using-the-cli' as `/${string}`, + }, + { + name: 'SQL', + url: '/guides/observability/inspect#using-sql' as `/${string}`, + }, + ], }, { - name: 'Tracing with the client SDKs', - url: '/guides/monitoring-and-debugging/client-side-tracing' as `/${string}`, + name: 'Advisors', + url: '/guides/observability/advisors' as `/${string}`, + }, + { + name: 'Reports', + url: '/guides/observability/reports' as `/${string}`, + }, + ], + }, + { + name: 'Detect issues', + url: '/guides/observability/detecting' as `/${string}`, + items: [ + { + name: 'Detection checks', + url: '/guides/observability/detecting' as `/${string}`, + }, + ], + }, + { + name: 'Diagnose and resolve', + url: '/guides/troubleshooting' as `/${string}`, + items: [ + { + name: 'Troubleshooting', + url: '/guides/troubleshooting' as `/${string}`, + }, + ], + }, + { + name: 'Hire an agent', + url: '/guides/observability/automate-with-agents' as `/${string}`, + items: [ + { + name: 'Generalist', + url: '/guides/observability/automate-with-agents/all' as `/${string}`, + }, + { + name: 'Health monitor', + url: '/guides/observability/automate-with-agents/health' as `/${string}`, + }, + { + name: 'Security monitor', + url: '/guides/observability/automate-with-agents/security' as `/${string}`, + }, + { + name: 'Performance monitor', + url: '/guides/observability/automate-with-agents/performance' as `/${string}`, + }, + { + name: 'Capacity monitor', + url: '/guides/observability/automate-with-agents/usage' as `/${string}`, + }, + ], + }, + { + name: 'Export', + url: undefined, + items: [ + { + name: 'Log drains', + url: '/guides/observability/log-drains' as `/${string}`, + }, + { + name: 'Client-side tracing', + url: '/guides/observability/client-side-tracing' as `/${string}`, + }, + { + name: 'Sentry integration', + url: '/guides/observability/sentry-monitoring' as `/${string}`, }, ], }, diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.utils.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.utils.ts index a44f85f4fba78..5622a2f49b12d 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.utils.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.utils.ts @@ -135,7 +135,9 @@ export const getMenuId = (pathname: string | null) => { return MenuId.LocalDevelopment case pathname.startsWith('ai-tools'): return MenuId.AiTools - case pathname.startsWith('monitoring-and-debugging'): + case pathname.startsWith('observability'): + return MenuId.Telemetry + case pathname.startsWith('troubleshooting'): return MenuId.Telemetry case pathname.startsWith('platform'): return MenuId.Platform diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenuGuideListItems.tsx b/apps/docs/components/Navigation/NavigationMenu/NavigationMenuGuideListItems.tsx index 31192c49a51c4..3e26b1f62ffa3 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenuGuideListItems.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenuGuideListItems.tsx @@ -8,6 +8,16 @@ import React, { useEffect, useRef } from 'react' import MenuIconPicker from './MenuIconPicker' +type NavAccordionItem = { + url?: string + items?: NavAccordionItem[] +} + +function hasActiveDescendant(item: NavAccordionItem, pathname: string): boolean { + if (item.url === pathname) return true + return item.items?.some((child) => hasActiveDescendant(child, pathname)) ?? false +} + const HeaderLink = React.memo(function HeaderLink(props: { title: string id: string @@ -35,7 +45,8 @@ const ContentAccordionLink = React.memo(function ContentAccordionLink(props: any const activeItemRef = useRef(null) const isChildActive = - props.subItem.items && props.subItem.items.some((child: any) => child.url === pathname) + props.subItem.items && + props.subItem.items.some((child: NavAccordionItem) => hasActiveDescendant(child, pathname)) const LinkContainer = (props) => { const isExternal = props.url.startsWith('https://') @@ -107,6 +118,17 @@ const ContentAccordionLink = React.memo(function ContentAccordionLink(props: any {props.subItem.items .filter((subItem) => subItem.enabled !== false) .map((subSubItem) => { + if (subSubItem.items && subSubItem.items.length > 0) { + return ( + + ) + } + return (
  • Cursor Settings > Tools & MCP**. Depending on the client, you may need to restart it to connect and detect all tools after authorization. +After you sign in, check that the MCP server is connected. For instance, in Cursor, navigate to **Settings > Cursor Settings > Tools & MCP**. Depending on the client, you may need to restart it to connect and detect all tools after authorization. To verify the client has access to the MCP server tools, try asking it to query your project or database using natural language. For example: "What tables are there in the database? Use MCP tools." @@ -56,7 +56,7 @@ The Supabase MCP server provides tools organized into feature groups. All groups ### Debugging -- `query_logs` - Run a read-only SQL query against project logs to filter, aggregate, or join across log fields +- `query_logs` - Run a read-only SQL query against project logs to filter, aggregate, or join across log fields. See [Query and filter logs](/docs/guides/observability/advanced-log-filtering). - `get_advisors` - Get security and performance advisors ### Development @@ -135,7 +135,7 @@ There are some situations where you might want to manually authenticate the MCP To authenticate the MCP server in a CI environment, you can create a personal access token (PAT) with the necessary scopes and pass it as a header to the MCP server. -1. Remember to never connect the MCP server to production data. Supabase MCP is only designed for development and testing purposes. See [Security risks](#security-risks). +1. Production projects can contain sensitive data. Before connecting one, scope the server to that project, enable [read-only mode](#configuration-options), restrict the available feature groups, and review the [security risks](#security-risks). 1. Navigate to your Supabase [access tokens](/dashboard/account/tokens) and generate a new token. Name the token based on its purpose, e.g. "Example App MCP CI token". @@ -151,7 +151,7 @@ To authenticate the MCP server in a CI environment, you can create a personal ac If your MCP client requires an OAuth client ID and secret (e.g. Azure API Center), you can manually create an OAuth app in your Supabase account and pass the credentials to the MCP client. -1. Remember to never connect the MCP server to production data. Supabase MCP is only designed for development and testing purposes. See [Security risks](#security-risks). +1. Production projects can contain sensitive data. Before connecting one, scope the server to that project, enable [read-only mode](#configuration-options), restrict the available feature groups, and review the [security risks](#security-risks). 1. Navigate to your Supabase organization's [OAuth apps](/dashboard/org/_/apps) and add a new application. Name the app based on its purpose, e.g. "Example App MCP". @@ -176,7 +176,9 @@ The primary attack vector unique to LLMs is prompt injection, which might trick -Most MCP clients like Cursor ask you to manually accept each tool call before they run. We recommend you always keep this setting enabled and always review the details of the tool calls before executing them. +Most MCP clients ask you to accept each tool call before it runs. Keep manual approval enabled for interactive work, and review each tool call before you run it. + +An unattended monitoring routine cannot request approval during each run. Approve in advance only the project-scoped, read-only tools that the routine needs. The routine must stop and report a recommendation instead of running a write operation. To lower this risk further, Supabase MCP wraps SQL results with additional instructions to discourage LLMs from following instructions or commands that might be present in the data. This is not foolproof though, so you should always review the output before proceeding with further actions. @@ -186,9 +188,9 @@ To lower this risk further, Supabase MCP wraps SQL results with additional instr We recommend the following best practices to mitigate security risks when using the Supabase MCP server: -- **Don't connect to production**: Use the MCP server with a development project, not production. LLMs are great at helping design and test applications, so leverage them in a safe environment without exposing real data. Be sure that your development environment contains non-production data (or obfuscated data). +- **Protect production data**: Connect to a production project only when the task requires production evidence. Use project scoping, read-only mode, restricted feature groups, and the narrowest data query that can answer the question. Do not include secrets or unrelated personal data in prompts or reports. - **Don't give to your customers**: The MCP server operates under the context of your developer permissions, so you should not give it to your customers or end users. Instead, use it internally as a developer tool to help you build and test your applications. -- **Read-only mode**: If you must connect to real data, set the server to [read-only](#configuration-options) mode, which executes all queries as a read-only Postgres user. +- **Read-only mode**: Set unattended monitoring and diagnostic routines to [read-only](#configuration-options) mode, which executes SQL queries as a read-only Postgres user. - **Project scoping**: Scope your MCP server to a [specific project](#configuration-options), limiting access to only that project's resources. This prevents LLMs from accessing data from other projects in your Supabase account. - **Branching**: Use Supabase's [branching feature](/docs/guides/deployment/branching) to create a development branch for your database. This allows you to test changes in a safe environment before merging them to production. - **Feature groups**: Restrict which [tool groups](#available-tools) are available using the `features` [configuration option](#configuration-options). This helps reduce the attack surface and limits the actions that LLMs can perform to only those that you need. diff --git a/apps/docs/content/guides/api/rest/generating-python-types.mdx b/apps/docs/content/guides/api/rest/generating-python-types.mdx index 8e3b42acbcb76..1ba0492e84630 100644 --- a/apps/docs/content/guides/api/rest/generating-python-types.mdx +++ b/apps/docs/content/guides/api/rest/generating-python-types.mdx @@ -17,7 +17,7 @@ You can [install the CLI](https://www.npmjs.com/package/supabase) via npm or oth npm i supabase --save-dev ``` -Login with your Personal Access Token: +Sign in with your Personal Access Token: ```bash npx supabase login diff --git a/apps/docs/content/guides/api/rest/generating-types.mdx b/apps/docs/content/guides/api/rest/generating-types.mdx index 64762769bc451..72462efef7443 100644 --- a/apps/docs/content/guides/api/rest/generating-types.mdx +++ b/apps/docs/content/guides/api/rest/generating-types.mdx @@ -22,7 +22,7 @@ You can [install the CLI](https://www.npmjs.com/package/supabase) via npm or oth npm i supabase@">=1.8.1" --save-dev ``` -Login with your Personal Access Token: +Sign in with your Personal Access Token: ```bash npx supabase login @@ -99,6 +99,7 @@ You can supply the type definitions to `supabase-js` like so: ```ts ./index.tsx import { createClient } from '@supabase/supabase-js' + import { Database } from './database.types' const supabase = createClient( @@ -123,7 +124,9 @@ export interface Database { ```ts ./database.types.ts import { MergeDeep } from 'type-fest' + import { Database as DatabaseGenerated } from './database-generated.types' + export { Json } from './database-generated.types' // Override the type for a specific column in a view: @@ -160,6 +163,7 @@ You can extend your generated database types to include custom JSON schemas usin ```ts ./database.types.ts import { MergeDeep } from 'type-fest' + import { Database as DatabaseGenerated } from './database-generated.types' // Define your custom JSON type @@ -280,7 +284,7 @@ create table cities ( We can get the nested `CountriesWithCities` type like this: ```ts -import { QueryResult, QueryData, QueryError } from '@supabase/supabase-js' +import { QueryData, QueryError, QueryResult } from '@supabase/supabase-js' const countriesWithCitiesQuery = supabase.from('countries').select(` id, diff --git a/apps/docs/content/guides/api/rest/postgrest-error-codes.mdx b/apps/docs/content/guides/api/rest/postgrest-error-codes.mdx index 603d458fdd2c3..36decb42cb92a 100644 --- a/apps/docs/content/guides/api/rest/postgrest-error-codes.mdx +++ b/apps/docs/content/guides/api/rest/postgrest-error-codes.mdx @@ -233,28 +233,3 @@ group by hour, path order by hour desc limit 100; ``` - -### Find data API request from specific authenticated user - -```sql -select - timestamp, - event_message, - log_attributes['request.headers.cf_connecting_ip'] as requesters_ip, - log_attributes['request.url'] as request_url, - log_attributes['request.method'] as request_method, - log_attributes['request.sb.jwt.authorization.payload.subject'] as user_id, - log_attributes['request.sb.jwt.apikey.payload.role'] as apikey_role, - log_attributes['request.sb.jwt.authorization.payload.role'] as authorization_token_role, - log_attributes['request.headers.user_agent'] as user_agent, - log_attributes['request.cf.city'] as city, - log_attributes['request.cf.country'] as country, - log_attributes['request.cf.postalCode'] as postalCode -from logs -where - source = 'edge_logs' - and match(log_attributes['request.path'], '^/rest/v1/') - and log_attributes['request.sb.jwt.authorization.payload.subject'] = 'SOME_USER_ID' -- <---ADD USER_ID from auth.users table -order by timestamp desc -limit 100; -``` diff --git a/apps/docs/content/guides/api/using-custom-schemas.mdx b/apps/docs/content/guides/api/using-custom-schemas.mdx index dc788a700250d..842f94d5013ae 100644 --- a/apps/docs/content/guides/api/using-custom-schemas.mdx +++ b/apps/docs/content/guides/api/using-custom-schemas.mdx @@ -45,6 +45,7 @@ Now you can access these schemas from data APIs: ```js // Initialize the JS client import { createClient } from '@supabase/supabase-js' + const supabase = createClient(SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY, { db: { schema: 'myschema' }, }) diff --git a/apps/docs/content/guides/auth/architecture.mdx b/apps/docs/content/guides/auth/architecture.mdx index 3665526c40c12..053c76df6ae70 100644 --- a/apps/docs/content/guides/auth/architecture.mdx +++ b/apps/docs/content/guides/auth/architecture.mdx @@ -55,7 +55,7 @@ The Auth service is responsible for: - Validating, issuing, and refreshing JWTs - Serving as the intermediary between your app and Auth information in the database -- Communicating with external providers for Social Login and SSO +- Communicating with external providers for social login and SSO ## Postgres diff --git a/apps/docs/content/guides/auth/audit-logs.mdx b/apps/docs/content/guides/auth/audit-logs.mdx index 9d74ea36edb68..9a57fa2220059 100644 --- a/apps/docs/content/guides/auth/audit-logs.mdx +++ b/apps/docs/content/guides/auth/audit-logs.mdx @@ -11,10 +11,10 @@ Auth audit logs provide comprehensive tracking of authentication events in your Supabase auth audit logs automatically capture all authentication events including: -- User signups and logins +- User sign-ups and sign-ins - Password changes and resets - Email verification events -- Token refresh and logout events +- Token refresh and sign-out events ## Storage options @@ -53,8 +53,8 @@ Audit logs contain detailed information about each authentication event: | Action | Description | | ------------------------------- | --------------------------------------- | -| `login` | User login attempt | -| `logout` | User logout | +| `login` | User sign-in attempt | +| `logout` | User sign-out | | `invite_accepted` | Team invitation accepted | | `user_signedup` | New user registration | | `user_invited` | User invitation sent | @@ -75,7 +75,7 @@ Audit logs contain detailed information about each authentication event: | `factor_deleted` | MFA factor deleted | | `recovery_codes_deleted` | MFA recovery codes deleted | | `factor_updated` | MFA factor settings updated | -| `mfa_code_login` | Login with MFA code | +| `mfa_code_login` | Sign in with MFA code | | `identity_unlinked` | An identity unlinked from account | ## Limitations diff --git a/apps/docs/content/guides/auth/auth-anonymous.mdx b/apps/docs/content/guides/auth/auth-anonymous.mdx index d3d764d45f52a..5e00867dd860c 100644 --- a/apps/docs/content/guides/auth/auth-anonymous.mdx +++ b/apps/docs/content/guides/auth/auth-anonymous.mdx @@ -342,7 +342,7 @@ Be aware that a single 'restrictive' RLS policy alone will fail unless combined ## Resolving identity conflicts -Depending on your application requirements, data conflicts can arise when an anonymous user is converted to a permanent user. For example, in the context of an e-commerce application, an anonymous user would be allowed to add items to the shopping cart without signing up / signing in. When they decide to sign-in to an existing account, you will need to decide how you want to resolve data conflicts in the shopping cart: +Depending on your application requirements, data conflicts can arise when an anonymous user is converted to a permanent user. For example, in the context of an e-commerce application, an anonymous user would be allowed to add items to the shopping cart without signing up / signing in. When they decide to sign in to an existing account, you will need to decide how you want to resolve data conflicts in the shopping cart: 1. Overwrite the items in the cart with those in the existing account 2. Overwrite the items in the cart with those from the anonymous user diff --git a/apps/docs/content/guides/auth/auth-email-passwordless.mdx b/apps/docs/content/guides/auth/auth-email-passwordless.mdx index 97c8c16089920..73c5f0bc67b2c 100644 --- a/apps/docs/content/guides/auth/auth-email-passwordless.mdx +++ b/apps/docs/content/guides/auth/auth-email-passwordless.mdx @@ -1,24 +1,24 @@ --- -title: 'Passwordless email logins' -subtitle: 'Email logins using Magic Links or One-Time Passwords (OTPs)' +title: 'Passwordless email sign-in' +subtitle: 'Email sign-in using Magic Links or One-Time Passwords (OTPs)' --- -Supabase Auth provides several passwordless login methods. Passwordless logins allow users to sign in without a password, by clicking a confirmation link or entering a verification code. +Supabase Auth provides several passwordless sign-in methods. Passwordless sign-in allows users to sign in without a password, by clicking a confirmation link or entering a verification code. -Passwordless login can: +Passwordless sign-in can: - Improve the user experience by not requiring users to create and remember a password - Increase security by reducing the risk of password-related security breaches - Reduce support burden of dealing with password resets and other password-related flows -Supabase Auth offers two passwordless login methods that use the user's email address: +Supabase Auth offers two passwordless sign-in methods that use the user's email address: - [Magic Link](#with-magic-link) - [OTP](#with-otp) ## With Magic Link -Magic Links are a form of passwordless login where users click on a link sent to their email address to log in to their accounts. Magic Links only work with email addresses and are one-time use only. +Magic Links are a form of passwordless sign-in where users click on a link sent to their email address to sign in to their accounts. Magic Links only work with email addresses and are one-time use only. ### Enabling Magic Link @@ -177,7 +177,7 @@ const { error } = await supabase.auth.verifyOtp({ ## With OTP -Email one-time passwords (OTP) are a form of passwordless login where users key in a six digit code sent to their email address to log in to their accounts. +Email one-time passwords (OTP) are a form of passwordless sign-in where users key in a six-digit code sent to their email address to sign in to their accounts. ### Enabling email OTP @@ -387,7 +387,7 @@ var session = await supabase.Auth.VerifyOTP("email@example.com", "123456", Email -If successful, the user is now logged in, and you receive a valid session that looks like: +If successful, the user is now signed in, and you receive a valid session that looks like: ```json { diff --git a/apps/docs/content/guides/auth/auth-hooks/custom-access-token-hook.mdx b/apps/docs/content/guides/auth/auth-hooks/custom-access-token-hook.mdx index aeb34c9c64ec7..6d6b2b44d2d28 100644 --- a/apps/docs/content/guides/auth/auth-hooks/custom-access-token-hook.mdx +++ b/apps/docs/content/guides/auth/auth-hooks/custom-access-token-hook.mdx @@ -326,7 +326,7 @@ revoke all -You can restrict access to internal applications with a hook. For example, you can require that employees log in via [SAML Single Sign On (SSO)](/docs/guides/auth/enterprise-sso/auth-sso-saml). You can exempt select employees from the policy via an allowlist. +You can restrict access to internal applications with a hook. For example, you can require that employees sign in via [SAML Single Sign On (SSO)](/docs/guides/auth/enterprise-sso/auth-sso-saml). You can exempt select employees from the policy via an allowlist. ```sql create or replace function public.restrict_application_access(event jsonb) @@ -383,9 +383,9 @@ revoke execute Your company wishes to add assign permissions via the role claim on the `app_metadata` field. Add the role claim to the token via a Hook. ```javascript -import { Webhook } from 'https://esm.sh/standardwebhooks@1.0.0' import { readAll } from 'https://deno.land/std/io/read_all.ts' import * as base64 from 'https://denopkg.com/chiefbiiko/base64/mod.ts' +import { Webhook } from 'https://esm.sh/standardwebhooks@1.0.0' Deno.serve(async (req) => { const payload = await req.text() @@ -426,12 +426,12 @@ Deno.serve(async (req) => { -You can restrict access to internal applications with a hook. For example, you can require that employees log in via [SAML Single Sign On (SSO)](/docs/guides/auth/enterprise-sso/auth-sso-saml). You can exempt select employees from the policy via an allowlist. +You can restrict access to internal applications with a hook. For example, you can require that employees sign in via [SAML Single Sign On (SSO)](/docs/guides/auth/enterprise-sso/auth-sso-saml). You can exempt select employees from the policy via an allowlist. ```javascript -import { Webhook } from 'https://esm.sh/standardwebhooks@1.0.0' import { readAll } from 'https://deno.land/std/io/read_all.ts' import * as base64 from 'https://denopkg.com/chiefbiiko/base64/mod.ts' +import { Webhook } from 'https://esm.sh/standardwebhooks@1.0.0' Deno.serve(async (req) => { const payload = await req.text() diff --git a/apps/docs/content/guides/auth/auth-hooks/password-verification-hook.mdx b/apps/docs/content/guides/auth/auth-hooks/password-verification-hook.mdx index 003b453f30ae9..bb941179bad81 100644 --- a/apps/docs/content/guides/auth/auth-hooks/password-verification-hook.mdx +++ b/apps/docs/content/guides/auth/auth-hooks/password-verification-hook.mdx @@ -3,7 +3,7 @@ id: 'password-verification-hook' title: 'Password Verification Hook' --- -Your company wishes to increase security beyond the requirements of the default password implementation in order to fulfill security or compliance requirements. You plan to track the status of a password sign-in attempt and take action via an email or a restriction on logins where necessary. +Your company wishes to increase security beyond the requirements of the default password implementation in order to fulfill security or compliance requirements. You plan to track the status of a password sign-in attempt and take action via an email or a restriction on sign-ins where necessary. As this hook runs on unauthenticated requests, malicious users can abuse the hook by calling it multiple times. Pay extra care when using the hook as you can unintentionally block legitimate users from accessing your application. @@ -57,11 +57,11 @@ Check if a password is valid prior to taking any additional action to ensure the Return these only if your hook processed the input without errors. -| Field | Type | Description | -| -------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `decision` | `string` | The decision on whether to allow authentication to move forward. Use `reject` to deny the verification attempt and log the user out of all active sessions. Use `continue` to use the default Supabase Auth behavior. | -| `message` | `string` | The message to show the user if the decision was `reject`. | -| `should_logout_user` | `boolean` | Whether to log out the user if a `reject` decision is issued. Has no effect when a `continue` decision is issued. | +| Field | Type | Description | +| -------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `decision` | `string` | The decision on whether to allow authentication to move forward. Use `reject` to deny the verification attempt and sign out the user of all active sessions. Use `continue` to use the default Supabase Auth behavior. | +| `message` | `string` | The message to show the user if the decision was `reject`. | +| `should_logout_user` | `boolean` | Whether to sign out the user if a `reject` decision is issued. Has no effect when a `continue` decision is issued. | ```json { diff --git a/apps/docs/content/guides/auth/auth-identity-linking.mdx b/apps/docs/content/guides/auth/auth-identity-linking.mdx index abc0bc9dd0fa3..ad8dc478e8370 100644 --- a/apps/docs/content/guides/auth/auth-identity-linking.mdx +++ b/apps/docs/content/guides/auth/auth-identity-linking.mdx @@ -20,7 +20,7 @@ Users that signed up with [SAML SSO](/docs/guides/auth/enterprise-sso/auth-sso-s ### Automatic linking -Supabase Auth automatically links identities with the same email address to a single user. This helps to improve the user experience when multiple OAuth login options are presented since the user does not need to remember which OAuth account they used to sign up with. When a new user signs in with OAuth, Supabase Auth will attempt to look for an existing user that uses the same email address. If a match is found, the new identity is linked to the user. +Supabase Auth automatically links identities with the same email address to a single user. This helps to improve the user experience when multiple OAuth sign-in options are presented since the user does not need to remember which OAuth account they used to sign up with. When a new user signs in with OAuth, Supabase Auth will attempt to look for an existing user that uses the same email address. If a match is found, the new identity is linked to the user. In order for automatic linking to correctly identify the user for linking, Supabase Auth needs to ensure that all user emails are unique. It would also be an insecure practice to automatically link an identity to a user with an unverified email address since that could lead to pre-account takeover attacks. To prevent this from happening, when a new identity can be linked to an existing user, Supabase Auth will remove any other unconfirmed identities linked to an existing user. @@ -35,7 +35,7 @@ In order for automatic linking to correctly identify the user for linking, Supab > -Supabase Auth allows a user to initiate identity linking with a different email address when they are logged in. To link an OAuth identity to the user, call [`linkIdentity()`](/docs/reference/javascript/auth-linkidentity): +Supabase Auth allows a user to initiate identity linking with a different email address when they are signed in. To link an OAuth identity to the user, call [`linkIdentity()`](/docs/reference/javascript/auth-linkidentity): ```js import { createClient } from '@supabase/supabase-js' @@ -50,7 +50,7 @@ const { data, error } = await supabase.auth.linkIdentity({ provider: 'google' }) <$Show if="sdk:dart"> -Supabase Auth allows a user to initiate identity linking with a different email address when they are logged in. To link an OAuth identity to the user, call [`linkIdentity()`](/docs/reference/dart/auth-linkidentity): +Supabase Auth allows a user to initiate identity linking with a different email address when they are signed in. To link an OAuth identity to the user, call [`linkIdentity()`](/docs/reference/dart/auth-linkidentity): ```dart await supabase.auth.linkIdentity(OAuthProvider.google); @@ -61,7 +61,7 @@ await supabase.auth.linkIdentity(OAuthProvider.google); <$Show if="sdk:swift"> -Supabase Auth allows a user to initiate identity linking with a different email address when they are logged in. To link an OAuth identity to the user, call [`linkIdentity()`](/docs/reference/swift/auth-linkidentity): +Supabase Auth allows a user to initiate identity linking with a different email address when they are signed in. To link an OAuth identity to the user, call [`linkIdentity()`](/docs/reference/swift/auth-linkidentity): ```swift try await supabase.auth.linkIdentity(provider: .google) @@ -72,7 +72,7 @@ try await supabase.auth.linkIdentity(provider: .google) <$Show if="sdk:kotlin"> -Supabase Auth allows a user to initiate identity linking with a different email address when they are logged in. To link an OAuth identity to the user, call [`linkIdentity()`](/docs/reference/kotlin/auth-linkidentity): +Supabase Auth allows a user to initiate identity linking with a different email address when they are signed in. To link an OAuth identity to the user, call [`linkIdentity()`](/docs/reference/kotlin/auth-linkidentity): ```kotlin supabase.auth.linkIdentity(Google) @@ -83,7 +83,7 @@ supabase.auth.linkIdentity(Google) <$Show if="sdk:python"> -Supabase Auth allows a user to initiate identity linking with a different email address when they are logged in. To link an OAuth identity to the user, call [`link_identity()`](/docs/reference/python/auth-linkidentity): +Supabase Auth allows a user to initiate identity linking with a different email address when they are signed in. To link an OAuth identity to the user, call [`link_identity()`](/docs/reference/python/auth-linkidentity): ```python response = supabase.auth.link_identity({'provider': 'google'}) @@ -94,7 +94,7 @@ response = supabase.auth.link_identity({'provider': 'google'}) <$Show if="sdk:csharp"> -Supabase Auth allows a user to initiate identity linking with a different email address when they are logged in. To link an OAuth identity to the user, call [`LinkIdentity()`](/docs/reference/csharp/link-identity): +Supabase Auth allows a user to initiate identity linking with a different email address when they are signed in. To link an OAuth identity to the user, call [`LinkIdentity()`](/docs/reference/csharp/link-identity): ```c# var state = await supabase.Auth.LinkIdentity(Provider.Google, new SignInOptions { FlowType = OAuthFlowType.PKCE }); @@ -175,7 +175,7 @@ This method supports the same OAuth providers as `signInWithIdToken()`: Google, > -You can use [`getUserIdentities()`](/docs/reference/javascript/auth-getuseridentities) to fetch all the identities linked to a user. Then, call [`unlinkIdentity()`](/docs/reference/javascript/auth-unlinkidentity) to unlink the identity. The user needs to be logged in and have at least 2 linked identities in order to unlink an existing identity. +You can use [`getUserIdentities()`](/docs/reference/javascript/auth-getuseridentities) to fetch all the identities linked to a user. Then, call [`unlinkIdentity()`](/docs/reference/javascript/auth-unlinkidentity) to unlink the identity. The user needs to be signed in and have at least 2 linked identities in order to unlink an existing identity. ```js import { createClient } from '@supabase/supabase-js' @@ -201,7 +201,7 @@ if (!identitiesError) { <$Show if="sdk:dart"> -You can use [`getUserIdentities()`](/docs/reference/dart/auth-getuseridentities) to fetch all the identities linked to a user. Then, call [`unlinkIdentity()`](/docs/reference/dart/auth-unlinkidentity) to unlink the identity. The user needs to be logged in and have at least 2 linked identities in order to unlink an existing identity. +You can use [`getUserIdentities()`](/docs/reference/dart/auth-getuseridentities) to fetch all the identities linked to a user. Then, call [`unlinkIdentity()`](/docs/reference/dart/auth-unlinkidentity) to unlink the identity. The user needs to be signed in and have at least 2 linked identities in order to unlink an existing identity. ```dart // retrieve all identities linked to a user @@ -220,7 +220,7 @@ await supabase.auth.unlinkIdentity(googleIdentity); <$Show if="sdk:swift"> -You can use [`getUserIdentities()`](/docs/reference/swift/auth-getuseridentities) to fetch all the identities linked to a user. Then, call [`unlinkIdentity()`](/docs/reference/swift/auth-unlinkidentity) to unlink the identity. The user needs to be logged in and have at least 2 linked identities in order to unlink an existing identity. +You can use [`getUserIdentities()`](/docs/reference/swift/auth-getuseridentities) to fetch all the identities linked to a user. Then, call [`unlinkIdentity()`](/docs/reference/swift/auth-unlinkidentity) to unlink the identity. The user needs to be signed in and have at least 2 linked identities in order to unlink an existing identity. ```swift // retrieve all identities linked to a user @@ -238,7 +238,7 @@ try await supabase.auth.unlinkIdentity(googleIdentity) <$Show if="sdk:kotlin"> -You can use [`currentIdentitiesOrNull()`](/docs/reference/kotlin/auth-getuseridentities) to get all the identities linked to a user. Then, call [`unlinkIdentity()`](/docs/reference/kotlin/auth-unlinkidentity) to unlink the identity. The user needs to be logged in and have at least 2 linked identities in order to unlink an existing identity. +You can use [`currentIdentitiesOrNull()`](/docs/reference/kotlin/auth-getuseridentities) to get all the identities linked to a user. Then, call [`unlinkIdentity()`](/docs/reference/kotlin/auth-unlinkidentity) to unlink the identity. The user needs to be signed in and have at least 2 linked identities in order to unlink an existing identity. ```kotlin //get all identities linked to a user @@ -256,7 +256,7 @@ supabase.auth.unlinkIdentity(googleIdentity.identityId!!) <$Show if="sdk:python"> -You can use [`get_user_identities()`](/docs/reference/python/auth-getuseridentities) to fetch all the identities linked to a user. Then, call [`unlink_identity()`](/docs/reference/python/auth-unlinkidentity) to unlink the identity. The user needs to be logged in and have at least 2 linked identities in order to unlink an existing identity. +You can use [`get_user_identities()`](/docs/reference/python/auth-getuseridentities) to fetch all the identities linked to a user. Then, call [`unlink_identity()`](/docs/reference/python/auth-unlinkidentity) to unlink the identity. The user needs to be signed in and have at least 2 linked identities in order to unlink an existing identity. ```python # retrieve all identities linked to a user @@ -275,7 +275,7 @@ if google_identity: <$Show if="sdk:csharp"> -Use `CurrentUser.Identities` to get all the identities linked to a user. Then, call [`UnlinkIdentity()`](/docs/reference/csharp/unlink-identity) to unlink the identity. The user needs to be logged in and have at least 2 linked identities in order to unlink an existing identity. +Use `CurrentUser.Identities` to get all the identities linked to a user. Then, call [`UnlinkIdentity()`](/docs/reference/csharp/unlink-identity) to unlink the identity. The user needs to be signed in and have at least 2 linked identities in order to unlink an existing identity. ```c# // get all identities linked to the user @@ -294,7 +294,7 @@ await supabase.Auth.UnlinkIdentity(googleIdentity); ## Frequently asked questions -### How to add email/password login to an OAuth account? +### How to add email/password sign-in to an OAuth account? Call the `updateUser({ password: 'validpassword'})` to add email with password authentication to an account created with an OAuth provider (Google, GitHub, etc.). diff --git a/apps/docs/content/guides/auth/auth-mfa.mdx b/apps/docs/content/guides/auth/auth-mfa.mdx index 1a0c97bdde1f5..d90c6b96fd767 100644 --- a/apps/docs/content/guides/auth/auth-mfa.mdx +++ b/apps/docs/content/guides/auth/auth-mfa.mdx @@ -11,7 +11,7 @@ It is considered a best practice to use MFA for your applications. Users with weak passwords or compromised social login accounts are prone to malicious account takeovers. These can be prevented with MFA because they require the user to provide proof of both of these: - Something they know. - Password, or access to a social-login account. + Password, or access to a social login account. - Something they have. Access to an authenticator app (a.k.a. TOTP) or a mobile phone. @@ -24,7 +24,7 @@ Applications using MFA require two important flows: 1. **Enrollment flow.** This lets users set up and control MFA in your app. 2. **Authentication flow.** - This lets users sign in using any factors after the conventional login step. + This lets users sign in using any factors after the conventional sign-in step. Supabase Auth provides: @@ -41,9 +41,9 @@ Once users have enrolled or signed-in with a factor, Supabase Auth adds addition This information is represented by an [Authenticator Assurance Level](https://pages.nist.gov/800-63-3-Implementation-Resources/63B/AAL/), a standard measure about the assurance of the user's identity Supabase Auth has for that particular session. There are two levels recognized today: 1. **Assurance Level 1: `aal1`** - Means that the user's identity was verified using a conventional login method + Means that the user's identity was verified using a conventional sign-in method such as email+password, magic link, one-time password, phone auth or social - login. + sign-in. 2. **Assurance Level 2: `aal2`** Means that the user's identity was additionally verified using at least one second factor, such as a TOTP code or One-Time Password code. @@ -61,12 +61,12 @@ Adding MFA to your app involves these four steps: 2. **Add unenroll flow.** You need to support a UI through which users can see existing devices and unenroll devices which are no longer relevant. -3. **Add challenge step to login.** - If a user has set-up MFA, your app's login flow needs to present a challenge +3. **Add challenge step to sign in.** + If a user has set-up MFA, your app's sign-in flow needs to present a challenge screen to the user asking them to prove they have access to the additional factor. 4. **Enforce rules for MFA logins.** - Once your users have a way to enroll and log in with MFA, you need to enforce + Once your users have a way to enroll and sign in with MFA, you need to enforce authorization rules across your app: on the frontend, backend, API servers or Row-Level Security policies. @@ -291,7 +291,7 @@ If your application uses the Supabase Database, Storage or Edge Functions, Row L 2. **Retrieve the `aal` claim from the JWT and compare its value according to your needs.** If you've encountered an AAL level that can be increased, ask the user to - continue the login process instead of logging them out. + continue the sign-in process instead of logging them out. 3. **Use the `https://.supabase.co/rest/v1/auth/factors` REST endpoint to identify if the user has enrolled any MFA factors.** Only `verified` factors should be acted upon. @@ -349,7 +349,7 @@ Once you have extracted the most recent entry in the array, you can compare the Currently recognized authentication methods are: -- `oauth` - any OAuth based sign in (social login). +- `oauth` - any OAuth-based sign-in (social login). - `password` - any password based sign in. - `otp` - any one-time password based sign in (email code, SMS code, magic link). @@ -361,8 +361,8 @@ The following additional claims are available when using PKCE flow: - `invite` - any sign in via an invitation. - `magiclink` - any sign in via magic link. Excludes logins resulting from invocation of `signUp`. -- `email/signup` - any login resulting from an email signup. -- `email_change` - any login resulting from a change in email. +- `email/signup` - any sign-in resulting from an email signup. +- `email_change` - any sign-in resulting from a change in email. More authentication methods will be added over time as we increase the number of authentication methods supported by Supabase. diff --git a/apps/docs/content/guides/auth/auth-mfa/phone.mdx b/apps/docs/content/guides/auth/auth-mfa/phone.mdx index 2bf410157f7ea..8e838878353f9 100644 --- a/apps/docs/content/guides/auth/auth-mfa/phone.mdx +++ b/apps/docs/content/guides/auth/auth-mfa/phone.mdx @@ -8,7 +8,7 @@ description: 'Add an additional layer of security with phone (SMS or WhatsApp) m Phone multi-factor authentication involves a shared code generated by Supabase Auth and the end user. The code is delivered via a messaging channel, such as SMS or WhatsApp, and the user uses the code to authenticate to Supabase Auth. -The phone messaging configuration for MFA is shared with [phone auth login](/docs/guides/auth/phone-login). The same provider configuration that is used for phone login is used for MFA. You can also use the [Send SMS Hook](/docs/guides/auth/auth-hooks/send-sms-hook) if you need to use an MFA (Phone) messaging provider different from what is supported natively. +The phone messaging configuration for MFA is shared with [phone auth sign-in](/docs/guides/auth/phone-login). The same provider configuration that is used for phone sign-in is used for MFA. You can also use the [Send SMS Hook](/docs/guides/auth/auth-hooks/send-sms-hook) if you need to use an MFA (Phone) messaging provider different from what is supported natively. Below is a flow chart illustrating how the Enrollment and Verify APIs work in the context of MFA (Phone). @@ -34,14 +34,14 @@ flowchart TD In the **setup flow**, a session already at AAL1 calls the Enroll API followed by the Challenge API, which sends a code to the user over SMS or WhatsApp. The user enters the code, the Verify API checks it, and on success the session is upgraded to AAL2. An incorrect code returns the user to the code-entry step. -In the **login flow**, the user signs in (upgrading the session to AAL1) and the List Factors API is called. If the user has one or more factors, they select their phone factor and enter the code that was sent, following the same Verify path to reach AAL2. If they have no factors enrolled, they are sent through the setup flow first. +In the **sign-in flow**, the user signs in (upgrading the session to AAL1) and the List Factors API is called. If the user has one or more factors, they select their phone factor and enter the code that was sent, following the same Verify path to reach AAL2. If they have no factors enrolled, they are sent through the setup flow first. ### Add enrollment flow An enrollment flow provides a UI for users to set up additional authentication factors. Most applications add the enrollment flow in two places within their app: -1. Right after login or sign up. - This allows users to set up Multi Factor Authentication (MFA) post login or account creation. Where possible, encourage all users to set up MFA. Many applications offer this as an opt-in step in an +1. Right after sign-in or sign up. + This allows users to set up Multi Factor Authentication (MFA) post sign-in or account creation. Where possible, encourage all users to set up MFA. Many applications offer this as an opt-in step in an effort to reduce onboarding friction. 2. From within a settings page. Allows users to set up, disable or modify their MFA settings. @@ -159,9 +159,9 @@ export function EnrollMFA({ } ``` -### Add a challenge step to login +### Add a challenge step to sign in -Once a user has logged in via their first factor (email+password, magic link, one time password, social login etc.) you need to perform a check if any additional factors need to be verified. +Once a user has signed in via their first factor (email+password, magic link, one-time password, social login etc.) you need to perform a check if any additional factors need to be verified. This can be done by using the `supabase.auth.mfa.getAuthenticatorAssuranceLevel()` API. When the user signs in and is redirected back to your app, you should call this method to extract the user's current and next authenticator assurance level (AAL). @@ -178,7 +178,7 @@ Below is a table that explains the combined meaning. #### Example: React -Adding the challenge step to login depends heavily on the architecture of your app. However, a fairly common way to structure React apps is to have a large component (often named `App`) which contains most of the authenticated application logic. +Adding the challenge step to sign in depends heavily on the architecture of your app. However, a fairly common way to structure React apps is to have a large component (often named `App`) which contains most of the authenticated application logic. This example will wrap this component with logic that will show an MFA challenge screen if necessary, before showing the full application. This is illustrated in the `AppWithMFA` example below. diff --git a/apps/docs/content/guides/auth/auth-mfa/totp.mdx b/apps/docs/content/guides/auth/auth-mfa/totp.mdx index 2660dea758a70..53cf98f68b586 100644 --- a/apps/docs/content/guides/auth/auth-mfa/totp.mdx +++ b/apps/docs/content/guides/auth/auth-mfa/totp.mdx @@ -34,7 +34,7 @@ flowchart TD In the **setup flow**, a session already at AAL1 calls the Enroll API, which returns a QR code for the user to scan with their authenticator app. The user enters the generated code, the Challenge and Verify APIs check it, and on success the session is upgraded to AAL2. If the code is incorrect, the user is prompted to enter it again. -In the **login flow**, the user signs in (upgrading the session to AAL1) and the List Factors API is called. If the user has one or more factors, they open their authenticator and enter a code, which follows the same Challenge and Verify path to reach AAL2. If they have no factors enrolled, they are sent through the setup flow first. +In the **sign-in flow**, the user signs in (upgrading the session to AAL1) and the List Factors API is called. If the user has one or more factors, they open their authenticator and enter a code, which follows the same Challenge and Verify path to reach AAL2. If they have no factors enrolled, they are sent through the setup flow first. @@ -46,8 +46,8 @@ In the **login flow**, the user signs in (upgrading the session to AAL1) and the An enrollment flow provides a UI for users to set up additional authentication factors. Most applications add the enrollment flow in two places within their app: -1. Right after login or sign up. - This lets users set up MFA immediately after they log in or create an +1. Right after sign-in or sign up. + This lets users set up MFA immediately after they sign in or create an account. We recommend encouraging all users to set up MFA if that makes sense for your application. Many applications offer this as an opt-in step in an effort to reduce onboarding friction. @@ -169,9 +169,9 @@ export function EnrollMFA({ } ``` -### Add a challenge step to login +### Add a challenge step to sign in -Once a user has logged in via their first factor (email+password, magic link, one time password, social login etc.) you need to perform a check if any additional factors need to be verified. +Once a user has signed in via their first factor (email+password, magic link, one-time password, social login etc.) you need to perform a check if any additional factors need to be verified. This can be done by using the `supabase.auth.mfa.getAuthenticatorAssuranceLevel()` API. When the user signs in and is redirected back to your app, you should call this method to extract the user's current and next authenticator assurance level (AAL). @@ -188,7 +188,7 @@ Below is a table that explains the combined meaning. #### Example: React -Adding the challenge step to login depends heavily on the architecture of your app. However, a fairly common way to structure React apps is to have a large component (often named `App`) which contains most of the authenticated application logic. +Adding the challenge step to sign in depends heavily on the architecture of your app. However, a fairly common way to structure React apps is to have a large component (often named `App`) which contains most of the authenticated application logic. This example will wrap this component with logic that will show an MFA challenge screen if necessary, before showing the full application. This is illustrated in the `AppWithMFA` example below. diff --git a/apps/docs/content/guides/auth/auth-smtp.mdx b/apps/docs/content/guides/auth/auth-smtp.mdx index 7ff2e24882895..75b4e5466011d 100644 --- a/apps/docs/content/guides/auth/auth-smtp.mdx +++ b/apps/docs/content/guides/auth/auth-smtp.mdx @@ -143,7 +143,7 @@ If you are planning on having a large surge of users coming at a specific time, Consider implementing additional protections for such events: - Build a queuing or waitlist system instead of allowing direct sign-up, which will help you control the number of messages being sent from the email sending service. -- Disable email-based sign ups for the event and use social login only. Alternatively you can deprioritize the email-based sign-up flows for the event by hiding them in the UI or making them harder to reach. +- Disable email-based sign-ups for the event and use social login only. Alternatively you can deprioritize the email-based sign-up flows for the event by hiding them in the UI or making them harder to reach. **Use the Send Email Auth Hook for more control.** @@ -161,6 +161,6 @@ If you need more control over the sending process, instead of using a SMTP serve **Increase the duration of user sessions.** -Having short lived [user sessions](/docs/guides/auth/sessions) can be problematic for email sending, as it forces active users to sign-in frequently, increasing the number of messages needed to be sent. Consider increasing the maximum duration of user sessions. If you do see an unnecessary increase in logins without a clear cause, check your frontend application for bugs. +Having short-lived [user sessions](/docs/guides/auth/sessions) can be problematic for email sending, as it forces active users to sign in frequently, increasing the number of messages needed to be sent. Consider increasing the maximum duration of user sessions. If you do see an unnecessary increase in sign-ins without a clear cause, check your frontend application for bugs. -If you are using a [SSR](/docs/guides/auth/server-side) framework on the frontend and are seeing an increased number of user logins without a clear cause, check your set up. Make sure to keep the `@supabase/ssr` package up to date and closely follow the guides we publish. Make sure that the middleware components of your SSR frontend works as intended and matches the guides we've published. Sometimes a misplaced `return` or conditional can cause early session termination. +If you are using a [SSR](/docs/guides/auth/server-side) framework on the frontend and are seeing an increased number of user sign-ins without a clear cause, check your set up. Make sure to keep the `@supabase/ssr` package up to date and closely follow the guides we publish. Make sure that the middleware components of your SSR frontend works as intended and matches the guides we've published. Sometimes a misplaced `return` or conditional can cause early session termination. diff --git a/apps/docs/content/guides/auth/enterprise-sso/auth-sso-saml.mdx b/apps/docs/content/guides/auth/enterprise-sso/auth-sso-saml.mdx index c839c206fee9b..9a4d0ccc22133 100644 --- a/apps/docs/content/guides/auth/enterprise-sso/auth-sso-saml.mdx +++ b/apps/docs/content/guides/auth/enterprise-sso/auth-sso-saml.mdx @@ -79,11 +79,11 @@ Alternatively, you can use the `supabase sso info --project-ref ` User accounts and identities created via SSO differ from regular (email, phone, password, social login...) accounts in these ways: - **No identity linking.** - Each user account verified using an SSO identity provider are not legible for [identity linking](/docs/guides/auth/auth-identity-linking) to existing user accounts for security reasons. That is, if a user `valid.email@supabase.io` had signed up with a password, and then uses their company SSO login with your project, there will be two `valid.email@supabase.io` user accounts in the system. + Each user account verified using an SSO identity provider are not eligible for [identity linking](/docs/guides/auth/auth-identity-linking) to existing user accounts for security reasons. That is, if a user `valid.email@supabase.io` had signed up with a password, and then uses their company SSO sign-in with your project, there will be two `valid.email@supabase.io` user accounts in the system. - **Emails are not necessarily unique.** Given the behavior with no identity linking, email addresses are no longer a unique identifier for a user account. Always use the user's UUID to correctly reference user accounts. - **Sessions may have a maximum duration.** - Depending on the configuration of the identity provider, a login session established with SSO may forcibly log out a user after a certain period of time. + Depending on the configuration of the identity provider, a sign-in session established with SSO may forcibly sign out a user after a certain period of time. ### Row Level Security @@ -94,7 +94,7 @@ Here are some commonly used statements to extract SSO related information from t - `auth.jwt()#>>'{amr,0,method}'` Returns the name of the last method used to verify the identity of this user. With SAML SSO this is `sso/saml`. - `auth.jwt()#>>'{amr,0,provider}'` - Returns the UUID of the SSO identity provider used by the user to sign-in. + Returns the UUID of the SSO identity provider used by the user to sign in. - `auth.jwt()#>>'{user_metadata,iss}'` Returns the identity provider's SAML 2.0 `EntityID` diff --git a/apps/docs/content/guides/auth/general-configuration.mdx b/apps/docs/content/guides/auth/general-configuration.mdx index fcb98df27917b..0bc629faf7b30 100644 --- a/apps/docs/content/guides/auth/general-configuration.mdx +++ b/apps/docs/content/guides/auth/general-configuration.mdx @@ -7,7 +7,7 @@ subtitle: 'General configuration options for Supabase Auth' This section covers the [general configuration options](/dashboard/project/_/auth) for Supabase Auth. If you are looking for another type of configuration, you may be interested in one of the following sections: - [Policies](/dashboard/project/_/database/policies) to manage Row Level Security policies for your tables. -- [Sign In / Providers](/dashboard/project/_/auth/providers) to configure authentication providers and login methods for your users. +- [Sign In / Providers](/dashboard/project/_/auth/providers) to configure authentication providers and sign-in methods for your users. - [Third Party Auth](/dashboard/project/_/auth/third-party) to use third-party authentication (TPA) systems based on JWTs to access your project. - [Sessions](/dashboard/project/_/auth/sessions) to configure settings for user sessions and refresh tokens. - [Rate limits](/dashboard/project/_/auth/rate-limits) to safeguard against bursts of incoming traffic to prevent abuse and maximize stability. @@ -25,7 +25,7 @@ Supabase Auth provides these [general configuration options](/dashboard/project/ - **Allow new users to sign up**: Users will be able to sign up. If this config is disabled, only existing users can sign in. - **Confirm Email**: Users will need to confirm their email address before signing in for the first time. - - Having **Confirm Email** disabled assumes that the user's email does not need to be verified in order to login and implicitly confirms the user's email in the database. + - Having **Confirm Email** disabled assumes that the user's email does not need to be verified in order to sign in and implicitly confirms the user's email in the database. - This option can be found in the email provider under the provider-specific configuration. {/* - If you previously relied on this config to autoconfirm a user's email address, you can switch to use **Allow unverified email sign in** instead. This new option allows the user to sign in with an unverified email which you can keep track of through the user object. It provides more versatility if you require your users to verify their email address in the future since you can structure your RLS policies to check the user's `email_verified` field. */} diff --git a/apps/docs/content/guides/auth/oauth-server/getting-started.mdx b/apps/docs/content/guides/auth/oauth-server/getting-started.mdx index eded448adc3fd..1e5eea02e5572 100644 --- a/apps/docs/content/guides/auth/oauth-server/getting-started.mdx +++ b/apps/docs/content/guides/auth/oauth-server/getting-started.mdx @@ -163,7 +163,7 @@ This is where you build the **frontend** for your authorization flow. When third Your authorization UI should: 1. **Extract authorization_id** - Get the `authorization_id` from the URL query parameters -2. **Authenticate the user** - If not already logged in, redirect to your login page (preserving the authorization_id) +2. **Authenticate the user** - If not already signed in, redirect to your sign-in page (preserving the authorization_id) 3. **Retrieve authorization details** - Use `supabase.auth.oauth.getAuthorizationDetails(authorization_id)` to get client information including requested scopes 4. **Display consent screen** - Show the user what app is requesting access and what scopes/permissions are being requested 5. **Handle user decision** - Call either `approveAuthorization(authorization_id)` or `denyAuthorization(authorization_id)` based on user choice @@ -455,7 +455,7 @@ export function OAuthConsent() { 1. **User navigates to your authorization path** - When a third-party app initiates OAuth, Supabase Auth redirects the user to your configured authorization path (e.g., `https://example.com/oauth/consent?authorization_id=`) 2. **Extract authorization_id** - Your page extracts the `authorization_id` from the URL query parameters -3. **Check authentication** - Your page checks if the user is logged in, redirecting to login if not (preserving the authorization_id) +3. **Check authentication** - Your page checks if the user is signed in, redirecting to sign in if not (preserving the authorization_id) 4. **Retrieve details** - Call `supabase.auth.oauth.getAuthorizationDetails(authorization_id)` to get information about the requesting client 5. **Show consent screen** - Display a UI asking the user to approve or deny access 6. **Handle decision** - When the user clicks approve/deny: diff --git a/apps/docs/content/guides/auth/oauth-server/oauth-flows.mdx b/apps/docs/content/guides/auth/oauth-server/oauth-flows.mdx index 855391dca71f5..f67a2951508e5 100644 --- a/apps/docs/content/guides/auth/oauth-server/oauth-flows.mdx +++ b/apps/docs/content/guides/auth/oauth-server/oauth-flows.mdx @@ -35,7 +35,7 @@ The flow consists of several steps: 1. **Client initiates authorization** - Third-party app redirects user to Supabase Auth's authorize endpoint 2. **Supabase validates and redirects** - Supabase Auth validates OAuth parameters and redirects user to your configured authorization URL -3. **User authenticates and authorizes** - Your frontend checks if user is logged in, shows consent screen, and handles approval/denial +3. **User authenticates and authorizes** - Your frontend checks if user is signed in, shows consent screen, and handles approval/denial 4. **Authorization code issued** - Supabase Auth generates a short-lived authorization code and redirects back to client 5. **Code exchange** - Client exchanges the code for tokens 6. **Access granted** - Client receives access token, refresh token, and ID token @@ -184,7 +184,7 @@ Your frontend application at the authorization path should: 1. **Extract authorization_id** - Get the `authorization_id` from the URL query parameters 2. **Fetch authorization details** - Call `supabase.auth.oauth.getAuthorizationDetails(authorization_id)` to retrieve information about the OAuth client and request parameters -3. **Check user authentication** - Verify if the user is logged in; if not, redirect to your login page (preserving the full authorization path including the `authorization_id`). After successful login, redirect the user back to the authorization path with the same `authorization_id` query parameter +3. **Check user authentication** - Verify if the user is signed in; if not, redirect to your sign-in page (preserving the full authorization path including the `authorization_id`). After successful sign-in, redirect the user back to the authorization path with the same `authorization_id` query parameter 4. **Display consent screen** - Show the user information about the requesting client (name, redirect URI, scopes) 5. **Handle user decision** - When the user approves or denies: - Call `supabase.auth.oauth.approveAuthorization(authorization_id)` to approve diff --git a/apps/docs/content/guides/auth/password-security.mdx b/apps/docs/content/guides/auth/password-security.mdx index 479ff4955a509..428aaeb26f1b8 100644 --- a/apps/docs/content/guides/auth/password-security.mdx +++ b/apps/docs/content/guides/auth/password-security.mdx @@ -16,7 +16,7 @@ This table shows the _minimum_ number of guesses that need to be tried to access In reality though, passwords are not always generated at random. They often contain variations of names, words, dates, and common phrases. Malicious actors can use these properties to guess a password in fewer attempts. -There are hundreds of millions (and growing!) known passwords out there. Malicious actors can use these lists of leaked passwords to automate login attempts (known as credential stuffing) and steal or access sensitive user data. +There are hundreds of millions (and growing!) known passwords out there. Malicious actors can use these lists of leaked passwords to automate sign-in attempts (known as credential stuffing) and steal or access sensitive user data. ## Password strength and leaked password protection diff --git a/apps/docs/content/guides/auth/phone-login.mdx b/apps/docs/content/guides/auth/phone-login.mdx index 7700b558b681a..9b48256870a1e 100644 --- a/apps/docs/content/guides/auth/phone-login.mdx +++ b/apps/docs/content/guides/auth/phone-login.mdx @@ -1,9 +1,9 @@ --- -title: 'Phone Login' -description: 'Learn about logging in to your platform using SMS one-time passwords.' +title: 'Phone sign-in' +description: 'Learn about signing in to your platform using SMS one-time passwords.' --- -Phone Login is a method of authentication that allows users to log in to a website or application without using a password. The user authenticates through a one-time password (OTP) sent via a channel (SMS or WhatsApp). +Phone sign-in is a method of authentication that allows users to sign in to a website or application without using a password. The user authenticates through a one-time password (OTP) sent via a channel (SMS or WhatsApp). @@ -11,9 +11,9 @@ At this time, `WhatsApp` is only supported as a channel for the Twilio and Twili -Users can also log in with their phones using Native Mobile Login with the built-in identity provider. For Native Mobile Login with Android and iOS, see the [Social Login guides](/docs/guides/auth/social-login). +Users can also sign in with their phones using Native Mobile Login with the built-in identity provider. For Native Mobile Login with Android and iOS, see the [social login guides](/docs/guides/auth/social-login). -Phone OTP login can: +Phone OTP sign-in can: - Improve the user experience by not requiring users to create and remember a password - Increase security by reducing the risk of password-related security breaches @@ -21,7 +21,7 @@ Phone OTP login can: <$Partial path="cost_warning.mdx" /> -## Enabling phone login +## Enabling phone sign-in Enable phone authentication on the [Auth Providers page](/dashboard/project/_/auth/providers) for hosted Supabase projects. @@ -229,7 +229,7 @@ curl -X POST 'https://.supabase.co/auth/v1/verify' \ -If successful the user will now be logged in and you should receive a valid session like: +If successful, the user will now be signed in and you should receive a valid session like: ```json { @@ -244,7 +244,7 @@ The access token can be sent in the Authorization header as a Bearer token for a ## Updating a phone number -To update a user's phone number, the user must be logged in. Call [`updateUser()`](/docs/reference/javascript/auth-updateuser) with their phone number: +To update a user's phone number, the user must be signed in. Call [`updateUser()`](/docs/reference/javascript/auth-updateuser) with their phone number: - + Create a helper file `lib/supabase.ts` that exports a Supabase client using your Project URL and key. @@ -90,9 +90,9 @@ hideToc: true - + - Create a React Native component to manage logins and sign ups. The app later uses the [`getClaims`](/docs/reference/javascript/auth-getclaims) method in `App.tsx` to validate the local JWT before showing the signed-in user. + Create a React Native component to manage sign-ins and sign-ups. The app later uses the [`getClaims`](/docs/reference/javascript/auth-getclaims) method in `App.tsx` to validate the local JWT before showing the signed-in user. @@ -111,7 +111,7 @@ hideToc: true - Add the `Auth` component to your `App.tsx` file. If the user is logged in, print the user id to the screen. + Add the `Auth` component to your `App.tsx` file. If the user is signed in, print the user id to the screen. diff --git a/apps/docs/content/guides/auth/quickstarts/react.mdx b/apps/docs/content/guides/auth/quickstarts/react.mdx index f624e8d03eced..a8ac9181ab478 100644 --- a/apps/docs/content/guides/auth/quickstarts/react.mdx +++ b/apps/docs/content/guides/auth/quickstarts/react.mdx @@ -83,7 +83,7 @@ hideToc: true - + <$Partial path="uiLibCta.mdx" /> @@ -121,7 +121,7 @@ hideToc: true - Start the app, go to http://localhost:5173 in a browser, and open the browser console and you should be able to register and log in. + Start the app, go to http://localhost:5173 in a browser, and open the browser console and you should be able to register and sign in. diff --git a/apps/docs/content/guides/auth/quickstarts/with-expo-react-native-social-auth.mdx b/apps/docs/content/guides/auth/quickstarts/with-expo-react-native-social-auth.mdx index 4646c475d567e..dda461e87e2d4 100644 --- a/apps/docs/content/guides/auth/quickstarts/with-expo-react-native-social-auth.mdx +++ b/apps/docs/content/guides/auth/quickstarts/with-expo-react-native-social-auth.mdx @@ -6,7 +6,7 @@ description: 'Learn how to implement social authentication in an app with Expo R This tutorial demonstrates how to build a React Native app with [Expo](https://expo.dev) that implements social authentication. The app showcases a complete authentication flow with protected navigation using: - [Supabase Database](/docs/guides/database/overview) - a Postgres database for storing your user data with [Row Level Security](/docs/guides/auth#row-level-security) to ensure data is protected and users can only access their own information. -- [Supabase Auth](/docs/guides/auth) - enables users to log in through social authentication providers (Apple and Google). +- [Supabase Auth](/docs/guides/auth) - enables users to sign in through social authentication providers (Apple and Google). ![Supabase Social Auth example](/docs/img/supabase-expo-social-auth-login.png) @@ -129,9 +129,9 @@ lines={[[1, -1]]} meta="name=components/splash-screen-controller.tsx" /> -### Create a logout component +### Create a sign-out component -Create a logout button component to handle user sign-out: +Create a sign-out button component to handle user sign-out: <$CodeSample path="/auth/expo-social-auth/components/social-auth-buttons/sign-out-button.tsx" @@ -139,7 +139,7 @@ lines={[[1, -1]]} meta="name=components/social-auth-buttons/sign-out-button.tsx" /> -And add it to the `app/(tabs)/index.tsx` file used to display the user profile data and the logout button: +And add it to the `app/(tabs)/index.tsx` file used to display the user profile data and the sign-out button: <$CodeSample path="/auth/expo-social-auth/app/(tabs)/index.tsx" @@ -147,9 +147,9 @@ lines={[[1, -1]]} meta="name=app/(tabs)/index.tsx" /> -### Create a login screen +### Create a sign-in screen -Next, create a basic login screen component: +Next, create a basic sign-in screen component: <$CodeSample path="/auth/expo-social-auth/app/login.tsx" @@ -177,7 +177,7 @@ npx expo prebuild npx expo start --clear ``` -Verify that the app works as expected. The splash screen displays while fetching the user profile, and the login page appears even when attempting to navigate to the home screen using the `Link` button. +Verify that the app works as expected. The splash screen displays while fetching the user profile, and the sign-in page appears even when attempting to navigate to the home screen using the `Link` button. @@ -194,7 +194,7 @@ If you only need to implement Google authentication, you can skip to the [Google ### Apple authentication -Start by adding the button inside the login screen: +Start by adding the button inside the sign-in screen: <$CodeTabs> @@ -237,7 +237,7 @@ npx expo start --tunnel And add it to the **Redirect URLs** field in [your Supabase dashboard Authentication configuration](/dashboard/project/_/auth/url-configuration). -For more information, follow the [Supabase Login with Apple](/docs/guides/auth/social-login/auth-apple) guide. +For more information, follow the [Supabase Sign in with Apple](/docs/guides/auth/social-login/auth-apple) guide. @@ -343,7 +343,7 @@ For more information, follow the [Supabase Login with Apple](/docs/guides/auth/s npx expo run:ios --no-build-cache --device ``` - You should see the login screen with the Apple authentication button. + You should see the sign-in screen with the Apple authentication button. @@ -466,7 +466,7 @@ For more information, follow the [Supabase Login with Apple](/docs/guides/auth/s ### Google authentication -Start by adding the button to the login screen: +Start by adding the button to the sign-in screen: <$CodeTabs> @@ -543,7 +543,7 @@ EXPO_PUBLIC_GOOGLE_AUTH_WEB_CLIENT_ID="YOUR_GOOGLE_AUTH_WEB_CLIENT_ID" npx expo run:ios && npx expo run:android ``` - You should see the login screen with the Google authentication button. + You should see the sign-in screen with the Google authentication button. ![Supabase Social Auth example](/docs/img/supabase-expo-social-auth-tabs.png) diff --git a/apps/docs/content/guides/auth/sessions.mdx b/apps/docs/content/guides/auth/sessions.mdx index 2a4083b87a2a1..a7e2c6cc13f8c 100644 --- a/apps/docs/content/guides/auth/sessions.mdx +++ b/apps/docs/content/guides/auth/sessions.mdx @@ -115,7 +115,7 @@ It's better for cost optimization and scaling as well, as the authentication sys Most applications rarely need such strong guarantees. Consider adjusting the JWT expiry time to an acceptable value. If this is still necessary, you should try to use this validation logic only for the most sensitive actions within your application. -When a user signs out, the sessions affected by the logout are removed from the database entirely. You can check that the `session_id` claim in the JWT corresponds to a row in the `auth.sessions` table. If such a row does not exist, it means that the user has logged out. +When a user signs out, the sessions affected by the sign-out are removed from the database entirely. You can check that the `session_id` claim in the JWT corresponds to a row in the `auth.sessions` table. If such a row does not exist, it means that the user has signed out. Note that sessions are not proactively terminated when their maximum lifetime (time-box) or inactivity timeout are reached. These sessions are cleaned up progressively 24 hours after reaching that status. This allows you to tweak the values or roll back changes without causing unintended user friction. diff --git a/apps/docs/content/guides/auth/social-login.mdx b/apps/docs/content/guides/auth/social-login.mdx index 6433597e5832e..cdcb87370fe80 100644 --- a/apps/docs/content/guides/auth/social-login.mdx +++ b/apps/docs/content/guides/auth/social-login.mdx @@ -1,20 +1,20 @@ --- -title: 'Social Login' -description: 'Logging in with social accounts' +title: 'Social login' +description: 'Signing in with social accounts' --- -Social Login (OAuth) is an open standard for authentication that allows users to log in to one website or application using their credentials from another website or application. OAuth allows users to grant third-party applications access to their online accounts without sharing their passwords. -OAuth is commonly used for things like logging in to a social media account from a third-party app. It is a secure and convenient way to authenticate users and share information between applications. +Social login (OAuth) is an open standard for authentication that allows users to sign in to one website or application using their credentials from another website or application. OAuth allows users to grant third-party applications access to their online accounts without sharing their passwords. +OAuth is commonly used for things like signing in to a social media account from a third-party app. It is a secure and convenient way to authenticate users and share information between applications. ## Benefits There are several reasons why you might want to add social login to your applications: -- **Improved user experience**: Users can register and log in to your application using their existing social media accounts, which can be faster and more convenient than creating a new account from scratch. This makes it easier for users to access your application, improving their overall experience. +- **Improved user experience**: Users can register and sign in to your application using their existing social media accounts, which can be faster and more convenient than creating a new account from scratch. This makes it easier for users to access your application, improving their overall experience. - **Better user engagement**: You can access additional data and insights about your users, such as their interests, demographics, and social connections. This can help you tailor your content and marketing efforts to better engage with your users and provide a more personalized experience. -- **Increased security**: Social login can improve the security of your application by leveraging the security measures and authentication protocols of the social media platforms that your users are logging in with. This can help protect against unauthorized access and account takeovers. +- **Increased security**: Social login can improve the security of your application by leveraging the security measures and authentication protocols of the social media platforms that your users are signing in with. This can help protect against unauthorized access and account takeovers. ## Set up a social provider with Supabase Auth diff --git a/apps/docs/content/guides/auth/social-login/auth-apple.mdx b/apps/docs/content/guides/auth/social-login/auth-apple.mdx index 78b8d9b0569fa..e98435a57ac12 100644 --- a/apps/docs/content/guides/auth/social-login/auth-apple.mdx +++ b/apps/docs/content/guides/auth/social-login/auth-apple.mdx @@ -1,6 +1,6 @@ --- id: 'auth-apple' -title: 'Login with Apple' +title: 'Sign in with Apple' description: 'Use Sign in with Apple with Supabase' tocVideo: '-tpcZzTdvN0' --- diff --git a/apps/docs/content/guides/auth/social-login/auth-azure.mdx b/apps/docs/content/guides/auth/social-login/auth-azure.mdx index 5d0dd8a3b6033..1c02a4ca4dbd1 100644 --- a/apps/docs/content/guides/auth/social-login/auth-azure.mdx +++ b/apps/docs/content/guides/auth/social-login/auth-azure.mdx @@ -1,6 +1,6 @@ --- id: 'auth-azure' -title: 'Login with Azure (Microsoft)' +title: 'Sign in with Azure (Microsoft)' description: 'Add Azure (Microsoft) OAuth to your Supabase project' --- @@ -18,7 +18,7 @@ Setting up OAuth with Azure consists of four broad steps: ## Access your Azure Developer account - Go to [portal.azure.com](https://portal.azure.com/#home). -- Login and select Microsoft Entra ID under the list of Azure Services. +- Sign in and select Microsoft Entra ID under the list of Azure Services. ## Register an application @@ -140,7 +140,7 @@ If your app is registered as _My organization only_ for the _Supported account t Configure this by storing a value under _Azure Tenant URL_ in the Supabase Auth provider configuration page for Azure that has the following format `https://login.microsoftonline.com/`. -## Add login code to your client app +## Add sign-in code to your client app diff --git a/apps/docs/content/guides/auth/social-login/auth-bitbucket.mdx b/apps/docs/content/guides/auth/social-login/auth-bitbucket.mdx index 45c9dc8a3b299..a482b25519043 100644 --- a/apps/docs/content/guides/auth/social-login/auth-bitbucket.mdx +++ b/apps/docs/content/guides/auth/social-login/auth-bitbucket.mdx @@ -1,6 +1,6 @@ --- id: 'auth-bitbucket' -title: 'Login with Bitbucket' +title: 'Sign in with Bitbucket' description: 'Add Bitbucket OAuth to your Supabase project' --- @@ -8,16 +8,16 @@ To enable Bitbucket Auth for your project, you need to set up a Bitbucket OAuth ## Overview -Setting up Bitbucket logins for your application consists of 3 parts: +Setting up Bitbucket sign-in for your application consists of 3 parts: - Create and configure a Bitbucket OAuth Consumer on [Bitbucket](https://bitbucket.org) - Add your Bitbucket OAuth Consumer keys to your [Supabase Project](/dashboard) -- Add the login code to your [Supabase JS Client App](https://github.com/supabase/supabase-js) +- Add the sign-in code to your [Supabase JS Client App](https://github.com/supabase/supabase-js) ## Access your Bitbucket account - Go to [bitbucket.org](https://bitbucket.org/). -- Click on `Login` at the top right to log in. +- Click on `Login` at the top right to sign in. ![Bitbucket Developer Portal.](/docs/img/guides/auth-bitbucket/bitbucket-portal.png) @@ -44,7 +44,7 @@ Setting up Bitbucket logins for your application consists of 3 parts: <$Partial path="social_provider_settings_supabase.mdx" variables={{ "provider": "BitBucket" }} /> -## Add login code to your client app +## Add sign-in code to your client app -## Set up Facebook login for your Facebook app +## Set up Facebook sign-in for your Facebook app From the `Add Products to your App` screen: @@ -99,7 +99,7 @@ curl -X PATCH "https://api.supabase.com/v1/projects/$PROJECT_REF/config/auth" \ }' ``` -## Add login code to your client app +## Add sign-in code to your client app .supabase.co/auth/v1/callback`. Make sure there are no trailing slashes or typos. -### Login works in development but not production +### Sign-in works in development but not production -If login works locally but fails in production, check: +If sign-in works locally but fails in production, check: - Your production URL is added to **Valid OAuth Redirect URIs** in Facebook - The App ID and Secret in your Supabase dashboard match your Facebook app diff --git a/apps/docs/content/guides/auth/social-login/auth-figma.mdx b/apps/docs/content/guides/auth/social-login/auth-figma.mdx index 1c3a0864d31c4..1148249d6c941 100644 --- a/apps/docs/content/guides/auth/social-login/auth-figma.mdx +++ b/apps/docs/content/guides/auth/social-login/auth-figma.mdx @@ -1,6 +1,6 @@ --- id: 'auth-figma' -title: 'Login with Figma' +title: 'Sign in with Figma' description: 'Add Figma OAuth to your Supabase project' --- @@ -8,16 +8,16 @@ To enable Figma Auth for your project, you need to set up a Figma OAuth applicat ## Overview -Setting up Figma logins for your application consists of 3 parts: +Setting up Figma sign-in for your application consists of 3 parts: - Create and configure a Figma App on the [Figma Developers page](https://www.figma.com/developers/apps). - Add your Figma `client_id` and `client_secret` to your [Supabase Project](https://app.supabase.com). -- Add the login code to your [Supabase JS Client App](https://github.com/supabase/supabase-js). +- Add the sign-in code to your [Supabase JS Client App](https://github.com/supabase/supabase-js). ## Access the Figma Developers page - Go to the [Figma Developers page](https://www.figma.com/developers/apps) -- Log in (if necessary) +- Sign in (if necessary) ## Find your callback URL @@ -44,7 +44,7 @@ Setting up Figma logins for your application consists of 3 parts: <$Partial path="social_provider_settings_supabase.mdx" variables={{ "provider": "Figma" }} /> -## Add login code to your client app +## Add sign-in code to your client app -## Add login code to your client app +## Add sign-in code to your client app -## Add login code to your client app +## Add sign-in code to your client app -Setting up Slack logins for your application consists of 3 parts: +Setting up Slack sign-in for your application consists of 3 parts: - Create and configure a Slack Project and App on the [Slack Developer Dashboard](https://api.slack.com/apps). - Add your Slack `API Key` and `API Secret Key` to your [Supabase Project](/dashboard). -- Add the login code to your [Supabase JS Client App](https://github.com/supabase/supabase-js). +- Add the sign-in code to your [Supabase JS Client App](https://github.com/supabase/supabase-js). ## Access your Slack Developer account - Go to [api.slack.com](https://api.slack.com/apps). -- Click on `Your Apps` at the top right to log in. +- Click on `Your Apps` at the top right to sign in. ![Slack Developer Portal.](/docs/img/guides/auth-slack/slack-portal.png) @@ -80,7 +80,7 @@ curl -X PATCH "https://api.supabase.com/v1/projects/$PROJECT_REF/config/auth" \ }' ``` -## Add login code to your client app +## Add sign-in code to your client app -## Add login code to your client app +## Add sign-in code to your client app -Setting up X / Twitter logins for your application consists of 3 parts: +Setting up X / Twitter sign-in for your application consists of 3 parts: - Create and configure an X Project and App on the [X Developer Dashboard](https://developer.x.com/en/portal/dashboard). - Add your X OAuth 2.0 `Client ID` and `Client Secret` to your [Supabase Project](/dashboard). -- Add the login code to your [Supabase JS Client App](https://github.com/supabase/supabase-js). +- Add the sign-in code to your [Supabase JS Client App](https://github.com/supabase/supabase-js). ## Access your X developer account - Go to [developer.x.com](https://developer.x.com). -- Click on `Sign in` at the top right to log in. +- Click on `Sign in` at the top right to sign in. ## Find your callback URL @@ -77,7 +77,7 @@ curl -X PATCH "https://api.supabase.com/v1/projects/$PROJECT_REF/config/auth" \ }' ``` -## Add login code to your client app +## Add sign-in code to your client app ```typescript -import { createClient } from '@supabase/supabase-js' import { createAuth0Client } from '@auth0/auth0-spa-js' +import { createClient } from '@supabase/supabase-js' const auth0 = await createAuth0Client({ domain: '', diff --git a/apps/docs/content/guides/auth/users.mdx b/apps/docs/content/guides/auth/users.mdx index 0ad2d0c0eff73..60e40de3b4b92 100644 --- a/apps/docs/content/guides/auth/users.mdx +++ b/apps/docs/content/guides/auth/users.mdx @@ -67,7 +67,7 @@ The user object contains the following attributes: | phone_confirmed_at | `string` | The timestamp that the user's phone was confirmed. If null, it means that the user's phone is not confirmed. | | confirmed_at | `string` | The timestamp that either the user's email or phone was confirmed. If null, it means that the user does not have a confirmed email address and phone number. | | last_sign_in_at | `string` | The timestamp that the user last signed in. | -| app_metadata | `object` | The `provider` attribute indicates the first provider that the user used to sign up with. The `providers` attribute indicates the list of providers that the user can use to login with. | +| app_metadata | `object` | The `provider` attribute indicates the first provider that the user used to sign up with. The `providers` attribute indicates the list of providers that the user can use to sign in with. | | user_metadata | `object` | Defaults to the first provider's identity data but can contain additional custom user metadata if specified. Refer to [**User Identity**](/docs/guides/auth/auth-identity-linking#the-user-identity) for more information about the identity object. Don't rely on the order of information in this field. Do not use it in security sensitive context (such as in RLS policies or authorization logic), as this value is editable by the user without any checks. | | identities | `UserIdentity[]` | Contains an object array of identities linked to the user. | | created_at | `string` | The timestamp that the user was created. | diff --git a/apps/docs/content/guides/database/connection-management.mdx b/apps/docs/content/guides/database/connection-management.mdx index 1d3910dbea44b..91d54ef6e4ce0 100644 --- a/apps/docs/content/guides/database/connection-management.mdx +++ b/apps/docs/content/guides/database/connection-management.mdx @@ -47,11 +47,11 @@ For Teams and Enterprise plans, Supabase provides Advanced Telemetry charts dire This chart helps you monitor connection pool usage, identify connection leaks, and plan capacity. It also shows a reference line for your compute size's maximum connection limit. -For more details on using these monitoring charts, see the [Reports guide](/docs/guides/monitoring-and-debugging/reports#advanced-telemetry). +For more details on using these monitoring charts, see the [Reports guide](/docs/guides/observability/reports#advanced-telemetry). #### Grafana Dashboard -Supabase offers a Grafana Dashboard that records and visualizes over 200 project metrics, including connections. For setup instructions, check the [metrics docs](/docs/guides/monitoring-and-debugging/metrics). +Supabase offers a Grafana Dashboard that records and visualizes over 200 project metrics, including connections. For setup instructions, check the [metrics docs](/docs/guides/observability/metrics). Its "Client Connections" graph displays connections for both Supavisor and Postgres ![client connection graph](/docs/img/database/grafana-connections.png) diff --git a/apps/docs/content/guides/database/custom-postgres-config.mdx b/apps/docs/content/guides/database/custom-postgres-config.mdx index 0fc8f870b953f..26cb649347d6a 100644 --- a/apps/docs/content/guides/database/custom-postgres-config.mdx +++ b/apps/docs/content/guides/database/custom-postgres-config.mdx @@ -166,7 +166,7 @@ Use the examples below with `supabase postgres-config update --project-ref diff --git a/apps/docs/content/guides/database/extensions/pgaudit.mdx b/apps/docs/content/guides/database/extensions/pgaudit.mdx index 5df317f86d733..78b20cff9fd91 100644 --- a/apps/docs/content/guides/database/extensions/pgaudit.mdx +++ b/apps/docs/content/guides/database/extensions/pgaudit.mdx @@ -388,5 +388,5 @@ PGAudit's [official documentation](https://www.pgaudit.org) focuses on system an - [Official `PGAudit` documentation](https://www.pgaudit.org) - [Database Function Logging](/docs/guides/database/functions#general-logging) -- [Supabase Logging](/docs/guides/monitoring-and-debugging/logs) +- [Supabase Logging](/docs/guides/observability/logs) - [Self-Hosting Logs](/docs/reference/self-hosting-analytics/introduction) diff --git a/apps/docs/content/guides/database/extensions/pgvector.mdx b/apps/docs/content/guides/database/extensions/pgvector.mdx index 81771089f4b28..5b114611f3631 100644 --- a/apps/docs/content/guides/database/extensions/pgvector.mdx +++ b/apps/docs/content/guides/database/extensions/pgvector.mdx @@ -80,6 +80,7 @@ In this example we'll generate a vector using Transformer.js, then store it in t ```js import { pipeline } from '@xenova/transformers' + const generateEmbedding = await pipeline('feature-extraction', 'Supabase/gte-small') const title = 'First post!' diff --git a/apps/docs/content/guides/database/postgres/data-deletion.mdx b/apps/docs/content/guides/database/postgres/data-deletion.mdx index a686cf8bd9ab4..e0ec7168e8235 100644 --- a/apps/docs/content/guides/database/postgres/data-deletion.mdx +++ b/apps/docs/content/guides/database/postgres/data-deletion.mdx @@ -200,6 +200,6 @@ The most efficient way to reclaim disk space, without locks, is to use [pg_repac ## Related links - [Safe Cascading Deletes](/docs/guides/database/postgres/cascade-deletes) -- [Inspecting your Database](/docs/guides/database/inspect) +- [Inspect the database](/docs/guides/observability/inspect) - [Understanding Database and Disk Size](/docs/guides/platform/database-size) - [Bloat in Postgres](/blog/postgres-bloat) diff --git a/apps/docs/content/guides/database/postgres/roles.mdx b/apps/docs/content/guides/database/postgres/roles.mdx index 9b46fe8ed3fbc..bcfba68a6b4a0 100644 --- a/apps/docs/content/guides/database/postgres/roles.mdx +++ b/apps/docs/content/guides/database/postgres/roles.mdx @@ -88,7 +88,7 @@ The default Postgres role. This has admin privileges. ### `anon` -For unauthenticated, public access. This is the role which the API (PostgREST) will use when a user _is not_ logged in. +For unauthenticated, public access. This is the role which the API (PostgREST) will use when a user _is not_ signed in. ### `authenticator` @@ -97,7 +97,7 @@ A special role for the API (PostgREST). It has very limited access, and is used ### `authenticated` -For "authenticated access." This is the role which the API (PostgREST) will use when a user _is_ logged in. +For "authenticated access." This is the role which the API (PostgREST) will use when a user _is_ signed in. ### `service_role` diff --git a/apps/docs/content/guides/database/postgres/row-level-security.mdx b/apps/docs/content/guides/database/postgres/row-level-security.mdx index 41e3f4dd48b37..7e1f717331c85 100644 --- a/apps/docs/content/guides/database/postgres/row-level-security.mdx +++ b/apps/docs/content/guides/database/postgres/row-level-security.mdx @@ -69,8 +69,8 @@ A missing grant raises a `42501` error before any policy runs. When a request fa Supabase maps every request to one of the roles: -- `anon`: an unauthenticated request (the user is not logged in) -- `authenticated`: an authenticated request (the user is logged in) +- `anon`: an unauthenticated request (the user is not signed in) +- `authenticated`: an authenticated request (the user is signed in) These are [Postgres Roles](/docs/guides/database/postgres/roles). You can use these roles within your Policies using the `TO` clause: diff --git a/apps/docs/content/guides/database/replication/manual-replication-monitoring.mdx b/apps/docs/content/guides/database/replication/manual-replication-monitoring.mdx index 0eaf48c40ee7b..aa4d5e38e8bb8 100644 --- a/apps/docs/content/guides/database/replication/manual-replication-monitoring.mdx +++ b/apps/docs/content/guides/database/replication/manual-replication-monitoring.mdx @@ -8,12 +8,12 @@ sidebar_label: 'Monitoring' Monitoring replication lag is important and there are 3 ways to do this: -1. Dashboard - In [Reports](/docs/guides/monitoring-and-debugging/reports), you can view the replication lag of your project +1. Dashboard - In [Reports](/docs/guides/observability/reports), you can view the replication lag of your project 2. Database - - pg_stat_subscription (subscriber) - if PID is null, then the subscription is not active - pg_stat_subscription_stats - look here for error_count to see if there were issues applying or syncing (if yes, check the logs for why) - pg_replication_slots - use this to check if the slot is active and you can also calculate the lag from here -3. [Metrics](/docs/guides/monitoring-and-debugging/metrics) - Using the prometheus endpoint for your project +3. [Metrics](/docs/guides/observability/metrics) - Using the prometheus endpoint for your project - replication_slots_max_lag_bytes - this is the more important one - pg_stat_replication_replay_lag - lag to replay WAL files from the source DB on the target DB (throttled by disk or high activity) - pg_stat_replication_send_lag - lag in sending WAL files from the source DB (a high lag means that the publisher is not being asked to send new WAL files OR network issues) diff --git a/apps/docs/content/guides/database/secure-data.mdx b/apps/docs/content/guides/database/secure-data.mdx index b554a772019bc..7f41378fbf0e4 100644 --- a/apps/docs/content/guides/database/secure-data.mdx +++ b/apps/docs/content/guides/database/secure-data.mdx @@ -28,7 +28,7 @@ For frontend apps, the Data API is the usual choice. You can keep your data secu - Turn on [Row Level Security](/docs/guides/database/postgres/row-level-security) (RLS) for your tables and properly configure your access policies to grant the least privileges necessary for your app to function - Use your Supabase **publishable key** when you create a Supabase client -Your publishable key is safe to expose with RLS enabled, because row access permission is checked against your access policies and the user's [JSON Web Token (JWT)](/docs/learn/auth-deep-dive/auth-deep-dive-jwts). The JWT is automatically sent by the Supabase client libraries if the user is logged in using Supabase Auth. +Your publishable key is safe to expose with RLS enabled, because row access permission is checked against your access policies and the user's [JSON Web Token (JWT)](/docs/learn/auth-deep-dive/auth-deep-dive-jwts). The JWT is automatically sent by the Supabase client libraries if the user is signed in using Supabase Auth. Older projects may also show an `anon` key. Treat it like a publishable key: it can identify your project, but it is not a secret and must be paired with RLS and least-privilege grants. diff --git a/apps/docs/content/guides/deployment/database-migrations.mdx b/apps/docs/content/guides/deployment/database-migrations.mdx index 33875de908ad8..3b09c41bf21ac 100644 --- a/apps/docs/content/guides/deployment/database-migrations.mdx +++ b/apps/docs/content/guides/deployment/database-migrations.mdx @@ -279,8 +279,8 @@ Head over to [Supabase](/dashboard) and create a new project to deploy to. - - [Login](/docs/reference/cli/supabase-login) to the Supabase CLI using an auto-generated Personal Access Token. + + [Sign in](/docs/reference/cli/supabase-login) to the Supabase CLI using an auto-generated Personal Access Token. diff --git a/apps/docs/content/guides/deployment/shared-responsibility-model.mdx b/apps/docs/content/guides/deployment/shared-responsibility-model.mdx index 41c5d17503931..7808b3b18c986 100644 --- a/apps/docs/content/guides/deployment/shared-responsibility-model.mdx +++ b/apps/docs/content/guides/deployment/shared-responsibility-model.mdx @@ -58,7 +58,7 @@ If you don’t want to implement logic inside your database, that is 100% fine. Supabase offers a lot of opportunities for flexibly integrating with third-party services, such as: -- OAuth and SAML login providers +- OAuth and SAML sign-in providers - SMTP and SMS sending APIs - Calls to external APIs within Postgres functions or triggers - Calls to external APIs within Edge Functions diff --git a/apps/docs/content/guides/functions/auth-legacy-jwt.mdx b/apps/docs/content/guides/functions/auth-legacy-jwt.mdx index 72f19204c05ce..7b9dd624f4c37 100644 --- a/apps/docs/content/guides/functions/auth-legacy-jwt.mdx +++ b/apps/docs/content/guides/functions/auth-legacy-jwt.mdx @@ -47,7 +47,7 @@ This context setting happens in the `Deno.serve()` callback argument, so that th ## Fetching the user -By getting the JWT from the `Authorization` header, you can provide the token to `getUser()` to fetch the user object to obtain metadata for the logged in user. +By getting the JWT from the `Authorization` header, you can provide the token to `getUser()` to fetch the user object to obtain metadata for the signed-in user. ```js Deno.serve(async (req: Request) => { diff --git a/apps/docs/content/guides/functions/cors.mdx b/apps/docs/content/guides/functions/cors.mdx index 6ae913d9cc9ee..43c2c60d58f35 100644 --- a/apps/docs/content/guides/functions/cors.mdx +++ b/apps/docs/content/guides/functions/cors.mdx @@ -56,7 +56,7 @@ export default { } ``` -Importing from the SDK keeps your allow-list aligned with the headers the client libraries send: when you upgrade the SDK version in your function and redeploy, newly added headers are picked up with it. As of `@supabase/supabase-js` v2.112.3 the list includes the trace context headers (`traceparent`, `tracestate`, `baggage`) used by [client-side tracing](/docs/guides/monitoring-and-debugging/client-side-tracing) — functions deployed with an older version need a redeploy before browsers can call them with trace propagation enabled. +Importing from the SDK keeps your allow-list aligned with the headers the client libraries send: when you upgrade the SDK version in your function and redeploy, newly added headers are picked up with it. As of `@supabase/supabase-js` v2.112.3 the list includes the trace context headers (`traceparent`, `tracestate`, `baggage`) used by [client-side tracing](/docs/guides/observability/client-side-tracing) — functions deployed with an older version need a redeploy before browsers can call them with trace propagation enabled. @@ -66,14 +66,14 @@ The allow-list only states what a browser _may_ send — it doesn't change what The full list, and when each header is sent: -| Header | Sent | -| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | -| `authorization` | Every request (session token or API key) | -| `apikey` | Every request | -| `x-client-info` | Every request (SDK name and version) | -| `content-type` | Requests with a body | -| `x-retry-count` | Only on automatic retry attempts (`postgrest-js` retries failed idempotent requests by default) | -| `traceparent`, `tracestate`, `baggage` | **Only when [trace propagation](/docs/guides/monitoring-and-debugging/client-side-tracing) is explicitly enabled** — never by default | +| Header | Sent | +| -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | +| `authorization` | Every request (session token or API key) | +| `apikey` | Every request | +| `x-client-info` | Every request (SDK name and version) | +| `content-type` | Requests with a body | +| `x-retry-count` | Only on automatic retry attempts (`postgrest-js` retries failed idempotent requests by default) | +| `traceparent`, `tracestate`, `baggage` | **Only when [trace propagation](/docs/guides/observability/client-side-tracing) is explicitly enabled** — never by default | ### For versions before 2.95.0 diff --git a/apps/docs/content/guides/functions/dependencies.mdx b/apps/docs/content/guides/functions/dependencies.mdx index 691274669987a..2bb5a5f62d6bf 100644 --- a/apps/docs/content/guides/functions/dependencies.mdx +++ b/apps/docs/content/guides/functions/dependencies.mdx @@ -14,6 +14,7 @@ Supabase Edge Functions support several ways to import dependencies: - Built-in [Node APIs](https://docs.deno.com/runtime/manual/node/compatibility) - Modules published to [JSR](https://jsr.io/) or [deno.land/x](https://deno.land/x) +{/* prettier-ignore */} ```ts // NPM packages (recommended) import { createClient } from 'npm:@supabase/supabase-js@2' diff --git a/apps/docs/content/guides/functions/deploy.mdx b/apps/docs/content/guides/functions/deploy.mdx index 68fdf89629706..eeb9812a16100 100644 --- a/apps/docs/content/guides/functions/deploy.mdx +++ b/apps/docs/content/guides/functions/deploy.mdx @@ -18,7 +18,7 @@ Before getting started, make sure you have the Supabase CLI installed. Check out ## Step 1: Authenticate -Log in to the Supabase CLI if you haven't already: +Sign in to the Supabase CLI if you haven't already: ```bash supabase login diff --git a/apps/docs/content/guides/functions/examples/discord-bot.mdx b/apps/docs/content/guides/functions/examples/discord-bot.mdx index a7ba70a4806f8..75b1eaeca92ee 100644 --- a/apps/docs/content/guides/functions/examples/discord-bot.mdx +++ b/apps/docs/content/guides/functions/examples/discord-bot.mdx @@ -16,7 +16,7 @@ video: 'https://www.youtube.com/v/J24Bvo_m7DM' ## Create an application on Discord Developer portal -1. Go to [https://discord.com/developers/applications](https://discord.com/developers/applications) (login using your discord account if required). +1. Go to [https://discord.com/developers/applications](https://discord.com/developers/applications) (sign in using your discord account if required). 2. Click on **New Application** button available at left side of your profile picture. 3. Name your application and click on **Create**. 4. Go to **Bot** section, click on **Add Bot**, and finally on **Yes, do it!** to confirm. diff --git a/apps/docs/content/guides/functions/examples/upstash-redis.mdx b/apps/docs/content/guides/functions/examples/upstash-redis.mdx index 329607922c289..69324662c1b16 100644 --- a/apps/docs/content/guides/functions/examples/upstash-redis.mdx +++ b/apps/docs/content/guides/functions/examples/upstash-redis.mdx @@ -39,8 +39,8 @@ supabase functions new upstash-redis-counter And add the code to the `index.ts` file: ```ts index.ts -import { Redis } from 'npm:@upstash/redis@^1' import { withSupabase } from 'npm:@supabase/server@^1' +import { Redis } from 'npm:@upstash/redis@^1' console.log(`Function "upstash-redis-counter" up and running!`) diff --git a/apps/docs/content/guides/functions/kysely-postgres.mdx b/apps/docs/content/guides/functions/kysely-postgres.mdx index 9b98eb9b86934..5bca2ba1c46e8 100644 --- a/apps/docs/content/guides/functions/kysely-postgres.mdx +++ b/apps/docs/content/guides/functions/kysely-postgres.mdx @@ -191,6 +191,7 @@ Create an `index.ts` file to execute a query on incoming requests: ```ts index.ts import { Pool } from 'jsr:@db/postgres@^0' +import { withSupabase } from 'npm:@supabase/server@^1' import { Generated, Kysely, @@ -198,7 +199,6 @@ import { PostgresIntrospector, PostgresQueryCompiler, } from 'npm:kysely@^0' -import { withSupabase } from 'npm:@supabase/server@^1' import { PostgresDriver } from './DenoPostgresDriver.ts' diff --git a/apps/docs/content/guides/functions/quickstart.mdx b/apps/docs/content/guides/functions/quickstart.mdx index 9b11d1ec6d666..91eb4ff3e235f 100644 --- a/apps/docs/content/guides/functions/quickstart.mdx +++ b/apps/docs/content/guides/functions/quickstart.mdx @@ -138,7 +138,7 @@ Create one at [database.new](https://database.new/). -First, login to the CLI if you haven't already, and authenticate with Supabase. This opens your browser to authenticate with Supabase; complete the login process in your browser. +First, sign in to the CLI if you haven't already, and authenticate with Supabase. This opens your browser to authenticate with Supabase; complete the sign-in process in your browser. ```bash supabase login diff --git a/apps/docs/content/guides/getting-started/features.mdx b/apps/docs/content/guides/getting-started/features.mdx index b573c41d5d161..98240af9be9c0 100644 --- a/apps/docs/content/guides/getting-started/features.mdx +++ b/apps/docs/content/guides/getting-started/features.mdx @@ -68,13 +68,13 @@ Deploy read-only databases across multiple regions, for lower latency and better ### Log drains -Export Supabase logs to third-party providers and external tooling. [Docs](/docs/guides/monitoring-and-debugging/log-drains). +Export Supabase logs to third-party providers and external tooling. [Docs](/docs/guides/observability/log-drains). ## Studio ### Studio Single Sign-On -Login to the Supabase dashboard via SSO. [Docs](/docs/guides/platform/sso). +Sign in to the Supabase dashboard via SSO. [Docs](/docs/guides/platform/sso).
    @@ -94,21 +94,21 @@ Synchronize shared state across your users, including online status and typing i ## Auth -### Email login +### Email sign-in -Build email logins for your application or website. [Docs](/docs/guides/auth/passwords). +Build email sign-in for your application or website. [Docs](/docs/guides/auth/passwords). ### Social login -Provide social logins - everything from Apple, to GitHub, to Slack. [Docs](/docs/guides/auth/social-login). +Provide social login - everything from Apple, to GitHub, to Slack. [Docs](/docs/guides/auth/social-login). -### Phone logins +### Phone sign-in -Provide phone logins using a third-party SMS provider. [Docs](/docs/guides/auth/phone-login). +Provide phone sign-in using a third-party SMS provider. [Docs](/docs/guides/auth/phone-login). -### Passwordless login +### Passwordless sign-in -Build passwordless logins via magic links for your application or website. [Docs](/docs/guides/auth/auth-email-passwordless). +Build passwordless sign-in via magic links for your application or website. [Docs](/docs/guides/auth/auth-email-passwordless). ### Authorization via Row Level Security @@ -238,10 +238,10 @@ In addition to the Beta requirements, features in GA are covered by the [uptime | Edge Functions | Regional Invocations | `GA` | ✅ | | Edge Functions | NPM compatibility | `GA` | ✅ | | Auth | | `GA` | ✅ | -| Auth | Email login | `GA` | ✅ | +| Auth | Email sign-in | `GA` | ✅ | | Auth | Social login | `GA` | ✅ | -| Auth | Phone login | `GA` | ✅ | -| Auth | Passwordless login | `GA` | ✅ | +| Auth | Phone sign-in | `GA` | ✅ | +| Auth | Passwordless sign-in | `GA` | ✅ | | Auth | SSO with SAML | `GA` | ✅ | | Auth | Authorization via RLS | `GA` | ✅ | | Auth | CAPTCHA protection | `GA` | ✅ | diff --git a/apps/docs/content/guides/getting-started/quickstarts/laravel.mdx b/apps/docs/content/guides/getting-started/quickstarts/laravel.mdx index cce73dd279023..fcf5b1d129ba5 100644 --- a/apps/docs/content/guides/getting-started/quickstarts/laravel.mdx +++ b/apps/docs/content/guides/getting-started/quickstarts/laravel.mdx @@ -95,7 +95,7 @@ php artisan migrate ## 8. Start the app -Run the development server. Go to http://127.0.0.1:8000 in a browser to see your application. You can also navigate to http://127.0.0.1:8000/register and http://127.0.0.1:8000/login to register and log in users. +Run the development server. Go to http://127.0.0.1:8000 in a browser to see your application. You can also navigate to http://127.0.0.1:8000/register and http://127.0.0.1:8000/login to register and sign in users. ```bash php artisan serve diff --git a/apps/docs/content/guides/getting-started/quickstarts/nextjs.mdx b/apps/docs/content/guides/getting-started/quickstarts/nextjs.mdx index 9ca784530e1f2..57fdfd03fb45c 100644 --- a/apps/docs/content/guides/getting-started/quickstarts/nextjs.mdx +++ b/apps/docs/content/guides/getting-started/quickstarts/nextjs.mdx @@ -39,7 +39,7 @@ NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY= ## 6. Allow public access to the instruments page -The `with-supabase` template redirects unauthenticated visitors to the login page for most routes. The `instruments` table is publicly readable, so update `lib/supabase/proxy.ts` to skip that redirect for `/instruments`. +The `with-supabase` template redirects unauthenticated visitors to the sign-in page for most routes. The `instruments` table is publicly readable, so update `lib/supabase/proxy.ts` to skip that redirect for `/instruments`. Find this `if` statement: diff --git a/apps/docs/content/guides/getting-started/quickstarts/refine.mdx b/apps/docs/content/guides/getting-started/quickstarts/refine.mdx index 1d6921561d508..0d9d6d1f293d1 100644 --- a/apps/docs/content/guides/getting-started/quickstarts/refine.mdx +++ b/apps/docs/content/guides/getting-started/quickstarts/refine.mdx @@ -107,15 +107,15 @@ import { BrowserRouter, Route, Routes } from 'react-router' import './App.css' -import authProvider from './providers/auth' -import { dataProvider } from './providers/data' -import { supabaseClient } from './providers/supabase-client' import { InstrumentsCreate, InstrumentsEdit, InstrumentsList, InstrumentsShow, } from './pages/instruments' +import authProvider from './providers/auth' +import { dataProvider } from './providers/data' +import { supabaseClient } from './providers/supabase-client' function App() { return ( diff --git a/apps/docs/content/guides/getting-started/quickstarts/tanstack.mdx b/apps/docs/content/guides/getting-started/quickstarts/tanstack.mdx index 9d0f220885f99..6cc4ac7a1f9e1 100644 --- a/apps/docs/content/guides/getting-started/quickstarts/tanstack.mdx +++ b/apps/docs/content/guides/getting-started/quickstarts/tanstack.mdx @@ -154,7 +154,7 @@ npm run dev ## Next steps -- Learn how to [protect routes and check sessions](/docs/guides/auth/server-side/creating-a-client?queryGroups=framework&framework=tanstack) with the server client, or drop in a complete [login and sign-up flow](/library/docs/tanstack/password-based-auth) from Supabase Library +- Learn how to [protect routes and check sessions](/docs/guides/auth/server-side/creating-a-client?queryGroups=framework&framework=tanstack) with the server client, or drop in a complete [sign-in and sign-up flow](/library/docs/tanstack/password-based-auth) from Supabase Library - [Insert more data](/docs/guides/database/import-data) into your database - Upload and serve static files using [Storage](/docs/guides/storage) - Explore [drop-in UI components](/ui) for your Supabase app diff --git a/apps/docs/content/guides/getting-started/tutorials/with-angular.mdx b/apps/docs/content/guides/getting-started/tutorials/with-angular.mdx index c65739aed50c6..0f138d95a2e46 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-angular.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-angular.mdx @@ -54,9 +54,9 @@ meta="name=src/app/supabase.service.ts" Optionally, update `src/styles.css` to style the app. You can find the full contents of this file [in the example repository](https://github.com/supabase/supabase/tree/master/examples/user-management/angular-user-management/src/styles.css). -### Set up a login component +### Set up a sign-in component -You need an Angular component to manage logins and sign ups. The component uses [Magic Links](/docs/guides/auth/auth-email-passwordless#with-magic-link), so users can sign in with their email without using passwords. +You need an Angular component to manage sign-ins and sign-ups. The component uses [Magic Links](/docs/guides/auth/auth-email-passwordless#with-magic-link), so users can sign in with their email without using passwords. diff --git a/apps/docs/content/guides/getting-started/tutorials/with-expo-react-native.mdx b/apps/docs/content/guides/getting-started/tutorials/with-expo-react-native.mdx index 64fbbdbc2b116..3f6ef30734477 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-expo-react-native.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-expo-react-native.mdx @@ -166,9 +166,9 @@ lines={[[1, -1]]} meta="name=styles/styles.ts" /> -### Set up a login component +### Set up a sign-in component -Set up a React Native component to manage logins and sign ups. +Set up a React Native component to manage sign-ins and sign-ups. Users should be able to sign in with their email and password. <$CodeSample diff --git a/apps/docs/content/guides/getting-started/tutorials/with-flutter.mdx b/apps/docs/content/guides/getting-started/tutorials/with-flutter.mdx index 19ea149237c05..f5bf9d3944323 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-flutter.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-flutter.mdx @@ -189,9 +189,9 @@ extension ContextExtension on BuildContext { Notice that we have a `showSnackBar` extension method that we will use to show snack bars in the app. You could define this method in a separate file and import it where needed, but for simplicity, we will define it here. -### Set up a login page +### Set up a sign-in page -Create a Flutter widget to manage logins and sign ups. We will use Magic Links, so users can sign in with their email without using passwords. +Create a Flutter widget to manage sign-ins and sign-ups. We will use Magic Links, so users can sign in with their email without using passwords. Notice that this page sets up a listener on the user's auth state using `onAuthStateChange`. A new event will fire when the user comes back to the app by clicking their magic link, which this page can catch and redirect the user accordingly. diff --git a/apps/docs/content/guides/getting-started/tutorials/with-ionic-angular.mdx b/apps/docs/content/guides/getting-started/tutorials/with-ionic-angular.mdx index a1bec2c404b83..0846bcdea8f28 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-ionic-angular.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-ionic-angular.mdx @@ -57,9 +57,9 @@ lines={[[1, -1]]} meta="name=src/app/supabase.service.ts" /> -### Set up a login route +### Set up a sign-in route -Set up a route to manage logins and signups. Use Magic Links so users can sign in with their email without using passwords. +Set up a route to manage sign-ins and sign-ups. Use Magic Links so users can sign in with their email without using passwords. Create a `LoginPage` with the `ionic g page login` Ionic CLI command. <$CodeSample diff --git a/apps/docs/content/guides/getting-started/tutorials/with-ionic-react.mdx b/apps/docs/content/guides/getting-started/tutorials/with-ionic-react.mdx index fac23b6ec1e24..310e4c69efb8b 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-ionic-react.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-ionic-react.mdx @@ -56,9 +56,9 @@ lines={[[1, -1]]} meta="name=src/supabaseClient.ts" /> -### Set up a login route +### Set up a sign-in route -Set up a React component to manage logins and sign ups which uses Magic Links, so users can sign in with their email without using passwords. +Set up a React component to manage sign-ins and sign-ups which uses Magic Links, so users can sign in with their email without using passwords. <$CodeSample path="/user-management/ionic-react-user-management/src/pages/Login.tsx" diff --git a/apps/docs/content/guides/getting-started/tutorials/with-ionic-vue.mdx b/apps/docs/content/guides/getting-started/tutorials/with-ionic-vue.mdx index fcf2908a8266a..a9af115c05af0 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-ionic-vue.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-ionic-vue.mdx @@ -54,9 +54,9 @@ lines={[[1, -1]]} meta="name=src/supabase.ts" /> -### Set up a login route +### Set up a sign-in route -Create a Vue component to manage logins and sign ups that uses Magic Links, so users can sign in with their email without using passwords. +Create a Vue component to manage sign-ins and sign-ups that uses Magic Links, so users can sign in with their email without using passwords. <$CodeSample path="/user-management/ionic-vue-user-management/src/views/Login.vue" diff --git a/apps/docs/content/guides/getting-started/tutorials/with-kotlin.mdx b/apps/docs/content/guides/getting-started/tutorials/with-kotlin.mdx index 877c240120dad..8bbabde0dc531 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-kotlin.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-kotlin.mdx @@ -6,7 +6,7 @@ description: 'Learn how to use Supabase in your Android Kotlin App.' This tutorial demonstrates how to build a basic product management app. The app demonstrates management operations, photo upload, account creation and authentication using: - [Supabase Database](/docs/guides/database/overview) - a Postgres database for storing your user data and [Row Level Security](/docs/guides/auth#row-level-security) so data is protected and users can only access their own information. -- [Supabase Auth](/docs/guides/auth) - users log in through magic links sent to their email (without having to set up a password). +- [Supabase Auth](/docs/guides/auth) - users sign in through magic links sent to their email (without having to set up a password). - [Supabase Storage](/docs/guides/storage) - users can upload a profile photo. ![manage-product-cover](/docs/img/guides/kotlin/manage-product-cover.png) diff --git a/apps/docs/content/guides/getting-started/tutorials/with-nextjs.mdx b/apps/docs/content/guides/getting-started/tutorials/with-nextjs.mdx index 9fd1f84564e12..8060eeec0a685 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-nextjs.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-nextjs.mdx @@ -126,11 +126,11 @@ meta="name=lib/supabase/proxy.ts" -### Set up a login page +### Set up a sign-in page -#### Login and signup form +#### Sign-in and sign-up form -To add login/signup page for your application, create a new folder named `login`, containing a `page.tsx` file with the following code for a login/signup form: +To add sign-in/sign-up page for your application, create a new folder named `login`, containing a `page.tsx` file with the following code for a sign-in/sign-up form: <$CodeTabs> @@ -142,13 +142,13 @@ meta="name=app/login/page.tsx" -Create the login/signup actions to hook up the form to the function which does the following: +Create the sign-in/sign-up actions to hook up the form to the function which does the following: - Retrieve the user's information. -- Send that information to Supabase as a signup request, which in turns sends a confirmation email. It uses [Magic Links](/docs/guides/auth/auth-email-passwordless#with-magic-link), so users can sign in with their email without using passwords. +- Send that information to Supabase as a sign-up request, which in turns sends a confirmation email. It uses [Magic Links](/docs/guides/auth/auth-email-passwordless#with-magic-link), so users can sign in with their email without using passwords. - Handle any error that arises. -Create the `action.ts` file in the `app/login` folder, which contains the login and signup functions and the `error/page.tsx` file, which displays an error message if the login or signup fails. +Create the `actions.ts` file in the `app/login` folder, which contains the sign-in and sign-up functions and the `error/page.tsx` file, which displays an error message if the sign-in or sign-up fails. <$CodeTabs> @@ -226,7 +226,7 @@ meta="name=app/account/page.tsx" ### Sign out -Create a route handler to handle the sign out from the server side, making sure to check if the user is logged in first. +Create a route handler to handle the sign-out from the server side, making sure to check if the user is signed in first. <$CodeSample path="/user-management/nextjs-user-management/app/auth/signout/route.ts" diff --git a/apps/docs/content/guides/getting-started/tutorials/with-nuxt-3.mdx b/apps/docs/content/guides/getting-started/tutorials/with-nuxt-3.mdx index 4541d2fc44b8f..10c7d8282ae6c 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-nuxt-3.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-nuxt-3.mdx @@ -73,7 +73,7 @@ export default defineNuxtConfig({ ### Set up Auth component -Set up a Vue component to manage logins and sign ups. We'll use Magic Links, so users can sign in with their email without using passwords. +Set up a Vue component to manage sign-ins and sign-ups. We'll use Magic Links, so users can sign in with their email without using passwords. <$CodeTabs> diff --git a/apps/docs/content/guides/getting-started/tutorials/with-react.mdx b/apps/docs/content/guides/getting-started/tutorials/with-react.mdx index 43c27e7c43470..e4d66f541c224 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-react.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-react.mdx @@ -58,9 +58,9 @@ meta="name=src/supabaseClient.js" An optional step is to update the CSS file `src/index.css` to make the app look better. You can find the full contents of this file [in the example repository](https://raw.githubusercontent.com/supabase/supabase/master/examples/user-management/react-user-management/src/index.css). -### Set up a login component +### Set up a sign-in component -You need a React component to manage logins and sign-ups. It uses [Magic Links](/docs/guides/auth/auth-email-passwordless#with-magic-link), so users can sign in with their email without using passwords. +You need a React component to manage sign-ins and sign-ups. It uses [Magic Links](/docs/guides/auth/auth-email-passwordless#with-magic-link), so users can sign in with their email without using passwords. diff --git a/apps/docs/content/guides/getting-started/tutorials/with-redwoodjs.mdx b/apps/docs/content/guides/getting-started/tutorials/with-redwoodjs.mdx index cb0774b4cd28d..9f482e115b699 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-redwoodjs.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-redwoodjs.mdx @@ -230,9 +230,9 @@ export default Routes -### Set up a login component +### Set up a sign-in component -Set up a Redwood component to manage logins and sign ups. We'll use Magic Links, so users can sign in with their email without using passwords. +Set up a Redwood component to manage sign-ins and sign-ups. We'll use Magic Links, so users can sign in with their email without using passwords. ```bash yarn rw g component auth @@ -485,7 +485,7 @@ export default HomePage -What we're doing here is showing the sign in form if you aren't logged in and your account profile if you are. +What we're doing here is showing the sign-in form if you aren't signed in and your account profile if you are. diff --git a/apps/docs/content/guides/getting-started/tutorials/with-refine.mdx b/apps/docs/content/guides/getting-started/tutorials/with-refine.mdx index 62b3582985ccb..536167c2e30c5 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-refine.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-refine.mdx @@ -15,7 +15,7 @@ If you get stuck while working through this guide, you can find the [full exampl ## About Refine -[Refine](https://github.com/refinedev/refine) is a React-based framework used to rapidly build data-heavy applications like admin panels, dashboards, storefronts and any type of CRUD apps. It separates app concerns into individual layers, each backed by a React context and respective provider object. For example, the auth layer represents a context served by a specific set of [`authProvider`](https://refine.dev/docs/tutorial/understanding-authprovider/index/) methods that carry out authentication and authorization actions such as logging in, logging out, getting roles data, etc. Similarly, the data layer offers another level of abstraction equipped with [`dataProvider`](https://refine.dev/docs/tutorial/understanding-dataprovider/index/) methods to handle CRUD operations at appropriate backend API endpoints. +[Refine](https://github.com/refinedev/refine) is a React-based framework used to rapidly build data-heavy applications like admin panels, dashboards, storefronts and any type of CRUD apps. It separates app concerns into individual layers, each backed by a React context and respective provider object. For example, the auth layer represents a context served by a specific set of [`authProvider`](https://refine.dev/docs/tutorial/understanding-authprovider/index/) methods that carry out authentication and authorization actions such as signing in, signing out, getting roles data, etc. Similarly, the data layer offers another level of abstraction equipped with [`dataProvider`](https://refine.dev/docs/tutorial/understanding-dataprovider/index/) methods to handle CRUD operations at appropriate backend API endpoints. Refine provides hassle-free integration with a Supabase backend with its supplementary [`@refinedev/supabase`](https://github.com/refinedev/refine/tree/main/packages/supabase) package. It generates `authProvider` and `dataProvider` methods at project initialization, so you don't need to spend much effort defining them yourself, choose Supabase as the backend service while creating the app with `create refine-app`. @@ -72,7 +72,7 @@ You can find the full contents of this file [in the example repository](https:// ### The `` component -In order to add login and user profile pages in this App, tweak the `` component inside `App.tsx`. +In order to add sign-in and user profile pages in this App, tweak the `` component inside `App.tsx`. The `App.tsx` file initially looks like this: @@ -87,7 +87,9 @@ import routerProvider, { } from '@refinedev/react-router' import { dataProvider, liveProvider } from '@refinedev/supabase' import { BrowserRouter, Route, Routes } from 'react-router' + import './App.css' + import authProvider from './authProvider' import { supabaseClient } from './utility' @@ -161,9 +163,9 @@ lines={[[1, -1]]} meta="name=src/authProvider.ts" /> -### Set up a login component +### Set up a sign-in component -As the app uses the headless Refine core package that comes with no supported UI framework set up a plain React component to manage logins and sign ups. +As the app uses the headless Refine core package that comes with no supported UI framework set up a plain React component to manage sign-ins and sign-ups. Create and edit `src/components/auth.tsx`: diff --git a/apps/docs/content/guides/getting-started/tutorials/with-solidjs.mdx b/apps/docs/content/guides/getting-started/tutorials/with-solidjs.mdx index 064a8c2c7325e..c95e2dd22b898 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-solidjs.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-solidjs.mdx @@ -64,9 +64,9 @@ meta="name=src/supabaseClient.tsx" An optional step is to update the CSS file `src/index.css` to make the app look better. You can find the full contents of this file [in the example repository](https://raw.githubusercontent.com/supabase/supabase/master/examples/user-management/solid-user-management/src/index.css). -### Set up a login component +### Set up a sign-in component -Set up a SolidJS component to manage logins and sign ups using Magic Links, so users can sign in with their email without using passwords. +Set up a SolidJS component to manage sign-ins and sign-ups using Magic Links, so users can sign in with their email without using passwords. <$CodeTabs> diff --git a/apps/docs/content/guides/getting-started/tutorials/with-svelte.mdx b/apps/docs/content/guides/getting-started/tutorials/with-svelte.mdx index 278ce20350233..8107b1befb411 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-svelte.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-svelte.mdx @@ -59,9 +59,9 @@ meta="name=src/supabaseClient.ts" Optionally, update the CSS file `src/app.css` to make the app look better. You can find the full contents of this file [in the example repository](https://raw.githubusercontent.com/supabase/supabase/master/examples/user-management/svelte-user-management/src/app.css). -### Set up a login component +### Set up a sign-in component -Set up a Svelte component to manage logins and sign ups. It uses Magic Links, so users can sign in with their email without using passwords. +Set up a Svelte component to manage sign-ins and sign-ups. It uses Magic Links, so users can sign in with their email without using passwords. <$CodeSample path="/user-management/svelte-user-management/src/lib/Auth.svelte" diff --git a/apps/docs/content/guides/getting-started/tutorials/with-sveltekit.mdx b/apps/docs/content/guides/getting-started/tutorials/with-sveltekit.mdx index 2b8e65cf30500..b9d3c1d6b2006 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-sveltekit.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-sveltekit.mdx @@ -132,9 +132,9 @@ meta="name=src/routes/+layout.svelte" -### Set up a login page +### Set up a sign-in page -Create a magic link login/signup page for your application by updating the `routes/+page.svelte` file: +Create a magic link sign-in/sign-up page for your application by updating the `routes/+page.svelte` file: <$CodeTabs> diff --git a/apps/docs/content/guides/getting-started/tutorials/with-swift.mdx b/apps/docs/content/guides/getting-started/tutorials/with-swift.mdx index 45057d067c16c..b3e783bfe71cd 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-swift.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-swift.mdx @@ -46,9 +46,9 @@ let supabase = SupabaseClient( -### Set up a login view +### Set up a sign-in view -Set up a SwiftUI view to manage logins and sign ups. +Set up a SwiftUI view to manage sign-ins and sign-ups. Users should be able to sign in using a magic link. <$CodeTabs> diff --git a/apps/docs/content/guides/getting-started/tutorials/with-vue-3.mdx b/apps/docs/content/guides/getting-started/tutorials/with-vue-3.mdx index 3013377e7a113..a76d052cde517 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-vue-3.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-vue-3.mdx @@ -66,7 +66,7 @@ meta="name=src/supabase.js" An optional step is to update the CSS file `src/style.css` to make the app look better. You can find the full contents of this file [in the example repository](https://raw.githubusercontent.com/supabase/supabase/master/examples/user-management/vue3-user-management/src/style.css). -### Set up a login component +### Set up a sign-in component Set up an `src/components/Auth.vue` component to manage to add Magic Links as an option, so users can sign in with their email without using passwords. diff --git a/apps/docs/content/guides/integrations/stripe-projects.mdx b/apps/docs/content/guides/integrations/stripe-projects.mdx index 59ef301554598..eba4ea6cf70e7 100644 --- a/apps/docs/content/guides/integrations/stripe-projects.mdx +++ b/apps/docs/content/guides/integrations/stripe-projects.mdx @@ -57,4 +57,4 @@ Your Supabase project and organization work exactly like ones you create directl - Stripe Projects is in developer preview, so behavior may change. - Provisioning links to a Supabase organization by matching the email on the Stripe account to a Supabase account; there's no option in the CLI flow to choose a different existing organization. -- To access the Supabase dashboard for a new organization provisioned through Stripe Projects, use the `open` command (`stripe projects open supabase`). To log in to the Supabase dashboard directly without the CLI, follow the reset password flow for this account. +- To access the Supabase dashboard for a new organization provisioned through Stripe Projects, use the `open` command (`stripe projects open supabase`). To sign in to the Supabase dashboard directly without the CLI, follow the reset password flow for this account. diff --git a/apps/docs/content/guides/local-development/database-migrations.mdx b/apps/docs/content/guides/local-development/database-migrations.mdx index ebbf6cb9030b1..d1acbc83519bf 100644 --- a/apps/docs/content/guides/local-development/database-migrations.mdx +++ b/apps/docs/content/guides/local-development/database-migrations.mdx @@ -221,7 +221,7 @@ The last step is deploying these changes to a live Supabase project. You've been developing your project locally, making changes to your tables via migrations. It's time to deploy your project to the Supabase Platform and start scaling up to millions of users! Head over to [Supabase](/dashboard) and create a new project to deploy to. -### Log in to the Supabase CLI +### Sign in to the Supabase CLI <$CodeTabs> diff --git a/apps/docs/content/guides/local-development/declarative-database-schemas.mdx b/apps/docs/content/guides/local-development/declarative-database-schemas.mdx index 404648f57b0d3..1611efb5a2432 100644 --- a/apps/docs/content/guides/local-development/declarative-database-schemas.mdx +++ b/apps/docs/content/guides/local-development/declarative-database-schemas.mdx @@ -171,8 +171,8 @@ supabase migration up - - [Log in](/docs/reference/cli/supabase-login) via the Supabase CLI. + + [Sign in](/docs/reference/cli/supabase-login) via the Supabase CLI. diff --git a/apps/docs/content/guides/monitoring-and-debugging.mdx b/apps/docs/content/guides/monitoring-and-debugging.mdx deleted file mode 100644 index 61e018404a271..0000000000000 --- a/apps/docs/content/guides/monitoring-and-debugging.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Monitoring and Debugging ---- - -Monitor your project, debug errors, and understand what's happening across the Supabase stack. - -Debugging with an AI agent? See [Debug with AI tools](/docs/guides/monitoring-and-debugging/debugging#debug-with-ai-tools) for the MCP tools and agent skill that let it read your logs and advisors. - - - - diff --git a/apps/docs/content/guides/monitoring-and-debugging/advanced-log-filtering.mdx b/apps/docs/content/guides/monitoring-and-debugging/advanced-log-filtering.mdx deleted file mode 100644 index e624cced45fb9..0000000000000 --- a/apps/docs/content/guides/monitoring-and-debugging/advanced-log-filtering.mdx +++ /dev/null @@ -1,290 +0,0 @@ ---- -title: 'Advanced Log Querying and Filtering' -description: 'Query and filter logs with regular expressions' ---- - -The [Logs Explorer](/dashboard/project/_/logs-explorer) exposes logs from each part of the Supabase stack, which you can query and filter using SQL. - -![Logs Explorer](/docs/img/guides/platform/logs/logs-explorer.png) - -You can access the following log sources from the **Sources** drop-down: - -- `auth_logs`: GoTrue server logs, containing authentication/authorization activity. -- `edge_logs`: Edge network logs, containing request and response metadata retrieved from Cloudflare. -- `function_edge_logs`: Edge network logs for only edge functions, containing network requests and response metadata for each execution. -- `function_logs`: Function internal logs, containing any `console` logging from within the edge function. -- `postgres_logs`: Postgres database logs, containing statements executed by connected applications. -- `realtime_logs`: Realtime server logs, containing client connection information. -- `storage_logs`: Storage server logs, containing object upload and retrieval information. - -The Logs Explorer runs on ClickHouse. Every log line from every source is one row in a single `logs` table, tagged by a `source` column. Structured fields live in a `log_attributes` map, and the raw line is in `event_message`. Filter by `source` to scope a query to one service. - - - -ClickHouse has been the default engine since June 2026. Projects created before this date use BigQuery, whose `cross join unnest(metadata)` syntax is deprecated. We recommend rewriting those queries in the ClickHouse syntax shown in this guide. - - - -## Timestamp display and behavior - -The `timestamp` column is a `DateTime64` value in UTC, formatted as an ISO-8601 string like `2026-06-22T09:34:06.215000`. You can order and compare it directly, so no conversion function is needed. In the Logs Explorer the selected time range is applied for you, so you rarely need to filter on `timestamp` by hand. - -```sql -select timestamp, event_message -from logs -where source = 'edge_logs' -order by timestamp desc -limit 100; -``` - -## Reading fields from log_attributes - -Structured fields live in the `log_attributes` map. Read a field with bracket access, keeping the full dotted key. There are no unnesting joins. - -```sql -select - log_attributes['request.method'] as method, - log_attributes['request.path'] as path, - log_attributes['response.status_code'] as status -from logs -where source = 'edge_logs' -limit 100; -``` - -The key keeps the full dotted path, with the `metadata` root dropped. What BigQuery expressed as `metadata.request.cf.country` is `log_attributes['request.cf.country']`. Keep the full prefix rather than shortening it. - -Map values are always strings. To compare or aggregate a numeric field, wrap it in `toInt32OrZero`, which returns `0` for a missing or non-numeric value: - -```sql -select count() as server_errors -from logs -where source = 'edge_logs' - and toInt32OrZero(log_attributes['response.status_code']) between 500 and 599; -``` - -Do not guess keys. Discover the keys a source sets from recent rows: - -```sql -select arrayJoin(mapKeys(log_attributes)) as key, count() as n -from logs -where source = 'postgres_logs' -group by key -order by n desc -limit 100; -``` - -## LIMIT and result row limitations - -The Logs Explorer has a maximum of 1000 rows per run. Use `LIMIT` to reduce the number of rows returned further. - -## Best practices - -1. **Use a narrow time range.** - -The Logs Explorer applies the time range you select, so keep it tight. Querying a very large range risks timeouts, especially for Enterprise customers with long retention, because of the extra data scanned. - -2. **Select only the fields you need.** - -Selecting the whole `log_attributes` map, or every column, reads far more data than you need and slows the query down. Select the specific keys instead. - -```sql --- ❌ Avoid this: selecting the whole attributes map -select timestamp, log_attributes -from logs -where source = 'edge_logs'; - --- ✅ Do this: select only the keys you need -select timestamp, log_attributes['request.method'] as method -from logs -where source = 'edge_logs'; -``` - -## Examples and templates - -The Logs Explorer includes **Templates** (available in the Templates tab or the dropdown in the Query tab) to help you get started. - -For example, you can enter the following query in the SQL Editor to retrieve each user's IP address: - -```sql -select timestamp, log_attributes['request.headers.x_real_ip'] as x_real_ip -from logs -where source = 'edge_logs' - and log_attributes['request.headers.x_real_ip'] != '' - and log_attributes['request.method'] = 'GET' -order by timestamp desc -limit 100; -``` - -## Understanding field references - -Every log source shares the same `logs` table. Each row has these columns: - -| column | description | -| ---------------- | -------------------------------------------------- | -| `id` | unique log identifier | -| `timestamp` | time the event was recorded | -| `event_message` | the log's message | -| `severity_text` | log level, when the source sets one | -| `source` | the service the log came from | -| `log_attributes` | structured per-source fields, keyed by dotted path | - -Service-specific details live in `log_attributes`. For example, in `postgres_logs` the `log_attributes['parsed.error_severity']` field holds the error level of an event. Read those fields with bracket access: - -```sql -select - event_message, - log_attributes['parsed.error_severity'] as error_severity, - log_attributes['parsed.user_name'] as user_name -from logs -where source = 'postgres_logs' -limit 100; -``` - -## Expanding results - -Logs returned by queries may be difficult to read in table format. Double-click a row to expand the result into more readable JSON: - -![Expanding log results](/docs/img/guides/platform/expanded-log-results.png) - -## Filtering with [regular expressions](https://en.wikipedia.org/wiki/Regular_expression) - -Use the ClickHouse [`match` function](https://clickhouse.com/docs/sql-reference/functions/string-search-functions#match) for regular expressions. In its most basic form, it checks whether a pattern is present in a column. - -```sql -select timestamp, event_message -from logs -where source = 'postgres_logs' - and match(event_message, 'is present') -limit 100; -``` - -There are multiple operators to consider using. - -### Find messages that start with a phrase - -`^` only looks for values at the start of a string - -```sql --- find only messages that start with connection -match(event_message, '^connection') -``` - -### Find messages that end with a phrase - -`$` only looks for values at the end of the string - -```sql --- find only messages that end with port=12345 -match(event_message, 'port=12345$') -``` - -### Ignore case sensitivity - -`(?i)` ignores capitalization for all proceeding characters - -```sql --- find all event_messages with the word "connection" -match(event_message, '(?i)COnnecTion') -``` - -For a plain case-insensitive substring match, `ilike` is simpler: - -```sql --- find all event_messages containing "connection", in any case -event_message ilike '%connection%' -``` - -### Wildcards - -`.` matches any single character, and `.*` matches any sequence of characters - -```sql --- find event_messages like "helloworld" -match(event_message, 'hello.*world') -``` - -### Alphanumeric ranges - -`[0-9a-zA-Z]` matches a single alphanumeric character. Anchor it with `^[0-9a-zA-Z]+$` to match a value that is entirely alphanumeric. - -```sql --- find event_messages that contain a digit between 1 and 5 (inclusive) -match(event_message, '[1-5]') -``` - -### Repeated values - -`x*` zero or more x -`x+` one or more x -`x?` zero or one x -`x{4,}` four or more x -`x{3}` exactly 3 x - -```sql --- find event_messages that contain any sequence of 3 digits -match(event_message, '[0-9]{3}') -``` - -### Escaping reserved characters - -`\.` is interpreted as a period `.` instead of as a wildcard - -```sql --- escapes . -match(event_message, 'hello world\.') -``` - -### `or` statements - -`x|y` any string with `x` or `y` present - -```sql --- find event_messages that have the word 'started' followed by either "host" or "authenticated" -match(event_message, 'started (host|authenticated)') -``` - -### `and`/`or`/`not` statements in SQL - -`and`, `or`, and `not` are native terms in SQL and can be used with regular expressions to filter results - -```sql -select timestamp, event_message -from logs -where source = 'postgres_logs' - and ( - (match(event_message, 'connection') and match(event_message, 'host')) - or not match(event_message, 'received') - ) -limit 100; -``` - -### Filtering example - -Filter for Postgres errors: - -```sql -select - timestamp, - log_attributes['parsed.error_severity'] as error_severity, - log_attributes['parsed.user_name'] as user_name, - event_message -from logs -where source = 'postgres_logs' - and match(log_attributes['parsed.error_severity'], 'ERROR|FATAL|PANIC') -order by timestamp desc -limit 100; -``` - -## Limitations - -### The wildcard operator `*` is not supported - -The logs query surface rejects `select *` and `count(*)`. List the columns you need, and use `count()` for row counts: - -```sql -select timestamp, event_message, log_attributes['parsed.error_severity'] as error_severity -from logs -where source = 'postgres_logs' -order by timestamp desc -limit 100; -``` diff --git a/apps/docs/content/guides/monitoring-and-debugging/debugging.mdx b/apps/docs/content/guides/monitoring-and-debugging/debugging.mdx deleted file mode 100644 index 1f995d36f8033..0000000000000 --- a/apps/docs/content/guides/monitoring-and-debugging/debugging.mdx +++ /dev/null @@ -1,98 +0,0 @@ ---- -id: 'debugging' -title: 'Debugging guide' -description: 'Isolate and fix Supabase issues by reading the error, isolating the failing layer, and gathering evidence from logs.' ---- - -Debug by evidence, not by guessing. A Supabase error almost always surfaces at one layer but originates at another, so the fastest path to a fix is finding _where_ the problem is, not pattern-matching the symptom. Retrying a failed request rarely helps; isolating the layer does. - -## Debug with AI tools - -An AI agent can work through this loop for you, but only if it can read your project's evidence instead of guessing from the error message. - -Debugging with an agent needs two things: - -- The [Supabase MCP server](/docs/guides/ai-tools/mcp) provides the tools this guide relies on: `get_logs` for a per-service log dump, `query_logs` to run read-only SQL against your logs for filtering and aggregation (see [Querying with the Logs Explorer](/docs/guides/monitoring-and-debugging/logs#querying-with-the-logs-explorer) for the ClickHouse SQL syntax it accepts), `get_advisors` for security and performance findings, and `execute_sql` to inspect your schema and policies. -- The [Supabase agent skill](/docs/guides/ai-tools/ai-skills) teaches the agent this workflow: locate the failing layer, gather evidence from the matching log source, and verify the fix by re-running the operation that failed. - -Install both in one step with the [Supabase plugin for AI coding agents](/docs/guides/ai-tools/plugins). Connecting an agent to your project carries security risks, so read the [MCP security best practices](/docs/guides/ai-tools/mcp#security-risks) first. - -## Follow these debugging steps - -Work through these steps in order, skipping straight to a fix before you have evidence for the cause is the most common way to waste time on a bug. - -1. **Reproduce the issue and read the error precisely.** Capture the exact status code, the error code, and the full message, not a paraphrase. A `401` is not a `403`; `PGRST002` is not `PGRST106`; a Postgres `SQLSTATE` such as `42501`, `42P01`, or `23505` points at the exact failure. The precise error is your strongest clue. If you're using `supabase-js`, remember that errors are **returned, not thrown**, check the `error` field in the `{ data, error }` response object. Make sure your code inspects `error` — a swallowed error is why many bugs look like "nothing happened". -2. **Locate the failing layer.** Use the request stack below. The status code and error code usually name the layer for you. -3. **Gather evidence for that layer.** Query its logs, run the security and performance advisors, and inspect the schema. Logs are the primary tool, and the layer you identified in the previous step tells you which log source to query. See [Read the logs](#read-the-logs) below. -4. **Isolate the cause** using the troubleshooting guide for that layer (see [Find the guide for your symptom](#find-the-guide-for-your-symptom) below). Confirm your hypothesis against the evidence before you act. Most Supabase issues trace back to a small, known set of causes, and the guide explains how to tell them apart. -5. **Apply the fix, then verify.** Re-run the exact operation that failed and confirm it now succeeds, and that the corresponding log line is clean. A fix you haven't re-run is still a guess. If a couple of attempts don't resolve it, stop and gather more evidence rather than repeating the same change. - -## Check the request stack - -A request from a client passes through several layers before it reaches your data. Errors propagate upward, so the layer that _reports_ an error is often not the layer that _caused_ it. - -Knowing the shape of the stack is what makes isolating the layer possible. - -``` -Client (supabase-js / SSR) - → Edge / API gateway → edge_logs (HTTP status, routing, rate limits) - The gateway routes each request to ONE of these services. They run in parallel, - not as a chain: - ├→ PostgREST (Data API) → postgrest_logs (low-signal; PGRST* evidence lives in edge_logs and postgres_logs) - ├→ GoTrue (Auth) → auth_logs (login, JWT, OAuth, email) - ├→ Storage API → storage_logs (uploads, object access) - └→ Realtime → realtime_logs (channels, presence, broadcast) - PostgREST, GoTrue, and Storage each reach the database independently: - → Supavisor (connection pooler) → supavisor_logs (pooling, timeouts) - → Postgres (SQL, RLS, triggers) → postgres_logs (SQLSTATE, RLS, functions) -``` - -Edge Functions sit outside this stack and log separately: `function_edge_logs` for the HTTP request to the function, and `function_logs` for `console` output from inside it. - - - -A permission error or an unexpectedly empty result at the API layer is often a Postgres row-level security or privilege problem one layer down, though filters, authentication, query shape, or a stale schema cache can produce the same symptom. When in doubt, trace toward the database. - - - -## Read the logs - -Once you know the layer, query that layer's log source directly rather than scanning everything. Pick one `source`, bound the time window, and select only the fields you need. - -When a query comes up empty, widen along an anchor, such as a timestamp, request ID, or error code, to follow the same request into the adjacent source (for example from `edge_logs` into `postgres_logs`) instead of broadening into an unfiltered scan. - -A wide, unfiltered query across every source buries the one line you need and, on paid projects, costs more in scanned data. - -The [Logging guide](/docs/guides/monitoring-and-debugging/logs) covers the Logs Explorer, the available log sources, and how to write queries against them. - -## Find the guide for your symptom - -Match your symptom to a layer, confirm it against that layer's logs, then open the troubleshooting guide for the specific cause and fix. If a symptom could fit two layers (for example, an auth call failing with what looks like an RLS error), start with the layer closest to the database. - -Supabase updates these troubleshooting guides continuously, so treat this table as a starting point rather than the final word: if your exact symptom isn't listed, search the [troubleshooting index](/docs/guides/troubleshooting) for the error string. - -| Symptom / error | Layer → log source | Troubleshooting guides | -| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Empty `data` array with rows present; wrong rows returned; UPDATE/DELETE affects 0 rows; `42501` permission denied; `service_role` still blocked; policy not matching | RLS & access → `postgres_logs` | [Empty select array](/docs/guides/troubleshooting/why-is-my-select-returning-an-empty-data-array-and-i-have-data-in-the-table-xvOPgx) · [service_role hits RLS](/docs/guides/troubleshooting/why-is-my-service-role-key-client-getting-rls-errors-or-not-returning-data-7_1K9z) · [Database API 42501](/docs/guides/troubleshooting/database-api-42501-errors) · [RLS Simplified](/docs/guides/troubleshooting/rls-simplified-BJTcS8) · [Deprecated RLS features](/docs/guides/troubleshooting/deprecated-rls-features-Pm77Zs) | -| `PGRST002`/`PGRST106`; "schema cache"; "could not find table/relationship"; new column or table not recognized; `42P01`; `520`; API returns nothing | Data API (PostgREST) → `edge_logs`, `postgres_logs` | [Refresh schema cache](/docs/guides/troubleshooting/refresh-postgrest-schema) · [PGRST002](/docs/guides/troubleshooting/postgrest-error-pgrst002-could-not-query-the-database-for-the-schema-cache-c396e9) · [New objects not recognized](/docs/guides/troubleshooting/postgrest-not-recognizing-new-columns-or-functions-bd75f5) · [42P01](/docs/guides/troubleshooting/resolving-42p01-relation-does-not-exist-error-W4_9-V) · [520 errors](/docs/guides/troubleshooting/fixing-520-errors-in-the-database-rest-api-Ur5-B2) · [API not returning](/docs/guides/troubleshooting/why-is-my-supabase-api-call-not-returning-PGzXw0) | -| Login/logout/session broken; JWT "invalid claim"/"missing sub"; cookies not sent; OAuth redirect wrong; OTP/magic-link expired; MFA/TOTP fails; auth `500`/`503`; emails not arriving | Auth → `auth_logs`, `postgres_logs` | [401 missing sub](/docs/guides/troubleshooting/auth-error-401-invalid-claim-missing-sub--AFwMR) · [500 auth errors](/docs/guides/troubleshooting/resolving-500-status-authentication-errors-7bU5U8) · [503 AuthRetryableFetchError](/docs/guides/troubleshooting/auth-error-503-authretryablefetcherror-51b88c) · [OTP expired](/docs/guides/troubleshooting/otp-verification-failures-token-has-expired-or-otp_expired-errors-5ee4d0) · [OAuth not redirecting](/docs/guides/troubleshooting/oauth-sign-in-isnt-redirecting-on-the-server-side-ShGMtr) · [No auth emails](/docs/guides/troubleshooting/not-receiving-auth-emails-from-the-supabase-project-OFSNzw) · [Next.js auth](/docs/guides/troubleshooting/how-do-you-troubleshoot-nextjs---supabase-auth-issues-riMCZV) | -| `statement timeout`; duplicate key or sequence error; trigger errors; slow `ALTER`; blocked queries; disk/memory/swap pressure; index size | Database (Postgres) → `postgres_logs` | [Statement timeout](/docs/guides/troubleshooting/canceling-statement-due-to-statement-timeout-581wFv) · [Duplicate key / sequence](/docs/guides/troubleshooting/inserting-into-sequenceserial-table-causes-duplicate-key-violates-unique-constraint-error-pi6DnC) · [Blocked queries](/docs/guides/troubleshooting/how-to-check-if-my-queries-are-being-blocked-by-other-queries-NSKtR1) · [Disk not shrinking](/docs/guides/troubleshooting/disk-size-not-shrinking-after-deleting-data-135390) · [Autovacuum stalled](/docs/guides/troubleshooting/autovacuum-stalled-due-to-inactive-replication-slot-d55aa2) · [High CPU](/docs/guides/troubleshooting/high-cpu-usage) | -| "too many connections"; "remaining connection slots"; `CONNECT_TIMEOUT`; pooler vs. direct connection; read-only transaction; `prepared statement already exists`; `no pg_hba.conf entry`; IPv4/IPv6; SASL/SCRAM | Connections & pooler → `supavisor_logs`, `postgres_logs` | [Too many connections](/docs/guides/troubleshooting/too-many-connections-for-database-postgres) · [Remaining slots](/docs/guides/troubleshooting/database-error-remaining-connection-slots-are-reserved-for-non-replication-superuser-connections-3V3nIb) · [Prepared statement exists](/docs/guides/troubleshooting/error-prepared-statement-xxx-already-exists-3laqeM) · [Read-only transaction](/docs/guides/troubleshooting/resolving-cannot-execute-update-in-a-read-only-transaction-on-transaction-pooler-connections-ef582c) · [CONNECT_TIMEOUT](/docs/guides/troubleshooting/troubleshooting-connect_timeout-or-hanging-queries-in-vercel-serverless-functions-775f92) · [Supavisor terminology](/docs/guides/troubleshooting/supavisor-and-connection-terminology-explained-9pr_ZO) | -| Edge Function `401`/`404`/`500`/`503`/`504`/`546`; CPU/memory/wall-clock limit hit; won't deploy; boot error; WebSocket drop; `esm.sh` import fails | Edge Functions → `function_edge_logs`, `function_logs` | [401](/docs/guides/troubleshooting/edge-function-401-error-response) · [500](/docs/guides/troubleshooting/edge-function-500-error-response) · [503 boot](/docs/guides/troubleshooting/edge-function-503-response) · [504](/docs/guides/troubleshooting/edge-function-504-error-response) · [546 resource limit](/docs/guides/troubleshooting/edge-function-546-error-response) · [Shutdown reasons](/docs/guides/troubleshooting/edge-function-shutdown-reasons-explained) · [Deploy fails](/docs/guides/troubleshooting/edge-function-fails-deploy) · [esm.sh import](/docs/guides/troubleshooting/importing-stripe-or-other-modules-from-esmsh-on-deno-edge-functions-throws-an-error-TmbB5p) | -| Realtime `TIMED_OUT`; `TooManyChannels`; silent disconnect; missed database changes; broadcast-from-DB warning; heartbeats | Realtime → `realtime_logs` | [TIMED_OUT](/docs/guides/troubleshooting/realtime-connections-timed_out-status) · [TooManyChannels](/docs/guides/troubleshooting/realtime-too-many-channels-error) · [Silent disconnects](/docs/guides/troubleshooting/realtime-handling-silent-disconnections-in-backgrounded-applications-592794) · [Broadcast warning](/docs/guides/troubleshooting/realtime-warn-sending-broadcast-message) · [Heartbeats](/docs/guides/troubleshooting/realtime-heartbeat-messages) · [Logger](/docs/guides/troubleshooting/realtime-debugging-with-logger) | -| Upload or list fails; public bucket inaccessible; `relation "objects" does not exist`; file size limit; folder or RLS issue | Storage → `storage_logs`, `postgres_logs` | [Public bucket upload/list](/docs/guides/troubleshooting/why-cant-i-uploadlistetc-my-public-bucket-Z6CmGt) · [403 RLS on upload](/docs/guides/troubleshooting/storage-error-403-forbidden-new-row-violates-row-level-security-policy-on-upload-a94384) · [relation objects does not exist](/docs/guides/troubleshooting/relation-objects-does-not-exist-error-during-storage-uploads-8f21f0) · [File size limits](/docs/guides/troubleshooting/upload-file-size-restrictions-Y4wQLT) · [Folder ops / hierarchical RLS](/docs/guides/troubleshooting/supabase-storage-inefficient-folder-operations-and-hierarchical-rls-challenges-b05a4d) | -| Webhook not firing; `pg_cron` job not running; `pg_net` queue stuck; `42501 ... http_request_queue` | Database jobs → `postgres_logs` | [Webhook debugging](/docs/guides/troubleshooting/webhook-debugging-guide-M8sk47) · [pg_cron debugging](/docs/guides/troubleshooting/pgcron-debugging-guide-n1KTaz) · [42501 http_request_queue](/docs/guides/troubleshooting/42501--permission-denied-for-table-httprequestqueue-KnozmQ) | -| Reading or querying logs; interpreting Postgres logs; finding API errors in logs; reading metrics | Diagnostics → any log source | [Logging guide](/docs/guides/monitoring-and-debugging/logs) · [Interpret Postgres logs](/docs/guides/troubleshooting/how-to-interpret-and-explore-the-postgres-logs-OuCIOj) · [API errors in logs](/docs/guides/troubleshooting/discovering-and-interpreting-api-errors-in-the-logs-7xREI9) · [Logging levels](/docs/guides/troubleshooting/understanding-postgresql-logging-levels-and-how-they-impact-your-project-KXiJRm) · [View database metrics](/docs/guides/troubleshooting/how-to-view-database-metrics-uqf2z_) | - -For query performance and schema-design questions such as indexing, `EXPLAIN`, N+1 queries, or partitioning, see the [Postgres guides](/docs/guides/database/overview). - -Debugging is complete only once you've re-run the failing operation, confirmed it succeeds, and checked that the layer's logs show a clean result. - -## Per-product debugging - -Each Supabase product has its own debugging resources. Use these as a starting point when the error originates in a specific service. - -- [Database — Debugging and monitoring](/docs/guides/database/inspect) -- [Auth — Error codes](/docs/guides/auth/debugging/error-codes) -- [Storage — Debugging](/docs/guides/storage/debugging/logs) -- [Edge Functions — Local debugging](/docs/guides/functions/debugging-tools) diff --git a/apps/docs/content/guides/monitoring-and-debugging/log-field-reference.mdx b/apps/docs/content/guides/monitoring-and-debugging/log-field-reference.mdx deleted file mode 100644 index 0f18f06eb8674..0000000000000 --- a/apps/docs/content/guides/monitoring-and-debugging/log-field-reference.mdx +++ /dev/null @@ -1,36 +0,0 @@ ---- -id: 'logs-field-reference' -title: 'Logs field reference' -description: 'Supabase Logs field reference' ---- - -Refer to the full field reference for each available source below. To access each nested key, you need to perform the [necessary unnesting joins](/docs/guides/monitoring-and-debugging/advanced-log-filtering#unnesting-arrays) - - - {(logConstants) => ( - - {logConstants.schemas.map((schema) => ( - - - - - - - - - - {schema.fields - .sort((a, b) => a.path - b.path) - .map((field) => ( - - - - - ))} - -
    PathType
    {field.path}{field.type}
    -
    - ))} -
    - )} -
    diff --git a/apps/docs/content/guides/monitoring-and-debugging/logs.mdx b/apps/docs/content/guides/monitoring-and-debugging/logs.mdx deleted file mode 100644 index c63d3faf3ed3e..0000000000000 --- a/apps/docs/content/guides/monitoring-and-debugging/logs.mdx +++ /dev/null @@ -1,417 +0,0 @@ ---- -id: 'logs' -title: 'Logging' -description: 'Getting started with Supabase Log Browser' ---- - -The Supabase Platform includes a Logs Explorer that allows log tracing and debugging. Log retention is based on your [project's pricing plan](/pricing). For details on how Logs usage is billed, see [Manage Logs usage](/docs/guides/platform/manage-your-usage/logs). - - - -If you are debugging a specific error or unexpected behavior, start with the [Debugging guide](/docs/guides/monitoring-and-debugging/debugging) — it routes you to the right log source based on your error code or symptom before you open the Logs Explorer. - - - -## Product logs - -Supabase provides a logging interface specific to each product. You can use regular expressions for keywords and patterns to search log event messages. You can also export and download the log events matching your query as a spreadsheet. - - - -For regular expression filtering, structured-field queries, and field discovery techniques, see [Advanced log filtering](/docs/guides/monitoring-and-debugging/advanced-log-filtering). - - - -{/* */} - - - - -[API logs](/dashboard/project/_/logs/edge-logs) show all network requests and response for the REST and GraphQL [APIs](../../guides/database/api). If [Read Replicas](/docs/guides/platform/read-replicas) are enabled, logs are automatically filtered between databases as well as the [API Load Balancer](/docs/guides/platform/read-replicas#api-load-balancer) endpoint. Logs for a specific endpoint can be toggled with the `Source` button on the upper-right section of the dashboard. - -When viewing logs originating from the API Load Balancer endpoint, the upstream database or the one that eventually handles the request can be found under the `Redirect Identifier` field. This is equivalent to `metadata.load_balancer_redirect_identifier` when querying the underlying logs. - -![API Logs](/docs/img/guides/platform/logs/logs-api.png) - - - - -[Postgres logs](/dashboard/project/_/logs/postgres-logs) show queries and activity for your [database](../../guides/database). If [Read Replicas](/docs/guides/platform/read-replicas) are enabled, logs are automatically filtered between databases. Logs for a specific database can be toggled with the `Source` button on the upper-right section of the dashboard. - -![Postgres Logs](/docs/img/guides/platform/logs/logs-database.png) - - - - -[Auth logs](/dashboard/project/_/logs/auth-logs) show all server logs for your [Auth usage](../../guides/auth). - -![Auth Logs](/docs/img/guides/platform/logs/logs-auth.png) - - - - -[Storage logs](/dashboard/project/_/logs/storage-logs) shows all server logs for your [Storage API](../../guides/storage). - -![Storage Logs](/docs/img/guides/platform/logs/logs-storage.png) - - - - -[Realtime logs](/dashboard/project/_/logs/realtime-logs) show all server logs for your [Realtime API usage](../../guides/realtime). - - - -Realtime connections are not logged by default. Turn on [Realtime connection logs per client](#logging-realtime-connections) with the `log_level` parameter. - - - -![Realtime Logs](/docs/img/guides/platform/logs/logs-realtime.png) - - - - -For each [Edge Function](/dashboard/project/_/functions), logs are available under the following tabs: - -**Invocations** - -The Invocations tab displays the edge logs of function calls. - -![Function Edge Logs](/docs/img/guides/platform/logs/logs-functions-edge.png) - -**Logs** - -The Logs tab displays logs emitted during function execution. - -![Function Logs](/docs/img/guides/platform/logs/logs-functions.png) - -**Log Message Length** - -Edge Function log messages have a max length of 10,000 characters. If you try to log a message longer than that it will be truncated. - - - - ---- - -## Working with API logs - -[API logs](/dashboard/project/_/logs/edge-logs) run through the Cloudflare edge servers and will have attached Cloudflare metadata under the `metadata.request.cf.*` fields. - -### Allowed headers - -A strict list of request and response headers are permitted in the API logs. Request and response headers will still be received by the server(s) and client(s), but will not be attached to the API logs generated. - -Request headers: - -- `accept` -- `cf-connecting-ip` -- `cf-ipcountry` -- `host` -- `user-agent` -- `x-forwarded-proto` -- `referer` -- `content-length` -- `x-real-ip` -- `x-client-info` -- `x-forwarded-user-agent` -- `range` -- `prefer` - -Response headers: - -- `cf-cache-status` -- `cf-ray` -- `content-location` -- `content-range` -- `content-type` -- `content-length` -- `date` -- `transfer-encoding` -- `x-kong-proxy-latency` -- `x-kong-upstream-latency` -- `sb-gateway-mode` -- `sb-gateway-version` - -### Additional request metadata - -To attach additional metadata to a request, it is recommended to use the `User-Agent` header for purposes such as device or version identification. - -For example: - -``` -node MyApp/1.2.3 (device-id:abc123) -Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0 MyApp/1.2.3 (Foo v1.3.2; Bar v2.2.2) -``` - - - -Do not log Personal Identifiable Information (PII) within the `User-Agent` header, to avoid infringing data protection privacy laws. Overly fine-grained and detailed user agents may allow fingerprinting and identification of the end user through PII. - - - -## Logging Postgres connections - -Postgres can log connection lifecycle events to your project's Postgres logs, for example when a client connects or authenticates. By default, Supabase sets `log_connections` to off for new projects and you must enable it first. - -To enable connection logging for audit or compliance, see [Postgres connection logging](/docs/guides/platform/postgres-connection-logging). - -In the [Logs Explorer](/dashboard/project/_/logs-explorer), connection lifecycle messages may be hidden by default. Use the connection logs filter in the sidebar to show them. - -## Logging Postgres queries - -To enable query logs for other categories of statements: - -1. [Enable the pgAudit extension](/dashboard/project/_/database/extensions). -2. Configure `pgaudit.log` (see below). Perform a fast reboot if needed. -3. View your query logs under [Logs > Postgres Logs](/dashboard/project/_/logs/postgres-logs). - -### Configuring `pgaudit.log` - -The stored value under `pgaudit.log` determines the classes of statements that are logged by [pgAudit extension](https://www.pgaudit.org/). Refer to the pgAudit documentation for the [full list of values](https://github.com/pgaudit/pgaudit/blob/master/README.md#pgauditlog). - -To enable logging for function calls/do blocks, writes, and DDL statements for a single session, execute the following within the session: - -```sql --- temporary single-session config update -set pgaudit.log = 'function, write, ddl'; -``` - -To _permanently_ set a logging configuration (beyond a single session), execute the following, then perform a fast reboot: - -```sql --- equivalent permanent config update. -alter role postgres set pgaudit.log to 'function, write, ddl'; -``` - -To help with debugging, we recommend adjusting the log scope to only relevant statements as having too wide of a scope would result in a lot of noise in your Postgres logs. - -Note that in the above example, the role is set to `postgres`. To log user-traffic flowing through the [HTTP APIs](../../guides/database/api#rest-api-overview) powered by PostgREST, set your configuration values for the `authenticator`. - -```sql --- for API-related logs -alter role authenticator set pgaudit.log to 'write'; -``` - -By default, the log level will be set to `log`. To view other levels, run the following: - -```sql --- adjust log level -alter role postgres set pgaudit.log_level to 'info'; -alter role postgres set pgaudit.log_level to 'debug5'; -``` - -Note that as per the pgAudit [log_level documentation](https://github.com/pgaudit/pgaudit/blob/master/README.md#pgauditlog_level), `error`, `fatal`, and `panic` are not allowed. - -To reset system-wide settings, execute the following, then perform a fast reboot: - -```sql --- resets stored config. -alter role postgres reset pgaudit.log -``` - - - -If any permission errors are encountered when executing `alter role postgres ...`, it is likely that your project has yet to receive the patch to the latest version of [supautils](https://github.com/supabase/supautils), which is currently being rolled out. - - - -### `RAISE`d log messages in Postgres - -Messages that are manually logged via `RAISE INFO`, `RAISE NOTICE`, `RAISE WARNING`, and `RAISE LOG` are shown in Postgres Logs. Note that only messages at or above your logging level are shown. Syncing of messages to Postgres Logs may take a few minutes. - -If your logs aren't showing, check your logging level by running: - -```sql -show log_min_messages; -``` - -Note that `LOG` is a higher level than `WARNING` and `ERROR`, so if your level is set to `LOG`, you will not see `WARNING` and `ERROR` messages. - -### Limits and caveats - -- Postgres log events on the Supabase Platform are limited to 100,000 characters. If a log event exceeds this limit, it will be truncated. This does not apply to self-hosting. -- Internal connection logs to Postgres within the Supabase Platform by internal services are not logged. This does not apply to self-hosting. - -## Logging realtime connections - -Realtime doesn't log new WebSocket connections or Channel joins by default. Enable connection logging per client by including an `info` `log_level` parameter when instantiating the Supabase client. - -```javascript -import { createClient } from '@supabase/supabase-js' - -const options = { - realtime: { - params: { - log_level: 'info', - }, - }, -} -const supabase = createClient('https://xyzcompany.supabase.co', 'sb_publishable_...', options) -``` - -## Logs Explorer - -The [Logs Explorer](/dashboard/project/_/logs-explorer) exposes logs from each part of the Supabase stack as a separate table that can be queried and joined using SQL. - -![Logs Explorer](/docs/img/guides/platform/logs/logs-explorer.png) - -You can access the following logs from the **Sources** drop-down: - -- `auth_logs`: GoTrue server logs, containing authentication/authorization activity. -- `edge_logs`: Edge network logs, containing request and response metadata retrieved from Cloudflare. -- `function_edge_logs`: Edge network logs for only edge functions, containing network requests and response metadata for each execution. -- `function_logs`: Function internal logs, containing any `console` logging from within the edge function. -- `postgres_logs`: Postgres database logs, containing statements executed by connected applications. -- `realtime_logs`: Realtime server logs, containing client connection information. -- `storage_logs`: Storage server logs, containing object upload and retrieval information. - -## Querying with the Logs Explorer - -The Logs Explorer runs on **ClickHouse**. Every log line from every source is a single row in the `logs` table, tagged by a `source` column. Structured fields live in a `log_attributes` map whose values are strings, and the raw line is in `event_message`. - - - -ClickHouse has been the default engine since June 2026. Projects created before this date use BigQuery, whose `cross join unnest(metadata)` syntax is deprecated. We recommend rewriting those queries in the ClickHouse syntax shown in this guide. - - - -Read fields with bracket access, keeping the full dotted key, for example `log_attributes['request.path']` rather than `path`. Wrap numeric values in `toInt32OrZero(...)`, which returns `0` for a missing or non-numeric value. Use `count()` rather than `count(*)`. - -For example, to find failing API requests: - -```sql -select timestamp, - toInt32OrZero(log_attributes['response.status_code']) as status, - log_attributes['request.path'] as path -from logs -where source = 'edge_logs' - and toInt32OrZero(log_attributes['response.status_code']) >= 400 -order by timestamp desc -limit 100; -``` - -For example, to find a specific Postgres SQLSTATE (`42501` permission denied, `42P01` relation missing, `23505` duplicate key): - -```sql -select timestamp, log_attributes['parsed.user_name'] as role, event_message -from logs -where source = 'postgres_logs' - and log_attributes['parsed.sql_state_code'] = '42501' -order by timestamp desc -limit 100; -``` - -Do not guess `log_attributes` keys. A missing key returns an empty string rather than an error, so a wrong key makes a working query look empty instead of failing. Discover the real keys for a source, or read `event_message`, which always holds the full line. Statement text and error detail live there, not in `parsed.query` or `parsed.detail`, which are usually empty: - -```sql -select arrayJoin(mapKeys(log_attributes)) as key, count() as n -from logs -where source = 'postgres_logs' -group by key -order by n desc -limit 100; -``` - -If you use the [Supabase MCP server](/docs/guides/ai-tools/mcp), the `query_logs` tool runs a custom ClickHouse query like the ones above on hosted projects. The `get_logs` tool returns a service's recent logs without SQL; it is deprecated on hosted projects in favor of `query_logs`, and remains the option for local and self-hosted projects. - -### LIMIT and result row limitations - -The Logs Explorer has a maximum of 1000 rows per run. Use `LIMIT` to optimize your queries by reducing the number of rows returned further. - -### Best practices - -1. **Include a filter over the timestamp.** - -Querying your entire log history might seem appealing. For **Enterprise** customers that have a large retention range, you run the risk of timeouts due additional time required to scan the larger dataset. - -2. **Avoid selecting large nested objects; select individual values instead.** - -When querying large objects, the columnar storage engine selects each column associated with each nested key, resulting in a large number of columns being selected. This inadvertently impacts the query speed and may result in timeouts or memory errors, especially for projects with a lot of logs. - -Instead, select only the values required. - -```sql --- ❌ Avoid this: selecting the whole attributes map -select timestamp, log_attributes -from logs -where source = 'edge_logs'; - --- ✅ Do this: select only the keys you need -select timestamp, log_attributes['request.method'] as method -from logs -where source = 'edge_logs'; -``` - -3. **Query one source at a time.** - -Identify which service owns the problem from the error or status code first, then query only that source. Scanning every source at once buries the signal you need and scans far more data than the investigation requires. - -4. **Follow a request across sources with an anchor.** Once a query gives you an anchor such as a timestamp, request id, or SQL state, filter the adjacent source by that anchor to correlate the request across layers (for example `edge_logs` to `postgres_logs`), instead of re-scanning each source from scratch. - -5. **Reference only fields you have confirmed.** - -A misspelled or non-existent field name either errors or silently returns nothing, which leaves a working query look empty. Confirm field names in the [field reference](#logs-field-reference), or select `event_message` and inspect a sample row first. - -### Logs field reference - -Refer to the full field reference for each source below. Each source's structured fields are listed as ClickHouse `log_attributes` keys, alongside the base columns (`id`, `timestamp`, `event_message`, `severity_text`, `source`) that every source has. - - - {(logConstants) => { - const otelBaseFields = [ - { path: 'id', type: 'string' }, - { path: 'timestamp', type: 'datetime' }, - { path: 'event_message', type: 'string' }, - { path: 'severity_text', type: 'string' }, - { path: 'source', type: 'string' }, - ] - const baseColumns = new Set(otelBaseFields.map((field) => field.path)) - return ( - - {logConstants.schemas.map((schema) => { - const fields = [ - ...otelBaseFields, - ...schema.fields - .filter((field) => !baseColumns.has(field.path)) - .map((field) => ({ - path: `log_attributes['${field.path.replace(/^metadata\./, '')}']`, - type: field.type, - })), - ] - return ( - - - - - - - - - - {fields.map((field) => ( - - - - - ))} - -
    PathType
    {field.path}{field.type}
    -
    - ) - })} -
    - ) - }} -
    diff --git a/apps/docs/content/guides/observability.mdx b/apps/docs/content/guides/observability.mdx new file mode 100644 index 0000000000000..7b3f6b054a9a6 --- /dev/null +++ b/apps/docs/content/guides/observability.mdx @@ -0,0 +1,38 @@ +--- +title: Observability +description: 'Access project data, detect issues, diagnose findings, and automate repeatable checks with an agent.' +--- + + + +Monitor your Supabase project with the tools you already use, as a person or an agent. + +## 1. Observe the data + +The sources you can query, and where to read them. + + + +## 2. Detect issues + +Use queries and checks against those sources to pick up health, security, performance, and usage signals. + + + +## 3. Diagnose and resolve + +Use a concrete finding, symptom, or error code to identify the cause and apply a known solution. + + + +## 4. Hire an agent + +Turn the checks you trust into a read-only routine in your agent harness and run it on a schedule. + + + +## Export your data + +Send logs and traces to the tools you already run. + + diff --git a/apps/docs/content/guides/observability/access-data.mdx b/apps/docs/content/guides/observability/access-data.mdx new file mode 100644 index 0000000000000..4e5cdbe7ab814 --- /dev/null +++ b/apps/docs/content/guides/observability/access-data.mdx @@ -0,0 +1,31 @@ +--- +id: 'access-data' +title: 'Observe the data' +description: 'Query logs, metrics, database diagnostics, and advisors. Each source page lists Studio, MCP, the API, and the CLI.' +--- + +This guide lists the project data you can query. Each source page lists where to read that source. To pick up a signal from this data, see [Detecting](/docs/guides/observability/detecting). + +## Logs + +Request, database, Auth, Storage, Realtime, and function events in ClickHouse. + +Query them with SQL in [Query and filter logs](/docs/guides/observability/advanced-log-filtering) from the [Logs Explorer](/dashboard/project/_/logs/explorer), MCP `query_logs`, or the [Management API](/docs/reference/api/v1-get-project-logs). Filter events without SQL in [Logs](/docs/guides/observability/logs). See the [Logs field reference](/docs/guides/observability/log-field-reference) for sources and fields. + +The CLI does not query ClickHouse logs. Call the Management API from a script, or [inspect the database](/docs/guides/observability/inspect) for Postgres diagnostics. + +## Metrics [#metrics-api] + +Prometheus-compatible CPU, IO, WAL, connections, and query stats. Scrape the [Metrics API](/docs/guides/observability/metrics) for custom dashboards, alerting, or retention beyond Studio. Chart a subset of the same window in [Reports](/docs/guides/observability/reports). + +## Database + +Live Postgres statistics such as bloat, cache hit rate, blocking sessions, index usage, and slow queries. Run the same checks from the [SQL Editor](/dashboard/project/_/sql), MCP `execute_sql`, or `supabase inspect db`. See [Inspect the database](/docs/guides/observability/inspect). + +## Advisors + +Deterministic security and performance findings. Pull them from Studio, MCP `get_advisors`, [`supabase db advisors`](/docs/reference/cli/usage#supabase-db-advisors), or the Management API. See [Advisors](/docs/guides/observability/advisors). + +## Reports + +Studio dashboards for API, Auth, Storage, Realtime, and database signals. Use them to pick a time window or resource, then follow [Detecting](/docs/guides/observability/detecting). See [Reports](/docs/guides/observability/reports). diff --git a/apps/docs/content/guides/observability/advanced-log-filtering.mdx b/apps/docs/content/guides/observability/advanced-log-filtering.mdx new file mode 100644 index 0000000000000..dc4e02d7f7510 --- /dev/null +++ b/apps/docs/content/guides/observability/advanced-log-filtering.mdx @@ -0,0 +1,539 @@ +--- +title: 'Query and filter logs' +description: 'Query project logs from Studio, MCP, the API, or a script. Record extra Postgres, API, and Realtime events.' +--- + +This guide explains how to query project logs and how to record extra events. The same ClickHouse SQL runs in the [Logs Explorer](/dashboard/project/_/logs/explorer), the MCP [`query_logs`](/docs/guides/ai-tools/mcp) tool, and the [Management API](/docs/reference/api/v1-get-project-logs). Filter events without SQL in [Logs](/docs/guides/observability/logs) in Studio. From a terminal, call the Management API; the CLI inspects the database rather than ClickHouse logs. + +Use this page to: + +- Query logs from [Studio](#studio), [MCP](#mcp), the [API](#api), or a [script](#cli) +- Pick a [`source`](#logs-explorer) for the layer that reported the error +- Record extra [API](#working-with-api-logs), [Postgres](#logging-postgres-queries), and [Realtime](#logging-realtime-connections) events +- Write [ClickHouse SQL](#querying-with-the-logs-explorer) + +Every log line is one row in a single `logs` table, tagged by a `source` column. Structured fields live in a `log_attributes` map, and the raw line is in `event_message`. Filter by `source` to scope a query to one service. + + + +ClickHouse has been the default engine since June 2026. Projects created before this date use BigQuery, whose `cross join unnest(metadata)` syntax is deprecated. We recommend rewriting those queries in the ClickHouse syntax shown in this guide. + + + +On hosted projects, prefer `query_logs` over `get_logs`. `get_logs` returns a service's recent logs without SQL; it remains the option for local and self-hosted projects. + +## Query from Studio, MCP, the API, or the CLI + +### Studio [#studio] + +Open [Logs](/dashboard/project/_/logs) to filter and inspect events. Open the [Logs Explorer](/dashboard/project/_/logs/explorer) to run ClickHouse SQL. See [Logs](/docs/guides/observability/logs) for the unified Logs interface. + +### MCP [#mcp] + +On hosted projects, call [`query_logs`](/docs/guides/ai-tools/mcp) with the same SQL as this guide. Keep the connection project-scoped and read-only. + +### API [#api] + +Pass ClickHouse SQL in the `sql` parameter of the [Management API logs endpoint](/docs/reference/api/v1-get-project-logs). Unless you pass `sql`, that endpoint queries `edge_logs` only. Supply `iso_timestamp_start` and `iso_timestamp_end`; the range must be 24 hours or less. + +### CLI [#cli] + +The Supabase CLI does not query ClickHouse logs. Call the [Management API](/docs/reference/api/v1-get-project-logs) from a script, or use [`supabase inspect db`](/docs/guides/observability/inspect) for database diagnostics. + +## Sources [#logs-explorer] + +Filter by `source` to query one service. The Logs Explorer **Sources** drop-down lists these values. + +Pick the source for the layer that reported the error. A request hits the API gateway first, then one service, then the pooler and Postgres. The layer that _reports_ an error is often not the layer that _caused_ it. When two sources could fit, start closer to the database. + +```mermaid +flowchart TD + Client --> Gateway["API gateway — edge_logs"] + Gateway --> PostgREST + Gateway --> Auth + Gateway --> Storage + Gateway --> Realtime + PostgREST --> Pooler["Pooler — supavisor_logs, pgbouncer_logs"] + Auth --> Pooler + Storage --> Pooler + Pooler --> Postgres["Postgres — postgres_logs"] +``` + +Edge Functions sit outside that path: `function_edge_logs` is the HTTP request to the function, and `function_logs` is `console` output from inside it. + +A permission error or an empty result at the API is often row-level security in `postgres_logs`. + +| `source` | Events | +| -------------------- | ------------------------------------------------------------------------------------------------------ | +| `edge_logs` | HTTP requests through the API gateway, including REST and GraphQL | +| `postgres_logs` | Database queries, SQLSTATE, RLS, and functions | +| `postgrest_logs` | PostgREST process logs. Low-signal; `PGRST*` evidence usually lives in `edge_logs` and `postgres_logs` | +| `auth_logs` | Auth server: login, JWT, OAuth, email | +| `auth_audit_logs` | Auth audit events | +| `storage_logs` | Storage API: uploads and object access | +| `realtime_logs` | Realtime server: channels, presence, broadcast | +| `function_edge_logs` | HTTP request and response for an Edge Function invocation | +| `function_logs` | `console` output from inside an Edge Function | +| `supavisor_logs` | Shared pooler: pooling and timeouts | +| `pgbouncer_logs` | Dedicated pooler | +| `pg_upgrade_logs` | Database version upgrade | + +For `postgres_logs`, statement text and error detail live in `event_message`. `parsed.query` and `parsed.detail` are usually empty. + +For API Load Balancer traffic, the upstream database is `log_attributes['load_balancer_redirect_identifier']`. + +See the [Logs field reference](/docs/guides/observability/log-field-reference) for the ClickHouse field names on each source. + +## Working with API logs [#working-with-api-logs] + +API Gateway logs run through Cloudflare and include Cloudflare metadata on the request. + +### Allowed headers + +A strict list of request and response headers are permitted in the API logs. Request and response headers will still be received by the server(s) and client(s), but will not be attached to the API logs generated. + +Request headers: + +- `accept` +- `cf-connecting-ip` +- `cf-ipcountry` +- `host` +- `user-agent` +- `x-forwarded-proto` +- `referer` +- `content-length` +- `x-real-ip` +- `x-client-info` +- `x-forwarded-user-agent` +- `range` +- `prefer` + +Response headers: + +- `cf-cache-status` +- `cf-ray` +- `content-location` +- `content-range` +- `content-type` +- `content-length` +- `date` +- `transfer-encoding` +- `x-kong-proxy-latency` +- `x-kong-upstream-latency` +- `sb-gateway-mode` +- `sb-gateway-version` + +### Additional request metadata + +To attach additional metadata to a request, it is recommended to use the `User-Agent` header for purposes such as device or version identification. + +For example: + +``` +node MyApp/1.2.3 (device-id:abc123) +Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0 MyApp/1.2.3 (Foo v1.3.2; Bar v2.2.2) +``` + + + +Do not log Personal Identifiable Information (PII) within the `User-Agent` header, to avoid infringing data protection privacy laws. Overly fine-grained and detailed user agents may allow fingerprinting and identification of the end user through PII. + + + +## Logging Postgres connections [#logging-postgres-connections] + +Postgres can log connection lifecycle events to your project's Postgres logs, for example when a client connects or authenticates. By default, Supabase sets `log_connections` to off for new projects and you must enable it first. + +To enable connection logging for audit or compliance, see [Postgres connection logging](/docs/guides/platform/postgres-connection-logging). + +In Logs, connection lifecycle messages are included when the Postgres log type is selected. Clear **Connection logs** under Postgres to hide them. + +## Logging Postgres queries [#logging-postgres-queries] + +To enable query logs for other categories of statements: + +1. [Enable the pgAudit extension](/dashboard/project/_/database/extensions). +2. Configure `pgaudit.log` (see below). Perform a fast reboot if needed. +3. View your query logs in [Logs](/dashboard/project/_/logs). Filter **Log Type** to Postgres. + +### Configuring `pgaudit.log` [#configuring-pgauditlog] + +The stored value under `pgaudit.log` determines the classes of statements that are logged by [pgAudit extension](https://www.pgaudit.org/). Refer to the pgAudit documentation for the [full list of values](https://github.com/pgaudit/pgaudit/blob/master/README.md#pgauditlog). + +To enable logging for function calls/do blocks, writes, and DDL statements for a single session, execute the following within the session: + +```sql +-- temporary single-session config update +set pgaudit.log = 'function, write, ddl'; +``` + +To _permanently_ set a logging configuration (beyond a single session), execute the following, then perform a fast reboot: + +```sql +-- equivalent permanent config update. +alter role postgres set pgaudit.log to 'function, write, ddl'; +``` + +To help with debugging, we recommend adjusting the log scope to only relevant statements as having too wide of a scope would result in a lot of noise in your Postgres logs. + +Note that in the above example, the role is set to `postgres`. To log user traffic flowing through the [HTTP APIs](/docs/guides/api#rest-api-overview), which use PostgREST, set your configuration values for the `authenticator`. + +```sql +-- for API-related logs +alter role authenticator set pgaudit.log to 'write'; +``` + +By default, the log level will be set to `log`. To view other levels, run the following: + +```sql +-- adjust log level +alter role postgres set pgaudit.log_level to 'info'; +alter role postgres set pgaudit.log_level to 'debug5'; +``` + +Note that as per the pgAudit [log_level documentation](https://github.com/pgaudit/pgaudit/blob/master/README.md#pgauditlog_level), `error`, `fatal`, and `panic` are not allowed. + +To reset system-wide settings, execute the following, then perform a fast reboot: + +```sql +-- resets stored config. +alter role postgres reset pgaudit.log +``` + + + +If any permission errors are encountered when executing `alter role postgres ...`, it is likely that your project has yet to receive the patch to the latest version of [supautils](https://github.com/supabase/supautils), which is currently being rolled out. + + + +### `RAISE`d log messages in Postgres + +Messages that are manually logged via `RAISE INFO`, `RAISE NOTICE`, `RAISE WARNING`, and `RAISE LOG` are shown in Postgres Logs. Note that only messages at or above your logging level are shown. Syncing of messages to Postgres Logs may take a few minutes. + +If your logs aren't showing, check your logging level by running: + +```sql +show log_min_messages; +``` + +Note that `LOG` is a higher level than `WARNING` and `ERROR`, so if your level is set to `LOG`, you will not see `WARNING` and `ERROR` messages. + +### Limits and caveats + +- Postgres log events on the Supabase Platform are limited to 100,000 characters. If a log event exceeds this limit, it will be truncated. This does not apply to self-hosting. +- Internal connection logs to Postgres within the Supabase Platform by internal services are not logged. This does not apply to self-hosting. + +## Logging realtime connections [#logging-realtime-connections] + +Realtime doesn't log new WebSocket connections or Channel joins by default. Enable connection logging per client by including an `info` `log_level` parameter when instantiating the Supabase client. + +```javascript +import { createClient } from '@supabase/supabase-js' + +const options = { + realtime: { + params: { + log_level: 'info', + }, + }, +} +const supabase = createClient('https://xyzcompany.supabase.co', 'sb_publishable_...', options) +``` + +## Querying logs [#querying-with-the-logs-explorer] + +Read fields with bracket access, keeping the full dotted key, for example `log_attributes['request.path']` rather than `path`. Wrap numeric values in `toInt32OrZero(...)`, which returns `0` for a missing or non-numeric value. Use `count()` rather than `count(*)`. + +For example, to find failing API requests: + +```sql +select timestamp, + toInt32OrZero(log_attributes['response.status_code']) as status, + log_attributes['request.path'] as path +from logs +where source = 'edge_logs' + and toInt32OrZero(log_attributes['response.status_code']) >= 400 +order by timestamp desc +limit 100; +``` + +For example, to find a specific Postgres SQLSTATE (`42501` permission denied, `42P01` relation missing, `23505` duplicate key): + +```sql +select timestamp, log_attributes['parsed.user_name'] as role, event_message +from logs +where source = 'postgres_logs' + and log_attributes['parsed.sql_state_code'] = '42501' +order by timestamp desc +limit 100; +``` + +The Management API accepts this SQL in the `sql` parameter. Unless you pass `sql`, that endpoint queries `edge_logs` only. Supply `iso_timestamp_start` and `iso_timestamp_end`; the range must be 24 hours or less. + +## Timestamp display and behavior + +The `timestamp` column is a `DateTime64` value in UTC, formatted as an ISO-8601 string like `2026-06-22T09:34:06.215000`. You can order and compare it directly, so no conversion function is needed. In the Logs Explorer the selected time range is applied for you, so you rarely need to filter on `timestamp` by hand. MCP and the Management API require an explicit time range. + +```sql +select timestamp, event_message +from logs +where source = 'edge_logs' +order by timestamp desc +limit 100; +``` + +## Reading fields from log_attributes + +Structured fields live in the `log_attributes` map. Read a field with bracket access, keeping the full dotted key. There are no unnesting joins. + +```sql +select + log_attributes['request.method'] as method, + log_attributes['request.path'] as path, + log_attributes['response.status_code'] as status +from logs +where source = 'edge_logs' +limit 100; +``` + +The key keeps the full dotted path, with the `metadata` root dropped. What BigQuery expressed as `metadata.request.cf.country` is `log_attributes['request.cf.country']`. Keep the full prefix rather than shortening it. + +Map values are always strings. To compare or aggregate a numeric field, wrap it in `toInt32OrZero`, which returns `0` for a missing or non-numeric value: + +```sql +select count() as server_errors +from logs +where source = 'edge_logs' + and toInt32OrZero(log_attributes['response.status_code']) between 500 and 599; +``` + +Do not guess keys. Discover the keys a source sets from recent rows: + +```sql +select arrayJoin(mapKeys(log_attributes)) as key, count() as n +from logs +where source = 'postgres_logs' +group by key +order by n desc +limit 100; +``` + +## LIMIT and result row limitations + +The Logs Explorer has a maximum of 1000 rows per run. Use `LIMIT` to reduce the number of rows returned further. + +## Best practices + +1. **Use a narrow time range.** + +The Logs Explorer applies the time range you select, so keep it tight. Querying a very large range risks timeouts, especially for Enterprise customers with long retention, because of the extra data scanned. + +2. **Select only the fields you need.** + +Selecting the whole `log_attributes` map, or every column, reads far more data than you need and slows the query down. Select the specific keys instead. + +```sql +-- ❌ Avoid this: selecting the whole attributes map +select timestamp, log_attributes +from logs +where source = 'edge_logs'; + +-- ✅ Do this: select only the keys you need +select timestamp, log_attributes['request.method'] as method +from logs +where source = 'edge_logs'; +``` + +3. **Query one source at a time.** + +Identify which service owns the problem from the error or status code first, then query only that source. Scanning every source at once buries the signal you need and scans far more data than the investigation requires. + +4. **Follow a request across sources with an anchor.** Once a query gives you an anchor such as a timestamp, request id, or SQL state, filter the adjacent source by that anchor to correlate the request across layers (for example `edge_logs` to `postgres_logs`), instead of re-scanning each source from scratch. + +5. **Reference only fields you have confirmed.** + +A misspelled or non-existent field name either errors or silently returns nothing, which leaves a working query look empty. Confirm field names in the [Logs field reference](/docs/guides/observability/log-field-reference), or select `event_message` and inspect a sample row first. + +## Examples and templates + +The Logs Explorer includes **Templates** (available in the Templates tab or the dropdown in the Query tab) to help you get started. + +For example, you can enter the following query in the SQL Editor to retrieve each user's IP address: + +```sql +select timestamp, log_attributes['request.headers.x_real_ip'] as x_real_ip +from logs +where source = 'edge_logs' + and log_attributes['request.headers.x_real_ip'] != '' + and log_attributes['request.method'] = 'GET' +order by timestamp desc +limit 100; +``` + +## Understanding field references + +Every log source shares the same `logs` table. Each row has these columns: + +| column | description | +| ---------------- | -------------------------------------------------- | +| `id` | unique log identifier | +| `timestamp` | time the event was recorded | +| `event_message` | the log's message | +| `severity_text` | log level, when the source sets one | +| `source` | the service the log came from | +| `log_attributes` | structured per-source fields, keyed by dotted path | + +Service-specific details live in `log_attributes`. For example, in `postgres_logs` the `log_attributes['parsed.error_severity']` field holds the error level of an event. Read those fields with bracket access: + +```sql +select + event_message, + log_attributes['parsed.error_severity'] as error_severity, + log_attributes['parsed.user_name'] as user_name +from logs +where source = 'postgres_logs' +limit 100; +``` + +## Filtering with [regular expressions](https://en.wikipedia.org/wiki/Regular_expression) + +Use the ClickHouse [`match` function](https://clickhouse.com/docs/sql-reference/functions/string-search-functions#match) for regular expressions. In its most basic form, it checks whether a pattern is present in a column. + +```sql +select timestamp, event_message +from logs +where source = 'postgres_logs' + and match(event_message, 'is present') +limit 100; +``` + +There are multiple operators to consider using. + +### Find messages that start with a phrase + +`^` only looks for values at the start of a string + +```sql +-- find only messages that start with connection +match(event_message, '^connection') +``` + +### Find messages that end with a phrase + +`$` only looks for values at the end of the string + +```sql +-- find only messages that end with port=12345 +match(event_message, 'port=12345$') +``` + +### Ignore case sensitivity + +`(?i)` ignores capitalization for all proceeding characters + +```sql +-- find all event_messages with the word "connection" +match(event_message, '(?i)COnnecTion') +``` + +For a plain case-insensitive substring match, `ilike` is simpler: + +```sql +-- find all event_messages containing "connection", in any case +event_message ilike '%connection%' +``` + +### Wildcards + +`.` matches any single character, and `.*` matches any sequence of characters + +```sql +-- find event_messages like "helloworld" +match(event_message, 'hello.*world') +``` + +### Alphanumeric ranges + +`[0-9a-zA-Z]` matches a single alphanumeric character. Anchor it with `^[0-9a-zA-Z]+$` to match a value that is entirely alphanumeric. + +```sql +-- find event_messages that contain a digit between 1 and 5 (inclusive) +match(event_message, '[1-5]') +``` + +### Repeated values + +`x*` zero or more x +`x+` one or more x +`x?` zero or one x +`x{4,}` four or more x +`x{3}` exactly 3 x + +```sql +-- find event_messages that contain any sequence of 3 digits +match(event_message, '[0-9]{3}') +``` + +### Escaping reserved characters + +`\.` is interpreted as a period `.` instead of as a wildcard + +```sql +-- escapes . +match(event_message, 'hello world\.') +``` + +### `or` statements + +`x|y` any string with `x` or `y` present + +```sql +-- find event_messages that have the word 'started' followed by either "host" or "authenticated" +match(event_message, 'started (host|authenticated)') +``` + +### `and`/`or`/`not` statements in SQL + +`and`, `or`, and `not` are native terms in SQL and can be used with regular expressions to filter results + +```sql +select timestamp, event_message +from logs +where source = 'postgres_logs' + and ( + (match(event_message, 'connection') and match(event_message, 'host')) + or not match(event_message, 'received') + ) +limit 100; +``` + +### Filtering example + +Filter for Postgres errors: + +```sql +select + timestamp, + log_attributes['parsed.error_severity'] as error_severity, + log_attributes['parsed.user_name'] as user_name, + event_message +from logs +where source = 'postgres_logs' + and match(log_attributes['parsed.error_severity'], 'ERROR|FATAL|PANIC') +order by timestamp desc +limit 100; +``` + +## Limitations + +### The wildcard operator `*` is not supported + +The logs query surface rejects `select *` and `count(*)`. List the columns you need, and use `count()` for row counts: + +```sql +select timestamp, event_message, log_attributes['parsed.error_severity'] as error_severity +from logs +where source = 'postgres_logs' +order by timestamp desc +limit 100; +``` diff --git a/apps/docs/content/guides/observability/advisors.mdx b/apps/docs/content/guides/observability/advisors.mdx new file mode 100644 index 0000000000000..7f64deff229f8 --- /dev/null +++ b/apps/docs/content/guides/observability/advisors.mdx @@ -0,0 +1,22 @@ +--- +id: 'advisors' +title: 'Advisors' +description: 'Deterministic security and performance findings you or an agent can pull as part of ongoing observability.' +--- + +Advisors are programmatic checks that ship with the platform. They inspect the live schema and return deterministic findings, such as missing indexes or incorrectly configured RLS policies. + +Use them as part of ongoing observability, together with [logs](/docs/guides/observability/advanced-log-filtering). A finding is not a fix. Confirm it against recent log evidence, then search [Diagnosing](/docs/guides/troubleshooting) for the check name or the object it names. + +You or an agent can pull the same checks from: + +- Studio: [Security Advisor](/dashboard/project/_/advisors/security) and [Performance Advisor](/dashboard/project/_/advisors/performance) +- MCP: `get_advisors` +- CLI: [`supabase db advisors`](/docs/reference/cli/supabase-db-advisors) +- Management API: [security advisors](/docs/reference/api/v1-get-security-advisors) and [performance advisors](/docs/reference/api/v1-get-performance-advisors) + +The advisors run automatically in Studio. Rerun them after you resolve an issue. + +## Available checks + + diff --git a/apps/docs/content/guides/observability/automate-with-agents.mdx b/apps/docs/content/guides/observability/automate-with-agents.mdx new file mode 100644 index 0000000000000..f36a0a83a9ea1 --- /dev/null +++ b/apps/docs/content/guides/observability/automate-with-agents.mdx @@ -0,0 +1,38 @@ +--- +id: 'automate-with-agents' +title: 'Hire an agent' +subtitle: 'Run a read-only monitoring routine in your own agent harness.' +description: 'Choose and set up a Health, Security, Performance, or Capacity monitor in Claude, Codex, or Cursor.' +--- + +This guide explains how to run a Supabase monitoring agent in your own harness. Each agent is a prompt plus a schedule. It reads project data and reports findings. It does not change the project. + +## Choose a routine + +Start with one monitor. Add another only when the project needs a different source or cadence. + +| Monitor | What it watches | Default cadence | Use it when | +| ---------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | --------------- | -------------------------------------------------------------- | +| [Health monitor](/docs/guides/observability/automate-with-agents/health) | API and Auth server errors, error-rate spikes, connection pressure | Hourly | You need incident detection and regular feedback loops | +| [Security monitor](/docs/guides/observability/automate-with-agents/security) | Security Advisor findings, authentication and authorization failures | Daily | You need a regular access-control and configuration review | +| [Performance monitor](/docs/guides/observability/automate-with-agents/performance) | Slow queries, lock waits, long-running sessions, Performance Advisor findings | Hourly | You need query and database performance checks | +| [Capacity monitor](/docs/guides/observability/automate-with-agents/usage) | Request, error, storage, table, and connection growth | Daily | You need to identify growth before it reaches a resource limit | + +For a small project, run the most relevant routine daily or weekly and include the other categories in its prompt. Split it into specialized monitors only when you need different owners, schedules, or alert thresholds. + +## Run the routine + +1. Connect the [Supabase MCP server](/docs/guides/ai-tools/mcp) with `project_ref` and `read_only=true`. +2. Open the monitor that matches the job from the table above. +3. Set it up in Claude, Codex, Cursor, or copy the prompt into another harness. +4. Run it on demand first. Then put the same prompt on a schedule. + +Each agent page describes what it will output. Send those findings through the connections your harness already has, such as Linear in Codex. + +Scheduled tasks start a fresh context on every run, so the prompt is self-contained. Review the first runs before you rely on the schedule. + + + +Logs and query results can contain secrets or personal information. Keep the agent read-only, aggregate evidence, and redact sensitive values. + + diff --git a/apps/docs/content/guides/observability/automate-with-agents/all.mdx b/apps/docs/content/guides/observability/automate-with-agents/all.mdx new file mode 100644 index 0000000000000..cca409477ee99 --- /dev/null +++ b/apps/docs/content/guides/observability/automate-with-agents/all.mdx @@ -0,0 +1,40 @@ +--- +id: 'automate-with-agents-all' +title: 'Generalist' +subtitle: 'Generalist is a read-only daily agent. It runs all four checks — health, security, performance, and usage — and reports only findings that need attention.' +description: 'A once-daily agent that checks all signal sources and reports across health, security, performance, and usage.' +--- + +```mermaid +flowchart TD + Schedule([Once per day]) --> Health[query_logs: health] + Schedule --> Security[get_advisors: security] + Schedule --> Performance[get_advisors + pg_stat_activity] + Schedule --> Usage[execute_sql: sizes and growth] + Health & Security & Performance & Usage --> Filter{Anything to report?} + Filter -->|Yes| Report[Daily summary] + Filter -->|No| Silent[Stay silent] +``` + +## What it watches + +- **Health** — API 5xx, Auth failures, error-rate spikes in the last 24 hours +- **Security** — Security Advisor findings, authorization failure spikes +- **Performance** — slow queries, lock waits, Performance Advisor findings +- **Usage** — database size, connection counts, API request growth, approaching limits + +It uses `query_logs`, `get_advisors`, and read-only `execute_sql` on project-scoped [Supabase MCP](/docs/guides/ai-tools/mcp). It does not change the project. + +## When it watches + + + +## What it will output + +Generalist reports only checks that turn up a finding. If health is clear, that section is omitted. If all checks are clear, the agent stays silent. When it does report, each section follows the same format as the specialist agent: a grouped finding, a likely cause, and a next step for a person to act on. + +<$Partial path="monitoring_agent_output.mdx" /> + +## Set up the agent + + diff --git a/apps/docs/content/guides/observability/automate-with-agents/health.mdx b/apps/docs/content/guides/observability/automate-with-agents/health.mdx new file mode 100644 index 0000000000000..caf743d941cb8 --- /dev/null +++ b/apps/docs/content/guides/observability/automate-with-agents/health.mdx @@ -0,0 +1,37 @@ +--- +id: 'automate-with-agents-health' +title: 'Health monitor' +subtitle: 'Health monitor is a read-only agent. It polls logs on a short interval, clusters errors, and reports only when a threshold is crossed.' +description: 'An on-call triage agent that watches logs for 5xx spikes, Auth failures, and availability issues.' +--- + +```mermaid +flowchart TD + Schedule([Every hour]) --> Inspect[query_logs] + Inspect --> Signals["5xx, Auth failures, error-rate spikes"] + Signals --> Threshold{Threshold crossed?} + Threshold -->|Yes| Report[Incident report] + Threshold -->|No| Silent[Stay silent] +``` + +## What it watches + +- API and Auth responses with status `>= 500` +- Error-rate spikes against a recent baseline +- Connection pressure when database inspection is available + +It uses `query_logs` on project-scoped, read-only [Supabase MCP](/docs/guides/ai-tools/mcp). It can use `get_advisors` for extra context. It does not change the project. + +## When it watches + + + +## What it will output + +When a threshold is crossed, Health monitor reports an incident: grouped errors, a few request IDs, a likely cause, and a troubleshooting link. If nothing crosses the threshold, it stays silent. + +<$Partial path="monitoring_agent_output.mdx" /> + +## Set up the agent + + diff --git a/apps/docs/content/guides/observability/automate-with-agents/performance.mdx b/apps/docs/content/guides/observability/automate-with-agents/performance.mdx new file mode 100644 index 0000000000000..333f77abb07ff --- /dev/null +++ b/apps/docs/content/guides/observability/automate-with-agents/performance.mdx @@ -0,0 +1,37 @@ +--- +id: 'automate-with-agents-performance' +title: 'Performance monitor' +subtitle: 'Performance monitor is a read-only agent. It inspects query statistics, blocking sessions, and Performance Advisor findings, then proposes the next change for a person to apply.' +description: 'A query health agent that looks for slow queries, lock waits, and performance advisor findings.' +--- + +```mermaid +flowchart TD + Schedule([Once per hour]) --> Inspect[get_advisors and execute_sql] + Inspect --> Signals["Slow queries, lock waits, advisor findings"] + Signals --> Review{Needs a change?} + Review -->|Yes| Report[Finding and verification plan] + Review -->|No| Silent[Stay silent] +``` + +## What it watches + +- Slow or regressing queries +- Lock waits and long-running sessions +- Unindexed foreign keys and other Performance Advisor findings + +It uses `get_advisors` and read-only `execute_sql` on project-scoped [Supabase MCP](/docs/guides/ai-tools/mcp). It does not create indexes, rewrite queries, or cancel sessions. + +## When it watches + + + +## What it will output + +Performance monitor reports slow or regressing queries, lock waits, and Performance Advisor findings, with a verification plan. It can recommend that a person cancel a session. It does not cancel the session or create indexes. + +<$Partial path="monitoring_agent_output.mdx" /> + +## Set up the agent + + diff --git a/apps/docs/content/guides/observability/automate-with-agents/security.mdx b/apps/docs/content/guides/observability/automate-with-agents/security.mdx new file mode 100644 index 0000000000000..8ff0ae96aa689 --- /dev/null +++ b/apps/docs/content/guides/observability/automate-with-agents/security.mdx @@ -0,0 +1,37 @@ +--- +id: 'automate-with-agents-security' +title: 'Security monitor' +subtitle: 'Security monitor is a read-only agent. It reviews Security Advisor findings and bounded authentication or authorization failure counts, then proposes changes for a person to apply.' +description: 'A security review agent that reports advisor findings and authentication or authorization spikes.' +--- + +```mermaid +flowchart TD + Schedule([Once per day]) --> Inspect[get_advisors and query_logs] + Inspect --> Signals[Advisor warnings and auth failures] + Signals --> Review{Needs review?} + Review -->|Yes| Report[Findings and proposed fix] + Review -->|No| Silent[Stay silent] +``` + +## What it watches + +- Security Advisor findings at warning and error level +- Authentication and authorization failure spikes +- RLS or privilege issues that advisors already name + +It uses `get_advisors` and `query_logs` on project-scoped, read-only [Supabase MCP](/docs/guides/ai-tools/mcp). It does not change policies, grants, API keys, or Auth settings. + +## When it watches + + + +## What it will output + +Security monitor reports warning and error advisor findings, grouped authentication or authorization failures, and the least invasive fix for a person to apply. If nothing needs review, it stays silent. + +<$Partial path="monitoring_agent_output.mdx" /> + +## Set up the agent + + diff --git a/apps/docs/content/guides/observability/automate-with-agents/usage.mdx b/apps/docs/content/guides/observability/automate-with-agents/usage.mdx new file mode 100644 index 0000000000000..5889a000b6581 --- /dev/null +++ b/apps/docs/content/guides/observability/automate-with-agents/usage.mdx @@ -0,0 +1,37 @@ +--- +id: 'automate-with-agents-usage' +title: 'Capacity monitor' +subtitle: 'Capacity monitor is a read-only agent. It trends API request volume and error rates, then warns before traffic or errors look like a capacity problem.' +description: 'A capacity agent that tracks API request growth, error rates, and approaching resource ceilings.' +--- + +```mermaid +flowchart TD + Schedule([Once each morning]) --> Inspect[query_logs and usage APIs] + Inspect --> Signals["Request growth, error rates, resource trends"] + Signals --> Limit{Likely to hit a limit?} + Limit -->|Yes| Report["Trend, projected date, scaling guide"] + Limit -->|No| Silent[Stay silent] +``` + +## What it watches + +- API request growth against a recent baseline +- Server-error rate increases +- Disk, connection, or table growth when database inspection is available + +It uses `query_logs` on project-scoped, read-only [Supabase MCP](/docs/guides/ai-tools/mcp) and the [Management API usage endpoints](/docs/reference/api/v1-get-project-usage-api-count) when those are already authorized. It does not change billing, compute, or plan settings. MCP does not expose organization billing totals. + +## When it watches + + + +## What it will output + +Capacity monitor reports request growth, error-rate changes, and resource trends. If a metric looks likely to hit a limit within 14 days, it flags the date and the relevant scaling guide. + +<$Partial path="monitoring_agent_output.mdx" /> + +## Set up the agent + + diff --git a/apps/docs/content/guides/monitoring-and-debugging/client-side-tracing.mdx b/apps/docs/content/guides/observability/client-side-tracing.mdx similarity index 98% rename from apps/docs/content/guides/monitoring-and-debugging/client-side-tracing.mdx rename to apps/docs/content/guides/observability/client-side-tracing.mdx index 790e92d11de50..003a67dded140 100644 --- a/apps/docs/content/guides/monitoring-and-debugging/client-side-tracing.mdx +++ b/apps/docs/content/guides/observability/client-side-tracing.mdx @@ -279,4 +279,4 @@ After trace context is flowing through, the `trace_id` appears in: - **API Gateway logs** — every request to PostgREST, Auth, Storage, and Realtime - **Edge Function logs** — invocations and any structured logs emitted from within the function -If you forward Supabase logs to a third-party backend via [Log Drains](/docs/guides/monitoring-and-debugging/log-drains), you can join Supabase logs to your own client and server traces using the shared `trace_id`. This is especially useful for self-hosted setups where you already operate your own OpenTelemetry collector — Supabase logs become first-class citizens in your existing tracing UI. +If you forward Supabase logs to a third-party backend via [Log Drains](/docs/guides/observability/log-drains), you can join Supabase logs to your own client and server traces using the shared `trace_id`. This is especially useful for self-hosted setups where you already operate your own OpenTelemetry collector — Supabase logs become first-class citizens in your existing tracing UI. diff --git a/apps/docs/content/guides/observability/detecting.mdx b/apps/docs/content/guides/observability/detecting.mdx new file mode 100644 index 0000000000000..7196a9779cd23 --- /dev/null +++ b/apps/docs/content/guides/observability/detecting.mdx @@ -0,0 +1,283 @@ +--- +id: 'detecting' +title: 'Detecting issues' +description: 'Run Health, Security, Performance, and Usage checks against logs and database statistics to pick up actionable signals.' +--- + +Detection is the step between accessing project data and troubleshooting a specific problem. Use the sources in [Observe the data](/docs/guides/observability/access-data) to produce a count, rate, trend, or named finding. Do not try to prove the root cause yet. + +This guide provides starting checks for [Health](#health), [Security](#security), [Performance](#performance), and [Usage](#usage). The log examples use ClickHouse SQL in the [Logs Explorer](/dashboard/project/_/logs/explorer) or MCP `query_logs`. The database examples use Postgres SQL in the [SQL Editor](/dashboard/project/_/sql) or MCP `execute_sql`. + +Use a time range that represents normal traffic, then compare it with the same period after a deployment or configuration change. When a check returns a spike, error code, SQLSTATE, object name, or advisor finding, take that evidence to [Diagnosing](/docs/guides/troubleshooting). + +## Health + +Health checks answer whether a service is available and behaving within its normal error and resource envelope. + +### Measure API server-error rate + +Count requests and 5xx responses by hour. A rate is more useful than a raw error count when traffic changes. + +```sql +select + toStartOfHour(timestamp) as hour, + count() as requests, + countIf(toInt32OrZero(log_attributes['response.status_code']) >= 500) as server_errors, + round( + 100.0 * countIf(toInt32OrZero(log_attributes['response.status_code']) >= 500) / + nullIf(count(), 0), + 2 + ) as server_error_percent +from logs +where source = 'edge_logs' +group by hour +order by hour desc +limit 24; +``` + +### Find failing API paths + +Use the rate check to find an affected window, then identify the paths and status codes producing the errors. + +```sql +select + log_attributes['request.path'] as path, + toInt32OrZero(log_attributes['response.status_code']) as status, + count() as errors +from logs +where source = 'edge_logs' + and toInt32OrZero(log_attributes['response.status_code']) >= 500 +group by path, status +order by errors desc +limit 20; +``` + +### Check Postgres connection pressure + +Compare active and waiting connections with the configured limit. A high percentage is a signal to inspect pooler settings, long-running transactions, and traffic before changing the limit. + +```sql +select + count(*) as current_connections, + count(*) filter (where state = 'active') as active_connections, + count(*) filter (where wait_event_type is not null) as waiting_connections, + current_setting('max_connections')::int as max_connections, + round( + 100.0 * count(*) / nullif(current_setting('max_connections')::int, 0), + 2 + ) as connection_percent +from pg_stat_activity; +``` + +You can read API response errors and service availability in [Reports](/docs/guides/observability/reports), or use the [Metrics API](/docs/guides/observability/metrics) for CPU and connection series. Once you have a failing path, status, or saturated resource, continue in [Diagnosing](/docs/guides/troubleshooting). + +## Security + +Security checks look for access-control findings and changes in authentication or authorization failures. Treat them as review signals, not proof of an attack. + +### Measure authorization failures + +Count 401 and 403 responses by hour and status. Compare the rate with a known-good window so normal unauthenticated traffic does not become an alert by itself. + +```sql +select + toStartOfHour(timestamp) as hour, + toInt32OrZero(log_attributes['response.status_code']) as status, + count() as failures +from logs +where source = 'edge_logs' + and toInt32OrZero(log_attributes['response.status_code']) in (401, 403) +group by hour, status +order by hour desc, status +limit 48; +``` + +### Find affected paths and methods + +After detecting a spike, group failures by route and method. This separates a broken client flow from failures spread across the API. + +```sql +select + log_attributes['request.method'] as method, + log_attributes['request.path'] as path, + toInt32OrZero(log_attributes['response.status_code']) as status, + count() as failures +from logs +where source = 'edge_logs' + and toInt32OrZero(log_attributes['response.status_code']) in (401, 403) +group by method, path, status +order by failures desc +limit 20; +``` + +### Find public-schema tables without RLS + +This database query is a focused inventory check. Confirm each result against the project's intended access model; a result is not evidence that data was exposed. + +```sql +select + n.nspname as schema_name, + c.relname as table_name +from + pg_class as c + join pg_namespace as n on n.oid = c.relnamespace +where n.nspname = 'public' and c.relkind in ('r', 'p') and not c.relrowsecurity +order by table_name; +``` + +Run [Security Advisor](/docs/guides/observability/advisors) from Studio, MCP `get_advisors`, the CLI, or the Management API for the full catalog of deterministic checks. Take a lint name, table, policy, path, or status pattern to [Diagnosing](/docs/guides/troubleshooting) before changing policies, grants, or keys. + +## Performance + +Performance checks identify expensive work, contention, and cache misses. They narrow the investigation to a query, relation, session, or resource. + +### Find long-running sessions + +Look for sessions that have been active or idle in a transaction for more than 30 seconds. + +```sql +select + pid, + usename as role, + state, + now() - query_start as duration, + wait_event_type, + wait_event, + left(query, 120) as query +from pg_stat_activity +where datname = current_database() + and pid != pg_backend_pid() + and state in ('active', 'idle in transaction') + and now() - query_start > interval '30 seconds' +order by duration desc +limit 20; +``` + +### Find blocked sessions + +Use `pg_blocking_pids` to name the blocked and blocking processes. Do not cancel either process until you understand the transaction and its impact. + +```sql +select + blocked.pid as blocked_pid, + blocked.usename as blocked_role, + blocker.pid as blocking_pid, + blocker.usename as blocking_role, + now() - blocked.query_start as blocked_for, + left(blocked.query, 120) as blocked_query, + left(blocker.query, 120) as blocking_query +from pg_stat_activity as blocked +cross join lateral unnest(pg_blocking_pids(blocked.pid)) as blocking_pid +join pg_stat_activity as blocker on blocker.pid = blocking_pid +order by blocked_for desc; +``` + +### Find expensive query patterns + +`pg_stat_statements` aggregates normalized queries over time. Rank by total execution time, then inspect mean time and calls before deciding whether a frequent query is inefficient. + +```sql +select + calls, + round(total_exec_time::numeric, 2) as total_time_ms, + round(mean_exec_time::numeric, 2) as mean_time_ms, + rows, + left(query, 160) as query +from pg_stat_statements +order by total_exec_time desc +limit 20; +``` + +### Measure shared-buffer hit rate + +A ratio below 99% means more than 1% of observed block accesses missed `shared_buffers`. Postgres cannot tell whether a miss was served by the operating system cache or physical disk. + +```sql +select + 'index hit rate' as name, + round(100.0 * sum(idx_blks_hit) / nullif(sum(idx_blks_hit) + sum(idx_blks_read), 0), 2) as ratio +from pg_statio_user_indexes +union all +select + 'table hit rate' as name, + round( + 100.0 * sum(heap_blks_hit) / nullif(sum(heap_blks_hit) + sum(heap_blks_read), 0), + 2 + ) as ratio +from pg_statio_user_tables; +``` + +Pull [Performance Advisor](/docs/guides/observability/advisors) findings and compare the same window with [Reports](/docs/guides/observability/reports) or the [Metrics API](/docs/guides/observability/metrics). The full command and SQL catalog is in [Inspect the database](/docs/guides/observability/inspect). + +## Usage + +Usage checks identify growth in traffic, data, and connections before it becomes a capacity problem. They do not calculate billing totals. + +### Trend API requests + +Count requests by hour to establish a baseline and spot step changes. + +```sql +select + toStartOfHour(timestamp) as hour, + count() as requests +from logs +where source = 'edge_logs' +group by hour +order by hour desc +limit 168; +``` + +### Find high-volume API paths + +Group by method and path to identify which workload accounts for the growth. + +```sql +select + log_attributes['request.method'] as method, + log_attributes['request.path'] as path, + count() as requests +from logs +where source = 'edge_logs' +group by method, path +order by requests desc +limit 20; +``` + +### Find the largest relations + +Measure tables and their indexes together. Save the result on a regular cadence to establish a growth trend. + +```sql +select + schemaname, + relname as table_name, + pg_total_relation_size(relid) as total_bytes, + pg_size_pretty(pg_total_relation_size(relid)) as total_size +from pg_catalog.pg_statio_user_tables +order by total_bytes desc +limit 20; +``` + +### Count connections by role and state + +Connection growth can reveal a new workload or a client that is not pooling correctly. + +```sql +select + usename as role, + state, + count(*) as connections +from pg_stat_activity +where datname = current_database() +group by role, state +order by connections desc; +``` + +[Reports](/docs/guides/observability/reports) show request, disk, and database-size trends without SQL. The [Management API usage endpoint](/docs/reference/api/v1-get-project-usage-api-count) returns request counts for authorized scripts. Use [`supabase inspect db table-sizes`](/docs/reference/cli/supabase-inspect-db-table-sizes) and [`bloat`](/docs/reference/cli/supabase-inspect-db-bloat) to run related database checks from the CLI. + +## Turn a detection into a diagnosis + +A detection result should name an affected time window and at least one concrete anchor: a path, status, SQLSTATE, request ID, query, relation, PID, policy, or advisor lint. Take that evidence to [Diagnosing](/docs/guides/troubleshooting), identify the cause, apply the smallest relevant solution, and rerun the same detection check to verify the result. + +After a check is useful and repeatable, [hire an agent](/docs/guides/observability/automate-with-agents) to run it on a schedule. diff --git a/apps/docs/content/guides/database/inspect.mdx b/apps/docs/content/guides/observability/inspect.mdx similarity index 71% rename from apps/docs/content/guides/database/inspect.mdx rename to apps/docs/content/guides/observability/inspect.mdx index 6b4a0f371a07a..41dde492d6a59 100644 --- a/apps/docs/content/guides/database/inspect.mdx +++ b/apps/docs/content/guides/observability/inspect.mdx @@ -1,25 +1,27 @@ --- -title: 'Database debugging and monitoring' -description: 'Inspecting your Postgres database for common issues around disk, query performance, index, locks, and more using the terminal.' +id: 'inspect' +title: 'Inspect the database' +description: 'Read live Postgres statistics such as bloat, cache hit rate, locks, and slow queries from the CLI, SQL Editor, or MCP.' --- -Database performance is a large topic and many factors can contribute. Some of the most common causes of poor performance include: +Database performance is a large topic and many factors can contribute. Common causes of poor performance include inefficient schemas or queries, missing or unused indexes, insufficient memory, lock contention, and table bloat. -- An inefficiently designed schema -- Inefficiently designed queries -- A lack of indexes causing slower than required queries over large tables -- Unused indexes causing slow `INSERT`, `UPDATE` and `DELETE` operations -- Not enough compute resources, such as memory, causing your database to go to disk for results too often -- Lock contention from multiple queries operating on heavily used tables -- Large amount of bloat on your tables causing poor query planning +Use the live Postgres statistics in this guide to check for those conditions. You or an agent can run the same checks from: -You can examine your database and queries for these issues using either the [Supabase CLI](/docs/guides/local-development/cli/getting-started) or SQL. +- Studio: [SQL Editor](/dashboard/project/_/sql) +- MCP: `execute_sql` +- CLI: [`supabase inspect db`](/docs/reference/cli/supabase-inspect-db) -## Using the CLI +Use this page to: + +- Run [CLI inspection commands](#using-the-cli) +- Copy the matching [SQL](#using-sql) -The Supabase CLI comes with a range of tools to help inspect your Postgres instances for potential issues. The CLI gets the information from Postgres internals. Therefore, most tools provided are compatible with any Postgres databases regardless if they are a Supabase project or not. +To pick up a signal from these checks, see [Detecting](/docs/guides/observability/detecting). For the other sources, see [Observe the data](/docs/guides/observability/access-data). + +## Using the CLI -You can find installation instructions for the Supabase CLI here. +The [Supabase CLI](/docs/guides/local-development/cli/getting-started) reads live statistics from [Postgres internals](https://www.postgresql.org/docs/current/internals.html). Most commands work on any Postgres database, not only a Supabase project. ### The `inspect db` command @@ -58,7 +60,7 @@ Working with Supabase, you can link the Supabase CLI with your project: supabase link --project-ref ``` -Then the CLI will automatically connect to your Supabase project whenever you are in the project folder and you no longer need to provide `—db-url`. +Then the CLI will automatically connect to your Supabase project whenever you are in the project folder and you no longer need to provide `--db-url`. ### Inspection commands @@ -108,7 +110,7 @@ Following commands require `pg_stat_statements` to be enabled: calls, locks, cac When using `pg_stat_statements` also take note that it only stores the latest 5,000 statements. Moreover, consider resetting the analysis after optimizing any queries by running `select pg_stat_statements_reset();` -Learn more about pg_stats [here](/docs/guides/database/extensions/pg_stat_statements). +Learn more about [`pg_stat_statements`](/docs/guides/database/extensions/pg_stat_statements). ## Using SQL @@ -124,7 +126,7 @@ $ grant pg_read_all_stats to postgres; ### Postgres cumulative statistics system -Postgres collects data about its own operations using the [cumulative statistics system](https://www.postgresql.org/docs/current/monitoring-stats.html). In addition to this, every Supabase project has the [pg_stat_statements extension](/docs/guides/database/extensions/pg_stat_statements) enabled by default. This extension records query execution performance details and is the best way to find inefficient queries. This information can be combined with the Postgres query plan analyzer to develop more efficient queries. +Postgres collects data about its own operations using the [cumulative statistics system](https://www.postgresql.org/docs/current/monitoring-stats.html). In addition to this, every Supabase project has the [pg_stat_statements extension](/docs/guides/database/extensions/pg_stat_statements) enabled by default. This extension records query execution performance details. Here are some example queries to get you started. @@ -238,28 +240,8 @@ select from pg_statio_user_tables; ``` -This shows the ratio of data blocks fetched from the Postgres [shared_buffers](https://www.postgresql.org/docs/15/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-MEMORY) cache against the data blocks that were read from disk/OS cache. - -If either of your index or table hit rate are < 99% then this can indicate your compute plan is too small for your current workload and you would benefit from more memory. [Upgrading your compute](/docs/guides/platform/compute-and-disk#compute) can be done from your [project dashboard](/dashboard/project/_/settings/infrastructure). - -### Optimizing poor performing queries - -Postgres has built in tooling to help you optimize poorly performing queries. You can use the [query plan analyzer](https://www.postgresql.org/docs/current/sql-explain.html) on any expensive queries that you have identified: - -```sql -explain analyze ; -``` - -When you include `analyze` in the explain statement, the database attempts to execute the query and provides a detailed query plan along with actual execution times. So, be careful using `explain analyze` with `insert`/`update`/`delete` queries, because the query will run, and could have unintended side-effects. - -If you run `explain` without the `analyze` keyword, the database will only perform query planning without executing the query. This approach can be beneficial when you want to inspect the query plan without affecting the database or if you encounter timeouts in your queries. - -Using the query plan analyzer to optimize your queries is a large topic, with a number of online resources available: +This shows the ratio of data blocks fetched from the Postgres [shared_buffers](https://www.postgresql.org/docs/15/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-MEMORY) cache against the data blocks that were read from disk or the OS cache. -- [Official docs.](https://www.postgresql.org/docs/current/using-explain.html) - {/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */} -- [The Art of PostgreSQL.](https://theartofpostgresql.com/explain-plan-visualizer/) -- [Postgres Wiki.](https://wiki.postgresql.org/wiki/Using_EXPLAIN) -- [Enterprise DB.](https://www.enterprisedb.com/blog/postgresql-query-optimization-performance-tuning-with-explain-analyze) +A ratio below 99% means more than 1% of observed block accesses missed `shared_buffers`. Postgres cannot distinguish whether those reads were served by the operating system cache or physical disk. Treat that as a [Performance](/docs/guides/observability/detecting#performance) signal, then search [Diagnosing](/docs/guides/troubleshooting). -You can pair the information available from `pg_stat_statements` with the detailed system metrics available [via your metrics endpoint](../telemetry/metrics) to better understand the behavior of your DB and the queries you're executing against it. +When a check names a slow statement, get a query plan with [`explain`](/docs/guides/database/query-optimization#analyze-the-query-plan) in SQL, or [`explain()`](/docs/guides/database/debugging-performance) on the Data API. Pair `pg_stat_statements` with the [Metrics API](/docs/guides/observability/metrics) to read the same window from Postgres stats and host metrics. diff --git a/apps/docs/content/guides/monitoring-and-debugging/log-drains.mdx b/apps/docs/content/guides/observability/log-drains.mdx similarity index 96% rename from apps/docs/content/guides/monitoring-and-debugging/log-drains.mdx rename to apps/docs/content/guides/observability/log-drains.mdx index 21216bba6fba5..968578c30aa3d 100644 --- a/apps/docs/content/guides/monitoring-and-debugging/log-drains.mdx +++ b/apps/docs/content/guides/observability/log-drains.mdx @@ -9,7 +9,7 @@ Log drains send all logs of the Supabase stack to one or more desired destinatio ## What you can do with log drains - Route Supabase logs (Postgres, Auth, Storage, Edge Functions, and more) to any observability platform. -- Combine Supabase logs with application-level traces — see [Tracing with the JS SDK](/docs/guides/monitoring-and-debugging/client-side-tracing) to extend your traces into Supabase. +- Combine Supabase logs with application-level traces — see [Tracing with the JS SDK](/docs/guides/observability/client-side-tracing) to extend your traces into Supabase. - Archive logs to S3 for long-term retention and compliance. - Build alerts and dashboards on top of Supabase log data in your preferred vendor. @@ -335,5 +335,5 @@ Logs are forwarded to a remote Syslog receiver using TCP or TLS, adhering to [RF ## Additional resources - [Log Drains pricing breakdown](/docs/guides/platform/manage-your-usage/log-drains) — cost per drain, per million events, and egress charges. -- [Metrics API](/docs/guides/monitoring-and-debugging/metrics) — export Postgres performance metrics alongside your logs. -- [Tracing with the JS SDK](/docs/guides/monitoring-and-debugging/client-side-tracing) — instrument your application and combine traces with Supabase logs. +- [Metrics API](/docs/guides/observability/metrics) — export Postgres performance metrics alongside your logs. +- [Tracing with the JS SDK](/docs/guides/observability/client-side-tracing) — instrument your application and combine traces with Supabase logs. diff --git a/apps/docs/content/guides/observability/log-field-reference.mdx b/apps/docs/content/guides/observability/log-field-reference.mdx new file mode 100644 index 0000000000000..ded838e551b71 --- /dev/null +++ b/apps/docs/content/guides/observability/log-field-reference.mdx @@ -0,0 +1,44 @@ +--- +id: 'logs-field-reference' +title: 'Logs field reference' +description: 'Supabase Logs field reference' +--- + +Use this reference to find the fields available for each log source. Query `id`, `timestamp`, `event_message`, and `source` as top-level columns. Other structured fields are keys in the `log_attributes` map: drop the `metadata.` prefix shown in the source schema and keep the rest of the dotted path. + +For example, the schema path `metadata.request.cf.country` is queried as `log_attributes['request.cf.country']`. See [Query and filter logs](/docs/guides/observability/advanced-log-filtering) for complete ClickHouse examples. + + + {(logConstants) => ( + + {logConstants.schemas.map((schema) => ( + + + + + + + + + + + {schema.fields + .sort((a, b) => a.path.localeCompare(b.path)) + .map((field) => ( + + + + + + ))} + +
    Schema pathClickHouse query fieldType
    {field.path} + {field.path.startsWith('metadata.') + ? `log_attributes['${field.path.slice('metadata.'.length)}']` + : field.path} + {field.type}
    +
    + ))} +
    + )} +
    diff --git a/apps/docs/content/guides/observability/logs.mdx b/apps/docs/content/guides/observability/logs.mdx new file mode 100644 index 0000000000000..6d8b9f622780d --- /dev/null +++ b/apps/docs/content/guides/observability/logs.mdx @@ -0,0 +1,81 @@ +--- +id: 'logs' +title: 'Logs' +description: 'Inspect project log events in the unified Logs view in Studio' +--- + +This guide explains how to inspect project logs in Studio. Log retention is based on your [project's pricing plan](/pricing). For details on how Logs usage is billed, see [Manage Logs usage](/docs/guides/platform/manage-your-usage/logs). + +Use this page to filter and inspect events in [Logs](#product-logs). To query the same data with SQL from Studio, MCP, the API, or a script, or to record extra Postgres, API, and Realtime events, see [Query and filter logs](/docs/guides/observability/advanced-log-filtering). + + + +If you already have a specific error, start at [Diagnosing](/docs/guides/troubleshooting). To pick up a signal from these events, see [Detecting](/docs/guides/observability/detecting). + + + +## Filter and inspect events [#product-logs] + +Open [Logs](/dashboard/project/_/logs). The page shows a timeline of success, warning, and error events, a filterable table, and a detail panel when you select a row. + +If you don't select a log type, Logs queries **Postgres** and **API Gateway** events. Selecting log types replaces that default set. + + + +For regular expression filtering, structured-field queries, and field discovery, see [Query and filter logs](/docs/guides/observability/advanced-log-filtering). + + + +### Filter logs + +1. Open [Logs](/dashboard/project/_/logs). +2. Set the **Time Range** in the sidebar. +3. Select one or more **Log Type** values. Nested toggles under API Gateway include or exclude Auth, Storage, and PostgREST request paths. The nested toggle under Postgres shows or hides connection logs. +4. Optionally filter by **Level**, **Status**, **Method**, **Pathname**, or **Event message**. Type in the filter bar to search event messages. +5. Optionally filter by **User**. This filter only matches Auth and Postgres events. + +Refresh the table, hide columns, download matching rows as CSV or JSON, or turn on live mode to stream new events. + +### Log types + +Selecting a log type in Studio queries the matching ClickHouse `source`. For the `source` names to use in SQL, see [Sources](/docs/guides/observability/advanced-log-filtering#logs-explorer). + +| Log type | Events | +| ------------- | ----------------------------------------------------------------- | +| API Gateway | HTTP requests through the API gateway, including REST and GraphQL | +| Postgres | Database queries and activity | +| PostgREST | PostgREST server logs | +| Auth | Auth server logs | +| Storage | Storage API server logs | +| Edge Function | Edge Function HTTP invocations and `console` output | +| Realtime | Realtime server logs | +| Supavisor | Connection pooler logs | +| PgBouncer | PgBouncer logs | + +Selecting **API Gateway** is not the same as selecting **Auth**, **Storage**, or **PostgREST**. The nested API Gateway toggles filter HTTP paths on the gateway. The Auth, Storage, and PostgREST log types query those services' own logs. + +### Postgres [#postgres] + +Postgres logs show queries and activity for your database. Connection lifecycle events appear here when [connection logging](/docs/guides/observability/advanced-log-filtering#logging-postgres-connections) is enabled. They are included by default; clear **Connection logs** under the Postgres log type to hide them. + +To record additional statement classes, see [Logging Postgres queries](/docs/guides/observability/advanced-log-filtering#logging-postgres-queries). + +### Inspect a log + +1. Select a row in the table. +2. Open **Overview** to follow the request through the services that handled it. Open **Raw JSON** for the full event. +3. Dock the panel at the bottom or on the right. + +Edge Function rows include console output from that invocation. In SQL, the HTTP request is `function_edge_logs` and console output is `function_logs`. Function log messages longer than 10,000 characters are truncated. + +### Expanding results [#expanding-results] + +In the [Logs Explorer](/dashboard/project/_/logs/explorer), query results can be hard to read in the table. Double-click a row to expand it as JSON: + +![Expanding log results](/docs/img/guides/platform/expanded-log-results.png) + +### Single-service collections [#single-service-collections] + +The Logs sidebar still lists collections for one service at a time, such as [API Gateway](/dashboard/project/_/logs/edge-logs) or [Postgres](/dashboard/project/_/logs/postgres-logs). Use a collection when you want a dedicated view. + +If [Read Replicas](/docs/guides/platform/read-replicas) are enabled, collections can filter by database with the **Source** control. For API logs from the [API Load Balancer](/docs/guides/platform/read-replicas#api-load-balancer), the upstream database is the Redirect Identifier field (`log_attributes['load_balancer_redirect_identifier']` in SQL). diff --git a/apps/docs/content/guides/monitoring-and-debugging/metrics.mdx b/apps/docs/content/guides/observability/metrics.mdx similarity index 89% rename from apps/docs/content/guides/monitoring-and-debugging/metrics.mdx rename to apps/docs/content/guides/observability/metrics.mdx index addbd36aba80a..bb7b7eec0435d 100644 --- a/apps/docs/content/guides/monitoring-and-debugging/metrics.mdx +++ b/apps/docs/content/guides/observability/metrics.mdx @@ -6,6 +6,8 @@ description: 'Export Supabase database metrics to any Prometheus-compatible tool Every Supabase project exposes a [Prometheus](https://prometheus.io/)-compatible **Metrics API** endpoint that surfaces ~200 Postgres performance and health series. You can scrape it into any observability stack to power custom dashboards, alerting rules, or long-term retention that goes beyond what Supabase Studio provides out of the box. +Chart a subset of the same window in Studio [Reports](/docs/guides/observability/reports). Use this page when you want the Prometheus-compatible scrape endpoint. + The Metrics API is currently in beta. Metric names and labels might evolve as we expand the dataset, and the feature is not available in self-hosted Supabase instances. @@ -40,5 +42,5 @@ Pick the workflow that best matches your tooling. Cards link to Supabase-authore - [Grafana Cloud’s Supabase integration doc](https://grafana.com/docs/grafana-cloud/monitor-infrastructure/integrations/integration-reference/integration-supabase/) (community-maintained, built on this Metrics API). - [Datadog’s Supabase integration doc](https://docs.datadoghq.com/integrations/supabase/) (community-maintained, built on this Metrics API). - [Elastic’s Supabase integration doc](https://www.elastic.co/docs/reference/integrations/supabase) (community-maintained). -- [Log Drains ](/docs/guides/monitoring-and-debugging/log-drains) for exporting event-based telemetry alongside metrics. +- [Log Drains ](/docs/guides/observability/log-drains) for exporting event-based telemetry alongside metrics. - [Query Performance report](/dashboard/project/_/observability/query-performance) for built-in visualizations based on the same underlying metrics. diff --git a/apps/docs/content/guides/monitoring-and-debugging/metrics/grafana-cloud.mdx b/apps/docs/content/guides/observability/metrics/grafana-cloud.mdx similarity index 100% rename from apps/docs/content/guides/monitoring-and-debugging/metrics/grafana-cloud.mdx rename to apps/docs/content/guides/observability/metrics/grafana-cloud.mdx diff --git a/apps/docs/content/guides/monitoring-and-debugging/metrics/grafana-self-hosted.mdx b/apps/docs/content/guides/observability/metrics/grafana-self-hosted.mdx similarity index 95% rename from apps/docs/content/guides/monitoring-and-debugging/metrics/grafana-self-hosted.mdx rename to apps/docs/content/guides/observability/metrics/grafana-self-hosted.mdx index ad4ec6fc6b671..aa0de4b6ee538 100644 --- a/apps/docs/content/guides/monitoring-and-debugging/metrics/grafana-self-hosted.mdx +++ b/apps/docs/content/guides/observability/metrics/grafana-self-hosted.mdx @@ -10,7 +10,7 @@ Self-hosting [Prometheus](https://prometheus.io/docs/prometheus/latest/installat Use this guide only if you need full manual control (custom scrape topology, self-hosted Prometheus or non-standard auth). -Otherwise, use the [Grafana Cloud integration](/docs/guides/monitoring-and-debugging/metrics/grafana-cloud#installation) available in the Supabase Dashboard. +Otherwise, use the [Grafana Cloud integration](/docs/guides/observability/metrics/grafana-cloud#installation) available in the Supabase Dashboard. diff --git a/apps/docs/content/guides/monitoring-and-debugging/metrics/vendor-agnostic.mdx b/apps/docs/content/guides/observability/metrics/vendor-agnostic.mdx similarity index 100% rename from apps/docs/content/guides/monitoring-and-debugging/metrics/vendor-agnostic.mdx rename to apps/docs/content/guides/observability/metrics/vendor-agnostic.mdx diff --git a/apps/docs/content/guides/monitoring-and-debugging/reports.mdx b/apps/docs/content/guides/observability/reports.mdx similarity index 100% rename from apps/docs/content/guides/monitoring-and-debugging/reports.mdx rename to apps/docs/content/guides/observability/reports.mdx diff --git a/apps/docs/content/guides/monitoring-and-debugging/sentry-monitoring.mdx b/apps/docs/content/guides/observability/sentry-monitoring.mdx similarity index 100% rename from apps/docs/content/guides/monitoring-and-debugging/sentry-monitoring.mdx rename to apps/docs/content/guides/observability/sentry-monitoring.mdx diff --git a/apps/docs/content/guides/platform/billing-faq.mdx b/apps/docs/content/guides/platform/billing-faq.mdx index 30c52f06d4e23..e38bb37e3880f 100644 --- a/apps/docs/content/guides/platform/billing-faq.mdx +++ b/apps/docs/content/guides/platform/billing-faq.mdx @@ -12,7 +12,7 @@ subtitle: 'This documentation covers frequently asked questions around subscript ### What are organizations and projects? The Supabase Platform has "organizations" and "projects". An organization may contain multiple projects. Each project is a dedicated Supabase instance with all of its sub-services including Storage, Auth, Functions and Realtime. -Each organization only has a single subscription with a single plan (Free, Pro, Team or Enterprise). Project add-ons such as [Compute](/docs/guides/platform/compute-and-disk), [IPv4](/docs/guides/platform/ipv4-address), [Log Drains](/docs/guides/monitoring-and-debugging/log-drains), [Advanced MFA](/docs/guides/auth/auth-mfa/phone), [Custom Domains](/docs/guides/platform/custom-domains) and [PITR](/docs/guides/platform/backups#point-in-time-recovery) are configured per project and are added to your organization subscription. +Each organization only has a single subscription with a single plan (Free, Pro, Team or Enterprise). Project add-ons such as [Compute](/docs/guides/platform/compute-and-disk), [IPv4](/docs/guides/platform/ipv4-address), [Log Drains](/docs/guides/observability/log-drains), [Advanced MFA](/docs/guides/auth/auth-mfa/phone), [Custom Domains](/docs/guides/platform/custom-domains) and [PITR](/docs/guides/platform/backups#point-in-time-recovery) are configured per project and are added to your organization subscription. Read more on [About billing on Supabase](/docs/guides/platform/billing-on-supabase#organization-based-billing). diff --git a/apps/docs/content/guides/platform/billing-on-supabase.mdx b/apps/docs/content/guides/platform/billing-on-supabase.mdx index cee1f1eeb8faf..deb7484c30dc6 100644 --- a/apps/docs/content/guides/platform/billing-on-supabase.mdx +++ b/apps/docs/content/guides/platform/billing-on-supabase.mdx @@ -84,7 +84,7 @@ While your subscription plan applies to your entire organization and is charged - [Compute](/docs/guides/platform/compute-and-disk#compute) to scale your database up to 64 cores and 256 GB RAM - [Read Replicas](/docs/guides/platform/read-replicas) to scale read operations and provide resiliency - [Disk](/docs/guides/platform/compute-and-disk#disk) to provision extra IOPS/throughput or use a high-performance SSD -- [Log Drains](/docs/guides/monitoring-and-debugging/log-drains) to sync Supabase logs to a logging system of your choice +- [Log Drains](/docs/guides/observability/log-drains) to sync Supabase logs to a logging system of your choice - [Custom Domains](/docs/guides/platform/custom-domains) to provide a branded experience - [PITR](/docs/guides/platform/backups#point-in-time-recovery) to roll back to any specific point in time, down to the minute - [IPv4](/docs/guides/platform/ipv4-address) for a dedicated IPv4 address diff --git a/apps/docs/content/guides/platform/custom-domains.mdx b/apps/docs/content/guides/platform/custom-domains.mdx index c294cbfbbb63d..90a2680095990 100644 --- a/apps/docs/content/guides/platform/custom-domains.mdx +++ b/apps/docs/content/guides/platform/custom-domains.mdx @@ -18,7 +18,7 @@ You can choose either a custom domain or vanity subdomain for each project. Custom domains change the way your project's URLs appear to your users. This is useful when: -- You are using [OAuth (Social Login)](/docs/guides/auth/social-login) with Supabase Auth and the project's URL is shown on the OAuth consent screen. +- You are using [OAuth (social login)](/docs/guides/auth/social-login) with Supabase Auth and the project's URL is shown on the OAuth consent screen. - You are creating APIs for third-party systems, for example, implementing webhooks or external API calls to your project via [Edge Functions](/docs/guides/functions). - You are storing URLs in a database or encoding them in QR codes. @@ -41,7 +41,7 @@ This example assumes your Supabase project is `abcdefghijklmnopqrst` with a corr To get started: 1. [Install](/docs/guides/local-development) the latest version of the Supabase CLI. -2. [Log in](/docs/guides/local-development/database-migrations#log-in-to-the-supabase-cli) to your Supabase account using the CLI. +2. [Sign in](/docs/guides/local-development/database-migrations#sign-in-to-the-supabase-cli) to your Supabase account using the CLI. 3. Ensure you have [Owner or Admin permissions](/docs/guides/platform/access-control#manage-team-members) for the project. 4. Get a custom domain from a DNS provider. Currently, only subdomains are supported. - Use `api.example.com` instead of `example.com`. @@ -153,7 +153,7 @@ Vanity subdomains allow you to present a basic branded experience, compared to c To get started: 1. [Install](/docs/guides/local-development) the latest version of the Supabase CLI. -1. [Log in](/docs/guides/local-development/database-migrations#log-in-to-the-supabase-cli) to your Supabase account using the CLI. +1. [Sign in](/docs/guides/local-development/database-migrations#sign-in-to-the-supabase-cli) to your Supabase account using the CLI. 1. Ensure that you have [Owner or Admin permissions](/docs/guides/platform/access-control#manage-team-members) for the project you'd like to set up a vanity subdomain for. 1. Ensure that your organization is on a paid plan (Pro/Team/Enterprise Plan) in the [Billing page of the Dashboard](/dashboard/org/_/billing). diff --git a/apps/docs/content/guides/platform/manage-your-usage/logs-ingest.mdx b/apps/docs/content/guides/platform/manage-your-usage/logs-ingest.mdx index c14b60cf62a4b..eb86f0ac58c7e 100644 --- a/apps/docs/content/guides/platform/manage-your-usage/logs-ingest.mdx +++ b/apps/docs/content/guides/platform/manage-your-usage/logs-ingest.mdx @@ -41,7 +41,7 @@ Every service in your Supabase project automatically generates logs — you don' - **Configure Postgres logging settings.** Postgres emits logs for connections, checkpoints, statements, and more — many of which can be tuned or disabled. Adjusting settings such as `log_connections`, `log_min_duration_statement`, and `log_statement` can significantly reduce Postgres log volume. See [Customizing Postgres configs](/docs/guides/database/custom-postgres-config) for the full list of configurable parameters. - **Reduce log-level verbosity** in your Edge Functions and server-side code (for example, `info` → `warn` in production). -- **Audit verbose logging in your application code.** Application-level logs forwarded to Supabase services count toward ingest. +- **Audit verbose application logging in your application code.** Application-level logs forwarded to Supabase services count toward ingest. - **Cap log payload size.** Large structured payloads can inflate GB-billed volume. - **Investigate spikes.** Use the [**Logs Explorer**](/dashboard/project/_/logs-explorer) in the Dashboard to find services or endpoints producing unusually high volume. diff --git a/apps/docs/content/guides/platform/manage-your-usage/monthly-active-users-sso.mdx b/apps/docs/content/guides/platform/manage-your-usage/monthly-active-users-sso.mdx index b99743659b0ff..531e905ff7923 100644 --- a/apps/docs/content/guides/platform/manage-your-usage/monthly-active-users-sso.mdx +++ b/apps/docs/content/guides/platform/manage-your-usage/monthly-active-users-sso.mdx @@ -5,7 +5,7 @@ title: 'Manage Monthly Active SSO Users usage' ## What you are charged for -You are charged for the number of distinct users who log in or refresh their token during the billing cycle using a SAML 2.0 compatible identity provider (e.g. Google Workspace, Microsoft Active Directory). Each unique user is counted only once per billing cycle, regardless of how many times they authenticate. These users are referred to as "SSO MAUs". +You are charged for the number of distinct users who sign in or refresh their token during the billing cycle using a SAML 2.0 compatible identity provider (e.g. Google Workspace, Microsoft Active Directory). Each unique user is counted only once per billing cycle, regardless of how many times they authenticate. These users are referred to as "SSO MAUs". ### Example diff --git a/apps/docs/content/guides/platform/manage-your-usage/monthly-active-users-third-party.mdx b/apps/docs/content/guides/platform/manage-your-usage/monthly-active-users-third-party.mdx index 417eaaf9f8097..d7746c5fff130 100644 --- a/apps/docs/content/guides/platform/manage-your-usage/monthly-active-users-third-party.mdx +++ b/apps/docs/content/guides/platform/manage-your-usage/monthly-active-users-third-party.mdx @@ -5,7 +5,7 @@ title: 'Manage Monthly Active Third-Party Users usage' ## What you are charged for -You are charged for the number of distinct users who log in or refresh their token during the billing cycle using a third-party authentication provider (Clerk, Firebase Auth, Auth0, AWS Cognito). Each unique user is counted only once per billing cycle, regardless of how many times they authenticate. These users are referred to as "Third-Party MAUs". +You are charged for the number of distinct users who sign in or refresh their token during the billing cycle using a third-party authentication provider (Clerk, Firebase Auth, Auth0, AWS Cognito). Each unique user is counted only once per billing cycle, regardless of how many times they authenticate. These users are referred to as "Third-Party MAUs". ### Example @@ -18,7 +18,7 @@ Your billing cycle runs from January 1 to January 31. Although User-1 was signed
    Third-Party MAU login screen Third-Party MAU login screen
  • 0 downtime
  • Users may need to log in again
  • |
    • Need to maintain 2 different Auth services, which may be more costly in the short-term
    • Need to maintain separate codepaths for the period of the migration
    • Some existing users may be inactive and have not signed in with the new provider. This means that you eventually need to backfill these users. However, this is a much smaller-scale one-off migration with lower risks since these users are inactive.
    | -| One-off |
    • No need to maintain 2 different auth services for an extended period of time
    |
    • Some downtime
    • Users will need to log in again. Risky for active users.
    | +| Rolling |
    • 0 downtime
    • Users may need to sign in again
    |
    • Need to maintain 2 different Auth services, which may be more costly in the short-term
    • Need to maintain separate codepaths for the period of the migration
    • Some existing users may be inactive and have not signed in with the new provider. This means that you eventually need to backfill these users. However, this is a much smaller-scale one-off migration with lower risks since these users are inactive.
    | +| One-off |
    • No need to maintain 2 different auth services for an extended period of time
    |
    • Some downtime
    • Users will need to sign in again. Risky for active users.
    | ## Migration steps @@ -49,12 +49,12 @@ To export password hashes and MFA factors, contact Auth0 support. ### Step 2: Import your users into Supabase Auth -The steps for importing your users depends on the login methods that you support. +The steps for importing your users depends on the sign-in methods that you support. See the following sections for how to import users with: -- [Password-based login](#password-based-methods) -- [Passwordless login](#passwordless-methods) +- [Password-based sign-in](#password-based-methods) +- [Passwordless sign-in](#passwordless-methods) - [OAuth](#oauth) #### Password-based methods @@ -73,7 +73,7 @@ Sign up new users using Supabase Auth's [signin methods](/docs/guides/auth/passw Migrate existing users to Supabase Auth. This requires two main steps: first, check which users need to be migrated, then create their accounts using the Supabase admin endpoints. 1. Get your Auth 0 user export and password hash export lists. -1. Filter for users who use password login. +1. Filter for users who use password sign-in. - Under the `identities` field in the user object, these users will have `auth0` as a provider. In the same identity object, you can find their Auth0 `user_id`. - Check that the user has a corresponding password hash by comparing their Auth0 `user_id` to the `oid` field in the password hash export. 1. Use Supabase Auth's [admin create user](/docs/reference/javascript/auth-admin-createuser) method to recreate the user in Supabase Auth. If the user has a confirmed email address or phone number, set `email_confirm` or `phone_confirm` to `true`. @@ -254,7 +254,7 @@ header="How do I migrate existing SAML Single Sign-On (SSO) connections?" id="saml" > -Customers may need to link their identity provider with Supabase Auth separately, but their users should still be able to sign-in as per-normal after authenticating with their identity provider. For more information about SSO with SAML 2.0, you can check out [this guide](/docs/guides/auth/enterprise-sso/auth-sso-saml). If you want to migrate your existing SAML SSO connections from Auth0 to Supabase Auth, reach out to us via support. +Customers may need to link their identity provider with Supabase Auth separately, but their users should still be able to sign in as per normal after authenticating with their identity provider. For more information about SSO with SAML 2.0, you can check out [this guide](/docs/guides/auth/enterprise-sso/auth-sso-saml). If you want to migrate your existing SAML SSO connections from Auth0 to Supabase Auth, reach out to us via support. diff --git a/apps/docs/content/guides/platform/migrating-to-supabase/firebase-auth.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/firebase-auth.mdx index ad4399f9e2c0a..3e012208c5879 100644 --- a/apps/docs/content/guides/platform/migrating-to-supabase/firebase-auth.mdx +++ b/apps/docs/content/guides/platform/migrating-to-supabase/firebase-auth.mdx @@ -36,7 +36,7 @@ Supabase provides several [tools](https://github.com/supabase-community/firebase ## Generate a Firebase private key [#generate-firebase-private-key] -1. Log in to your [Firebase Console](https://console.firebase.google.com/project) and open your project. +1. Sign in to your [Firebase Console](https://console.firebase.google.com/project) and open your project. 1. Click the gear icon next to **Project Overview** in the sidebar and select **Project Settings**. 1. Click **Service Accounts** and select **Firebase Admin SDK**. 1. Click **Generate new private key**. @@ -44,7 +44,7 @@ Supabase provides several [tools](https://github.com/supabase-community/firebase ## Save your Firebase password hash parameters [#save-firebase-hash-parameters] -1. Log in to your [Firebase Console](https://console.firebase.google.com/project) and open your project. +1. Sign in to your [Firebase Console](https://console.firebase.google.com/project) and open your project. 1. Select **Authentication** (Build section) in the sidebar. 1. Select **Users** in the top menu. 1. At the top right of the users list, open the menu (3 dots) and click **Password hash parameters**. diff --git a/apps/docs/content/guides/platform/migrating-to-supabase/firebase-storage.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/firebase-storage.mdx index 12a84f98cadba..82d4bbdaab7f4 100644 --- a/apps/docs/content/guides/platform/migrating-to-supabase/firebase-storage.mdx +++ b/apps/docs/content/guides/platform/migrating-to-supabase/firebase-storage.mdx @@ -25,7 +25,7 @@ Supabase provides several [tools](https://github.com/supabase-community/firebase ## Generate a Firebase private key [#generate-firebase-private-key] -1. Log in to your [Firebase Console](https://console.firebase.google.com/project) and open your project. +1. Sign in to your [Firebase Console](https://console.firebase.google.com/project) and open your project. 1. Click the gear icon next to **Project Overview** in the sidebar and select **Project Settings**. 1. Click **Service Accounts** and select **Firebase Admin SDK**. 1. Click **Generate new private key**. diff --git a/apps/docs/content/guides/platform/migrating-to-supabase/firestore-data.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/firestore-data.mdx index 647a5c880cb60..6579d26323d7b 100644 --- a/apps/docs/content/guides/platform/migrating-to-supabase/firestore-data.mdx +++ b/apps/docs/content/guides/platform/migrating-to-supabase/firestore-data.mdx @@ -35,7 +35,7 @@ The Firestore `collection` is "flattened" and converted to a table with basic co ## Generate a Firebase private key [#generate-firebase-private-key] -1. Log in to your [Firebase Console](https://console.firebase.google.com/project) and open your project. +1. Sign in to your [Firebase Console](https://console.firebase.google.com/project) and open your project. 1. Click the gear icon next to **Project Overview** in the sidebar and select **Project Settings**. 1. Click **Service Accounts** and select **Firebase Admin SDK**. 1. Click **Generate new private key**. diff --git a/apps/docs/content/guides/platform/migrating-to-supabase/heroku.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/heroku.mdx index 036416e874612..99209b9e86dbe 100644 --- a/apps/docs/content/guides/platform/migrating-to-supabase/heroku.mdx +++ b/apps/docs/content/guides/platform/migrating-to-supabase/heroku.mdx @@ -23,7 +23,7 @@ Alternatively, use the [Heroku to Supabase migration tool](https://migrate.supab ## Retrieve your Heroku database credentials [#retrieve-heroku-credentials] -1. Log in to your [Heroku account](https://heroku.com) and select the project you want to migrate. +1. Sign in to your [Heroku account](https://heroku.com) and select the project you want to migrate. 1. Click **Resources** in the menu and select your **Heroku Postgres** database. 1. Click **Settings** in the menu. 1. Click **View Credentials** and save the following information: diff --git a/apps/docs/content/guides/platform/migrating-to-supabase/mssql.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/mssql.mdx index e555d0b662210..42c3ed8481165 100644 --- a/apps/docs/content/guides/platform/migrating-to-supabase/mssql.mdx +++ b/apps/docs/content/guides/platform/migrating-to-supabase/mssql.mdx @@ -10,7 +10,7 @@ This guide aims to demonstrate the process of transferring your Microsoft SQL Se Before you begin the migration, you need to collect essential information about your MSSQL database. Follow these steps: -1. Log in to your MSSQL database provider. +1. Sign in to your MSSQL database provider. 1. Locate and note the following database details: - Hostname or IP address - Database name diff --git a/apps/docs/content/guides/platform/migrating-to-supabase/mysql.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/mysql.mdx index 24a66b899f6df..68eabc48da2f9 100644 --- a/apps/docs/content/guides/platform/migrating-to-supabase/mysql.mdx +++ b/apps/docs/content/guides/platform/migrating-to-supabase/mysql.mdx @@ -10,7 +10,7 @@ This guide aims to exhibit the process of transferring your MySQL database to Su Before you begin the migration, you need to collect essential information about your MySQL database. Follow these steps: -1. Log in to your MySQL database provider. +1. Sign in to your MySQL database provider. 1. Locate and note the following database details: - Hostname or IP address diff --git a/apps/docs/content/guides/platform/migrating-to-supabase/neon.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/neon.mdx index 73907c736ea63..0bb1501bddefe 100644 --- a/apps/docs/content/guides/platform/migrating-to-supabase/neon.mdx +++ b/apps/docs/content/guides/platform/migrating-to-supabase/neon.mdx @@ -8,7 +8,7 @@ This guide demonstrates how to migrate your Neon database to Supabase to get the ## Retrieve your Neon database credentials [#retrieve-credentials] -1. Log in to your Neon Console [https://console.neon.tech/login](https://console.neon.tech/login). +1. Sign in to your Neon Console [https://console.neon.tech/login](https://console.neon.tech/login). 1. Select **Projects** on the left. 1. Click on your project in the list. 1. From your Project Dashboard find your **Connection string** and click **Copy snippet** to copy it to the clipboard (do not check "pooled connection"). diff --git a/apps/docs/content/guides/platform/migrating-to-supabase/render.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/render.mdx index 1e12f8e6ca286..e3f678a412f47 100644 --- a/apps/docs/content/guides/platform/migrating-to-supabase/render.mdx +++ b/apps/docs/content/guides/platform/migrating-to-supabase/render.mdx @@ -12,7 +12,7 @@ This guide demonstrates how to migrate from Render to Supabase to get the most o ## Retrieve your Render database credentials [#retrieve-render-credentials] -1. Log in to your [Render account](https://render.com) and select the project you want to migrate. +1. Sign in to your [Render account](https://render.com) and select the project you want to migrate. 1. Click **Dashboard** in the menu and click in your **Postgres** database. 1. Scroll down in the **Info** tab. 1. Click on **PSQL Command** and edit it adding the content after `PSQL_COMMAND=`. diff --git a/apps/docs/content/guides/platform/migrating-to-supabase/vercel-postgres.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/vercel-postgres.mdx index dbd73ffa4006e..bd215b392aa7b 100644 --- a/apps/docs/content/guides/platform/migrating-to-supabase/vercel-postgres.mdx +++ b/apps/docs/content/guides/platform/migrating-to-supabase/vercel-postgres.mdx @@ -8,7 +8,7 @@ This guide demonstrates how to migrate your Vercel Postgres database to Supabase ## Retrieve your Vercel Postgres database credentials [#retrieve-credentials] -1. Log in to your Vercel Dashboard [https://vercel.com/login](https://vercel.com/login). +1. Sign in to your Vercel Dashboard [https://vercel.com/login](https://vercel.com/login). 1. Click on the **Storage** tab. 1. Click on your Postgres Database. 1. Under the **Quickstart** section, select **psql** then click **Show Secret** to reveal your database password. diff --git a/apps/docs/content/guides/platform/migrating-within-supabase/backup-restore.mdx b/apps/docs/content/guides/platform/migrating-within-supabase/backup-restore.mdx index 5a38ace3123ef..e6415d7258dbf 100644 --- a/apps/docs/content/guides/platform/migrating-within-supabase/backup-restore.mdx +++ b/apps/docs/content/guides/platform/migrating-within-supabase/backup-restore.mdx @@ -299,7 +299,7 @@ DROP ROLE IF EXISTS cli_login_postgres; - + With the Supabase CLI [Supabase CLI](/docs/guides/local-development/cli/getting-started), run: ```bash supabase login diff --git a/apps/docs/content/guides/platform/multi-factor-authentication.mdx b/apps/docs/content/guides/platform/multi-factor-authentication.mdx index d460dcb623289..fd9a099c51e65 100644 --- a/apps/docs/content/guides/platform/multi-factor-authentication.mdx +++ b/apps/docs/content/guides/platform/multi-factor-authentication.mdx @@ -18,7 +18,7 @@ Currently, Supabase supports adding a unique time-based one-time password (TOTP) ## Enable MFA -You can enable MFA for your user account under your [Supabase account settings](/dashboard/account/security). Enabling MFA will result in all other user sessions to be automatically logged out and forced to sign-in again with MFA. +You can enable MFA for your user account under your [Supabase account settings](/dashboard/account/security). Enabling MFA will result in all other user sessions to be automatically logged out and forced to sign in again with MFA. @@ -32,7 +32,7 @@ For security reasons, we will not be able to restore access to your account if y -## Login with MFA +## Sign in with MFA Once you've enabled MFA for your Supabase user account, you will be prompted to enter your second factor challenge code as seen in your preferred TOTP app. @@ -40,7 +40,7 @@ If you are an organization owner and on the Pro, Team or Enterprise plan, you ca ## Disable MFA -You can disable MFA for your user account under your [Supabase account settings](/dashboard/account/security). On subsequent login attempts, you will not be prompted to enter an MFA code. +You can disable MFA for your user account under your [Supabase account settings](/dashboard/account/security). On subsequent sign-in attempts, you will not be prompted to enter an MFA code. diff --git a/apps/docs/content/guides/platform/network-restrictions.mdx b/apps/docs/content/guides/platform/network-restrictions.mdx index 1427441a21560..7a3ec0bcc8813 100644 --- a/apps/docs/content/guides/platform/network-restrictions.mdx +++ b/apps/docs/content/guides/platform/network-restrictions.mdx @@ -28,7 +28,7 @@ To configure network restrictions with the dashboard: To configure network restrictions with the CLI: 1. [Install](/docs/guides/local-development) the Supabase CLI 1.22.0+. -1. [Log in](/docs/guides/local-development/database-migrations#log-in-to-the-supabase-cli) to your Supabase account. +1. [Sign in](/docs/guides/local-development/database-migrations#sign-in-to-the-supabase-cli) to your Supabase account. 1. If your project was created before December 23, 2022, [upgrade it to the latest Supabase version](/docs/guides/platform/upgrading) before using network restrictions. 1. Ensure you have [Owner or Admin permissions](/docs/guides/platform/access-control#manage-team-members) for the project. diff --git a/apps/docs/content/guides/platform/performance.mdx b/apps/docs/content/guides/platform/performance.mdx index c93edb08b0e6a..246ad18e91dc9 100644 --- a/apps/docs/content/guides/platform/performance.mdx +++ b/apps/docs/content/guides/platform/performance.mdx @@ -8,7 +8,7 @@ The Supabase platform automatically optimizes your Postgres database to take adv ## Examining query performance -Unoptimized queries are a major cause of poor database performance. To analyze the performance of your queries, see the [Debugging and monitoring guide](/docs/guides/database/inspect). +Unoptimized queries are a major cause of poor database performance. To analyze the performance of your queries, see [Inspect the database](/docs/guides/observability/inspect). ## Optimizing the number of connections diff --git a/apps/docs/content/guides/platform/postgres-connection-logging.mdx b/apps/docs/content/guides/platform/postgres-connection-logging.mdx index b78166e888555..b0ef15ab47d55 100644 --- a/apps/docs/content/guides/platform/postgres-connection-logging.mdx +++ b/apps/docs/content/guides/platform/postgres-connection-logging.mdx @@ -4,7 +4,7 @@ title: 'Postgres connection logging' description: 'Enable or disable Postgres connection logging for audit and compliance.' --- -For security monitoring and compliance audits, Postgres can log connection lifecycle events to your project's [Postgres logs](/docs/guides/monitoring-and-debugging/logs#postgres), including events such as `connection received`, `connection authenticated`, and `connection authorized`. +For security monitoring and compliance audits, Postgres can log connection lifecycle events to your project's [Postgres logs](/docs/guides/observability/logs#postgres), including events such as `connection received`, `connection authenticated`, and `connection authorized`. ## Default behavior @@ -28,7 +28,7 @@ Connection logging supports audit and monitoring controls required by some compl - **HIPAA** — High-compliance projects should keep connection logging enabled. See the [shared responsibility model for healthcare data](/docs/guides/deployment/shared-responsibility-model#managing-healthcare-data) and [HIPAA compliance guide](/docs/guides/security/hipaa-compliance). - **SOC 2** — Users who need connection audit evidence should enable logging and retain logs according to their own policies. See the [SOC 2 compliance guide](/docs/guides/security/soc-2-compliance). -Disabling connection logging does not affect other Supabase logging (for example, [Platform Audit Logs](/docs/guides/security/platform-audit-logs), [Auth Audit Logs](/docs/guides/auth/audit-logs), or [pgAudit](/docs/guides/monitoring-and-debugging/logs#configuring-pgauditlog)). +Disabling connection logging does not affect other Supabase logging (for example, [Platform Audit Logs](/docs/guides/security/platform-audit-logs), [Auth Audit Logs](/docs/guides/auth/audit-logs), or [pgAudit](/docs/guides/observability/advanced-log-filtering#configuring-pgauditlog)). ## Manage connection logging via the dashboard @@ -38,7 +38,7 @@ Ensure that you have [Owner or Admin permissions](/docs/guides/platform/access-c -Connection events appear in Postgres logs. In the [Logs Explorer](/dashboard/project/_/logs-explorer), connection lifecycle messages may be hidden by default to reduce noise. Use the connection logs filter in the sidebar to show or hide them. +Connection events appear in [Postgres logs](/docs/guides/observability/logs#postgres). They are included by default when the Postgres log type is selected. Clear **Connection logs** under Postgres to hide them. diff --git a/apps/docs/content/guides/platform/privatelink.mdx b/apps/docs/content/guides/platform/privatelink.mdx index e1ac45325ed3f..08e22a1eb0789 100644 --- a/apps/docs/content/guides/platform/privatelink.mdx +++ b/apps/docs/content/guides/platform/privatelink.mdx @@ -59,7 +59,7 @@ Select **View connection** to see the VPC Lattice resource configuration ID and Supabase will send you an AWS Resource Share containing the VPC Lattice Resource Configurations for your projects. To accept this share: -1. Login to your AWS Management Console, ensure you are in the AWS region where your Supabase project is located +1. Sign in to your AWS Management Console, ensure you are in the AWS region where your Supabase project is located 2. Navigate to the AWS Resource Access Manager (RAM) console {/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */} 3. Go to [Shared with me > Resource shares](https://console.aws.amazon.com/ram/home#SharedResourceShares) diff --git a/apps/docs/content/guides/platform/project-transfer.mdx b/apps/docs/content/guides/platform/project-transfer.mdx index cc4718c63406a..f4152076a1060 100644 --- a/apps/docs/content/guides/platform/project-transfer.mdx +++ b/apps/docs/content/guides/platform/project-transfer.mdx @@ -43,7 +43,7 @@ Target organization - the organization you want to move the project to ## Usage-billing and project add-ons -For usage metrics such as disk size, egress or image transformations and project add-ons such as [Compute Add-On](/docs/guides/platform/compute-and-disk), [Point-In-Time-Recovery](/docs/guides/platform/backups#point-in-time-recovery), [IPv4](/docs/guides/platform/ipv4-address), [Log Drains](/docs/guides/monitoring-and-debugging/log-drains), [Advanced MFA](/docs/guides/auth/auth-mfa/phone) or a [Custom Domain](/docs/guides/platform/custom-domains), the source organization will still be charged for the usage up until the transfer. The charges will be added to the invoice when the billing cycle resets. +For usage metrics such as disk size, egress or image transformations and project add-ons such as [Compute Add-On](/docs/guides/platform/compute-and-disk), [Point-In-Time-Recovery](/docs/guides/platform/backups#point-in-time-recovery), [IPv4](/docs/guides/platform/ipv4-address), [Log Drains](/docs/guides/observability/log-drains), [Advanced MFA](/docs/guides/auth/auth-mfa/phone) or a [Custom Domain](/docs/guides/platform/custom-domains), the source organization will still be charged for the usage up until the transfer. The charges will be added to the invoice when the billing cycle resets. The target organization will be charged at the end of the billing cycle for usage after the project transfer. diff --git a/apps/docs/content/guides/platform/read-replicas.mdx b/apps/docs/content/guides/platform/read-replicas.mdx index f5d3e62700ae8..a5f80918644dc 100644 --- a/apps/docs/content/guides/platform/read-replicas.mdx +++ b/apps/docs/content/guides/platform/read-replicas.mdx @@ -152,7 +152,7 @@ When a Read Replica is deployed, it emits logs from the following services: - [PostgREST](/dashboard/project/_/logs/postgrest-logs) - [Supavisor](/dashboard/project/_/logs/pooler-logs) -Views on [Log Explorer](/docs/guides/monitoring-and-debugging/logs) are automatically filtered by databases, with the logs of the Primary database displayed by default. Viewing logs from other databases can be toggled with the `Source` button found on the upper-right part section of the Logs Explorer page. +Single-service [log collections](/docs/guides/observability/logs#single-service-collections) filter by database, with the Primary database displayed by default. Switch databases with the **Source** control. For API logs, logs can originate from the API Load Balancer as well. The upstream database or the one that eventually handles the request can be found under the `Redirect Identifier` field. This is equivalent to `metadata.load_balancer_redirect_identifier` when querying the underlying logs. @@ -160,7 +160,7 @@ For API logs, logs can originate from the API Load Balancer as well. The upstrea Observability and metrics for Read Replicas are available on the Supabase Dashboard. Resource utilization for a specific Read Replica can be viewed on the [Database Reports page](/dashboard/project/_/observability/database) by toggling for `Source`. Likewise, metrics on API requests going through either a Read Replica or Load Balancer API endpoint are also available on the dashboard through the [API Reports page](/dashboard/project/_/observability/api-overview) -We recommend ingesting your [project's metrics](/docs/guides/monitoring-and-debugging/metrics) into your own environment. If you have an existing ingestion pipeline set up for your project, you can [update it](https://github.com/supabase/supabase-grafana?tab=readme-ov-file#read-replica-support) to additionally ingest metrics from your Read Replicas. +We recommend ingesting your [project's metrics](/docs/guides/observability/metrics) into your own environment. If you have an existing ingestion pipeline set up for your project, you can [update it](https://github.com/supabase/supabase-grafana?tab=readme-ov-file#read-replica-support) to additionally ingest metrics from your Read Replicas. ### Centralized configuration management diff --git a/apps/docs/content/guides/platform/read-replicas/getting-started.mdx b/apps/docs/content/guides/platform/read-replicas/getting-started.mdx index 9a0d885041f92..d376490f459a9 100644 --- a/apps/docs/content/guides/platform/read-replicas/getting-started.mdx +++ b/apps/docs/content/guides/platform/read-replicas/getting-started.mdx @@ -129,7 +129,7 @@ There is no single threshold to indicate when you should address replication lag -If you are already ingesting your [project's metrics](/docs/guides/monitoring-and-debugging/metrics) into your own environment, you can also keep track of replication lag and set alarms with the `physical_replication_lag_physical_replica_lag_seconds` metric. +If you are already ingesting your [project's metrics](/docs/guides/observability/metrics) into your own environment, you can also keep track of replication lag and set alarms with the `physical_replication_lag_physical_replica_lag_seconds` metric. diff --git a/apps/docs/content/guides/platform/ssl-enforcement.mdx b/apps/docs/content/guides/platform/ssl-enforcement.mdx index 726596f60bca4..f911eef9f0554 100644 --- a/apps/docs/content/guides/platform/ssl-enforcement.mdx +++ b/apps/docs/content/guides/platform/ssl-enforcement.mdx @@ -62,7 +62,7 @@ curl -X PUT "https://api.supabase.com/v1/projects/$PROJECT_REF/ssl-enforcement" To get started: 1. [Install](/docs/guides/local-development) the Supabase CLI 1.37.0+. -1. [Log in](/docs/guides/local-development/database-migrations#log-in-to-the-supabase-cli) to your Supabase account using the CLI. +1. [Sign in](/docs/guides/local-development/database-migrations#sign-in-to-the-supabase-cli) to your Supabase account using the CLI. 1. Ensure that you have [Owner or Admin permissions](/docs/guides/platform/access-control#manage-team-members) for the project that you are enabling SSL enforcement. ### Check enforcement status diff --git a/apps/docs/content/guides/platform/sso.mdx b/apps/docs/content/guides/platform/sso.mdx index 881157813373b..d623c5fe50a5a 100644 --- a/apps/docs/content/guides/platform/sso.mdx +++ b/apps/docs/content/guides/platform/sso.mdx @@ -9,7 +9,7 @@ Looking for docs on how to add Single Sign-On support in your Supabase project? -Supabase offers single sign-on (SSO) as a login option to provide additional account security for your team. This allows company administrators to enforce the use of an identity provider when logging into Supabase. SSO improves the onboarding and offboarding experience of the company as the employee only needs a single set of credentials to access third-party applications or tools which can also be revoked by an administrator. +Supabase offers single sign-on (SSO) as a sign-in option to provide additional account security for your team. This allows company administrators to enforce the use of an identity provider when signing in to Supabase. SSO improves the onboarding and offboarding experience of the company as the employee only needs a single set of credentials to access third-party applications or tools which can also be revoked by an administrator. @@ -40,13 +40,13 @@ After configuring your SSO provider, thorough testing is essential. See our [SSO -## Choosing your login flow +## Choosing your sign-in flow -Supabase supports two SSO login flows: **IdP-initiated** and **SP-initiated**. You can enable one or both depending on your organization's needs. +Supabase supports two SSO sign-in flows: **IdP-initiated** and **SP-initiated**. You can enable one or both depending on your organization's needs. -### IdP-initiated login (recommended) +### IdP-initiated sign-in (recommended) -Users start their login from your identity provider (Okta, Azure AD, Google Workspace) by clicking an app tile or bookmark. This is the **simplest and most common configuration** - it requires no domain configuration and works automatically once SSO is enabled. +Users start their sign-in from your identity provider (Okta, Azure AD, Google Workspace) by clicking an app tile or bookmark. This is the **simplest and most common configuration** - it requires no domain configuration and works automatically once SSO is enabled. **Best for:** @@ -54,9 +54,9 @@ Users start their login from your identity provider (Okta, Azure AD, Google Work - Multiple SAML apps per domain (Dev, Staging, Prod) - Simplest user experience -### SP-initiated login +### SP-initiated sign-in -Users start their login at supabase.com by entering their email address, then are redirected to your identity provider. This flow requires configuring email domains to route users to the correct IdP. +Users start their sign-in at supabase.com by entering their email address, then are redirected to your identity provider. This flow requires configuring email domains to route users to the correct IdP. **Best for:** @@ -67,16 +67,16 @@ Users start their login at supabase.com by entering their email address, then ar ### Need help choosing? - **Quick decision:** Start with IdP-initiated only (the default). It works for 90% of use cases. -- **Detailed guidance:** See [Choosing the Right Login Flow](/docs/guides/platform/sso/choosing-login-flow) for scenario-based recommendations. -- **Technical details:** Read [Understanding SSO Login Flows](/docs/guides/platform/sso/login-flows) for in-depth explanations. +- **Detailed guidance:** See [Choosing the Right Sign-in Flow](/docs/guides/platform/sso/choosing-login-flow) for scenario-based recommendations. +- **Technical details:** Read [Understanding SSO Sign-in Flows](/docs/guides/platform/sso/login-flows) for in-depth explanations. ## Key configuration options -- **Login flows** - Choose between IdP-initiated (users start from identity provider), SP-initiated (users start at supabase.com), or both. IdP-initiated is recommended for most organizations and requires no domain configuration. See [Choosing the Right Login Flow](/docs/guides/platform/sso/choosing-login-flow) for guidance. -- **Email domains** - Required only if you enable SP-initiated login. You can associate one or more email domains with your SSO provider. Users with matching email addresses can sign in via SSO at supabase.com. Not required for IdP-initiated flow. -- **Auto-join** - Optionally allow users with a matching domain to join your organization automatically when they sign in via SSO. This applies on every login, not only on first signup. +- **Sign-in flows** - Choose between IdP-initiated (users start from identity provider), SP-initiated (users start at supabase.com), or both. IdP-initiated is recommended for most organizations and requires no domain configuration. See [Choosing the Right Sign-in Flow](/docs/guides/platform/sso/choosing-login-flow) for guidance. +- **Email domains** - Required only if you enable SP-initiated sign-in. You can associate one or more email domains with your SSO provider. Users with matching email addresses can sign in via SSO at supabase.com. Not required for IdP-initiated flow. +- **Auto-join** - Optionally allow users with a matching domain to join your organization automatically when they sign in via SSO. This applies on every sign-in, not only on first sign-up. - **Default role for auto-joined users** - Choose the role (e.g., `Read-only`, `Developer`, `Administrator`, `Owner`) that automatically joined users receive. We recommend using `Developer` as the default (principle of least privilege) and promoting users individually as needed. Refer to [access control](/docs/guides/platform/access-control) for more information about roles. -- **Invitation types** - When inviting users to your organization, you can explicitly choose whether the invitation requires SSO authentication or allows non-SSO login (password/social). This enables mixed authentication organizations with both SSO and non-SSO users. +- **Invitation types** - When inviting users to your organization, you can explicitly choose whether the invitation requires SSO authentication or allows non-SSO sign-in (password/social). This enables mixed authentication organizations with both SSO and non-SSO users. ## How SSO works in Supabase @@ -95,10 +95,10 @@ When SSO is enabled for an organization: 1. Create or verify at least one non-SSO owner account exists (required for safety) 2. Configure your SSO provider following one of our [provider-specific guides](#supported-providers) 3. Start with auto-join **disabled** to test the configuration -4. Test SSO login with your own account +4. Test SSO sign-in with your own account 5. Once confirmed working, enable auto-join if desired 6. Thoroughly test using our [SSO Testing and Best Practices](/docs/guides/platform/sso/testing-best-practices) guide -7. Invite users to the organization or let them auto-join on login +7. Invite users to the organization or let them auto-join on sign-in @@ -108,9 +108,9 @@ If a user is already a member of the organization under a non-SSO account, they -Each user account verified using an SSO identity provider will not be legible for [identity linking](/docs/guides/auth/auth-identity-linking) to existing user accounts in the system. That is, if a user `valid.email@supabase.io` had signed up with a password, and then uses their company SSO login with your project, there will be two `valid.email@supabase.io` user accounts in the system. +Each user account verified using an SSO identity provider will not be eligible for [identity linking](/docs/guides/auth/auth-identity-linking) to existing user accounts in the system. That is, if a user `valid.email@supabase.io` had signed up with a password, and then uses their company SSO sign-in with your project, there will be two `valid.email@supabase.io` user accounts in the system. -Users will need to ensure they are logged in with the correct account when accessing organizations/projects. +Users will need to ensure they are signed in with the correct account when accessing organizations/projects. @@ -124,7 +124,7 @@ The system requires at least one non-SSO owner account before allowing SSO provi Before disabling or deleting SSO: -- Verify a non-SSO owner account exists and can log in +- Verify a non-SSO owner account exists and can sign in - Communicate to affected users in advance - Consider whether disabling is better than deleting if the change is temporary @@ -141,7 +141,7 @@ To revoke access for a specific SSO user without disabling the provider entirely Before rolling out SSO to your organization, we strongly recommend thorough testing and following security best practices. Our comprehensive guide covers: -- Step-by-step testing procedures for SSO login, auto-join, and invitations +- Step-by-step testing procedures for SSO sign-in, auto-join, and invitations - Troubleshooting common issues (many of which previously required support intervention) - Security best practices including certificate monitoring and domain configuration - Operational guidance for making SSO changes safely diff --git a/apps/docs/content/guides/platform/sso/azure.mdx b/apps/docs/content/guides/platform/sso/azure.mdx index 913f534ed2416..db6f954bdd38a 100644 --- a/apps/docs/content/guides/platform/sso/azure.mdx +++ b/apps/docs/content/guides/platform/sso/azure.mdx @@ -128,13 +128,13 @@ Fill out the Attribute Mapping section using the **Azure** preset. ![Attribute mapping configuration](/docs/img/sso-dashboard-configure-attributes-azure.png) -## Step 12: Join organization on signup (optional) [#dashboard-configure-autojoin] +## Step 12: Join organization on sign-up (optional) [#dashboard-configure-autojoin] -By default this setting is disabled, users logging in via SSO will not be added to your organization automatically. +By default this setting is disabled, users signing in via SSO will not be added to your organization automatically. ![Auto-join disabled](/docs/img/sso-dashboard-configure-autojoin-disabled.png) -Toggle this on if you want SSO-authenticated users to be **automatically added to your organization** when they log in via SSO. Auto-join applies on **every login**, not only on first signup - this makes it safe to test SSO before enabling this feature. +Toggle this on if you want SSO-authenticated users to be **automatically added to your organization** when they sign in via SSO. Auto-join applies on **every sign-in**, not only on first sign-up - this makes it safe to test SSO before enabling this feature. ![Auto-join enable](/docs/img/sso-dashboard-configure-autojoin-enabled.png) diff --git a/apps/docs/content/guides/platform/sso/choosing-login-flow.mdx b/apps/docs/content/guides/platform/sso/choosing-login-flow.mdx index 2e6d6c65ed3aa..6cc84c067dca3 100644 --- a/apps/docs/content/guides/platform/sso/choosing-login-flow.mdx +++ b/apps/docs/content/guides/platform/sso/choosing-login-flow.mdx @@ -1,9 +1,9 @@ --- -title: 'Choosing the Right SSO Login Flow' -description: 'Quick reference guide to help you choose between IdP-initiated, SP-initiated, or both login flows based on your use case.' +title: 'Choosing the Right SSO Sign-in Flow' +description: 'Quick reference guide to help you choose between IdP-initiated, SP-initiated, or both sign-in flows based on your use case.' --- -Not sure which single sign-on (SSO) login flow to enable? This guide maps common enterprise scenarios to the recommended configuration. +Not sure which single sign-on (SSO) sign-in flow to enable? This guide maps common enterprise scenarios to the recommended configuration. @@ -92,7 +92,7 @@ Do users need to start login at supabase.com? 3. Configure identity provider metadata 4. Create Supabase app tile in your IdP -**Result:** One-click SSO login for all users. +**Result:** One-click SSO sign-in for all users. --- @@ -101,7 +101,7 @@ Do users need to start login at supabase.com? **Your situation:** - Users frequently bookmark supabase.com directly -- You want to support starting login from Supabase +- You want to support starting sign-in from Supabase - Single domain, single organization **Recommended configuration:** Enable both flows ✅ @@ -120,7 +120,7 @@ Do users need to start login at supabase.com? 4. Configure identity provider metadata 5. Create Supabase app tile in your IdP (optional but recommended) -**Result:** Users can start login from either Supabase or IdP. +**Result:** Users can start sign-in from either Supabase or IdP. --- @@ -128,7 +128,7 @@ Do users need to start login at supabase.com? **Your situation:** -- Currently using password-based login +- Currently using password-based sign-in - Transitioning to SSO - Users are used to starting at supabase.com @@ -136,7 +136,7 @@ Do users need to start login at supabase.com? **Why:** -- Familiar login starting point for existing users +- Familiar sign-in starting point for existing users - Gradual transition to IdP-based access - Can promote IdP tiles after users adapt @@ -267,7 +267,7 @@ Communicate clearly which authentication method each user should use. ## Testing your configuration -After choosing your login flow, thoroughly test: +After choosing your sign-in flow, thoroughly test: 1. **IdP-initiated:** Click app tile in IdP → Verify redirect to Supabase 2. **SP-initiated:** Go to supabase.com/sign-in-sso → Enter email → Verify IdP redirect @@ -278,7 +278,7 @@ See our comprehensive [SSO Testing and Best Practices guide](/docs/guides/platfo ## When to change configuration -You can safely change login flow configuration at any time: +You can safely change sign-in flow configuration at any time: ### Adding SP-initiated to IdP-only @@ -314,7 +314,7 @@ If you need help choosing the right configuration for your organization, contact ## Next steps -- **Understand the technical details:** Read [Understanding SSO Login Flows](/docs/guides/platform/sso/login-flows) +- **Understand the technical details:** Read [Understanding SSO Sign-in Flows](/docs/guides/platform/sso/login-flows) - **Configure your provider:** Follow our [provider-specific guides](/docs/guides/platform/sso#supported-providers) - **Test your setup:** Review [SSO Testing and Best Practices](/docs/guides/platform/sso/testing-best-practices) - **Enable auto-join:** Configure [auto-join settings](/docs/guides/platform/sso#key-configuration-options) diff --git a/apps/docs/content/guides/platform/sso/enterprise-mcp-authentication.mdx b/apps/docs/content/guides/platform/sso/enterprise-mcp-authentication.mdx index 1b887d93a7d30..e70cc5997bb83 100644 --- a/apps/docs/content/guides/platform/sso/enterprise-mcp-authentication.mdx +++ b/apps/docs/content/guides/platform/sso/enterprise-mcp-authentication.mdx @@ -37,7 +37,7 @@ Before members can use enterprise-managed authentication: ## How it works -1. **Member signs in to the MCP client via your IdP**, using the same SSO login your members already use, over OpenID Connect or SAML. The IdP returns an identity token to the MCP client. +1. **Member signs in to the MCP client via your IdP**, using the same SSO sign-in your members already use, over OpenID Connect or SAML. The IdP returns an identity token to the MCP client. 2. **MCP client exchanges that identity token for an ID-JAG, at the IdP.** This is a separate request the client makes to the IdP (an [RFC 8693](https://datatracker.ietf.org/doc/html/rfc8693) token exchange), asking for a token scoped specifically to Supabase. The IdP checks its own policy before issuing one. 3. **IdP returns the ID-JAG to the MCP client.** 4. **MCP client presents the ID-JAG to Supabase's OAuth server**, using it as a [JWT authorization grant](https://datatracker.ietf.org/doc/html/rfc7523), with no interactive consent screen. @@ -54,7 +54,7 @@ Without it, every member has to manually connect and authorize the MCP client ag - **No central control**: admins can't see or revoke the MCP client's access at the organization level; it's spread across individual user approvals. - **Inconsistent access**: a member's access through the MCP client isn't guaranteed to stay in sync with the role your IdP already assigns them. -With enterprise-managed authentication, an organization owner authorizes the MCP client once for the whole organization. From then on, access follows your existing SSO login, with no separate approval and no manual reconnection when a token expires. +With enterprise-managed authentication, an organization owner authorizes the MCP client once for the whole organization. From then on, access follows your existing SSO sign-in, with no separate approval and no manual reconnection when a token expires. ## Configuring your ID-JAG issuer diff --git a/apps/docs/content/guides/platform/sso/gsuite.mdx b/apps/docs/content/guides/platform/sso/gsuite.mdx index d28c1fda108ce..9702c7096e5ce 100644 --- a/apps/docs/content/guides/platform/sso/gsuite.mdx +++ b/apps/docs/content/guides/platform/sso/gsuite.mdx @@ -63,7 +63,7 @@ Fill out these service provider details on the next screen. ## Step 6: Configure attribute mapping [#configure-attribute-mapping] -Attribute mappings allow Supabase to get information about your Google Workspace users on each login. +Attribute mappings allow Supabase to get information about your Google Workspace users on each sign-in. **A _Primary email_ to `email` mapping is required.** Other mappings shown below are optional and configurable depending on your Google Workspace setup. If in doubt, replicate the same config as shown. @@ -136,15 +136,15 @@ If you did not customize your settings you may save some time by clicking the ** -**Recommended workflow:** Start with auto-join **disabled** to test your SSO configuration. Once SSO login is working correctly, enable auto-join if desired. +**Recommended workflow:** Start with auto-join **disabled** to test your SSO configuration. Once SSO sign-in is working correctly, enable auto-join if desired. -By default this setting is disabled, users logging in via SSO will not be added to your organization automatically. +By default this setting is disabled, users signing in via SSO will not be added to your organization automatically. ![Auto-join disabled](/docs/img/sso-dashboard-configure-autojoin-disabled.png) -Toggle this on if you want SSO-authenticated users to be **automatically added to your organization** when they log in via SSO. Auto-join applies on **every login**, not only on first signup - this makes it safe to test SSO before enabling this feature. +Toggle this on if you want SSO-authenticated users to be **automatically added to your organization** when they sign in via SSO. Auto-join applies on **every sign-in**, not only on first signup - this makes it safe to test SSO before enabling this feature. ![Auto-join enable](/docs/img/sso-dashboard-configure-autojoin-enabled.png) diff --git a/apps/docs/content/guides/platform/sso/login-flows.mdx b/apps/docs/content/guides/platform/sso/login-flows.mdx index b67b0fab73475..44bd9031357a9 100644 --- a/apps/docs/content/guides/platform/sso/login-flows.mdx +++ b/apps/docs/content/guides/platform/sso/login-flows.mdx @@ -1,29 +1,29 @@ --- -title: 'Understanding SSO Login Flows' -description: 'Learn about IdP-initiated and SP-initiated SSO login flows and when to use each approach.' +title: 'Understanding SSO Sign-in Flows' +description: 'Learn about IdP-initiated and SP-initiated SSO sign-in flows and when to use each approach.' --- -When configuring SSO for your organization, you can choose between two different login flows: **identity provider (IdP)-initiated** and **service provider (SP)-initiated**. Understanding the difference helps you provide the best experience for your users. +When configuring SSO for your organization, you can choose between two different sign-in flows: **identity provider (IdP)-initiated** and **service provider (SP)-initiated**. Understanding the difference helps you provide the best experience for your users. -Most enterprises use IdP-initiated flow for its simplicity and better user experience. Enable SP-initiated only if you need users to start their login journey at supabase.com. +Most enterprises use IdP-initiated flow for its simplicity and better user experience. Enable SP-initiated only if you need users to start their sign-in journey at supabase.com. -See our [Choosing the Right Login Flow guide](/docs/guides/platform/sso/choosing-login-flow) for use case examples. +See our [Choosing the Right Sign-in Flow guide](/docs/guides/platform/sso/choosing-login-flow) for use case examples. -## Overview of login flows +## Overview of sign-in flows ### IdP-initiated (Identity Provider Initiated) -With IdP-initiated flow, users start their login journey from your identity provider (Okta, Azure AD, Google Workspace, etc.) and are directly authenticated into Supabase. +With IdP-initiated flow, users start their sign-in journey from your identity provider (Okta, Azure AD, Google Workspace, etc.) and are directly authenticated into Supabase. **User experience:** 1. User opens their identity provider dashboard (e.g., Okta homepage, Azure MyApps) 2. User clicks the Supabase app tile or bookmark -3. User is immediately logged into Supabase (if already authenticated with IdP) +3. User is immediately signed in to Supabase (if already authenticated with IdP) **Key characteristics:** @@ -49,7 +49,7 @@ With SP-initiated flow, users start at supabase.com, enter their email address, - ✅ Familiar flow for users who bookmark supabase.com - ✅ Supports domain-based automatic IdP routing - ⚠️ Requires configuring email domains -- ⚠️ More steps in the login process +- ⚠️ More steps in the sign-in process ## Choosing between flows @@ -65,7 +65,7 @@ With SP-initiated flow, users start at supabase.com, enter their email address, **Common scenarios:** - "Our team accesses all tools through Okta tiles" -- "We want the simplest possible login experience" +- "We want the simplest possible sign-in experience" - "We need separate Dev and Prod SAML apps under the same domain" - "Users should never need to remember supabase.com" @@ -81,7 +81,7 @@ With SP-initiated flow, users start at supabase.com, enter their email address, - "Some users bookmark supabase.com and expect to start there" - "We're transitioning from password auth to SSO" -- "Users need a consistent login page across all tools" +- "Users need a consistent sign-in page across all tools" - "We want domain-based automatic IdP selection" ### When to enable both flows @@ -94,7 +94,7 @@ You can enable both flows simultaneously to support different user preferences. - Gradual SSO migration with mixed authentication - Supporting both technical and non-technical users -## Configuring login flows +## Configuring sign-in flows ### Enabling IdP-initiated flow (default) @@ -133,13 +133,13 @@ To enable SP-initiated flow, you need to configure email domains: -Only users with email addresses matching your configured domains can use SP-initiated login. Users with other domains cannot sign in via SSO at supabase.com (but can still use IdP-initiated flow if you configure it in your IdP). +Only users with email addresses matching your configured domains can use SP-initiated sign-in. Users with other domains cannot sign in via SSO at supabase.com (but can still use IdP-initiated flow if you configure it in your IdP). ### Switching between flows -You can change login flow configuration at any time: +You can change sign-in flow configuration at any time: #### To switch from SP-initiated to IdP-only @@ -224,11 +224,11 @@ This is the recommended approach for enterprises with multiple environments. Con ### Can you use both flows simultaneously? -Yes! Enable SP-initiated login and configure domains. IdP-initiated flow continues to work automatically. +Yes! Enable SP-initiated sign-in and configure domains. IdP-initiated flow continues to work automatically. ### What happens when you don't configure domains? -Without domains, only IdP-initiated flow is available. Users cannot start their login at supabase.com. +Without domains, only IdP-initiated flow is available. Users cannot start their sign-in at supabase.com. ### Does the IdP require configuration? @@ -261,7 +261,7 @@ See our [SSO Testing and Best Practices](/docs/guides/platform/sso/testing-best- ## Next steps -- **Choose your login flow:** See [Choosing the Right Login Flow](/docs/guides/platform/sso/choosing-login-flow) +- **Choose your sign-in flow:** See [Choosing the Right Sign-in Flow](/docs/guides/platform/sso/choosing-login-flow) - **Configure your provider:** Follow our [provider-specific guides](/docs/guides/platform/sso#supported-providers) - **Test thoroughly:** Review [SSO Testing and Best Practices](/docs/guides/platform/sso/testing-best-practices) - **Enable auto-join:** Configure [auto-join settings](/docs/guides/platform/sso#key-configuration-options) for seamless onboarding diff --git a/apps/docs/content/guides/platform/sso/multiple-providers.mdx b/apps/docs/content/guides/platform/sso/multiple-providers.mdx index 7e5f49b3a532c..5e5d84adc6f49 100644 --- a/apps/docs/content/guides/platform/sso/multiple-providers.mdx +++ b/apps/docs/content/guides/platform/sso/multiple-providers.mdx @@ -25,7 +25,7 @@ The traditional challenge with multiple SAML apps is domain conflicts. With SP-i Configure each environment as IdP-initiated only (no domains). Users access each environment through different app tiles in your identity provider. -For technical details, see [the Understanding SSO Login Flows guide](/docs/guides/platform/sso/login-flows#multiple-saml-apps-per-domain). +For technical details, see [the Understanding SSO Sign-in Flows guide](/docs/guides/platform/sso/login-flows#multiple-saml-apps-per-domain). @@ -122,7 +122,7 @@ Assign appropriate users to each app. Users only see the tiles they're assigned Configure both organizations with SP-initiated enabled using the same domain: - Both organizations add `company.com` as a domain -- Users can log in via SP-initiated at supabase.com +- Users can sign in via SP-initiated at supabase.com - System routes based on org membership (first match wins) - Also provide IDP tiles for explicit routing @@ -190,7 +190,7 @@ All authenticate through the same central IDP but use different email domains. 1. Enable SSO with SP-initiated flow 2. Add all domains: `parent.com`, `subsidiary1.com`, `subsidiary2.com` 3. Configure single IDP metadata -4. Users with any matching domain can log in via supabase.com +4. Users with any matching domain can sign in via supabase.com #### Option B: Separate providers per subsidiary (IDP-initiated) @@ -542,5 +542,5 @@ If you currently have a single SSO provider and need to add more: - **Configure your IDP:** Follow your [provider-specific guide](/docs/guides/platform/sso#supported-providers) - **Test thoroughly:** Review [SSO Testing and Best Practices](/docs/guides/platform/sso/testing-best-practices) -- **Understand login flows:** Read [Understanding SSO Login Flows](/docs/guides/platform/sso/login-flows) -- **Choose the right flow:** See [Choosing the Right Login Flow](/docs/guides/platform/sso/choosing-login-flow) +- **Understand sign-in flows:** Read [Understanding SSO Sign-in Flows](/docs/guides/platform/sso/login-flows) +- **Choose the right flow:** See [Choosing the Right Sign-in Flow](/docs/guides/platform/sso/choosing-login-flow) diff --git a/apps/docs/content/guides/platform/sso/okta.mdx b/apps/docs/content/guides/platform/sso/okta.mdx index 8e51b7d7940e5..d0fba4986bb52 100644 --- a/apps/docs/content/guides/platform/sso/okta.mdx +++ b/apps/docs/content/guides/platform/sso/okta.mdx @@ -53,7 +53,7 @@ These settings let Supabase use SAML 2.0 properly with your Okta application. Ma ## Step 5: Fill out attribute statements [#add-attribute-statements] -Attribute Statements allow Supabase to get information about your Okta users on each login. +Attribute Statements allow Supabase to get information about your Okta users on each sign-in. **A `email` to `user.email` statement is required.** Other mappings shown below are optional and configurable depending on your Okta setup. If in doubt, replicate the same config as shown. You will use this mapping later in [Step 10](#dashboard-configure-attributes). @@ -122,15 +122,15 @@ If you did not customize your settings you may save some time by clicking the ** -**Recommended workflow:** Start with auto-join **disabled** to test your SSO configuration. Once SSO login is working correctly, enable auto-join if desired. +**Recommended workflow:** Start with auto-join **disabled** to test your SSO configuration. Once SSO sign-in is working correctly, enable auto-join if desired. -By default this setting is disabled, users logging in via SSO will not be added to your organization automatically. +By default this setting is disabled, users signing in via SSO will not be added to your organization automatically. ![Auto-join disabled](/docs/img/sso-dashboard-configure-autojoin-disabled.png) -Toggle this on if you want SSO-authenticated users to be **automatically added to your organization** when they log in via SSO. Auto-join applies on **every login**, not only on first signup - this makes it safe to test SSO before enabling this feature. +Toggle this on if you want SSO-authenticated users to be **automatically added to your organization** when they sign in via SSO. Auto-join applies on **every sign-in**, not only on first signup - this makes it safe to test SSO before enabling this feature. ![Auto-join enable](/docs/img/sso-dashboard-configure-autojoin-enabled.png) diff --git a/apps/docs/content/guides/platform/sso/testing-best-practices.mdx b/apps/docs/content/guides/platform/sso/testing-best-practices.mdx index 7877fc94f31b5..e68fa60acac09 100644 --- a/apps/docs/content/guides/platform/sso/testing-best-practices.mdx +++ b/apps/docs/content/guides/platform/sso/testing-best-practices.mdx @@ -10,19 +10,19 @@ After configuring your SSO provider, thorough testing is essential before rollin Before you begin testing, verify: - Organization has Team or Enterprise plan -- Login flow type decided (IdP-initiated, SP-initiated, or both) - see [Choosing a Login Flow](/docs/guides/platform/sso/choosing-login-flow) +- Sign-in flow type decided (IdP-initiated, SP-initiated, or both) - see [Choosing a Sign-in Flow](/docs/guides/platform/sso/choosing-login-flow) - Email domains identified (only required if using SP-initiated) - Auto-join settings and default role are decided - **At least one non-SSO owner account exists** (critical safety requirement) - Certificate expiration dates are documented (especially for Google Workspace) -## Testing login flows +## Testing sign-in flows -Before testing auto-join and other features, verify which login flows work for your SSO configuration. See [Understanding SSO Login Flows](/docs/guides/platform/sso/login-flows) for technical details. +Before testing auto-join and other features, verify which sign-in flows work for your SSO configuration. See [Understanding SSO Sign-in Flows](/docs/guides/platform/sso/login-flows) for technical details. -### Testing IdP-initiated login +### Testing IdP-initiated sign-in -IdP-initiated login is always available and doesn't require domain configuration. This should be your primary test. +IdP-initiated sign-in is always available and doesn't require domain configuration. This should be your primary test. **Test procedure:** @@ -33,8 +33,8 @@ IdP-initiated login is always available and doesn't require domain configuration 2. **Verify authentication:** - If already authenticated with IdP: Immediate redirect to Supabase - - If not authenticated: Complete IdP login flow, then redirect - - Check you're logged into the correct organization + - If not authenticated: Complete IdP sign-in flow, then redirect + - Check you're signed in to the correct organization - Verify user profile information is populated correctly 3. **Confirm success:** @@ -44,13 +44,13 @@ IdP-initiated login is always available and doesn't require domain configuration **Expected results:** -- ✅ Direct login from IdP with no intermediate steps +- ✅ Direct sign-in from IdP with no intermediate steps - ✅ Works regardless of domain configuration - ✅ User information properly mapped from IdP -### Testing SP-initiated login +### Testing SP-initiated sign-in -SP-initiated login requires domain configuration. Only test this if you've enabled SP-initiated flow. +SP-initiated sign-in requires domain configuration. Only test this if you've enabled SP-initiated flow. @@ -113,7 +113,7 @@ You've configured SSO with: 2. **Verify IdP-initiated works:** - Open IdP dashboard - Click Supabase app tile - - Should successfully log in + - Should successfully sign in - Verify correct organization access 3. **Confirm multi-environment pattern works (if applicable):** @@ -124,8 +124,8 @@ You've configured SSO with: **Expected results:** -- ✅ IdP-initiated login works perfectly -- ❌ SP-initiated login unavailable (expected) +- ✅ IdP-initiated sign-in works perfectly +- ❌ SP-initiated sign-in unavailable (expected) - ✅ Multiple environments accessible via different tiles - ✅ No domain conflicts between environments @@ -135,19 +135,19 @@ You've configured SSO with: -### Login flow verification checklist +### Sign-in flow verification checklist -- IdP-initiated login works from IdP dashboard -- SP-initiated login works (if domains configured) +- IdP-initiated sign-in works from IdP dashboard +- SP-initiated sign-in works (if domains configured) - SP-initiated properly blocked if no domains configured - Domain matching works correctly for SP-initiated - Non-matching domains show appropriate errors - Multiple environments route correctly (if using multiple providers) - Both flows work simultaneously (if both enabled) -## Testing SSO login flow +## Testing SSO sign-in flow -### Basic login test +### Basic sign-in test 1. **Navigate to the SSO sign-in page**: - Visit [Sign in with SSO](/dashboard/sign-in-sso) @@ -160,7 +160,7 @@ You've configured SSO with: 3. **Verify redirect to identity provider**: - You should be redirected to your identity provider (Okta, Azure AD, Google Workspace) - If already signed in to your IdP, you may be automatically redirected back - - If not signed in, complete the IdP login flow + - If not signed in, complete the IdP sign-in flow 4. **Confirm successful sign-in**: - You should be redirected back to Supabase dashboard @@ -180,7 +180,7 @@ Test with 2-3 additional users to verify: -**Recent improvement:** Auto-join now applies on EVERY login, not only on first signup. This resolves a common issue where org owners would test with auto-join disabled, enable it, then log in again expecting to auto-join. +**Recent improvement:** Auto-join now applies on EVERY sign-in, not only on first signup. This resolves a common issue where org owners would test with auto-join disabled, enable it, then sign in again expecting to auto-join. @@ -190,7 +190,7 @@ Test with 2-3 additional users to verify: - Navigate to [SSO settings](/dashboard/org/_/sso) - Ensure "Join organization on signup" is **disabled** - Configure your SSO provider - - Test basic SSO login (see above) + - Test basic SSO sign-in (see above) 2. **Enable auto-join after successful test**: - Return to [SSO settings](/dashboard/org/_/sso) @@ -199,7 +199,7 @@ Test with 2-3 additional users to verify: - Click "Save changes" 3. **Test auto-join with your account**: - - **Log out completely** from Supabase + - **Sign out completely** from Supabase - Sign in again via SSO - Verify you were automatically added to the organization - Check you received the correct default role @@ -217,7 +217,7 @@ Test with 2-3 additional users to verify: - Note: With IdP-initiated only, domain matching doesn't apply 6. **Test idempotency (prevents duplicate memberships)**: - - Log in again with an account that's already a member + - Sign in again with an account that's already a member - Verify no error occurs - Check members list - should be no duplicate entry - Confirm role hasn't changed unexpectedly @@ -253,7 +253,7 @@ Test with 2-3 additional users to verify: - Auto-join works when enabled - Users receive correct default role - Non-matching domains are excluded (if using SP-initiated with domains) -- Existing users auto-join on their next login (not only on new signups) +- Existing users auto-join on their next sign-in (not only on new signups) - Auto-join can be disabled and re-enabled as needed - Auto-join is idempotent (no duplicate memberships) - Auto-join works with IdP-initiated only (no domains) @@ -275,7 +275,7 @@ Test with 2-3 additional users to verify: - Select **"Require SSO"** option - Enter recipient email and select role - Send invitation - - Recipient must log in via SSO to accept + - Recipient must sign in via SSO to accept 2. **Create non-SSO invitation**: - Create a new invitation @@ -285,9 +285,9 @@ Test with 2-3 additional users to verify: 3. **Test SSO mismatch scenario**: - Create an SSO-required invitation - - Have recipient try to accept while logged in with a non-SSO account + - Have recipient try to accept while signed in with a non-SSO account - Error should display: "Invite token SSO provider does not match the one you are logged in with" - - Recipient should log out and sign in via SSO + - Recipient should sign out and sign in via SSO - Can then successfully accept the invitation ### Common invitation scenarios @@ -322,7 +322,7 @@ SSO accounts have specific restrictions to prevent accidental organization locko ### Testing SSO account deletion restrictions -1. **Log in with SSO account:** +1. **Sign in with SSO account:** - Authenticate via SSO (IdP or SP-initiated) - Navigate to [SSO settings](/dashboard/org/_/sso) - Verify you are an organization owner @@ -347,7 +347,7 @@ SSO accounts have specific restrictions to prevent accidental organization locko ### Testing with non-SSO owner account -1. **Log in with non-SSO owner:** +1. **Sign in with non-SSO owner:** - Use password or social auth account - Must be organization owner - Navigate to [SSO settings](/dashboard/org/_/sso) @@ -387,8 +387,8 @@ Based on customer pain points that previously required support intervention: **Solution:** -- Auto-join now applies on **every login**, not only on first signup -- To test: Enable auto-join, log out completely, log back in via SSO +- Auto-join now applies on **every sign-in**, not only on first signup +- To test: Enable auto-join, sign out completely, sign in again via SSO - If still not working, verify domain configuration matches user email exactly #### "Can't invite users with the right authentication type" @@ -407,17 +407,17 @@ Based on customer pain points that previously required support intervention: #### "Invitation acceptance shows 'SSO provider mismatch' error" -**Cause:** User is logged in with wrong authentication method for the invitation +**Cause:** User is signed in with wrong authentication method for the invitation **Solution:** -1. Check if invitation requires SSO or non-SSO login -2. Log out completely +1. Check if invitation requires SSO or non-SSO sign-in +2. Sign out completely 3. Sign in with the correct method (SSO or password/social) 4. Accept the invitation 5. Contact the person who sent the invitation if unsure about the type -#### "Deleted the SSO provider and now members can't log in" +#### "Deleted the SSO provider and now members can't sign in" **Recent safety improvements:** @@ -492,7 +492,7 @@ This behavior prevents "orphaned" SSO accounts that can no longer authenticate. 1. **Add non-SSO owner:** - Create or invite a non-SSO user (password or social login) - Promote to owner role - - **Critical:** Verify non-SSO owner can log in BEFORE deletion + - **Critical:** Verify non-SSO owner can sign in BEFORE deletion - Store credentials securely 2. **Document SSO members:** @@ -502,7 +502,7 @@ This behavior prevents "orphaned" SSO accounts that can no longer authenticate. **Test procedure:** 1. **Attempt deletion as non-SSO owner:** - - Log in with non-SSO owner account + - Sign in with non-SSO owner account - Navigate to [SSO settings](/dashboard/org/_/sso) - Delete SSO provider - Confirm deletion @@ -540,7 +540,7 @@ This behavior prevents "orphaned" SSO accounts that can no longer authenticate. - Document their roles 2. **Delete SSO provider:** - - Log in as non-SSO owner + - Sign in as non-SSO owner - Delete SSO provider - System may show member count being removed @@ -565,7 +565,7 @@ This behavior prevents "orphaned" SSO accounts that can no longer authenticate. 1. **Ensure non-SSO owner exists:** - Verify at least one non-SSO owner - - Test their login before deletion + - Test their sign-in before deletion 2. **Delete SSO provider:** - System allows deletion (non-SSO owner exists) @@ -596,7 +596,7 @@ This behavior prevents "orphaned" SSO accounts that can no longer authenticate. 1. **Create dedicated non-SSO owner account** - Use password authentication - - **Test that this account can log in** + - **Test that this account can sign in** - Store credentials in secure password manager - Verify owner permissions @@ -667,7 +667,7 @@ Common causes: **Solution:** 1. Create or convert an existing member to a non-SSO owner account -2. Verify the non-SSO owner can log in +2. Verify the non-SSO owner can sign in 3. Then proceed with SSO provider deletion **Why this is required:** Prevents complete organization lockout if SSO becomes unavailable @@ -682,7 +682,7 @@ Common causes: - System enforces this when deleting SSO provider - Create dedicated non-SSO owner **before** enabling SSO - Store credentials securely in a password manager -- Verify this account can log in before critical changes +- Verify this account can sign in before critical changes #### Monitor certificate expiration @@ -714,7 +714,7 @@ Common causes: 1. Create or verify non-SSO owner account exists 2. Configure SSO provider with auto-join **DISABLED** -3. Test SSO login with your own account +3. Test SSO sign-in with your own account 4. Verify attribute mappings are correct 5. Test with 2-3 additional users 6. Enable auto-join if desired @@ -757,7 +757,7 @@ Common causes: #### After SSO configuration changes -- Test login immediately +- Test sign-in immediately - Verify auto-join still works (if enabled) - Check that invitations are working - Confirm no users are locked out @@ -783,11 +783,11 @@ Common causes: Before rolling out SSO to your organization: -**Authentication & Login Flows:** +**Authentication & Sign-in Flows:** -- IdP-initiated login works from IdP dashboard -- SP-initiated login works (if domains configured) -- Appropriate login flow chosen for your use case +- IdP-initiated sign-in works from IdP dashboard +- SP-initiated sign-in works (if domains configured) +- Appropriate sign-in flow chosen for your use case - Domain configuration correct (or intentionally empty for IdP-only) - Multiple environments route correctly (if using multiple providers) @@ -795,7 +795,7 @@ Before rolling out SSO to your organization: - Auto-join adds users to correct organization (if enabled) - Auto-joined users receive correct default role -- Auto-join works on first login (not only on signup) +- Auto-join works on first sign-in (not only on signup) - Existing users auto-join when feature enabled - Auto-join is idempotent (no duplicate memberships) - Auto-join works with IdP-initiated (no domains required) @@ -811,7 +811,7 @@ Before rolling out SSO to your organization: **Safety & Access Controls:** - At least one non-SSO owner account exists -- Non-SSO owner account can log in successfully +- Non-SSO owner account can sign in successfully - Non-SSO credentials stored securely - SSO account deletion restrictions understood and tested - Safe deletion behavior verified (if tested) @@ -820,14 +820,14 @@ Before rolling out SSO to your organization: - Certificate expiration date documented with calendar reminders - Team notified of SSO availability -- Login instructions provided (IdP tile and/or supabase.com) +- Sign-in instructions provided (IdP tile and/or supabase.com) - Rollback plan documented - Support contact information available **Testing Completed:** - Tested with multiple user accounts -- Both login flows tested (if both enabled) +- Both sign-in flows tested (if both enabled) - Auto-join behavior verified - SSO account restrictions confirmed - Domain restrictions validated (if applicable) diff --git a/apps/docs/content/guides/queues/consuming-messages-with-edge-functions.mdx b/apps/docs/content/guides/queues/consuming-messages-with-edge-functions.mdx index 8a890895fe688..79b7e9d3e0986 100644 --- a/apps/docs/content/guides/queues/consuming-messages-with-edge-functions.mdx +++ b/apps/docs/content/guides/queues/consuming-messages-with-edge-functions.mdx @@ -15,6 +15,7 @@ This is a Supabase Edge Function that reads 5 messages off the queue, processes ```tsx import 'jsr:@supabase/functions-js/edge-runtime.d.ts' + import { createClient } from 'npm:@supabase/supabase-js@2' const supabaseUrl = 'supabaseURL' diff --git a/apps/docs/content/guides/realtime/reports.mdx b/apps/docs/content/guides/realtime/reports.mdx index fe6bd5697a443..a40553a12e647 100644 --- a/apps/docs/content/guides/realtime/reports.mdx +++ b/apps/docs/content/guides/realtime/reports.mdx @@ -239,7 +239,7 @@ height={625} | Check logs | Investigate replication errors or performance issues in your project dashboard | [Realtime Logs Dashboard](/dashboard/project/_/database/realtime-logs) | | Monitor database | Review database resource utilization, connection counts, and query performance that may affect replication | [Database Observability Dashboard](/dashboard/project/_/observability/database) | | Review replication metrics | Use `pg_stat_subscription`, `pg_replication_slots`, and other Postgres views to diagnose replication issues | [manual replication monitoring guide](/docs/guides/database/replication/manual-replication-monitoring) | -| Debug database issues | Use CLI inspection tools to identify bloat, lock contention, and long-running queries affecting replication | [Database Inspection Tools Guide](/docs/guides/database/inspect) | +| Debug database issues | Use CLI inspection tools to identify bloat, lock contention, and long-running queries affecting replication | [Inspect the database](/docs/guides/observability/inspect) | | Optimize performance | Optimize query performance and connection management to reduce database load | [Performance Tuning Guide](/docs/guides/platform/performance) | | Configure timeouts | Configure statement timeouts to prevent long-running transactions from blocking replication | [Database Timeouts Guide](/docs/guides/database/postgres/timeouts) | | Learn broadcast from DB | Understand how broadcast from database works and best practices for implementation | [Broadcast from Database Guide](/docs/guides/realtime/broadcast#trigger-broadcast-messages-from-your-database) | diff --git a/apps/docs/content/guides/security/platform-audit-logs.mdx b/apps/docs/content/guides/security/platform-audit-logs.mdx index 47344d0169693..47f6554e97751 100644 --- a/apps/docs/content/guides/security/platform-audit-logs.mdx +++ b/apps/docs/content/guides/security/platform-audit-logs.mdx @@ -46,7 +46,7 @@ Each Supabase user account also has access to [Account Audit logs](/dashboard/ac ## Accessing Audit Log Drains -Audit Log Drains can be configured under your [organization's audit log drains](/dashboard/org/_/audit-log-drains). For setup instructions and supported destinations, see the [Log Drains guide](/docs/guides/monitoring-and-debugging/log-drains). +Audit Log Drains can be configured under your [organization's audit log drains](/dashboard/org/_/audit-log-drains). For setup instructions and supported destinations, see the [Log Drains guide](/docs/guides/observability/log-drains). ## Limitations diff --git a/apps/docs/content/guides/security/platform-security.mdx b/apps/docs/content/guides/security/platform-security.mdx index e6ed64b34c023..f25f5e71220be 100644 --- a/apps/docs/content/guides/security/platform-security.mdx +++ b/apps/docs/content/guides/security/platform-security.mdx @@ -25,7 +25,7 @@ For configuration information, see [Enforce MFA on Organization](/docs/guides/pl ### SSO for organizations -Supabase offers single sign-on (SSO) as a login option to provide additional account security for your team. This allows company administrators to enforce the use of an identity provider when logging into Supabase. +Supabase offers single sign-on (SSO) as a sign-in option to provide additional account security for your team. This allows company administrators to enforce the use of an identity provider when signing in to Supabase. For configuration information, see [Enable SSO for Your Organization](/docs/guides/platform/sso). diff --git a/apps/docs/content/guides/self-hosting/docker.mdx b/apps/docs/content/guides/self-hosting/docker.mdx index 6b17aced1e484..ca849c63247ea 100644 --- a/apps/docs/content/guides/self-hosting/docker.mdx +++ b/apps/docs/content/guides/self-hosting/docker.mdx @@ -534,11 +534,11 @@ JWT_SECRET=${JWT_SECRET} ### Configuring social login (OAuth) providers -See the [Configure Social Login (OAuth) Providers](/docs/guides/self-hosting/self-hosted-oauth) guide for setup instructions. +See the [Configure social login (OAuth) Providers](/docs/guides/self-hosting/self-hosted-oauth) guide for setup instructions. -### Configuring phone login, SMS, and MFA +### Configuring phone sign-in, SMS, and MFA -See the [Configure Phone Login & MFA](/docs/guides/self-hosting/self-hosted-phone-mfa) guide for SMS provider setup, OTP settings, and multi-factor authentication configuration. +See the [Configure Phone sign-in & MFA](/docs/guides/self-hosting/self-hosted-phone-mfa) guide for SMS provider setup, OTP settings, and multi-factor authentication configuration. ### Configuring an email server diff --git a/apps/docs/content/guides/self-hosting/self-hosted-oauth.mdx b/apps/docs/content/guides/self-hosting/self-hosted-oauth.mdx index 331c94c5f1339..66e4872deb9c6 100644 --- a/apps/docs/content/guides/self-hosting/self-hosted-oauth.mdx +++ b/apps/docs/content/guides/self-hosting/self-hosted-oauth.mdx @@ -1,5 +1,5 @@ --- -title: 'Configure Social Login (OAuth) Providers' +title: 'Configure social login (OAuth) providers' description: 'Set up social login (OAuth/OIDC) providers for self-hosted Supabase with Docker.' subtitle: 'Set up social login (OAuth/OIDC) providers for self-hosted Supabase with Docker.' --- @@ -286,7 +286,7 @@ auth: -`KEYCLOAK_URL` is **required**. It must be the full realm URL (e.g., `https://keycloak.example.com/realms/myrealm`). The Auth service uses this to discover the OIDC endpoints (`.well-known/openid-configuration`). Without it, Keycloak login will not work. +`KEYCLOAK_URL` is **required**. It must be the full realm URL (e.g., `https://keycloak.example.com/realms/myrealm`). The Auth service uses this to discover the OIDC endpoints (`.well-known/openid-configuration`). Without it, Keycloak sign-in will not work. @@ -298,28 +298,28 @@ auth: Supabase Auth supports the following OAuth providers: -| Provider | Env prefix | Additional variables | Docs | -| ----------------- | ---------------- | ------------------------------- | --------------------------------------------------------------------- | -| Apple | `APPLE_` | - | [Login with Apple](/docs/guides/auth/social-login/auth-apple) | -| Azure (Microsoft) | `AZURE_` | `URL` (tenant URL) | [Login with Azure](/docs/guides/auth/social-login/auth-azure) | -| Bitbucket | `BITBUCKET_` | - | [Login with Bitbucket](/docs/guides/auth/social-login/auth-bitbucket) | -| Discord | `DISCORD_` | - | [Login with Discord](/docs/guides/auth/social-login/auth-discord) | -| Facebook | `FACEBOOK_` | - | [Login with Facebook](/docs/guides/auth/social-login/auth-facebook) | -| Figma | `FIGMA_` | - | [Login with Figma](/docs/guides/auth/social-login/auth-figma) | -| GitHub | `GITHUB_` | `URL` (for GitHub Enterprise) | [Login with GitHub](/docs/guides/auth/social-login/auth-github) | -| GitLab | `GITLAB_` | `URL` (for self-hosted GitLab) | [Login with GitLab](/docs/guides/auth/social-login/auth-gitlab) | -| Google | `GOOGLE_` | - | [Login with Google](/docs/guides/auth/social-login/auth-google) | -| Kakao | `KAKAO_` | - | [Login with Kakao](/docs/guides/auth/social-login/auth-kakao) | -| Keycloak (OIDC) | `KEYCLOAK_` | `URL` (realm URL, **required**) | [Login with Keycloak](/docs/guides/auth/social-login/auth-keycloak) | -| LinkedIn (OIDC) | `LINKEDIN_OIDC_` | - | [Login with LinkedIn](/docs/guides/auth/social-login/auth-linkedin) | -| Notion | `NOTION_` | - | [Login with Notion](/docs/guides/auth/social-login/auth-notion) | -| Slack (OIDC) | `SLACK_OIDC_` | - | [Login with Slack](/docs/guides/auth/social-login/auth-slack) | -| Snapchat | `SNAPCHAT_` | - | - | -| Spotify | `SPOTIFY_` | - | [Login with Spotify](/docs/guides/auth/social-login/auth-spotify) | -| Twitch | `TWITCH_` | - | [Login with Twitch](/docs/guides/auth/social-login/auth-twitch) | -| Twitter | `TWITTER_` | - | [Login with Twitter](/docs/guides/auth/social-login/auth-twitter) | -| WorkOS | `WORKOS_` | - | [Login with WorkOS](/docs/guides/auth/social-login/auth-workos) | -| Zoom | `ZOOM_` | - | [Login with Zoom](/docs/guides/auth/social-login/auth-zoom) | +| Provider | Env prefix | Additional variables | Docs | +| ----------------- | ---------------- | ------------------------------- | ----------------------------------------------------------------------- | +| Apple | `APPLE_` | - | [Sign in with Apple](/docs/guides/auth/social-login/auth-apple) | +| Azure (Microsoft) | `AZURE_` | `URL` (tenant URL) | [Sign in with Azure](/docs/guides/auth/social-login/auth-azure) | +| Bitbucket | `BITBUCKET_` | - | [Sign in with Bitbucket](/docs/guides/auth/social-login/auth-bitbucket) | +| Discord | `DISCORD_` | - | [Sign in with Discord](/docs/guides/auth/social-login/auth-discord) | +| Facebook | `FACEBOOK_` | - | [Sign in with Facebook](/docs/guides/auth/social-login/auth-facebook) | +| Figma | `FIGMA_` | - | [Sign in with Figma](/docs/guides/auth/social-login/auth-figma) | +| GitHub | `GITHUB_` | `URL` (for GitHub Enterprise) | [Sign in with GitHub](/docs/guides/auth/social-login/auth-github) | +| GitLab | `GITLAB_` | `URL` (for self-hosted GitLab) | [Sign in with GitLab](/docs/guides/auth/social-login/auth-gitlab) | +| Google | `GOOGLE_` | - | [Sign in with Google](/docs/guides/auth/social-login/auth-google) | +| Kakao | `KAKAO_` | - | [Sign in with Kakao](/docs/guides/auth/social-login/auth-kakao) | +| Keycloak (OIDC) | `KEYCLOAK_` | `URL` (realm URL, **required**) | [Sign in with Keycloak](/docs/guides/auth/social-login/auth-keycloak) | +| LinkedIn (OIDC) | `LINKEDIN_OIDC_` | - | [Sign in with LinkedIn](/docs/guides/auth/social-login/auth-linkedin) | +| Notion | `NOTION_` | - | [Sign in with Notion](/docs/guides/auth/social-login/auth-notion) | +| Slack (OIDC) | `SLACK_OIDC_` | - | [Sign in with Slack](/docs/guides/auth/social-login/auth-slack) | +| Snapchat | `SNAPCHAT_` | - | - | +| Spotify | `SPOTIFY_` | - | [Sign in with Spotify](/docs/guides/auth/social-login/auth-spotify) | +| Twitch | `TWITCH_` | - | [Sign in with Twitch](/docs/guides/auth/social-login/auth-twitch) | +| Twitter | `TWITTER_` | - | [Sign in with Twitter](/docs/guides/auth/social-login/auth-twitter) | +| WorkOS | `WORKOS_` | - | [Sign in with WorkOS](/docs/guides/auth/social-login/auth-workos) | +| Zoom | `ZOOM_` | - | [Sign in with Zoom](/docs/guides/auth/social-login/auth-zoom) | For each provider, you need at minimum `ENABLED`, `CLIENT_ID`, `SECRET`, and `REDIRECT_URI` in `.env` and `docker-compose.yml`. @@ -329,7 +329,7 @@ For each provider, you need at minimum `ENABLED`, `CLIENT_ID`, `SECRET`, and `RE -## Test the login flow +## Test the sign-in flow You can test OAuth with the following minimal HTML page: @@ -378,7 +378,7 @@ You can test OAuth with the following minimal HTML page: ``` -For detailed client-side integration, see [Social Login](/docs/guides/auth/social-login). +For detailed client-side integration, see [social login](/docs/guides/auth/social-login). ## Troubleshooting @@ -400,9 +400,9 @@ auth: Run `sh run.sh printenv auth | grep GOTRUE_EXTERNAL` to verify the variables are reaching the container. -### Site URL or redirect URL errors after login +### Site URL or redirect URL errors after sign-in -After a successful OAuth login, the Auth service redirects to `SITE_URL` or a URL from `ADDITIONAL_REDIRECT_URLS`. Ensure: +After a successful OAuth sign-in, the Auth service redirects to `SITE_URL` or a URL from `ADDITIONAL_REDIRECT_URLS`. Ensure: - `SITE_URL` in `.env` is set to your **application's URL** - If your app uses a different redirect URL, add it to `ADDITIONAL_REDIRECT_URLS` (comma-separated) diff --git a/apps/docs/content/guides/self-hosting/self-hosted-phone-mfa.mdx b/apps/docs/content/guides/self-hosting/self-hosted-phone-mfa.mdx index 99eaa048419c6..071b14df568a5 100644 --- a/apps/docs/content/guides/self-hosting/self-hosted-phone-mfa.mdx +++ b/apps/docs/content/guides/self-hosting/self-hosted-phone-mfa.mdx @@ -1,12 +1,12 @@ --- -title: 'Configure Phone Login & MFA' -description: 'Set up phone login SMS providers, OTP settings, and multi-factor authentication for self-hosted Supabase with Docker.' -subtitle: 'Set up phone login SMS providers, OTP settings, and multi-factor authentication for self-hosted Supabase with Docker.' +title: 'Configure Phone sign-in & MFA' +description: 'Set up phone sign-in SMS providers, OTP settings, and multi-factor authentication for self-hosted Supabase with Docker.' +subtitle: 'Set up phone sign-in SMS providers, OTP settings, and multi-factor authentication for self-hosted Supabase with Docker.' --- -This guide covers the **server-side configuration** for phone login and multi-factor authentication (MFA) on a self-hosted Supabase instance running with Docker Compose. +This guide covers the **server-side configuration** for phone sign-in and multi-factor authentication (MFA) on a self-hosted Supabase instance running with Docker Compose. -For client-side implementation, see [Phone Login](/docs/guides/auth/phone-login) and [Multi-Factor Authentication](/docs/guides/auth/auth-mfa). +For client-side implementation, see [Phone sign-in](/docs/guides/auth/phone-login) and [Multi-Factor Authentication](/docs/guides/auth/auth-mfa). ## Before you begin @@ -153,7 +153,7 @@ MFA_TOTP_VERIFY_ENABLED=false ### Phone MFA -Phone MFA is **disabled by default** (opt-in). It uses the same SMS provider configuration as phone login. +Phone MFA is **disabled by default** (opt-in). It uses the same SMS provider configuration as phone sign-in. To enable: diff --git a/apps/docs/content/guides/self-hosting/self-hosted-saml-sso.mdx b/apps/docs/content/guides/self-hosting/self-hosted-saml-sso.mdx index e0514267ef99d..15054f368e0c1 100644 --- a/apps/docs/content/guides/self-hosting/self-hosted-saml-sso.mdx +++ b/apps/docs/content/guides/self-hosting/self-hosted-saml-sso.mdx @@ -32,7 +32,7 @@ SAML SSO is configured in two layers: 1. **Global SAML enable (environment variables)** - a small set of env vars that enable the SAML engine and provide a signing key. These go in `.env` and `docker-compose.yml`. 2. **Per-IdP configuration (admin API)** - individual Identity Providers are registered, updated, and deleted at runtime via the Auth admin API. No restart is needed when adding or removing providers. -The login flow works as follows: +The sign-in flow works as follows: 1. Your app calls `POST /auth/v1/sso` with a domain or provider_id 2. Auth generates a SAML `AuthnRequest` and returns a redirect URL to the IdP @@ -506,15 +506,15 @@ Both return `{ "url": "https://idp.example.com/sso?SAMLRequest=..." }`. ### Domain-based vs provider-based lookup -| Method | Use case | -| ------------ | --------------------------------------------------------------------------------------------------------------------------------------- | -| `domain` | Extract the domain from the user's email and let Auth find the right IdP. Best for login forms where the user enters their email first. | -| `providerId` | Use when you know the exact provider - for example, a dedicated "Sign in with Okta" button. | +| Method | Use case | +| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | +| `domain` | Extract the domain from the user's email and let Auth find the right IdP. Best for sign-in forms where the user enters their email first. | +| `providerId` | Use when you know the exact provider - for example, a dedicated "Sign in with Okta" button. | -## Test the login flow +## Test the sign-in flow -1. Open your application and trigger SSO login (or use the curl command above) -2. You should be redirected to your IdP's login page +1. Open your application and trigger SSO sign-in (or use the curl command above) +2. You should be redirected to your IdP's sign-in page 3. After authenticating, the IdP posts back to the ACS endpoint 4. Auth processes the assertion and redirects you back to your `SITE_URL` (or `redirect_to` URL) with session tokens diff --git a/apps/docs/content/guides/storage/cdn/metrics.mdx b/apps/docs/content/guides/storage/cdn/metrics.mdx index 139010a6214c9..30156f9351726 100644 --- a/apps/docs/content/guides/storage/cdn/metrics.mdx +++ b/apps/docs/content/guides/storage/cdn/metrics.mdx @@ -5,7 +5,7 @@ description: 'Learn how Supabase Storage caches objects with a CDN.' sidebar_label: 'CDN' --- -Cache hits can be determined via the `log_attributes['response.headers.cf_cache_status']` key in the [logs](/docs/guides/monitoring-and-debugging/logs). Any value that corresponds to either `HIT`, `STALE`, `REVALIDATED`, or `UPDATING` is categorized as a cache hit. +Cache hits can be determined via the `log_attributes['response.headers.cf_cache_status']` key in [Query and filter logs](/docs/guides/observability/advanced-log-filtering#logs-explorer). Any value that corresponds to either `HIT`, `STALE`, `REVALIDATED`, or `UPDATING` is categorized as a cache hit. The following example query will show the top cache misses from the `edge_logs`: ```sql diff --git a/apps/docs/content/guides/storage/debugging/logs.mdx b/apps/docs/content/guides/storage/debugging/logs.mdx index 6586e3828fb1b..2d188d8ed9f62 100644 --- a/apps/docs/content/guides/storage/debugging/logs.mdx +++ b/apps/docs/content/guides/storage/debugging/logs.mdx @@ -11,7 +11,7 @@ For more advanced filtering needs, use the [SQL Editor](/dashboard/project/_/sql -For more details on filtering the log tables, see [Advanced Log Filtering](/docs/guides/monitoring-and-debugging/advanced-log-filtering) +For more details on filtering the log tables, see [Query and filter logs](/docs/guides/observability/advanced-log-filtering) diff --git a/apps/docs/content/guides/storage/management/copy-move-objects.mdx b/apps/docs/content/guides/storage/management/copy-move-objects.mdx index 844bdbf6d5293..1725badee7ee3 100644 --- a/apps/docs/content/guides/storage/management/copy-move-objects.mdx +++ b/apps/docs/content/guides/storage/management/copy-move-objects.mdx @@ -18,6 +18,7 @@ To copy an object within the same bucket, use the `copy` method. ```javascript import { createClient } from '@supabase/supabase-js' + const supabase = createClient('your_project_url', 'your_supabase_api_key') // ---cut--- @@ -30,6 +31,7 @@ To copy an object across buckets, use the `copy` method and specify the destinat ```javascript import { createClient } from '@supabase/supabase-js' + const supabase = createClient('your_project_url', 'your_supabase_api_key') // ---cut--- @@ -50,6 +52,7 @@ To move an object within the same bucket, you can use the `move` method. ```javascript import { createClient } from '@supabase/supabase-js' + const supabase = createClient('your_project_url', 'your_supabase_api_key') // ---cut--- @@ -64,6 +67,7 @@ To move an object across buckets, use the `move` method and specify the destinat ```javascript import { createClient } from '@supabase/supabase-js' + const supabase = createClient('your_project_url', 'your_supabase_api_key') // ---cut--- diff --git a/apps/docs/content/guides/storage/management/delete-objects.mdx b/apps/docs/content/guides/storage/management/delete-objects.mdx index f3719ab5785d3..03c102d3628e3 100644 --- a/apps/docs/content/guides/storage/management/delete-objects.mdx +++ b/apps/docs/content/guides/storage/management/delete-objects.mdx @@ -20,6 +20,7 @@ To delete one or more objects, use the `remove` method. ```javascript import { createClient } from '@supabase/supabase-js' + const supabase = createClient('your_project_url', 'your_supabase_api_key') // ---cut--- diff --git a/apps/docs/content/guides/storage/serving/downloads.mdx b/apps/docs/content/guides/storage/serving/downloads.mdx index fe267d3711134..23235fb6c1f6f 100644 --- a/apps/docs/content/guides/storage/serving/downloads.mdx +++ b/apps/docs/content/guides/storage/serving/downloads.mdx @@ -21,6 +21,7 @@ You can also use the Supabase SDK `getPublicUrl` to generate this URL for you ```js import { createClient } from '@supabase/supabase-js' + const supabase = createClient('your_project_url', 'your_supabase_api_key') // ---cut--- @@ -50,6 +51,7 @@ When using the SDK's `download()` method, you can pass additional query paramete ```js import { createClient } from '@supabase/supabase-js' + const supabase = createClient('your_project_url', 'your_supabase_api_key') // ---cut--- @@ -130,6 +132,7 @@ You can sign a time-limited URL that you can share to your users by invoking the ```js import { createClient } from '@supabase/supabase-js' + const supabase = createClient('your_project_url', 'your_supabase_api_key') // ---cut--- diff --git a/apps/docs/content/troubleshooting/discovering-and-interpreting-api-errors-in-the-logs-7xREI9.mdx b/apps/docs/content/troubleshooting/discovering-and-interpreting-api-errors-in-the-logs-7xREI9.mdx index d45b79326c0d6..a355e06527821 100644 --- a/apps/docs/content/troubleshooting/discovering-and-interpreting-api-errors-in-the-logs-7xREI9.mdx +++ b/apps/docs/content/troubleshooting/discovering-and-interpreting-api-errors-in-the-logs-7xREI9.mdx @@ -39,7 +39,7 @@ limit 100; The most useful fields for debugging are: -> NOTE: not every field is included below. For a full list, check the API Edge [field reference](/docs/guides/monitoring-and-debugging/logs#logs-field-reference) +> NOTE: not every field is included below. For a full list, check the API Gateway and Function Edge [logs field reference](/docs/guides/observability/log-field-reference). ### Request object @@ -98,21 +98,18 @@ limit 100; **Suggested use cases:** - identify problematic queries -- identify unusual behavior by authenticated users -| Column | Description | Sample value | -| -------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | -| request.method | Request Method (PATCH, GET, PUT...) | GET | -| request.url | Request URL, which contains the PostgREST formatted query | https://yuhplfrsdxxxtldakizi.supabase.co/rest/v1/users?select=username&id=eq.63b6190e-214f-4b8a-b72d-3af6e1921411&limit=1 | -| request.sb.jwt.authorization.payload.subject | authenticated user's ID | 63b6190e-214f-4b8a-b72d-3af6e1921411 | +| Column | Description | Sample value | +| -------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | +| request.method | Request Method (PATCH, GET, PUT...) | GET | +| request.url | Request URL, which contains the PostgREST formatted query | https://yuhplfrsdxxxtldakizi.supabase.co/rest/v1/users?select=username&id=eq.63b6190e-214f-4b8a-b72d-3af6e1921411&limit=1 | **Unnesting example:** ```sql select log_attributes['request.method'] as method, - log_attributes['request.url'] as url, - log_attributes['request.sb.jwt.authorization.payload.subject'] as auth_user + log_attributes['request.url'] as url from logs where source = 'edge_logs' limit 100; @@ -291,21 +288,3 @@ group by ip order by ip_count desc limit 100; ``` - -**Search frequented query paths by authenticated user:** - -```sql -select - -- only available for front-end clients - log_attributes['request.sb.jwt.authorization.payload.subject'] as auth_user, - log_attributes['request.path'] as path, - count() as request_count -from logs -where - source = 'edge_logs' - -- only look at DB API - and match(log_attributes['request.path'], '^/rest/v1/') -group by auth_user, path -order by request_count desc -limit 100; -``` diff --git a/apps/docs/content/troubleshooting/exhaust-disk-io.mdx b/apps/docs/content/troubleshooting/exhaust-disk-io.mdx index 0df86d3eaace3..5d7b5451eb216 100644 --- a/apps/docs/content/troubleshooting/exhaust-disk-io.mdx +++ b/apps/docs/content/troubleshooting/exhaust-disk-io.mdx @@ -25,7 +25,7 @@ Running out of Disk IO Budget means that your instance is using more disk than i To check your Disk IO Budget on the Supabase Platform, head over to [Database Health in the Observability section](/dashboard/project/_/observability/database). -It is also possible to monitor your resources and set up alerts using Prometheus/Grafana. With Grafana you will be able to pinpoint potential causes and see more fine-grained metrics like how much of your RAM is used for caching and your Swap usage. Read the [Metrics Guide](/docs/guides/monitoring-and-debugging/metrics) to learn more. +It is also possible to monitor your resources and set up alerts using Prometheus/Grafana. With Grafana you will be able to pinpoint potential causes and see more fine-grained metrics like how much of your RAM is used for caching and your Swap usage. Read the [Metrics Guide](/docs/guides/observability/metrics) to learn more. ## Common reasons for high disk IO usage diff --git a/apps/docs/content/troubleshooting/exhaust-ram.mdx b/apps/docs/content/troubleshooting/exhaust-ram.mdx index 30351258315a4..51128f0f31ebf 100644 --- a/apps/docs/content/troubleshooting/exhaust-ram.mdx +++ b/apps/docs/content/troubleshooting/exhaust-ram.mdx @@ -31,7 +31,7 @@ High RAM usage could come with a range of issues: To check your RAM usage on the Supabase Platform, head over to [Database Health in the Observability section](/dashboard/project/_/observability/database). -It is also possible to monitor your resources and set up alerts using Prometheus/Grafana. With Grafana you will be able to see how much of your RAM is used for caching and you can track other metrics such as your Swap usage. Read the [Metrics Guide](/docs/guides/monitoring-and-debugging/metrics) to learn more. +It is also possible to monitor your resources and set up alerts using Prometheus/Grafana. With Grafana you will be able to see how much of your RAM is used for caching and you can track other metrics such as your Swap usage. Read the [Metrics Guide](/docs/guides/observability/metrics) to learn more. ## Common reasons for high RAM usage diff --git a/apps/docs/content/troubleshooting/exhaust-swap.mdx b/apps/docs/content/troubleshooting/exhaust-swap.mdx index 5f8b5c60f201d..db0ea394ee2ca 100644 --- a/apps/docs/content/troubleshooting/exhaust-swap.mdx +++ b/apps/docs/content/troubleshooting/exhaust-swap.mdx @@ -33,7 +33,7 @@ High Swap usage can affect your database performance. For example, you might see ## Monitor your swap -You can monitor your resources and set up alerts using Prometheus/Grafana. See the [metrics guide](/docs/guides/monitoring-and-debugging/metrics) for more information. +You can monitor your resources and set up alerts using Prometheus/Grafana. See the [metrics guide](/docs/guides/observability/metrics) for more information. An [example repository](https://github.com/supabase/supabase-grafana) to ingest metrics and visualize them with Grafana is provided in the linked guide, where we maintain a [list of the exported metrics](https://github.com/supabase/supabase-grafana/blob/main/docs/metrics.md). diff --git a/apps/docs/content/troubleshooting/failed-to-retrieve-tables.mdx b/apps/docs/content/troubleshooting/failed-to-retrieve-tables.mdx index acda37f4d4cc1..6bd2d9327a143 100644 --- a/apps/docs/content/troubleshooting/failed-to-retrieve-tables.mdx +++ b/apps/docs/content/troubleshooting/failed-to-retrieve-tables.mdx @@ -43,4 +43,4 @@ Once you are confident there will not be a crash loop, you can review the follow - Continue to monitor your project's [query performance tab](/dashboard/project/_/observability/query-performance) and [enable index advisor](/docs/guides/database/extensions/index_advisor) if you haven't already - especially if there are a lot of select queries. - If after monitoring your changes you still do not notice improvements, consider upgrading compute if you think this level of activity is going to be regular. It will give you more memory overhead to process tasks like this. You can view all compute offerings [here](/dashboard/project/_/settings/infrastructure). -If you want to effectively monitor your project's performance minute by minute, you can use the [Metrics API](/docs/guides/monitoring-and-debugging/metrics). +If you want to effectively monitor your project's performance minute by minute, you can use the [Metrics API](/docs/guides/observability/metrics). diff --git a/apps/docs/content/troubleshooting/failed-to-run-sql-query-connection-terminated-due-to-connection-timeout.mdx b/apps/docs/content/troubleshooting/failed-to-run-sql-query-connection-terminated-due-to-connection-timeout.mdx index 351692dc37c45..e10774c29ec1c 100644 --- a/apps/docs/content/troubleshooting/failed-to-run-sql-query-connection-terminated-due-to-connection-timeout.mdx +++ b/apps/docs/content/troubleshooting/failed-to-run-sql-query-connection-terminated-due-to-connection-timeout.mdx @@ -23,4 +23,4 @@ Review the appropriate guides based on your scenario: - [High Disk I/O](/docs/guides/troubleshooting/exhaust-disk-io) - [Query optimization](/docs/guides/database/query-optimization) -You can also set up alerts using a [Prometheus endpoint / Grafana charts](/docs/guides/monitoring-and-debugging/metrics) to monitor vital resources. +You can also set up alerts using a [Prometheus endpoint / Grafana charts](/docs/guides/observability/metrics) to monitor vital resources. diff --git a/apps/docs/content/troubleshooting/grafana-not-displaying-data-sXJrMj.mdx b/apps/docs/content/troubleshooting/grafana-not-displaying-data-sXJrMj.mdx index c13e0e40dd27d..34616aeec8347 100644 --- a/apps/docs/content/troubleshooting/grafana-not-displaying-data-sXJrMj.mdx +++ b/apps/docs/content/troubleshooting/grafana-not-displaying-data-sXJrMj.mdx @@ -7,7 +7,7 @@ keywords = [ "grafana", "docker", "metrics", "configuration" ] database_id = "76a4099e-450f-4b5b-a539-224760348c18" --- -This guide is for identifying configuration mistakes in [self-hosted Supabase Grafana installations](/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted) +This guide is for identifying configuration mistakes in [self-hosted Supabase Grafana installations](/docs/guides/observability/metrics/grafana-self-hosted) ## Step 1: Ping your Grafana endpoint diff --git a/apps/docs/content/troubleshooting/high-cpu-usage.mdx b/apps/docs/content/troubleshooting/high-cpu-usage.mdx index eedcf49ba233a..dcf18aa429016 100644 --- a/apps/docs/content/troubleshooting/high-cpu-usage.mdx +++ b/apps/docs/content/troubleshooting/high-cpu-usage.mdx @@ -25,7 +25,7 @@ You can check your CPU usage directly on the Supabase Platform. For this go to d ![CPU usage reported on Supabase dashboard](/docs/img/guides/platform/exhaust-cpu-report.png) -It is also possible to monitor your resources and set up alerts using Prometheus/Grafana. You can find a guide for this [here](/docs/guides/monitoring-and-debugging/metrics). +It is also possible to monitor your resources and set up alerts using Prometheus/Grafana. You can find a guide for this [here](/docs/guides/observability/metrics). ## Common reasons for high CPU usage diff --git a/apps/docs/content/troubleshooting/how-to-interpret-and-explore-the-postgres-logs-OuCIOj.mdx b/apps/docs/content/troubleshooting/how-to-interpret-and-explore-the-postgres-logs-OuCIOj.mdx index f2045b422d32c..d588c5a938f31 100644 --- a/apps/docs/content/troubleshooting/how-to-interpret-and-explore-the-postgres-logs-OuCIOj.mdx +++ b/apps/docs/content/troubleshooting/how-to-interpret-and-explore-the-postgres-logs-OuCIOj.mdx @@ -391,5 +391,5 @@ To see the default types of events that are logged, you can check this [guide](h - [Debugging with the DB API logs](https://github.com/orgs/supabase/discussions/22849) - [Debugging Database Functions](/docs/guides/database/functions#debugging-functions) - [pg_audit](/docs/guides/database/extensions/pgaudit) -- [Supabase Logging](/docs/guides/monitoring-and-debugging/logs) +- [Supabase Logging](/docs/guides/observability/logs) - [Self-Hosting Logs](/docs/reference/self-hosting-analytics/introduction) diff --git a/apps/docs/content/troubleshooting/how-to-view-database-metrics-uqf2z_.mdx b/apps/docs/content/troubleshooting/how-to-view-database-metrics-uqf2z_.mdx index ee301203a7d81..3587783f45dd2 100644 --- a/apps/docs/content/troubleshooting/how-to-view-database-metrics-uqf2z_.mdx +++ b/apps/docs/content/troubleshooting/how-to-view-database-metrics-uqf2z_.mdx @@ -7,6 +7,6 @@ keywords = [ "metrics", "grafana", "monitoring" ] database_id = "da2d95e5-abc5-47c8-8389-1554d12abf91" --- -To monitor real-time metrics of your database, like CPU, EBS, active database connections, and memory usage, you can deploy a Grafana Dashboard. Check our [GitHub repo](https://github.com/supabase/supabase-grafana) for setup instructions for local or free [Fly.io](http://fly.io/) deployments. Refer to our concise [documentation](/docs/guides/monitoring-and-debugging/metrics) to learn more about the metrics endpoint. +To monitor real-time metrics of your database, like CPU, EBS, active database connections, and memory usage, you can deploy a Grafana Dashboard. Check our [GitHub repo](https://github.com/supabase/supabase-grafana) for setup instructions for local or free [Fly.io](http://fly.io/) deployments. Refer to our concise [documentation](/docs/guides/observability/metrics) to learn more about the metrics endpoint. While the [Dashboard's Reports Page](/dashboard/project/_/observability) displays some metric data, it provides hourly averages, not real-time by the second data. However, it offers query metrics, which the Grafana Dashboard does not include. diff --git a/apps/docs/content/troubleshooting/interpreting-supabase-grafana-cpu-charts-9JSlkC.mdx b/apps/docs/content/troubleshooting/interpreting-supabase-grafana-cpu-charts-9JSlkC.mdx index 5e86d52777e46..8d8506516f5e1 100644 --- a/apps/docs/content/troubleshooting/interpreting-supabase-grafana-cpu-charts-9JSlkC.mdx +++ b/apps/docs/content/troubleshooting/interpreting-supabase-grafana-cpu-charts-9JSlkC.mdx @@ -7,7 +7,7 @@ keywords = [ "cpu", "grafana", "metrics" ] database_id = "ef05da0a-f8bc-44a4-9719-5ae811dba104" --- -> [Guide](/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted) for setting up Supabase Grafana +> [Guide](/docs/guides/observability/metrics/grafana-self-hosted) for setting up Supabase Grafana ## CPU diff --git a/apps/docs/content/troubleshooting/interpreting-supabase-grafana-io-charts-MUynDR.mdx b/apps/docs/content/troubleshooting/interpreting-supabase-grafana-io-charts-MUynDR.mdx index 3b93646ebe2f2..bdca726ddb9fd 100644 --- a/apps/docs/content/troubleshooting/interpreting-supabase-grafana-io-charts-MUynDR.mdx +++ b/apps/docs/content/troubleshooting/interpreting-supabase-grafana-io-charts-MUynDR.mdx @@ -7,7 +7,7 @@ keywords = [ "io", "disk", "database", "grafana" ] database_id = "0056cd40-df04-4045-bbfb-c245cb15b85d" --- -> [Supabase Grafana Installation Guide](/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted) +> [Supabase Grafana Installation Guide](/docs/guides/observability/metrics/grafana-self-hosted) There are two primary values that matter for IO: diff --git a/apps/docs/content/troubleshooting/monitor-supavisor-postgres-connections.mdx b/apps/docs/content/troubleshooting/monitor-supavisor-postgres-connections.mdx index 6b1592a592ad7..86b51f56db867 100644 --- a/apps/docs/content/troubleshooting/monitor-supavisor-postgres-connections.mdx +++ b/apps/docs/content/troubleshooting/monitor-supavisor-postgres-connections.mdx @@ -19,7 +19,7 @@ _Visual of Grafana Dashboard_ It can be run locally within Docker. Alternatively, you can deploy it to fly.io or Grafana Cloud, which are better for long-term data collection. -Installation instructions can be found in it the [metrics docs ](/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted) +Installation instructions can be found in it the [metrics docs ](/docs/guides/observability/metrics/grafana-self-hosted) ## Observing connections diff --git a/apps/docs/content/troubleshooting/pgcron-debugging-guide-n1KTaz.mdx b/apps/docs/content/troubleshooting/pgcron-debugging-guide-n1KTaz.mdx index f2d72bb059c36..393f990ec764e 100644 --- a/apps/docs/content/troubleshooting/pgcron-debugging-guide-n1KTaz.mdx +++ b/apps/docs/content/troubleshooting/pgcron-debugging-guide-n1KTaz.mdx @@ -114,7 +114,7 @@ You can view your concurrent peak connection usage throughout the day at the bot Unfortunately, excessive resource strain can slow down or disrupt jobs. -Go to the [reports page](/dashboard/project/_/observability/database) (or [Supabase Grafana](/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted) if you have it setup), and check for signs of resource exhaustion. If it's clear your database is under pressure, consider upgrading your compute add-on or following the advice from one of the optimization guides: +Go to the [reports page](/dashboard/project/_/observability/database) (or [Supabase Grafana](/docs/guides/observability/metrics/grafana-self-hosted) if you have it setup), and check for signs of resource exhaustion. If it's clear your database is under pressure, consider upgrading your compute add-on or following the advice from one of the optimization guides: - [Connections](https://github.com/orgs/supabase/discussions/27141) - [Disk/IO](https://github.com/orgs/supabase/discussions/27003) @@ -150,7 +150,7 @@ order by timestamp desc limit 100; ``` -If you're interested in modifying the query, there is an advanced [guide](https://github.com/orgs/supabase/discussions/26224) for navigating the Postgres logs and a general-purpose [one](/docs/guides/monitoring-and-debugging/advanced-log-filtering) for applying filters. +If you're interested in modifying the query, there is an advanced [guide](https://github.com/orgs/supabase/discussions/26224) for navigating the Postgres logs and a general-purpose [one](/docs/guides/observability/advanced-log-filtering) for applying filters.
    diff --git a/apps/docs/content/troubleshooting/steps-to-improve-query-performance-with-indexes-q8PoC9.mdx b/apps/docs/content/troubleshooting/steps-to-improve-query-performance-with-indexes-q8PoC9.mdx index 2abdb07268c5f..40648fdb38e3c 100644 --- a/apps/docs/content/troubleshooting/steps-to-improve-query-performance-with-indexes-q8PoC9.mdx +++ b/apps/docs/content/troubleshooting/steps-to-improve-query-performance-with-indexes-q8PoC9.mdx @@ -23,7 +23,7 @@ Supabase has an [open-source Grafana Repo](https://github.com/supabase/supabase- _Visual of Grafana Dashboard_ ![image](/docs/img/troubleshooting/18ed2c88-332e-4e66-b9b4-c37e99a39104.png) -It can be run locally within Docker or can be deployed for free to fly.io. Installation instructions can be found in [Supabase's metrics docs](/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted) +It can be run locally within Docker or can be deployed for free to fly.io. Installation instructions can be found in [Supabase's metrics docs](/docs/guides/observability/metrics/grafana-self-hosted) ### Query optimization through indexes diff --git a/apps/docs/content/troubleshooting/supabase-grafana-memory-charts.mdx b/apps/docs/content/troubleshooting/supabase-grafana-memory-charts.mdx index 3c636edfa58ee..a70cc475010f4 100644 --- a/apps/docs/content/troubleshooting/supabase-grafana-memory-charts.mdx +++ b/apps/docs/content/troubleshooting/supabase-grafana-memory-charts.mdx @@ -7,7 +7,7 @@ date_created = "2024-06-05" database_id = "179d70f3-1e26-4346-9ee8-d340fad382a3" --- -> [Supabase Grafana Installation Guide](/docs/guides/monitoring-and-debugging/metrics/grafana-self-hosted) +> [Supabase Grafana Installation Guide](/docs/guides/observability/metrics/grafana-self-hosted) Here are examples of unhealthy memory usage: ![image](https://github.com/supabase/supabase/assets/91111415/baebfc74-642d-4988-992c-bb0f473a05ad) @@ -22,7 +22,7 @@ The cache in Postgres is important because the database will store frequently ac Most data in a database is idle, but in cases where there is little available memory or uncached data is rapidly accessed, [thrashing]() can occur. -Ideally, you want queries to hit the cache 99% of the time. You can use the [Supabase CLI](/docs/guides/database/inspect) `inspect db cache hit` command to check your cache hit rate. Alternatively, you can run the [query](https://github.com/supabase/cli/blob/c9cce58025fded16b4c332747f819a44f45c3b83/internal/inspect/bloat/bloat.go#L17) found in the CLI's GitHub repo in the [SQL Editor](/dashboard/project/_/sql/) +Ideally, you want queries to hit the cache 99% of the time. You can use the [Supabase CLI](/docs/guides/monitoring-and-debugging/inspect) `inspect db cache hit` command to check your cache hit rate. Alternatively, you can run the [query](https://github.com/supabase/cli/blob/c9cce58025fded16b4c332747f819a44f45c3b83/internal/inspect/bloat/bloat.go#L17) found in the CLI's GitHub repo in the [SQL Editor](/dashboard/project/_/sql/) ```sh # login to the CLI diff --git a/apps/docs/content/troubleshooting/supavisor-faq-YyP5tI.mdx b/apps/docs/content/troubleshooting/supavisor-faq-YyP5tI.mdx index 96218a1a82e05..f2cef8f49c109 100644 --- a/apps/docs/content/troubleshooting/supavisor-faq-YyP5tI.mdx +++ b/apps/docs/content/troubleshooting/supavisor-faq-YyP5tI.mdx @@ -159,7 +159,7 @@ As a rule of thumb, if you're using the DB REST API or multiple app-based "user+ Connection usage can be monitored with a Supabase Grafana Dashboard. It provides realtime visibility of over 200 database metrics, such as graphs of CPU, EBS, and active direct/pooler connections. It can be extremely useful for monitoring and debugging instances. -You can check our [GitHub repo](https://github.com/supabase/supabase-grafana) for setup instructions for local deployments or free cloud deployments on [Fly.io](http://fly.io/). Refer to Supabase [documentation](/docs/guides/monitoring-and-debugging/metrics) to learn more about the metrics endpoint. +You can check our [GitHub repo](https://github.com/supabase/supabase-grafana) for setup instructions for local deployments or free cloud deployments on [Fly.io](http://fly.io/). Refer to Supabase [documentation](/docs/guides/observability/metrics) to learn more about the metrics endpoint. ## **Can Supavisor really support a million connections?** diff --git a/apps/docs/data/ai-prompts.data.ts b/apps/docs/data/ai-prompts.data.ts index 788b3acf364e5..66081d5bcb578 100644 --- a/apps/docs/data/ai-prompts.data.ts +++ b/apps/docs/data/ai-prompts.data.ts @@ -1,3 +1,5 @@ +import { setupCommand } from '~/components/HomePageCover.constants' + /** Embedded AI prompt bodies keyed by `AiPrompt` `id`. */ export const aiPrompts = { astrojs: `Help me add Supabase to my Astro project. Create a Supabase project at @@ -265,6 +267,199 @@ database.new and run the instruments table SQL. Then: REFERENCE https://supabase.com/docs/guides/getting-started/quickstarts/vue.md`, + 'monitoring-and-debugging': `Help me monitor and debug my Supabase project. Keep all access read-only. Do the following: +1. Install the Supabase CLI globally with \`${setupCommand.installCli}\`. +2. Install the Supabase Plugin with \`${setupCommand.installPlugin}\`. The plugin includes the Supabase MCP server. +3. Review my project and determine whether Supabase is already initialized. If it is not initialized, run \`${setupCommand.initialize}\`. +4. Read https://supabase.com/docs/guides/observability.md and follow it.`, + 'monitoring-agent-health': `You are "Health monitor", an on-call health agent for a Supabase project. +Reach the project only through Supabase MCP in read-only mode. + +Run once per hour. On each shift: +1. Call query_logs for the api and auth services. Keep events with + status_code >= 500 in the last hour. +2. Group errors by path and error_code. +3. For each group with more than 10 events, treat it as an incident: + collect up to 5 request IDs, state the likely cause in one sentence, + and link the most relevant troubleshooting guide. +4. If nothing crosses the threshold, stay silent. + +Do not change the project. Be terse. Lead with the suspected cause. + +REFERENCE +https://supabase.com/docs/guides/observability/detecting.md#health`, + 'monitoring-agent-security': `You are "Security monitor", a security review agent for a Supabase project. +Reach the project only through Supabase MCP in read-only mode. + +Run once per day. On each review: +1. Call get_advisors with type security. Report warning and error findings. +2. Call query_logs for auth and api authorization failures in the last 24 hours. + Group by status or error code, not by user, email, or IP address. +3. Report a spike only when the current count is at least twice the recent + baseline and at least 20 events. +4. Propose the least invasive fix. Do not change policies, grants, or keys. + +Do not change the project. If nothing needs review, stay silent. + +REFERENCE +https://supabase.com/docs/guides/observability/detecting.md#security`, + 'monitoring-agent-performance': `You are "Performance monitor", a Postgres performance agent for a Supabase project. +Reach the project only through Supabase MCP in read-only mode. + +Run once per hour. On each check: +1. Call get_advisors with type performance. +2. Call execute_sql to inspect pg_stat_activity for sessions active longer + than 30 seconds and any session waiting on a lock. +3. Identify blocking vs blocked PIDs. Recommend pg_cancel_backend or + pg_terminate_backend and explain the blast radius. Do not run either. +4. Report query regressions and missing-index findings with a verification plan. + +Do not change the project, create indexes, or cancel sessions. + +REFERENCE +https://supabase.com/docs/guides/observability/detecting.md#performance`, + 'monitoring-agent-usage': `You are "Capacity monitor", a capacity-planning agent for a Supabase project. +Reach the project only through Supabase MCP in read-only mode. + +Run once each morning. On each review: +1. Call execute_sql for database size, per-table sizes, and connection counts. +2. Compare today's numbers to the trailing 7-day trend. +3. Call get_advisors with type performance for unindexed foreign keys and + unused indexes that contribute to growth. +4. If query_logs is available, report API request growth and server-error rate + changes. Do not infer billing quotas from project API counts. +5. If any metric is projected to hit a limit within 14 days, flag the date + and the relevant scaling guide. + +Do not change billing, compute, or plan settings. + +REFERENCE +https://supabase.com/docs/guides/observability/detecting.md#usage`, + 'monitoring-agent-all': `You are "Generalist", a daily read-only agent for a Supabase project. + +TOOLS AVAILABLE +- query_logs: query ClickHouse logs (edge_logs, auth_logs, postgres_logs, + function_edge_logs, function_logs, storage_logs, realtime_logs, supavisor_logs) +- get_advisors: pull Splinter lint findings (security and performance categories) +- execute_sql: run read-only SQL against the live Postgres database +If you are running inside Claude Code with the Supabase plugin or skills installed, +those provide the same tools plus richer context from the local project. + +Reach the project only through Supabase MCP with read_only=true. +Run once per day. Work through all four checks in order. + +HEALTH +1. Call query_logs with this SQL to count errors across all log sources in 1-hour + buckets over the last 24 hours: + + SELECT toStartOfHour(timestamp) AS hour, + source, + count() AS events + FROM logs + WHERE timestamp >= now() - interval 24 hour + AND ( + (source = 'edge_logs' + AND toInt32OrZero(log_attributes['response.status_code']) >= 500) + OR (source = 'postgres_logs' + AND log_attributes['parsed.error_severity'] IN ('ERROR', 'FATAL')) + OR (source = 'auth_logs' + AND event_message ILIKE '%failed%') + ) + GROUP BY hour, source + ORDER BY hour DESC, events DESC + + Declare an incident for any source/hour bucket with more than 20 events. + For each incident, collect up to 5 example event_messages to identify the cause. + +SECURITY +2. Call get_advisors with type=security. Collect ALL findings (error, warn, info). + For each finding, include the documentation link from the MCP response if one + is provided. +3. Call query_logs for authorization and authentication failures in the last + 24 hours. Group by status code or error code, not by user, email, or IP. + Report a spike only when the count is at least twice the recent baseline + and at least 20 events. Do not change policies, grants, or keys. + +PERFORMANCE +4. Call get_advisors with type=performance. Collect ALL findings (error, warn, info). + For each finding, include the documentation link from the MCP response if one + is provided. +5. Call execute_sql to find long-running or blocking sessions: + SELECT pid, usename, state, now()-query_start AS duration, wait_event_type, + left(query,120) AS query FROM pg_stat_activity + WHERE state IN ('active','idle in transaction') + AND now()-query_start > interval '30 seconds' + AND pid <> pg_backend_pid() ORDER BY duration DESC LIMIT 10; +6. Call execute_sql for cache hit rate. Flag any table below 0.99: + SELECT relname, heap_blks_hit::float/(heap_blks_hit+heap_blks_read+1) AS hit_rate + FROM pg_statio_user_tables ORDER BY hit_rate ASC LIMIT 10; + +USAGE +7. Call execute_sql for database size, top 10 table sizes, and connection counts + by role. Compare to the 7-day trend if earlier results are in context. +8. Call query_logs to count edge_logs requests by path for the last 24 hours. + Compare to the prior 24-hour window if available. + Flag if growth looks likely to hit a limit within 14 days. + +OUTPUT FORMAT +Produce a markdown report. Group advisor findings by severity (error, warn, info). +Omit a section entirely if its checks found nothing to act on. +If all checks are clear, output only: "All clear." + +--- + +## Daily report + +### Health +**[source] — [hour]** · [N] errors +Cause: [one sentence from example event_messages] +Fix: +\`\`\`sql +-- investigation or remediation query +\`\`\` + +### Security +**[finding title]** · [severity] +Docs: [link from MCP response, if provided] +Fix: +\`\`\`sql +-- remediation SQL +\`\`\` + +**[status/error code] spike** · [N] events (baseline: [N]) +Fix: [one sentence — e.g. check this RLS policy, rotate this key] + +### Performance +**[advisor finding title]** · [severity] +Docs: [link from MCP response, if provided] +Fix: +\`\`\`sql +-- remediation SQL +\`\`\` + +**Session [pid]** · [duration] · [state] · role: [usename] +Query: \`[excerpt]\` +Fix — confirm it is safe to cancel, then run in SQL editor: +\`\`\`sql +SELECT pg_cancel_backend([pid]); +\`\`\` + +**Cache hit rate: [table]** · [hit_rate] +Fix: [one sentence — e.g. investigate sequential scans on this table] + +### Usage +**[metric]**: [current] · 7-day trend: [direction] +[If limit risk:] Projected to reach limit by [date]. +See: https://supabase.com/docs/guides/platform/compute-and-disk + +--- + +Do not suggest new features, schema changes unrelated to a detected issue, +or improvements beyond fixing what you found. Only report detected problems +and the specific SQL, CLI command, or Studio step to fix each one. + +REFERENCE +https://supabase.com/docs/guides/observability/automate-with-agents/all.md`, } as const export type AiPromptId = keyof typeof aiPrompts diff --git a/apps/docs/data/content-listings/index.ts b/apps/docs/data/content-listings/index.ts index cd9935a9e6baa..aca30691be863 100644 --- a/apps/docs/data/content-listings/index.ts +++ b/apps/docs/data/content-listings/index.ts @@ -27,7 +27,13 @@ import { selfHostingSupport, } from './self-hosting.data' import { storageExamples, storageGetStarted, storageResources } from './storage.data' -import { telemetryDebugging, telemetryMonitoring } from './telemetry.data' +import { + telemetryAccessWhat, + telemetryDetect, + telemetryDiagnose, + telemetryExport, + telemetryHireAgent, +} from './telemetry.data' const ALL_GROUPS: readonly ContentListingGroup[] = [ aiToolsSupportedAgents, @@ -61,8 +67,11 @@ const ALL_GROUPS: readonly ContentListingGroup[] = [ storageGetStarted, storageExamples, storageResources, - telemetryDebugging, - telemetryMonitoring, + telemetryAccessWhat, + telemetryDetect, + telemetryDiagnose, + telemetryHireAgent, + telemetryExport, ] export const CONTENT_LISTINGS: Readonly> = Object.fromEntries( diff --git a/apps/docs/data/content-listings/log-drains.data.ts b/apps/docs/data/content-listings/log-drains.data.ts index d8f4b9f7f0c68..6d337dc6ecabf 100644 --- a/apps/docs/data/content-listings/log-drains.data.ts +++ b/apps/docs/data/content-listings/log-drains.data.ts @@ -9,55 +9,55 @@ export const logDrainsDestinations: ContentListingGroup = { { title: 'Custom Endpoint', description: 'Forward logs as a POST request to any custom HTTP endpoint.', - href: '/guides/monitoring-and-debugging/log-drains#custom-endpoint', + href: '/guides/observability/log-drains#custom-endpoint', icon: { kind: 'braces', color: '#3ECF8E', bg: 'rgba(62,207,142,0.1)' }, }, { title: 'OpenTelemetry (OTLP)', description: 'Send logs to any OTLP-compatible endpoint using Protocol Buffers over HTTP.', - href: '/guides/monitoring-and-debugging/log-drains#opentelemetry-otlp', + href: '/guides/observability/log-drains#opentelemetry-otlp', icon: { kind: 'otlp', color: '#F5A623', bg: 'rgba(245,166,35,0.1)' }, }, { title: 'Datadog', description: 'Stream logs directly into Datadog for monitoring and analysis.', - href: '/guides/monitoring-and-debugging/log-drains#datadog', + href: '/guides/observability/log-drains#datadog', icon: { kind: 'datadog', color: '#632CA6', bg: 'rgba(99,44,166,0.1)' }, }, { title: 'Loki', description: 'Ingest logs into Grafana Loki using the HTTP push API.', - href: '/guides/monitoring-and-debugging/log-drains#loki', + href: '/guides/observability/log-drains#loki', icon: { kind: 'grafana', color: '#F05A28', bg: 'rgba(240,90,40,0.1)' }, }, { title: 'Amazon S3', description: 'Write batched log files directly to an S3 bucket you own.', - href: '/guides/monitoring-and-debugging/log-drains#amazon-s3', + href: '/guides/observability/log-drains#amazon-s3', icon: { kind: 'cloud', color: '#FF9900', bg: 'rgba(255,153,0,0.1)' }, }, { title: 'Sentry', description: "Send logs to Sentry's Logging product for filtering and grouping.", - href: '/guides/monitoring-and-debugging/log-drains#sentry', + href: '/guides/observability/log-drains#sentry', icon: { kind: 'sentry', color: '#362D59', bg: 'rgba(54,45,89,0.1)' }, }, { title: 'Axiom', description: 'Forward logs to an Axiom dataset for storage and analysis.', - href: '/guides/monitoring-and-debugging/log-drains#axiom', + href: '/guides/observability/log-drains#axiom', icon: { kind: 'axiom', color: '#6366F1', bg: 'rgba(99,102,241,0.1)' }, }, { title: 'Last9', description: 'Stream logs to Last9 for OpenTelemetry-native observability.', - href: '/guides/monitoring-and-debugging/log-drains#last9', + href: '/guides/observability/log-drains#last9', icon: { kind: 'last9', color: '#00B4A0', bg: 'rgba(0,180,160,0.1)' }, }, { title: 'Syslog', description: 'Forward logs to a remote Syslog receiver over TCP or TLS (RFC 5424).', - href: '/guides/monitoring-and-debugging/log-drains#syslog', + href: '/guides/observability/log-drains#syslog', icon: { kind: 'server', color: '#64748B', bg: 'rgba(100,116,139,0.1)' }, }, ], diff --git a/apps/docs/data/content-listings/telemetry.data.ts b/apps/docs/data/content-listings/telemetry.data.ts index da6d1024f2a73..b901c3ba4819e 100644 --- a/apps/docs/data/content-listings/telemetry.data.ts +++ b/apps/docs/data/content-listings/telemetry.data.ts @@ -1,75 +1,125 @@ +import { monitoringAgents } from '~/data/monitoring-agents.data' +import { getScheduleLabel } from '~/data/monitoring-agents.utils' import type { ContentListingGroup } from '~/lib/content-listings.schema' -export const telemetryDebugging: ContentListingGroup = { - id: 'telemetry-debugging', - heading: 'Debugging', +export const telemetryAccessWhat: ContentListingGroup = { + id: 'telemetry-access-what', type: 'grid', columns: 2, items: [ { - title: 'Debugging guide', - href: '/guides/monitoring-and-debugging/debugging', + title: 'Logs', + href: '/guides/observability/advanced-log-filtering', description: - 'Isolate the failing layer, read logs as evidence, and match symptoms to troubleshooting guides.', + 'Query ClickHouse logs from Studio, MCP, or the API. Filter events in the Logs UI.', }, { - title: 'Logging', - href: '/guides/monitoring-and-debugging/logs', - description: 'Query events from any Supabase service using the Logs Explorer.', + title: 'Metrics API', + href: '/guides/observability/metrics', + description: 'Scrape Prometheus-compatible database metrics, or chart a subset in Reports.', }, { - title: 'Advanced log filtering', - href: '/guides/monitoring-and-debugging/advanced-log-filtering', - description: 'Regex filtering, structured-field queries, and field discovery in ClickHouse.', + title: 'Database', + href: '/guides/observability/inspect', + description: 'Inspect live Postgres stats from the CLI, the SQL Editor, or MCP.', }, { - title: 'Troubleshooting index', - href: '/guides/troubleshooting', - description: 'Searchable index of known error codes, symptoms, and fixes.', + title: 'Advisors', + href: '/guides/observability/advisors', + description: 'Pull security and performance findings from Studio, MCP, the CLI, or the API.', }, { - title: 'Diagnosing stuck and blocked queries', - href: '/guides/database/connection-management#diagnosing-stuck-and-blocked-queries', - description: 'Find sessions blocked by a lock, and cancel or terminate the one responsible.', + title: 'Reports', + href: '/guides/observability/reports', + description: 'Studio dashboards for API, Auth, Storage, Realtime, and database signals.', + }, + ], +} + +export const telemetryDetect: ContentListingGroup = { + id: 'telemetry-detect', + type: 'grid', + items: [ + { + title: 'Detect issues', + href: '/guides/observability/detecting', + description: + 'Run health, security, performance, and usage checks against logs and database statistics to pick up a signal.', + }, + ], +} + +export const telemetryDiagnose: ContentListingGroup = { + id: 'telemetry-diagnose', + type: 'grid', + items: [ + { + title: 'Diagnose and resolve', + href: '/guides/troubleshooting', + description: + 'Use a concrete finding, symptom, or error code to identify the cause and apply a known solution.', }, ], } -export const telemetryMonitoring: ContentListingGroup = { - id: 'telemetry-monitoring', - heading: 'Monitoring', +export const telemetryHireAgent: ContentListingGroup = { + id: 'telemetry-hire-agent', type: 'grid', columns: 2, items: [ { - title: 'Log drains', - href: '/guides/monitoring-and-debugging/log-drains', - description: 'Forward logs to Datadog, Loki, Axiom, S3, or a custom HTTP endpoint.', + title: 'Generalist', + href: '/guides/observability/automate-with-agents/all', + subtitle: getScheduleLabel(monitoringAgents.all), + description: + 'Run all four checks — health, security, performance, and usage — in one daily pass.', }, { - title: 'Reports', - href: '/guides/monitoring-and-debugging/reports', - description: 'Built-in dashboards for API, Auth, Storage, and Realtime activity.', + title: monitoringAgents.health.name, + href: '/guides/observability/automate-with-agents/health', + subtitle: getScheduleLabel(monitoringAgents.health), + description: 'Watch logs for 5xx spikes and Auth failures.', }, { - title: 'Metrics', - href: '/guides/monitoring-and-debugging/metrics', - description: 'Prometheus-compatible database metrics for Grafana and other tools.', + title: monitoringAgents.security.name, + href: '/guides/observability/automate-with-agents/security', + subtitle: getScheduleLabel(monitoringAgents.security), + description: 'Review advisor findings and authorization failures.', }, { - title: 'Client-side tracing', - href: '/guides/monitoring-and-debugging/client-side-tracing', - description: 'Correlate browser requests end-to-end using W3C Trace Context.', + title: monitoringAgents.performance.name, + href: '/guides/observability/automate-with-agents/performance', + subtitle: getScheduleLabel(monitoringAgents.performance), + description: 'Find slow queries, lock waits, and missing indexes.', }, { - title: 'Query optimization', - href: '/guides/database/query-optimization', - description: 'Find and fix slow queries using indexes and query plan analysis.', + title: monitoringAgents.usage.name, + href: '/guides/observability/automate-with-agents/usage', + subtitle: getScheduleLabel(monitoringAgents.usage), + description: 'Track request growth, error rates, and approaching limits.', + }, + ], +} + +export const telemetryExport: ContentListingGroup = { + id: 'telemetry-export', + type: 'grid', + columns: 3, + items: [ + { + title: 'Log drains', + href: '/guides/observability/log-drains', + description: 'Send project logs to your own destination.', + }, + { + title: 'Client-side tracing', + href: '/guides/observability/client-side-tracing', + description: 'Propagate W3C trace context from the client through Supabase services.', }, { title: 'Sentry integration', - href: '/guides/monitoring-and-debugging/sentry-monitoring', - description: 'Send errors to Sentry for alerting and grouping.', + href: '/guides/observability/sentry-monitoring', + description: 'Capture supabase-js errors and spans in Sentry.', }, ], } diff --git a/apps/docs/data/monitoring-agents.data.ts b/apps/docs/data/monitoring-agents.data.ts new file mode 100644 index 0000000000000..ca7a6d2b84c6e --- /dev/null +++ b/apps/docs/data/monitoring-agents.data.ts @@ -0,0 +1,64 @@ +import type { AiPromptId } from './ai-prompts.data' + +export const monitoringAgents = { + health: { + id: 'health', + name: 'Health monitor', + promptId: 'monitoring-agent-health' as AiPromptId, + schedule: { + cadence: 'once per hour', + intervalMinutes: 60, + scheduled: 'Run it once per hour on a schedule.', + onDemand: + 'Run it on demand after a deployment, or whenever you need a health check outside that interval.', + }, + }, + security: { + id: 'security', + name: 'Security monitor', + promptId: 'monitoring-agent-security' as AiPromptId, + schedule: { + cadence: 'once per day', + intervalMinutes: 1440, + scheduled: 'Run it once per day on a schedule.', + onDemand: 'Run it on demand after you change Auth, RLS, or other access controls.', + }, + }, + performance: { + id: 'performance', + name: 'Performance monitor', + promptId: 'monitoring-agent-performance' as AiPromptId, + schedule: { + cadence: 'once per hour', + intervalMinutes: 60, + scheduled: 'Run it once per hour on a schedule.', + onDemand: 'Run it on demand after a latency regression or a schema change.', + }, + }, + usage: { + id: 'usage', + name: 'Capacity monitor', + promptId: 'monitoring-agent-usage' as AiPromptId, + schedule: { + cadence: 'once each morning', + intervalMinutes: 1440, + scheduled: 'Run it once per day on a schedule.', + onDemand: 'Run it on demand after an unexpected traffic change.', + }, + }, + all: { + id: 'all', + name: 'Generalist', + promptId: 'monitoring-agent-all' as AiPromptId, + schedule: { + cadence: 'once per day', + intervalMinutes: 1440, + scheduled: 'Run it once per day at the start of your day or shift.', + onDemand: + 'Run it on demand after a deployment or whenever you want a full project health check.', + }, + }, +} as const + +export type MonitoringAgentId = keyof typeof monitoringAgents +export type MonitoringAgent = (typeof monitoringAgents)[MonitoringAgentId] diff --git a/apps/docs/data/monitoring-agents.utils.test.ts b/apps/docs/data/monitoring-agents.utils.test.ts new file mode 100644 index 0000000000000..bf488d8e34d6a --- /dev/null +++ b/apps/docs/data/monitoring-agents.utils.test.ts @@ -0,0 +1,83 @@ +import { describe, expect, it } from 'vitest' + +import { monitoringAgents } from './monitoring-agents.data' +import { + getCronExpression, + getMonitoringAgent, + getMonitoringAgentHarnesses, + getScheduleMarks, +} from './monitoring-agents.utils' + +describe('getMonitoringAgent', () => { + it('returns a registered agent', () => { + expect(getMonitoringAgent('health').name).toBe('Health monitor') + }) + + it('fails clearly for an unknown id', () => { + expect(() => getMonitoringAgent('missing')).toThrow('Unknown monitoring agent id: missing') + }) +}) + +describe('getScheduleMarks', () => { + it('renders a 24-hour day for 15-minute cadence', () => { + const { window, marks } = getScheduleMarks(15) + expect(window).toBe('day') + expect(marks).toHaveLength(96) + expect(marks.filter((mark) => mark.label).map((mark) => mark.label)).toEqual([ + '12am', + '6am', + '12pm', + '6pm', + ]) + }) + + it('renders a 24-hour day for hourly cadence', () => { + const { window, marks } = getScheduleMarks(60) + expect(window).toBe('day') + expect(marks).toHaveLength(24) + expect(marks[0].label).toBe('12am') + expect(marks[12].label).toBe('12pm') + }) + + it('renders a week for daily cadence', () => { + const { window, marks } = getScheduleMarks(1440) + expect(window).toBe('week') + expect(marks.map((mark) => mark.label)).toEqual([ + 'Mon', + 'Tue', + 'Wed', + 'Thu', + 'Fri', + 'Sat', + 'Sun', + ]) + }) +}) + +describe('getCronExpression', () => { + it('maps supported intervals', () => { + expect(getCronExpression(15)).toBe('*/15 * * * *') + expect(getCronExpression(60)).toBe('0 * * * *') + expect(getCronExpression(1440)).toBe('0 9 * * *') + }) +}) + +describe('getMonitoringAgentHarnesses', () => { + it('uses a Claude routine for hourly health checks', () => { + const claude = getMonitoringAgentHarnesses(monitoringAgents.health).find( + (harness) => harness.key === 'claude' + ) + + expect(claude?.intro).toContain('Create a Claude routine') + expect(claude?.note).toBeUndefined() + }) + + it('omits the Desktop-task note when the cadence is hourly or slower', () => { + const claude = getMonitoringAgentHarnesses(monitoringAgents.performance).find( + (harness) => harness.key === 'claude' + ) + + expect(claude?.intro).toContain('Create a Claude routine') + expect(claude?.note).toBeUndefined() + }) +}) diff --git a/apps/docs/data/monitoring-agents.utils.ts b/apps/docs/data/monitoring-agents.utils.ts new file mode 100644 index 0000000000000..5c084726600fc --- /dev/null +++ b/apps/docs/data/monitoring-agents.utils.ts @@ -0,0 +1,139 @@ +import { aiPrompts } from './ai-prompts.data' +import { + monitoringAgents, + type MonitoringAgent, + type MonitoringAgentId, +} from './monitoring-agents.data' + +export type MonitoringAgentHarnessKey = 'claude' | 'codex' | 'cursor' + +export type ScheduleMark = { + key: string + label?: string +} + +export type MonitoringAgentHarnessSetup = { + key: MonitoringAgentHarnessKey + label: string + icon: 'claude' | 'openai' | 'cursor' + hasDistinctDarkIcon?: boolean + docsUrl: string + intro: string + steps: string[] + note?: string +} + +const WEEKDAY_LABELS = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] as const +const DAY_LABELS = ['12am', '6am', '12pm', '6pm'] as const + +const MCP_STEP = + 'Connect the [Supabase MCP server](/docs/guides/ai-tools/mcp) with `project_ref` and `read_only=true`.' + +export function getMonitoringAgent(id: string): MonitoringAgent { + const agent = monitoringAgents[id as MonitoringAgentId] + if (!agent) { + throw new Error(`Unknown monitoring agent id: ${id}`) + } + return agent +} + +export function getMonitoringAgentPrompt(agent: MonitoringAgent): string { + const prompt = aiPrompts[agent.promptId] + if (!prompt) { + throw new Error(`Unknown AiPrompt id: ${agent.promptId}`) + } + return prompt +} + +export function getCronExpression(intervalMinutes: number): string { + if (intervalMinutes === 15) return '*/15 * * * *' + if (intervalMinutes === 60) return '0 * * * *' + if (intervalMinutes === 1440) return '0 9 * * *' + throw new Error(`Unsupported monitoring agent interval: ${intervalMinutes}`) +} + +export function getScheduleMarks(intervalMinutes: number): { + window: 'day' | 'week' + marks: ScheduleMark[] +} { + if (intervalMinutes >= 24 * 60) { + return { + window: 'week', + marks: WEEKDAY_LABELS.map((label) => ({ key: label, label })), + } + } + + const marksPerDay = (24 * 60) / intervalMinutes + if (!Number.isInteger(marksPerDay)) { + throw new Error(`intervalMinutes must divide 1440 evenly. Received: ${intervalMinutes}`) + } + + const labelEvery = marksPerDay / 4 + const marks = Array.from({ length: marksPerDay }, (_, index) => ({ + key: String(index), + label: index % labelEvery === 0 ? DAY_LABELS[index / labelEvery] : undefined, + })) + + return { window: 'day', marks } +} + +export function getScheduleLabel(agent: MonitoringAgent): string { + const cadence = agent.schedule.cadence + return cadence.charAt(0).toUpperCase() + cadence.slice(1) +} + +export function getMonitoringAgentHarnesses(agent: MonitoringAgent): MonitoringAgentHarnessSetup[] { + const cron = getCronExpression(agent.schedule.intervalMinutes) + const cadence = agent.schedule.cadence + const isSubHourly = agent.schedule.intervalMinutes < 60 + + return [ + { + key: 'claude', + label: 'Claude', + icon: 'claude', + docsUrl: isSubHourly + ? 'https://code.claude.com/docs/en/desktop-scheduled-tasks' + : 'https://code.claude.com/docs/en/routines', + intro: isSubHourly + ? `Create a Claude Desktop scheduled task that runs ${agent.name} ${cadence}.` + : `Create a Claude routine that runs ${agent.name} ${cadence}.`, + steps: [ + MCP_STEP, + isSubHourly + ? 'In the Claude Code Desktop app, open **Routines**, click **New routine**, and choose **Local**.' + : 'Open [Claude routines](https://claude.ai/code/routines) or run `/schedule` in Claude Code.', + `Name it ${agent.name}. Paste the prompt. Set the schedule to ${cadence}.`, + ], + note: isSubHourly + ? 'Cloud routines have a 1-hour minimum. Use a [Desktop scheduled task](https://code.claude.com/docs/en/desktop-scheduled-tasks) for this cadence.' + : undefined, + }, + { + key: 'codex', + label: 'Codex', + icon: 'openai', + hasDistinctDarkIcon: true, + docsUrl: 'https://developers.openai.com/codex/app/automations', + intro: `Create a Codex scheduled task that runs ${agent.name} ${cadence}.`, + steps: [ + MCP_STEP, + 'Open **Scheduled** in the ChatGPT desktop app, or ask Codex to create a standalone scheduled task.', + `Name it ${agent.name}. Paste the prompt. Set the schedule to ${cadence}. Each run should start a new chat.`, + ], + }, + { + key: 'cursor', + label: 'Cursor', + icon: 'cursor', + hasDistinctDarkIcon: true, + docsUrl: 'https://cursor.com/docs/cloud-agent/automations', + intro: `Create a Cursor automation that runs ${agent.name} ${cadence}.`, + steps: [ + MCP_STEP, + 'Create an automation in the Agents Window, at [cursor.com/automations](https://cursor.com/automations), or with the `/automate` skill.', + `Name it ${agent.name}. Use a scheduled trigger (${cadence}, cron \`${cron}\`). Paste the prompt. Keep the agent read-only, with no repository.`, + ], + }, + ] +} diff --git a/apps/docs/features/docs/GuidesMdx.utils.tsx b/apps/docs/features/docs/GuidesMdx.utils.tsx index ab1d34c649453..0212f9886a95c 100644 --- a/apps/docs/features/docs/GuidesMdx.utils.tsx +++ b/apps/docs/features/docs/GuidesMdx.utils.tsx @@ -34,7 +34,7 @@ const PUBLISHED_SECTIONS = [ 'graphql', 'integrations', 'local-development', - 'monitoring-and-debugging', + 'observability', 'platform', 'queues', 'realtime', diff --git a/apps/docs/features/docs/MdxBase.shared.tsx b/apps/docs/features/docs/MdxBase.shared.tsx index a7124288ec4c0..355c3f129ab3b 100644 --- a/apps/docs/features/docs/MdxBase.shared.tsx +++ b/apps/docs/features/docs/MdxBase.shared.tsx @@ -39,6 +39,8 @@ import { GlassPanel } from 'ui-patterns/GlassPanel' import SqlToRest from 'ui-patterns/SqlToRest' import { AgentPluginsPanel } from '../ui/AgentPluginsPanel' +import { AgentSetup } from '../ui/AgentSetup' +import { AgentWatchSchedule } from '../ui/AgentWatchSchedule' import { AiPrompt } from '../ui/AiPrompt' import { ErrorCodes } from '../ui/ErrorCodes' import { McpConfigPanel } from '../ui/McpConfigPanel' @@ -69,6 +71,8 @@ const components = { AccordionItem, Admonition: AdmonitionWithMargin, AgentPluginsPanel, + AgentSetup, + AgentWatchSchedule, AiPrompt, AiPromptsIndex, AiSkillsIndex, diff --git a/apps/docs/features/ui/AgentSetup.tsx b/apps/docs/features/ui/AgentSetup.tsx new file mode 100644 index 0000000000000..5c7c30e68b701 --- /dev/null +++ b/apps/docs/features/ui/AgentSetup.tsx @@ -0,0 +1,111 @@ +'use client' + +import { + getMonitoringAgent, + getMonitoringAgentHarnesses, + type MonitoringAgentHarnessSetup, +} from '~/data/monitoring-agents.utils' +import { Sparkles } from 'lucide-react' +import { useTheme } from 'next-themes' +import { type ReactNode } from 'react' +import ReactMarkdown from 'react-markdown' +import { ConnectionIcon } from 'ui-patterns/McpUrlBuilder' + +import { AiPrompt } from './AiPrompt' +import { TabPanel, Tabs } from './Tabs' + +type AgentSetupProps = { + id: string +} + +const markdownComponents = { + p: ({ children }: { children?: ReactNode }) => <>{children}, + a: ({ href, children }: { href?: string; children?: ReactNode }) => { + if (!href) return <>{children} + const external = /^(?:[a-z][a-z0-9+\-.]*:|\/\/)/i.test(href) + return ( + + {children} + + ) + }, + code: ({ children }: { children?: ReactNode }) => ( + + {children} + + ), +} + +function HarnessBody({ harness }: { harness: MonitoringAgentHarnessSetup }) { + return ( + <> +

    {harness.intro}

    +
      + {harness.steps.map((step) => ( +
    1. + {step} +
    2. + ))} +
    + {harness.note && ( +

    + {harness.note} +

    + )} +

    + + {harness.label} docs + +

    + + ) +} + +function AgentSetup({ id }: AgentSetupProps) { + const agent = getMonitoringAgent(id) + const harnesses = getMonitoringAgentHarnesses(agent) + const { resolvedTheme } = useTheme() + const theme = resolvedTheme?.includes('dark') ? 'dark' : 'light' + + return ( + + }> + + + {harnesses.map((harness) => ( + + } + > + + + ))} + + ) +} + +export { AgentSetup } +export type { AgentSetupProps } diff --git a/apps/docs/features/ui/AgentWatchSchedule.tsx b/apps/docs/features/ui/AgentWatchSchedule.tsx new file mode 100644 index 0000000000000..bed8bd0b8fdec --- /dev/null +++ b/apps/docs/features/ui/AgentWatchSchedule.tsx @@ -0,0 +1,89 @@ +import { + getMonitoringAgent, + getScheduleLabel, + getScheduleMarks, +} from '~/data/monitoring-agents.utils' + +type AgentWatchScheduleProps = { + id: string +} + +function DaySchedule({ + marks, + cadence, +}: { + marks: ReturnType['marks'] + cadence: string +}) { + const labeled = marks.filter((mark) => mark.label) + + return ( +
    +
    + {labeled.map((mark) => { + const index = marks.findIndex((item) => item.key === mark.key) + return ( + + {mark.label} + + ) + })} +
    +
    + {marks.map((mark) => ( + + ))} +
    +
    + ) +} + +function WeekSchedule({ + marks, + cadence, +}: { + marks: ReturnType['marks'] + cadence: string +}) { + return ( +
    + {marks.map((mark) => ( +
    +
    + +
    + {mark.label} +
    + ))} +
    + ) +} + +function AgentWatchSchedule({ id }: AgentWatchScheduleProps) { + const agent = getMonitoringAgent(id) + const { window, marks } = getScheduleMarks(agent.schedule.intervalMinutes) + const title = getScheduleLabel(agent) + + return ( +
    +

    {title}

    + {window === 'week' ? ( + + ) : ( + + )} +

    {agent.schedule.onDemand}

    +
    + ) +} + +export { AgentWatchSchedule } +export type { AgentWatchScheduleProps } diff --git a/apps/docs/features/ui/AiPrompt.tsx b/apps/docs/features/ui/AiPrompt.tsx index 0abe0bac1cd37..2162b500a8928 100644 --- a/apps/docs/features/ui/AiPrompt.tsx +++ b/apps/docs/features/ui/AiPrompt.tsx @@ -8,6 +8,8 @@ import { Prompt, PromptContent, PromptCopy, PromptPanel, PromptTitle } from './P type AiPromptProps = { /** Looks up prompt text from `aiPrompts`. */ id: AiPromptId | string + /** Includes the prompt body in generated guide Markdown. */ + includeInMarkdown?: boolean } /** @@ -16,8 +18,8 @@ type AiPromptProps = { * boundary (where child types arrive as `react.lazy` and the panel * would otherwise render nothing). * - * Prompt text lives in `~/data/ai-prompts.data`. Markdown export - * intentionally omits this component (HTML-only copy panel). + * Prompt text lives in `~/data/ai-prompts.data`. Markdown export is opt-in so + * existing quickstarts do not duplicate their instructions in bulk exports. */ function AiPrompt({ id }: AiPromptProps) { const prompt = aiPrompts[id as AiPromptId] diff --git a/apps/docs/features/ui/Tabs.tsx b/apps/docs/features/ui/Tabs.tsx index 2c01f57be29fe..66344d117ec29 100644 --- a/apps/docs/features/ui/Tabs.tsx +++ b/apps/docs/features/ui/Tabs.tsx @@ -55,7 +55,7 @@ export const tabsListVariants = cva(cn('flex'), { export const tabsTriggerListVariants = cva( cn( - 'relative cursor-pointer flex items-center space-x-2 text-center transition-colors focus-ring' + 'relative cursor-pointer flex items-center space-x-2 text-center transition-colors focus-ring [&_img]:m-0 [&_img]:size-3.5 [&_svg]:size-3.5' ), { variants: { @@ -218,7 +218,7 @@ export const Tabs = ({ type, scrollable, wrappable, - className: cn({ 'bg-background': stickyTabList != null }, listClassNames), + className: cn('not-prose', { 'bg-background': stickyTabList != null }, listClassNames), })} ref={stickyRef} > diff --git a/apps/docs/internals/generate-guides-markdown.ts b/apps/docs/internals/generate-guides-markdown.ts index c7d94bce7f0b7..788bb55c6c785 100644 --- a/apps/docs/internals/generate-guides-markdown.ts +++ b/apps/docs/internals/generate-guides-markdown.ts @@ -16,6 +16,9 @@ import { mcpConfigPanelMarkdown as McpConfigPanel } from 'ui-patterns/McpUrlBuil import { addBaseUrlPrefix, getInternalLinkBaseUrl, withDocsBasePath } from './internal-links' import { AccordionItem } from './markdown-schema/Accordion' import { Admonition } from './markdown-schema/Admonition' +import { AgentSetup } from './markdown-schema/AgentSetup' +import { AgentWatchSchedule } from './markdown-schema/AgentWatchSchedule' +import { AiPrompt } from './markdown-schema/AiPrompt' import { AiSkillsIndex } from './markdown-schema/AiSkillsIndex' import { AuthProviders } from './markdown-schema/AuthProviders' import { ComputeDiskLimitsTable } from './markdown-schema/ComputeDiskLimitsTable' @@ -184,6 +187,9 @@ function applySchema(parent: Parent, schema: ComponentSchema): void { const SCHEMA: ComponentSchema = { AccordionItem, Admonition, + AgentSetup, + AgentWatchSchedule, + AiPrompt, AiSkillsIndex, IconCheck, IconX, diff --git a/apps/docs/internals/markdown-schema/AgentSetup.test.ts b/apps/docs/internals/markdown-schema/AgentSetup.test.ts new file mode 100644 index 0000000000000..23899b887eab0 --- /dev/null +++ b/apps/docs/internals/markdown-schema/AgentSetup.test.ts @@ -0,0 +1,34 @@ +import { describe, expect, it } from 'vitest' + +import { AgentSetup } from './AgentSetup' + +describe('AgentSetup markdown schema', () => { + it('serializes the prompt and harness setup for a registered agent', () => { + const markdown = AgentSetup({ props: { id: 'health' } }) + + expect(markdown).toContain('**Prompt**') + expect(markdown).toContain('You are "Health monitor"') + expect(markdown).toContain('```text') + expect(markdown).toContain('**Claude**') + expect(markdown).toContain('**Codex**') + expect(markdown).toContain('**Cursor**') + expect(markdown).toContain('claude.ai/code/routines') + expect(markdown).toContain('`0 * * * *`') + expect(markdown).toContain('[Claude docs](https://code.claude.com/docs/en/routines)') + expect(markdown).toContain('[Codex docs](https://developers.openai.com/codex/app/automations)') + expect(markdown).toContain('[Cursor docs](https://cursor.com/docs/cloud-agent/automations)') + }) + + it('points hourly agents at Claude cloud routines', () => { + const markdown = AgentSetup({ props: { id: 'performance' } }) + + expect(markdown).toContain('claude.ai/code/routines') + expect(markdown).not.toContain('Desktop scheduled task') + }) + + it('fails clearly for an unknown agent', () => { + expect(() => AgentSetup({ props: { id: 'missing' } })).toThrow( + 'Unknown monitoring agent id: missing' + ) + }) +}) diff --git a/apps/docs/internals/markdown-schema/AgentSetup.ts b/apps/docs/internals/markdown-schema/AgentSetup.ts new file mode 100644 index 0000000000000..8b6d5568e47aa --- /dev/null +++ b/apps/docs/internals/markdown-schema/AgentSetup.ts @@ -0,0 +1,31 @@ +import { + getMonitoringAgent, + getMonitoringAgentHarnesses, + getMonitoringAgentPrompt, +} from '~/data/monitoring-agents.utils' + +type HandlerContext = { + props: Record +} + +function renderMarkdownSteps(steps: string[]): string { + return steps.map((step, index) => `${index + 1}. ${step}`).join('\n') +} + +export function AgentSetup({ props }: HandlerContext): string { + const agent = getMonitoringAgent(String(props.id ?? '')) + const prompt = getMonitoringAgentPrompt(agent) + const harnesses = getMonitoringAgentHarnesses(agent) + + const sections = [ + `**Prompt**\n\n\`\`\`text\n${prompt}\n\`\`\``, + ...harnesses.map((harness) => { + const parts = [`**${harness.label}**`, harness.intro, renderMarkdownSteps(harness.steps)] + if (harness.note) parts.push(harness.note) + parts.push(`[${harness.label} docs](${harness.docsUrl})`) + return parts.join('\n\n') + }), + ] + + return sections.join('\n\n') +} diff --git a/apps/docs/internals/markdown-schema/AgentWatchSchedule.test.ts b/apps/docs/internals/markdown-schema/AgentWatchSchedule.test.ts new file mode 100644 index 0000000000000..5f974c56eee27 --- /dev/null +++ b/apps/docs/internals/markdown-schema/AgentWatchSchedule.test.ts @@ -0,0 +1,18 @@ +import { describe, expect, it } from 'vitest' + +import { AgentWatchSchedule } from './AgentWatchSchedule' + +describe('AgentWatchSchedule markdown schema', () => { + it('serializes the scheduled and on-demand copy', () => { + const markdown = AgentWatchSchedule({ props: { id: 'health' } }) + + expect(markdown).toContain('Run it once per hour on a schedule.') + expect(markdown).toContain('Run it on demand after a deployment') + }) + + it('fails clearly for an unknown agent', () => { + expect(() => AgentWatchSchedule({ props: { id: 'missing' } })).toThrow( + 'Unknown monitoring agent id: missing' + ) + }) +}) diff --git a/apps/docs/internals/markdown-schema/AgentWatchSchedule.ts b/apps/docs/internals/markdown-schema/AgentWatchSchedule.ts new file mode 100644 index 0000000000000..a5c33b3ffd896 --- /dev/null +++ b/apps/docs/internals/markdown-schema/AgentWatchSchedule.ts @@ -0,0 +1,10 @@ +import { getMonitoringAgent } from '~/data/monitoring-agents.utils' + +type HandlerContext = { + props: Record +} + +export function AgentWatchSchedule({ props }: HandlerContext): string { + const agent = getMonitoringAgent(String(props.id ?? '')) + return `${agent.schedule.scheduled}\n\n${agent.schedule.onDemand}` +} diff --git a/apps/docs/internals/markdown-schema/AiPrompt.test.ts b/apps/docs/internals/markdown-schema/AiPrompt.test.ts new file mode 100644 index 0000000000000..528b9a5523dc0 --- /dev/null +++ b/apps/docs/internals/markdown-schema/AiPrompt.test.ts @@ -0,0 +1,55 @@ +import { describe, expect, it } from 'vitest' + +import { AiPrompt } from './AiPrompt' + +describe('AiPrompt markdown schema', () => { + it('omits prompts by default', () => { + expect(AiPrompt({ props: { id: 'nextjs' } })).toBe('') + }) + + it('serializes an opted-in prompt from the shared registry', () => { + const markdown = AiPrompt({ + props: { id: 'nextjs', includeInMarkdown: true }, + }) + + expect(markdown).toContain('**AI Prompt**') + expect(markdown).toContain('Help me add Supabase to my Next.js project.') + expect(markdown).toContain('```text') + }) + + it.each([ + ['monitoring-agent-health', 'Health monitor', 'health'], + ['monitoring-agent-security', 'Security monitor', 'security'], + ['monitoring-agent-performance', 'Performance monitor', 'performance'], + ['monitoring-agent-usage', 'Capacity monitor', 'usage'], + ])('serializes the %s agent prompt', (id, persona, detectionSection) => { + const markdown = AiPrompt({ props: { id, includeInMarkdown: true } }) + + expect(markdown).toContain('**AI Prompt**') + expect(markdown).toContain(persona) + expect(markdown).toContain('read-only') + expect(markdown).toContain( + `https://supabase.com/docs/guides/observability/detecting.md#${detectionSection}` + ) + expect(markdown).toContain('```text') + }) + + it('serializes the monitoring overview prompt', () => { + const markdown = AiPrompt({ + props: { id: 'monitoring-and-debugging', includeInMarkdown: true }, + }) + + expect(markdown).toContain('Help me monitor and debug my Supabase project.') + expect(markdown).toContain('npm install -g supabase') + expect(markdown).toContain('npx plugins add supabase-community/supabase-plugin') + expect(markdown).toContain('read-only') + expect(markdown).toContain('https://supabase.com/docs/guides/observability.md') + expect(markdown).toContain('```text') + }) + + it('fails clearly for an unknown opted-in prompt', () => { + expect(() => AiPrompt({ props: { id: 'missing-prompt', includeInMarkdown: true } })).toThrow( + 'Unknown AiPrompt id: missing-prompt' + ) + }) +}) diff --git a/apps/docs/internals/markdown-schema/AiPrompt.ts b/apps/docs/internals/markdown-schema/AiPrompt.ts new file mode 100644 index 0000000000000..6a1ed36cfdbf8 --- /dev/null +++ b/apps/docs/internals/markdown-schema/AiPrompt.ts @@ -0,0 +1,20 @@ +import { aiPrompts, type AiPromptId } from '~/data/ai-prompts.data' + +type HandlerContext = { + props: Record +} + +export function AiPrompt({ props }: HandlerContext): string { + const includeInMarkdown = props.includeInMarkdown === true || props.includeInMarkdown === 'true' + + if (!includeInMarkdown) return '' + + const id = String(props.id ?? '') + const prompt = aiPrompts[id as AiPromptId] + + if (!prompt) { + throw new Error(`Unknown AiPrompt id: ${id}`) + } + + return `**AI Prompt**\n\n\`\`\`text\n${prompt}\n\`\`\`` +} diff --git a/apps/docs/internals/markdown-schema/ContentListings.ts b/apps/docs/internals/markdown-schema/ContentListings.ts index ce78463b70afa..6817ce1f91969 100644 --- a/apps/docs/internals/markdown-schema/ContentListings.ts +++ b/apps/docs/internals/markdown-schema/ContentListings.ts @@ -37,7 +37,8 @@ export function serializeContentListingGroupToMarkdown( const href = isExternalContentListingHref(item.href) ? item.href : `${linkBaseUrl}${withDocsBasePath(item.href)}` - lines.push(`- **[${item.title}](${href}):** ${item.description}`) + const description = item.subtitle ? `${item.subtitle}. ${item.description}` : item.description + lines.push(`- **[${item.title}](${href}):** ${description}`) } return lines.join('\n') diff --git a/apps/docs/layouts/MainSkeleton.tsx b/apps/docs/layouts/MainSkeleton.tsx index baedba068c641..25ac4a5819974 100644 --- a/apps/docs/layouts/MainSkeleton.tsx +++ b/apps/docs/layouts/MainSkeleton.tsx @@ -59,7 +59,7 @@ const levelsData = { }, telemetry: { icon: 'telemetry', - name: 'Telemetry', + name: 'Observability', }, realtime: { icon: 'realtime', diff --git a/apps/docs/lib/breadcrumbs.test.ts b/apps/docs/lib/breadcrumbs.test.ts new file mode 100644 index 0000000000000..14c77a48eafc8 --- /dev/null +++ b/apps/docs/lib/breadcrumbs.test.ts @@ -0,0 +1,16 @@ +import { describe, expect, it } from 'vitest' + +import { resolveBreadcrumbs } from './breadcrumbs' + +describe('resolveBreadcrumbs', () => { + it('places troubleshooting under detect and diagnose', () => { + expect(resolveBreadcrumbs('/guides/troubleshooting')).toEqual([ + { + name: 'Observability', + url: '/guides/observability', + }, + { name: 'Detect and diagnose' }, + { name: 'Diagnosing', url: '/guides/troubleshooting' }, + ]) + }) +}) diff --git a/apps/docs/lib/breadcrumbs.ts b/apps/docs/lib/breadcrumbs.ts index ac6643c80b574..a89f74e8c59a8 100644 --- a/apps/docs/lib/breadcrumbs.ts +++ b/apps/docs/lib/breadcrumbs.ts @@ -26,7 +26,7 @@ const SECTION_PATH_TO_KEY: Record = { security: 'security', 'self-hosting': 'self_hosting', storage: 'storage', - 'monitoring-and-debugging': 'telemetry', + observability: 'telemetry', } function getSectionMenu(pathname: string) { @@ -55,7 +55,14 @@ function findMenuItemByUrl( export function resolveBreadcrumbs(pathname: string): BreadcrumbItem[] { if (pathname.startsWith('/guides/troubleshooting')) { - return [{ name: 'Troubleshooting', url: '/guides/troubleshooting' }] + return [ + { + name: 'Observability', + url: '/guides/observability', + }, + { name: 'Detect and diagnose' }, + { name: 'Diagnosing', url: '/guides/troubleshooting' }, + ] } if (pathname.startsWith('/guides/getting-started/ai-prompts')) { return [ diff --git a/apps/docs/lib/content-listings.test.ts b/apps/docs/lib/content-listings.test.ts index 87b0d5d82fea7..71f0de5c6f671 100644 --- a/apps/docs/lib/content-listings.test.ts +++ b/apps/docs/lib/content-listings.test.ts @@ -62,6 +62,27 @@ describe('serializeContentListingGroupToMarkdown', () => { ) }) + it('includes a subtitle before the description', () => { + const markdown = serializeContentListingGroupToMarkdown( + { + id: 'hire-agent', + items: [ + { + title: 'Health monitor', + href: '/guides/observability/automate-with-agents/health', + subtitle: 'Every 15 minutes', + description: 'Watch logs for 5xx spikes and Auth failures.', + }, + ], + }, + 'https://supabase.com' + ) + + expect(markdown).toContain( + '**[Health monitor](https://supabase.com/docs/guides/observability/automate-with-agents/health):** Every 15 minutes. Watch logs for 5xx spikes and Auth failures.' + ) + }) + it('preserves external hrefs in markdown export', () => { const markdown = serializeContentListingGroupToMarkdown( { @@ -257,10 +278,18 @@ describe('dashboard content listing hrefs', () => { describe('contentListingItemSchema icon', () => { const baseItem = { title: 'Datadog', - href: '/guides/monitoring-and-debugging/log-drains#datadog', + href: '/guides/observability/log-drains#datadog', description: 'Stream logs directly into Datadog for monitoring and analysis.', } + it('accepts an optional subtitle', () => { + const result = contentListingItemSchema.safeParse({ + ...baseItem, + subtitle: 'Every 15 minutes', + }) + expect(result.success).toBe(true) + }) + it('accepts a plain string icon path', () => { const result = contentListingItemSchema.safeParse({ ...baseItem, diff --git a/apps/docs/lib/content-listings.zod.mjs b/apps/docs/lib/content-listings.zod.mjs index a678cb6b57863..decf8220a0371 100644 --- a/apps/docs/lib/content-listings.zod.mjs +++ b/apps/docs/lib/content-listings.zod.mjs @@ -24,6 +24,8 @@ export const contentListingItemSchema = z.object({ title: z.string().min(1), href: z.string().min(1), description: z.string().min(1), + /** Shown under the title on grid cards, before the description. */ + subtitle: z.string().min(1).optional(), icon: contentListingIconSchema.optional(), hasLightIcon: z.boolean().optional(), badge: z.string().min(1).optional(), diff --git a/apps/docs/next.config.mjs b/apps/docs/next.config.mjs index 4da99c4f570f5..edafab3c4208d 100644 --- a/apps/docs/next.config.mjs +++ b/apps/docs/next.config.mjs @@ -187,6 +187,16 @@ const nextConfig = { destination: '/guides/database/replication/pipelines-faq', permanent: true, }, + { + source: '/guides/database/inspect', + destination: '/guides/monitoring-and-debugging/inspect', + permanent: true, + }, + { + source: '/guides/database/database-advisors', + destination: '/guides/observability/advisors', + permanent: true, + }, ] }, typescript: { diff --git a/apps/docs/scripts/search/sources/index.ts b/apps/docs/scripts/search/sources/index.ts index 091cb8adca176..ed67571899a1a 100644 --- a/apps/docs/scripts/search/sources/index.ts +++ b/apps/docs/scripts/search/sources/index.ts @@ -140,7 +140,7 @@ export async function fetchCliLibReferenceSource() { export async function fetchLintWarningsGuideSources() { return new LintWarningsGuideLoader( 'guide', - '/guides/database/database-advisors', + '/guides/observability/advisors', 'supabase', 'splinter', 'main', diff --git a/apps/docs/spec/cli_v1_commands--old.yaml b/apps/docs/spec/cli_v1_commands--old.yaml index f3671ceb1aea0..509df82773393 100644 --- a/apps/docs/spec/cli_v1_commands--old.yaml +++ b/apps/docs/spec/cli_v1_commands--old.yaml @@ -172,7 +172,7 @@ commands: - id: supabase-projects-list title: supabase projects list summary: List all Supabase projects - description: List all Supabase projects the logged-in user can access. + description: List all Supabase projects the signed-in user can access. tags: [] links: [] usage: |- @@ -218,7 +218,7 @@ commands: - id: supabase-orgs-list title: supabase orgs list summary: List all organizations - description: List all organizations the logged-in user belongs. + description: List all organizations the signed-in user belongs. tags: [] links: [] usage: |- diff --git a/apps/docs/spec/cli_v1_commands.yaml b/apps/docs/spec/cli_v1_commands.yaml index ab1ba004251bc..69af4b60ae33c 100644 --- a/apps/docs/spec/cli_v1_commands.yaml +++ b/apps/docs/spec/cli_v1_commands.yaml @@ -730,7 +730,7 @@ commands: title: supabase sso remove summary: Remove an existing SSO identity provider description: | - Remove a connection to an already added SSO identity provider. Removing the provider will prevent existing users from logging in. Please treat this command with care. + Remove a connection to an already added SSO identity provider. Removing the provider will prevent existing users from signing in. Please treat this command with care. examples: - id: basic-usage name: Remove a provider @@ -1085,7 +1085,7 @@ commands: - id: supabase-projects-list title: supabase projects list summary: List all Supabase projects - description: List all Supabase projects the logged-in user can access. + description: List all Supabase projects the signed-in user can access. tags: [] links: [] usage: supabase projects list @@ -1346,7 +1346,7 @@ commands: - id: supabase-orgs-list title: supabase orgs list summary: List all organizations - description: List all organizations the logged-in user belongs. + description: List all organizations the signed-in user belongs to. tags: [] links: [] usage: supabase orgs list @@ -1355,7 +1355,7 @@ commands: - id: supabase-orgs-create title: supabase orgs create summary: Create an organization - description: Create an organization for the logged-in user. + description: Create an organization for the signed-in user. tags: [] links: [] usage: supabase orgs create @@ -1794,7 +1794,7 @@ commands: summary: Authenticate using an access token description: |2 - Connect the Supabase CLI to your Supabase account by logging in with your [personal access token](https://supabase.com/dashboard/account/tokens). + Connect the Supabase CLI to your Supabase account by signing in with your [personal access token](https://supabase.com/dashboard/account/tokens). Your access token is stored securely in [native credentials storage](https://github.com/zalando/go-keyring#dependencies). If native credentials storage is unavailable, it will be written to a plain text file at `~/.supabase/access-token`. diff --git a/apps/docs/spec/cli_v1_config.yaml b/apps/docs/spec/cli_v1_config.yaml index 1bf0a040dd72b..6c0a612d95a36 100644 --- a/apps/docs/spec/cli_v1_config.yaml +++ b/apps/docs/spec/cli_v1_config.yaml @@ -1489,7 +1489,7 @@ parameters: required: false default: '' description: | - Force log out after the specified duration. Sample values include: '50m', '20h'. + Force sign out after the specified duration. Sample values include: '50m', '20h'. links: - name: 'Auth Sessions' link: 'https://supabase.com/docs/guides/auth/sessions' @@ -1500,7 +1500,7 @@ parameters: required: false default: '' description: | - Force log out if the user has been inactive longer than the specified duration. Sample values include: '50m', '20h'. + Force sign out if the user has been inactive longer than the specified duration. Sample values include: '50m', '20h'. links: - name: 'Auth Sessions' link: 'https://supabase.com/docs/guides/auth/sessions' diff --git a/apps/docs/spec/reference/dart/v2/partials/introduction.mdx b/apps/docs/spec/reference/dart/v2/partials/introduction.mdx index a1b21c70f2b60..497b8f6d07d2f 100644 --- a/apps/docs/spec/reference/dart/v2/partials/introduction.mdx +++ b/apps/docs/spec/reference/dart/v2/partials/introduction.mdx @@ -2,6 +2,6 @@ title: 'Introduction' --- -This reference documents every object and method available in Supabase's Flutter library, [supabase-flutter](https://pub.dev/packages/supabase_flutter). You can use supabase-flutter to interact with your Postgres database, listen to database changes, invoke Deno Edge Functions, build login and user management functionality, and manage large files. +This reference documents every object and method available in Supabase's Flutter library, [supabase-flutter](https://pub.dev/packages/supabase_flutter). You can use supabase-flutter to interact with your Postgres database, listen to database changes, invoke Deno Edge Functions, build sign-in and user management functionality, and manage large files. We also provide a [supabase](https://pub.dev/packages/supabase) package for non-Flutter projects. diff --git a/apps/docs/spec/reference/javascript/v2/partials/introduction.mdx b/apps/docs/spec/reference/javascript/v2/partials/introduction.mdx index 2de91f081eba8..b1f0825fe2d23 100644 --- a/apps/docs/spec/reference/javascript/v2/partials/introduction.mdx +++ b/apps/docs/spec/reference/javascript/v2/partials/introduction.mdx @@ -3,7 +3,7 @@ id: introduction title: Introduction --- -This reference documents every object and method available in Supabase's isomorphic JavaScript library, `supabase-js`. You can use `supabase-js` to interact with your Postgres database, listen to database changes, invoke Deno Edge Functions, build login and user management functionality, and manage large files. +This reference documents every object and method available in Supabase's isomorphic JavaScript library, `supabase-js`. You can use `supabase-js` to interact with your Postgres database, listen to database changes, invoke Deno Edge Functions, build sign-in and user management functionality, and manage large files. To convert SQL queries to `supabase-js` calls, use the [SQL to REST API translator](/docs/guides/api/sql-to-rest). diff --git a/apps/docs/spec/supabase_csharp_v0.yml b/apps/docs/spec/supabase_csharp_v0.yml index 09134ade3ae4c..03ea3bd09509f 100644 --- a/apps/docs/spec/supabase_csharp_v0.yml +++ b/apps/docs/spec/supabase_csharp_v0.yml @@ -119,7 +119,7 @@ functions: description: | Creates a new user. notes: | - - By default, the user needs to verify their email address before logging in. To turn this off, disable **Confirm email** in [your project](https://supabase.com/dashboard/project/_/auth/providers). + - By default, the user needs to verify their email address before signing in. To turn this off, disable **Confirm email** in [your project](https://supabase.com/dashboard/project/_/auth/providers). - **Confirm email** determines if users need to confirm their email address after signing up. - If **Confirm email** is enabled, a `user` is returned but `session` is null. - If **Confirm email** is disabled, both a `user` and a `session` are returned. @@ -138,7 +138,7 @@ functions: - id: sign-in-with-password title: 'SignIn(email, password)' description: | - Log in an existing user using email or phone number with password. + Sign in an existing user using email or phone number with password. notes: | - Requires either an email and password or a phone number and password. examples: @@ -215,7 +215,7 @@ functions: - id: sign-out title: 'SignOut()' description: | - Signs out the current user, if there is a logged in user. + Signs out the current user, if there is a signed-in user. notes: | - In order to use the `SignOut()` method, the user needs to be signed in first. examples: @@ -254,9 +254,9 @@ functions: - id: get-user title: 'CurrentUser' description: | - Returns the user data, if there is a logged in user. + Returns the user data, if there is a signed-in user. examples: - - name: Get the logged in user + - name: Get the signed-in user isSpotlight: true code: | ```c# @@ -265,7 +265,7 @@ functions: - id: update-user title: 'UpdateUser()' description: | - Updates user data, if there is a logged in user. + Updates user data, if there is a signed-in user. notes: | - In order to use the `UpdateUser()` method, the user needs to be signed in first. - By Default, email updates sends a confirmation link to both the user's current and new email. diff --git a/apps/docs/spec/supabase_csharp_v1.yml b/apps/docs/spec/supabase_csharp_v1.yml index a5b868a0c6aff..dd5e3078e4dd4 100644 --- a/apps/docs/spec/supabase_csharp_v1.yml +++ b/apps/docs/spec/supabase_csharp_v1.yml @@ -116,7 +116,7 @@ functions: description: | Creates a new user. notes: | - - By default, the user needs to verify their email address before logging in. To turn this off, disable **Confirm email** in [your project](https://supabase.com/dashboard/project/_/auth/providers). + - By default, the user needs to verify their email address before signing in. To turn this off, disable **Confirm email** in [your project](https://supabase.com/dashboard/project/_/auth/providers). - **Confirm email** determines if users need to confirm their email address after signing up. - If **Confirm email** is enabled, a `user` is returned but `session` is null. - If **Confirm email** is disabled, both a `user` and a `session` are returned. @@ -135,7 +135,7 @@ functions: - id: sign-in-with-password title: 'SignIn(email, password)' description: | - Log in an existing user using email or phone number with password. + Sign in an existing user using email or phone number with password. notes: | - Requires either an email and password or a phone number and password. examples: @@ -212,7 +212,7 @@ functions: - id: sign-out title: 'SignOut()' description: | - Signs out the current user, if there is a logged in user. + Signs out the current user, if there is a signed-in user. notes: | - In order to use the `SignOut()` method, the user needs to be signed in first. examples: @@ -259,9 +259,9 @@ functions: - id: get-user title: 'CurrentUser' description: | - Returns the user data, if there is a logged in user. + Returns the user data, if there is a signed-in user. examples: - - name: Get the logged in user + - name: Get the signed-in user isSpotlight: true code: | ```c# @@ -270,7 +270,7 @@ functions: - id: update-user title: 'UpdateUser()' description: | - Updates user data, if there is a logged in user. + Updates user data, if there is a signed-in user. notes: | - In order to use the `UpdateUser()` method, the user needs to be signed in first. - By Default, email updates sends a confirmation link to both the user's current and new email. @@ -1558,7 +1558,7 @@ functions: - id: from-create-signed-upload-url description: | - Creates a signed URL that can be used to upload a file without requiring a logged-in user. This is useful for handing off uploads to an untrusted client. + Creates a signed URL that can be used to upload a file without requiring a signed-in user. This is useful for handing off uploads to an untrusted client. title: 'From().CreateUploadSignedUrl()' notes: | - Policy permissions required: diff --git a/apps/docs/spec/supabase_dart_v1.yml b/apps/docs/spec/supabase_dart_v1.yml index 709d4c1329473..2df29e6137128 100644 --- a/apps/docs/spec/supabase_dart_v1.yml +++ b/apps/docs/spec/supabase_dart_v1.yml @@ -56,7 +56,7 @@ functions: description: | Creates a new user. notes: | - - By default, the user needs to verify their email address before logging in. To turn this off, disable **Confirm email** in [your project](https://supabase.com/dashboard/project/_/auth/providers). + - By default, the user needs to verify their email address before signing in. To turn this off, disable **Confirm email** in [your project](https://supabase.com/dashboard/project/_/auth/providers). - **Confirm email** determines if users need to confirm their email address after signing up. - If **Confirm email** is enabled, a `user` is returned but `session` is null. - If **Confirm email** is disabled, both a `user` and a `session` are returned. @@ -107,7 +107,7 @@ functions: - id: sign-in-with-password title: 'signInWithPassword()' description: | - Log in an existing user using email or phone number with password. + Sign in an existing user using email or phone number with password. notes: | - Requires either an email and password or a phone number and password. examples: @@ -239,7 +239,7 @@ functions: - id: sign-out title: 'signOut()' description: | - Signs out the current user, if there is a logged in user. + Signs out the current user, if there is a signed-in user. notes: | - In order to use the `signOut()` method, the user needs to be signed in first. examples: @@ -297,9 +297,9 @@ functions: - id: get-user title: 'currentUser' description: | - Returns the user data, if there is a logged in user. + Returns the user data, if there is a signed-in user. examples: - - name: Get the logged in user + - name: Get the signed-in user isSpotlight: true code: | ```dart @@ -308,7 +308,7 @@ functions: - id: update-user title: 'updateUser()' description: | - Updates user data for a logged in user. + Updates user data for a signed-in user. notes: | - In order to use the `updateUser()` method, the user needs to be signed in first. - By Default, email updates sends a confirmation link to both the user's current and new email. @@ -750,7 +750,7 @@ functions: - id: parsing-custom-headers name: Parsing custom headers. description: | - Any `headers` will be passed through to the function. A common pattern is to pass a logged-in user's JWT token as an Authorization header. + Any `headers` will be passed through to the function. A common pattern is to pass a signed-in user's JWT token as an Authorization header. isSpotlight: true code: | ```dart diff --git a/apps/docs/spec/supabase_dart_v2.yml b/apps/docs/spec/supabase_dart_v2.yml index cb46b3999c742..8fba01c867319 100644 --- a/apps/docs/spec/supabase_dart_v2.yml +++ b/apps/docs/spec/supabase_dart_v2.yml @@ -121,7 +121,7 @@ functions: description: | Creates a new user. notes: | - - By default, the user needs to verify their email address before logging in. To turn this off, disable **Confirm email** in [your project](https://supabase.com/dashboard/project/_/auth/providers). + - By default, the user needs to verify their email address before signing in. To turn this off, disable **Confirm email** in [your project](https://supabase.com/dashboard/project/_/auth/providers). - **Confirm email** determines if users need to confirm their email address after signing up. - If **Confirm email** is enabled, a `user` is returned but `session` is null. - If **Confirm email** is disabled, both a `user` and a `session` are returned. @@ -363,7 +363,7 @@ functions: - id: sign-in-with-password title: 'signInWithPassword()' description: | - Log in an existing user using email or phone number with password. + Sign in an existing user using email or phone number with password. notes: | - Requires either an email and password or a phone number and password. params: @@ -977,7 +977,7 @@ functions: - id: register-passkey title: 'registerPasskey()' notes: | - Registers a new passkey (WebAuthn credential) for the signed in user. + Registers a new passkey (WebAuthn credential) for the signed-in user. - Available on `supabase_flutter` 2.15.0 and later as an extension on `GoTrueClient`. - Drives the full WebAuthn ceremony end to end: starts the registration with the Supabase server, calls the `authenticator` you supply to create a credential on the device, and verifies it with the server. - Requires a signed in (non-anonymous) user. If the user has verified MFA factors, the session has to be at `aal2` to manage passkeys. @@ -1011,7 +1011,7 @@ functions: - id: sign-out title: 'signOut()' description: | - Signs out the current user, if there is a logged in user. + Signs out the current user, if there is a signed-in user. notes: | - In order to use the `signOut()` method, the user needs to be signed in first. params: @@ -1233,9 +1233,9 @@ functions: - id: get-user title: 'currentUser' description: | - Returns the user data, if there is a logged in user. + Returns the user data, if there is a signed-in user. examples: - - name: Get the logged in user + - name: Get the signed-in user isSpotlight: true code: | ```dart @@ -1280,7 +1280,7 @@ functions: - id: update-user title: 'updateUser()' description: | - Updates user data for a logged in user. + Updates user data for a signed-in user. notes: | - In order to use the `updateUser()` method, the user needs to be signed in first. - By default, email updates sends a confirmation link to both the user's current and new email. @@ -2298,7 +2298,7 @@ functions: - id: passkey-list title: 'passkey.list()' notes: | - Returns the list of passkeys registered to the signed in user. + Returns the list of passkeys registered to the signed-in user. examples: - id: list-passkeys name: List the current user's passkeys @@ -2334,7 +2334,7 @@ functions: - id: passkey-delete title: 'passkey.delete()' notes: | - Deletes a passkey from the signed in user. + Deletes a passkey from the signed-in user. - If the user has verified MFA factors, the session has to be at `aal2` to manage passkeys. params: - name: passkeyId @@ -2354,7 +2354,7 @@ functions: - id: passkey-start-registration title: 'passkey.startRegistration()' notes: | - Starts the registration of a new passkey for the signed in user. + Starts the registration of a new passkey for the signed-in user. - Requires a signed in (non-anonymous) user. - Pass the returned `options` to the platform's passkey API to create the credential, then call [`passkey.verifyRegistration()`](/docs/reference/dart/auth-passkey-verifyregistration) with the result. - When the server omits `user.name`/`displayName` in the registration options, they are backfilled with `friendlyName` (or a generic `Passkey` default) before the platform ceremony. @@ -3269,7 +3269,7 @@ functions: - id: parsing-custom-headers name: Parsing custom headers. description: | - Any `headers` will be passed through to the function. A common pattern is to pass a logged-in user's JWT token as an Authorization header. + Any `headers` will be passed through to the function. A common pattern is to pass a signed-in user's JWT token as an Authorization header. isSpotlight: true code: | ```dart diff --git a/apps/docs/spec/supabase_js_v1.yml b/apps/docs/spec/supabase_js_v1.yml index 14946e1024664..d11dc4343e649 100644 --- a/apps/docs/spec/supabase_js_v1.yml +++ b/apps/docs/spec/supabase_js_v1.yml @@ -82,7 +82,7 @@ functions: title: 'signUp()' $ref: '@supabase/gotrue-js.GoTrueClient.signUp' notes: | - - By default, the user will need to verify their email address before logging in. If you would like to change this, you can disable "Email Confirmations" by going to Authentication -> Settings on [supabase.com/dashboard](https://supabase.com/dashboard) + - By default, the user will need to verify their email address before signing in. If you would like to change this, you can disable "Email Confirmations" by going to Authentication -> Settings on [supabase.com/dashboard](https://supabase.com/dashboard) - If "Email Confirmations" is turned on, a `user` is returned but `session` will be null - If "Email Confirmations" is turned off, both a `user` and a `session` will be returned - When the user confirms their email address, they will be redirected to localhost:3000 by default. To change this, you can go to Authentication -> Settings on [supabase.com/dashboard](https://supabase.com/dashboard) @@ -148,7 +148,7 @@ functions: - A user can sign up either via email or OAuth. - If you provide `email` without a `password`, the user will be sent a magic link. - The magic link's destination URL is determined by the SITE_URL config variable. To change this, you can go to Authentication -> Settings on [supabase.com/dashboard](https://supabase.com/dashboard) - - Specifying a `provider` will open the browser to the relevant login page. + - Specifying a `provider` will open the browser to the relevant sign-in page. examples: - id: sign-in-with-email-and-password name: Sign in with email and password @@ -192,10 +192,10 @@ functions: - id: sign-in-using-a-third-party-provider-with-redirect name: Sign in using a third-party provider with redirect description: | - Note that the `redirectTo` param is only relevant for OAuth logins, where the login flow is managed by - the Auth server. If you are using email/phone logins you should set up your own redirects (within the email/sms template). + Note that the `redirectTo` param is only relevant for OAuth sign-ins, where the sign-in flow is managed by + the Auth server. If you are using email/phone sign-ins you should set up your own redirects (within the email/sms template). - Sometimes you want to control where the user is redirected to after they are logged in. Supabase supports this for + Sometimes you want to control where the user is redirected to after they are signed in. Supabase supports this for any URL path on your website (the URL must either be on the same domain as your [Site URL](https://supabase.com/dashboard/project/_/auth/url-configuration) or match one of the Redirect URLs). See [redirect URLs and wildcards](/docs/guides/auth/redirect-urls#use-wildcards-in-redirect-urls) to add additional redirect URLs to your project. @@ -224,7 +224,7 @@ functions: - id: sign-in-with-refresh-token name: Sign in using a refresh token (e.g. in React Native). description: | - If you are completing a sign up or login in a React Native app you can pass the refresh token obtained from the provider to obtain a session. + If you are completing a sign up or sign-in in a React Native app you can pass the refresh token obtained from the provider to obtain a session. code: | ```js // An example using Expo's `AuthSession` @@ -273,7 +273,7 @@ functions: This method gets the user object from memory. examples: - id: - name: Get the logged in user + name: Get the signed-in user isSpotlight: true code: | ```js @@ -288,7 +288,7 @@ functions: To only send a confirmation link to the user's new email, disable **Secure email change** in your project's [email auth provider settings](https://supabase.com/dashboard/project/_/auth/providers). User metadata: It's generally better to store user data in a table within your public schema (i.e., `public.users`). - Use the `update()` method if you have data which rarely changes or is specific only to the logged in user. + Use the `update()` method if you have data which rarely changes or is specific only to the signed-in user. examples: - id: update-the-email-for-an-authenticated-user name: Update the email for an authenticated user @@ -737,7 +737,7 @@ functions: - id: passing-custom-headers name: Passing custom headers. description: | - You can pass custom headers to your Edge Function. Note: supabase-js automatically passes the `Authorization` header with the signed in user's JWT. + You can pass custom headers to your Edge Function. Note: supabase-js automatically passes the `Authorization` header with the signed-in user's JWT. isSpotlight: true code: | ```js diff --git a/apps/docs/spec/supabase_kt_v1.yml b/apps/docs/spec/supabase_kt_v1.yml index e8e869ea71ba2..4dd30b2de6eb7 100644 --- a/apps/docs/spec/supabase_kt_v1.yml +++ b/apps/docs/spec/supabase_kt_v1.yml @@ -29,7 +29,7 @@ functions: ### OAuth and OTP link verification [supabase-kt](https://github.com/supabase-community/supabase-kt) provides several platform implementations for OAuth and OTP link verification. \ - **On JVM**, it uses a HTTP Callback Server to receive the session data from a successful OAuth login. + **On JVM**, it uses a HTTP Callback Server to receive the session data from a successful OAuth sign-in. *Note: OTP link verification such as sign ups are not supported on JVM. You may have to send a verification token rather than a url in your E-Mail. To send the token, rather than a redirect url, you have to change `{{ .ConfirmationURL }}` in your sign up email to `{{ .Token }}`* @@ -63,7 +63,7 @@ functions: On Android: `supabase.handleDeeplinks(intent)` \ On IOS/macOS: `supabase.handleDeeplinks(url)` - Then you can just login using OAuth: + Then you can just sign in using OAuth: ```kotlin supabase.gotrue.loginWith(Google) ``` @@ -140,15 +140,15 @@ functions: **Desktop:** - `httpPort`: The port the web server is running on, when logging in with OAuth. Default: `0` (random port). + `httpPort`: The port the web server is running on, when signing in with OAuth. Default: `0` (random port). - `timeout`: The timeout for the web server, when logging in with OAuth. Default: `1.minutes`. + `timeout`: The timeout for the web server, when signing in with OAuth. Default: `1.minutes`. - `htmlTitle`: The title of the redirect page, when logging in with OAuth. Default: `"Supabase Auth"`. + `htmlTitle`: The title of the redirect page, when signing in with OAuth. Default: `"Supabase Auth"`. - `htmlText`: The text of the redirect page, when logging in with OAuth. Default: `"Logged in. You may continue in your app."`. + `htmlText`: The text of the redirect page, when signing in with OAuth. Default: `"Logged in. You may continue in your app."`. - `htmlIconUrl`: The icon of the redirect page, when logging in with OAuth. Default: `"https://supabase.com/brand-assets/supabase-logo-icon.png"`. + `htmlIconUrl`: The icon of the redirect page, when signing in with OAuth. Default: `"https://supabase.com/brand-assets/supabase-logo-icon.png"`. - id: configure-postgrest name: Configure PostgREST module code: | @@ -2094,10 +2094,10 @@ functions: $ref: '@supabase/gotrue-js.GoTrueClient.signUp' notes: | Creates a new user. - - By default, the user needs to verify their email address before logging in. To turn this off, disable **Confirm email** in [your project](https://supabase.com/dashboard/project/_/auth/providers). + - By default, the user needs to verify their email address before signing in. To turn this off, disable **Confirm email** in [your project](https://supabase.com/dashboard/project/_/auth/providers). - **Confirm email** determines if users need to confirm their email address after signing up. - - If **Confirm email** is enabled, the return value is the user and you won't be logged in automatically. - - If **Confirm email** is disabled, the return value is null and you will be logged in instead. + - If **Confirm email** is enabled, the return value is the user and you won't be signed in automatically. + - If **Confirm email** is disabled, the return value is null and you will be signed in instead. - When the user confirms their email address, they are redirected to the [`SITE_URL`](https://supabase.com/docs/guides/auth/redirect-urls) by default. You can modify your `SITE_URL` or add additional redirect URLs in [your project](https://supabase.com/dashboard/project/_/auth/url-configuration). - To learn how to handle OTP links & OAuth refer to [initializing](/docs/reference/kotlin/initializing) - If signUpWith() is called for an existing confirmed user: @@ -2345,7 +2345,7 @@ functions: title: 'Verify OTPs' $ref: '@supabase/gotrue-js.GoTrueClient.verifyOtp' notes: | - Log in a user given a User supplied OTP received via mobile. + Sign in a user given a User supplied OTP received via mobile. examples: - id: verify-email-otp(otp) name: Verify an Email OTP @@ -2447,7 +2447,7 @@ functions: - Should be used only when you require the most current user data. For faster results, `getCurrentSessionOrNull()?.user` is recommended. examples: - id: get-the-logged-in-user-with-the-current-existing-session - name: Get the logged in user with the current session + name: Get the signed-in user with the current session isSpotlight: true code: | ```kotlin @@ -2570,7 +2570,7 @@ functions: title: 'Send a password reset request' notes: | Sends a password reset request to the given email address. - - The password reset flow consist of 2 broad steps: (i) Allow the user to login via the password reset link; (ii) Update the user's password. + - The password reset flow consists of 2 broad steps: (i) Allow the user to sign in via the password reset link; (ii) Update the user's password. - The `sendRecoveryEmail()` only sends a password reset link to the user's email. To update the user's password, see [`modifyUser()`](/docs/reference/kotlin/auth-updateuser). - The user gets redirected back to your app, assuming you setup [OTP handling](/docs/reference/kotlin/initializing) @@ -2737,7 +2737,7 @@ functions: val enabledFlow = supabase.gotrue.mfa.isMfaEnabledFlow ``` - id: aal-enabled-for-current-session - name: Check whether the user is logged in using AAL2 + name: Check whether the user is signed in using AAL2 isSpotlight: true code: | ```kotlin diff --git a/apps/docs/spec/supabase_kt_v2.yml b/apps/docs/spec/supabase_kt_v2.yml index a42bb368f45ce..5681c7641f335 100644 --- a/apps/docs/spec/supabase_kt_v2.yml +++ b/apps/docs/spec/supabase_kt_v2.yml @@ -30,7 +30,7 @@ functions: [supabase-kt](https://github.com/supabase-community/supabase-kt) provides several platform implementations for OAuth and OTP link verification. - **On Desktop platforms (JVM, MacOS\*, Linux)**, it uses a HTTP Callback Server to receive the session data from a successful OAuth login. The success page can be customized via `AuthConfig#httpCallbackConfig` \ + **On Desktop platforms (JVM, MacOS\*, Linux)**, it uses a HTTP Callback Server to receive the session data from a successful OAuth sign-in. The success page can be customized via `AuthConfig#httpCallbackConfig` \ \* If no deeplinks are being used. *Note: OTP link verification such as sign ups are not supported on JVM. You may have to send a verification token rather than a url in your email. To send the token, rather than a redirect url, change `{{ .ConfirmationURL }}` in your sign up email to `{{ .Token }}`* @@ -66,7 +66,7 @@ functions: If you don't want a separate activity, just call this function at the top of your `onCreate` function in your MainActivity. \ On iOS/MacOS: `supabase.handleDeeplinks(url)` - Then you can log in using OAuth: + Then you can sign in using OAuth: ```kotlin supabase.auth.signInWith(Google) ``` @@ -182,15 +182,15 @@ functions: **Desktop:** - `httpPort`: The port the web server is running on, when logging in with OAuth. Default: `0` (random port). + `httpPort`: The port the web server is running on, when signing in with OAuth. Default: `0` (random port). - `timeout`: The timeout for the web server, when logging in with OAuth. Default: `1.minutes`. + `timeout`: The timeout for the web server, when signing in with OAuth. Default: `1.minutes`. - `htmlTitle`: The title of the redirect page, when logging in with OAuth. Default: `"Supabase Auth"`. + `htmlTitle`: The title of the redirect page, when signing in with OAuth. Default: `"Supabase Auth"`. - `htmlText`: The text of the redirect page, when logging in with OAuth. Default: `"Logged in. You may continue in your app."`. + `htmlText`: The text of the redirect page, when signing in with OAuth. Default: `"Logged in. You may continue in your app."`. - `htmlIconUrl`: The icon of the redirect page, when logging in with OAuth. Default: `"https://supabase.com/brand-assets/supabase-logo-icon.png"`. + `htmlIconUrl`: The icon of the redirect page, when signing in with OAuth. Default: `"https://supabase.com/brand-assets/supabase-logo-icon.png"`. - id: configure-postgrest name: Configure PostgREST module code: | @@ -2824,10 +2824,10 @@ functions: $ref: '@supabase/gotrue-js.GoTrueClient.signUp' notes: | Creates a new user. - - By default, the user needs to verify their email address before logging in. To turn this off, disable **Confirm email** in [your project](https://supabase.com/dashboard/project/_/auth/providers). + - By default, the user needs to verify their email address before signing in. To turn this off, disable **Confirm email** in [your project](https://supabase.com/dashboard/project/_/auth/providers). - **Confirm email** determines if users need to confirm their email address after signing up. - - If **Confirm email** is enabled, the return value is the user and you won't be logged in automatically. - - If **Confirm email** is disabled, the return value is null and you will be logged in instead. + - If **Confirm email** is enabled, the return value is the user and you won't be signed in automatically. + - If **Confirm email** is disabled, the return value is null and you will be signed in instead. - When the user confirms their email address, they are redirected to the [`SITE_URL`](https://supabase.com/docs/guides/auth/redirect-urls) by default. You can modify your `SITE_URL` or add additional redirect URLs in [your project](https://supabase.com/dashboard/project/_/auth/url-configuration). - To learn how to handle OTP links & OAuth refer to [initializing](/docs/reference/kotlin/initializing) - If signUpWith() is called for an existing confirmed user: @@ -3423,7 +3423,7 @@ functions: description: The JWT token. examples: - id: get-the-logged-in-user-with-the-current-existing-session - name: Get the logged in user with the current session + name: Get the signed-in user with the current session isSpotlight: true code: | ```kotlin @@ -3696,7 +3696,7 @@ functions: title: 'Send a password reset request' notes: | Sends a password reset request to the given email address. - - The password reset flow consist of 2 broad steps: (i) Allow the user to login via the password reset link; (ii) Update the user's password. + - The password reset flow consists of 2 broad steps: (i) Allow the user to sign in via the password reset link; (ii) Update the user's password. - The `resetPasswordForEmail()` only sends a password reset link to the user's email. To update the user's password, see [`updateUser()`](/docs/reference/kotlin/auth-updateuser). - The user gets redirected back to your app, assuming you setup [OTP handling](/docs/reference/kotlin/initializing) @@ -3962,7 +3962,7 @@ functions: val statusFlow = supabase.auth.mfa.statusFlow ``` - id: aal-enabled-for-current-session - name: Check whether the user is logged in using AAL2 + name: Check whether the user is signed in using AAL2 isSpotlight: true code: | ```kotlin diff --git a/apps/docs/spec/supabase_kt_v3.yml b/apps/docs/spec/supabase_kt_v3.yml index be7d643535dd4..c5dd7db3a28af 100644 --- a/apps/docs/spec/supabase_kt_v3.yml +++ b/apps/docs/spec/supabase_kt_v3.yml @@ -35,7 +35,7 @@ functions: The following will explain how each target handles OAuth and OTP link verification, if supported. - **On Desktop platforms (JVM, MacOS\*, Linux, Windows)**, it uses a HTTP Callback Server to receive the session data from a successful OAuth login. The success page can be customized via `AuthConfig#httpCallbackConfig` \ + **On Desktop platforms (JVM, MacOS\*, Linux, Windows)**, it uses a HTTP Callback Server to receive the session data from a successful OAuth sign-in. The success page can be customized via `AuthConfig#httpCallbackConfig` \ \* If no deeplinks are being used. This works as-is, by default. *Note: OTP link verification such as sign ups are not supported on JVM. You may have to send a verification token rather than a url in your email. To send the token, rather than a redirect url, change `{{ .ConfirmationURL }}` in your sign up email to `{{ .Token }}`* @@ -71,7 +71,7 @@ functions: If you don't want a separate activity, just call this function at the top of your `onCreate` function in your MainActivity. \ On iOS/MacOS: `supabase.handleDeeplinks(url)` - Then you can log in using OAuth: + Then you can sign in using OAuth: ```kotlin supabase.auth.signInWith(Google) ``` @@ -187,15 +187,15 @@ functions: **Desktop:** - `httpPort`: The port the web server is running on, when logging in with OAuth. Default: `0` (random port). + `httpPort`: The port the web server is running on, when signing in with OAuth. Default: `0` (random port). - `timeout`: The timeout for the web server, when logging in with OAuth. Default: `1.minutes`. + `timeout`: The timeout for the web server, when signing in with OAuth. Default: `1.minutes`. - `htmlTitle`: The title of the redirect page, when logging in with OAuth. Default: `"Supabase Auth"`. + `htmlTitle`: The title of the redirect page, when signing in with OAuth. Default: `"Supabase Auth"`. - `htmlText`: The text of the redirect page, when logging in with OAuth. Default: `"Logged in. You may continue in your app."`. + `htmlText`: The text of the redirect page, when signing in with OAuth. Default: `"Logged in. You may continue in your app."`. - `htmlIconUrl`: The icon of the redirect page, when logging in with OAuth. Default: `"https://supabase.com/brand-assets/supabase-logo-icon.png"`. + `htmlIconUrl`: The icon of the redirect page, when signing in with OAuth. Default: `"https://supabase.com/brand-assets/supabase-logo-icon.png"`. - id: configure-postgrest name: Configure PostgREST module code: | @@ -3010,10 +3010,10 @@ functions: $ref: '@supabase/gotrue-js.GoTrueClient.signUp' notes: | Creates a new user. - - By default, the user needs to verify their email address before logging in. To turn this off, disable **Confirm email** in [your project](https://supabase.com/dashboard/project/_/auth/providers). + - By default, the user needs to verify their email address before signing in. To turn this off, disable **Confirm email** in [your project](https://supabase.com/dashboard/project/_/auth/providers). - **Confirm email** determines if users need to confirm their email address after signing up. - - If **Confirm email** is enabled, the return value is the user and you won't be logged in automatically. - - If **Confirm email** is disabled, the return value is null and you will be logged in instead. + - If **Confirm email** is enabled, the return value is the user and you won't be signed in automatically. + - If **Confirm email** is disabled, the return value is null and you will be signed in instead. - When the user confirms their email address, they are redirected to the [`SITE_URL`](https://supabase.com/docs/guides/auth/redirect-urls) by default. You can modify your `SITE_URL` or add additional redirect URLs in [your project](https://supabase.com/dashboard/project/_/auth/url-configuration). - To learn how to handle OTP links & OAuth refer to [initializing](/docs/reference/kotlin/initializing) - If signUpWith() is called for an existing confirmed user: @@ -3628,7 +3628,7 @@ functions: description: The JWT token. examples: - id: get-the-logged-in-user-with-the-current-existing-session - name: Get the logged in user with the current session + name: Get the signed-in user with the current session isSpotlight: true code: | ```kotlin @@ -3931,7 +3931,7 @@ functions: title: 'Send a password reset request' notes: | Sends a password reset request to the given email address. - - The password reset flow consist of 2 broad steps: (i) Allow the user to login via the password reset link; (ii) Update the user's password. + - The password reset flow consists of 2 broad steps: (i) Allow the user to sign in via the password reset link; (ii) Update the user's password. - The `resetPasswordForEmail()` only sends a password reset link to the user's email. To update the user's password, see [`updateUser()`](/docs/reference/kotlin/auth-updateuser). - The user gets redirected back to your app, assuming you setup [OTP handling](/docs/reference/kotlin/initializing) @@ -4197,7 +4197,7 @@ functions: val statusFlow = supabase.auth.mfa.statusFlow ``` - id: aal-enabled-for-current-session - name: Check whether the user is logged in using AAL2 + name: Check whether the user is signed in using AAL2 isSpotlight: true code: | ```kotlin diff --git a/apps/docs/spec/supabase_py_v2.yml b/apps/docs/spec/supabase_py_v2.yml index 5b77ff8d10e44..36e420ec03384 100644 --- a/apps/docs/spec/supabase_py_v2.yml +++ b/apps/docs/spec/supabase_py_v2.yml @@ -52,11 +52,11 @@ functions: - name: persist_session isOptional: true type: bool - description: Whether to persist a logged in session to storage. + description: Whether to persist a signed-in session to storage. - name: storage isOptional: true type: SyncSupportedStorage - description: A storage provider. Used to store the logged in session. + description: A storage provider. Used to store the signed-in session. - name: realtime isOptional: true type: string @@ -157,7 +157,7 @@ functions: The channel to use for sending messages. Only for phone signups. notes: | - - By default, the user needs to verify their email address before logging in. To turn this off, disable **Confirm email** in [your project](https://supabase.com/dashboard/project/_/auth/providers). + - By default, the user needs to verify their email address before signing in. To turn this off, disable **Confirm email** in [your project](https://supabase.com/dashboard/project/_/auth/providers). - **Confirm email** determines if users need to confirm their email address after signing up. - If **Confirm email** is enabled, a `user` is returned but `session` is null. - If **Confirm email** is disabled, both a `user` and a `session` are returned. @@ -165,7 +165,7 @@ functions: - If sign_up() is called for an existing confirmed user: - When both **Confirm email** and **Confirm phone** (even when phone provider is disabled) are enabled in [your project](/dashboard/project/_/auth/providers), an obfuscated/fake user object is returned. - When either **Confirm email** or **Confirm phone** (even when phone provider is disabled) is disabled, the error message, `User already registered` is returned. - - To fetch the currently logged-in user, refer to [`get_user()`](/docs/reference/python/auth-getuser). + - To fetch the currently signed-in user, refer to [`get_user()`](/docs/reference/python/auth-getuser). examples: - id: signup name: Sign up with an email and password @@ -457,7 +457,7 @@ functions: isOptional: true type: string notes: | - Log in an existing user with an email and password or phone and password. + Sign in an existing user with an email and password or phone and password. - Requires either an email and password or a phone number and password. examples: - id: sign-in-with-email-and-password @@ -1235,7 +1235,7 @@ functions: - The User model includes the following fields (since v2.28.0): `is_sso_user` (bool, defaults to `False`), `deleted_at` (optional string), and `banned_until` (optional string) in addition to the existing fields. examples: - id: get-the-logged-in-user-with-the-current-existing-session - name: Get the logged in user with the current existing session + name: Get the signed-in user with the current existing session isSpotlight: true code: | ``` @@ -1275,7 +1275,7 @@ functions: } ``` - id: get-the-logged-in-user-with-a-custom-access-token-jwt - name: Get the logged in user with a custom access token jwt + name: Get the signed-in user with a custom access token jwt isSpotlight: false code: | ``` @@ -1861,7 +1861,7 @@ functions: isOptional: false type: string notes: | - Log in an existing user by exchanging an Auth Code issued during the PKCE flow. + Sign in an existing user by exchanging an Auth Code issued during the PKCE flow. - Used when `flow_type` is set to `pkce` in client options. examples: @@ -3088,7 +3088,7 @@ functions: type: string description: Verification token received when the user completes the captcha on the site. notes: | - - The password reset flow consist of 2 broad steps: (i) Allow the user to login via the password reset link; (ii) Update the user's password. + - The password reset flow consists of 2 broad steps: (i) Allow the user to sign in via the password reset link; (ii) Update the user's password. - The `reset_password_for_email()` only sends a password reset link to the user's email. To update the user's password, see [`update_user()`](/docs/reference/python/auth-updateuser). - When the user clicks the reset link in the email they are redirected back to your application. @@ -7320,7 +7320,7 @@ functions: description: | The library accepts custom headers via the `headers` option. - Note: `supabase-py` automatically populates the `Authorization` header if there is a signed in user. + Note: `supabase-py` automatically populates the `Authorization` header if there is a signed-in user. isSpotlight: true code: | ```python diff --git a/apps/docs/spec/supabase_swift_v1.yml b/apps/docs/spec/supabase_swift_v1.yml index 6251a84fa52ef..e7c455a60ee55 100644 --- a/apps/docs/spec/supabase_swift_v1.yml +++ b/apps/docs/spec/supabase_swift_v1.yml @@ -81,7 +81,7 @@ functions: - id: sign-up title: 'signUp()' notes: | - - By default, the user needs to verify their email address before logging in. To turn this off, disable **Confirm email** in [your project](/dashboard/project/_/auth/providers). + - By default, the user needs to verify their email address before signing in. To turn this off, disable **Confirm email** in [your project](/dashboard/project/_/auth/providers). - **Confirm email** determines if users need to confirm their email address after signing up. - If **Confirm email** is enabled, a `user` is returned but `session` is null. - If **Confirm email** is disabled, both a `user` and a `session` are returned. @@ -89,7 +89,7 @@ functions: - If signUp() is called for an existing confirmed user: - If **Confirm email** is enabled in [your project](/dashboard/project/_/auth/providers), an obfuscated/fake user object is returned. - If **Confirm email** is disabled, the error message, `User already registered` is returned. - - To fetch the currently logged-in user, refer to [`getUser()`](/docs/reference/swift/get-user). + - To fetch the currently signed-in user, refer to [`getUser()`](/docs/reference/swift/get-user). examples: - id: sign-up name: Sign up @@ -165,7 +165,7 @@ functions: title: 'signInWithOTP()' notes: | - This method is used for passwordless sign-ins where a OTP is sent to the user's email or phone number. - - If the user doesn't exist, `signInWithOTP()` will signup the user instead. To restrict this behavior, you can set `shouldCreateUser` to `false`. + - If the user doesn't exist, `signInWithOTP()` will sign up the user instead. To restrict this behavior, you can set `shouldCreateUser` to `false`. - If you're using an email, you can configure whether you want the user to receive a magiclink or a OTP. - If you're using phone, you can configure whether you want the user to receive a OTP. - The magic link's destination URL is determined by the [`SITE_URL`](/docs/guides/auth/redirect-urls). @@ -327,14 +327,14 @@ functions: - Should be used only when you require the most current user data. For faster results, `session.user` is recommended. examples: - id: get-the-logged-in-user-with-the-current-existing-session - name: Get the logged in user with the current existing session + name: Get the signed-in user with the current existing session isSpotlight: true code: | ```swift let user = try await supabase.auth.user() ``` - id: get-the-logged-in-user-with-a-custom-access-token-jwt - name: Get the logged in user with a custom access token jwt + name: Get the signed-in user with a custom access token jwt isSpotlight: false code: | ```swift @@ -2731,7 +2731,7 @@ functions: - id: passing-custom-headers name: Passing custom headers description: | - You can pass custom headers to your function. Note: supabase-js automatically passes the `Authorization` header with the signed in user's JWT. + You can pass custom headers to your function. Note: supabase-swift automatically passes the `Authorization` header with the signed-in user's JWT. isSpotlight: true code: | ```swift diff --git a/apps/docs/spec/supabase_swift_v2.yml b/apps/docs/spec/supabase_swift_v2.yml index 132a3fd12b50b..71a1178071189 100644 --- a/apps/docs/spec/supabase_swift_v2.yml +++ b/apps/docs/spec/supabase_swift_v2.yml @@ -224,7 +224,7 @@ functions: - If signUp() is called for an existing confirmed user: - When both **Confirm email** and **Confirm phone** (even when phone provider is disabled) are enabled in [your project](/dashboard/project/_/auth/providers), an obfuscated/fake user object is returned. - When either **Confirm email** or **Confirm phone** (even when phone provider is disabled) is disabled, the error message, `User already registered` is returned. - - To fetch the currently logged-in user, refer to [`getUser()`](/docs/reference/swift/get-user). + - To fetch the currently signed-in user, refer to [`getUser()`](/docs/reference/swift/get-user). overwriteParams: - name: email isOptional: true @@ -335,7 +335,7 @@ functions: - Check the [User Sessions](/docs/guides/auth/sessions) docs for more information. - Use this to clean up any local storage your application has associated with the user. - `TOKEN_REFRESHED` - - Emitted each time a new access and refresh token are fetched for the signed in user. + - Emitted each time a new access and refresh token are fetched for the signed-in user. - It's best practice and highly recommended to extract the access token (JWT) and store it in memory for further use in your application. - Avoid frequent calls to `supabase.auth.session` for the same purpose. - There is a background process that keeps track of when the session should be refreshed so you will always receive valid tokens by listening to this event. @@ -4741,7 +4741,7 @@ functions: - id: passing-custom-headers name: Passing custom headers description: | - You can pass custom headers to your function. Note: supabase-js automatically passes the `Authorization` header with the signed in user's JWT. + You can pass custom headers to your function. Note: supabase-swift automatically passes the `Authorization` header with the signed-in user's JWT. isSpotlight: true code: | ```swift diff --git a/apps/studio/components/interfaces/Linter/LintDetail.tsx b/apps/studio/components/interfaces/Linter/LintDetail.tsx index 4c55e559be0f3..e36ccce30ab67 100644 --- a/apps/studio/components/interfaces/Linter/LintDetail.tsx +++ b/apps/studio/components/interfaces/Linter/LintDetail.tsx @@ -95,7 +95,7 @@ export const LintDetail = ({ item.name === lint.name)?.docsLink || - `${DOCS_URL}/guides/database/database-linter` + `${DOCS_URL}/guides/observability/advisors` } target="_blank" rel="noreferrer" diff --git a/apps/studio/components/interfaces/Linter/Linter.utils.tsx b/apps/studio/components/interfaces/Linter/Linter.utils.tsx index a4e240fcc2e52..0796fb3fadd3e 100644 --- a/apps/studio/components/interfaces/Linter/Linter.utils.tsx +++ b/apps/studio/components/interfaces/Linter/Linter.utils.tsx @@ -33,7 +33,7 @@ export const lintInfoMap: LintInfo[] = [ link: ({ projectRef, metadata }) => `/project/${projectRef}/database/indexes?schema=${encodeURIComponent(metadata?.schema ?? '')}`, linkText: 'Create an index', - docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0001_unindexed_foreign_keys`, + docsLink: `${DOCS_URL}/guides/observability/advisors?queryGroups=lint&lint=0001_unindexed_foreign_keys`, category: 'performance', }, { @@ -42,7 +42,7 @@ export const lintInfoMap: LintInfo[] = [ icon: , link: ({ projectRef }) => `/project/${projectRef}/editor`, linkText: 'View table', - docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0002_auth_users_exposed`, + docsLink: `${DOCS_URL}/guides/observability/advisors?queryGroups=lint&lint=0002_auth_users_exposed`, category: 'security', }, { @@ -51,7 +51,7 @@ export const lintInfoMap: LintInfo[] = [ icon: , link: ({ projectRef }) => `/project/${projectRef}/database/policies`, linkText: 'View policies', - docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0003_auth_rls_initplan`, + docsLink: `${DOCS_URL}/guides/observability/advisors?queryGroups=lint&lint=0003_auth_rls_initplan`, category: 'performance', }, { @@ -60,7 +60,7 @@ export const lintInfoMap: LintInfo[] = [ icon: , link: ({ projectRef }) => `/project/${projectRef}/editor`, linkText: 'View table', - docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0004_no_primary_key`, + docsLink: `${DOCS_URL}/guides/observability/advisors?queryGroups=lint&lint=0004_no_primary_key`, category: 'performance', }, { @@ -70,7 +70,7 @@ export const lintInfoMap: LintInfo[] = [ link: ({ projectRef, metadata }) => `/project/${projectRef}/database/indexes?schema=${encodeURIComponent(metadata?.schema ?? '')}&table=${encodeURIComponent(metadata?.name ?? '')}`, linkText: 'View index', - docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0005_unused_index`, + docsLink: `${DOCS_URL}/guides/observability/advisors?queryGroups=lint&lint=0005_unused_index`, category: 'performance', }, { @@ -80,7 +80,7 @@ export const lintInfoMap: LintInfo[] = [ link: ({ projectRef, metadata }) => `/project/${projectRef}/database/policies?schema=${encodeURIComponent(metadata?.schema ?? '')}&search=${encodeURIComponent(metadata?.name ?? '')}`, linkText: 'View policies', - docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0006_multiple_permissive_policies`, + docsLink: `${DOCS_URL}/guides/observability/advisors?queryGroups=lint&lint=0006_multiple_permissive_policies`, category: 'performance', }, { @@ -90,7 +90,7 @@ export const lintInfoMap: LintInfo[] = [ link: ({ projectRef, metadata }) => `/project/${projectRef}/database/policies?schema=${encodeURIComponent(metadata?.schema ?? '')}&search=${encodeURIComponent(metadata?.name ?? '')}`, linkText: 'View policies', - docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0007_policy_exists_rls_disabled`, + docsLink: `${DOCS_URL}/guides/observability/advisors?queryGroups=lint&lint=0007_policy_exists_rls_disabled`, category: 'security', }, { @@ -100,7 +100,7 @@ export const lintInfoMap: LintInfo[] = [ link: ({ projectRef, metadata }) => `/project/${projectRef}/database/policies?schema=${encodeURIComponent(metadata?.schema ?? '')}&search=${encodeURIComponent(metadata?.name ?? '')}`, linkText: 'View table', - docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0008_rls_enabled_no_policy`, + docsLink: `${DOCS_URL}/guides/observability/advisors?queryGroups=lint&lint=0008_rls_enabled_no_policy`, category: 'security', }, { @@ -110,7 +110,7 @@ export const lintInfoMap: LintInfo[] = [ link: ({ projectRef, metadata }) => `/project/${projectRef}/database/indexes?schema=${encodeURIComponent(metadata?.schema ?? '')}&table=${encodeURIComponent(metadata?.name ?? '')}`, linkText: 'View index', - docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0009_duplicate_index`, + docsLink: `${DOCS_URL}/guides/observability/advisors?queryGroups=lint&lint=0009_duplicate_index`, category: 'performance', }, { @@ -118,9 +118,9 @@ export const lintInfoMap: LintInfo[] = [ title: 'Security Definer View', icon: , link: () => - `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0010_security_definer_view`, + `${DOCS_URL}/guides/observability/advisors?queryGroups=lint&lint=0010_security_definer_view`, linkText: 'View docs', - docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0010_security_definer_view`, + docsLink: `${DOCS_URL}/guides/observability/advisors?queryGroups=lint&lint=0010_security_definer_view`, category: 'security', }, { @@ -130,7 +130,7 @@ export const lintInfoMap: LintInfo[] = [ link: ({ projectRef, metadata }) => `/project/${projectRef}/database/functions?schema=${encodeURIComponent(metadata?.schema ?? '')}&search=${encodeURIComponent(metadata?.name ?? '')}`, linkText: 'View functions', - docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0011_function_search_path_mutable`, + docsLink: `${DOCS_URL}/guides/observability/advisors?queryGroups=lint&lint=0011_function_search_path_mutable`, category: 'security', }, { @@ -139,7 +139,7 @@ export const lintInfoMap: LintInfo[] = [ icon: , link: ({ projectRef }) => `/project/${projectRef}/auth/providers`, linkText: 'View settings', - docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0012_auth_allow_anonymous_sign_ins`, + docsLink: `${DOCS_URL}/guides/observability/advisors?queryGroups=lint&lint=0012_auth_allow_anonymous_sign_ins`, category: 'security', }, { @@ -149,7 +149,7 @@ export const lintInfoMap: LintInfo[] = [ link: ({ projectRef, metadata }) => `/project/${projectRef}/database/policies?schema=${encodeURIComponent(metadata?.schema ?? '')}&search=${encodeURIComponent(metadata?.name ?? '')}`, linkText: 'View policies', - docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0013_rls_disabled_in_public`, + docsLink: `${DOCS_URL}/guides/observability/advisors?queryGroups=lint&lint=0013_rls_disabled_in_public`, category: 'security', }, { @@ -159,7 +159,7 @@ export const lintInfoMap: LintInfo[] = [ link: ({ projectRef, metadata }) => `/project/${projectRef}/database/extensions?filter=${encodeURIComponent(metadata?.name ?? '')}`, linkText: 'View extension', - docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0014_extension_in_public`, + docsLink: `${DOCS_URL}/guides/observability/advisors?queryGroups=lint&lint=0014_extension_in_public`, category: 'security', }, { @@ -195,25 +195,25 @@ export const lintInfoMap: LintInfo[] = [ icon: , link: ({ projectRef }) => `/project/${projectRef}/database/policies`, linkText: 'View policies', - docsLink: `${DOCS_URL}/guides/database/database-linter?queryGroups=lint&lint=0015_rls_references_user_metadata`, + docsLink: `${DOCS_URL}/guides/observability/advisors?queryGroups=lint&lint=0015_rls_references_user_metadata`, category: 'security', }, { name: 'materialized_view_in_api', title: 'Materialized View in API', icon: , - link: () => `${DOCS_URL}/guides/database/database-advisors?lint=0016_materialized_view_in_api`, + link: () => `${DOCS_URL}/guides/observability/advisors?lint=0016_materialized_view_in_api`, linkText: 'View docs', - docsLink: `${DOCS_URL}/guides/database/database-advisors?lint=0016_materialized_view_in_api`, + docsLink: `${DOCS_URL}/guides/observability/advisors?lint=0016_materialized_view_in_api`, category: 'security', }, { name: 'foreign_table_in_api', title: 'Foreign Table in API', icon: , - link: () => `${DOCS_URL}/guides/database/database-linter?lint=0017_foreign_table_in_api`, + link: () => `${DOCS_URL}/guides/observability/advisors?lint=0017_foreign_table_in_api`, linkText: 'View docs', - docsLink: `${DOCS_URL}/guides/database/database-linter?lint=0017_foreign_table_in_api`, + docsLink: `${DOCS_URL}/guides/observability/advisors?lint=0017_foreign_table_in_api`, category: 'security', }, { @@ -221,9 +221,9 @@ export const lintInfoMap: LintInfo[] = [ title: 'Unsupported reg types', icon: , link: () => - `${DOCS_URL}/guides/database/database-advisors?lint=0018_unsupported_reg_types&queryGroups=lint`, + `${DOCS_URL}/guides/observability/advisors?lint=0018_unsupported_reg_types&queryGroups=lint`, linkText: 'View docs', - docsLink: `${DOCS_URL}/guides/database/database-advisors?lint=0018_unsupported_reg_types&queryGroups=lint`, + docsLink: `${DOCS_URL}/guides/observability/advisors?lint=0018_unsupported_reg_types&queryGroups=lint`, category: 'security', }, { @@ -333,7 +333,7 @@ export const lintInfoMap: LintInfo[] = [ link: ({ projectRef, metadata }) => `/project/${projectRef}/editor?schema=${encodeURIComponent(metadata?.schema ?? '')}&table=${encodeURIComponent(metadata?.name ?? '')}`, linkText: 'View table', - docsLink: `${DOCS_URL}/guides/database/database-linter?lint=0023_sensitive_columns_exposed`, + docsLink: `${DOCS_URL}/guides/observability/advisors?lint=0023_sensitive_columns_exposed`, category: 'security', }, { @@ -343,7 +343,7 @@ export const lintInfoMap: LintInfo[] = [ link: ({ projectRef, metadata }) => `/project/${projectRef}/database/policies?schema=${encodeURIComponent(metadata?.schema ?? '')}&search=${encodeURIComponent(metadata?.name ?? '')}`, linkText: 'View policies', - docsLink: `${DOCS_URL}/guides/database/database-linter?lint=0024_permissive_rls_policy`, + docsLink: `${DOCS_URL}/guides/observability/advisors?lint=0024_permissive_rls_policy`, category: 'security', }, { @@ -355,7 +355,7 @@ export const lintInfoMap: LintInfo[] = [ return `/project/${projectRef}/storage/files/buckets/${encodeURIComponent(bucketId ?? metadata?.name ?? '')}` }, linkText: 'View bucket', - docsLink: `${DOCS_URL}/guides/database/database-linter?lint=0025_public_bucket_allows_listing`, + docsLink: `${DOCS_URL}/guides/observability/advisors?lint=0025_public_bucket_allows_listing`, category: 'security', }, { @@ -365,7 +365,7 @@ export const lintInfoMap: LintInfo[] = [ link: ({ projectRef, metadata }) => `/project/${projectRef}/editor?schema=${encodeURIComponent(metadata?.schema ?? '')}&table=${encodeURIComponent(metadata?.name ?? '')}`, linkText: 'View object', - docsLink: `${DOCS_URL}/guides/database/database-linter?lint=0026_pg_graphql_anon_table_exposed`, + docsLink: `${DOCS_URL}/guides/observability/advisors?lint=0026_pg_graphql_anon_table_exposed`, category: 'security', }, { @@ -375,7 +375,7 @@ export const lintInfoMap: LintInfo[] = [ link: ({ projectRef, metadata }) => `/project/${projectRef}/editor?schema=${encodeURIComponent(metadata?.schema ?? '')}&table=${encodeURIComponent(metadata?.name ?? '')}`, linkText: 'View object', - docsLink: `${DOCS_URL}/guides/database/database-linter?lint=0027_pg_graphql_authenticated_table_exposed`, + docsLink: `${DOCS_URL}/guides/observability/advisors?lint=0027_pg_graphql_authenticated_table_exposed`, category: 'security', }, { @@ -385,7 +385,7 @@ export const lintInfoMap: LintInfo[] = [ link: ({ projectRef, metadata }) => `/project/${projectRef}/database/functions?schema=${encodeURIComponent(metadata?.schema ?? '')}&search=${encodeURIComponent(metadata?.name ?? '')}`, linkText: 'View function', - docsLink: `${DOCS_URL}/guides/database/database-linter?lint=0028_anon_security_definer_function_executable`, + docsLink: `${DOCS_URL}/guides/observability/advisors?lint=0028_anon_security_definer_function_executable`, category: 'security', }, { @@ -395,7 +395,7 @@ export const lintInfoMap: LintInfo[] = [ link: ({ projectRef, metadata }) => `/project/${projectRef}/database/functions?schema=${encodeURIComponent(metadata?.schema ?? '')}&search=${encodeURIComponent(metadata?.name ?? '')}`, linkText: 'View function', - docsLink: `${DOCS_URL}/guides/database/database-linter?lint=0029_authenticated_security_definer_function_executable`, + docsLink: `${DOCS_URL}/guides/observability/advisors?lint=0029_authenticated_security_definer_function_executable`, category: 'security', }, // Health lints report on the running project rather than on schema, so they link to the diff --git a/apps/studio/components/interfaces/Linter/LinterPageFooter.tsx b/apps/studio/components/interfaces/Linter/LinterPageFooter.tsx index 2f89c3047cacf..fdeead296c440 100644 --- a/apps/studio/components/interfaces/Linter/LinterPageFooter.tsx +++ b/apps/studio/components/interfaces/Linter/LinterPageFooter.tsx @@ -87,7 +87,7 @@ export const LinterPageFooter = ({ )} diff --git a/apps/studio/components/interfaces/QueryPerformance/WithStatements/WithStatements.tsx b/apps/studio/components/interfaces/QueryPerformance/WithStatements/WithStatements.tsx index 1d22c5fadf3f2..e843a0a5eeec8 100644 --- a/apps/studio/components/interfaces/QueryPerformance/WithStatements/WithStatements.tsx +++ b/apps/studio/components/interfaces/QueryPerformance/WithStatements/WithStatements.tsx @@ -297,7 +297,7 @@ export const WithStatements = ({ diff --git a/apps/studio/components/interfaces/Settings/API/UnsafeEntitiesConfirmModal.tsx b/apps/studio/components/interfaces/Settings/API/UnsafeEntitiesConfirmModal.tsx index 5a4edd6da23a5..7fad3486f1a2a 100644 --- a/apps/studio/components/interfaces/Settings/API/UnsafeEntitiesConfirmModal.tsx +++ b/apps/studio/components/interfaces/Settings/API/UnsafeEntitiesConfirmModal.tsx @@ -21,28 +21,28 @@ const ENTITY_TYPE_META: Record< heading: 'Tables without Row Level Security', recommendation: 'Enable RLS on these tables to control access per-row.', docsUrl: - 'https://supabase.com/docs/guides/database/database-linter?lint=0013_rls_disabled_in_public', + 'https://supabase.com/docs/guides/observability/advisors?lint=0013_rls_disabled_in_public', }, 'foreign table': { heading: 'Foreign tables', recommendation: 'Foreign tables do not support RLS. Revoke access from the anon and authenticated roles.', docsUrl: - 'https://supabase.com/docs/guides/database/database-linter?lint=0017_foreign_table_in_api', + 'https://supabase.com/docs/guides/observability/advisors?lint=0017_foreign_table_in_api', }, 'materialized view': { heading: 'Materialized views', recommendation: 'Materialized views do not support RLS. Revoke access from the anon and authenticated roles.', docsUrl: - 'https://supabase.com/docs/guides/database/database-linter?lint=0016_materialized_view_in_api', + 'https://supabase.com/docs/guides/observability/advisors?lint=0016_materialized_view_in_api', }, view: { heading: 'Views without SECURITY INVOKER', recommendation: 'These views run with the permissions of the view creator, not the querying user. Set SECURITY INVOKER to enforce caller permissions.', docsUrl: - 'https://supabase.com/docs/guides/database/database-linter?lint=0010_security_definer_view', + 'https://supabase.com/docs/guides/observability/advisors?lint=0010_security_definer_view', }, } diff --git a/apps/studio/lib/ai/prompts.ts b/apps/studio/lib/ai/prompts.ts index c92ea1efe3649..ec5c277130587 100644 --- a/apps/studio/lib/ai/prompts.ts +++ b/apps/studio/lib/ai/prompts.ts @@ -371,11 +371,11 @@ export const PG_BEST_PRACTICES = ` - After creating a table, check and configure Data API access and RLS before use (see the "Exposing a Table to the Data API" section in RLS knowledge for the full workflow). - Define foreign key references within the \`CREATE TABLE\` statement. - Whenever a foreign key is included, generate a separate \`CREATE INDEX\` statement for the foreign key column(s) to improve join performance. -- **Foreign Tables:** Place foreign tables in a schema named \`private\` (create the schema if needed). Explain the security risk (RLS bypass) and include a link: https://supabase.com/docs/guides/database/database-advisors?queryGroups=lint&lint=0017_foreign_table_in_api. +- **Foreign Tables:** Place foreign tables in a schema named \`private\` (create the schema if needed). Explain the security risk (RLS bypass) and include a link: https://supabase.com/docs/guides/observability/advisors?queryGroups=lint&lint=0017_foreign_table_in_api. ### Views - Add \`with (security_invoker=on)\` immediately after \`CREATE VIEW view_name\`. -- **Materialized Views:** Store materialized views in the \`private\` schema (create if needed). Explain the security risk (RLS bypass) and reference: https://supabase.com/docs/guides/database/database-advisors?queryGroups=lint&lint=0016_materialized_view_in_api. +- **Materialized Views:** Store materialized views in the \`private\` schema (create if needed). Explain the security risk (RLS bypass) and reference: https://supabase.com/docs/guides/observability/advisors?queryGroups=lint&lint=0016_materialized_view_in_api. ### Extensions - Always install extensions in the \`extensions\` schema or a dedicated schema; never in \`public\`. diff --git a/apps/studio/lib/ai/tools/mock-tools.ts b/apps/studio/lib/ai/tools/mock-tools.ts index 6d586a04e454a..4ab6899066cf4 100644 --- a/apps/studio/lib/ai/tools/mock-tools.ts +++ b/apps/studio/lib/ai/tools/mock-tools.ts @@ -92,7 +92,7 @@ const MOCK_ADVISORIES_DATA = [ category: 'security', message: 'Materialized views in API schema can bypass RLS. Move them to private schema.', remediationUrl: - 'https://supabase.com/docs/guides/database/database-advisors?queryGroups=lint&lint=0016_materialized_view_in_api', + 'https://supabase.com/docs/guides/observability/advisors?queryGroups=lint&lint=0016_materialized_view_in_api', }, { id: '0031_functions_no_rls_guard', @@ -100,7 +100,7 @@ const MOCK_ADVISORIES_DATA = [ category: 'security', message: 'Function api.health_check should verify auth context before querying tables.', remediationUrl: - 'https://supabase.com/docs/guides/database/database-advisors?queryGroups=lint&lint=0031_functions_no_rls_guard', + 'https://supabase.com/docs/guides/observability/advisors?queryGroups=lint&lint=0031_functions_no_rls_guard', }, { id: '1012_slow_query', diff --git a/apps/studio/pages/project/[ref]/advisors/performance.tsx b/apps/studio/pages/project/[ref]/advisors/performance.tsx index 27b3d9154480c..8b589bae1bf39 100644 --- a/apps/studio/pages/project/[ref]/advisors/performance.tsx +++ b/apps/studio/pages/project/[ref]/advisors/performance.tsx @@ -73,7 +73,7 @@ const ProjectLints: NextPageWithLayout = () => { { {/* Main container — indented 1 col at lg, alongside back button at xl */} -
    +
    {/* Article header — spans the full main container width */}
    @@ -202,7 +202,7 @@ const BlogPostRenderer = async ({ )}
    -
    +
    {blogMetaData.youtubeHero ? (