Skip to main content

Console role matrix

Regenerated 2026-10-18 from FRONTEND/src/lib/consoleRbac.ts (route rules and actions), FRONTEND/src/lib/rolePermissionTemplates.ts (role to permission templates) and the router in FRONTEND/src/App.tsx.

The Console: the operator view over alerts, cases, filings and the Edge fleet

Figure 1 — The Console is a read-and-act view over the Control Plane. It never stores transaction data; transaction detail is read live from the Edge through the tunnel the Edge opens. What each role can see and do is the subject of this page.

One permission model​

The Console and the Control Plane use the same permission names (BACKEND Permission enum).

  • Controller guards use hasAuthority('<PERMISSION>'). consoleRbac.ts checks the same permission for the route or action, so the Console hides what the server would refuse. Where a Control Plane guard is role-based (hasAnyRole), consoleRbac.ts mirrors that role set and names the guard it copies (REGULATORY_FILING_ROLES, BLACKLIST_READ_ROLES, BLACKLIST_WRITE_ROLES, EDGE_CONFIG_EDITOR_ROLES, BACKFILL_PSP_ROLES).
  • At runtime the permissions come from the session (role.permissions, read from role_permissions_dynamic). The Console falls back to templatePermissionsForRole() only when the session carries no grants.
  • The tenant role templates match RoleService.PSP_ROLE_TEMPLATES (Java) and the Flyway seeds: V127 (PSP_ADMIN, PSP_USER, COMPLIANCE_OFFICER), V128 (MLRO, CASE_MANAGER, AUDITOR), V218 (PSP_ANALYST, SCREENING_ANALYST), V257 (no SAR permission for PSP_USER), V271 (every tenant PSP gets its own copy of the tenant role set) and V272 (MANAGE_ROLES and VIEW_AUDIT_LOGS for PSP_ADMIN; VIEW_AUDIT_LOGS for COMPLIANCE_OFFICER). A PSP admin may edit its own roles, so a live PSP can differ from this table.
  • SUPER_ADMIN and ADMIN hold every permission. APP_CONTROLLER holds none by template but is a platform operator.
  • Role hierarchy for role-based guards (SecurityConfig.ROLE_HIERARCHY): SUPER_ADMIN and PLATFORM_ADMIN > ADMIN > PSP_ADMIN > PSP_USER; MLRO > COMPLIANCE_OFFICER > CASE_MANAGER > INVESTIGATOR > ANALYST > VIEWER; PSP_ANALYST and SCREENING_ANALYST > ANALYST; AUDITOR > VIEWER (read-only). The hierarchy applies to hasRole/hasAnyRole guards only, not to permissions.
  • Platform operator: SUPER_ADMIN, ADMIN or PLATFORM_ADMIN on the HOKEKA_PLATFORM tenant (pspId 0), or APP_CONTROLLER (isPlatformAdmin in FRONTEND/src/lib/userAccess.ts). Platform roles can never be assigned to tenant users (RoleAssignmentPolicy).

Personas​

