Commit Graph
5604 Commits
Author SHA1 Message Date
Claude 53e0e57ffe fix(storage): keep the preview panel's URL button and row handles as they were
The redesign renamed the panel's "Get URL" button to "Copy URL" while the row
context menu kept "Get URL", leaving one action with two names, and gave the
panel's file name a `title` — the attribute the explorer rows use as their
handle, so `getByTitle` matched two elements once a preview was open.

Also snap five off-token sizes to the scale the ratchet enforces, and point the
E2E delete helper at the confirmation's real label now that it says what it
does instead of ConfirmationModal's "Submit" default.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn
2026-10-08 18:37:02 +02:00
Claude 183d5f2114 fix(storage): say the version matched the policy and will be deleted
Leads with what happened and that it is permanent, then bounds the wait.
The previous wording blamed a missing schedule; the real reason there is no
exact timestamp is that the cleanup spans several systems.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn
2026-10-08 18:37:02 +02:00
Claude fdd935c05f fix(storage): say cleanup can take up to 24 hours
There is no computable expiry timestamp: cleanup runs at no fixed moment
and removal can lag by a day, so the tooltip says so rather than implying
the next pass is imminent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn
2026-10-08 18:37:02 +02:00
Claude 88f2609670 feat(storage): say a version is queued to expire, not expiring now
"Expiring now" claimed a moment that does not exist: cleanup is a periodic
pass, so a version that has met the policy stays listed until it runs. The
tooltip says why, within a max width.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn
2026-10-08 18:37:02 +02:00
Claude 42a0ced1de fix(storage): refresh the row after restoring a version
Restoring a noncurrent version invalidated the version list but left the
explorer row showing the old size, type and modified date, since the live
listing is the explorer's own state rather than a React Query cache.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn
2026-10-08 18:37:02 +02:00
Claude ffc1ab56e6 refactor(storage): trim comments to one line where they earn their place
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn
2026-10-08 18:37:02 +02:00
Claude 39f0406192 fix(storage): preview a version's own bytes, not the current ones
The version history rendered a generic mime-type icon per row, and the
compare widget put that same icon on both sides — so every entry for a
file looked identical and the comparison showed nothing to compare.

The sign and public-url endpoints already accept `options.versionId`;
nothing asked for it. `useFetchFileUrlQuery` now takes a `versionId` and
keys on it, and the preview rendering moves out of `PreviewPane` into a
`FilePreview` component both the pane and the compare widget use, so a
version preview cannot silently fall back to the current bytes.

Image rows in the history list render their own thumbnail under 5MB;
larger files and other mime types keep the icon rather than pull a whole
object down for a 28px box.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn
2026-10-08 18:37:02 +02:00
Claude e2cc696922 feat(storage): offer Archive and Delete permanently from the row menu
The file preview panel already splits the two on a versioned bucket, but
the explorer's own row menu still offered a single "Delete" — which
archives there, without saying so.

The row menu now reads "Archive" on a versioned bucket and gains a
"Delete permanently" entry beside it.

`ConfirmPurgeModal` is mounted once by the explorer and driven by
`itemToPurge` on the store, the same shape the row delete already uses.
The preview panel routes its own permanent delete through it too, so the
confirmation copy exists in one place rather than two.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn
2026-10-08 18:37:02 +02:00
Claude 0b8ef6dad2 feat(storage): drive version history off the real endpoints
The preview panel now addresses versions by the object's full path, which
is what the list, move and delete endpoints take, rather than by the leaf
name the explorer renders. `VersionHistory` keeps `objectName` for copy
and takes `path` separately.

Expiry countdowns read the bucket's stored lifecycle policy instead of an
empty placeholder, so a row's fate reflects the policy that governs it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn
2026-10-08 18:37:02 +02:00
Francesco SansalvadoreandClaude Sonnet 5 0cd08c6b1a fix(storage): tell the truth in the empty version history
The empty state read "Overwriting this file will retain a recoverable copy here"
regardless of whether the bucket was actually versioned. Since
`getBucketVersioningState` reports `disabled` for every bucket until the API
exposes the field, that promise was showing on every file in every bucket.

Splits it: `disabled` now says versioning is off and points at the bucket
settings; `enabled`/`suspended` keep the original copy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-08 18:37:02 +02:00
Francesco Sansalvadore 89e946acc2 improve comments 2026-10-08 18:37:02 +02:00
Francesco SansalvadoreandClaude Sonnet 5 60d8c45f8e refactor(storage): drop the unreachable cap-only lifecycle branch
Follows the same change in the version-fate helper: a version cap always arrives
alongside an expiration age, so the policy summary only has three shapes to
describe (age alone, or age plus cap under either operator). Removes the
cap-only sentence and the "no age limit" chip, and `daysRemaining` on
`expires-on-next-upload` no longer needs an undefined guard.

Also adds the explicit `tabIndex={0}` that `supabase/require-explicit-tabindex`
wants on the four raw buttons in this feature. These were lint *errors*, not
warnings, so the ratchet never surfaced them.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-08 18:37:02 +02:00
Francesco SansalvadoreandClaude Sonnet 5 28b78001cb refactor(storage): say "retained" rather than "kept" for versions
Completes the rename in the version history rows, the lifecycle policy summary,
and the delete confirmation copy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-08 18:37:02 +02:00
Francesco SansalvadoreandClaude Sonnet 5 55fc610c2e feat(storage): add version history to the file preview panel
Rebuilds the file preview panel around object versioning: a collapsible Versions
section listing every version with its removal outlook, an inline
compare-and-restore widget, and delete actions that say what they actually do on
a versioned bucket.

- `VersionHistory` + `VersionHistoryPolicyRow` + `VersionThumbnail` — the version
  list, the inline lifecycle policy summary, and the row glyph
- `VersionCompareWidget` — takes over the top of the panel when a noncurrent
  version is selected, so restoring is a visible comparison, not a modal
- `PreviewSection` — the collapsible section wrapper
- `PreviewPane` — new panel chrome, viewport-clamped thumbnail, and an
  Archive / Delete permanently split button on versioned buckets
- `ConfirmDeleteModal` — on a versioned bucket a delete is a soft delete, so the
  copy no longer claims it cannot be undone

Delete markers are surfaced as their own row type. They are the empty
placeholders S3 writes on a soft delete, and they can outlive the delete
(delete → upload → delete → restore leaves one mid-history), so a live file's
history can contain them. There is nothing to preview or restore, so the row is
non-interactive, dimmed, labelled "Delete marker", and its only action is
removing the marker itself.

Version data comes from the stubbed query added in the previous PR, so the
Versions section renders its empty state until the Storage API lands.

Fixes carried over from the prototype rather than ported:
- Version rows were a clickable `<li>` whose `onKeyDown` passed a function
  reference instead of calling it, so keyboard activation did nothing. They are
  real `<button>`s now, which fixes activation and a11y together.
- The policy summary put a `<Button>` inside tooltip content, unreachable by
  pointer or keyboard — now a `HoverCard`.
- Permanent delete fired a bare `toast.success` with no mutation behind it.
- Dropped the download and "Get version URL" menu items, which were toast stubs.
- Deduplicated a double `filter` over versions and memoized the fate map.

Also re-syncs `selectedBucket` in the explorer store when the bucket query
refetches. It was only ever seeded once, so editing a bucket left consumers
reading stale metadata — which is how Copy URL could sign a URL for the wrong
visibility after a public/private toggle.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-08 18:37:02 +02:00
Jordi Enric dbfa35ddb3 fix(studio): remove unsupported log drain form variants (#51449)
## 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.
2026-10-08 15:25:44 +00:00
690ef5e7f7 feat(studio): scoped oauth apps, admins can see an app grants (#50979)
## Problem

Admins need to see the grants associated to an approved OAuth
application that uses scoped tokens.

## Solution

- Add a menu to the org settings oauth approved apps rows to see the
grant list
- Update the react query hook to use infinite query for the grant list

<img width="1149" height="356" alt="image"
src="https://github.com/user-attachments/assets/2e6cfc76-5584-4447-aa19-a0bf103e2218"
/>

<img width="429" height="395" alt="image"
src="https://github.com/user-attachments/assets/dd811d33-2c0a-46df-b9e9-3cbf8ad2fa7f"
/>

<img width="434" height="267" alt="image"
src="https://github.com/user-attachments/assets/108905ba-4dcb-4dca-abe2-1a4e1fc3dbd2"
/>

## Review instructions

In Org Settings/OAuth apps, you should see a menu button for each app
that contains a _View grants_ item. Clicking this item should open a
dialog with the grants

---------

Co-authored-by: kemal <hello@kemal.earth>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-08 15:48:51 +02:00
Joshen Lim 18080d88f7 Joshenlim/fe 4512 make GitHub connection setup obvious on empty branching page (#51393)
## 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"
/>
2026-10-08 19:54:41 +08:00
Bobbie Soedirgo 536fbd5470 fix: make auto rls SQL Multigres-compatible (#51428)
Part of resolving
[INC-868](https://supabase.slack.com/archives/C0C8EBVUX2L/p1791443825740829?thread_ts=1791411302.921479&cid=C0C8EBVUX2L)

Auto RLS SQL isn't Multigres-compatible since it uses `EXECUTE` with a
freeform `%s` parameter

Tested locally
2026-10-08 11:59:35 +02:00
12ab771e86 feat(studio): authorized apps table in org settings (#50529)
<img width="1150" height="669" alt="image"
src="https://github.com/user-attachments/assets/0b324577-bed5-4272-a7e0-f4444a0c1230"
/>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com>
2026-10-08 11:25:07 +02:00
Julian Domke af3e397e7f feat(credit-codes): show that credit codes were reduced by partner deals (#51173) 2026-10-08 07:38:53 +00:00
Danny WhiteandJoshen Lim 78dc739901 fix(studio): show support inline and honour AlertError layouts (#51377)
## 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>
2026-10-08 16:04:32 +11:00
Joshen Lim 26c838a433 Joshenlim/fe 4590 studio sql export can silently swap values for numeric (#51382)
## 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
2026-10-08 11:41:16 +08:00
Danny White 6c829b32da fix(studio): enable Pipelines before opening creation (#51311)
## 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.
2026-10-08 10:42:39 +11:00
supabase-vercel-tedd[bot]andAli Waseem d72211556b feat(studio): link overview Machine size card to Infrastructure settings (#51402)
## 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>
2026-10-07 14:37:52 -06:00
Francesco SansalvadoreandClaude Sonnet 5 2d0bd7af69 feat(storage): add object versions data layer (#49207)
| # | 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>
2026-10-07 22:12:19 +02:00
kemal.earth 329b0a0156 fix(studio): animation gradient on log drains empty state (#51403)
## Problem

Animation had values that became deprecated after colour migration.

## Solution

Updated to use the same background colour as everywhere else. To test,
on a free organization navigate to Settings > Log Drains.

| Before | After |
|--------|--------|
| <img width="764" height="356" alt="Screenshot 2026-10-07 at 18 20 21"
src="https://github.com/user-attachments/assets/eb07c4fa-e089-4558-83fe-01ff189eeae4"
/> | <img width="760" height="342" alt="Screenshot 2026-10-07 at 18 24
06"
src="https://github.com/user-attachments/assets/dc7b3998-df1c-4df0-ae15-e23286787cf4"
/> |
2026-10-07 18:42:05 +01:00
Chris Gwilliams ccb1c60166 fix: show dialog to prevent restoring larger projects to nano compute (#51309) 2026-10-07 20:04:04 +03:00
Alaister YoungandAlaister Young 55c297655e fix(studio): keep project sidebar navigation accessible (#51055)
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>
2026-10-07 18:45:58 +02:00
6ef729cb5c feat(storage): versioning bucket modals (FE-4161) (#49205)
| # | 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>
2026-10-07 16:38:35 +02:00
Yuvraj Singh d1205a05e9 fix(studio): default cron HTTP timeout when timeout_milliseconds is omitted (#51385)
## 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)
2026-10-07 15:51:54 +02:00
Charis 22886fd304 feat(studio): add flag-gated general region selection (#51274)
## 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.
2026-10-07 09:43:28 -04:00
454a232947 feat(studio): scoped oauth interstitial ui (#50090)
## 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>
2026-10-07 10:56:24 +02:00
Danny White a4910196b8 fix(studio): use Badge for auth provider enabled state (#51310)
## 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)
2026-10-07 17:30:30 +11:00
Danny White 5c4745a117 fix(studio): smooth Terms of Service dialog intro copy (#51370)
## 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)
2026-10-07 16:08:44 +11:00
Danny White 272bb26635 fix(studio): remove duplicate status page link in incident banner (#51305)
## 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.
2026-10-06 23:16:25 +00:00
Danny White b5c865521f feat(studio): notify users about the Terms of Service update (#51302)
## 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.
2026-10-07 09:09:01 +11:00
Charis ab383421c5 fix(studio): show sign-in banner based on Dashboard component [FE-3443] (#51283)
## 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)
2026-10-06 15:56:48 -04:00
Charis 28f59449c3 [FE-4543] fix(studio): remove outdated resize downtime warning (#51344)
## 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
2026-10-06 15:34:15 -04:00
Ivan VasilovandClaude Sonnet 5.5 9d1661dec1 chore: Reorganize the Files buckets code (#51350)
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-06 15:29:35 +00:00
Jordi Enric c0c51dc168 test(logs): stabilize pathname refresh assertion DEBUG-230 (#51351)
## 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.
2026-10-06 09:11:00 -06:00
Jordi Enric d2ffd76395 perf(logs): load pathname facet counts on demand DEBUG-230 (#51112)
## 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.
2026-10-06 16:38:30 +02:00
Joshen Lim eb20a4674d getTableDefinitionSql to escape SQL identifiers (#51258)
## 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`
2026-10-06 21:34:36 +08:00
K-Dog (Kevin) 1da25a7e72 chore(hipaa): self-serve PITR (#51342)
There is no reason why HIPAA customers cannot self-serve PITR add-on.
Instead of telling customers to reach out to support, let them
self-serve it.

- Docs also wrongfully stated the need for Small compute add-on.
- Ability to self-serve PITR
- Only 28-day PITR available
- Price is now also correct and displays $0 (pending backend change)

When enabled (marked as HIPAA compliant):
<img width="1128" height="216" alt="Screenshot 2026-10-06 at 1 53 01 PM"
src="https://github.com/user-attachments/assets/d83982e7-c71b-4236-ab29-67f85fc40f39"
/>

When not enabled (marked as HIPAA compliant):
<img width="1132" height="255" alt="Screenshot 2026-10-06 at 1 53 55 PM"
src="https://github.com/user-attachments/assets/f182813b-2163-4905-8cdf-9c69983ec1b9"
/>

<img width="772" height="542" alt="Screenshot 2026-10-06 at 1 56 08 PM"
src="https://github.com/user-attachments/assets/2cd59439-74b9-49d6-90d1-47c8d1722c9f"
/>
2026-10-06 15:11:55 +02:00
Joshen Lim 23e7bbcdc6 Joshenlim/fe 3359 fix user permission UI for orgs with thousands of projects (#51329)
## 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
2026-10-06 06:41:39 -06:00
089133cc2c feat(storage): add bucket object versioning form fields (FE-4161) (#49203)
| # | 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>
2026-10-06 14:24:50 +02:00
Joshen LimandGildas Garcia dc95335a8d Joshenlim/fe 4068 warn users ai assistant history can be wiped (#51260)
## 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>
2026-10-06 11:37:26 +08:00
Joshen Lim 2538f7eb29 Fix unescaped SQL identifiers in row export (#51256)
## 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
2026-10-06 11:35:01 +08:00
Joshen Lim be1ba651ed Add branching nav items to cmd k (#51255)
## 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"
/>
2026-10-06 11:12:53 +08:00
Joshen Lim 642a02db49 Prevent enabling spend cap if org has projects with RRs (#51253)
## 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`
2026-10-06 11:12:35 +08:00
Pamela Chia 20d6f2197f chore(studio): remove privacy policy notice (#51299)
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
2026-10-05 19:24:14 -07:00