Docs

#Roles & permissions

Ratifia controls who in your org can do what through roles. A role is a named bundle of permissions, and a person's (or an API key's) access is the union of every role they're assigned. Roles and their assignments are owned by Ratifia, per org, so access doesn't drift from wherever your team happens to sign in.

#Permissions

A permission is a single coarse capability. The full vocabulary:

PermissionGrants
decisions:read-minesee the decisions you take part in: you are one of its approvers or its assignee, or you voted on it. Also a pending decision that names no approvers, since anyone may answer it
decisions:read-allsee every decision in the org
decisions:decideapprove / reject decisions
decisions:requestask for decisions: create, read, cancel, verify and consume them; register a worker; trigger a run (for API keys)
policies:readview approval policies
policies:writecreate / edit approval policies
approvers:writemanage approvers
settings:writechange org settings
members:managemanage members and their role assignments
roles:managecreate / edit / delete custom roles
apikeys:managemanage API keys
billing:read / billing:writeview / manage billing
usage:readview usage
audit:readread the audit log

The same vocabulary is shared by the dashboard (what it shows you) and the API (what it lets you call), so a permission means the same thing wherever it's checked.

Roles govern people and API keys alike. See API keys below.

#Built-in roles

Three roles ship with every org and are always present. They're defined in code, not stored as editable rows, so they never drift:

  • admin. Full access, including managing roles, members, and billing.
  • approver. Review and decide (decisions:read-mine, decisions:decide). They see their own Inbox and Archives, not other people's decisions, and nothing under Configuration. To let someone read policies or every decision, give them a custom role with policies:read or decisions:read-all.
  • integration (API keys only). Request, verify and consume decisions, and read policies (decisions:request, decisions:read-mine, decisions:read-all, policies:read). It can't change who approves. New API keys get this role.

Built-in roles can't be edited or deleted, and their names (admin, approver, integration) are reserved, so you can't create a custom role with any of them.

#Custom roles

Need something between the two? Create a custom role with exactly the permissions you choose. Custom roles are org-scoped and managed in the dashboard under Roles (or via /v1/roles, gated on roles:manage). Deleting a custom role also drops it from everyone it was assigned to.

#Assigning roles

Assign roles to people in the dashboard under Members (or via /v1/members, gated on members:manage). Each member lists their roles; add or remove assignments there. A member with several roles gets the combined permissions of all of them.

Nobody is locked out by default

A person with no explicit role assigned still gets a safe default so they're never stranded: a solo account resolves to admin, and a team member with nothing assigned yet gets the approver baseline (they can review). Any explicit assignment, including a restrictive custom role, always overrides this default.

#API keys

An API key holds roles too, chosen when you create it in the dashboard under API Keys; you can change them later without changing the key. A key can do only what its roles allow, and a key with no role can do nothing. Rotating a key keeps its roles.

What each integration needs:

IntegrationRole
Agents via the MCP server, the SDK, the Inngest adapter, n8nintegration (the default)
Policy-as-code (POST /v1/worker/policies, preview)a role with policies:write, e.g. admin

Keep policies:write off keys that don't manage policies. A key that can write a policy can change who approves, so a leaked one could route the next approval to someone else. Every such change still creates a policy version and an audit row.

No key can vote, whatever its roles: deciding is for people (not_an_approver).

Keys created before roles existed were given admin, the access they already had. Narrow them under API Keys.

#The last-admin guard

An org can never lose its ability to administer itself:

  • Removing the final admin from an org is rejected. There must always be at least one admin.
  • The org owner's admin role is permanent; nobody, not even the owner, can remove it.

#Enforcement

Permissions are enforced server-side: a request from someone (or an API key) lacking the required permission is rejected with 403 insufficient_permission, naming the permission. The dashboard uses the same vocabulary to hide actions a person can't take, so the UI and the API agree on who can do what.