Skip to main content

RBAC & Permission Matrix

This page is the authoritative list of permission keys. Module specs, API docs and tests reference these keys; a new key is added here first. Roles and scopes come from CONVENTIONS §4; the authorisation flow is in §6.2 of the architecture.

1. Role model​

1.1 Concepts​

ConceptDefinition
Permission<module>.<resource>.<action>, for example lve.request.approve
GrantA permission plus a maximum scope: lve.request.approve@TEAM
RoleA named set of grants. Seeded roles are templates; tenants clone them into custom roles
Role assignmentUser + role + optional narrowing filter (a location, department or legal entity). The effective scope is the grant's scope intersected with the filter
ScopeSELF (S) → TEAM (T, direct and indirect reports from reports_to) → DEPARTMENT (D) → LOCATION (L) → ORG (O)
CheckEvery request is evaluated as the pair (permission, scope) against the target record's employee, department and location, at the record's effective date

1.2 Seeded role templates​

Roles are additive. Every user holds employee; the other columns in the matrix show only what a role adds. A dash in a non-employee column never removes the user's own SELF grant from employee.

ColumnRole keyDefault assignment scope
OWNorg_ownerORG
HRAhr_adminORG
HRMhr_managerORG; assign with a location filter for site HR (effective L)
FAfinance_adminORG
PMpayroll_managerORG; assign with a location or legal-entity filter if payroll is run per site
LMline_managerTEAM. Derived automatically for anyone with at least one report; never assigned by hand
SAsales_adminORG
SMsales_managerTEAM; LOCATION by filter
EMPemployeeSELF. Held by every user
FEfield_executiveSELF (adds tracking and CRM)
KIOkiosk_operatorLOCATION, punch-only
INSinstructorOwn courses (shown as S)
AUDauditorORG, read-only

1.3 Custom roles​

  • Created by cloning a template (iam.role.manage). A custom role can only contain grants at or below the creator's own grants (no privilege escalation through role editing).
  • A role can be assigned only by someone who holds every grant in it at an equal or wider scope (iam.role.assign).
  • Nobody can edit a role they currently hold or assign a role to themselves; the second person rule applies.
  • Common custom roles: Department Head (a line_manager clone with approvals at D), Site Admin (an hr_manager clone with an L filter and no emp.profile.create), Payroll Viewer (read-only payroll for an external CA firm, with an expiry date on the assignment).
  • Role changes notify org_owner and are audited; quarterly access review lists every assignment with its last use.
  • Templates are versioned. When a release adds a new permission to a seeded template, tenants on the template get it; tenants with a cloned custom role see a "new permission available" prompt instead.

1.4 Field-level protection​

Sensitive fields are filtered after row-level authorisation, in the serializer, so every API, export and report path applies the same rule.

Field groupFieldsRequired permissionWithout it
Identity numbersAadhaar, PAN, passport, voter IDemp.sensitive.readLast 4 characters only
BankAccount number, IFSC, account holderemp.sensitive.readLast 4 of the account; IFSC shown
Health and familyMedical leave reasons, disability, blood group, nominee detailsemp.sensitive.readHidden
CompensationCTC, components, revisions, loans, tax declarationspay.compensation.readHidden; reports drop the columns
PayslipsPayslip documents and figurespay.payslip.readNot accessible
Location trailsGPS points, routes, batteryffm.tracking.readOnly visit check-ins (ffm.visit.read)
BiometricFace template, enrolment status detailsNever readable by any role (system use only)Status "Enrolled / Not enrolled" only

Each unmasked read of a C4 field is written to the audit log (security). Exports of sensitive fields require step-up MFA.

1.5 Segregation of duties​

Enabled by default when a tenant has at least two users holding payroll permissions. Tenants with one payroll person get a persistent warning, and the compensating control is that org_owner is notified of every run approval and bank file.

