Commit Graph
5960 Commits
Author SHA1 Message Date
Charis 21511042a3 feat(studio): assistant logs context and reports guard (#48514)
## 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 — final PR (9/9) of the SQL editor logs-source stack.

**Base branch:** `charislam/sql-editor-inline-ai-clickhouse-dialect` (PR
8). Nothing here is user-visible: entry points stay behind
`sqlEditorLogsSource` + `otelLegacyLogs`, and flag rollout happens after
the whole stack merges.

## What is the current behavior?

- The Assistant has no idea a SQL editor snippet targets the logs
backend. Ask it about a logs snippet and it answers in Postgres, because
the attached query is fenced as ` ```sql ` and nothing tells the model
otherwise.
- Because the `sql` fence is what `MessageMarkdown` treats as runnable
Postgres, an attached ClickHouse query is rendered with a
Run-against-Postgres affordance and branded with `untrustedSql`.
- "Debug with Assistant" on a failed logs query produces a dialect-less
prompt, so both the in-app assistant and the copyable version get
debugged as Postgres.
- A report referencing a `log_sql` snippet runs its ClickHouse SQL
against the user's Postgres database and surfaces the resulting error.

## What is the new behavior?

**Assistant panel.** The "Current Query" chip records which backend the
attached query targets. That reaches the model two ways: each attachment
is fenced with its own dialect (` ```clickhouse ` vs ` ```sql `), and a
`containsLogsSnippets` flag rides on the user message as AI SDK
`metadata`. The server reads the flag off the conversation and prepends
the ClickHouse dialect rules plus the logs schema reference as a
non-cached context message.

Two design points worth calling out in review:

- The flag lives on the **message**, not the request body, so Retry and
the tool-approval continuation reproduce the context a message was
originally asked in — neither of those passes a per-call body.
- It's derived from **what's actually attached**, so detaching the chip
drops the claim rather than leaving the two able to disagree.

The `clickhouse` fence also keeps a logs query out of
`MessageMarkdown`'s `sql` branch, so it's no longer offered as runnable
Postgres or branded with `untrustedSql` — a boundary this stack's
distinct brands exist to prevent crossing.

**Debug flow.** `buildDebugChatArgs` attaches its query with a source
for the same reason, and names the dialect in the prompt text so the
copyable version stands on its own outside the app.

**Reports.** A report only stores a snippet id, so whether it queries
the logs backend is only knowable once the content loads. `ReportBlock`
guards on the fetched type and renders a `LogsSnippetReportBlock`
placeholder instead of executing. Double-guarded: no `sql` for a logs
snippet (so it's out of the query key and `queryFn` short-circuits even
on an explicit `refetch`) and `enabled` excludes it.

**Incidental cleanups.** `buildAssistantContextMessages` extracted out
of `generate-assistant-response`; a schema-access sentinel that was
duplicated as a string literal across two files (and compared against)
replaced with one exported constant; `SqlSnippet` deduplicated to a
single declaration; `resolveSnippetSource` / `isLogsSource` shared
instead of re-implemented per surface.

**Tests.** 4 new/extended suites. Notable cases pinned: a message with
no metadata must validate (`safeValidateUIMessages` applies
`metadataSchema` to *every* message, so a required schema would 400
every existing conversation); only *user* messages count, so a model
reply can't talk the server into a different dialect; a mixed-attachment
message is flagged without overclaiming a single source; and
`ReportBlock` registers no pg-meta mock for the logs cases, so an
unhandled request failing the test *is* the assertion that logs SQL
never reaches Postgres.

Verified: `pnpm typecheck`, `lint:ratchet` (no regression), Prettier,
and the full Studio suite (459 files / 4969 tests).

## Additional context

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

## Summary by CodeRabbit

- **New Features**
- Added support for recognizing log snippets in reports, with clear
guidance to open them in the SQL editor or remove them.
- AI Assistant now understands log snippets and provides
ClickHouse-specific context, formatting, and troubleshooting guidance.
- Snippets retain their source information when shared with the AI
Assistant.

- **Bug Fixes**
- Prevented unsupported log snippets from being executed as regular
database queries.
  - Improved source detection when opening snippets directly from links.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-04 09:02:40 -04:00
Charis 8b38e0d1ed feat(studio): ClickHouse dialect for logs snippet AI + rewrite to ClickHouse (#48501)
## 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, plus a refactor of the shared logs-rewrite flow.

PR 8 of the SQL editor query-source series. Stacked on #48457 — review
that one first, and merge this after it.

## What is the current behavior?

A `log_sql` snippet runs against the ClickHouse-backed analytics
endpoint, but the SQL editor's AI still writes Postgres: inline edits
get Postgres system prompts, and the result is run through
`sql-formatter`, which mangles ClickHouse backticks and `log_attributes`
map lookups.

Legacy Logs Explorer saved queries open in the editor as `log_sql`
snippets. Those are BigQuery dialect and error against the ClickHouse
endpoint the editor runs them on, with no in-editor way out — only the
Logs Explorer offered a rewrite.

The completion route was also asymmetric. It assembled a
schema/code/instruction message for Postgres but forwarded `prompt`
verbatim for ClickHouse, so a client wanting ClickHouse had to
hand-build the equivalent string.

## What is the new behavior?

**Inline AI speaks ClickHouse for logs snippets.** `sqlSourceToDialect`
maps a snippet's source to `postgres`/`clickhouse` and
`buildCompletionRequestBody` threads it through. For ClickHouse,
`useSqlEditorAi` strips code fences from the response and skips
`formatSql`. Execution and dialect both follow the snippet type, so a
snippet's valid dialect never flips.

**Rewrite to ClickHouse in the editor.** A banner offers the rewrite for
a logs snippet whose text trips `looksLikeLegacyLogsQuery`, and proposes
the result through the editor's existing AI diff view rather than
replacing the snippet, so it's accepted or discarded like any other AI
edit. Gated on `otelLegacyLogs`: on a non-migrated org the BigQuery text
is still correct, so rewriting it would break a working query.

The offer is a state machine (`offered` / `rewriting` / `failed` /
`noRewriteNeeded` / `dismissed`) with a declarative table of valid
transitions, so the states are mutually exclusive by construction and
dismissal is terminal. A failure keeps its message and offers a retry; a
response identical to the input is reported rather than opening an empty
diff.

**One place assembles completion prompts.** The route now uses a single
template for both dialects, branching only the schema section and — for
`intent: 'rewrite'` — the instruction. `lib/ai/clickhouse-logs.ts` is
the single home for ClickHouse-logs prompt content, replacing two
independently maintained descriptions of the same table. Clients carry
no prompt text.

**The rewrite flow is shared with the Logs Explorer.** Both surfaces
previously hand-rolled the same sequence and had drifted: only one
detected a no-op rewrite, they sourced `log_attributes` keys
differently, and the Explorer formatted errors with an `as Error` cast.
Both now use `useLegacyLogsRewrite` and the same state-driven banner, so
the Explorer picks up no-op detection and typed error extraction.

**Attribute keys are fetched on submit, not while typing.** The detected
source would otherwise feed a reactive query key, making every edit that
changed it cost another network call. `useLogsAttributeKeys` is
imperative and goes through `queryClient.fetchQuery`, so a source
already cached — including by the Explorer header and query panel, which
subscribe reactively — is reused. This also closes a gap where inline
edits never received keys at all, unlike full rewrites.

`getErrorMessage` gains an optional typed fallback and no longer
stringifies a bare object into `'[object Object]'`; every existing
caller already hand-rolled a fallback, except `QueueSettings`, which
interpolated the raw result and now passes one.

Nothing here is user-visible until the `sqlEditorLogsSource` flag is
enabled.

Tests: dialect selection and request-body shape, the ClickHouse prompt
content (including that the schema section does not restate the dialect
rules), the reducer's valid and invalid transitions,
`shouldOfferLegacyLogsRewrite`, on-submit key discovery with cache
reuse, and `getErrorMessage`.

## Additional context

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

## Summary by CodeRabbit

* **New Features**
* Added an Assistant banner to help rewrite legacy BigQuery-style logs
queries into ClickHouse SQL.
* SQL assistance now adapts to the selected query type, including
relevant log attribute context.
* Rewrite suggestions can be reviewed as editor diffs before being
applied.

* **Bug Fixes**
* Improved rewrite failure handling, retry options, dismissal behavior,
and “no rewrite needed” messaging.
* Error notifications now provide a clearer fallback message when
details are unavailable.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-04 09:02:40 -04:00
Charis b3c5c9fc04 feat(studio): logs snippets in SQL editor nav, search, and tabs (#48457)
## What

PR 7 of the SQL-editor query-source (Database vs Logs) stack. Surfaces
`log_sql` snippets as a distinct query source across the SQL editor
sidebar. Stacked on **`charislam/toolbar-ui-creation-flow`** (PR 6 —
toolbar UI + creation flow); review/merge that first.

Nothing is user-visible until the flags roll out — every entry point
requires **both** `sqlEditorLogsSource` **and** `otelLegacyLogs`.

## Changes

- **Nav** — a flag-gated **Logs** section (`LogsSnippetsSection`) backed
by its own single-type `log_sql` query. The active snippet is injected
only into the section it belongs to, via a shared
`withActiveSnippet(snippets, active, belongsPredicate)` helper (also
DRYs the private/favorites/shared injections).
- **Search** (`SearchList`) — a **Logs** result group with a shared,
extracted `SqlSnippetTree`; the "N results found" count now sums
database + logs, with loading/empty states covering both queries.
- **Tabs** — an immutable `sqlSource` field on tab/recent-item metadata
(set at tab creation, lazily backfilled once the snippet loads via
`useEffectEvent`), and a distinct `ScrollText` icon via a shared
`LogsSnippetIcon`. Tab cleanup treats `log_sql` tabs as live and only
prunes them when logs data is authoritative (`canPruneLogsTabs`), so a
disabled/erroring logs query never wrongly deletes logs tabs or blocks
database-tab cleanup.
- **Data layer** — `useSqlSnippetsQuery` gains an optional `type` param
so logs reuse the same `SnippetWithContent` shape as the other sections
(no casts).

## Tests

- `state/tabs.test.ts` — `sqlSource` backfill + creation-time
carry-through.
- `components/layouts/Tabs/Tabs.utils.test.tsx` — cleanup prunes stale
database/logs snippets, keeps live ones, and preserves logs tabs when
logs data isn't authoritative.

## Verification

- `pnpm --filter studio typecheck` ✓
- `pnpm --filter studio run lint:ratchet` ✓
- `pnpm test:studio` (affected suites) ✓

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

* **New Features**
* Added a collapsible Logs section to the SQL editor sidebar for
browsing, sorting, selecting, renaming, and deleting log queries.
* Expanded SQL search with separate, paginated results for database and
log queries.
* Added dedicated log-query icons across navigation, tabs, previews, and
recent items.
* **Bug Fixes**
* Improved tab and recent-item cleanup while preserving active log
queries and accurate source metadata.
* **Tests**
* Added coverage for log tab cleanup and SQL source metadata
synchronization.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-04 09:02:39 -04:00
Jordi Enric a66dae48f2 fix(studio): restart action for table editor load errors FE-4054 (#48687)
## Problem

When the table editor showed a "Failed to load tables" or "Failed to
load schemas" error (for example, when the underlying database or API
gateway is unhealthy), there was no working way to restart the project
from that error state. Restarting only worked by navigating to Project
Settings.

## Fix

"Failed to load tables" goes through the existing `ErrorMatcher`
classification system, which only showed troubleshooting steps
(including a restart action) for connection-timeout errors. Added an
`ERROR_MAPPINGS` entry for the unclassified/generic API error case,
reusing the existing `RestartDatabaseTroubleshootingSection` and
`RestartProjectDialog` components already used for connection timeouts.

"Failed to load schemas" (in the shared `SchemaSelector`, used across
the table editor and several Database pages) only offered a retry. Added
a "Restart database" button next to it, wired to the same
`RestartProjectDialog`.

## How to test

- In the table editor, trigger a table-load failure that isn't a
connection timeout (any generic API error). The error card should now
show a "Try restarting your project" step with a working restart action.
- Open the schema selector while schemas fail to load (e.g. mock a 503
from the schemas query). A "Restart database" button should appear next
to "Reload schemas" and open the restart confirmation dialog.
-
`apps/studio/components/interfaces/ErrorHandling/ErrorMatcher.test.tsx`
and `apps/studio/components/ui/SchemaSelector.test.tsx` cover both
cases.

FE-4054

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

* **New Features**
  * Added database restart guidance when schema loading fails.
* Added options to reload schemas or restart the database, including a
confirmation prompt.
* Added troubleshooting guidance for unclassified table-loading errors.

* **Bug Fixes**
* Improved error handling by displaying relevant fallback guidance for
unknown errors while preserving classified troubleshooting instructions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-04 14:36:06 +02:00
Jordi Enric 2ba2c37163 fix(studio): preserve deep-linked date range in Unified Logs FE-4020 (#48685)
## Problem

Clicking a bar in a usage chart (e.g. the Postgres activity chart on the
project dashboard) navigates to Unified Logs with the log_type filter
applied correctly, but the clicked bar's time range is silently dropped:
the page falls back to the default last-hour window. If the actual
matching logs are outside that window, the main list shows "No results
found" even though the sidebar facet count (computed from the correct
deep-linked range) shows a nonzero count.

Root cause: the table's initial `columnFilters` state was seeded only
from the `filter` URL param, never from `date`. A debounced effect syncs
`columnFilters` back into the URL shortly after mount, and for the
`date` field it treats a missing `columnFilters` entry as a cleared
brush, overwriting the deep-linked `date` param with null.

## Fix

Added `buildDefaultColumnFilters` in `UnifiedLogs.filters.ts`, which
seeds a `date` entry into the initial `columnFilters` from `search.date`
when present, alongside the existing filter-param seeding.
`UnifiedLogs.tsx` now uses this helper instead of building
`defaultColumnFilters` inline, so a deep-linked range survives the
debounced round-trip instead of getting nulled out.

## How to test

- On the project dashboard, click a bar in a usage chart (e.g. Postgres
activity) for a time period further back than the last hour.
- Expected result: Unified Logs opens with both the log_type filter and
the clicked bar's date range applied, and the row list matches the
sidebar facet count instead of showing "No results found".
- `UnifiedLogs.filters.test.ts` has unit tests covering the new seeding
behavior.

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

## Summary by CodeRabbit

* **Bug Fixes**
  * Improved log filtering from URL parameters.
  * Preserved valid date ranges when opening deep-linked log views.
* Prevented malformed or duplicate date filters from appearing in the
logs table.

* **Tests**
* Added coverage for valid, missing, malformed, and duplicate date
filter scenarios.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-04 12:37:59 +02:00
Stephen MorganandJoshen Lim 9dc5c0faf3 feat: privatelink read replica (#48642)
Frontend changes for new privatelink functionality.
The updates to the API are already live, but will be putting the UI
changes behind a feature flag while we do some full end to end testing.

Changes to Integration page:
<img width="744" height="456" alt="image"
src="https://github.com/user-attachments/assets/02026083-4b61-4f36-927b-1bac42cb73e2"
/>

Changes to create associations page:
<img width="859" height="411" alt="image"
src="https://github.com/user-attachments/assets/303b4ec5-3b5a-4eaf-8d22-45e1e63a0705"
/>

Fixes SEC-919

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

- **New Features**
- AWS PrivateLink connections can target the primary database or a read
replica.
- Connection lists and confirmation dialogs now identify the selected
database clearly.
- Replica details include improved status information and a “Manage
replica” link.

- **Bug Fixes**
- Replica removal errors now provide clearer guidance and link to
integration settings when PrivateLink issues occur.

- **Updates**
- Infrastructure diagrams focus on visualization, with replica
management actions moved to dedicated management views.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-08-04 20:47:48 +12:00
Alaister YoungandAlaister Young 270925b680 feat(studio): add dashboard_auth:sign_in_with_chatgpt enabled feature (#48677)
Adds a `dashboard_auth:sign_in_with_chatgpt` enabled-features flag so
deployments can disable the sign in with ChatGPT button via
`disabled_features`, the same way `dashboard_auth:sign_in_with_github`
works. Previously the button was only gated by the ConfigCat rollout
flag / localStorage opt-in, so white-labeled deployments with custom
auth providers had no way to turn it off.

**Added:**
- `dashboard_auth:sign_in_with_chatgpt` (default `true`) in
`enabled-features.json` + schema
- Tests covering the feature-disabled state

**Changed:**
- `useEnabledIdentityProviders` now gates ChatGPT as `featureEnabled &&
(localStorageOptIn || configCatFlag)` — the feature flag is the static
kill switch, the existing OR'd pair remains the rollout mechanism

## To test

- Sign-in and sign-up pages behave exactly as before by default (flag
defaults to `true`, ConfigCat/localStorage rollout gate unchanged)
- With `dashboard_auth:sign_in_with_chatgpt` in a profile's
`disabled_features`, the ChatGPT button no longer renders even with
`?siwc-enabled=1` or the ConfigCat flag on
- GitHub button gating unaffected

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

## Summary by CodeRabbit

- **New Features**
  - Added a feature flag to control ChatGPT sign-in availability.
- ChatGPT sign-in is now available only when the feature is enabled and
an applicable rollout or opt-in condition is met.

- **Tests**
- Expanded coverage for ChatGPT and GitHub sign-in provider availability
under different feature-flag and rollout conditions.

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

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-08-04 13:58:43 +07:00
Joshen Lim a0cec24f49 Remove references to fly (#48648)
## Context

As per PR title - should not have any visual nor functional change 

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

## Summary by CodeRabbit

- **Changes**
- Standardized infrastructure, region, and database configuration around
AWS-based environments.
- Removed Fly.io-specific region and provider options from project
creation, instance sizing, and infrastructure settings.
- Enabled disk validation, spend-cap eligibility, backup restoration,
and extension setup consistently across supported projects.
- Updated billing and region displays to use the applicable AWS
configuration.
- **Bug Fixes**
- Corrected project-specific restrictions that could incorrectly hide
configuration and billing controls.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-03 21:14:50 +07:00
Joshen Lim 8e3e14f198 Joshen/fe 4064 add a toast callout for feature preview (#48645)
## Context

Adds a banner toast for the database connections feature preview

<img width="315" height="322" alt="image"
src="https://github.com/user-attachments/assets/8caaab88-10a0-4a06-b678-25fc9c44dd81"
/>

## Other changes

As the observability page currently has a number of banner toasts
(metrics API, unified logs, index advisor for query performance), am
opting to REMOVE the metrics API's banner toast by virtue of how long
its been around for. Mainly to prevent over stacking of banner toasts as
it can be annoying.


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

* **New Features**
* Added a dismissible Database Connections banner with SQL examples and
a link to its feature preview.
  * Banner dismissal and CTA interactions are now tracked.
  * Dismissed banners can reappear when reintroduced.

* **Bug Fixes**
  * Banners are hidden after the feature is enabled or dismissed.
  * Improved banner handling to prevent duplicate active banners.

* **Changes**
* Replaced the Metrics API banner with the Database Connections banner.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-03 21:02:19 +07:00
Joshen Lim 9006e33f11 Add categories for feature previews (#48641)
## Context

Given that our number of feature previews have been expanding, am opting
to group them into categories for easier understanding of the context of
each feature preview.

Ideally we're able to tag all feature previews into categories (or add
more categories), but leaving the unclassified ones under "others" for
now

<img width="936" height="661" alt="image"
src="https://github.com/user-attachments/assets/b48bd9a2-fe33-4cb0-9288-1cd9c8264da0"
/>


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

## Summary by CodeRabbit

* **New Features**
  * Feature previews are now organized into expandable categories.
  * Observability and database previews are grouped for easier browsing.
  * Uncategorized previews remain available under an “Others” section.
* Existing feature selection options and sorting behavior are preserved.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-03 17:30:09 +07:00
Danny White 76257f164b fix(studio): align storage row icon weight (#48480)
## What kind of change does this PR introduce?

Bug fix stacked on #48478.

## What is the current behavior?

Storage Explorer renders the custom closed-folder icon at `1.5` but
leaves the Lucide open-folder icon at its default `2`. The duplicated
file-picker implementation also uses a different set of stroke-width
overrides.

## What is the new behavior?

A shared `StorageRowIcon` renders loading, open and closed folder,
image, audio, video and generic file icons at `1.5` across Storage
Explorer, row editing and the bucket file picker.

Test by comparing open and closed folders and file-type rows in Storage
Explorer and the bucket file picker.

| Before | After |
| --- | --- |
| <img width="524" height="336" alt="CleanShot 2026-08-03 at 18 38
06@2x"
src="https://github.com/user-attachments/assets/15eb8b9f-69fc-4eee-8428-d7ec26dce8dc"
/> | <img width="522" height="328" alt="CleanShot 2026-08-03 at 18 39
20@2x"
src="https://github.com/user-attachments/assets/17b7dddd-8d36-421c-8356-c9c1bd7456e8"
/> |
| _Thicker image and file icon compared to folder icon_ | _Every icon
has the same stroke thickness_ |

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

* **Improvements**
* Standardized file, folder, media, and loading icons across storage
views.
* Improved visual consistency with unified icon sizing, styling, and
stroke width.

* **Tests**
* Added coverage for loading, folder, media, and generic file icon
states.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-03 19:37:54 +10:00
Joshen Lim fc69c45985 Bring database connections to feature preview (#48638)
## Context

As per PR title - brings Database Connections into feature preview
Should be working for both hosted + self-host/local

Also adjusts existing feature previews to remove "New"
- Platform webhooks
- Temporary database access

<img width="600" alt="image"
src="https://github.com/user-attachments/assets/b18ae8ca-ce0b-4649-975c-e70749a87dcd"
/>


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

* **New Features**
* Added a Database Connections preview highlighting live activity, query
blocking detection, session termination, and AI-assisted summaries.
* Added access to project-specific observability connections from the
preview.
* Added a Database Connections entry to the observability menu when
enabled.

* **Improvements**
* Updated feature previews and labels, including changes to “new” status
indicators.
  * Added controls to manage Database Connections preview visibility.

* **Bug Fixes**
* Improved blocker detection so results respect the selected role
filters.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-03 16:48:59 +08:00
Alaister YoungandAlaister Young 3f5ac679e0 fix(studio): redirect to feature preview route after enabling (#48637)
Enabling a feature preview that has a route (e.g. Column-level
privileges) closed the modal but never navigated to the feature's page
on the TanStack runtime (local + staging). The modal closed itself via a
nuqs query-param update *and* called `router.push` — the queued nuqs
flush navigates to the pathname it captured before the push, landing
after the redirect and reverting it. The Next runtime was unaffected
because the stock nuqs pages adapter patches the URL shallowly via the
history API instead of navigating.

**Changed:**

- When the enabled preview has a `getRoute`, skip the explicit
`toggleFeaturePreviewModal(false)` — `router.push(route)` navigates
without the `featurePreviewModal` param, which is what closes the modal.
One URL update instead of two racing ones; works on both runtimes.
- Previews without a route keep the explicit close (unchanged behavior).

## To test

- On a project page, open Feature Previews (avatar menu), select
**Column-level privileges**, click **Enable feature** → modal closes and
you land on `/project/{ref}/database/column-privileges` with the "We've
taken you to where you can try it out." toast (no bounce back to the
previous page)
- Repeat with **Disable Advisor rules** → lands on
`/project/{ref}/advisors/rules/security`
- Enable a preview without a route (e.g. **PG Delta Diff**) → modal
closes, stays on the current page, "It's now active across the
dashboard." toast
- Disable a preview → modal stays open, "disabled" toast, no navigation
- Verified locally on the TanStack runtime; worth a quick click-through
on the Vercel preview (Next runtime) too

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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved feature activation navigation to prevent conflicting URL
updates.
* Non-route features continue to close the preview modal and display the
activation confirmation.

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

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-08-03 15:39:48 +07:00
Danny White 73c9dbfa52 fix(studio): standardise custom icon weight (#48478)
## What kind of change does this PR introduce?

Bug fix and internal tooling update. Resolves FE-3472.

## What is the current behavior?

Custom Studio icons use inconsistent source stroke widths, and some
child-level styling prevents component props from overriding them. Mixed
custom and Lucide icon sets can therefore appear uneven.

## What is the new behavior?

Custom stroke icons use a root-level `stroke-width="1.5"`; fill-only
logos use `stroke="none"`. The build validates that contract and
regenerated components preserve existing exports and props.

Studio applies the same `1.5` weight across Reports categories and uses
one shared destination icon mapping in the replication selector,
destination rows and diagram.

| Before | After |
| --- | --- |
| <img width="418" height="516" alt="56398"
src="https://github.com/user-attachments/assets/6afa7042-e6be-40e7-9911-af2f61238c9d"
/> | <img width="390" height="550" alt="CleanShot 2026-07-30 at 17 12
37@2x"
src="https://github.com/user-attachments/assets/870f49cf-c8fa-40db-8be8-2eb5f264ff4a"
/> |
| <img width="510" height="734" alt="CleanShot 2026-07-30 at 17 19
28@2x"
src="https://github.com/user-attachments/assets/a5b2c088-dcd2-4907-976b-5820794d06e3"
/> | <img width="554" height="742" alt="CleanShot 2026-07-30 at 17 16
06@2x"
src="https://github.com/user-attachments/assets/ed3a77c4-5d94-4ca7-b9e4-1403b725a981"
/> |


## Testing

At 100% zoom, compare custom and Lucide icon weight in:

- Reports: **Add your first chart** and **Add block**
- Database > Replication: the destination selector, destination rows and
replication diagram
- Command menu (`⌘K`): **Search Database Tables**, **Search RLS
Policies**, **Search Edge Functions** and **Search Storage**
- Authentication > Users: right-click a user row and compare the
context-menu icons
- Database > Schema Visualizer: open a table node overflow menu
- A paused project: **Export your data > Download backups**

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

* **New Features**
* Added consistent destination icons across replication panels, rows,
and diagrams.
  * Updated instance health and metric icons for clearer identification.
* Standardized icon stroke weight and reduced default icon stroke
thickness.

* **Documentation**
* Clarified custom icon requirements, default properties, and validation
guidance.

* **Bug Fixes**
* Improved consistency of icon rendering across replication destinations
and reports.

* **Tests**
* Added coverage for icon SVG validation and replication destination
icon rendering.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-03 17:48:50 +10:00
Joshen Lim 2c53ca4a79 Support listing and reading custom reports from Assistant (#48530)
## Context

This is pre-requisite work for adding support to managing custom reports
from the Assistant. Planning to break this into a number of PRs, briefly
- Adding read support for custom reports
- Adding write support for custom reports
- Adding run support for custom reports
  - Should be able to infer data from the results then

This PR starts with adding support for listing and reading custom
reports from the Assistant

## Other changes involved
- Updates setting up of the home page report to have better title and
description
- Swaps the variant of the ToggleGroup in the SQL block for custom
reports as the default variant blends into the background color of the
PopoverContent

## To test
- [ ] Assistant should be able to list custom reports + read its
contents
<img width="428" height="755" alt="image"
src="https://github.com/user-attachments/assets/6a15b660-c0ee-4a06-984c-87eff3943eec"
/>


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

- **New Features**
- Added AI-assisted tools to list reports and retrieve report details,
including chart counts, layouts, configurations, and SQL-backed chart
information.
  - Added clearer empty-state messaging when no snippets are available.

- **Improvements**
- New homepage reports now use the name “Homepage Report” and include a
descriptive project-home summary.
  - Updated query controls with refreshed visual styling.
  - Improved content requests to support additional request context.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-03 13:59:50 +07:00
Danny White 022b374f2d show Stripe Projects errors inline (#48472)
## What kind of change does this PR introduce?

Bug fix.

## What is the current behavior?

Stripe Projects confirmation failures only appear in a toast.

The existing **Unable to load authorization** Admonition is a separate
error state shown when the account request itself cannot be loaded.

## What is the new behavior?

Confirmation failures remain visible below the authorisation actions,
clear on retry, and do not also trigger a toast. They use the shared
`InterstitialActionError`.

| Before | After |
| --- | --- |
| <img width="1024" height="759" alt="Authorize Stripe Projects
Supabase"
src="https://github.com/user-attachments/assets/83cb3144-9ddb-46b7-bfce-970497be61e2"
/> | <img width="1024" height="759" alt="Authorize Stripe Projects
Supabase"
src="https://github.com/user-attachments/assets/bccedde9-9935-457b-a980-0c80499f2f27"
/> |

## To test

These instructions visually check the after state on this branch.
Opening an invalid `ar_id` without the hardcodes only exercises the
existing load-error Admonition, which this PR does not change.

### After on this branch

1. In `apps/studio/pages/partners/stripe/projects/login.tsx`, replace
the `confirmationError` assignment with:
   ```tsx
const confirmationError = 'Failed to authorize Stripe Projects: Test
error'
   ```
2. In the same file, replace the block beginning with `const linkedOrg`
and ending with `interstitialDescription` with:
   ```tsx
   const linkedOrg = { name: 'Example Organization' }
   const emailMatches = true
const displayName = primaryEmail ?? username ?? 'reviewer@example.com'
   const isPending = false
   const isConfirmed = false
   const isConfirming = false
   const isError = false
   const showAuthorizationState = true
   const interstitialDescription =
     'This will create an organization on your behalf in Supabase'
   ```
3. While signed in locally, open
`http://localhost:8082/partners/stripe/projects/login?ar_id=test`.
4. Confirm the error appears below **Authorize Stripe Projects** and
**Cancel**. No real Stripe request is required.
5. Revert both temporary edits.

### Before on master (optional)

1. Check out `master`.
2. In `apps/studio/pages/partners/stripe/projects/login.tsx`, replace
the block beginning with `const linkedOrg` and ending with
`interstitialDescription` with the same block from step 2 above. Do not
add `confirmationError`.
3. While signed in locally, open
`http://localhost:8082/partners/stripe/projects/login?ar_id=test`.
4. Click **Authorize Stripe Projects**.
5. Confirm the failed confirmation appears in a toast beginning **Failed
to confirm account request**.
6. Revert the temporary edit before changing branches.

## Additional context

Stacked on #48471.

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

## Summary by CodeRabbit

* **Bug Fixes**
* Authorization errors during Stripe Projects login are now displayed
inline in both authorization flows.
  * Authorization remains available after a failed confirmation attempt.
* Failed authorization requests no longer trigger an additional toast
notification.
  * Previous errors are cleared when retrying authorization.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-03 11:48:46 +07:00
Danny White e7796315d2 fix sheets stealing focus (#48521)
## What kind of change does this PR introduce?

Bug fix. Resolves DEPR-539.

## What is the current behavior?

When a focused child unmounts, Radix can move focus to the Sheet wrapper
and break the expected tab order. Several callsites suppress the
wrapper's tabindex individually.

## What is the new behavior?

Sheet still focuses its first interactive child when opened, but the
wrapper itself is no longer focusable by default. Callers can opt in
with an explicit `tabIndex` when needed.

## Additional context

### Testing

Compare this Studio experience on both this branch and `master`:

1. Open any project with an Edge Function.
2. Go to **Edge Functions**, open the function, then click **Test**.
3. Under **Headers**, click **Add Headers**. Click the first header key
input, then Tab slowly through the header inputs and remove buttons.

On `master`, focus can jump to the whole Sheet. On this branch, focus
stays on the controls in order.

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

## Summary by CodeRabbit

* **Bug Fixes**
  * Improved keyboard focus behavior across sheets and panels.
* Sheets now focus the first available interactive element when opened,
without adding unnecessary focus targets.
* Preserved support for programmatic focus and prevented focus from
unexpectedly moving to the sheet when focused content is removed.
* Updated authentication, integrations, connection, logging, storage,
and other sheet interfaces consistently.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-03 10:01:47 +10:00
Danny WhiteandJoshen Lim 7a77760a10 fix(studio): confirm before discarding dirty replication destination forms (#48522)
## What kind of change does this PR introduce?

Bug fix (dirty form dismissal for Replication destination sheets), plus
small docs/skill updates so agents pick up the existing modality
pattern.

## What is the current behavior?

Closing the Add/Edit destination sheet (Cancel, Escape, or backdrop)
discards in-progress form state with no confirm. Same for the nested
Create publication sheet.

## What is the new behavior?

Dirty closes go through `useConfirmOnClose` +
`DiscardChangesConfirmationDialog`, matching other Studio sheets.
Successful submit still closes without prompting.

Also: skills + `forms.mdx` now point at Modality “Dirty form dismissal”.

| After |
| --- |
| <img width="1024" height="759" alt="Replication Database Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/6f568a2a-c76b-442a-b592-d638bb36adc4"
/> |

### How to test

1. Studio → Database → Replication → **Add destination** (any pipelines
type with access).
2. Change a field so the form is dirty.
3. Try Cancel, Escape, and backdrop click → discard dialog appears;
**Keep editing** stays open; **Discard changes** closes.
4. Submit successfully with a valid config → sheet closes with no
discard dialog.
5. Repeat for **Edit destination** from a destination row menu.
6. Optional: Add destination → create a new publication from the
publication picker → dirty that nested sheet and dismiss the same way.
7. Optional: Add destination → Read Replica → change region → dismiss →
discard dialog; deploy still closes without prompting.

## Additional context

Sheet owns the close guard; forms report dirty via a ref because RHF
lives in the child. Nested `NewPublicationPanel` wires the guard
locally.

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

- **New Features**
- Added unsaved-changes tracking to replication destination and
publication forms.
- Added confirmation prompts before closing forms with unsaved changes
via Cancel, Escape, or backdrop dismissal.
- Forms now reset appropriately after successful submission or confirmed
dismissal.

- **Documentation**
- Updated form and UI pattern guidance to document dirty-form dismissal
behavior for sheets and dialogs.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-08-03 10:00:41 +10:00
Danny White eef0f57309 fix(studio): clarify Storage columns keyboard focus and selection (#48222)
## What kind of change does this PR introduce?

Accessibility / UX fix
([DEPR-630](https://linear.app/supabase/issue/DEPR-630)).

## What is the current behavior?

In Storage **As columns** view, keyboard select is unclear: the checkbox
stays hidden until hover, so Tab/Space selection is hard to see. The row
actions (three dots) menu also shows a browser default blue outline on
Tab.

## What is the new behavior?

Same icon/checkbox swap as list/hover, but also on keyboard focus:
- Checkbox replaces the icon on hover, `:focus-within`, and when
selected (no layout shift)
- Checkbox becomes visible when focused via keyboard (without needing
hover)
- Row gets an inset outline while the checkbox is focused
- Folders have no checkbox (non-focusable spacer only)
- Row actions trigger uses `focus-ring` instead of the browser blue
outline

| Before | After |
| --- | --- |
| <img width="1046" height="362" alt="CleanShot 2026-07-31 at 14 37
47@2x"
src="https://github.com/user-attachments/assets/9b827627-17e6-49a6-87a3-1253b4cef1da"
/> | <img width="1046" height="390" alt="CleanShot 2026-07-31 at 14 37
13@2x"
src="https://github.com/user-attachments/assets/2fd2b426-a8e2-4fda-b1ba-4df728b7b2f1"
/> |
| _Checkbox focussed but not visually shown_ | _Checkbox focussed and
visually shown_ |

## To test

1. Open the **Studio preview** for this PR.
2. Go to **Storage → Files** → open a bucket with several files.
3. Set view to **As columns**.
4. Tab until a **file** checkbox is focused.

**Expect:**
- Icon is replaced by the checkbox (same slot; neighbouring row icons
should not look shifted)
- Checkbox visible without hovering
- Row shows an inset outline

5. Press **Space** to select. Checkbox stays in the icon slot; selection
background applies.
6. Hover another file. Same icon to checkbox swap as before.
7. Tab to the three-dot actions control on a row. Expect the shared
focus ring (not a blue browser outline); the menu icon should become
visible.
8. Folders: no checkbox in the tab order; click icon/name still opens
the folder.
9. Smoke **As list**. Same swap behaviour.

## Additional context

From Kemal's DEPR-621 review.
2026-08-03 09:59:19 +10:00
Danny White f7454cf94e feat(studio): oauth impersonation warning on authorize (#48162)
## What kind of change does this PR introduce?

Feature + docs. Stacked on #48161 (logo contract /
[DEPR-604](https://linear.app/supabase/issue/DEPR-604/define-connect-logo-asset-and-variant-contract)).

## What is the current behavior?

After #48161, curated logos only resolve from allowlisted `redirect_uri`
hosts. A requester can still present a trusted partner **name** (e.g.
Claude) while redirecting to an unrelated remote host; the UI shows
Supabase alone but does not call out the mismatch.

## What is the new behavior?

- Shows a caution admonition when the requester name looks like a
trusted partner (Claude, Cursor, ChatGPT/OpenAI, Perplexity) but
`redirect_uri` is a **remote** host outside that partner's allowlist.
- Skips localhost / loopback redirects for the caution (common for local
MCP clients); those still get curated logos when the name matches a
trusted partner.
- Highlights the footer redirect URL in warning colour when the caution
is shown.
- Documents the behaviour in the Connect interstitials pattern.

### To test

Real MCP clients (Claude, Cursor, etc.) only send users to
**production** `/authorize`, so you cannot drive a local or preview
Studio build from those tools. Use a Network override instead:

1. Start Studio and sign in (`pnpm dev:studio`, or use the [Vercel
preview](https://studio-staging-git-danny-oauth-impersonation-warning-supabase.vercel.app/)).
2. Open `/dashboard/authorize?auth_id=foo` (any `auth_id` is fine; the
real response may 404) ([Vercel
preview](https://studio-staging-git-danny-oauth-impersonation-warning-supabase.vercel.app/dashboard/authorize?auth_id=foo)).
3. DevTools → **Network** → find `GET
…/platform/oauth/authorizations/foo` (or whatever id you used).
4. Right-click → **Override content** (enable Local Overrides / pick a
folder if prompted).
5. Paste one of the payloads below (status **200**), save, then reload
the authorize page.
6. Keep `expires_at` in the future so the request does not look expired.

#### Impersonation caution (trusted name + remote non-allowlisted
redirect)

Expect:

- Supabase alone (no curated Claude mark)
- Caution: “Redirect does not match this app name”
- Footer redirect URL in warning colour

```json
{
  "name": "Claude",
  "website": "https://claude.ai",
  "icon": null,
  "domain": "claude.ai",
  "redirect_uri": "https://evil.com/callback",
  "expires_at": "2099-01-01T00:00:00.000Z",
  "scopes": ["organizations:read", "projects:read"],
  "approved_at": null,
  "registration_type": "dynamic"
}
```

| Preview |
| --- |
| <img width="764" height="958" alt="Authorize Claude Supabase"
src="https://github.com/user-attachments/assets/e6eee016-5710-41ba-9925-87511e009e22"
/> |

#### Localhost MCP: no caution

Expect curated Claude + Supabase pair (name match + loopback), **no**
caution, normal footer colour. Local MCP clients often use loopback
redirects.

```json
{
  "name": "Claude",
  "website": "https://claude.ai",
  "icon": null,
  "domain": "claude.ai",
  "redirect_uri": "http://127.0.0.1:42813/callback",
  "expires_at": "2099-01-01T00:00:00.000Z",
  "scopes": ["organizations:read", "projects:read"],
  "approved_at": null,
  "registration_type": "dynamic"
}
```

| Preview |
| --- |
| <img width="764" height="958" alt="Authorize Claude Supabase"
src="https://github.com/user-attachments/assets/79f36865-3c8e-43e5-9490-24288efc74aa"
/> |

#### Legitimate curated partner: no caution

Expect curated Cursor + Supabase pair, no admonition, normal footer
colour.

```json
{
  "name": "Cursor",
  "website": "https://cursor.com",
  "icon": null,
  "domain": "cursor.com",
  "redirect_uri": "https://cursor.com/callback",
  "expires_at": "2099-01-01T00:00:00.000Z",
  "scopes": ["organizations:read", "projects:read"],
  "approved_at": null,
  "registration_type": "dynamic"
}
```

| Preview |
| --- |
| <img width="764" height="958" alt="56164"
src="https://github.com/user-attachments/assets/412333a3-a74f-42eb-9f63-d56b6a26bf91"
/> |

#### Unrelated name + remote redirect: no caution

Expect Supabase alone (no icon), no admonition.

```json
{
  "name": "Acme Tools",
  "website": "https://evil.com",
  "icon": null,
  "domain": "evil.com",
  "redirect_uri": "https://evil.com/callback",
  "expires_at": "2099-01-01T00:00:00.000Z",
  "scopes": ["organizations:read", "projects:read"],
  "approved_at": null,
  "registration_type": "dynamic"
}
```

| Preview |
| --- |
| <img width="764" height="958" alt="Authorize Acme Tools Supabase"
src="https://github.com/user-attachments/assets/dab24817-5c26-4aa1-a447-796c4af5868b"
/> |

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

## Summary by CodeRabbit

- **New Features**
- Added an OAuth caution when a requester name matches a known partner
but uses an unapproved remote redirect host.
- Improved trusted partner logo selection for localhost/loopback
redirects while preserving safe fallbacks for untrusted redirects.

- **Documentation**
- Updated Connect interstitial guidance for redirect mismatches and
localhost/loopback behavior.

- **Tests**
- Expanded coverage for caution visibility, messaging, localhost logo
pairing, and trusted redirect scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-02 23:57:27 +00:00
Danny WhiteandJoshen Lim 2b26da360e show API and AWS authorization errors inline (#48471)
## What kind of change does this PR introduce?

Bug fix and design-system update.

## What is the current behavior?

API authorisation and AWS Marketplace action failures use transient
toasts. The inline action-error treatment introduced for organisation
invitations is implemented locally.

## What is the new behavior?

Action failures remain visible below their actions and clear on retry or
organisation change.

This PR adds a shared `InterstitialActionError` component, updates the
connect-interstitial guidance and demo to use it, and retroactively
applies it to `OrganizationInvite`.

Mutation errors are read directly from their mutation hooks rather than
copied into component state.

| Before | After |
| --- | --- |
| <img width="1024" height="759" alt="Authorize API Access Supabase"
src="https://github.com/user-attachments/assets/9520aff3-496d-44b1-b5b5-02b331872e32"
/> | <img width="1024" height="759" alt="Authorize API Access Supabase"
src="https://github.com/user-attachments/assets/2d09e337-573a-45b5-80ac-7c546ed1401d"
/> |
| <img width="1024" height="759" alt="Link AWS Marketplace Supabase"
src="https://github.com/user-attachments/assets/bb1a4581-0399-432a-8037-d84ab15ecc4b"
/> | <img width="1024" height="759" alt="Link AWS Marketplace Supabase"
src="https://github.com/user-attachments/assets/f9d43cd9-c661-42ed-91c0-e45ccb9c19f5"
/> |

_Note since taking that AWS screenshot: the error message now replaces
the prior footer text. I.e. “Learn more about billing through AWS.” is
now gone when an error message is present._

## To test

### AWS Marketplace

For a visual check with local Studio running:

1. In
`apps/studio/components/interfaces/Organization/CloudMarketplace/AwsMarketplaceOnboarding.tsx`,
immediately before `if (!buyerId)`, temporarily add:
   ```tsx
   return (
     <AwsMarketplaceInterstitial>
       <div className="flex flex-col gap-5">
         <InterstitialAccountRow displayName="reviewer@example.com" />
         <OrganizationSelector
           organizations={[
             {
               name: 'Example Organization',
               slug: 'example-organization',
               plan: { id: 'pro', name: 'Pro' },
             } as Organization,
           ]}
           selectedSlug="example-organization"
           disabled
           onSelect={() => undefined}
         />
         <div className="flex flex-col gap-5">
           <div className="flex flex-col gap-2">
             <Button variant="primary" block>
               Link organization
             </Button>
<InterstitialActionError error="Failed to link organization: Test error"
/>
           </div>
<p className="text-center text-xs text-foreground-lighter text-balance">
<InlineLink href={`${DOCS_URL}/guides/platform/aws-marketplace`}>
               Learn more
             </InlineLink>{' '}
             about billing through AWS.
           </p>
         </div>
       </div>
     </AwsMarketplaceInterstitial>
   )
   ```
2. Open `http://localhost:8082/aws-marketplace-onboarding?buyer_id=test`
while signed in.
3. Confirm the error appears below **Link organization** with a divider.

Remove the temporary return before committing anything.

### API authorization

For a visual check with local Studio running:

1. In
`apps/studio/components/interfaces/ApiAuthorization/ApiAuthorization.Valid.tsx`,
immediately before `if (isLoading)`, temporarily add:
   ```tsx
   return (
     <ApiAuthorizationMainView
       approvalState="indeterminate"
       form={form}
       requester={{
         name: 'Test App',
         website: 'https://example.com',
         icon: null,
         domain: 'example.com',
         scopes: [],
         expires_at: '2099-01-01T00:00:00.000Z',
         approved_at: null,
         registration_type: 'static',
       }}
       organizations={{
         _tag: 'success',
         organizations: [
{ name: 'Example Organization', slug: 'example-organization' } as
Organization,
         ],
       }}
       requestedOrganizationSlug={undefined}
       actionError="Failed to authorize request: Test error"
       onOrganizationChange={() => undefined}
       onApprove={() => undefined}
       onDecline={() => undefined}
     />
   )
   ```
2. Open `http://localhost:8082/authorize?auth_id=test` while signed in.
3. Confirm the error appears below the authorisation actions with a
divider.

Remove the temporary return before committing anything.


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

* **New Features**
* Added consistent inline error messaging for authorization,
organization invitations, and AWS Marketplace onboarding.
* Error messages now appear within the relevant interstitial and replace
supporting footer content until resolved.
  * Retry and action buttons remain available after failed operations.
* **Bug Fixes**
* AWS Marketplace linking failures no longer trigger toast
notifications.
  * Billing guidance is hidden while an onboarding error is displayed.
* **Tests**
* Added coverage for authorization, cancellation, and AWS Marketplace
failure states.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-08-03 09:43:23 +10:00
Sean Oliver e88a3723e1 feat(studio): add PostHog session replay with masked-by-default policy (#48515)
## 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?

Telemetry feature.

## What is the current behavior?

- Session replay is off, and nothing in the code keeps it off.
- `packages/common/posthog-client.ts` sets no recording config at all.
- So PostHog's project setting alone decides, for every app sharing that
project.
- Studio, www and docs share one project.
- Studio shows customer data almost everywhere: SQL editor, table rows,
connection strings, API keys.
- posthog-js masks inputs by default. It does not mask rendered text.
- [GROWTH-1055](https://linear.app/supabase/issue/GROWTH-1055)

## What is the new behavior?

- `posthogClient.init()` takes a masking config, and disables recording
when it gets none.
- Studio passes one behind `NEXT_PUBLIC_POSTHOG_SESSION_REPLAY`.
- Every other app passes nothing, so it never loads the recorder.
- Studio masks all text and all inputs.
- `data-ph-capture="true"` opts one element's text back in. Unused so
far.
- Canvas is blocked, because it records as images that text masking
cannot reach.
- Query strings and fragments are stripped from recorded URLs, where
auth callbacks carry tokens.
- Request and response bodies are never recorded.
- Console logs are never recorded, since masking only reaches DOM text.
- Masking is set in code, so PostHog's settings cannot loosen it.
- Consent gating is unchanged. Nothing records before a user accepts.

## Additional context

- Recording needs three things: this env var, the PostHog project
toggle, and user consent.
- All three are off or unset, so merging this changes nothing at
runtime.
- `NEXT_PUBLIC_POSTHOG_SESSION_REPLAY` goes into Vercel on Preview scope
first, to test on a preview build.
- Production scope comes later, once we are ready to record there.
- `NEXT_PUBLIC_*` is inlined at build time, so each scope needs a
rebuild afterwards.
- Text inside HTML attributes (`title`, `alt`, `href`) is still recorded
as-is.
- posthog-js exposes no hook for masking attributes, so covering it
needs `ph-no-capture` per component.
- Staging has no server-side masking config, so that is where this gets
verified.
- Plan: enable recording on staging, verify masked text on a preview,
then decide on production.
- Network timing stays on for the dashboard performance work. Payloads
stay off.
- Tests cover both masking functions and the config values.

## Screenshots


https://github.com/user-attachments/assets/aa064a04-f977-4453-a3da-2fe0cdcead08

<img width="889" height="651" alt="CleanShot 2026-07-31 at 10 13 43"
src="https://github.com/user-attachments/assets/f1d07946-fd68-42b2-89f1-d201bc605638"
/>



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

## Summary by CodeRabbit

* **New Features**
  * Added privacy-focused session replay for Studio.
* Text and form inputs are masked by default, with explicit opt-in
capture.
  * Network recordings remove query strings and fragments.
  * Headers, request bodies, canvas data, and console logs are excluded.

* **Bug Fixes**
  * Improved whitespace and capture-attribute handling during masking.
* Session replay remains disabled without a masking policy or explicit
enablement.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-31 15:37:05 -07:00
Charis ec64135f9d perf(pg-meta): scope column privileges query to a single table (#48553)
## 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?

Performance improvement

## What is the current behavior?

The column privileges page in Studio only ever renders one table, but
the underlying query still `aclexplode`s every column in the whole
schema and filters the result client-side.

## What is the new behavior?

Adds a scoped SQL path that prunes `pg_class`/`pg_namespace` to the
requested schema+table before exploding ACLs, gated behind the
`pgMetaScopedIntrospection` flag, with a plan-guard test asserting
`pg_class`/`pg_attribute` stay index-driven. Studio's query hook and
cache keys now thread the selected table through so column-privilege
invalidation and cold-load races are scoped correctly, and the page
fetches per-table instead of per-schema.

## Additional context

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

## Summary by CodeRabbit

* **Improvements**
* Column privileges are now scoped to the selected schema and table for
more accurate results.
* Changing schemas automatically updates the table selection and
refreshes the displayed privileges.
* Privilege updates now refresh only the relevant schema, table, and
column data.
* Loading states are handled more accurately when no table is selected.

* **Bug Fixes**
* Improved consistency between scoped and unscoped column privilege
results, including table-, column-, and grant-option privileges.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-31 15:26:37 -04:00
ChloeGarciaMillerand e241a21a9a fix: ESLint errors relating to accessibility in table editor, API Key and Access Token (#48479)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Added aria-label attributes and Tooltip to buttons

## What is the current behavior?

alt attributes and Tooltip were missing

## What is the new behavior?

Buttons have now aria-label attributes and Tooltip.

## Additional context

No visual changes have been made.


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

* **Accessibility Improvements**
* Added tooltips and improved accessible labeling for filter removal,
sort controls, and action menu triggers.
* Enhanced “More actions”/“More options” tooltips and aria-labels for
API keys and access tokens.
* Updated token scope selection and token banner close actions to use
clearer tooltip messaging.
* Wrapped panel close control with a tooltip and added an aria-label for
clearer screen reader support.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-31 18:05:41 +02:00
kemal.earth bc95a2f19a fix(studio): edge func exec time formatting in reports (#48539)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Fixes Edge Function Execution Time chart within our observability
reports time formatting. This also fixes the non-hovered state which
would lose the `ms` formatting.

| Before | After |
|--------|--------|
| <img width="2160" height="652" alt="cleanshot_2026-07-29_at_02 15
53_2x"
src="https://github.com/user-attachments/assets/cfd6dbc2-f283-4379-a133-581c76990cb5"
/> | <img width="797" height="314" alt="Screenshot 2026-07-31 at 14 30
48"
src="https://github.com/user-attachments/assets/f5f1ace5-b6ef-43db-aebd-e10d31631013"
/> |



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

## Summary by CodeRabbit

* **New Features**
* Improved execution-time chart formatting with clearer millisecond
values, thousands separators, and configurable precision.
* Chart highlights now support custom value formatting alongside
existing number, percentage, and byte formats.

* **Bug Fixes**
  * Non-finite execution-time values now display safely as `0ms`.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-31 16:20:37 +01:00
Charis 50e1eb7436 chore(eslint): bump eslint-config-next to v16 for useEffectEvent (#48458)
## 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?

Chore / build (ESLint config upgrade + lint cleanup).

## What is the current behavior?

`eslint-plugin-react-hooks` v5 (pulled in transitively by
`eslint-config-next` v15) doesn't recognize stable `useEffectEvent`, so
every effect that calls an effect-event handler needs an `eslint-disable
react-hooks/exhaustive-deps` to silence a false positive. There are 30
such dead disables across Studio.

## What is the new behavior?

Bumps `eslint-config-next` to v16, which pulls in
`eslint-plugin-react-hooks` v7 whose `exhaustive-deps` understands
`useEffectEvent`, and removes the 30 now-dead disable directives (and
their orphaned explanatory comments).

Supporting changes:

- **Flat-config migration**: v16 is a native flat-config array (v15 was
eslintrc), so `eslint-config-supabase` now spreads it directly instead
of bridging through `FlatCompat`.
- **React Compiler rules off**: v16 enables react-hooks v7's
`recommended`, which layers the React Compiler lint rules on top of the
two classic rules. These are switched off (derived dynamically from what
next enables) to keep this change scoped to the `exhaustive-deps`
improvement.
- **Plugin-registration fallout** (v16 scopes plugin registration to a
file glob rather than registering globally like FlatCompat did): stop
re-registering `@typescript-eslint` (shared) and `jsx-a11y` (studio);
scope our react / react-hooks / jsx-a11y rule overrides (studio, www) to
v16's plugin glob so they don't error on files outside it (e.g. `.cjs`).
- **Lint surface preserved**: v16's glob newly includes `.mts`/`.cts`
(v15 didn't lint them), which surfaced pre-existing errors in tooling
scripts. The shared config keeps the prior surface by leaving
`.mts`/`.cts` unlinted; linting them is left as a separate change.
- **Ratchet**: rebaselines `@tanstack/query/exhaustive-deps` 9 → 89. v15
forced next's `@babel/eslint-parser` onto `.ts` files, hiding these
deps; v16 parses `.ts` with `@typescript-eslint/parser` and correctly
surfaces the intentional `connectionString`-excluded-from-`queryKey`
pattern. Worth a follow-up to review whether any are real
cache-correctness bugs.
- Drops three now-dead devDeps from `eslint-config-supabase`:
`@eslint/eslintrc`, `@eslint/js`, `@typescript-eslint/eslint-plugin`.

Verified locally: `turbo run lint` → 7/7 packages pass with 0 errors;
Studio `lint:ratchet` passes; Prettier clean on changed files; typecheck
unaffected.

## Additional context

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

## Summary by CodeRabbit

* **Chores**
* Refined linting configuration and removed outdated lint suppressions
across Studio.
* Updated Next.js linting support and refreshed related development
configuration.
  * Expanded lint baseline coverage for query-related code.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-31 09:01:05 -04:00
Joshen Lim fd67a8014f Joshen/fe 4018 bug gh branch validation in branch modal fails silently if (#48432)
## Context

Realised that if the project has a GH integration, but the user's
account is not connected to GH - the branch validation in the "Sync with
Git Branch" field will not work. The Edit branch modal also obfuscates
the error being returned from the validation API so its not clear what
the issue is
<img width="500" alt="image"
src="https://github.com/user-attachments/assets/739dfe7c-8920-4edf-a751-63d7f6273db4"
/>

Opting to show an "Authorize" CTA for this scenario so it's clear from
the user's POV what to do (Refer to "To test" below for screenshots)


## To test

- [ ] Verify that on an account which isn't connect to GH + project with
no GH integration - CTA is as per normal ("Configure") which should
direct you to the settings -> integrations page (Same for edit branch)
<img width="500" alt="image"
src="https://github.com/user-attachments/assets/9a010fde-8ab0-43d6-b5c9-ced9fed1426e"
/>
<img width="500" alt="image"
src="https://github.com/user-attachments/assets/d129cccf-7238-4305-913b-0cf78c7dcc26"
/>

- [ ] Set up a GH integration and check Create / Edit branch - the
branch input field should work with proper branch name validation
<img width="500" alt="image"
src="https://github.com/user-attachments/assets/4d643956-2d11-406b-b198-193f3221b7a9"
/>

- [ ] Now go to Account settings and remove the GH connection, then
check the Create / Edit branch modals - should have the "Authorize" CTA
(instead of the input field)
<img width="500" alt="image"
src="https://github.com/user-attachments/assets/ac152c0d-2e9c-4d89-95bc-36127c0fc8df"
/>
<img width="500" alt="image"
src="https://github.com/user-attachments/assets/d1f50d38-d801-4546-96fd-8cf3b5d0f805"
/>




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

* **New Features**
* Added a “Sync with a GitHub branch” connection entry with an inline
authorize flow.
* Integrated GitHub authorization awareness into branch create/edit
modals so users are guided to authorize or proceed to syncing.
* **Bug Fixes**
* Unified loading, success, and error handling for GitHub
authorization/connection checks across create and edit flows.
  * Improved Git branch validation messaging to show cleaner error text.
* **Accessibility/UX**
* Updated modal UI text and added an explicit label for the “Include
data” toggle.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-31 16:52:12 +07:00
Pamela Chia c4c58ef3e3 feat: remove pandadoc dpa request flow (#48525)
Terms of Service v3 (effective August 1, 2026, #48482) incorporates the
Data Processing Addendum by reference, so customers no longer sign a
separate DPA. Legal confirmed the PandaDoc signing flow can go;
previously signed DPAs remain binding. This removes the frontend flow
only. I'll remove the platform endpoint (`POST
/platform/organizations/{slug}/documents/dpa`) separately once the
PandaDoc contract conversation wraps.

**Changed:**

- **Dashboard DPA card no longer requests PandaDoc documents**: the
Request DPA button and confirm modal are replaced with a View DPA link
to the canonical legal page, with evergreen copy explaining the DPA is
part of the Terms. Tracked via the same `document_view_button_clicked`
event the other document cards use.
- **Legacy `/legal/dpa` page retired**: the page told users to request a
signed DPA from the dashboard, which no longer exists. It now
permanently redirects to
`/legal/customer-resources/data-processing-addendum` (the follow-up
already flagged in #48483), and the footer link is removed. The
`dpa_pdf_opened` and `dpa_request_button_clicked` events are removed
with their last call sites. The latest privacy version links the
canonical page directly; archived v1/v2 keep their original `/legal/dpa`
link, served by the redirect.
- **Orphaned DPA PDFs removed**: the four dated `Supabase+DPA+*.pdf`
files under `/downloads/docs` had zero remaining references once the
signing flow is gone. No redirect: nothing links these URLs, so they
404.
- **Subscription tracking**: the subprocessor updates form now fires
`www_subprocessor_updates_subscribed` on successful submit, so we can
measure uptake of the notification list that replaces per-customer DPA
emails.

## To test

Verified on the Vercel previews (Playwright):

- [x] Studio: `/org/_/documents` shows the DPA card with the
incorporation copy and a working View DPA link (href = canonical page);
no Request DPA button, no PandaDoc mention; TIA/SOC2/ISO27001/HIPAA
cards unaffected
- [x] www: `/legal/dpa` permanently redirects to
`/legal/customer-resources/data-processing-addendum`; footer no longer
shows DPA; zero console errors
- [x] www: subscribing on the subprocessor page succeeds (200 from the
form route, profile created with topic_4) and fires
`www_subprocessor_updates_subscribed` (201 from the telemetry endpoint);
test profile unsubscribed afterwards
- [x] www: `/downloads/docs/Supabase+DPA+260601.pdf` returns 404 with no
redirect; DPA card copy verified without the effective date

## Linear

- fixes GROWTH-1068
2026-07-31 16:18:25 +08:00
Pamela Chia 4ae0c08967 feat: tos v3 update banner + publish subprocessor list (#48524)
Terms of Service v3 (effective August 1, 2026, #48482) incorporates the
Data Processing Addendum by reference, and Legal asked for an in-app
notice announcing the change. The subprocessor list page that the new
Terms, DPA, and notice all point at was merged as an intentionally
hidden draft (#48100) and never un-hidden.

**Changed:**

- **Dashboard ToS-update banner**: re-enables `BannerTOSUpdate` with the
v3 copy provided by Legal (DPA incorporation, subprocessor list
location, fees provisions). New expiry (August 29) and a new
localStorage key, since anyone who dismissed the May v2 banner would
otherwise never see this one.
- **Subprocessor list page published**: removes `noindex,nofollow` and
links the page from the Legal Hub index, so the page customers are told
to subscribe on is actually discoverable.
- **Studio e2e fixture updated**: the global Playwright fixture
suppressed the banner via the old localStorage key; with the gate live
again it would have rendered the banner into every e2e run. It now sets
the new key.

## To test

Verified on the Vercel previews :

- [x] Studio: banner renders on dashboard load with the Notice badge and
new copy; Learn more dialog shows the three changes with correct hrefs
(DPA page, subprocessor list, /terms); Understood dismisses and persists
across reload via `terms-of-service-update-2026-08-01`
- [x] www: `/legal` lists Subprocessor List under Customer Legal
Resources; `/legal/customer-resources/subprocessor-list` serves `robots`
meta `index,follow` and renders the download button + subscribe form;
zero console errors on all tested pages

## Linear

- fixes GROWTH-1067


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

## Summary by CodeRabbit

* **New Features**
* Added a publicly accessible Subprocessor List to the legal resources.
* Updated the Terms of Service notice to reflect the August 1, 2026
update, including data processing, subprocessors, fraud prevention, and
consumer provisions.

* **Documentation**
* Made the Subprocessor List discoverable through standard search
indexing and the legal resources page.
* Extended the Terms of Service banner availability through August 29,
2026.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-31 15:49:08 +08:00
fadymak e6b8725571 feat(account): require a user to name their TOTP authenticator (#48493)
Currently it's an autogenerated name. We want users to explicitly enter
a name for their authenticator so that:

- They can remember that they took the action of registering an
authenticator
- They can see a meaningful name during sign-in if they have multiple
TOTP authenticators

<img width="536" height="269" alt="Screenshot 2026-07-30 at 16 05 10"
src="https://github.com/user-attachments/assets/e43de27f-b4ca-4d4f-969a-578267eeebe4"
/>

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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved TOTP enrollment: confirmation is no longer enabled unless an
authenticator app name is provided (validated beyond whitespace).

* **UI Improvements**
* Updated the authenticator app name label/description, added an example
placeholder, and auto-focused the field when the confirmation step
appears.
* Refined the on-screen guidance for suggested authenticator apps (e.g.,
Google Authenticator or 1Password).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-31 09:16:41 +02:00
Joshen Lim 0e92a9574c Joshen/fe 3932 support branching conversations (#48519)
## Context

Adds support for branching off from an Assistant's Response - which
creates a new chat with all the previous messages including from where
we're branching off from
<img width="204" height="97" alt="image"
src="https://github.com/user-attachments/assets/0b171ae6-f2b4-4b58-87fa-0010ad45f777"
/>

Branched conversations will have an indication of where it was branched
off from
<img width="404" height="427" alt="image"
src="https://github.com/user-attachments/assets/bed8502f-3f83-4f76-bc00-feac86fa57a6"
/>


## Other changes
- Also added support for copying an Assistant's Response
<img width="190" height="115" alt="image"
src="https://github.com/user-attachments/assets/5e4aa0b8-eb6e-485f-80c0-3028b95720f7"
/>


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

* **New Features**
  * Branch conversations from assistant messages into a new chat.
  * View the originating conversation and navigate back to it.
  * Copy assistant message content with visual confirmation.
  * Access branching and copying actions from message controls.
* **UI Updates**
  * Added “Branched from” indicators for branched conversations.
  * Updated the assistant disclaimer text to “The Assistant.”
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-31 13:38:02 +07:00
Alaister YoungandAlaister Young fc5e03f9e3 [FE-4019] fix(studio): direct-only connection strings with SSL params for Multigres (#48433)
Multigres (high-availability) projects only accept TLS connections with
direct SSL negotiation, and they don't support connection pooling at all
— neither Supavisor nor the dedicated PgBouncer pooler exists for them.
Studio previously showed pooler connection strings that would fail with
"server closed the connection unexpectedly". This PR makes every
connection-string surface direct-only for HA projects and appends
`?sslmode=require&sslnegotiation=direct` to the examples. Non-HA
projects are unchanged.

Addresses
[FE-4019](https://linear.app/supabase/issue/FE-4019/append-ssl-params-to-multigres-connection-string-examples-in-ui)

**Changed:**

- `buildConnectionStringPooler` gets an HA branch that collapses every
slot in the bag to the direct connection string with the SSL params
appended (mirroring the existing CLI branch, which also has no pooler) —
dedicated slots come back `undefined` and
`ipv4SupportedForDedicatedPooler` is forced off. Since HA never reaches
the pooler layout anymore, the earlier per-URI SSL-append logic on
pooler strings is removed
- `useConnectState` coerces `connectionMethod` to `direct` and
`useSharedPooler` to `false` for HA projects. The Connect sheet restores
the last-used method from localStorage shared across projects, so a
"Transaction pooler" selection made on a regular project could otherwise
leak pooler-flavored notices, badges, and telemetry into an HA project
- Prisma and Drizzle ORM tabs get an HA branch:
`DATABASE_URL`/`DIRECT_URL` both use the direct connection, no
`?pgbouncer=true` appended, with a comment explaining Multigres doesn't
support pooling. The 5-arm nested ternaries in both files are flattened
into `getEnvCode` helpers that switch on a shared
`resolveOrmConnectionScenario` helper (`OrmConnection.utils.ts`), so the
deployment-mode/HA branching lives in one tested place and each file
keeps only its own formatting
- The PgBouncer and Supavisor config queries are disabled (`enabled:
!isHighAvailability`) in the Connect sheet — those endpoints serve
pooler config that doesn't exist on Multigres
- `parseConnectionParams` keeps the URI's query string in a new `search`
field so formats rebuilt from parsed parts can carry it
- psql switches from the `-h/-p/-d/-U` flag form to the quoted-URI form
when query params are present (flags can't express them; psql still
prompts for the password)
- JDBC appends the params using pgJDBC's casing (`sslNegotiation`,
supported since 42.7.4)
- Prisma's `?pgbouncer=true` appends are query-aware (join with `&` when
the URI already has a query string) via a new
`appendConnectionStringParams` helper
- The project home "Direct connection string" copy item also appends the
params for HA projects

**Added:**

- Unit tests for the HA collapse behavior (all slots direct, dedicated
config and IPv4 add-on ignored, no SSL params on non-HA output), the
`useConnectState` coercion, the psql/JDBC builders (moved from
`content.tsx` into `ConnectionString.utils.ts` so they're testable), and
`resolveOrmConnectionScenario` (every deployment-mode/HA/pooler branch)

**Known gaps (left out deliberately):**

- The grid ExportDialog psql/pg_dump commands, the .NET
`appsettings.json` (Npgsql only supports direct negotiation from v9 via
`SSL Negotiation=Direct`), and the SQLAlchemy keyword-style `.env` are
flag/keyword forms that can't carry the URI params — these would still
fail against Multigres and need a follow-up
- Settings > Database's Connection Pooling section and the pooler logs
page have no HA gating yet — they'd still render pooler config UI for a
Multigres project and should be hidden in a follow-up

## To test

On a **Multigres (HA) project** (staging only supports `us-east-1` for
Multigres):

- Open the Connect sheet → Direct tab: there's no connection-method
picker, and the connection string is the direct one ending with
`?sslmode=require&sslnegotiation=direct` for the URI, PHP, and psql
(quoted-URI form) types; JDBC includes
`&sslmode=require&sslNegotiation=direct`
- ORM tab → Prisma: both `DATABASE_URL` and `DIRECT_URL` are the direct
connection string with the SSL params, no `pgbouncer=true`, with a
"Multigres does not support connection pooling" comment. Drizzle
likewise shows the direct string only
- Framework tabs (e.g. Next.js): every `DATABASE_URL` carries the direct
string with the params exactly once
- Open the network tab: no requests to `/config/pgbouncer` or
`/config/supavisor` while using the Connect sheet
- To check the localStorage coercion: on a **regular** project pick
"Transaction pooler" in the Connect sheet, then open the sheet on the
Multigres project — no pooler badge/notices, string is still direct
- Copy the URI, substitute your password, and `psql "<string>"` — it
should connect
- Project home → Copy dropdown → "Direct connection string" includes the
params

On a **regular (non-Multigres) project** — confirm nothing changed:

- Connect sheet: direct/session/transaction strings for all connection
types (URI, psql flag form, JDBC, PHP) look the same as before, no SSL
params appended
- Prisma/Drizzle tabs render identically (`?pgbouncer=true` still
appended with `?`, dedicated-pooler alternatives still shown per IPv4
add-on state)
- Project home copy dropdown is unchanged


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

* **New Features**
* Enhanced connection-string generation for high-availability projects,
including required SSL settings for direct connections.
* Preserved URI query parameters in PostgreSQL, `psql`, JDBC, and
generated environment configurations.
* Improved ORM environment templates with clearer handling for pooler
and high-availability connection scenarios.

* **Bug Fixes**
* High-availability projects now consistently use direct connections
instead of pooler options.
* Connection strings and generated templates update correctly when
availability settings change.

* **Tests**
* Expanded coverage for query parameters, high-availability behavior,
and connection scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-07-31 14:34:31 +08:00
Joshen Lim 78957bcd68 Replace disable pipelines cta with enable pipelines if pipelines not enabled yet (#48518)
## Context

Addresses 2 issues found for the Replication UI

- "Disable Pipelines" CTA was still being shown despite Pipelines not
being enabled yet
- Opting to show the "Enable Pipelines" CTA instead in this case, which
will open the `EnablePipelinesModal`
<img width="269" height="162" alt="image"
src="https://github.com/user-attachments/assets/41e5ec7d-11b1-4008-ae9d-64def00329eb"
/>
- Fixes "Disable Pipelines" being incorrectly disabled


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

* **New Features**
* Added options to enable or disable Pipelines directly from the
replication destinations menu.
* Added an enablement modal with messaging and upgrade actions based on
available access.
* Added support for opening the Pipelines modal through external
controls.

* **Bug Fixes**
  * Corrected action disabled states and destination-removal guidance.
* Improved error handling when disabling Pipelines, including a reliable
fallback message.
* Refined modal and dialog layout spacing for a more consistent
presentation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-31 11:43:02 +07:00
Danny White 4381e1290c fix(studio): replace form-group green focus shadows with focus-ring (#48221)
## What kind of change does this PR introduce?

Bug fix / a11y cleanup
([DEPR-629](https://linear.app/supabase/issue/DEPR-629)).

## What is the current behavior?

`apps/studio/styles/globals.css` still styles `.form-group` /
`.form-control` inputs with a legacy soft green focus glow (`box-shadow:
… rgba(62, 207, 142, …)` plus `ring-current`). That can fight modern
focus rings if those classes are ever present.

## What is the new behavior?

Those legacy focus rules are removed. Matching inputs use `@apply
focus-ring` instead.

| Before | After |
| --- | --- |
| <img width="882" height="246" alt="CleanShot 2026-07-31 at 13 28
42@2x"
src="https://github.com/user-attachments/assets/3aa00e2f-918f-4e72-9db0-4ad75864cc58"
/> | <img width="864" height="244" alt="CleanShot 2026-07-31 at 13 28
57@2x"
src="https://github.com/user-attachments/assets/4a96439d-16de-4ebb-ab07-2ae7cbf46c0b"
/> |

## To test

These CSS selectors are legacy. Easiest before/after is a one-line probe
in the browser.

1. Open the **Studio preview** for this PR (and, for comparison,
production Studio or `master`).
2. Go to any project (any page is fine).
3. Open DevTools → Console and paste:

```js
document.body.insertAdjacentHTML(
  'beforeend',
  `<div class="form-group" style="position:fixed;right:16px;bottom:16px;z-index:9999;padding:12px;background:var(--background);border:1px solid var(--border);border-radius:8px">
    <label style="display:block;margin-bottom:8px">Legacy form-group probe</label>
    <input type="text" value="Tab to me" />
  </div>`
)
```

4. Click the injected input (or Tab to it).

| | Focus look |
| --- | --- |
| **Before** (production / `master`) | Soft **green** halo |
| **After** (this PR) | Shared **`focus-ring`** only (no green glow, no
double stack) |

Optional smoke (no visual change expected): **Project Settings → General
→ Project name** — Tab into the field; normal shared focus ring still
works.

## Additional context

- Related: #41575, DEPR-628
2026-07-31 14:29:13 +10:00
Danny WhiteandJoshen Lim 5edcaef74c chore: show organization invite errors inline (#48470)
## What kind of change does this PR introduce?

Bug fix and design-system documentation update.

## What is the current behavior?

Invite acceptance failures only appear in a transient toast.

## What is the new behavior?

Invite failures remain visible beside the actions. The design-system
guidance now distinguishes field, action, state, and toast feedback.

| Before | After |
| --- | --- |
| <img width="759" height="619" alt="Join Organization Supabase"
src="https://github.com/user-attachments/assets/ed8e974c-5da3-477a-81da-628d3f847131"
/> | <img width="741" height="768" alt="Join Organization Supabase"
src="https://github.com/user-attachments/assets/4c3f6bcd-4ed9-40b2-8280-e8c8a44ecbd6"
/> |

## To test

With local Studio running at `http://localhost:8082`:

1. Open
`apps/studio/components/interfaces/OrganizationInvite/OrganizationInvite.utils.ts`.
2. At line 37, immediately inside `getOrganizationInviteStatus`, add:
   ```tsx
   return 'ready'
   ```
This deliberately bypasses invite lookup and account checks for the
visual test.
3. Open
`apps/studio/components/interfaces/OrganizationInvite/OrganizationInvite.tsx`.
4. At line 30, change:
   ```tsx
   const [joinError, setJoinError] = useState<string>()
   ```
   to:
   ```tsx
const [joinError, setJoinError] = useState<string>('Invite token can
only be accepted via an SSO account')
   ```
5. Open `http://localhost:8082/join?token=test&slug=test` while signed
in.
6. Confirm the card says **Join an organization** and shows the error
below **Decline**, separated from the actions by a divider.
7. Revert both temporary edits before committing anything.

## Additional context

First PR in a five-PR stack.


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

- **New Features**
- Added a new connect interstitial example showcasing an inline
action-error state with clear retry guidance.

- **Bug Fixes**
- Invitation acceptance failures now show inline destructive feedback
under “Accept invite,” keeping the button enabled for retry (and
removing prior toast-based failure behavior).
  - Updated the invalid-invitation title to “Invalid invitation.”
  - Changed the “Decline” link destination to `/organizations`.

- **Documentation**
  - Expanded Sonner toast “When to use” guidance.
- Refined form and connect interstitial action-feedback patterns (inline
vs toast usage).

- **Tests**
- Updated and added coverage for the inline error rendering and “Invalid
invitation” text.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-07-31 06:23:24 +10:00
Danny WhiteandJoshen Lim 205527c716 feat(studio): tune up replication page layout and empty state (#48265)
## What kind of change does this PR introduce?

UI polish for Database → Replication: empty state, page layout, diagram
containment, filter actions, and destination sheet copy.

## What is the current behavior?

- Empty destinations use a custom dashed box with generic copy.
- The diagram is full-bleed with `border-y`.
- Page chrome still uses legacy Scaffold wrappers and a long header
description that duplicates the empty state.
- Filter-row “Add destination” is a default button ahead of secondary
actions; Usage always shows.
- Local ETL warning sits on the page list.
- Destination sheet title/helper/access copy is more verbose; Type
helper sits beside the label.

## What is the new behavior?

- Empty state uses `EmptyStatePresentational` with clearer CTA copy;
toolbar “Add destination” is primary at the end of the filter row;
empty-state CTA stays default.
- Usage only appears when there is at least one Pipelines destination.
- Page uses `PageHeader` / `PageContainer` / `PageSection`, with a short
header: “Read replicas and analytics pipelines”.
- Diagram sits in a rounded bordered frame inside the page container
(same treatment as project overview).
- Local ETL warning shows in the add-destination sheet for Pipelines
types only, without blocking the form; Type + warning scroll with the
sheet body.
- Type helper sits under the dropdown as one flowing paragraph (“Cannot
be changed after creation…” plus shortened stage notice).
- Sheet title is “Add destination”; close only fires on dismiss; Lucide
icons (e.g. Snowflake) use consistent stroke width.

| Before | After |
| --- | --- |
| <img width="1479" height="930" alt="Replication Database Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/a3caf0ba-ed1a-4659-bdef-f66b67e85be4"
/> | <img width="1479" height="930" alt="Replication Database Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/d5a82641-a316-4577-9480-959346994c40"
/> |
| <img width="1479" height="930" alt="Replication Database Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/4f956e26-b8d4-4653-a60e-ceca7ec1e070"
/> | <img width="1479" height="930" alt="Replication Database Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/a72461ab-dea9-48a6-ab88-852a12ac80a5"
/> |

### Test plan

- [x] Open **Database → Replication** with no replicas/destinations:
empty state, primary filter-row Add destination, default empty-state Add
destination, no Usage button.
- [x] Confirm header→diagram and diagram→filter spacing feel even;
filter→empty state/table stays tight (`space-y-4`).
- [x] Confirm diagram is contained (rounded border), not full-bleed.
- [x] Add a Pipelines destination (or use a project that has one): Usage
appears; table still works; search “no results” still works.
- [ ] Open **Add destination**: title “Add destination”; Type helper
under the dropdown; Read Replica has no local warning; Pipelines type
shows local warning without hiding fields (when ETL isn’t set up
locally).
- [ ] Without Pipelines access: request-access panel shows “alpha” copy
and “Request alpha access”.
- [ ] Spot-check dark/light themes.

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-07-31 06:20:38 +10:00
Thomas 63a74d488f chore(billing): rework texts on aws marketplace onboarding page (#47735) 2026-07-30 17:31:13 +02:00
Monica Khoury 3c30514818 fix: open integrated support form from Feedback → Issue → Contact sup… (#48488)
PR description:

## Summary

- Clicking Feedback → Issue → Contact support was navigating to
`/support/new` (the old full-page form) instead of opening the
integrated sidebar support form
- Fixed by setting a `helpPanelState.requestedView` signal before
opening the Help sidebar, so it opens directly at the support form view
- Added a small valtio store (`state/help-panel-state.ts`) to
communicate the desired view between `FeedbackDropdown` and `HelpPanel`

## Test plan

- [ ] Feedback → Issue → Contact support opens the Help sidebar at the
support form (not `/support/new`)
- [ ] Help button → Contact support still works as before
- [ ] Closing and reopening the Help sidebar via the Help button opens
at the home view

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

## Summary by CodeRabbit

* **New Features**
* Selecting **Support** from the Help menu now opens the Help Panel
directly to the Support view.
* The Help Panel automatically updates to the requested section when
opened.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-30 17:15:52 +03:00
Daniel Guerra 5a3e3598d0 feat(billing): Lazy load BillingSettings queries for components that are not in view (#48454)
## What kind of change does this PR introduce?

There are some expensive queries that are requested every time the
Billing Settings page loads, some of them happen for components that are
outside of the initial viewport. We can avoid performing those requests
unless the user explicitly scrolls to the relevant section. A similar
pattern has been implemented in the past for the Credit Balance section
in https://github.com/supabase/supabase/pull/45481.

I decided to skip the lazy load pattern in the components that appear at
the top of the Billing Settings (Subscription and Cost Control).

## What is the current behavior?

When loading the billing settings page, all components (except
CreditBalance) will perform requests to load the data they need.

## What is the new behavior?

The components will perform the request to load their data until they
are inside the viewport. You can verify this by opening the developer
tools and monitor the requests as you scroll through the page.

## Testing

These changes can be easily tested by making your browser's height very
short then opening the org billing settings `/org/{slug}/billing`. Open
the developer tools and filter for XHR requests. As you scroll through
the page, the requests will be made.

To verify that all potential requests are covered, I compared the
requests done during a fresh load with another settings page, the only
extra requests made by the billing settings page are the ones relevant
to the components at the very top (or the BillingSettings container
itself, which requests the subscription).

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

* **Performance Improvements**
* Billing, payment methods, billing customer details, upcoming invoices,
and invoice lists now load only when their sections scroll into view,
reducing initial loading.
* Existing access/permission checks are still applied before fetching
billing-related data.

* **Tests**
* Updated billing and invoices tests to mock viewport intersection
behavior (IntersectionObserver) to match the new lazy-loading behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-30 07:55:40 -06:00
CharisandJoshen Lim c16c7e94cc feat(studio): SQL editor logs source — toolbar UI + creation flow (#48452)
## What

PR 6 of the SQL-editor "query source (Database vs Logs)" stack (builds
on the merged PR 5, #48414). Adds the user-facing toolbar surface for
the logs query source and consolidates the SQL-editor toolbar into a
single **source menu**.

Everything stays behind `sqlEditorLogsSource` + `otelLegacyLogs`
(dual-flag gated); with the flags off the toolbar is unchanged.

## Changes

- **Consolidated source menu** (`QuerySourceMenu`) — one `Database ▾` /
`Logs ▾` dropdown that both labels the snippet's source and hosts the
source-specific controls as flyout submenus:
- Database: database selector (`Primary` / read replicas), `Run as`
(role impersonation), and `Row limit`.
- Logs: `Time range` — the same relative presets as the Logs Explorer
plus a `Custom range…` calendar dialog.
- **Source is immutable** — the Database/Logs rows aren't a toggle. An
existing (materialized) snippet opens a *fresh* tab of the target source
(never reinterpreting a query against the wrong backend); a blank new
tab re-flavors in place. Extracted as the pure, unit-tested
`resolveSourceSwitch`.
- **New-snippet-with-source** threaded through `/sql/new?source=`, the
nav "Create a new logs query" entry, and the duplicate flow. Logs
snippets hide the (db-dialect) Export action.
- **Run-affordance guard** — the Run button is disabled + annotated for
a logs snippet on a non-ClickHouse org (sits above PR 5's execution
short-circuit).
- **Retention entitlement gating** — both preset and custom logs ranges
past `log.retention_days` surface the upgrade prompt instead of applying
silently. Prettify is disabled for logs (sql-formatter mangles
ClickHouse).

## Tests

- `querySource.test.ts` — `logDateRangesEqual` (structural
relative/absolute matching, incl. the "Last hour" vs "Last 1 hour" label
case).
- `QuerySourceMenu.utils.test.ts` — `resolveSourceSwitch`
push-vs-replace / no-op behavior.

`pnpm --filter studio typecheck` · `lint:ratchet` · Prettier · SQL
editor suite (307 tests) all green.

## For reviewers

To test manually, enable the `sqlEditorLogsSource` feature flag for
yourself on local/staging. There is no nav for Log SQL snippets
currently (that is by design, this PR is big enough as-is), so to check
an existing logs snippet, you can create one using the existing Logs
Explorer, copy its UUID, and force navigate to that snippet in the SQL
editor via URL.

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

## Summary by CodeRabbit

* **New Features**
* Added support for creating and switching between database and logs
queries.
  * Added log time-range presets and custom date-range selection.
  * Added database, run-as role, and row-limit controls.
* Added read-replica selection, including options to create a new
replica when available.
* **Improvements**
  * Added clearer explanations when query execution is unavailable.
* Disabled SQL formatting and query export where unsupported for logs
queries.

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

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-07-30 08:38:11 -04:00
Ivan Vasilov 6b14df7724 chore: Bump vulnerable deps (#48387)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
  * Updated Next.js, PostCSS, and tar package versions.
  * Added the required TypeScript native tooling where needed.
* Refined package configuration and dependency ordering across the
project.
  * Removed an unused empty dependency configuration.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-30 14:23:43 +02:00
Saxon FletcherandAlaister Young ddc1f4175f HA continued surface coverage (#48425)
- Updates connection pooling settings to be read-only when a high
availability project with ip4 admonition removed
- Updates organization usage to be disabled until supported
- Updates database publications to be disabled until supported

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

* **New Features**
* Added High Availability handling for database publications, usage, and
connection pooling.
* Publications and usage now display dedicated “unavailable” empty
states and hide gated content when High Availability is enabled.
* Connection pooling switches to managed/read-only mode on High
Availability, disabling edits and form submission and disabling related
data fetching.
  * Pooling mode controls are hidden on High Availability.
* **Refactor**
* Refactored database publications pages by extracting main rendering
logic into internal components.
* **Tests**
* Added Vitest + React Testing Library coverage for High Availability
behavior across publications availability, usage, connection pooling,
and pooling modes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-07-30 16:37:45 +08:00
Saxon Fletcher f9a1d2e983 Disable unsupported Studio features for HA projects (#48376)
## Summary

More gating to support upcoming High Availability projects. 

- Keep the Recent Branch stat visible on the project home page for HA
projects, but disable its interaction, reduce its opacity, and skip the
branches query.
- Treat Realtime as disabled for HA projects in the service-status
dropdown so it does not make the project appear unhealthy or trigger
unhealthy polling.
- Show the shared unsupported-feature empty state for Custom Domains and
skip its query on HA projects.
- Disable the Enable Realtime checkbox in the table creation sheet for
HA projects.


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

- **New Features**
- Added High Availability–aware behavior across activity stats, service
status, custom domains, and table realtime controls.
- Introduced reusable Branch value UI that shows an “Unavailable” state
in High Availability mode.
- Added a dedicated realtime toggle UI that disables interaction and
updates helper text when unavailable.

- **Bug Fixes**
- Ensured realtime is treated as disabled (not unhealthy) in High
Availability and prevented realtime enabling/saving.
- Reduced unnecessary data fetching by gating addon/custom-domain
requests and disabling branch queries.

- **Tests**
- Added coverage for realtime status resolution, BranchStatValue
“Unavailable” rendering, and TableRealtimeToggle behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-30 16:37:13 +08:00
d2a3162bf1 Add high availability project creation controls (#48375)
## Summary

- Move High Availability into the standard project creation settings
above Compute, gated by the `instances.high_availability` entitlement.
- Mark the option as Alpha and explain that it is free during Alpha for
up to two projects.
- Enforce the supported HA configuration: `AWS_K8S`, Postgres 17 on the
`ga` release channel (no custom version is sent — the API resolves the
image), and the environment-specific local/staging region restrictions.
- Show eligible locations in a dedicated **High Availability Regions**
group.
- Preserve the existing Advanced Configuration availability rules and
additionally hide the section while HA is enabled.
- Restore the previous provider and Postgres settings when HA is
switched off.

## How to test
1. Go to create a new project
2. Ensure you have access to high availability (e.g. on local)
3. Toggle high availability on and note how the project form restricts
settings listed above

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

* **New Features**
* Added High Availability to project creation with Alpha warning
labeling and improved switch accessibility.
* Constrains region selection to compatible High Availability regions
and enforces HA-specific engine/release settings.
* Disables/hides custom PostgreSQL version selection when High
Availability is enabled (and omits HA custom request payloads).

* **Bug Fixes**
* Improved persistence of selected PostgreSQL version and region across
data reloads and configuration panel reopen/toggle.
* Restores region when form state temporarily drops values during
remounts.

* **Tests**
* Expanded end-to-end coverage for HA UI, region grouping, and
submit/payload restoration behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-07-30 16:36:54 +08:00
Alaister YoungandAlaister Young 0833c586ac fix(studio): use redirect({ to }) for internal TanStack redirects (#48469)
Hover-preloading any link that points at a redirecting path (e.g. the
org invite "Decline" link to `/projects`) hung the tab under the
TanStack runtime: `redirect({ href })` is treated as an opaque external
target, and the router's preload retry ignores `href` when rebuilding
the location, so it re-runs the same `beforeLoad`, throws the same
redirect, and recurses forever (TanStack/router#7141 — internal targets
must use `to`).

**Changed:**

- `routes/__root.tsx` — the redirect-table `beforeLoad` splits the
destination with `splitInternalUrl()` and throws `redirect({ to, search,
hash, statusCode })` instead of `redirect({ href })`. `to` is
basepath-relative, so the manual `BASE_PATH` prefix goes away too.
- `routes/index.tsx` — same `href` → `to`/`search`/`hash` switch for the
`/` redirects; the "targets aren't in the routeTree yet" comment was
stale (all three destinations resolve to real routes now).
- `OrganizationInvite.tsx` — "Decline" links straight to
`/organizations`, skipping the `/projects` redirect hop entirely.

## To test

- On the TanStack runtime, hover (don't click) a link to a redirecting
path — e.g. the auth overview's "Go to observability" link
(`/project/:ref/reports/auth`) or the 404 page's `/projects` link. The
page must stay responsive (this hung before).
- `/projects` → `/organizations` (307), `/project/:ref/database` →
`/database/tables` (308), `/` → `/org`.
- Query/hash semantics still hold: `/?next=new-project&projectName=x` →
`/new/new-project?projectName=x`;
`/project/:ref/database/wrappers?foo=bar` →
`/integrations?category=wrapper&foo=bar`; `/org/:slug/invoices#other` →
`/org/:slug/billing#invoices`.
- Chained redirects stay bounded: `/project/:ref/database/linter` →
`/advisors/security` in two hops.

All of the above verified locally via Playwright against the TanStack
dev server; `redirects.shared` / `internal-url` / compat-router unit
tests pass.

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

- **Bug Fixes**
- Fixed the invitation “Decline” action to route users to the
Organizations page instead of the Projects page.
- Improved Studio redirect/navigation handling by correctly preserving
URL search parameters and hash fragments and routing to the intended
destination.
- **Tests**
- Updated Organization Invite test expectations to reflect the corrected
“Decline” link destination.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-07-30 12:42:47 +08:00
Joshen Lim fcfb0f0222 Refactor all usage of form.watch to either useWatch or subscribe (#48436)
## Context

Replaces all usage of `form.watch()` to use `useWatch` instead + follows
the "name what you watch" convention as specified in the react-hook-form
skills.

There's also a small refactor in `SmtpForm.tsx` which removes the
unnecessary use of a `useState` to track if SMTP is enabled or not

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

* **Improvements**
* Updated many Studio forms to watch specific fields more precisely,
improving live UI updates for previews, warnings, conditional sections,
and validation messages.
* Enhanced responsiveness across settings, authentication, billing,
storage, integrations, and support flows while keeping save/update
behavior the same.
* **Refined Experiences**
* Improved the analytics table creation flow with tighter, enum-based
column type validation and structured, type-specific column options.
* **Preserved Behavior**
* Maintained existing permission checks, submission flows, and
account-management workflows.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-30 11:45:40 +08:00
Ali Waseem 66658ab339 fix(studio): bucket multi-hour report ranges hourly instead of by minute (#48409)
Selecting "Last 7 days" on an Observability report rendered only the
most recent ~10 hours, while the header still showed the full range.

`timestamp_trunc` only does minute/hour/day, so
`analyticsIntervalToGranularity` floors any sub-hour interval to
`minute`. The `'30m'` and `'10m'` intervals used for 7-day and 24-hour
ranges therefore asked for 10,080 and 1,440 per-minute buckets. The
analytics endpoint caps each query at 1,000 data points, and report
queries are ordered newest-first with no `LIMIT`, so the oldest buckets
got dropped. Confirmed against a production HAR: 168h requested, exactly
1,000 rows returned, 10.6h of data.

Both tiers now use `'1h'` — 168 and 24 buckets respectively, well inside
the cap. Applies to Edge Functions, Auth and Realtime reports, which
share this helper.

Remaining sites that can exceed 1,000 points, not touched here:

- Logs event chart (`calcChartStart`) — minute buckets over a range
extended 6h earlier (~1,080), and hourly over a range extended 5 days
earlier (90d → 2,280)
- API and Storage reports (`PRESET_CONFIG`) and `SharedAPIReport` —
hardcoded `hour`, so a 90-day custom range is 2,160 points
- Query Insights — hardcoded `MINUTE` grouped per query, so unbounded

UnifiedLogs is fine; its ladder already caps at 720.

Fixes FE-4023

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

## Summary by CodeRabbit

* **Bug Fixes**
* Updated report date-range interval selection for ranges up to seven
days to use hourly granularity instead of 30-minute intervals for
clearer, more consistent reporting.

* **Tests**
* Added automated coverage for interval granularity across minute-,
hour-, and multi-week ranges.
* Included assertions validating expected hourly bucket counts for a
seven-day window.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-29 11:16:47 -06:00
Miranda Limonczenko 0d465e7b5f chore(ui): Remove 'tip' from Admonition (#48419)
Closes FE-3966

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

YES

## Problem

- The admonition uses both 'tip' and 'note', but the visual distinction
has long-ago collapsed.
- 'Note' is used far more frequently than 'tip'
- The two are very similar and it is confusing to know which one to use
when they are visually identical

## Solution

Collapse 'tip' and 'note' into one by removing all places where there is
'tip' and updating all references to 'tip' into 'note'.

**Note:** This PR also resolves new broken links flagged by the E2E docs
checker. It may move to another PR since E2Es keep erroring.

### Specific changes

See below for an AI-generated list of changes:

- **Type system** — removed `'tip'` from `AdmonitionType`, its
`TYPE_TO_VARIANT`/`TYPE_LABEL` entries, and the test case in
[`packages/ui-patterns/src/Admonition/](packages/ui-patterns/src/Admonition/)
- **Remark plugin** —
[remarkAdmonition.ts](apps/docs/lib/mdx/plugins/remarkAdmonition.ts) now
maps mkdocs `tip` → `note`
- **Lint allowlist** — `tip` dropped from `supa-mdx-lint.config.toml`
- **Content migration** — all 109 files with `type="tip"` (across
`apps/docs`, `apps/www`, `apps/studio`) converted to `type="note"`; zero
remaining hits confirmed by repo-wide grep
- **Style guide** — `CONTRIBUTING.md` and `contributing/content.mdx`
updated to describe 4 admonition types instead of 5

### Usage before implementation

See the usage table that points toward 'note' as being dominant across
all apps:

Here's the usage table:

| Location | `note` | `tip` |
|---|---|---|
| apps/docs | ~480 | ~143 |
| apps/studio | 34 | 6 |
| apps/www (blog) | 19 | 3 |
| packages/ui-patterns (tests) | 3 | 1 (parametrized) |
| design-system / ui-library / packages/ui / packages/common | 0–1 (test
fixture only) | 0 |

## Preview links


| App | Page | Search text (Ctrl+F) | Verify |
|---|---|---|---|
| docs |
[/docs/guides/ai-tools/byo-mcp](https://docs-git-admonition-collapse-note-tip-supabase.vercel.app/docs/guides/ai-tools/byo-mcp)
| official MCP TypeScript SDK | callout's aria-label="Note" |
| docs |
[/docs/guides/ai-tools/mcp](https://docs-git-admonition-collapse-note-tip-supabase.vercel.app/docs/guides/ai-tools/mcp)
| MCP server is available at | callout's aria-label="Note" |
| docs |
[/docs/guides/ai/python-clients](https://docs-git-admonition-collapse-note-tip-supabase.vercel.app/docs/guides/ai/python-clients)
| Click Connect at the top of any project page | callout's
aria-label="Note" |
| docs |
[/docs/guides/auth/audit-logs](https://docs-git-admonition-collapse-note-tip-supabase.vercel.app/docs/guides/auth/audit-logs)
| Disabling Postgres storage reduces your database storage costs |
callout's aria-label="Note" |
| docs |
[/docs/guides/database/tables](https://docs-git-admonition-collapse-note-tip-supabase.vercel.app/docs/guides/database/tables)
| access a custom schema through the Supabase Data API | callout's
aria-label="Note" |
| docs |
[/docs/guides/troubleshooting/edge-function-404-error-response](https://docs-git-admonition-collapse-note-tip-supabase.vercel.app/docs/guides/troubleshooting/edge-function-404-error-response)
| Always configure an appropriate time frame | callout's
aria-label="Note" (was single-quoted type='tip') |
| www | [blog:
cli-v2-config-as-code](https://zone-www-dot-com-git-admonition-collapse-note-tip-supabase.vercel.app/blog/cli-v2-config-as-code)
| Detecting config drift | callout's aria-label="Note" |
| www | [blog:
cli-v2-config-as-code](https://zone-www-dot-com-git-admonition-collapse-note-tip-supabase.vercel.app/blog/cli-v2-config-as-code)
| Setting Edge Function secrets | callout's aria-label="Note" |
| www | [blog:
nosql-mongodb-compatibility-with-ferretdb-and-flydotio](https://zone-www-dot-com-git-admonition-collapse-note-tip-supabase.vercel.app/blog/nosql-mongodb-compatibility-with-ferretdb-and-flydotio)
| If your network supports IPv6 connections | callout's
aria-label="Note" |

Note: the `www` rows use the `zone-www-dot-com` preview host, not the
`docs` one you gave — since blog pages are served from the www app, not
docs.


## Manual testing

1. Open preview links for affected pages.
2. Inspect. Open console.
3. Paste the following in and see there is no 'Tip' on the page:
```
document.querySelectorAll('[role="alert"]').forEach(el => console.log(el.getAttribute('aria-label'), el.textContent.slice(0,60)))
```



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

* **Documentation**
* Standardized informational callouts across docs and tutorials from
**“Tip”** to **“Note”**, updating multiple examples and guidance blocks.
* Updated a few related doc references/links and conditional “Next
steps” content.
* **UI Updates**
* Switched various in-app banners and notices to the **“Note”** style
variant.
* **Bug Fixes / Improvements**
* Removed support for the retired **“Tip”** callout type and aligned
docs linting, component behavior, and aria labeling to the remaining
admonition types.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-29 09:26:50 -07:00
hallidayo 6a6ebf8702 feat: logs sticky header (#44020)
## 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?

[Supabase Studio >
Logs](<https://supabase.com/dashboard/project/_/logs/edge-logs>)

## What is the current behavior?

When you click on an log row and you scroll the header disappears so you
can not close the log straight away you have to scroll back up.

## What is the new behavior?


https://github.com/user-attachments/assets/8cac74d8-e3ce-429c-a9ca-393779d1efd9

## Additional context

## Summary by CodeRabbit

* **UI Improvements**
* The log selection tabs now stay visible while scrolling, with a fixed
header style, better layering, and a solid background for improved
readability.
2026-07-29 17:57:22 +02:00
Charis 4c8ed105d2 feat(studio): logs SQL execution wiring + source-aware run gestures (#48414)
## 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 (SQL editor: execution wiring for logs-source snippets). Part of
the stacked SQL-editor "Database vs Logs" query-source series.

## What is the current behavior?

The SQL editor only ever runs queries against the user's Postgres
database. There is no execution path for a logs (`log_sql`) snippet, and
the run-button telemetry event carries no backend discriminator.

## What is the new behavior?

- `useRunSource(id)` derives the run backend from the snippet type; a
`log_sql` snippet resolves to `{ type: 'logs', dateRange }`, pairing the
run with its session time range (default: last hour).
- `useLogsSqlExecution` runs a promoted `SafeLogSqlFragment` against the
analytics OTEL (ClickHouse) endpoint with the resolved time range as
`iso_timestamp_start`/`iso_timestamp_end` request params. The endpoint
is **pinned to OTEL** — a snippet's dialect must not flip with org
migration.
- The run gestures (toolbar button and Cmd+Enter) branch on the source
and promote with the matching `acceptUntrusted*` right at the user
action, preserving the auditable promotion-at-gesture boundary. pg
intellisense is gated off for logs snippets.
- The `sql_editor_query_run_button_clicked` telemetry event gains a
required `{ source: 'database' | 'logs' }` property, fired from both
execution paths.
- Capability guard: a `log_sql` snippet is reachable by direct URL
regardless of the (later) entry-point flag gating, so `executeLogsQuery`
short-circuits when `otelLegacyLogs` is off — recording a clear "not
available yet" result message instead of firing a request that would
only return an opaque backend error on a non-ClickHouse project. This is
a guard on the gesture, not endpoint selection.
- Tests: `useRunSource` routing, `useLogsSqlExecution`
endpoint/range/structured-error/capability-guard, and a reusable `flags`
option on `renderSqlEditorHook`.

No UI entry points are added — the feature runs dark until the
flag-gated creation/nav PRs later in the stack.

## Additional context

Stacked on the query-source series; base branch is `master` now that PR
4 (log date range domain + session state, #48401) is merged. Follow-ups
in the stack add the toolbar/creation UI (with a run-affordance gate on
`otelLegacyLogs`), nav section, AI dialect support, and reports guard.

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

## Summary by CodeRabbit

* **New Features**
  * Added support for running log queries directly from the SQL editor.
* Log query results, errors, and time ranges are now handled within the
editor session.
* Added automatic selection between database and log query execution,
including support for custom date ranges.
* SQL assistance is disabled while editing log queries where database
definitions do not apply.

* **Tests**
* Added coverage for log query execution, date ranges, feature
availability, and execution source selection.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-29 10:43:48 -04:00