Roles and permissions¶
Account roles today¶
Every user has one account role. It decides routing and most access.
| Role | Who | Lands on |
|---|---|---|
platform_admin |
Kwilo staff | /admin |
org_admin |
Runs an organisation | /admin |
unit_manager |
Runs one institution or department | /admin |
instructor |
Faculty / trainer | /teach |
learner |
Institutional learner | /learn |
guardian |
Parent of an institutional learner | parent home |
external_educator |
Marketplace creator | /creator/dashboard |
b2c_user |
Individual on Kwilo Learner | /learn |
Institutional accounts are admin-provisioned. There's no self-serve institutional signup.
ERP permissions¶
Inside Campus, access is checked in two steps, in this order:
- Module gate. Is the module entitled for this institution? If not, 404.
- Permission. Does the user hold the permission at this exact institution? If not, 403.
Permissions are module.action, with three actions per module: view, write, manage. manage is the privileged tier: refunds, waivers, publishing, schema edits.
Modules with permissions: students, fees, admissions, timetable, attendance, exam_ops, hr, library, payroll, helpdesk, id_cards, forms.
Roles that carry permissions¶
| Role | Grants |
|---|---|
org_admin |
Everything, assigned at each institution in the organisation |
principal |
Everything, at their own institution |
<module>_viewer |
view |
<module>_editor |
view, write |
<module>_admin |
view, write, manage |
hod, faculty |
Labels only, no permissions yet |
Granting a staff member access to an ERP module assigns the matching editor or admin role. A staff member with no assigned roles gets only self-service: their own leave, payslips and library loans.
There's no org-wide wildcard. A permission applies only at the institution it was assigned for, which matches how database row-level security isolates each institution.
Known limits¶
- Enforcement is server-side only. The web sidebar and buttons still follow the account role, so a viewer may see a button the API will refuse.
- There's no UI to assign authority roles like principal.
managecan't separate duties inside a module. Someone who can refund can also waive.- Attendance permissions exist but aren't checked, because attendance is a core route, not an ERP router.
Where it lives¶
apps/backend/src/core/authorization/(catalog, roles service, dependencies)- Each ERP module's router under
apps/backend/src/erp/ apps/backend/src/erp/framework/role_sync.py