Commit Graph

158 Commits

Author SHA1 Message Date
Jordi Enric 4fa3169e8e test(logs): regression coverage for datepicker Invalid time value crash (#48027)
## Problem

The database-report chart to logs flow could crash the logs date picker
with "RangeError: Invalid time value" (react-day-picker formatting an
Invalid Date), and there was no regression coverage for it.

## Fix

Adds two Vitest tests that reproduce the crash path:

- Logs.Datepickers.test.tsx: opening LogsDatePicker with an unparseable
value (the legacy epoch-ms its/ite) must render the calendar instead of
throwing.
- LogsPreviewer.test.tsx (MSW): its/ite from the URL load into the
picker and it opens without crashing, covering the chart-to-logs
navigation end to end.

Note: these tests depend on the fix in #48009. On master the crash-guard
test fails with the exact "Invalid time value" error (that is the
regression it catches), so CI here will be red until #48009 merges.

## How to test

- Run: pnpm --filter studio exec vitest --run
tests/features/logs/Logs.Datepickers.test.tsx
tests/features/logs/LogsPreviewer.test.tsx
- On master: the "unparseable date value" test fails with RangeError:
Invalid time value.
- With #48009 merged in: both pass.


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

## Summary by CodeRabbit

* **Tests**
* Added coverage to ensure the logs date picker handles legacy or
unparseable date values without crashing.
* Added coverage verifying log preview date ranges are populated from
URL parameters and can be opened successfully.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-17 10:11:24 +02:00
Ali Waseem b100272376 chore(sql-editor): remove Pretty Explain feature (#47981)
Removes the SQL Editor Pretty Explain feature — the Explain tab, the Run
EXPLAIN ANALYZE action + shortcut, and its dead plumbing. It's been
gated off behind the `DisablePrettyExplainOnSqlEditor` kill switch for
weeks with no usage or complaints.

`ExplainVisualizer` / `isExplainQuery` are kept — they're used
independently by Query Insights, Query Performance, and the EditorPanel
quick-runner. Manually-run `EXPLAIN` queries still render as raw rows in
the Results tab.

Typecheck, lint, and all affected unit tests pass.

Closes FE-3930

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

## Summary by CodeRabbit

* **Changes**
* Removed the SQL editor’s EXPLAIN execution workflow, including its
toolbar action, keyboard shortcut, utility tab, and visual query-plan
display.
  * Simplified query execution to focus on standard results and charts.
* Improved result clearing when switching databases and refined
execution error handling.
* Updated SQL editor state and tests to reflect the streamlined
experience.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-16 11:04:34 +08:00
Charis 52a25c2ebb refactor(sql-editor): extract AI/diff + shortcuts hooks (decompose 5/6) (#47935)
## What

Decompose step **5 of 6** for `SQLEditor.tsx`. Extracts the Assistant /
diff cluster and the keyboard-shortcut wiring out of the
`SQLEditorContent` monolith into two focused, individually-testable
hooks:

- **`useSqlEditorAi`** — SQL completion (`complete`), the ask-AI prompt
flow (`handlePrompt`), accept/discard diff handlers, `onDebug` /
`buildDebugPrompt` helpers, `handleDiffEditorMount`, and the fragile
diff lifecycle effects (one-shot diff-request drain, diff-editor value
sync, ask-AI widget visibility).
- **`useSqlEditorShortcuts`** — the registered shortcuts (focus editor,
new snippet, format, explain) plus the accept/discard/escape keydown
handling.

`SQLEditorContent` now composes these hooks alongside the
execution/explain hooks landed in decompose 4.

## Behavior-preserving

This is a pure extraction. The moved function bodies, effect logic,
dependency arrays, and JSX are unchanged from the previous monolith
(verified via `git diff` against the pre-decomposition source). In
particular:

- `useEffectEvent` is preserved for `drainDiffRequest` / `resetDiff`.
- `editorMountCount` remains single-owner (passed into the AI hook to
drive the one-shot drain).
- The untrusted→safe SQL promotion (`acceptUntrustedSql`) continues to
happen in the run/explain gesture and warning-modal handlers in
`SQLEditorContent`, as close to the explicit user action as possible.

The Phase-1 characterization suite (`SQLEditor.test.tsx`, 11 tests)
remains green.

## Stack

Part of the SQLEditor decomposition stack (1/6 … 6/6). Builds on
decompose 4 (execution + explain hooks, #47923). Next: PR6 splits the
JSX into panes + final cleanup.


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

## Summary by CodeRabbit

* **New Features**
* Improved SQL editor AI assistance, including completion prompts,
debugging support, and diff review controls.
* Added keyboard shortcuts for accepting or discarding AI-generated SQL
changes.
* Added shortcuts for focusing the editor, creating snippets, formatting
queries, and explaining SQL.

* **Bug Fixes**
  * Prevented SQL execution while reviewing AI-generated differences.
* Improved handling of AI diff state during editor loading and
interaction.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-14 15:14:12 -04:00
Charis d453e57086 test(sql-editor): characterization tests for SQLEditor (decompose 1/6) (#47820)
## Summary

Add some tests for the SQL editor so I can refactor it without
regressions. Tests are not best practice because they are intended to be
temporary and improving them would require refactoring first (currently
they are over-mocking and asserting on internal details).

Stacked on top of #47792 (`charislam/sql-editor-top-bar-controls`).

## What this adds

`apps/studio/tests/components/SQLEditor/SQLEditor.test.tsx` (11 tests):

- Run success → `addResult` + Results tab; EXPLAIN-shaped result
auto-switches to the explain tab; a non-EXPLAIN run switches back.
- Run error with `position` → error-highlight line math +
`deltaDecorations` + `revealLineInCenter`; the next run clears the
highlight.
- Run button refocuses the editor; disabled + short-circuits while a
diff is open.
- Diff request queued before mount drains exactly once (one-shot; no
re-apply on remount).
- Ask-AI widget renders only while the prompt is open (render-time
`editorRef.current` read).
- Destructive query → warning modal → confirm forces the re-run;
confirm-with-RLS appends enable-RLS statements.

## Test approach

Real Monaco / DiffEditor are replaced with lightweight fakes exposing a
controllable editor; child panels + orthogonal context hooks are
stubbed; the execute mutation runs for real against an MSW-mocked
`/platform/pg-meta/:ref/query`. Tests assert on public behavior so they
survive the internal refactor unchanged.

## Verification

- `pnpm --filter studio exec vitest run
tests/components/SQLEditor/SQLEditor.test.tsx` — 11/11 pass (stable
across repeated runs)
- `pnpm --filter studio typecheck` — clean
- `eslint` — 0 errors

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

## Summary by CodeRabbit

* **Tests**
* Added comprehensive coverage for SQL editor behavior, including query
execution, result and explain views, error highlighting, editor focus,
and diff mode.
* Added validation for destructive-query confirmations, including RLS
confirmation flows.
* Added coverage for queued diff requests and conditional AI prompt
display.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-10 10:47:45 -04:00
Ali Waseem 7141b0ae2d test(studio): add MSW tests for project creation flow (#47790)
Adds 21 MSW component tests covering the project creation wizard's
permutations (plan/region/compute/OrioleDB/security
options/GitHub/blocking states/errors). Closes FE-3883; surfaced a real
empty-region submit bug tracked in FE-3884.

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

* **Tests**
* Added a comprehensive UI/request test suite for the Studio
project-creation wizard.
* Validates paid vs. free plan behavior (including compute sizing rules)
and that region selection submits the correct payload, including the
“Recommended” option.
* Covers blocking and warning states (project limits, overdue invoices
with billing CTA, and feature-flagged disabled creation), plus error
handling when regions fail to load.
* Exercises confirmation modals, database/security option flows,
client-side validation, GitHub gating/repo selection, and toast errors
on API failures.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-10 07:20:00 -06:00
Saxon Fletcher 09ea558d54 Vercel install layout (#47550)
Bring the Vercel install layout up to date with other connect screens.
Resolves DEPR-615.

| Before | After |
| --- | --- |
| <img width="1600" height="1200" alt="CleanShot 2026-07-03 at 10 51
59@2x"
src="https://github.com/user-attachments/assets/6a8c2910-8c45-4c7d-8d38-8b80c5cf4c83"
/> | <img width="1150" height="1318" alt="CleanShot 2026-07-03 at 11 56
17@2x"
src="https://github.com/user-attachments/assets/3a5add5c-fea4-44f3-a368-5732257b27d9"
/> |

## Testing

- Open the deploy preview or staging URL for
`/dashboard/integrations/vercel/install` with callback params from a
real Vercel Marketplace install redirect (see _Vercel_ subheading
below).
- Confirm the install screen renders with the selected Supabase account,
organization picker, and primary install CTA.
- Remove required callback params such as `code`, `configurationId`, or
`source` to verify the "Missing Vercel installation details" warning
state.
- Clicking "Install integration" with an expired or reused `code` can
show `Creating Vercel integration failed: Failed to get Vercel access
token`; that is expected for preview UI validation. A full successful
install requires a fresh Vercel-generated code from the install flow.

To reiterate; this won’t work because the code will be invalid. But it
should show that everything is hooked up right for prod.

### Vercel

1. Go to Supabase. Open either org-level or project (settings) level
integrations.
2. Tap "[Install Vercel
Integration](https://vercel.com/integrations/supabase-local)".
3. Follow the install instructions from that Vercel page. This should
open a browser window.
4. Copy the URL of that browser window. Take the params and paste them
instead at the end of the deploy preview URL.

Example of #4:

```txt
Before:
https://supabase.com/dashboard/integrations/vercel/install?code=jDhIBDlD58zzLVtuSNjJpUSu&configurationId=icfg_v3dKllQIniSOwdVI3gypnZh3&next=https%3A%2F%2Fvercel.com%2Ftest-5706s-projects%2F~%2Fintegrations%2Ficfg_v3dKllQIniSOwdVI3gypnZh3%2Finstalled&source=marketplace&teamId=team_mPkGQZjTLBEUXh15b03iVsTg

After
https://studio-staging-git-chore-install-layout-supabase.vercel.app/dashboard/integrations/vercel/install?code=jDhIBDlD58zzLVtuSNjJpUSu&configurationId=icfg_v3dKllQIniSOwdVI3gypnZh3&next=https%3A%2F%2Fvercel.com%2Ftest-5706s-projects%2F~%2Fintegrations%2Ficfg_v3dKllQIniSOwdVI3gypnZh3%2Finstalled&source=marketplace&teamId=team_mPkGQZjTLBEUXh15b03iVsTg
```

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

## Summary by CodeRabbit

* **New Features**
* Updated the installation experience with a cleaner, more guided
layout.
* Added clearer organization selection during setup, including
visibility into which organizations are already installed.

* **Bug Fixes**
  * Improved loading and error handling during installation.
* Added clearer warnings for missing setup details, already-installed
integrations, and cases with no available organizations.
* Fixed routing behavior so organization selection is preserved more
reliably.

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

---------

Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com>
2026-07-06 19:34:20 +10:00
Vaibhav 804475fd3a fix: redirect urls (#47487)
## TL;DR

fixes redirect url  normalization..

## PS:

| Before | After |
| --- | --- |
| Broken: whitespace could make the same redirect URL appear as a
separate entry and break delete behavior | Fixed: equivalent redirect
URLs are normalized consistently, so display, save, and delete behavior
stay in sync |
| <img width="800" height="274" alt="Before redirect URLs behavior"
src="https://github.com/user-attachments/assets/47dbb1ca-7c7d-482b-a67e-08c2eb2cd030"
/> | ![After redirect URLs
behavior](https://github.com/user-attachments/assets/b90dfad3-9ec2-4431-8412-34d4faca62da)
|

## ref:
- closes https://github.com/supabase/supabase/issues/47478

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

* **Bug Fixes**
* Improved redirect URL handling so saved and displayed URLs are
consistently trimmed, normalized, deduplicated, and parsed from
comma-separated allow lists.
* Tightened redirect URL validation to better catch invalid formats and
prevent duplicates both against the existing allow list and within a new
submission.
* Fixed redirect URL deletion to remove the exact set of URLs confirmed
by the user.
* **Tests**
* Added/updated tests to cover redirect URL normalization and parsing
behavior for stored comma-separated allow lists.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-01 08:24:17 -06:00
Gildas Garcia 0e3364bbad Chore/cleanup studio deps (#47399)
## Problem

Knip reported some unused dependencies. Some are actually used in
builds, etc but others are not.

## Solution

Remove the really unused dependencies

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

## Summary by CodeRabbit

* **Chores**
* Cleaned up unused dependencies and removed some obsolete test/support
files.
* Updated project ignore rules to better match current app structure and
generated files.
* **Bug Fixes**
* No user-facing behavior changed; this release is focused on
maintenance and cleanup.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-30 14:03:40 +02:00
Seid Muhammed affdcb35ff fix(studio): sum numeric-string columns in cumulative SQL charts (#47378)
Fixes: #47377

## What is the current behavior?

Enabling **Cumulative** on a results chart concatenates Y-axis values
instead
of summing them whenever the column is a `bigint`, `numeric`, `money`,
or
`count(*)` aggregate — which Postgres returns as JSON strings. For
per-row
values `10, 20, 30` the chart plots `10, 1020, 102030`.

`getCumulativeResults` ran `(prev[yKey] || 0) + row[yKey]` on raw result
rows.
The Y-axis selector explicitly allows numeric-string columns, so this is
a
common, fully-supported path (e.g. any `count(*) ... group by`).

## What is the new behavior?

Both operands are coerced with `Number()` before the addition, keeping
the
existing `|| 0` fallback for null/undefined/non-numeric values. The
series now
sums correctly: `10, 30, 60`.

The cumulative logic was previously duplicated in `ChartConfig.tsx` and
`QueryBlock.utils.ts` (which is how this bug slipped in twice). It is
now a
single shared, tested helper: `getCumulativeResults` lives in
`QueryBlock.utils.ts`, and `ChartConfig.tsx` imports it instead of
re-declaring
its own copy. The shared helper's `ChartConfig` type import is `import
type` to
avoid a runtime circular dependency, and its signature accepts
`readonly` rows
so both call sites type-check.

## Additional context

- Added regression tests for numeric-string inputs and for
null/undefined/non-numeric fallback to `0`. The existing tests only
covered
literal `number` inputs, never the string form Postgres actually
returns.
- Verified the new tests fail against the old code (`y: '010'`,
`'05undefined'`)
and pass with the fix. Full `QueryBlock.utils.test.ts` suite: 18
passing.

No migrations, no API changes, no infra changes.


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

## Summary by CodeRabbit

* **Bug Fixes**
* Fixed cumulative chart calculations so numeric values are always added
correctly, even when results arrive as strings.
* Improved handling of empty or non-numeric values in cumulative totals
so they are treated as zero instead of breaking the sum.

* **Tests**
* Added coverage for cumulative result calculations with numeric strings
and missing values.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-29 14:53:24 +00:00
Gildas Garcia c6fc456910 chore: cleanup duplicate exports studio (#47387)
## Problem

Knip reports many duplicate exports (both named and default). Besides,
we're moving away from default exports and even have an eslint rule to
enforce it on new code.

## Solution

- Cleanup those exports
- Update imports when necessary

No functional changes. If it builds, it's fine
2026-06-29 15:46:16 +02:00
Jordi Enric 2aa1b52234 feat(studio): add feature to rewrite queries DEBUG-145 (#47266)
## Problem

Moving the Logs Explorer to ClickHouse means users' saved BigQuery
queries no longer run.
<img width="2430" height="1010" alt="CleanShot 2026-06-29 at 11 36
04@2x"
src="https://github.com/user-attachments/assets/ae0ab155-7d3d-4ae9-81c3-22bf3a88cf8c"
/>

## Fix

Rewrite the query with AI instead of a SQL transpiler. AI handles the
long tail of nested fields and dialect differences far better than a
rule-based rewriter, and it needs no extra runtime dependency.

- `rewriteLogsSqlWithAI` posts the current query to
`/api/ai/code/complete` with `dialect: 'clickhouse'`. The endpoint skips
the Postgres schema and best-practices for that dialect and uses
logs-specific instructions and model so the output is ClickHouse logs
SQL (FROM `logs` + `source` filter, no `unnest` joins, nested fields
read from `log_attributes['...']`).
- The query's `source` is detected and its real `log_attributes` keys
are fetched and passed to the model, so it maps to exact paths instead
of guessing.
- The rewrite runs in the background and is proposed as a side-by-side
accept/discard diff in the editor. The AI Assistant panel is not opened.
- Entry points: a banner shown only for legacy-looking queries
(dismissal persisted), and a "Fix Query" button next to Field Reference.
- The Field Reference drawers discover `log_attributes` keys from real
data so the listed fields match what the source actually emits.

## Dependencies

Built on top of #47265 (Logs Explorer -> OTEL endpoint) — that is the
base branch of this PR. Merge #47265 first. Behind `otelLegacyLogs` (off
by default).

Part of DEBUG-145 (split from #47087).

## How to test

- Open the Logs Explorer with a BigQuery logs query (the templates have
some), click "Fix Query", and confirm the diff shows valid ClickHouse
SQL. Accept it and confirm the applied query runs.

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

* **New Features**
* Added an OTEL legacy logs workflow (behind a feature flag) with an
interactive banner and a “Fix Query” ClickHouse rewrite action,
including an accept/discard diff review overlay.
* Introduced OTEL-aware field reference rendering with dynamic discovery
of `log_attributes` keys and updated OTEL source insertion behavior.
* Enabled dialect-aware SQL completion for ClickHouse logs, using
logs-specific instructions and output constraints.
* **Bug Fixes**
* Improved rewrite flow validation and handling, including log source
detection and cleanup of AI-generated SQL formatting.
* **Tests**
* Added Vitest coverage for rewrite prompt generation,
detection/classification utilities, SQL fence stripping, OTEL field
mapping, and OTEL log attribute key discovery.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-06-29 14:31:18 +02:00
Danny White 032bd09b0c feat(studio): use theme-aware OAuth requester logos (#47138)
## What kind of change does this PR introduce?

Bug fix. 

- Follow-up work to FE-3640
- Contributes to DEPR-604

## What is the current behavior?

Known dynamic OAuth requesters on `/dashboard/authorize` relied on
OAuth-specific hard-coded icon assets that were dark-mode only.

Cursor did not have separate light/dark assets in the shared MCP icon
registry, Perplexity only had a light tile asset with baked-in padding,
and OpenAI used the older blossom mark.

## What is the new behavior?

Known OAuth requester logos now resolve through the shared MCP icon
registry while preserving the existing `SupabaseLogo` treatment for
paired authorisation screens.

Cursor uses transparent SVG light/dark variants, Perplexity has cropped
transparent SVG light/dark variants, and OpenAI/ChatGPT uses the newer
monoblossom SVG in black/white variants. Claude remains static until a
suitable variant is available.

Unknown requester icons still render from the provided URL and fall back
to the requester initial if the image fails.

| Before | After |
| --- | --- |
| <img width="828" height="636" alt="Authorize OpenAI
Supabase-E2A05664-589F-458F-8452-9CEE008D558A"
src="https://github.com/user-attachments/assets/140021b1-ff05-4092-98ef-2eae94ff2ddb"
/> | <img width="828" height="636" alt="Authorize OpenAI
Supabase-EC7E00BD-439A-45D1-8E55-240B227C6897"
src="https://github.com/user-attachments/assets/93e603f2-5cbf-4219-b692-d36ac98e8d2a"
/> |
| <img width="828" height="636" alt="66 Authorize OpenAI
Supabase-CB31FF76-86DB-43A6-A426-46B99B8B1B91"
src="https://github.com/user-attachments/assets/b261416e-39b8-40b3-87fd-461653aa0334"
/> | <img width="828" height="636" alt="Authorize OpenAI
Supabase-EAFCF2F2-5CEA-4FE6-8AC0-819F764B414E"
src="https://github.com/user-attachments/assets/35ad7525-0fa9-4438-b117-4e70b78eb719"
/> |

## To test

1. Navigate to `http://localhost:8082/authorize?auth_id=test-auth-id`
2. Open DevTools → Network
3. Find `/platform/oauth/authorizations/test-auth-id`
4. Right-click → Override content
5. Replace the response body with:
	```js
	{
	  "name": "Perplexity",
	  "website": "https://perplexity.ai",
	  "icon": null,
	  "domain": "perplexity.ai",
	  "scopes": [],
	  "expires_at": "2026-12-31T23:59:59.000Z",
	  "approved_at": null,
	  "registration_type": "dynamic"
	}
	```
6. Then change "name" to Cursor, Claude, ChatGPT, or OpenAI and refresh
to inspect each logo

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

* **New Features**
* OAuth app requester logos now dynamically adapt to light and dark
themes, with improved logo selection for known requesters.
  * Cursor now uses a distinct dark icon variant.
  * Added Perplexity client icon support.

* **Bug Fixes**
* Improved logo rendering robustness: if a logo can’t be loaded, the UI
falls back to the requester’s initial.

* **Tests**
* Expanded coverage for theme-aware logo rendering and icon variant
handling, including unknown-icon and fallback scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-24 09:30:48 -06:00
Joshen Lim fd0f2dd459 Scope last visited organization local storage to profile (#47071)
## Context

If a user switches account without an explicit log out via the
dashboard, landing back on `/org` will redirect users to the last
visited organization as stored in local storage, in which it can result
in the following state if the last visited organization does not exist
in the current account
<img width="2538" height="1060" alt="image"
src="https://github.com/user-attachments/assets/270e482a-3515-48ef-898b-87e76fce80d6"
/>

## Changes involved
Am opting to scope the last visited organization to the user profile
instead - this would be a bit more cleaner than trying to actively clear
the last visited org slug from local storage with implicit account
changes as there's no deterministic way to track that (afaik) from FE
side of things

## To test
Can reproduce the problem as such
- Ensure that you have 2 accounts to log in with, and one account has an
org that the other is not a part of
- For the organization that has the "extra" org, ensure that you click
into it so that the last visited org slug is saved in local storage
- Mimic changing accounts by visiting
`/auth/v1/authorize?provider=github` (using the domain for the env that
you're testing on - e.g localhost:8000 for local, or green for staging
preview)

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

* **New Features**
* Unified “last visited organization” handling across the Studio UI with
a shared hook, improving consistency for home/dashboard return,
cancel/back navigation, and account routing.

* **Bug Fixes**
* Updated redirects to only route to an organization when a valid
last-visited value is available; otherwise users go to the general
organizations page.
* Kept MFA enrollment and factor delete/leave flows aligned to the
unified last-visited organization value.

* **Tests**
* Updated onboarding and layout tests to match the new last-visited
organization storage key format and hook/query success behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-18 17:42:18 +08:00
Gildas Garcia 96d43099bb chore: refactor Button API so that it can be used a standard button (#46880)
## Problem

Our `<Button>` component breaks the default `button` contract by
redefining the `type` prop to set its variant (`primary`, `default`,
etc) instead of the button type (`submit`, `button`, etc).
This is confusing and forces to write more code when using it with
shadcn components that expect/inject the standard button props.

## Solution

- rename the `type` prop to `variant`
- rename the `htmlType` prop to `type`
- propagate the changes where necessary
- format code

## How to test

As this is just prop renaming, if it builds it's ok

---------

Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
2026-06-16 23:59:58 +02:00
Danny White 43c2229f1e fix(studio): align /authorize invalid and edge states with interstitial UI (#46960)
## What kind of change does this PR introduce?

Bug fix / UI polish

## What is the current behavior?

Visiting `/authorize` without an `auth_id` renders a bare `Card` outside
the shared Connect interstitial — no centered layout, no Supabase logo,
inconsistent with every other `/authorize` state (loading, error, form,
approved).

Two edge cases also produce poor UX: a blank flash while
`router.isReady` is false, and a silent empty page when the
authorization query succeeds but returns no requester.

## What is the new behavior?

- **Missing `auth_id`**: `ApiAuthorizationInvalidScreen` now uses
`InterstitialLayout` with `SupabaseLogo`, a user-facing title ("Missing
authorization link"), warning admonition, and "Back to dashboard" —
matching the error screen and CLI missing-params pattern.
- **Router not ready**: `authorize.tsx` shows
`ApiAuthorizationLoadingScreen` instead of `null`.
- **Empty requester**: `ApiAuthorization.Valid.tsx` renders
`ApiAuthorizationErrorScreen` instead of returning `null`.

Tests updated in `ApiAuthorization.test.tsx`; added `authorize.test.tsx`
for router-not-ready loading.

| Before | After |
| --- | --- |
| <img width="524" height="455" alt="Authorize API Access
Supabase-DCB404EC-7D65-4DD1-A6E0-B720DC765DA7"
src="https://github.com/user-attachments/assets/8d2b68fc-e008-4145-aa74-3154a883083c"
/> | <img width="524" height="455" alt="Authorize API Access
Supabase-6B642066-D0BE-4EDC-A186-A0290B4B5634"
src="https://github.com/user-attachments/assets/b04bee93-6b23-411f-8e36-9a0fff8a975d"
/> |

## To test

Please do a visual check on `http://localhost:8082/authorize` (no
`auth_id` or other parameters).

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

* **Bug Fixes**
* Improved the UI and copy shown when the authorization link is missing.
* Updated behavior to show an explicit error screen when authorization
requester data is unavailable.
* **New Features**
* Added a loading state for the authorization page while router
parameters are initializing.
* **Tests**
* Updated component expectations for the missing authorization and
“unable to load” scenarios.
* Added a page test to verify the loading message when the router is not
ready.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 16:19:57 +08:00
Francesco Sansalvadore c713135384 fix(studio): wrappers install state + one-click install (#46697)
- fix install badge state in wrappers detail page
- add "Install" button in top action bar
  - "Install wrapper" if required extensions _aren't_ installed
  - "Add new wrapper" if required extensions _are_ installed
- make wrappers "one-click install" by 
  - showing the required extensions in the CreateWrappersSheet 
  - and automatically installing them on wrapper submission

Only available behind `isMarketplaceEnabled` flag at the moment.

https://github.com/user-attachments/assets/38f5549d-938e-4e2f-a723-53b9a028e9dc
2026-06-09 12:34:20 +02:00
Ivan Vasilov 40c947ebfb fix: Handle non existant columns when sorting tables (#46741)
When a user has sorted by some column in the Table Editor and the column
is deleted, the sort data is wrong so it causes issues. In the general
view in the Table Editor, the error is handled by removing the sort key
when a specific error is detected but it can still happen in
ForeignRowSelector.

To test:
1. Have 2 tables with references between them.
2. In the `sessionStorage`, under the `supabase_grid-<ref>` key, update
the sort key to a non-existant column for a table.
3. Try to open the `ForeignRowSelector` for that table by clicking on a
cell in the referencing column.

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

* **Bug Fixes**
* Sorting now validates referenced columns and ignores invalid sort
entries.
* Local sort restoration and UI sort application now derive sorts from
the original table context for more consistent behavior across editors
and popovers.
* Prefetch logic uses the resolved table context when falling back to
saved sorts.

* **Tests**
* Added cases for malformed and out-of-scope sort parameters to prevent
regressions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-09 12:30:13 +02:00
Danny White 35df570342 feat(studio): move /authorize to connect interstitial (#46359)
> [!CAUTION]
> The `do-not-merge` label has been applied because this contains mocks
for easier review and testing. I'll remove those mocks before merging.

## What kind of change does this PR introduce?

Feature. Part of the shared Connect UI (interstitial) rollout. Previous
slices: #46058, #45909, #45862.

## What is the current behavior?

The `/authorize` MCP/OAuth consent screen uses the old `Card`/`Alert`
layout.

## What is the new behavior?

- Wraps all `/authorize` states in `InterstitialLayout` (the shared
full-screen centered card used across Connect flows)
- Shows a quiet footnote below the Cancel button ("Authorizing will
redirect you to \<url\>") for non-localhost redirect URIs, so users can
verify the destination before approving. No extra friction for localhost
flows (local MCP servers)

| Before | After |
| --- | --- |
| <img width="692" height="997" alt="Authorize API access
Supabase-F6C3747A-5077-43D8-A509-3E16B1DDC168"
src="https://github.com/user-attachments/assets/e86dde34-94cb-48ef-b026-66aac9122df6"
/> | <img width="692" height="997" alt="Authorize API Access
Supabase-FE6FD8B3-1159-4EA5-94D7-EA5CEA7A25F3"
src="https://github.com/user-attachments/assets/c1a94a44-51d9-40d8-8046-f3104a27b929"
/> |
| <img width="692" height="997" alt="Authorize API access
Supabase-86742351-3521-4B62-AF87-403CB7E7F4F5"
src="https://github.com/user-attachments/assets/41cff7af-b9e4-4a20-a979-7148b4220265"
/> | <img width="692" height="997" alt="Authorize Cursor
Supabase-B665B4A4-600F-462B-8C97-84B171EC3103"
src="https://github.com/user-attachments/assets/804286f2-ce51-45ab-bb3f-315f8ac62445"
/> |
| <img width="692" height="997" alt="Authorize API access
Supabase-C73DC3D0-8646-4E6E-A259-3E84AE46DAF2"
src="https://github.com/user-attachments/assets/8f285edb-438f-4262-9faa-f1133c679ed4"
/> | <img width="692" height="997" alt="Authorize Cursor
Supabase-FEA86625-27D5-4DB5-B4D4-1A2CB804E56E"
src="https://github.com/user-attachments/assets/b54f2ceb-e1cf-4c7e-be3f-8e1b0942e9a4"
/> |
| <img width="692" height="997" alt="Authorize API access
Supabase-48E0C7CB-DDDD-4305-B821-F3BEB52C4A4E"
src="https://github.com/user-attachments/assets/7d123c57-e05d-408c-8df9-d747a3afd714"
/> | <img width="692" height="997" alt="Authorize Cursor
Supabase-CE8F9905-FAE0-4C06-B77A-9F269B2100FE"
src="https://github.com/user-attachments/assets/9f403b83-5de3-43c8-a592-c3022e041243"
/> |
| <img width="692" height="997" alt="Authorize API access
Supabase-E37D2CD5-476F-4F49-A5FB-631B265025DC"
src="https://github.com/user-attachments/assets/3d235315-d7c0-4279-b23f-e8b595888511"
/> | <img width="692" height="997" alt="Authorize Cursor
Supabase-DF078AEB-BB78-4647-9FA2-5D5403CCA5D6"
src="https://github.com/user-attachments/assets/53d51718-8707-4b97-9cbe-8e523f4ce0e0"
/> |
| <img width="692" height="997" alt="Authorize API access
Supabase-D6F6817F-D8DD-4D55-85BB-A15100814AAB"
src="https://github.com/user-attachments/assets/c80c5579-772a-4dfe-a247-b0b9772b9690"
/> | <img width="692" height="997" alt="Authorize Cursor
Supabase-E457B580-9786-43AD-9CF9-FE4F5BB8E785"
src="https://github.com/user-attachments/assets/30c47b05-edf5-4380-a2f1-aedb99482540"
/> |
| <img width="692" height="997" alt="Authorize API access
Supabase-4F3D6AA4-E2E3-4526-B391-49B6E0861911"
src="https://github.com/user-attachments/assets/ffbe5b65-6eef-49d7-95f1-c29072c320b8"
/> | <img width="692" height="997" alt="Authorize Cursor
Supabase-CA9FFCC9-4CA2-4718-AD49-B02D86C6EF6A"
src="https://github.com/user-attachments/assets/8fd7ff39-19f5-4414-af13-3821290735b2"
/> |
| <img width="692" height="997" alt="Authorize API access
Supabase-E507B7A5-9AD0-4F17-8743-63A7B47D171A"
src="https://github.com/user-attachments/assets/1639b5cc-69c4-4a43-b049-6f989e2cdbb1"
/> | <img width="692" height="997" alt="Authorize Cursor
Supabase-9844BB27-2429-4BA6-BD36-1AB54099F44F"
src="https://github.com/user-attachments/assets/a94b88e2-9c2f-4941-840a-5182342bb335"
/> |
| <img width="692" height="997" alt="Authorize API access
Supabase-27684173-9DBB-4F6E-9F7F-87EFD4E10A5F"
src="https://github.com/user-attachments/assets/91794c96-8a81-4d83-9c97-01d134639676"
/> | <img width="692" height="997" alt="Authorize Cursor
Supabase-04E31F7B-D098-4814-A394-01CE3D3E5A51"
src="https://github.com/user-attachments/assets/ba0284a3-363c-4aa5-9e4a-c378aed9c42c"
/> |
| <img width="692" height="997" alt="Authorize API access
Supabase-207CBC69-4957-499C-92E8-163F2B34C8AD"
src="https://github.com/user-attachments/assets/1bafedd2-bba8-473c-ba57-637289f1c940"
/> | <img width="692" height="997" alt="Authorize API Access
Supabase-C1627071-4AE2-4012-8F7C-4E6D883618A3"
src="https://github.com/user-attachments/assets/a6fc6125-3c1e-4b8c-821a-c3c9f32f3cc0"
/> |

## To test

A mock toolbar is included for easy local testing. Navigate to
`/authorize?mock=loading` and then switch between the following
variants:

| State | What to check |
| --- | --- |
| `loading` | Shimmer skeleton inside the card |
| `ready` | Regular waiting state |
| `approving` | Authorize button shows spinner, both buttons disabled |
| `approved` | Success admonition: "Authorization approved" |
| `expired` | Warning admonition: "Authorization request expired", no
action buttons |
| `organizations-loading` | Org selector shimmer, no action buttons |
| `organizations-error` | "Unable to load organizations" admonition, no
action buttons |
| `empty` | "No organizations found" admonition, no action buttons |
| `not-member` | "Organization unavailable" admonition, no action
buttons |
| `error` | "Unable to load authorization" error screen |

Then please test the `organization_slug` prefill:
`/authorize?mock=ready&organization_slug=<your-org-name-here>`. That org
selector should be pre-selected and locked.

To test against a real OAuth app, use a registered app on
`supabase.green` — the mock states cover all edge cases but a live
round-trip confirms the approve/decline API calls.

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

## Summary by CodeRabbit

## Release Notes

* **New Features**
* Added mock preview functionality for testing API authorization and
Connect flows
* Introduced collapsible, grouped permissions view for OAuth
authorization requests

* **Refactor**
* Redesigned API authorization screens with improved layout and
messaging
  * Restructured permissions display for better organization and clarity

* **Bug Fixes**
  * Fixed inline link underline decoration color

* **Tests**
  * Updated authorization flow test assertions to match new UI behavior

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46359?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-06-08 10:51:04 -06:00
Ali Waseem a776b54863 fix(studio): show role permission descriptions in edit access drawer (#46627)
Mirrors the recent invite drawer change (#46515) on the edit access
drawer. Each role option now describes its permissions via the shared
\`ROLE_DESCRIPTIONS\` map instead of showing just the role name.

Closes FE-3524.

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

* **New Features**
* Role selection in Team Settings now shows full, role-specific
permission descriptions and appends any disabled-reason details for
clarity.

* **Tests**
* Added integration tests covering the role panel UI: role listing,
selected role label, documentation link, role-specific descriptions, and
an admin-safety notice; includes test environment compatibility stubs
for animations and routing.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-04 07:41:39 -06:00
Andrey A. b28f91741f fix(self-hosted): reveal and copy secret api key in project settings (#46592) 2026-06-03 09:03:23 +02:00
Andrey A. 0c8b71de64 feat(self-hosted): update project home for self-hosted and cli (#46544) 2026-06-02 15:38:28 +02:00
Andrey A. ca9b02b5ac feat(self-hosted): add minimal project settings (#46554) 2026-06-02 15:37:42 +02:00
Ali Waseem 3e7d8d0f68 chore: Update styling and more descriptive information for roles when inviting members (#46515)
## 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?
- Better role selector thats actually more helpful with descriptions
- More tests with MSW
- Refactored to a side panel due to more information being presented in
the modal

## How to test
- Try inviting members to an org
- Make sure members can still be revoked!

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

## Summary by CodeRabbit

* **New Features**
* Team member invitation interface redesigned from modal dialog to side
panel.
* Role selection now displays as an interactive radio list with
descriptions for each role.
* Improved form layout with horizontal organization for better
usability.

* **Tests**
* Added integration and unit tests for team member invitation
functionality.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-02 07:34:22 -06:00
Joshen Lim 1d203f6c93 feat: Support CLI for Vector buckets (#46381)
## Context

> [!IMPORTANT]  
> Will open up for review once CLI PR is merged and deployed so that
it's easier to test

Related PR: https://github.com/supabase/cli/pull/5230

Adding support for vector buckets for local CLI - will need to be tested
locally via `pnpm run dev:studio-local`

## To test
There's a bit of testing instructions in the linear ticket
[here](https://linear.app/supabase/issue/FE-3474/show-vector-buckets-in-local-admin-studio)
as it involves using a branch of CLI - otherwise do reach out to
Fabrizio if any help might be needed, but generally:

### Local CLI
You might need to manually set `isCli` to `true` in `StorageMenuV2` if
the "Vectors" nav item isn't showing up on the storage UI given we're
testing via `pnpm run dev:studio-local`
- [x] Can create bucket
- [x] Can delete bucket
- [x] Can create indexes
- [x] Can insert data into indexes (via FDW)
- [x] Can delete indexes

Known issues (that aren't directly solvable from FE end)
Reach out to Fabrizio for context as we were both investigating this
- PG database needs to be on 17.6 (otherwise there's no S3 vectors FDW)
- Storage version needs to be on 1.59.0

### Self-hosted (This might be tricky to actually test, but just ensure
that the code satisfies this)
- [x] Cannot see vector buckets

### Hosted
- [x] Everything works status quo

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

* **New Features**
* Vector bucket management UI and platform APIs (create/list/delete
buckets & indexes)
* Local S3 credentials endpoint and client-side hook for self‑hosted/CLI
use

* **Bug Fixes**
* Improved S3 vector setup notifications and clearer error guidance for
manual installation

* **Refactor**
* Deployment-mode gating: platform vs CLI/self‑hosted now controls
feature visibility and page behavior

* **Tests**
* Added suites covering deployment-mode gates and vector bucket
error/usage scenarios

* **Chores**
  * Build env updated to expose local S3 credential vars

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46381?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

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

---------

Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-06-01 08:02:22 -06:00
Ali Waseem 6236ee9ef9 POC: bring back MSW to remove the pattern of vi.mock (#46439)
## 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?

Right now our tests for API mocking is using vi.mock and mocking that
query or fetch handler. This is not the right approach IMO, 2 years ago
@jordienr added MSW with some very powerful helpers. The idea is to move
component test that rely on API using MSW within ViteTest. Principles
are simple:
- Mock API responses
- Mount your component that uses API responses
- Tests and assert on UI 
- Added Skill for Clanker

This pattern is 100 times better than what we have

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

* **Tests**
* Expanded and strengthened test suites for secrets, org lookup, support
flows, OAuth auth, and onboarding; mocks now use contract-backed
responses for more realistic coverage.

* **Documentation**
* Added a comprehensive guide describing a standardized pattern for
component tests that mock network requests.

* **Chores**
* Improved test helpers, typing for API mocks, and test runner
configuration for more reliable and maintainable tests.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46439?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

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

---------

Co-authored-by: Alaister Young <alaister@users.noreply.github.com>
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-05-28 12:58:50 +00:00
Andrey A. c1276c8e9a feat(self-hosted): add new API keys to self-hosted Studio and MCP server (#46173) 2026-05-22 12:11:00 +02:00
Danny White 51ecfbb86d studio(chore): reuse org details fields in AWS marketplace flow (#46087)
## What kind of change does this PR introduce?

Refactor. Resolves FE-3216.

## What is the current behavior?

The AWS Marketplace create-organisation dialog owns its own copy of the
organisation name, type, and company-size form fields. It’s duplicative
and has drifted from the normal `/new` organisation form, making the AWS
flow harder to keep aligned.

This is stacked on #46058.

## What is the new behavior?

- Extracts the shared organisation details schema, defaults, option
constants, and fields from the normal `NewOrgForm`
- Reuses those shared fields in both the full organisation creation form
and the AWS Marketplace create-and-link dialog
- Keeps the AWS Marketplace flow anchored in the onboarding interstitial
rather than routing through `/new`
- Keeps the AWS-specific buyer ID, AWS-managed organisation endpoint,
create-and-link success state, and modal dismissal behaviour

| Before | After |
| --- | --- |
| <img width="1024" height="759" alt="Link AWS Marketplace
Supabase-3742FEDF-53BD-4E80-926D-498B2EA94773"
src="https://github.com/user-attachments/assets/617ee422-1cf0-4858-801b-a4ee5ee402c9"
/> | <img width="1024" height="759" alt="Link AWS Marketplace
Supabase-0FEE2292-CB9F-43AA-B131-B6A549890970"
src="https://github.com/user-attachments/assets/ff017468-f8ac-469a-bb17-eea07842306f"
/> |

## Additional context

The shared field extraction is intentionally limited to organisation
details. Billing, plan selection, spend cap, Stripe, captcha, and the
`/new/[slug]` redirect behaviour stay owned by `NewOrgForm`; AWS
Marketplace keeps its separate create-and-link container because AWS
owns the billing contract.

## Validation

- `pnpm --filter studio exec vitest --run
tests/pages/aws-marketplace-onboarding.test.tsx`
- `pnpm --filter studio lint:ratchet --rule no-restricted-exports`
- `git diff --check`

Full Studio typecheck was also run, but it currently fails on existing
unrelated repo-wide React/implicit-any errors outside this diff.


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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved AWS Marketplace organization creation dialog to prevent
accidental closure while the creation process is in progress.

* **Improvements**
* Standardized organization details form handling across different
organization creation flows for improved consistency and user
experience.

* **Tests**
* Added comprehensive test coverage for the AWS Marketplace organization
creation workflow, including form submission, validation, and state
transitions.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46087?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-22 14:10:07 +10:00
Danny White a8720dee1f feat(studio): move AWS Marketplace to connect interstitial (#46058)
## What kind of change does this PR introduce?

Feature. Resolves DEPR-556.

## What is the current behavior?

AWS Marketplace onboarding uses a separate scaffold and AWS-specific
organization selection UI, so it does not match the newer shared connect
interstitial pattern used by Redeem Credits.

## What is the new behavior?

- Moves `/aws-marketplace-onboarding` onto the shared connect
interstitial shell with AWS and Supabase branding
- Reuses the shared organization selector behaviour from Redeem Credits,
including last-visited organization promotion, selected organization
promotion, the create-organization card, and compact overflow disclosure
- Keeps the existing AWS data path for buyer eligibility, onboarding
info, organization linking, AWS-managed organization creation, and
success/error/ineligible states
- Removes the now-unused legacy AWS Marketplace layout/scaffold
components
- Removes the temporary reviewer mocks from the branch before merge

## Additional context

This PR preserves the current AWS-managed organization creation modal so
the AWS flow keeps working while adopting the shared connect sheet.
FE-3216 should move that creation path into the general organization
form later, likely replacing the AWS-specific modal with a preconfigured
`/new` flow that can still return to AWS Marketplace onboarding and link
automatically.

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-05-22 13:59:05 +10:00
Kanishk Dudeja ba77d15d41 chore(billing): remove billing address modal and tax id banner (#46210)
This PR removes the billing address modal and tax id banner code
completely since we no longer need it.

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

* **Removed Features**
  * Billing address update modal is no longer accessible.
  * Tax ID banner has been removed from the app UI.
  * Placeholder banner block disabled.

* **Tests**
  * Automated tests for the billing address modal were removed.

* **Chores**
  * Associated local-storage key for the tax ID banner was removed.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46210?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-21 18:30:18 +05:30
Danny White df77fc9011 fix(cli): resolve infinite loader on device code screen (#46137)
## Summary

Follow-up fix for
[#46120](https://github.com/supabase/supabase/pull/46120).

PR #46120 correctly guarded against duplicate `POST /platform/cli/login`
calls using a `useRef`, but left `navigate` in the `useEffect` deps
array. Because the parent passes an inline lambda, `navigate` gets a new
reference on every render. This causes React to:

1. Run the effect cleanup mid-flight (setting `isActive = false`)
2. Re-run the effect, which hits the session-id ref guard and returns
early

When step 1 happens while the POST is in-flight, the response arrives
with `isActive === false`, silently drops the `navigate(...)` call, and
leaves status stuck at `{ _tag: 'loading' }` — the infinite spinner
reported in Slack.

## Fix

Store `navigate` in a ref (updated each render) and call
`navigateRef.current(...)` inside `createSession`. Remove `navigate`
from the deps array so parent re-renders never trigger a cleanup while
the POST is in-flight.

```ts
const navigateRef = useRef(navigate)
navigateRef.current = navigate   // always up to date, never a dep
```

All 7 existing CLI login unit tests pass, including the "POSTs exactly
once even when parent re-renders" regression test.

## Test plan

- [ ] Run `pnpm test:studio tests/pages/cli-login.test.tsx` — all 7
tests pass
- [ ] Browser: `supabase login` flow completes and shows the
verification code screen without hanging on the loader
- [ ] DevTools Network: exactly one `POST /platform/cli/login` fires per
login attempt

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

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

* **Bug Fixes**
* Improved CLI login navigation reliability when parent components
update during session creation.

* **Style**
  * Adjusted loading indicator styling on the CLI login screen.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46137?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com>
2026-05-20 12:26:02 +02:00
Andrew Valleteau da3b0cb3ec fix(cli): login creating duplicate tokens on re-renders (#46120)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Bug fix

## What is the current behavior?

The CLI login page was firing `POST /platform/cli/login` multiple times
per page load due to an unstable `navigate` reference in the parent
component re-triggering the effect. This caused several duplicate
personal access tokens to be created for each browser sign-in attempt
(regression CLI-1491).

Additionally, error messages from non-Error rejection shapes (like those
from openapi-fetch) were being replaced with a generic "Unknown error"
message instead of surfacing the actual platform error.

## What is the new behavior?

1. **Prevents duplicate API calls**: Added a `useRef` guard
(`startedForSessionIdRef`) to ensure `createCliLoginSession` is only
called once per `sessionId`, even if the parent component re-renders
with a new `navigate` reference.

2. **Improved error handling**: Created a `getErrorMessage()` utility
that properly extracts error messages from both Error instances and
plain objects (e.g., `{ message: string, statusCode: number }`),
allowing platform error messages to surface instead of generic
fallbacks.

3. **Added comprehensive test coverage**:
- E2E test verifying the POST fires exactly once per page load with
realistic network latency
   - E2E test confirming platform error messages are displayed correctly
   - Unit test for non-Error rejection shapes
- Unit test verifying the effect doesn't re-trigger on parent re-renders

## Additional context

The fix addresses the root cause by:
- Using a ref to track which `sessionId` has already been processed,
preventing re-execution when deps change
- Extracting error message handling into a reusable utility that handles
both Error instances and plain objects
- Adding tests that specifically check for the regression (multiple POST
calls and error message display)

The E2E test includes a 400ms delay in the mock response to simulate
real-world conditions where the original bug only surfaced after React
committed multiple re-renders.

Closes: CLI-1491

https://claude.ai/code/session_01GAujw33MTRBRYSnS8cxcEa

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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved CLI login error handling to display platform-specific error
messages instead of generic fallback text.
  * Fixed duplicate login session creation during component rerenders.

* **Tests**
  * Added test coverage for error message display in CLI login.
* Added regression tests for single session creation and platform error
scenarios.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46120?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-20 09:17:22 +02:00
Gildas Garcia 4e86c39ea1 chore: remove <ContextMenu> _Shadcn_ suffix (#45971)
## Problem

The `_Shadcn_` suffix isn't needed anymore on `<ContextMenu_Shadcn_>`
and related components

## Solution

Remove it. No other changes

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

* **Refactor**
* Replaced legacy context-menu component variants with the unified UI
context-menu components across the app for consistent rendering and
imports; behavior and menu content remain unchanged.
* **Tests**
* Updated a test mock to track the unified context-menu component mount
count.
* **Chores**
* Simplified UI package re-exports to expose the canonical context-menu
symbols.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45971)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-15 15:09:25 +02:00
Danny White 205ab69061 feat(studio): move CLI login to connect interstitial (#45814)
## What kind of change does this PR introduce?

Feature / UI refactor

## What is the current behaviour?

The CLI browser login route still uses the older API authorisation
layout and redirects missing or failed sign-in session states to generic
404/500 pages.

## What is the new behaviour?

Moves `/cli/login` onto the shared connect interstitial layout as the
next small stacked slice after the organisation invite work.

This keeps the real CLI login contract intact while updating the
surface:
- creates the CLI login session from `session_id`, `public_key`, and
optional `token_name`
- redirects to the generated `device_code`
- renders missing-parameter and session-creation failures in-card
instead of redirecting away
- keeps the 8-character verification code selectable and copyable as a
single string
- uses a full-width primary `Copy code` action

This also adds the small shared interstitial helpers needed by this
surface and adjusts `CopyButton` so the copied check icon inherits the
primary button colour instead of turning green.

This also removes the CLI version admonition:

> Browser login flow requires Supabase CLI version 1.219.0 and above.

I checked with our stats and the CLI team. The vast majority of users
are on a newer version.

| Before | After |
| --- | --- |
| <img width="1024" height="759" alt="Authorize API access
Supabase-D1E3CF26-BD59-4BB2-B457-B552EE47E3DA"
src="https://github.com/user-attachments/assets/c89b8b13-fa98-41b7-8093-e59d15b2aa9e"
/> | <img width="1024" height="759" alt="Authorize CLI
Supabase-C9977F21-88B8-441B-8A2C-09A9515935B0"
src="https://github.com/user-attachments/assets/ca13b65a-3875-425c-b73b-8f2101c1e406"
/> |
| <img width="1024" height="759"
alt="Supabase-F42FBEAF-F74D-4920-8A51-7C25004F66D5"
src="https://github.com/user-attachments/assets/51adb1e6-a2fb-41fb-b36f-0ae466fe60e2"
/> | <img width="1024" height="759" alt="Authorize CLI
Supabase-8159A1B1-2594-4183-AC35-FEF1EFD4EA37"
src="https://github.com/user-attachments/assets/6f143218-795d-41c9-a8e1-52e529a6b988"
/>
| <img width="1024" height="759"
alt="Supabase-2506E468-9F42-44B9-A5B7-BC4D3777F552"
src="https://github.com/user-attachments/assets/a304fca5-cf26-4ae7-abe9-77cdbc21fba5"
/> | <img width="1024" height="759" alt="Authorize CLI
Supabase-A0EE1239-A345-427C-9CF7-997037A8FC0E"
src="https://github.com/user-attachments/assets/33118777-35f3-49d6-bc1e-30e7124b3677"
/> |
| <img width="1024" height="759" alt="Authorize API access
Supabase-A7B84CA6-D230-4C3E-9227-DE21CE35375C"
src="https://github.com/user-attachments/assets/78eb6296-035a-4201-b254-b97eda44443c"
/> | <img width="1024" height="759" alt="Authorize CLI
Supabase-F55E26B2-609B-449C-9C64-08AA90AE3D1E"
src="https://github.com/user-attachments/assets/ff7b3b4e-729c-4681-844d-2d5d94bfc084"
/> |

## Testing instructions

Use the Vercel preview URL for this PR once it is available. The
examples below use `<preview-origin>` as a placeholder, for example
`https://studio-git-dnywh-feat-cli-login-interstitial-supabase.vercel.app`.

You need to be signed in to Studio to see these states because
`/cli/login` is still behind `withAuth`.

Ready state:
- Open `<preview-origin>/cli/login?device_code=ABCD1234`
- Check the page title is `Authorize CLI | Supabase`
- Check the card title is `Authorize Supabase CLI`
- Check the code fills the width, uses the normal sans font, and can be
selected
- Drag-select the code and copy it; the clipboard should contain
`ABCD1234`, not one character per line
- Click `Copy code`; the button should show the usual copied success
state without a green check icon on the primary button

Missing parameters state:
- Open `<preview-origin>/cli/login`
- Check the card says `Missing sign-in parameters` and names the missing
`session_id` and `public_key` parameters
- Open `<preview-origin>/cli/login?session_id=session-test`
- Check it still stays in-card and names the missing `public_key`
parameter instead of redirecting to `/404`

Creation error state:
- Open
`<preview-origin>/cli/login?session_id=not-real&public_key=not-real&token_name=local-dev`
- Check it stays in-card with `Unable to create CLI sign-in` instead of
redirecting to `/500`
- The exact error detail can vary by environment; the important bit is
that the failure is shown inside the interstitial card

Loading state:
- This is transient because there are no production mocks in this slice
- To inspect it manually, throttle the browser network before opening a
session-creation URL such as
`<preview-origin>/cli/login?session_id=not-real&public_key=not-real`

Real CLI flow:
- Run the browser login flow from Supabase CLI as usual
- When the CLI opens a Studio URL, keep the path and query string but
replace the origin with the PR preview origin
- The page should create the login session and then route to
`/cli/login?device_code=<8 character code>`
- Enter that 8-character code back in the CLI prompt


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

* **New Features**
* Redesigned CLI login flow with clearer state-driven screens and
improved verification UI.
* Added a small paired-logo component for centered logo pairs with a
connector icon.

* **Improvements**
* Copy button behavior and styling refined for consistent visual
feedback across variants.

* **Tests**
* New unit tests covering copy-button behavior and multiple CLI login UI
flows.

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45814)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-13 11:14:38 +10:00
Danny White 9660b0075c refine organisation invite state helpers (#45813)
## What kind of change does this PR introduce?

Code cleanup. Follow-up to #45774.

## What is the current behavior?

The organisation invite interstitial derives invite states, titles, and
descriptions from nested conditional logic in the component. That makes
the component harder to scan and pushes too much state coverage into
render tests.

## What is the new behavior?

See #45774 for screenshots of the general UI before-and-after (which
this one builds upon). That PR also contains testing instructions.

Extracts the invite status and content decisions into small pure
helpers, then covers those helpers with focused unit tests.

The component keeps the user-facing render and interaction coverage,
including the invalid lookup regression where a 404 should render the
invalid invite state instead of raw backend copy.


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

## Summary by CodeRabbit

* **Refactor**
* Improved organization invite flow with enhanced error state handling
for expired, invalid, and wrong-account scenarios.
* Better consistency in error messages and user guidance throughout the
invite process.

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45813)

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-13 10:40:41 +10:00
Danny White 791fc74412 feat(studio): shared connect layout for organisation invites (#45774)
## What kind of change does this PR introduce?

Feature. Part of DEPR-279.

## What is the current behavior?

The organization invite page has its own bespoke centered card and
page-level Supabase logo.

## What is the new behavior?

Introduces a minimal shared interstitial layout and migrates `/join`
onto it as the first small connect-surface slice. The invite API and
accept-invite mutation paths are unchanged.

| Before | After |
| --- | --- |
| <img width="1024" height="794"
alt="Supabase-F2325C57-D5DE-445D-8083-12EF8A1EE0CA"
src="https://github.com/user-attachments/assets/b23dcc7a-c649-4b59-9393-9232d74f0c6b"
/> | <img width="1024" height="794" alt="Join Organization
Supabase-66CDA329-0531-4B12-AC32-A7E21931F876"
src="https://github.com/user-attachments/assets/454917ce-1a96-4e50-b003-6c16a541b39a"
/> |
| <img width="1060" height="822" alt="CleanShot 2026-03-13 at 11 04
43@2x-2616AECB-8203-4439-A1CD-45AB18FC4CA8
1-584A0600-CCE0-4F16-9111-9BEB94BE85EC"
src="https://github.com/user-attachments/assets/871c7dcb-120e-40cd-afc8-2cec95e4b7ae"
/> | <img width="1024" height="794" alt="Join Organization
Supabase-26AD978E-4CF9-4600-9885-082084349E94"
src="https://github.com/user-attachments/assets/ee9bfaff-dde4-4366-abae-77dc8a95c4ef"
/> |
| <img width="1024" height="794"
alt="Supabase-4993D74C-D62B-43B7-9681-826BE1591AC4"
src="https://github.com/user-attachments/assets/1c411ae0-90e7-481d-a4cc-3eac26267291"
/> | <img width="1024" height="794" alt="Join Organization
Supabase-C84D4E4C-24F5-463D-B1D6-D11D3256596F"
src="https://github.com/user-attachments/assets/688387a4-3c49-41db-b89c-7c5531e91aed"
/> |
| <img width="1024" height="794"
alt="Supabase-D9BD2601-98A4-489D-A51D-CEB73F51FA6F"
src="https://github.com/user-attachments/assets/6d1da65f-d655-4047-9f6a-db65f8c0a729"
/> | <img width="1024" height="794" alt="Join Organization
Supabase-50065F40-179A-4BD6-8F1D-6106FFD8A15C"
src="https://github.com/user-attachments/assets/e61809f9-dcec-4e51-ba94-91b04010ec50"
/> |

## Testing notes

Staging invite emails are generated with the fixed staging dashboard
origin, for example:

```text
https://supabase.green/dashboard/join?token=...&slug=...
```

To test this PR preview with a real invite token, keep the path and
query string from the email but replace the origin with the Vercel
preview origin, for example:

```text
https://studio-staging-git-dnywh-featconnect-interstitial-join-supabase.vercel.app/dashboard/join?token=...&slug=...
```

### Manual state checks

- **Signed out:** open the swapped invite URL in an incognito window or
a browser signed out of Studio. Expected: `View invitation`,
sign-in/create-account actions, and no loading skeleton hang.
- **Wrong account:** sign in to the PR preview as an account that is not
the invite recipient, then open the swapped invite URL. Expected: `Wrong
account`, warning callout, and `Sign out`.
- **Happy path:** sign in as the invited email address, then open the
swapped invite URL. Expected: `Join {Organization}`, signed-in account
row, `Accept invite`, and `Decline`. Accepting should join the
organization.
- **Invalid token:** alter one character in the token in the swapped
invite URL. Expected: invalid invite state.
- **No longer valid:** accept the invite once, then open the same
swapped invite URL again. Expected: no-longer-valid/already-used state,
depending on the backend response.

### Test-covered states

Expired invites, generic backend error, loading, and
create-account-disabled states are harder to force manually in staging.
They are covered by `tests/components/OrganizationInvite.test.tsx`.

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

* **Refactor**
* Redesigned the organization invitation experience with an interstitial
layout, clearer early-return flows for signed-out, loading,
expired/invalid, wrong-account, and accepted-invite states; primary CTA
now reads “Accept invite”.
* Streamlined error and sign-out flows with clearer, focused messaging.

* **New Features**
* Added a reusable interstitial layout and compact account row for
invitation screens.

* **Tests**
* Added comprehensive tests covering invite states, accept/decline
actions, and error handling.

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45774)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-12 10:41:47 +10:00
Alaister Young d676c832f3 fix(studio): pre-empt React 19 regressions in tests + Support form (#45784)
Four React-19-sensitive patterns that pass on React 18 today but break
under React 19 (verified on the in-flight TanStack Start branch).
Landing on master now so the eventual React 19 upgrade is a no-op for
tests, instead of a separate cleanup pass under upgrade pressure.

Each fix is a strict superset / less-fragile equivalent of the existing
pattern, so master (React 18) stays green.

**Changed:**
- `hooks/misc/useStateTransition.ts` — fire on entry into `newTest` from
any state other than `newTest`, instead of requiring exactly `prevTest →
newTest`. React 18+ auto-batches dispatches across awaits (e.g.
`dispatch SUBMIT` in the handler, `dispatch ERROR` in `onError`),
collapsing `editing → submitting → error` into a single render where the
intermediate `submitting` tick is never observed. Strict superset of the
old check for our reducers — `success`/`error` are only reachable from
`submitting`.
- `Support/CategoryAndSeverityInfo.tsx` — guard `onValueChange` against
Radix Select's spurious `''` emission. When the controlled value
transitions from `undefined` to a defined value whose `SelectItem` isn't
mounted yet (dropdown closed → items haven't registered), Radix's hidden
`BubbleSelect` fires `onValueChange('')` and clobbers the field. No
`SelectItem` can have `value=""` (Radix throws), so any `''` is
guaranteed spurious — drop it before calling `field.onChange`.
([radix-ui/primitives#3381](https://github.com/radix-ui/primitives/issues/3381))
- `EditSecretModal.test.tsx` — `getByLabelText` → `findByLabelText`.
Under React 19's scheduling, the decrypted-value query resolves on a
separate render tick, so form fields appear one tick after the skeleton.
- `LogsPreviewer.test.tsx` — `addEventListener('click', spy)` instead of
`loadOlder.onclick = vi.fn()`. React 19 reassigns `.onclick` on managed
elements as part of its event wiring, clobbering the direct-property
spy.

## To test

### Unit tests
- `pnpm --filter studio test` — all unit tests pass on master (React 18)

### Support form URL prefill (Radix Select guard)
- `/support/new?category=Problem` → category dropdown reads "APIs and
client libraries" on first paint
- `/support/new?category=dashboard_bug` → "Dashboard bug"
(case-insensitive match)
- `/support/new?category=invalid_garbage` → falls back to "Select an
issue" placeholder, no crash
- `/support/new?subject=My%20issue&message=Details%20here` → subject and
message inputs are prefilled
- `/support/new?projectRef=<your-ref>&category=Problem` → both project
selector and category set, library selector appears
- With a prefilled URL, click the category dropdown and pick a different
option — the new value sticks (this is the path that surfaced the Radix
bug, want to confirm we didn't break user selection)
- DevTools console on first load should be clean — no React hydration
mismatch warning

### Support form submit (`useStateTransition` success + error branches)
- Submit a valid support form → green toast "Support request sent"
appears **once**, view swaps to the success screen, one `POST
/platform/feedback/send` in the network panel
- Block `POST /platform/feedback/send` in DevTools → submit → red error
toast appears **once** (not twice — if you see two toasts the relaxed
transition is firing more than it should), form stays editable with all
inputs preserved
- Unblock and submit again → success path runs cleanly

### Sidebar support form (same reducer + `useStateTransition`, separate
component)
- Open the support widget in the side nav (`SupportSidebarForm`)
- Repeat the success and error paths — should behave identically

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

## Summary by CodeRabbit

* **Bug Fixes**
* Fixed category selector to prevent selected values from being
unexpectedly cleared during form interactions.

* **Tests**
* Improved test reliability for modal field rendering and event handling
assertions.

* **Chores**
  * Clarified internal comments for form initialization logic.

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45784)

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

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-05-11 21:56:51 +08:00
Jordi Enric d8bb0ade65 feat(studio): add timezone picker to user dropdown (#45517)
## Problem

The dashboard renders all timestamps in the browser's local timezone.
When debugging app issues, users often want to see logs and timestamps
in a different timezone (e.g. their app's deployment region) without
changing their OS clock.

## Fix

- New Timezone submenu in the user-avatar dropdown, sitting next to the
existing Theme picker. Search-as-you-type combobox over the full IANA
catalog plus an Auto detect option.
- Selection persists in localStorage (`supabase-ui-timezone`) and
survives `clearLocalStorage()`. No backend schema change.
- New `lib/datetime.tsx` exposes pure timezone-aware formatters
(`formatDateTime`, `formatDate`, `formatTime`, `formatFromNow`,
`toTimezone`) plus a `TimezoneProvider` and matching React hooks
(`useTimezone`, `useFormatDateTime`, ...). The pure functions take `tz`
explicitly so they're easy to unit test (17 vitest cases covering DST
transitions, multi-tz formatting, unix-micro/Date inputs, invalid-tz
fallback).
- The selected timezone propagates to every existing `<TimestampInfo>`
in Studio via a new `TimestampInfoProvider` context exported from
`ui-patterns`. No per-callsite changes needed for those ~20+ surfaces.
- The `UnifiedLogs` date column migrates off `date-fns` to the new
`useFormatDateTime` hook (the rest of the date-fns callers stay as-is,
since they're either internal range math or non-display).
- `ALL_TIMEZONES` (~600 entries) moves out of `PITR.constants.ts` into a
shared `lib/constants/timezones.ts`. PITR keeps a re-export shim so its
callers don't move. New `TIMEZONES_BY_IANA` dedupes the catalog by
primary IANA name (the original list contains both PDT and PST rows for
`America/Los_Angeles`, etc.) and `findTimezoneByIana` provides reverse
lookup.
- Telemetry: `timezone_picker_clicked` PostHog event with
`previousTimezone`, `nextTimezone`, `isAutoDetected` properties.

Notes for reviewers:
- Bare `dayjs(x).format(...)` calls (~157 files) intentionally still
render in browser-local time. Surfaces opt in by switching to the new
wrappers, so this PR is the abstraction plus logs adoption; broader
migration is a follow-up.
- Two `// prettier-ignore` lines (`apps/studio/pages/_app.tsx`,
`apps/studio/components/interfaces/UnifiedLogs/UnifiedLogs.fields.tsx`)
work around a pre-existing local-tooling issue where
`prettier-plugin-sql-cst` strips angle-bracket type arguments under
certain conditions. Project's pinned prettier (3.8.1) does not strip;
the issue surfaces with a globally-installed prettier. Worth tracking
separately.
- Hydration: `guessLocalTimezone()` and `useLocalStorageQuery` are
client-only. Studio is mostly CSR via the Pages Router, but any SSR'd
`<TimestampInfo>` may briefly render in the server's tz before client
hydration. Existing behavior already had this mismatch with `.local()`;
this PR does not regress it.
- Backend timestamps round-tripped through query params and mutations
stay UTC. The picker is display-only.

## How to test

- Run `pnpm dev:studio`, sign in.
- Open the user avatar dropdown (top right). Hover Timezone.
- Search for "tokyo", pick `(UTC+09:00) Osaka, Sapporo, Tokyo`.
- Open any project, navigate to Logs (e.g. `Project > Logs > Edge
Functions`). Hover a log row's timestamp; the popover should show UTC,
the chosen tz (`Asia/Tokyo`), and the relative time. Visible cell text
should be in JST.
- Visit any page that uses `<TimestampInfo>` (Database > Backups,
Project Pause state, Edge Function details). Same tooltip should reflect
Asia/Tokyo.
- Refresh the page; timezone is still Asia/Tokyo.
- Reopen the picker, choose Auto detect; timestamps revert to browser
local.
- Run `pnpm --filter studio test lib/datetime.test.ts`. 17 tests should
pass.

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

* **New Features**
* Timezone selector added to the user menu with auto-detect and manual
override
* App-wide timezone provider and hooks plus a shared timezone catalog
for consistent timezone-aware display
* Timestamp components accept an optional timezone prop and respect user
preference (persisted)

* **Bug Fixes / Improvements**
* Logs and timestamp displays now use the new timezone formatting hooks

* **Tests**
  * Added comprehensive datetime and timezone catalog tests

* **Telemetry**
  * Telemetry event added for timezone picker interactions
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-06 14:52:36 +02:00
Ali Waseem 153f2619bc feat(studio): show expand affordance for large SQL result cells (#45589)
## Summary

- Adds a hover-revealed expand button to SQL result cells whose value is
unlikely to fit on one line (objects, arrays, strings >60 chars, or
strings with newlines). Clicking opens the existing `CellDetailPanel`
for that cell.
- Switches the expand state from a boolean tied to the selected cell to
a direct `{ column, value }` reference, so the context menu and the new
button both target the right-clicked / clicked cell.
- Extracts the per-cell renderer into its own `ResultCell` component to
keep `Results.tsx` digestible and the new affordance isolated.
- Covers the new logic with exhaustive `isLargeValue` unit tests and a
`ResultCell` component test (visibility, click, right-click).

Linear: [FE-3130](https://linear.app/supabase/issue/FE-3130)

## Test plan

- [x] Run a SQL query that returns mixed cell types (short strings, long
strings, JSON objects, arrays, nulls) and confirm the expand button
appears only on cells where content is likely truncated.
- [x] Hover a large cell and click the expand button — `CellDetailPanel`
opens with the correct column + value.
- [x] Right-click a large cell and choose "View cell content" — same
panel opens with the right cell.
- [x] Right-click a small cell and "Copy cell content" — clipboard
contains the raw value.
- [x] Resize a column wider than its content and confirm the button
still positions correctly.
- [x] `pnpm vitest` for `Results.utils.test.ts`, `Results.test.tsx`,
`ResultCell.test.tsx` — all green.

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

## Summary by CodeRabbit

* **New Features**
* Enhanced SQL result cells with automatic detection and expansion
functionality for large values (exceeding 60 characters or containing
line breaks)
  * Added expand button to view full cell content directly in results
  * Integrated right-click context menu for cell content options
  * Improved display of null values in query results

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-05 11:00:09 -06:00
Samir Ketema ee5d4a9314 chore: remove format param from audit log query (#45466)
## 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?

Cleanup after shipping https://github.com/supabase/supabase/pull/45389,
the backend is now defaulting to the new v2 `format`, and made `format`
param optional.

So this:
- removes references to `v2` naming, as this is the only format
- removes the `format` query param from the audit logs API calls

## What is the current behavior?

Same audit log functionality shown in
https://github.com/supabase/supabase/pull/45389

## What is the new behavior?

Functionally the same behavior for audit logs.

- [x] Manual test in staging

## Additional context

⚠️ Will leave the `do-not-merge` tag on until:
- [ ] backend `format` optional PR lands in production.


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

## Summary by CodeRabbit

* **Refactor**
* Consolidated audit log type definitions and updated internal API
request formatting for audit endpoints across Account and Organization
audit log components. No changes to user-facing functionality or audit
log display.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-04 16:24:44 -07:00
Danny White e540f9089f fix(studio): restore Safari table editor cell copy and context menu (#45353)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Bug fix.

## What is the current behavior?

- Safari Table Editor cells fail to copy from a focused cell with `⌘C`.
- Safari right-click can show the browser menu instead of the custom
cell menu.
- Copy can leave RDG's copied-cell fill behind.

## What is the new behavior?

- Reuses the existing shared `copyToClipboard(value, onSuccess)`
pattern, with the Safari clipboard fix inside that util.
- Handles selected-cell `⌘C` in the RDG keydown path, preventing
browser/RDG defaults and showing the success toast only after copy.
- Replaces the row-level synthetic context-menu shim with RDG's
`onCellContextMenu`, so we prevent Safari's browser menu at the source
and select/focus the target cell.
- Keeps the selected-cell outline while the controlled menu is open.

## Additional context

- `RowRenderer` was only supporting the old context-menu shim; removing
it is part of moving to RDG's cell event path.

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

## Summary by CodeRabbit

## Release Notes

* **New Features**
* Context menu now provides feedback with toast notifications when
copying cells or rows.
* Selected cells retain their visual styling when context menu is open.

* **Bug Fixes**
  * Improved keyboard shortcut handling for copy functionality.
  * Enhanced clipboard error handling with user-friendly error messages.

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

---------

Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-05-04 11:34:28 +10:00
Samir Ketema d666b950ff feat: update audit log schema & UI (#45389)
## 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?

- Update to the audit log schema (changes were already applied in
staging)
- Updates the org & project audit log page to reflect the changes to the
schema
- The schema should be agnostic to whether logs were emitted to logflare
with the old & new schema format - the backend adjusts old logs to the
new format.

## What is the current behavior?

Currently, the frontend is parsing the legacy schema as the backend
returns this by default. It also doesn't show some of these new fields
yet.

## What is the new behavior?

### Org Audit Logs - Table View
<img width="1810" height="1310" alt="CleanShot 2026-04-29 at 18 27 22"
src="https://github.com/user-attachments/assets/47fec068-1ffa-4e52-bc46-3bffdef55adb"
/>

### Org Audit Logs - Single log View

<img width="1842" height="1494" alt="CleanShot 2026-04-29 at 18 27 37"
src="https://github.com/user-attachments/assets/3cff3bdf-4a6a-4981-acaa-7f95bb3ae9cf"
/>

Note that the `Target` field is no longer there. We just show the
`metadata` JSON.
<img width="1842" height="1494" alt="CleanShot 2026-04-29 at 18 27 40"
src="https://github.com/user-attachments/assets/d2e681f0-41a6-4bc7-a3d7-ec7e8101616c"
/>

### Account (Profile) Audit Logs - Table View

<img width="1810" height="1310" alt="CleanShot 2026-04-29 at 18 25 20"
src="https://github.com/user-attachments/assets/c72e19df-9b82-4611-8889-7af463769550"
/>

### Account (Profile) Audit Logs - Single log View

<img width="1810" height="1310" alt="CleanShot 2026-04-29 at 18 25 32"
src="https://github.com/user-attachments/assets/46f8d3b6-4f2f-4944-b891-431a93e5f3c3"
/>

## Additional context

⚠️ currently leaving the `do not merge` tag on, until:
- [x] I have verified it works in staging
- [x] We've deployed the new schema to production


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

* **New Features**
* Audit logs now use the v2 format with microsecond-accurate timestamps,
improved ordering, and a revamped details panel showing clearer
actor/action/request/project/org fields and fallback labels.
* Page/header layout updated so audit logs render at top level with
adjusted spacing.

* **Refactor**
* Shared sorting and filtering utilities added for consistent
user/project filtering and non-mutating log sorting.

* **Tests**
* Added tests for timestamp conversion, sorting, filtering, and
date-range formatting.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-30 13:52:16 -07:00
Joshen Lim 7f5865872a Enforce noUnusedLocals and noUnusedParameters in tsconfig.json + fix all related issues (#45264)
## Context

Enforce `noUnusedLocals` and `noUnusedParameters` in tsconfig.json + fix
all related issues
2026-04-27 17:42:34 +08:00
Samir Ketema 8454ec241d feat: add batch email org invites (#44832)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Feature

## What is the current behavior?

When sending organization invites to multiple emails at once, the
invitations API is called once for each email passed, passing a single
email address in the `email` field.

## What is the new behavior?

A single request is used when sending multiple organization invites at
once, by using the new `emails` field.

## Additional context

This builds further on https://github.com/supabase/supabase/pull/42637

⚠️ Note: I'd like to merge this after getting the API changes in first:
https://github.com/supabase/platform/pull/31561


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

* **New Features**
* Bulk invite: paste comma-separated emails (parsed, trimmed,
deduplicated, lowercased) and send as a single batched request; inputs
are categorized into new, already-invited, and existing members.
  * SSO and project scope options included in invite payloads.

* **Bug Fixes / API**
* Invitation endpoint now accepts multiple emails; resend uses
multi-email format. Invalid addresses are blocked, existing members are
skipped with error toasts, and overall success is reported with the
dialog closing after invite.

* **Tests**
* Added unit and UI tests covering parsing, categorization, payload
building, validation limits, and invite flows.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com>
2026-04-23 18:02:08 +00:00
Danny White 1ab7251060 chore(studio): clarify partnered orgs and projects (#44328)
## What kind of change does this PR introduce?

UI improvements.

- Resolves DEPR-401
- Resolves DEPR-424
- Resolves DEPR-425

## What is the current behaviour?

Studio currently blurs two different concepts together:

- `billing_partner` / `billing_via_partner`, which represent real
billing ownership for marketplace-managed organisations such as AWS and
Vercel
- Stripe connection state, which is not actually partner billing in the
same sense, but was previously being mocked through the same UI paths

That made the Stripe work harder to reason about and left some local
behaviour dependent on temporary overrides rather than the API shape we
want to ship.

## What is the new behaviour?

This PR separates those concerns while keeping the existing AWS and
Vercel marketplace experience intact.

- AWS and Vercel continue to use `billing_partner` /
`billing_via_partner` for billing ownership, lockouts, and manage CTAs
- Stripe display state now comes from `integration_source`, which lets
Studio show Stripe-specific badges and alerts without treating Stripe as
a billing partner
- organisation-level partner UI is unified across AWS, Vercel, and
Stripe, including the org banner, navbar icon treatment, and
organisation cards
- project-level Stripe UI now appears only when the project itself is
marked as Stripe-connected, including the project switcher, project list
surfaces, and a project-level banner
- Stripe-connected organisations are no longer incorrectly blocked
behind the AWS/Vercel-style billing management alerts for invoices,
billing address, payment methods, or plan changes
- banner dismissal is scoped to the relevant org/project and
partner/integration state

## Review order

Most of the diff size here is regression tests and generated types. The
behavioural changes are concentrated in a smaller set of files.

Recommended review order:

1. `integration_source` vs `billing_partner` data-model split and
org/project query mapping
2. org-level UI: partner icon, org banner, org dropdown/card treatment
3. billing gating updates for Stripe vs AWS/Vercel
4. project-level Stripe UI: dropdown, list surfaces, banner
5. tests and generated types

| Stripe Org(s) |
| --- |
| <img width="1024" height="759" alt="Organizations Supabase"
src="https://github.com/user-attachments/assets/d0ef338c-3b41-4c6d-b3bd-f21a2c182840"
/> |

| Vercel Org(s) |
| --- |
| <img width="1024" height="759" alt="Organizations Supabase"
src="https://github.com/user-attachments/assets/1dc57770-3f24-45ac-840f-34680555cde8"
/> |

| AWS Org(s) |
| --- |
| <img width="1024" height="759" alt="Organizations Supabase"
src="https://github.com/user-attachments/assets/7847dad0-ee30-4a65-ab0b-b3b16af0d34f"
/> |

| Stripe Org, Non-Stripe Project |
| --- |
| <img width="1152" height="885" alt="Mallet Toolshed
Supabase-1673E019-792C-462C-B6F8-C5DDB810B331"
src="https://github.com/user-attachments/assets/556fbea3-b5ae-4f2f-96b9-6f66c6654e4a"
/> |

| Stripe Org, Stripe Project |
| --- |
| <img width="1152" height="885" alt="Hammer Toolshed
Supabase-7E86C17C-561F-4221-BD16-EAFF7D41AAE0"
src="https://github.com/user-attachments/assets/94f8daf6-0320-413e-8d56-59f9acaaea15"
/> |

| Vercel Org |
| --- |
| <img width="1024" height="759" alt="Projects Toolshed
Supabase-A7891653-9366-4B99-89DD-789D70CD52E3"
src="https://github.com/user-attachments/assets/c87ee6e8-4451-4866-a905-23a38b2593e3"
/> |

| AWS Org |
| --- |
| <img width="1024" height="759" alt="Projects Toolshed
Supabase-58A43ECE-569E-4541-9463-346A90B02CFF"
src="https://github.com/user-attachments/assets/9350a180-4d58-42a1-ad1a-95893c2e8b12"
/> |

This also removes the old Stripe mock override path in Studio so the
frontend matches the intended API model more closely.

## ~~Dependencies~~ (merged!)

This work depends on the private platform change that exposes
`integration_source` on the relevant organisation and project payloads:

- https://github.com/supabase/platform/pull/31874

_Update: now merged._

## Local testing

### Stripe

If you have the private `platform` repo checked out locally, make sure
your local API returns `integration_source: 'stripe_projects'`
consistently for the Stripe-linked org/project you are testing.

Important responses:

- `/platform/organizations`
- `/platform/organizations/:slug/projects`
- `/platform/projects/:ref`

Verify:

- org banner and org icon show the Stripe connected state
- unopened and opened project switcher both show Stripe only for
Stripe-linked projects
- project cards / table rows show the Stripe chip only for Stripe-linked
projects
- the project-level Stripe banner appears across project surfaces
- billing address, tax ID, invoices, payment methods, and plan changes
remain editable in Studio for Stripe orgs

### Vercel

Use a Vercel Marketplace org with real `billing_partner` /
`billing_via_partner` values.

Important org-level endpoints for local mocking in `platform`:

- `/platform/organizations`
- `/platform/organizations/:slug`
- `/platform/organizations/:slug/billing/subscription`

Project-level Vercel indicators still come from
`/platform/integrations/:slug`, not `integration_source`.

### AWS

Use an AWS Marketplace org with real `billing_partner` /
`billing_via_partner` values.

Important org-level endpoints for local mocking in `platform`:

- `/platform/organizations`
- `/platform/organizations/:slug`
- `/platform/organizations/:slug/billing/subscription`

AWS does not currently have a Stripe-like project-level indicator in
these org/project payloads.

## Notes

- `billing_partner` is no longer the right abstraction for the
Stripe-connected case in this PR. It remains the source of truth for
marketplace billing ownership, while Stripe currently uses
`integration_source` as a connection/display signal.
- I re-ran `pnpm api:codegen` while tightening this PR and kept only the
generated type changes this branch actually depends on, to avoid
unrelated API drift in the review.

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

* **New Features**
  * Stripe Projects integration added for billing and project flows
* Partner icons/badges shown across org and project lists, dropdowns,
and rows
* Dismissible, partner-specific marketplace/integration banners with
contextual CTA behavior
* Improved partner-billing detection to drive billing UI and
invoice/plan availability

* **Tests**
* Extensive new test coverage for billing UI, partner-managed fallbacks,
banners, icons, and related flows
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
2026-04-23 12:17:24 +10:00
Ali Waseem e8df67d5d5 chore: migrate shortcuts to new hooks API (#44955)
## 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?

Cleanup shortcuts with new hooks

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

* **Refactor**
* Centralized keyboard shortcut system for consistent shortcut behavior
across the app and moved preference toggles to a unified registry.

* **New Features**
* Added explicit shortcuts for Command Menu, AI Assistant, Inline
Editor, and result copy/download actions.
* Hotkey preferences UI now renders dynamically from the centralized
shortcut list.

* **Tests**
* Test helpers updated to include the command menu provider for accurate
shortcut behavior in tests.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-17 10:02:56 -06:00
Alaister Young 1b1d05ff96 chore: upgrade vite to v8 and vitest to v4 (#44833)
Upgrade vite and vitest to their latest major versions across the
monorepo, along with related packages.

**Changed:**
- `vite` catalog: `^7.3.2` → `^8.0.8` (Rolldown replaces esbuild/Rollup)
- `vitest` catalog: `^3.2.0` → `^4.1.4`
- `@vitejs/plugin-react`: `^4.3.4` → `^6.0.1`
- `@vitest/coverage-v8`: `^3.2.0` → `^4.1.4`
- `@vitest/ui`: `^3.2.0` → `^4.1.4`
- `vite-tsconfig-paths`: `^4.3.2` / `^5.1.4` → `^6.1.1`

**Pinned to vite 7:**
- `apps/lite-studio` — `@react-router/dev` hasn't declared vite 8
support yet
- `blocks/vue` — Nuxt plugins (`vite-plugin-inspect`, `vite-dev-rpc`,
`vite-hot-client`, `vite-plugin-vue-tracer`) haven't declared vite 8
support yet

**Test fixes for vitest 4 breaking changes:**
- **`apps/studio/lib/api/snippets.utils.test.ts`** — Replaced
`vi.mock('fs/promises')` automock with an explicit factory. Vitest 4's
automocking doesn't create mock functions for getter-based exports on
Node built-ins, so `mockedFS.access.mockResolvedValue` etc. were
`undefined`.
- **`apps/studio/lib/api/self-hosted/functions/index.test.ts`** —
Changed `mockReturnValue` to `mockImplementation(function() { ... })`
for a constructor mock. Vitest 4 no longer allows `mockReturnValue` when
the mock is called with `new`.
- **`apps/studio/tests/pages/api/mcp/index.test.ts`** — Changed arrow
function to regular `function` in `mockImplementation` for
`StreamableHTTPServerTransport`. Arrow functions can't be constructors,
and vitest 4 now enforces this.
- **`packages/ui-patterns/vitest.setup.ts`** — Changed `ResizeObserver`
mock from arrow function to regular `function` for the same constructor
enforcement reason. This was crashing Radix popover rendering in jsdom.

## To test

- `pnpm test:studio` — all 226 test files should pass
- `pnpm --filter ui-patterns vitest run` — all 183 tests should pass
- `pnpm --filter www test -- --run` — all 19 tests should pass
- `pnpm --filter ui vitest run` — all tests should pass
- `pnpm --filter dev-tools vitest run` — all tests should pass
- `pnpm --filter ai-commands vitest run` — all tests should pass

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

* **Chores**
* Standardized and updated development tooling versions and version
sources for consistent installs across the repo (Vite, Vitest,
vite-tsconfig-paths and related plugins/catalog entries).
* **Tests**
* Improved test mocks and typings (updated mock
factories/implementations and tightened spy/type assertions) to increase
test reliability and compatibility with updated tooling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-04-16 00:13:48 +09:00
Jordi Enric 21584fe512 feat(studio): add backup cli instructions (#44621)
## Problem

When a project is paused, in a failed state, or about to be deleted,
users have no obvious way to take a logical backup of their data before
proceeding. This is particularly risky at deletion time — once deleted,
data is gone.

## Solution

Introduce a new `LogicalBackupCliInstructions` component that surfaces
ready-to-run `supabase db dump` commands pre-filled with the project's
direct connection details.

### Where it appears

| State | How |
|---|---|
| Project paused (restorable) | Inline in `ProjectPausedState` with a
note to resume first |
| Pause failed | Dialog via "Download backup" button when no backup is
available |
| Restore failed | Dialog via "Download backup" button when no backup is
available |
| Delete project modal | Inline in `DeleteProjectModal` for all plans |

Not shown in `PauseDisabledState` (project paused 90+ days, compute
stopped — `pg_dump` would fail anyway).

### What the component does

- Fetches the project's direct connection settings via
`useProjectSettingsV2Query`
- Builds a connection URI with a `[YOUR-PASSWORD]` placeholder (password
is never stored or displayed)
- Shows three shell commands to dump roles, schema, and data separately
— mirroring the [logical backup
docs](https://supabase.com/docs/guides/platform/backups)
- Optionally shows a **Reset database password** button (gated on
`UPDATE projects` permission); shown in the paused state, hidden
elsewhere via `showResetPassword={false}`
- Includes inline guidance to percent-encode special characters in the
password

### Shell safety

The generated `--db-url` values are wrapped in single quotes to prevent
shell metacharacter expansion when users paste and run the commands.
`npx supabase login` is intentionally omitted — the `--db-url` flag
authenticates directly against Postgres and does not require a Supabase
account.

### Backup button behaviour in failed states

The "Download backup" button in `PauseFailedState` and
`RestoreFailedState` now always stays enabled:
- **Backup available** — downloads immediately (unchanged)
- **No backup / physical backups** — opens a dialog with CLI
instructions instead of silently failing

## How to test

**Delete project flow**
1. Open any project → Settings → General → Delete project
2. Verify the CLI backup section appears with the project's host, port,
user, and db name pre-filled
3. Verify no Reset database password button is shown

**Paused project**
1. Open a paused project (`ProjectPausedState`) — verify CLI
instructions appear with the "Your project must be resumed before
running these commands." note
2. Open a project paused for 90+ days (`PauseDisabledState`) — verify
CLI instructions do not appear

**Failed states**
1. Simulate a pause-failed or restore-failed state
2. If a downloadable backup exists — "Download backup" downloads it
directly
3. Block the backup API or use a project with physical backups —
"Download backup" should open the CLI instructions dialog

**Error state**
1. Block the project settings API call (DevTools → Network → block
request)
2. Verify an error message appears with a link to Database settings
3. Verify a loading skeleton shows while the request is in flight

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 16:39:32 +02:00
Ignacio Dobronich cfce3c7efc refactor: save tax ID via customer update endpoint (#44728)
## Summary

- Consolidate tax ID saving into the `PUT
/organizations/{slug}/customer` endpoint instead of using a
separate `/tax-ids` endpoint


## Test plan

### Updating billing information
From the billing dashboard`/org/_/billing`:
- [ ] Manually test updating billing address + tax ID from org billing
settings - single API call should save both
- [ ] Clear the Tax ID in the org, save and assert that it has been
deleted
- [ ] Modify all the fields in the address form, including TaxID. Click
"Cancel" and assert that everything has returned to the previous values.

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

* **Refactor**
* Billing address and tax ID updates are now sent in a single update
operation.
* Error messaging for billing updates consolidated into a single failure
notification.
* Tax ID handling clarified: you can clear tax ID explicitly or leave it
unchanged; omitting address fields no longer overwrites existing
address.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 09:49:57 -03:00
Charis 205cbe7d26 chore(studio}: enforce import order, remove bare import specifiers (#44585) 2026-04-07 20:34:10 -04:00
Ali Waseem fbb0770b47 fix(studio): AI assistant results make page unresponsive (#44578)
## Summary

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

- Replaced per-cell `ContextMenu_Shadcn_` in SQL result tables with a
single shared instance
- Each Radix ContextMenu registers a `keydown` listener on `document`
via `useEffect`. With 1000+ row result sets, this created thousands of
document-level listeners. Chrome trace showed listeners growing from 21k
to 347k, with every keystroke taking ~250ms (70k+ function calls per
long task)
- Fixed DataGrid not rendering in Firefox by using flex layout instead
of `height: 100%` for sizing
- Fixed double scrollbar in QueryBlock results by making the container a
flex column and removing `overflow-auto`
- Moved format utils into `Results.utils.ts`

## Test plan

The `Results` component and `QueryBlock` are used in several places.
Each should be verified:

- [x] **AI Assistant** — Have the assistant run a query returning 1000+
rows. Verify the page stays responsive while typing and there is only a
single scrollbar on the results table
- [x] **AI Assistant (Firefox)** — Same as above but in Firefox. Verify
the results table actually renders
- [x] **SQL Editor results panel** — Run a query in the SQL Editor.
Verify results render correctly with a single scrollbar in the utility
panel
- [x] **SQL Editor explain tab** — Run an EXPLAIN query. Verify explain
results render
- [x] **Editor Panel** (used in Table Editor SQL preview) — Verify
results display correctly
- [x] **Context menu** — Right-click a cell in any of the above and
verify "Copy cell content" and "View cell content" still work

## Traces
<img width="891" height="599" alt="image"
src="https://github.com/user-attachments/assets/6e1b710b-ca9e-4748-9369-d03457d80206"
/>


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

* **Bug Fixes**
* Fixed context menu behavior so it opens at the cursor and is
instantiated once.
* Improved clipboard copy formatting for cell values; NULLs copy as
empty and cells render as "NULL".

* **Style**
* Adjusted table layout and scrolling behavior to improve results
container sizing.

* **Tests**
* Added tests for results rendering, context-menu behavior, and
cell/clipboard formatting utilities.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-06 13:04:24 -06:00