## 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>`.
## 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>
## 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
## [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>
## 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>
## 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>
## 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`
## 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.
## 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.
## 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.
The close button on the Auth users detail panel (and the queue message
panel) is absolutely positioned, but `TabsList` is `position: relative`
and comes later in tree order — so it painted on top of the button and
swallowed every click. The button looked fine and did nothing.
Stacks the button above the tab list, adds an accessible name to the
users panel button, and covers it with an E2E test (Playwright does real
hit-testing, so it fails without the fix).
Fixes FE-4519
## Problem
The log drain form still includes Postgres, ClickHouse, and BigQuery
placeholder variants even though the dashboard does not offer these
destinations. Production Platform API create/update types now exclude
them, causing Studio type errors when the API declarations are
regenerated.
## Fix
Remove the unused variants from the form and submission schemas. Accept
the broader response type for incoming defaults, resolve defaults
through the selectable destination list, and use the form schema type
for the selector.
## How to test
- Run `pnpm --filter studio typecheck` with committed API types and with
types generated from production. Both should pass.
- Run Prettier and ESLint on `LogDrainDestinationSheetForm.tsx`.
- Open project or organization audit log drain settings and add a
supported destination. Available destinations remain unchanged.
Validation: Studio typecheck passes with both committed API types and
freshly generated production API types. Prettier passes; ESLint reports
only existing warnings. Generated declarations are not included in this
PR.
## Context
Adds an empty state for the branch management page, if no preview
branches have yet to be created (overview wont be shown) - mainly visual
changes here. The main intention here is to surface the GH connection
setup a bit more (otherwise the only CTA for that is in the side nav
which is easily missed + its not clear up front what the benefit of the
GH connection is in the context of branching)
This is how it looked like before for reference:
<img width="1346" height="956" alt="image"
src="https://github.com/user-attachments/assets/776ce3f4-e12b-42e4-8e90-0d5ca15dc58f"
/>
And this is what I'm thinking for the empty state:
<img width="1037" height="431" alt="image"
src="https://github.com/user-attachments/assets/d3a8871e-74d2-499a-b317-f739ed925668"
/>
GH connection will flip its badge and hide the CTA if there already is a
GH connection
<img width="1038" height="443" alt="image"
src="https://github.com/user-attachments/assets/4bf2d34d-6c74-4206-b83c-38ba84b99fb3"
/>
## Problem
AlertError forces a vertical layout whenever additional actions are
supplied, even when the caller explicitly requests horizontal or
responsive layout. Stripe Sync Engine's uninstall error is one affected
call site, the other was Pipelines as demoed in #51311.
## Solution
Honour an explicit layout. Preserve the existing defaults: vertical with
additional actions, responsive otherwise.
Replace the standalone Contact support action with an InlineLink in the
contact support prose, preserving support form context and breadcrumb
capture. Keep custom actions such as Retry. If instructions are hidden
or custom prose omits contact support, retain a separate inline support
link. With `hideContactSupport`, show no support link and shorten the
default instructions to “Try refreshing your browser.” Custom
descriptions remain unchanged. The local Pipelines configuration error
explicitly hides support. Add the explicit responsive layout at the
Pipelines call site.
| Before | After |
| --- | --- |
| <img width="914" height="426" alt="CleanShot 2026-10-07 at 17 51
20@2x"
src="https://github.com/user-attachments/assets/6cbddfee-97f5-4a7a-bafa-7b5dfd6ab8bf"
/> | <img width="916" height="422" alt="CleanShot 2026-10-07 at 18 26
06@2x"
src="https://github.com/user-attachments/assets/a21952a6-1c1a-437c-af73-c5736f33fd98"
/> |
| <img width="1566" height="384" alt="CleanShot 2026-10-07 at 18 28
07@2x"
src="https://github.com/user-attachments/assets/bdc2a043-421f-4c22-9bd3-37859c6e85c7"
/> | <img width="1568" height="308" alt="CleanShot 2026-10-07 at 18 26
58@2x"
src="https://github.com/user-attachments/assets/da0f2c6a-6254-4196-944b-5665e87b3c3c"
/> |
## Review instructions
1. In a fresh local test project with no existing `stripe` schema, run
this in SQL Editor:
```sql
begin;
create schema stripe;
comment on schema stripe is
'{"status":"uninstall error","errorMessage":"Local layout test: uninstallation failed"}';
commit;
```
2. Open **Integrations → Stripe Sync Engine → Overview** and reload.
Check **Failed to uninstall Stripe Sync Engine** at wide and narrow
widths, including **Retry uninstallation** and the inline **contact
support** link. Do not click Retry: it invokes the real uninstall
operation.
3. Remove the empty fixture with `drop schema stripe restrict;`.
4. Block the Pipelines source-status request and resize the page: Retry
uses the responsive layout.
5. AlertError callers without an explicit layout should retain their
existing presentation. Confirm default and custom contact support prose
use an inline link, with no standalone support action. Hidden
instructions and custom prose without contact support retain an inline
fallback. With `hideContactSupport`, the default prose is “Try
refreshing your browser.” and no support link appears; custom
descriptions remain unchanged.
6. Automated regression coverage checks that an explicit responsive
layout survives additional actions, and that hiding support removes the
default support wording while preserving custom descriptions.
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
## Context
Resolves https://github.com/supabase/supabase/issues/51330
Odd bug on the Table Editor where "Copy as SQL" CTA would misalign
column names to values if the columns had numerical like names such as
`2024` for example.
Also added an unrelated fix for "Copy as JSON":
- Was adding an `idx` column to the output even if the table didn't have
(was a react data grid internal detail)
- Column name ordering didn't match the table
## To reproduce:
1. Create and populate a table:
```
create table public.yearly_totals (id bigint, "2024" bigint, "2023" bigint);
insert into public.yearly_totals values (7, 99, 42);
```
2. Select the row in the Table Editor, then "Copy as SQL" -> The output
will turn out to be
```INSERT INTO public.yearly_totals (id, "2024", "2023") VALUES (42, 99, 7);```
instead of
```INSERT INTO public.yearly_totals (id, "2024", "2023") VALUES (7,
99,42);```
## To test
- [ ] Verify that the Copy to SQL output matches the intended as per the
set up above
## Problem
Add pipeline opens the creation sheet before users enable Pipelines. A
pending or failed source lookup also lets creation open with an unknown
enablement state.
## Solution
Show the existing enablement dialog first when required, then open
creation after successful enablement. Cancellation and failed enablement
keep creation closed; enabling through the page menu does not open
creation.
Disable both Add pipeline buttons and their keyboard shortcut until the
source lookup succeeds. Failed lookups show an error with Retry,
including the local replication configuration message. Analytics Bucket
keeps its existing creation path.
| Before | After |
| --- | --- |
| <img width="1275" height="919" alt="Pipelines Database Shears Toolshed
Supabase"
src="https://github.com/user-attachments/assets/cf328732-4342-4758-bde2-98b393341d6a"
/> | _No longer in sheet; dialog is shown conditionally before sheet._ |
| <img width="1275" height="919" alt="Pipelines Database Shears Toolshed
Supabase"
src="https://github.com/user-attachments/assets/f593e271-d29c-4955-8849-0bb64946d4cc"
/> | <img width="1275" height="919" alt="Pipelines Database Shears
Toolshed Supabase"
src="https://github.com/user-attachments/assets/3257d391-b892-44df-85d1-5a2108072312"
/>|
| _“Enable Pipelines”_ | _“Enable”_ |
| After |
| --- |
| <img width="1275" height="919" alt="Pipelines Database Shears Toolshed
Supabase"
src="https://github.com/user-attachments/assets/b11770a1-4785-49ee-950d-d821892b3245"
/> |
| _Loading_ |
| <img width="1275" height="919" alt="Pipelines Database Shears Toolshed
Supabase"
src="https://github.com/user-attachments/assets/710f82be-ca6f-4337-a5ce-b65f9d7f6a32"
/> |
| _Lookup failed_ |
| <img width="1275" height="919" alt="Pipelines Database Shears Toolshed
Supabase"
src="https://github.com/user-attachments/assets/68486ca8-37e8-4b27-89ae-8004f159c38a"
/> |
| _Plan-access loading, throttled_ |
## Review instructions
Use a project with Pipelines access and a working replication API (which
should work on [deploy
preview](https://studio-staging-git-dnywh-fixpipeline-enable-create-supabase.vercel.app/)).
Test the PR preview or locally
([instructions](https://app.notion.com/p/supabase/Danny-s-Local-ETL-Pipelines-Setup-3b25004b775f8058a108f8f67fc813e9?source=copy_link)).
In DevTools Network, enable **Disable cache** before each reload.
Analytics Bucket intentionally bypasses the source-status guard.
1. **Loading:** select **Slow 3G**, reload, and watch the request ending
in `/replication/<ref>/sources`. While it is pending, both **Add
pipeline** buttons must be disabled and **Shift+N** must open nothing.
Both buttons replace the plus with a loading spinner and have no loading
tooltip. Restore **No throttling** afterwards.
2. **Lookup failed:** right-click that source request and choose **Block
request URL**, then reload. After retries finish, expect **Failed to
retrieve pipeline enablement status** with **Retry**, disabled Add
buttons whose tooltip matches the error title, and no sheet/dialog from
**Shift+N**. An unconfigured local replication API instead shows
**Replication unavailable locally**. Unblock the request before clicking
**Retry**.
3. **Lookup succeeded:** on a disposable project with Pipelines
disabled, successful Retry restores Add pipeline. Clicking it opens
**Enable Pipelines**. Cancel stays on the list; **Enable** opens the
sheet after successful enablement. On an already enabled project, Add
pipeline opens the sheet directly. Enabling through the page's three-dot
menu stays on the list. Analytics Bucket opens its sheet without ETL
enablement.
4. **Plan-access loading is separate:** in Chrome 145 or newer, find
`/organizations/<slug>/entitlements` in Network, right-click it and
choose **Throttle request**. In the **Request conditions** drawer,
select Slow 3G for that request only, leaving global throttling off.
Reload on a Pro organisation with Pipelines disabled and open Add
pipeline after the source lookup succeeds. While entitlements remain
pending, expect body shimmers, the accessible “Checking Pipelines
access…” status, a disabled loading **Enable** button, and no upgrade
prompt. Remove the request condition afterwards. If your DevTools lacks
per-request throttling, use the component tests for deterministic
coverage.
## Problem
The project overview shows the project's compute size in a card labeled
"Compute", but the card is not clickable. Compute changes are managed on
Infrastructure settings, so users have to find that page on their own.
The adjacent cards (GitHub, Recent branch, Last migration, Last backup)
already link to where you manage them.
## Solution
- Rename the card label from "Compute" to "Machine size" and pass
`href={getInfrastructurePath(ref)}` to `SingleStat`. That renders the
same `Link` wrapper as the adjacent cards, so it gets the same link
semantics, keyboard focus and hover style. The value (compute badge or
"Unknown", plus the High Availability badge) is unchanged.
- Add `onClick={(e) => e.stopPropagation()}` to the
`HighAvailabilityBadge` hover card content. This is the same pattern
`ComputeBadgeWrapper` already uses. The hover card is portaled, but
React still bubbles its clicks to the new card link. Without this, the
link's `onClick` would intercept clicks inside the HA hover card.
Clicking "Read more" would then go to Infrastructure instead of opening
the docs in a new tab.
Out of scope: "Compute" labels elsewhere, the Infrastructure page and
compute provisioning behavior.
Notes:
- The compute badge's hover card trigger already calls `stopPropagation`
on click, because it also sits inside clickable project cards and table
rows. When you click the badge itself, the browser still follows the
native anchor to Infrastructure settings, but it does a full page load
instead of a client-side navigation. This PR leaves that shared
component unchanged.
- While the project is resizing, the overview is replaced by the
resizing state, so the card is not shown then. Settings routes stay
reachable while a project is building, so the link doesn't bounce users
back home.
- No new component test: rendering `ActivityStats` needs mocks for about
eight queries, including `ServiceStatus`. The change only sets an `href`
on an existing component, so a browser check is a better fit.
## Review instructions
1. Open a platform project's overview (`/project/<ref>`).
2. The card next to Status reads "Machine size" and still shows the
compute badge (and the HA badge on HA projects).
3. Click the card, or Tab to it and press Enter. You land on
`/project/<ref>/settings/infrastructure`.
4. Hover the compute badge: its hover card still opens, and "Upgrade
compute" still goes to Infrastructure.
5. On an HA project, hover the High Availability badge and click "Read
more". The docs open in a new tab and the page does not navigate.
6. GitHub, Recent branch, Last migration and Last backup keep their
labels and destinations.
Checks: `tsc --noEmit` for Studio (no new errors; one unrelated error in
`packages/ui-patterns/.../InstructionBlocks.tsx` was already there),
`eslint` on the touched files (no new warnings), Prettier check, `vitest
components/interfaces/ProjectHome` (34 passed).
## Checklist
- [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 applies the docs
[style
guide](https://github.com/supabase/supabase/tree/master/apps/docs/style-guide)
---------
Co-authored-by: supabase-vercel-tedd[bot] <336548405+supabase-vercel-tedd[bot]@users.noreply.github.com>
Co-authored-by: Ali Waseem <waseema393@gmail.com>
| # | Branch | Base |
| - | ------ | ---- |
| 1 | `feat/storage-versioning-private-alpha` — merged | `master` |
| 2 | `feat/storage-versioning/002-bucket-form-fields` | `master` |
| 3 | `feat/storage-versioning/003-bucket-modals` | 2 |
| 4 | `feat/storage-versioning/004-object-versions-data` ◀ | 3 |
| 5 | `feat/storage-versioning/005-file-preview-versions` | 4 |
| 6 | `feat/storage-versioning/006-billing-storage-retention` | 5 |
| 7 | `feat/storage-versioning/007-archived-objects-data` | 6 |
| 8 | `feat/storage-versioning/008-archived-rows` | 7 |
| 9 | `feat/storage-versioning/009-archived-preview-pane` | 8 |
| 10 | `feat/storage-versioning/010-replace-file` | 9 |
## [4/10] Storage object versioning: object versions data layer
**Base:** `feat/storage-versioning/003-bucket-modals` (PR 3)
### This PR
The query and mutation hooks for the version history UI, written to
`queryOptions` using the real Storage endpoints.
- `object-versions-query.ts` — the version list, plus `ObjectVersion`
and `LifecyclePolicy`
- `object-version-restore-mutation.ts` — promote a noncurrent version to
current
- `object-version-delete-mutation.ts` — remove one specific version
- `object-purge-mutation.ts` — delete an object and every version,
bypassing versioning
- `VersionHistory.utils.ts` — `computeVersionFate`, the pure rule
deciding what removal outlook each version row shows
- `BroomSparklesIcon.tsx` — inline SVG for a glyph absent from
lucide-react 0.436
Easier to test directly from next PR in the stack #49208 which wires the
queries to the real file preview panel ui.
---------
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Project sidebars now expose enabled navigation on fixed-width pages, and
the mobile project menu has an accessible dialog name. Fixed sidebar
sizing and editor resize controls remain intact.
**Changed:**
- Remove the disabled state from the shared sidebar panel while
retaining 256px fixed sizing, the disabled resize handle, and existing
editor resize limits.
- Add a screen-reader-only Project menu title inside the mobile project
sheet without changing other sheets or their titles.
**Added:**
- Tests using the actual resizable wrappers for enabled navigation and
handle semantics, and the actual mobile sheet for its accessible name
through menu navigation.
## To test
- Navigate through Database and Settings sidebar links with ordinary
clicks and Tab/Enter. Enabled links should have no disabled ancestor.
- Confirm fixed sidebars remain 256px wide, including an ordinary drag
of their disabled handle.
- In SQL Editor, verify keyboard resizing stays within 256–512px and
collapse/expand still works; restore the original width and visibility
without editing or executing anything.
- Open the mobile project menu. Confirm its dialog name is Project menu,
navigate through Tables, and close it without a missing-title warning.
Restore the viewport.
Validation: real regressions reproduce disabled navigation inheritance
and the unnamed mobile dialog before their fixes. All 26 focused
layout/menu/utility tests and source checks passed. Initial full browser
checks passed normal mouse/keyboard navigation, fixed-handle drag
resistance, editor resize limits, collapse/expand, and mobile
navigation, with viewport/state restored and no backend writes. Both
Next and TanStack production rebuilds passed. The focused mobile retest
passed the linked Project menu title through sections, closing,
navigation, and reopening with no new missing-title warnings, followed
by desktop sidebar and editor controls; viewport, width, and visibility
were restored. Unrelated development React mount/ref warnings remain
separately recorded; native Next local browser and catalog data were not
verified.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Project sidebar links remain available when sidebar resizing is turned
off; the resize handle stays unavailable in that setting.
* The mobile project menu retains the “Project menu” name as you
navigate between sections.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
| # | Branch | Base |
| - | ------ | ---- |
| 1 | `feat/storage-versioning-private-alpha` — merged | `master` |
| 2 | `feat/storage-versioning/002-bucket-form-fields` | `master` |
| 3 | `feat/storage-versioning/003-bucket-modals` ◀ | 2 |
| 4 | `feat/storage-versioning/004-object-versions-data` | 3 |
| 5 | `feat/storage-versioning/005-file-preview-versions` | 4 |
| 6 | `feat/storage-versioning/006-billing-storage-retention` | 5 |
| 7 | `feat/storage-versioning/007-archived-objects-data` | 6 |
| 8 | `feat/storage-versioning/008-archived-rows` | 7 |
| 9 | `feat/storage-versioning/009-archived-preview-pane` | 8 |
| 10 | `feat/storage-versioning/010-replace-file` | 9 |
## [3/10] Storage object versioning: wire into the bucket modals
**Base:** `feat/storage-versioning/002-bucket-form-fields` (PR 2)
### This PR
Mounts the object-versioning form section in the create and edit bucket
modals behind the feature preview, and saves it.
- create and edit bucket modals spread `bucketVersioningFormFields` into
their existing form schema
- lifecycle defaults to 30 days / 10 versions
- edit adds a confirmation before suspending an actively versioned
bucket
## Enabling object versioning on a new bucket and setting lifecycle
policies
https://github.com/user-attachments/assets/194f8319-4929-432e-8a50-206f180a77a8
## Edit and suspend object-versioning
https://github.com/user-attachments/assets/f31e1d34-9840-4f5a-a269-6a911214742d
## To reproduce
1. Make sure storage versioning is enabled under feature previews >
Storage Versioning
2. Open Storage Bucket File explorer
3. create new bucket and enable Object Versioning
4. set lifecycle policy
- Noncurrent version expiration: can be either empty or >1
- Retained noncurrent versions: can be either empty or between 1 and 100
and can't exist without "Noncurrent version expiration"
5. Open new bucket with object versioning and test changing lifecycle
policies
6. Disabling object-versioning shows proper warning and updates
`versioning_status` to SUSPENDED (it can never go back to DISABLED once
it has been enabled on a bucket)
---------
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
## Problem
`parseCronJobCommand` reads the timeout of an `net.http_get` /
`net.http_post` cron command like this:
```ts
const timeout = timeoutMatch?.[1] || ''
// ...
timeoutMs: Number(timeout ?? 1000),
```
When the command has no `timeout_milliseconds` argument, `timeout` is
`''`, which isn't nullish, so the `?? 1000` fallback never applies and
`timeoutMs` becomes `Number('') === 0`.
`timeout_milliseconds` is optional in pg_net, so this is common for jobs
created in SQL, e.g.:
```sql
select cron.schedule('ping', '* * * * *', $$ select net.http_get(url:='https://example.com/health') $$);
```
Opening such a job in the cron editor shows a timeout of **0 ms**, and
saving fails validation (the field requires 1000 to 5000 ms) until the
user edits a value they never set.
## Solution
Use the parsed value when present, and otherwise fall back to pg_net's
default for `timeout_milliseconds` (5000 ms in current pg_net). That's
what the job actually runs with, so opening and saving it in Studio
doesn't change its behavior. It's also within the form's allowed range.
Added tests for the Edge Function and HTTP request paths without
`timeout_milliseconds`. Both fail on `master` (`timeoutMs: 0`), and the
existing cron tests still pass.
## Review instructions
1. In the SQL editor, run:
```sql
select cron.schedule('ping', '0 * * * *', $$ select
net.http_get(url:='https://example.com') $$);
```
2. Open Integrations > Cron > `ping` > Edit.
3. Before: the timeout field shows `0` and saving shows a validation
error. After: it shows `5000` and saves.
4. `pnpm --filter studio test
components/interfaces/Integrations/CronJobs/CronJobs.utils.test.ts`
## Checklist
- [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 applies the docs
[style
guide](https://github.com/supabase/supabase/tree/master/apps/docs/style-guide)
## Problem
We want to be able to show free-plan organizations a simplified region
selector that only lists general regions (Americas, Europe,
Asia-Pacific), controlled per organization through ConfigCat.
## Solution
- ConfigCat flags are now evaluated with `organization_slug` and
`organization_created_at` (Unix seconds) custom attributes, so flags can
target and bucket by organization.
- `organization_created_at` is read from `GET
/platform/organizations/{slug}`, fetched only for free-plan
organizations, since the organization list response doesn't include it.
- Two flags:
- `freeTierGeneralRegionEnrollment`: the organization is enrolled
(control or test).
- `freeTierGeneralRegionSelection`: the organization sees only general
regions.
- For enrolled free organizations, the region selector stays in its
loading state until flags have been evaluated with the organization's
creation time, so specific regions aren't shown and then removed.
- In the test variant, the selector hides specific regions and shows a
footer linking to the plan upgrade panel. High Availability keeps its
own region list.
- Telemetry: new `free_tier_general_region_experiment_exposed` and
`free_tier_general_region_upgrade_clicked` events, and
`freeTierGeneralRegionExperiment` / `regionSelectionType` properties on
`project_creation_simple_version_submitted`.
- `created_at` is added to `OrganizationSlugResponse` in the generated
platform types, matching the API.
## Review instructions
1. With both flags off, open `/new/[slug]` for a free organization and
confirm the region selector is unchanged.
2. Using the dev toolbar, set `freeTierGeneralRegionEnrollment` and
`freeTierGeneralRegionSelection` to `true`. Confirm only general regions
are listed and the footer links to the billing plan panel.
3. Set `freeTierGeneralRegionSelection` to `false` and confirm the full
selector is shown.
4. Repeat with a paid organization and confirm the full selector is
always shown.
## 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?
The scoped OAuth consent interstitial: scope display, org/project
selection,
consent screen assembly, success screen, and post-submit role-validation
error state. Consolidates the former stacked PRs #49481, #49484, #49486,
#49489, #49951 into one reviewable unit (each contained the last; no
code
was dropped).
- Entirely behind `useFlag('oauthAppScopedGrants')` — no reachable UI
with
the flag off.
- Runs on the mock data layer from #49476 (`USE_MOCKS`-gated); no real
endpoints are called.
- Covers PROD-626, PROD-627, PROD-628, PROD-629, PROD-653.
Base is #49476 (data contracts + mocks); will retarget to master once it
merges.
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com>
## Problem
Auth Providers uses a bespoke Enabled/Disabled chip that mixes brand
tokens with primary colour. Custom Auth Providers already uses the
standard `Badge` for the same meaning.
## Solution
Replace the bespoke chip with the existing `Badge`:
```tsx
<Badge variant={isActive ? 'success' : 'default'}>
{isActive ? 'Enabled' : 'Disabled'}
</Badge>
```
No new status primitive in this PR. Built-in providers now match Custom
Providers.
| Before | After |
| --- | --- |
| <img width="958" height="1568" alt="CleanShot 2026-10-06 at 17 19
40@2x"
src="https://github.com/user-attachments/assets/08850f4e-528a-4e47-958f-207e72783b16"
/> | <img width="934" height="1482" alt="CleanShot 2026-10-07 at 11 46
41@2x"
src="https://github.com/user-attachments/assets/232903f7-86bd-4c5c-ae1d-d873cddcf67b"
/> |
## Review instructions
1. Open Auth → Providers (built-in list). Confirm each provider shows a
small `Enabled` / `Disabled` Badge, with no brand/primary token mash-up
or oversized pill.
2. Optional: open Auth → Providers → Custom and compare the Enabled
column; it should feel like the same Badge treatment.
## Checklist
- [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 applies the docs
[style
guide](https://github.com/supabase/supabase/tree/master/apps/docs/style-guide)
## Problem
Joshen left a copy nit on #51302 after merge: the dialog intro reads
awkwardly as two short lines.
## Solution
Merge them into one sentence: “We’ve updated our Terms of Service which
includes the following:”
## Review instructions
1. Open an organisation landing page (`/organizations` or `/org/<slug>`)
in the Studio preview.
2. Click **Learn more** on the Terms of Service notice.
3. Confirm the dialog opens with a single intro line before the bullet
list, not two separate sentences.
## 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 applies the docs
[style
guide](https://github.com/supabase/supabase/tree/master/apps/docs/style-guide)
## Problem
During active incidents, the Studio status banner read:
> We are investigating a technical issue · Follow the status page for
updates Status page
The trailing "Status page" goes alongside plain-text copy that already
mentioned "status page".
## Solution
Match the emergency-override and legacy banners: make "status page" the
inline link inside the sentence, and drop the trailing link. Added a
regression test covering the link text and href.
| Figure |
| --- |
| <img width="1280" height="288" alt="6696"
src="https://github.com/user-attachments/assets/e267f0d0-5484-45a5-969f-03e184b903dd"
/> |
| _Before_ |
| <img width="1280" height="288" alt="47231"
src="https://github.com/user-attachments/assets/2beee89e-3674-43f5-9d13-6dc04d153549"
/> |
| _After_ |
## Review instructions
As of writing this: we have an active indident so you could just log in
to the [staging
preview](https://studio-staging-git-dnywh-dd493a51-supabase.vercel.app/).
Otherwise:
1. Open `apps/studio/components/layouts/AppLayout/StatusBanner.tsx` and
confirm the incident description is `Follow the [status page] for
updates` with no trailing "Status page" link.
2. Optionally run `pnpm --filter studio exec vitest run
components/layouts/AppLayout/StatusBanner.test.tsx`.
3. If you have a local Studio with an active incident (or
`ongoingIncident` override), confirm the banner shows a single linked
"status page" and no duplicate trailing link.
## Problem
Dashboard users need a notice about the Terms of Service update
alongside #51106 and #51107.
## Solution
Reuse the organisation landing-page notice pattern from #50397. A
compact “We've updated our Terms of Service.” notice opens the
explanation and agreement link through **Learn more**. Closing the
notice or choosing **Got it** remembers dismissal in the browser with a
new version-specific key.
```text
Organisation landing page
Notice → Learn more → Explanation and Terms of Service link
Close / Got it → Remember dismissal
```
| After |
| --- |
| <img width="628" height="444" alt="CleanShot 2026-10-06 at 14 47
46@2x"
src="https://github.com/user-attachments/assets/72922712-321f-4972-b20c-1a075e0745d0"
/> |
| _Banner_ |
| <img width="1078" height="718" alt="CleanShot 2026-10-06 at 16 58
18@2x"
src="https://github.com/user-attachments/assets/2109c2ab-e9b7-4855-8acb-42d5232cd002"
/> |
| _Dialog_ |
## Review instructions
1. Open `/organizations` or an organisation's `/org/<slug>` landing page
in the hosted Studio preview. Expect the compact notice.
2. Click **Learn more**. Expect the explanation and a link to the Terms
of Service. Escape closes the dialog without dismissing the notice.
3. Choose **Got it**, then reload. The notice stays dismissed. Repeat in
a fresh browser profile using **Close banner**.
4. Open a project or an organisation settings page. The notice should
not appear.
## Summary
* Makes sign-in banner visible on unauthenticated pages
* Show only when one of the affected components is Dashboard
* Works only when new status page (under feature flag) is being used
* Regression fix: Auth pages without the status banner (sign-up,
sign-in-mfa, sign-in-recovery-code, sign-in-sso, sign-in-partner,
forgot-password, forgot-password-mfa, reset-password) no longer reserve
dead space at the top for a banner they don't render
## Test plan
- [X] TypeScript: `tsc --noEmit` passes clean, no type errors
- [X] Unit tests: All new/existing tests pass in
`apps/studio/lib/status-page/status-page.utils.test.ts` and
`apps/studio/components/layouts/AppLayout/StatusBanner.utils.test.ts`
(697 files / 7833 tests, no regressions)
- [X] Manual verification: Sign-in page still renders the banner
correctly when an incident affecting Dashboard is active; no layout
regression
**Related:**
[FE-3443](https://linear.app/supabase/issue/FE-3443/only-show-sign-in-incident-banner-when-relevant)
## Summary
Removes the "Resizes may require more downtime than normal on this
project." warning from the disk/compute review dialog. This warning was
added for cross-architecture migrations during resize operations, which
are no longer performed, and has caused unnecessary customer support
inquiries.
## Closes
FE-4543
https://linear.app/supabase/issue/FE-4543
## Problem
The Studio unit test added in #51112 failed on master because the
`/after` element returned by `findByText` was detached by a rerender
before `toBeInTheDocument` ran. The failure repeated across all three
test attempts in [this
job](https://github.com/supabase/supabase/actions/runs/37480673016/job/112327649118).
## Fix
Retry the DOM lookup and assertion together with `waitFor`, so each
attempt checks the current element synchronously. Keep the existing
timeout and assertions covering pathname refresh before the URL updates.
## How to test
- Run `pnpm --filter studio exec vitest run
components/interfaces/UnifiedLogs/UnifiedLogs.test.tsx`.
- Expected result: pathname options refresh after selecting POST and the
test passes.
- Prettier and `git diff --check` pass. Local Vitest was blocked before
assertions by the available dependency tree using React 18 instead of
React 19; ESLint was blocked by a missing `@eslint/compat` dependency.
CI validation is pending.
## Problem
Unified Logs included a pathname aggregation in every initial sidebar
count query, even when the pathname filter was closed. This issue is
tracked in
[DEBUG-230](https://linear.app/supabase/issue/DEBUG-230/fetch-sidebar-counts-only-when-needed).
## Fix
Remove pathname aggregation from the initial ClickHouse and BigQuery
count queries while keeping the existing shared count scans. Fetch
scoped pathname options through the existing facet query when the filter
opens or its search changes. Order limited pathname results by count,
validate response rows with Zod, and retain selected paths during
loading and validation errors. Use live sidebar filters while their URL
update is pending and URL filters after navigation. Cache results by
project and filter scope, and wait for feature flags before requesting
options.
## How to test
- Open Unified Logs, then open Pathname and search. Confirm options load
on demand.
- Change the time range, another filter, or navigate through browser
history. Confirm the options reflect the current scope.
- Close and reopen Pathname without changing the scope. Confirm cached
options return.
- Run the pathname filter component tests and Studio typecheck.
## Context
Similar to domain to https://github.com/supabase/supabase/pull/51256 -
`getTableDefinitionSql` doesn't escape SQL identifiers, which generates
invalid SQL on the dashboard's table editor for the "Copy table schema"
CTA, or the table definition tab.
Also fixes the "Copy table schema" CTA which was missing the `scoped`
parameter when calling `getTableDefinition`
Changes here addresses this issue, can test with a table named like
`test"table`
## Context
Adds virtualization to the organization team members page - browser
performance was facing issues for organizations with a large amount of
members (e.g 1000+), primarily due to some computation within
`MemberActions.tsx`, so virtualization addresses this by controlling the
number of member rows being rendered in the DOM at any one time.
<img width="1182" height="435" alt="image"
src="https://github.com/user-attachments/assets/e3da7036-c1c8-4d73-a363-85ecbdb79179"
/>
## Unrelated changes
- Updated `TeamSettings` to use the `PageContainer` components for UI
consistency
- Updated user `ProfileImage` to render the first alphabet of the email,
rather than a generic user icon
<img width="275" height="126" alt="image"
src="https://github.com/user-attachments/assets/17eae3b1-c527-4b8f-afcd-c5151bdaf869"
/>
- Updated row heights of member rows to be more smaller
- Updated MFA column to use tooltips with a clearer CTA for members that
don't have MFA enabled
<img width="332" height="144" alt="image"
src="https://github.com/user-attachments/assets/a479af31-7fec-454d-b64e-e6314fd6d55e"
/>
- Added a filter for MFA status
<img width="375" height="177" alt="image"
src="https://github.com/user-attachments/assets/fd87105e-524d-4ded-b471-769592be96c7"
/>
## To test
- Can override the content for the `members` network request with the
following sample JSON, main thing is just to test that initial load +
searching should not run into any significant browser performance
issues.
[members-response-1000.json](https://github.com/user-attachments/files/33100317/members-response-1000.json)
- Can also test on production that this mock response does indeed cause
browser performance issues as well
| # | Branch | Base |
| - | ------ | ---- |
| 1 | `feat/storage-versioning-private-alpha` — merged | `master` |
| 2 | `feat/storage-versioning/002-bucket-form-fields` ◀ | `master` |
| 3 | `feat/storage-versioning/003-bucket-modals` | 2 |
| 4 | `feat/storage-versioning/004-object-versions-data` | 3 |
| 5 | `feat/storage-versioning/005-file-preview-versions` | 4 |
| 6 | `feat/storage-versioning/006-billing-storage-retention` | 5 |
| 7 | `feat/storage-versioning/007-archived-objects-data` | 6 |
| 8 | `feat/storage-versioning/008-archived-rows` | 7 |
| 9 | `feat/storage-versioning/009-archived-preview-pane` | 8 |
| 10 | `feat/storage-versioning/010-replace-file` | 9 |
## [2/10] Storage object versioning: bucket form fields
The object versioning + lifecycle policy form section for the create and
edit bucket modals.
Mounted onto the ui in PR 3 #49205
- `BucketVersioningFields` — the versioning switch and the suspension /
public-bucket / retention-tightening warnings
- `LifecyclePolicySection` — the retention window and version cap inputs
- `ExpirationModeToggle` — how the two conditions combine (and / or)
- `BucketVersioningFields.schema.ts` — zod fields the parent modals
spread into their own schema, plus `superRefineBucketVersioning`
- `BucketVersioningFields.utils.ts` — retention-tightening detection
- `StorageVersioning.constants.ts` — versioning state and expiration
mode types, the prefill defaults, and `getBucketVersioningState`
Note: a single s3 lifecycle policy expects both `version_expiry_days`
and `max_noncurrent_versions` and always evaluate the two fields within
the same policy with an AND logic. To enable both AND and OR/EITHER
logic, we save two distinct s3 policies so we can enforce the OR logic.
See demos and how to reproduce in #49205
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Summary
* **New Features**
* Eligible projects with the preview enabled can configure object
versioning for storage buckets, including version expiration,
retained-version limits, and “and/or” lifecycle conditions.
* Settings default to 30 days and 10 retained versions, with validation
for retention values and requirements for setting a version limit.
* Notices highlight public buckets, missing lifecycle conditions,
suspending existing versioning, and changes that tighten retention
limits.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
## Context
Chats with the AI Assistant is currently stored locally on the browser
and not synced across devices which caused a bit of confusion for some
users when they realised they couldn't access their chat histories on
different devices. (Ideal state tbh is to persist the chat
conversations, but that'll need support on the BE)
PR here just adds a foot note to both the chat history dropdown in the
side panel + chat nav for the explorer regarding this - opting for
something with a small footprint
<img width="293" height="322" alt="image"
src="https://github.com/user-attachments/assets/284ee0c1-16bf-432b-b473-29ee048ed4cc"
/>
<img width="392" height="956" alt="image"
src="https://github.com/user-attachments/assets/e5eb1409-fa63-4dae-9439-86facbe41277"
/>
---------
Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com>
## Context
Resolves https://github.com/supabase/supabase/issues/49977
Addresses an issue in `formatTableRowsToSQL` to use `ident` for schema,
table, and column name which will handle escaping of SQL identifiers.
Can verify fix by creating a table like `test"table`, then adding some
rows, and selecting either Copy as SQL or Export as SQL
## Context
Adds a couple of branching nav items to Command K
- Create new branch
- Branch management
- Merge requests
- Github Connection (For branching)
- Branching feedback
Switch branch is still available, and only visible after a branch has
been created (status quo)
<img width="610" height="531" alt="image"
src="https://github.com/user-attachments/assets/3068184e-889d-44ed-8cf6-2afd59ffb109"
/>
## Context
Prevents organizations from enabling spend cap if the org has projects
with read replicas - We currently gate creation of read replicas to
ensure that orgs have spend caps disabled, but were missing the guard
for the other way around
<img width="662" height="378" alt="image"
src="https://github.com/user-attachments/assets/44ad036c-4c1b-48e8-beb7-f16f6170c9fb"
/>
## Other changes involved
- Refactored to use new `Sheet` and `Table` components in
`SpendCapSidePanel`
I removed the Studio Privacy Policy update notice that #50397 added on
2026-09-16, when Privacy Policy v4 took effect. It has been up for
almost three weeks, and the ToS v4 banner (#51109) goes out next. I did
the same in #44380, removing the March 2026 privacy notice after 15
days.
This is the exact inverse of #50397: the banner component and its test,
the banner ID, the dismissal local storage key, and the org-landing path
helper that only this notice used.
## To test
Tested on Vercel preview:
- [ ] In a fresh browser profile (no
`privacy-policy-update-2026-09-16-dismissed` key), open
`/organizations`: expect no Privacy Policy notice
- [ ] Open `/org/<slug>`: expect no Privacy Policy notice and the
project list renders normally
- [ ] Open a project's Logs page: expect the logs deprecation banner
behavior unchanged (only shows before its expiry)
## Linear
- fixes GROWTH-1322