- Two layers: organization roles (org-wide capabilities, e.g.
ADMIN,MEMBER,EXTERNAL) and team roles (per-team capabilities, e.g.ADMIN,MEMBER,VIEWER). - Two surfaces:
/settings/roles(the role catalog: pre-built + custom) and/settings/role-bindings(who is bound to what role at what scope). - One stitching mechanism: a
RoleBindingrow glues a user to a role at a scope (organization, team, project, or governance subscope).
aiTools:manage without granting full organization:manage, or when an audit asks “who can read the audit log” and you want a screen instead of a Slack thread.
Pairs with: Members & invites (assigning roles when inviting), Audit log (every role binding mutation records a row), and AI Gateway → RBAC (the gateway-side enforcement of permissions).
Organization roles
The three pre-built org roles. Each user in the org has exactly one.
The minimum-privilege default is intentional: an
ORGANIZATION role binding for a MEMBER does not grant team-level access. Team-level permissions come from team-role bindings (next).
Seats
Paid plans meter seats, and there are two kinds. Which one a person occupies follows from what they can do, not from a separate billing switch:- A full seat is someone who can change things.
- A lite seat is someone who can only look at what the team produces.
annotations:create would make the same person a full one. If you want a reviewer who annotates, leave them on the built-in lite role rather than building a custom role for it.
What a lite member can do
They can open the projects they are invited to and read what the team produces there:
Annotations are the exception: on the built-in lite role a member can leave and edit them, so reviewers can mark up what they read without needing a full seat.
These are permissions, not screens, so they hold wherever the data is reached. A lite member using the MCP server with their own account, or the API with their own credentials, sees exactly what they see in the app.
Trace viewing is included in a lite seat. If you want someone who cannot open a trace at all, build a custom role that withholds
traces:view and bind it to them.Choosing between them
The question to ask about a person is whether they need to change anything. Someone who reviews output, watches dashboards and comments on what they find is a lite seat. Someone who builds prompts, runs experiments, edits datasets, or configures the gateway is a full seat.Team roles
The four pre-built team roles. A user can have different team roles on different teams (ADMIN on Engineering, VIEWER on Marketing).
A user’s effective permissions on a resource are the union of every binding that applies, org-level baseline + team-level baseline + any custom-role overrides.
Permission catalog
Every gate in the codebase is a string of the shape<resource>:<verb>. The full catalog (abridged):
- Organization:
organization:view,organization:manage,organization:delete. - Governance:
governance:view,governance:manage,ingestionSources:*,anomalyRules:*,complianceExport:view,activityMonitor:view. - AI Tools Portal:
aiTools:view(everyone),aiTools:manage(admin). - Audit log:
auditLog:view(team-level by default; note the audit log UI page is gated toorganization:manage, the underlying procedure is onauditLog:view). - Per-team resources:
project:*,analytics:*,traces:*,virtualKeys:*,gatewayBudgets:*,gatewayProviders:*,routingPolicies:*,gatewayGuardrails:*,gatewayLogs:*,gatewayUsage:*,gatewayCacheRules:*,evaluations:*,datasets:*,workflows:*,prompts:*,scenarios:*,secrets:*.
What organization:manage gates today
The legacy /settings/{audit-log, teams, members, roles, groups} pages all require organization:manage (admins only). Underlying tRPC procedures match, role.getAll, organization.getAllOrganizationMembers, organization.getOrganizationPendingInvites, team.getTeamsWithRoleBindings, organization.getMemberById, group.getById, group.listForMember, group.listAll, limits.checkAndSendUsageLimitNotification are all gated to organization:manage server-side.
Picker procedures (team.getTeamsWithMembers, team.getTeamWithMembers, organization.getOrganizationWithMembersAndTheirTeams) intentionally stay on organization:view so non-admin pickers (the AddAutomationDrawer, GroupBindingInputRow, project pickers, onboarding flows) continue working, but they redact other members’ email addresses to null for non-admin callers and strip other users’ Personal Workspaces from the result entirely.
The role catalog at /settings/roles
The catalog page lists every role available in the org:
- 4 pre-built org roles (ADMIN, MEMBER, EXTERNAL, VIEWER).
- 4 pre-built team roles (ADMIN, MEMBER, VIEWER, CUSTOM).
- Any custom roles your admin has authored (see below).
MEMBER does, because the gateway and the control plane both encode those defaults. Custom rows are editable.
Custom roles
Custom roles are how you say “letbob@acme.test manage the AI Tools Portal but not the rest of the org.” They’re a RoleBinding row whose role = "CUSTOM" and whose customRoleId references a CustomRole row whose permissions JSON column lists exactly the gates that role grants.
To create one:
- Open
/settings/roles→ + New custom role. - Name the role (e.g.
aitools-curator). - Tick the permissions to grant. Permissions are scope-aware, granting
aiTools:manageat organization scope is different from granting it at team scope. - Save.
- Open
/settings/role-bindings→ + New binding. - Pick the user, pick the role (
aitools-curatorfrom the catalog), pick the scope (Organization, a specific team, a specific project, a governance subscope). - Save.
- Their org-role defaults (e.g. MEMBER →
organization:view+aiTools:view). - Their team-role defaults for every team they’re on.
- The new custom binding (
aiTools:manageat org scope).
Role bindings at /settings/role-bindings
The bindings page is a deep table: every active RoleBinding row in the org. Filter by user, role, scope, or scope target. The most common admin questions:
The page is the answer to “who can do what in this org.” Every change records an audit log row.
How permissions resolve at request time
A request hitting any*:manage-gated procedure flows through checkOrganizationPermission (or checkTeamPermission for team-scoped procs), which:
- Walks the user’s role bindings.
- Builds the effective permission set as the union of: org-role defaults + every team-role default the user has + every custom-role permission via active bindings.
- Returns
trueif the requested permission is in the set.
Where to next
- Invite someone with a specific role: Members & invites.
- Audit who did what: Audit log.
- Gateway-side enforcement: AI Gateway → RBAC.
- Workspace scoping: Workspaces (where org, team, project sit relative to each other).