Roles and capabilities
A capability is permission to do one kind of thing, like setting budgets or reading the audit log. Roles bundle capabilities, and they are the only way anyone gets one.
A capabilityCapabilityQuyền hạnPermission to do one kind of thing, such as setting budgets or reading the audit log. Roles are the only way to get one.Open in glossary is permission to do one kind of thing, like setting budgets or reading the audit log. A roleRoleVai tròA bundle of capabilities. Everyone has one built-in role — Org Owner, Org Admin or Org User — and groups can add custom roles on top.Open in glossary bundles capabilities, and roles are the only way anyone gets one. This page answers what may this person do. Which things is Resource visibility; how much is Budgets and policy.
Key rules
- Roles are the only source of capability. Departments, group membership itself and screen state grant none.
- Everyone has one built-in role: Org Owner, Org Admin or Org User.
- Custom roles add on top, held directly or through a groupGroupNhómA set of people used to give roles and to name in sharing rules. A person can be in many groups; a group never holds money.Open in glossary.
- Four capabilities are built-in only. No custom role can hold them.
- Every capability is organisation-wide. None carries a department.
| Capability | Org Owner built-in | Org Admin built-in | Org User built-in | Department Lead custom | Cost Analyst custom | Compliance Reviewer custom | Knowledge Curator custom | Agent Curator custom | In a custom role? grant ceiling |
|---|---|---|---|---|---|---|---|---|---|
| Organisation | |||||||||
Change organisation settings org.settings.manage | — | Built-in only | |||||||
Manage billing billing.manage | Owner only | — | Built-in only | ||||||
| People | |||||||||
Manage people user.manage | — | — | — | — | — | — | Yes | ||
View the portal as someone else user.impersonate | — | Built-in only | |||||||
Approve a request to view as someone impersonation.approve | — | Built-in only | |||||||
Manage departments department.manage | — | — | — | — | — | — | Yes | ||
Manage groups group.manage | — | — | — | — | — | — | Yes | ||
Manage roles role.manage | — | — | — | — | — | — | Yes | ||
| Models & spend | |||||||||
Manage the model catalogue and approve keys model_catalog.manage | — | — | — | — | — | — | Yes | ||
Add a department's own provider key byok.manage | — | — | — | — | — | Yes | |||
Set budgets and limits policy.manage | — | — | — | — | — | — | Yes | ||
See spend across the organisation usage.view_org | — | — | — | — | — | Yes | |||
See your own department's spend usage.view_department | — | — | — | — | — | Yes | |||
| Resources | |||||||||
Change sharing on any resource visibility.manage | — | — | — | — | — | — | Yes | ||
Manage agents agent.manage | — | — | — | — | — | Yes | |||
Publish an agent to everyone agent.publish_org | — | — | — | — | — | Yes | |||
Manage skills skill.manage | — | — | — | — | — | Yes | |||
Manage prompts prompt.manage | — | — | — | — | — | Yes | |||
Manage artifacts artifact.manage | — | — | — | — | — | — | Yes | ||
Manage knowledge bases knowledge.manage | — | — | — | — | — | Yes | |||
| Apps & tools | |||||||||
Manage tools tool.manage | — | — | — | — | — | — | Yes | ||
Manage connected apps application.manage | — | — | — | — | — | — | Yes | ||
| Oversight | |||||||||
Read the audit log audit.view | — | — | — | — | — | Yes | |||
Export the audit log audit.export | — | — | — | — | — | Yes | |||
Read conversations as evidence transcript.read | — | — | — | — | — | Yes | |||
Approve a request to read conversations transcript.approve | — | — | — | — | — | — | Yes | ||
| No capability matches this filter. | |||||||||
Sources of capability
Your effective set of capabilities is the merge of three sources:
- Your built-in role, from your organisation tier: Org Owner, Org Admin or Org User.
- Custom roles held directly. A person may hold several.
- Custom roles from every group you belong to. Groups carry reusable bundles.
One resolver computes this for every caller. Nothing is cached between requests and there is no second implementation, so every screen and every check sees the same answer.
The resolver keeps provenance per grant. If you reach a capability directly and through two groups, the admin “why does this user have this” view shows all three paths.
The same resolver is used for every read, write and sharing-rule edit of a shared resource, a turn’s step-by-step trace, a conversation transcript, a file’s bytes, and the admin preview of someone’s effective capabilities.
There is no team-role tier — no team owner and no team admin. Org Admins manage departments. The interface calls the Org Admin role Organisation admin, and the department field on an invitation states that it buys no authority: the department is the budget a person is billed to, the role is authority over the whole organisation.
Seeded roles
Creating the organisation seeds three built-in roles and five custom ones, together with the default department. The five custom roles are ordinary roles: you can rename, re-scope or delete them, they are subject to the grant ceiling, and none is attached to a group until you attach it.
| Role | Kind | Holds | Deliberately excluded |
|---|---|---|---|
| Org Owner | built-in | every capability | — |
| Org Admin | built-in | every capability except billing.manage | billing.manage |
| Org User | built-in | the base tier, no admin capability | — |
| Department Lead | custom | usage.view_department, byok.manage | policy.manage, department.manage; curating a knowledge base comes from owning it |
| Cost Analyst | custom | usage.view_org | the department-level read, which would narrow nothing |
| Compliance Reviewer | custom | audit.view, audit.export, transcript.read | anything configurable, and transcript.approve, so a reviewer cannot approve what reviewers ask for |
| Knowledge Curator | custom | knowledge.manage | visibility.manage, which reaches every resource type |
| Agent Curator | custom | agent.manage, skill.manage, prompt.manage, agent.publish_org | artifacts, which are outputs rather than configuration |
Org User is the base tier: chat, use what is shared with you, keep personal memory, and add a provider key of your own in Settings › Model keys. That last one needs no capability, because it is your own key and your own money.
All 26 capabilities
Org Owner holds all 26. Org Admin holds all except billing.manage. Org User holds none. “Built-in only” capabilities can never be put on a custom role.
| Area | Capability | What it allows | In a custom role? |
|---|---|---|---|
| Organisation | org.settings.manage | Change organisation settings | Built-in only |
| Organisation | billing.manage | Manage billing (Org Owner only) | Built-in only |
| People | user.manage | Manage people | Yes |
| People | user.impersonate | View the portal as someone else | Built-in only |
| People | impersonation.approve | Approve a request to view as someone | Built-in only |
| People | department.manage | Manage departments | Yes |
| People | group.manage | Manage groups | Yes |
| People | role.manage | Manage roles | Yes |
| Models and spend | model_catalog.manage | Manage the model catalogue and approve keys | Yes |
| Models and spend | byok.manage | Add a key your department pays for | Yes |
| Models and spend | policy.manage | Set budgets and limits | Yes |
| Models and spend | usage.view_org | See spend across the organisation | Yes |
| Models and spend | usage.view_department | See your own department’s spend | Yes |
| Resources | visibility.manage | Change sharing on any resource | Yes |
| Resources | agent.manage | Manage agents | Yes |
| Resources | agent.publish_org | Publish an agent to everyone | Yes |
| Resources | skill.manage | Manage skills | Yes |
| Resources | prompt.manage | Manage prompts | Yes |
| Resources | artifact.manage | Manage artifacts | Yes |
| Resources | knowledge.manage | Manage knowledge bases | Yes |
| Apps and tools | tool.manage | Manage tools | Yes |
| Apps and tools | application.manage | Manage connected apps | Yes |
| Oversight | audit.view | Read the audit log | Yes |
| Oversight | audit.export | Export the audit log | Yes |
| Oversight | transcript.read | Read conversations as evidence | Yes |
| Oversight | transcript.approve | Approve a request to read conversations | Yes |
transcript.read also opens the audit log’s Conversations tab, which lists every conversation in the organisation and serves the files each one produced. Where your organisation requires approval, the capability only lets its holder ask: a conversation opens under a grant that someone holding transcript.approve approved. See Access approvals.
How department-shaped capabilities narrow
Every capability is organisation-wide. Resource checks combine it with the target’s ownership and visibility before anything runs.
usage.view_departmentshows only your department, because the department is taken from you, not from the request.byok.managenarrows the same way: it lets you paste a key your own department pays for, and the check compares the key’s department with yours. Pasting a key of your own needs no capability.- Approving a key is
model_catalog.manage, which both admin tiers hold and a custom role may be granted. policy.manageanddepartment.managetake the department from the request and only check that it belongs to your organisation. A lead holding either could rewrite every other department’s budget and model policy, so setting one department’s budget is not possible below an administrator.- Curating a department’s knowledge base is not a capability. An administrator names the lead as the knowledge base’s owner, and ownership grants the write.
The grant ceiling
Four capabilities are non-delegable. They stay on built-in roles, and granting one to a custom role is refused.
| Capability | Held by | Delegable? |
|---|---|---|
org.settings.manage | Org Owner, Org Admin | No |
billing.manage | Org Owner | No |
user.impersonate | Org Owner, Org Admin | No |
impersonation.approve | Org Owner, Org Admin | No |
A second ceiling sits on authoring: what someone building an agent may reference is bounded by their own effective policy, and anything beyond it is refused when they save. See Building an agent.
Impersonation
An administrator holding user.impersonate can View as a named person for 30 minutes, to reproduce what that person sees. Every rule, budget and capability in play is the person’s, never the admin’s. It is refused if the person holds a capability the admin lacks, and both start and end are audited. The full rules live in Access approvals › Impersonation.
Invitations
| Rule | Result |
|---|---|
| Invite a member or an administrator | Allowed |
| Invite an owner | Refused |
| Name a department from outside the organisation | Not found |
| Issue or resend while the directory is managed by your identity provider | Refused (directory frozen) |
| Withdraw an open invitation | Allowed in either directory mode |
An owner cannot be invited because that tier carries billing.manage, which is non-delegable. The first owner is whoever created the organisation; a later one is set by ECV directly. The department is chosen when the invitation is written, not when it is accepted, so nobody’s first message lands in the unassigned bucket. Directory modes are explained in Departments › Directory mode; the sign-in flow is in Identity.
Rules every check obeys
- Deny wins. One deny rule blocks, even for the owner. See Resource visibility.
- Moving someone between tiers is the owner’s alone, because promoting to owner hands over billing. The people directory follows the tier, not
user.manage. - You can read your own permissions. The profile loaded after sign-in carries your effective set (without provenance). The admin explanation view uses the same resolver.
- No back doors. Identity is passed explicitly to every check, so agents and background jobs running without a browser request cannot skip authorisation.
- One rule, one place. Each rule exists once and can answer “page 3 of what this person can see” efficiently; the access preview calls the live resolver.
- Fail closed. An unknown person sees nothing; a disabled account sees nothing; a missing resource is not visible; a missing policy refuses rather than borrowing from the level above.
- “Forbidden” or “not found”. Forbidden means it exists but you may not; not found means you are not entitled to know. A resource that is not visible to you is always “not found”.
Why it works this way
Why can't a Department Lead set their own department's budget?
Setting budgets is one organisation-wide capability. Giving it to a lead would let them rewrite every department’s budget and model access, not just their own. So budgets stay with administrators, while the lead role sees its own department’s spend and can add a key their department pays for.
Why are four capabilities never delegable?
Each controls the portal itself rather than work inside it: organisation settings, billing, acting as someone else, and approving that. A custom role holding one could rewrite the limits on every other role, so they stay with Org Owner and Org Admin — and billing with the Org Owner alone.
Why doesn't joining a department give any capability?
A department decides who pays, not what you may do. Keeping capabilities on roles alone means moving someone to another budget never changes what they are allowed to do.
Under the hood
Route declarations
@RequireCapability gates a fixed capability. A class-level declaration covers every route in the controller; a handler’s own decorator overrides the class rather than adding to it; holding any one listed entry opens the route. A test walks the vocabulary and fails on any capability no source file checks.
@RequireAccess(resource, mode) resolves the target’s visibility reference and checks read or write access before the use case runs:
@Patch(":id")
@RequireAccess("AGENT", "write")The third argument defaults to id; name a different route parameter when a parent path identifies the resource:
@Get("nodes/:nodeId/documents")
@RequireAccess("KNOWLEDGE_BASE", "read", "nodeId")A method declaration overrides a class declaration. read requires visibility; write requires visibility and either ownership or the type’s manage capability, so write satisfies a read check, and DENY blocks both even for owners and managers. Sharing, creation and permissions conditional on the requested change keep their own policies.
Shared enforcement and target resolution
Guards and direct callers use AssertResourceAccess. A guard passes verified access with the caller (bound to caller, org, visibility id and mode), so repeated assertions for that resource reuse the result during the invocation; serialising identity drops its verification. A plain AuthContext always evaluates current policy, so agent runtimes and workers reach the same live checks without an HTTP guard.
The guard resolves domain ids on the server and fetches only access metadata; the use case loads content. MEMORY_RECORD and KNOWLEDGE_DOCUMENT reach their collection; VISIBILITY names a visibility row directly (personal library choices). MEMORY_NODE resolves the same collection as KNOWLEDGE_BASE and keeps the memory API’s node_not_found; knowledge routes keep knowledge_node_not_found, which the knowledge screen uses to show restricted access. Collections filter visibility before pagination.
Grant ceiling, resolver and error codes
The ceiling is application code: Role.assertGrantable refuses a non-builtin role granted a non-delegable capability, and a spec proves the database alone would allow the row. The admin preview is GET /effective-capabilities.
| Case | Response |
|---|---|
| Invite an owner | 400 invite_role_not_invitable |
| Department from another organisation | 404 |
Issue or resend in IDP mode | 409 directory_frozen |
| Exists but not permitted | 403 |
| Not visible, or in another organisation | 404 |