feat(workspaces): bypass personal workspace limit for platform admins#4463
feat(workspaces): bypass personal workspace limit for platform admins#4463TheodoreSpeaks wants to merge 2 commits intostagingfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview When an admin is in an org context, the policy now keeps them in Reviewed by Cursor Bugbot for commit 673ae39. Bugbot is set up for automated code reviews on this repo. Configure here. |
Greptile SummaryThis PR adds a platform admin bypass in
Confidence Score: 4/5Safe to merge; the admin bypass is correctly isolated behind billing and does not affect org or billing-disabled paths. The core logic is straightforward and well-tested for the primary cases. The two notable concerns — the unconditional extra DB query for non-admin users and the untested silent fall-back to personal mode when an admin has an active org context without a valid subscription — are quality and coverage gaps rather than outright breakage of the new or existing paths. apps/sim/lib/workspaces/policy.ts and its test file deserve a second look around the activeOrganizationId + isPlatformAdmin interaction. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[getWorkspaceCreationPolicy] --> B{activeOrganizationId\nset and no orgRole?}
B -- Yes --> C[Return 403\nOrg context blocked]
B -- No --> D{isBillingEnabled?}
D -- No --> E[Return unlimited\npersonal or org]
D -- Yes --> F{organizationId + orgRole\nwith valid subscription?}
F -- Yes --> G{orgRole is\nowner or admin?}
G -- Yes --> H[Return org policy\ncanCreate: true]
G -- No --> I[Return 403\nOrg role insufficient]
F -- No --> J{isPlatformAdmin?\nNEW DB query}
J -- Yes --> K[Return personal policy\ncanCreate: true\nmaxWorkspaces: null]
J -- No --> L[getHighestPrioritySubscription]
L --> M{currentWorkspaceCount\n>= maxWorkspaces?}
M -- Yes --> N[Return 403\nPlan limit reached]
M -- No --> O[Return personal policy\ncanCreate: true]
Reviews (1): Last reviewed commit: "feat(workspaces): bypass personal worksp..." | Re-trigger Greptile |
| if (await isPlatformAdmin(userId)) { | ||
| return { | ||
| canCreate: true, | ||
| workspaceMode: WORKSPACE_MODE.PERSONAL, | ||
| organizationId: null, | ||
| billedAccountUserId: userId, | ||
| maxWorkspaces: null, | ||
| currentWorkspaceCount: await countNonOrganizationOwnedWorkspaces(userId), | ||
| reason: null, | ||
| status: 200, | ||
| } | ||
| } |
There was a problem hiding this comment.
Extra DB query for every non-admin personal workspace check
isPlatformAdmin issues a full SELECT round-trip for every call that reaches that branch — i.e., every billing-enabled personal workspace policy check where the user is not in an active org with a team/enterprise subscription. Since admins are rare, the vast majority of these queries will return role: 'user' and the result is discarded immediately before the subscription lookup begins. The admin bypass could be guarded with an early-exit check from a value already in scope (e.g. a cached session attribute or a flag passed in by the caller), avoiding the extra query for the common case.
| if (await isPlatformAdmin(userId)) { | ||
| return { | ||
| canCreate: true, | ||
| workspaceMode: WORKSPACE_MODE.PERSONAL, | ||
| organizationId: null, | ||
| billedAccountUserId: userId, | ||
| maxWorkspaces: null, | ||
| currentWorkspaceCount: await countNonOrganizationOwnedWorkspaces(userId), | ||
| reason: null, | ||
| status: 200, | ||
| } | ||
| } |
There was a problem hiding this comment.
Platform admin in an active org context falls back to personal mode silently
When a platform admin calls getWorkspaceCreationPolicy with activeOrganizationId set (e.g. they are an org member but the org lacks a team/enterprise subscription), the code falls through the org-subscription block (lines 243–277), hits isPlatformAdmin, and returns workspaceMode: WORKSPACE_MODE.PERSONAL with organizationId: null. The caller asked for org context but receives a personal policy — no error, no signal, just a silent mode downgrade. This could lead to a workspace being created as personal when the admin intended to create it under the org. There is currently no test covering this path.
Summary
user.role === 'admin') bypass the per-plan personal workspace capisPlatformAdmincheck ingetWorkspaceCreationPolicy; UI auto-respects via existingcanCreategateType of Change
Testing
bun run lint— cleanbun run check:api-validation:strict— passedbunx vitest run lib/workspaces— 83 passed (19 in policy.test.ts)Checklist