mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 09:55:06 +03:00
3c305148186c311db7ec03f2e17e91ff94de1200
319
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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 --> |
||
|
|
b8310dbf23 |
feat(studio): move SIWC rollout gate to ConfigCat (#48360)
## 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? Replace the deploy-gated `dashboard_auth:sign_in_with_chatgpt` AND-gate with useFlag('ShowSignInWithChatGptButton') OR'd against the existing localStorage opt-in switch, so rollout/rollback no longer requires a frontend deploy. Remove the now-dead static flag, its only consumer was this gate. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * ChatGPT sign-in availability now responds to either the local opt-in setting or the updated configuration flag. * GitHub sign-in continues to follow its dedicated feature setting. * **Bug Fixes** * Corrected identity provider visibility across different sign-in configuration combinations. * **Chores** * Removed the obsolete ChatGPT sign-in feature setting. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b9ab634cd0 |
fix(studio): stop 403'd integration queries from looping on remount (#48350)
Resolves FE-4014
A user with a project-scoped role opening any project integration
overview (e.g. Cron) hits an unbounded request loop — the page sits on a
skeleton forever while hammering the platform API until it gets rate
limited.
**Changed:**
- `useProjectOAuthIntegrationData` now passes `retryOnMount: false` to
its five queries, so a 403 settles as a terminal error instead of
refetching on every consumer mount
## Why
Project-scoped roles have no org-level permissions, so `GET
/platform/organizations/{slug}/oauth/apps` 403s. We don't retry 4xx, so
the query settles into `error` with no data — and an errored query with
no data is never fresh, so it refetches on *every* new observer mount.
That feeds a loop: refetch → `isLoading` true → `IntegrationPage` swaps
its whole subtree to a skeleton → `<Component />` unmounts → 403 lands →
`isLoading` false → remounts → mounts fresh observers → refetch.
Measured ~20 req/s (480 observer add/removes and 120 requests in a 6s
window) until the API 429s it, then it continues at the retry cadence
indefinitely.
The other four queries in that hook can 403 the same way for restricted
roles, and any one of them alone sustains the loop — hence the option on
all five.
Not fixed here: `IntegrationPage` tearing down its subtree whenever
`isLoading` flips
(`pages/project/[ref]/integrations/[id]/[pageId]/[childId]/index.tsx:58-94`)
is the amplifier that turns a wasted request into a loop, and will still
reset UI state on any background refetch. Worth a follow-up.
## To test
Needs an account with a project-scoped role in a shared org (not an org
owner/admin).
- Open `/project/{ref}/integrations` for that project, click into Cron
(or any integration) → overview should render, not sit on a skeleton
- Network tab: `organizations/{slug}/oauth/apps?type=authorized` should
fire once and 403, not repeat
- Console should show 1 error, not hundreds ending in a 429
- As an org owner, integration overviews should behave exactly as before
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Prevented repeated refetching of integration data after handled
authorization/403 errors, avoiding refetch loops on remount.
* Improved consistency on integration landing screens by standardizing
how related integration queries are enabled and retried.
* **Enhancements**
* Added permission-aware loading/error handling for OAuth integration
data, showing OAuth results only when the selected organization grants
read access.
* **Chores**
* Updated permission-check typings to treat an explicitly empty project
reference as absent.
* **Tests**
* Extended integration settings tests with permission fixtures to cover
OAuth read access.
<!-- 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>
|
||
|
|
0fe2366659 |
[FE-3790] fix(studio): hide Multigres from user-facing surfaces (#48191)
Hides the "Multigres" term from user-facing surfaces — it's the tech powering High Availability projects, but "High Availability" is the only term users should see for now (per Slack discussion with Saxon/Ivan). **Changed:** - High Availability badge hover card (project overview) no longer says "Driven by Multigres" - Project creation HA toggle description drops the Multigres name + multigres.com link, keeps the informational copy - All schema dropdowns now hide the `multigres` schema on HA projects, by wiring in the previously-unused `filterSchemasForHighAvailability` helper: - `SchemaSelector` (shared — Table Editor, Functions, Indexes, Triggers, Schema Visualizer, etc.) - `ExposedSchemaSelector` (API settings → exposed schemas) - `EnableExtensionModal`, `CreateIndexSidePanel`, `ForeignKeySelector`, `WrapperTableEditor`, Integrations install sheet `AdvancedSettings` - SQL editor schema autocomplete (`useAddDefinitions`) - Schema list computations in the touched components are now memoized (incl. stabilizing `SchemaSelector`'s `excludedSchemas` default so the memo actually holds) **Added:** - Unit tests for `filterSchemasForHighAvailability` / `resolveHighAvailability` - MSW component test for `SchemaSelector` asserting `multigres` is hidden on HA projects and still shown on non-HA projects The filter is HA-gated on purpose: a self-hosted/non-HA user with their own schema named `multigres` still sees it. The flag-gated Multigres option in Logs is intentionally untouched — that exposure is kept for the Multigres team's debugging (separate track). ## To test - On an HA project (`high_availability: true`): hover the High Availability badge on project overview — no "Multigres" mention; open schema dropdowns in Table Editor / Database pages / SQL editor autocomplete — no `multigres` schema - Project creation with HA entitlement: toggle description has no Multigres wording/link - On a non-HA project: schema dropdowns behave as before <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Made schema dropdowns and related selectors high-availability aware across extensions, indexes, integrations, SQL editing, API exposed schemas, and relationship editors. * Updated project high-availability UI text and badge hover description to remove outdated branding and clarify horizontally scalable Postgres architecture. * **Tests** * Added coverage to ensure the schema “multigres” option is hidden/shown correctly based on high availability, and validated high-availability value handling. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
0b53a1869f |
fix(studio): wire up siwc-enabled query param opt-in on sign-in/sign-up (#48126)
Add `useSiwcQueryParamOptIn`, which flips on the ChatGPT sign-in rollout localStorage flag when `?siwc-enabled=1` is present, and call it from both pages/sign-in.tsx and pages/sign-up.tsx. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for enabling the sign-in experience via `?siwc-enabled=1`, automatically updating the stored opt-in flag on both sign-in and sign-up pages. * **Tests** * Added coverage confirming the stored flag is updated only for `siwc-enabled=1`, and not for missing, non-`1`, `0`, or repeated/array values. * Added assertions that the behavior is triggered consistently when rendering the sign-in and sign-up pages. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
8962308215 |
Add support for multiple custom auth providers in custom-content (#48030)
## Context Adds support for multiple custom auth providers in custom-content <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for multiple custom sign-in providers via a new plural configuration. * Updated the sign-in page to render all configured custom provider options while maintaining compatibility with the legacy single-provider setting. * Improved the custom provider button display to remove internal prefixes from provider names. * **Documentation** * Updated the configuration schema, examples, and sample data to document the new multi-provider setting. * Marked the legacy single-provider configuration as deprecated in favor of the plural option. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
18b273cde0 |
fix(studio): hide Postgres Version Upgrade logs behind a flag (#48007)
## Problem The legacy Logs Explorer's Postgres Version Upgrade page (Database Operations section) shows no results for most users. pg_upgrade_logs rows aren't tagged with the project attribute the shared logs endpoint scopes on, only a host field, so the project-scoped query returns nothing even though the data exists. ## Fix Hides the Database Operations sidebar section behind a new showPostgresUpgradeLogs feature flag (default off), following the same pattern as showMultigresLogs. The page route itself is untouched, only the sidebar entry point is gated. ## How to test - With the flag off, open the legacy Logs Explorer sidebar and confirm the Database Operations section and Postgres Version Upgrade item are gone - With the flag on, confirm the section and item render as before <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added conditional access to Postgres Version Upgrade logs based on feature availability. * Failed Postgres upgrade notifications now show a “View logs” option only when supported. * **Bug Fixes** * Prevented unsupported Postgres upgrade log links and navigation options from appearing. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
58621818d0 |
feat(studio): switch TanStack skew protection to ?dpl= query params (#48008)
Switches the TanStack build's Vercel skew protection from the `__vdpl` session cookie to `?dpl=<deployment-id>` query params baked into asset URLs at build time. Assets stay pinned to the deployment that built them, while document navigations and API fetches always reach the latest deployment (with the cookie, a session stayed fully pinned — including reloads — until the tab closed). **Removed:** - `pinDeploymentForSession` (the `__vdpl` cookie) from `router.tsx`, plus the cookie clearing in the refresh toast and the `vite:preloadError` backstop - `credentials: 'omit'` on the deployment-commit check — its only purpose was escaping the cookie pin, and API fetches are now inherently unpinned **Added:** - `skewProtectionDpl` plugin + `experimental.renderBuiltUrl` in `vite.config.ts`, active only when `VERCEL_SKEW_PROTECTION_ENABLED=1`. Full coverage needs three mechanisms (Vite has no single hook for this — see [vitejs/vite#13834](https://github.com/vitejs/vite/discussions/13834#discussioncomment-7469745)): 1. `renderBuiltUrl` — CSS `url()`s, images, workers, and `__vite__mapDeps` preload lists 2. a `generateBundle` (`order: 'post'`) rewrite of chunk-to-chunk `import`/`from` specifiers, which Rolldown emits as bare relative paths that `renderBuiltUrl` never sees — with sourcemaps recombined per chunk (`magic-string` + `@jridgewell/remapping` devDeps) so Sentry columns stay exact 3. a post-`buildApp` patch of the prerendered `_shell.html` (script/preload tags + embedded router manifest come from TanStack, not Vite's asset pipeline); without it the entry graph double-downloads because preload and import URLs differ ## To test - Built with fake `VERCEL_SKEW_PROTECTION_ENABLED=1 VERCEL_DEPLOYMENT_ID=dpl_TESTPIN123abc`: every chunk import specifier (static + dynamic), `__vite__mapDeps` entry, CSS font URL, and `_shell.html` asset URL carries `?dpl=`; zero unpinned `/assets/` references remain - Sourcemap accuracy verified by tracing a minified position through the recombined map: resolves to the exact original file/line/column (`use-check-latest-deploy.tsx:62:8`) - Built without the env vars: output contains no `dpl=` anywhere (self-hosted/e2e builds unaffected) - `smoke:tanstack` passes on both builds; `tsc --noEmit` and eslint clean - On the preview: load the dashboard, check Network tab — chunk/CSS requests should carry `?dpl=` matching the deployment; hard reload should hit the latest deployment (no pin on document requests) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Improved deployment consistency by pinning generated asset and module URLs to the current deployment (using `?dpl=`). * Simplified refresh and preload-error recovery to reduce reload-loop risk. * Kept API request behavior aligned with the updated deployment routing/pinning approach. * Preserved correct routing across deployment configurations. * **Developer Experience** * Added build-time tooling to rewrite pinned URLs for client assets while maintaining source map integrity. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
320604d0e7 |
feat(studio): ship both upgrade CTA placements, remove A/B experiment (#47881)
## What Concludes the `upgradeCtaPlacement` experiment ([#45858](https://github.com/supabase/supabase/pull/45858)) by shipping **both** placements permanently and removing the A/B scaffolding. The experiment tested two upgrade-CTA placements against a control: - **`user_dropdown`** — an "Upgrade to Pro" button in the account/user dropdown - **`org_projects_list`** — a plan-usage card in the org project list Both moved paid conversion in the same direction over control with no activation downside, and they live on separate surfaces, so we're keeping both rather than picking one. ## Changes - **Remove the experiment machinery.** Deleted `useUpgradeCtaExperiment` (PostHog `upgradeCtaPlacement` flag read, `control` arm, variant selection, per-org localStorage seeding, exposure tracking) and replaced it with a small `useShowUpgradeCta` hook that gates purely on **free plan + hosted platform**. Both placements now render for every eligible free-plan org. - **Telemetry cleanup.** Removed the `upgrade_cta_placement_experiment_exposed` event (pure experiment scaffolding). Kept `upgrade_cta_clicked` (with its `placement` property) so we can still measure the CTAs going forward; de-experimented its wording. - **Dead code.** Removed the unused `prependCard` prop plumbing added to `ProjectList` / `EmptyStates` (no caller ever passed it — the org card renders via the `<aside>`). - De-experimented the remaining doc comments in `PlanUsageCard`. Gating is unchanged in spirit: paid orgs and self-hosted never see the CTA. `useShowUpgradeCta` waits until the org plan is known before returning true, so the CTA fades in for free users and never flashes for paid users. ## Testing - `pnpm --filter common typecheck` and `pnpm --filter studio typecheck` pass. - eslint + prettier clean on the changed files. - Manually checked <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Upgrade/usage CTAs now appear only when the organization is confirmed to be on a free plan, avoiding premature rendering before plan data is available. - Upgrade CTA visibility is now consistently driven across supported project and organization surfaces (including the user dropdown) for org-scoped routes. - **Bug Fixes** - Removed obsolete “prepend” placeholders from the project list loading and grid views to keep card layouts consistent. - **Documentation** - Clarified upgrade CTA telemetry wording and adjusted the frontend telemetry contract. - **Tests** - Added coverage for upgrade-CTA visibility behavior across key scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
17ee3e6977 |
feat(studio): add Multigres log type to unified logs FE-3785 (#47560)
## Problem The Multigres log type is available in the legacy logs collections but was missing from the new unified logs, so Multigres logs could not be selected or viewed there. ## Fix Wire the `multigres_logs` source into unified logs the same way the other single-source types (Realtime, Supavisor, PgBouncer) are: a display label, a filter condition, the derived `log_type` expression, a display-casing entry, and a sidebar icon. ## How to test - Open a project with Multigres logs and go to the new unified logs view - Open the Log Type filter and confirm "Multigres" appears as an option - Select "Multigres" and confirm rows from the `multigres_logs` source are returned and labeled "Multigres" with the network icon - Expected result: Multigres logs are filterable and display correctly, matching the legacy logs behavior ## Notes Level/severity uses the shared `severity_text` fallback that all non-HTTP sources rely on. If Multigres rows come back always classified as success, the OTEL pipeline may not populate `severity_text` for this source (legacy logs read the level from a JSON `event_message`), which would need a source-specific level branch. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for the **Multigres** log type in Unified Logs (labels, icon, and derived filtering/grouping/counting). * Unified Logs now renders Multigres **event_message** by extracting the `msg` field from valid JSON, with correct capitalization. * Unified Logs row click telemetry now recognizes **Multigres**. * The **Multigres** log type option is hidden when the selected project is not high-availability. * **Tests** * Added/updated unit tests for Multigres event-message parsing and shared event-message display behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
3667601895 |
feat(studio): add sign in with ChatGPT (#47772)
## 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 ## Summary Introduce a "Sign in with ChatGPT" option gated by the new `dashboard_auth:sign_in_with_chatgpt` feature flag and a manual localStorage rollout switch (`SIGN_IN_CHATGPT_ENABLED`), since the feature is still WIP. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for signing in with ChatGPT alongside GitHub. * ChatGPT sign-in now depends on both a feature flag and an additional rollout setting. * Updated provider availability so the app can show the correct sign-in options. * **Bug Fixes** * Improved validation and coverage to ensure sign-in options appear only when fully enabled. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
944c5862f3 |
Chore/small refactors (#47740)
## Context Just extracting the fixes which I think are applicable from this [PR](https://github.com/supabase/supabase/pull/47695) Main files are - `apps/studio/hooks/analytics/useLogsQuery.tsx` - `packages/common/auth.tsx` - `packages/common/feature-flags.tsx` ## Changes involved - Adjust `useLogsQuery` to accept an object as prop, rather than 4 individual params - This one doesn't address any Sentry issues, but is just a improvement to the function's API imo, more readable - Adjust how user email is retrieved in `feature-flags` - Related Sentry issue [here](https://supabase.sentry.io/issues/7592718607/?project=5459134) - The error is a bit vague, but Claude's attempt to fix looks alright in general IMO - Minimally verified that feature flags are loading as expected still <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved log-related screens and queries for more reliable loading and filtering across the app. * Fixed profile and account data handling so identity details are retrieved more consistently. * Improved authentication handling to better recognize missing user data and keep the app stable. * Updated feature flag personalization to use more accurate account information. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
18431efb25 |
fix(studio): TanStack post-merge fixes — Monaco loader, fonts, CSP (from #46424) (#47657)
Post-merge fixes for the TanStack Start migration (#46424) — things that broke on the TanStack build as master evolved under the migration branches. Kept on their own branch off master rather than piling onto the E2E-matrix PR (#47119); all land on master and cascade up to S6 + the big PR. Common theme: a master PR changed something the Next pipeline handles via `next/font` / `pages/_app.tsx` / `next.config.ts`, but the hand-rolled TanStack equivalent (`routes/__root.tsx`, `styles/fonts.css`, `vercel.ts`) wasn't updated to match — invisible on the Next deploy, broken only on TanStack. --- ## 1. Monaco loader path (#47182) #47182 re-nested the served Monaco assets from a flat `public/monaco-editor/` layout into `public/monaco-editor/vs/` and updated `pages/_app.tsx`, but `routes/__root.tsx` still pointed `loader.config` at the old path, so `loader.js` 404'd and **no Monaco editor mounted anywhere in the TanStack build**. Now mirrors the Next config (`${origin}${BASE_PATH}/monaco-editor/vs`, window-guarded for SSR). Was failing the whole `tanstack` E2E shard on #47119. ## 2. Inter + Manrope fonts (#47306) #47306 renamed Tailwind's sans var `--font-custom` → `--font-sans` and added `--font-heading` (Manrope), set via `next/font` on Next. `fonts.css` still only set the now-ignored `--font-custom`, so the body fell back to the theme's system chain (`Circular, custom-font, Helvetica…`) at weight 450 — that's the "Inter weights look wrong". Manrope was missing entirely. - Wire `--font-sans` (Inter) + `--font-heading` (Manrope) to match `next/font`. - **Vendor all three families** (Inter, Manrope, Source Code Pro) via `@font-face` so nothing depends on the Google Fonts CDN — matches `next/font` self-hosting, and (see below) `font-src` doesn't allow `fonts.gstatic.com` anyway. Verified in-browser: computed `body` → `Inter`, headings → `Manrope`, all loading from local `/assets/*.woff2`. ## 3. Security headers / CSP (next.config.ts `headers()`) The Next build sets X-Frame-Options / X-Content-Type-Options / HSTS / **Content-Security-Policy** / Referrer-Policy via `next.config.ts`. The TanStack build never carried these over — `vercel.ts` only set cache-control, so **the deployed TanStack dashboard shipped with no CSP at all**. The TanStack deploy serves a static shell (no server to attach headers), so they go in the Vercel config: - `security-headers.ts` — shared source of truth, reuses `getCSP()`, env-gated exactly like next.config. - `vercel.ts` — apply to every response (all base-path prefixes): full `getCSP()` + HSTS on platform. - `scripts/serve.js` — the non-platform set (`frame-ancestors 'none'`) for the self-hosted server. **Tested the policy in a real browser** (temporarily enforced it on the TanStack build via /test-supabase-local): everything passed except one real gap — `font-src` was missing `data:`, so GraphiQL's bundled Monaco codicon font and Stripe's payment-element fonts (both data: URIs) were blocked (37 violations on a cold load). Added `data:` to `font-src` in `csp.ts` → violations drop to zero, SQL editor Monaco renders clean. That gap affects the Next build too. --- ## 4. `node:path` import crashing `/project/[ref]/merge` Found by a full-site click-through of the TanStack build (all product areas, ongoing — see below). `useEdgeFunctionsDiff.ts` + `EdgeFunctionsDiffPanel.tsx` did `import { basename } from 'path'` in client code. Webpack (Next) polyfills `path` in the browser; Vite externalizes it, so the whole `/merge` route crashed with "Module \"path\" has been externalized for browser compatibility". Replaced the two `basename` call sites with a string helper. Verified in-browser: `/merge` renders. ## 5. URL shape — Next-style search-param semantics + shim fixes The dashboard produced malformed URLs vs the Next build (strange query params, trailing slashes, `##` hashes). Root cause + audit verified empirically against `@tanstack/react-router@1.170.10`; all fixed with unit tests and browser-verified: - **`createRouter` used TanStack's default JSON search codec** — `?flag=true` became `?flag=%22true%22` via links, repeated `?filter=…&filter=…` collapsed into a JSON array (breaking multi-filter/sort table-editor URLs and the account-page round-trip, which double-encoded), and search values arrived as numbers/booleans where the app expects strings. New `lib/router-search-params.ts` (Next-style: strings in, strings out, repeated keys → string[]) wired into the router. - **Link shim** (`compat/next/link.tsx`): `URL.hash` includes the leading `#` while TanStack's `hash` prop adds its own → every `href="…#section"` navigated to `##section` (hash-scroll broke); `Object.fromEntries(searchParams)` dropped repeated query params. Both fixed. - **Trailing slash injected before the query** on every `?`-only relative navigation (`/auth/providers/?provider=…`): fixed in the compat router (prefix current pathname) and via a custom nuqs adapter (`lib/nuqs-tanstack-adapter.tsx`) replacing the stock tanstack-router adapter, whose `navigate({ to: '?…' })` writes hit the same TanStack behavior (123 files use nuqs). - **Pathname-less `router.push({ query })` leaked path params** — Next re-consumes `ref`/`id` from `query` into the path pattern; the shim didn't, yielding `/editor/17597?schema=public&ref=<ref>&id=17597&filter=…` from table-editor filter/sort, linter panels, and advisor shortcuts. The shim now defaults the pathname to the current route pattern and backfills omitted params. - **Redirects dropped query + hash** (Next's `redirects()` preserves them): `__root.tsx` `matchRedirect` and `routes/index.tsx` now carry incoming params/hash through (consumed rule params excluded, destination's own params win). `/?next=new-project&projectName=zzz` → `/new/new-project?projectName=zzz`; `/sql/quickstarts?template=x#frag` → `/sql/examples?template=x#frag`. Browser-verified post-fix: advisors `?preset=WARN`, providers `?provider=Google`, `?schema=auth` — all clean (no `/?`, no leaks); repeated `filter` params survive hydration; `=true` unquoted; single `#`. ## 6. TanStack `navigate` corrupting query values (Logs Explorer SQL newline loss) TanStack router-core treats a query string embedded in `navigate({ to })` as part of the *path*: `decodePath` percent-decodes it and `sanitizePathSegment` strips control characters, silently deleting every `%0A`. Logs Explorer's SQL (`s` param) lost its newlines on Run/reload — `order by timestamp desc` / `limit 5` glued into `desclimit 5`, which then failed the LIMIT lint. Pre-existing on the TanStack build (the stock nuqs adapter had the same shape); Next unaffected. Fixed by never embedding query strings in `to`: the nuqs adapter and the compat `router.push`/`replace`/`prefetch` (plus the `next/navigation` shim) now pass search as an object through the app codec (`splitInternalUrl` hoisted to `lib/internal-url.ts`). Guard test drives a real `createRouter` with multi-line SQL through both producers. Browser-verified: newlines survive the full Run → reload → re-Run cycle. ## 7. Integration overview markdown never loaded (all integrations) `MarkdownContent` used a template-literal dynamic import (``import(`@/static-data/integrations/${id}/overview.md`)``) — webpack builds a context module for that, Vite can't analyze it, so every integration detail page threw `Failed to resolve module specifier` and rendered no overview text. Fixed with an explicit lazy registry of literal imports (`static-data/integrations/overviews.ts`, drift-guarded by a test) plus an `mdRawLoader()` Vite plugin mirroring next.config's turbopack raw-loader rule. Both runtimes keep working; md stays out of the main bundle. ## 8. GraphiQL editor never mounted (`exports is not defined`) Our `umdAmdShortCircuit()` Vite plugin (which disarms Monaco's global AMD loader for deps like papaparse) rewrote `typeof define === 'function' && define.amd` to `false` inside `monaco-editor`'s bundled copy of marked — whose UMD relies on its own *local* `define` shim — so the whole optimized monaco chunk failed to evaluate and GraphiQL's editor pane stayed blank. The check now only short-circuits when `define` is the global AMD loader. Browser-verified: all four GraphiQL Monaco panes mount, queries execute. (Known follow-up: GraphiQL's Monaco workers fall back to the main thread under Vite — functional, worker wiring is Next-specific `setup-workers/webpack`.) ## 9. `@sentry/nextjs` bundling Next internals — built TanStack bundle crashed (caught by E2E) The E2E suite against the **built** TanStack bundle (not the dev server) found lazy chunks like `table-editor-*.js` dead on arrival: `@sentry/nextjs` (imported by ~25 client files) drags in `next/dist/shared/lib/constants`, whose module scope evaluates `process?.features?.typescript` — optional chaining doesn't guard an undeclared `process` in the browser, so the whole chunk failed at load with `ReferenceError: process is not defined`. Dev shims `process`, which is why weeks of dev-server testing never saw it. Fixed by aliasing `@sentry/nextjs` → `compat/sentry-nextjs.ts` (re-exports `@sentry/react`, same deduped 10.59.0, plus explicit stand-ins for the three Next-only APIs) in the Vite build only. Verified: fresh build has zero Next-internals markers in any chunk; table editor loads clean; full E2E suite run against the built bundle. Note for the stack: `alaister/tanstack-start` / the E2E-matrix branch already carried a different fix for the same crash (a `next/constants` shim) that never made it to master — the cherry-pick onto those branches keeps **both** (the shim covers any other transitive importer; the alias keeps Next internals out of the client bundle entirely). **Follow-up found while fixing:** Sentry is never *initialized* in the TanStack runtime — `instrumentation-client.ts` / `sentry.server.config.ts` are Next-convention files nothing imports under TanStack, so `captureException` calls are silent no-ops. Needs an `@sentry/react` init (+ `tanstackRouterBrowserTracingIntegration`) wired into the TanStack client entry as its own PR. ## 10. GraphiQL Monaco workers + edge-function Deno typings (Vite-only gaps) - **GraphiQL's Monaco workers ran on the main thread** under Vite ("Could not create web worker(s)…" — `setup-workers/webpack`'s `new URL(...)` form isn't rewritten by Vite). A `graphiqlViteWorkers()` plugin resolves the import to graphiql's own `setup-workers/vite` variant for client builds (SSR untouched, Next untouched); the setup-workers chain is `optimizeDeps.exclude`d because the Rolldown optimizer can't load `?worker` ids. - **Edge-function editors silently lost their Deno typings** — `AIEditor` loaded `public/deno/*.d.ts` via `/* @vite-ignore */` imports that always failed at runtime under Vite. The `.md` raw loader is generalized into `rawTextLoader` (exact-path allowlist for the two typings files, served as virtual string modules so the dep scanner never parses `.d.ts` syntax), and the imports are now static-analyzable literals that both bundlers handle (turbopack's raw-loader rules match them on the Next side). ## Split out for reviewability App-level fixes that reproduce on the Next build too (DOM-nesting hydration errors, the ghost deleted-snippet nav, the recurring pg-meta `migrations` 400) moved to their own PR: #47667. Sentry initialization for the TanStack runtime (captures were silent no-ops) is #47666, stacked on this PR. ## Full-site test campaign Drove every dashboard product area on the local TanStack build (Playwright, human-style) hunting migration regressions: redirects/404/catch-alls, org, account, project home/branches/merge, table editor CRUD, SQL editor (Monaco/run/save/templates/AI), all database pages, all auth pages, storage CRUD, edge functions + realtime, logs/observability, advisors, settings, integrations hub incl. nested routes, global UI (palette/connect/switchers/theme/fonts), and a cross-cutting sweep (document titles, back/forward chain, hard-refresh hydration on deep URLs, trailing-slash active state). Every failure found is fixed above and re-verified in-browser; remaining console quirks were cross-checked against the deployed Next build and are pre-existing (tracked separately). ## To test Most fixes are already browser-verified + covered by unit tests and the self-hosted E2E suite; the last two landed after the final browser pass and still need an in-browser check: 1. **GraphiQL Monaco workers** — restart the dev server (clear `apps/studio/node_modules/.vite` once first — the optimizer cache may hold a stale prebundle of the worker chain). Open `/project/<ref>/integrations/graphiql/graphiql` with the console open: the `Could not create web worker(s). Falling back to loading web worker code in main thread` warning must be gone, and DevTools → Sources → Threads shows the three workers (json, editor, graphql). Autocomplete in the query editor stays responsive. 2. **Edge-function Deno typings** — `/project/<ref>/functions/new`: no "Failed to load … typings" console error, and typing `Deno.` in the editor offers typed completions (e.g. `Deno.env`). Spot-checks for the rest (all previously verified): - `/project/<ref>/merge` renders (no "Module path" crash). - Multi-line SQL in Logs Explorer survives Run → reload (no `desclimit` gluing, no LIMIT-lint false failure); `s` param keeps `%0A`. - `/auth/providers` → open a provider → `?provider=…` with no trailing slash before `?`; table-editor filter/sort URLs carry no leaked `ref`/`id` params; `/?next=new-project&projectName=x` lands on `/new/new-project?projectName=x`. - Integration detail pages (cron/queues/vault/data_api) show their overview prose; GraphiQL query editor mounts. - Built bundle (`MODE=test vite build` + `start:tanstack`): table editor loads with no `process is not defined`. - `curl -sI` any page on a platform deploy: `X-Content-Type-Options: nosniff` (was the invalid `no-sniff`). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Centralized integration overview markdown loading with registry-based lookup. * Improved Monaco loading/asset path handling for smoother editor startup. * **Bug Fixes** * Next-style navigation/search handling now preserves pathname, hash, repeated query keys, and special characters (including newlines). * Redirects now reliably carry over query and hash with correct precedence. * **Security/Configuration** * Updated CSP font sourcing and unified security headers delivery across environments; conditional HSTS behavior. * Refreshed font CSS variables and font-face definitions to match the theme. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --- ### Review feedback: non-prod favicon (Joshen) The TanStack `__root.tsx` hardcoded the prod favicon; local + hosted staging now use the white staging favicon (`/favicon/staging`), matching what `pages/_app.tsx` passes to `MetaFaviconsPagesRouter` for non-prod. Rather than pull the pages-router component into the TanStack head, it reuses the same synchronous `NEXT_PUBLIC_ENVIRONMENT` signal the file already uses for `IS_DEV_TOOLBAR_ENABLED` (the `head()` route option isn't a React component, so it can't run `_app`'s async CLI check — but the env signal covers the reported local/staging case). --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
9af6e65df4 |
fix(studio): DOM-nesting hydration errors, ghost deleted-snippet nav, and migrations query 400s (#47667)
App-level fixes that reproduce on BOTH the Next and TanStack builds — split out of #47657 (which stays TanStack-only) for reviewability. All were found by a full-site click-through of the dashboard. ## Invalid HTML nesting (React 19 "will cause a hydration error" console errors) - **FormLayout description rendered in a `<p>`** (`packages/ui-patterns`): consumers pass arbitrary JSX (the RowEditor's `created_at` timezone note passes a `<div>` with `<p>`s) → `<p>`-in-`<p>` / `<div>`-in-`<p>`. Container is now a `<div>` with identical classes (Tailwind preflight makes them render the same). - **Switch toggles nested inside Tooltip trigger buttons** (button-in-button) in ColumnEditor ("Allow Nullable" + "Is Unique"), ExtensionRow, and PublicationsTableItem → repo-standard `TooltipTrigger asChild` + `<div>` wrapper. - **Saved log queries rendered a `<div>` directly inside `<tbody>`** (`/logs/explorer/saved`) → rows are now proper `<tr><td colSpan>` wrappers; the component itself is untouched (it's valid in its sidebar usage). - **Nested anchors in observability metric cards**: a card-level `<Link>` wrapped MetricCard's "More information" `<Link>` (identical URLs) → the chevron affordance renders as a `<span>` when no `href` is passed; clicks bubble to the card link, tooltips preserved. Design-system standalone usage unaffected. - **`objectFit="cover"` passed to modern `next/image`** on the featured integration card (unknown-prop warning) — the className already had `object-cover`; prop dropped. ## Ghost dead-snippet after deletion Deleting the active SQL snippet left its id in `useDashboardHistory` (`history.sql`), so the "SQL Editor" nav item navigated to `/sql/<deleted-id>` — content fetch 404s, no editor pane renders, and a phantom tab reappears. Fixed both ends: delete flows now purge dashboard history (and the tabs store clears a stale `previewTabId`), and `/sql/[id]` treats a snippet 404 as "clean up + `router.replace` to `/sql/new` + toast" instead of rendering the dead state. Unit tests for the store/history cleanup. ## `pg-meta` migrations query 400s on every project load `ActivityStats` on project home runs the migrations list query, whose SQL was a bare `select * from supabase_migrations.schema_migrations` — that table only exists once a migration has run, so every other project logged a failed `?key=migrations` request on every load (visible in production consoles too). The SQL is now guarded with `to_regclass` + `query_to_xml` (same pattern as the advisor lints' `storage.buckets` guard), returning zero rows instead of erroring; legacy version-only tables still work. Tested against real dockerized Postgres (absent table, populated ordering, special chars, legacy schema) + MSW hook tests. Found and verified via /test-supabase-local (browser click-through + console audit on both builds). ## To test Console must stay free of React DOM-nesting errors ("cannot be a descendant of" / "cannot contain a nested") on each surface: 1. Table editor → Insert row panel (`created_at` field renders its timezone note) and Edit column panel ("Allow Nullable"/"Is Unique" tooltips still hover). 2. `/database/extensions` and `/database/publications` → toggle switches render, tooltips hover. 3. `/logs/explorer/saved` (with ≥1 saved query) → rows render full-width inside the table, hover shows Actions. 4. `/observability` → no nested-anchor error on load; card body click and the chevron both navigate; label help-icons still show tooltips. 5. `/integrations` → no `objectFit` unknown-prop warning; featured card images still cover. 6. **Ghost snippet**: open a SQL snippet → delete it via the sidebar → click the "SQL Editor" nav item → lands on `/sql/new` (no phantom tab, no 404 content fetch). Direct-load `/sql/<random-uuid>` → toast + redirect to `/sql/new`. 7. **Migrations 400**: load project home with a project that has never run a migration → the `pg-meta/<ref>/query?key=migrations` request returns **200** with `[]` (previously a 400 on every load). Database → Migrations still lists real migrations when they exist. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit * **Bug Fixes** * Deleted SQL snippets are fully removed from dashboard history and stale editor/tab state; users are redirected with a toast. * Closing preview tabs no longer leaves stale references. * Improved toggle/tooltip/dialog interactions to avoid broken UI, including metric headers showing tooltips even without direct links. * Migrations display safely when migration tables/relations are missing. * **UI Improvements** * Refreshed layout for saved queries, form descriptions, and integration imagery. * **Tests** * Added coverage for snippet history cleanup, tab removal, migrations SQL behavior, and query edge cases. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --- ### Review feedback: `query_to_xml` breaks on Multigres (Ivan) The defensive migrations query (added here to stop the `?key=migrations` 400 when the table doesn't exist yet) originally guarded with `query_to_xml`, which is forbidden through Multigres's pooler (MUL-736 / PSQL-1318). Rewritten without `query_to_xml`/`xmltable` using the splinter#170 pattern: a PL/pgSQL `do` block guarded by `to_regclass` (PL/pgSQL defers planning, so a missing table never errors) stashes the rows into a transaction-local GUC via `set_config`, and a trailing `select` reads them back with `jsonb_array_elements`. Verified that postgres-meta sends the whole SQL as one simple-query string → single implicit transaction → the local GUC survives to the `select` and doesn't leak into the pooled connection. 6/6 dockerized-Postgres tests (absent table → `[]`, populated/ordered/special-chars, legacy version-only table, full pg-meta-shaped multi-statement string, GUC non-leakage). Note (out of scope, pre-existing): `packages/pg-meta/src/sql/studio/advisor/lints.ts` still uses `query_to_xml` — a separate pre-existing Multigres risk that should get its own splinter-pattern sync. --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Joshen Lim <joshenlimek@gmail.com> Co-authored-by: Saxon Fletcher <saxonafletcher@gmail.com> |
||
|
|
5dc054ae8f |
feat(studio): warn in Connect sheet when Data API is disabled (#47537)
## What kind of change does this PR introduce? Feature. Resolves DEPR-599. ## What is the current behavior? When the Data API is disabled (PostgREST has no exposed schemas), the Connect sheet still shows client-library setup steps for Framework and MCP modes without indicating that database queries will fail. ## What is the new behavior? When database access via the Connect instructions requires PostgREST, an inline warning appears above the steps (setup instructions remain visible): - **Framework**: warns when Data API is off; install, env vars, and auth/SSR setup still work - **MCP**: warns only when Database tools apply (selected explicitly, or by default when no feature filter is set) The warning fails open if PostgREST config cannot be loaded, and links to Data API settings via an "Enable Data API" CTA. | After | | --- | | <img width="1664" height="718" alt="CleanShot 2026-07-02 at 21 29 16@2x" src="https://github.com/user-attachments/assets/80d21927-c4dd-4158-8946-bf648b95e451" />| ## Additional context - Gating logic lives in `ConnectStepsSection.utils.ts` with unit tests - Out of scope: warning when Data API is on but zero tables/schemas are exposed - Coexists with the upcoming warehouse branch's catalog warning — that lives in a separate `WarehouseCatalogPanel` for `catalog` mode only <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Connection setup now checks Data API enablement and conditionally shows a “Data API disabled” warning, including an action to open Data API settings. * **Bug Fixes** * Warning logic now more accurately reflects the selected connection mode and chosen feature/tool selections. * **Tests** * Added a focused test suite covering the Data API configuration decision rules and when the warning should appear. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
a6a04f24cd | fix(studio): correct exposed-schema settings for the Data API (#47511) | ||
|
|
3fcf980b0a |
fix(studio): batch of production Sentry crash fixes (array/null guards) (#47460)
Fixes a batch of production Studio crashes from Sentry (all caught by the global error boundary). Most are missing array/null guards where an endpoint typed as an array — or with a nested array field — returned a non-array body in production; a few are one-off render crashes. Resolves FE-3748. ## Issues fixed | Sentry | Error | Fix | | --- | --- | --- | | [J7R](https://supabase.sentry.io/issues/7492997940/) | Maximum update depth exceeded | Disable RadialBar animation in disk-cooldown countdown | | [JR5](https://supabase.sentry.io/issues/7548484681/) | resourceWarnings.find is not a function | Guard in ResourceExhaustionWarningBanner | | [JCJ](https://supabase.sentry.io/issues/7506024989/) | resourceWarnings.find is not a function | Guard in ProjectLayout + normalize query | | [K1Y](https://supabase.sentry.io/issues/7584792331/) | snippet.name on undefined | Optional-chain SQL editor download filename | | [B3K](https://supabase.sentry.io/issues/7141649636/) | pagination.count on undefined | Guard pagination in projects infinite query | | [JVP](https://supabase.sentry.io/issues/7560437621/) | schemas.some / extensions.find | Coerce pg-meta lists to arrays in useInstalledIntegrations | | [JR2](https://supabase.sentry.io/issues/7548339272/) | extensions.find is not a function | (same fix as JVP) | | [JQR](https://supabase.sentry.io/issues/7547163939/) | lints.filter is not a function | Normalize project lints query | | [JR3](https://supabase.sentry.io/issues/7548433501/) | entitlements.find is not a function | Guard call sites + normalize entitlements query | | [JQS](https://supabase.sentry.io/issues/7547557098/) | selected_addons.find is not a function | Normalize addons query arrays | <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved stability across several Studio screens by handling missing or unexpected data more safely. * Downloads now use a fallback name when a snippet name isn’t available. * Project, entitlement, schema, addon, warning, and extension views are less likely to break when data is missing or not in the expected format. * Pagination and countdown visuals now behave more consistently, with reduced chance of runtime errors or animation-related glitches. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
0abfbdd3d7 |
fix(studio): preserve session and redirect to MFA when AAL elevation is needed (#47145)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Bug fix. ## What is the current behavior? `withAuth` calls `signOut()` and redirects to `/sign-in` whenever the current AAL is below the required level. For IdP-initiated SSO logins — where the user lands directly on `/dashboard` rather than passing through `/sign-in-mfa` — this destroys the valid AAL1 session that was just established. Subsequent mgmt-api requests then return 401 Unauthorized, and the user is dumped on `/sign-in` with no way to recover except restarting the SSO flow (which loops them back to the same state). The platform already returns an actionable `403 Insufficient AAL: MFA required` on the first mgmt-api request, but the dashboard does not capture it. ## What is the new behavior? `withAuth` now distinguishes between "not logged in" and "needs AAL elevation": - **Logged in but AAL1** → `router.push('/sign-in-mfa?returnTo=…')`, session preserved. The existing `/sign-in-mfa` page picks up the session, renders the MFA form, and bounces the user to `returnTo` after a successful challenge. - **Not logged in** → unchanged: `signOut()` then redirect to `/sign-in?returnTo=…`. - `/sign-in-mfa` is also added to the "already there, do nothing" guard so the user isn't re-redirected mid-challenge. This relies on the gotrue client's local AAL state via `useAuthenticatorAssuranceLevelQuery`, which fires before any mgmt-api request, so no fetcher-level error parsing is needed. ## Additional context <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved multi-factor authentication (MFA) elevation flow to preserve user sessions instead of forcing sign-out and requiring users to restart sign-in. * Fixed unnecessary redirects when users are already on sign-in pages. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
c6fc456910 |
chore: cleanup duplicate exports studio (#47387)
## Problem Knip reports many duplicate exports (both named and default). Besides, we're moving away from default exports and even have an eslint rule to enforce it on new code. ## Solution - Cleanup those exports - Update imports when necessary No functional changes. If it builds, it's fine |
||
|
|
2aa1b52234 |
feat(studio): add feature to rewrite queries DEBUG-145 (#47266)
## Problem Moving the Logs Explorer to ClickHouse means users' saved BigQuery queries no longer run. <img width="2430" height="1010" alt="CleanShot 2026-06-29 at 11 36 04@2x" src="https://github.com/user-attachments/assets/ae0ab155-7d3d-4ae9-81c3-22bf3a88cf8c" /> ## Fix Rewrite the query with AI instead of a SQL transpiler. AI handles the long tail of nested fields and dialect differences far better than a rule-based rewriter, and it needs no extra runtime dependency. - `rewriteLogsSqlWithAI` posts the current query to `/api/ai/code/complete` with `dialect: 'clickhouse'`. The endpoint skips the Postgres schema and best-practices for that dialect and uses logs-specific instructions and model so the output is ClickHouse logs SQL (FROM `logs` + `source` filter, no `unnest` joins, nested fields read from `log_attributes['...']`). - The query's `source` is detected and its real `log_attributes` keys are fetched and passed to the model, so it maps to exact paths instead of guessing. - The rewrite runs in the background and is proposed as a side-by-side accept/discard diff in the editor. The AI Assistant panel is not opened. - Entry points: a banner shown only for legacy-looking queries (dismissal persisted), and a "Fix Query" button next to Field Reference. - The Field Reference drawers discover `log_attributes` keys from real data so the listed fields match what the source actually emits. ## Dependencies Built on top of #47265 (Logs Explorer -> OTEL endpoint) — that is the base branch of this PR. Merge #47265 first. Behind `otelLegacyLogs` (off by default). Part of DEBUG-145 (split from #47087). ## How to test - Open the Logs Explorer with a BigQuery logs query (the templates have some), click "Fix Query", and confirm the diff shows valid ClickHouse SQL. Accept it and confirm the applied query runs. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added an OTEL legacy logs workflow (behind a feature flag) with an interactive banner and a “Fix Query” ClickHouse rewrite action, including an accept/discard diff review overlay. * Introduced OTEL-aware field reference rendering with dynamic discovery of `log_attributes` keys and updated OTEL source insertion behavior. * Enabled dialect-aware SQL completion for ClickHouse logs, using logs-specific instructions and output constraints. * **Bug Fixes** * Improved rewrite flow validation and handling, including log source detection and cleanup of AI-generated SQL formatting. * **Tests** * Added Vitest coverage for rewrite prompt generation, detection/classification utilities, SQL fence stripping, OTEL field mapping, and OTEL log attribute key discovery. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
143769afac |
feat(studio): shared High Availability disabled hook and UI primitives (#47322)
Add generic building blocks for blocking features on High Availability projects: - useHighAvailability hook: HA state only (isHighAvailability, isPending) - HighAvailabilityDisabledEmptyState (full-page empty state) - HighAvailabilityDisabledSectionNotice (in-section admonition) The components carry a generic default title/description; consuming pages pass their own copy via props. HA state is read from the project's high_availability flag (same source as the High Availability badge on the project home page). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added clearer messaging for features that aren’t available in High Availability projects. * Introduced a standard High Availability status check to help the app adapt what it shows. * **Bug Fixes** * Hid non-applicable schema options when High Availability is enabled, reducing confusion in selection lists. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
e0ba04caf4 |
feat(studio): migrate per-service log pages to OTEL endpoint behind a flag DEBUG-145 (#47264)
## Problem The legacy per-service log pages (postgres, auth, api, edge functions, storage, realtime, cron, etc.) and the single-log detail panel query the BigQuery-backed `logs.all` analytics endpoint. We are moving these reads onto the OTEL ClickHouse endpoint (`logs.all.otel`). ## Fix - Add `Logs.utils.otel.ts`: ClickHouse query builders (rows/count/chart/single) + row mappers that target the single `logs` table keyed by `source`, reading fields from the `log_attributes` map and aliasing columns to the leaf names the renderers expect. - Parameterize `buildWhereClauses` / `genWhereStatement` in `Logs.utils.ts` so the OTEL builders reuse the shared nested AND/OR filter grouping. Defaults keep the BigQuery behavior unchanged. - Gate `useLogsPreview` (rows, count, chart) and `useSingleLog` (detail) on the new `otelLegacyLogs` flag. BigQuery stays the default when the flag is off. - Extract the OTEL timestamp parser into `parseOtelTimestamp` (`otel-inspection.utils.ts`) and reuse it in `unified-logs-infinite-query.ts` (replaces an inline copy of the same logic; no behavior change). ## Dependencies None. Standalone, safe to merge on its own. Behind `otelLegacyLogs` (off by default), so no user-facing change. Part of DEBUG-145 (split from #47087). ## How to test - In staging, go to Legacy Logs. - All logs pages should work the same as before. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added OTEL-backed logs support for preview, count, chart, and single-log details when enabled. * **Bug Fixes** * Improved timestamp parsing/normalization for OTEL data to ensure correct display and pagination. * Enhanced filtering behavior, including safer handling of unknown filter keys and invalid values across OTEL queries. * Improved single-log result shaping to preserve expected API/database metadata in OTEL mode. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
f34aa108d5 |
chore: dead code cleanup (#47294)
## Problem There's still more unused code in the repository which slows down everything: - checkouts - tooling - probably builds (not sure how good turbopack is at handling this) ## Solution - remove old unused code - remove more recent code after checking git history to ensure it's not unfinished/ongoing work <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Removed several unused interface, onboarding, and helper components from the studio app. * Cleaned up outdated branching, integrations, query performance, support, and table/grid UI elements. * Removed a few unused utility hooks and key-mapping logic. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
9eab4f8fbf |
build(studio): Vite/TanStack-Start build pipeline behind flag (stack 1/6, from #46424) (#47107)
**Stack 1/6** of the TanStack Start migration (#46424), split into reviewable, independently-mergeable PRs. > [!IMPORTANT] > **Next stays the default and only active framework after this PR.** This wires up the Vite/TanStack-Start build pipeline behind the `STUDIO_FRAMEWORK` flag, but there are no TanStack routes yet — so the TanStack build isn't functional or tested until later PRs in the stack. Nothing about the Next build, dev, or deploy changes behaviourally here. ## What's in this PR - **Dispatch:** `dev`/`build`/`start` now go through `scripts/dispatch.js`, which runs the Next variant unless `STUDIO_FRAMEWORK=tanstack`. The original commands are preserved as `dev:next`/`build:next`/`start:next`. - **Build pipeline:** `vite.config.ts`, `serve.js`, `smoke-server.mjs`, vite/tanstack deps, `turbo.jsonc`. - **`tsconfig.json`:** `jsx: react-jsx`, `moduleResolution: Bundler`, `target: ES2022`. Because `include` is `**/*.ts(x)`, this re-typechecks the whole app, so the companion adaptations below land with it. - **Shared adaptations (companions to the tsconfig change):** `BufferSource` casts, `packages/ui` unused-`React` import removals, etc. - **Routing/middleware plumbing:** `next.config.ts` + `redirects.shared.ts` (redirect rules now shared with `vercel.ts`), `proxy.ts`/`start.ts` middleware + `hosted-api-allowlist.ts`. ## Verification Run locally off `master`: frozen install ✓, `studio` typecheck ✓, **Next build ✓** (compiles + generates all routes), lint ratchet ✓ ("some rules improved"), prettier ✓. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a hosted API endpoint allowlist to return 404 for non-supported `/api/*` routes. * Introduced a TanStack route-migration checklist and expanded TanStack Start routing support. * **Improvements** * Enhanced deployment refresh/detection by tightening cookie handling for “latest deployment” updates. * Centralized redirect/maintenance-mode rules for consistent platform vs self-hosted behavior. * Improved production serving with a dedicated static + proxy server and a post-build smoke test. * **Dependencies** * Updated TanStack-related packages and React Table/query tooling versions. * **Documentation / Chores** * Updated formatting and tooling config; added shared build environment parsing utilities. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
fd0f2dd459 |
Scope last visited organization local storage to profile (#47071)
## Context If a user switches account without an explicit log out via the dashboard, landing back on `/org` will redirect users to the last visited organization as stored in local storage, in which it can result in the following state if the last visited organization does not exist in the current account <img width="2538" height="1060" alt="image" src="https://github.com/user-attachments/assets/270e482a-3515-48ef-898b-87e76fce80d6" /> ## Changes involved Am opting to scope the last visited organization to the user profile instead - this would be a bit more cleaner than trying to actively clear the last visited org slug from local storage with implicit account changes as there's no deterministic way to track that (afaik) from FE side of things ## To test Can reproduce the problem as such - Ensure that you have 2 accounts to log in with, and one account has an org that the other is not a part of - For the organization that has the "extra" org, ensure that you click into it so that the last visited org slug is saved in local storage - Mimic changing accounts by visiting `/auth/v1/authorize?provider=github` (using the domain for the env that you're testing on - e.g localhost:8000 for local, or green for staging preview) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Unified “last visited organization” handling across the Studio UI with a shared hook, improving consistency for home/dashboard return, cancel/back navigation, and account routing. * **Bug Fixes** * Updated redirects to only route to an organization when a valid last-visited value is available; otherwise users go to the general organizations page. * Kept MFA enrollment and factor delete/leave flows aligned to the unified last-visited organization value. * **Tests** * Updated onboarding and layout tests to match the new last-visited organization storage key format and hook/query success behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
e491182054 |
Auth flow improvements (#46967)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES/NO ## What kind of change does this PR introduce? Bug fix, feature, docs update, ... ## What is the current behavior? Please link any relevant issues here. ## What is the new behavior? Feel free to include screenshots if it includes visual changes. ## Additional context Add any other context or screenshots. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **New Features** * Added “Continue with {provider}” sign-in and sign-up flows using enabled external identity providers. * Enabled inbound branding to focus a specific provider for customized sign-in/sign-up experiences. * **Improvements** * Refined the sign-in options layout and “last used” tracking for clearer authentication choices. * Updated account identity/provider connection experiences (link/unlink and management UI). * **Bug Fixes** * Fixed hydration mismatches in sign-in and password-related layouts. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
dc5ddd8c4c |
chore(telemetry): align event interface names with action strings (#47048)
## Summary Aligns 16 telemetry event interface identifiers in `packages/common/telemetry-constants.ts` so each interface name equals the PascalCase of its `action` string (`PascalCase(action) + Event`). This is a follow-up to the GROWTH-798 audit (#45964), which fixed the `action` strings and several interface names but left these 16 identifiers mismatched. I renamed identifiers only: every `action` string is untouched, so there is zero impact on PostHog event names or historical data. Before this change, 176/192 interfaces matched the convention. This brings it to 192/192. ## Changes Structural renames (interface name was dropping or reordering words vs the action): - `AskAIEvent` to `AskAiClickedEvent` - `CopyAsMarkdownEvent` to `CopyAsMarkdownClickedEvent` - `DocsRecommendation404ClickedEvent` to `Docs404RecommendationClickedEvent` (from #46990) - `EventPageCtaClickedEvent` to `WwwEventPageCtaClickedEvent` (completes the interface side of GROWTH-798 HIGH #1) - `ImportDataFileAddedEvent` to `ImportDataDropzoneFileAddedEvent` (also updates the consumer `apps/studio/hooks/ui/useCsvFileDrop.ts`) - `QueryPerformanceAIExplanationButtonClickedEvent` to `QueryPerformanceExplainWithAiButtonClickedEvent` Initialism casing (normalized to the file-majority lowercase transform; `Sql` 9:2, `Api` 3:2, `Ai` 6:2): - `CustomReportAddSQLBlockClickedEvent` to `CustomReportAddSqlBlockClickedEvent` - `CustomReportAssistantSQLBlockAddedEvent` to `CustomReportAssistantSqlBlockAddedEvent` - `HomepageGitHubButtonClickedEvent` to `HomepageGithubButtonClickedEvent` - `MetricsAPIBannerCtaButtonClickedEvent` to `MetricsApiBannerCtaButtonClickedEvent` - `MetricsAPIBannerDismissButtonClickedEvent` to `MetricsApiBannerDismissButtonClickedEvent` - `TableRLSEnabledEvent` to `TableRlsEnabledEvent` - `RLSGeneratePoliciesClickedEvent` to `RlsGeneratePoliciesClickedEvent` - `RLSGeneratedPolicyRemovedEvent` to `RlsGeneratedPolicyRemovedEvent` - `RLSGeneratedPoliciesCreatedEvent` to `RlsGeneratedPoliciesCreatedEvent` - `RLSTesterRunQueryClickedEvent` to `RlsTesterRunQueryClickedEvent` ## Testing Type-only change, no runtime or PostHog behavior to exercise. Verified that all 192 interfaces now match `PascalCase(action) + Event` (0 mismatches), the `TelemetryEvent` union has no duplicates, no old identifier names remain anywhere in the repo, and the one external consumer (`useCsvFileDrop.ts`) still resolves via its `['action']` indexed access since the action strings are unchanged. ## Linear - fixes GROWTH-928 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Updated internal telemetry infrastructure for consistency and maintainability. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
96d43099bb |
chore: refactor Button API so that it can be used a standard button (#46880)
## Problem Our `<Button>` component breaks the default `button` contract by redefining the `type` prop to set its variant (`primary`, `default`, etc) instead of the button type (`submit`, `button`, etc). This is confusing and forces to write more code when using it with shadcn components that expect/inject the standard button props. ## Solution - rename the `type` prop to `variant` - rename the `htmlType` prop to `type` - propagate the changes where necessary - format code ## How to test As this is just prop renaming, if it builds it's ok --------- Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
92e79e67d9 |
feat: Add error state to charts (#46991)
This PR adds an error state to the usage charts on the Project home page. <img width="1708" height="471" alt="Screenshot 2026-06-16 at 18 10 20" src="https://github.com/user-attachments/assets/cba87dad-5e23-4cd1-b787-0ea699445d7f" /> I also added an error state to the charts in the [design system](https://design-system-git-feat-chart-error-state-supabase.vercel.app/design-system/docs/ui-patterns/charts#chart-states). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Charts now display error states when data retrieval or processing fails, providing users with clear feedback about issues. * Improved error visibility and handling across analytics and charting components for better transparency. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
1baaded0bb |
Consolidate execute-sql-query into execute-sql-mutation (#46944)
## Context Just some clean up as I was going through stuff - `useExecuteSqlQuery` is deprecated and not used at all - As such `execute-sql-query` is technically irrelevant, the more relevant file is `execute-sql-mutation` - Hence opting to consolidate `execute-sql-query` into `execute-sql-mutation` - Also removing `ExecuteSqlError` since its just re-exporting the `ResponseError` type There's a lot of file changes but its essentially just updating the importing statements across the files |
||
|
|
2191669d08 |
feat(studio): add upgrade CTA placement experiment (#45858)
## Summary Replaces the header upgrade CTA (PR #44494, which design team wanted to iterate on) with a placement experiment that tests three non-chrome surfaces for the free-plan "Upgrade to Pro" CTA. PostHog flag `upgradeCtaPlacement` (free-plan users only) with four arms: | Variant | Surface | | --- | --- | | `control` | No CTA (baseline cohort, still tracked) | | `user_dropdown` | Full-width button pinned in the account dropdown | | `org_projects_list` | Project-card-shaped usage tile, first card in the org project grid | ## Details ### `user_dropdown` - Full-width `Upgrade to Pro` button in `UserDropdown`, gated to org-scoped routes only (`/project/*`, `/org/*`) so the org-billing CTA never shows on `/account`, `/organizations`, etc. — addresses the scope concern raised in review. - Dropdown uses controlled `open` state so it closes before navigation (it lives in the global layout, so a route change alone wouldn't dismiss the overlay). ### `org_projects_list` - `PlanUsageCard` renders as the first `<li>` in the project grid (via `ProjectList`'s `prependCard`), matching `ProjectCard` shape so it reads like another project tile. Also renders during the project-list loading state to avoid pop-in. <img width="3804" height="1494" alt="Arc 2026-06-08 20 02 54" src="https://github.com/user-attachments/assets/09c2218c-43d1-49ce-bae7-5075c9750d72" /> ### Shared card styling - Metric rows (Egress, Database size, Monthly active users, File storage) show `current / limit` with a progress ring; ring/value turn warning at ≥80% and over at ≥100%. - Rows are clickable deep-links to `/org/[slug]/usage#<anchor>` with a hover chevron and dashed separators; the same row component is used by both the embedded and project-card variants. - Skeleton placeholder renders from first paint so the card reserves layout while `useOrgUsageQuery` resolves. - Exposure is fired optimistically while the org query loads (skeleton shows immediately), but the experiment exposure event only fires once free-plan is confirmed. ### Telemetry - `upgrade_cta_clicked` with `placement: user_dropdown | home_usage_card | org_projects_list`. - `upgrade_cta_placement_experiment_exposed` with `variant` — the custom exposure event (snake_case experiment id `upgrade_cta_placement`; the flag key stays camelCase `upgradeCtaPlacement`). ### Header CTA sunset - `HeaderUpgradeButton` and its wiring in `LayoutHeader` / `MobileNavigationBar` removed (master's #46144 already removed the button; this branch drops the remaining `header_upgrade_cta_clicked` event). ## Before merging - [x] Create the `upgradeCtaPlacement` flag + experiment in PostHog (4 variants, free-plan targeting, custom exposure event `upgrade_cta_placement_experiment_exposed`). - [x] Archive the now-orphaned `headerUpgradeCta` flag. ## Test plan - [x] Override the flag per variant via the dev toolbar on staging; confirm each surface renders and `upgrade_cta_clicked` fires with the right `placement`. - [x] `control` shows no CTA but still emits the exposure event. - [x] Paid-plan org and self-hosted (`IS_PLATFORM=false`) show nothing. - [x] Clicking a metric row deep-links to the matching usage section; clicking Upgrade routes to billing. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Experimentally surface an “Upgrade to Pro” CTA in the user dropdown and on the projects page for eligible free-plan orgs. * Added a Plan Usage card showing free-plan metrics and upgrade prompts on the organization projects page; hides when irrelevant or errored. * Project list and its loading view support inserting a custom/prepend card in card mode. * **Telemetry** * Added tracking for CTA clicks and experiment exposure; placement is persisted per org. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: kemal <hello@kemal.earth> |
||
|
|
2c915ca9fb | fix(observability): align overview Connections count with details view DEBUG-75 (#46271) | ||
|
|
ff34a6753c |
chore: remove unnecessary <PreventNavigationOnUnsavedChanges> (#46763)
## Problem Since the refactor done in #43900, the `<PreventNavigationOnUnsavedChanges>` does not bring much value. ## Solution Remove `PreventNavigationOnUnsavedChanges` and update consumers to leverage `usePreventNavigationOnUnsavedChanges` and `DiscardChangesConfirmationDialog` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Improved the architecture of unsaved-changes navigation handling across multiple features. Components now use a more modular hook-based approach for better code organization and consistency. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
1c2d28d5b3 |
chore: wrap local storage into helper methods that are safer (#46628)
## 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? - Noticing our code we have many patterns of calling localstorage and handling those errors - We should add those in a single well tested file - Handle those errors in the singleton which makes it easier for us to debug customer issues. Logger is outputing local storage warnings for feature we expose - Side effect of this is random crashes on studio when local storage isn't available or handled correctly <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Improved browser storage handling across the app for more reliable persistence and graceful behavior in restricted or non-browser environments (settings, previews, charts, tabs, sign-in/session flows, integrations, and UI state). * **New Features** * Introduced a safe storage layer to standardize and harden local/session persistence. * **Tests** * Added comprehensive tests covering the new safe storage behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
a7dda67549 |
feat(studio): add Multigres logs collection for HA projects (#46499)
## Problem High availability (Multigres) projects don't expose Multigres service logs in the Studio logs UI, so users on HA projects have no entry point to inspect them. ## Fix Add a `Multigres` logs collection, gated behind the `multigresLogs` ConfigCat flag **and** the project's `high_availability` flag (`useShowMultigresLogs`): - New `Multigres` entry in the logs sidebar `Collections`, linking to a new `multigres-logs` page that queries the `multigres_logs` table. - Wire `multigres_logs` through the logs constants, types, table SQL, query type, and service labels. - Row formatting: parse the JSON `event_message` and render `level` through `SeverityFormatter` and `msg` through `TextFormatter`, matching the other service collections (instead of dumping raw JSON). - `WARN` severity is now styled like `WARNING` (amber), since Multigres emits `level: WARN`. - Log detail drawer: parse the JSON `event_message` and spread its keys onto the log so each field (level, msg, query, error, connection_id, etc.) renders as its own collapsible row. - Single-log query omits the `metadata` column for `multigres_logs` (the table has no such column), fixing an `INVALID_ARGUMENT` error when opening the detail drawer. - Event chart: parse the level out of `event_message` via `JSON_VALUE` so error/warning bars are counted (the table has no top-level level column). - Add the `multigres_logs` source schema to the Field Reference drawer, same gating. ## Why a feature flag `high_availability` is an existing product feature that predates Multigres, so existing HA projects could otherwise see a broken collection querying a `multigres_logs` table they don't have. Requiring the `multigresLogs` flag ships the feature dark and decouples rollout from HA status. The flag must be created in ConfigCat before enabling; until then `useFlag` returns false and the feature stays hidden. ## How to test - Enable the `multigresLogs` flag (or override locally) and open a project where `high_availability` is `true`. - Navigate to `Logs`. Confirm a `Multigres` entry appears under `Collections` (after `Replication`). - Open it: the page loads at `/project/<ref>/logs/multigres-logs` and queries `multigres_logs`. - Confirm rows show a colored severity pill (including amber `WARN`) and a readable message rather than raw JSON. - Confirm the chart counts error/warning bars correctly. - Click a row: the detail drawer shows each parsed field as its own row, with no error. - Open the Field Reference drawer and confirm `Multigres` is listed as a source. - With the flag off, or on a non-HA project, confirm the collection and Field Reference source are both hidden. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Multigres added as a dedicated log source with its own Logs page, sidebar entry, and query type. * Log list and preview now parse Multigres payloads to surface timestamp, severity, and formatted message. * Multigres integrated into charting, prompt labels, and field-reference UI (hidden unless enabled). * New hook controls showing Multigres UI only when feature flag + HA project condition are met. * **Bug Fixes** * Severity rendering treats "WARN" the same as "WARNING". * **Tests** * Unit tests added for Multigres parsing and the show-Multigres hook. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
fa55a9c4bd |
chore: use ro connstring for observability (#44806)
## 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? function change ## What is the current behavior? defaults to the read-write connection string when doing observability report queries ## What is the new behavior? uses the read-only connection string instead ## Additional context these should only ever be read-only operations, reporting should not have side effects and this adds a guardrail to ensure that remains the case <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit **Bug Fixes** - Corrected database replica query handling by using read-only connection strings for replica database access. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
7f5e3cab93 | chore(studio): remove expired Fly.io deprecation banner (#46535) | ||
|
|
fd1f437eca |
feat(logs): brand remaining analytics SQL callers with SafeLogSqlFragment (#46476)
## Summary
PR 10 of the analytics SQL safety series. Migrates the last surface of
analytics queries that flowed through plain
`get(.../analytics/endpoints/logs.all, { query: { sql } })` or the
`fetchLogs(projectRef, sql: string, ...)` helper over to
`executeAnalyticsSql` with branded `SafeLogSqlFragment` inputs.
After this PR, every analytics SQL call site builds its query through
the safe-analytics-sql helpers and hits the wire through the single
`executeAnalyticsSql` boundary. User-controlled values (filter
operators, numeric thresholds, function IDs, regions, provider names)
all flow through `analyticsLiteral` / branded operator maps; static
fragments are wrapped in `safeSql`. PR 11 (ESLint / vitest rule
forbidding direct analytics-endpoint POST/GET outside
`executeAnalyticsSql`) is the next and final step.
## Changes
- **`hooks/analytics/useProjectUsageStats.tsx`** — route the
already-branded `genChartQuery` output through `executeAnalyticsSql`
(parallels `useLogsPreview`).
- **`data/reports/report.utils.ts`** — tighten `fetchLogs(sql)` from
`string` to `SafeLogSqlFragment`; the wire boundary is now the same
single `executeAnalyticsSql` wrapper used by the rest of the analytics
path. Adds two pre-branded fragment maps reused by the report configs:
- `SAFE_GRANULARITY_SQL` — closed set returned by
`analyticsIntervalToGranularity`.
- `SAFE_COMPARISON_OPERATOR_SQL` — closed set on
`NumericFilter.operator`.
- **`components/interfaces/Auth/Overview/OverviewErrors.constants.ts`**
— wrap the two static `AUTH_TOP_*_SQL` fragments in `safeSql` (no
interpolation, but the type now flows).
- **`data/reports/v2/edge-functions.config.ts`** — `filterToWhereClause`
and every entry in `METRIC_SQL` now return `SafeLogSqlFragment`.
User-controlled values (`status_code.value`, `execution_time.value`,
function IDs, regions) pass through `analyticsLiteral`; operators look
up the branded map; the granularity uses the branded map. The
wire-format strings are unchanged, so the existing
`edge-functions.test.tsx` exact-string expectations still hold.
- **`data/reports/v2/auth.config.ts`** — same shape applied to all ten
`AUTH_REPORT_SQL` entries. The legacy `whereClause.replace(/^WHERE\s+/,
'')` pattern is replaced by two helpers that emit `AND`-prefixed
predicate fragments directly (`authFiltersToAndPredicates`,
`edgeLogsFiltersToAndPredicates`). Static provider SELECT / GROUP BY
fragments are pre-branded.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Enhanced security for analytics and reporting queries by updating
query construction methods across auth, edge functions, and project
usage reports.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46476?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
7e9badc6b8 |
chore(studio): migrate useStaticEffectEvent to React 19 useEffectEvent (#46415)
Studio is on `react@^19.2.6`, and `useEffectEvent` shipped stable in React 19.2 with the same signature as the userland polyfill. This drops the local hook in `apps/studio` and `apps/www` in favor of the built-in. **Removed:** - `apps/studio/hooks/useStaticEffectEvent.ts` - `apps/www/hooks/useStaticEffectEvent.ts` - `.claude/skills/use-static-effect-event/` — skill is obsolete **Changed:** - 26 call sites: dropped the `useStaticEffectEvent` import, added `useEffectEvent` to the existing `react` import, renamed call sites - `.claude/CLAUDE.md`: `apps/studio` row updated React 18 → React 19 - `.claude/skills/vercel-composition-patterns/SKILL.md`: removed stale "Studio uses React 18, skip these patterns" warning ## To test - `pnpm typecheck --filter=studio` — passes locally - `pnpm typecheck --filter=www` — passes locally - `grep -rn "useStaticEffectEvent"` returns nothing outside `node_modules` - Smoke-test areas that use the hook: schema visualizer edges (intersection check), spreadsheet import, sign-in/CLI login flows, side panels with unsaved-changes prompts **Out of scope:** pre-existing Tailwind lint warning on `DefaultEdge.tsx:141` (`outline` + `outline-1` conflict) — unrelated to this migration <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Internal event handling migrated to React’s built-in event hooks across the Studio app; no user-facing changes. * **Documentation** * Clarified React 19 compatibility and noted Studio now targets React 19. * Removed obsolete documentation for a deprecated internal hook. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46415?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
47c084e51d |
refactor(studio): migrate telemetry to useTrack (#46140)
## Summary
I migrated every `useSendEventMutation` call site in `apps/studio` to
`useTrack`, deleted the legacy hook, and added a lint guardrail so it
can't return. `useTrack` is the type-safe replacement: it auto-injects
`groups: { project, organization }` from the selected project/org and
types `action` + `properties` against `TelemetryEvent`. Existing call
sites built groups manually and were not type-checked at the action
level. The migration covers 81 files (60 trivial swaps, 9 org-only, 3
pre-auth, 5 bespoke, 4 test mocks).
## Changes
- Migrated trivial call sites across `pages/project/[ref]`,
`components/interfaces/*` (Reports, Storage, Realtime/Inspector,
SQLEditor, Functions, EdgeFunctions, Integrations, ProjectAPIDocs,
Branching/BranchManagement, TableGridEditor, Connect, Docs, Auth,
Support, Home, ProjectHome, App), `components/layouts/*`, and
`components/ui/*`.
- Migrated org-only sites (`Organization/Documents/*`,
`Organization/BillingSettings/Subscription/*`,
`Organization/SecuritySettings.tsx`,
`Account/Preferences/DashboardSettingsToggles.tsx`) by dropping the
manual `groups: { organization: ... }` and letting `useTrack`
auto-inject. Verified `useSelectedProjectQuery` is disabled on org
routes (gates on URL `[ref]`).
- Migrated pre-auth sites (`SignInForm.tsx`, `sign-in-mfa.tsx`,
`profile.tsx`) where neither project nor org is resolved.
- Bespoke handling:
- `execute-sql-mutation.ts` and `table-row-create-mutation.ts`: pass `{
project: projectRef }` via `groupOverrides` since the mutation can
target a non-selected project ref.
- `useStudioCommandMenuTelemetry.ts`: kept a direct `sendTelemetryEvent`
call because studio groups must override pre-built event groups
(opposite of `useTrack`'s override direction).
- `AIAssistantOption.tsx`: passes sentinel-aware `groupOverrides` so
`NO_PROJECT_MARKER`/`NO_ORG_MARKER` continue to suppress group emission.
- `SidePanelEditor.utils.tsx`: utility functions `createTable` and
`updateTable` now take a `track: Track` parameter (threaded from
`SidePanelEditor.tsx`); dropped the `organizationSlug` arg since groups
are no longer assembled manually.
- Branch-event attribution: preserved `parentProjectRef` overrides on
`branch_updated`, `branch_merge_completed`, `branch_merge_failed`,
`branch_merge_submitted`, `branch_delete_button_clicked`,
`branch_review_with_assistant_clicked`, and
`branch_*_merge_request_button_clicked`. Original code grouped these
under the parent (production) project, not the branch ref;
auto-injection would have shifted them onto the branch.
- Switched 4 test mocks from `@/data/telemetry/send-event-mutation` to
`@/lib/telemetry/track`. Removed obsolete tests around manual groups and
`try/catch` on telemetry rejection.
- Deleted `apps/studio/data/telemetry/send-event-mutation.ts`. The
deleted module is its own guardrail: any reintroduction of the import
fails at TypeScript module resolution before lint runs.
## Testing
Tested on preview deploy:
- [x] SQL editor `CREATE TABLE` fires `table_created` with method
`sql_editor` and `groups.project` set to the mutation's `projectRef`.
- [x] Table editor creates a table from the side panel; `table_created`
fires from `SidePanelEditor.utils` via threaded `track`.
- [x] Help button (`/project/[ref]/...`) fires `help_button_clicked`
with auto-injected project + org groups.
- [x] Sign-in form fires `sign_in` with empty groups (pre-auth,
expected).
- [x] Org documents page (`/org/[slug]/documents`) fires
`document_view_button_clicked` with org group only, no stale project
ref.
- [x] Command menu (`Cmd+K`) inside a project still fires
`command_menu_opened` with studio's project/org overriding any
event-supplied groups.
- [x] Support form "Ask the Assistant" without selected org fires
`ai_assistant_in_support_form_clicked` with no project/org groups
(sentinels suppress).
- [x] On a branch, "Update branch" / "Merge branch" / "Close merge
request" events fire with `groups.project` set to the parent project
ref, not the branch ref.
Local checks:
- [x] 22/22 tests pass across the 4 updated test files
(`SidePanelEditor.utils.createTable`, `EdgeFunctionRenderer`,
`LayoutSidebar`, `PlanUpdateSidePanel`).
- [x] `rg useSendEventMutation apps/studio` returns 0 hits.
## Linear
- fixes GROWTH-860
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Standardized telemetry across the Studio to a unified tracking system;
events now send simplified payloads with less contextual/grouping data.
* No user-facing flows changed; UI behavior, permissions, and
interactions remain the same.
* **Tests**
* Updated telemetry mocks and tests to align with the new tracking
approach.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46140?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
a7d51cdf52 |
feat(logs): brand legacy analytics SQL stack with SafeLogSqlFragment (#46351)
## 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? Refactor / type safety improvement ## What is the current behavior? The legacy log query stack (`genDefaultQuery`, `genCountQuery`, `genChartQuery`, `genWhereStatement`, `useLogsPreview`, `useSingleLog`) builds SQL from raw strings with no type-level guarantee that values are safely interpolated. Identifier helpers (`bqIdent`, `bqDottedIdent`, `clickhouseIdent`, `clickhouseDottedIdent`) are duplicated across BigQuery and ClickHouse variants, and `bqDottedIdent` wraps the entire dotted path in one backtick pair (`` `request.pathname` ``), which BigQuery treats as a literal column name rather than a UNNEST alias field — causing runtime query failures on dotted filter keys. ## What is the new behavior? - All gen functions return `SafeLogSqlFragment` and all callers route through `executeAnalyticsSql`, enforcing compile-time SQL provenance tracking across the legacy stack. - `bqIdent` / `bqDottedIdent` / `clickhouseIdent` / `clickhouseDottedIdent` are replaced by a single `quotedIdent` function that backtick-quotes each segment individually (e.g. `` `request`.`pathname` ``). ClickHouse natively accepts backticks, so one function serves both engines and the dotted-path quoting bug is fixed. - `SQL_FILTER_TEMPLATES` entries are converted to `SafeLogSqlFragment` (static via `safeSql`, dynamic via `safeSql` + `analyticsLiteral`). - `buildWhereClauses` is extracted as a private helper returning `SafeLogSqlFragment[]` so the pg_cron path can merge clauses without unsafe slice-and-cast. ## Additional context <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Logs query generation migrated to safer, engine-agnostic SQL fragments, typed filter templates, and unified identifier quoting for stronger injection protection and more consistent queries. * Logs preview and single-log retrieval now execute analytics SQL end-to-end using the unified executor. * **New Features** * Analytics SQL executor can call the backend via GET or POST and accepts method selection. * **Tests** * Updated tests to validate unified identifier quoting and safe-SQL helper behavior. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46351?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
c1b473e472 | fix: adjust connect sheet for cli and self-hosted (#46217) | ||
|
|
2c651ddabc | fix(experiment): make dataApiRevokeOnCreateDefault flag reads shape-agnostic (#46289) | ||
|
|
fdceb29260 |
fix(telemetry): exposure event captures dataApiDefaultPrivileges + drop race-fix hook (#46085)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Bug fix. ## What is the current behavior? This PR addresses three issues with the implementation of the `dataApiRevokeOnCreateDefault` experiment ([GROWTH-858](https://linear.app/supabase/issue/GROWTH-858)) on the frontend side: 1. The `project_creation_default_privileges_exposed` event payload captures `dataApiEnabled`, which is the parent "Enable Data API" toggle. That value defaults to `true` for everyone in both arms, which doesn't help understand how people are interacting with the form. 2. The hook itself was gating on PostHog JS SDK values rather than our backend server values being sent from `/telemetry/feature-flags`. 3. The form on `/new/[slug]` captures `dataApiDefaultPrivileges` defaults once at mount via react-hook-form's `defaultValues`. If the flag is still loading when the page mounts, `useDataApiRevokeOnCreateDefaultEnabled()` returns `false` (coerced from undefined), and the form locks the field to the legacy default of `true`. The flag later resolving has no effect, and treatment users get the legacy default visually and in the exposure event. ## What is the new behavior? 1. Main-surface payload now sends `dataApiDefaultPrivileges` — the form field the experiment actually controls (`true` = legacy grants kept, `false` = revoked on create). Post-fix data will let us read out whether treatment users actually got the new default. 2. Hook is simplified: drop `orgCountReady`, drop the `onFeatureFlags` subscription, drop the `posthogClient` import. It now fires once when the flag resolves, period. Vercel surface is unchanged (still no `dataApiDefaultPrivileges` since there's no user-facing toggle there). Tests updated. 3. New useEffect in `/new/[slug]` watches the raw flag value and syncs `dataApiDefaultPrivileges` to the correct experiment-driven default when the flag resolves, gated on `getFieldState(...).isDirty` so we don't clobber intentional user input. ## Additional context Backend half of this fix is at supabase/platform#32933 (passes `org_count` and `signup_timestamp` in `personProperties` so the audience filter actually evaluates correctly). Both PRs are needed for the experiment to bucket at 5% and be measurable. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Changes** * Telemetry now records the selected default-privileges setting (dataApiDefaultPrivileges) in project-creation events; the previous dataApiEnabled field was removed. * Project-creation flows apply the experiment-driven default for that setting once the experiment resolves, but they do not overwrite user-edited choices. Vercel new-project flow syncs with the experiment until the user changes the checkbox. * **Tests** * Updated tests to validate tracking, deduplication, and sync/timing behaviors for dataApiDefaultPrivileges. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46085?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
dc211a972c |
Fix count query for unified logs (#46093)
## Context The query to retrieve counts in unified logs have been error-ing out with this `sql parser error: Expected: end of statement, found: UNION at Line: 71, Column: 2` This PR fixes that - can verify visually as the status filters are now populated correctly <img width="365" height="148" alt="image" src="https://github.com/user-attachments/assets/9397cca1-0519-4fe1-9397-c37d399c4b44" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Improved status-based log filtering so single-value and multi-value filters return more accurate results across all log sources. * Made facet count calculations (method, status, pathname) more robust for consistent counts. * **Bug Fixes** * Standardized log endpoint resolution so log retrieval behaves consistently when telemetry mode changes. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46093?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0bed80b340 |
chore(telemetry): clean up frontend event catalog (#45964)
## Summary Resolves 13 findings (2 HIGH, 5 MEDIUM, 6 LOW) from the frontend telemetry audit: 1 action-string collision, 1 camelCase experiment name, 9 dead events removed, 4 missing org groups attached, 1 ambiguous property renamed, 1 raw-string property narrowed, plus consolidations and a structural tightening on TABLE_EVENT_ACTIONS. ## Changes ### HIGH - Rename `EventPageCtaClickedEvent.action` to `www_event_page_cta_clicked` so it no longer collides with the pricing CTA event (which had a different schema sharing the same action string) - Snake_case the header-upgrade experiment exposure name (`headerUpgradeCta_experiment_exposed` → `header_upgrade_cta_experiment_exposed`); PostHog flag key and `?source=` URL param unchanged ### MEDIUM - Remove 4 dead `ProjectCreation*Step*` events (referenced a v2 route that doesn't exist; 0 emissions) - Remove 4 dead experiment exposure events: `ProjectCreationRlsOptionExperimentExposed`, `HomeNewExperimentExposed`, `TableCreateGeneratePoliciesExperimentExposed`, `TableCreateGeneratePoliciesExperimentConverted` (0 emissions) - Attach org group to `dpa_request_button_clicked` (0% had `$group_0` per Hex) - Delete `RegisterStateOfStartups2025NewsletterClicked` (interface naming outlier, 0 emissions, page renamed to 2026) - Rename `AssistantSuggestionRunQueryClickedEvent.category` to `mutationType` with tightened literal union (`'functions' | 'rls-policies' | 'unknown'`) - Attach org group to `project_creation_default_privileges_exposed` on Vercel surface via explicit `groupOverrides` (auto-injection misses because `useSelectedOrganizationQuery` is undefined on that page) ### LOW - Consolidate `IndexAdvisorBannerEnableButtonClickedEvent` + `IndexAdvisorDialogEnableButtonClickedEvent` into one event with `origin: 'banner' | 'dialog'` - Rename `ImportDataFileDroppedEvent` → `ImportDataFileAddedEvent` so the interface name matches the action and the verb is on the approved list - Rename `LogDrainConfirmButtonSubmittedEvent` → `LogDrainRemovedEvent` and action to `log_drain_removed` (fires on delete-confirm modal, matches `CronJobRemovedEvent` pattern) - Add `type` property to `CronJobRemovedEvent` (parsed from the job's command), matching the create/update event shape - Tighten `TABLE_EVENT_ACTIONS` values with `satisfies` against the event union so renames in the union fail typecheck here too - Attach org group to `www_pricing_plan_cta_clicked` at 5 emission sites when an org is available in the page context - Narrow `unified_logs_row_clicked.logType` from raw `string` to the 5-literal `LOG_TYPES` union (zod already validates server values) ### Bundled refactor Migrated 5 emission sites from deprecated `useSendEventMutation` to `useTrack` while their containing files were being edited: `DPA.tsx`, `DisplayBlockRenderer.tsx`, `Grid.tsx` (2 events), `DeleteCronJob.tsx`. Full sweep of the remaining ~79 files is a separate follow-up. ## Testing Mostly just renaming of events ## Linear - fixes GROWTH-798 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Standardized telemetry to a unified tracking system for more consistent analytics. * Simplified experiment exposure reporting for upgrade prompts. * **New Features** * More granular tracking for CSV import, cron job deletions, log drain removals, DPA downloads/requests, and pricing CTAs. * Assistant now classifies mutation queries more precisely. * **Bug Fixes** * Improved default-privileges exposure logic on Vercel deployments (skips when org missing). <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45964) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
2d4e87f579 |
studio: SafeSql for reports, query performance, privileges (4/7) (#45998)
## Summary Part 4 of the SafeSql migration stack ([#45897](https://github.com/supabase/supabase/pull/45897), [#45903](https://github.com/supabase/supabase/pull/45903), [#45990](https://github.com/supabase/supabase/pull/45990), this PR, …). Converts the remaining reports, query performance, observability, index advisor, and privileges call sites of `executeSql` to produce `SafeSqlFragment` values. The `ReportQuery.sql` field flips from `string` to `SafeSqlFragment`, which cascades into every consumer — landed here atomically so each branch typechecks cleanly. Touched areas: - `interfaces/Reports/*` — `ReportQuery.sql: SafeSqlFragment`, plus all report definitions/utilities updated - `interfaces/QueryPerformance/useQueryPerformanceQuery.ts` - `interfaces/Database/IndexAdvisor/*` and `data/database/{table-index-advisor,retrieve-index-advisor-result}-query.ts` - `data/privileges/{table-api-access,update-exposed-entities}-mutation.ts` - `interfaces/Storage/StoragePolicies/StoragePolicies.tsx` - `hooks/analytics/useDbQuery.tsx` - `Observability/useSlowQueriesCount.ts` + `useQueryInsightsIssues.utils.test.ts` ## Test plan - [x] `pnpm typecheck` passes - [x] `useQueryInsightsIssues.utils.test.ts` passes - [x] Dev-server smoke test: reports pages, query performance, index advisor, storage policies <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Reworked SQL construction and typings across reporting, query performance, index advisor, and privilege features to use safer SQL fragments, improving reliability and preventing query composition issues. * **Types** * Reporting query types were split to distinguish database vs. logs queries, enabling correct handling and validation. * **Docs/Utils** * Added a helper to consistently generate logs SQL for report hooks. * **Tests** * Updated tests to exercise the new SQL-building API. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45998) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
86a3f8b03d |
chore: upgrade to react-19 (#45886)
- Most changes are related to either types or `useRef` usages (it now requires an initial value). - also updated `vaul` to its latest version and haven't noticed any change ([design-system demo](https://design-system-git-react-19-supabase.vercel.app/design-system/docs/components/drawer)) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Upgraded workspace to React 19. * **Bug Fixes** * Improved null-safety and ref handling across editors, UI components, shortcuts, and markdown/image rendering to reduce runtime errors. * Safer event/timeout/interval cleanup and more robust command/context handling. * **Chores** * Bumped vaul dependency versions. * **Documentation** * Type and TypeScript accuracy improvements for clearer developer feedback. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45886) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
4c77ab5fef |
feat(telemetry): mirror org_count to PostHog person property (#45946)
## 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 + two follow-on fixes — small, scoped to telemetry / experiment plumbing. ## What is the current behavior? PostHog feature flags evaluated in Studio only have access to the `gotrue_id` person property (set in `useTelemetryIdentify`) and the `organization`/`project` group associations from pageviews. Flags can't target users by org membership without a behavioral cohort, which refreshes on a ~hourly schedule and lags behind real-time signup state. This is blocking the rollout of the `dataApiRevokeOnCreateDefault` experiment ahead of the May 30 default-privileges breaking change — we need to target brand-new dashboard signups with no prior org membership, and there's no person property to filter on. ## What is the new behavior? Three changes, scoped tightly to make experiment targeting reliable for brand-new signups: ### 1. Mirror `org_count` to a PostHog person property (`apps/studio/lib/telemetry.tsx`) The Studio `Telemetry` component now mirrors the user's current org-list length to a PostHog person property `org_count` via `posthog.identify(user.id, { org_count })`. The effect: - Subscribes to `useOrganizationsQuery` (shares the same React Query cache as `useSelectedOrganizationQuery`, so no extra network requests). - Dedupes via a ref keyed on `{ userId, orgCount }` so we only call identify when the value actually changes — handles user-switch (logout/login as different user with same count) correctly. - Generic enough to be useful beyond this experiment — analytics segmentation by org membership, future flags that depend on multi-org behavior, etc. ### 2. Merge pre-init identify properties (`packages/common/posthog-client.ts`) The previous `pendingIdentification` slot was a single-write buffer — calling `posthogClient.identify()` before the PostHog SDK initialized would overwrite any prior queued identify. Latent until this PR added a second identify caller (`org_count`), which exposed the last-write-wins behavior on first-visitor-before-consent flows. Now merges properties across pre-init calls for the same user so both `{ gotrue_id }` and `{ org_count }` land on the person record when the SDK flushes. Caught during Codex review. ### 3. Gate the exposure event on `org_count` being present (`apps/studio/hooks/misc/useDataApiRevokeOnCreateDefault.ts`) `useTrackDefaultPrivilegesExposure` previously fired on the first non-undefined value of the `dataApiRevokeOnCreateDefault` flag. For brand-new signups, this races the `org_count` identify: the initial `/flags/` response (before targeting can match) returns the untargeted variant, the exposure locks it in via `hasTracked`, then our identify fires and a subsequent `/flags/` refresh updates the flag — but the exposure has already recorded the wrong variant. Fix: gate the exposure on `org_count` being present on the SDK person, subscribing via `onFeatureFlags` so we pick up the post-identify `/flags/` response. Adds `posthogClient.getPersonProperty` as the local-state reader. Without this, the experiment would have a ~5-15% noise floor on cohort assignment for new signups. ## Verification End-to-end verified locally against the staging PostHog project (34343): - Local Studio's PostHog SDK has `$stored_person_properties: { gotrue_id: <uuid>, org_count: 1 }` after sign-in. - Both `$set` events landed server-side within ~300ms of each other, and the staging person record now shows `org_count = 1.0` with `gotrue_id` preserved. - Targeting query `person.properties.org_count == 1` works end-to-end against staging. ## Additional context Ref: [GROWTH-853](https://linear.app/supabase/issue/GROWTH-853) Targeting plan for the flag once shipped: `person.org_count == 1` plus a behavioral filter on recent `sign_up` event, at 5% rollout. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Telemetry now records and syncs the user's organization count as an analytics person property and avoids redundant identifications when unchanged. * Analytics client now merges queued identification properties made before initialization and exposes a method to read stored person properties. * **Bug Fixes** * Tracking now waits for organization-count readiness before firing certain exposure events to prevent missing data. * **Tests** * Added/updated tests to cover person-property behavior and gating logic. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45946) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
19e0b36650 | feat(logs): migrate unified logs queries to OTEL endpoint DEBUG-71 (#45642) |