Permission System Tables¶
Permissions (permissions)¶
Purpose: Defines all system permissions
Use Case Example: Define permission "budget:edit" allowing users to edit budgets.
| Column | Type | Description |
|---|---|---|
| id | UUID | Unique identifier |
| permission_key | TEXT | Unique key (e.g., 'project:view') |
| description | TEXT | Human-readable description |
| module | TEXT | Feature area (Projects, Budgets, Reports) |
| scope | scope_type | The scope where this permission applies: 'organisation' or 'project' (default: 'project') |
Permission Roles (permission_roles)¶
Purpose: Defines roles that bundle multiple permissions together
Use Case Example: Create "Organisation Admin" role with permissions for managing users, projects, and organisation settings.
| Column | Type | Description |
|---|---|---|
| id | UUID | Unique identifier for the role |
| name | TEXT | Display name of the role |
| description | TEXT | Optional description of the role |
| role_key | TEXT | Unique key identifier for the role |
| priority | INTEGER | Priority order for displaying roles (lower numbers first) |
| is_active | BOOLEAN | Whether this role is currently active and can be assigned |
| scope | scope_type | The scope where this role applies: 'organisation' or 'project' (default: 'project') |
| created_at | TIMESTAMPTZ | Timestamp when the role was created |
| updated_at | TIMESTAMPTZ | Timestamp when the role was last updated |
Permission Role Links (permission_role_links)¶
Purpose: Links permissions to roles
Use Case Example: Grant "organisation:view", "organisation:edit", and "organisation:users" permissions to the "Organisation Admin" role.
| Column | Type | Description |
|---|---|---|
| permission_role_id | UUID | Reference to permission role |
| permission_id | UUID | Reference to permission |
Per-Module Permission Catalogues¶
The following permission tables are seeded into permissions via migrations and linked to roles via permission_role_links.
Production Phases Permissions¶
| Permission Key | Name | Description | Module | Scope |
|---|---|---|---|---|
| production_phase:view | View Production Phases | View production phases and production days (read-only). Required to see human-readable phase and day labels on budget daily allocations. | Production Phases | project |
| production_phase:manage | Manage Production Phases | Create, edit, and manage production phases and days for the project | Production Phases | project |
Payment System Permissions¶
| Permission Key | Name | Description | Module | Scope |
|---|---|---|---|---|
| payment:method:manage | Manage Payment Methods | Create, edit, and manage payment methods for the project | Payments | project |
| payment:view | View Payments | View payments | Payments | project |
| payment:schedule | Schedule Payments | Schedule payments for approved transactions | Payments | project |
Role Assignments:
project:ownerrole includespayment:schedulepermission
Approval System Permissions¶
| Permission Key | Description | Scope |
|---|---|---|
| approval_rule:view | View approval configurations | project |
| approval_rule:create | Create approval configurations | project |
| approval_rule:edit | Edit approval configurations | project |
| approval_rule:delete | Delete approval configurations | project |
| approval:view | View approval requests | project |
| approval:approve | Approve/reject/query records | project |
| approval:can:action:queried | Approve/reject items that are in Queried status | project |
| approval:escalate:urgent | Skip to highest tier and send urgent notifications | project |
| approval:soft:view | View and action records with processing issues when no formal approval config | project |
Transaction Permissions¶
Inserted into permissions, scope project, module Transactions:
| Permission Key | Name | Description |
|---|---|---|
transaction:void |
Void Transaction | Void a transaction, setting its status to Cancelled and recording a cancellation reason. |
transaction:duplicate:replace |
Use Duplicate as Replacement | Resolve a duplicate-detection issue by voiding the duplicate transaction and submitting its document as the replacement on the matched original's open approval query. |
transaction:void is granted, at migration time, to exactly the roles that hold transaction:reject (Project Owner, Project Admin, Finance Manager, Line Producer, Approver). The grant is data-driven (selects roles by joining on the reject permission) so it tracks any future change to the reject grant.
transaction:duplicate:replace is granted from two disjoint sources: the same data-driven derivation from transaction:reject holders (the void half of the action mirrors reject authority), plus the Compliance Reviewer role (project:compliance:reviewer) named explicitly by role key. Compliance Reviewer holds neither reject nor void, so it cannot be derived from an existing grant, but it is the triage role the action exists for. Six roles hold the key today: Project Owner, Project Admin, Finance Manager, Line Producer, Approver, Compliance Reviewer. The dual authority the key expresses — void one record while acting on a different record's queried approval — is why it is a dedicated key rather than a composite of transaction:void and approval:can:action:queried.
Form & Entity-Association Permissions¶
Inserted into permissions, scope project:
| permission_key | name | module | description |
|---|---|---|---|
form:send |
Send Form | form |
Send a form to a project participant |
form:resend |
Resend Form | form |
Resend a previously dispatched form |
form:fill_on_behalf |
Fill Form on Behalf | form |
Fill in a form on behalf of a participant |
form:view_submission |
View Form Submission | form |
View a submitted form and its data |
entity_association:edit |
Edit Entity Association | entity_association |
Create or update entity associations |
All five permissions are linked at migration time to roles project:owner, project:admin, project:line:producer, and project:production:management via permission_role_links.
Project Relationship Permissions¶
Inserted into permissions, scope project:
| permission_key | name | module | description |
|---|---|---|---|
project_relationship:edit |
Edit Project Relationships | Project Relationship |
Edit project relationships and entities |
project_relationship:export |
Export Project Relationships | Project Relationship |
Export project relationships and entities |
project_relationship:change_type |
Change Entity Type | Project Relationship |
Change an entity type between Supplier, Crew and Cast on a project relationship |
project_relationship:change_type is granted, at migration time, to the same five roles that hold project_relationship:edit: project:owner, project:admin, project:line:producer, project:production:management, and project:finance:manager. It gates the "Change type" action on the project relationship view, which flips the entity between Business (Supplier) and Person (Crew/Cast) and re-points the relationship role.
project_relationship:export is granted, at migration time, to the same five roles. It gates the "Export CSV" / "Export with Attachments" actions on the project relationship view; the export server pipeline additionally only includes the transactions, payments and form-submission sections when the caller holds the matching transaction:view, payment:view and form view/send permissions.
Project Configuration Permissions¶
Inserted into permissions, scope project, module Projects:
| permission_key | name | description |
|---|---|---|
project:manage_currency_rates |
Manage Currency Rates | Set and correct the static rates that convert foreign-currency transactions to project currency. |
project:manage_currency_rates gates writes to project_currency_rates (see FINANCIAL.md). It is granted, at migration time, to the same three roles that hold payment:method:manage: project:owner, project:admin, and project:finance:manager. Reading rates only requires project membership; the dedicated permission is required to add or correct a rate because rates directly move converted budget figures.
Service-Role-Only Tables (no permission key, no authenticated grant)¶
A few tables are reachable only by service-role code and carry no permission key and no authenticated grant — access is not gated by a permission the UI checks, but by the table having no user-facing grant at all.
notification_action_tokens— Service-role only.authenticatedholds NO grant (SELECT/INSERT/UPDATE/DELETE all revoked) and there are NO RLS policies. Every token operation (mint, validate, consume) runs service-role in the server layer. A token is a bearer capability, not user data — see NOTIFICATIONS.md § "Notification Action Tokens".