Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions content/docs/permissions/administrator-guide.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,13 @@ is a structured spreadsheet — you never hand-write JSON:
- **Capabilities** — named grants like `manage_users` or `studio.access`.

Prefer the smallest change that works, in this order: **bind an existing set
to a position** → **clone and adjust** → **author a new set**. Editing a set
that shipped with an app creates an *environment overlay* — your change wins,
survives upgrades, and can be reset back to the vendor baseline; the API name
is immutable after creation. And keep the additive model in mind: author
to a position** → **clone and adjust** → **author a new set**. A set shipped
in code — by an app you installed, or as a platform default such as
`member_default` — can't be edited in the environment (a save answers
`403 NOT_OVERRIDABLE`): clone it and adjust the clone, which is your own set
while upgrades keep reaching the original. Sets created here, clones, and sets
saved into a writable runtime package are edited in place. The API name is
immutable after creation. And keep the additive model in mind: author
coherent capability bundles, never "subtraction sets".
Full model: [Permission Sets](/docs/permissions/permission-sets).

Expand Down Expand Up @@ -193,7 +196,8 @@ org structure, it's a business unit.

**Can I delete the built-in permission sets?** No — sets like
`member_default` and `organization_admin` are the platform baseline. Shipped
sets can be overlaid (Step 5) or simply left unassigned.
sets can't be edited in place either, but they can be cloned and adjusted
(Step 5) or simply left unassigned.

## Where is everything

Expand Down
27 changes: 16 additions & 11 deletions content/docs/permissions/permission-sets.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ A package ships its own sets (`managedBy: 'package'` + `packageId`), seeded
idempotently at boot and re-seeded on upgrade; environment-authored sets
(`platform`/`user`) are never clobbered. The data layer refuses forging package
provenance through the admin door (two-doors separation, evolved by ADR-0094 —
ordinary edits of a packaged set become environment overlays, see below), which
an edit of a set shipped in code is refused; clone it instead, see below), which
is what makes package uninstall well-defined — and enforced: uninstalling a
package (`DELETE /api/v1/packages/:id`) revokes its own sets, their
position/user bindings, and its pending audience-binding suggestions in the
Expand All @@ -329,14 +329,16 @@ goes through the data engine) is redirected into a metadata write and the
record is re-derived by an awaited projector, so the two can never drift. This
has three author-visible consequences:

- **Editing any declared set through Setup — packaged sets included** becomes
an environment overlay of that definition (the standard metadata
customization): it genuinely takes effect, where a record-only edit
previously displayed but never enforced. The row keeps its package
provenance; the Studio layered view diffs the shipped baseline against your
customization, and removing the overlay resets to the baseline. Note the
trade every overlay makes: while an overlay pins a set, the vendor's later
baseline changes don't take effect for it until you reset or re-author.
- **A set shipped in code cannot be edited in the environment.** That is a set
an installed package declares (a `*.permission.ts` file, a stack's
`permissionSets`) or a platform default such as `member_default`. Editing it
through Setup or the metadata API answers `403 NOT_OVERRIDABLE` and stores
nothing. Clone it to a new name instead (the **Clone** action on the set, or
`POST /api/v1/data/sys_permission_set` with a new name) and edit the clone:
the clone is your organization's own set, and package upgrades keep reaching
the original. Every other set (one created in this environment, a clone, or
one saved into a writable runtime package) is edited in place: the edit
lands on its one stored definition, and the record follows it.
- **The API name is immutable after creation.** It is the definition's metadata
identity, so the create form accepts it but the edit form locks it, and a
rename through the data door is rejected. Clone the set to a new name instead.
Expand All @@ -348,8 +350,11 @@ has three author-visible consequences:
packaged set entirely.

A cross-package job function needs no hand-authored cross-package set: bind
each package's own sets to one **position** (the union model adds), and use an
overlay where a packaged set must be narrowed.
each package's own sets to one **position** (the union model adds). Where a
packaged set grants too much, clone it, narrow the clone, and bind the clone
in its place: restriction is done by not granting. Narrowing the packaged set
itself is the package author's change: they edit the declaration in the
package and re-publish it (ADR-0086 two-doors).

### Declared ≠ enforced — diagnosing a frozen package set

Expand Down
Loading