Roles & Policies
Access control in BuildPad DaaS is split across three layers: roles, policies, and permissions.
Roles
A role is a named group (e.g., Editor, Viewer). Users can hold multiple roles simultaneously. Navigate to /roles to create and manage roles.
Each role detail page has three tabs:
- Basic Information — name, icon, parent role
- Users — users currently assigned to this role
- Policies — attach/detach policies (M2M)
Policies
A policy is the source of truth for access flags. Navigate to /policies to manage policies.
Each policy can have:
- Admin access — bypasses all permission checks globally
- App access — grants access to the DaaS Studio
- Delegate access — allows a static-token service account to pass the
X-On-Behalf-Of: <user-uuid>header; the service account’s own policies still govern what actions are permitted, but the audit log records the delegated user as the actor (server-to-server only — ignored for cookie/session requests)
Policies are attached to roles (and optionally directly to users). A user’s effective permissions are the union of all policies from all their roles.
Permissions
Each permission rule controls one action on one collection for one policy:
- Actions:
create,read,update,delete,share - Fields: which columns are accessible
- Item filter: JSON filter rule limiting which rows are accessible
- Validation: rules constraining written values
- Presets: default values injected at create time
Permission rules are configured in the permissions table on the policy detail page, under the Record-Level Access tab (module capabilities live in the adjacent Module-Level Access tab).
Permissions are evaluated as the union of all policies assigned to a user — both directly and through all their roles. Admin access on any single policy bypasses all checks for that user.
Module-Level Access
Collection permissions control data — which rows and columns someone can touch. Module-level access controls features — whether someone can use a part of the app at all.
A feature permission is called a key. Keys have names like system:logs.
You manage the list of keys on the Module Access Keys page (under Access
in the sidebar), where they are arranged in a tree. You then grant keys to a
policy on its Module-Level Access tab.
A user gets every key that any one of their policies grants.
Keys that come built in:
system:logs— lets a non-admin open the Logs pageworkflow:approve/workflow:reject— used by workflow transitions (a command can listmodule_access_keys, and the user needs either one of those keys or one of the command’s policies)
Checking keys in code
GET /api/permissions/me returns a user’s keys as a moduleAccess record, and
React components can check one with usePermissions().hasModuleAccess(key).
Be aware that this browser-side check only decides what a user sees. It cannot stop a request, so a key that protects something real must also be checked on the server. This matters because keys have no database-level safety net the way collection permissions do — if the server check is missing, nothing else catches it.
See Module Access for how to read keys over the API and check them in your own server code.
Built-in Access Check
GET /api/access — list all access records
GET /api/policies/me — effective policies for current user
GET /api/roles/me — roles for current user
GET /api/permissions/me — effective permissions for current user