Chartered by maintainer ruling, 2026-08-24, live PM chat, verbatim: 「立卡,优先处理,并评估有没有相关任务要一起处理」 — with the design direction proposed by the maintainer in the same session: 「admin_full_access 能否在内核中用元数据约定,然后具体谁是超级管理员通过环境变量配置邮箱?」. Direction is ruled; this card designs the details and sequences the implementation. Design-first: no implementation dispatch until the design is accepted.
The problem (business form, from the #2734 → #10103 → #11532 lineage)
The platform's own super-admin right is anchored on a data row inside the tenant data model: an org-less admin_full_access row in sys_permission_set, referenced by row id from an unscoped sys_user_permission_set grant (resolve-authz-context.ts §6b), seeded ~1.3s before the first organization exists. It is the last structural exception to the ruled walled-tenancy doctrine ("every row belongs to exactly one organization"; #10103 Option C). Costs: single-point fragility (touch the row → platform lockout or silent re-mint), a recurring tax on every sweep/gate/diagnostic (three ruling rounds spent on this family already), and an asterisk in the security story.
Ruled direction
- The permission set's CONTENT is a kernel metadata declaration — code-declared, versioned, spec-validated, PR-reviewed. No runtime row holds the super-admin capability set; nothing can delete or mutate it at runtime. (Mainstream precedent: Keycloak
KEYCLOAK_ADMIN, GitLab root bootstrap, Grafana GF_SECURITY_ADMIN_*, Kubernetes deployment-credential superuser — operator-level admin comes from deployment config, never from business data.) - The HOLDER comes from deployment config: an env variable listing admin email(s). Platform-admin derivation becomes: caller's verified email ∈ configured list →
PLATFORM_ADMIN with the declared capability set.
Five security pins the design must nail (from the chartering discussion)
- Verified-email match only — the env entry confers nothing until an account holding that email has passed verification; normalize (lowercase) and match exactly. Otherwise registering the configured address is a privilege escalation.
- Empty config = fail closed — no platform admin exists; the development-mode dev-admin seed stays development-only.
- Auditability — the resolved admin list is surfaced read-only (Setup / discovery / health) since there is no grant row left to query.
- Revocation = config change + reload — acceptable for this role; cloud's control plane injects per-deployment env, which fits.
- Loud migration — existing deployments carrying the row-id grant: derivation prefers env; a detected legacy grant logs a deprecation pointing at the config path; removal of the legacy path is a sequenced follow-up, never a silent dual-track.
Related tasks assessed for joint handling (maintainer asked; triage's reading)
| card | relation | sequencing |
|---|
#10348 (ruled C today, pm:queue) | Consolidates the two stray plugin-auth judges onto resolve-authz-context.ts — the very function this design rewires | Land #10348 first: then the derivation changes in exactly one place. The design card's implementation must not start before it. |
#10949 (pm:blocked, live authz defects in those judges) | May be partially absorbed by #10348-C | Re-priced there (already noted on #10348). |
| objectstack#11211 (merged: walled owner-email elevation) + the #10103 "env-door projection" | An email/env elevation mechanism already partially exists. | ⚠️ Premise-first for the designer: measure the landed mechanism and unify onto it — one email door, not two parallel ones. |
| cloud#1509 (P0: first self-registrant becomes platform_admin, bypassing invite-only) | The env-email anchor is the structural fix for this class: self-registration must never confer platform admin; only configured emails do | Design must state the walled bootstrap flow end-to-end; a cloud-side leg follows the design (coordinate with the cloud seat's #1614→#1509 train — do not collide with its in-flight acceptance). |
| #11532 (closed today: honest diagnostic) | The 8 org-less rows' retirement becomes possible once nothing references admin_full_access by row id | Seeders stop minting + reap of the 8 rows is the implementation's final leg (the other 7 rows have per-org copies already; verify zero readers before reaping). |
Not related despite proximity: #11579 (auth settings pre-bind), #11627 (MySQL hash keys), #10556 (sinks).
Discipline
Priority: maintainer-ordered front-of-queue (priority:p0 per the verbatim above — jump authorization recorded; ⛔ does not exempt claim protocol or serial constraints). Clause-②: yes (changes authorization derivation — the widest contract there is); contract-review tier mandatory on the implementation. Deliverable of THIS card: the design document (options where real choices remain — e.g. env spelling, multi-admin, reload semantics — with a four-axis pass), then split implementation cards per surface (packages/core derivation · kernel declaration · plugin-security seeders/reap · migration · cloud leg).
Refs: #10103 (ruling + fork analysis) · #11532 (measured constraints: row-id derivation, bootstrap-before-first-org) · #10348 (consolidation prerequisite) · cloud#1406/#1509 · #2734 · ADR-0068 · ADR-0120 D3.
Chartered by maintainer ruling, 2026-08-24, live PM chat, verbatim: 「立卡,优先处理,并评估有没有相关任务要一起处理」 — with the design direction proposed by the maintainer in the same session: 「admin_full_access 能否在内核中用元数据约定,然后具体谁是超级管理员通过环境变量配置邮箱?」. Direction is ruled; this card designs the details and sequences the implementation. Design-first: no implementation dispatch until the design is accepted.
The problem (business form, from the #2734 → #10103 → #11532 lineage)
The platform's own super-admin right is anchored on a data row inside the tenant data model: an org-less
admin_full_accessrow insys_permission_set, referenced by row id from an unscopedsys_user_permission_setgrant (resolve-authz-context.ts§6b), seeded ~1.3s before the first organization exists. It is the last structural exception to the ruled walled-tenancy doctrine ("every row belongs to exactly one organization"; #10103 Option C). Costs: single-point fragility (touch the row → platform lockout or silent re-mint), a recurring tax on every sweep/gate/diagnostic (three ruling rounds spent on this family already), and an asterisk in the security story.Ruled direction
KEYCLOAK_ADMIN, GitLab root bootstrap, GrafanaGF_SECURITY_ADMIN_*, Kubernetes deployment-credential superuser — operator-level admin comes from deployment config, never from business data.)PLATFORM_ADMINwith the declared capability set.Five security pins the design must nail (from the chartering discussion)
Related tasks assessed for joint handling (maintainer asked; triage's reading)
pm:queue)resolve-authz-context.ts— the very function this design rewirespm:blocked, live authz defects in those judges)admin_full_accessby row idNot related despite proximity: #11579 (auth settings pre-bind), #11627 (MySQL hash keys), #10556 (sinks).
Discipline
Priority: maintainer-ordered front-of-queue (
priority:p0per the verbatim above — jump authorization recorded; ⛔ does not exempt claim protocol or serial constraints). Clause-②: yes (changes authorization derivation — the widest contract there is); contract-review tier mandatory on the implementation. Deliverable of THIS card: the design document (options where real choices remain — e.g. env spelling, multi-admin, reload semantics — with a four-axis pass), then split implementation cards per surface (packages/corederivation · kernel declaration · plugin-security seeders/reap · migration · cloud leg).Refs: #10103 (ruling + fork analysis) · #11532 (measured constraints: row-id derivation, bootstrap-before-first-org) · #10348 (consolidation prerequisite) · cloud#1406/#1509 · #2734 · ADR-0068 · ADR-0120 D3.