# RBAC Usage Guide

## Core Roles

- `super_admin`: unrestricted access through Gate before hook. Do not remove the last super admin.
- `admin`: basic operational administrator for essential platform management, without full finance, corporate finance, or permission-assignment powers.
- `registration_officer`: handles registration processing, WhatsApp enrollment follow-up, and registration lifecycle management.
- `training_manager`: manages training operations, courses, cohorts, schedules, attendance, instructors, and certificates until training completion.
- `corporate_manager`: manages institution/B2B workflows only: leads, organizations, proposals, agreements, corporate cohorts, trainees, attendance, and corporate reports.
- `finance_officer`: manages payments, expenses, revenues, corporate invoices, receivables, payment allocation, credit notes, and financial reports.
- `general_manager`: view/report role for general administration dashboards, statistics, and executive visibility without mutating operations.
- `teacher`: sees only assigned cohorts, sessions, materials, attendance, and teacher workspace.
- `support`: follows enrollments, payments, and messages, but cannot approve payments unless granted `payments.approve`.
- `student`: sees only their own portal data.

Detailed matrix:

`docs/rbac_operational_roles_matrix.md`

Legacy aliases are preserved for compatibility:

- `super-admin` mirrors `super_admin`.
- `instructor` mirrors `teacher`.

## Permission Source Of Truth

The canonical permission matrix lives in:

`app/Support/Rbac/PermissionCatalog.php`

When adding a new feature:

1. Add the permission to the correct group in `PermissionCatalog::groupedPermissions()`.
2. Add it to the relevant role in `PermissionCatalog::permissionsForRole()`.
3. Add AR/FR labels in `lang/ar/security.php` and `lang/fr/security.php`.
4. Protect the route with `can:<permission>`.
5. Authorize sensitive Livewire actions using `$this->authorize()` or `Gate::authorize()`.
6. Add a feature test for allowed and denied users.

## Managing Roles From Admin

Routes:

- `/admin/security/roles`: list roles.
- `/admin/security/roles/{role}/edit`: edit the permission matrix.
- `/admin/security/users`: assign a core role to a user.
- `/admin/security/audit`: view RBAC audit events.

Required permissions:

- `roles.view` to view roles and RBAC audit.
- `roles.update` to edit a role.
- `permissions.assign` to save role permissions.
- `users.view` to view user assignments.
- `users.update` to update a user role.

## Permission-First Admin Routes

Admin routes can be opened by users who have the exact permission, even if they are not full admins. This is intentional and allows precise operator accounts.

Examples:

- `courses.view` grants access to `/admin/courses`.
- `cohorts.view` grants access to `/admin/cohorts`.
- `payments.view` grants access to payment review pages.
- `messaging.outbox.view` grants access to `/admin/messaging/outbox`.

Routes without an explicit `can:*` middleware remain protected by the legacy admin middleware until they are migrated.

## Super Admin Protection

Rules:

- Non-super admins cannot edit `super_admin`.
- The last super admin cannot be downgraded from the users security page.
- `User::isSuperAdmin()` checks both Spatie roles and the legacy `users.role` column.

## Data Visibility Rules

- Routes must be protected, but routes are not enough.
- Policies must protect model-level access.
- Queries must be scoped to the current user for teacher and student areas.
- Menus can hide unavailable links, but hidden links are only UX, not security.

## Testing

Core regression tests are in:

`tests/Feature/Security/RbacAccessTest.php`

Run:

```bash
php artisan test tests/Feature/Security/RbacAccessTest.php
```
