Skip to content

platform-admin re-anchor L2 (core): env-configured verified-email derivation of PLATFORM_ADMIN — the config branch inside the single derivation site #11970

Description

@os-support-ai

Leg L2 of the accepted #11663 platform-admin re-anchor design. Provenance: design document = #11663 comment 5394453215 (§2, §3, §4 Choices 1–3 and 7, §6 row L2); maintainer acceptance = #11663 comment 5404675670 (2026-08-25, verbatim 「接受你的建议,继续」, bundle 1A/2B/3A/4A/5A/6A/7A). Filed by PM session session_01KWRU3s15AJz7PGW7a7wdCh.

Blocked-by: #11965
Blocked-by: #10348

(#10348-C consolidates the stray judges onto resolve-authz-context.ts — the stated prerequisite so this derivation changes in exactly one place; #11965 is the spec capability declaration this leg reads.)

Surface: packages/core — new security/platform-admin.ts (promoted isEmailVerified, normalization, list parse, derivation); the config branch in resolve-authz-context.ts §6b; + @objectstack/types dependency (Choice 7A — measured acyclic); ADMIN_STANDING_SURFACE update.

Ruled shape (⛔ not re-litigable here):

  • 1A: reuse OS_PLATFORM_OWNER_EMAIL (packages/types/src/env.ts:172); no second variable.
  • 2B: comma-separated list; one normalization (lowercase), duplicates collapsed, blanks dropped, any unparseable entry fails the whole variable closed — never skip-and-continue.
  • 3A: live env read per derivation with a per-process memo keyed on the raw string; ⛔ no runtime mutation endpoint.
  • Verified-email match only (an unverified account holding a configured address confers nothing); empty/unset config = zero platform admins, fail closed (dev-admin seed stays development-only).
  • Derived standing is added; the legacy row-id grant read is still honoured in this leg (migration step 3 — nothing revoked here).

Known cost, stated up front: this moves the pinned golden — reading email_verified makes the sys_user read unconditional for authenticated principals, and the query multiset is pinned in resolve-authz-context.batch-equivalence.test.ts + .golden.json. Move it with an explanation; ⛔ never silently re-baseline. Also touches packages/verify/src/harness.ts:360-371 + two CLI e2e fixtures (verified-email shape after #11343).

Discipline: Clause-②: yes (authorization derivation); needs:contract-review at review; contract-review tier mandatory.

Acceptance criterion: with OS_PLATFORM_OWNER_EMAIL=a@b.c and a verified account a@b.c, derivation yields PLATFORM_ADMIN with the declared capability set; unset/empty/malformed variable yields zero config-derived admins (loudly); legacy grant path still honoured and logging its deprecation pointer.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions