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
7 changes: 4 additions & 3 deletions content/docs/build/automation/approvals.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Each entry in `approvers` names a `type` and a `value`:
| `team` | Members of a flat collaboration team |
| `field` | The user id held in a field on the triggering record |
| `user` | One named user id |
| `org_membership_level` | An org-membership tier (`owner` / `admin` / `delegated_admin` / `member`) |
| `org_membership_level` | An [org-membership tier](/docs/configure/users#organization-membership-tiers) (`owner` / `admin` / `delegated_admin` / `member`) |
| `expression` | A CEL expression resolved at node entry — see below |

Prefer the indirect bindings (`manager`, `position`, `department`,
Expand All @@ -84,8 +84,9 @@ should no longer see them.

> **Warning — `position` vs the membership tier.**
> `{ type: 'position', value: 'finance_manager' }` routes to the holders of a
> position (`sys_user_position`). The org-membership tier (`sys_member.role`:
> `owner`/`admin`/`delegated_admin`/`member`) is addressed as
> position (`sys_user_position`). The
> [org-membership tier](/docs/configure/users#organization-membership-tiers)
> (`sys_member.role`: `owner`/`admin`/`delegated_admin`/`member`) is addressed as
> `type: 'org_membership_level'` since 16.0; the old spelling `role` is a
> **deprecated alias for one release** — it still loads and resolves
> identically, with a warning, and is removed in the next major. A position name
Expand Down
3 changes: 2 additions & 1 deletion content/docs/configure/notifications.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ selector string goes through the same resolver. Whether either belongs in a
standing subscription is an open question the platform has not settled.

> **`role:` here means the organization-membership tier, not a job function.**
> The tiers are `owner`, `admin`, `delegated_admin`, and `member` — the standing
> The tiers are [`owner`, `admin`, `delegated_admin`, and
> `member`](/docs/configure/users#organization-membership-tiers) — the standing
> a user holds in the organization. Job function is a
> [position](/docs/configure/permissions/positions), and position names are not
> addressable here: `role:sales_manager` matches nobody. *Role* is retired
Expand Down
57 changes: 57 additions & 0 deletions content/docs/configure/users.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,63 @@ breakdown.
Payloads, password policies, and phone-only accounts are covered in
[Authentication → Admin user management](/docs/configure/authentication#admin-user-management-objectstack-143).

## Organization-membership tiers

Every membership row (`sys_member`) carries a **tier** — the standing a
user holds in the organization. The vocabulary is closed and owned by
the platform (ADR-0108): these four values, and nothing an app declares
widens them.

| Tier | What it means |
|---|---|
| `owner` | Top standing in the organization. May invite at any tier, and is the only tier that may remove another owner |
| `admin` | Administers the organization. May invite at any tier except `owner` |
| `delegated_admin` | May issue organization invitations **without** being an org admin. That reach is the whole of it — the tier itself resolves to no permissions; see below |
| `member` | Ordinary standing. No administrative reach; access arrives through positions and permission sets, like everyone else's |

> **Two different records are called a "membership" on this page.**
> `sys_member` answers *which organization do you belong to, and at what
> tier*. `sys_business_unit_member` —
> [the next section](#place-people-in-the-org-tree-memberships) —
> answers *which business unit do you sit in*. Placing someone in the
> org tree changes no tier, and changing a tier places nobody.

The tier is chosen on the invitation (`sys_invitation.role`) and stored
on the membership row (`sys_member.role`). Both fields are the same
fixed four-value select, so an application's own business role
(`sales_manager`) cannot be stored in either, and an invitation naming
one is rejected before any row is written. Job function is a
[position](/docs/configure/permissions/positions).

Two rules bound who may hand out which tier: an invitation may never
confer a tier above the issuer's own, and an issuer below `admin` may
invite only as `member`.

**A tier is a grade that decides what you can *reach* — never a bundle
of what you may *do*.** The visible power of `owner` and `admin` comes
from a separate mechanism: memberships at those two tiers are
automatically granted an organization-admin permission set scoped to
that organization. That permission set carries the authority; the tier
only decides who receives it.

### `delegated_admin` is not delegated administration

Two mechanisms with near-identical names. Reaching for the wrong one is
the mistake this section exists to prevent:

| | `delegated_admin` (a membership tier) | [Delegated administration](/docs/configure/permissions/permission-sets#delegated-administration) (a permission set) |
|---|---|---|
| Lives on | `sys_member.role` | An `adminScope` carried by a permission set |
| Answers | *Can you reach the invitation flow at all?* | *What may you actually grant* — which business units, which permission sets |
| On its own | Lets you invite a plain member, and place nobody | Lets you administer through the ordinary assignment path, but not issue invitations |

The two are **doubly opt-in and independent**: someone must set the
membership tier **and** grant an `adminScope` before a scoped delegate
can issue an invitation that also places the new person in a business
unit with positions. Granting one is not granting the other — holding
`delegated_admin` confers none of the powers listed under
[delegated administration](/docs/configure/permissions/permission-sets#delegated-administration).

## Place people in the org tree (memberships)

Placing a person in the org tree is a separate record: a **Business
Expand Down