Core resources and relations
- organization — the tenant (employer). Roles:
admin,hr_manager,member. - employee — has a direct
selfrelation to the user, amanagerrelation, andcan_view_sensitivegated to the employee themself plus HR. - team — nests recursively via a
parent_teamrelation; a teamleadinherits from parent teams. - payroll and benefits — admin/HR-manager only.
- time_off_request — initiated by an
employee, approved by theirmanager.
What the model gets right
Employee self-service. The employee is the direct subject on their own record, so the sameCheck API serves the employee portal and the HR admin console — no separate query path.
Manager hierarchy without inheritance to PII. A manager can see direct reports’ non-sensitive profile data, but can_view_sensitive does not flow through the manager chain. Skip-level managers see organizational data but not SSNs.
PII as a distinct relation. can_view_record and can_view_sensitive are separate, so you can grant a recruiter or a contractor partial profile access without exposing identifiers covered by GDPR, CCPA, or local equivalents.
Time-off approvals routed by relationship. The approver is whoever the manager relation points at on the day of the request — no separate “approval routing” table.
Where this maps to OpenFGA features
Common extensions
- Compensation reviews. A
compensation_reviewobject withreviewer(manager),approver(HR), andsubject(employee) — three relations, three views into the same object. - Org redesigns. Re-parenting a team is one tuple write; everyone above and below sees the new hierarchy on the next
Check. - Contractors and contingent workers. Add a
contractortype with a subset ofemployeerelations rather than overloading employee with a type flag.