feat(custom-blocks): org-member visibility, workspace-admin-gated management#5507
Conversation
…page The Custom blocks page lives in the Enterprise nav section, which the sidebar filter hides unless the user is an org admin/owner. But the server authz for managing custom blocks is source-workspace admin (hasWorkspaceAdminAccess), not org admin — so a workspace admin who could manage a block via the API couldn't even reach the page. Add an `allowNonOrgAdmin` nav flag that exempts an item from the org admin/owner requirement (the plan/hosted entitlement still applies; the page enforces its own per-resource authz), and set it on custom-blocks. Other Enterprise items (access control, audit logs, SSO, data retention/drains, whitelabeling) stay org-admin-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ddpeoz81CSqYQ73Dzf7yo
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview The Enterprise settings sidebar no longer requires org admin/owner for Custom blocks via a new The list API and client contract now include each block’s source Reviewed by Cursor Bugbot for commit 414375f. Bugbot is set up for automated code reviews on this repo. Configure here. |
Greptile SummaryThis PR decouples visibility from management for org-wide custom blocks: any enterprise org member can now browse the Custom blocks settings page (via a new
Confidence Score: 5/5Safe to merge. All write paths are fail-closed and the server-side authz is unchanged; the UI changes only mirror existing server checks. The three-tier authz model (visibility → create → manage) is correctly implemented end to end. The No files require special attention. The most complex change is in Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[User navigates to Settings] --> B{Enterprise plan?}
B -- No --> C[Nav item hidden]
B -- Yes --> D[Custom Blocks nav item visible\nvia allowNonOrgAdmin]
D --> E[Custom Blocks page loads]
E --> F{canManage:\nfeature flag + enterprise?}
F -- No --> G[Show Enterprise plan required message]
F -- Yes --> H[Show block list]
H --> I{canCreate:\nadmin of any org workspace?}
I -- Yes --> J[Show Create block button]
I -- No --> K[Hide Create block button\nread-only list view]
H --> L[User clicks a block]
L --> M{canManageBlock:\nadmin of block's SOURCE workspace?}
M -- Yes --> N[Full edit view\nSave / Discard / Delete]
M -- No --> O[Read-only view\nall fields disabled\nno action buttons]
J --> P[Create block flow\nWorkspace picker shows\nonly admin workspaces]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[User navigates to Settings] --> B{Enterprise plan?}
B -- No --> C[Nav item hidden]
B -- Yes --> D[Custom Blocks nav item visible\nvia allowNonOrgAdmin]
D --> E[Custom Blocks page loads]
E --> F{canManage:\nfeature flag + enterprise?}
F -- No --> G[Show Enterprise plan required message]
F -- Yes --> H[Show block list]
H --> I{canCreate:\nadmin of any org workspace?}
I -- Yes --> J[Show Create block button]
I -- No --> K[Hide Create block button\nread-only list view]
H --> L[User clicks a block]
L --> M{canManageBlock:\nadmin of block's SOURCE workspace?}
M -- Yes --> N[Full edit view\nSave / Discard / Delete]
M -- No --> O[Read-only view\nall fields disabled\nno action buttons]
J --> P[Create block flow\nWorkspace picker shows\nonly admin workspaces]
Reviews (3): Last reviewed commit: "fix(custom-blocks): don't flag create as..." | Re-trigger Greptile |
…admin Split visibility from management to match the org-wide nature of custom blocks: - View: any org member (the nav item is now plan-gated, not org-admin). - Create: the "Create block" action shows only when the user is admin of a workspace in the current org, matching the publish route's source-workspace admin authz. - Source picker: lists only workspaces the user administers (in the current org); the default selection snaps to an eligible workspace when the current one isn't one they can publish from. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ddpeoz81CSqYQ73Dzf7yo
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit cd25970. Configure here.
- Add the source workspaceId to the block wire type and gate the detail view on it: a viewer who isn't an admin of the block's source workspace gets a read-only view — no Save/Discard, no Delete, all fields disabled. Matches the server authz (edit/delete require source-workspace admin), so the UI no longer dangles buttons that 403. - SettingsResourceRow: add an opt-in `iconFill` so uploaded image icons fill the tile edge-to-edge instead of clamping to 20px; glyph svgs still normalize to 20px. Custom blocks list opts in. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ddpeoz81CSqYQ73Dzf7yo
The publish path builds a CustomBlockWithInputs literal; it was missing the workspaceId field added to the interface, breaking the type check. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ddpeoz81CSqYQ73Dzf7yo
|
@greptile review |
The create dirty-check compared selectedWorkspaceId against the URL workspace, but the source picker now auto-snaps to the first workspace the user can publish from — which may differ. Compare against that eligible default so opening/discarding the create flow doesn't show a false unsaved-changes state. (Bugbot) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ddpeoz81CSqYQ73Dzf7yo
|
@greptile review |

Summary
Custom blocks are org-wide shared resources, so visibility and management are decoupled — and management gates match the server's source-workspace-admin authz.
Visibility (any org member):
allowNonOrgAdminnav flag exempts an item from the org-admin requirementrequiresTeam/requiresEnterpriseotherwise impose (plan + hosted entitlement still applies). Set only oncustom-blocks; other Enterprise items stay org-admin-only.Create (workspace admin):
canAdmincheck.Manage an existing block (source-workspace admin):
workspaceIdto the block wire type and gated the detail view on it. A viewer who isn't an admin of the block's source workspace gets a read-only view — no Save/Discard, no Delete, all fields disabled. Mirrors the server authz (edit/delete requirehasWorkspaceAdminAccess), so the UI no longer dangles buttons that 403.Polish:
SettingsResourceRowgains an opt-iniconFillso uploaded image icons fill the tile edge-to-edge instead of clamping to 20px (glyph svgs still normalize). Custom blocks list opts in.Files
settings/navigation.ts,settings-sidebar.tsx—allowNonOrgAdminflag + filter.ee/custom-blocks/components/custom-blocks.tsx—canCreategate +iconFill.ee/custom-blocks/components/custom-block-detail.tsx— picker admin-filter + read-onlycanManageBlockgate.lib/workflows/custom-blocks/operations.ts,lib/api/contracts/custom-blocks.ts,app/api/custom-blocks/route.ts— sourceworkspaceIdon the wire.settings/components/settings-resource-row/settings-resource-row.tsx—iconFillprop.Type of Change
Testing
biome check+tsc --noEmitclean on all changed files; custom-block test suites pass.Checklist
🤖 Generated with Claude Code