feat(permissions): client-side RBAC capability gating across the UI#3241
Open
feat(permissions): client-side RBAC capability gating across the UI#3241
Conversation
Introduces high-level permission capabilities mapped to tool names, a new useMemberPermissions hook, and a refreshed org-role-detail UI with grouped capability toggles and settings layout integration. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Split ai-providers into view (model listing) and manage (key ops), move tags to Organization, collapse registry browse and publish into a single "Manage registry" capability, drop threads:manage (threads are a core chat action, not a manageable permission), move connections:sql to Developer, and add vm:access for previously ungated VM tools. Also widens spacing in the org permissions tab (gap-6 to gap-10). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove view-only permission capabilities that all org members should have by default (connections, agents, automations, AI providers, object storage, VM previews). Replace ctx.access.check() with ctx.access.grant() in the relevant tool handlers so any authenticated member can use them regardless of their role's permission set. Also fix CI failures: delete unused use-member-permissions.ts hook (which referenced a non-existent KEYS.myRolePermissions), remove export from PERMISSION_CAPABILITIES (internal use only), and delete dead getPermissionOptions function. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… defineTool Add basicUsage?: boolean to ToolBinder. When set, the execute wrapper in defineTool automatically grants access before the handler runs, removing the need for explicit ctx.access.grant() calls in individual handlers. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add basicUsage flag to PermissionCapability. Capabilities marked basicUsage are automatically granted to all authenticated org members via BASIC_USAGE_TOOLS set checked in AccessControl.checkResource(). Tool handlers uniformly call ctx.access.check() — the registry is the single source of truth. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…stry capability Replace per-capability basicUsage flag with a single 'basic-usage' capability listing all tools all org members can access by default. Hidden from the role editor UI via getCapabilitySections() filter. BASIC_USAGE_TOOLS derives from this capability by id. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Tool handlers don't need any changes for the basic-usage refactor — access is granted via the registry capability and the AccessControl layer. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…sion set Revert access-control.ts runtime override. Instead, buildPermission() in the role editor always includes BASIC_USAGE_TOOLS in the saved 'self' permission, so Better Auth's normal permission check returns true for those tools without any special-case logic at the access layer. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move the basic-usage check above the auth/role checks in checkResource so it runs first. Custom roles never need to include these tools in their saved permission set — the registry alone defines them, the UI hides the capability, and access-control auto-grants at runtime. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduces useCapability/useCapabilities hooks and RequireCapability/ PermissionTooltip/NoPermissionState components so the UI proactively hides or disables actions the current user's role doesn't permit, mirroring server-side AccessControl logic. Applies capability checks across settings pages, connections, agents, automations, monitoring, and AI providers. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contributor
🧪 BenchmarkShould we run the Virtual MCP strategy benchmark for this PR? React with 👍 to run the benchmark.
Benchmark will run on the next push after you react. |
Contributor
Release OptionsSuggested: Minor ( React with an emoji to override the release type:
Current version:
|
…ants and UI gating Adds grant-resource-access helper, access-denied utility, settings index redirect, and wires capability checks throughout UI components, hooks, layouts, and tool handlers. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…save
- virtual-mcp: roll form back to persisted agent on no-permission auto-save
instead of adopting the user's input as the new defaults.
- access-denied: tighten regex to AccessControl/Better-Auth wording so
unrelated upstream errors aren't relabeled as permission failures.
- use-capability: rolePermits now also accepts wildcard shapes
({ "*": ["*"] }, { "self": ["*"] }) and aggregates actions across
resource buckets so non-self grants aren't silently denied client-side.
- grant-resource-access: skip when the role already has full access via
any wildcard shape, not just permission["*"].
- thread/list: throw ForbiddenError when a non-self userId filter is
requested without THREADS_VIEW_ALL_MEMBERS instead of silently
rewriting it; document the constraint on the input schema.
- org-role-detail: admin and user are now fully customizable. Built-in
admin/user permission overrides are persisted as organizationRole rows
and surfaced via useOrganizationRoles().builtinOverrides so the editor
loads them with a stored id and updates in place. First save recovers
from "role name already exists" by listing roles and updating the
existing row, so re-saving admin or user no longer errors.
- registry-metadata: drop dead TOOL_LABELS table left over from the
removed getPermissionOptions helper.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
7966e33 to
bfbc99c
Compare
Previous fix aggregated grants across all resource buckets, but the
auto-grant helper writes { [connectionId]: ["*"] } for every connection
on every custom role. Aggregating that turned the "*" action into a
global wildcard, which gave every member with any connection grant
full UI access.
Capability tools are static org-level permission names, so the gating
only needs to look at the `self` bucket. Per-connection wildcards mean
"all tools on this connection" — not "wildcard every capability".
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is this contribution about?
This PR introduces a proactive client-side permissions layer that mirrors the server-side
AccessControllogic. Custom-role users now see disabled/hidden UI and clean empty states for sections they can't access, rather than hitting API errors. The core primitives are auseCapability/useCapabilitieshook, aRequireCapabilityroute-level guard, aPermissionTooltipwrapper for inline disabled states, and aNoPermissionStateempty-state component. Capability checks are applied across settings pages, connections, agents, automations, monitoring, and AI providers. Server-sideAccessControlalso received a small fix to always grantbasic-usagetools regardless of role.Screenshots/Demonstration
How to Test
connections:manage).Review Checklist
Summary by cubic
Add client‑side RBAC capability gating so users only see or can click what their role allows, with clean “No access” states and helpful tooltips. Introduces a capability model that mirrors server checks and auto‑grants basic usage tools to all members.
New Features
useCapability/useCapabilities,RequireCapability,PermissionTooltip,NoPermissionState.basic-usagecapability; tools under it are always allowed for org members, reducing friction for read‑only/essential actions.Refactors
PERMISSION_CAPABILITIESwith helpers for grouping and toggling.Written for commit a2ff84f. Summary will update on new commits. Review in cubic