RuleEnforcement
The preparer of a payroll run (pay.run.create) cannot approve the same run (pay.run.approve)Hard block
A user who changed compensation for an employee in the run period cannot approve the run that includes that changeHard block, listed in the approval screen
A user who changed an employee's bank details in the last 24 hours cannot generate a bank file containing that employeeHard block; the line is excluded or another user generates the file
Nobody approves their own leave, regularisation, claim, timesheet, travel or F&FHard block; routed to the next approver
The person who computes F&F (ext.settlement.compute) cannot approve itHard block
A user cannot grant themselves a role or edit a role they holdHard block
Claims verified by finance must not be approved and verified by the same userHard block
Support sessions cannot approve, run payroll, generate files, change roles or exportHard block (guard), regardless of consent

2. Tenant permission matrix​

Legend: S = SELF, T = TEAM, D = DEPARTMENT, L = LOCATION, O = ORG, — = not granted by this role. Columns are listed in section 1.2. Master-data reads that contain no personal data (company, holidays, org chart, directory) are O for everyone. Total: 141 permission keys.

PLT: Platform & Tenant Administration (tenant-facing)​

PermissionWhat it allowsOWNHRAHRMFAPMLMSASMEMPFEKIOINSAUD
plt.subscription.readView plan, usage, invoicesOO—O————————O
plt.subscription.manageChange plan, add-ons, payment methodO————————————
plt.support_access.approveApprove or deny Spyrl support access; revoke sessionsOO———————————
plt.data_export.requestRequest a full tenant exportO————————————
plt.tenant.close_requestRequest account closure and deletionO————————————

ORG: Organisation Setup & Masters​

PermissionWhat it allowsOWNHRAHRMFAPMLMSASMEMPFEKIOINSAUD
org.company.readView company profile, locations, departments————————O————
org.company.manageEdit legal entity, statutory registrationsOO———————————
org.location.manageCreate and edit locations and geo-fenced sitesOO———————————
org.department.manageDepartments and cost centresOO———————————
org.designation.manageDesignations and gradesOO———————————
org.holiday.readView holiday calendars————————O————
org.holiday.manageEdit holiday calendarsOOO——————————
org.custom_field.manageDefine custom fieldsOO———————————
org.branding.manageLogo, colours, sender nameOO———————————
org.chart.readView the org chart————————O————

IAM: Identity, Access & Security​

PermissionWhat it allowsOWNHRAHRMFAPMLMSASMEMPFEKIOINSAUD
iam.user.readView user accounts and statusOOO——T——————O
iam.user.inviteSend or resend activation invitesOOO——————————
iam.user.deactivateDeactivate or reactivate usersOOO——————————
iam.role.readView roles and assignmentsOO——————————O
iam.role.manageCreate, clone and edit custom rolesOO———————————
iam.role.assignAssign roles (only roles whose grants you hold)OO———————————
iam.policy.managePassword, session, MFA and device policiesOO———————————
iam.sso.manageConfigure OIDC and SAML connectionsOO———————————
iam.device.approveApprove a new mobile deviceOOO——T—T—————
iam.session.revokeList and revoke sessionsOOO—————S————
iam.audit.readSearch the audit logOO——————————O
iam.audit.exportExport the audit logO———————————O
iam.api_client.manageCreate API clients and webhook subscriptionsOO———————————

EMP: Core HR & Onboarding​

PermissionWhat it allowsOWNHRAHRMFAPMLMSASMEMPFEKIOINSAUD
emp.directory.readDirectory: name, photo, designation, work contact————————O————
emp.profile.readFull profile (non-sensitive fields)OOOOOT—TS———O
emp.profile.createAdd employees (new hire)OOO——————————
emp.profile.updateEdit employee records directlyOOO——————————
emp.change_request.createRequest a change to own profile————————S————
emp.change_request.approveApprove profile change requestsOOO——————————
emp.sensitive.readUnmask Aadhaar, PAN, bank, health fieldsOO—OO———S————
emp.sensitive.updateEdit Aadhaar, PAN, bank fields directlyOO———————————
emp.document.readView employee documentsOOO—————S———O
emp.document.uploadUpload documentsOOO—————S————
emp.document.verifyMark documents verifiedOOO——————————
emp.job.changeTransfers, promotions, manager changes (effective-dated)OOO——————————
emp.probation.confirmConfirm or extend probationOOO——T———————
emp.onboarding.manageOnboarding checklists and inductionOOO——T———————
emp.import.runBulk imports (dry-run and commit)OOO——————————
emp.letter.generateGenerate letters from templatesOOO——————————

