> For the complete documentation index, see [llms.txt](https://help.resouris.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.resouris.com/part-2-running-resouris/permissions.md).

# Roles and access

ReSouris uses a **closed-set** access model: **fifteen roles**, and a permission catalogue that no tenant can extend. You cannot invent a role name or a permission string — both are declared in the product's security corpus and seeded by migration. What you *can* do is decide which roles each person holds, and which permissions each role carries in your tenant.

> ⛔ **A NEW TENANT HAS NO ROLES AT ALL.** Roles are per-tenant rows, not global ones. A tenant created this morning has an empty role catalogue. The first administrator can still reach the admin screens — the **name** `tenant_admin` is what gates those — while holding almost no individual permissions, so individual actions refuse with `permission_denied`. Create the roles you need at `/ui/admin/roles` as one of the first things you do. See [Configuring a brand-new tenant](/start-here/getting-started.md#configuring-a-brand-new-tenant).

## Two gates, not one

This catches people out, so it is worth stating plainly. Reaching an admin screen and performing an action on it are checked separately:

1. **The role name** gates the `/ui/admin/...` URL prefix. Holding a role called `tenant_admin` is what gets you through the door.
2. **The permission** gates the action behind it. A role with no permissions passes the first gate and fails the second.

So a role holding **zero permissions is not an unused role** — it still opens admin surfaces. And when an action refuses, the redirect names the permission that was missing (`?error=permission_denied:<permission>`), which is the quickest way to find what to grant.

## The fifteen roles

| Role                       | What it is for                                                                                                                                                                       | Permissions |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- |
| `platform_admin`           | Operates the deployment; manages tenants, flags and quotas.                                                                                                                          | 42          |
| `tenant_admin`             | Administers one tenant; manages its users and roles. The broadest tenant-level role.                                                                                                 | 129         |
| `rostering_manager`        | Generates, publishes and archives rosters.                                                                                                                                           | 47          |
| `scheduler`                | Edits draft rosters and assignments.                                                                                                                                                 | 9           |
| `team_leader`              | Reads rosters; approves leave for a defined team.                                                                                                                                    | 17          |
| `staff_member`             | Reads own assignments and leave; submits leave and subject-access requests.                                                                                                          | 22          |
| `roster_area_admin`        | Administers users, roles, feedback threads and equity flags **within one or more roster areas**. Granted with a `department_id` scope; grant it more than once for multi-area reach. | 23          |
| `roster_user`              | Reads own published roster slots only.                                                                                                                                               | 6           |
| `auditor`                  | Reads audit events, and nothing else.                                                                                                                                                | 5           |
| `trust_admin`              | Maintains Trust Admin session status per service line and date — the Upcoming / All-clinics traffic-light workflow.                                                                  | 2           |
| `data_protection_officer`  | Decides that an offboarded staff record is **purged** rather than held.                                                                                                              | 2           |
| `support_readonly`         | Reads sanitised diagnostics inside a support session.                                                                                                                                | 2           |
| `hcs_professional_lead`    | The third leg of triple-signoff on job-plan approval.                                                                                                                                | 1           |
| `hcs_appeal_moderator`     | Neutral chair of job-plan appeal panels.                                                                                                                                             | 1           |
| `consistency_panel_member` | Member of a Trust-level consistency panel reviewing DCC/SPA/ANR distribution across departments.                                                                                     | 0           |

## Things the table does not make obvious

> ⛔ **A TENANT ADMINISTRATOR CANNOT PUBLISH A ROSTER.** `roster.generate` and `roster.publish` are held by `rostering_manager` **only**. `tenant_admin` is the broadest role by count — 129 of the catalogue — and it still does not include these. If generating a roster refuses, this is almost always why: somebody needs `rostering_manager`, not more administrator rights.

> ⚠️ **`data_protection_officer` is seeded deliberately EMPTY.** It is the only holder of `admin.staff.purge`, and a purge is terminal — the database refuses to un-purge a record, because an anonymisation that can be reversed is pseudonymisation and remains personal data. The role exists in every tenant and is assigned to nobody, so nobody can purge until somebody deliberately assigns it. It is **not** granted to `tenant_admin`, which would have let every administrator irreversibly anonymise a colleague. It is named for a post that exists in the customer: every public authority must designate a DPO.

> ⓘ **`consistency_panel_member` holds zero permissions, and that is correct.** Panel membership is recorded as data (`consistency_panel_member` rows), and the chair's own CRUD lives on a separate permission, `admin.job_plan.consistency_panel.chair`. The role exists so that membership is a stated fact rather than an informal list.

> ⓘ **One permission is held by nobody on purpose.** `absence.reason.read` gates the *reason* on a sickness record. It is seeded and granted to no role, so the reason is invisible by default and a tenant must consciously decide who may read it.

## What the permissions cover

Permissions read `<area>.<action>` — `roster.publish`, `admin.leave-requests.decide`, `equity.view`. The corpus catalogues **170** of them across **34** areas. A tenant database holds **173** rows: three more (`absence.reason.read`, `dashboard_layout.write`, `saved_view.write`) are seeded without a corpus route entry because they gate UI surfaces directly rather than a JSON API operation.

The `admin.*` area is by far the largest at 81 permissions — every admin screen that can change something has one. The rest, by size:

| Area                                                                       | Count | What it gates                                                                                                                  |
| -------------------------------------------------------------------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------ |
| `admin`                                                                    | 81    | Every admin surface that writes: RBAC, SSO, rule packs, service lines, staff, job plans, reconciliation.                       |
| `roster`                                                                   | 7     | Read, generate, publish, regenerate, update, reschedule.                                                                       |
| `dashboard`                                                                | 6     | Creating personal and tenant widget dashboards, publishing them, curating the widget catalogue.                                |
| `tenant`                                                                   | 5     | Tenant-level settings and lifecycle.                                                                                           |
| `equity`                                                                   | 4     | Viewing fairness figures, raising a flag, responding, publishing a policy.                                                     |
| `my_rostaire`, `my_details`, `my_roster`, `self_service`                   | 11    | The worker portal: own roster, own details, own leave, own dashboards.                                                         |
| `staff`                                                                    | 4     | The staff catalogue.                                                                                                           |
| `training_plan`                                                            | 4     | Own and all plans, propose, approve.                                                                                           |
| `job_plan`                                                                 | 3     | Own, all, edit.                                                                                                                |
| `notification`                                                             | 4     | Subscriptions and delivery.                                                                                                    |
| `user`                                                                     | 4     | User administration, export and import.                                                                                        |
| `leave`                                                                    | 3     | Request, decide, withdraw.                                                                                                     |
| `licence`                                                                  | 3     | Install, verify, inspect.                                                                                                      |
| `plugin`                                                                   | 3     | Load and manage plugins.                                                                                                       |
| `report`                                                                   | 3     | Report building and delivery.                                                                                                  |
| `cross_tenant`                                                             | 2     | Offering and accepting cover across tenants — see [Share cover between organisations](/part-2-running-resouris/federation.md). |
| `cross_department_cover`                                                   | 1     | Cover across departments inside one tenant — see [Lend staff between departments](/run-the-roster/cross-department-cover.md).  |
| `webhook`                                                                  | 2     | Create and disable outbound webhooks — see [Send events to another system](/part-2-running-resouris/webhooks.md).              |
| `backup`, `entitlement`, `feedback`, `language`, `llm`, `privacy`, `rules` | 14    | Backup and restore, entitlement ledgers, feedback threads, language packs, LLM features, privacy notices, rule packs.          |
| `audit`, `diagnostics`, `flags`, `observability`, `quotas`, `sickness`     | 6     | One each.                                                                                                                      |

The authoritative list is corpus section 3.2 at `v1.1/docs/security/security-v1.1.md`. It is the file the access middleware itself parses, so a permission that is not in it is unknown to the product and refused.

## Assigning roles

**Settings → RBAC**, gated on `admin.rbac.manage` (held by `platform_admin` and `tenant_admin`). Attach one or more roles per user. `roster_area_admin` additionally requires choosing the `department_id` it is scoped to; the middleware refuses that role access outside its department.

Role changes emit `rbac.role_assigned` and `rbac.role_revoked` audit events, so who granted what and when is answerable from the audit page.

## Departmental scoping

Beyond role, read paths are scoped by tenant-level row-level security. On top of that:

* `roster_area_admin` is scoped to one `department_id` per grant.
* Feedback threads carry an optional `department_id` and are filtered by it.
* The equity tables carry department-isolation policies alongside tenant isolation — see [Architecture](/reference/architecture.md).

> ⚠️ Department scoping follows **ownership**, not blast radius: a department sees what it owns. A shared space used by two departments is visible to both, which is the point of sharing it — see [Manage spaces](/set-up-what-you-schedule/manage-spaces.md).

## Closed-set discipline

The role and permission cardinalities are pinned in `v1.1/package-manifest-v1.1.json` and enforced by `tests/arc/test_closed_set_integrity.py`. Adding a permission is deliberately not a one-line change — it has to land in every place that would otherwise disagree:

1. A migration seeding it with `INSERT ... ON CONFLICT DO NOTHING`.
2. An entry in corpus section 3.2, with the roles that hold it.
3. An OpenAPI operation in `v1.1/docs/api/api-v1.1.md` if it gates a JSON API surface.
4. An enforcement site in code binding it to a route or action.
5. A grant to whichever roles should hold it — seeding the permission grants it to nobody.
6. The pinned cardinality in the closed-set test.

Miss any one and the gates disagree with each other: a permission with no corpus entry is refused as unknown, and a permission with no grant is held by nobody. Both fail silently from a user's point of view — the screen simply refuses.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://help.resouris.com/part-2-running-resouris/permissions.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
