Skip to main content

Documentation Index

Fetch the complete documentation index at: https://langwatch.ai/docs/llms.txt

Use this file to discover all available pages before exploring further.

LangWatch RBAC has two layers, two surfaces, and one stitching mechanism:
  • 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 RoleBinding row glues a user to a role at a scope (organization, team, project, or governance subscope).
Most orgs never touch this page. The pre-built roles cover the common cases. You only land here when you need to delegate 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.
Org roleDefaultsWhat it grants by default
ADMINFirst user to sign in becomes adminorganization:view, organization:manage, organization:delete; the full governance surface (governance:view, governance:manage, ingestionSources:*, anomalyRules:*, complianceExport:view, activityMonitor:view); aiTools:view + aiTools:manage.
MEMBERDefault for inviteesorganization:view, aiTools:view. No governance permissions, no member-list reads, no audit log access by default. The team-role (below) is what gives them anything beyond /me.
EXTERNALLite-member shape, opt-in via the invite drawerSame as MEMBER. EXTERNAL also has stricter team-level defaults: even when on a team they default to view-only on most resources.
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).

Team roles

The four pre-built team roles. A user can have different team roles on different teams (ADMIN on Engineering, VIEWER on Marketing).
Team roleWhat it grants by default
ADMINThe full team-scoped permission set: project:create/update, analytics:manage, traces:create, virtualKeys:create/update/rotate/manage, gatewayBudgets:view/manage, gatewayProviders:view/update/manage, routingPolicies:view/manage, gatewayGuardrails:view/attach/detach/manage, gatewayLogs:view, auditLog:view, gatewayUsage:view, gatewayCacheRules:*.
MEMBERSame shape minus the *:manage permissions. Read + create + update on most resources; can’t delete or reconfigure providers, policies.
VIEWERView-only across the team. No create, update, delete on anything. The right shape for stakeholders who need read access to a team’s traces but should never reconfigure anything.
CUSTOMEmpty by default. Permissions come from the CustomRolePermissions JSON column on the RoleBinding row, see Custom roles below.
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 to organization:manage, the underlying procedure is on auditLog: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

After this PR’s RBAC defense-in-depth pass, 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).
Pre-built rows are read-only: you can’t change what 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 “let bob@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:
  1. Open /settings/roles+ New custom role.
  2. Name the role (e.g. aitools-curator).
  3. Tick the permissions to grant. Permissions are scope-aware, granting aiTools:manage at organization scope is different from granting it at team scope.
  4. Save.
To bind the role to a user:
  1. Open /settings/role-bindings+ New binding.
  2. Pick the user, pick the role (aitools-curator from the catalog), pick the scope (Organization, a specific team, a specific project, a governance subscope).
  3. Save.
The binding is now active. The user’s effective permissions are the union of:
  • 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:manage at 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:
QuestionFilter
Who can manage the AI Tools Portal?Role = aiTools-curator (or any custom role granting aiTools:manage).
Who has admin on the Marketing team?Role = ADMIN, Scope = Team, Scope target = Marketing.
What does bob@acme.test actually have access to?User = bob. Cross-reference with the permission catalog for what each role grants.
Has anyone been bound at Organization scope to MEMBER?Role = MEMBER, Scope = Organization. (Note: org-scoped MEMBER bindings do NOT imply team- or project-level access, the resolver is hierarchical.)
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:
  1. Walks the user’s role bindings.
  2. 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.
  3. Returns true if the requested permission is in the set.
The resolver is per-request. Permission changes take effect on the next request from the user, there’s no session-level cache. JWT TTL (1h) is the upper bound on how long a stale grant can leak via existing tokens.

Where to next