RBAC matrix
Generated from packages/auth/src/rbac.ts at build time. Cannot drift from code.
A check (✓) means the role has the action. The Product column tags whether an action is bound to one product (Payroll / Bookkeeping) or is product-neutral (client / template / staff admin surfaces).
| Action | Product | CLIENT_SUBMITTER | CLIENT_APPROVER | PAYROLL_EXECUTIVE | PAYROLL_LEAD | BOOKKEEPER | SENIOR_ACCOUNTANT | ADMIN | PLATFORM_ADMIN | FS_PREPARER | FS_REVIEWER | XBRL_PREPARER | XBRL_REVIEWER | CORRESPONDENCE_OPERATOR | CORRESPONDENCE_REVIEWER |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
SUBMIT_INTAKE | PAYROLL | ✓ | |||||||||||||
APPROVE_PAYROLL | PAYROLL | ✓ | |||||||||||||
VIEW_CYCLE | PAYROLL | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ||||||||
MANAGE_CYCLE | PAYROLL | ✓ | ✓ | ✓ | ✓ | ||||||||||
RESOLVE_ISSUE | PAYROLL | ✓ | ✓ | ||||||||||||
GENERATE_EXPORT | PAYROLL | ✓ | ✓ | ||||||||||||
UPLOAD_OUTPUT | PAYROLL | ✓ | ✓ | ||||||||||||
REQUEST_APPROVAL | PAYROLL | ✓ | ✓ | ||||||||||||
OVERRIDE_ISSUE | PAYROLL | ✓ | |||||||||||||
VIEW_BATCH | BOOKKEEPING | ✓ | ✓ | ✓ | ✓ | ||||||||||
MANAGE_BATCH | BOOKKEEPING | ✓ | ✓ | ✓ | ✓ | ||||||||||
APPROVE_JOURNAL | BOOKKEEPING | ✓ | ✓ | ✓ | ✓ | ||||||||||
GENERATE_UPLOAD_FILE | BOOKKEEPING | ✓ | ✓ | ✓ | ✓ | ||||||||||
RECONCILE_BANK_TXN | BOOKKEEPING | ✓ | ✓ | ✓ | ✓ | ||||||||||
OVERRIDE_JOURNAL_FLAG | BOOKKEEPING | ✓ | ✓ | ✓ | |||||||||||
VIEW_FS_ENGAGEMENT | FINANCIAL_STATEMENTS | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | |||||||
MANAGE_FS_ENGAGEMENT | FINANCIAL_STATEMENTS | ✓ | ✓ | ✓ | ✓ | ✓ | |||||||||
UPLOAD_TRIAL_BALANCE | FINANCIAL_STATEMENTS | ✓ | ✓ | ✓ | ✓ | ✓ | |||||||||
CONFIRM_FS_MAPPING | FINANCIAL_STATEMENTS | ✓ | ✓ | ✓ | ✓ | ✓ | |||||||||
OVERRIDE_FS_MAPPING | FINANCIAL_STATEMENTS | ✓ | ✓ | ✓ | ✓ | ✓ | |||||||||
GENERATE_STATEMENTS | FINANCIAL_STATEMENTS | ✓ | ✓ | ✓ | ✓ | ✓ | |||||||||
RESPOND_DISCLOSURE | FINANCIAL_STATEMENTS | ✓ | ✓ | ✓ | ✓ | ✓ | |||||||||
GENERATE_NOTES | FINANCIAL_STATEMENTS | ✓ | ✓ | ✓ | ✓ | ✓ | |||||||||
EXPORT_FS_DOCUMENT | FINANCIAL_STATEMENTS | ✓ | ✓ | ✓ | ✓ | ||||||||||
APPROVE_FS | FINANCIAL_STATEMENTS | ✓ | |||||||||||||
VIEW_XBRL_FILING | XBRL_FILING | ✓ | ✓ | ✓ | ✓ | ✓ | |||||||||
MANAGE_XBRL_FILING | XBRL_FILING | ✓ | ✓ | ✓ | ✓ | ✓ | |||||||||
INGEST_XBRL_DOCUMENT | XBRL_FILING | ✓ | ✓ | ✓ | ✓ | ✓ | |||||||||
CONFIRM_TAG_MAPPING | XBRL_FILING | ✓ | ✓ | ✓ | ✓ | ✓ | |||||||||
ADD_MAPPING_SYNONYM | XBRL_FILING | ✓ | ✓ | ✓ | ✓ | ||||||||||
RUN_XBRL_VALIDATION | XBRL_FILING | ✓ | ✓ | ✓ | ✓ | ||||||||||
EXPORT_BIZFINX | XBRL_FILING | ✓ | ✓ | ✓ | ✓ | ||||||||||
EXPORT_XBRL_XML | XBRL_FILING | ✓ | ✓ | ✓ | ✓ | ||||||||||
MARK_XBRL_FILED | XBRL_FILING | ✓ | ✓ | ✓ | |||||||||||
APPROVE_XBRL | XBRL_FILING | ✓ | |||||||||||||
INGEST_CORRESPONDENCE | CORRESPONDENCE | ✓ | ✓ | ✓ | ✓ | ||||||||||
CLASSIFY_CORRESPONDENCE | CORRESPONDENCE | ✓ | ✓ | ✓ | ✓ | ||||||||||
REVIEW_CORRESPONDENCE | CORRESPONDENCE | ✓ | ✓ | ✓ | ✓ | ||||||||||
MATCH_CORRESPONDENCE | CORRESPONDENCE | ✓ | ✓ | ✓ | ✓ | ||||||||||
DISPATCH_CORRESPONDENCE | CORRESPONDENCE | ✓ | ✓ | ✓ | ✓ | ||||||||||
MANAGE_CORRESPONDENCE_CONFIG | CORRESPONDENCE | ✓ | ✓ | ✓ | |||||||||||
MANAGE_CLIENTS | — | ✓ | ✓ | ✓ | ✓ | ||||||||||
MANAGE_CLIENT_CONTACTS | — | ✓ | ✓ | ||||||||||||
ADD_CLIENT_CONTACT | — | ✓ | ✓ | ✓ | |||||||||||
MANAGE_TEMPLATES | — | ✓ | ✓ | ✓ | ✓ | ||||||||||
MANAGE_STAFF | — | ✓ | ✓ | ||||||||||||
RUN_FINANCIAL_ANALYSIS | — | ✓ | ✓ | ✓ | ✓ | ✓ | |||||||||
VIEW_TAX_YEAR | TAX | ✓ | ✓ | ✓ | |||||||||||
MANAGE_TAX_YEAR | TAX | ✓ | ✓ | ✓ | |||||||||||
COMPUTE_TAX | TAX | ✓ | ✓ | ✓ |
How to read this
- A role can perform an action across the platform if it has the cell checked.
- An action's product scope (when not
—) means staff can only use it within that product. A Bookkeeper withMANAGE_CLIENTS(product-neutral) can edit any client; a Payroll Executive withVIEW_CYCLE(Payroll-scoped) cannot view bookkeeping batches even if the route doesn't 404. - "Manage" actions imply read access; you don't need both
VIEW_CYCLEandMANAGE_CYCLEtogether.
Rules the matrix does not show
Some payroll rules are decided per person or per record, in the routes, so a role's tick above is not the whole answer.
- Approve a month without the client (
POST /ops/cycles/:id/approval-draft/approve-without-client): Payroll Lead only. Admins and Platform Admins cannot (26 Oct 2026, R7): the decision stands in for the client's approval, and the PM spec makes the Operations Lead the independent sign-off. Only after the approval request was sent, with a reason; refused to a Lead who changed or linked the company's contacts during the month or in the last 30 days. - Final approval after that decision: never the person who made it, whatever their role, while anyone else who may give the final approval (Payroll Lead, Admin, Platform Admin) is active. No role is exempt. With nobody else, the one person may, and the audit row marks it (
sameLeadRecordedClientApproval). - Not the person who prepared the month (final approval, tie-out release, CPF sign-off, payment approval): one rule at every gate, no role exempt (28 Oct 2026, R7's standard rule; the Platform Admin exemption is gone). Whoever prepared the month may not pass the gate while anyone else who may pass it exists: an active staff member in one of the gate's roles who did not prepare the month themselves (Payroll Lead, Admin, Platform Admin — for the payment approval too, on both kinds of month: since 28 Oct 2026 (S7-06) the review inbox's
PAY.INSTRUCT_PAYMENTcard is narrowed to those roles, like the Close route of a month with no run; a Payroll Executive may not approve payment). The refusal names them, Payroll Leads first. With nobody else, the preparer may, and the gate's audit row (cycle.final_approved,payroll.tie_out.signed_off,payroll.cpf.signed_off,cycle.closed) carriespreparerPassedAlone: trueand what they did. - What counts as preparing a month: confirming its intake; approving, rejecting, editing or filling in a change; uploading or attaching a document; moving a document into or out of the month, removing one or putting it back, or changing its type (matched on the month named in the audit row); answering a client's request card on the month for them; confirming a due increment; pressing Re-check; sending the client approval request; regenerating the export. A Lead's control decisions (overrides, sign-offs, the final approval and the export it triggers, accepting a bank account, recording residency) are not.
- Client contacts: adding one needs
ADD_CLIENT_CONTACT(Admin, Platform Admin, Payroll Lead; the Lead since 29 Oct 2026), in onboarding or on the People tab; changing or removing one needsMANAGE_CLIENT_CONTACTS(Admin, Platform Admin); reading needsMANAGE_CLIENTS. An approver's new email, and a chat linked to an approver from the Inbox, wait for a second console admin; with one admin, that admin confirms as a separate step on record. - Linking an unknown chat sender to a contact (Inbox, This is…): any Inbox operator for a contact who cannot approve; console admins only, with a reason and a second admin's confirmation, for one who can.
- The employee record (
/ops/entities/:id/payroll-employees, Employees tab): payroll operators only (Payroll Executive, Payroll Lead, Admin, Platform Admin). Revealing a hidden value (NRIC/FIN, passport, work pass, bank account number, birth date) is recorded. - The company payroll link, staff side (
/ops/entities/:id/payroll-link, People tab › Payroll link): payroll operators see it and send or resend it; onlyMANAGE_CLIENT_CONTACTS(Admin, Platform Admin) revokes it (26 Oct 2026, LINK-0). - The company payroll link, client side (
/portal/link/:token): no role. A contact of that company who is active, has a payroll right and an email on record signs in with an emailed code; the session opens only the link's own pages, not other client routes (26 Oct 2026, SIGN-1, R29).