Conversation
… around when you change the current selection
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…and-tenant-dropdowns
And update the button copy because I do like the more explicit version
…and-tenant-dropdowns
|
📝 Documentation updates detected! New suggestion: Update multi-tenancy instructions for standalone organization/tenant dropdowns Tip: Use Vale? Add your vale.ini when setting up your Docs Collection. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix prepared fixes for both issues found in the latest run.
- ✅ Fixed: Organization select crashes when org has no tenants
- Filtered organizations with empty tenants arrays from dropdown to prevent crash when clicking organizations with all archived tenants.
- ✅ Fixed: Throwing lookup breaks isTenantArchivedInOrg for archived tenants
- Changed getOrganizationForTenant to return undefined instead of throwing for missing tenants, fixing isTenantArchivedInOrg graceful handling.
Or push these changes by commenting:
@cursor push e01cabaaeb
Preview (e01cabaaeb)
diff --git a/frontend/app/src/components/v1/molecules/nav-bar/organization-selector.tsx b/frontend/app/src/components/v1/molecules/nav-bar/organization-selector.tsx
--- a/frontend/app/src/components/v1/molecules/nav-bar/organization-selector.tsx
+++ b/frontend/app/src/components/v1/molecules/nav-bar/organization-selector.tsx
@@ -54,12 +54,14 @@
if (!organizations) {
return [];
}
- return [...organizations].sort((a, b) => {
- if (a.isOwner !== b.isOwner) {
- return a.isOwner ? -1 : 1;
- }
- return a.name.localeCompare(b.name, undefined, { sensitivity: 'base' });
- });
+ return [...organizations]
+ .filter((org) => org.tenants.length > 0)
+ .sort((a, b) => {
+ if (a.isOwner !== b.isOwner) {
+ return a.isOwner ? -1 : 1;
+ }
+ return a.name.localeCompare(b.name, undefined, { sensitivity: 'base' });
+ });
}, [organizations]);
const handleOrgSelect = useCallback(
diff --git a/frontend/app/src/providers/user-universe.tsx b/frontend/app/src/providers/user-universe.tsx
--- a/frontend/app/src/providers/user-universe.tsx
+++ b/frontend/app/src/providers/user-universe.tsx
@@ -30,7 +30,9 @@
isLoaded: true;
organizations: OrganizationForUserList['rows'];
tenantMemberships: TenantMember[];
- getOrganizationForTenant: (tenantId: string) => OrganizationForUser;
+ getOrganizationForTenant: (
+ tenantId: string,
+ ) => OrganizationForUser | undefined;
getTenantWithTenantId: (tenantId: string) => Tenant;
}
| {
@@ -225,7 +227,9 @@
);
const getOrganizationForTenant = (tenantId: string) => {
const organization = tenantIdToOrganization.get(tenantId);
- invariant(organization);
+ if (!organization) {
+ return undefined;
+ }
return organization;
};This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
| setOpen(false); | ||
| }, | ||
| [isUniverseLoaded, getTenantWithTenantId, setTenant], | ||
| ); |
There was a problem hiding this comment.
Organization select crashes when org has no tenants
Medium Severity
handleOrgSelect calls org.tenants.at(0) and then invariant(firstTenant), which throws if the array is empty. Since the user universe query filters archived tenants from organization.tenants, an organization whose tenants are all archived will have an empty tenants array. That org still appears in sortedOrgs (no filtering step removes zero-tenant orgs), so clicking it in the dropdown causes a runtime crash.
Additional Locations (1)
| isUserUniverseLoaded, | ||
| isCloudEnabled, | ||
| ], | ||
| ); |
There was a problem hiding this comment.
Throwing lookup breaks isTenantArchivedInOrg for archived tenants
Medium Severity
getOrganizationForTenant from the user universe now uses invariant and throws when a tenant ID isn't in the map, whereas the old implementation gracefully returned undefined. The isTenantArchivedInOrg function in use-organizations.ts calls getOrganizationForTenant with potentially archived tenant IDs and checks for a falsy return (if (!orgForTenant)). Since archived tenants are now filtered from the map, looking up an archived tenant crashes instead of returning undefined. This breaks tenant-forbidden.tsx line 140, which is the error page shown when access is denied.



I'll leave this as a draft PR until my other PRs get merged with their other changes to some of the organization UI, since I don't want to touch the Cypress tests in this branch until that gets merged in, and there may be other conflicts.
Description
Standalone organization/tenant dropdowns, ala Vercel.
Other changes along the way:
getOrganizationForTenantFixes # (issue)
Type of change
What's Changed
Note
Medium Risk
Medium risk because it changes the API contract/codegen to require
TenantMember.tenant(potentially breaking clients that relied on it being optional) and refactors tenant/org selection plus user-universe data shaping, which can affect navigation and tenant scoping across the app.Overview
Introduces standalone organization and tenant dropdowns in the top nav (Vercel-style):
OrganizationSelectornow selects an org (and switches to its first tenant) while a newTenantSelectorhandles tenant switching and “New Tenant”; the old combinedtenant-switcherUI is removed.Updates the user universe provider to precompute constant-time lookups (
getOrganizationForTenant,getTenantWithTenantId), sort tenants/org tenants by name, and filter out archived tenants, and adjustsuse-organizationsto delegate org lookup to this provider.Makes
TenantMember.tenantrequired across the OpenAPI schema and regenerated clients (Go/TS/Python/Ruby) and tweaks related transformers; also includes regenerated Ruby REST SDK additions for durable-task/task APIs (e.g.,v1_durable_task_branch,v1_task_restore) and new task “running/evicted” fields, plus small Cypress selector tweaks and enablingexperimentalRunAllSpecs.Written by Cursor Bugbot for commit 46fd4d1. This will update automatically on new commits. Configure here.