Skip to content

URD: Permissions

ModuleCORE-02Versionv0.6
StatusBuilt · hierarchy In-progressDate2026-06-04

Business documentation. This URD is Permissions' feature list - each feature below is one Functional Area (<AREA>). The same <AREA> keys the feature's PRDs (PRD-<AREA>-NNN) and tests (TC-<AREA>-NNN), and each feature is listed in the Delivery feature catalog. See the Feature Spine convention.

1. Purpose

Define how access to features and data is controlled. Permissions lets administrators assign roles to users, grant permissions to those roles, scope roles to a specific organization or merchant, and have every query automatically filtered to what the requesting user is allowed to see - enforced through a Casbin priority-based RBAC model with per-merchant domains.

2. Scope

IncludedExcluded
Eight fixed system roles + priority hierarchyWildcard permissions
System-role bypass (Super Admin / Admin / Operator)Permission categories / UI grouping
Automatic role-based data filteringTime- or shift-based permissions
Custom role creation with priority and scopePermission audit logging
Permission catalog (create / update / delete)Role templates / bundles
Grant / revoke permissions to rolesPer-merchant active-role switching
Grant / revoke roles to usersTechnical API specifications (see developer docs)
Effective-permission query (direct + inherited)
Per-organization & per-merchant scoping
Privilege-escalation guard

3. Definitions

TermDefinition
RoleA named access level with a numeric priority. SYSTEM (fixed) or CUSTOM (user-created).
PermissionA named action on a resource, identified by a globally unique code.
Grant (policy)A record granting a permission to a role or directly to a user.
Membership (group)A record linking a user to a role, a user to an org/merchant, or a role to an org/merchant.
Effective permissionsThe union of all permissions a user holds: direct grants + permissions inherited through roles.
Scoped roleA custom role bound to a specific organization or merchant, limiting where it applies.
DomainThe merchant a grant applies within, selected per request by the active-merchant header.
System-role bypassSuper Admin, Admin, and Operator skip all data filtering and hold every permission.
HQ-owner expansionAn Owner at a head-quarter merchant automatically reaches every sibling merchant of that organizer.
Privilege escalationManaging a role at or above the actor's own priority - always blocked.

4. Conceptual Model

Conceptual only - the full policy data model lives in the developer RBAC docs.

5. Feature Catalog

The feature list of this module. Each row is one feature (a Functional Area). Detail in §6. Mirrored in the Delivery feature catalog.

Feature IDFeaturePhaseStatusPriority
ROLEFixed RolesP1BuiltHigh
CROLECustom RolesP2BuiltHigh
PERMPermission CatalogP2BuiltHigh
GRANTGrant / RevokeP2BuiltHigh
EFFEffective Permissions & ScopeP2BuiltHigh
HIERResource, Action & Domain HierarchyP3In-progressHigh
DECLPermission DeclarationP3In-progressHigh

Status: live from Plane where mapped, otherwise registry-declared. Vocabulary mirrors Plane (state-group / phase).

6. Features

