RBAC
Role-based access control. Permission keys are declared in the manifest. Roles and assignments are managed at runtime via the API or Studio.
How It Works
RBAC in RootCX is global -- a single role can span multiple apps, tools, and integrations. The manifest declares permission keys for apps. At runtime, you create roles, attach permission keys to them, and assign roles to users. A user's effective permissions are the union of all permission keys from all their assigned roles.
Four concepts:
- Permission keys: Define what actions exist. Keys use a
namespace:scope:actionconvention:- Apps:
app:<appId>:<entity>.<action>(e.g.app:crm:contacts.read) - Tools:
tool:<toolName>(e.g.tool:query_data,tool:mutate_data,tool:invoke_agent) - Integrations:
integration:<id>:<action>(e.g.integration:gmail:send) - Global admin:
*(matches everything)
- Apps:
- Roles: Created at runtime via the API or Studio. Group permission keys together (e.g. an
editorrole with read/write keys, aviewerrole with only.readkeys). Roles support inheritance -- a role can inherit from other roles, forming a hierarchy. - Assignments: Map a user to one or more roles.
- Inheritance: Roles can declare an
inheritslist pointing to other roles. The system walks the full chain merging all permission keys transitively. Cycles are detected and rejected.
Wildcard Matching
Permission keys support wildcards with the :* suffix:
| Pattern | Matches | Does NOT match |
|---|---|---|
* |
Everything | -- |
app:crm:* |
app:crm:contacts.read, app:crm:deals.create |
app:support:tickets.read |
tool:* |
tool:query_data, tool:invoke_agent |
app:crm:contacts.read |
integration:gmail:* |
integration:gmail:send, integration:gmail:receive |
integration:slack:send |
Actions
Each permission key maps to an HTTP method on the Data API:
| Action suffix | HTTP | Description |
|---|---|---|
.create |
POST | Create a new record. |
.read |
GET | List or get records. |
.update |
PATCH | Modify an existing record. |
.delete |
DELETE | Remove a record. |
To gate custom actions, declare matching keys in the permissions block (e.g. action.pipeline). Your app's keys will be automatically prefixed with app:<appId>:.
Built-in Role
The system includes one built-in role:
admin-- has permission["*"](global admin). Cannot be deleted or modified. The first registered user is automatically assigned this role.

Managing Roles
Create roles, attach permission keys, set up inheritance, and assign roles to users from the Roles & Permissions panel. Changes take effect immediately on the user's next request.
Using Code
Manage roles and assignments via the API. All RBAC endpoints (except GET /api/v1/permissions) require admin permissions.
POST /api/v1/roles/assign
{ "userId": "3f7a1b2c-...", "role": "editor" }
POST /api/v1/roles/revoke
{ "userId": "3f7a1b2c-...", "role": "editor" }
Cannot revoke the last admin role -- prevents lockout.
GET /api/v1/permissions
Returns the current user's effective permissions (no admin required):
{
"roles": ["editor", "viewer"],
"permissions": ["app:crm:contacts.create", "app:crm:contacts.read", "app:crm:contacts.update"]
}
See the REST API Reference for the full list of RBAC endpoints.
AI Agents
Agents operate under a system identity. When an agent is deployed, a system user and role (agent:<appId>) are automatically created. By default, the agent role has app:<appId>:* (full access to its own data) and tool:* (all built-in tools). Restrict access by updating the agent's role permissions.