Skip to content

Permissions

For organization administrators. You need the rights named for each task. Only a platform admin can change settings under /v1/platform. Start with the administrator manual.

This page shows how OpenBot decides if a caller may do something. Every call to /v1 names what it needs: an action on a resource. OpenBot checks it before the call runs.

OpenBot uses the ability library for this work. The model has four parts:

Part What it is
Resource A kind of thing to act on, such as a Chat or a Bot. Each one has a list of actions and a path.
Rule Says Allow or Deny for some actions on some resources, when its condition is true.
Policy A tree of rules. It gives one answer for a request: allow, deny, or no answer.
Role A named policy, such as Member or Administrator. Organizations can add their own.

A member gets the policies of their roles, plus their own member policy. A user token also has its own policy, and both must allow the call. The platform can add a ceiling with deny rules for every organization. See The order of checks.


List them with GET /v1/organization/resources. Each item has the kind, the actions, the fields and the path of one resource.

Resource Action What it allows
Chat read Read Chats, their history and the work that they gave away.
Chat write Change, interrupt and delete Chats, and cancel the work that they gave away.
Chat run Send messages to Bots, so that they work in a Chat.
File read Read your files and their bytes.
File write Upload and delete your files.
Request resolve Answer the requests of your Bots for new capabilities.
Bot read Read Bots, their memory, Rules and Grants.
Bot write Create and change Bots, their memory, Rules and Grants.
Bot delegate Give work to a Bot, from a client or from another Bot.
Bot share Invite people to use a Bot, and manage its members.
Trigger read Read triggers: their schedules and webhooks.
Trigger write Create, change and delete triggers, and set their webhook secrets.
Channel read Read the Channels of the organization and the people linked to them.
Channel write Create, change and delete Channels, set their secrets, and unlink people.
Channel use Talk with the Bot of a Channel, and let your Bots post to it.
ChannelIdentity read Read your linked accounts on the platforms of Channels.
ChannelIdentity write Link and unlink your accounts on the platforms of Channels.
Computer read Read Computers, the Bots that may use them, and their usage.
Computer write Create, change and delete Computers, pair machines, and make connector tokens.
Computer use Run commands, change files, open ports and use the desktop, and let your Bots use them.
ComputerProvider read Read the accounts at Computer providers.
ComputerProvider write Add, change and delete accounts at Computer providers, and their keys.
ComputerProvider use Create Computers with an account at a Computer provider.
Vault read Read Vaults, their items, and the Bots that may use them. Secrets are never shown.
Vault write Add, change and delete Vaults and their items, and set their values.
Vault use Let your Bots use Vaults in Code Mode.
SecretProvider read Read the accounts at secret providers.
SecretProvider write Add, change and delete accounts at secret providers, and their tokens.
SecretProvider use Let Vault items read their secrets from an account at a secret provider.
Connection read Read App connections and App accounts.
Connection write Create, change and delete App connections, and sign in to App accounts.
App use Find Apps, and use App operations and App views.
App publish Use the developer tools for Apps that you publish.
Model use Choose a model for a Chat, and see it in the model catalog.
Token read List API tokens.
Token write Create and revoke API tokens.
Organization read Read the organization and its settings.
Organization write Change the organization and its settings.
Member read List members, their roles and their policies.
Member write Change the roles, policies and status of members, and remove members.
Role write Create, change and delete the custom roles of the organization.
ModelProvider read Read the models and model providers of the organization. Keys are never shown.
ModelProvider write Add, change and remove the models, model providers and keys of the organization.
Sso read Read the email domains and SSO connections.
Sso write Add and verify email domains, and change SSO connections.
AuditLog read Read the audit log.
Usage read Read the model usage and its cost, and the credits of the organization.
Budget read Read the budgets and how much of them is spent.
Budget write Create, change and delete budgets.
Platform read Read the platform settings, organizations, admins and shared models and model providers.
Platform write Change the platform settings, organizations, admins and shared models and model providers.

Platform is only for platform admins. See The platform.

The API reference lists the routes. The contract in @openbot-build/api says which action each route needs.


A path puts each resource in a tree. A rule can cover a part of the tree.

Resource Path
Chat, File, Request, Connection org / <org> / user / <user> / <kind> / <id>
Bot, Trigger, Computer, ComputerProvider, Vault, SecretProvider org / <org> / user / <owner> / <kind> / <id>
App, Token, ChannelIdentity org / <org> / user / <user> / <kind>
Channel org / <org> / channel / <id>
Model org / <org> / model / <provider> / <id>
Organization, Member, Role, ModelProvider, Sso, AuditLog, Usage, Budget org / <org>
Platform platform

The kind part is the kind in small letters, with _ between words, such as computer_provider. App uses apps.

A shared Bot, trigger, Computer, Computer provider, Vault or secret provider has no owner. Its ownerUserId field is null. A Bot that another Bot owns has the owner at the top of its owner tree. When a Bot makes a Bot, the member it works for needs write on Bots of that owner.


A policy is JSON text. The HTTP fields policy and ceiling are strings in requests and responses. To send a policy object, use JSON.stringify(policy) once for that field, then encode the outer request as JSON. The typed client does this with the policy Codec (the Schema that reads and writes the policy).

The text below lets the caller read and change their own Chats:

{
"_tag": "Rules",
"algorithm": "denyOverrides",
"rules": [
{
"_tag": "Allow",
"actions": ["read", "write"],
"resources": ["Chat"],
"when": {
"_tag": "Under",
"prefix": [
{ "_tag": "Literal", "value": "org" },
{ "_tag": "Principal", "path": "organizationId" },
{ "_tag": "Literal", "value": "user" },
{ "_tag": "Principal", "path": "userId" }
]
}
}
]
}

OpenBot checks every policy when it reads it. A kind, an action or a field that does not exist gives 400. A policy in a request may have at most 100 rules, and may be at most 8 levels deep.

Ability 3.1.0 has no library size, depth or search limits. The OpenBot request limits above still apply. Field lists use real paths or *; patterns such as owner* are not valid.

When you move from Ability 2 to 3, stop all servers and run openbot-migrate. The migration changes the platform ceiling from an object to JSON text. Role, member and token columns already hold JSON text. Clients must send strings for policy and ceiling. Old policies must use valid fields. A policy that cannot load grants no access.

A rule has these fields:

Field What it is
_tag Allow or Deny.
actions The actions. * is every action.
resources The kinds, such as Chat. * is every kind.
when Optional. The condition. Without it, the rule covers every value of the kinds.
reason Optional. A reason. A Forbidden error from a deny rule shows it.

A list of rules has an algorithm. It decides which rule gives the answer when more than one rule applies:

Algorithm Winner
denyOverrides A deny rule wins over every allow rule.
permitOverrides An allow rule wins over every deny rule.
firstApplicable The first rule that applies.
lastApplicable The last rule that applies.

A policy can also put policies together:

Node Answer
{"_tag":"All","policies"} Every policy must allow. One deny is enough to deny.
{"_tag":"Any","policies"} One allow is enough.
{"_tag":"FirstOf","policies"} The first policy that allows or denies.
{"_tag":"Ceiling","cap","policy"} A deny from cap always wins. An allow from cap does nothing.

A condition tests the fields and the path of a resource:

Node True when
{"_tag":"Compare","op","field","value"} The field compares to the value. op is eq, ne, lt, lte, gt or gte.
{"_tag":"In","field","values"} The field is equal to one of the values.
{"_tag":"Exists","field"} The field is not null.
{"_tag":"Under","prefix"} The path of the resource starts with the prefix.
{"_tag":"And"/"Or","conditions"} Logic.
{"_tag":"Not","condition"} Logic.
{"_tag":"True"}, {"_tag":"False"} Always, or never.

