ObjectOS
ConfigurePermissions

Permissions

Identity, positions, permission sets, record access, and field security — the whole access model on one page.

ObjectOS has a layered access model borrowed from the playbook that's worked in enterprise software for two decades: identity → positions → permission sets → record access → field security. Each layer answers a different question, and you can ignore the ones you don't need. (ObjectStack 13 consolidated the legacy Roles and Profiles concepts into positions — see Positions.)

The model in one diagram

Authentication       Who is the caller?

Identity             Which user/org/membership is active?

Positions            Which job functions do they hold?

Permission sets      What CAN they do — apps, objects, fields, system?

Record access        WHICH records can they touch?

Field security       For those records, which FIELDS are readable / writable?

Each layer is enforced by the security plugin. You can use just permission sets (no positions, no sharing rules) for simple apps and add the rest as the requirement appears.

Layer 1 — Identity

Identity objects live in your project database. The most important ones:

ObjectWhat it represents
sys_userA person or service account that can authenticate
sys_organizationTenant / workspace boundary (multi-tenant apps)
sys_memberA user's membership in an organization
sys_business_unit, sys_teamOptional org structure for sharing rules
sys_invitationPending invite waiting to be accepted
sys_sessionActive authenticated session
sys_api_keyLong-lived programmatic credential bound to a user

In a multi-tenant deployment:

  • Users are scoped to the project database.
  • Sessions are scoped to the project hostname.
  • Row-level checks use the current user's organization and permissions.
  • Control-plane users are not automatically business users — they must be mapped in via platform SSO or explicit provisioning.

You create/manage these from Console (/_console/) at runtime, or seed them in objectstack.config.ts for fresh environments.

Layer 2 — Positions

Positions model job functions ("Sales Manager", "Support Agent"). They are flat — hierarchy lives on the business-unit tree, so sharing rules and reports say things like "the record owner's unit and subordinate units." Two seeded audience anchors, everyone (all authenticated users) and guest (anonymous callers), let you bind baseline permission sets without custom fallback logic. Use positions to distribute permission sets by function; skip custom positions for flat teams.

See Positions.

Layer 3 — Permission sets

Permission sets are the primary way to grant capabilities. They attach to users directly or via positions.

What they grant

TypeExamples
Application accessOpen CRM, open the support portal
Object permissionsCreate / read / update / delete records of an object
Field permissionsRead or update specific fields
System permissionsAccess Console, run reports, export data, view audit log
Integration permissionsUse API keys, configure webhooks, run admin actions

Object permission flags

These are the exact flag names the security plugin checks:

FlagMeaning
allowReadRead records the user can see via record access
allowCreateCreate new records
allowEditUpdate records the user can see
allowDeleteDelete records the user can see
viewAllRecordsRead every record for the object, ignoring record-access rules
modifyAllRecordsUpdate/delete every record; implies viewAllRecords

viewAllRecords and modifyAllRecords are tenant-wide super-user grants for that object. Reserve them for explicit administrative permission sets and keep them out of any user-facing position.

See Permission Sets.

Layer 4 — Record access

For users without viewAllRecords, which rows can they see?

The model supports:

  • Implicit ownership (rows the user created or owns)
  • Sharing rules (declarative — "team A sees team A's records")
  • Explicit shares (sys_record_share rows — one-off shares, granted to a user, position, or unit-and-subordinates)
  • Organization scoping (the row's organization_id matches the user's organization)

Since ObjectStack 13, custom objects with an owner field default to a private sharing model — declare sharingModel explicitly to open them up.

See Record Access.

Layer 5 — Field security

Even when a user can see a record, individual fields can be:

  • Hidden — field is stripped from API and UI responses.
  • Read-only — field is returned but rejected on write.

Field security is per object + per permission set. Typical use:

  • Hide salary on sys_user from anyone outside HR.
  • Make external_account_id readable but not editable to support reps.

It's enforced in the same evaluator as object permissions, so it applies uniformly across REST, ObjectQL, and Console.

Where to start

If you're building …Use
A single-team internal toolPermission sets only
A multi-team app with managers seeing reportsBusiness units + positions + permission sets
A multi-tenant SaaS-shaped appOrg scoping + permission sets
A regulated app with PIIAdd field security on top
A complex CRM-style appThe full stack

Diagnose & audit

  • The explain engine (explain(principal, object, operation)) reports the verdict of every layer in order — required permissions, object CRUD, field security, OWD baseline, sharing, row-level security — with per-layer attribution. Console surfaces it as the "Why can this user access?" panel. Explaining another user requires the manage_users capability.
  • /_console/ shows the effective permissions of any user as they're evaluated.
  • Audit log (sys_audit_log) records permission-sensitive changes — grants, role assignments, permission-set edits.
  • Denied requests log the failing rule (object permission vs record access vs field security) so support can answer "why can't I see this?" quickly.

On this page