RBAC & Permissions
NearSync uses a role-based access control (RBAC) system that governs what each user can see and do. Permissions are checked at both the UI layer (navigation gating, component visibility) and the data layer (RLS policies).
System Roles
NearSync defines six system roles in ascending order of access:
| Role | Description |
|---|---|
| viewer | Read-only access to assigned modules |
| staff | Standard operational access - can create and edit records within assigned modules |
| manager | Module-level management - can manage team members' records and approve workflows |
| admin | Organization-wide administration - can configure settings, manage users, and access all modules |
| org_owner | Full organization control - includes billing, subscription management, and destructive operations |
| super_admin | Platform-level access - reserved for NearSync platform operations (managed deployments only) |
Permission Architecture
The RBAC system is built on three database tables:
Roles Table
Stores the available roles with metadata:
- Role identifier (e.g.,
admin,manager,staff) - Display name and description
- Role hierarchy level (used for determining permission inheritance)
Permissions Table
Defines individual permission keys that map to specific actions:
- Permission key (e.g.,
sales.view,finance.invoices.create,people.employees.delete) - Module scope (which HQ module the permission belongs to)
- Description of what the permission controls
Permissions follow a consistent naming pattern: module.feature.action, where actions include view, create, edit, delete, manage, and export.
Role-Permission Mappings
Maps roles to their granted permissions. A single role can have many permissions, and permissions can be shared across roles.
How Permissions Are Checked
Client-Side: Navigation Gating
The navigation system reads the current user's role and permissions to determine which HQ modules, sub-modules, and features are visible. Unauthorized modules are hidden from the sidebar entirely - they are not shown in a disabled state.
The ModuleGuard component wraps protected routes and redirects unauthorized users:
ModuleGuard checks:
1. Is the user authenticated?
2. Does the user's role grant the required permission?
3. Is the module enabled in the system manifest?
If any check fails, the user is redirected rather than shown a forbidden state.
Client-Side: Component-Level Checks
Individual UI elements (buttons, forms, actions) check permissions via the useAuth().checkPermission(key) hook. For example, the "Create Invoice" button is only rendered if the user has the finance.invoices.create permission.
Server-Side: RLS Enforcement
Row-Level Security policies reference the authenticated user's JWT claims to enforce data access at the database level. Even if the UI is manipulated to bypass client-side checks, the database will reject unauthorized queries.
See Row-Level Security for details on server-side enforcement.
Module Gating via System Manifest
Beyond RBAC, module access is also controlled by the system manifest - a per-organization configuration that defines which modules are available based on the subscription tier.
- Feature flags (60+) provide granular sub-module gating
- The
ModuleGuardcomponent checks both RBAC permissions and manifest flags - This dual gating ensures that users cannot access modules their organization has not purchased, regardless of their role
Permission Changes
- Permission changes are applied via database updates to the role-permission mapping table
- The application subscribes to realtime updates on permission tables via Supabase Realtime
- When an admin changes a user's role or modifies role permissions, the affected user's UI updates without requiring a page refresh or re-login
Adding Permissions for New Modules
When new modules are added to NearSync, a database migration defines the new permission keys and assigns default role mappings. This ensures that:
- Existing roles automatically receive appropriate access to new features
- The permission hierarchy is maintained
- No manual permission assignment is required for standard role configurations
Related Pages
- Authentication - how users are authenticated before permission checks
- Row-Level Security - how permissions are enforced at the database level
- Security Overview - how RBAC fits into the overall security architecture