A value is {"_tag":"Literal","value":...}, or a field of the caller: {"_tag":"Principal","path":"userId"} or "organizationId". A field of the caller with no value never matches, also with ne.

These conditions are the ones you need most:

Condition Covers
Under with org, the organizationId of the caller Everything in the organization.
Under with org, organizationId, user, userId Everything of the caller.
Compare eq on ownerUserId with null The shared Bots, triggers or Computers.
Compare eq on id One resource.

Every policy of a member only works in the organization of the member. A rule that names another organization gives nothing.

use on Model covers the models that a member may choose for a Chat. GET /v1/organization/model_catalog only shows these models. This rule stops a member from using one model provider:

{
"_tag": "Deny",
"actions": ["use"],
"resources": ["Model"],
"when": {
"_tag": "Compare",
"op": "eq",
"field": "provider",
"value": { "_tag": "Literal", "value": "prov_4c1e..." }
}
}

OpenBot checks three policies:

  1. The ceiling of the platform. It only has deny rules, and they apply in every organization. See Platform.
  2. The member policy: the policies of the member’s roles, plus their own member policy. A deny rule in any of them wins.
  3. The token policy, when the caller uses a user token.

A deny anywhere means no. The member policy, and the token policy when there is one, must also allow the call. With no answer, the answer is no.

OpenBot reads these policies again for each check. So a change to a role, a member or a token works at once.

An execution keeps its resource owner separate from the person who started it. For Channel work, the speaker and each saved caller must pass the policy on the actual resource owner. A later check reads their current rights again. An approval cannot change that owner or remove a token limit.

A list, such as GET /v1/triggers, only has the resources that the caller may read. OpenBot changes the policy into a condition on the list, for most lists in the database query itself. So a deny rule on one resource hides it from the list too.

List conditions and direct checks give the same answer for a missing owner. For example, NOT (ownerUserId = "member") includes a shared resource whose ownerUserId is null.

Lists of Chats, files, App connections and Channels apply the policy in the database query. A deny rule hides only the matching items. With no items that the caller may read, the list is empty. File pages and their next cursor count only the files that the caller may read. A file cursor must still belong to the caller and pass the current read policy.

Creating a Chat, file, App connection or Channel still needs write on the full scope of that kind. List filtering does not give write access.

A user token must pass its own policy and the policy of its member. So a token can do less than its member, but never more. If an administrator takes a role away from the member, every token of that member loses it too.

A token made without policy gets this policy. It allows every act of its member, except acts on tokens and on the platform:

{
"_tag": "Rules",
"algorithm": "denyOverrides",
"rules": [
{
"_tag": "Allow",
"actions": ["*"],
"resources": ["Chat", "File", "Request", "...", "Budget"]
}
]
}

This example makes a token that can only read your Chats:

Terminal window
curl -b cookies.txt \
-H "Origin: https://api.example.com" \
-H "Content-Type: application/json" \
-d '{"name":"Dashboard","policy":"{\"_tag\":\"Rules\",\"algorithm\":\"denyOverrides\",\"rules\":[{\"_tag\":\"Allow\",\"actions\":[\"read\"],\"resources\":[\"Chat\"]}]}"}' \
https://api.example.com/v1/user/tokens

The rule has no condition, but the policy of the member still limits the token to what you may read.


List them with GET /v1/organization/roles. The list has the built-in roles and the custom roles of the organization. Each role has builtin: true or builtin: false, and its policy.

Every organization has these roles. They cannot change. A change returns 409 with RoleReadOnly.

Role What it can do
super_administrator Everything in the organization. Only a Super Administrator can give or take away this role.
administrator Manage the organization, its members, its shared Bots, its shared triggers, its shared Computers and its Channels, and read the audit log. Work only with your own Chats and connections.
administrator_read_only Read the organization, its members, usage, budgets and the audit log, and read the shared Bots, triggers, Computers and Channels. Work only with your own Chats and connections.
member Work with your own Bots, Chats, triggers, Computers, connections and tokens, use the shared Bots, triggers, Computers, Channels and models of the organization, and read its settings.
auditor Read the organization, its members, usage, budgets and the audit log. Nothing else.

