Roles Overview

The 11 NQLA roles, grouped into platform, company, and end-user tiers.

3 min read

Roles Overview

NQLA controls access with role-based access control (RBAC) built on the Spatie Permission package. Every account is assigned one role; that role grants a fixed set of permissions, and the data the account can see is then scoped on top of those permissions.

The three role groups

  • Platform / staff — operate the whole platform across every tenant: super_admin, admin, staff, customer_support.
  • Company — operate a single delivery or storage company: storage_company_admin, storage_company_staff, delivery_company_admin, delivery_company_staff, and the transitional pending_company.
  • End-userdriver (works deliveries on the mobile API) and client (the merchant / seller).

The 11 roles

Role Group Data scope Purpose
super_admin Platform All (unrestricted) Full platform control — all 297 permissions
admin Platform All (cross-tenant) Day-to-day platform administration & master data
staff Platform All (read-heavy) Internal operational review of inventory & orders
customer_support Platform All (read-only) Look up users/orders/subscriptions to assist customers
storage_company_admin Company Own storage company Manage company staff + confirm inbound stock
storage_company_staff Company Own storage company Confirm/reject inbound stock (no user mgmt)
delivery_company_admin Company Own delivery company Manage drivers/staff + dispatch assigned orders
delivery_company_staff Company Own delivery company Update delivery status (no user mgmt)
pending_company Company Own pending subscription only New company awaiting admin approval
driver End-user Assigned orders only Deliver orders assigned to them
client End-user Own records only Merchant / seller — products, orders, wallet

How permissions work

  • There are 297 granular permissions (e.g. view orders, create products, approve withdrawal-requests). They are stored as Spatie permission rows and mirrored in code as constants in app/Constants/Permissions.php.
  • Access is deny-by-default: a route or action is blocked unless the role explicitly holds the required permission. Routes are gated with middleware('permission:…') and actions with @can / authorize().
  • Roles are seeded in database/seeders/SaasRoleSeeder.php. super_admin is special — it is synced to every permission, so new permissions are automatically available to it.
  • Segregation of duties is enforced for money: viewing the payout queue (manage withdrawal-requests) is a different grant from releasing funds (approve withdrawal-requests).

How scoping works

Holding a permission is necessary but not sufficient — the rows you actually see are narrowed by scope:

  • Tenant / platform scope — platform roles see records across all tenants.
  • Company scope — company roles see only records belonging to their own company (orders/inventory assigned to it, its own users).
  • Owner scope — a client sees only rows where they are the owner (their products, orders, wallet, disputes).
  • Assigned scope — a driver sees only orders where they are the assigned driver.

See the per-role pages for the exact permissions, screens, and endpoints of each role.