ATT: Attendance, Shifts & Time​

PermissionWhat it allowsOWNHRAHRMFAPMLMSASMEMPFEKIOINSAUD
att.punch.createPunch in/out for self (web, mobile)————————S————
att.punch.create_on_behalfPunch for others at a front desk or kiosk——————————L——
att.punch.ingestDevice and sync-agent ingest (machine tokens only, no human role)—————————————
att.record.readView attendance records and day statusOOOOOT—TS———O
att.record.editCorrect attendance directly (reason required)OOO——————————
att.day.recomputeRecompute employee-days for a date range (job; refused for locked periods)OOO—O————————
att.work_request.requestRequest a work type for a day: WFH, on-duty, remote location————————S————
att.work_request.approveApprove work-type requests (on-behalf entries are auto-approved)O—O——T———————
att.regularization.requestRequest regularisation————————S————
att.regularization.approveApprove regularisationO—O——T———————
att.permission.requestRequest short permission (hours)————————S————
att.permission.approveApprove permissionO—O——T———————
att.overtime.approveApprove overtimeO—O——T———————
att.shift.manageShift mastersOOO——————————
att.roster.manageRosters and rotationsOOO——T———————
att.shift_change.requestRequest a shift change or swap————————S————
att.shift_change.approveApprove shift changesO—O——T———————
att.policy.manageAttendance policies and assignmentOO———————————
att.geofence.manageGeo-fences and allowed networksOOO——————————
att.device.manageRegister biometric devices, kiosks, mappingsOOO——————————
att.face.enrollEnrol or reset a face profile (consent required)—OO——T——S—L——
att.period.lockLock or unlock an attendance periodO—O—O————————
att.import.runImport attendance (CSV, device logs)OOO——————————

LVE: Leave & Holidays​

PermissionWhat it allowsOWNHRAHRMFAPMLMSASMEMPFEKIOINSAUD
lve.balance.readView leave balances and ledgerOOO—OT——S———O
lve.request.createApply for leave————————S————
lve.request.cancelCancel a leave requestO—O—————S————
lve.request.approveApprove or reject leaveO—O——T———————
lve.request.create_on_behalfApply leave for someone elseO—O——T———————
lve.type.manageLeave typesOO———————————
lve.policy.manageLeave policies (accrual, carry-forward, sandwich)OO———————————
lve.balance.adjustManual balance adjustment (ledger entry with reason)OOO——————————
lve.compoff.approveApprove comp-off creditsO—O——T———————
lve.encashment.approveApprove leave encashmentO—OO—————————

PAY: Payroll & Statutory Compliance​

PermissionWhat it allowsOWNHRAHRMFAPMLMSASMEMPFEKIOINSAUD
pay.payslip.readView payslipsO——OO———S———O
pay.compensation.readView CTC, salary structure, componentsO——OO———S———O
pay.compensation.updateChange compensation (effective-dated)O——OO————————
pay.structure.manageSalary structure templatesO——O—————————
pay.component.managePay components and formulasO——O—————————
pay.policy.managePay groups, payroll calendar, statutory settingsO——O—————————
pay.input.manageVariable inputs, arrears, one-time deductionsO———O————————
pay.run.createCreate and calculate a payroll runO———O————————
pay.run.reviewView run results, variance and validation reportsO——OO———————O
pay.run.approveApprove a calculated runO——O—————————
pay.run.lockLock an approved run and publish payslipsO——OO————————
pay.run.reverseReverse a locked run (creates a reversal run)O——O—————————
pay.loan.manageLoans and advancesO———O————————
pay.advance.requestRequest a salary advance (eligibility and recovery months shown)————————S————
pay.tax_declaration.submitSubmit IT declarations and proofs————————S————
pay.tax_declaration.verifyVerify declarations and proofsO———O————————
pay.statutory_file.generateGenerate ECR, ESIC, PT, LWF, 24Q filesO——OO————————
pay.bank_file.generateGenerate bank payout filesO——OO————————
pay.journal.exportExport payroll journal (Tally, Zoho, CSV)O——OO————————
pay.statutory_pack.acceptAccept a new statutory pack versionO——O—————————
pay.form16.publishPublish Form 16 to employeesO——OO————————

