Lewati ke konten utama

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:

  1. Least privilege — minimum access required to do the job.
  2. Need-to-know — sensitive data is only seen by those with a real work need.
  3. 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).
  4. Named access — every user must use a personal account. Shared accounts are forbidden.
  5. Reviewable — every role change must be explainable: who requested, who approved, when, and why.
  6. Explicit scope — roles that apply per-merchant (scope merchant) must not be used for cross-merchant access until the merchant_id column is available in identity.user_roles (see §3 & §16).

3. Role Assignment Scope

Roles in Kesles are split by their consumption scope:

Scope (identity.roles.scope)AudienceExample RolesNotes
internalKesles employeessuperadmin, admin, finance, operations, support, provider_admin, partner_adminPlatform-wide: a user with this role applies to the whole of Kesles, not per merchant.
webGeneral web dashboard / viewer usersviewer, web_userRead-only fallback.
merchantUsers on the merchant sidemerchant_owner, merchant_admin, merchant_staffDesigned merchant-scoped; currently still treated platform-wide because identity.user_roles does not yet have a merchant_id column.
mobileEnd-users of the mobile appmobile_userNot 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_roles are platform-level. A user with the merchant_admin role 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_id to identity.user_roles so that merchant-scoped roles can be tied to a specific merchant. See merchant_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):

  1. at least 3 active users need the same combination of access;
  2. the existing role is too broad and risky for audit;
  3. 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). The partner_admin role 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 replace partner_users, which links identity.users to a partner for portal access). Upgrading to a login account is done via the linked_user_id column 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.

RoleDashboardMerchantMaster DataPurchasingSalesInventoryTransactionDeviceReportIAMSettings
superadminRWWW+AWWWWWWW
adminRWW (incl. Partner Reps)W (limited A)WWRRRR + assignW
provider_adminRR/W limitedRRRR manage
partner_adminRR (scope)W (Partner & Partner Reps)R (scope)R
financeRRR + create + payRW (export)W (export)R
operationsRR + registration AR (Partner & Partner Reps, Device)R + create + GR receiveR + update SO/shippingWRRR
supportRRR (Partner Reps)RRRRRR + audit
viewerRRR (Partner Reps)RRRRRRR (currency/tax)
web_userR
merchant_owner*RW (own)RW (merchant user)
merchant_admin*RW (own)R
merchant_staff*RR (own)R
merchant_reviewer†RW (review)RR
compliance_auditor†RRRRRRRRR + exportR auditR
finance_readonly†RRRRRR + exportR
access_manager†RW
inventory_controller†RRR (device)RWWR
sales_ops†RRWRRR

Notes:

  • * merchant-scoped role; fully effective once merchant_id is active in identity.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).

RolePartnerPartner RepsPayment Devices
superadminWW (CRUD)W
adminWW (CRUD)W
partner_adminW (scope)W (CRUD, scope)
provider_admin
finance
operationsRRR/W limited
supportRRR
viewerRR

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 (set status='deleted' + deleted_at). Historical referral attribution remains stored in merchant_registration_requests.referral_partner_rep_id + referral_partner_rep_name snapshot.

8. Role Assignment Rules

  1. Default: a user has one primary role.
  2. Multi-role is used only when work needs cannot be covered by one role.
  3. Combinations to avoid unless explicitly approved:
    • finance + access_manager
    • operations + superadmin
    • support + sensitive write role
    • partner_admin + finance (cross-partner AR/AP conflict)
    • merchant_* + any internal role
  4. superadmin must not be granted to interns, vendors, or temporary users.
  5. Temporary roles must have a review or revoke date (record in the ticket until the expires_at field is available — §16).

9. New User Onboarding SOP

Purpose

Ensure new users get the right access on day one without over-permission.

Steps

  1. The requester sends an access request.
  2. The business-function approver validates the access need.
  3. Admin or Access Manager creates the account in Users & Access → Users.
  4. Role is chosen based on work function, not formal title alone.
  5. The user is tested for login and verified to see only relevant menus (verify via Role Access Map).
  6. 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

  1. Change request comes in with a written reason.
  2. Check the user's current role and actual access (use Role Access Map for simulation).
  3. Decide: full role swap / temporary role addition / role reduction / revoke.
  4. The approver approves.
  5. Admin/Access Manager performs the change in Users & Access.
  6. The user is asked to re-login if necessary.
  7. 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

  1. HR/supervisor sends an offboarding notification.
  2. Access Manager/Admin disables the account ASAP (set users.status = 'deleted' or locked).
  3. All additional roles are revoked via identity.user_roles.
  4. Check sensitive access: superadmin, admin, access_manager, finance.
  5. Document the revoke time in the ticket (until the revoked_at DB column is available — §16).

Emergency steps

  1. Disable the account immediately without waiting for full approval.
  2. Reset password / force logout of all active sessions (Sessions menu).
  3. Audit the user's last actions (Audit Logs menu).
  4. 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

  1. Define the business purpose of the new role (write in the SOP draft + business case).
  2. Create a list of menus + actions (read/create/update/delete/approve/export/assign/receive/pay).
  3. Compare with existing roles — overlap <90%.
  4. Determine the role owner (business function).
  5. Review by product + backend + security.
  6. 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.

14. Role Selection Guide

  • View general data only: viewer.
  • Help investigate without write: support.
  • Manage merchant onboarding/review: operations (or merchant_reviewer if 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 (or inventory_controller if active).
  • Manage sales order/shipping: operations (or sales_ops if 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 limited admin.
  • Manage almost all cross-module operations: admin.
  • Full control / sensitive override: superadmin.

15. Special Guardrails

  1. superadmin must use MFA when the feature is available.
  2. Privileged account passwords must not be shared via plain chat/email.
  3. All sensitive data exports follow the data handling policy + are recorded.
  4. Sensitive write roles must not be used for general demos or public screen recordings.
  5. 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_KEY in whatsapp-service / firebase-service / email-service, paired with WHATSAPP_SERVICE_API_KEY and CORE_API_INTERNAL_KEY on the caller side) must be coordinated simultaneously across merchant_core_api, dashboard-api, and the notification services.
  6. 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:

  1. Permission-based middleware not finalised. Several endpoints in services/dashboard_api/internal/app/rbac.go still use hasAnyRole(...) instead of hasPermission(code). Additional permissions in seeds 013/014 are not enforced in all handlers.
  2. Main API (merchant_core_api) does not yet read identity.user_roles. Full RBAC integration exists only in dashboard-api; mobile/merchant flows still use internal flags.
  3. Merchant scoping not in place. identity.user_roles does not yet have merchant_idmerchant-scoped roles are still platform-wide. See multi-tenant plan.
  4. Audit trail for revoked user_roles missing. Currently revoke = hard-delete row. Record in the ticket until revoked_at, revoked_by_user_id, revoke_reason columns are added.
  5. Separation of duties not technically enforced. Risky combinations in §8.3 still rely on manual review.
  6. 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.
  7. Template roles in §5 not yet inserted into the DB. Activation requires updating seeds 002 + 014.
  8. Dual-tier referral resolver not fully live. Migration 056 + seed 015 already provide partner.partner_reps, but the resolver in merchant_core_api/internal/merchant/merchant.go still only looks up partner.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).
  1. Move enforcement from hasAnyRole(...) to per-action permission codes (high priority — blocks the role-template roll-out plan).
  2. 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_at for full audit.
  3. Integrate IAM into merchant_core_api — add permission checks to relevant endpoints.
  4. Add structured audit logs for role/permission changes (not only application logs).
  5. Add a monthly "access review report" job (email/Slack to the access owner).
  6. Activate the template roles (§5) in the DB once a concrete business case exists; build derived seeds consistently.
  7. Implement add/edit permission UI (currently read-only) in Users & Access → Permissions once the permission catalog is to be managed outside the engineering team.

18. Architecture & Code References

Plans & designs used as the SOP basis:

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.sqlpartner.partner_reps table + referral_partner_rep_id/name columns in registration & merchant.
  • merchant_database/db_kesles_merchant/seeds/015_seed_partner_rep_permissions.sql — 4 master_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 Reps master data (sales/seller per partner). Per-person referral code replaces the partner level; legacy partners.referral_code is 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 via partner_reps.linked_user_id + partner.partner_users when 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.
  • superadmin remains the strictest role and is not the default template.
  • viewer is kept as general read-only; web_user is the minimum fallback so a new user can log in before a role is determined.
  • support is differentiated from viewer because it needs investigative visibility (sessions, security_devices, audit log).
  • finance_readonly is kept as a template to separate checker from approver once the role is activated.
  • access_manager is kept as a target for separation from business admin.
  • provider_admin is officially distinguished from partner_admin: provider = payment integrator, partner = referral / revenue share.
  • merchant_* roles are not yet assigned to internal employees; pending the merchant portal + merchant_id in identity.user_roles.