Roles and permissions

The permission model in detail, and how to design roles for your shop.

Every staff account carries one role, and a role is a set of permissions.

Which permissions are enforced on the server

Twenty are checked server-side today, and a request without one is refused with a 403 naming the permission:

pos.sell · pos.hold · pos.refund · pos.discount · pos.view_products · pos.open_close_register · inventory.view · inventory.adjust · inventory.stocktake · inventory.transfer · inventory.import · invoicing.view · invoicing.create · invoicing.send · invoicing.payments · crm.view · crm.edit · repairs.view · marketing.send · settings.access_levels

A few are worth being precise about. invoicing.create covers raising an invoice, issuing a credit note against one, and editing or deleting the invoice afterwards — the same authority either way. pos.open_close_register covers closing the till, and putting it on break or resuming it — the actions that stamp counted cash and the variance onto a session. Opening a register is not yet gated, because the POS screen opens one automatically when a shift starts and refusing that would leave the day with no session to reconcile against.

The reads are gated as well as the writes, which is the point of the newer ones: inventory.view, invoicing.view and crm.view decide whether stock levels, invoices and customer records come back at all, and pos.view_products covers the product catalogue wherever it is read — POS grid, barcode scan, and the product pickers in Inventory, Invoicing and Repairs. All four are held by every role on the default matrix, so unticking one is a deliberate act rather than a surprise.

crm.edit is checked on the bulk customer import, which also requires the admin role — so it narrows nothing today and exists so the gate is already right if that route's role floor is ever lowered.

The rest of the matrix currently shapes what the interface offers rather than being enforced at the API — with one qualification: most settings.* keys sit on routes that already require the admin role, which is a stricter rule than the permission would be. Where a key is genuinely unenforced, treat it as an organising tool, not as a security boundary — the real boundaries are company tenancy, store assignment on store-scoped requests, and the PIN gate.

The roles

RoleWhat it is
staffCounter staff. Sell and look things up.
supervisorRuns a shift. Refunds, discounts, the register, stock.
adminRuns the business. Everything, always.
superadminPlatform role. Not a tenant role.

What each role can do by default

A new company starts with this matrix. staff gets:

  • Point of Sale — process sales, hold sales, view products
  • View-only access to Inventory, Invoicing, CRM, Repairs and the Dashboard

supervisor adds:

  • Point of Sale — refunds, discounts, price overrides, voids, opening and closing the register, and POS reports
  • Inventory — adjustments, transfers and stocktakes
  • Invoicing — create, send and take payments
  • CRM — edit customers
  • Repairs — create and update tickets
  • Marketing — view
  • Settings — products, targets and receipts

admin holds every permission. That is not a default you can edit away — see below.

Settings — Access Levels
Staff
Supervisor
Admin
Point of Sale
POS-001Process sales
POS-002Hold / park sales
POS-003Process refunds
POS-004Apply discounts
POS-005Override a price
POS-008Open / close register
The permission matrix, showing the Point of Sale group. Every permission carries a short codePOS-003 is "Process refunds" — which is the quickest way to be precise about one in a support conversation. The admin column is switched on and disabled: admin always holds every permission, because the matrix is edited by admins and a save that could strip their own rights would lock them out of this very screen. Toggles shown are the shipped defaults.

Editing the matrix

Only the staff and supervisor columns are editable. The admin column is fixed at full access on purpose: the matrix is edited by admins, so a save that could strip admin rights would lock every admin out of the screen needed to undo it.

An empty matrix is a real setting

A company can deliberately grant staff and supervisors nothing at all. Because admin's full row set is always written alongside, that choice is stored and honoured rather than being mistaken for "this company has never customised its permissions" and silently reset to the defaults.

Permission names and codes

Every permission has a short code as well as a name — POS-003 is "Process refunds", INV-002 is stock adjustments. The code is shown beside the permission on the Access Levels screen and is the least ambiguous way to refer to one.

Permissions are grouped by area — pos.*, inventory.*, invoicing.*, crm.*, repairs.*, marketing.*, dashboard.* and settings.*. The ones that come up most often at the counter:

PermissionAllowsstaffsupervisor
pos.sellProcess salesYesYes
pos.holdHold / park salesYesYes
pos.view_productsSee the product listYesYes
pos.refundProcess refundsNoYes
pos.discountApply discountsNoYes
pos.voidVoid a saleNoYes
pos.open_close_registerOpen / close the tillNoYes
pos.view_reportsPOS reportingNoYes

pos.price_override is not in that list and no longer appears on the Access Levels screen. There is no price-override path in POS — the server re-derives every line price on a sale — so the switch controlled nothing. The key is still recognised and still stored, so no saved role was rewritten when it was hidden; it comes back if the capability is ever built. Overriding a repair price is a different, real thing, and it is gated on a supervisor or admin PIN rather than on this permission.

Roles are not the only gate

Two further checks sit alongside permissions. Staff are restricted to the store locations they are assigned to, on reads as well as on changes; owners and admins reach every shop. And a number of actions additionally require a staff PIN at the moment they are performed.

Still stuck? We answer every message.Contact support