Roles & access control
Access is two layers: a role that decides which portal you land in and what you can do by default, plus an additive Groups layer that grants extra granular permissions without moving you between portals.
The five roles
| Role | Portal | Scope |
|---|---|---|
GLOBAL_ADMIN | Global Admin (/p/ga) | The whole platform — every tenant, plus plans, subscriptions and settings |
SUPER_ADMIN | Super Admin (/p/sa) | One company — owner-level, including admins, branded email, security keyword |
COMPANY_ADMIN | Super Admin (/p/sa) | One company — same portal as SUPER_ADMIN |
ADMIN | Admin (/p/ad) | One company — day-to-day HR operations |
EMPLOYEE | Employee (/p/em) | Their own record only |
Every record carries a tenant_code, and a query is always scoped to the caller's tenant — a company's data can never be read across the tenant boundary.
Groups: the additive layer
A Group is a tenant-scoped collection of users that grants a set of Permissions on top of whatever the user's role already gives them. It never takes anything away, and it can never grant across tenants (tenant_code is never null).
A user's effective permission set = the defaults for their role, unioned with the permissions of every group they belong to.
The permission catalog is a fixed, code-defined list grouped by the area it gates — for example:
| Domain | Sample permissions |
|---|---|
| HR — Leave | HR_LEAVE_VIEW_ALL, HR_LEAVE_APPROVE, HR_LEAVE_MANAGE_BALANCE |
| HR — Attendance | HR_ATTENDANCE_VIEW_ALL, HR_ATTENDANCE_MANAGE, HR_ATTENDANCE_ADMIN |
| HR — Lifecycle | HR_EMPLOYEE_MANAGE, HR_HIERARCHY_MANAGE, HR_DOCUMENTS_MANAGE, HR_POLICIES_MANAGE |
| HR — Other | HR_TICKETS_MANAGE, HR_PERFORMANCE_MANAGE |
| Finance — Payroll | FINANCE_PAYROLL_RUN, FINANCE_PAYROLL_APPROVE, FINANCE_PAYROLL_MANAGE, FINANCE_PAYROLL_VIEW_ALL |
| Finance — Money | FINANCE_SALARY_MANAGE, FINANCE_BANK_MANAGE, FINANCE_BANK_VERIFY, FINANCE_INVOICES_MANAGE, FINANCE_REIMBURSEMENTS_VIEW_ALL |
Groups add permissions; they do not restrict a role. A Role.ADMIN user retains the full default Admin scope even when groups are in play — group membership only ever widens what they can reach.
When the shared LDAP directory is enabled, a group has an LDAP counterpart (cn=) that is renamed in step with the group so a rename never orphans the directory entry.
The security keyword
Each company has one security keyword, set by its Super Admin and stored AES-encrypted (never in plain text, never returned in an API response). It is a second factor for sensitive actions — revealing or changing it requires an OTP sent to the Super Admin, and it gates operations that a stolen session alone should not be able to perform.
Encryption uses SECURITY_KEYWORD_ENC_KEY, which must be distinct from JWT_SECRET and GLOBAL_ADMIN_SECRET.
Global Admin access to a company's data
A Global Admin cannot silently read a tenant's operational data. To get in for support, they raise a company access request; the company's Super Admin approves or rejects it, and the grant is time-scoped and logged. A blocked request surfaces as an explicit access-denied state, not a silent empty screen.