Roles & permissions
There are thirteen roles. Two are for client contacts, eleven are for staff users. Permissions are encoded in code — see packages/auth/src/rbac.ts — and the RBAC matrix page is generated from that file at build time, so it cannot drift.
The permission question
Every access check answers one question: may this role, acting for this tenant, perform this action on this group or entity? Three dimensions are evaluated together, and access is denied by default:
- Tenant — every record belongs to one tenant; no role sees across tenants. Enforced at the database (see the platform model).
- Scope — group-scoped roles see the whole group and its rollup; entity-scoped roles see one entity.
- Role — what actions are permitted at all.
Client-contact roles
These are the magic-link recipients. They never see the staff dashboard.
- Client submitter — usually the client's HR or finance person. Submits the monthly intake (payroll), responds to unreconciled items (bookkeeping). Cannot approve.
- Client approver — usually a director / FC. Approves the payroll cycle, the financial-statement engagement, the XBRL filing. Cannot submit. No client role may approve a regulated action — the regulated filing decision is always a tenant operator's.
Staff roles
| Role | Primary surface | Can do |
|---|---|---|
| Payroll Executive | Payroll cycles | Manage cycles, resolve issues, generate exports, upload outputs, request approvals |
| Payroll Lead | Payroll cycles + admin | Everything Payroll Executive does, plus override blocking issues, manage clients, manage templates |
| Bookkeeper | Bookkeeping batches & reconciliation | Manage batches, approve journal entries, generate upload files, run reconciliation |
| Senior Accountant | Bookkeeping + FS + XBRL + admin | Everything Bookkeeper does, plus override journal flags, full FS reviewer surface, full XBRL preparer + validation + export surface (no MARK_XBRL_FILED), add mapping synonyms, manage clients, manage templates |
| FS Preparer | Financial-statement engagements | Manage FS engagements, upload trial balance, confirm/override SFRS taxonomy mappings, generate statements, respond to disclosure interrogation, generate notes. Cannot export the final DOCX |
| FS Reviewer | Financial-statement engagements | Everything FS Preparer does, plus export the publication-ready DOCX |
| XBRL Preparer | XBRL filings (read-only FS access) | Manage XBRL filings, ingest documents (DOCX/PDF), confirm or override every tag mapping. Cannot run validation or export |
| XBRL Reviewer | XBRL filings (read-only FS access) | Everything XBRL Preparer does, plus run validation, generate BizFinx XLSX, generate XBRL XML, mark filed (regulator-facing), and add mapping synonyms |
| Correspondence Operator | Mail-intake queue | Ingest, classify, review, and match incoming correspondence; dispatch clean items to clients |
| Correspondence Reviewer | Mail-intake queue | Everything Correspondence Operator does, plus manage correspondence configuration (mailbox, dispatch mode, matching) |
| Platform Admin | All products + staff | Manage staff users, manage clients, manage templates; view and act across every product; can override issues, override journal flags, mark XBRL filed, and add mapping synonyms |
How escalation works
- A blocking validation issue on a payroll submission can be overridden by a Payroll Lead or Platform Admin via the POL approval flow. A Payroll Executive cannot override on their own.
- A flagged journal entry (low confidence, foreign-currency, keyword-only match) can be overridden by a Senior Accountant or Platform Admin. A Bookkeeper can approve normal entries but not override flags.
- A blocked XBRL export (validation error or unconfirmed mapping) cannot be overridden — by anyone, including Platform Admin. The five non-negotiable rules are enforced in code: fix the validation result, confirm the mapping, then re-export.
- The XBRL mark-as-filed action (records the ACRA reference and seals the filing) is restricted to XBRL Reviewer and Platform Admin — the regulator-facing step deliberately requires the role assigned to liaise with ACRA.
- Adding a synonym to the shared XBRL mapping library (affects all clients' future filings) is restricted to XBRL Reviewer, Senior Accountant, and Platform Admin. Each write is audited.
- Anything tenant-bleed-suspected escalates to Platform Admin and follows the runbook.
Where this is enforced
Three layers, all reading the same matrix:
- API — every Fastify route guards with
requirePermission(Action.X). - Web sidebar — the dashboard nav mirrors the matrix; nav entries the role can't access don't appear.
- Worker jobs — staff-triggered jobs check the actor's role before running.
If you find a discrepancy — e.g. the sidebar shows a link your role can't access — that's a bug, not your error. Open an issue.
Note on the PRD role model. The product spec (PRD D1-2) describes a forward-looking role model in terms of personas (Group Principal, Operator, Module Specialist, Group Lead, Pack Maintainer, …). The roles above are what is implemented in code today; they map onto those personas but are named for the products currently live.