Skip to content

PRD: Fixed & custom roles

ModulePermissionsPRD IDPRD-ROLE-001
StatusReady to devFEATROLE
EpicPlaneBANA-1512
Date2026-05-27Versionv1.0
Packages@nx/identityURDROLE
SurfaceClient · Owner/MgrBO · Ops
OwnerPhát Nguyễn

What fixed & custom roles are

BANA controls feature and data access through a priority-based RBAC model with per-merchant scope. The mechanism itself has no opinion about which roles exist or who may create them - that's the role layer's job. Without it, every merchant would start empty: no default access levels, nothing stopping an admin from minting a role more powerful than themselves, and no way to limit a role to one organizer or merchant.

This PRD builds that role layer: eight fixed roles (Role) that ship with every merchant from day one, plus a mechanism for Admin/Owner to create their own custom roles without ever breaking the platform's baseline access model. It's the foundation the rest of the Permissions module (grants, effective permissions, hierarchy) builds on.

Why a role layer is needed

A merchant needs sensible defaults the moment it is created, a fixed set of roles no one can tamper with, and the freedom for Admin and Owner to define narrower roles for their own staff. Roles also have to line up with the per-merchant scope model, so a role's scope travels with the user when they sign in, and role listings filter by merchant and organizer.

From a new organizer to a custom role

Every merchant has eight fixed roles ready from the moment it is created (Super Admin, Admin, Operator, Owner, Cashier, Employee, Customer, Guest), ranked by a numeric priority; the top three - Super Admin, Admin, Operator - bypass all data filtering, while Owner sees only their own organizer and merchants, and Employee/Cashier see only assigned merchants.

The moment a user creates an organizer, they get the Owner role assigned automatically, no manual grant needed.

On the Client app, the Team section has a Role screen where Admin/Owner create custom roles: set a bilingual name, pick a priority from 3 tiers - High/Medium/Low (no typing raw numbers), choose the scope, and pick the permission tree to grant. A new role's priority must always be strictly below the creator's own highest priority - no one can ever create a role at or above their own level.

Deleting a custom role is blocked while users remain assigned to it; a successful delete cascades away every grant and scope link that belonged to it. On the Back Office, operations staff manage roles the same way, filtered by organizer or merchant.

The easiest place to get it wrong

The Edit/Delete buttons show for everyone, the server does the blocking

Fixed roles can never be deleted; editing a fixed role's name, description, or priority is reserved for callers who hold Operator or above. On the form, the priority field is locked for every fixed role regardless of who's viewing it, but the Edit button still shows for everyone - the server is what actually rejects the request when someone without enough privilege submits.

The UI never hides an action based on the viewer's permission. Clicking a button you don't have permission for gets you rejected with a clear message, not a button that disappeared first.

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.