PersonaRole namesTenant
Platform super adminSUPER_ADMIN, ADMINHOKEKA_PLATFORM (pspId 0)
Platform operatorPLATFORM_ADMINHOKEKA_PLATFORM
PSP administratorPSP_ADMINPSP tenant
MLROMLROPSP tenant
Compliance officerCOMPLIANCE_OFFICERPSP tenant
Case managerCASE_MANAGERPSP tenant
Investigator / analystsINVESTIGATOR, PSP_ANALYST, SCREENING_ANALYST, ANALYSTPSP tenant
PSP operatorPSP_USERPSP tenant
Read-onlyAUDITOR, VIEWERPSP tenant
Fraud & riskFRAUD_ANALYST, FRAUD_MANAGERPSP tenant
Payments & disputesPAYMENTS_OPSPSP tenant
Finance & managementFINANCE_OFFICER, EXECUTIVEPSP tenant
  • The team roles come from V281 and RoleService.PSP_ROLE_TEMPLATES. None holds a SAR permission. FINANCE_OFFICER and EXECUTIVE hold only VIEW_FINANCE: aggregate KPIs and their own Hokeka invoices, no case, alert, merchant, dispute or transaction rows. PAYMENTS_OPS holds VIEW_DISPUTES, VIEW_TRANSACTION_DETAILS and VIEW_PLATFORM_HEALTH (read-only Edge health). FRAUD_MANAGER inherits FRAUD_ANALYST and nothing else.

  • BANK_AUDITOR and BANK_OFFICER exist as role names but are not assignable tenant roles. They are not in RoleAssignmentPolicy.TENANT_TEMPLATE_ROLES, and they are not platform roles.

  • At runtime PLATFORM_ADMIN holds MANAGE_USERS and MANAGE_ROLES (V224__platform_user_management_permissions.sql). The Console's fallback template for PLATFORM_ADMIN (FRONTEND/src/lib/rolePermissionTemplates.ts) does not list them. The Console uses the permissions the server returns, so the template only matters when those are missing.

Routes​

Every authenticated route in App.tsx passes through PermissionRoute, which calls canAccessRoute() with the most specific matching prefix. A user without access sees an in-app Access restricted panel. Sub-routes inherit their prefix rule (/cases/*, /transaction-monitoring/*, /users/*, /records/:recordType/:recordId, /kyc-documents/:merchantId, /psps/:pspId/configure). Legacy aliases redirect: /monitoring to /transaction-monitoring, /audit-logs to /audit, /rules to /rules-generation, /reports-center to /reports.

Public routes (no session): /login, /signup (invitation-only notice), /accept-invite, /forgot-password, /password-reset/confirm, /password-reset.html.

"Roles holding it" is computed from the role templates (platform roles at pspId 0, tenant roles at a tenant pspId).

Route prefixRequired (any of)Roles holding it
/dashboardauthenticatedall roles
/profileauthenticatedall roles
/messagesauthenticatedall roles
/transaction-monitoringVIEW_TRANSACTION_DETAILSall roles
/customer-360VIEW_PII or MERCHANT_VIEWSUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER, PSP_ANALYST, SCREENING_ANALYST, PSP_USER, AUDITOR
/market-surveillanceREPORT_VIEW or VIEW_TRANSACTION_DETAILSall roles
/mobile-moneyVIEW_TRANSACTION_DETAILSall roles
/wallet-intelligenceVIEW_TRANSACTION_DETAILSall roles
/recordsVIEW_TRANSACTION_DETAILS or VIEW_CASESall roles
/alertsVIEW_CASESall roles
/casesVIEW_CASESall roles
/networkVIEW_CASESall roles
/kyc-documentsMERCHANT_VIEWSUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER, PSP_ANALYST, SCREENING_ANALYST, PSP_USER, AUDITOR
/screeningVIEW_SCREENING_RESULTSall roles except VIEWER
/rules-generationMANAGE_RULESSUPER_ADMIN, ADMIN, PSP_ADMIN
/limits-amlMANAGE_RULES or CONFIGURE_SYSTEMSUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN
/regulatory-reportsVIEW_SAR (REPORT_VIEW alone is not enough: tipping-off)SUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER, PSP_ANALYST, SCREENING_ANALYST, AUDITOR, VIEWER
/filed-documentsVIEW_SAR and a role in REGULATORY_FILING_ROLES (SUPER_ADMIN, ADMIN, PLATFORM_ADMIN, MLRO, COMPLIANCE_OFFICER)SUPER_ADMIN, ADMIN, PLATFORM_ADMIN, MLRO, COMPLIANCE_OFFICER
/listsMANAGE_WATCHLISTS, PSP_SETTINGS_VIEW or MANAGE_PSP, or a role in BLACKLIST_READ_ROLESSUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, INVESTIGATOR, SCREENING_ANALYST, PSP_USER
/risk-analyticsREPORT_VIEWSUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER, PSP_ANALYST, PSP_USER, AUDITOR
/reportsREPORT_VIEWSUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER, PSP_ANALYST, PSP_USER, AUDITOR
/chargebacksVIEW_CASES, MERCHANT_VIEW or VIEW_DISPUTESall roles except FINANCE_OFFICER and EXECUTIVE
/compliance-calendarVIEW_SAR or REPORT_VIEWall roles except INVESTIGATOR and ANALYST
/analyticsREPORT_VIEWSUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER, PSP_ANALYST, PSP_USER, AUDITOR
/auditVIEW_AUDIT_LOGSSUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, AUDITOR
/data-access-logVIEW_AUDIT_LOGSSUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, AUDITOR
/merchantsMERCHANT_VIEW (the Control Plane scopes rows to the PSP)SUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER, PSP_ANALYST, SCREENING_ANALYST, PSP_USER, AUDITOR
/pspsMANAGE_PSP, platform operator onlySUPER_ADMIN, ADMIN, PLATFORM_ADMIN
/edge-nodesMANAGE_PSP or PSP_SETTINGS_VIEWSUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN
/edge-backfillMANAGE_PSP or a role in BACKFILL_PSP_ROLES (PSP_ADMIN, ADMIN, MLRO, COMPLIANCE_OFFICER)SUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER
/usersMANAGE_USERSSUPER_ADMIN, ADMIN, PSP_ADMIN
/settingsPSP_SETTINGS_VIEW, CONFIGURE_SYSTEM or MANAGE_PSPSUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN
/billingMANAGE_PSP or PSP_SETTINGS_VIEW (tenant users are redirected to /settings, Billing tab)SUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN
/runtime-errorsCONFIGURE_SYSTEM, platform operator onlySUPER_ADMIN, ADMIN, PLATFORM_ADMIN
/organizationPSP_SETTINGS_VIEW, tenant onlyPSP_ADMIN

"All roles" means SUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER, INVESTIGATOR, PSP_ANALYST, SCREENING_ANALYST, ANALYST, PSP_USER, AUDITOR and VIEWER.

The sidebar (buildConsoleNavGroups) shows an item only when canAccessRoute() allows its route. Groups: Intelligence (Dashboard, Live Monitoring, Customer 360, Market Surveillance, Mobile Money, Wallet Intelligence, Alerts, Cases, Messages, Network), Compliance (KYC, Screening, Risk Rules, Transaction Limits, Regulatory Reports, Filed Documents, Blocklists & Limits, Chargebacks, Compliance Calendar), Analytics (Risk Analytics, Reports, Analytics, Audit Logs, Data Access Log) and Administration. Platform operators see Merchants, PSPs, Edge Nodes, Edge Back-fill, Users, Runtime Errors and Settings; tenant users see My Organization, Merchants, Users (with MANAGE_USERS), Edge Nodes (PSP_SETTINGS_VIEW, MANAGE_PSP or VIEW_PLATFORM_HEALTH), Edge Back-fill and Settings. Compliance Calendar follows its role guard (SUPER_ADMIN, ADMIN, PLATFORM_ADMIN, COMPLIANCE_OFFICER, MLRO, PSP_ADMIN). The Help section (Edge install and setup guides) shows only to users who can open Edge Nodes.

Dashboard workspaces​

/dashboard?workspace=<id> shows one of six layouts (FRONTEND/src/lib/dashboardWorkspaces.ts). The tabs list only the workspaces the user may open; a requested workspace the user may not open falls back to the role default.

WorkspaceOpens withDefault for
fraud-riskVIEW_CASES and VIEW_TRANSACTION_DETAILSFRAUD_*, ANALYST, PSP_ANALYST, PSP_USER
complianceVIEW_SAR, or INVESTIGATOR / CASE_MANAGERMLRO, COMPLIANCE_OFFICER, CASE_MANAGER, INVESTIGATOR, SCREENING_ANALYST, VIEWER, platform staff
payments-opsVIEW_DISPUTES or VIEW_PLATFORM_HEALTH, PSP_ADMIN, platform staffPAYMENTS_OPS
finance-managementVIEW_FINANCE, PSP_ADMIN, platform staffFINANCE_OFFICER, EXECUTIVE, PSP_ADMIN
merchant-lifecycleMERCHANT_EDITnone (opened from the tabs)
platform-controlsVIEW_AUDIT_LOGS or VIEW_PLATFORM_HEALTH, platform staffAUDITOR, BANK_AUDITOR

The layout is not the security boundary. Each widget also needs the permission its endpoint checks: alert rows VIEW_CASES (DashboardController live-alerts), merchant names MERCHANT_VIEW (top-risk, merchant cases), decision rows the DecisionStatsController roles, disputes the /chargebacks route, Edge health the /edge-nodes route, invoices VIEW_FINANCE / PSP_ADMIN (PspAdminBillingController, own PSP only). Aggregate KPIs are open to any signed-in user. A drill-down link renders only when canAccessRoute() allows its target, so summary-only users keep the figures without a way into the detail. Featured-case actions follow canPerformAction().

Actions​

Action (canPerformAction)CheckRoles holding it
alert.updateStatus, alert.resolveDispositionASSIGN_CASES or CLOSE_CASES (PUT /alerts/{id}/status, /resolve)SUPER_ADMIN, ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER, INVESTIGATOR, PSP_ANALYST
alert.exportEXPORT_DATA or VIEW_CASESall roles
alert.escalateToCaseCREATE_CASESSUPER_ADMIN, ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER
case.assignASSIGN_CASESSUPER_ADMIN, ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER, INVESTIGATOR, PSP_ANALYST
case.noteADD_CASE_NOTESSUPER_ADMIN, ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER, PSP_ANALYST, PSP_USER
case.evidenceADD_CASE_EVIDENCESUPER_ADMIN, ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER, INVESTIGATOR, PSP_ANALYST
case.escalateESCALATE_CASESSUPER_ADMIN, ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER
case.closeCLOSE_CASESSUPER_ADMIN, ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER
case.reopenREOPEN_CASESSUPER_ADMIN, ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER
case.updateStatusASSIGN_CASES, CLOSE_CASES or ESCALATE_CASESSUPER_ADMIN, ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER, INVESTIGATOR, PSP_ANALYST
sar.create, sar.submitCREATE_SAR (POST /compliance/sar, /compliance/sar/workflow; a SAR without a case is raised from Edge decision records, and POST /compliance/sar/workflow/{id}/transactions sets them while DRAFT or REJECTED)SUPER_ADMIN, ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER
sar.approve, sar.rejectAPPROVE_SARSUPER_ADMIN, ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER
sar.fileFILE_SARSUPER_ADMIN, ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER
filing.fileFILE_SAR, a REGULATORY_FILING_ROLES role and not a platform operator (POST /sar/{id}/file, /ctr/{id}/file; only the PSP's own staff file)MLRO, COMPLIANCE_OFFICER
filedDocuments.viewVIEW_SAR and a REGULATORY_FILING_ROLES roleSUPER_ADMIN, ADMIN, PLATFORM_ADMIN, MLRO, COMPLIANCE_OFFICER
rules.manageMANAGE_RULESSUPER_ADMIN, ADMIN, PSP_ADMIN
users.manageMANAGE_USERSSUPER_ADMIN, ADMIN, PSP_ADMIN
roles.manageMANAGE_ROLES (a PSP admin only within its own PSP, only permissions it holds, never a platform role)SUPER_ADMIN, ADMIN, PSP_ADMIN
psp.manageMANAGE_PSPSUPER_ADMIN, ADMIN, PLATFORM_ADMIN
screening.ingestMANAGE_WATCHLISTS (POST /sanctions/download/trigger)SUPER_ADMIN, ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, SCREENING_ANALYST
screening.overrideOVERRIDE_SCREENING_MATCHSUPER_ADMIN, ADMIN, MLRO, SCREENING_ANALYST
virtualAssets.registerVirtualAssetComplianceController wallet registration and Travel Rule preparation rolesSUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER, INVESTIGATOR, PSP_ANALYST, SCREENING_ANALYST, ANALYST
virtualAssets.screenVirtualAssetComplianceController wallet/VASP screening rolesSUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER, INVESTIGATOR, PSP_ANALYST, SCREENING_ANALYST, ANALYST
virtualAssets.writeVASP records, Travel Rule policies and transmission (hasAnyRole compliance administrators)SUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER
virtualAssets.verifyIdentityTravel Rule identity verification roles (analyst-only roles excluded)SUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, CASE_MANAGER, INVESTIGATOR
blacklist.viewBLACKLIST_READ_ROLES role or MANAGE_WATCHLISTSSUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, INVESTIGATOR, SCREENING_ANALYST, PSP_USER
blacklist.manageBLACKLIST_WRITE_ROLES role or MANAGE_WATCHLISTSSUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER, SCREENING_ANALYST
edgeConfig.viewplatform operator or any user of the PSP (PspDataSettingsAccess.requireRead)all roles
edgeConfig.manageplatform operator, or the PSP's PSP_ADMIN/ADMIN (requireConfigEditor)SUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN
backfill.view, backfill.controlplatform operator, or a BACKFILL_PSP_ROLES role of the PSPSUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN, MLRO, COMPLIANCE_OFFICER
backfill.startplatform operator (LedgerBackfillAccess.requirePlatformOperator)SUPER_ADMIN, ADMIN, PLATFORM_ADMIN
billing.platformplatform operator and MANAGE_PSPSUPER_ADMIN, ADMIN, PLATFORM_ADMIN
billing.payPSP_SETTINGS_EDIT or PAY_INVOICES on the caller's own PSP (POST /billing/payments/invoices/{id}/checkout, /mpesa; V285)PSP_ADMIN, FINANCE_OFFICER
merchant.lifecycleMERCHANT_EDIT, own PSP (POST /merchants/{id}/suspend, /reactivate, DELETE /merchants/{id}; closing or suspending blocks the merchant on the PSP's Edges)SUPER_ADMIN, ADMIN, PLATFORM_ADMIN, PSP_ADMIN
runtimeErrors.viewplatform operator and CONFIGURE_SYSTEMSUPER_ADMIN, ADMIN, PLATFORM_ADMIN
ai.settingsplatform operator with CONFIGURE_SYSTEM (/settings, Hokeka AI tab; the APP_CONTROLLER service account gets no platform tab)SUPER_ADMIN, ADMIN, PLATFORM_ADMIN
dispute.recordActionMANAGE_DISPUTES (POST /chargeback/disputes/{id}/action, own PSP only; V282)SUPER_ADMIN, ADMIN, PSP_ADMIN, FRAUD_MANAGER, PAYMENTS_OPS

Alert dispositions that confirm a true positive return 202 / pending_second_review until a second, different reviewer confirms the same disposition (maker-checker, V286). A different disposition returns the alert to investigating with review status RETURNED; escalating to a case is always final. Server guards on SAR endpoints use the same permissions as the Console (VIEW_SAR, CREATE_SAR, AMEND_SAR, FILE_SAR, APPROVE_SAR); /limits needs MANAGE_RULES or CONFIGURE_SYSTEM, like the /limits-aml route. VIEW_FINANCE (finance, management) opens /settings with the Billing tab only.

Automated tests​

Vitest: FRONTEND/src/lib/consoleRbac.test.ts checks nav, route and action expectations per persona; FRONTEND/src/lib/dashboardWorkspaces.test.ts checks workspaces, row-widget exclusion and team menus. JUnit: ConsoleBackendRbacAlignmentTest evaluates the real @PreAuthorize guards for every team role. scripts/live-console-role-matrix.mjs runs the personas against a live Console.

Demo accounts (seeded)​

See BACKEND/src/main/resources/db/migration/V127__seed_demo_accounts.sql (password documented in the migration header).