Some built-in roles also act on roles, model providers, SSO, Channels, usage and budgets:

Role Extra resources for organization features
super_administrator Every action on every resource, except Platform.
administrator Every action on Role, ModelProvider, Sso, Channel, Usage and Budget.
administrator_read_only read on ModelProvider, Sso, Channel, Usage and Budget.
auditor read on Usage and Budget.

To give a member less than a role, give the member a policy with deny rules. This example stops a member from running work, but lets them read their Chats:

Terminal window
curl -X PATCH -b cookies.txt \
-H "Origin: https://api.example.com" \
-H "Content-Type: application/json" \
-d '{"policy":"{\"_tag\":\"Rules\",\"algorithm\":\"denyOverrides\",\"rules\":[{\"_tag\":\"Deny\",\"actions\":[\"run\"],\"resources\":[\"Chat\"]}]}"}' \
https://api.example.com/v1/organization/members/u_456

An organization can add its own roles. A custom role has a name, a description and a policy. Its ID starts with role_. Creating, changing and deleting custom roles needs write on Role.

Terminal window
curl -H "Authorization: Bearer $OPENBOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"Reviewer","description":"Reads Chats and answers requests.","policy":"{\"_tag\":\"Rules\",\"algorithm\":\"denyOverrides\",\"rules\":[{\"_tag\":\"Allow\",\"actions\":[\"read\",\"resolve\"],\"resources\":[\"Chat\",\"Request\"],\"when\":{\"_tag\":\"Under\",\"prefix\":[{\"_tag\":\"Literal\",\"value\":\"org\"},{\"_tag\":\"Principal\",\"path\":\"organizationId\"},{\"_tag\":\"Literal\",\"value\":\"user\"},{\"_tag\":\"Principal\",\"path\":\"userId\"}]}}]}"}' \
https://api.example.com/v1/organization/roles
Route What it does
POST /v1/organization/roles Creates a custom role.
GET /v1/organization/roles/:roleId Reads one role.
PATCH /v1/organization/roles/:roleId Changes a custom role.
DELETE /v1/organization/roles/:roleId Deletes a custom role.
  • The allow rules of a role cannot give anything that you cannot do yourself. OpenBot tests each allow rule with you as the caller. You must be able to do its actions on every value that the rule allows in the organization. The answer is exact: it looks at the fields and the path of the resource. A rule that allows no value gives nothing, so it passes. Otherwise OpenBot returns 403 with Forbidden.
  • A change applies to every member with the role at once.
  • You cannot delete a role while a member or the defaultRoles of the organization use it. OpenBot returns 409 with RoleInUse.

Give a custom role to a member with PATCH /v1/organization/members/:userId. See Organization.


The actions on Platform are for platform admins. Its path is platform, so no rule about an organization covers it.

  • No role in an organization gives them, not even super_administrator.
  • The ceiling does not apply to them, so a ceiling never locks out the platform admins.
  • A user token of a platform admin gets them only when its own policy allows them.

See Platform for an example token.


Status Error When
400 Schema error A policy names a kind, an action or a field that does not exist.
403 Forbidden No rule allows the call, or a rule denies it. See the body below.
404 RoleNotFound The organization has no role with this ID.
409 RoleReadOnly You tried to change or delete a built-in role.
409 RoleInUse A member or the default roles still use the role.
503 PolicyUnavailable OpenBot cannot read the roles and policies of the caller right now.

The body of Forbidden names the action and the kind. It has the reason of a deny rule when one gave the answer:

{
"_tag": "Forbidden",
"action": "write",
"kind": "Chat"
}

You can only reach your own Chats and connections. A Chat of another member answers 404, as if it does not exist. A Bot, trigger or Computer that you may not read answers 404 in the same way.