Permissions (RBAC)
Neemias implements Role-Based Access Control (RBAC) with 8+ built-in roles and 17 granular permissions. Since v0.56.0, users can hold multiple roles simultaneously (AuthPrincipal.roles[]). Starting from version v0.26.0, dynamic roles can be created and managed via the API.
The @neemias/permissions package is the single source of truth — both the frontend (Vite) and the Worker (Wrangler) import definitions from this package.
Built-in roles
| Role | Permissions | Typical use |
|---|---|---|
| ADMIN | All 17 permissions | System administrator |
| CHAMADOR | attendance, students.search | Attendance taking |
| RELATORIOS | reports, students.search | Report viewing |
| CADASTRO | students.add, students.search, sessions.add, sessions.edit, nuclei.manage, classes.manage | Student registration and class management |
| RESPONSAVEL | students.search (own children) | Parent viewing child attendance |
| VOLUNTARIO | attendance, students.search, reports (assigned) | Volunteer teacher |
| COORDENACAO_KIDS | attendance, students.add, sessions.add, nuclei.manage, classes.manage (assigned) | Kids ministry coordinator |
| ADMINISTRATIVO_KIDS | students.add, students.search, sessions.add, attendance, reports (assigned) | Kids ministry administrator |
Multi-role (v0.56.0+): Users can hold multiple roles.
AuthPrincipal.roles[]+primaryRole. See ADR-0022.v0.55.1:
VOLUNTEERremoved,VOLUNTARIO_KIDS→VOLUNTARIO.
Permission matrix
Attendance
| Permission | ADMIN | CHAMADOR | RELATORIOS | CADASTRO |
|---|---|---|---|---|
attendance | ✅ | ✅ | ❌ | ❌ |
Students
| Permission | ADMIN | CHAMADOR | RELATORIOS | CADASTRO |
|---|---|---|---|---|
students.add | ✅ | ❌ | ❌ | ✅ |
students.edit | ✅ | ❌ | ❌ | ❌ |
students.delete | ✅ | ❌ | ❌ | ❌ |
students.search | ✅ | ✅ | ✅ | ✅ |
Users
| Permission | ADMIN | CHAMADOR | RELATORIOS | CADASTRO |
|---|---|---|---|---|
users.view | ✅ | ❌ | ❌ | ❌ |
users.create | ✅ | ❌ | ❌ | ❌ |
users.edit | ✅ | ❌ | ❌ | ❌ |
users.deactivate | ✅ | ❌ | ❌ | ❌ |
users.resetPassword | ✅ | ❌ | ❌ | ❌ |
Settings
| Permission | ADMIN | CHAMADOR | RELATORIOS | CADASTRO |
|---|---|---|---|---|
settings | ✅ | ❌ | ❌ | ❌ |
Import/Export
| Permission | ADMIN | CHAMADOR | RELATORIOS | CADASTRO |
|---|---|---|---|---|
import-export | ✅ | ❌ | ❌ | ❌ |
Sessions (Class sessions)
| Permission | ADMIN | CHAMADOR | RELATORIOS | CADASTRO |
|---|---|---|---|---|
sessions.add | ✅ | ❌ | ❌ | ✅ |
sessions.edit | ✅ | ❌ | ❌ | ✅ |
Nuclei
| Permission | ADMIN | CHAMADOR | RELATORIOS | CADASTRO |
|---|---|---|---|---|
nuclei.manage | ✅ | ❌ | ❌ | ✅ |
Classes
| Permission | ADMIN | CHAMADOR | RELATORIOS | CADASTRO |
|---|---|---|---|---|
classes.manage | ✅ | ❌ | ❌ | ✅ |
Reports
| Permission | ADMIN | CHAMADOR | RELATORIOS | CADASTRO |
|---|---|---|---|---|
reports | ✅ | ❌ | ✅ | ❌ |
Dynamic roles (v0.26.0+)
In addition to the 4 built-in roles, the system supports dynamic roles created via the API. Each dynamic role has:
- name: unique identifier (e.g.,
"SUPERVISOR") - displayName: friendly name (e.g.,
"Regional Supervisor") - permissions: array of strings with the granted permissions
- isSystem:
falsefor custom roles (built-in roles haveisSystem: true)
Dynamic roles are managed exclusively by users with users.create / users.edit permissions (ADMIN).
Role schema
interface Role {
name: string; // min 1, max 50
displayName: string; // min 1, max 100
permissions: string[];
isSystem: boolean;
createdAt: string; // ISO 8601 datetime
updatedAt: string; // ISO 8601 datetime
}How to add a new role
Add an entry in the PERMISSIONS map in packages/permissions/index.ts. The UserRole type is derived automatically — no separate type definition to maintain.
export const PERMISSIONS = {
// ... existing roles ...
NEW_ROLE: ["attendance", "reports"],
} as const;Source: packages/permissions/index.ts