Skip to content

Commit 34fc0cc

Browse files
os-zhuangclaude
andauthored
docs(authz): two-doors permission separation is landed, not a roadmap gap (ADR-0086 P2) (#2580)
authorization.mdx listed "Two doors (ADR-0086 D6/D7)" under Known gaps & roadmap, but the framework (publish-time materialization + managed_by data-layer write gate) and objectui (package Access door draft/publish) halves have shipped. Move it into the ADR-0086 provenance section as a landed "Two doors, one metadata" subsection describing the package door (draft→publish→materialize), the env-admin door (live, assignment), and the data-layer write gate (admin door cannot edit/forge managed_by:'package' rows, fail-closed ahead of the CRUD check; isSystem bypasses). Also refresh the enterprise-auth roadmap bullet: P1 + the P2 session/global-IP/ shared-multi-node-rate-limit-store items are landed; the remaining gap is per-org allowed_ip_ranges (#2571). Add the ADR-0005 deny/muting subtract layer as the genuinely-deferred ADR-0086 P2 remainder. Claude-Session: https://claude.ai/code/session_014y5kiH3aPLWtRRRGcVrXcT Co-authored-by: Claude <noreply@anthropic.com>
1 parent ffafb30 commit 34fc0cc

1 file changed

Lines changed: 36 additions & 4 deletions

File tree

content/docs/concepts/authorization.mdx

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,35 @@ package (metadata); subject bindings and env-specific values stay as config.**
106106
(`bootstrapDeclaredRoles`, ADR-0057 D6) — a declarable-but-never-seeded
107107
array is exactly the inert-metadata smell ADR-0078 prohibits.
108108

109+
### Two doors, one metadata (ADR-0086 D6/D7)
110+
111+
The `managedBy` provenance axis is not just descriptive — the platform
112+
**populates and gates on it**, so editing a permission set flows through exactly
113+
one of two doors, each writing only what it owns:
114+
115+
- **Package door** (studio `/studio/:packageId/access`) — a package's own set is
116+
**metadata**, so edits are saved as a **draft** stamped with the `packageId`
117+
(`saveMetaItem` `mode:'draft'`) and go live with the package's atomic
118+
**Publish**, exactly like Data and Interfaces. On publish, a registered
119+
materializer (`registerPublishMaterializer`) projects the published body into
120+
`sys_permission_set` as `managedBy:'package'` + `packageId`, reusing the same
121+
upsert as the boot seeder (`upsertPackagePermissionSet`). Enforcement is
122+
unaffected while a set is still a draft (drafts never enter the active
123+
resolve).
124+
- **Environment-admin door** (`metadata-admin`) — the cross-package all-objects
125+
matrix plus subject **assignment** (`sys_user_permission_set`,
126+
`sys_role_permission_set`), edited **live** (config). It owns env-authored
127+
sets (`managedBy` `platform`/`user`) and assignments — not package sets.
128+
- **Data-layer write gate** — the security middleware **refuses** any admin-door
129+
write to a `managedBy:'package'` `sys_permission_set` row, and refuses a
130+
payload that forges that provenance (insert or update, single or array). It
131+
fails closed ahead of the CRUD check — even a `modifyAllRecords` super-user is
132+
blocked — so the door separation is a real boundary, not a UI hint. System /
133+
boot writes carry `isSystem` and bypass it, so the seeder and materializer are
134+
never self-blocked. An environment adjusts a packaged set through the
135+
ADR-0005 overlay / muting subtract layer (below), never by editing the base
136+
record.
137+
109138
## Lifecycle coverage (five stages)
110139

111140
| Stage | What holds today | Owned by |
@@ -145,10 +174,13 @@ The complete, prioritized gap map lives in issue **#2561** (the production
145174
references (ADR-0066 ⑨).
146175
- **Per-operation `requiredPermissions`** (ADR-0066 ⑤) — read-open /
147176
write-gated objects.
148-
- **Enterprise authentication** (ADR-0069) — password policy, lockout,
149-
enforced MFA (P1); session lifecycle, IP allowlists (P2); SSO/SCIM (P3).
150-
- **Two doors** (ADR-0086 D6/D7) — package Access door under draft/publish;
151-
env-admin door live, cross-package.
177+
- **Deny/muting subtract layer** (ADR-0005 overlay; ADR-0066 precedence step 4)
178+
— how an environment adjusts a *packaged* set without forking it; deferred
179+
until proven need (ADR-0086 P2).
180+
- **Enterprise authentication** (ADR-0069) — password policy, lockout, enforced
181+
MFA (P1) and session lifecycle + global IP allowlist + shared multi-node
182+
rate-limit store (P2) are **landed**; the remaining gap is per-org
183+
`allowed_ip_ranges` (#2571). SSO/SCIM is P3.
152184

153185
## ADR index
154186

0 commit comments

Comments
 (0)