NTF: Notifications & Workflow​

PermissionWhat it allowsOWNHRAHRMFAPMLMSASMEMPFEKIOINSAUD
ntf.inbox.readOwn notifications and pending approvals————————S————
ntf.delegation.manageDelegate approvals (own; others for admins)—O——————S————
ntf.workflow.manageApproval chains, SLAs, escalationOO———————————
ntf.template.manageNotification and letter text templatesOO———————————
ntf.channel.manageChannels, sender identity, reminder schedulesOO———————————

RPT: Reporting, Dashboards & Exports​

PermissionWhat it allowsOWNHRAHRMFAPMLMSASMEMPFEKIOINSAUD
rpt.dashboard.readDashboards (scope-filtered)OOOOOTOTS———O
rpt.report.readStandard reports (scope-filtered, sensitive fields masked)OOOOOTOTS——SO
rpt.report.exportExport reports to Excel/CSV/PDFOOOOOTOT————O
rpt.report.scheduleSchedule reports by emailOOOOOTOT—————
rpt.payroll_report.readSalary-bearing reports (registers, statutory)O——OO———————O
rpt.custom_report.buildBuild custom reports (R4)OO—O——O——————

MOB: Mobile & Kiosk​

PermissionWhat it allowsOWNHRAHRMFAPMLMSASMEMPFEKIOINSAUD
mob.kiosk.enrollEnrol a kiosk tablet for a locationOOO——————————
mob.kiosk.operateOperate kiosk mode (punch-only)——————————L——

CLM: Claims & Expenses​

PermissionWhat it allowsOWNHRAHRMFAPMLMSASMEMPFEKIOINSAUD
clm.claim.createSubmit claims and advances————————S————
clm.claim.approveApprove claims (manager step)O————T—T—————
clm.claim.verifyFinance verification of receipts and limits———OO————————
clm.claim.payMark for payout (payroll or bank file)O——OO————————
clm.policy.manageExpense categories, limits, per-diem, mileageOO—O—————————

EXT: Exit & Full-and-Final​

PermissionWhat it allowsOWNHRAHRMFAPMLMSASMEMPFEKIOINSAUD
ext.resignation.submitSubmit resignation————————S————
ext.resignation.approveAccept resignation, set last working dayO—O——T———————
ext.termination.initiateInitiate terminationOOO——————————
ext.master.manageSeparation reasons, termination categories, clearance templatesOO———————————
ext.clearance.updateUpdate clearance itemsOOOOOT———————
ext.settlement.computeCompute full-and-final settlementO———O————————
ext.settlement.approveApprove full-and-final settlementO——O—————————

ENG: Engagement​

PermissionWhat it allowsOWNHRAHRMFAPMLMSASMEMPFEKIOINSAUD
eng.announcement.readRead announcements targeted to me————————S————
eng.announcement.publishPublish announcementsOOO——T———————
eng.recognition.giveGive recognition to colleagues————————O————
eng.program.manageRecognition programmes and badgesOO———————————

FFM: Field Force & Sales CRM​