One sub-section per feature, in catalog order. Each feature keeps its description, requirements, and acceptance together. Priority = MoSCoW (Must / Should / Could / Won't).

ROLE - Fixed Roles Built

Feature ID: permissions/ROLE · Phase: P1 · PRDs: - · Dev: @nx/identity

What it does for users: eight system roles ship pre-seeded with a fixed priority order; the highest three see all data, while Owner, Cashier, and Employee are automatically limited to the organization or merchants they belong to.

Requirements

IDPRequirement
URD-ROLE-001MProvide eight fixed roles seeded at startup: Super Admin, Admin, Operator, Owner, Cashier, Employee, Customer, Guest
URD-ROLE-002MFixed (SYSTEM) roles cannot be modified or deleted
URD-ROLE-003MEach role has a numeric priority that sets its place in the hierarchy
URD-ROLE-004MSuper Admin, Admin, and Operator bypass all data filtering and hold every permission
URD-ROLE-005MOwner sees only their own organization and its merchants
URD-ROLE-006MEmployee (and Cashier) see only merchants they are assigned to
URD-ROLE-007MEvery list and count operation is filtered by the requesting user's scope
URD-ROLE-008MAutomatic filtering cannot be overridden by a user-supplied filter or direct ID access
URD-ROLE-009SAn Owner at a head-quarter merchant reaches every sibling merchant of that organizer

Acceptance

AC-ROLE-01: Data filtering by role
GivenWhenThen
Users with different rolesThey hit the same endpointSuper Admin/Admin/Operator see all; Owner sees own org; Employee/Cashier see assigned merchants
Any list/count queryRun by a scoped userFiltering is automatic and cannot be overridden
A scoped user supplies a wider filter or a foreign IDRequest is madeThe filter is ignored / access denied
AC-ROLE-02: Fixed-role protection
GivenWhenThen
Any of the eight system rolesUser tries to modify or delete itOperation rejected
A fixed role's priorityUser tries to change itRejected - priorities are immutable

CROLE - Custom Roles Built

Feature ID: permissions/CROLE · Phase: P2 · PRDs: - · Dev: @nx/identity

What it does for users: administrators and owners create their own roles with a custom name, priority, and an optional organization/merchant scope - always below their own priority - and remove them safely once no users remain assigned.

Requirements

IDPRequirement
URD-CROLE-001MAuthorized users can create custom roles with an i18n name, priority, and optional scope
URD-CROLE-002MRole identifier is auto-generated from priority + name and is unique within its scope
URD-CROLE-003MA new role's priority must be strictly lower than the creator's own highest priority
URD-CROLE-004MCustom roles can be scoped to a specific organization or merchant
URD-CROLE-005MCustom roles can be updated (name, description, priority)
URD-CROLE-006MA role cannot be deleted while users are still assigned to it
URD-CROLE-007MDeleting a role cascade-removes its permission grants and scope links
URD-CROLE-008SAn Owner can create roles scoped only to their own organization or merchants

Acceptance

AC-CROLE-01: Custom role creation
GivenWhenThen
Admin or OwnerCreates a role with priority + nameRole created with type CUSTOM, identifier auto-generated
Priority ≥ creator's ownCreation attemptedRejected (privilege escalation)
Org/merchant scope providedRole createdScope link created
Same priority + name in same scopeCreation attemptedRejected (identifier collision)
AC-CROLE-02: Role deletion
GivenWhenThen
Custom role with no usersAdmin deletesRole + grants + scope links soft-deleted
Custom role with assigned usersAdmin deletesBlocked - must unassign users first
System roleAdmin deletesRejected - fixed roles are immutable

PERM - Permission Catalog Built

Feature ID: permissions/PERM · Phase: P2 · PRDs: - · Dev: @nx/identity

What it does for users: administrators maintain the catalog of permissions - each a uniquely coded action on a resource with i18n name and description - and cannot remove one that is still in use.

Requirements

IDPRequirement
URD-PERM-001MAdmin can create permissions with a unique code, action, scope, and subject
URD-PERM-002MPermission code must be globally unique
URD-PERM-003MPermission name and description support i18n
URD-PERM-004MAdmin can update and delete permissions
URD-PERM-005MA permission with active grants cannot be deleted

Acceptance

AC-PERM-01: Permission catalog integrity
GivenWhenThen
Admin defines a permissionA unique code, action, scope, and subject are suppliedThe permission is created
A duplicate codeCreation attemptedRejected - codes are globally unique
A permission with active grantsAdmin deletesBlocked - must revoke grants first

GRANT - Grant / Revoke Built

Feature ID: permissions/GRANT · Phase: P2 · PRDs: - · Dev: @nx/identity

What it does for users: administrators attach or remove permissions on a role and assign or unassign roles to users; every operation is idempotent and blocked when it would touch a role at or above the actor's own priority.

Requirements

IDPRequirement
URD-GRANT-001MAdmin can grant one or more permissions to a role
URD-GRANT-002MAdmin can revoke one or more permissions from a role
URD-GRANT-003MGranting an already-granted permission is idempotent (skipped, not duplicated)
URD-GRANT-004MAdmin can grant and revoke roles to/from users
URD-GRANT-005MPrivilege-escalation guard is enforced on every grant/revoke operation
URD-GRANT-006MAdmin can view all permissions granted to a role
URD-GRANT-007MAdmin can view all users assigned to a role and all roles assigned to a user

Acceptance

AC-GRANT-01: Permission grant
GivenWhenThen
Role + permission IDsAdmin grantsGrant records created, count returned
Permission already grantedAdmin grants againSkipped (idempotent), skip count returned
Actor priority ≤ role priorityAdmin grantsRejected (privilege escalation)

EFF - Effective Permissions & Scope Built

Feature ID: permissions/EFF · Phase: P2 · PRDs: - · Dev: @nx/identity

What it does for users: anyone can ask what a user is actually allowed to do - the deduplicated union of direct grants and role-inherited grants - and which organizations and merchants they belong to, resolved within the active merchant domain.

Requirements

IDPRequirement
URD-EFF-001MCompute effective permissions as the union of direct + role-inherited grants (deduplicated)
URD-EFF-002SThe query supports a mode filter: direct, inherit, or both
URD-EFF-003MRetrieve all organizations and all merchants a user belongs to
URD-EFF-004MA grant resolves only within the active merchant domain chosen per request

Acceptance

AC-EFF-01: Effective permissions
GivenWhenThen
User with roles + direct grantsEffective queryUnion of direct + inherited, deduplicated
Mode = directQueryOnly direct grants returned
Mode = inheritQueryOnly role-inherited grants returned

HIER - Resource, Action & Domain Hierarchy In-progress

Feature ID: permissions/HIER · Phase: P3 · PRDs: PRD-HIER-001 · Map: Permission Hierarchy · Dev: @nx/identity

What it does for users: permissions form a resource tree × action lattice × domain tree, so one coarse grant (e.g. Sale:manage) replaces many flat grants - covering every subject, operation, and merchant beneath it.

Requirements

IDPRequirement
URD-HIER-001MA grant MAY target a resource at any level - module, subject, or operation - and automatically covers all descendants
URD-HIER-002MOperation resources nest under their subject by dotted code (SaleOrder.refundSaleOrder) with no extra configuration
URD-HIER-003MA subject MAY roll up to a module so a module-level grant covers every subject in it (grant on SaleSaleOrder, SaleOrderItem, …)
URD-HIER-004SA child entity MAY nest under a parent across naming (SaleOrderItemSaleOrder) so the parent grant covers the child
URD-HIER-005MActions form a lattice - manage ⊃ {write, read, execute}, write ⊃ {create, update, delete} - a broader granted action satisfies any narrower request
URD-HIER-006MA route requests a base action (read/create/update/delete/execute); a grant MAY use any tier including manage/write
URD-HIER-007MA grant scoped to an Organizer applies to every merchant under it; a grant scoped to a Merchant applies only there
URD-HIER-008MA head-quarter / management role reaches all merchants of its organizer via an organizer-scoped grant - without a per-merchant membership row
URD-HIER-009SA grant MAY pin to SYSTEM_WIDE (everywhere) or ANY_MEMBER (every joined merchant)

Acceptance

AC-HIER-01: Coarse grant covers descendants (manage example)
GivenWhenThen
A role granted (SaleOrder, manage)A request to read SaleOrder.refundAllowed - manage ⊃ read (lattice) and SaleOrder.refund ⊂ SaleOrder (dotted)
A role granted (Sale, manage) (module)Any operation on SaleOrderItemAllowed - SaleOrderItem ⊂ Sale (module roll-up)
A role granted (SaleOrder, read) onlyA request to create SaleOrderDenied - read does not cover create
AC-HIER-02: Domain scope (organizer vs merchant / HQ)
GivenWhenThen
A role granted on Organizer_9A request in any Merchant under organizer 9Allowed via g3 - no per-merchant membership needed
A role granted on Merchant_7 onlyA request in Merchant_8Denied - scope is a single merchant
An HQ/management user (organizer-scoped grant)Acting on any sibling merchantAllowed - reaches all merchants of the organizer

DECL - Permission Declaration In-progress

Feature ID: permissions/DECL · Phase: P3 · PRDs: PRD-HIER-001 · Dev: @nx/identity

What it does for users: permissions, the action lattice, and the resource/domain hierarchy are declared in code with minimal boilerplate and seeded idempotently, so a new controller needs one helper call and removed codes are reconciled away automatically.

Requirements

IDPRequirement
URD-DECL-001MPermissions, the action lattice, and resource/domain hierarchy edges are declared in code and seeded idempotently
URD-DECL-002MDeclaring a controller's operations + resource node + base action takes minimal boilerplate (one helper call)
URD-DECL-003MRole→grant assignment is declared as a small matrix (e.g. OWNER → Sale:manage), not a per-operation enumeration
URD-DECL-004MSeeding reconciles removed codes idempotently - no stale permissions/grants accumulate
URD-DECL-005CThe toolkit is built in nx-seller first, with a clear path to port into IGNIS later

Acceptance

AC-DECL-01: Minimal-boilerplate declaration
GivenWhenThen
A new controllerAuthor declares its resource + operations in one helper callPermissions + route authorize specs are produced without enumerating CRUD
The action lattice + hierarchy edgesMigrations rung5/g4/g3 edges seeded idempotently; re-run changes nothing
A permission code removed from the declarationMigrations runThe stale permission + its grants are reconciled away

7. Constraints & Non-Goals

Constraints

IDConstraint
C-01Eight fixed roles are seeded at startup and are immutable
C-02No one can create or manage a role at or above their own priority
C-03Permission codes are globally unique
C-04Grant operations are idempotent
C-05All records are soft-deleted, never physically removed
C-06The session token is stateless - role/permission changes take effect on next sign-in
C-07All operations require authentication
C-08A grant resolves within one active merchant domain per request

Non-Goals

  • Arbitrary glob/regex permissions (e.g. sales.*) - coarse access comes from the resource tree + manage action (HIER), not globs
  • Time- or shift-based permissions
  • Permission audit log
  • Per-merchant active-role switching

Superseded by HIER: the former non-goals "wildcard permissions", "permission categories / UI grouping" (now module roll-up), and "role templates / bundles" (now a coarse role→grant matrix) are replaced by the resource/action/domain hierarchy.

8. Version History

DateAuthorDescriptionVer
2026-02-26P. Do - Product OwnerInitial user storiesv0.1
2026-04-16ProductRestructured to URD formatv0.3
2026-05-29ProductMigrated to module-docs convention; reconciled with Casbin per-merchant RBAC (8 roles, priorities, domains); re-keyed areas (ROLE/CROLE/PERM/GRANT/EFF)v0.4
2026-06-04ProductAdded Resource/Action/Domain Hierarchy (HIER) + Permission Declaration (DECL) areas for the resource-action-hierarchy increment (PRD-HIER-001); superseded wildcard/categories/bundles non-goalsv0.5
2026-06-04Claude (AI pair)Reorganize by feature (Feature Spine); each feature carries its own requirements + acceptancev0.6

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