**Problem:** Admin had users.create permission but couldn't use it due to workflow requiring superadmin-only /admin/roles endpoint.
**Solution:** Created scalable endpoint that adapts role selection to user's permission level.
**Changes:**
- NEW: GET /admin/roles/assignable endpoint with intelligent role filtering
- Superadmin: Returns all roles
- Admin: Returns admin, finance, non-elevated custom roles (excludes superadmin)
- Prevents privilege escalation via permission comparison
- UPDATED: InviteStaffDialog now uses /admin/roles/assignable
- Removed 403 fallback logic (no longer needed)
- Backend handles role filtering dynamically
- UPDATED: AdminStaff 'Invite Staff' button back to permission-based
- Changed from user.role === 'superadmin' to hasPermission('users.create')
- Both admin and superadmin can now invite staff with role restrictions
**Security:**
- ✅ Privilege escalation blocked (admin can't create superadmin)
- ✅ Custom roles filtered by permission comparison
- ✅ Multi-layer enforcement (frontend + backend)
**Files Modified:**
- backend/server.py (+94 lines)
- frontend/src/components/InviteStaffDialog.js (-14 lines)
- frontend/src/pages/admin/AdminStaff.js (1 line changed)
- RBAC_IMPLEMENTATION_FINAL.md (new documentation)
**Testing:**
- Superadmin can assign all roles including superadmin ✓
- Admin can assign admin and finance ✓
- Admin cannot see/assign superadmin ✓
- Custom role elevation detection working ✓
214 KiB
214 KiB