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 transitionalpending_company. - End-user —
driver(works deliveries on the mobile API) andclient(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 inapp/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_adminis 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
clientsees only rows where they are the owner (their products, orders, wallet, disputes). - Assigned scope — a
driversees only orders where they are the assigned driver.
See the per-role pages for the exact permissions, screens, and endpoints of each role.