Commit Graph
6718 Commits
Author SHA1 Message Date
Joshen Lim 09a1f431bc Mass update for all lucide icon imports to use the component with Icon suffix (#51659)
## Context

This is largely just a mechanical change here:
Opting to use lucide icons with the `Icon` suffix across all icon
imports within `studio`
- so that it’s clearer which components are icons + reduces the
possibility of name collision with our own components
- e.g <User /> vs <UserIcon />

Also added a eslint rule for this:
<img width="1069" height="167" alt="image"
src="https://github.com/user-attachments/assets/7f36f443-5ca2-4bf6-8d22-86e774513bfc"
/>

And updated `AGENTS.md` as such:
```
Icons come from `lucide-react`, always imported with the `Icon` suffix (`import { CheckIcon, Trash2Icon } from 'lucide-react'`) — never the bare names (`Check`) or `Check as CheckIcon` aliases (lint-enforced).
```
2026-10-14 12:56:55 +02:00
Brian-AnandDanny White f1082e28c7 chore: migrate Framer Motion imports to Motion (#51520)
## Problem

Closes #31221.
The applications and shared UI packages still import the former
`framer-motion` package instead of Motion's React entry point.

## Solution

Replace runtime imports, type imports, and three test mocks with
`motion/react` across the consuming workspaces.
Replace the seven direct dependency declarations with `motion:
^11.18.2`.
Preserve the existing animation engine version and all other dependency
resolutions, including the asynchronous `domMax` feature loader.
Historical blog examples remain as published; `framer-motion` remains a
transitive implementation dependency of Motion.

## Review instructions

1. Run `pnpm install --frozen-lockfile` and check the seven dependency
replacements in the lockfile.
2. Open the WWW Auth page and Docs homepage at desktop and mobile
widths, with normal and reduced motion preferences.
3. Open the mobile navigation, expand Product on WWW, and close the menu
using Escape and the close button.
4. Check the existing animation components, shared form validation, and
Studio tests for unchanged behavior.

Validation:

- Studio: 731 test files, 8,334 passing tests and one expected failure,
with `--maxWorkers=4`.
- Shared UI, UI patterns, WWW, and UI library: 615 passing tests.
- `pnpm run typecheck --concurrency=1`: all 16 repository tasks pass.
- All six application source lint scripts and lint ratchets pass;
generated Docs example copies are excluded from local lint.
- Repository Prettier source check, lockfile formatting, and case hazard
check pass.
- WWW: 10 existing end-to-end checks across nine pages.
- Docs: 5 existing guide link and accessibility checks across Database
and Auth.
- WWW and Docs mobile navigation pass at desktop/mobile sizes with
normal/reduced motion; SQL-to-REST translation tabs exercise the
asynchronous feature loader without browser errors.
- Frozen-lockfile installation passes; all existing package and snapshot
resolutions are unchanged.
- Learn and UI library command palettes open, filter results, and close
with Escape without browser errors.
- Independent code review finds no actionable defects.
- `npm run build -- --filter=www --filter=docs --filter=studio
--filter=learn --filter=library --concurrency=1 --continue=always`: all
five affected applications build successfully (9 tasks including
prerequisites); asset uploads disabled for local validation.

## Checklist

- [x] I have read
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
- [x] If I wrote a new docs topic or edited an existing topic, I used
the `/write-the-docs` or `/edit-the-docs` skill, which applies the docs
[style
guide](https://github.com/supabase/supabase/tree/master/apps/docs/style-guide)
(no docs topics changed)

---------

Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com>
2026-10-14 07:16:00 +00:00
Danny White 7fa436050a refactor(studio): compose the pipeline data section for wizard reuse (#51572)
## Problem

The pipeline wizard in #49243 needs publication, initial sync and
replication settings together on its data step.

## Solution

Compose `PipelineDataSection` from the existing controls and use it in
preview-enabled creation. It includes the publication selector,
initial-sync controls and data advanced settings, including BigQuery
table layout.

This preserves the grouping from #51570. Preview off and editing keep
the existing layout. Validation and creation behaviour stay the same; no
wizard routing is added. Stacked on #51570.

## Review instructions

1. Open the [Pipelines
preview](https://studio-staging-git-dnywh-featpipeline-data-section-supabase.vercel.app/dashboard/project/_/database/pipelines),
select a test project with Pipelines enabled and go to **Database →
Pipelines**. Enable **Pipeline creation wizard** in Feature Previews,
then click **Add pipeline**. Confirm **Data** follows **Destination
connection**, with publication and initial sync above its **Advanced
settings**.
2. Select a publication and change the initial-sync option. For
selected-table options, confirm the publication tables are available.
Click **New publication** in the publication selector and confirm the
existing creation panel opens, then cancel it.
3. Expand **Advanced settings** under **Data**. Confirm replication
settings appear, plus table layout for BigQuery, without connection pool
size, staleness or role. Change **Batch wait time**, collapse and reopen
the accordion, and confirm the value remains. Check desktop and phone
widths. Cancel and discard changes; no credentials or pipeline creation
are needed.
4. Turn the preview off and reopen **Add pipeline**. Confirm the
original layout remains. With the preview on, edit an existing pipeline
and confirm its original layout also remains.
2026-10-14 10:28:21 +11:00
Danny White 37fb536e6c feat(studio): group connection settings in the pipeline creation preview (#51570)
## Problem

The pipeline wizard in #49243 needs connection settings before table
selection.

## Solution

With **Pipeline creation wizard** enabled, rearrange the creation sheet
into destination selection, **Destination connection**, then **Data**.
Group name, region, credentials and connection advanced settings
together. Keep publication, initial sync, replication settings and
BigQuery table layout in the data section.

Preview off and editing keep the existing layout. Validation and
creation behaviour stay the same. This still uses the sheet; no wizard
routing is added. Stacked on #51568.

| Feature Preview Off | Feature Preview On |
| --- | --- |
| <img width="1272" height="2536" alt="CleanShot 2026-10-13 at 13 16
36@2x"
src="https://github.com/user-attachments/assets/ebad1082-b9ae-4f5e-91ad-08638ea2b032"
/> | <img width="1244" height="2538" alt="CleanShot 2026-10-13 at 13 17
20@2x"
src="https://github.com/user-attachments/assets/b5400b31-d60e-44e7-a4d6-cca1732b7974"
/> |
| _One “Advanced settings” at the bottom of the sheet that combines
everything. Destination details handles Publication and Initial sync._ |
_An “Advanced settings” accordion under BigQuery settings. Another
“Advanced settings” under Data (clipped above). Data contains fields for
Publication and Initial sync._ |

## Review instructions

1. Open the [Pipelines
preview](https://studio-staging-git-dnywh-featpipeline-connectio-6d0876-supabase.vercel.app/dashboard/project/_/database/pipelines),
select a test project with Pipelines enabled and click **Add pipeline**.
Enable **Pipeline creation wizard** in Feature Previews, then reopen the
sheet. Confirm the order is destination cards → connection → data.
2. With BigQuery selected, expand **Advanced settings** under
**Destination connection**. Confirm it contains pool size and staleness.
Expand **Advanced settings** under **Data** below publication and
initial sync. Confirm it contains replication settings and table layout,
without duplicate connection fields. Change a value and collapse/reopen
the accordion; confirm it remains.
3. If available, select DuckLake or Snowflake. Confirm their connection
accordion contains **Pool size** or **Role**, respectively. ClickHouse
and Analytics Bucket have no connection accordion. Check desktop and
phone widths. Cancel and discard changes; no credentials or pipeline
creation are needed.
4. Turn the preview off and reopen **Add pipeline**. Confirm the
original layout returns. With the preview on, edit an existing pipeline
and confirm it also keeps the original layout.
2026-10-14 10:17:20 +11:00
Danny White d457ab59c7 feat(studio): add pipeline wizard destination selection (#51568)
## Problem

The pipeline creation wizard in #49243 needs a destination selection
step that can be reviewed before wizard routing lands.

## Solution

Add `PipelineDestinationSelection` with BigQuery, DuckLake, Snowflake,
ClickHouse and deprecated Analytics Bucket radio options, using Studio’s
existing destination logos. Show it in the creation sheet only when
**Pipeline creation wizard** is enabled in Feature Previews and allowed
by ConfigCat. Preview off and editing retain the existing dropdown.

This is an incremental preview: creation still uses the sheet. No wizard
routing or design-system changes are included.

| Feature Preview Off | Feature Preview On |
| --- | --- |
| <img width="1274" height="1316" alt="CleanShot 2026-10-13 at 10 39
24@2x"
src="https://github.com/user-attachments/assets/433e4fb1-5fa2-4dc3-982e-0aee6b266015"
/> | <img width="1250" height="1890" alt="CleanShot 2026-10-13 at 10 53
09@2x"
src="https://github.com/user-attachments/assets/033d7e43-1a57-4d61-90e8-9048e3560909"
/> |

## Review instructions

1. Open the [preview to Database →
Pipelines](https://studio-staging-git-dnywh-featpipeline-destinati-54dc7d-supabase.vercel.app/dashboard/project/_/database/pipelines),
select a test project with Pipelines enabled and click **Add pipeline**.
With **Pipeline creation wizard** off, confirm the existing destination
dropdown appears.
2. Close the sheet, enable **Pipeline creation wizard** in Feature
Previews and reopen **Add pipeline**. Confirm radio cards replace the
dropdown, with BigQuery selected initially and only destinations
available to your project shown.
3. If Analytics Bucket is available, confirm its card has a
**DEPRECATED** badge. Select it and confirm the bucket fields appear and
the description below says **Destination type cannot be changed after
creation. Analytics Bucket is deprecated.** Click another destination.
Confirm only one card is selected and the connection fields below switch
to that destination. Use arrow keys to move focus and Space to select a
destination. Check at desktop and phone widths. Cancel and discard
changes; no credentials or pipeline creation are needed.
4. With the preview still on, open an existing pipeline for editing.
Confirm its destination dropdown remains locked. Turn the preview off
and reopen **Add pipeline** to confirm the original dropdown returns.
2026-10-14 09:59:48 +11:00
Monica Khoury eaad809abf fix: webhook retry error handling (nested error envelope + unhandled rejections) (#51591)
## What
Fixes two bugs found while writing component tests for the platform
webhooks page (follow-up to FE-3749):

1. The webhooks API nests error details under an `error` key (`{ error:
{ code, message } }`), but the shared `handleError` only reads a
top-level `message`. This meant the friendly rate-limit message ("wait a
minute and try again") never actually fired, it always fell back to a
generic error. Fixed with a local unwrapping `handleError` in
`platform-webhooks-fetchers.ts`.
2. Every mutation handler on the page (`mutateAsync` for
create/update/delete/regenerate-secret/send-test-event/retry) left the
re-thrown error from React Query uncaught, producing an unhandled
promise rejection on every failure, even though the error toast itself
was already correct. Fixed by wrapping each call in try/catch.

## Why
Found while writing the stacked test PR for FE-3749; filed as
[FE-4620](https://linear.app/supabase/issue/FE-4620/two-webhook-error-handling-bugs-found-while-writing-retryrate-limit)
since it's a correctness fix independent of the test work.

## Testing
Manually verified both fixes on localhost: rate-limit retry now shows
the friendly message, and no `Uncaught (in promise)` errors appear in
the console on any mutation failure.
2026-10-13 19:44:21 +03:00
Joshen Lim 3a33cbcce5 Show main branch as part of the empty state (#51607)
## Context

Shows the production branch as part of the branching empty state (Shifts
`BranchingEmptyState` into `Overview`)

It's so that users can still then reach the "View logs" button for the
production branch which was otherwise hidden

<img width="1214" height="531" alt="image"
src="https://github.com/user-attachments/assets/3bc702f2-950b-4d9e-8b4f-78149af9ed82"
/>
2026-10-13 15:48:48 +00:00
Gildas GarciaandJoshen Lim 4bf7b16473 feat(studio): scoped oauth apps reconsent UI (#51078)
## Problem

When users must grant access to an app they already added because its
scopes changed, they should have a clear understanding of the changes

## Solution

Show only the scopes differences by default

<img width="844" height="962" alt="image"
src="https://github.com/user-attachments/assets/6289f4cf-200f-4660-b9a1-aedbaaa963e3"
/>

## Review instructions

Try this UI with
[`authorize?mock_scenario=reconsent`](https://studio-staging-git-gildasgarcia-oauth-apps-inte-6106b6-supabase.vercel.app/dashboard/authorize?mock_scenario=reconsent)

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-10-13 17:25:50 +02:00
Francesco Sansalvadore 25708ed67a chore(studio): storage versioning override conflict (#51593)
## Problem

When uploading a file with same name of already existing file, the ui
automatically creates a new file with incremental number and doesn't
consider the scenario of giving the possibility of storing the new
upload as a version of the already existing file.

## Solution

Provide modal to chose the behaviour when name conflict happens when
uploading a file:
- Replace existing file (same file with version history)
- Keep both (new file with incremental numbering)


https://github.com/user-attachments/assets/ee192be9-4087-4e14-89f1-1c82acf550cd

Manage edge case of clashes with files created when bucket had
versioning enabled (so with `is_versioned` flag to true) and clashing
upload happens when bucket is in SUSPENDED state.


https://github.com/user-attachments/assets/00694c77-07c1-405e-bd54-bdf0bf99d274

Unrelated fix:
- add "Delete permanently" action when selecting multiple files with
versioning enabled

<img width="510" height="203" alt="Screenshot 2026-10-13 at 15 59 27"
src="https://github.com/user-attachments/assets/5692fc23-2fd3-4259-9de2-3932aecbccd0"
/>
2026-10-13 17:14:30 +02:00
8b9af56867 feat(studio): link specific region to regions docs in free-tier region selector (#51590)
<!-- claude-slack-attribution -->
_Requested by **Charis Lam** · [Slack
thread](https://supabase.slack.com/archives/C0161K73J1J/p1791896774914759)_

**Before:** The free-tier region selector footer read "Upgrade to Pro to
choose a specific region." with only "Upgrade to Pro" linked (to the
billing plan panel).

**After:** "specific region" also links to
https://supabase.com/docs/guides/platform/regions (opens in a new tab),
so users can see which regions exist. Requested by Lukas Bernert on
#51282.

Wrapped "specific region" in `InlineLink` with
`${DOCS_URL}/guides/platform/regions` in `RegionSelector.tsx` and
extended the existing wizard test to assert the link href.

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

https://claude.ai/code/session_01TsqepmwoWCXiv9BTxQK7MD

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

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-10-13 10:58:28 -04:00
ChloeGarciaMillerandandGildas Garcia e0d3489c87 fix: ESLint errors relating to accessibility in project settings (#50848)
## Problem

Some aria-label and Tooltip are missing for icon-only buttons.

The components are used in
- project settings / infrastructure
- integrations / data API / settings

## Solution

Improving accessibility by adding `aria-label` and `Tooltip`.

<!--
## Preview links

If relevant, include links to changed pages for easy review access.

Copy the preview base URL from the Vercel bot comment on this PR. Use
the following table as an example template.

| Site | Live | Preview | Search for |
| -------------- |
-------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------
| ----------------------------- |
| WWW | [/blog/your-post](https://supabase.com/blog/your-post) |
[/blog/your-post](https://zone-www-dot-com-git-branch-name-supabase.vercel.app/blog/your-post)
| unique phrase from the change |
| Docs |
[/docs/guides/your-page](https://supabase.com/docs/guides/your-page) |
[/docs/guides/your-page](https://docs-git-branch-name-supabase.vercel.app/docs/guides/your-page)
| unique phrase from the change |
| Studio | [/dashboard](https://supabase.com/dashboard) |
[/dashboard](https://studio-git-branch-name-supabase.vercel.app/dashboard)
| unique phrase from the change |
| Design system | [/design-system](https://supabase.com/design-system) |
[/design-system](https://design-system-git-branch-name-supabase.vercel.app/design-system)
| unique phrase from the change |
| UI library | [/library](https://supabase.com/library) |
[/library](https://ui-library-git-branch-name-supabase.vercel.app/library)
| unique phrase from the change |
| Knowledge base |
[/kb/guides/your-page](https://supabase.com/kb/guides/your-page) |
[/kb/guides/your-page](https://kb-git-branch-name-supabase.vercel.app/kb/guides/your-page)
| unique phrase from the change |
-->

<!-- ## Additional context

No visual changes have been made.

-->

## Review instructions

Provide a clear numbered procedure that the PR reviewer can walk
through.

1. Open the pages where the updated components are used
2. See that the tooltips appear correctly when interacting with the
relevant elements


## Checklist

Check all before review:

- [X] I have read
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
- [ ] If I wrote a new docs topic or edited an existing topic, I used
the `/write-the-docs` or `/edit-the-docs` skill, which references
[WORD_LIST](https://github.com/supabase/supabase/blob/master/apps/docs/WORD_LIST.md)
and the docs
[CONTRIBUTING](https://github.com/supabase/supabase/blob/master/apps/docs/CONTRIBUTING.md)
guide


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

* **Accessibility**
* API function, schema, and table selectors have clear accessible names
and tooltips.
* Selector status summaries are announced politely by screen readers,
including schema loading states and available counts.
* **UI**
* Simplified the layout of the “Automatically expose new tables” setting
without changing its behavior.
* Corrected the transition styling on the infrastructure flow button;
its reduced-motion behavior remains unchanged.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com>
2026-10-13 16:36:05 +02:00
claude[bot]andClaude 44ed522778 chore(studio): bump no-arbitrary-values ratchet baseline to 198 (#51594)
<!-- claude-slack-attribution -->
_Requested by **Charis Lam** · [Slack
thread](https://supabase.slack.com/archives/C0161K73J1J/p1791896774914759)_

**Before:** The `ratchet` check fails on any PR that includes current
master. The baseline for `shadcn/no-arbitrary-values` is 197, but master
has 198 since `text-[11px]` landed in `ArchivedVersionRestoreWidget.tsx`
via #51476. The baseline bot lowered it to 197 right after (#51524).

**After:** The baseline is 198, matching master, so the check passes
again.

This only changes that one rule's number (plus its per-file breakdown
entry for the widget) in
`apps/studio/.github/eslint-rule-baselines.json` and leaves the
underlying arbitrary value for its owner to fix.

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

https://claude.ai/code/session_01TsqepmwoWCXiv9BTxQK7MD

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

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-13 14:28:03 +00:00
Mert YEREKAPANandJoshen Lim e5bc7d8fa1 chore(studio): ship fullscreen pricing panel, remove plan presentation experiment (#51554)
## Summary

The `pricingPanelPlanPresentation` experiment is concluded with
`fullscreen` as the winner. This makes it the only presentation and
removes the experiment code.

- Plan-change panel always opens as the full-screen overlay with the
pricing-page style cards.
- Removed the `control`, `parity`, `gaps` and `fullscreen-gaps`
presentations: the side-sheet shell, the original compact card, and the
"Not included" / "Plan limits" gap rows.
- Removed `plan-presentation.ts` (flag read, eligibility gate, exposure
tracking, gap lists) and its tests.
- Removed the `pricing_panel_plan_presentation_experiment_exposed` event
from `telemetry-constants.ts`.
- The panel no longer waits for PostHog flags to resolve before opening.
- `useTrackExperimentExposure` stays; it's kept across experiment gaps
in `knip.jsonc`.

**Behavior change for previously ineligible orgs:** partner-billed,
Stripe-managed, AWS Marketplace, Enterprise/Platform orgs and members
without billing write were held on `control` during the test. They now
also get the full-screen panel. Their partner-managed notices and
disabled CTAs are unchanged.

## After merge

- [ ] Archive the `pricingPanelPlanPresentation` flag and end the
experiment in PostHog.

## Test plan

- [x] `vitest` for `BillingSettings/Subscription`: 11 passing
(partner-managed messaging, full-screen shell, pricing-page cards, no
gap rows)
- [x] `tsc`: no errors in touched files
- [x] `knip --workspace apps/studio`: clean
- [ ] Preview: open `/org/[slug]/billing?panel=subscriptionPlan` for a
Free org and a partner-billed org

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

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-10-13 06:58:30 -07:00
Joshen Lim 0f238b5296 Make project vercel integrations collapsible (#51585)
## Context

For a project that might have multiple connections to Vercel projects,
the Settings -> Integrations -> Vercel section can get really long as
we're showing the configuration fields for all projects by default

Opting to make each vercel integration a collapsible instead

Also improves the "Configure connection" CTA from org integration
settings to include an id in the URL, so that redirecting users to the
project settings integrations page will land them on the right section

### Before

Organization settings -> integrations
<img width="500" alt="image"
src="https://github.com/user-attachments/assets/f5b9ea2c-0a95-4aff-9416-e16f853d3b8e"
/>

Project settings -> Integrations
<img width="500" alt="image"
src="https://github.com/user-attachments/assets/361d5ac7-5919-4103-aaae-cdb5b1a1ce8c"
/>


### After

Organization settings -> integrations
<img width="500" alt="image"
src="https://github.com/user-attachments/assets/232cfef7-affe-4f06-a019-7f86ee7805db"
/>

Project Settings -> Integrations
<img width="500" alt="image"
src="https://github.com/user-attachments/assets/c3902451-0578-4bfc-8149-2d6f9c276ebd"
/>
2026-10-13 07:52:33 -06:00
supabase-supabase-autofixer[bot]andgithub-actions[bot] a89da5babb [bot] Decrease ESLint ratchet baselines (#51524)
Automated weekly decrease of ESLint ratchet baselines.

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-10-13 09:42:54 -04:00
Jordi Enric 6f36fe879b fix(studio): require an available project region FE-3884 (#51582)
## Problem

Project creation can send a request without a region, which the API
rejects. Empty region values pass frontend validation, and a failed
available-regions request fills in a static region name that cannot
resolve to a region selection.

## Fix

Keep the region selector controlled from mount and require a nonempty
value. Disable creation when available regions fail to load, guard
submission against unresolved region selections, and preserve the static
fallback for providers that use it.

Fixes
[FE-3884](https://linear.app/supabase/issue/FE-3884/project-creation-wizard-can-submit-with-an-empty-region).

## How to test

- Open the new-project form and verify the recommended region submits
without manually selecting a region.
- Submit with an empty region. Expected result: an inline validation
error appears and no project creation request is sent.
- Fail the available-regions endpoint, including after changing compute
size with a region already selected. Expected result: the region-loading
error appears, creation is disabled, and direct form submission sends no
project creation request.
- Run `pnpm --filter studio exec vitest --run
'tests/pages/new/[slug].test.tsx'
tests/pages/vercel-deploy-button-new-project.test.tsx
components/interfaces/ProjectCreation/ProjectCreation.schema.test.ts`.

Local validation: all 54 focused tests and formatting pass. Focused
ESLint has no errors. Local typecheck reports the existing image type
mismatch in InstructionBlocks.tsx; CI typecheck passed for the previous
commit.
2026-10-13 12:20:43 +02:00
ec2657e4f7 fix: Filter the version selector in the new project form by the chosen project type (#51490)
This pull request enhances the project creation flow by introducing
support for filtering Postgres versions based on the OrioleDB engine.
The main changes involve updating the `PostgresVersionSelector`
component to allow filtering for OrioleDB-specific versions, and
integrating this logic into the internal-only configuration step of
project creation. This provides a clearer and more flexible experience
when selecting Postgres versions, especially for internal or advanced
users.

**Postgres Version Selection Enhancements:**

* Added a new `useOrioleDbForCreate` prop to `PostgresVersionSelector`,
allowing the component to filter available Postgres versions to only
OrioleDB-based options or exclude them, based on user selection. The
prop defaults to `undefined` for no filtering.
[[1]](diffhunk://#diff-1842d78cb2a4be2c2b6e1581981d8111304fd9aaf0ad45df273d8c001938bcd9R41-R50)
[[2]](diffhunk://#diff-1842d78cb2a4be2c2b6e1581981d8111304fd9aaf0ad45df273d8c001938bcd9R82-R85)
[[3]](diffhunk://#diff-1842d78cb2a4be2c2b6e1581981d8111304fd9aaf0ad45df273d8c001938bcd9L92-R114)
* Added a `description` prop to `PostgresVersionSelector` for improved
UI guidance, and passed this prop through the form.
[[1]](diffhunk://#diff-1842d78cb2a4be2c2b6e1581981d8111304fd9aaf0ad45df273d8c001938bcd9R41-R50)
[[2]](diffhunk://#diff-1842d78cb2a4be2c2b6e1581981d8111304fd9aaf0ad45df273d8c001938bcd9R82-R85)
[[3]](diffhunk://#diff-1842d78cb2a4be2c2b6e1581981d8111304fd9aaf0ad45df273d8c001938bcd9L139-R161)

**Integration with Project Creation Flow:**

* Updated `InternalOnlyConfiguration` to watch the `useOrioleDb` form
field and pass its value to `PostgresVersionSelector`, ensuring the
version list is filtered appropriately during project creation. Also,
conditionally set the description to guide users toward advanced
configuration for OrioleDB.
[[1]](diffhunk://#diff-f0fa51a1cc67bb1a2c38d2c595eb3cab3a45813a027a04942d684914f2c3de93R33)
[[2]](diffhunk://#diff-f0fa51a1cc67bb1a2c38d2c595eb3cab3a45813a027a04942d684914f2c3de93R60-R65)
* Adjusted the render order in `ProjectCreationForm` to ensure advanced
configuration and internal-only configuration are displayed in a logical
sequence.

**Other Improvements:**

* Imported the `isSuccess` utility from `effect/Result` in
`PostgresVersionSelector.tsx` to support the updated logic.

---------

Co-authored-by: Alaister Young <alaister@users.noreply.github.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-10-13 12:15:51 +02:00
kemal.earthandGildas Garcia 64a6aa9085 feat(studio): ui for oauth app create edit form (#51023)
## Problem

Extends the create and edit form for OAuth apps. Adds two toggles and
their connections.

## How to test

In _Organization Settings \ OAuth Apps_

### New app

- You should be able to create an app without toggling any of the two
new options
- Toggling any of the two new option should require a confirmation that
blocks the form submition until checked

### Existing app

**The default values for existing apps are hard coded for now**
- You should be able to update any of the app props except the _Use the
permissions of the person who connects_ option which should be disabled.
- Toggling the _Ask for specific projects_ option should require a
confirmation that blocks the form submition until checked

---------

Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com>
2026-10-13 11:25:19 +02:00
Efekan 550f18b050 fix(studio): clarify authenticator app name and add direct support link during MFA sign-in (#51531)
## Problem

When users set up two-factor authentication (TOTP) in the dashboard, the
enrollment modal asks them to name their authenticator app, with the
placeholder suggesting `e.g.: Google Authenticator`. Many users keep or
type this example name without realizing it is simply a custom nickname
for the factor.

On the sign-in MFA screen (`SignInMfaForm.tsx`), the code input
previously rendered its label as:
> `Code generated by Google Authenticator`

This phrasing can lead users to believe that Supabase has locked their
account specifically to Google's authenticator app—even when they
actually scanned the QR code with Apple Passwords / iOS Keychain,
1Password, or Bitwarden. As reported in #51502, users who rely on their
iPhone's built-in authenticator can get alarmed, thinking their
authentication setup was unexpectedly swapped.

Furthermore, if a user is genuinely locked out (e.g. lost device and
backup codes), the "Email support" option previously only surfaced after
an explicit authentication exception occurred, rather than being readily
discoverable under the *"Unable to sign in?"* help section.

Closes #51502

## Solution

1. **Clear, standard form label & descriptive subtext**:
- Replaced the ambiguous `Code generated by [Friendly Name]` label with
a standard `Authentication code` label.
   - Moved the factor's friendly name into the field description:
- When a name is configured: `From the authenticator app registered as
[Friendly Name]`
- Fallback when no name is set: `From the authenticator app registered
to this account`
- This makes it immediately obvious that `[Friendly Name]` is just the
custom label they chose, rather than a hard vendor requirement.

2. **Direct support escape hatch**:
- Added an **"Email support to regain access"** link directly into the
*"Unable to sign in?"* list in both `SignInMfaForm` and
`SignInRecoveryCodeForm`.
- Users who are stuck now have an immediate, obvious way to reach out
without needing to trigger errors or hunt down the support email.

3. **Extracted testable helper logic**:
- Extracted friendly-name normalization and support mailto generation
into a dedicated `SignInMfa.utils.ts` module.
- Added unit test coverage in `SignInMfa.utils.test.ts` (9 tests
covering trims, null/empty cases, and mailto parameters).

## Review instructions

1. Navigate to `/sign-in-mfa` (with an account that has a TOTP factor
enrolled).
2. Verify that the input label reads `Authentication code`.
3. Check the subtext: verify that it clarifies `From the authenticator
app registered as [Name]`.
4. Inspect the *"Unable to sign in?"* section at the bottom:
- Confirm that "Email support to regain access" is visible and opens a
pre-addressed email to `support@supabase.com` with subject `Unable to
sign in via MFA`.
5. Check `/sign-in-recovery-code` and verify the same support link is
present.

## Checklist

- [x] I have read
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
- [x] Unit tests added and passing (`vitest run
components/interfaces/SignIn/SignInMfa.utils.test.ts`)
- [x] Code passes Prettier formatting check
- [x] Code passes ESLint without adding warnings
2026-10-13 09:59:32 +02:00
kemal.earthandCharis Lam b2dab2b896 feat(studio): update region selector in create form (#51282)
## Problem

Updates the region selector in create form to we can run a small
experiment.

---------

Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com>
2026-10-13 08:43:21 +01:00
Joshen Lim fe8b4df66d Chore/tiny refactor org limit (#51550)
## Context

Tiny refactor that I happened to pass by as I was reviewing other PRs

`useOrgProjectsInfiniteQuery` has a default `limit` value at 96 set in
the hook, 96 mainly for the home page to render a full row of cards
since cards are rendered in rows of 3

However, we have a couple of callsites for `useOrgProjectsInfiniteQuery`
that were passing a different `limit` value, hence these would be
triggered as a separate API request.

Am opting to remove the `limit` parameter from
`useOrgProjectsInfiniteQuery` so that the limit is standardized to 96
- So that data can be cached without having to invoke another API
request wherever `useOrgProjectsInfiniteQuery` is called
- I doubt that there'll be a need in a UI that will require calling
`useOrgProjectsInfiniteQuery` with a separate value for `limit` but
please do let me know otherwise if I might be overlooking anything!
2026-10-13 11:06:49 +08:00
Francesco SansalvadoreandClaude Sonnet 5 cb4307f15b feat(studio): storage versioning - archived UI (#51476)
## This PR

Adds **Show archived** to the file explorer's view options and list them
in the file explorer.

- `useStoragePreference` — `showArchivedInline`, stored per project
- `ArchivedFilesContext` — owns the archived list and which object is
selected
- `FileExplorer` — merges archived rows into each column and re-sorts,
since the server-side sort never sees them
- `FileExplorerRow` — dimmed striped rendering, no checkbox, no context
menu
- `FileExplorerHeader` — the toggle, rendered only behind the feature
preview
- `StorageExplorer` — mounts the provider


https://github.com/user-attachments/assets/a26551b4-b22d-485e-9d23-3e78c4a89315

Clicking an archived row opens a preview panel: where the file used to
live, when it was archived, its retained versions, and the actions to
bring it back or delete it permanently.

- `ArchivedFilePreviewPane` — the pane, replacing `PreviewPane` while an
archived row is selected
- `ArchivedVersionRestoreWidget` — takes over the top of the pane when a
specific retained version is selected
- `ArchivedVersionRow` — one version, with its restore / delete actions
- `StorageExplorerContent` — the pane swap


https://github.com/user-attachments/assets/03c9eae6-e9e3-4bd0-8145-953625e125d1

Other additions behind the feature preview:

- The buckets list show a **Versioning** column.
- `BucketVersioningPill` — a `file-stack` badge beside the bucket name
in the breadcrumbs, brand when versioning is enabled and warning when it
is suspended, so the bucket's state is visible from inside the explorer
rather than only from the buckets list.


https://github.com/user-attachments/assets/f4827aac-a9ff-4300-92ac-073848d63606

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-12 17:13:16 +02:00
Guillaume Faas 7625a0353e feat(studio): add dotnet framework to Connect flow (#51257)
## Feature

Add a ".NET" option to the "Connect" flow in the Dashboard, with several
variants.

## Preview links

If relevant, include links to changed pages for easy review access.

Copy the preview base URL from the Vercel bot comment on this PR. Use
the following table as an example template.

| Site | Live | Preview | Search for |
| -------------- |
-------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------
| ----------------------------- |
| Studio | [/dashboard](https://supabase.com/dashboard) |
[/dashboard](https://studio-staging-git-guillaumefaas-sdk-1881-add-s-537090-supabase.vercel.app/)
| Add .NET option in Connect |

## Review instructions

1. Click on the "Connect" button when on a project page
2. Select ".NET" in the frameworks drop-down
3. Verify the 3 variants (ASP.NET Core, Unity, Console)

## Checklist

Check all before review:

- [x] I have read
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
- [x] If I wrote a new docs topic or edited an existing topic, I used
the `/write-the-docs` or `/edit-the-docs` skill, which applies the docs
[style
guide](https://github.com/supabase/supabase/tree/master/apps/docs/style-guide)
2026-10-12 10:34:54 +02:00
Gildas GarciaandJoshen Lim 88bc1ac384 feat(studio): oauth apps users own grant list in account settings (#50903)
## Purpose

Users now have an _apps_ page in their account settings allowing them to
see their own grants, the projects they affect and to disconnect an app.

This PR only uses mock data. Besides, the page and menu item are behind
a feature flag enabled on staging

<!--
## Preview links

If relevant, include links to changed pages for easy review access.

Copy the preview base URL from the Vercel bot comment on this PR. Use
the following table as an example template.

| Site | Live | Preview | Search for |
| -------------- |
-------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------
| ----------------------------- |
| WWW | [/blog/your-post](https://supabase.com/blog/your-post) |
[/blog/your-post](https://zone-www-dot-com-git-branch-name-supabase.vercel.app/blog/your-post)
| unique phrase from the change |
| Docs |
[/docs/guides/your-page](https://supabase.com/docs/guides/your-page) |
[/docs/guides/your-page](https://docs-git-branch-name-supabase.vercel.app/docs/guides/your-page)
| unique phrase from the change |
| Studio | [/dashboard](https://supabase.com/dashboard) |
[/dashboard](https://studio-git-branch-name-supabase.vercel.app/dashboard)
| unique phrase from the change |
| Design system | [/design-system](https://supabase.com/design-system) |
[/design-system](https://design-system-git-branch-name-supabase.vercel.app/design-system)
| unique phrase from the change |
| UI library | [/library](https://supabase.com/library) |
[/library](https://ui-library-git-branch-name-supabase.vercel.app/library)
| unique phrase from the change |
| Knowledge base |
[/kb/guides/your-page](https://supabase.com/kb/guides/your-page) |
[/kb/guides/your-page](https://kb-git-branch-name-supabase.vercel.app/kb/guides/your-page)
| unique phrase from the change |
-->

<!-- ## Additional context

Optionally add any other context or screenshots.

-->

## Review instructions

- In _Account/OAuth Apps_, you should see a list of apps
<img width="748" height="359" alt="image"
src="https://github.com/user-attachments/assets/8c50a467-e2c1-4000-aecf-09d5db1591d3"
/>
- Each app should have a menu entry allowing to disconnect it (fake for
now)
<img width="587" height="278" alt="image"
src="https://github.com/user-attachments/assets/6221fbd6-3b61-4d93-903e-9aedaf94de3f"
/>
- Each app but the last should have a menu entry that opens a dialog to
see the connected projects
<img width="657" height="651" alt="image"
src="https://github.com/user-attachments/assets/e985f933-fdfb-4d28-93c3-b3678d7d8a53"
/>

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-10-12 10:15:33 +02:00
Francesco SansalvadoreandClaude Sonnet 5 876bb8cf9e feat(storage): archived objects data layer (#49677)
## This PR

On a versioned bucket a file or a version can be "soft deleted/archived"
or "permanently deleted".

- `archived-objects-query.ts` — `ArchivedObject` /
`ArchivedObjectVersion` types + `archivedObjectsQueryOptions`
- `archived-object-restore-mutation.ts` — bring an archived object back
into the live tree
- `archived-object-purge-mutation.ts` — delete it and every version,
permanently
- `archived-object-version-delete-mutation.ts` — remove one retained
version
- `archivedOverlay.utils.ts` — synthesizes the explorer rows for one
folder from the archived list
- `archivedVersions.utils.ts` — an archived object's history as one
flat, newest-first list

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-12 09:57:39 +02:00
Danny White f2d8eba736 refactor(studio): share pipeline region and selection copy for wizard review (#51540)
## Problem

The pipeline creation wizard in #49243 needs to reuse the pipeline
region display and publication and initial-sync wording in review. These
currently live inside the sheet’s fields.

## Solution

Extract `PipelineRegionReadonly` and shared selection copy, with the
existing sheet as their first consumer. Region styling, labels,
descriptions and selection behaviour stay the same.

## Review instructions

1. Open the [preview to Database →
Pipelines](https://studio-staging-git-dnywh-refactorpipeline-revie-080d09-supabase.vercel.app/dashboard/project/_/database/pipelines),
select a test project with Pipelines enabled and click **Add pipeline**.
2. Confirm **Pipeline region** still shows the flag, region name and
code as read-only information, with the same description and spacing.
3. Select a publication and open **Initial sync**. Confirm the four
options keep their existing labels and descriptions. Choose **Selected
tables only**, select a table, then choose **All except selected
tables**. Confirm the selection description switches from running to
skipping initial sync and still says ongoing replication includes every
publication table. Cancel and discard changes; no credentials or
pipeline creation are needed.
2026-10-12 17:51:52 +11:00
Guillaume Faas 1c97fe51be docs: move C# SDK from community to official support (#51487)
## Problem

Remove COMMUNITY badge from C# SDK Reference, and fix links pointing to
`supabase community`.

## Checklist

Check all before review:

- [x] I have read
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
- [x] If I wrote a new docs topic or edited an existing topic, I used
the `/write-the-docs` or `/edit-the-docs` skill, which applies the docs
[style
guide](https://github.com/supabase/supabase/tree/master/apps/docs/style-guide)
2026-10-12 14:48:36 +08:00
Danny White 188f5a743b refactor(studio): extract replication fields for wizard reuse (#51538)
## Problem

The pipeline creation wizard in #49243 needs replication settings on its
data step, separately from destination connection settings. These fields
currently live inside the sheet’s Advanced settings accordion.

## Solution

Extract **Batch wait time**, **Table sync workers**, **Initial sync
connections per table** and **Invalidated slot behavior** into
`ReplicationFields`. Keep the existing accordion as its first consumer.
Labels, defaults, units, field order and empty-value handling stay the
same.

## Review instructions

1. Open the [preview to Database →
Pipelines](https://studio-staging-git-dnywh-refactorpipeline-repli-2d71d1-supabase.vercel.app/dashboard/project/_/database/pipelines),
select a test project with Pipelines enabled and click **Add pipeline**.
Expand **Advanced settings**.
2. Confirm the four replication settings appear in their existing order,
before BigQuery’s connection settings and table layout. For DuckLake,
**Pool size** stays above them; for Snowflake, **Role** stays below
them.
3. Enter `0` for **Batch wait time**, `8` for **Table sync workers** and
`3` for **Initial sync connections per table**. Clear and re-enter each
value. Confirm no `NaN` appears. Select **Recreate slot**, then collapse
and reopen the accordion. Confirm all values remain. Cancel and discard
changes; no credentials or pipeline creation are needed.
2026-10-12 17:45:36 +11:00
Jordi EnricandJoshen Lim d1e0b551c5 fix(studio): show correct timezone offsets FE-4612 (#51484)
## Problem

Restore timezone labels use fixed UTC offsets from the timezone catalog.
Madrid displays UTC+01:00 during daylight saving time even though the
reported restore timestamp correctly uses UTC+02:00.

## Fix

Calculate display offsets from the restore instant and the timezone's
IANA identifier using Intl. Apply the same formatter to dropdown
options, the selected timezone, and PITR confirmation while preserving
existing restore calculations and timezone selection identity.

Fixes https://linear.app/supabase/issue/FE-4612

## How to test

- Choose Madrid in restore-to-new-project or PITR and compare winter and
summer restore dates. Expected result: UTC+01:00 in winter and UTC+02:00
during daylight saving time, including the confirmation label.
- Check UTC, New York, Kolkata, and Kathmandu. Expected result: correct
zero, negative, and fractional offsets.
- Focused Vitest suite: 15 tests passed, including both Madrid DST
boundaries and timestamp preservation. The component test verifies
visible trigger and option labels update after a date change, Madrid
search results, selection preserving the original timezone object, and
popover closure. It also passes under UTC and Hong Kong browser
timezones. Prettier and diff checks passed.
- All CI checks passed for the latest commit, including Studio tests,
all four Next.js/TanStack E2E shards, typecheck, lint ratchet,
formatting, spelling, unused-code checks, and Docker build. Full local
typecheck and ESLint validation were blocked by the shared dependency
installation being out of sync with this checkout.

Calculation audit confirmed the reported October 9 Madrid 05:12 to UTC
03:12 conversion. Separate existing date-control issues were found when
browser and restore timezones differ and around the repeated autumn
hour; those are outside this label fix and relevant to FE-4129.

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-10-12 14:36:48 +08:00
Joshen Lim 369927892f Harden profile creation logic from dashboard (#51483)
## Context

When signing up a new account on the dashboard, the dashboard's the one
making the request to create a new profile for the user (ideally not,
but the proper fix on the BE is currently blocked). We do so by making
an initial request to GET `/profile`, and if it returns a 404, it's
implied that the account doesn't exist and we fire `createProfile`

Because of this, a race condition could exist (due to replica lag for
example):
- GET `/profile` returns 404, treat user as new
- POST `/profile` returns 200
- Profile query is still in "error" state (`isError` is `true), and post
sign-in tries to redirect to the new org page which triggers the
`useEfect`
[here](https://github.com/supabase/supabase/blob/master/apps/studio/lib/profile.tsx#L82-L96)
- Which prompts another POST `/profile`, and it returns a 409 because
the account's already created
- This then keeps going in a loop which keeps calling `createProfile`
and we didn't have a way to handle this, leading to users in a stuck
loading state until the browser's refreshed

## Changes involved
- Opt to invalidate the profile, permissions, and organizations if the
user runs into a 409
- This should refresh the profile and we'll no longer be stuck in a
create loop since `isError` should no longer be `true` then
- Tighten the dependency array for where `createProfile` is triggered
- Add exponential backoff up to 3 times for profile creation for
transient failures (5xx, network, 429)
- Never retry profile creation for 409, since there's no point doing so
2026-10-12 11:28:12 +08:00
Coenen BenjaminandDanny White 853bac960e feat(studio): limit DuckLake managed setup to the current project (#51380)
## Problem

In **Add pipeline**, the managed DuckLake configuration method (**Select
Supabase projects**) lets users pick any project in their organization
for the catalog and for storage. For now, managed DuckLake should only
use the current project.

## Solution

- Rename the option to **Use this Supabase project** and remove the
**Catalog project** and **Storage project** selectors. Users still set
**Metadata schema** and **Bucket**.
- Remove `ducklakeCatalogProjectRef` and `ducklakeStorageProjectRef`
from the form schema, default values, and validation rather than hiding
them, so the form can't carry another project's ref.
`buildDucklakeConfig` sets both `catalogProjectRef` and
`storageProjectRef` to the current project ref, which the config
builders already receive from the URL.
- The bucket list and the **New bucket** dialog always target the
current project. The cross-region warning is removed because it can no
longer trigger.
- `data/replication` (types and API payload mapping) is unchanged. It
still sends `project_ref` for the catalog and storage, now always the
current project.
- Fix in passing: creating a bucket from the dialog now sets the field
with `shouldDirty` and `shouldValidate`, so a stale "Bucket is
required." error clears.
- Edit mode and **Enter connection details** are unchanged.

The DuckLake docs page
(`apps/docs/content/guides/database/replication/pipelines/ducklake.mdx`)
still describes choosing separate projects. It'll be updated in a
follow-up PR that should merge after this one ships.

## Review instructions

1. Open a project, go to **Database** > **Pipelines**, select **Add
pipeline**, and choose **DuckLake**.
2. Under **Configuration method**, check that the first option is **Use
current Supabase project** and that there's no **Catalog project** or
**Storage project** selector.
3. Open the **Bucket** list and check that it shows the current
project's buckets. **New bucket** creates a private bucket in the
current project.
4. Create the pipeline and check that the request sends the current
project ref as both `catalog.project_ref` and `storage.project_ref`.
5. Run the unit tests: `cd apps/studio && pnpm vitest run
components/interfaces/Database/Replication/DestinationPanel/DestinationForm
data/replication`

## Checklist

Check all before review:

- [ ] I have read
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
- [ ] If I wrote a new docs topic or edited an existing topic, I used
the `/write-the-docs` or `/edit-the-docs` skill, which applies the docs
[style
guide](https://github.com/supabase/supabase/tree/master/apps/docs/style-guide)

---------

Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com>
2026-10-12 00:14:22 +00:00
Danny White 7b48b298ee feat(apps): distinguish local development with blue blueprint favicons (#51420)
## Problem

- Local apps are hard to distinguish from hosted apps in browser tabs.

## Solution

- Add blue blueprint icons to local development in all 8 apps and Studio
CLI.
- Keep normal branding for production, hosted staging and self-hosted
Studio.
- Builds on #51419.


| Before | After |
| --- | --- |
| <img width="1290" height="76" alt="CleanShot 2026-10-08 at 13 29
14@2x"
src="https://github.com/user-attachments/assets/72bc50d7-37e0-47d0-8dfd-50e233a443bd"
/> | <img width="1282" height="72" alt="CleanShot 2026-10-08 at 13 30
03@2x"
src="https://github.com/user-attachments/assets/afb15a70-3938-4cff-9b41-dc6c25460b7c"
/> |

## Review instructions

- Start an app locally. Its browser tab should show the blue icon.
- Check Studio CLI uses blue and hosted staging uses white.
- Check production icons are unchanged, including Learn's black and
white icon.
- Run `node scripts/validate-favicons.mjs`. All 16 sets should pass.

Asset and routing checks, formatting and Common/Studio type checks
passed. Full builds have not been run.

## Checklist

- [x] I have read
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
2026-10-12 10:26:51 +11:00
Danny White a42433c9bd refactor(studio): extract destination connection fields for wizard reuse (#51471)
## Problem

The pipeline creation wizard in #49243 needs destination connection
settings on its connection step, separately from replication settings
and table layout. These fields currently live inside the sheet’s
Advanced settings accordion.

## Solution

Extract BigQuery’s **Connection pool size** and **Maximum staleness**,
DuckLake’s **Pool size**, and Snowflake’s optional **Role** into
reusable connection-field components. Keep the existing accordion as
their first consumer. Labels, defaults, units, field order and
empty-value handling stay the same.

## Review instructions

1. Open the [preview to Database →
Pipelines](https://studio-staging-git-dnywh-refactorpipeline-conne-4a9108-supabase.vercel.app/dashboard/project/_/database/pipelines),
select a test project with Pipelines enabled and click **Add pipeline**.
Keep BigQuery selected and expand **Advanced settings**.
2. Confirm **Connection pool size** and **Maximum staleness** still
appear below **Invalidated slot behavior** and above **Table layout**,
with the same descriptions and the **connections** and **minutes**
units.
5. Select DuckLake, if available, and expand **Advanced settings**.
Confirm **Pool size** remains above **Batch wait time**, with its
existing description and 1–6 limits.
6. Select Snowflake, if available, and expand **Advanced settings**.
Confirm optional **Role** remains below **Invalidated slot behavior**,
with the `PIPELINES_ROLE` placeholder.
2026-10-12 10:19:39 +11:00
Danny White ae69908aed refactor(studio): extract destination validation for wizard reuse (#51470)
## Problem

The pipeline creation wizard in #49243 needs to validate its destination
connection before table selection. The sheet currently builds that
request inside its full configuration validation.

## Solution

Extract `useDestinationValidation` and use it from the sheet. It builds
and sends the existing destination request, with optional pipeline
settings. The sheet still validates destination and pipeline settings in
parallel and retains its existing loading, error and warning handling.

This foundation adds no visible changes or wizard routing.

## Review instructions

Use a test project with Pipelines enabled, a publication containing
tables, and working BigQuery credentials.

1. Open the [deploy preview at Database →
Pipelines](https://studio-staging-git-dnywh-refactorpipeline-desti-ebcb9d-supabase.vercel.app/dashboard/project/_/database/pipelines),
select your test project and click **Add pipeline**. Confirm the
existing sheet opens with BigQuery selected.
2. Enter the required fields and select a publication. Use valid
service-account JSON, but set **Dataset ID** to a dataset that does not
exist. Click **Start pipeline**. While the request runs, expect a
loading state and disabled submission. Once validation completes, expect
configuration issues in the sheet, retained field values and no pipeline
creation.
3. Correct the dataset ID and click **Start pipeline** again. Expect
validation to recover and open the **Create and start pipeline** cost
confirmation when there are no remaining issues. Click **Cancel** to
avoid creating the pipeline.
4. If your test project returns warnings, confirm they appear inline and
the action changes to **Start pipeline anyway**. Click it again:
unchanged warnings should open the warning confirmation, and continuing
should open the cost confirmation. Critical issues must still block
progression.
2026-10-12 10:18:56 +11:00
Danny White 325a5a0da7 fix(studio): polish extension installation dialogs (#51463)
## Problem

The enable-extension dialog in #51440 needs clearer installation copy
and a consistent disclosure for custom-schema guidance. On narrow
screens, footer buttons touch and dialog content can scroll sideways.

## Solution

Polish the dialog on top of #51440:

- Explain fixed-schema requirements and hide custom-schema guidance when
the extension requires a specific schema.
- Share the disclosure interaction with the session-expired and
API-hardening dialogs through `ui-patterns/DialogDisclosure`, documented
with a live design-system example.
- Fix narrow-screen overflow and add vertical spacing to shared dialog
footers.
- Refine inline-code styling and update the PostGIS instructions and E2E
button locator.


| After |
| --- |
| <img width="852" height="710" alt="CleanShot 2026-10-09 at 12 17
47@2x"
src="https://github.com/user-attachments/assets/59f6f1e7-9884-4cdb-b678-62b7f88a8ec5"
/> |
| _Standard extension_ |
| <img width="836" height="1092" alt="52254"
src="https://github.com/user-attachments/assets/dbf53d3e-6583-4c3b-8f43-577e0723d9a7"
/> |
| _Standard extension expanded accordion_ |
| <img width="836" height="604" alt="CleanShot 2026-10-09 at 12 20
04@2x"
src="https://github.com/user-attachments/assets/c8e3961f-2683-440c-a2a2-48ccd53c4a17"
/> |
| _Extension with fixed schema_ |

## Review instructions

1. Open `/project/<ref>/database/extensions`. Turn on the toggle for a
disabled `postgres_fdw` extension. Expand **Install in a different
schema** and check its hover, keyboard focus and full-width click
target. Repeat with `pg_cron` or `pgmq`: the intro must say **must**,
and custom-schema guidance must be absent. Cancel without enabling.
2. At 320 px and 375 px, check the extension dialog's alignment,
inline-code rendering, wrapped SQL and stacked **Enable** / **Cancel**
spacing. Confirm the page does not scroll sideways.
3. On a platform project with the Data API enabled, open
`/project/<ref>/integrations/data_api/settings`. Under **Harden Data
API**, click **Harden Data API**. Expand both sections and check the
same trigger behaviour. Confirm completed sections still show their
check icons. Close without applying either action.
4. The session-expired dialog has no direct route. It is rendered by
`apps/studio/hooks/misc/withAuth.tsx` after authentication loading
exceeds 10 seconds. For repeatable local review, temporarily pass
`visible={true}` to its `SessionTimeoutModal` callsite, then open
`/projects`. Expand **Having trouble?** by clicking the text or chevron
and using Enter / Space. Check the help text and controls. Close the
dialog without signing out or clearing site data, then undo the
temporary prop change.
5. In the design system, open
[`/docs/components/dialog#optional-details`](https://design-system-git-dnywh-choreextension-dialog-polish-supabase.vercel.app/design-system/docs/components/dialog#optional-details).
Click **Export results**, then expand **What’s included** with the mouse
and keyboard. The demo imports the same `ui-patterns/DialogDisclosure`
used by Studio.
6. Open another dialog and an alert dialog at a narrow width. Check the
shared 8 px gap between stacked footer buttons. Review inline-code
examples on `/docs/components/typography` for the shared styling change.
2026-10-12 10:18:45 +11:00
Danny White 255a80e219 refactor(apps): standardise existing favicon assets and declarations (#51419)
## Problem

- Favicon files and markup are duplicated across apps.

## Solution

- Replace old files with one ICO, one Apple icon and two manifest icons
per set.
- Share icon markup and add generation notes and scripts.
- Keep existing branding, including Learn's black and white icon.
- Make the border radius match across all apps’ favicons.

## Review instructions

- Check normal app icons and Studio staging in browser tabs.
- Check icons load under `/docs` and `/kb`.
- Run `node scripts/validate-favicons.mjs`. All 8 sets should pass.
2026-10-12 10:18:18 +11:00
Monica KhouryandCharis Lam 2d5768d3c1 feat(studio): wire Platform Webhooks UI to real backend API (#51352)
## What
Wires the existing (mocked) Platform Webhooks UI to the real Management
API backend, per FE-3749.

- New `data/platform-webhooks/` query/mutation hooks, calling the real
`/v2/organizations/{slug}/webhooks/...` and
`/v2/projects/{ref}/webhooks/...` endpoints
- Updated `PlatformWebhooks.types.ts` to match the real API contract
(field names, shapes)
- Added a signing secret field to the create-endpoint form (API requires
a user-provided secret, not server-generated like the mock assumed)
- Removed the event-type column from the deliveries table (the real
list-deliveries endpoint doesn't return event type, only the
single-delivery endpoint does)
- Removed `PlatformWebhooks.mock.ts` / `.store.ts` and their tests

## Why
UI was built ~80% against mock data months ago; this closes the gap to a
real, working feature.

## Known open items (not blocking, tracked separately)
- `name` field has no backend storage yet — client-only for now, open
question with Ali/Paweł
- Deliveries table only fetches the backend's default single page — real
server-side pagination not yet wired (see FE-3750)

## Follow-up PR (stacked)
Tests for the new `data/platform-webhooks/` hooks (MSW-based), per the
ticket's own scope split.

## Testing
Manually tested end-to-end against local backend: created/edited/deleted
an endpoint, verified the real signature using webhook.site,
independently recomputed the HMAC and confirmed it matches the
`webhook-signature` header.

Linear: FE-3749

---------

Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com>
2026-10-09 22:41:09 +03:00
Ignacio Dobronich eeae6027d5 fix: don't warn about SMS MFA charges on branch projects (#51459) 2026-10-09 12:57:27 -03:00
Alaister Young f7b7969728 fix(studio): cancel pending banner removal timeouts on unmount (#51491) 2026-10-09 17:38:50 +02:00
Matt Rossman 0d8cd9c315 feat(studio): prompt for a higher AI opt-in level instead of "no tool access" (#51411)
## Motivation

When an Assistant tool needs a higher opt-in level than the org has, the
user only sees the model say it has no access with (inconsistent)
written instructions how to fix, instead of Assistant proactively
facilitating the fix.

<img width="400" alt="CleanShot 2026-10-07 at 3 44 29 PM@2x"
src="https://github.com/user-attachments/assets/ba95568a-5db4-4d8c-b4ff-64855f2b87ec"
/>

The majority of recent labelled [Assistant
Issues](https://www.braintrust.dev/app/supabase.io/p/Assistant/topics)
in Braintrust are tools or query results blocked by the org opt-in
level. We've considered making Assistant disabled entirely when data
opt-in is off to eliminate the most common footgun (AI-405), but that's
an intrusive change which could break legitimate use cases.

## Changes



https://github.com/user-attachments/assets/206a2438-630e-4368-9cec-2b04b66c9cd4



A new `update_opt_in_level` tool renders an inline card which prompts
admins to review the opt-in level and highlights the proposed change
(non-admins see a message telling them to contact their admin to change
the setting). Saving approves the call and the turn resumes at the new
level. Results appear in a Braintrust tool span based on
https://github.com/supabase/supabase/pull/45654.

I added 5 evals that simulate the user answering the opt-in card to
verify that the Assistant asks when blocked, continues after the user
accepts, and doesn't invent data after a skip. Tool Usage and
Correctness are at 100% in the [sample
run](https://www.braintrust.dev/app/supabase.io/p/Dev%20(mattrossman%2FAssistant)/experiments/mattrossman%2Fai-158-prompt-users-to-update-settings-instead-of-showing-no-tool-1791483991).

<details>
<summary>📸 Screenshots</summary>

| Admin, pending | Modal, Current and Proposed |
| -- | -- |
| <img width="100%" alt="CleanShot 2026-10-07 at 3 23 37 PM@2x"
src="https://github.com/user-attachments/assets/2fc8ba11-0530-4028-a056-40ca02afd3ef"
/> | <img width="1184" height="1754" alt="CleanShot 2026-10-07 at 3 32
37 PM@2x"
src="https://github.com/user-attachments/assets/73639633-89ac-4d4c-b869-d9301735d5b9"
/> |
| **After saving, turn continues** | **Non-admin** |
| <img width="100%" alt="CleanShot 2026-10-07 at 3 27 14 PM@2x"
src="https://github.com/user-attachments/assets/a91c6760-6dfb-4f51-9ef8-4bdbe1b22495"
/> | <img width="100%" alt="CleanShot 2026-10-07 at 3 15 33 PM@2x"
src="https://github.com/user-attachments/assets/ecb9aa87-26dc-4b69-a086-cb77a28bb860"
/> |

</details>

## Verification

To test in staging, set your org's Assistant opt-in level to Disabled,
ask "What tables do I have?", and review the card. Try selecting the
proposed (or different) opt-in level and saving to continue.

[This
trace](https://www.braintrust.dev/app/supabase.io/p/Dev%20(mattrossman%2FAssistant)/experiments/mattrossman%2Fai-158-prompt-users-to-update-settings-instead-of-showing-no-tool-1791483991?r=90066cd9-4da3-4817-9650-c369d2b42cea)
is a sample from the accept eval case after saving Schema Only, note the
`update_opt_in_level` span.

## Safety considerations

I added a banner to the modal to make it more obvious that this setting
impacts the whole org, not just the current chat or project:

<img width="592" height="78" alt="CleanShot 2026-10-08 at 2 04 44 PM@2x"
src="https://github.com/user-attachments/assets/6b140ed6-65fb-4bc0-b5cc-9c82fe2a67aa"
/>


I leave the current opt-in value selected by default in the form so the
user has to consciously select the proposed value instead of mindlessly
clicking save without understanding implications.

`execute_sql` and `run_notebook` outputs are now stamped with the level
they ran under, and history is sanitized by the least permissive of the
stamped vs current opt-in levels. That way raising the level mid-chat
doesn't unexpectedly expose earlier query rows to the model.

Closes AI-158
2026-10-09 10:39:23 -04:00
kemal.earth 6119ea1eb5 feat(design-system): remove table head hover in design system (#51452)
## Problem

All our tables had shadcn's rather annoying row hover on a
non-interactive `<thead>`.

## Solution

Some tailwind/css magic to stop the hover on `<thead>`.
2026-10-09 13:56:50 +01:00
4f23e91174 feat(studio): scoped oauth apps, admins can revoke an app (#50980)
## Problem

Admins should be able to revoke an OAuth app that uses scoped tokens.

## Solution

## Solution

- Add a menu to the org settings oauth approved apps rows to revoke the
app

<img width="1164" height="342" alt="image"
src="https://github.com/user-attachments/assets/1323318a-7c68-436e-ae77-0c79d763e4cc"
/>


<img width="441" height="350" alt="image"
src="https://github.com/user-attachments/assets/dd5cf88e-184a-4edb-a240-340bd2f58727"
/>

## Review instructions

In Org Settings/OAuth apps, you should see a menu button for each app
that contains a _Revoke_ item. Clicking this item should open a dialog
to revoke the app.
Notice how the focus is back on the dropdown trigger button when the
dialog is closed (canceled or success)

---------

Co-authored-by: kemal <hello@kemal.earth>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-10-09 11:30:52 +02:00
Joshen Lim 2b393377c6 Show connection settings if already configured despite no GH auth (#51427)
## Context

A project could already have a GitHub integration set up by another
member, which will show up in the branch management side navigation as
such:
<img width="259" height="255" alt="image"
src="https://github.com/user-attachments/assets/8bc12ef2-5f25-4245-9c89-4563b08a42a8"
/>

However if the user hasn't authenticated with GitHub, the project
settings -> integrations page will obfuscate the integration details
with a "Connect GitHub" CTA, which is a confusing UX as it hints that
there's no integration set up + conflicts with what's on the branch
management page
<img width="768" height="318" alt="image"
src="https://github.com/user-attachments/assets/a68409c0-f2db-407d-9bac-c109a0d14214"
/>

## Changes involved

Opting to show the integration details if there's one set up
irregardless of whether the user has authenticated with GH, but we'll
require the user to complete the authentication to manage the
integration settings as such (all input fields will also be disabled
until the auth is complete):
<img width="1031" height="511" alt="image"
src="https://github.com/user-attachments/assets/6fad387b-6e76-475e-b4e6-76972d8f76b6"
/>

Note that you can still disable the integration nonetheless irregardless
of the GH connection status

Also fixes the "Remove connection" CTA from Account Preferences - we
were invalidating the GH authorization query cache but the GH
authorization requests normally fails with a 404 if there's no auth set
up, so the query cache would remain stale. Opting to clear the query
cache instead of invalidating

## To test
- [ ] Set up a GH integration for your project under project settings ->
integrations
- [ ] Head to account preferences to remove your GH connection
- [ ] Go back to the project settings -> integrations page, should still
see the GH integration details, just unable to edit
- [ ] Connect with GH, and you should be able to edit the integration
details thereafter
2026-10-09 16:28:49 +08:00
Francesco SansalvadoreandClaude Sonnet 5 1b27761bec feat(storage): add version history to the file preview panel (FE-4163) (#49208)
## [5/10] Storage object versioning: version history in the file preview
panel

**Base:** `feat/storage-versioning/004-object-versions-data` #49207 

### This PR

Adds all the versioning ui to the file preview panel.

- polished file preview panel (header, buttons, nits)
- added "Upload file" to the action buttons
- "Delete permanently" now defaults to "Archive" as primary action, and
"Delete permanently" via a dropdown menu as a more destructive action
- added "Versions" toggle section to the file preview panel
- with lifecycle policy "summary"
  - with additional explanation on hover
- versions can be restored or deleted permanently 

### How to test

- in a File storage bucket, open a file preview panel
- when the "Storage Versioning" feature preview flag is true, the
preview panel should show
    - a "versions" section
    - a new "upload file" button next to the "download file" button
- the "delete permanently" button should show "Archive" + a dropdown
with the "Delete permanently" option
- if the feature preview flag is toggled _off_, the preview panel should
looks as before (but with some minor polish)


https://github.com/user-attachments/assets/56f6b9aa-b3a0-45bd-b3e7-5788967d196a

With the feature preview toggled _on_:
- the ui should show the lifecycle policy "summary" that will affect
this file
- hovering the lifecycle policy summary should explain how the policy
will affect/clean up the noncurrent files
- the lifecycle policy summary hover card button should link and open
the "edit bucket modal"
- create a new version of a file by using the "Upload file" (next to
"download file")
  - the file should have a new "Current" version
  - the previous version should become a "noncurrent" version
- the noncurrent version should reflect the lifecycle policy that will
eventually affect it with some additional context on hover via a tooltip
- clicking on a noncurrent version should open a "comparison widget"
that provides a way to restore it and re-promote it to "current" or
delete it permanently
- these actions are also available via dropdown menu from the version
item
- a file should be "archiveable" (please note that showing/managing
archived files will come in the next pr in the stack)
- confirmation modals should prompt to confirm to proceed to restoring
or permanently deleting a noncurrent version


https://github.com/user-attachments/assets/803a6f15-7f32-44ae-9e24-1c201aab178a

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-09 09:36:41 +02:00
Danny WhiteandJoshen Lim d5341f37f9 chore(studio): use standard Badge for deprecated extensions (#51461)
## Problem

The deprecated indicator next to extensions like `pgjwt` on Database →
Extensions was a `ButtonTooltip` styled to look like a badge
(`variant="warning"`, triangle icon, `rounded-full`). That adds another
one-off badge-like control instead of using the shared `Badge`.

## Solution

Replace it with a warning `Badge` plus the same tooltip content (when
the extension will be removed).

| Before | After |
| --- | --- |
| <img width="356" height="114" alt="CleanShot 2026-10-09 at 10 38
08@2x"
src="https://github.com/user-attachments/assets/98a2356e-203e-4946-b399-63a53ea9804f"
/> | <img width="312" height="116" alt="CleanShot 2026-10-09 at 10 43
08@2x"
src="https://github.com/user-attachments/assets/ee9ff91d-79f6-4a50-b508-ebe602497cfe"
/> |

## Review instructions

1. Open Studio → Database → Extensions.
2. Find `pgjwt` (or another deprecated extension).
3. Confirm a warning `Deprecated` badge appears next to the name (no
triangle icon / pill button).
4. Hover (or focus) the badge and confirm the removal tooltip still
shows.

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-10-09 14:23:37 +08:00
Saxon FletcherandDanny White 692b14d47b fix(ui): opaque sticky table column hover (#47668)
## Problem

On tables with a sticky last column (Database Extensions, OAuth Apps,
Custom Auth Providers), hovering a row lets scrolled cell content show
through the sticky column.

Root cause: row hover uses `bg-surface-200`, which maps to `--muted`
(alpha). That works for normal cells (nothing behind them) but sticky
cells sit above horizontally scrolled content, so the tint is
see-through.

## Solution

In `ShadowScrollArea` when `stickyLastColumn` is set:

- Keep an opaque `bg-surface-100` base on sticky cells
- Composite the muted hover tint via `background-image` so hover matches
`TableRow` without becoming transparent

Also:

- Extensions: use `Table containerProps={{ stickyLastColumn: true }}`
instead of nesting a second `ShadowScrollArea` (same pattern as OAuth /
Custom Auth)
- OAuth Apps and Custom Auth Providers: drop redundant per-cell
`bg-surface-100` / `hover:bg-surface-200` so sticky hover comes only
from `ShadowScrollArea`

| Before | After |
| --- | --- |
| <img width="1042" height="98" alt="27097"
src="https://github.com/user-attachments/assets/204a7dc4-d5ac-40b7-87fb-fdb03982eaad"
/> | <img width="1084" height="101" alt="94456"
src="https://github.com/user-attachments/assets/c6db3607-6bbe-4488-a0a5-81f5a0436d66"
/> |

## Review instructions

1. Open Database Extensions. Narrow the viewport or scroll the table
horizontally so the Enabled column is sticky.
2. Hover a row while Links or description content sits under the Enabled
column. The sticky cell should stay opaque and match the row hover tint
(light and dark).
3. Optionally repeat on Auth → OAuth Apps and Auth → Custom Providers
(actions column).

Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com>
2026-10-09 17:12:47 +11:00
Joshen Lim a76b861b50 Remove schema selector in DB extensions enable dialog (#51440)
## Context

We've had a number of users run into issues after installing database
extensions in schemas outside of the `extensions` schema - in particular
for the `public` schema, which issues that normally surface are either:
- Inability to enable RLS because the extensions are owned by
`supabase_admin` when created
  - Security advisor hence constantly flags this as an issue
- Inability to move the extension for the same reason
- There is a solution for but it requires a lengthy resolution as
outlined here in [our
docs](https://supabase.com/docs/guides/database/extensions/postgis#moving-postgis-to-a-different-schema)

While the option to select a schema to enable the database extension was
for convenience, this is typically more for power users which seems to
be more of a footgun for most other users.

Hence we're opting to remove the schema selection option in the enable
extension modal to also streamline the UX for enabling an extension by
removing that additional cognitive load.

## Changes involved

### Before:
<img width="430" height="248" alt="image"
src="https://github.com/user-attachments/assets/e99ce86c-b56c-4149-86ca-2457da65b179"
/>

### After:
<img width="438" height="328" alt="image"
src="https://github.com/user-attachments/assets/6be599d5-185b-4efe-9718-b50ac0ed4948"
/>

Clicking on the foot note expands a note as such with an alternative for
power users:
<img width="425" height="434" alt="image"
src="https://github.com/user-attachments/assets/7cbf0b59-0ddc-4933-8c6b-4e30a32115b5"
/>

Extensions will be installed in the `extensions` by default unless
otherwise specified by the extension itself within
`default_version_schema`
2026-10-09 13:15:48 +08:00
Danny White cd00775dd7 feat(studio): add the pipeline creation wizard preview foundation (#51425)
## Problem

The redesigned pipeline creation flow (mega branch being worked on in
#49243) needs an incremental rollout while the existing creation sheet
remains the default.

## Solution

- Register **Pipeline creation wizard** in Feature Previews, with
visibility controlled by the `pipelineCreationWizard` ConfigCat flag.
- Require the flag and an explicit user opt-in (via Feature previews
dialog) before enabling the preview.

This adds the preview registration, copy, storage key, and gate. It does
not change creation routing or ship the wizard. The complete gated flow
can be tested on #49243.

The ConfigCat flag is configured as follows:

- **Local/staging:** true for everyone.
- **Production:** false by default, true for the **Supabase Team Email**
segment.

The flag makes the preview visible; it does not opt anyone in. Users
enable it once in Feature Previews. No dev toolbar override is needed in
local/staging.

## Review instructions

1. In local or staging hosted Studio, open **Feature previews**. Find
**Pipeline creation wizard**. With no saved preference, it should be off
by default.
2. Toggle it on and reload. The opt-in should persist. Toggle it off and
reload to confirm opt-out persists. **Add pipeline** still opens the
sheet in this foundation PR.
2026-10-09 14:55:38 +11:00
Danny White 600c48840f chore(studio): remove outdated Pipelines feedback button (#51424)
## Problem

The Pipelines header links to an older feedback discussion. The
dashboard's existing Feedback control already captures the current
route.

## Solution

Remove the “Leave feedback” button and its unused URL constant.

| Before | After |
| --- | --- |
| <img width="1932" height="340" alt="32431"
src="https://github.com/user-attachments/assets/ef5f919c-503b-4fcc-9137-90ddeb6c07dd"
/> | <img width="1930" height="350" alt="CleanShot 2026-10-08 at 15 47
38@2x"
src="https://github.com/user-attachments/assets/d44df2a0-8681-4594-9679-148d639d08fd"
/> |

## Review instructions

1. Open a project's Database > Pipelines page at
`/project/<ref>/database/pipelines`.
2. Confirm the header shows the documentation button without “Leave
feedback”.
3. Confirm the diagram and the usage and enable/disable dropdown actions
are unchanged.
2026-10-09 14:24:08 +11:00
Ping-Min Lin 1ee88e0fee feat(studio): show Realtime on High Availability projects in staging (#51372)
## What kind of change does this PR introduce?

Feature, limited to staging and local.

## What is the current behavior?

On High Availability projects, Studio always disables Realtime: the
Realtime pages and the Publications pages show an "unavailable" message,
the table editor's "Enable Realtime" checkbox is disabled, and the
project home shows Realtime as disabled.

## What is the new behavior?

A new `useIsRealtimeUnavailable()` hook treats Realtime as unavailable
only on High Availability projects outside staging and local (via
`IS_STAGING_OR_LOCAL`). Those four places use it instead of checking
`high_availability` directly.

- **Production:** unchanged.
- **Staging and local:** Realtime behaves as on standard projects.

## Additional context

Whether a High Availability project is actually registered as a Realtime
tenant is gated separately on the platform side. Until then, the pages
render but Realtime connections for that project fail.

Tests: a new `resolveRealtimeUnavailable` test, and the
`TableRealtimeToggle` and `resolveRealtimeServiceStatus` tests updated
for the renamed parameter.
2026-10-08 14:05:37 -07:00