mirror of
https://github.com/supabase/supabase.git
synced 2026-10-09 03:15:06 +03:00
cli/docs-example-how-to
591
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
00ecb53059 |
feat(etl): ETL usage insights+pricing docs (#47873)
Adds pipeline usage insights to summary and daily breakdowns + usage billing docs |
||
|
|
4fd5f8adf1 |
Vercel project connect layout (#47623)
Bring the Vercel project connect layout up to date with other connect screens. Follows up from https://github.com/supabase/supabase/pull/47550 which is required. | Before | After | | --- | --- | | <img width="2368" height="1680" alt="image" src="https://github.com/user-attachments/assets/f5c0b8ef-8fb5-4176-b0cf-98e33958dcc8" /> | <img width="848" height="808" alt="image" src="https://github.com/user-attachments/assets/e64c289f-0b73-4605-ad38-4552d3d6f934" /> | <img width="883" height="733" alt="image" src="https://github.com/user-attachments/assets/7ccd9b72-de6a-4c21-ac8e-abe773bb8116" /> ## Testing - Open the deploy preview or staging URL for `/dashboard/integrations/vercel/acme-production/marketplace/choose-project` with callback params from a real Vercel Marketplace install redirect (see _Vercel_ subheading below). ### Vercel - Run through the [install flow](https://github.com/supabase/supabase/pull/47550) on a real project until you get to the project connection screen, copy the url and paste into staging preview <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit * **New Features** * Introduced interstitial-style Vercel integration experiences for both install and choose-project flows, with improved page titles and clearer environment-variable guidance (including tooltip details). * **Bug Fixes** * Improved Vercel integration matching by configuration id and strengthened loading/error handling with more specific “not found” messaging. * **Refactor** * Enhanced the Vercel/GitHub project chooser with a dedicated interstitial mode. * Updated partner logo rendering to support optional styling customization. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> Co-authored-by: Alaister Young <alaister@users.noreply.github.com> |
||
|
|
9858562b8b |
fix(telemetry): dedupe funnel toast error events (#47802)
## Summary Since #47293, an API failure on a signup / org-creation / project-creation form emitted `dashboard_error_created` twice: `useTrackFunnelError` fired the origin-tagged event and the global `ToastErrorTracker` independently fired the legacy untagged `source:'toast'` event for the same toast, each behind its own 10% sampling draw. I verified the twin rate empirically at 8-11% of origin-tagged funnel toasts, exactly the floor for two independent 10% draws, meaning the twin co-fires for effectively every funnel error ([Hex thread](https://app.hex.tech/supabase/thread/019f3bc1-3a5c-7200-9122-8e3439bfbe8c)). Any consumer counting funnel errors without an `origin IS NOT NULL` filter saw ~2x inflation. The fix makes `ToastErrorTracker` the sole emitter of `source:'toast'` events, so the duplicate is unrepresentable rather than suppressed. Funnel call sites pass the id returned by `toast.error()` into `trackFunnelError`, which registers the funnel properties against that toast id instead of firing its own event – the tracker then emits a single `dashboard_error_created` enriched with `origin` / `errorCategory` / `errorReason` / `errorCode` for registered toasts, and the plain untagged event otherwise. The `'toast'` overload of `trackFunnelError` requires the toast id, so a missed pairing is a compile error rather than a silent double count. Registration is unconditional and there's only one sampling draw, so suppression can't lose a sampling race. `'form'`-sourced funnel events are unchanged. ## Changes - `lib/toast-errors.tsx`: toast-id → funnel-properties registry (`registerFunnelErrorToast`); `ToastErrorTracker` emits one (optionally enriched) event per error toast under a single 10% draw, deleting entries once consumed - `lib/telemetry/use-track-funnel-error.ts`: overloaded signature – `'toast'` requires the id returned by `toast.error()` (type-enforced), `'form'` keeps direct emission with its own sampling - Update the 7 funnel `toast.error` call sites in `NewOrgForm`, `SignUpForm`, and `pages/new/[slug]` to pass the toast id - Component tests for the tracker (previously uncovered), including an end-to-end test through `useTrackFunnelError` - Code hygiene (also flagged by CodeRabbit): all four `dashboard_error_created` emitters (toast, form, `AlertError`, `ErrorMatcher`) independently encoded the 10% draw – downstream analysis assumes a uniform sampling multiplier across sources, so one site drifting would silently skew comparisons. The rate and the draw now live in one place (`isDashboardErrorSampled()` in `lib/telemetry/error-sampling.ts`). No behavior change. - Mount `ToastErrorTracker` in the TanStack root (`routes/__root.tsx`), mirroring `pages/_app.tsx`. The TanStack tree mounted `Toaster` but never the tracker, so untagged toast error telemetry has never fired in that flavour – and with the tracker now the sole emitter, the missing mount would have silently dropped funnel toast events there too. Side effect once the TanStack flavour ships: untagged `source:'toast'` volume from it goes from zero to normal. ## Testing Component-tested (`apps/studio/lib/toast-errors.test.tsx`): - [x] Unregistered error toast fires exactly one untagged `dashboard_error_created {source:'toast'}` - [x] Registered funnel toast fires exactly one event, enriched with `origin`/`errorCategory`/`errorReason`/`errorCode` - [x] `useTrackFunnelError` with a toast id routes through the tracker as a single enriched event - [x] Non-error toasts ignored; the 10% sampling gate still applies Full Studio unit suite passes (392 files / 4371 tests), plus typecheck and lint. Also verified end-to-end in a local browser (TanStack flavour, sample rate temporarily forced to 1): a failed signup produced exactly one `dashboard_error_created` with `{source:'toast', origin:'signup', errorCategory:'api', errorReason:'email_already_registered', errorCode:403}` and no untagged twin (two independent trials); an unregistered error toast produced exactly one plain `{source:'toast'}`; a client-side validation failure produced exactly one `{source:'form', origin:'signup', errorCategory:'validation', errorReason:'email_invalid'}`; success toasts produced nothing. Post-deploy I'll re-run the twin-rate query from the Hex thread; the untagged-twin rate on funnel pages should decay to ~0 as stale bundles reload over 2-3 days. ## Notes - Origin-tagged funnel toast events now ride the tracker's single 10% draw instead of their own independent draw – statistically identical volume, but the event fires on the tracker's next effect rather than synchronously at the call site (irrelevant for PostHog) - Registration must happen in the same synchronous block as `toast.error()` (documented on the `TrackFunnelError` type) – all current call sites comply - The invalid Postgres version toast in `pages/new/[slug].tsx` (~line 416) needs no special-casing: unregistered toasts keep the plain untagged event, so its telemetry is preserved - Heads-up for `dashboard_error_created` consumers: overall untagged `source:'toast'` volume will dip slightly after this deploys, since funnel-page twins disappear. A volume monitor seeing that drop is this fix landing, not a tracking regression (same class as the intended GROWTH-893 sampling-unification drop). ## Linear - fixes GROWTH-965 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Enhanced error telemetry for organization creation, sign-up, payment, and project-creation flows by associating failures with toast identifiers and enriched funnel context. * Standardized dashboard error sampling logic across error handling components for consistency. * **Tests** * Added comprehensive test coverage for toast error tracking, including funnel registration, deduplication, filtering, and sampling behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
87c5f74ceb |
Add CTA to update tax ID if run into tax ID issues when upgrading plan (#47767)
## Context There's a chance users may run into tax ID issues when upgrading a plan as such: <img width="412" height="120" alt="image" src="https://github.com/user-attachments/assets/4c559ae0-d942-4c10-b83a-c5944a2a49ee" /> Adding a CTA here to guide users and mitigate confusion on how to proceed to remediate <img width="399" height="147" alt="image" src="https://github.com/user-attachments/assets/3bcaca14-bd77-4168-b9ab-cd6b75f79e24" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved billing-profile validation feedback by standardizing error messaging for tax ID vs. billing address country mismatches. * Added an in-toast “Update tax ID” action to guide users directly to the fix. * Updated the billing dialog’s close behavior so it returns users to the relevant address section (including scrolling to it automatically). <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
d949a19f97 |
fix(studio): extend downgrade error toast duration (#47780)
## Summary - Downgrading to Free tier is blocked server-side when an org has an active branch, but the resulting error toast in `ExitSurveyModal.tsx` used the default 4s toast duration, making it easy to miss. - Adds `duration: 10_000, dismissible: true`, matching the pattern already used for other important billing error toasts (`org-subscription-update-mutation.ts`, `NewOrgForm.tsx`). Fixes FE-3882 ## Test plan - [ ] Attempt to downgrade an org with an active branch to Free tier and confirm the error toast stays visible for 10s and can be dismissed <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved the downgrade error message to stay visible longer and be easier to dismiss, making failures clearer for users. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
1aa23f9f64 |
fix: fix several accessibility issues on the organization home page (#47769)
## Problem - Organizations links are not accessible with keyboard - Project list buttons are missing labels - Headings should be sequential <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved keyboard and screen-reader accessibility for project actions and project reference copy controls. * Added clearer tooltip guidance for copying a project reference. * Updated project and organization card interactions for more consistent click and focus behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
f34fdd6c8f |
Skip using count estimate function for retrieving row counts if in read only context (#47761)
## Context Currently when retrieving row counts of a table in the Table Editor, we're using a `COUNT_ESTIMATE` pg function ([ref](https://github.com/supabase/supabase/blob/master/packages/pg-meta/src/sql/studio/database/get-count-estimate.ts#L5)) to retrieve an estimate (instead of checking `pg_class` -> `reltuples`) as that would theoretically provide a more accurate representation. However, in a read only context, that function can't be used - users will run into `cannot execute CREATE FUNCTION in a read-only transaction`, so we need to fallback to just checking `pg_class` in this scenario. The logic's already set up as we were previously looking into allowing users to use a read replica to power the dashboard, but we also need to consider members with read-only roles within the organization, so this PR updates the logic a little to factor that in. ## To test - [ ] With a read-only role, open the table editor and verify that we're not using the count estimate function to retrieve the table row counts <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Updated the invite member dialog to open in a larger size for better usability. * **Bug Fixes** * Improved table row count behavior so it now respects read-only access and permission limits more reliably. * Count estimates should now be shown more consistently across different database contexts. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
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> |
||
|
|
cabe14e5ca |
chore: remove _Shadcn_ suffix from ui tabs components (#47628)
## Problem Now that we migrated all usages of the deprecated `Tabs` component, we don't need the `_Shadcn_` suffix anymore. ## Solution Remove `_Shadcn_` suffix from `ui` tabs components. That's all this PR does, no visual nor functional changes <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Standardized tab components across the app so pages and dialogs now use the same consistent tab UI. * Improved tab-based views in design, docs, studio, learn, and website experiences for a more uniform interface. * **Chores** * Updated shared UI exports to expose tab components directly, simplifying future usage across the product. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
98cfe3307e |
feat(telemetry): fix creation-funnel tracking gaps (#47386)
## Summary The creation-funnel instrumentation that shipped Jun 25 (#47291, #47293) had real gaps, surfaced by the weekly telemetry audit and confirmed against production PostHog data before I touched code. The two automated reports also contradicted each other on `errorReason`; I checked production (every value is a controlled slug) and the emit path (only `useTrackFunnelError` sets it, and it only accepts classified slugs), so I left the type as-is rather than add a cross-package abstraction for a risk that cannot occur today. ## Changes - Classify HTTP 401/403/404 API errors as `unauthorized` / `forbidden` / `not_found` instead of the catch-all `other`. In production the `org_creation` `other` bucket was ~96% 401s (~1,300 real over 4 days), invisible in reason breakdowns. The status-code fallback runs after the message-pattern match, so specific reasons still win and it only rescues errors that would otherwise be `other`. - Add a single `tier` property (`tier_free` / `tier_pro` / `tier_payg` / `tier_team`) to `organization_creation_completed`, which previously carried no properties. One canonical billing slug (matching `SubscriptionTier`) instead of two overlapping plan/tier fields, so the org-creation funnel segments cleanly by tier and joins against subscription data. `tier_payg` is uncapped PRO. - Freeze the submitted tier at submit time (snapshot in `createOrg`) rather than reading live form state in the success callback, so the event records the tier that was actually created even if the user edits the form during the async payment flow. - Emit `project_creation_form_exposed` with `surface: 'vercel'` on the integration deploy-button project-creation page (the enum value existed but was never fired). Gated on the URL `slug` so the impression is captured as soon as the form renders, matching the sibling exposure hook on that page. I also checked the confirm-modal error path flagged in the insights post: it already classifies via the shared `useProjectCreateMutation.onError`, so adding instrumentation there would double-count. No change made. ## Testing These are analytics events with no UI change, so correctness is in what lands in PostHog. Post-deploy validation I will run against production (project 34344): - `dashboard_error_created` where `origin='org_creation'` and `errorReason='other'` drops ~96%, with `unauthorized` / `not_found` appearing. - `organization_creation_completed.tier` populated on 100% of new events with one of the four tier slugs. - `project_creation_form_exposed` with `surface='vercel'` goes from 0 to greater than 0. ## Linear - fixes GROWTH-948 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added telemetry for organization creation completion that includes the selected billing tier. * Added one-time telemetry when the Vercel project creation form is exposed. * **Bug Fixes** * Improved API error classification to more accurately distinguish unauthorized, forbidden, and not found responses. * **Documentation** * Updated telemetry event definitions to require tier metadata for organization creation events. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b30db91d71 |
chore: cleanup UI patterns exports (#47406)
## Problem We now export components under a subpath in ui-patterns to avoid barrel files as they slow down every tools (from IDE to linters, etc.) and may also affect bundles our users have to download. ## Solution - Remove the UI patterns index file - Fix invalid impors |
||
|
|
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 |
||
|
|
1f03c0dc0e |
fix(billing): trim Tax ID inputs to trigger required validation (#47311)
### Summary This PR trims the Tax ID value on the frontend so that whitespace-only entries (e.g. " ") are correctly treated as "not set" instead of a valid value. Previously the "is the Tax ID set?" checks relied on string length/truthiness, so whitespace-only input slipped through as a real value - bypassing validation and getting persisted. ### Testing - Subscription upgrade & top-up forms: verified the form no longer submits when only whitespace is entered for the Tax ID. The validation message now shows. - Billing address form: no inline message is shown, but the Tax ID is submitted as null, which clears it. This is unchanged from current behaviour. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Tax ID values are now trimmed before validation and submission, reducing errors caused by accidental leading or trailing spaces. * Billing and payment flows now consistently use the cleaned Tax ID value when deciding whether to save or send it. * Customer tax ID details passed to payment setup now reflect the trimmed value, helping avoid mismatches with external payment processing. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0a797ef4ea |
feat(studio): add creation funnel telemetry (#47291)
## Summary Adds frontend funnel telemetry to the organization-creation and project-creation flows in Studio, so each is measurable as a funnel (form exposed → completed) entirely from frontend events. Feeds the KPI 3 FE Benchmark Friction dashboard. Org creation had zero frontend funnel events before this (only a backend event that fires across every surface), and project creation had no clean form-view impression. ## Changes - Define `organization_creation_form_exposed`, `organization_creation_completed`, and `project_creation_form_exposed` in the telemetry constants. - Fire `organization_creation_form_exposed` when the new-org form renders, gated on the profile resolving so pre-auth redirects are not counted. Fire `organization_creation_completed` from the create success callback, covering both the free and the paid pending-payment-intent paths, attaching the new org slug as the organization group. - Fire `project_creation_form_exposed` once the org and the create-project permission have resolved, so it anchors on the form being visible rather than the route loading. Project completion reuses the existing client-side success event, so no duplicate completion event was added. ## Notes I chose exposed → completed over exposed → submitted. The org slug only exists after the create API resolves, so the completion event is the only org-funnel event that can carry the organization group; a submit-time event cannot, which would break org-level segmentation. A pageview is not a sufficient exposure anchor either: pageview capture is off, and the manual pageview fires on route change before the form is interactive (pre-auth redirect, async permission load, the no-org redirect). The `completed` verb follows the repo's approved-verb list (`.claude/skills/telemetry-standards`); the repo previously migrated `branch_merge_succeeded` to `branch_merge_completed` for the same reason. ## Testing Tested on the preview deploy: - [x] `/dashboard/new` while signed in → `organization_creation_form_exposed` fires once. - [x] Create a free org → `organization_creation_completed` fires with the organization group set. - [x] `/dashboard/new/[slug]` with create permission → `project_creation_form_exposed` fires once with `surface=main` and the organization group. - [x] No event re-fires on re-render or tab refocus. Post-deploy: confirm in PostHog prod (project 34344) via HogQL that each event fires with the expected properties and the organization / project group set. ## Linear - fixes FE-3690 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added improved tracking for organization and project creation flows, including when forms are shown and when organization creation completes. * Captures creation metadata to support better reporting on onboarding and setup progress. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
2d0bcd4714 |
feat(telemetry): classify funnel creation errors (#47293)
## Summary The KPI-3 friction dashboard needs to know *why* users hit errors on the signup, project-creation, and org-creation funnels, not just that they did. The existing `dashboard_error_created` event already fires for these paths (10% sampled, with `$pathname`), but carries no reason: ~98.5% of events have no `errorType` and no property carries an error message. This adds PII-safe classification computed client-side from a controlled vocabulary, so raw error text never leaves the browser. Validation errors (previously invisible, since they are inline form errors that never raise a toast) are now captured on invalid submit. ## Changes - Extend `dashboard_error_created` with `origin`, `errorCategory`, `errorReason`, `errorCode`, and a `form` source value - Add a pure, unit-tested classifier (`funnel-errors.ts`) and a 10%-sampled tracking hook (`use-track-funnel-error.ts`); the classifier maps errors to stable slugs and emits only slugs + HTTP status, never raw message text - Classify signup errors (API failures + validation) in `SignUpForm` - Classify project-creation errors (API failures, OrioleDB guard, validation) in the new-project wizard - Classify org-creation errors (API failures, payment/card declines, confirm-subscription, validation) in `NewOrgForm` ## Testing 13 unit tests cover every classifier branch (validation / api / network / payment, status-code handling, message-pattern matching, and fallbacks). To verify on the Vercel preview (events are 10% sampled; set the sample rate to 1 locally to observe each fire): - Signup with a weak but non-empty password: `origin=signup, source=form, errorCategory=validation, errorReason=password_invalid` - Signup with an already-registered email: `origin=signup, source=toast, errorCategory=api, errorReason=email_already_registered` - New project with an empty name: `origin=project_creation, source=form, errorReason=project_name_invalid` - New org with an empty name: `origin=org_creation, source=form, errorReason=org_name_missing` - New org with a declined test card: `origin=org_creation, errorCategory=payment` PII: raw `error.message` is never sent; only controlled slugs and HTTP status. Dashboard consumers must filter `origin IS NOT NULL` so these do not collide with the generic toast events the global tracker still emits. ## Linear - fixes FE-3691 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added improved, categorized telemetry for signup, project creation, and organization creation errors, including payment, subscription-change, and validation failures. * Extended dashboard error events with optional structured diagnostics (origin, category, reason, and optional error code) and support for form-origin reporting. * **Bug Fixes** * Improved project-creation handling to record a validation telemetry event when an Oriole image is unavailable. * Ensured payment-related and subscription-change failures are captured consistently alongside existing user toasts. * **Tests** * Added unit tests covering API/network/validation/Stripe error classification and reason mapping. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
ef148b6504 |
fix(studio): org MFA enforcement toggle visibility and UX (DEPR-606) (#47285)
## What kind of change does this PR introduce? Bug fix. Resolves DEPR-606. ## What is the current behavior? On org Security settings, the MFA enforcement switch could appear on without a green track. Users without personal MFA saw a disabled toggle with a tooltip. ## What is the new behavior? - Switch checked state renders correctly (removed tooltip trigger from the switch). - Users who need personal MFA first see an admonition with a link to account security instead of a disabled toggle. I felt this was a better user experience and more straightforward than the alternative: fighting the TooltipTrigger’s `data-state` conflict with the Switch’s checked state. | Before | After | | --- | --- | | <img width="1024" height="563" alt="Security Organization Settings Toolshed Supabase-4413F7B1-C7DC-4958-8C6F-ADEFDE4F310C" src="https://github.com/user-attachments/assets/8c71b0d8-db49-4af5-874b-5372df03379d" /> | <img width="1024" height="563" alt="Security Organization Settings Toolshed Supabase-ADD5BC82-B433-4EA0-A6BB-874703150663" src="https://github.com/user-attachments/assets/3c6d3545-fd58-426b-afaf-edd8f7ac4789" /> | | <img width="1024" height="563" alt="Security Organization Settings Toolshed Supabase-F57ED4AA-5A56-4F6A-8F35-569CAC26AFA2" src="https://github.com/user-attachments/assets/2bc49f34-7819-49fa-ac32-7e59678041fd" /> | <img width="1024" height="563" alt="Security Organization Settings Toolshed Supabase-AA795D85-1C17-4C08-9ED1-BBF08C28F2B4" src="https://github.com/user-attachments/assets/db1822b0-17fc-42df-bdec-0935e46ab5ff" /> | | <img width="1024" height="563" alt="Security Organization Settings Toolshed Supabase-8D8A196F-FA27-4FD3-BC52-DB933E61D59A" src="https://github.com/user-attachments/assets/bae30a9e-eda9-4a97-845c-0c4751f03a05" /> | <img width="1024" height="563" alt="Security Organization Settings Toolshed Supabase-5BD4F063-B402-4E03-ACE4-254BB28C232C" src="https://github.com/user-attachments/assets/0a3c4d6b-2981-47e9-9679-56bfcd7faf5d" /> | ## Additional context Test on `/org/<slug>/security` in light mode with and without personal MFA enabled. Or just hardcode the ternaries to see the various states on local. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added clearer guidance for organization security settings when MFA must first be enabled on a personal account. * Improved loading behavior while member data is fetched. * **Bug Fixes** * Prevented the MFA enforcement form from showing until personal MFA requirements are met. * Refined the MFA toggle disabled logic to apply only when appropriate. * **UI Improvements** * Replaced the MFA tooltip with an in-page notice. * Updated the primary action button label from “Save changes” to “Save.” <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
032bd09b0c |
feat(studio): use theme-aware OAuth requester logos (#47138)
## What kind of change does this PR introduce? Bug fix. - Follow-up work to FE-3640 - Contributes to DEPR-604 ## What is the current behavior? Known dynamic OAuth requesters on `/dashboard/authorize` relied on OAuth-specific hard-coded icon assets that were dark-mode only. Cursor did not have separate light/dark assets in the shared MCP icon registry, Perplexity only had a light tile asset with baked-in padding, and OpenAI used the older blossom mark. ## What is the new behavior? Known OAuth requester logos now resolve through the shared MCP icon registry while preserving the existing `SupabaseLogo` treatment for paired authorisation screens. Cursor uses transparent SVG light/dark variants, Perplexity has cropped transparent SVG light/dark variants, and OpenAI/ChatGPT uses the newer monoblossom SVG in black/white variants. Claude remains static until a suitable variant is available. Unknown requester icons still render from the provided URL and fall back to the requester initial if the image fails. | Before | After | | --- | --- | | <img width="828" height="636" alt="Authorize OpenAI Supabase-E2A05664-589F-458F-8452-9CEE008D558A" src="https://github.com/user-attachments/assets/140021b1-ff05-4092-98ef-2eae94ff2ddb" /> | <img width="828" height="636" alt="Authorize OpenAI Supabase-EC7E00BD-439A-45D1-8E55-240B227C6897" src="https://github.com/user-attachments/assets/93e603f2-5cbf-4219-b692-d36ac98e8d2a" /> | | <img width="828" height="636" alt="66 Authorize OpenAI Supabase-CB31FF76-86DB-43A6-A426-46B99B8B1B91" src="https://github.com/user-attachments/assets/b261416e-39b8-40b3-87fd-461653aa0334" /> | <img width="828" height="636" alt="Authorize OpenAI Supabase-EAFCF2F2-5CEA-4FE6-8AC0-819F764B414E" src="https://github.com/user-attachments/assets/35ad7525-0fa9-4438-b117-4e70b78eb719" /> | ## To test 1. Navigate to `http://localhost:8082/authorize?auth_id=test-auth-id` 2. Open DevTools → Network 3. Find `/platform/oauth/authorizations/test-auth-id` 4. Right-click → Override content 5. Replace the response body with: ```js { "name": "Perplexity", "website": "https://perplexity.ai", "icon": null, "domain": "perplexity.ai", "scopes": [], "expires_at": "2026-12-31T23:59:59.000Z", "approved_at": null, "registration_type": "dynamic" } ``` 6. Then change "name" to Cursor, Claude, ChatGPT, or OpenAI and refresh to inspect each logo <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * OAuth app requester logos now dynamically adapt to light and dark themes, with improved logo selection for known requesters. * Cursor now uses a distinct dark icon variant. * Added Perplexity client icon support. * **Bug Fixes** * Improved logo rendering robustness: if a logo can’t be loaded, the UI falls back to the requester’s initial. * **Tests** * Expanded coverage for theme-aware logo rendering and icon variant handling, including unknown-icon and fallback scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> |
||
|
|
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> |
||
|
|
d549e1f16b | fix(billing): clarify averaged usage messaging (#47181) | ||
|
|
171ca026b5 |
feat(studio): Add integration settings page with connected resources (#46961)
Adds integrations settings page to each oauth integration to show associated resources (e.g. API keys, config, oauth apps, etc) <img width="1150" height="892" alt="Screenshot 2026-06-16 at 2 44 31 PM" src="https://github.com/user-attachments/assets/035cc602-886d-43bc-a5a7-e14f76dd37c3" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary * **New Features** * Added a Marketplace “Settings” tab with a grouped **Connected resources** view (OAuth apps, API keys, Edge Function secrets, SMTP), including loading/empty/missing-resource states and per-kind removal actions. * Added a resource-group section UI plus integration-aware grouping/copy customization and missing-kind zero-states. * **Bug Fixes** * Improved installed-state detection for Grafana and Doppler by broadening conditions. * Added an orphaned-resources warning when expected OAuth apps are missing. * **Refactor** * Unified connected-resource removal into a single flow with OAuth-specific revoke handling. * **Tests** * Added comprehensive UI and utility coverage for grouping, states, and destructive removal behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
f8e682c443 |
fix: Add custom icon overrides for specific MCP apps (#47130)
This PR hardcodes icons for most used AI apps (`Claude`, `Perplexity`, `ChatGPT` and `Cursor`) because their icons are coming from other domains which we don't want to add CORS exemptions for. <img width="534" height="638" alt="Screenshot 2026-06-19 at 16 44 12" src="https://github.com/user-attachments/assets/258cfb7b-e0fa-4408-bc2d-911c197f097d" /> <img width="499" height="676" alt="Screenshot 2026-06-19 at 16 44 48" src="https://github.com/user-attachments/assets/67004935-bad1-4cf9-8d4c-edbb5c466288" /> <img width="667" height="753" alt="Screenshot 2026-06-19 at 16 48 59" src="https://github.com/user-attachments/assets/cd12677f-dfde-438b-bc54-4be36c7c0fa2" /> <img width="608" height="715" alt="Screenshot 2026-06-19 at 16 49 21" src="https://github.com/user-attachments/assets/d2b642ca-598d-4ac8-8177-179ef249cb58" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit ## Release Notes * **Bug Fixes** * Improved OAuth app authorization detail logos by adding app-specific fallback icons for known app identifiers, ensuring the correct logo shows when the original icon is missing or fails to load. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
1b41e0bff2 |
fix(billing): clicking outside downgrade modal closes it (#47070)
Replaced the `DowngradeModal`'s `AlertDialog` with a normal `Dialog`, since `AlertDialog` won't close if you click outside the modal by design. Left is current PR, right is staging: <img width="1600" height="537" alt="Screenshot 2026-06-18 at 10 07 46" src="https://github.com/user-attachments/assets/ce1bcc17-d1c9-4fcd-ad3b-f2fcfd8824f6" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Updated the downgrade confirmation modal to use the newer dialog UI components. * Preserved the existing warning and checklist content (including project impact and email/reset notices) and kept the same confirm/cancel behavior and disabled state handling. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com> |
||
|
|
77ecfd5997 |
fix(studio): org integrations layout (FE-3617) (#47007)
## What kind of change does this PR introduce? UI bug fix. Resolves FE-3617. ## What is the current behavior? On `/org/[slug]/integrations`, the Vercel section renders full-width and the page uses a mixed layout: GitHub still uses the old Scaffold two-column pattern while `VercelSection` was migrated to `PageSection` without a page container in #46868. ## What is the new behavior? - Migrates `/org/[slug]/integrations` to `PageHeader` + `PageContainer size="small"` + `PageSection`, matching project settings integrations - Puts the Vercel "Install Vercel Integration" CTA in the same dashed card pattern as "Add new project connection" (org + project) - Consolidates GitHub into a shared `GitHubSection` with `isProjectScoped`, mirroring `VercelSection` | Before | After | | --- | --- | | <img width="1728" height="997" alt="Integrations Peels Org Supabase-BEB84402-99AA-4EF2-8B8F-3CAE98FEA33D" src="https://github.com/user-attachments/assets/f52741d5-9c31-4707-a10f-c613e0b80bf4" /> | <img width="1728" height="997" alt="Integrations Freebie Supabase-975CF6FD-135B-4E84-AD0B-B47CD8F2AC73" src="https://github.com/user-attachments/assets/1d665601-a38e-4e6b-b205-fde99efa2237" /> | ## To test - [x] `/org/{slug}/integrations`: GitHub and Vercel sections contained, vertically stacked - [x] Vercel connection tree connectors render correctly when integration is installed - [x] `/project/{ref}/settings/integrations`: no regression - [x] Org keyboard shortcut for add connection still works --------- Co-authored-by: Cursor <cursoragent@cursor.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 --> |
||
|
|
3211d52a2a |
fix(studio): fallback to initial when OAuth logo fails to load (#46953)
## What kind of change does this PR introduce? Bug fix. Resolves DEPR-594. ## What is the current behavior? On Studio, when an OAuth app provides an `icon` URL that fails to load (e.g. Cursor MCP’s logo on Vercel Blob is blocked by CSP `img-src`), `RequesterLogo` renders an empty gray box on `/authorize` even though a letter fallback already exists when `icon` is null. ## What is the new behavior? `RequesterLogo` tracks image load failures via `onError` and falls back to the app name initial—the same treatment used when no icon URL is provided. Applies to the authorize interstitial and approved state. This is graceful degradation, not a logo-delivery fix. Partner logos that load successfully (e.g. Figma on `*.supabase.co`) are unchanged. ## Additional context **Proper fix (later):** Mirror partner logos to Supabase-controlled storage at dynamic registration time. This is tracked in [DEPR-596](https://linear.app/supabase/issue/DEPR-596). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * OAuth app requester logos now feature enhanced error handling. If a logo image fails to load, the system automatically displays a fallback text-based avatar using the requester's initials. Logo displays refresh correctly when you update app icons, ensuring a consistent and reliable user experience throughout your application management. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
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> |
||
|
|
a59b797216 |
fix: improve redirect validation (#46794)
## 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? returnTo is not correctly validated ## What is the new behavior? returnTo is validated <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved validation of redirect URLs used after organization creation; when a return URL is provided it is now validated before redirecting, while auth-related query parameters are still preserved. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b347c8341d |
chore(etl): etl add-on forward compat (#46869)
Prep work for new ETL pipeline add-on, forward compatible |
||
|
|
00afaeac73 |
feat(studio): Issuer field in SSO form (#46187)
> [!CAUTION] > This new SSO field is UI-only until `oidc_issuer` is added to the `config` object. ## What kind of change does this PR introduce? Feature ## What is the current behavior? The SAML SSO provider config form has no way to supply an OIDC Issuer URL, which is required for enterprise-managed MCP authentication. ## What is the new behavior? - Adds an **OIDC Issuer URL** field to the SAML SSO provider config form (`/org/_/sso`) inside an "Advanced settings" collapsible. - Minor UI touch-ups to that SSO form. | After | | --- | | <img width="1434" height="2458" alt="94962" src="https://github.com/user-attachments/assets/e56f83cd-6e30-4a3f-a78d-330fc053953a" /> | The `oidcIssuer` field is UI-only right now; it renders but does not write. Before merging: 1. Add `oidc_issuer` to the SSO config API type (removes the `as any` cast in `SSOConfig.tsx:219`) 2. Add `oidc_issuer: values.oidcIssuer || undefined` to the `onSubmit` payload at `SSOConfig.tsx:183` 3. Wire the backend endpoint to persist and return the field <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * SSO settings now include an "Advanced settings" collapsible with an OIDC issuer field. * **UX / Bug Fixes** * Small UI/description refinements in SSO forms and attribute-mapping layouts. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46187?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Cemal Kilic <cemalkilic96@gmail.com> Co-authored-by: Cemal Kılıç <cemalkilic@users.noreply.github.com> |
||
|
|
122171aecb |
fix: correct usage page URL from /organization to /org (#46777)
The usage page link in the UpcomingInvoice billing breakdown used the incorrect path, resulting in a 404. Corrected to to match the rest of the app. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Corrected the usage page link shown in the billing breakdown tooltip for non-compute items so it now points to the proper /org/... URL, ensuring users are taken to the correct usage page from billing documentation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
35df570342 |
feat(studio): move /authorize to connect interstitial (#46359)
> [!CAUTION] > The `do-not-merge` label has been applied because this contains mocks for easier review and testing. I'll remove those mocks before merging. ## What kind of change does this PR introduce? Feature. Part of the shared Connect UI (interstitial) rollout. Previous slices: #46058, #45909, #45862. ## What is the current behavior? The `/authorize` MCP/OAuth consent screen uses the old `Card`/`Alert` layout. ## What is the new behavior? - Wraps all `/authorize` states in `InterstitialLayout` (the shared full-screen centered card used across Connect flows) - Shows a quiet footnote below the Cancel button ("Authorizing will redirect you to \<url\>") for non-localhost redirect URIs, so users can verify the destination before approving. No extra friction for localhost flows (local MCP servers) | Before | After | | --- | --- | | <img width="692" height="997" alt="Authorize API access Supabase-F6C3747A-5077-43D8-A509-3E16B1DDC168" src="https://github.com/user-attachments/assets/e86dde34-94cb-48ef-b026-66aac9122df6" /> | <img width="692" height="997" alt="Authorize API Access Supabase-FE6FD8B3-1159-4EA5-94D7-EA5CEA7A25F3" src="https://github.com/user-attachments/assets/c1a94a44-51d9-40d8-8046-f3104a27b929" /> | | <img width="692" height="997" alt="Authorize API access Supabase-86742351-3521-4B62-AF87-403CB7E7F4F5" src="https://github.com/user-attachments/assets/41cff7af-b9e4-4a20-a979-7148b4220265" /> | <img width="692" height="997" alt="Authorize Cursor Supabase-B665B4A4-600F-462B-8C97-84B171EC3103" src="https://github.com/user-attachments/assets/804286f2-ce51-45ab-bb3f-315f8ac62445" /> | | <img width="692" height="997" alt="Authorize API access Supabase-C73DC3D0-8646-4E6E-A259-3E84AE46DAF2" src="https://github.com/user-attachments/assets/8f285edb-438f-4262-9faa-f1133c679ed4" /> | <img width="692" height="997" alt="Authorize Cursor Supabase-FEA86625-27D5-4DB5-B4D4-1A2CB804E56E" src="https://github.com/user-attachments/assets/b54f2ceb-e1cf-4c7e-be3f-8e1b0942e9a4" /> | | <img width="692" height="997" alt="Authorize API access Supabase-48E0C7CB-DDDD-4305-B821-F3BEB52C4A4E" src="https://github.com/user-attachments/assets/7d123c57-e05d-408c-8df9-d747a3afd714" /> | <img width="692" height="997" alt="Authorize Cursor Supabase-CE8F9905-FAE0-4C06-B77A-9F269B2100FE" src="https://github.com/user-attachments/assets/9f403b83-5de3-43c8-a592-c3022e041243" /> | | <img width="692" height="997" alt="Authorize API access Supabase-E37D2CD5-476F-4F49-A5FB-631B265025DC" src="https://github.com/user-attachments/assets/3d235315-d7c0-4279-b23f-e8b595888511" /> | <img width="692" height="997" alt="Authorize Cursor Supabase-DF078AEB-BB78-4647-9FA2-5D5403CCA5D6" src="https://github.com/user-attachments/assets/53d51718-8707-4b97-9cbe-8e523f4ce0e0" /> | | <img width="692" height="997" alt="Authorize API access Supabase-D6F6817F-D8DD-4D55-85BB-A15100814AAB" src="https://github.com/user-attachments/assets/c80c5579-772a-4dfe-a247-b0b9772b9690" /> | <img width="692" height="997" alt="Authorize Cursor Supabase-E457B580-9786-43AD-9CF9-FE4F5BB8E785" src="https://github.com/user-attachments/assets/30c47b05-edf5-4380-a2f1-aedb99482540" /> | | <img width="692" height="997" alt="Authorize API access Supabase-4F3D6AA4-E2E3-4526-B391-49B6E0861911" src="https://github.com/user-attachments/assets/ffbe5b65-6eef-49d7-95f1-c29072c320b8" /> | <img width="692" height="997" alt="Authorize Cursor Supabase-CA9FFCC9-4CA2-4718-AD49-B02D86C6EF6A" src="https://github.com/user-attachments/assets/8fd7ff39-19f5-4414-af13-3821290735b2" /> | | <img width="692" height="997" alt="Authorize API access Supabase-E507B7A5-9AD0-4F17-8743-63A7B47D171A" src="https://github.com/user-attachments/assets/1639b5cc-69c4-4a43-b049-6f989e2cdbb1" /> | <img width="692" height="997" alt="Authorize Cursor Supabase-9844BB27-2429-4BA6-BD36-1AB54099F44F" src="https://github.com/user-attachments/assets/a94b88e2-9c2f-4941-840a-5182342bb335" /> | | <img width="692" height="997" alt="Authorize API access Supabase-27684173-9DBB-4F6E-9F7F-87EFD4E10A5F" src="https://github.com/user-attachments/assets/91794c96-8a81-4d83-9c97-01d134639676" /> | <img width="692" height="997" alt="Authorize Cursor Supabase-04E31F7B-D098-4814-A394-01CE3D3E5A51" src="https://github.com/user-attachments/assets/ba0284a3-363c-4aa5-9e4a-c378aed9c42c" /> | | <img width="692" height="997" alt="Authorize API access Supabase-207CBC69-4957-499C-92E8-163F2B34C8AD" src="https://github.com/user-attachments/assets/1bafedd2-bba8-473c-ba57-637289f1c940" /> | <img width="692" height="997" alt="Authorize API Access Supabase-C1627071-4AE2-4012-8F7C-4E6D883618A3" src="https://github.com/user-attachments/assets/a6fc6125-3c1e-4b8c-821a-c3c9f32f3cc0" /> | ## To test A mock toolbar is included for easy local testing. Navigate to `/authorize?mock=loading` and then switch between the following variants: | State | What to check | | --- | --- | | `loading` | Shimmer skeleton inside the card | | `ready` | Regular waiting state | | `approving` | Authorize button shows spinner, both buttons disabled | | `approved` | Success admonition: "Authorization approved" | | `expired` | Warning admonition: "Authorization request expired", no action buttons | | `organizations-loading` | Org selector shimmer, no action buttons | | `organizations-error` | "Unable to load organizations" admonition, no action buttons | | `empty` | "No organizations found" admonition, no action buttons | | `not-member` | "Organization unavailable" admonition, no action buttons | | `error` | "Unable to load authorization" error screen | Then please test the `organization_slug` prefill: `/authorize?mock=ready&organization_slug=<your-org-name-here>`. That org selector should be pre-selected and locked. To test against a real OAuth app, use a registered app on `supabase.green` — the mock states cover all edge cases but a live round-trip confirms the approve/decline API calls. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **New Features** * Added mock preview functionality for testing API authorization and Connect flows * Introduced collapsible, grouped permissions view for OAuth authorization requests * **Refactor** * Redesigned API authorization screens with improved layout and messaging * Restructured permissions display for better organization and clarity * **Bug Fixes** * Fixed inline link underline decoration color * **Tests** * Updated authorization flow test assertions to match new UI behavior <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46359?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Ali Waseem <waseema393@gmail.com> |
||
|
|
3e3496ef6c | fix(studio): copy updates to revoke oauth modal (#46687) | ||
|
|
bf81e46173 | chore: update DPA to June 2026 version (#46558) | ||
|
|
dfaf59010b |
feat(billing): show cancel subscription button on billing page (#46500)
Extracts the Cancellation Flow from the subscriptions side panel and adds a new button that initiates the flow (old journey is still possible): (screenshots see below) Verified manually: - ✅ confirmed the old downgrade flow works, Team -> Pro; Pro -> Free - ✅ confirmed the new downgrade flow works - ✅ button does not show up when on free plan; no flicker - ✅ button does not show up on enterprise/platform plan - ✅ verified button is disabled when managed by AWS marketplace (hardcoded in `useSelectedOrganizationQuery`) - ✅ verified button is disabled if `canUpdateSubscriton` is false, hardcoded in `useAsyncCheckPermissions` - ✅ modal for exceeding-free-projects shows up <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a guided subscription cancellation flow with confirmation steps, member/usage checks, and an exit survey. * Exposed a visible "Cancel Subscription" control in billing settings, enabled/disabled with contextual tooltip messaging. * **Improvements** * Downgrade/exit survey confirm action can be disabled when appropriate; exit survey confirm label updated to "Downgrade Now". * **Chores** * Added frontend telemetry for cancellation button interactions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
a776b54863 |
fix(studio): show role permission descriptions in edit access drawer (#46627)
Mirrors the recent invite drawer change (#46515) on the edit access drawer. Each role option now describes its permissions via the shared \`ROLE_DESCRIPTIONS\` map instead of showing just the role name. Closes FE-3524. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Role selection in Team Settings now shows full, role-specific permission descriptions and appends any disabled-reason details for clarity. * **Tests** * Added integration tests covering the role panel UI: role listing, selected role label, documentation link, role-specific descriptions, and an admin-safety notice; includes test environment compatibility stubs for animations and routing. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
3e7d8d0f68 |
chore: Update styling and more descriptive information for roles when inviting members (#46515)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? - Better role selector thats actually more helpful with descriptions - More tests with MSW - Refactored to a side panel due to more information being presented in the modal ## How to test - Try inviting members to an org - Make sure members can still be revoked! <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Team member invitation interface redesigned from modal dialog to side panel. * Role selection now displays as an interactive radio list with descriptions for each role. * Improved form layout with horizontal organization for better usability. * **Tests** * Added integration and unit tests for team member invitation functionality. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b2b5cba287 |
feat(studio): add organization shortcuts (#46356)
## What kind of change does this PR introduce? Feature. Resolves FE-3470. ## What is the current behavior? Organization surfaces have a `G then ,` shortcut to enter org settings, but once inside there is no keyboard navigation, sidebar tooltips, or action shortcuts for the various org pages. | Area | Current behaviour | | --- | --- | | Org Settings sidebar | Routes are click-only once users are inside Settings. | | OAuth Apps | Publish / confirm actions have no keyboard shortcuts. | | Private Apps | Create app has no keyboard shortcut. | | Team | Invite / send actions have no keyboard shortcuts. | | Integrations | Add project connection has no keyboard shortcut. | | Org Projects | New project and search have no keyboard shortcuts. | | Audit Logs | Refresh has no keyboard shortcut. | ## What is the new behavior? Mirrors the Project Settings shortcut pattern (#46352) across all Organization surfaces. | Area | New shortcut coverage | | --- | --- | | Org Settings sidebar | `S then G/C/S/A/P/W/L/D` for General, Security, SSO, OAuth apps, Private apps, Webhooks, Audit logs, Legal documents. Shortcut badge appears on hover in the sidebar. | | Org Settings entry | `G then ,` (remapped from `G then O`) to match the Project Settings chord. | | OAuth Apps | `Shift+N` opens Publish app panel; `Mod+Enter` confirms the open panel. | | Private Apps | `Shift+N` opens Create app sheet (works in both empty-state and list-state). | | Team | `Shift+N` opens Invite members dialog; `Mod+Enter` sends the invitation(s). | | Integrations | `Shift+N` triggers Add project connection when permitted. | | Org Projects | `Shift+N` navigates to new project; `Shift+F` focuses the search input. | | Audit Logs | `Shift+R` refreshes the log list. | ### Implementation notes - Threads `shortcutId` through the `WithSidebar` pipeline (`SidebarLink` → `SubMenuSection` → `ProductMenuGroup`) so tooltip display is automatic — no new rendering logic. - Layout-scoped chords mount only while `OrganizationSettingsLayout` is active, so `S then G` in org settings does not conflict with `S then G` in project settings. - Cheatsheet reference groups promoted to typed constants with readable labels (was: bare strings like `'org-oauth-apps'`). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * System-wide keyboard shortcuts for org areas: project search & new project, private app creation, OAuth app publish/confirm, add GitHub integration, invite members (open/submit), and refresh audit logs. * Sidebar and product menu now show assigned shortcuts for faster navigation; org settings navigation shortcut remapped. * **Tests** * Added coverage for org shortcut registry behavior, sequences, and ordering. * **Chores** * New shortcut reference groups and ordering for improved discoverability. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46356?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Ali Waseem <waseema393@gmail.com> |
||
|
|
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> |
||
|
|
6236ee9ef9 |
POC: bring back MSW to remove the pattern of vi.mock (#46439)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Right now our tests for API mocking is using vi.mock and mocking that query or fetch handler. This is not the right approach IMO, 2 years ago @jordienr added MSW with some very powerful helpers. The idea is to move component test that rely on API using MSW within ViteTest. Principles are simple: - Mock API responses - Mount your component that uses API responses - Tests and assert on UI - Added Skill for Clanker This pattern is 100 times better than what we have <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Expanded and strengthened test suites for secrets, org lookup, support flows, OAuth auth, and onboarding; mocks now use contract-backed responses for more realistic coverage. * **Documentation** * Added a comprehensive guide describing a standardized pattern for component tests that mock network requests. * **Chores** * Improved test helpers, typing for API mocks, and test runner configuration for more reliable and maintainable tests. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46439?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <alaister@users.noreply.github.com> Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
a45776ecb9 |
feat(studio): restrict auth email template editing for free projects (#45396)
## What kind of change does this PR introduce? Feature / abuse-prevention update. Resolves DEPR-198. ## What is the current behaviour? Free projects using Supabase's built-in email service can edit raw Auth email template subjects and HTML in Studio. That is the risky cohort this project is trying to constrain. ## What is the new behaviour? ### Template editing restrictions For free projects using Supabase's built-in email service, Studio keeps Auth email templates viewable and previewable but disables subject/body editing and saving. Editing is unlocked by setting up Custom SMTP, configuring a send-email hook, or upgrading to a paid plan. **Grandfathering:** projects created before `2026-06-01T00:00:00Z` (the platform enforcement cutoff) are exempt; their editing UI stays unlocked. This mirrors `FREE_TIER_TEMPLATE_BLOCK_CUTOFF_DATE` in the platform PR exactly. | After | | --- | | <img width="1024" height="759" alt="Emails Authentication Fizz Test Supabase-173BB09B-0FB9-4133-8202-9E310DDB347A" src="https://github.com/user-attachments/assets/c966212d-ed0c-443b-8197-440cc2937ef6" /> | | <img width="1024" height="759" alt="Emails Authentication Fizz Test Supabase-CD5845EB-0E45-4779-8989-44E775B2411A" src="https://github.com/user-attachments/assets/055a64d6-b5e8-4d37-a261-6e280f04536a" /> | ### Warning dialogs on transitions that reset templates Two flows now surface a warning before the user commits to a state change that resets their custom email templates to defaults: 1. **Disabling custom SMTP** (SMTP settings page): a confirmation dialog warns that templates will be reset to defaults and the email rate limit reduced to 2 per hour. On confirm, Studio resets all 13 templates via the existing per-template reset endpoint (`Promise.allSettled`). The "won't be able to edit" sentence is shown only for post-cutoff projects; grandfathered projects skip it. The corresponding server-side enforcement is in the Platform PR: https://github.com/supabase/platform/pull/33129 2. **Downgrading to the Free plan** (billing settings): an admonition in the existing downgrade confirmation modal warns that custom templates will be reset to defaults and won't be editable without custom SMTP. The admonition is shown only when the org has at least one post-cutoff project; orgs whose projects are all grandfathered skip it. | Custom SMTP | Downgrading | | --- | --- | | <img width="862" height="586" alt="66764" src="https://github.com/user-attachments/assets/6470c8a6-2f79-40a5-ad3b-bfe5b0ba9c54" /> | <img width="1268" height="1552" alt="CleanShot 2026-05-22 at 17 28 37@2x-FEB1901E-38E6-42DF-8C27-0A036D8A1B94" src="https://github.com/user-attachments/assets/e8caa9e6-c3ed-4787-b771-af77a43eb854" /> | ### Informational admonition when enabling SMTP When a user enables custom SMTP for the first time, a sandwiched admonition above the save footer informs them that the email rate limit will be increased to 30 per hour and can be adjusted. _This is just a minor cosmetic change, unrelated to the email template disabling. Sorry._ | Before | After | | --- | --- | | <img width="1024" height="759" alt="Emails Authentication Chisel Toolshed Supabase-54317D18-803C-4A58-8211-2359355D083B" src="https://github.com/user-attachments/assets/29eff649-02dc-40f3-a379-0b4d484a76c7" /> | <img width="1024" height="759" alt="Emails Authentication Chisel Toolshed Supabase-9E12399E-E9FB-4F9A-B029-A08008EA4B50" src="https://github.com/user-attachments/assets/e542ed86-4da6-407e-8293-0f4c0f071e18" /> | ## How to test All existing projects pre-date the enforcement cutoff (`2026-06-01T00:00:00Z`) and are grandfathered, so the restriction UI won't appear by default. To force the restricted state locally, back-date the cutoff in one file: In `apps/studio/components/interfaces/Auth/EmailTemplates/EmailTemplates.utils.ts`, temporarily change: ```ts export const FREE_TIER_TEMPLATE_BLOCK_CUTOFF_DATE = '2026-06-01T00:00:00Z' ``` to: ```ts export const FREE_TIER_TEMPLATE_BLOCK_CUTOFF_DATE = '2025-01-01T00:00:00Z' ``` Revert before committing. With the cutoff back-dated, use a free-plan project and: - **Template restriction + admonition:** navigate to Authentication > Emails with no custom SMTP configured. Subject/body fields should be read-only and the "Set up SMTP" admonition should appear, with its dropdown offering upgrade and send-email hook options. - **SMTP disable warning:** enable custom SMTP on a project, then disable it via Authentication > SMTP Settings. The confirmation dialog should warn that templates will reset to defaults and that editing will be restricted after disabling. - **Downgrade warning:** in billing settings, initiate a downgrade to the Free plan. The downgrade modal should include an admonition warning about template reset and restricted editing (only if the org has at least one post-cutoff project). ## Additional context The default Auth email template copy was also improved across docs, examples, and UI library snippets (separate prior commits). The per-template reset button (`ResetTemplateDialog`) was migrated to the async `AlertDialogAction` pattern introduced in #45960; the dialog stays open and shows a loading state while the reset is in-flight, closes on success, and stays open on error. Closes PRODSEC-183 --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: Stephen Morgan <stephen@doublethink.co.nz> |
||
|
|
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 -->
|
||
|
|
5c85ec9035 |
feat(studio): format Logs Ingest and Logs Query usage as GB FE-3400 (#46387)
- adds new log ingestion billing metrics Linear: FE-3400 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
838fe7f976 |
chore: migrate Organization settings Modal to Dialog (#46332)
## Problem Organization settings still uses the deprecated `Modal` for: - downgrading subscription - requesting feedback after downgrading - showing an alert about members limit - requesting feedback after upgrading - deleting a published OAuth app - showing preview of a new OAuth app - Revoking an OAuth app ## Solution - use `Dialog` instead <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Replaced legacy modal UI with the app's modern dialog/alert-dialog components across billing and OAuth settings (upgrade/downgrade, exit survey, members-limit, delete/revoke, preview), keeping existing content and flows. * Confirm/cancel flows updated for more reliable async handling and clearer loading/disabled states during actions. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46332?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 --> |
||
|
|
51ecfbb86d |
studio(chore): reuse org details fields in AWS marketplace flow (#46087)
## What kind of change does this PR introduce? Refactor. Resolves FE-3216. ## What is the current behavior? The AWS Marketplace create-organisation dialog owns its own copy of the organisation name, type, and company-size form fields. It’s duplicative and has drifted from the normal `/new` organisation form, making the AWS flow harder to keep aligned. This is stacked on #46058. ## What is the new behavior? - Extracts the shared organisation details schema, defaults, option constants, and fields from the normal `NewOrgForm` - Reuses those shared fields in both the full organisation creation form and the AWS Marketplace create-and-link dialog - Keeps the AWS Marketplace flow anchored in the onboarding interstitial rather than routing through `/new` - Keeps the AWS-specific buyer ID, AWS-managed organisation endpoint, create-and-link success state, and modal dismissal behaviour | Before | After | | --- | --- | | <img width="1024" height="759" alt="Link AWS Marketplace Supabase-3742FEDF-53BD-4E80-926D-498B2EA94773" src="https://github.com/user-attachments/assets/617ee422-1cf0-4858-801b-a4ee5ee402c9" /> | <img width="1024" height="759" alt="Link AWS Marketplace Supabase-0FEE2292-CB9F-43AA-B131-B6A549890970" src="https://github.com/user-attachments/assets/ff017468-f8ac-469a-bb17-eea07842306f" /> | ## Additional context The shared field extraction is intentionally limited to organisation details. Billing, plan selection, spend cap, Stripe, captcha, and the `/new/[slug]` redirect behaviour stay owned by `NewOrgForm`; AWS Marketplace keeps its separate create-and-link container because AWS owns the billing contract. ## Validation - `pnpm --filter studio exec vitest --run tests/pages/aws-marketplace-onboarding.test.tsx` - `pnpm --filter studio lint:ratchet --rule no-restricted-exports` - `git diff --check` Full Studio typecheck was also run, but it currently fails on existing unrelated repo-wide React/implicit-any errors outside this diff. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved AWS Marketplace organization creation dialog to prevent accidental closure while the creation process is in progress. * **Improvements** * Standardized organization details form handling across different organization creation flows for improved consistency and user experience. * **Tests** * Added comprehensive test coverage for the AWS Marketplace organization creation workflow, including form submission, validation, and state transitions. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46087?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
a8720dee1f |
feat(studio): move AWS Marketplace to connect interstitial (#46058)
## What kind of change does this PR introduce? Feature. Resolves DEPR-556. ## What is the current behavior? AWS Marketplace onboarding uses a separate scaffold and AWS-specific organization selection UI, so it does not match the newer shared connect interstitial pattern used by Redeem Credits. ## What is the new behavior? - Moves `/aws-marketplace-onboarding` onto the shared connect interstitial shell with AWS and Supabase branding - Reuses the shared organization selector behaviour from Redeem Credits, including last-visited organization promotion, selected organization promotion, the create-organization card, and compact overflow disclosure - Keeps the existing AWS data path for buyer eligibility, onboarding info, organization linking, AWS-managed organization creation, and success/error/ineligible states - Removes the now-unused legacy AWS Marketplace layout/scaffold components - Removes the temporary reviewer mocks from the branch before merge ## Additional context This PR preserves the current AWS-managed organization creation modal so the AWS flow keeps working while adopting the shared connect sheet. FE-3216 should move that creation path into the general organization form later, likely replacing the AWS-specific modal with a preconfigured `/new` flow that can still return to AWS Marketplace onboarding and link automatically. --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
243e079a2c |
chore: remove _Shadcn_ suffix from Command components (#46153)
## Problem The `_Shadcn_` suffix isn't needed anymore on `Command` components ## Solution - Remove the `_Shadcn_` suffix - Simplify UI package exports - Apply prettier <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Simplified command component imports and exports across the UI library by removing internal naming aliases and adopting direct component references. Updated the public UI package barrel export to use wildcard re-exports for cleaner API surface. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46153?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 --> |
||
|
|
c414146572 | fix(upcomingInvoice): do not manually subtract credits (#46116) | ||
|
|
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 --> |
||
|
|
e65da2c3e7 |
feat(studio): move redeem credits to connect interstitial (#45909)
## What kind of change does this PR introduce? Feature. Part of DEPR-556. ## What is the current behavior? The `/redeem` credit redemption page uses the legacy redeem credits layout and scaffolded two-column UI. It is visually separate from the newer connect interstitial surfaces. ## What is the new behavior? `/redeem` now uses the shared connect interstitial layout with a Supabase logo, signed-in account row, organisation selector, and full-width redeem action. The existing `CreditCodeRedemption` modal still owns the actual code entry, hCaptcha, permission checks, mutation, and success/error handling. Creating a new organisation links to `/new` with a return URL, and the returned organisation is preselected when present. Temporary mock states are available on non-production and Vercel preview environments: - `/redeem?mock=loading` - `/redeem?mock=ready` - `/redeem?mock=redeeming` - `/redeem?mock=redeemed` - `/redeem?mock=already-redeemed` - `/redeem?mock=invalid` - `/redeem?mock=wrong-account` - `/redeem?mock=error` | Before | After | | --- | --- | | <img width="1024" height="759" alt="Redeem Credits Supabase-66AF2C81-89A0-4F95-A591-3550AAD7112A" src="https://github.com/user-attachments/assets/1e0dd7af-3168-4566-a7d9-0b889fe69d4e" /> | <img width="1024" height="759" alt="Redeem Credits Supabase-7F9C59DD-73EC-4717-B2B7-3E6BB325273C" src="https://github.com/user-attachments/assets/60e44213-d2ab-4b5c-b03e-38a3425dbd27" /> | | <img width="1024" height="759" alt="Redeem Credits Supabase-A77F2F93-98C3-42E9-B028-049E1AAC0CA3" src="https://github.com/user-attachments/assets/25087b51-94cb-40c7-9dde-1fc957b7dd8e" /> | <img width="1024" height="759" alt="Redeem Credits Supabase-4C4B7818-16A5-430E-B54F-E7FF34229CA0" src="https://github.com/user-attachments/assets/4da11122-b547-4e1e-a953-8d2e4c478431" /> | | <img width="1024" height="759" alt="Redeem Credits Supabase-A77F2F93-98C3-42E9-B028-049E1AAC0CA3" src="https://github.com/user-attachments/assets/25087b51-94cb-40c7-9dde-1fc957b7dd8e" /> | <img width="1024" height="759" alt="Redeem Credits Supabase-4C4B7818-16A5-430E-B54F-E7FF34229CA0" src="https://github.com/user-attachments/assets/4da11122-b547-4e1e-a953-8d2e4c478431" /> | <img width="1024" height="759" alt="Redeem Credits Supabase-49FC982C-2605-41B3-8216-B8F270825247" src="https://github.com/user-attachments/assets/8e5fc351-6e11-4fef-9d55-1a60fa34a89a" /> | | <img width="1024" height="759" alt="Redeem Credits Supabase-6AF18EF8-1699-4341-A900-34E3AEB59703" src="https://github.com/user-attachments/assets/7adf3d15-73a7-4ef1-9d25-bfcb07b1b15c" /> | <img width="1024" height="759" alt="Redeem Credits Supabase-4F8BBF66-6AF6-403F-B949-079F8E47200B" src="https://github.com/user-attachments/assets/b05461de-1fd3-4251-9a22-9d1a4dea2b20" /> | | <img width="1024" height="759" alt="Redeem Credits Supabase-320E56E7-A291-426B-92B4-5CD4518C85B6" src="https://github.com/user-attachments/assets/aa172303-0219-425d-9c8b-07044a9f5cac" /> | <img width="1024" height="759" alt="Redeem Credits Supabase-7E55274C-E39E-443B-B636-63B597E11494" src="https://github.com/user-attachments/assets/4a09d19e-a61c-4c1d-a0a2-e535e53aeee7" /> | | <img width="1024" height="759" alt="Redeem Credits Supabase-4D5A1985-D36B-48E1-8108-E95C10C52A12" src="https://github.com/user-attachments/assets/e3baffe9-e0ac-4dff-8f4c-1b01d34fbfe4" /> | <img width="1024" height="759" alt="Redeem Credits Supabase-B1296556-9DDF-48ED-A0DA-4BEFF5D20FBA" src="https://github.com/user-attachments/assets/27ed8201-960b-45e3-a32f-115045d0443e" /> | | <img width="1024" height="759" alt="Redeem Credits Supabase-193C4266-29BC-4B03-A746-4C2CE3BD29EB" src="https://github.com/user-attachments/assets/230fb7a0-4049-46b7-84d4-eb549099863b" /> | <img width="1024" height="759" alt="Redeem Credits Supabase-751A900D-A8CF-425C-A745-1511B6DC81E3" src="https://github.com/user-attachments/assets/55ab5719-a77c-486b-b2d0-5926a524a7b4" /> | | <img width="1024" height="759" alt="Redeem Credits Supabase-29305C15-19B7-4015-9041-62B79E0C95A8" src="https://github.com/user-attachments/assets/a1b2ba08-2d1a-4a95-a6ac-4d9e3faf9327" /> | <img width="1024" height="759" alt="Redeem Credits Supabase-A1628FDB-CFBE-47E7-83D7-3D3D426C3C1E" src="https://github.com/user-attachments/assets/7fbbf75e-1f8e-478f-83ec-2ab06dff0545" /> | <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **New Features** * Added organization selector to the credits redemption workflow. * New "Create Organization" card for quick access to organization creation. * **Refactor** * Streamlined the credits redemption page for improved user experience. * Enhanced organization card display with customizable descriptions. * **Style** * Removed "Coming soon" beta indicators from action cards. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45909?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: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
aedd91a9bb |
chore: remove <HoverCard> _Shadcn_ suffix (#45987)
## Problem The `_Shadcn_` suffix isn't needed anymore on `HoverCard` components ## Solution Remove it. No other changes <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Standardized hover-card component usage across the apps and design system for consistent behavior and markup. * No user-facing changes — hover previews, tooltips, snippet/template previews, and code hover panels retain the same appearance and interactions. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45987) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |