Skip to content

RBAC & Permission Matrix

Role-Based Access Control (RBAC)

PLANOVI enforces a dual-layer security model:

  1. Frontend: Guarded UI components, disabled buttons, and route interception via RbacContextProvider.
  2. Backend: Postgres Row-Level Security (RLS) policies enforcing company-level isolation and role validation.

Permission Key Format

Permissions are structured as normalized lowercase strings:

$$\text{permission_key} = \text{{module_name}} _ \text{{action_type}}$$

Supported Action Types

Action TypeDB ActionDescriptionHelper Method
viewVIEWRead access to screens, lists, or telemetry.rbac.canView(module)
createCREATECreate new entities, files, or tickets.rbac.canCreate(module)
updateUPDATEEdit existing resources or update states.rbac.canEdit(module)
deleteDELETERemove records, archive assets, delete tasks.rbac.canDelete(module)
othersOTHERSHigh-level administrative operations.rbac.canManage(module)

Granular Action Helpers

  • canApprove(module): Authorize democratic resolutions or expense declarations.
  • canAssign(module): Assign field work orders to technicians.
  • canExport(module): Export financial ledger audits and Tauron CSV files.
  • canControl(module): Dispatch telemetry control instructions to inverters and batteries.

Module Permission Matrix

The table below illustrates default permission mappings across roles for the Energy Cooperative features:

Module / ScreenSuperAdmin / OwnerAdminTechnicianMemberAuditorViewer
Energy DashboardFullFullViewViewViewView
My Devices (IoT)Full / ControlFull / ControlControl / ViewView (Own)ViewView
Energy BalanceFullFullViewViewViewView
Member WalletFullView / ManageNoneView / PayViewNone
Financial LedgerFullView / ExportNoneView (Own)Audit / ExportNone
Governance CenterFullManageView / VoteVoteAuditView
Technician QueueFullAssignExecute / UpdateNoneViewNone
Knowledge BaseFullEdit / CreateViewViewViewView
Jarvis Voice AIFullFullStandardStandardStandardStandard
Scheduler & BookingsFullFullView TasksBookViewView

Usage in Flutter Widgets

To protect a button or screen section, wrap the widget with Consumer<RbacContextProvider>:

Consumer<RbacContextProvider>(
builder: (context, rbac, child) {
if (!rbac.canControl('energy_devices')) {
return const SizedBox.shrink(); // Hide button for unauthorized users
}
return ElevatedButton.icon(
icon: const Icon(Icons.power_settings_new),
label: const Text('Zmień tryb falownika'),
onPressed: () => _toggleInverterMode(),
);
},
);

For full-page guards, check rbac.canView(...) in initState() or route builders, rendering the shared ModuleMaintenanceScreen or unauthorized placeholder if permissions are absent.