PermissionWhat it allowsOWNHRAHRMFAPMLMSASMEMPFEKIOINSAUD
ffm.tracking.readView live and past location trailsO——————T—————
ffm.visit.createCheck in at client visits—————————S———
ffm.visit.readView visit historyO—————OT—S——O
ffm.account.readView accounts, contacts, leadsO—————OT—S———
ffm.account.manageCreate and edit accounts and leadsO—————OT—S———
ffm.lead.assignAssign or reassign leads and accountsO—————OT—————
ffm.pipeline.managePipeline stages and templatesO—————O——————
ffm.beat.manageBeat and route plansO—————OT—————
ffm.target.manageSales targetsO—————OT—————
ffm.travel.submitSubmit travel (kms) for a day—————————S———
ffm.travel.approveApprove or revise travel kms (reason required)O——————T—————
ffm.payment.collectRecord a payment collected in the field—————————S———

TSM: Timesheets & Projects​

PermissionWhat it allowsOWNHRAHRMFAPMLMSASMEMPFEKIOINSAUD
tsm.timesheet.submitSubmit timesheets————————S————
tsm.timesheet.approveApprove timesheetsO————T———————
tsm.project.manageProjects, tasks, allocationsOO———————————

LMS: Learning Management​

PermissionWhat it allowsOWNHRAHRMFAPMLMSASMEMPFEKIOINSAUD
lms.course.readTake assigned and open courses————————S————
lms.course.manageCreate and edit coursesOO—————————S—
lms.course.assignAssign courses to learnersOOO——T—————S—
lms.assessment.gradeGrade assessments—O—————————S—

Notes on the matrix​

  • line_manager approvals are the first step of most workflows; HR roles hold O-scope approvals so they can act as later steps or as a fallback. Which steps exist is configured in NTF workflows, not in roles.
  • auditor is read-only and time-limited by assignment expiry. It sees compensation and payroll reports (statutory audits need them) but never unmasked identity or bank numbers.
  • org_owner holds almost everything so a small company can run with one admin, but segregation-of-duties rules still apply per action.
  • hr_admin configures and manages people data but does not see compensation by default; tenants that want HR to see salaries add pay.compensation.read to a custom role.
  • sales_admin configures the CRM but cannot see live location trails; only sales_manager (TEAM) and org_owner can, to limit surveillance (privacy).
  • Machine principals (API clients, device tokens, kiosk tokens) receive OAuth scopes named after the same permission keys, with ORG or LOCATION scope only, and never *.sensitive.* unless explicitly granted.

3. Platform roles​

Platform roles live in the control plane and its own identity provider, separate from tenant roles (administration). No platform role carries any tenant permission; tenant data is reachable only through a consented support session.

PermissionWhat it allowsplatform_adminsupport_engineerbilling_adminrelease_manager
plt.tenant.readView tenant registry, usage, health✓✓✓✓
plt.tenant.manageTrial, suspend, reactivate, export, delete, move cells (deletion and moves need a second approver)✓———
plt.plan.managePlans, entitlements, overrides✓—✓—
plt.invoice.manageInvoices, credits, dunning✓—✓—
plt.flag.manageRelease flags and targeting✓——✓
plt.flag.kill_switchToggle documented kill switches during an incident✓✓—✓
plt.cell.manageCreate and resize cells, maintenance windows✓——✓
plt.release.rolloutStart, pause, resume, abort, roll back waves; minimum mobile version✓——✓
plt.support.requestRequest a support session✓✓——
plt.support.emergency_approveApprove an emergency session without tenant consent (second person)✓———
plt.statutory_pack.publishPublish statutory pack versions✓———
plt.announcement.publishBanners and announcements✓✓—✓
plt.audit.readPlatform audit log✓———
plt.platform_user.manageManage platform staff accounts✓———

4. Keeping the matrix true​

  • The matrix is generated from packages/policy/permissions.ts (the seeded templates). A CI check fails if this page and the code disagree.
  • Authorisation tests are generated from the same source: for each key and role, a test asserts allow inside scope and deny outside scope (testing strategy).
  • New permissions need a security review entry: the data class touched, the default roles, and any SoD rule.