Roles, permissions & module access
Three database roles plus per-person module access form the permission model. Enforced at the database level via row-level security — hidden UI buttons are never the only line of defense.
Every person in a restaurant carries exactly one role. On top of the role, each person has a per-module access list — so two managers can see different modules depending on the workspace configuration.
Database roles
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| admin | role | — | — | Full operational power in the restaurant. Sees every module, manages the team and reservation policies. On first setup the workspace owner becomes admin of their restaurant. |
| manager | role | — | — | Like admin but without billing access and a few configuration paths. Typical for deputy managers or shift leads with administrative responsibility. |
| employee | role | — | — | Operational role. Sees only assigned modules by default — for example service staff see reservations, knowledge and chat. Module access is fine-tuned per person. |
Onboard's own support role. Platform admins are not staff of a restaurant and don't appear in day-to-day operations — but they can cross tenants for support. Every action by a platform admin is flagged separately in the audit log.
Module access
On top of the role, each person has a list of modules they may access. The list is pre-filled at invite time — managers get everything, employees get nothing — and admins can adjust it per person. Example: a bartender sees Reservations and Chat but not Reports. A back-office employee sees Reports and Vouchers but not Shifts.
How access is enforced
Module access is enforced in three layers that must all agree:
- Middleware. Rejects RSC requests against module URLs the user is not entitled to. Blocks direct page hits.
- Server-side guard. Every module-bound server component calls
assertModuleAccess(). Locks down static generation and fetch bypasses. - Database RLS. Postgres policies check restaurant_id and role from the JWT. Even if middleware and guard failed, the database would not hand out cross-tenant rows.
Multi-location
In multi-location setups, a person can carry a different role per location — admin at headquarters, manager at the branch, no role at the bar. Data is location-isolated; RLS policies enforce that at the database level. More on location separation.