Skip to content

feat(workspaces): bypass personal workspace limit for platform admins#4463

Open
TheodoreSpeaks wants to merge 2 commits intostagingfrom
feat/admin-unlimited-workspaces
Open

feat(workspaces): bypass personal workspace limit for platform admins#4463
TheodoreSpeaks wants to merge 2 commits intostagingfrom
feat/admin-unlimited-workspaces

Conversation

@TheodoreSpeaks
Copy link
Copy Markdown
Collaborator

Summary

  • Platform admins (user.role === 'admin') bypass the per-plan personal workspace cap
  • Added isPlatformAdmin check in getWorkspaceCreationPolicy; UI auto-respects via existing canCreate gate
  • Tests cover admin bypass and continued enforcement for non-admins

Type of Change

  • Improvement

Testing

  • bun run lint — clean
  • bun run check:api-validation:strict — passed
  • bunx vitest run lib/workspaces — 83 passed (19 in policy.test.ts)

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link
Copy Markdown

vercel Bot commented May 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped May 6, 2026 2:12am

Request Review

@cursor
Copy link
Copy Markdown

cursor Bot commented May 6, 2026

PR Summary

Medium Risk
Changes workspace-creation authorization/entitlement logic by introducing a platform-admin bypass, which could affect billing enforcement and access control if misclassified roles occur. Scope is contained to getWorkspaceCreationPolicy with added test coverage.

Overview
Adds a platform-admin (user.role === 'admin') bypass in getWorkspaceCreationPolicy: admins can always create personal workspaces with no per-plan cap and without calling getHighestPrioritySubscription.

When an admin is in an org context, the policy now keeps them in ORGANIZATION mode only if they are an org owner/admin; otherwise it falls back to personal mode. Tests were updated to account for the extra DB lookup and expanded to cover admin bypass behavior plus continued enforcement for non-admin users.

Reviewed by Cursor Bugbot for commit 673ae39. Bugbot is set up for automated code reviews on this repo. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 6, 2026

Greptile Summary

This PR adds a platform admin bypass in getWorkspaceCreationPolicy so users with role === 'admin' skip the per-plan personal workspace cap and always get canCreate: true with maxWorkspaces: null. Existing tests were updated to account for the new isPlatformAdmin DB call, and two new test cases cover the admin bypass and continued enforcement for non-admins.

  • A new isPlatformAdmin helper issues a SELECT on the user table on every call that reaches the personal-workspace path when billing is enabled, adding one extra DB round-trip for all non-admin users as a side effect.
  • The admin bypass is inserted after the org-subscription block, so a platform admin with activeOrganizationId set whose org lacks a team/enterprise subscription silently receives personal workspace policy (organizationId: null) rather than an error or an explicit signal — a corner case with no test coverage.

Confidence Score: 4/5

Safe 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

Filename Overview
apps/sim/lib/workspaces/policy.ts Adds isPlatformAdmin helper (single DB query) and a bypass branch before the subscription check; logic is correct for the happy path but adds a DB round-trip for every non-admin user and has an untested edge case where an admin with activeOrganizationId silently falls back to personal workspace mode.
apps/sim/lib/workspaces/policy.test.ts Correctly updates existing mock arrays to account for the new isPlatformAdmin DB call; adds two new test cases for admin bypass and non-admin enforcement. Missing coverage for a platform admin with activeOrganizationId set and no valid org subscription.

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]
Loading

Reviews (1): Last reviewed commit: "feat(workspaces): bypass personal worksp..." | Re-trigger Greptile

Comment on lines +279 to +290
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,
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 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.

Comment on lines +279 to +290
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,
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant