Commit Graph
38499 Commits
Author SHA1 Message Date
Gildas Garcia 63bedef77f MFA Recovery codes: allow users to download their recovery codes (#50267)
## What kind of change does this PR introduce?

After users have set up a new MFA (first or not), we must:

- check whether recovery codes have already been generated
- if there are none, generate recovery codes and display them, "forcing"
users to copy them
- if already generated, show them how many are still available

> [!NOTE]
> The _Delete my recovery codes_ button in last screenshot only appear
on local and staging environments

## How to test

- On an account that doesn't have recovery codes generated yet and has
an MFA added
- You should see an admonition suggesting to generate the codes

## Screenshots

<img width="729" height="306" alt="image"
src="https://github.com/user-attachments/assets/79ba3870-4ef8-4571-9fd6-36eed20c9c24"
/>

<img width="550" height="356" alt="image"
src="https://github.com/user-attachments/assets/1632611a-996a-470d-b6cd-a4693b0f4602"
/>

<img width="719" height="205" alt="image"
src="https://github.com/user-attachments/assets/73cef611-05cf-4fac-bbd2-243f9b28e48d"
/>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Added support for generating, copying, and confirming MFA recovery
codes.
- Added recovery-code status visibility, including remaining and
exhausted codes.
  - Added the ability to delete recovery codes with confirmation.
- Added clear loading, success, and error states for recovery-code
actions.
  - Recovery-code status refreshes after codes are generated or deleted.

- **Bug Fixes**
- Recovery-code notices now remain visible when all codes have been
used.
  - Recovery-code dialogs can now be closed after generation errors.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 11:16:47 +02:00
Jordi Enric 24f8549e41 fix(studio): open edge function logs from chart clicks FE-3922 (#50364)
## Problem

Clicking an invocation bar on the Edge Function overview did not
preserve the selected chart segment, so the destination could not open a
focused investigation window.

## Fix

Forward the clicked bar timestamp and navigate to Logs or Invocations
with an encoded, focused time range. Share the existing chart range
calculation and add real Recharts interaction coverage.

## How to test

- Open an Edge Function Overview page with invocation data.
- Click a populated bar in the Total Invocations chart.
- Expected result: Logs or Invocations opens with its and ite query
parameters centered on the clicked bar.
- Repeat with unified logs enabled and disabled to verify both
destinations.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Clicking a bar in the Edge Function invocations chart now opens the
relevant logs or invocations view.
- The destination is focused on a time window surrounding the selected
invocation, making investigation faster.
- Chart bars now provide a pointer cursor to indicate they are
interactive.

- **Bug Fixes**
- Chart clicks without valid invocation data no longer trigger incorrect
navigation.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 11:06:37 +02:00
Ali Waseem 56820eb048 fix(studio): use configured gp3 max-throughput ceiling (#50355)
`calculateMaxThroughput` still hard-capped at 1000 MB/s while
`DISK_LIMITS.gp3.maxThroughput` moved to 2000, so large gp3 disks were
rejected with a misleading "Need at least N IOPS to support X MB/s"
error even when IOPS and compute were already sufficient. Now reads the
configured ceiling, mirroring the IOPS fix in #50269 that missed this
sibling.

Fixes FE-4385

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- GP3 storage configurations can now support throughput scaling up to
2,000 MB/s when sufficient compute capacity is available.
- Larger GP3 configurations, including up to 4,096 GB with 80,000 IOPS
and 2,000 MB/s throughput, are now recognized as valid when capacity
requirements are met.

- **Bug Fixes**
- Corrected the maximum GP3 throughput calculation to honor the
supported service limit.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 17:00:10 +08:00
Jake Ng 608c3a0813 chore(docs): add Jake Ng to humans.txt (#50378)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Add Jake Ng to humans.txt

## What is the current behavior?

Jake Ng is not in humans.txt

## What is the new behavior?

Jake Ng has joined Supabase

## Additional context

Done as part of the onboarding tasks.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Added Jake Ng to the team member list in the public contributor
information.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 10:38:28 +02:00
Joshen Lim ad5202d53d Joshenlim/fe 4378 update editorpanel save cta when explorer is enabled (#50324)
## Context

Swaps out the "Save as snippet" CTA in the `EditorPanel` to the "Save to
notebook" dropdown CTA if explorer is enabled
<img width="488" height="147" alt="image"
src="https://github.com/user-attachments/assets/915017a1-c416-4904-8146-b0695244d2bd"
/>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a save-query dropdown in Explorer for creating a new notebook or
adding a query to an existing notebook.
* Added notebook search, loading states, and empty-state messaging when
selecting an existing notebook.
  * Saved queries now open in the selected notebook after insertion.

* **Improvements**
  * Added an accessible label to the query title input.
* Updated query-saving controls to appear appropriately when Explorer is
enabled.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 16:26:44 +08:00
Raúl Barroso cad51d85fd docs: give your app an MCP server (BYO-MCP guide rewrite) (#50218)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Fixes AI-1009

Updates the BYO-MCP guide so it includes information about the new
middleware that will let users authenticate much more easily when
building their own MCP server. This one includes a couple of
clarifications which are important to document (use of environment
variables, etc.)

## What is the new behavior?


- Updated the existing guide (and example) for deploying an MCP server
to use `@modelcontextprotocol/server` v2 with `createMcpHandler`.
- Added new bits related to the new middleware which helps with
authentication specifying the required versions of supabase/server and
supabase/middleware, and also the auth prerequisites
- Includes a table of where each MCP client takes the URL.
- Added a new example to
`examples/edge-functions/supabase/functions/mcp/` to illustrate the
authentication example `authenticated-mcp-server`.

## Publish order

> [!IMPORTANT]  
> There will be a companion PR to include the library components so this
PR is blocked until https://github.com/supabase/supabase/pull/49579
ships.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added comprehensive guidance for deploying authenticated MCP servers
with OAuth 2.1, Supabase Auth, and user-scoped data access.
* Added an authenticated MCP server example with `list_todos` and
`create_todo` tools, protected by row-level security.
* Added setup instructions for OAuth configuration, consent screens,
local testing, and deployment.

* **Documentation**
* Updated authentication guidance and MCP security warnings across
related guides.
  * Added links to MCP server and OAuth consent resources.

* **Refactor**
* Simplified the unauthenticated MCP server example and updated its
tooling configuration.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 09:45:14 +02:00
Joshen Lim 1caeb92122 Editor panel fix save snippet (#50262)
## Context

Currently hitting "Save snippet" in the Editor panel doesn't actually do
anything - happening because it's using the legacy `needSaving` queue
logic that we had before manual saving became the default. Tiny fix to
just call `requestSave` instead
<img width="469" height="484" alt="image"
src="https://github.com/user-attachments/assets/66c8fd41-9e7c-44ad-8bb0-cdea8de68bd2"
/>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Improvements**
- Saving a snippet now updates the SQL editor with the latest content
automatically.
- New snippets created from the expanded editor or save dialog are saved
through the standard save flow.

- **Accessibility**
- Added an accessible label to the snippet name field for improved
screen reader support.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 15:35:31 +08:00
Julian Domke 17280319f0 chore(billing): remove invoice type casts (#50338) 2026-09-15 09:16:51 +02:00
Joshen Lim 558bee9ebf Improve SQL Editor auto completion for column names (#48734)
## Context

Currently with the SQL Editor, the auto-completion via intellisense only
works nicely with the `.` operator - e.g after keying in a schema and
trying to find a table as such:
<img width="500" alt="image"
src="https://github.com/user-attachments/assets/86ec8455-47b9-43d3-925a-c13d0fd6ac44"
/>

But lacks support for finding the columns of a table after a `where`
clause - so the changes here addresses that by mainly adjust the
`PgSQLCompletionProvider`

Also addresses a number of type fixes (replaces all the `any` types)

<img width="500" alt="image"
src="https://github.com/user-attachments/assets/e23672a6-2b48-4a98-b300-69f822d12b38"
/>

<img width="415" height="319" alt="image"
src="https://github.com/user-attachments/assets/e6ee64d2-90dd-47d6-9fd2-e8b07821ebb6"
/>



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Improved PostgreSQL SQL editor suggestions with table, column, alias,
schema, and join-aware completions.
* Added context-aware support for statements, quoted identifiers,
subqueries, and qualified columns.
  * Enhanced PostgreSQL function signature assistance.
* Added safer behavior when database metadata is incomplete or
unavailable.

* **Bug Fixes**
  * Prioritized relevant columns and removed duplicate suggestions.

* **Tests**
* Added comprehensive coverage for SQL parsing, metadata handling, and
completion behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 12:34:20 +08:00
Miranda Limonczenko 4d57edd622 docs(database): add data type guidance to the tables guide (#50025)
Refs FDBKIN-4668

Part 5 of a 5-PR stack on
`apps/docs/content/guides/database/tables.mdx`. Builds on #50024.

## Problem

Reader feedback in FDBKIN-4668 reports developers mixing `timestamptz`
and `timestamp` across production schemas for lack of guidance. This PR
adds the guidance half of that ask. The issue also asks for linting in
the schema designer, which is a Frontend change and stays open.

The page listed 44 data types and recommended neither side of any pair a
reader actually has to choose between: `timestamp` or `timestamptz`,
`varchar` or `text`, `numeric` or `float`, `integer` or `bigint`.

No example on the page had a timestamp column at all, and `timestamptz`
appeared only inside the reference table.

## Solution

Adds a short "Choosing a type" section to the Reference group, stating a
safe default for each pair and why.

Also changes `salary bigint` to `salary numeric` in the private schema
example. That line was checked against the wrong-outcome test in #50023
and deliberately left there, because a reader storing cents in a
`bigint` gets a working table. It changes here because **this branch is
what makes it wrong**: once the page recommends `numeric` for money, an
example doing the opposite two screens away teaches the reader the
opposite of what the page just said.

## Manual testing

Preview:
https://docs-git-docs-tables-datatypes-supabase.vercel.app/docs/guides/database/tables#choosing-a-type

1. Open the preview at that anchor. "Choosing a type" renders above the
data type table.
2. Open `#data-types` on the same preview. It still lands on the
reference table, which Studio deep-links to from three components.
3. In a local database, insert `1234.56` into `private.salaries.salary`
and select `salary * 3`. Returns `3703.68` exactly.

## Verification (`test-the-docs`)

Run in the Compose sandbox against a local stack.

| Check | Result |
| --- | --- |
| `create table private.salaries` with `salary numeric` | pass |
| `insert ... values (1234.56, ...)` then `select salary, salary * 3` |
pass — returns `1234.56` and `3703.68`, exact |

The same example failed to run at all before this stack, because
`public.actors` didn't exist on the page's path. #50023 fixes that.




<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Documentation**
- Updated the Postgres tables guide with practical guidance for choosing
column types.
- Added recommendations for timestamps, text, monetary and decimal
values, and identifiers.
- Updated the example salary column to use the `numeric` type instead of
`bigint`.
- Expanded the column type reference section to help readers select
appropriate types for common data.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 19:50:23 -07:00
Ivan Vasilov 944d7730cd chore: Disable the msw logs in Github actions (#50365)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Tests**
  - Reduced diagnostic logging during automated CI test runs.
- Request, mock, and request-handling details remain available in non-CI
environments for troubleshooting.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 10:40:27 +08:00
Danny WhiteandJoshen Lim 1755580dcf feat(studio): move Warehouse setup into Integrations (#50247)
## What kind of change does this PR introduce?

Feature and information architecture change. Builds on #50246.

## What is the current behaviour?

Warehouse setup, progress, errors, table selection, and connection
details all live in the transient Connect sheet. Closing the sheet hides
the current replication state, and the integration is absent from the
Integrations page.

## What is the new behaviour?

Warehouse now has a persistent Overview page at
`/project/{ref}/integrations/warehouse/overview`:

- Before setup, the existing schema and table picker enables Warehouse.
- During setup, the page shows the current phase and per-table backfill
state where available.
- Setup and status failures remain visible on the page with retry
actions where possible.
- Once complete, the page shows Status, Tables, then Connect.
- The Connect sheet becomes read-only. Before Warehouse is ready, it
links directly to the Overview page for setup, progress, or recovery.

| Before | After |
| --- | --- |
| <img width="1200" height="907" alt="Chives Pantry Supabase"
src="https://github.com/user-attachments/assets/82dc7fb0-3859-499e-96ab-56f70a5c7325"
/> | <img width="1200" height="907" alt="Chives Pantry Supabase"
src="https://github.com/user-attachments/assets/7428e301-27f8-48fe-91e0-6880b132920d"
/> |
| <img width="1200" height="907" alt="Chives Pantry Supabase"
src="https://github.com/user-attachments/assets/82dc7fb0-3859-499e-96ab-56f70a5c7325"
/> | <img width="1200" height="907" alt="54709"
src="https://github.com/user-attachments/assets/0c589e5b-e13c-4554-a6ee-6730d0e95c07"
/> |
| <img width="1200" height="907" alt="ETL BigTable ETL Team Supabase"
src="https://github.com/user-attachments/assets/18ec9f6c-3724-453f-bbbb-c7149758246e"
/> | <img width="1200" height="907" alt="Regular AWS Teamer Supabase"
src="https://github.com/user-attachments/assets/3819c9fe-e56d-4cec-988d-5e724f8d990a"
/> |

## To test

Use a project whose organisation is included in the Warehouse
allow-list.

1. Open `/project/{ref}/integrations`, filter by **Data platform**, and
open Warehouse.
2. Before setup, confirm the existing schema and table picker appears
and starts with no tables selected.
3. Start setup and confirm the Status section polls through setup and
table backfill phases.
4. Confirm setup failures remain visible and expose Retry when the API
returns affected tables.
5. After setup, confirm the section order is Status, Tables, Connect.
6. Confirm existing replicated tables are selected and locked, while
additional tables can be added.
7. Open `/project/{ref}?showConnect=true&connectTab=warehouse` and
confirm it links to the Overview page before setup, during setup, and
after a setup failure.
8. Once setup is complete, confirm the Connect sheet shows the FlightSQL
and DuckDB connection controls from #50246.
9. Repeat the Overview checks with **One-Click Integrations** turned
off.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added Supabase Warehouse to the integrations catalog, with overview
documentation and availability-aware display.
* Added Warehouse setup and management flows, including schema and table
selection, replication progress, status details, connection options, and
retry actions.
* Added DuckDB and FlightSQL engine selection with Connect sheet URL and
preference synchronization.
* Added table replication status, lag, timestamps, and size information.

* **Bug Fixes**
* Warehouse setup status requests no longer retry automatically after
failures.
* Improved recovery messaging and retry behavior for setup and
connection errors.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-09-15 12:38:13 +10:00
Joshen Lim ad198b15ab Joshenlim/fe 4376 improve storage log overview and field filtering (#50337)
## Context

Updates the `getValue` for retrieving data from `enrichedData` in
`serviceFlowFields` to pull the appropriate fields for storage logs.

### Before
<img width="403" height="342" alt="image"
src="https://github.com/user-attachments/assets/b9a8e501-79bc-4ed2-ad1e-dd57f55a091e"
/>


### After
<img width="413" height="411" alt="image"
src="https://github.com/user-attachments/assets/8e87c352-ecf8-4246-b5b7-3b4d16274b06"
/>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Expanded log details to display more network, location, technology,
and storage information from available request and response data.
* Added support for additional response-time formats, including valid
zero-duration values.

* **Bug Fixes**
  * Improved truncation and alignment of log detail values.
  * Enhanced accessibility for the “More options” control.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 10:24:18 +08:00
Miranda Limonczenko ef3cfad9ed docs(database): add access control to the tables guide (#50024)
Closes DOCS-1314

Brings the Eval to green.

Part 4 of a 5-PR stack on
`apps/docs/content/guides/database/tables.mdx`. Builds on #50023.

## Problem

The page taught table creation and never said to protect a table. Across
the original 573 lines, "row level security" appeared once, and that
mention was about `security_invoker` on views. There was no `enable row
level security`, no policy, and no `auth.uid()` anywhere.

The gap was uneven between the two paths the page offers. The Table
Editor enables row level security by default and warns that a table
without it is publicly writable and readable. The SQL path on the same
page produced an unprotected table and said nothing about it.

Two further gaps followed from that one:

- **Every example was a single access class.** `movies`, `categories`,
`actors`, `performances`, and `private.salaries` are all the same shape.
The page had no pattern for what most applications actually look like: a
shared table everyone reads sitting beside a per-person table only its
owner reads. The shared one is the one that gets skipped.
- **Nothing told the reader to check the result.** No verify, no
confirm, and no expected output anywhere on the page.

## Solution

Adds a "Securing your tables" section between creating a table and
loading data:

- Enabling row level security and writing a first policy, with the
consequence stated: a table with row level security and no policy
returns no rows to anyone.
- A worked example with two access classes, `movies` and `watchlists`.
- A verification step. Two queries against `pg_tables` and `pg_policies`
confirm that every table exists, has row level security enabled, and has
at least one policy.

Policy examples follow the idioms in the Row Level Security guide,
including the wrapped `(select auth.uid())` form. The guide is
cross-referenced rather than restated.

## Verification (`test-the-docs`)

All 22 SQL fences on the page were run in document order against a local
stack, the way a reader pasting top to bottom would.

| Snippet / step | Class | Result | Notes |
| --- | --- | --- | --- |
| `create table movies` (Creating tables) | runnable-local | pass | |
| `create table movies` ×2 (Primary keys) | illustrative-only | skipped
| Re-shows the same table to explain `identity`; not a continuation |
| `alter table movies enable row level security` | runnable-local | pass
| |
| `create policy "Anyone can read movies"` | runnable-local | pass | |
| `create table watchlists` + 2 policies | runnable-local | pass | |
| Verification query, `pg_tables` | runnable-local | pass | Lists both
tables with `rowsecurity` true |
| Verification query, `pg_policies` | runnable-local | pass | Lists all
three policies |
| `insert into movies` (Basic data loading) | runnable-local | pass | |
| `create table categories` + foreign key | runnable-local | pass | |
| `create table actors` / `performances` | runnable-local | pass |
Failed before this stack; see below |
| `create schema private` | runnable-local | pass | |
| `create table private.salaries` | runnable-local | pass | Failed
before this stack; see below |
| Views section, 9 fences | illustrative-only | skipped | Depend on
`students`, `courses`, and `grades`, which the page shows as rendered
tables and never creates |

**Tier A path:** `movies` → enable RLS → policy → `watchlists` +
policies → both verification queries → `insert into movies` →
`categories` + FK → `actors`/`performances` → `private` schema →
`private.salaries`. Runs clean end to end.

**Tier B, RLS behavior.** Every access claim in "Securing your tables"
was exercised with two real users:

| Check | Expected | Observed |
| --- | --- | --- |
| User A inserts into their own watchlist | succeeds | succeeds, A sees
1 row |
| User B reads A's rows | 0 rows | 0 rows |
| `anon` reads `movies` | rows returned | 2 rows |
| `anon` reads `watchlists` | 0 rows | 0 rows |
| User B inserts a row owned by A | rejected | `new row violates
row-level security policy for table "watchlists"` |

**Environment:** Compose sandbox (`sandbox/run.sh up-stack`), DinD +
`supabase start`, Postgres 17. Fences ran in-container only, never on
the host.

**Note on the sandbox.** `supabase start` inside the nested daemon hit
repeated `toomanyrequests: Rate exceeded` from ECR Public. The CLI
retries and the stack does come up, but expect a slow first run.

## What this PR leaves to the one above it

Data type guidance is #50025.

## Manual testing

Preview:
https://docs-git-docs-tables-rls-supabase.vercel.app/docs/guides/database/tables#securing-your-tables

1. Open the preview at that anchor. The three subsections render, and
the numbered steps show their embedded SQL blocks.
2. In a local project, run the `movies` and `watchlists` snippets, then
the two verification queries. Both tables appear with `rowsecurity` true
and at least one policy each.
3. As a signed-out client, select from `movies` and from `watchlists`.
`movies` returns rows; `watchlists` returns none.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Documentation**
- Expanded the database tables guide with instructions to secure tables
before adding rows.
- Added guidance on enabling row-level security and creating policies
for shared and per-person tables.
- Clarified that policies control row access, while revoked table grants
can cause permission errors.
- Documented owner-scoped access using authenticated user IDs and ways
to verify table protection.
- Explained that read-only policies reject inserts through the Data API
and provided alternatives.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 18:49:11 -07:00
Miranda Limonczenko 31a0f450cf docs(database): correct the Dashboard table creation steps (#50023)
Part 3 of a 5-PR stack on
`apps/docs/content/guides/database/tables.mdx`. Builds on #50022.

## Problem

Three claims fail the test that a reader following the page would hit a
wrong outcome.

**The Dashboard steps don't match the product.** They said to click
**New Table**, save, then click **New Column**. Columns are defined
inside the table creation panel, so a reader who follows the steps saves
a table with no columns and then hunts for a button that isn't part of
that flow. The labels are also sentence case in the product: **New
table** and **New column**.

**The Dashboard example diverges from the rest of the page.** The steps
created a table named `todos` with a `task` column, while the SQL tab
beside them and every later example use `movies`. A reader who took the
Dashboard path and then ran the first Loading data snippet got `relation
"movies" does not exist`.

**The page's SQL doesn't compose.** Running every fence in document
order showed that the many-to-many example under "Joining tables with
foreign keys" opened by creating `movies` again. A reader who already
created it got `relation "movies" already exists`, the block stopped, so
`actors` was never created, and the `private.salaries` example two
sections later then failed with `relation "public.actors" does not
exist`. **One redundant statement broke two sections.**

**The bulk loading example couldn't work.** `COPY` accepts text, CSV,
and binary input, and the page listed JSON. `\COPY movies FROM
'./movies.csv'` expects a value for every column, and `movies` has three
while the sample file has two. The options example passed `CSV HEADER`
against a file with no header row, which silently dropped the first
record. Found by CodeRabbit.

## Solution

Rewrites the five Dashboard steps to match the panel and to produce
`movies`, so both tabs leave the reader in the same place. Drops the
redundant `create table movies` from the many-to-many block; the prose
above it already says "You have a list of `movies`". Names the columns
in both `COPY` commands, corrects the format list, points the `HEADER`
example at a file that has one, and removes the space before each quoted
CSV field.

Dashboard changes verified against `TableEditor.tsx`, which renders
`ColumnManagement` inside the creation panel; `TableEditorMenu.tsx` and
`ColumnList.tsx` for the labels; and `DEFAULT_COLUMNS` in
`TableEditor.constants.ts` for the `id` and `created_at` columns the
editor adds.

## Checked and deliberately left

- `grant all on table transcripts to authenticated`. Broader than the
example needs, but a reader gets the working result the page promises,
so it doesn't meet the bar for this branch.
- "By default, views are accessed with their creator's permission."
Accurate. `security_invoker` is opt-in.
- `salary bigint` in the private schema example. Left here; it changes
in #50025, where the page starts recommending `numeric` for money and
the example becomes inconsistent with it.

## Flagged, not changed

- The `api-create-table-sm.mp4` video in the Dashboard tab may show the
older flow. Its contents weren't verified.
- **Nothing in the Views section is runnable.** All nine of its fences
depend on `students`, `courses`, and `grades`, which the page shows as
rendered tables and never creates. Supplying that DDL is new content, so
it isn't this branch's job, but it's worth a ticket.

## Manual testing

Preview:
https://docs-git-docs-tables-technical-supabase.vercel.app/docs/guides/database/tables

1. Open the preview and read the Dashboard tab under "Creating tables".
It says **New table**, creates `movies`, and defines both columns in the
same panel.
2. Open the Table Editor in a project and click **New table**. The panel
has a **Name** field and a **Columns** section, and there is no separate
**New Column** step.
3. In a fresh local database, run the SQL fences from "Creating tables"
through `private.salaries` in page order. Each one succeeds.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Documentation**
- Updated the “Creating tables” guide to use a `movies` table with
`name` and `description` columns.
- Reworded and consolidated the table-creation steps, including the
`created_at` column in the SQL example.
- Updated bulk data loading instructions for CSV imports, connection
setup, named columns, and header-delimited files; removed JSON from the
listed formats.
- Simplified the many-to-many example by removing the redundant `movies`
table definition.
  - Clarified schema selection based on the current `search_path`.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 17:32:36 -07:00
Danny White 2e435986c9 feat(studio): polish the Replication pipelines list (#50252)
## What kind of change does this PR introduce?

Studio UI and interaction polish. This is the second PR in the Pipelines
review stack and depends on #50251.

## What is the current behaviour?

Pipeline rows require a separate view action, cannot be sorted, and
present lifecycle, lag, and destination terminology inconsistently.

## What is the new behaviour?

Makes rows navigable with link-like mouse and keyboard behaviour, adds
Name and Status sorting, reuses cached status queries, and moves row
actions into the overflow menu. It also clarifies pipeline terminology,
adds Docs and feedback actions, and standardises state, error, lag, and
loading presentation with accessible announcements.

| Before | After |
| --- | --- |
| <img width="1280" height="1323" alt="Replication Database ETL BigTable
ETL Team Supabase"
src="https://github.com/user-attachments/assets/53a62283-0e58-4408-8409-2b87a38af159"
/> | <img width="1280" height="1323" alt="Replication Database Agua
Basket Supabase"
src="https://github.com/user-attachments/assets/ba4de1e0-4a84-43b4-8975-ca05a3056bcf"
/> |

## To test

1. Open `/project/<ref>/database/replication`.
2. Sort by Name and Status, then confirm failed and stopped pipelines
surface first when Status is ascending.
3. Click a row, use Enter or Space, and modifier-click or middle-click
to verify link behaviour.
4. Open the row overflow menu and confirm it does not navigate.
5. Check loading, initial sync, caught up, numeric lag, unavailable lag,
and table-error states where available.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Added sortable pipeline lists with clearer loading, empty, and error
states.
- Pipeline rows now support direct navigation, detail viewing, status
indicators, lag progress, and table error summaries.
- Added initial-sync progress indicators and accessible status
announcements.
  - Added documentation and feedback links.
  - Improved pipeline version update and enable/disable dialogs.

- **Bug Fixes**
  - Prevented right-clicks from triggering navigation.
  - Improved unavailable lag and initial-sync handling.

- **Style**
- Standardized replication terminology and confirmation messaging around
pipelines.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 10:07:49 +10:00
74c116de74 docs: add Multigres Public Alpha documentation — MERGE ON SEP 14, 2026 (#49020)
## I have read the CONTRIBUTING.md file.

YES

## What kind of change does this PR introduce?

This PR adds Public Alpha documentation for Multigres, Supabase's
multi-node Postgres high-availability integration. It introduces an
overview guide, a compatibility stub, Database sidebar navigation, a
Features table row, and a "What you get" card grid. ContentListings
items can now omit `href` so those cards are not forced to be links.

Linear: MUL-452.

~~🚨 **DO NOT MERGE UNTIL THE PUBLIC ALPHA GOES LIVE** 🚨~~ [@jhydra12
OK'ed merging, FYI]


## What is the current behavior?

- Linear item: Documentation for Multigres
- Production has no Multigres guides.
`https://supabase.com/docs/guides/database/multigres` and
`https://supabase.com/docs/guides/database/multigres/compatibility`
return 404
- The Database sidebar has no Multigres section
- The Features status table does not list Multigres
- ContentListings items required a link (`href` was mandatory)

## What is the new behavior?

- Overview guide at `/docs/guides/database/multigres` covering alpha
status, eligibility, enablement, and what is not included
- Compatibility stub at `/docs/guides/database/multigres/compatibility`
- Database sidebar: Multigres → Overview, Compatibility (after OrioleDB)
- Features table: Database / Multigres / `public alpha`
- "What you get" renders as three non-link ContentListings cards
- `href` is optional on ContentListings items; markdown export renders
unlinked entries when it is omitted

## Additional context

- Worktree:
~/GitHub/supabase/supabase-worktrees/nikrichers/mul-452-documentation-for-multigres-ready
- Branch commits: Initial Multigres docs draft; Edits (cards, copy, MDX
comments); merge master; spelling allow-list for Multigres, Vitess, and
sharding

- Verification:

| Check                                   | Result          |
| --------------------------------------- | --------------- |
| Preview overview                        | 200             |
| Preview compatibility                   | 200             |
| Production overview                     | 404 (expected)  |
| Production compatibility                | 404 (expected)  |
| `supa-mdx-lint` on changed MDX          | pass            |
| `vitest` `lib/content-listings.test.ts` | pass (21 tests) |

### Proof: Multigres docs pages render, including non-link What you get
cards

**Verified:** production 404 · Vercel docs preview 200

#### Overview [(PR
preview)](https://docs-git-nikrichers-mul-452-documentation-for-m-6f8a59-supabase.vercel.app/docs/guides/database/multigres)

<img width="1388" height="2272" alt="image"
src="https://github.com/user-attachments/assets/2780f728-07c0-4320-9826-8f6e68df21e6"
/>

#### Compatibility [(PR
preview)](https://docs-git-nikrichers-mul-452-documentation-for-m-6f8a59-supabase.vercel.app/docs/guides/database/multigres/compatibility)

<img width="1388" height="852" alt="image"
src="https://github.com/user-attachments/assets/1f8f7181-5b7d-4d01-b376-a2eac923626b"
/>

### Test plan

- [ ] [Production
overview](https://supabase.com/docs/guides/database/multigres) (404) vs
[preview
overview](https://docs-git-nikrichers-mul-452-documentation-for-m-6f8a59-supabase.vercel.app/docs/guides/database/multigres)
- [ ] [Production
compatibility](https://supabase.com/docs/guides/database/multigres/compatibility)
(404) vs [preview
compatibility](https://docs-git-nikrichers-mul-452-documentation-for-m-6f8a59-supabase.vercel.app/docs/guides/database/multigres/compatibility)
- [ ] Database sidebar shows Multigres → Overview and Compatibility
after OrioleDB
- [ ] Overview shows Public Alpha caution, three What you get cards (not
links), eligibility, and one-way-migration caution
- [ ] Compatibility page is a placeholder that links back to the
overview
- [ ] Features table lists Database / Multigres / `public alpha`
- [ ] `supa-mdx-lint` on
`apps/docs/content/guides/database/multigres.mdx`,
`apps/docs/content/guides/database/multigres/compatibility.mdx`, and
`apps/docs/content/guides/getting-started/features.mdx`


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added Multigres documentation covering availability, setup,
compatibility, limitations, migration behavior, and external resources.
  * Added Multigres to database navigation and feature-status listings.
* Added an overview of Multigres benefits, including automatic failover,
unchanged connection strings, and consensus-backed write durability.

* **Improvements**
* Content listings now support informational items without links across
layouts.
* Improved listing rendering and click tracking for linked and
non-linked items.

* **Documentation**
* Added spelling support for Multigres, Vitess, and sharding
terminology.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Nik Richers <nik@validmind.ai>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-09-15 09:48:39 +10:00
Miranda Limonczenko 5979218c97 docs(database): split out views and group the tables guide by information type (#50022)
Part 2 of a 5-PR stack on
`apps/docs/content/guides/database/tables.mdx`. Builds on #50021.

## Problem

Four structural problems, all covered by the Guides section of
CONTRIBUTING.

**Views was a second topic living inside a guide about tables.** Roughly
180 lines, its own subsections four levels deep, sharing nothing with
the tables above it beyond the word "table".

**The page didn't say what it was for.** It opened with three paragraphs
and a sample table before a reader could tell whether the page matched
their goal. CONTRIBUTING asks a guide to begin with a sentence declaring
its intent.

**The top level mixed information types.** It was a flat list of every
task, so "Schemas" and "Primary keys" sat beside "Creating tables" and
background interrupted the action path.

**Reference material interrupted the procedure.** A 44-row data type
table sat between "Creating tables" and "Loading data", so a reader
following the action path walked through it.

Plus a duplicate video: the Dashboard tab under "Joining tables with
foreign keys" embedded the same YouTube ID that frontmatter already
serves as the table of contents video.

## Solution

Moves and regrouping.

- **Views moves to its own page**, `guides/database/views`, with its
headings promoted one level and the two view-related links from
Resources moved with it.
- The page opens with an intent sentence, then a section outline, then a
"What is a table?" section holding the definition and the spreadsheet
comparison.
- The remaining sections split into three groups by information type,
ordered procedures, context, reference: **Creating and managing tables**
holds creating, loading, and joining; **How tables are organized** holds
primary keys, relationships, and schemas; **Reference** holds the data
type table.
- "Joining tables with foreign keys" held both classes, so it splits.
The steps keep the heading and stay in the procedures group. The
concept, what relational means and the diagram showing it, becomes
**Relationships between tables** in the context group. The two
cross-reference each other.
- The duplicate video goes, and with the Dashboard tab empty the
surrounding `Tabs` wrapper goes too.

## Anchors

**Every heading keeps its text, so every anchor keeps its slug.**
Demoting a heading changes its level, not its anchor. That matters
because the inbound links are mostly outside `apps/docs`: Studio
deep-links to `#data-types` from three components and `#primary-keys`
from two, and `apps/www` links to `#creating-tables` and
`#joining-tables-with-foreign-keys`.

`#views` is the one exception, since that content left the page. Its
single inbound link, in `guides/ai/engineering-for-scale.mdx`, now
points at the new page, and both `NavigationMenu.constants.ts` entries
are updated: the existing item becomes "Managing tables and data" and a
"Views" item sits beside it.

## One deletion that isn't a move

The "Columns" heading and its one sentence, "You must define the data
type when you create a column." The heading held only the two
subsections that moved out, and the sentence repeats a line 50 lines
above it.

## Deferred

Reordering "View security" behind an access-control foundation. That
move only reads correctly once the foundation exists, so it travels with
that content in #50024.

## Manual testing

Preview:
https://docs-git-docs-tables-structure-supabase.vercel.app/docs/guides/database/tables

1. Open the preview. The page opens with its intent, then a four-entry
outline, then "What is a table?". Each outline link resolves, and the
three groups below read as procedures, then context, then reference.
2. Open `#data-types`, `#primary-keys`, `#creating-tables`, and
`#joining-tables-with-foreign-keys` on the preview. All four still land
on their sections.
3. Open
https://docs-git-docs-tables-structure-supabase.vercel.app/docs/guides/database/views.
The new page renders, and "Views" appears in the sidebar beside
"Managing tables and data".
4. Run `pnpm build:guides-markdown` from `apps/docs`. It generates 782
files, one more than before. Discard the change to
`public/markdown/manifest.json`, which the repo commits as `[]`.



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Documentation**
- Added a dedicated guide covering Postgres views, including creation,
querying, security options, and materialized views.
- Reorganized the Tables and data guide with clearer sections,
navigation links, table organization details, and reference information.
  - Updated the many-to-many example to display SQL directly.
- Split database navigation into separate “Managing tables and data” and
“Views” entries.
- Added a PostgreSQL log configuration entry and a C# client reference
link.
  - Updated documentation links to point to the new Views guide.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 16:43:05 -07:00
Miranda Limonczenko e022145be9 docs(database): apply house style to the tables guide (#50021)
Part 1 of a 5-PR stack on
`apps/docs/content/guides/database/tables.mdx`, one change type per PR.

## Problem

The page addressed the reader as "we" in about 18 places. CONTRIBUTING
reserves `we` for the Supabase team and asks that the reader be `you`.
None of it was caught by the linter, because
`Rule004ExcludeWords/first_person` only bans singular first person.

Alongside that: scare quotes on established terms, parenthetical asides
that CONTRIBUTING disallows, future tense where present tense reads
better, an ordered list that repeated `1.` four times, and three
relative links where `/docs/...` paths belong.

**The three diagrams had alt text that named a topic instead of
describing the picture.** "Schemas and tables" tells a screen reader
nothing about a diagram showing two schema boxes, one labeled `public`
holding six tables and one labeled `api` holding three.

## Solution

Inline rewrites and cuts. **Nothing in this PR moves a line from one
place to another.**

Each alt now describes its diagram: the column types in the table
diagram, the arrow between matching columns in the foreign key diagram,
and the two labeled schemas with their table counts.

Two deletions worth calling out:

- The `<br />` spacer after the data type table.
- The four-item benefits list under "When to use views". The four
headings immediately below restate it verbatim.

Also fixes "Every column is a predefined type", which states the
relationship backwards. A column has a type; it isn't one.

## One dead link, surfaced by the conversion

The Loading data intro pointed at `guides/database/api`, which isn't a
page. It exists only as a redirect in `apps/www/lib/redirects.js`, and
that redirect doesn't serve the docs deployment, so the link 404s there.
As a relative link it was invisible to the link checker; converting it
to a `/docs/...` path is what made the Docs E2E suite catch it.

It now points at `/docs/guides/api`, the live page that 13 other guides
already link to.

## What this PR leaves to the ones above it

Section moves and the Views page split are #50022. Corrections to claims
are #50023. New content is #50024 and #50025.

## Manual testing

Preview:
https://docs-git-docs-tables-style-supabase.vercel.app/docs/guides/database/tables

1. Open the preview. The intro reads "Excel spreadsheets" and
"relational databases", and the only remaining "we" is "We provide a SQL
editor within the Dashboard", which refers to Supabase rather than the
reader.
2. Inspect the three images on the preview. Each `alt` describes the
diagram rather than naming its topic.
3. Follow the **Data API** link under "Loading data". It resolves
instead of returning 404.
4. Run `npx prettier --check
apps/docs/content/guides/database/tables.mdx` and `pnpm lint:mdx` from
`apps/docs`. Both pass.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Documentation**
- Clarified guidance on table creation, data types, primary keys, bulk
loading, relationships, schemas, views, and materialized views.
- Improved wording, capitalization, terminology, and internal navigation
throughout the tables guide.
  - Updated diagram alt text with more descriptive captions.
  - Updated the loading data section to link to the Data API guide.
- Revised the bulk-loading example with an explicit column list, CSV
options, and a simplified database connection command.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 16:31:11 -07:00
Ali Waseem 2cd9b42e80 fix(studio): add a keyboard shortcut for the Compute sidebar item (#50361)
The Compute entry in the project sidebar was the only product route
without a `shortcutId`, so it had neither a `G`-chord nor the hover
keybind tooltip every sibling gets. Bound it to `G` then `C` (previously
unused) and added a test asserting every product route carries a
shortcut.

Fixes FE-4389

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Added a keyboard shortcut for quick navigation to Compute: press
**G**, then **C**.
- Compute navigation now includes a discoverable shortcut for consistent
access from the navigation interface.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 19:44:40 +00:00
bd95407a9c fix(ui): validate stored resizable-panel layout before handing it to react-resizable-panels (#50349)
## Summary
- `serverCompatibleLocalStorage.getItem()` already guards against
localStorage access itself throwing (SSR, private browsing, sandboxed
iframes), but returns whatever string is stored without checking it's
valid JSON.
- `react-resizable-panels`' own `useDefaultLayout()` calls
`JSON.parse()` on that value with no try/catch, so a stored value that
isn't valid JSON (overwritten by another script sharing the origin, a
browser extension, or a leftover value from a previous format) throws
and crashes the whole panel group instead of falling back to the default
layout.
- Fix: validate the value is parseable JSON in `getItem()` itself
(matching the file's existing best-effort persistence philosophy) and
return `null` — same as a missing value — when it isn't.

## Evidence (Sentry, past week)
- [SUPABASE-APP-KA8](https://supabase.sentry.io/issues/7726278966/) —
`SyntaxError: Unexpected token 'K', "KV-OK" is not valid JSON`,
full-page crash via `globalErrorBoundary` on `/project/[ref]/sql/[id]`.

## Test plan
- [ ] Manually confirmed the existing `transformLayoutKey`/try-catch
behavior for a missing or inaccessible key is unchanged
- [ ] Considered adding a unit test for
`serverCompatibleLocalStorage.getItem()`, but it isn't currently
exported; happy to export it and add a test if reviewers want one

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01RUrmUfMBpPqkgerh9onNTM

---
_Generated by [Claude
Code](https://claude.ai/code/session_01RUrmUfMBpPqkgerh9onNTM)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-09-14 13:39:54 -06:00
8bbd1d3048 fix(studio): fall back to unified preset for an unrecognized query-performance preset (#50348)
## Summary
- `useIndexInvalidation()` resolves the `preset` URL param through
`QUERY_PERFORMANCE_PRESET_MAP` with no fallback.
- A value that isn't one of the four known
`QUERY_PERFORMANCE_REPORT_TYPES` (stale bookmark, hand-edited URL, a
renamed/removed preset) resolves to `undefined`.
- That `undefined` preset flows into `generateQueryPerformanceSql()`,
which indexes `queryPerfQueries.queries[preset]` with it, producing
`undefined` for `baseSQL` — and the very next line reads
`baseSQL.queryType`, crashing the whole page via `globalErrorBoundary`.
- Fix: fall back to the `unified` preset when the URL value doesn't map
to a known preset, mirroring the `parseAsString.withDefault('unified')`
intent already expressed a few lines above for the case where the param
is entirely absent.

## Evidence (Sentry, past week)
- [SUPABASE-APP-K9Z](https://supabase.sentry.io/issues/7721026586/) —
`TypeError: Cannot read properties of undefined (reading 'queryType')`
on `/dashboard/project/[ref]/observability/query-performance`.

## Test plan
- [ ] Existing `useQueryPerformanceQuery.test.ts` suite still passes
- [ ] Manually confirmed
`QUERY_PERFORMANCE_PRESET_MAP[QUERY_PERFORMANCE_REPORT_TYPES.UNIFIED]`
resolves to `'unified'`, a valid key in
`PRESET_CONFIG[Presets.QUERY_PERFORMANCE].queries`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01RUrmUfMBpPqkgerh9onNTM

---
_Generated by [Claude
Code](https://claude.ai/code/session_01RUrmUfMBpPqkgerh9onNTM)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-09-14 13:28:24 -06:00
Miranda Limonczenko bc917370d1 docs: recommend a local CLI install on the front page (#50356)
Closes DOCS-1391

## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Docs update.

## What is the current behavior?

The docs front page is the only place that still recommends a global CLI
install. It shows `npm install -g supabase` in both the CLI tab and the
AI prompt, and tells the agent to run `supabase init`.

Everywhere else in the docs installs the CLI as a project dev
dependency, so the version is pinned in `package.json` and everyone on a
team runs the same one.

## What is the new behavior?

- `installCli` becomes `npm install supabase --save-dev`, matching
[Install and run the
CLI](https://supabase.com/docs/guides/local-development/cli/getting-started).
- `initialize` becomes `npx supabase init`. A dev-dependency install
leaves no global `supabase` command.
- The AI prompt says "as a project dev dependency" and states the
reason, so an agent doesn't fall back to a global install.
- Updates the same wording in the monitoring and debugging prompt, which
shares the constants.
- Updates the `AiPrompt` markdown schema test assertion.

## Manual testing

1. Open the [docs front page
preview](https://docs-git-docs-cli-local-install-supabase.vercel.app/docs).
The AI Prompt tab reads "Install the Supabase CLI as a project dev
dependency with `npm install supabase --save-dev`, so the version is
pinned per project" and ends with `npx supabase init`.
2. Select the **CLI** tab. It shows `npm install supabase --save-dev` on
the first line and `npx plugins add supabase-community/supabase-plugin`
on the second.
3. Run `pnpm run -F docs test:local:unwatch
internals/markdown-schema/AiPrompt.test.ts`. All tests pass.
2026-09-14 12:21:59 -07:00
Prashant Sridharan c38117b613 Added new go page for CISO dinner at Select (#50360)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Added a CISO dinner landing page and integration with Notion.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added an RSVP page for the Supabase Select 2026 CISO Dinner in San
Francisco.
* Included event details, host information, attendee fields, and RSVP
submission with confirmation redirect.
* Added a thank-you page confirming successful registration and sharing
event timing and security resources.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 20:20:43 +01:00
c3ccf9179f fix(www): skip the careers-page globe when WebGL is unavailable (#50350)
## Summary
- `cobe`'s `createGlobe()` resolves the canvas context internally as
`getContext('webgl2') || getContext('webgl') || 'experimental-webgl'` (a
context-name *string*, not an actual context). When both `webgl2` and
`webgl` are unavailable, it falls through to that string, but modern
browsers no longer support the `experimental-webgl` context name, so the
resulting context is `null` and cobe crashes internally reading
`.enable(...)` on it.
- `apps/www/components/Globe.tsx` (used only on `/careers`) had no guard
for this, so a browser/device with WebGL disabled or unavailable (GPU
blocklist, corporate policy, privacy setting) crashes the entire careers
page via `globalErrorBoundary`.
- Fix: detect WebGL support ourselves (`getContext('webgl2') ||
getContext('webgl')`) before mounting the globe, and skip rendering it
(no globe, rest of the page renders fine) when unsupported.

## Evidence (Sentry, past week)
- [WWW-41](https://supabase.sentry.io/issues/7731263201/) — `TypeError:
Cannot read properties of null (reading 'enable')` on `/careers`, leaf
frame inside `cobe`/`phenomenon`.

## Test plan
- [ ] Manually confirmed `Globe.tsx` is only imported by
`apps/www/pages/careers.tsx`
- [ ] No automated test added (this is a purely decorative,
non-interactive canvas element with no existing test coverage); happy to
add one if reviewers want it

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01RUrmUfMBpPqkgerh9onNTM

---
_Generated by [Claude
Code](https://claude.ai/code/session_01RUrmUfMBpPqkgerh9onNTM)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-09-14 13:20:02 -06:00
62fe0fca4a fix(studio): guard branches and read-replicas queries against non-array 200 bodies (#50347)
## Summary
- `getBranches()` (`apps/studio/data/branches/branches-query.ts`) and
`getReadReplicas()` (`apps/studio/data/read-replicas/replicas-query.ts`)
cast the raw API response body to an array with no runtime check.
- When the endpoint returns a defined-but-non-array 200 body, the `??
[]` fallback in each consumer doesn't catch it (the value isn't
nullish), and the first `.find`/`.filter` call throws, crashing the
whole page via `globalErrorBoundary`.
- This is the same known class of bug already fixed elsewhere in the
codebase (e.g. `apps/studio/data/lint/lint-query.ts`, and the
`api-keys`/`oauthApps`/`secrets` fetchers) — applies the same
`Array.isArray(data) ? data : EMPTY_ARR` guard.

## Evidence (Sentry, past week)
- [SUPABASE-APP-KA2](https://supabase.sentry.io/issues/7722780387/) —
`(m??[]).find is not a function` in `ActivityStats.tsx`
(`branchesData.find`), full-page crash on `/dashboard/project/[ref]`.
- [SUPABASE-APP-KAE](https://supabase.sentry.io/issues/7729679561/) —
`u.filter is not a function` in `AWSPrivateLinkForm.tsx`
(`databases.filter`), full-page crash on
`/project/[ref]/settings/integrations`.

## Test plan
- [ ] Existing query hook tests still pass
- [ ] Manually verified `Array.isArray` guard mirrors the established
`lint-query.ts` pattern

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01RUrmUfMBpPqkgerh9onNTM

---
_Generated by [Claude
Code](https://claude.ai/code/session_01RUrmUfMBpPqkgerh9onNTM)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-09-14 19:16:41 +00:00
Sean Oliver d439ba57f4 feat(studio): mask HTML attributes in session replay (#48818)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Hardening ahead of any decision to enable session replay, plus a
dependency bump. Follow-up to #48515.

### What's inside

- ~50 lines of logic: the callback, the `url()` pattern, and the theme
and SVG-reference gates
([session-replay.ts](https://github.com/supabase/supabase/pull/48818/changes#diff-b7e4f10387ee7a116dd1673f70a55c0ba066687ff2d228bc2320eba75a349fac))
- ~170 lines of allowlist, one attribute name per line, skimmable ([same
file](https://github.com/supabase/supabase/pull/48818/changes#diff-b7e4f10387ee7a116dd1673f70a55c0ba066687ff2d228bc2320eba75a349fac))
- ~150 lines of comments saying why each group is allowlisted, since a
wrong entry is a privacy or a fidelity bug ([same
file](https://github.com/supabase/supabase/pull/48818/changes#diff-b7e4f10387ee7a116dd1673f70a55c0ba066687ff2d228bc2320eba75a349fac))
- ~430 lines of tests, one case per policy decision
([session-replay.test.ts](https://github.com/supabase/supabase/pull/48818/changes#diff-f9feb872ad0136cf87c7e9fb2af72eb3f4019464c06f0b7dd050ffb85373ccb8))
- 1 line of dependency bump, plus its lockfile
([package.json](https://github.com/supabase/supabase/pull/48818/changes#diff-50d7c39a9430d37971aa76858165ab4f7921c4cc4340b28e9b673ce6982e63cf))

## What is the current behavior?

Session replay is disabled in every environment, and no recordings
exist. This is about what a recording *would* contain if it were ever
switched on.

Attributes are the one channel replay masking cannot reach. `maskTextFn`
only sees DOM text nodes, so a component interpolating customer data
into a `placeholder`, `title` or `aria-label` would be captured
verbatim. Before `posthog-js` 1.413.0 there was no hook for it at all,
and the only mitigation was blocking the element, which drops it from
the capture entirely.

Two places in Studio where that would apply:

- `CreateOrUpdateCustomProviderSheet.tsx:506-507` interpolates the
project's API host into both `value` and `placeholder`. The `value` is
masked. The `placeholder` is not.
- `FileExplorerHeader.tsx:185` renders `Search in
${currentFolderName}...`, a customer storage folder name.

The list is not complete. Any component echoing context into a tooltip
reproduces it, and the author has no reason to be thinking about replay.

Linear [GROWTH-1094](https://linear.app/supabase/issue/GROWTH-1094).
Blocks [GROWTH-1073](https://linear.app/supabase/issue/GROWTH-1073).

## What is the new behavior?

`maskAttributeFn` with a default-deny policy: an allowlist of the
attributes replay needs to render, everything else masked.

### Policy edge cases

- **rrweb's `rr_*` layout attributes have to be allowlisted
explicitly.** posthog-js only applies its own exemption for those when
`maskAllElementAttributes` does the masking. A callback does not get the
exemption.
- **HTML `id` is masked. SVG `id` passes.** `AreaChart.tsx:119` emits
`<linearGradient id="colorUv">` and references it as
`fill="url(#colorUv)"`, so masking it breaks the gradient. But Studio
also binds customer-named values to `id` (`bucket.id` is a storage
bucket name). Split on `element.namespaceURI`.
- **SVG reference attributes pass only fragment-only targets.** recharts
clips every series with `clip-path="url(#clipPath-<id>)"`, so
`clip-path`, `mask`, `filter`, `marker-*`, `fill` and `stroke` have to
survive. They accept external URLs too, so the policy checks the target
rather than allowlisting the attribute name.
- **The `url()` pattern consumes escaped delimiters and ignores case.**
A target containing a quote serializes as `\"` and one containing a
bracket as `\)`, so a naive `[^")]*` stops at the backslash and leaves
the tail of the URL recorded. `URL(...)` is the same function as
`url(...)`. A token the pattern cannot parse falls through to a masking
fallback rather than passing.
- **`url()` targets inside `style` are masked, keeping the
declarations.** The feedback widget puts `toPng(document.body)`, a
base64 PNG of the whole dashboard, into a `background-image`, and the
storage preview panes put signed object URLs there. No other masking
path covers those, because they are not text nodes, a canvas, a network
request or an `img src`.

The config also pins `maskAllElementAttributes: false`. Left unset it
resolves from the PostHog UI, and `true` discards `maskAttributeFn`
entirely.

The `posthog-js` floor rises to `^1.416.1`, the first version carrying
both attribute masking and the "coarse option wins" precedence.

This does not enable recording anywhere.

## Additional context

### Verification

Ran on the studio-staging preview against a live session: 817 seconds,
190 clicks, 82 keypresses. Staging has no server-side masking config, so
everything masked came from this code.

| Check | Result |
|---|---|
| Storage folder search placeholder | Asterisked. Pre-fix it read
`Search in <folder>...` |
| Custom auth provider sheet | Fully masked, including the callback URL
field |
| Canary folder name in event properties | 0 hits, with 51 events in the
session as the control |
| Console capture | `console_log_count: 0` despite the project having
`capture_console_log_opt_in: true` |
| Telemetry regression | None: `$pageview` x34, `$pageleave` x5,
`$groupidentify` x4, `$identify` x1 |

Recording was scoped to that one preview by an origin restriction plus a
URL trigger. Both were reverted afterwards along with the project
toggle.

The policy has 175 unit tests. Separately, the config was bundled with
esbuild and applied to a DOM reproducing Studio's serialized output (the
AreaChart gradient, a recharts `clip-path`, a lucide icon, an inline
`background-image`), and the chart, gradient fill and icon come out
pixel-identical.

### Known fidelity costs

- `img src` is masked, so images don't render in replay. Storage object
URLs are signed customer content.
- `ProviderIcon` renders its mark as `maskImage: url(<src>)` and
`normalizeIconPath` accepts absolute URLs, so provider icons don't
render either.

### Out of scope

rrweb records `<style>` element text without calling either masking
function, because its text-node serializer skips masking when the parent
is `STYLE`. This PR does not reach that channel. Fixed separately in
#50270 / [GROWTH-1229](https://linear.app/supabase/issue/GROWTH-1229).

`captureJsonLd` also defaults on as of PostHog's 2026-08-30 defaults,
which is a capture channel masking doesn't reach. Studio renders no
`ld+json`, so it's inert there, and pinning it off was left out to keep
this PR to its scope.

### The allowlist is the weak part

The policy is default-deny over attribute *names*, so its surface is
every attribute any shipped library emits, and that set grows with each
dependency. A miss is also invisible to these tests, which assert what
the function returns rather than whether some selector elsewhere still
matches. Both failure directions are reachable that way: an attribute
carrying customer data, and an attribute a stylesheet needs.

[GROWTH-1232](https://linear.app/supabase/issue/GROWTH-1232) tracks the
mechanism change: scope by namespace instead of by name, since 50 of the
159 entries exist only to serve SVG rendering, plus a conformance test
that derives the expected set from the codebase so a new dependency
fails CI rather than degrading a replay. Deliberately not done here,
since rewriting the mechanism of a privacy control buys maintainability
rather than correctness.
2026-09-14 09:48:58 -07:00
Sean Oliver 32f17f994d fix(studio): key query chart series by position, not column name (#50270)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Bug fix. Hardening ahead of any decision to enable session replay.

### What's inside

- ~47 lines of logic: positional series keys, the X-key collision guard,
and the rewiring of rows, cumulative results and axis width
([QueryResultChart.tsx](https://github.com/supabase/supabase/pull/50270/changes#diff-dae994728613498678bcc06a3ea5176b36708e06b531cfc7eddae3e588fff528))
- ~123 lines of tests, one case per chart type, cumulative setting and
edge case
([QueryResultChart.test.tsx](https://github.com/supabase/supabase/pull/50270/changes#diff-6e1c92ad725bac0324db4d079f3d0cd061b8f6e2aecdc21bcdc5969c90dc3c59))

## What is the current behavior?

Session replay is disabled in every environment, and no recordings
exist. This is about what a recording *would* contain if it were ever
switched on: charting a query result would put the customer's own column
names into it.

`ChartContainer` writes every chart config key into a `<style>` element
as `--color-<key>`. rrweb records `<style>` text verbatim:

```js
u = "STYLE" === parentTagName || void 0
h = "SCRIPT" === parentTagName || void 0
!u && !h && o && r && (o = maskTextFn ? maskTextFn(o, parent) : o.replace(/\S/g, "*"))
```

The `!u` guard means `maskTextFn` never sees stylesheet text. It is a
text node, so `maskAttributeFn` does not see it either. CSS written into
the DOM is a channel no masking hook reaches.

`QueryResultChart` keyed its config by the column names picked for the Y
axis, which come from the customer's own SQL results. With recording
enabled, a query charting a column named `customer_email` would produce
`--color-customer_email` in the captured DOM.

Linear [GROWTH-1229](https://linear.app/supabase/issue/GROWTH-1229).
#48818 masks the attribute channel. This channel is text, so that PR
does not reach it.

## What is the new behavior?

Y series are keyed by position (`series_0`, `series_1`), so no customer
string reaches the config keys.

The column name still goes through as `config[key].label`, which
`chart.tsx` renders into the tooltip and legend as text. Text nodes
outside `<style>` are masked by `maskReplayText`, so the name is safe
there and the chart stays readable.

The X column keeps its own name. Only config keys reach the `<style>`
and the X column is never one, so renaming it would buy nothing, and it
would cost the `timestamp` handling: `ChartBar` and `ChartLine` branch
on `xKey === 'timestamp'` to format tooltip dates and render the
date-range footer. Keeping the original name needs one guard, since an X
column literally named `series_0` would share a row key with the first Y
series. `xKeyFor` appends underscores until the two are distinct.

## Additional context

### Testing

Eleven tests. They assert the rendered `<style>` contains
`--color-series_0` and does not contain the column name, across both
chart types and both cumulative settings, plus the two-series case, the
`timestamp` column and the collision guard.

Three are verified to catch the defect they cover: the style-key
assertion fails against the unfixed component, the `timestamp` assertion
fails when the X key is pinned to a constant, and the `xKeyFor` cases
fail when the guard's body is removed.

`vitest run components/interfaces/Explorer` passes: 170 tests across 16
files.

The tooltip and legend path isn't asserted, because recharts doesn't
render either one at the 0x0 size jsdom gives the container. That the
label is what renders there comes from reading `chart.tsx`. It is
unverified at runtime.

### Remaining exposure

Every other `ChartContainer` caller passes literal keys
(`--color-error`, `--color-ok_count`), and `UnifiedLogs` filters a
static config by a fixed level set, so this was the only caller feeding
it customer strings.

`chart-bar.tsx:119-124` and `chart-line.tsx` still fall back to building
a config from whatever `dataKeys` they're given, so a future caller can
reintroduce this without touching `QueryResultChart`. A general guard
would have to live in `ChartContainer` or in the replay config.

CSSOM writes (`insertRule`, `replace`, `replaceSync`, adopted
stylesheets) also emit CSS outside both masking hooks. This PR does not
close that path.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Bug Fixes**
- Improved query result charts to preserve the source column name used
for the X-axis.
- Prevented X-axis names from conflicting with generated series
identifiers.
- Ensured bar and line charts consistently bind data to the correct
X-axis and series.
- Preserved timestamp-based chart behavior, including the date-range
footer.
- Chart series styling now uses stable positional identifiers, ensuring
colors remain correctly assigned across configured series.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 09:48:47 -07:00
kemal.earthandAli Waseem 4aa34f556a feat(studio): mcp secrets interstitial polish (#50351)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

- We made the Next step copy a bit more generic so it doesn't read like
it's pointing you back to Inspector UI.
- Added CTA on key stored screen to send you to Edge Function Secrets
directly.
- Tidies up footer area to always be centrally aligned across all
states.

### 1. Enable the feature flag

### 2. Preview states via URL

Mock mode is enabled automatically in local/staging. Navigate to
`/mcp/secrets` with a `state` query param:

http://localhost:8082/mcp/secrets?state=<state>

States that need no other params:

| `state` value    | What it shows                          |
| ----------------- | --------------------------------------- |
| `loading`          | Loading skeleton                        |
| `expired`          | Link expired                            |
| `cancelled`        | Request cancelled                       |
| `paused`           | Storing keys paused                     |
| `wrong-account`    | Signed in as the wrong account          |
| `error`            | Generic failure                         |

States that need a real project —ame=<KEY_NAME>`:

| `state` value      | What it sh           |
| -------------------- | ---------------------- |
| `form`                | The "st              |
| `stored`              | Success              |
| `stored-timeout`      | Successopped waiting |
| `already-stored` | Key was already stored, nothing to do |

Example:

http://localhost:8082/mcp/secretsJECT_REF&name=OPENAI_API_KEY

### 3. What to check

- [ ] `stored` / `already-stored`tions secrets"** button linking to
`/project/<ref>/functions/secrets
- [ ] States without a project re `paused`, `error`) don't show that
button
- [ ] Footer text is centered on
- [ ] `wrong-account` → **Switch its footer is centered
- [ ] The provider-dashboard link` state, use a `name`
like`OPENAI_API_KEY` or `RESEND_API_Khint) is centered too


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added a project-specific link to Edge Functions secrets from the MCP
setup screen when a project is available.
* Added a separator to distinguish the secrets link from the remaining
setup guidance.

* **Improvements**
* Updated completion guidance to tell users to return to their agent and
confirm the setup is finished.
* Standardized interstitial footer content with centered guidance and
consistent provider dashboard instructions.

* **Tests**
* Added coverage for displaying the project-specific secrets link and
hiding it when no project is associated.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-09-14 17:44:42 +01:00
b0de9dd7a6 Create log docs (#47047)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

docs update

## What is the current behavior?

No docs on how to interpret and configure PG logs

## What is the new behavior?

Adds docs on how to interpret and manage PG logs

## Additional context

Related Linear issue:
-
https://linear.app/supabase/issue/DEBUG-131/create-docs-outlining-all-log-settings


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Documentation**
  * Added a new guide for customizing Supabase-hosted Postgres logging.
* Documented available log settings with default values, plus SQL
examples to inspect effective settings and role-specific overrides.
* Covered configuration options (CLI, Management API, SQL), including
precedence rules, role-level override/reset examples, and restart
guidance for scheduled logging.
* Updated the docs navigation with a new “Postgres log configuration”
entry.
* **Chores**
  * Updated the MDX spelling allow list to include “subfield”.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-09-14 12:15:15 -04:00
Nik RichersandNik Richers ea79df46bc docs: explain purpose of /edit-the-docs in CONTRIBUTING.md rather than the "Write the docs" checklist (#50313)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Docs authoring guidance: keep `/edit-the-docs` out of the Write the docs
checklist and document when to use what skill in `CONTRIBUTING.md`.

## What is the current behavior?

The Write the docs checklist mentions `/edit-the-docs` mid-flow and
lists it among checklist skills. That skill is a different workflow and
audience, so it risks steering people off the six-stage process.

## What is the new behavior?

- Checklist lists only Write the docs skills; no `/edit-the-docs`
mid-stage note.
- `CONTRIBUTING.md` splits **Write the docs skills** from **Edit
existing pages**.
- Write the docs applies when product intent and code drive the change,
including revising or restructuring existing pages. `edit-the-docs` is
for style, structure, or brevity when the product story is unchanged.

## Additional context

Also drops a redundant `/test-the-docs` note from "What good looks like"
(Self-review still covers it).

---------

Co-authored-by: Nik Richers <nik@validmind.ai>
2026-09-14 09:02:17 -07:00
Ivan VasilovandAli Waseem c60bb37a74 chore: Bump nextjs to non-vulnerable version (#50341)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Updated the Next.js version used by the application and documentation
sites.
* Aligned workspace tooling with the latest supported Next.js 16.3.5
release and refreshed related platform builds.
  * Updated application and documentation sites to Next.js 15.5.24.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-09-14 17:55:02 +02:00
Joshen Lim c9e035910d Add HA toggle to enabled features (#50344)
## Context

As per PR title - flags the HA toggle in project creation form behind a
flag in enabled-features
Behaviour should be status quo for both staging and prod

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added a high-availability option to the project creation flow for
eligible accounts when the feature is enabled.
  * The option is available through controlled feature configuration.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 23:14:10 +08:00
Joshen Lim 5104754018 Fix types master (#50345)
## Context

Just needed to adjust the API types import - the name likely changed
somewhere
`AnalyticsResponse` -> `AnalyticsResponse_Output`

Verified the typecheck locally

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Tests**
* Updated analytics test typing to align with the current analytics
response schema.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 23:02:16 +08:00
Jordi Enric 35f2eeefcf fix(observability): replace egress chart with usage link FE-4310 (#49850)
## Problem

The Network Traffic egress chart is derived from request logs and can
substantially undercount billed traffic. Showing it beside diagnostic
ingress data left customers with an untrustworthy egress number.

## Fix

Remove the log-derived egress chart, retain ingress, and add a Billable
egress callout that links to the selected organization’s Usage page. The
callout is shown only on hosted Studio, where organization billing data
is available.

## How to test

- Open API, Storage, Auth, or PostgREST observability.
- Confirm Network Traffic shows only the ingress chart.
- Confirm the Billable egress callout links to the organization Usage
page’s egress section.
- Expected result: diagnostic traffic and billable usage are no longer
presented as competing egress totals.
- Automated checks: git diff --check and final code review passed.
Focused lint could not run because missing dependencies require registry
access, and DNS for registry.npmjs.org is unavailable.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Updates**
* Clarified Network Traffic report tooltips to explain that ingress is
measured from request logs.
* Platform deployment reports now display ingress data only; egress
charts are no longer shown.
* Added a notice linking to the Usage page for billable egress details.
* Applied the updated Network Traffic explanation consistently across
API overview, storage, and shared report views.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 15:43:55 +02:00
Jordi Enric d2ed60da27 fix(auth): migrate overview errors to clickhouse (#50174)
## Problem

Auth overview error tables call the legacy logs endpoint through
fetchLogs defaults, even with the ClickHouse migration enabled.
Success-rate cards also show zero when there are no requests and
misleading relative changes between small rates.

## Fix

Select matching BigQuery or ClickHouse queries with otelLegacyLogs,
separate caches by engine, and normalize numeric results.

Show No data for success rates without requests and omit comparisons
when either period has no requests. Show success-rate changes in
percentage points: 0% to 0.2% displays +0.2 pp. Omit undefined relative
changes from a zero baseline for activity and sign-up counts. Show
explicit errors for failed log requests, including error payloads
returned with HTTP 200, instead of empty tables.

## Validation

- Auth overview error tables compared against staging with matching
data.
- 84 focused tests passed across four suites, including 25 direct
formatter tests.
- 12 MSW integration tests exercise both endpoint/SQL pairs, HTTP and
embedded API failures, and rendered No data, genuine 0%, and +0.2 pp
states.
- Unit tests cover missing periods, zero requests, percentage-point and
relative changes, SQL structure, and numeric result parsing.
- Formatting and diff checks passed; code review found no actionable
issues.
- Full local lint/typecheck are limited by shared checkout dependencies.
Browser comparison confirmed the deployed rate display uses percentage
points and shows No data without a comparison for absent server
requests; populated error rows match staging. The final formatter
extraction (9886b78682) was also deployed and verified in the browser;
CI completion remains outstanding.

Split from #50173.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Added OpenTelemetry support for authentication error and metrics
reporting.
- Added clearer handling of missing metric data, including “No data”
states.
- Improved success-rate change calculations using percentage-point
differences.
  - Added user-visible error states when analytics requests fail.

- **Bug Fixes**
- Improved validation and handling of authentication metrics and error
data.
  - Corrected formatting and rounding for metric values and changes.

- **Tests**
- Expanded coverage for legacy and OpenTelemetry analytics, error
handling, empty data, formatting, and edge cases.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 15:35:03 +02:00
Jordi Enric 38e8f12b1b fix(studio): gate homepage health advisor (#50328)
## Problem

Health Advisor results appear on the project homepage whenever the main
`healthAdvisor` flag is enabled, so the homepage cannot be rolled out
separately. The existing gates also contain redundant boolean and
platform checks.

## Fix

Require both `healthAdvisor` and `healthAdvisorInHomepage` before
fetching or displaying health advisories on the homepage. Simplify all
Health Advisor gates to use the boolean ConfigCat flag directly,
including the cleanup requested in the review of #50326.

## How to test

- Enable only `healthAdvisor` and verify Health Advisor remains
available outside the homepage while health results do not appear or
load on the homepage.
- Enable both flags and verify health results appear on the homepage.
- Disable `healthAdvisor` and verify Health Advisor remains unavailable
everywhere.
- Existing targeted tests pass: 5 tests across Advisor menu and panel
integration suites.
- Prettier and whitespace checks pass.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Health Advisor is now available in non-platform environments when
enabled.
* Navigation, filtering, lint checks, and project pages consistently
follow the Health Advisor feature setting.
  * Self-hosted environments can use the Health Advisor category.
* **Bug Fixes**
* Homepage Health Advisor visibility now follows both the Health Advisor
and homepage-specific settings.
* Updated empty states and health lint results to match the configured
availability.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 13:34:24 +00:00
Anthony Lio 819df2ae4d feat(www): menu nav enhancements (#50282)
## What kind of change does this PR introduce?

feature reworks the www header dropdowns

## What is the current behavior?

menu dropdown navigation animation between items feels scattered

## What is the new behavior?

- adds dropdown card resize with a transition and the content crossfades
when switching
- removes dead zone between or under nav items
- sets card is centered on the screen + enhance tablet bp
- adds slight ui refresh spacing, colors, sizes

| state | preview |
| -------|------|
| before | <video
src="https://github.com/user-attachments/assets/acd8e161-a697-4070-b751-4f4e9f1eab19"
/> |
| after | <video
src="https://github.com/user-attachments/assets/fe403afd-0074-4cb5-9223-fd6cdd2f7d5a"
/> |



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Navigation dropdowns now provide smoother directional transitions,
keyboard-focus states, and reduced-motion support.
* Product navigation is organized into clearer Products and Modules
sections.
* Navigation layouts adapt earlier across screen sizes with responsive
two-column arrangements.

* **Style**
* Updated dropdown spacing, colors, borders, menu item styling, and
customer imagery sizing.
  * Refined blog loading placeholders with slightly tighter spacing.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 15:51:39 +03:00
Pedro RodriguesandClaude Sonnet 5 22d7bc0cfd feat(studio-evals): custom search_docs tool for the eval harness (no token / no PAT) (#50092)
- Eval harness's only live tool, `search_docs`, no longer needs the
in-process MCP client or its dummy token — it now calls the public docs
GraphQL API (`https://supabase.com/docs/api/graphql`) directly. Low risk
as this is an eval-harness change only. Production assistant path
(`mcp-tools.ts`) untouched.

**Update:** per [@mattrossman's
review](https://github.com/supabase/supabase/pull/50092#discussion_r3980396341),
the eval tool's description embeds the Content API's own GraphQL schema
(fetched via a `{ schema }` query and minified with `gqlmin`), mirroring
how `@supabase/mcp-server-supabase`'s `docs-tools.ts`/`loadSchema`
populates production's `search_docs` description. Without it, the model
had no schema to work from and issued malformed queries, which caused
the 218 `search_docs` errors and the -25pp Docs Faithfulness regression
in the first eval run on this PR. Schema loading is required:
`createSearchDocsTool()` rejects if the schema fetch fails, so preflight
and the gated eval job fail loudly instead of producing untrustworthy
fallback results. `createSearchDocsTool` is async because the `ai`
package's `tool()` only accepts a plain string `description`, unlike the
MCP SDK's async description support; both callers (`getMockTools`,
`evals/preflight.ts`) await it. `gqlmin` is a direct `apps/studio`
dependency and was already transitive via
`@supabase/mcp-server-supabase`.

### Verification
- `pnpm -C apps/studio exec -- tsc --noEmit` reaches the compiler; it
reports only the pre-existing unrelated
`packages/ui-patterns/src/McpUrlBuilder/components/InstructionBlocks.tsx`
`StaticImageData` error.
- `pnpm -C apps/studio exec -- vitest run
lib/ai/tools/mock-tools.test.ts lib/ai/tools/mcp-tools.test.ts` — 21/21
passed.
- `pnpm exec tsx evals/preflight.ts` — live docs API schema fetch and
search_docs call passed.
- `NEXT_PUBLIC_CONTENT_API_URL=http://127.0.0.1:1/graphql pnpm -C
apps/studio exec -- tsx evals/preflight.ts` — failed fast as expected,
proving schema/API failures gate evals.
- Fresh `run-evals` pass: Docs Faithfulness 55.7% (0pp), with no
systemic `search_docs` regression.

Risk: eval-harness-only; schema/API outage now fails the eval job before
scoring rather than allowing fallback descriptions.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added documentation search powered by the public Supabase
documentation GraphQL API.
* Documentation search results now include live schema information and
clearer error handling for failed or invalid requests.

* **Bug Fixes**
* Improved evaluation tooling reliability by removing unnecessary
connection-abort behavior.
* Updated validation to detect missing search tools and malformed
documentation responses.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-14 12:51:14 +02:00
claude[bot]andClaude 25f411657d fix(telemetry): widen plan-presentation exposure event variant type to 5 variants (#50318)
&lt;!-- ccr-slack-attribution --&gt;
_Requested by **Pam Chia** · [Slack
thread](https://supabase.slack.com/archives/C076KTY11DF/p1789349119093319?thread_ts=1789349119.093319&cid=C076KTY11DF)_

## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Bug fix (telemetry type).

## What is the current behavior?

The `pricing_panel_plan_presentation_experiment_exposed` event's
`variant` property in `packages/common/telemetry-constants.ts` only
types 3 of the experiment's 5 live variants (`'control' | 'parity' |
'gaps'`), even though the experiment source in `plan-presentation.ts`
defines and actively uses 5: `control`, `parity`, `gaps`, `fullscreen`,
`fullscreen-gaps`. The two full-screen variants are silently untyped in
the telemetry catalog.

## What is the new behavior?

The `variant` property is widened to `'control' | 'parity' | 'gaps' |
'fullscreen' | 'fullscreen-gaps'`, matching the exact casing of
`PLAN_PRESENTATION_VARIANTS` in the experiment source, and consistent
with how other experiment-variant unions in the same file (e.g.
`rlsOptionVariant`) are kept in sync with their source enum.

## Additional context

Linear: GROWTH-1234

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01Gxb4n5ujMPeio1VmkowHc5

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Gxb4n5ujMPeio1VmkowHc5)_

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-14 18:24:36 +08:00
Gildas Garcia 6f15081892 Scoped PAT: show dependencies between permissions (#50271)
## Problem

Some permissions require others to actually have an effect, for
instance:

- `api_gateway_keys_secret_read` requires `api_gateway_keys_read` or
`api_gateway_keys_write`
- `data_api_config_secret_read` requires `data_api_config_read` or
`data_api_config_write`

This is not obvious from a user perspective.

## Solution

We decided to make these requirements explicit by:
- Adding a line in the permission item stating the dependency
- Disabling the permission if its dependency isn't met
- Resetting the permission if it was selected but the dependencies
aren't met anymore

## How to test

- On
[staging](https://studio-staging-git-gildasgarcia-fe-4380-dashboa-b2a227-supabase.vercel.app/dashboard/account/tokens)
- Create a new token
- Check that _API Key Secrets_ is greyed out and disabled
- Select _API Key_ read or read-write
-  _API Key Secrets_ shouldn't be greyed out and disabled
- Select a value for _API Key Secrets_
- Set _API Key_ to none
- Check that _API Key Secrets_ is greyed out, disabled and reset to none
too
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
  - Added dependency-aware permissions for scoped access tokens.
- Permission descriptions now show required dependencies and permission
levels.
- Dependent permissions automatically reset to “None” when requirements
are not met.
- Permission controls and unavailable selections reflect dependency
requirements.
- **Accessibility**
- Screen readers now receive an announcement when a permission is reset
to “None” due to unmet dependencies.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 11:09:46 +02:00
Jordi Enric 519a3a5644 fix(studio): gate health advisor behind feature flag (#50326)
## Problem

Health Advisor runs checks and displays health alerts without a
dedicated rollout flag.

## Fix

Gate Health Advisor behind the ConfigCat `healthAdvisor` flag,
defaulting to off when missing or loading. This covers the navigation
and shortcut, command menu, direct page access, homepage alerts, Advisor
panel filters and details, and health-check requests. Cached health
results and saved Health filters no longer surface health content when
disabled. Existing platform-only restrictions remain.

The `healthAdvisor` flag will be created separately in ConfigCat.

## How to test

- With `healthAdvisor` off, verify Health Advisor is absent from
navigation, command search, homepage alerts, and Advisor panel
categories. Opening `/project/<ref>/advisors/health` shows an
unavailable message. No health-check POST requests should run.
- With the flag on for an active platform project, verify these surfaces
return and health checks load.
- Disable the flag after loading health results and selecting the Health
filter or an alert. Verify cached health alerts disappear and the panel
remains usable.
- Existing menu tests pass. No new feature flag tests are included.
Formatting and whitespace checks passed.
- Local lint could not start because the available dependency
installation is missing `@eslint/compat`. Full TypeScript validation
failed with missing dependencies and incompatible workspace types in the
reused local dependency installation; it did not provide a clean
validation result.



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Health Advisor availability is now controlled by a feature flag on the
platform.
* When enabled, health advisories appear in advisor menus, filters,
project checks, and empty-state messaging.
* When unavailable, the Health Advisor page clearly indicates that it
isn’t available for the project.

* **Bug Fixes**
* Health advisory data is no longer requested when the feature is
disabled, preventing unavailable health results and errors from
appearing.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 11:00:02 +02:00
Guillaume Faas 1531eb427d docs(csharp): add new C# Reference for v8.0.0 (#50116)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Documentation update: add a new page for the C# SDK reference v8.0.0


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Added C# client reference documentation for version 8.1.0.
  * Added navigation for the C# Reference v8 documentation.
* Documented authentication, database, Realtime, Storage, filtering, and
query APIs with C# examples.

* **Documentation**
* Added C# SDK 8.0.0 and 8.1.0 release notes, including breaking
changes, new capabilities, and bug fixes.
* Updated documentation version listings and search coverage for C# v8.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 10:07:26 +02:00
Guillaume Faas ae7167fe58 docs: update SignUp documentation in C# reference (#48733)
Addresses https://github.com/supabase-community/gotrue-csharp/issues/85

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Documentation**
- Clarified sign-up behavior, including returned sessions, email
confirmation, automatic session adoption, and sign-in events.
- Documented existing-user obfuscation and the error raised when
registration is rejected.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 10:07:10 +02:00
Coenen Benjamin 9f7944a853 fix(warehouse): add support for both db host and db host addr in catalog (#50261) 2026-09-14 16:01:46 +08:00
Jordi Enric fb22534439 fix: share sentry crash policy and enable www reporting (#50232)
## Problem

The website initializes Sentry only on the server and edge runtimes,
leaving browser crashes unreported. Its crash-reporting setup also needs
the same consent and third-party filtering policy that docs and Studio
otherwise maintain separately.

## Fix

Add www browser initialization and tagged crash capture for both Next.js
routers, with accessible fallback focus. Move the shared
consent/platform and third-party filtering into common/sentry, reuse it
from all three apps, and remove the duplicated docs/www helpers and
tests. Preserve each app's initialization and Studio's additional noise
filtering, sampling, and sanitization.

Include the source-map upload token in www's build cache inputs, and
trigger the shared/www and Studio test workflows when the shared policy
changes.

## How to test

- Run `pnpm --filter www test ../../packages/common/sentry.test.ts
lib/sentry-capture.test.tsx`: all 22 shared-policy and real-SDK capture
tests passed locally.
- Run `pnpm --filter studio exec vitest run
lib/sentry-client-options.test.ts`: all 42 Studio options and
policy-parity tests passed locally.
- The www capture tests exercise the actual initializer and both router
handlers with an in-memory transport, verify crash tags and fallback
focus, and enforce consent. Removing initialization, capture calls,
boundary tags, or consent gating was verified to fail these tests.
- On a www preview with its DSN configured, accept telemetry consent and
trigger temporary render errors in both routers. Verify they reach the
www Sentry project with the boundary tag and readable stack traces.

Formatting passes. Full local app typechecks encounter existing
dependency/generated-file drift, with no diagnostics in changed files.
Three unchanged TanStack mock call-count tests fail locally and
reproduce against the pre-refactor implementation. Live Sentry ingestion
and source-map uploads remain deployment checks.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Accessibility**
- Error pages now automatically move focus to a clearly labeled error
message, helping screen-reader and keyboard users understand when a page
fails.

- **Reliability**
- Browser error reporting now captures application crashes more
consistently across supported page types and navigation transitions.
- Reporting respects consent and platform availability while filtering
unrelated third-party failures.

- **Testing**
- Expanded automated coverage for error capture, reporting rules,
consent handling, and accessible error-page behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 09:28:08 +02:00
Danny WhiteandJoshen Lim 4dd8a95f0b feat(studio): polish Warehouse connection methods (#50246)
## What kind of change does this PR introduce?

Feature polish and a connection behaviour change.

## What is the current behaviour?

The Warehouse Connect sheet presents FlightSQL and DuckDB configuration
together. Enabling Warehouse also enables DuckDB catalogue access
automatically, even when the user only needs FlightSQL.

## What is the new behaviour?

The Connect sheet now starts with a query engine selector:

- FlightSQL shows the endpoint, connection string, user, password
action, and command-line example.
- DuckDB shows a persistent catalogue access switch. When enabled,
credentials and the attach script appear as the same numbered "Follow
these steps" flow used by other connection methods.
- Switching back to FlightSQL removes the DuckDB instructions.

> [!NOTE]
> This is an incremental change towards [this
UI](https://linear.app/supabase/project/warehouse-core-mvp-b85711dc2eff/activity#project-update-4e3183e1),
where the Integrations page is the control plane and Connect sheet is
simply for read-only connect values.

https://github.com/supabase/supabase/pull/50247 and
https://github.com/supabase/supabase/pull/50195 are subsequent PRs that
get us there.

> [!IMPORTANT]
> Enabling Warehouse no longer enables DuckDB catalogue access
automatically. DuckDB users must enable it explicitly from the
connection details. FlightSQL is unaffected.

This keeps global Warehouse provisioning separate from optional
credentials for one query engine. It also prevents successful Warehouse
setup from being followed by a secondary catalogue mutation that can
fail independently.

| Before | After |
| --- | --- |
| <img width="1280" height="1323" alt="10752"
src="https://github.com/user-attachments/assets/83b1069b-a262-4068-a5e3-b7f49860fdb2"
/> | <img width="1280" height="1323" alt="Regular AWS Teamer Supabase"
src="https://github.com/user-attachments/assets/86ff1fe4-6513-44a8-88e1-1c7985f4910e"
/> |
| <img width="1280" height="1323" alt="10752"
src="https://github.com/user-attachments/assets/83b1069b-a262-4068-a5e3-b7f49860fdb2"
/> | <img width="1280" height="1323" alt="31254"
src="https://github.com/user-attachments/assets/733f074d-a52a-44a6-8898-a8f3c2b68294"
/> |
| _Unable to replicate._ | <img width="1280" height="1323" alt="Regular
AWS Teamer Supabase"
src="https://github.com/user-attachments/assets/c7d4ee59-b3f0-48b0-a6d7-2202ef5c2609"
/> |

## To test

1. Open `/project/{ref}?showConnect=true&connectTab=warehouse` on a
project. Enable Warehouse on 1+ table.
2. Confirm FlightSQL is selected initially and its connection fields are
visible.
3. Select DuckDB and confirm the catalogue switch is always visible.
4. Enable catalogue access and confirm the environment variables and SQL
appear below in two numbered steps.
5. Switch back to FlightSQL and confirm the DuckDB steps disappear.
6. Set up Warehouse on a project where it is not yet enabled and confirm
DuckDB catalogue access is not enabled automatically.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a query-engine selector for FlightSQL and DuckDB connection
setups.
* Added guided DuckDB setup steps, copy-to-clipboard support, and
reveal/hide controls for secrets.
  * Added a catalog access toggle with confirmation feedback.
  * Catalog details load only when DuckDB is selected.

* **Updates**
  * Streamlined warehouse connection layouts with consistent spacing.
* Catalog access is now controlled separately from the initial warehouse
setup.
* Excluded sensitive setup details from copied prompts and added
copy-status announcements.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-09-14 10:49:45 +10:00
19d7233580 feat(ui-library): add headless app block for TanStack Start (#49579)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Feature — a new UI Library block. Stacked on #49573 (already in main)

Fixes AI-1064

## What is the new behavior?

Adds `headless-app-tanstack`: customers sign in, authorize an MCP
client, and use the product through agent tool calls. It composes the
existing Password-Based Auth, OAuth Consent, and MCP Server blocks.

- `/agents` provides a copyable connection prompt, lists OAuth
authorizations, and lets customers revoke access.
- The shared MCP runtime exposes `whoami` plus example task CRUD tools.
Tools use the caller's Supabase client, with database grants and RLS
enforcing ownership.
- A root-level `supabase/` directory supplies local Auth/OAuth
configuration, a declarative tasks schema, and Edge Function files,
including `.env.example`.
- Docs cover local setup, signing keys, migrations, environment
configuration, deployment, and extending the tools.
`/example/headless-app` previews the sign-in, consent, connect, and
connected states.

Shared block fixes make a fresh install work:

- Explicit public URL resolution fixes OAuth discovery in local Edge
Runtime when middleware runtime detection fails. Both external OAuth
access tokens and ordinary authenticated app session tokens remain
supported; embedded agents do not need an additional consent flow.
- Registry targets keep backend files outside `src/`, and generated
consumer routes omit source-only TypeScript suppressions.
- Signup respects `auth.email.enable_confirmations`; sign-in/signup
preserve the return destination. Missing consent IDs retain the existing
error state without serializing `null` into the URL.

## How to test

Use the UI Library on **staging** and follow the block pages'
instructions.

1. Open the **Headless App** block page for TanStack Start. Install it
into a fresh app and follow the setup instructions through connecting an
MCP client.
2. Sign up, open `/agents`, and use the connection prompt to authorize a
client. Call `whoami`, then create, list, update, and delete a task.
3. Confirm the client appears on `/agents`. Revoke access and verify it
disappears and token refresh fails. An existing access token can
continue working until it expires.
4. Follow the **MCP Server** block page's embedded-agent instructions
using an authenticated app session. Confirm tools work without another
OAuth consent flow and `whoami` returns `client_id: null`.
5. With a second user, confirm each user can only access their own
tasks. Check that signup behaves correctly for the configured
email-confirmation setting.
6. Check the Headless App preview states and run the installed app's
typecheck and production build.

## Validation performed

Fresh local installation and browser/SDK verification passed: 26 live
MCP/Data API checks, 10 Deno tests, and 7 connection-page component
tests. Also passed UI Library typecheck, targeted lint,
registry/Markdown builds, and fresh consumer typecheck/production build.
Both OAuth and ordinary app session authentication were exercised.

Hosted deployment and consuming the confirmation-email link were not
tested.



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Added a TanStack Headless App example with sign-in, OAuth consent, MCP
connection, and connected-agent screens.
- Added task management tools for listing, creating, updating, and
deleting tasks through MCP.
- Added connected-agent management, including server URL and prompt
copying, refresh, and access revocation.
  - Added a new Headless App registry block and documentation.

- **Bug Fixes**
- Preserved intended destinations through sign-up, email confirmation,
and protected-route login redirects.
- Improved OAuth discovery URL handling across forwarded-host
deployments.

- **Documentation**
- Updated setup, environment, deployment, and Supabase CLI guidance for
headless apps and MCP servers.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Saxon Fletcher <SaxonF@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: repro <repro@local>
Co-authored-by: Raúl Barroso <code@raulb.dev>
2026-09-14 10:30:26 +10:00
Danny White 31046e7a7f perf(design-system): improve local dev content reload (#50069)
## What kind of change does this PR introduce?

Performance improvement for design-system doc page reload in local dev.

## What is the current behavior?

Doc pages import all compiled MDX from a single `.velite/allDocs.json`
bundle (~27MB for 105 docs). Velite rebuilds are fast, but every MDX
save forces Next to re-parse that entire file.

## What is the new behavior?

- Writes each doc's compiled MDX to `.velite/codes/{codeId}.json`;
`allDocs.json` keeps metadata only (~367KB)
- Loads doc code on demand in `lib/docs.ts` via `readFile`, with
`connection()` + dynamic `import('@/.velite')` in dev so pages re-read
fresh output after Velite rebuilds
- Skips `generateStaticParams` in dev
- Velite `output.clean` only in production
- README notes the per-doc output and adds commented getting-started
commands

Dev workflow is unchanged: `pnpm dev` still runs `velite dev` alongside
Next.js.

## To test

Local-only:

1. `cd apps/design-system && pnpm dev`
2. Open http://localhost:3003/design-system/docs/components/button
3. Edit `content/docs/components/button.mdx`, wait for `[VELITE] rebuild
finished`, refresh: change should land in ~200ms, not multi-second

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Documentation**
- Updated design-system setup instructions for environment
configuration, installation, development, and the local browser URL.
- Added guidance for building documentation content and regenerating
components.
  - Updated alternative command examples.
  - Removed the previous “Hot reload” section.

- **Improvements**
- Improved documentation page loading during development and production
builds.
- Documentation pages now reliably display their associated code
examples.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 09:40:17 +10:00
Danny White ffc76c1e36 feat(studio): give replication destinations a brand mark (#50251)
## What kind of change does this PR introduce?

Studio UI polish. This is the first PR in the Pipelines review stack and
targets `master`. Resolves DEPR-674.

## What is the current behaviour?

Replication destinations use generic line icons across the destination
picker, pipelines list, and replication diagram. The existing shared
ClickHouse and Snowflake assets also use older artwork.

## What is the new behaviour?

Adds a reusable `DestinationLogo` treatment and uses it consistently
across Replication surfaces. BigQuery, ClickHouse, DuckLake, and
Snowflake now use their colour brand marks, while destinations without a
dedicated asset retain their existing line icon in the same frame.

The refreshed ClickHouse and Snowflake artwork replaces the canonical
shared assets, so existing consumers such as the Wrappers catalogue
receive the updated marks too.

| Light | Dark |
| --- | --- |
| <img width="572" height="804" alt="CleanShot 2026-09-11 at 16 48
42@2x"
src="https://github.com/user-attachments/assets/5c2eaef3-8714-4c0a-8bcc-7c8618abd677"
/> | <img width="552" height="788" alt="CleanShot 2026-09-11 at 16 47
30@2x"
src="https://github.com/user-attachments/assets/2aff8775-cdc1-4d6b-9f78-7b40d42e102a"
/> |

| Add Pipeline form |
| --- |
| <img width="1252" height="730" alt="CleanShot 2026-09-11 at 16 48
57@2x"
src="https://github.com/user-attachments/assets/025a158c-57ee-495e-8356-00ed1717d09d"
/> |

## To test

1. Open `/project/<ref>/database/replication` and start adding a
pipeline.
2. Confirm the BigQuery, ClickHouse, DuckLake, and Snowflake marks
appear consistently in the destination picker, pipelines list, and
replication diagram.
3. Open the ClickHouse and Snowflake entries in the Wrappers catalogue
and confirm they use the refreshed artwork.
4. Confirm Analytics Bucket retains its existing fallback icon within
the same frame.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Visual Updates**
* Destination logos now display dedicated brand marks for ClickHouse,
DuckLake, Snowflake, and BigQuery.
* Updated replication destination selectors, rows, and diagrams to use
consistent destination logos.
  * Adjusted the destination type column width for improved layout.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-14 09:31:27 +10:00