ObjectOS
ConfigurePermissions

Permission Sets

Grant application, object, field, and system permissions.

Permission sets are the primary way to grant capabilities. They can be assigned directly to users or indirectly through positions. Assignments may carry valid_from / valid_until windows — expired grants stop resolving immediately.

What permission sets control

Permission typeExamples
Application accessUser can open CRM or Setup
Object permissionsCreate, read, update, delete records
Field permissionsRead or update selected fields
System permissionsAccess Setup, run reports, view audit logs
Integration permissionsUse API keys, webhooks, or admin actions

Object permissions

Object permissions answer:

Can this user perform this operation on this object at all?

Permission set grants use these flag names (as enforced by the security plugin's permission evaluator):

FlagMeaning
allowReadRead records allowed by record access rules
allowCreateCreate records
allowEditUpdate records allowed by record access rules
allowDeleteDelete records allowed by record access rules
allowExportTake a bulk, machine-readable copy of the object's records
viewAllRecordsRead every record for the object, bypassing record access
modifyAllRecordsUpdate or delete every record for the object, bypassing record access; implies viewAllRecords for reads

Record access still matters unless viewAllRecords or modifyAllRecords bypasses the normal row-level boundary. Reserve those flags for administrative permission sets — they are effectively a tenant-wide super-user grant for that object.

Export is its own grant

Export is an object permission, not a system permission, and it is opt-in:

allowExportResult
unsetexport denied
falsedenied
trueallowed (still bounded by allowRead)

Unset used to mean "inherit read". Since ObjectStack 17.0 it means denied, and viewAllRecords / modifyAllRecords no longer confer it either — "may see all data" and "may take a bulk copy of it" are deliberately different grants.

objects: {
  deal: { allowRead: true, allowExport: true },   // ← add the grant
}

Three consequences worth planning for:

  • No shipped set carries the grant — the upgrade is what takes it away. Package-shipped sets are re-seeded on upgrade, and since ObjectStack 17.1 admin_full_access, organization_admin and the derived organization_admin_no_bypass no longer grant export on the * wildcard. There is deliberately no automatic replacement: export is granted per object, in an app's own permission set. Grant allowExport explicitly wherever admin export is intended, in a set you author. Environment-authored sets never carried it either — edit any custom set whose users export. Nothing fails at parse time, so an upgrade that edits nothing is valid metadata whose administrators have quietly lost export on every object no app set names.
  • member_default deliberately does not carry the grant, so ordinary authenticated users lose export until an admin grants it. That is the point of the flip, not an oversight.
  • A set carrying allowExport is high-privilege, so it cannot be bound to the everyone or guest audience anchors — otherwise the opt-in would be defeatable by binding an exporting set to an anonymous anchor.

Merge is most-permissive, exactly like the CRUD bits: any assigned set granting true grants export, and false and unset produce the same outcome. Reports are covered by the same axis.

System permissions

System permissions are for platform actions such as:

  • Setup access;
  • manage users;
  • manage positions and permission sets;
  • run reports;
  • manage integrations;
  • view audit logs.

Keep system permissions separate from business object permissions so administrators can audit them easily.

Start with a few named permission sets:

Permission setPurpose
Basic UserLogin and access the main application
Setup AdministratorManage users, roles, settings, and diagnostics
Report ViewerView reports and dashboards
Integration OperatorManage webhooks/API keys
Support UserRead/update support objects

Then add domain-specific sets for the customer's application.

Marking a set isDefault suggests it for assignment when the owning package is installed (this replaces the pre-13 isProfile flag).

Delegated administration

A permission set can carry an adminScope that turns its holders into scoped administrators. The scope declares:

  • where delegates may act — a business-unit subtree;
  • what they may do — manageAssignments, manageBindings, authorEnvironmentSets;
  • which permission sets they may distribute (assignablePermissionSets).

Delegates write single rows against allowlisted sets only, and every grant is stamped with granted_by for audit. Granting or authoring a set that itself has an adminScope requires the grantor to hold a strictly containing scope. Tenant-level admins bypass the gate entirely.

Field security (appendix)

Permission sets also carry field-level grants. Even when a user can read a record, individual fields can be hidden or made read-only.

Two modes

ModeEffect
HiddenField is stripped from API responses and generated views entirely
Read-onlyField is returned but writes are rejected

Where it's enforced

The same evaluator that checks object permissions applies field rules on every path — REST, ObjectQL, generated forms, exports. There is no "back door" through a lower-level API.

Typical patterns

Use caseRecommendation
HR data on sys_user (salary, SSN)Hide for everyone except an HR permission set
External system identifiersRead-only for support, writable for integration operators
Internal cost vs. customer price on productHide cost from sales, surface to finance
Notes field with PHIHide unless permission set includes the relevant clinical role

Authoring guidance

  • Default to hide rather than read-only when the field carries sensitive data — read-only still leaks the value into responses and logs.
  • Always write field-permission keys object-qualified (crm_lead.budget, not budget) — since ObjectStack 14.4 the security-fls-unqualified-key lint rejects bare keys at compile time, because they silently matched nothing.
  • Bundle field rules into permission sets that match a real job function (HR Manager, Finance Read-only) instead of inventing one set per field — easier to audit.
  • For compliance use cases, pair field security with audit log retention so you can answer "who saw this row?" after the fact.

On this page