ZuloOne
English
Sign in
Menu

Permissions

Updated

A role is a named set of grants. The matrix is object permissions (MetaObjectPermissions): Role × object × permission type × granted. The kernel checks that matrix on the API. The current user answers who is writing, not what they may do.

This page is tenant roles and object permissions, not the hosting account.

Note

An object with no permission rows is public to any authenticated caller (PermissionPolicy.AllowOnEmptyMatrix). A command with no Execute row is open to everyone. That trap is already on Approve a purchase order: grant Execute on the command in the role, or the button is not a gate.

POST /api/commands/{id}/execute asks the permission service for object type Command, that command's MetaId, permission type Execute. Until a row exists, the check passes. After the first row, the caller needs a granted role.

The same empty-matrix rule is the default for business objects (dictionary, document, register, …). That default is intentional: tightening it would lock unfinished tenants. A web service that must not be public sets requireExplicitRoles so Execute is required before anybody can call it.

Every stand seeds three system roles for the phone: Agents (SalesAgent), Sales managers (Manager), Warehouse (Storekeeper). SecuritySeeder creates the roles; after the business layer is installed, MobileRoleSeeder writes Allow cells from the embedded seeds (Master → Read, transactional document → Read/Create/Update/Post, named document command → Execute). The same pass seeds five office contours with no mobile view: Sales, Purchasing, Accountant, HR, Production (OfficeRoleGrants — documents Read/Create/Update/Post, write dictionaries Read/Create/Update, bound document commands Execute; Sales does not get Approve/Reject on the sales order). Warehouse also receives the office inventory documents. Registers are omitted: a Read cell on a register would close Write. Those cells are insert-if-missing, so a later Revoke on the role stays. They are also the first rows on SalesOrder, PickTask, and the rest — after that, a login without one of those roles (or a superuser) cannot touch those objects in the office either. Grant a role assigns the login; Install the phone app is the path.

Named capabilities (Admin, Developer, Set closed / Set audit / Post in audit on the posting boundary) are the other half. Nobody holds a named permission until a role is granted — default deny, unlike the object matrix. A role marked superuser bypasses the model.

A role inherits its parents (MetaRoleInheritances). An explicit deny on the caller's own role wins even if another role grants. A parent's deny only silences that branch.

ZuloOne:CoreDevelopmentMode=true skips RequirePermission so the test rig stays open. Production (false) requires an authenticated user on every endpoint that is not [AllowAnonymous].

The office keeps the JWT in HttpOnly cookies. Mobile and agents still send Authorization: Bearer. That is how the caller is identified. The matrix above is what they may do. Designer writes, compile, data transfer, and the other closed gates are Auth and API gates — not this page.

A register with any permission row does not leave Write open when only Read was granted.

See also#

Where next#

Was this page helpful?