mirror of
https://github.com/supabase/supabase.git
synced 2026-06-13 10:09:12 +08:00
create-pull-request/patch
143 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c713135384 |
fix(studio): wrappers install state + one-click install (#46697)
- fix install badge state in wrappers detail page - add "Install" button in top action bar - "Install wrapper" if required extensions _aren't_ installed - "Add new wrapper" if required extensions _are_ installed - make wrappers "one-click install" by - showing the required extensions in the CreateWrappersSheet - and automatically installing them on wrapper submission Only available behind `isMarketplaceEnabled` flag at the moment. https://github.com/user-attachments/assets/38f5549d-938e-4e2f-a723-53b9a028e9dc |
||
|
|
40c947ebfb |
fix: Handle non existant columns when sorting tables (#46741)
When a user has sorted by some column in the Table Editor and the column is deleted, the sort data is wrong so it causes issues. In the general view in the Table Editor, the error is handled by removing the sort key when a specific error is detected but it can still happen in ForeignRowSelector. To test: 1. Have 2 tables with references between them. 2. In the `sessionStorage`, under the `supabase_grid-<ref>` key, update the sort key to a non-existant column for a table. 3. Try to open the `ForeignRowSelector` for that table by clicking on a cell in the referencing column. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Sorting now validates referenced columns and ignores invalid sort entries. * Local sort restoration and UI sort application now derive sorts from the original table context for more consistent behavior across editors and popovers. * Prefetch logic uses the resolved table context when falling back to saved sorts. * **Tests** * Added cases for malformed and out-of-scope sort parameters to prevent regressions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
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> |
||
|
|
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 --> |
||
|
|
b28f91741f | fix(self-hosted): reveal and copy secret api key in project settings (#46592) | ||
|
|
0c8b71de64 | feat(self-hosted): update project home for self-hosted and cli (#46544) | ||
|
|
ca9b02b5ac | feat(self-hosted): add minimal project settings (#46554) | ||
|
|
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 --> |
||
|
|
1d203f6c93 |
feat: Support CLI for Vector buckets (#46381)
## Context > [!IMPORTANT] > Will open up for review once CLI PR is merged and deployed so that it's easier to test Related PR: https://github.com/supabase/cli/pull/5230 Adding support for vector buckets for local CLI - will need to be tested locally via `pnpm run dev:studio-local` ## To test There's a bit of testing instructions in the linear ticket [here](https://linear.app/supabase/issue/FE-3474/show-vector-buckets-in-local-admin-studio) as it involves using a branch of CLI - otherwise do reach out to Fabrizio if any help might be needed, but generally: ### Local CLI You might need to manually set `isCli` to `true` in `StorageMenuV2` if the "Vectors" nav item isn't showing up on the storage UI given we're testing via `pnpm run dev:studio-local` - [x] Can create bucket - [x] Can delete bucket - [x] Can create indexes - [x] Can insert data into indexes (via FDW) - [x] Can delete indexes Known issues (that aren't directly solvable from FE end) Reach out to Fabrizio for context as we were both investigating this - PG database needs to be on 17.6 (otherwise there's no S3 vectors FDW) - Storage version needs to be on 1.59.0 ### Self-hosted (This might be tricky to actually test, but just ensure that the code satisfies this) - [x] Cannot see vector buckets ### Hosted - [x] Everything works status quo <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Vector bucket management UI and platform APIs (create/list/delete buckets & indexes) * Local S3 credentials endpoint and client-side hook for self‑hosted/CLI use * **Bug Fixes** * Improved S3 vector setup notifications and clearer error guidance for manual installation * **Refactor** * Deployment-mode gating: platform vs CLI/self‑hosted now controls feature visibility and page behavior * **Tests** * Added suites covering deployment-mode gates and vector bucket error/usage scenarios * **Chores** * Build env updated to expose local S3 credential vars <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46381?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Ali Waseem <waseema393@gmail.com> |
||
|
|
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> |
||
|
|
c1276c8e9a | feat(self-hosted): add new API keys to self-hosted Studio and MCP server (#46173) | ||
|
|
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> |
||
|
|
ba77d15d41 |
chore(billing): remove billing address modal and tax id banner (#46210)
This PR removes the billing address modal and tax id banner code completely since we no longer need it. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Removed Features** * Billing address update modal is no longer accessible. * Tax ID banner has been removed from the app UI. * Placeholder banner block disabled. * **Tests** * Automated tests for the billing address modal were removed. * **Chores** * Associated local-storage key for the tax ID banner was removed. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46210?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
df77fc9011 |
fix(cli): resolve infinite loader on device code screen (#46137)
## Summary Follow-up fix for [#46120](https://github.com/supabase/supabase/pull/46120). PR #46120 correctly guarded against duplicate `POST /platform/cli/login` calls using a `useRef`, but left `navigate` in the `useEffect` deps array. Because the parent passes an inline lambda, `navigate` gets a new reference on every render. This causes React to: 1. Run the effect cleanup mid-flight (setting `isActive = false`) 2. Re-run the effect, which hits the session-id ref guard and returns early When step 1 happens while the POST is in-flight, the response arrives with `isActive === false`, silently drops the `navigate(...)` call, and leaves status stuck at `{ _tag: 'loading' }` — the infinite spinner reported in Slack. ## Fix Store `navigate` in a ref (updated each render) and call `navigateRef.current(...)` inside `createSession`. Remove `navigate` from the deps array so parent re-renders never trigger a cleanup while the POST is in-flight. ```ts const navigateRef = useRef(navigate) navigateRef.current = navigate // always up to date, never a dep ``` All 7 existing CLI login unit tests pass, including the "POSTs exactly once even when parent re-renders" regression test. ## Test plan - [ ] Run `pnpm test:studio tests/pages/cli-login.test.tsx` — all 7 tests pass - [ ] Browser: `supabase login` flow completes and shows the verification code screen without hanging on the loader - [ ] DevTools Network: exactly one `POST /platform/cli/login` fires per login attempt 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved CLI login navigation reliability when parent components update during session creation. * **Style** * Adjusted loading indicator styling on the CLI login screen. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46137?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com> |
||
|
|
da3b0cb3ec |
fix(cli): login creating duplicate tokens on re-renders (#46120)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Bug fix ## What is the current behavior? The CLI login page was firing `POST /platform/cli/login` multiple times per page load due to an unstable `navigate` reference in the parent component re-triggering the effect. This caused several duplicate personal access tokens to be created for each browser sign-in attempt (regression CLI-1491). Additionally, error messages from non-Error rejection shapes (like those from openapi-fetch) were being replaced with a generic "Unknown error" message instead of surfacing the actual platform error. ## What is the new behavior? 1. **Prevents duplicate API calls**: Added a `useRef` guard (`startedForSessionIdRef`) to ensure `createCliLoginSession` is only called once per `sessionId`, even if the parent component re-renders with a new `navigate` reference. 2. **Improved error handling**: Created a `getErrorMessage()` utility that properly extracts error messages from both Error instances and plain objects (e.g., `{ message: string, statusCode: number }`), allowing platform error messages to surface instead of generic fallbacks. 3. **Added comprehensive test coverage**: - E2E test verifying the POST fires exactly once per page load with realistic network latency - E2E test confirming platform error messages are displayed correctly - Unit test for non-Error rejection shapes - Unit test verifying the effect doesn't re-trigger on parent re-renders ## Additional context The fix addresses the root cause by: - Using a ref to track which `sessionId` has already been processed, preventing re-execution when deps change - Extracting error message handling into a reusable utility that handles both Error instances and plain objects - Adding tests that specifically check for the regression (multiple POST calls and error message display) The E2E test includes a 400ms delay in the mock response to simulate real-world conditions where the original bug only surfaced after React committed multiple re-renders. Closes: CLI-1491 https://claude.ai/code/session_01GAujw33MTRBRYSnS8cxcEa <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved CLI login error handling to display platform-specific error messages instead of generic fallback text. * Fixed duplicate login session creation during component rerenders. * **Tests** * Added test coverage for error message display in CLI login. * Added regression tests for single session creation and platform error scenarios. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46120?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
4e86c39ea1 |
chore: remove <ContextMenu> _Shadcn_ suffix (#45971)
## Problem The `_Shadcn_` suffix isn't needed anymore on `<ContextMenu_Shadcn_>` and related components ## Solution Remove it. No other changes <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Replaced legacy context-menu component variants with the unified UI context-menu components across the app for consistent rendering and imports; behavior and menu content remain unchanged. * **Tests** * Updated a test mock to track the unified context-menu component mount count. * **Chores** * Simplified UI package re-exports to expose the canonical context-menu symbols. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45971) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
205ab69061 |
feat(studio): move CLI login to connect interstitial (#45814)
## What kind of change does this PR introduce? Feature / UI refactor ## What is the current behaviour? The CLI browser login route still uses the older API authorisation layout and redirects missing or failed sign-in session states to generic 404/500 pages. ## What is the new behaviour? Moves `/cli/login` onto the shared connect interstitial layout as the next small stacked slice after the organisation invite work. This keeps the real CLI login contract intact while updating the surface: - creates the CLI login session from `session_id`, `public_key`, and optional `token_name` - redirects to the generated `device_code` - renders missing-parameter and session-creation failures in-card instead of redirecting away - keeps the 8-character verification code selectable and copyable as a single string - uses a full-width primary `Copy code` action This also adds the small shared interstitial helpers needed by this surface and adjusts `CopyButton` so the copied check icon inherits the primary button colour instead of turning green. This also removes the CLI version admonition: > Browser login flow requires Supabase CLI version 1.219.0 and above. I checked with our stats and the CLI team. The vast majority of users are on a newer version. | Before | After | | --- | --- | | <img width="1024" height="759" alt="Authorize API access Supabase-D1E3CF26-BD59-4BB2-B457-B552EE47E3DA" src="https://github.com/user-attachments/assets/c89b8b13-fa98-41b7-8093-e59d15b2aa9e" /> | <img width="1024" height="759" alt="Authorize CLI Supabase-C9977F21-88B8-441B-8A2C-09A9515935B0" src="https://github.com/user-attachments/assets/ca13b65a-3875-425c-b73b-8f2101c1e406" /> | | <img width="1024" height="759" alt="Supabase-F42FBEAF-F74D-4920-8A51-7C25004F66D5" src="https://github.com/user-attachments/assets/51adb1e6-a2fb-41fb-b36f-0ae466fe60e2" /> | <img width="1024" height="759" alt="Authorize CLI Supabase-8159A1B1-2594-4183-AC35-FEF1EFD4EA37" src="https://github.com/user-attachments/assets/6f143218-795d-41c9-a8e1-52e529a6b988" /> | <img width="1024" height="759" alt="Supabase-2506E468-9F42-44B9-A5B7-BC4D3777F552" src="https://github.com/user-attachments/assets/a304fca5-cf26-4ae7-abe9-77cdbc21fba5" /> | <img width="1024" height="759" alt="Authorize CLI Supabase-A0EE1239-A345-427C-9CF7-997037A8FC0E" src="https://github.com/user-attachments/assets/33118777-35f3-49d6-bc1e-30e7124b3677" /> | | <img width="1024" height="759" alt="Authorize API access Supabase-A7B84CA6-D230-4C3E-9227-DE21CE35375C" src="https://github.com/user-attachments/assets/78eb6296-035a-4201-b254-b97eda44443c" /> | <img width="1024" height="759" alt="Authorize CLI Supabase-F55E26B2-609B-449C-9C64-08AA90AE3D1E" src="https://github.com/user-attachments/assets/ff7b3b4e-729c-4681-844d-2d5d94bfc084" /> | ## Testing instructions Use the Vercel preview URL for this PR once it is available. The examples below use `<preview-origin>` as a placeholder, for example `https://studio-git-dnywh-feat-cli-login-interstitial-supabase.vercel.app`. You need to be signed in to Studio to see these states because `/cli/login` is still behind `withAuth`. Ready state: - Open `<preview-origin>/cli/login?device_code=ABCD1234` - Check the page title is `Authorize CLI | Supabase` - Check the card title is `Authorize Supabase CLI` - Check the code fills the width, uses the normal sans font, and can be selected - Drag-select the code and copy it; the clipboard should contain `ABCD1234`, not one character per line - Click `Copy code`; the button should show the usual copied success state without a green check icon on the primary button Missing parameters state: - Open `<preview-origin>/cli/login` - Check the card says `Missing sign-in parameters` and names the missing `session_id` and `public_key` parameters - Open `<preview-origin>/cli/login?session_id=session-test` - Check it still stays in-card and names the missing `public_key` parameter instead of redirecting to `/404` Creation error state: - Open `<preview-origin>/cli/login?session_id=not-real&public_key=not-real&token_name=local-dev` - Check it stays in-card with `Unable to create CLI sign-in` instead of redirecting to `/500` - The exact error detail can vary by environment; the important bit is that the failure is shown inside the interstitial card Loading state: - This is transient because there are no production mocks in this slice - To inspect it manually, throttle the browser network before opening a session-creation URL such as `<preview-origin>/cli/login?session_id=not-real&public_key=not-real` Real CLI flow: - Run the browser login flow from Supabase CLI as usual - When the CLI opens a Studio URL, keep the path and query string but replace the origin with the PR preview origin - The page should create the login session and then route to `/cli/login?device_code=<8 character code>` - Enter that 8-character code back in the CLI prompt <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Redesigned CLI login flow with clearer state-driven screens and improved verification UI. * Added a small paired-logo component for centered logo pairs with a connector icon. * **Improvements** * Copy button behavior and styling refined for consistent visual feedback across variants. * **Tests** * New unit tests covering copy-button behavior and multiple CLI login UI flows. [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45814) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
9660b0075c |
refine organisation invite state helpers (#45813)
## What kind of change does this PR introduce? Code cleanup. Follow-up to #45774. ## What is the current behavior? The organisation invite interstitial derives invite states, titles, and descriptions from nested conditional logic in the component. That makes the component harder to scan and pushes too much state coverage into render tests. ## What is the new behavior? See #45774 for screenshots of the general UI before-and-after (which this one builds upon). That PR also contains testing instructions. Extracts the invite status and content decisions into small pure helpers, then covers those helpers with focused unit tests. The component keeps the user-facing render and interaction coverage, including the invalid lookup regression where a 404 should render the invalid invite state instead of raw backend copy. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Improved organization invite flow with enhanced error state handling for expired, invalid, and wrong-account scenarios. * Better consistency in error messages and user guidance throughout the invite process. [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45813) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
791fc74412 |
feat(studio): shared connect layout for organisation invites (#45774)
## What kind of change does this PR introduce? Feature. Part of DEPR-279. ## What is the current behavior? The organization invite page has its own bespoke centered card and page-level Supabase logo. ## What is the new behavior? Introduces a minimal shared interstitial layout and migrates `/join` onto it as the first small connect-surface slice. The invite API and accept-invite mutation paths are unchanged. | Before | After | | --- | --- | | <img width="1024" height="794" alt="Supabase-F2325C57-D5DE-445D-8083-12EF8A1EE0CA" src="https://github.com/user-attachments/assets/b23dcc7a-c649-4b59-9393-9232d74f0c6b" /> | <img width="1024" height="794" alt="Join Organization Supabase-66CDA329-0531-4B12-AC32-A7E21931F876" src="https://github.com/user-attachments/assets/454917ce-1a96-4e50-b003-6c16a541b39a" /> | | <img width="1060" height="822" alt="CleanShot 2026-03-13 at 11 04 43@2x-2616AECB-8203-4439-A1CD-45AB18FC4CA8 1-584A0600-CCE0-4F16-9111-9BEB94BE85EC" src="https://github.com/user-attachments/assets/871c7dcb-120e-40cd-afc8-2cec95e4b7ae" /> | <img width="1024" height="794" alt="Join Organization Supabase-26AD978E-4CF9-4600-9885-082084349E94" src="https://github.com/user-attachments/assets/ee9bfaff-dde4-4366-abae-77dc8a95c4ef" /> | | <img width="1024" height="794" alt="Supabase-4993D74C-D62B-43B7-9681-826BE1591AC4" src="https://github.com/user-attachments/assets/1c411ae0-90e7-481d-a4cc-3eac26267291" /> | <img width="1024" height="794" alt="Join Organization Supabase-C84D4E4C-24F5-463D-B1D6-D11D3256596F" src="https://github.com/user-attachments/assets/688387a4-3c49-41db-b89c-7c5531e91aed" /> | | <img width="1024" height="794" alt="Supabase-D9BD2601-98A4-489D-A51D-CEB73F51FA6F" src="https://github.com/user-attachments/assets/6d1da65f-d655-4047-9f6a-db65f8c0a729" /> | <img width="1024" height="794" alt="Join Organization Supabase-50065F40-179A-4BD6-8F1D-6106FFD8A15C" src="https://github.com/user-attachments/assets/e61809f9-dcec-4e51-ba94-91b04010ec50" /> | ## Testing notes Staging invite emails are generated with the fixed staging dashboard origin, for example: ```text https://supabase.green/dashboard/join?token=...&slug=... ``` To test this PR preview with a real invite token, keep the path and query string from the email but replace the origin with the Vercel preview origin, for example: ```text https://studio-staging-git-dnywh-featconnect-interstitial-join-supabase.vercel.app/dashboard/join?token=...&slug=... ``` ### Manual state checks - **Signed out:** open the swapped invite URL in an incognito window or a browser signed out of Studio. Expected: `View invitation`, sign-in/create-account actions, and no loading skeleton hang. - **Wrong account:** sign in to the PR preview as an account that is not the invite recipient, then open the swapped invite URL. Expected: `Wrong account`, warning callout, and `Sign out`. - **Happy path:** sign in as the invited email address, then open the swapped invite URL. Expected: `Join {Organization}`, signed-in account row, `Accept invite`, and `Decline`. Accepting should join the organization. - **Invalid token:** alter one character in the token in the swapped invite URL. Expected: invalid invite state. - **No longer valid:** accept the invite once, then open the same swapped invite URL again. Expected: no-longer-valid/already-used state, depending on the backend response. ### Test-covered states Expired invites, generic backend error, loading, and create-account-disabled states are harder to force manually in staging. They are covered by `tests/components/OrganizationInvite.test.tsx`. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Redesigned the organization invitation experience with an interstitial layout, clearer early-return flows for signed-out, loading, expired/invalid, wrong-account, and accepted-invite states; primary CTA now reads “Accept invite”. * Streamlined error and sign-out flows with clearer, focused messaging. * **New Features** * Added a reusable interstitial layout and compact account row for invitation screens. * **Tests** * Added comprehensive tests covering invite states, accept/decline actions, and error handling. [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45774) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
d676c832f3 |
fix(studio): pre-empt React 19 regressions in tests + Support form (#45784)
Four React-19-sensitive patterns that pass on React 18 today but break
under React 19 (verified on the in-flight TanStack Start branch).
Landing on master now so the eventual React 19 upgrade is a no-op for
tests, instead of a separate cleanup pass under upgrade pressure.
Each fix is a strict superset / less-fragile equivalent of the existing
pattern, so master (React 18) stays green.
**Changed:**
- `hooks/misc/useStateTransition.ts` — fire on entry into `newTest` from
any state other than `newTest`, instead of requiring exactly `prevTest →
newTest`. React 18+ auto-batches dispatches across awaits (e.g.
`dispatch SUBMIT` in the handler, `dispatch ERROR` in `onError`),
collapsing `editing → submitting → error` into a single render where the
intermediate `submitting` tick is never observed. Strict superset of the
old check for our reducers — `success`/`error` are only reachable from
`submitting`.
- `Support/CategoryAndSeverityInfo.tsx` — guard `onValueChange` against
Radix Select's spurious `''` emission. When the controlled value
transitions from `undefined` to a defined value whose `SelectItem` isn't
mounted yet (dropdown closed → items haven't registered), Radix's hidden
`BubbleSelect` fires `onValueChange('')` and clobbers the field. No
`SelectItem` can have `value=""` (Radix throws), so any `''` is
guaranteed spurious — drop it before calling `field.onChange`.
([radix-ui/primitives#3381](https://github.com/radix-ui/primitives/issues/3381))
- `EditSecretModal.test.tsx` — `getByLabelText` → `findByLabelText`.
Under React 19's scheduling, the decrypted-value query resolves on a
separate render tick, so form fields appear one tick after the skeleton.
- `LogsPreviewer.test.tsx` — `addEventListener('click', spy)` instead of
`loadOlder.onclick = vi.fn()`. React 19 reassigns `.onclick` on managed
elements as part of its event wiring, clobbering the direct-property
spy.
## To test
### Unit tests
- `pnpm --filter studio test` — all unit tests pass on master (React 18)
### Support form URL prefill (Radix Select guard)
- `/support/new?category=Problem` → category dropdown reads "APIs and
client libraries" on first paint
- `/support/new?category=dashboard_bug` → "Dashboard bug"
(case-insensitive match)
- `/support/new?category=invalid_garbage` → falls back to "Select an
issue" placeholder, no crash
- `/support/new?subject=My%20issue&message=Details%20here` → subject and
message inputs are prefilled
- `/support/new?projectRef=<your-ref>&category=Problem` → both project
selector and category set, library selector appears
- With a prefilled URL, click the category dropdown and pick a different
option — the new value sticks (this is the path that surfaced the Radix
bug, want to confirm we didn't break user selection)
- DevTools console on first load should be clean — no React hydration
mismatch warning
### Support form submit (`useStateTransition` success + error branches)
- Submit a valid support form → green toast "Support request sent"
appears **once**, view swaps to the success screen, one `POST
/platform/feedback/send` in the network panel
- Block `POST /platform/feedback/send` in DevTools → submit → red error
toast appears **once** (not twice — if you see two toasts the relaxed
transition is firing more than it should), form stays editable with all
inputs preserved
- Unblock and submit again → success path runs cleanly
### Sidebar support form (same reducer + `useStateTransition`, separate
component)
- Open the support widget in the side nav (`SupportSidebarForm`)
- Repeat the success and error paths — should behave identically
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Fixed category selector to prevent selected values from being
unexpectedly cleared during form interactions.
* **Tests**
* Improved test reliability for modal field rendering and event handling
assertions.
* **Chores**
* Clarified internal comments for form initialization logic.
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45784)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
|
||
|
|
d8bb0ade65 |
feat(studio): add timezone picker to user dropdown (#45517)
## Problem The dashboard renders all timestamps in the browser's local timezone. When debugging app issues, users often want to see logs and timestamps in a different timezone (e.g. their app's deployment region) without changing their OS clock. ## Fix - New Timezone submenu in the user-avatar dropdown, sitting next to the existing Theme picker. Search-as-you-type combobox over the full IANA catalog plus an Auto detect option. - Selection persists in localStorage (`supabase-ui-timezone`) and survives `clearLocalStorage()`. No backend schema change. - New `lib/datetime.tsx` exposes pure timezone-aware formatters (`formatDateTime`, `formatDate`, `formatTime`, `formatFromNow`, `toTimezone`) plus a `TimezoneProvider` and matching React hooks (`useTimezone`, `useFormatDateTime`, ...). The pure functions take `tz` explicitly so they're easy to unit test (17 vitest cases covering DST transitions, multi-tz formatting, unix-micro/Date inputs, invalid-tz fallback). - The selected timezone propagates to every existing `<TimestampInfo>` in Studio via a new `TimestampInfoProvider` context exported from `ui-patterns`. No per-callsite changes needed for those ~20+ surfaces. - The `UnifiedLogs` date column migrates off `date-fns` to the new `useFormatDateTime` hook (the rest of the date-fns callers stay as-is, since they're either internal range math or non-display). - `ALL_TIMEZONES` (~600 entries) moves out of `PITR.constants.ts` into a shared `lib/constants/timezones.ts`. PITR keeps a re-export shim so its callers don't move. New `TIMEZONES_BY_IANA` dedupes the catalog by primary IANA name (the original list contains both PDT and PST rows for `America/Los_Angeles`, etc.) and `findTimezoneByIana` provides reverse lookup. - Telemetry: `timezone_picker_clicked` PostHog event with `previousTimezone`, `nextTimezone`, `isAutoDetected` properties. Notes for reviewers: - Bare `dayjs(x).format(...)` calls (~157 files) intentionally still render in browser-local time. Surfaces opt in by switching to the new wrappers, so this PR is the abstraction plus logs adoption; broader migration is a follow-up. - Two `// prettier-ignore` lines (`apps/studio/pages/_app.tsx`, `apps/studio/components/interfaces/UnifiedLogs/UnifiedLogs.fields.tsx`) work around a pre-existing local-tooling issue where `prettier-plugin-sql-cst` strips angle-bracket type arguments under certain conditions. Project's pinned prettier (3.8.1) does not strip; the issue surfaces with a globally-installed prettier. Worth tracking separately. - Hydration: `guessLocalTimezone()` and `useLocalStorageQuery` are client-only. Studio is mostly CSR via the Pages Router, but any SSR'd `<TimestampInfo>` may briefly render in the server's tz before client hydration. Existing behavior already had this mismatch with `.local()`; this PR does not regress it. - Backend timestamps round-tripped through query params and mutations stay UTC. The picker is display-only. ## How to test - Run `pnpm dev:studio`, sign in. - Open the user avatar dropdown (top right). Hover Timezone. - Search for "tokyo", pick `(UTC+09:00) Osaka, Sapporo, Tokyo`. - Open any project, navigate to Logs (e.g. `Project > Logs > Edge Functions`). Hover a log row's timestamp; the popover should show UTC, the chosen tz (`Asia/Tokyo`), and the relative time. Visible cell text should be in JST. - Visit any page that uses `<TimestampInfo>` (Database > Backups, Project Pause state, Edge Function details). Same tooltip should reflect Asia/Tokyo. - Refresh the page; timezone is still Asia/Tokyo. - Reopen the picker, choose Auto detect; timestamps revert to browser local. - Run `pnpm --filter studio test lib/datetime.test.ts`. 17 tests should pass. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Timezone selector added to the user menu with auto-detect and manual override * App-wide timezone provider and hooks plus a shared timezone catalog for consistent timezone-aware display * Timestamp components accept an optional timezone prop and respect user preference (persisted) * **Bug Fixes / Improvements** * Logs and timestamp displays now use the new timezone formatting hooks * **Tests** * Added comprehensive datetime and timezone catalog tests * **Telemetry** * Telemetry event added for timezone picker interactions <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
153f2619bc |
feat(studio): show expand affordance for large SQL result cells (#45589)
## Summary
- Adds a hover-revealed expand button to SQL result cells whose value is
unlikely to fit on one line (objects, arrays, strings >60 chars, or
strings with newlines). Clicking opens the existing `CellDetailPanel`
for that cell.
- Switches the expand state from a boolean tied to the selected cell to
a direct `{ column, value }` reference, so the context menu and the new
button both target the right-clicked / clicked cell.
- Extracts the per-cell renderer into its own `ResultCell` component to
keep `Results.tsx` digestible and the new affordance isolated.
- Covers the new logic with exhaustive `isLargeValue` unit tests and a
`ResultCell` component test (visibility, click, right-click).
Linear: [FE-3130](https://linear.app/supabase/issue/FE-3130)
## Test plan
- [x] Run a SQL query that returns mixed cell types (short strings, long
strings, JSON objects, arrays, nulls) and confirm the expand button
appears only on cells where content is likely truncated.
- [x] Hover a large cell and click the expand button — `CellDetailPanel`
opens with the correct column + value.
- [x] Right-click a large cell and choose "View cell content" — same
panel opens with the right cell.
- [x] Right-click a small cell and "Copy cell content" — clipboard
contains the raw value.
- [x] Resize a column wider than its content and confirm the button
still positions correctly.
- [x] `pnpm vitest` for `Results.utils.test.ts`, `Results.test.tsx`,
`ResultCell.test.tsx` — all green.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Enhanced SQL result cells with automatic detection and expansion
functionality for large values (exceeding 60 characters or containing
line breaks)
* Added expand button to view full cell content directly in results
* Integrated right-click context menu for cell content options
* Improved display of null values in query results
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
ee5d4a9314 |
chore: remove format param from audit log query (#45466)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Cleanup after shipping https://github.com/supabase/supabase/pull/45389, the backend is now defaulting to the new v2 `format`, and made `format` param optional. So this: - removes references to `v2` naming, as this is the only format - removes the `format` query param from the audit logs API calls ## What is the current behavior? Same audit log functionality shown in https://github.com/supabase/supabase/pull/45389 ## What is the new behavior? Functionally the same behavior for audit logs. - [x] Manual test in staging ## Additional context ⚠️ Will leave the `do-not-merge` tag on until: - [ ] backend `format` optional PR lands in production. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Consolidated audit log type definitions and updated internal API request formatting for audit endpoints across Account and Organization audit log components. No changes to user-facing functionality or audit log display. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
e540f9089f |
fix(studio): restore Safari table editor cell copy and context menu (#45353)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Bug fix. ## What is the current behavior? - Safari Table Editor cells fail to copy from a focused cell with `⌘C`. - Safari right-click can show the browser menu instead of the custom cell menu. - Copy can leave RDG's copied-cell fill behind. ## What is the new behavior? - Reuses the existing shared `copyToClipboard(value, onSuccess)` pattern, with the Safari clipboard fix inside that util. - Handles selected-cell `⌘C` in the RDG keydown path, preventing browser/RDG defaults and showing the success toast only after copy. - Replaces the row-level synthetic context-menu shim with RDG's `onCellContextMenu`, so we prevent Safari's browser menu at the source and select/focus the target cell. - Keeps the selected-cell outline while the controlled menu is open. ## Additional context - `RowRenderer` was only supporting the old context-menu shim; removing it is part of moving to RDG's cell event path. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **New Features** * Context menu now provides feedback with toast notifications when copying cells or rows. * Selected cells retain their visual styling when context menu is open. * **Bug Fixes** * Improved keyboard shortcut handling for copy functionality. * Enhanced clipboard error handling with user-friendly error messages. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Ali Waseem <waseema393@gmail.com> |
||
|
|
d666b950ff |
feat: update audit log schema & UI (#45389)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? - Update to the audit log schema (changes were already applied in staging) - Updates the org & project audit log page to reflect the changes to the schema - The schema should be agnostic to whether logs were emitted to logflare with the old & new schema format - the backend adjusts old logs to the new format. ## What is the current behavior? Currently, the frontend is parsing the legacy schema as the backend returns this by default. It also doesn't show some of these new fields yet. ## What is the new behavior? ### Org Audit Logs - Table View <img width="1810" height="1310" alt="CleanShot 2026-04-29 at 18 27 22" src="https://github.com/user-attachments/assets/47fec068-1ffa-4e52-bc46-3bffdef55adb" /> ### Org Audit Logs - Single log View <img width="1842" height="1494" alt="CleanShot 2026-04-29 at 18 27 37" src="https://github.com/user-attachments/assets/3cff3bdf-4a6a-4981-acaa-7f95bb3ae9cf" /> Note that the `Target` field is no longer there. We just show the `metadata` JSON. <img width="1842" height="1494" alt="CleanShot 2026-04-29 at 18 27 40" src="https://github.com/user-attachments/assets/d2e681f0-41a6-4bc7-a3d7-ec7e8101616c" /> ### Account (Profile) Audit Logs - Table View <img width="1810" height="1310" alt="CleanShot 2026-04-29 at 18 25 20" src="https://github.com/user-attachments/assets/c72e19df-9b82-4611-8889-7af463769550" /> ### Account (Profile) Audit Logs - Single log View <img width="1810" height="1310" alt="CleanShot 2026-04-29 at 18 25 32" src="https://github.com/user-attachments/assets/46f8d3b6-4f2f-4944-b891-431a93e5f3c3" /> ## Additional context ⚠️ currently leaving the `do not merge` tag on, until: - [x] I have verified it works in staging - [x] We've deployed the new schema to production <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Audit logs now use the v2 format with microsecond-accurate timestamps, improved ordering, and a revamped details panel showing clearer actor/action/request/project/org fields and fallback labels. * Page/header layout updated so audit logs render at top level with adjusted spacing. * **Refactor** * Shared sorting and filtering utilities added for consistent user/project filtering and non-mutating log sorting. * **Tests** * Added tests for timestamp conversion, sorting, filtering, and date-range formatting. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
7f5865872a |
Enforce noUnusedLocals and noUnusedParameters in tsconfig.json + fix all related issues (#45264)
## Context Enforce `noUnusedLocals` and `noUnusedParameters` in tsconfig.json + fix all related issues |
||
|
|
8454ec241d |
feat: add batch email org invites (#44832)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Feature ## What is the current behavior? When sending organization invites to multiple emails at once, the invitations API is called once for each email passed, passing a single email address in the `email` field. ## What is the new behavior? A single request is used when sending multiple organization invites at once, by using the new `emails` field. ## Additional context This builds further on https://github.com/supabase/supabase/pull/42637 ⚠️ Note: I'd like to merge this after getting the API changes in first: https://github.com/supabase/platform/pull/31561 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Bulk invite: paste comma-separated emails (parsed, trimmed, deduplicated, lowercased) and send as a single batched request; inputs are categorized into new, already-invited, and existing members. * SSO and project scope options included in invite payloads. * **Bug Fixes / API** * Invitation endpoint now accepts multiple emails; resend uses multi-email format. Invalid addresses are blocked, existing members are skipped with error toasts, and overall success is reported with the dialog closing after invite. * **Tests** * Added unit and UI tests covering parsing, categorization, payload building, validation limits, and invite flows. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com> |
||
|
|
1ab7251060 |
chore(studio): clarify partnered orgs and projects (#44328)
## What kind of change does this PR introduce? UI improvements. - Resolves DEPR-401 - Resolves DEPR-424 - Resolves DEPR-425 ## What is the current behaviour? Studio currently blurs two different concepts together: - `billing_partner` / `billing_via_partner`, which represent real billing ownership for marketplace-managed organisations such as AWS and Vercel - Stripe connection state, which is not actually partner billing in the same sense, but was previously being mocked through the same UI paths That made the Stripe work harder to reason about and left some local behaviour dependent on temporary overrides rather than the API shape we want to ship. ## What is the new behaviour? This PR separates those concerns while keeping the existing AWS and Vercel marketplace experience intact. - AWS and Vercel continue to use `billing_partner` / `billing_via_partner` for billing ownership, lockouts, and manage CTAs - Stripe display state now comes from `integration_source`, which lets Studio show Stripe-specific badges and alerts without treating Stripe as a billing partner - organisation-level partner UI is unified across AWS, Vercel, and Stripe, including the org banner, navbar icon treatment, and organisation cards - project-level Stripe UI now appears only when the project itself is marked as Stripe-connected, including the project switcher, project list surfaces, and a project-level banner - Stripe-connected organisations are no longer incorrectly blocked behind the AWS/Vercel-style billing management alerts for invoices, billing address, payment methods, or plan changes - banner dismissal is scoped to the relevant org/project and partner/integration state ## Review order Most of the diff size here is regression tests and generated types. The behavioural changes are concentrated in a smaller set of files. Recommended review order: 1. `integration_source` vs `billing_partner` data-model split and org/project query mapping 2. org-level UI: partner icon, org banner, org dropdown/card treatment 3. billing gating updates for Stripe vs AWS/Vercel 4. project-level Stripe UI: dropdown, list surfaces, banner 5. tests and generated types | Stripe Org(s) | | --- | | <img width="1024" height="759" alt="Organizations Supabase" src="https://github.com/user-attachments/assets/d0ef338c-3b41-4c6d-b3bd-f21a2c182840" /> | | Vercel Org(s) | | --- | | <img width="1024" height="759" alt="Organizations Supabase" src="https://github.com/user-attachments/assets/1dc57770-3f24-45ac-840f-34680555cde8" /> | | AWS Org(s) | | --- | | <img width="1024" height="759" alt="Organizations Supabase" src="https://github.com/user-attachments/assets/7847dad0-ee30-4a65-ab0b-b3b16af0d34f" /> | | Stripe Org, Non-Stripe Project | | --- | | <img width="1152" height="885" alt="Mallet Toolshed Supabase-1673E019-792C-462C-B6F8-C5DDB810B331" src="https://github.com/user-attachments/assets/556fbea3-b5ae-4f2f-96b9-6f66c6654e4a" /> | | Stripe Org, Stripe Project | | --- | | <img width="1152" height="885" alt="Hammer Toolshed Supabase-7E86C17C-561F-4221-BD16-EAFF7D41AAE0" src="https://github.com/user-attachments/assets/94f8daf6-0320-413e-8d56-59f9acaaea15" /> | | Vercel Org | | --- | | <img width="1024" height="759" alt="Projects Toolshed Supabase-A7891653-9366-4B99-89DD-789D70CD52E3" src="https://github.com/user-attachments/assets/c87ee6e8-4451-4866-a905-23a38b2593e3" /> | | AWS Org | | --- | | <img width="1024" height="759" alt="Projects Toolshed Supabase-58A43ECE-569E-4541-9463-346A90B02CFF" src="https://github.com/user-attachments/assets/9350a180-4d58-42a1-ad1a-95893c2e8b12" /> | This also removes the old Stripe mock override path in Studio so the frontend matches the intended API model more closely. ## ~~Dependencies~~ (merged!) This work depends on the private platform change that exposes `integration_source` on the relevant organisation and project payloads: - https://github.com/supabase/platform/pull/31874 _Update: now merged._ ## Local testing ### Stripe If you have the private `platform` repo checked out locally, make sure your local API returns `integration_source: 'stripe_projects'` consistently for the Stripe-linked org/project you are testing. Important responses: - `/platform/organizations` - `/platform/organizations/:slug/projects` - `/platform/projects/:ref` Verify: - org banner and org icon show the Stripe connected state - unopened and opened project switcher both show Stripe only for Stripe-linked projects - project cards / table rows show the Stripe chip only for Stripe-linked projects - the project-level Stripe banner appears across project surfaces - billing address, tax ID, invoices, payment methods, and plan changes remain editable in Studio for Stripe orgs ### Vercel Use a Vercel Marketplace org with real `billing_partner` / `billing_via_partner` values. Important org-level endpoints for local mocking in `platform`: - `/platform/organizations` - `/platform/organizations/:slug` - `/platform/organizations/:slug/billing/subscription` Project-level Vercel indicators still come from `/platform/integrations/:slug`, not `integration_source`. ### AWS Use an AWS Marketplace org with real `billing_partner` / `billing_via_partner` values. Important org-level endpoints for local mocking in `platform`: - `/platform/organizations` - `/platform/organizations/:slug` - `/platform/organizations/:slug/billing/subscription` AWS does not currently have a Stripe-like project-level indicator in these org/project payloads. ## Notes - `billing_partner` is no longer the right abstraction for the Stripe-connected case in this PR. It remains the source of truth for marketplace billing ownership, while Stripe currently uses `integration_source` as a connection/display signal. - I re-ran `pnpm api:codegen` while tightening this PR and kept only the generated type changes this branch actually depends on, to avoid unrelated API drift in the review. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Stripe Projects integration added for billing and project flows * Partner icons/badges shown across org and project lists, dropdowns, and rows * Dismissible, partner-specific marketplace/integration banners with contextual CTA behavior * Improved partner-billing detection to drive billing UI and invoice/plan availability * **Tests** * Extensive new test coverage for billing UI, partner-managed fallbacks, banners, icons, and related flows <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
e8df67d5d5 |
chore: migrate shortcuts to new hooks API (#44955)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Cleanup shortcuts with new hooks <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Centralized keyboard shortcut system for consistent shortcut behavior across the app and moved preference toggles to a unified registry. * **New Features** * Added explicit shortcuts for Command Menu, AI Assistant, Inline Editor, and result copy/download actions. * Hotkey preferences UI now renders dynamically from the centralized shortcut list. * **Tests** * Test helpers updated to include the command menu provider for accurate shortcut behavior in tests. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
1b1d05ff96 |
chore: upgrade vite to v8 and vitest to v4 (#44833)
Upgrade vite and vitest to their latest major versions across the
monorepo, along with related packages.
**Changed:**
- `vite` catalog: `^7.3.2` → `^8.0.8` (Rolldown replaces esbuild/Rollup)
- `vitest` catalog: `^3.2.0` → `^4.1.4`
- `@vitejs/plugin-react`: `^4.3.4` → `^6.0.1`
- `@vitest/coverage-v8`: `^3.2.0` → `^4.1.4`
- `@vitest/ui`: `^3.2.0` → `^4.1.4`
- `vite-tsconfig-paths`: `^4.3.2` / `^5.1.4` → `^6.1.1`
**Pinned to vite 7:**
- `apps/lite-studio` — `@react-router/dev` hasn't declared vite 8
support yet
- `blocks/vue` — Nuxt plugins (`vite-plugin-inspect`, `vite-dev-rpc`,
`vite-hot-client`, `vite-plugin-vue-tracer`) haven't declared vite 8
support yet
**Test fixes for vitest 4 breaking changes:**
- **`apps/studio/lib/api/snippets.utils.test.ts`** — Replaced
`vi.mock('fs/promises')` automock with an explicit factory. Vitest 4's
automocking doesn't create mock functions for getter-based exports on
Node built-ins, so `mockedFS.access.mockResolvedValue` etc. were
`undefined`.
- **`apps/studio/lib/api/self-hosted/functions/index.test.ts`** —
Changed `mockReturnValue` to `mockImplementation(function() { ... })`
for a constructor mock. Vitest 4 no longer allows `mockReturnValue` when
the mock is called with `new`.
- **`apps/studio/tests/pages/api/mcp/index.test.ts`** — Changed arrow
function to regular `function` in `mockImplementation` for
`StreamableHTTPServerTransport`. Arrow functions can't be constructors,
and vitest 4 now enforces this.
- **`packages/ui-patterns/vitest.setup.ts`** — Changed `ResizeObserver`
mock from arrow function to regular `function` for the same constructor
enforcement reason. This was crashing Radix popover rendering in jsdom.
## To test
- `pnpm test:studio` — all 226 test files should pass
- `pnpm --filter ui-patterns vitest run` — all 183 tests should pass
- `pnpm --filter www test -- --run` — all 19 tests should pass
- `pnpm --filter ui vitest run` — all tests should pass
- `pnpm --filter dev-tools vitest run` — all tests should pass
- `pnpm --filter ai-commands vitest run` — all tests should pass
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Standardized and updated development tooling versions and version
sources for consistent installs across the repo (Vite, Vitest,
vite-tsconfig-paths and related plugins/catalog entries).
* **Tests**
* Improved test mocks and typings (updated mock
factories/implementations and tightened spy/type assertions) to increase
test reliability and compatibility with updated tooling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
|
||
|
|
21584fe512 |
feat(studio): add backup cli instructions (#44621)
## Problem When a project is paused, in a failed state, or about to be deleted, users have no obvious way to take a logical backup of their data before proceeding. This is particularly risky at deletion time — once deleted, data is gone. ## Solution Introduce a new `LogicalBackupCliInstructions` component that surfaces ready-to-run `supabase db dump` commands pre-filled with the project's direct connection details. ### Where it appears | State | How | |---|---| | Project paused (restorable) | Inline in `ProjectPausedState` with a note to resume first | | Pause failed | Dialog via "Download backup" button when no backup is available | | Restore failed | Dialog via "Download backup" button when no backup is available | | Delete project modal | Inline in `DeleteProjectModal` for all plans | Not shown in `PauseDisabledState` (project paused 90+ days, compute stopped — `pg_dump` would fail anyway). ### What the component does - Fetches the project's direct connection settings via `useProjectSettingsV2Query` - Builds a connection URI with a `[YOUR-PASSWORD]` placeholder (password is never stored or displayed) - Shows three shell commands to dump roles, schema, and data separately — mirroring the [logical backup docs](https://supabase.com/docs/guides/platform/backups) - Optionally shows a **Reset database password** button (gated on `UPDATE projects` permission); shown in the paused state, hidden elsewhere via `showResetPassword={false}` - Includes inline guidance to percent-encode special characters in the password ### Shell safety The generated `--db-url` values are wrapped in single quotes to prevent shell metacharacter expansion when users paste and run the commands. `npx supabase login` is intentionally omitted — the `--db-url` flag authenticates directly against Postgres and does not require a Supabase account. ### Backup button behaviour in failed states The "Download backup" button in `PauseFailedState` and `RestoreFailedState` now always stays enabled: - **Backup available** — downloads immediately (unchanged) - **No backup / physical backups** — opens a dialog with CLI instructions instead of silently failing ## How to test **Delete project flow** 1. Open any project → Settings → General → Delete project 2. Verify the CLI backup section appears with the project's host, port, user, and db name pre-filled 3. Verify no Reset database password button is shown **Paused project** 1. Open a paused project (`ProjectPausedState`) — verify CLI instructions appear with the "Your project must be resumed before running these commands." note 2. Open a project paused for 90+ days (`PauseDisabledState`) — verify CLI instructions do not appear **Failed states** 1. Simulate a pause-failed or restore-failed state 2. If a downloadable backup exists — "Download backup" downloads it directly 3. Block the backup API or use a project with physical backups — "Download backup" should open the CLI instructions dialog **Error state** 1. Block the project settings API call (DevTools → Network → block request) 2. Verify an error message appears with a link to Database settings 3. Verify a loading skeleton shows while the request is in flight --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
cfce3c7efc |
refactor: save tax ID via customer update endpoint (#44728)
## Summary
- Consolidate tax ID saving into the `PUT
/organizations/{slug}/customer` endpoint instead of using a
separate `/tax-ids` endpoint
## Test plan
### Updating billing information
From the billing dashboard`/org/_/billing`:
- [ ] Manually test updating billing address + tax ID from org billing
settings - single API call should save both
- [ ] Clear the Tax ID in the org, save and assert that it has been
deleted
- [ ] Modify all the fields in the address form, including TaxID. Click
"Cancel" and assert that everything has returned to the previous values.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Billing address and tax ID updates are now sent in a single update
operation.
* Error messaging for billing updates consolidated into a single failure
notification.
* Tax ID handling clarified: you can clear tax ID explicitly or leave it
unchanged; omitting address fields no longer overwrites existing
address.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
||
|
|
205cbe7d26 | chore(studio}: enforce import order, remove bare import specifiers (#44585) | ||
|
|
fbb0770b47 |
fix(studio): AI assistant results make page unresponsive (#44578)
## Summary Fixes https://linear.app/supabase/issue/FE-2941 - Replaced per-cell `ContextMenu_Shadcn_` in SQL result tables with a single shared instance - Each Radix ContextMenu registers a `keydown` listener on `document` via `useEffect`. With 1000+ row result sets, this created thousands of document-level listeners. Chrome trace showed listeners growing from 21k to 347k, with every keystroke taking ~250ms (70k+ function calls per long task) - Fixed DataGrid not rendering in Firefox by using flex layout instead of `height: 100%` for sizing - Fixed double scrollbar in QueryBlock results by making the container a flex column and removing `overflow-auto` - Moved format utils into `Results.utils.ts` ## Test plan The `Results` component and `QueryBlock` are used in several places. Each should be verified: - [x] **AI Assistant** — Have the assistant run a query returning 1000+ rows. Verify the page stays responsive while typing and there is only a single scrollbar on the results table - [x] **AI Assistant (Firefox)** — Same as above but in Firefox. Verify the results table actually renders - [x] **SQL Editor results panel** — Run a query in the SQL Editor. Verify results render correctly with a single scrollbar in the utility panel - [x] **SQL Editor explain tab** — Run an EXPLAIN query. Verify explain results render - [x] **Editor Panel** (used in Table Editor SQL preview) — Verify results display correctly - [x] **Context menu** — Right-click a cell in any of the above and verify "Copy cell content" and "View cell content" still work ## Traces <img width="891" height="599" alt="image" src="https://github.com/user-attachments/assets/6e1b710b-ca9e-4748-9369-d03457d80206" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed context menu behavior so it opens at the cursor and is instantiated once. * Improved clipboard copy formatting for cell values; NULLs copy as empty and cells render as "NULL". * **Style** * Adjusted table layout and scrolling behavior to improve results container sizing. * **Tests** * Added tests for results rendering, context-menu behavior, and cell/clipboard formatting utilities. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
33c890f564 |
fix(studio): allow selecting columns for empty-cell NULL conversion on CSV import (#44515)
Bug fix / enhancement to an existing Studio import flow. ## What is the current behavior? Studio currently supports converting empty CSV cells to `NULL`, but the behavior applies across all imported columns. That makes it impossible to preserve empty strings in some columns while still treating empty cells as `NULL` in others. This follows up on the earlier CSV import fix discussed in #43281, which addressed the underlying issue reported in #43258. ## What is the new behavior? This PR updates the CSV import flow so users can choose exactly which imported columns should convert empty cells to `NULL`. The import flow now: - keeps all imported columns selected by default for backwards-compatible behavior - lets users narrow that selection down to specific columns - keeps preview behavior aligned with the actual inserted data ## Additional context I manually verified the full create-table-from-CSV flow locally in Studio, including saving the imported data and confirming that only the selected columns were persisted as `NULL` while other empty cells remained empty values. Formatting was checked with Prettier. A direct production build run was started locally, but the Next.js build process remained running without producing a final result during this session, so I am not claiming a completed local build verification here. ## Related issues - Fix follow-up for #43281 - Original issue: #43258 ## Summary by CodeRabbit ## Release Notes * **New Features** * Added a "Set empty cells as NULL" selector during spreadsheet import, allowing users to specify which columns should treat empty strings as NULL values rather than converting all nullable columns automatically. * Enhanced import preview to display NULL representation for selected empty-string columns. * **Tests** * Added test coverage for selective empty-string-to-NULL conversion behavior. --------- Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com> |
||
|
|
6563dc7998 |
refactor: authorize page (#44522)
Refactor authorize page to move Next.js dependencies into the page shell and have Next.js-agnostic code for the core logic. Add unit tests for authorize screen. ## Summary by CodeRabbit * **New Features** * New end-to-end API authorization UI: loading, error, invalid, approved, and main approval screens. * Organization selector with preselection, create-organization link, MCP warning, expiration handling, and approve/decline actions. * Improved page title handling via layout/head provider. * **Tests** * Added comprehensive component tests covering loading, error, approval flows, organization states, validation, and side effects. |
||
|
|
6be596ea34 |
feat: add user preference to enable queue operations (#44366)
## 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? - Remove queue operations from feature preview into settings - Refactor dashboard settings - Resolves DEPR-434 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Dashboard settings panel in Account preferences with toggles for Inline Editor and Queue Operations; “Dashboard” added to project Configuration. * **Removed** * Old Inline Editor settings UI and the Queue Operations feature-preview UI removed. * **Refactor** * Consolidated dashboard preferences into a single settings surface; banners and actions now navigate to preferences; account/preferences layouts and back-navigation behavior adjusted for platform vs self-hosted. * **Tests** * Added tests for settings UI, menu generation, redirects, and local-storage. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com> |
||
|
|
2335906d08 |
feat(read-replicas): bump up max read replicas for small instances (#44027)
INDATA-193 BACKEND: <https://github.com/supabase/platform/pull/30575> <img width="1199" height="1005" alt="Screenshot 2026-04-03 at 11 54 29" src="https://github.com/user-attachments/assets/38e9d676-449f-45c0-9e07-f273312a812f" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Consolidated read replica limit configuration to provide more consistent behavior across different compute tiers. * **Tests** * Added comprehensive test coverage for read replica eligibility checks and replica limit calculations based on compute tier. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
be3737d9d0 |
feat(billing): use Stripe AddressElement for billing address form (#44105)
### Summary This PR refactors the billing address form to use Stripe AddressElement on both the org billing page and the missing-address modal, adding Google Maps autocomplete and country-aware state/province inputs. ### Testing - Address element renders on org billing page, autocomplete works, and state/province options update per country. - Existing billing address data loads correctly into the form. - Need to verify this with invalid country/state as well. - Save enables only when the form is dirty after editing address or tax ID fields. - Cancel restores both address and tax ID to the original values. - Submitting with missing required address fields shows a validation toast. - Tax ID options are filtered by the selected billing country. - Tax-ID-only edits submit successfully without interacting with the address form. - Without billing write permission, address fields are read-only. - Update billing address modal behaves the same as the org billing page. - Address element appearance looks correct in both light and dark mode. - Payment method form remains unchanged and still uses floating labels. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Billing form now uses Stripe Address Element via Stripe Elements with an embedded custom font and theme-aware appearance; tax-ID entry remains separate. * **Bug Fixes** * Stronger address validation and submit gating, improved dirty-state tracking, explicit save confirmation and reset behavior, and clearer error toasts on update failures. * **Tests** * Expanded tests covering hook behavior, address element validation, submit gating, payloads, reset, and permission scenarios. * **Style** * Adjusted billing email form spacing/layout. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
55e0b34a18 |
fix(studio): add option to treat empty CSV cells as NULL on import (#43281)
When importing a CSV file, empty cells were always imported as empty strings with no way to import NULL values instead. This adds a "Treat empty cells as NULL" checkbox to the import configuration panel. When enabled, PapaParse's transform option converts empty strings to null before the data is parsed and previewed, so the imported rows correctly contain NULL rather than empty strings. Fixes #43258. ## What kind of change does this PR introduce? Bug fix ## What is the current behavior? Empty cells in a CSV file are always imported as empty strings with no way to import NULL values instead. Fixes #43258. ## What is the new behavior? "Treat empty cells as NULL" checkbox is added to the import configuration panel. When enabled, empty cells are imported as NULL instead of empty strings. Toggling the checkbox instantly re-parses the preview. ## Additional context The fix uses PapaParse's transform option to convert empty strings to null before parsing. Applies to both file uploads and pasted text. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com> |
||
|
|
c55908bbf0 |
chore(billing): make update billing address modal non-dismissable (#44127)
### Summary This PR removes the visible close button from the billing address required modal to make it non dismissable, since the majority of users on paid orgs are still not filling their billing address. The modal already prevents dismissal via Esc and outside/backdrop interaction, and this change preserves that behavior. The existing submit flow is unchanged, so the modal still closes after a successful billing address update. ### Manual testing: 1. Open Studio in a state where the billing address required modal appears. 2. Confirm the top-right close button is no longer shown. 3. Press Esc and verify the modal remains open. 4. Click outside the modal / on the backdrop and verify the modal remains open. 5. Submit a valid billing address and verify the modal closes after a successful save. For testing whether an update successfully closes the modal, you can: - You can create a free org without a billing address - You will need to tweak this logic (on the frontend) ``` const shouldShow = Boolean( IS_PLATFORM && // showMissingAddressModal && org && // org.plan.id !== 'free' && org.organization_missing_address && !org.billing_partner && permissionsLoaded && canBillingWrite ) ``` - Tweak the backend logic which computes `organization_missing_address` to exclude free orgs --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
98b1b79909 |
Chore/shift manual queries into pg meta 04 (#43956)
## Context Shifts all remaining dashboard queries into pg-meta so that we centralize all manually written queries in one place Having them in packages/pg-meta also allows us to write tests for them ## To test Just needs a smoke test on - Role Impersonation - Lints - Data API - Database - Enumerated Types - Integrations - Foreign Data Wrappers - Vault |
||
|
|
5d942e2a46 |
refactor(billing): allow GB VAT tax IDs for Isle of Man customers (#43640)
### Summary This PR adds support for Isle of Man customers to use GB VAT tax IDs. Isle of Man uses the UK VAT system, so Orb requires country: 'GB' for validation - but the billing address country is IM. - Adds an IM VAT entry to `TAX_IDS` with a new `taxCountryIso2` override field, so the UI shows "IM VAT" while sending country: 'GB' to Orb - Introduces `getEffectiveTaxCountry()` to resolve the correct country code for Orb - Introduces `resolveStoredTaxId()` to map stored Orb data back to the correct UI entry, using billing address country to disambiguate IM vs GB - Updates all three billing forms to use these utilities: Billing Settings page, Add Payment Method modal and Update Billing Address modal ### Testing #### Automated tests I've added unit tests in this PR #### Manual tests You can use the following country/city/postal code combinations to test: - Isle of Man, Douglas, IM1 2LE - United Kingdom, Crumlin, BT29 4AA **Billing Settings page** - Select Isle of Man as billing country → tax ID dropdown shows "Isle of Man - IM VAT" - Select United Kingdom as billing country → tax ID dropdown shows "United Kingdom - UK VAT" / "United Kingdom - GB VAT" (not "IM VAT") - Select IM VAT, enter a valid GB VAT number, save → check network tab, Orb receives country: 'GB' - Reload page for an IM customer with existing tax ID → "IM VAT" is pre-selected (not "UK VAT") - Reload page for a GB customer with existing tax ID → "UK VAT" is pre-selected (no regression) - Change country from IM to GB → available tax IDs update, IM VAT no longer shown **Add Payment Method modal** - Open modal for an IM customer with existing tax ID → "IM VAT" is pre-selected - Check "I'm purchasing as a business", select Isle of Man in Stripe address → tax ID dropdown shows "IM VAT" - Check "I'm purchasing as a business", select United Kingdom in Stripe address → tax ID dropdown shows "UK VAT" / "GB VAT" - Submit with IM VAT → check network tab, tax ID is saved with country: 'GB' - Open modal for a GB customer → no regression, "UK VAT" shown as before **Update Billing Address modal** Appears for paid orgs missing a billing address - Open modal for an IM customer with existing tax ID → "IM VAT" is pre-selected - Open modal for a GB customer with existing tax ID → "UK VAT" is pre-selected - Fill in IM address + IM VAT and save → saves correctly, modal closes --------- Co-authored-by: Ignacio Dobronich <ignacio@dobronich.com> |
||
|
|
62426253c3 |
fix: pass exposedSchemas to getLints in MCP advisor operations (#43790)
## Summary - MCP `getSecurityAdvisors` and `getPerformanceAdvisors` now pass `exposedSchemas` to `getLints`, fixing empty advisor results in local/self-hosted environments - Extracts `DEFAULT_EXPOSED_SCHEMAS` constant shared between the MCP handler and the `run-lints` API route (cc @joshenlim related https://github.com/supabase/supabase/pull/40043) - Adds unit tests for `enrichLintsQuery` and the MCP advisor operations ## The bug The MCP advisor tools (`get_advisors`) return empty arrays (`[]`) for **all** scenarios when running locally via `supabase start`. No security or performance advisors are surfaced, even when the database has clear issues (e.g., tables with no RLS). ### Root cause In `lib/api/self-hosted/mcp.ts`, both `getSecurityAdvisors` and `getPerformanceAdvisors` call `getLints({ headers })` **without passing `exposedSchemas`**: ```typescript // Before (mcp.ts:131) const { data, error } = await getLints({ headers }) ``` When `exposedSchemas` is `undefined`, `enrichLintsQuery` in `lints.ts` skips the `SET LOCAL pgrst.db_schemas = '...'` SQL statement: ```typescript // lints.ts:23 ${!!exposedSchemas ? `set local pgrst.db_schemas = '${exposedSchemas}';` : ''} ``` Without this GUC being set, the splinter SQL queries filter results using `current_setting('pgrst.db_schemas', 't')` — which returns an empty string in local environments. Every schema-filtered lint matches no schemas and returns zero rows. ### Why this only affects local/self-hosted environments In **hosted Supabase**, PostgREST sets the `pgrst.db_schemas` GUC on its own database connections based on the project's API configuration. The Studio MCP server in production reads the same project configuration, so the GUC is already available. **Locally**, PostgREST runs in a separate Docker container and only sets this GUC on _its own_ connections. Studio connects directly to PostgreSQL (bypassing PostgREST), so `current_setting('pgrst.db_schemas', 't')` returns `''`. The HTTP API endpoint (`/api/platform/.../run-lints`) already worked because `run-lints.ts` passes `exposedSchemas: 'public, storage'` — this parameter was simply never added to the MCP code path. ## How we verified the fix ### 1. Tests written to fail against the previous code We wrote two test files that target the exact bug: **`tests/unit/lints/enrichLintsQuery.test.ts`** — validates the SQL generation: - Confirms `SET LOCAL pgrst.db_schemas` is included when `exposedSchemas` is provided - Confirms it's omitted when `undefined` or empty (documenting current behavior) **`tests/unit/lints/mcp-advisors.test.ts`** — validates the MCP operations: - Asserts `getSecurityAdvisors` passes `exposedSchemas` to `getLints` - Asserts `getPerformanceAdvisors` passes `exposedSchemas` to `getLints` - Asserts the value matches `DEFAULT_EXPOSED_SCHEMAS` - Verifies SECURITY/PERFORMANCE category filtering still works Before the fix, the two `exposedSchemas` assertions failed: ``` FAIL getSecurityAdvisors should pass exposedSchemas to getLints → expected { Object (headers) } to have property "exposedSchemas" FAIL getPerformanceAdvisors should pass exposedSchemas to getLints → expected { Object (headers) } to have property "exposedSchemas" ``` ### 2. Fix applied, all tests pass After adding `exposedSchemas: DEFAULT_EXPOSED_SCHEMAS` to both MCP operations, all 14 tests pass (9 new + 5 existing MCP tests). ## Test plan run `supabase start`, create a table without RLS, call `get_advisors` via MCP — should return `rls_disabled_in_public` lint --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
83592b1932 |
feat(billing): show billing address modal for paid orgs with missing address (#43480)
### Summary This PR adds a dismissable modal that prompts paid org users to fill in their billing address. We need billing addresses for tax compliance and the existing banner hasn't been as effective (~10k orgs still missing). The modal shows on page load when all of these are true: - ConfigCat flag `enableBillingAddressModal` is on - Org is on a paid plan (not free) - Org does not have billing address set - Org is not partner-managed - User has BILLING_WRITE permission on stripe.customer The modal can be dismissed via the close button, but re-opens on every page navigation. Once the user saves a valid address, the organizations query is invalidated and organization_missing_address flips to false - the modal stops appearing permanently. <img width="1256" height="703" alt="Screenshot 2026-03-05 at 4 22 11 PM" src="https://github.com/user-attachments/assets/57e7d1b8-b3b6-4366-ad23-60910a0defe8" /> ### Testing #### Automated Tests I've added unit tests in this PR #### Manual testing Manual test cases: - Free org - modal does not appear - Partner-managed org - modal does not appear - User with "developer role" modal does not appear - Configcat Flag disabled - modal does not appear - Dismiss modal, navigate to another page - modal re-opens - Fill form and save - modal closes and does not reappear - API failure loading billing data - shows error state with Retry button --------- Co-authored-by: Ignacio Dobronich <ignacio@dobronich.com> |
||
|
|
173b725c93 |
fix: add old homepage to self hosted w/ unit tests (#43705)
## 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? - Bring back the old home page for self hosted, because the new one does not work for self hosted users - Unit tests to catch this in the future |
||
|
|
b997b7fb13 |
feat(studio): org project branch mobile selector (#43238)
- add new [OrgSelector](https://github.com/supabase/supabase/pull/43238/changes#diff-214b339101a9c06864ea2755ac7246eb4c971ce74c5d3169b1385a28ee1d4227) and [ProjectBranchSelector](https://github.com/supabase/supabase/pull/43238/changes#diff-82d25c128c306b61bea7481026f58f670a229874f23ca3a1a1d78ddeabde21e0) components to the mobile navigation, replacing the previous which took up a lot of horizontal space - org/project/branch dropdowns now open up in the bottom MobileSheetNav for a better mobile ux - desktop nav remains unchanged |
||
|
|
2fc591887e |
fix: missing org id lint error (#43642)
Fixes the `organization_missing_tax_id` missing in type error |
||
|
|
4fdab665a8 |
chore: Fix vulnerable packages (#43634)
Fix bunch of vulnerable dependencies: - https://github.com/supabase/supabase/security/dependabot/3027 - https://github.com/supabase/supabase/security/dependabot/3038 - https://github.com/supabase/supabase/security/dependabot/3058 - https://github.com/supabase/supabase/security/dependabot/3064 - https://github.com/supabase/supabase/security/dependabot/3065 - https://github.com/supabase/supabase/security/dependabot/3085 - https://github.com/supabase/supabase/security/dependabot/3095 |