You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Tracking issue for ADR-0090 (proposed in #2695; companion reference: docs/design/permission-model.md).
Summary
Converge the permission model ahead of launch: five admin-facing concepts (permission set · position · business unit · sharing/OWD · team), secure defaults, one-step renames with no compatibility aliases (launch window), a typed principal model (humans / AI agents / services / guests / externals), scoped delegated administration, and a machine-enforced authoring-safety story for AI-drafted metadata.
Origin incident: an object created without sharingModel + an ordinary C/R/U permission set silently granted org-wide read/write of other users' records (objectstack-ai/objectui#2348 — the Studio OWD control shipped there is the UI half; this ADR fixes the platform half).
Decisions (see ADR for full rationale)
D1 — Custom objects default to OWD private; unset state removed (existing metadata grandfathered by explicit stamping)
D2 — Profile concept removed (isProfile deleted; isDefault narrows to an install-time suggestion)
D3 — sys_role→sys_position, sys_user_role→sys_user_position, sys_role_permission_set→sys_position_permission_set, ctx.roles[]→ctx.positions[], current_user.role→current_user.position; "role" becomes a lint-enforced forbidden word (sole exception: better-auth sys_member.role / org_membership_level)
D7 — Security-domain publish linter + tiered human gates
D8 — Teams receive sharing only; never own records, never bind permission sets
D9 — Audience anchors: builtin guest position joins everyone; packages suggest audience bindings, never ship shared builtin sets; no admin anchor (superuser wildcard covers new packages)
D10 — Principal taxonomy (kind: human|agent|service|guest|system, audience: internal|external, onBehalfOf); agents act on the intersection of their grants and their delegator's, under a lint ceiling, with human co-sign for destructive ops; services = seatless least-privilege machine identities
D11 — External OWD: optional externalSharingModel, default private, validated external ≤ internal; BU depth inapplicable to externals
Tracking issue for ADR-0090 (proposed in #2695; companion reference:
docs/design/permission-model.md).Summary
Converge the permission model ahead of launch: five admin-facing concepts (permission set · position · business unit · sharing/OWD · team), secure defaults, one-step renames with no compatibility aliases (launch window), a typed principal model (humans / AI agents / services / guests / externals), scoped delegated administration, and a machine-enforced authoring-safety story for AI-drafted metadata.
Origin incident: an object created without
sharingModel+ an ordinary C/R/U permission set silently granted org-wide read/write of other users' records (objectstack-ai/objectui#2348 — the Studio OWD control shipped there is the UI half; this ADR fixes the platform half).Decisions (see ADR for full rationale)
private; unset state removed (existing metadata grandfathered by explicit stamping)isProfiledeleted;isDefaultnarrows to an install-time suggestion)sys_role→sys_position,sys_user_role→sys_user_position,sys_role_permission_set→sys_position_permission_set,ctx.roles[]→ctx.positions[],current_user.role→current_user.position; "role" becomes a lint-enforced forbidden word (sole exception: better-authsys_member.role/org_membership_level)read/read_write/fullaliases; authoring rejectseveryoneposition carries default grants (per-request resolution, install-time suggestion prompt, no fallback cliff, high-privilege bits blocked)guestposition joinseveryone; packages suggest audience bindings, never ship shared builtin sets; no admin anchor (superuser wildcard covers new packages)kind: human|agent|service|guest|system,audience: internal|external,onBehalfOf); agents act on the intersection of their grants and their delegator's, under a lint ceiling, with human co-sign for destructive ops; services = seatless least-privilege machine identitiesexternalSharingModel, defaultprivate, validatedexternal ≤ internal; BU depth inapplicable to externalseveryone/guestanchors and security publishes stay tenant-levelPhased delivery (each independently shippable, proofs per ADR-0054)
isProfileremoval, D1 default flip + grandfather stamping, plus spec shapes: ctx principal taxonomy (D10) +externalSharingModel(D11). Proof: full suite + dogfood re-run of the objectui#2348 scenario showing owner isolation with no explicit OWD authoredeveryone+guestbuiltin seeding, install-time suggestion prompts, cliff removal. Proof: package install/uninstall grant-liveness e2e + anonymous-principal e2econtent/docs/permissions/*to matchdocs/design/permission-model.mdNamed follow-up ADRs (scoped out of 0090, to be opened separately)
Supersedes / amends
ADR-0056 D7 (default-profile fallback →
everyoneposition) · ADR-0057 D5/D7 alias clauses (pre-launch one-step renames). ADR-0057's core (BU tree, scope depth,sys_user_roledecoupling) is untouched and load-bearing.🤖 Generated with Claude Code
https://claude.ai/code/session_012oLzaP8n7A3YKFmgaHWC8H