Appearance
Convention: Permission Evaluation
Scope: how a request is actually decided — combining a permissionSet's rules with a holder's restrictions — at evaluation time. Referenced by every feature with a restrictable or building-scoped endpoint, not just Users & Access. See Permission Model for the surrounding concept (catalog, breadth, precedence, assignments); this page is the one place that spells out what an endpoint handler actually does with all of it, end to end.
The algorithm
- Gather every assignment that applies to the actor: a single read of their own permissionSetUserAssignment rows — in-scope (this request's tenant) and platform-wide (
tenantId = null) alike. This already includes access held via group membership: every group-derived grant is materialized here (sourceGroupIdset to the originating group) by synchronous propagation whenever group membership or a group's own Permission Set grants change — see Permission Model — Group access propagation. Evaluation itself never reads groupMembership or permissionSetGroupAssignment — those are the authoring source propagation reads from, not something the request path joins through. - Collect every rule naming the requested capability across the resulting permissionSets.
- Apply deny-first precedence (see Permission Model — Rule precedence): if any collected rule is
deny, the request is denied, unconditionally. Otherwise the winning rule is whicheverallowrule applies — itsscopeand its holder (the winningpermissionSetUserAssignmentrow, and the restriction on it) are carried forward to the next step. Default deny — no rule anywhere names the capability — is the base case, not a fallback error path. - Narrow by the winning rule holder's restriction, if any. A rule of
scope: allmeans "every record the permission code covers" only when its holder carries no restriction for the relevant dimension. When they do, apply one of the three enforcement modes below.
The three enforcement modes
Which mode applies depends on the shape of the endpoint being evaluated, not on the permission code or rule — the same code can be enforced differently depending on which endpoint is asking.
- List endpoint (e.g.
GET /v1/buildings): the restriction becomes aWHERE buildingId IN (values)filter layered on top of whatever the endpoint would otherwise return. - Single-record endpoint (e.g.
GET/PATCH /v1/buildings/{buildingId}, or any action against one record): the restriction becomes a membership check — is this record's resolved dimension value in the holder'svalues? If not, denied (403) even though the permission code itself is granted. - Create endpoint, for a new record under a restricted dimension: neither a list filter nor a membership check applies, since there is nothing yet to filter or check against. Instead the restriction constrains what value the new record may receive — the holder must actively choose from among their own allowed
values. There is no auto-assignment, even when the holder has only one allowed value.
Cascade through linked resources
A restriction is not limited to the record type its dimension names — it reaches through relationships to that record, and can walk more than one relationship hop before reaching the restricted dimension (e.g. a reading → gauge → building is a two-hop cascade, not a direct reference). See restrictions — cascade through linked resources for the full cascade rules. Resolving a cascade for a given target is the caller's responsibility, not something this evaluation step or the diagnostic read solves generically — see that page's own note on this.
Worked examples
- Building, single-record: a
building-restricted holder withtenant.buildings.manage(scopeall) canPATCHbuilding A only if A is in their restriction'svalues; a document attached to A is reachable under the same check, via the cascade. clientGroup, create: an external "Admin-manažer" role holding a platform-level (tenantId = null) grant restricted byclientGroupcan create a tenant only from a client belonging to one of their allowed clientGroups — the create-time mode: they choose the originating client from among the ones their restriction allows, nothing is auto-assigned.
References
- Permission Model — the surrounding concept: catalog, breadth, precedence, caching.
- groupMembership.restrictions — the restriction shape and its two dimensions.