Dashboard Role & Access SOP
Audience: Super Admin, Admin, Access Manager, operational team leads.
Scope: Kesles Merchant internal dashboard, Users & Access menu.
Status: v2.1 — adds the Partner Reps master data (individual sales/sellers under a partner) replacing the partner referral level.
Last reviewed: 2026-04-23.
1. Purpose
This document is the reference for:
- defining which dashboard roles may be used;
- explaining the responsibility boundary of each role and the link to actual business processes (Purchasing, Sales, Inventory, Merchant onboarding, IAM);
- setting the SOP for granting, changing, and revoking access;
- reducing over-permission on internal as well as merchant-facing accounts;
- making it easier to audit during incidents, organisational changes, or new team/merchant onboarding.
2. Access Principles
All role assignments must follow the following principles:
- Least privilege — minimum access required to do the job.
- Need-to-know — sensitive data is only seen by those with a real work need.
- Separation of duties — avoid one user holding access that lets them create, approve, and close a process without cross-control (e.g., create PO + approve PO + pay invoice).
- Named access — every user must use a personal account. Shared accounts are forbidden.
- Reviewable — every role change must be explainable: who requested, who approved, when, and why.
- Explicit scope — roles that apply per-merchant (scope
merchant) must not be used for cross-merchant access until themerchant_idcolumn is available inidentity.user_roles(see §3 & §16).
3. Role Assignment Scope
Roles in Kesles are split by their consumption scope:
Scope (identity.roles.scope) | Audience | Example Roles | Notes |
|---|---|---|---|
internal | Kesles employees | superadmin, admin, finance, operations, support, provider_admin, partner_admin | Platform-wide: a user with this role applies to the whole of Kesles, not per merchant. |
web | General web dashboard / viewer users | viewer, web_user | Read-only fallback. |
merchant | Users on the merchant side | merchant_owner, merchant_admin, merchant_staff | Designed merchant-scoped; currently still treated platform-wide because identity.user_roles does not yet have a merchant_id column. |
mobile | End-users of the mobile app | mobile_user | Not a dashboard role; included here for reference. This SOP does not govern mobile_user other than personal data policy. |
Multi-tenant implementation phase:
- Phase 1 (current): All assignments in
identity.user_rolesare platform-level. A user with themerchant_adminrole will hold those rights for EVERY merchant they touch via the dashboard — governance is performed in the SOP, not yet in the DB. - Phase 2 (planned): A migration adds
merchant_idtoidentity.user_rolesso that merchant-scoped roles can be tied to a specific merchant. Seemerchant_docs/docs/database/plans/user-merchant-plan.md. Until that migration is live,merchant-scope roles must be granted very selectively and accompanied by written approval.
4. Roles Already in the Database
Derived from the 002_seed_roles.sql seed. DB descriptions have been tidied and exposed via the GET /api/dashboard/users-access/roles endpoint (description column).
4.1 internal roles (Kesles employees)
superadmin— full cross-system control.admin— general admin and operations.provider_admin— internal provider access (see §6.3).partner_admin— internal partner access (see §6.4).finance— finance & financial reporting.operations— merchant operations, devices, receiving.support— operational assistance & user support.
4.2 web / mobile roles
viewer— read-only dashboard & reports.web_user— minimal fallback (dashboard overview + own profile).mobile_user— mobile app end-user; not relevant to the dashboard SOP.
4.3 merchant roles (merchant-facing)
merchant_owner— merchant owner.merchant_admin— merchant-level operational admin.merchant_staff— merchant staff (limited access).
Merchant-facing roles are NOT for Kesles employees. Employees who need to access merchant data must use the admin/operations/support/partner_admin role as appropriate.
5. Template Roles (Not Yet in the Database)
The six roles below are still operational candidates and have NOT been inserted into identity.roles. Activate them only if one of the following conditions is met (see also §13):
- at least 3 active users need the same combination of access;
- the existing role is too broad and risky for audit;
- a new function appears that requires clear duty segregation.
Candidate roles:
merchant_reviewer— onboarding & KYC review.compliance_auditor— broad read for audit.finance_readonly— finance read/export only (checker, not approver).access_manager— manages user & role without business access.inventory_controller— stock control, receiving, device stock.sales_ops— quotation, sales order, shipping operations.
Once activated, update the seed files 002_seed_roles.sql + 014_seed_dashboard_role_permissions_extended.sql and change the status in §6 from "proposed" to "active".
6. Role Definitions
6.1 Super Admin (superadmin)
Purpose — top role for system control, access, and override of sensitive cases.
Allowed: manage users, roles, permissions, limited overrides allowed by the system, set partner scope (global), perform secret rotation (§14 Settings → Secrets).
Not allowed: be used as a daily account; be shared between more than one person.
Suitable for: Head of Product/Tech, internal platform owner, critical incident PIC.
6.2 Admin (admin)
Purpose — general cross-domain admin operator without top-tier privileges.
Allowed: manage merchants, master data (including Partner Reps — sales/sellers per partner + referral code), purchasing/sales/inventory (full per seed 014), assign user roles (without creating new permission codes), update operational settings. Not allowed: use superadmin-only rights (create/update/delete permission catalog, rotate production secrets without approval, global override). Suitable for: core dashboard admin, ops lead, ops PM.
6.3 Provider Admin (provider_admin)
Purpose — internal access for payment provider or integrator connected to the platform (e.g., internal EDC/QRIS integration partner).
Allowed: read merchant, transactions, devices, reports; limited device binding updates; manage merchant users related to provider onboarding (scope to be limited once merchant-scoped role is live). Not allowed: manage internal roles/permissions, change global settings, access finance data outside provider-related transactions. Suitable for: provider integration team, provider on-call engineer.
6.4 Partner Admin (partner_admin)
Purpose — internal team that manages external partners/referrals (partner onboarding, revenue share, webhook, partner sales/seller master data).
Allowed: read merchants and transactions within partner access scope (see architecture/partner-access-scope-plan.md); manage partner data, revenue-share rules, and webhooks; test webhook delivery; manage Master Data → Partner Reps (add/edit/deactivate partner sales sellers + generate per-person referral codes).
Not allowed: manage non-partner internal users, change roles/permissions, change global platform settings.
Suitable for: partner operations PIC, channel/referral management.
Note: external partners do not log in to the internal dashboard. They access the API via OAuth client-credentials (
partner.api_credentials). Thepartner_adminrole is a Kesles-internal role, not a role for partner-side users.Partner sales (people) also do not have a dashboard account — their data is stored as master
partner.partner_reps(this does not replacepartner_users, which links identity.users to a partner for portal access). Upgrading to a login account is done via thelinked_user_idcolumn when the partner portal is released.
6.5 Finance (finance)
Purpose — billing, purchasing, vendor, invoice, payment, financial reporting.
Allowed: read merchants for AR/AP; access transactions + export; read vendor/PO/GR; create & pay purchase_invoice; read sales quotation/order/shipping; export reports; read currency/tax masters.
Not allowed: approve PO (still with admin/operations until approver role is split off); manage user/role; change device/inventory outside the financial-audit context.
Suitable for: finance ops, AP/AR staff, finance controller.
6.6 Operations (operations)
Purpose — merchant ops, inventory, device, shipping, receiving.
Allowed: registration queue (read/approve/reject); update device; goods receipt (create/receive); inventory adjust & manage; update sales order & shipping; create/update PO; read partner/payment_device master.
Not allowed: manage roles/users; approve finance payments; change sensitive platform settings.
Suitable for: warehouse, deployment ops, field ops coordinator, onboarding ops.
6.7 Support (support)
Purpose — investigate and resolve issues without large change rights.
Allowed: read merchants, transactions, devices, users, purchasing/sales/inventory, sessions, security_devices, audit log. Not allowed: create/update/delete operational entities; change role, settings, payment, vendor. Suitable for: internal customer support, merchant support, level-1 technical support.
6.8 Viewer (viewer)
Purpose — general read access for light audit, observation, or internal stakeholders.
Allowed: read dashboard, merchant, transactions, report, purchasing, sales, inventory, company_profile, currency, tax. Not allowed: any change. Suitable for: observer, non-operational manager, light reviewer.
6.9 Web User (web_user)
Purpose — minimal fallback for web users not yet assigned a specific role.
Allowed: dashboard overview + own profile. Not allowed: access business modules. Suitable for: temporary accounts, demo accounts, new accounts awaiting assignment.
6.10 Merchant Owner / Admin / Staff
merchant-scoped roles. Not yet wired to a dedicated merchant portal; until the merchant portal launches, these roles are only used for simulated access or when an internal admin logs in as a merchant representative.
merchant_owner— all rights at the merchant level + assign merchant users.merchant_admin— update merchant data + profile; does not assign users.merchant_staff— read merchant + update own profile.
Once merchant-scoped merchant_id is in identity.user_roles, this role will be tied per-merchant. Until then, avoid assigning to Kesles employee accounts.
6.11 Template Roles (proposed — not in DB)
Details remain relevant as the target operating model. Activation follows §5.
- Merchant Reviewer — KYC & onboarding review. Allowed: read full merchant data, update review status (when the module is available). Not allowed: finance, role mgmt, settings.
- Compliance Auditor — broad read for periodic audit. Allowed: read all business modules + company_profile + audit_log + export reports. Not allowed: change data/access/settings.
- Finance Readonly — finance analyst/checker. Allowed: read transactions, PO, vendor, invoice, payment summary; export reports. Not allowed: create PO, approve/pay invoice, manage vendor, manage users.
- Access Manager — manage IAM without business rights. Allowed: create/update users, assign/revoke roles, view matrix, perform periodic access review. Not allowed: change merchant/finance/purchasing/sales/inventory/non-IAM settings.
- Inventory Controller — stock & device movement. Allowed: read/manage inventory, goods receipt, update operational device stock, read vendor & PO as reference. Not allowed: payment approval, role management, global settings.
- Sales Ops — quotation, sales order, shipping. Allowed: read merchants, manage sales order & shipping, read transactions & sales reports. Not allowed: approve finance, manage user/role, change global settings.
7. Compact Access Matrix
R = read, W = write/manage, A = approve, — = not needed. This matrix is consistent with seed 014_seed_dashboard_role_permissions_extended.sql; check the seed file for the exact permission codes.
| Role | Dashboard | Merchant | Master Data | Purchasing | Sales | Inventory | Transaction | Device | Report | IAM | Settings |
|---|---|---|---|---|---|---|---|---|---|---|---|
| superadmin | R | W | W | W+A | W | W | W | W | W | W | W |
| admin | R | W | W (incl. Partner Reps) | W (limited A) | W | W | R | R | R | R + assign | W |
| provider_admin | R | R/W limited | — | — | — | — | R | R | R | R manage | — |
| partner_admin | R | R (scope) | W (Partner & Partner Reps) | — | — | — | R (scope) | — | R | — | — |
| finance | R | R | — | R + create + pay | R | — | W (export) | — | W (export) | — | R |
| operations | R | R + registration A | R (Partner & Partner Reps, Device) | R + create + GR receive | R + update SO/shipping | W | R | R | R | — | — |
| support | R | R | R (Partner Reps) | R | R | R | R | R | — | R + audit | — |
| viewer | R | R | R (Partner Reps) | R | R | R | R | R | R | — | R (currency/tax) |
| web_user | R | — | — | — | — | — | — | — | — | — | — |
| merchant_owner* | R | W (own) | — | — | — | — | R | — | — | W (merchant user) | — |
| merchant_admin* | R | W (own) | — | — | — | — | R | — | — | — | — |
| merchant_staff* | R | R (own) | — | — | — | — | R | — | — | — | — |
| merchant_reviewer† | R | W (review) | — | — | — | — | R | — | R | — | — |
| compliance_auditor† | R | R | R | R | R | R | R | R | R + export | R audit | R |
| finance_readonly† | R | R | — | R | R | — | R | — | R + export | — | R |
| access_manager† | R | — | — | — | — | — | — | — | — | W | — |
| inventory_controller† | R | R | R (device) | R | — | W | — | W | R | — | — |
| sales_ops† | R | R | — | — | W | R | R | — | R | — | — |
Notes:
*merchant-scoped role; fully effective oncemerchant_idis active inidentity.user_roles.†template role — not yet in the DB (see §5).- This matrix is the operational target. Backend enforcement today is still mixed — role-based (
rbac.go) and permission-based; during transition, pick the narrowest safe role.
7.1 Master Data sub-matrix
Breakdown of access on the Master Data submenu (consistent with seed 014_seed_dashboard_role_permissions_extended.sql + seed 015_seed_partner_rep_permissions.sql).
| Role | Partner | Partner Reps | Payment Devices |
|---|---|---|---|
| superadmin | W | W (CRUD) | W |
| admin | W | W (CRUD) | W |
| partner_admin | W (scope) | W (CRUD, scope) | — |
| provider_admin | — | — | — |
| finance | — | — | — |
| operations | R | R | R/W limited |
| support | R | R | R |
| viewer | R | R | — |
Permissions related to Partner Reps:
master_data.partner_rep.read— list & detail.master_data.partner_rep.create— add a new seller + generate a per-person referral code.master_data.partner_rep.update— edit PIC / status / referral code.master_data.partner_rep.delete— soft delete (setstatus='deleted'+deleted_at). Historical referral attribution remains stored inmerchant_registration_requests.referral_partner_rep_id+referral_partner_rep_namesnapshot.
8. Role Assignment Rules
- Default: a user has one primary role.
- Multi-role is used only when work needs cannot be covered by one role.
- Combinations to avoid unless explicitly approved:
finance+access_manageroperations+superadminsupport+ sensitive write rolepartner_admin+finance(cross-partner AR/AP conflict)merchant_*+ anyinternalrole
superadminmust not be granted to interns, vendors, or temporary users.- Temporary roles must have a review or revoke date (record in the ticket until the
expires_atfield is available — §16).
9. New User Onboarding SOP
Purpose
Ensure new users get the right access on day one without over-permission.
Steps
- The requester sends an access request.
- The business-function approver validates the access need.
- Admin or Access Manager creates the account in
Users & Access → Users. - Role is chosen based on work function, not formal title alone.
- The user is tested for login and verified to see only relevant menus (verify via Role Access Map).
- Approval evidence is recorded on the team's ticket/channel.
Minimum required data
- full name, work email, unit/division, direct supervisor, requested role, business reason, validity period (if temporary).
Minimum approval
viewer,support,web_user,finance_readonly: direct supervisor.finance,operations,partner_admin,provider_admin,merchant_reviewer,sales_ops,inventory_controller: function head.admin,access_manager: function head + system owner.superadmin: at least two senior internal approvers + incident/need note.
10. Role Change SOP
Used when
- moving teams, increased responsibility, temporary project, role too broad/narrow.
Steps
- Change request comes in with a written reason.
- Check the user's current role and actual access (use Role Access Map for simulation).
- Decide: full role swap / temporary role addition / role reduction / revoke.
- The approver approves.
- Admin/Access Manager performs the change in
Users & Access. - The user is asked to re-login if necessary.
- Record the change in the ticket log.
Important rules
- Do not add a new role if swapping the existing one is enough.
- Temporary roles MUST have an end date.
- After a project ends, the additional role must be revoked.
11. Offboarding & Access Revoke SOP
Trigger
- resignation, transfer to non-dashboard unit, vendor contract end, suspected account compromise, disciplinary action.
Normal steps
- HR/supervisor sends an offboarding notification.
- Access Manager/Admin disables the account ASAP (set
users.status = 'deleted'orlocked). - All additional roles are revoked via
identity.user_roles. - Check sensitive access:
superadmin,admin,access_manager,finance. - Document the revoke time in the ticket (until the
revoked_atDB column is available — §16).
Emergency steps
- Disable the account immediately without waiting for full approval.
- Reset password / force logout of all active sessions (
Sessionsmenu). - Audit the user's last actions (
Audit Logsmenu). - Report to the system owner and security/internal lead.
12. Periodic Access Review SOP
Frequency
- Monthly:
superadmin,admin,access_manager,provider_admin. - Quarterly: all write roles (finance, operations, partner_admin, merchant_*).
- Half-yearly: all dashboard users.
Review checklist
- is the user still active in that function?
- is the role still appropriate for the actual task?
- is there a multi-role no longer needed?
- is there a dormant account?
- is there a vendor/temporary account not yet revoked?
- is there a
merchant_*role held by an internal employee (anti-pattern)?
Review output
- keep / downgrade / revoke / escalate for investigation.
13. New Role Creation SOP
A new role is created if one of the following is met:
- at least 3 active users need the same access combination;
- the existing role is too broad and risky for audit;
- a new function appears that needs clear duty segregation.
Steps
- Define the business purpose of the new role (write in the SOP draft + business case).
- Create a list of menus + actions (read/create/update/delete/approve/export/assign/receive/pay).
- Compare with existing roles — overlap <90%.
- Determine the role owner (business function).
- Review by product + backend + security.
- Once approved:
- add a row to seed
002_seed_roles.sql; - add mapping to seed
014_seed_dashboard_role_permissions_extended.sql; - update this SOP (move the role from §5 to §6);
- test 403/allowed paths in Role Access Map.
- add a row to seed
14. Role Selection Guide
- View general data only:
viewer. - Help investigate without write:
support. - Manage merchant onboarding/review:
operations(ormerchant_reviewerif active). - Manage vendor, invoice, payment, purchasing:
finance(create/pay) +operations(create PO/GR). - Finance analysis/reporting only:
finance_readonly(if active). - Manage stock, receiving, device movement:
operations(orinventory_controllerif active). - Manage sales order/shipping:
operations(orsales_opsif active). - Manage partner, revenue share, webhook, and partner sales seller master data (Partner Reps):
partner_admin. - Internal payment provider integration:
provider_admin. - Manage user/role without business rights:
access_manager(if active) or limitedadmin. - Manage almost all cross-module operations:
admin. - Full control / sensitive override:
superadmin.
15. Special Guardrails
superadminmust use MFA when the feature is available.- Privileged account passwords must not be shared via plain chat/email.
- All sensitive data exports follow the data handling policy + are recorded.
- Sensitive write roles must not be used for general demos or public screen recordings.
- Secrets generated in the Settings → Secrets menu are produced locally in the browser and are NOT stored on the server; rotation of JWT / internal service keys (
INTERNAL_NOTIFICATION_API_KEYinwhatsapp-service/firebase-service/email-service, paired withWHATSAPP_SERVICE_API_KEYandCORE_API_INTERNAL_KEYon the caller side) must be coordinated simultaneously acrossmerchant_core_api,dashboard-api, and the notification services. - If a user requests "temporary" access, record the duration + owner approval in the ticket.
16. Current Implementation Gaps
This document is currently more advanced than backend enforcement. The following gaps must be acknowledged when assigning:
- Permission-based middleware not finalised. Several endpoints in
services/dashboard_api/internal/app/rbac.gostill usehasAnyRole(...)instead ofhasPermission(code). Additional permissions in seeds 013/014 are not enforced in all handlers. - Main API (
merchant_core_api) does not yet readidentity.user_roles. Full RBAC integration exists only indashboard-api; mobile/merchant flows still use internal flags. - Merchant scoping not in place.
identity.user_rolesdoes not yet havemerchant_id—merchant-scoped roles are still platform-wide. See multi-tenant plan. - Audit trail for revoked user_roles missing. Currently revoke = hard-delete row. Record in the ticket until
revoked_at,revoked_by_user_id,revoke_reasoncolumns are added. - Separation of duties not technically enforced. Risky combinations in §8.3 still rely on manual review.
- Role Access Map UI does not yet bridge create/update permission catalog. New permission codes are created via DB migration/seed, not from the UI.
- Template roles in §5 not yet inserted into the DB. Activation requires updating seeds 002 + 014.
- Dual-tier referral resolver not fully live. Migration 056 + seed 015 already provide
partner.partner_reps, but the resolver inmerchant_core_api/internal/merchant/merchant.gostill only looks uppartner.partners.referral_code. Until the resolver is updated, per-rep attribution is recorded only for registrations whose partner code matches the default rep created via data migration (step 3 in the Partner Reps implementation).
17. Recommended Next Implementations
- Move enforcement from
hasAnyRole(...)to per-action permission codes (high priority — blocks the role-template roll-out plan). - Add migrations to
identity.user_roles:merchant_id uuid null(foreign key to merchant) for phase 2 multi-tenant.revoked_at timestamptz null,revoked_by_user_id uuid null,revoke_reason text null.requested_by_user_id,approved_by_user_id,expires_atfor full audit.
- Integrate IAM into
merchant_core_api— add permission checks to relevant endpoints. - Add structured audit logs for role/permission changes (not only application logs).
- Add a monthly "access review report" job (email/Slack to the access owner).
- Activate the template roles (§5) in the DB once a concrete business case exists; build derived seeds consistently.
- Implement add/edit permission UI (currently read-only) in
Users & Access → Permissionsonce the permission catalog is to be managed outside the engineering team.
18. Architecture & Code References
Plans & designs used as the SOP basis:
architecture/partner-access-scope-plan.md— partner visibility mode, revenue share, credential override.architecture/purchasing-sales-refactor-plan.md— procurement vs selling separation, PO/GR/Invoice flow.architecture/vendor-expansion-pdf-plan.md— multi-currency PO, SWIFT, milestone approval.merchant_docs/docs/database/plans/user-merchant-plan.md— multi-tenant user × merchant.merchant_docs/docs/architecture/repo-maturation-plan.md— service ownership.runbooks/partner-access-setup.md— partner onboarding runbook.
Database seeds:
merchant_database/db_kesles_merchant/seeds/002_seed_roles.sql— 13 base roles.merchant_database/db_kesles_merchant/seeds/003_seed_permissions.sql— base permissions (24).merchant_database/db_kesles_merchant/seeds/004_seed_role_permissions.sql— base permission mapping.merchant_database/db_kesles_merchant/seeds/013_seed_dashboard_permissions_extended.sql— ~78 additional permissions (purchasing/sales/inventory/iam/settings detail).merchant_database/db_kesles_merchant/seeds/014_seed_dashboard_role_permissions_extended.sql— extra permission mapping to internal roles.merchant_database/db_kesles_merchant/migrations/056_create_partner_reps.sql—partner.partner_repstable +referral_partner_rep_id/namecolumns in registration & merchant.merchant_database/db_kesles_merchant/seeds/015_seed_partner_rep_permissions.sql— 4master_data.partner_rep.*permissions + role mapping.
Code implementation:
apps/merchant_dashboard/lib/dashboard/features/home/presentation/models/dashboard_rbac.dart— frontend role & permission enums.apps/merchant_dashboard/lib/dashboard/features/home/presentation/models/dashboard_menu.dart— permissions required per menu.services/dashboard_api/internal/app/rbac.go— role whitelist per handler (transition).services/dashboard_api/internal/app/dashboard_users_access.go— user mgmt endpoint.services/dashboard_api/internal/app/dashboard_role_access.go— role & permission mgmt endpoint.
19. Decision Log
- 2026-04-23 — SOP v2.1: add
Partner Repsmaster data (sales/seller per partner). Per-person referral code replaces the partner level; legacypartners.referral_codeis retained as a fallback for attributions not yet bound to a rep. Partner sales do not have a dashboard account — only PIC + referral_code; upgrading to a login account is done viapartner_reps.linked_user_id+partner.partner_userswhen the partner portal is released.master_data.partner_rep.*permissions are added in seed 015 with mapping: superadmin/admin/partner_admin (CRUD), operations/support/viewer (read). - 2026-04-23 — SOP v2: align with the 13 DB roles, add the assignment scope chapter, integrate Purchasing/Sales/Inventory/IAM modules.
superadminremains the strictest role and is not the default template.vieweris kept as general read-only;web_useris the minimum fallback so a new user can log in before a role is determined.supportis differentiated fromviewerbecause it needs investigative visibility (sessions, security_devices, audit log).finance_readonlyis kept as a template to separate checker from approver once the role is activated.access_manageris kept as a target for separation from businessadmin.provider_adminis officially distinguished frompartner_admin: provider = payment integrator, partner = referral / revenue share.merchant_*roles are not yet assigned to internal employees; pending the merchant portal +merchant_idinidentity.user_roles.