Roles & Permissions
A complete reference for CareNova's four user roles, the full permissions matrix, how permissions are enforced, and how to customize them.
Written By Dev010
Last updated 19 days ago
CareNova uses a Role-Based Access Control (RBAC) system with four roles and 50+ granular permission keys. Permissions are enforced at two levels β the dashboard navigation and every server action β so access restrictions cannot be bypassed by manipulating the UI.
The Four Roles
Every user account has exactly one role stored in users.role. The role is assigned when an account is approved by an admin.
What Each Role Can Access
Admin
Full unrestricted access to every module and every action in the system. Admin bypasses all permission checks β hasPermission() always returns true for admin regardless of what is configured in the permissions matrix.
Admin-exclusive modules:
Staff Management
Permissions configuration
Landing Settings
Pending Approval
Full financial management (invoices, payments, expenses)
All system settings
Doctor
Focused on clinical workflows. Doctors see patients, manage their own appointments, write prescriptions, create medical records, and review test reports.
Default doctor access:
Analytics dashboard (view only)
Patients β view, create, edit
Appointments β view, create, edit, reschedule, cancel
Medical Records β view, create, edit
Prescriptions β view, create, edit
Test Reports β view, create, edit
Odontograms β view, create, edit (dental clinics only)
Services β view only
Departments β view only
Blog β view and manage posts
Receptionist
Focused on front desk operations. Receptionists book appointments, manage patient profiles, and handle billing.
Default receptionist access:
Analytics dashboard (view only)
Patients β view, create, edit
Appointments β view, create, edit, reschedule, cancel, assign
Invoices β view, create, edit
Payments β view, create, edit
Services β view only
Departments β view only
Staff β view only
Nurse
Focused on clinical support. Nurses record vitals, assist with medical records, manage inventory, and support clinical workflows.
Default nurse access:
Patients β view, edit
Appointments β view, edit, reschedule
Medical Records β view, create
Prescriptions β view only
Test Reports β view only
Inventory β view, create, edit, delete
Services β view only
Departments β view only
Permission Keys
Permissions are controlled by individual keys in the format module.action. There are 50+ keys across all modules:
Full key examples:
appointments.view
appointments.create
appointments.delete
patients.export
billing.view
medical_records.create
odontogram.edit
settings.editPermissions Matrix
The table below shows the default permissions for each role across all modules:
These are the default permissions. All of these can be customized from the Permissions page in the dashboard.
Customizing Permissions
The permissions matrix is fully editable from the dashboard β no code changes required.
Navigate to Dashboard β Permissions (Admin only).
The Permissions page shows a toggle matrix for every permission key across Doctor, Receptionist, and Nurse roles. Toggle any permission on or off and click Save Permissions.
Changes take effect immediately β the next request from affected users will reflect the updated permissions.
Admin permissions cannot be modified from the UI. Admin always has full access to everything β this is hardcoded and cannot be changed.
Seeding Default Permissions
If the role_permissions table is empty, run the permissions seed script to populate it with the defaults shown in the matrix above:
npm run seed:permissionsThis is safe to run multiple times β it uses upsert logic and will not duplicate existing entries.
How Permissions Are Enforced
Permissions are enforced at two independent levels. Both must pass for an action to succeed.
Level 1 β Navigation (UI)
The sidebar navigation filters items based on the user's role and permissions. If a user does not have module.view permission, the module does not appear in the sidebar and the route is effectively hidden.
This is handled in nav-main.tsx β each nav item has a permissionKey property that is checked against the user's loaded permissions before rendering.
Level 2 β Server Actions (Backend)
Every mutation β create, update, delete β calls requirePermission() or requireRole() at the start of the server action before any database operation runs:
// Example from appointment-actions.ts
export async function createAppointment(data) {
const user = await getCachedCurrentUser();
await requirePermission("appointments.create");
// ... rest of action
}If the permission check fails, a PermissionDeniedError is thrown and the action returns an error β no data is written.
Hiding a nav item in the UI is not sufficient security on its own. CareNova always enforces permissions server-side as well. A user cannot bypass access control by navigating directly to a URL or calling a server action directly.
Where Permissions Are Stored
Permissions are stored in the role_permissions table:
Each (role, permission_key) pair is unique. When hasPermission(role, key) is called, it queries this table for the matching row and returns the granted value.
Admin is never stored in this table β the hasPermission function returns true for admin unconditionally.
Troubleshooting
A module is not visible in the sidebar for a role that should have access:
Go to Dashboard β Permissions and confirm the
module.viewpermission is toggled on for that roleCheck that
npm run seed:permissionshas been run β an emptyrole_permissionstable means no permissions are grantedHard refresh the browser after making permission changes
A user can see a module but cannot create or edit records:
The
module.viewpermission is granted butmodule.createormodule.editis notGo to Dashboard β Permissions and enable the specific action permissions needed
Permission changes not taking effect:
Permissions are loaded per-request β the user does not need to log out
Hard refresh the browser (Cmd+Shift+R)
Confirm the save was successful β check for the success toast notification
role_permissions table is empty:
Run
npm run seed:permissionsto populate with default permissionsOr go to Dashboard β Permissions and configure manually
Next Step
Continue to Audit Logs to learn how CareNova records authentication events and how admins can review system activity.