Skip to content

Commit 65fe2c9

Browse files
committed
docs(plugin-auth): 用实测结论替换「清空能力=管理员失效」的推断 (#6084)
`resolveAuthzContext` 的 `hasPlatformAdminGrant` 只看 `ps.name === 'admin_full_access'` (resolve-authz-context.ts:390),`derivePosture` 就凭这个布尔返回 PLATFORM_ADMIN —— 清空 `system_permissions` 并不会让 platform admin 失效,posture 与 superuser bypass 都挂在**名字**上。原注释把它写成一处 break-glass 缺口是错的;改为记录实测结论,顺带 把「只读 name」这条静态跳过键的依据说实。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JwwiU9bjhwy2SWj13ho8uv
1 parent 0acf821 commit 65fe2c9

1 file changed

Lines changed: 15 additions & 9 deletions

File tree

packages/plugins/plugin-auth/src/last-admin-guard.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -215,12 +215,17 @@
215215
*
216216
* Scope in the other direction: this guard watches writes to the four tables
217217
* the administrator population is derived from, and stops there. It has no
218-
* opinion on what a permission set CONTAINS — emptying `admin_full_access`'s
219-
* `system_permissions` would leave administrators who administer nothing, but
220-
* that is a capability question (ADR-0086), and answering it here would make
221-
* every permission-set edit in Setup a break-glass decision. "Who is an
222-
* administrator" is resolved by NAME in this codebase (`resolveAuthzContext`,
223-
* ADR-0068 D2), so the guard reads exactly the name.
218+
* opinion on what a permission set CONTAINS, and that is not a gap being left
219+
* open — it was measured. `resolveAuthzContext` sets `hasPlatformAdminGrant`
220+
* from `ps.name === 'admin_full_access'` alone and `derivePosture` returns
221+
* `PLATFORM_ADMIN` off that boolean, so emptying the set's
222+
* `system_permissions` does NOT un-make a platform admin: the posture rung and
223+
* the superuser bypass ride on the NAME (ADR-0068 D2 / ADR-0095 D3). Such an
224+
* edit costs the holder `setup.access` / `studio.access` — Setup and Studio go
225+
* invisible — while the data plane still answers, so it is recoverable from
226+
* inside the product and is a capability question (ADR-0086), not a break-glass
227+
* one. The name is the whole of what makes an administrator here, so the name
228+
* is the whole of what this guard reads.
224229
*
225230
* ## Relationship to the ADR-0092 identity write guard
226231
*
@@ -544,9 +549,10 @@ const GRANT_STANDING_KEYS = [
544549
* because the platform-admin half of the enumeration reads exactly one column
545550
* of that table: the `name` it looks the set up by. Everything else a
546551
* permission-set write touches (`label`, `description`, the four permission
547-
* JSON blobs, `active`, provenance) is invisible to "who is an administrator",
548-
* so those writes — which is every projection pass and every Setup edit — cost
549-
* this guard no reads at all.
552+
* JSON blobs, `active`, provenance) is invisible to "who is an administrator" —
553+
* `resolveAuthzContext` derives `platform_admin` from the NAME, not from the
554+
* capabilities the set carries — so those writes, which is every projection
555+
* pass and every Setup edit, cost this guard no reads at all.
550556
*
551557
* `id` is deliberately NOT here even though the enumeration reads it. On this
552558
* engine `data.id` on an update ADDRESSES the row (it is what

0 commit comments

Comments
 (0)