Repository navigation
platform-admin re-anchor L8 (cloud seam): control-plane env injection + invite-only interaction — cloud seat leg, designed blind #11977
Description
Activity
分诊解锁 ·
pm:blocked→pm:queue—— 阻塞已过期本轮「停放面专项」由
check-half-states.mjs的 H19 扫出:本卡的Blocked-by:目标已全部关闭,阻塞比阻塞方活得久。⛔ 本席没有采信 sweep 的那一行,逐个目标直读复核:
Blocked-by:目标直读结果 #11970(L2)closed / completed #11974(L4)closed / completed ⇒ 声明的前置条件已全部兑现 ⇒ 解除阻塞,回
pm:queue。⚠️ 本席只解除了「机器可读的那条阻塞线」。若本卡另有未写进Blocked-by:的实际前置(设计未定、上游 PR 在飞、等某人一句话),⇒ 请补一条Blocked-by:或Restart-when:再挂回pm:blocked,⛔ 不要只把标签改回去 —— 一条没有机器可读出口的阻塞,与被遗弃无法区分(H9 的判据)。⚠️ 本卡是链上的 L8(cloud seam),与 #11975 / #11976 同批解除。⚠️ 它触 cloud 面 —— 本席 R+58/R+61 实测:cloud 的 API 通道可达,而git ls-remote仍 128。⇒ 接手方若需读 cloud 源码,先确认自己的通道,⛔ 不要假设「仓不可达」(它的 issue 面是活的,有 59 张 open)。
Generated by Claude Code
Claim: PM loop round R35 (wave 3) — the cloud seat's review this leg was filed for
Session:session_017Wu48ZSjk7HJjyJmGNBtUk
Branch: none — this card's deliverable is a review of the L8 design assumptions against cloud's tree and, if they hold, a cloud-repo issue carrying the leg (back-linked here); a fork on #11663 if they do not. No code in this dispatch.
Worktree:cloud-readings-l8(detached at cloudorigin/main, read-only)
Domain: repo:cloud (whole-repo seat, seat post #6026 — the named reader)
File surface: none (reads only)
Container & model: M design review,mode:subagent,model: opus
Clause-②: no
Serial constraints cleared: n/a — no writes to the tree. Coordination note from the card body: the cloud#1614→#1509 train it warns about is finished (cloud#1509 closed-completed 2026-08-30 via PR #1656 + objectstack#11343), so the "do not collide with its in-flight acceptance" caveat is moot and is verified rather than assumed by the dev.
Generated by Claude Code
Cloud seat review of L8's cloud assumptions — result: FORK, no cloud card filed
repo:cloudexecution seat (seat post #6026), sessionsession_017Wu48ZSjk7HJjyJmGNBtUk, PM round R35. This is the review the L8 card names as its required first step, and the leg was designed blind (design §9.1: "cloud#1509 / cloud#1614 — NOT MEASURED").Refs for every reading below
- cloud
origin/main=58c20e2c3b346db6472ec26e225fe375f029e151(read in a detached read-only worktree; no build, no install, no writes). - framework pin =
.objectstack-shaon that commit =655b106ce2804d2cdb9ed4386df795152535d372(framework read viagit show PIN:path; the shared checkout's HEAD was never moved). - design = [Design] Re-anchor platform-admin:
admin_full_accessbecomes a kernel metadata declaration; WHO holds it comes from env-configured verified emails — retiring the org-less row anchor #11663 comment 5394453215, §6 row L8 + §9; acceptance = [Design] Re-anchor platform-admin:admin_full_accessbecomes a kernel metadata declaration; WHO holds it comes from env-configured verified emails — retiring the org-less row anchor #11663 comment 5404675670 (2026-08-25, 「接受你的建议,继续」).
Dependency ancestry — the framework surface L8 consumes is already inside cloud's pin. L2 landed as PR #13146, merge
33184fd29289cab2527dc295df4a67d6e17c013a; L4 landed as PR #13514, mergeb9972720f843033d24ec657f3d17b75435fca74a.git merge-base --is-ancestorreturns exit 0 for both against655b106c. So a cloud card would carry noBlocked-by:on #11970 / #11974 — that half of the L8 gate is already discharged. Confirmed at the pin by reading the code, not the cards:packages/core/src/security/platform-admin.tsexists withparsePlatformAdminEmails/PLATFORM_ADMIN_EMAIL_SEPARATORand fail-the-whole-variable-closed semantics;resolve-authz-context.ts:754-786is the §6b-config anchor;plugin-security/src/bootstrap-platform-admin.ts:415-488is the walled no-mint branch.
Per-assumption table
# design assumption (as the L8 row states it) measured on cloud 58c20e2c/ pin655b106cverdict A1 cloud can inject OS_PLATFORM_OWNER_EMAILper deploymentIt already does, for the one plane that is walled. apps/cloud/cloudflare/worker.ts:240forwards the variable;apps/cloud/wrangler.toml:243and:396set it. The plane is walled becauseapps/cloud/cloudflare/worker.ts:484hard-codesOS_MULTI_ORG_ENABLED: 'true'into the containerenvVarsdefaults for every environment that Worker deploys.holds — and already landed, before this leg was filed A2 ...per tenant environment ("the control plane injects env into a tenant environment's runtime") ⛔ No such seam, and none is representable. One tenant-runtime container hosts up to 50 per-environment kernels in one process ( apps/objectos/cloudflare/worker.ts:283OS_KERNEL_CACHE_SIZE: '50',:284-308a 4h LRU,packages/objectos-runtime/src/kernel-manager.ts), and env is assembled once per container at construction (apps/objectos/cloudflare/worker.ts:169FORWARDED_ENV_KEYS,:279envVars,:413forwardWorkerEnv). A per-environment value cannot be expressed; a runtime-wide one names the same administrator across every tenant it hosts.CONTRADICTED A3 list form ("Choice 2B") is read at cloud's pin Yes at the framework, and cloud has zero code readers of its own to widen: the only cloud occurrences are the forward-list entry, the wrangler values, deploy templates/docs and test env assignments. objectstack#13147 (the five single-value readers) is closed/completed. holds A4 the source of truth for "the platform owner(s) of this deployment" on the cloud side For the control plane: the env var (A1). For a tenant environment it is not an env var at all — it is sys_environment.metadata.ownerSeed.email, derived from the creating control-planesys_userat provisioning time (packages/service-tenant/src/environment-provisioning.ts:1062-1071), replayed at cold boot (packages/objectos-runtime/src/artifact-kernel-factory.ts:1446-1500).adjusted — it is a control-plane DB row, not config A5 that email is verified at the point cloud would inject it ⛔ No. environment-provisioning.ts:1064-1071readsu.emailand neveremail_verified; a repo-wide grep foremail_verified|emailVerifiedacrosspackages/service-cloud/src,packages/service-tenant/src,packages/objectos-runtime/srcandapps/cloud/cloudflarereturns 6 hits, none of them a check — and one of them ispackages/objectos-runtime/src/environment-owner-seed.ts:91, which stampsemail_verified: trueinto the tenant DB unconditionally. The only verification lives a layer up as a Worker default (apps/cloud/cloudflare/worker.ts:461OS_AUTH_REQUIRE_EMAIL_VERIFICATION: 'true'), which is not a check at the seam and is overridable per deployment.CONTRADICTED B1 invite-only, control plane: self-registration must not confer platform admin Holds, and is already consumed. packages/service-cloud/src/control-plane-preset.ts:531declaresmembershipPolicy: 'invite-only'(host-level, sopackages/organizations/src/membership-policy-gate.tsaccepts it). Cloud's own pin tests were already rewritten to the L4 contract by the pin bump PR #1817:apps/cloud/test/signup-org-flow.test.ts:399-413andapps/cloud/test/unscoped-control-plane-tenant-wall.test.ts:2891-2916now assert the grant row's absence and name objectstack#13514 for why.holds — already landed B2 invite-only, tenant runtime: "only configured verified emails confer platform admin" ⛔ False on cloud by design, and the framework currently agrees with cloud rather than with this sentence. The tenant runtime is not walled: git grep -cforOS_TENANCY_POSTURE|OS_MULTI_ORG_ENABLED|OS_PLATFORM_OWNER_EMAILover the wholeapps/objectostree returns 0 (positive control: the same pattern returns 5 inapps/cloud/cloudflare/worker.tsand 7 inapps/cloud/wrangler.toml), andpackages/objectos-runtime/src/artifact-kernel-factory.ts:841gates multi-org on the demoted boolean, which is absent ⇒single. Under Choice 4A the framework therefore keeps first-user promotion and its grant row there on purpose, and cloud's two owner-admin doors both write exactly that row.CONTRADICTED as framed C "do not collide with the #1614→#1509 train" Moot, verified rather than assumed: cloud#1509 closed completed 2026-08-30 (PR #1656, then #1684), and its closing comment records objectstack#11343's fix c0714eb5as an ancestor of the then-pin. Nothing is in flight on that surface.holds (spent)
The two contradictions, mechanically
1. There is no per-environment env seam, and cloud's per-environment platform admin is a GRANT ROW.
packages/objectos-runtime/src/env-owner-admin-grant.ts:67ensurePlatformAdminGrantinserts an unscopedsys_user_permission_setrow pointing atadmin_full_access—:91 organization_id: null— under{ context: { isSystem: true } }, best-effort, errors swallowed (:95-97). That is byte-for-byte the composite runtime FK the design's H2 describes and the legacy anchor #13515 deletes the read of. Two doors reach it, and neither isOS_PLATFORM_OWNER_EMAIL:packages/objectos-runtime/src/auth-proxy-plugin.ts:319— the console "Open" button'ssso_as_ownerhandoff, elevating onpayload.admin === truefrom a control-plane-signed token (and JIT-creating the user withemailVerified: trueat:301);packages/objectos-runtime/src/artifact-kernel-factory.ts:1461-1464→registerEnvOwnerAdminGrant(env-owner-admin-grant.ts:126) — asys_user-insert middleware that elevates the row whose email matchesownerSeed.emailand reads verified (:143-147).
So the cloud analogue of "the deployment declares its administrators in config" is "the control plane recorded who created this environment, in a row". The L8 row's content — inject the variable per deployment — has no target on this plane.
2. The verified-email pin does not survive the cloud seam. The middleware at
env-owner-admin-grant.ts:143-147genuinely requiresemail_verifiedon the tenant row — but the tenant row it reads is frequently one cloud itself wrote withemail_verified: truehard-coded (environment-owner-seed.ts:91), from an address the control plane copied without ever consultingemailVerified(environment-provisioning.ts:1064-1071). The framework's P1 is satisfied in form on the tenant side while the verification decision was never actually made anywhere. This one is independent of the fork and is worth fixing whichever way the fork is ruled.Sequencing correction — the trigger is #11979 (Choice 4B), not #13515 (L5). #13515's acceptance criterion explicitly protects
single-posture standing ("single-posture first-user standing is unchanged unless #11979 landed first"), and the pin's deprecation pointer is posture-keyed for the same reason (resolve-authz-context.ts:790-828). So cloud's grant-row doors are safe today and safe through L5. They go dead when Choice 4B lands — and they go dead silently:ensurePlatformAdminGrantswallows its own errors, and after 4B the row it writes simply confers nothing. The observable symptom would be env owners losing Setup/Studio with no error anywhere.
Collision list (open cloud cards and PRs on this surface)
Read from the REST list endpoints on
objectstack-ai/cloud(49 open issues, 7 open PRs), filtered locally onOS_PLATFORM_OWNER_EMAIL|platform_admin|platformAdmin|invite-only|walled|emailVerified|email_verified|ownerSeed|platform-admin|11663.card relation cloud#1332 ( pm:blocked, finding) — "the hosted tenant runtime never readsOS_TENANCY_POSTURE;artifact-kernel-factory.tsstill gates on the demotedOS_MULTI_ORG_ENABLEDboolean"Adjacent and load-bearing. It measures the same absence B2 rests on and already frames the two defensible end states (make the tenant runtime posture-aware, or rule it posture-blind by design). A cloud L8 card must not re-decide that; it depends on it. objectstack#11225 ( security,repo:cloud, dispatched — being measured in this container now)Same neighbourhood, different predicate: clause 2 of the #11184 ruling is about auto-join to the Default Organization in the enterprise packages/organizations; L8's B is about platform-admin standing. Cited, not duplicated, and deliberately not re-measured here.cloud#1452, cloud#1765, cloud#1331, cloud#874 Walled/isolated-posture neighbours (tenant Studio exposure, position picker, the hotcrm SaaS shape decision, ADR-0105 group mode). None touches the owner-email or platform-admin anchor. open PRs #1883 #1882 #1881 #1880 #1878 #1834 #1746 File lists checked individually: none touches env-owner-admin-grant.ts,environment-owner-seed.ts,environment-provisioning.ts, the worker env assembly, or the wrangler owner vars. No PR collision.
Why no cloud card, and what the fork asks
Per this card's own instruction — contradictions come back as a fork on #11663, never as a silent adaptation — I have posted the fork there and filed nothing in
objectstack-ai/cloud. Filing now would require me to pick between two architectures for cloud's per-environment platform admin, which is exactly the decision the fork escalates.The card is drafted and mechanical to file the moment the fork is ruled. Recommended shape:
- Title:
platform-admin re-anchor, cloud leg: make the per-environment owner anchor survive Choice 4B, and verify the owner email at the seam - Repo/labels:
objectstack-ai/cloud, unassigned, nopm:*,security(the repo carries that label — cloud#1509 holds it). - Scope: (i)
environment-provisioning.ts:1062-1071consultsemail_verifiedwhen buildingownerSeed, andenvironment-owner-seed.ts:91stops asserting a verification cloud did not perform; (ii) whichever anchor the fork rules, applied to both doors (auth-proxy-plugin.ts:319,env-owner-admin-grant.ts:126); (iii) a pin test that reddens when the anchor stops conferring, so 4B cannot land silently on cloud. - Acceptance criterion: on a tenant environment whose creator's control-plane email is unverified, the owner does not reach
admin_full_access; on a verified creator they do; and the assertion is made against the served session payload, not against the row. Blocked-by:— none on platform-admin re-anchor L2 (core): env-configured verified-email derivation of PLATFORM_ADMIN — the config branch inside the single derivation site #11970 / platform-admin re-anchor L4 (plugin-security): bootstrap stops granting under walled postures; explain reports config-derived standing; deprecation log for legacy grants #11974 (both inside the pin, shown above). It would carryBlocked-by:the fork ruling on [Design] Re-anchor platform-admin:admin_full_accessbecomes a kernel metadata declaration; WHO holds it comes from env-configured verified emails — retiring the org-less row anchor #11663 and, for limb (ii), objectstack#11979 (Choice 4B); limb (i) is unblocked today.
One residue that is not a cloud card: the objectos-ee deploy surfaces still describe the variable as a single address (
apps/objectos-ee/deploy/composed-artifact-boot.md:76,114,apps/objectos-ee/deploy/README.md:125). Under Choice 2B they are incomplete rather than wrong, and the operator runbook for that variable is L7's surface (#11976), not cloud's — recorded here so it is not lost, deliberately not filed.
Generated by Claude Code
- cloud
Fork posted — pointer. The two contradicted assumptions from the review above went back to the design as a fork on the L8 row: #11663 comment 5521187539 (#11663 (comment)). It carries the four-axis pass and the recommendation (option B — declare the owner on
sys_environment.metadata.ownerSeedand keep one derivation site; option A named as the time-boxed interim), plus the sequencing correction that the cloud leg's real dependency is #11979 (Choice 4B), not #13515 (L5).⛔ No cloud card filed, per this card's own instruction for the contradicted branch. The recommended card shape, its scope, its acceptance criterion and its
Blocked-by:analysis are written out in the review above and are mechanical to file once the fork is ruled. This card's acceptance criterion ("a cloud-repo issue exists carrying this leg") is therefore not met and should not be marked as met — the leg cannot be carried into cloud as written.
Generated by Claude Code
os-dev-report
{ "issue": 11977, "status": "needs_decision", "branch": null, "pr": null, "premise_still_valid": false, "summary": "Review-only dispatch (no code, no branch, no PR). The L8 row's cloud assumptions were measured against cloud origin/main 58c20e2c and its framework pin 655b106c; two are contradicted, so the leg went back as a fork on #11663 (comment 5521187539) and NO cloud card was filed. What HOLDS and is already landed before this leg was dispatched: apps/cloud already injects OS_PLATFORM_OWNER_EMAIL (cloudflare/worker.ts:240, wrangler.toml:243/:396), is walled (worker.ts:484), declares membershipPolicy 'invite-only' (service-cloud/src/control-plane-preset.ts:531), and its own pin tests were rewritten to the L4 no-mint contract by pin bump PR #1817 (apps/cloud/test/signup-org-flow.test.ts:399-413, unscoped-control-plane-tenant-wall.test.ts:2891-2916). Choice 2B costs cloud nothing: zero cloud code readers of the variable. CONTRADICTION 1 - there is no per-tenant-environment env seam and none is representable: one container LRU-hosts up to 50 per-environment kernels in one process (apps/objectos/cloudflare/worker.ts:283, packages/objectos-runtime/src/kernel-manager.ts) with env assembled once at construction (worker.ts:169/:279/:413), so a per-environment value cannot exist and a runtime-wide one would name one administrator across every tenant. Cloud's actual per-environment anchor is a control-plane DB row, sys_environment.metadata.ownerSeed.email (service-tenant/src/environment-provisioning.ts:1062-1071), conferring standing by WRITING the legacy unscoped admin_full_access grant row (objectos-runtime/src/env-owner-admin-grant.ts:67, :91) through two doors that are not the env variable (auth-proxy-plugin.ts:319 console handoff; env-owner-admin-grant.ts:126 OIDC middleware). CONTRADICTION 2 - P1 'verified-email match only' does not survive the seam: environment-provisioning.ts:1064-1071 copies the creator's email and never reads email_verified, and environment-owner-seed.ts:91 stamps email_verified: true into the tenant DB unconditionally, so the tenant-side verification check (env-owner-admin-grant.ts:143-147) reads a verification cloud asserted rather than performed; the only real check is a Worker default one layer up (apps/cloud/cloudflare/worker.ts:461). SEQUENCING CORRECTION in the design's favour: Choice 4A protects cloud today (the tenant runtime is single posture - zero hits for the three posture/owner variables across all of apps/objectos, positive control 5 and 7 hits in apps/cloud; artifact-kernel-factory.ts:841 gates on the demoted boolean, the same absence cloud#1332 files), and #13515 (L5) explicitly protects single-posture standing - so the cloud leg's real dependency is #11979 (Choice 4B), whose landing kills both cloud doors SILENTLY (the grant write still succeeds and simply stops conferring; the writer swallows its own errors). Dependency ancestry checked rather than assumed: L2's merge 33184fd2 and L4's merge b9972720 are both ancestors of the pin (git merge-base --is-ancestor, exit 0), so a cloud card would carry no Blocked-by on #11970/#11974. The card's process premise held (its own 'designed blind, review first' warning was correct); its content premise - that the cloud leg is control-plane env injection per deployment - is what the tree contradicts, and its acceptance criterion ('a cloud-repo issue exists carrying this leg') cannot be met as written.", "tests": "None run, and none owed: this dispatch writes no product code and was explicitly read-only (no install, no build, no branch, no edits) - so there is nothing of mine to verify, and reporting a build or a suite here would be reporting a measurement I did not make. Every claim is a read of cloud origin/main 58c20e2c in a detached read-only worktree (/home/user/cloud-readings-l8, removed at the end) or of the framework at pin 655b106c via `git show PIN:path` (the shared /home/user/objectstack checkout's HEAD was never moved; only `git fetch origin 655b106c`). Two mechanical checks were run rather than asserted. (1) Ancestry: `git merge-base --is-ancestor 33184fd2... 655b106c` and the same for b9972720... both returned exit 0, printing 'IS ancestor of pin'. (2) The zero-hit claim underpinning 'the tenant runtime is single posture' was run WITH a positive control, because a bare zero proves nothing: `grep -c 'OS_TENANCY_POSTURE\\|OS_MULTI_ORG_ENABLED\\|OS_PLATFORM_OWNER_EMAIL'` returns 0 for apps/objectos/cloudflare/worker.ts and apps/objectos/wrangler.toml and 0 files across the whole apps/objectos tree, while the same pattern returns 5 in apps/cloud/cloudflare/worker.ts and 7 in apps/cloud/wrangler.toml. Both posted comments were read back in full via REST and diffed byte-for-byte against the local source: the only differences are a trailing-newline normalization (diff shows one added blank line and 'No newline at end of file'), i.e. the body sanitizer stripped nothing.", "mcp_calls": "0 - the whole run went through the zero-quota REST channel, probed first as the discipline requires: an authenticated repo-scoped REST read returned HTTP 200 with a 15000/hr core budget, so reads (issues, comments, timeline, PR metadata, PR file lists, the open-issue listing) and the three comment writes all went over REST. `gh` is absent in this container. No MCP GitHub tool was called; the dedup/collision scan used the REST list endpoints (49 open issues, 7 open PRs on objectstack-ai/cloud) plus a local regex filter, never a wide search.", "open_questions": [ { "question": "What anchors platform-admin standing for a cloud TENANT ENVIRONMENT once Choice 4B (#11979) lands, and what does 'verified' mean at the control-plane seam? Cloud has no per-environment env seam (50 kernels share one process), so its anchor today is the legacy unscoped grant row written from sys_environment.metadata.ownerSeed - the exact row the re-anchor retires - and the owner email behind it was never checked for verification.", "options": [ "A - rule the row: declare that database-per-tenant, single-posture runtimes keep the grant-row anchor permanently; #11979/#13515 carve it out rather than removing it, and cloud fixes only the verification gap.", "B - declare the owner, keep one derivation site: make ownerSeed the per-environment analogue of the variable (control plane records a VERIFIED owner) and give the framework a non-env config source feeding the same 6b-config derivation, so the row stops being the anchor without a second derivation site appearing.", "C - make the env variable per-environment: one process per tenant environment so the design's shape applies literally." ], "recommendation": "B, with A named explicitly as the time-boxed interim. Long-term soundness leads and is the axis that decides it: B is the only option that keeps 'declared = enforced' and one derivation site, whereas A freezes the runtime-writable row the ruling set out to retire and leaves a permanent posture-keyed carve-out - two derivation shapes keyed on posture, which the design's own Choice 4 calls drift bait. AI-safety agrees (B > A > C): under A the superuser anchor stays a row any system-context write can insert, and cloud's writer swallows its own errors, so failure is invisible in both directions. Real business need: A and B both serve the shipped product; C serves nothing measured and contradicts the runtime's economics (50 kernels per container, 4h LRU, a keep-warm workflow). Startup scope: C is out of proportion, and B's framework half belongs inside L2's existing derivation site rather than as a new mechanism. Two riders on the recommendation: (1) #11979 must not land until the cloud anchor has moved, or 4B ships a silent lockout on the hosted fleet; (2) the ownerSeed verification gap is independent of this fork and weakens P1 today, so it should be fixed whichever way A/B is ruled." } ], "out_of_scope_findings": [ "NOT filed, deliberately, and recorded in the review comment instead: the objectos-ee deploy surfaces still describe OS_PLATFORM_OWNER_EMAIL as a single address (apps/objectos-ee/deploy/composed-artifact-boot.md:76,114; apps/objectos-ee/deploy/README.md:125). Under Choice 2B they are incomplete rather than wrong, and the operator runbook for that variable is L7's surface (#11976), not cloud's. Filing it as a cloud card would also breach this dispatch's 'no cloud card on the contradicted branch' instruction.", "Not a new finding - cited as an existing adjacent card so it is not re-filed: cloud#1332 (pm:blocked) already measures that the hosted tenant runtime never reads OS_TENANCY_POSTURE and gates on the demoted OS_MULTI_ORG_ENABLED boolean, and it already frames the two defensible end states. Contradiction 1 depends on that card rather than re-deciding it.", "objectstack#11225 (security, repo:cloud, dispatched and being measured in this container now) is the same neighbourhood with a different predicate - auto-join to the Default Organization in the enterprise organizations package, versus platform-admin standing here. Cited, not duplicated, and deliberately not re-measured." ] }
Generated by Claude Code
决策卡:cloud 租户环境的 platform-admin 锚点在 Choice 4B 落地后落在哪里、以及「已验证邮箱」在控制面接缝处指什么 —— L8 设计在 cloud 树上被两处证伪,转决策箱
repo:cloud席(座位贴 #6026,sessionsession_017Wu48ZSjk7HJjyJmGNBtUk,R35)。本卡原为「cloud 席复核 L8 设计假设后在 cloud 仓立执行卡」;复核已做(上方 dev 评论,cloud58c20e2c、pin655b106c,逐条 file:line),分叉已按卡面要求贴到 #11663(评论 5521187539)。结论不在本席裁量内 —— 它动的是安全/权限边界(谁在租户环境里是平台管理员、凭什么)—— 故本卡换needs-user-decision,⛔ 未立 cloud 卡。一句话问题
托管云上每个租户环境的「平台管理员」资格今天靠一行运行时可写的授权行(控制面在建环境时按创建者邮箱写入的
admin_full_access行,env-owner-admin-grant.ts:67/:91)撑着;#11663 的重锚设计要退役的正是这类行,而它设想的替代物(每个部署注入一个OS_PLATFORM_OWNER_EMAIL)在 cloud 的运行时里做不出来:一个容器同进程 LRU 托管最多 50 个租户内核(apps/objectos/cloudflare/worker.ts:283、kernel-manager.ts),环境变量只能是进程级的 —— 一个值就是全部租户共用一位管理员。问维护者:Choice 4B(#11979)落地后,租户环境的管理员锚点该是什么?前提(每条带 re-check,本席采信 dev 实测)
- cloud 控制面自身已具备设计要的一切:注入了
OS_PLATFORM_OWNER_EMAIL(apps/cloud/cloudflare/worker.ts:240)、walled、invite-only(control-plane-preset.ts:531),pin bump PR feat(spec): ADR-0047 — interface/list pages get a lean, relevant config form #1817 已把控制面的 pin 测试改到 L4 的 no-mint 契约。→ 控制面这一半无事可做。re-check:git grep -n OS_PLATFORM_OWNER_EMAIL origin/main -- apps/cloud。 - 租户运行时无 per-environment 环境变量接缝,且不可表示(同进程多内核,env 在构造时装配一次:
worker.ts:169/:279/:413)。re-check:git grep -n -c 'OS_TENANCY_POSTURE\|OS_MULTI_ORG_ENABLED\|OS_PLATFORM_OWNER_EMAIL' origin/main -- apps/objectos= 0(阳性对照 apps/cloud = 5/7)。 - 「已验证邮箱」在接缝处不成立:
environment-provisioning.ts:1064-1071复制创建者邮箱、不读email_verified;environment-owner-seed.ts:91无条件把email_verified: true盖进租户库 —— 租户侧的验证检查(env-owner-admin-grant.ts:143-147)读的是 cloud 声称的验证,不是做过的验证。 - 时序:Choice 4A 今天仍保护 cloud(租户运行时单姿态;platform-admin re-anchor (L5 removal half): delete the legacy grant-row read — one minor after L4's landing #13515 明写保护单姿态资格);真正的依赖是 platform-admin re-anchor follow-up (Choice 4B): config-anchor the
singleposture — first-user promotion becomes development-only fallback #11979(Choice 4B),它一落地,cloud 的两扇门(console handoffauth-proxy-plugin.ts:319、OIDC 中间件env-owner-admin-grant.ts:126)静默失效 —— 授权行照写、只是不再授予,写入方还吞掉自己的错误。L2/L4 的合并提交均已在 pin 内(merge-base 实测),cloud 卡不需要 Blocked-by 它们。
选项 × 真实代价(从业务角度)
选项 做什么 客户可感知的代价 A. 裁定「行就是锚」 数据库按租户、单姿态的托管运行时永久保留授权行锚点;#11979/#13515 为它开豁免而非删除;cloud 只补验证缺口 租户环境的超级用户资格永远是一行任何 system-context 写入都能插的行;失败在两个方向都不可见(写入方吞错)。是设计自己称为「漂移温床」的按姿态双派生形状 B. 声明 owner、单一派生点 控制面记录已验证的环境 owner( ownerSeed升格为 per-environment 的变量对应物),框架提供非 env 的配置源喂给 L2 既有的 6b 派生 —— 行不再是锚,派生点仍只有一个declared = enforced 成立;需要框架半边(在 L2 已有派生点内加一个配置源,不是新机制)+ cloud 半边(记录并核验 owner);过渡期需 A 作时限内的临时状态 C. 每租户一进程 让设计的形状字面成立 推翻运行时经济模型(50 内核/容器、4h LRU、keep-warm 工作流),无任何实测拉动 推荐
B,并显式把 A 记为有时限的过渡态。两条附带条件不随 A/B 变:① #11979 不得先于 cloud 锚点迁移落地,否则托管舰队静默锁死管理员;②
ownerSeed的验证缺口(前提 3)独立于本分叉、今天就削弱 P1,无论裁 A 还是 B 都要修。os-decision-facets
① 项目长远合理性:B 缩小特例 —— 一个派生点、声明即强制;A 把设计要退役的可写行永久化并留下按姿态的豁免,是契约增生;C 与运行时模型相悖。
② 实际业务拉动:今天每个托管租户都靠这行授权行进入自己的环境(已发布产品的既有路径),4B 一落地即断 —— 拉动为实、且有截止期。
③ 防 AI 犯错:B > A > C —— A 让超级用户锚点停留在任何 system-context 写入都能插入、且写入方吞错的行上,失败双向不可见;B 把它收成一次可核验的声明。
④ 创业阶段不扩散:C 出局(零拉动、推翻经济模型);B 的框架半边住进 L2 既有派生点而非新机制;A 零新代码但把临时形状固化成永久义务。
推荐:B(A 作时限过渡)。选项:A / B / C。
本分析看不见什么:ownerSeed在生产库中未验证邮箱的实际比例;#11979 的当前实现是否已带姿态豁免;框架侧「非 env 配置源」的具体形状(L2 派生点是否已预留)。裁后执行段
裁 B ⇒ 本卡收窄为记录卡关闭,cloud 仓立执行卡(记录并核验 owner + 验证缺口修复),框架半边由分诊立
domain:services/engine卡,#11979 挂Blocked-by:指向它;裁 A ⇒ cloud 仓立「验证缺口」执行卡,#11979/#13515 由其席补豁免,本卡关闭;裁 C ⇒ 升级为 ADR 级设计卡。任一裁定同笔摘needs-user-decision。
Generated by Claude Code
- cloud 控制面自身已具备设计要的一切:注入了
os-project-manager commented
on Sep 3, 2026 CollaboratorMore actionsReferred to the maintainer — not ruled (2026-09-03)
Provenance. In the director seat's live session (
session_01ShyhexkB2d1AeRZ85tgAAe), decision batch #24, this card was presented with the cloud seat's fork (comment 5521221594 here; #11663 comment 5521187539) and the recommendation B (declare a verified owner onsys_environment.metadata.ownerSeed, one derivation site; A as a time-boxed interim; two riders: #11979 must not land before the cloud anchor moves, and theownerSeedverification gap is fixed either way). The maintainer's reply, verbatim: 「11977 转维护者,其他同意」 — this card is taken by the maintainer personally; no option was adopted and no seat may act on it as ruled.What this means for the seats.
- ⛔ No cloud card is filed and no framework card is filed on this fork until the maintainer rules on it here or on [Design] Re-anchor platform-admin:
admin_full_accessbecomes a kernel metadata declaration; WHO holds it comes from env-configured verified emails — retiring the org-less row anchor #11663. ⚠️ The sequencing rider stands as a fact, not a ruling: the cloud seat measured that platform-admin re-anchor follow-up (Choice 4B): config-anchor thesingleposture — first-user promotion becomes development-only fallback #11979 (Choice 4B) landing before the cloud anchor moves silently disables both of cloud's owner-admin doors. Whoever dispatches platform-admin re-anchor follow-up (Choice 4B): config-anchor thesingleposture — first-user promotion becomes development-only fallback #11979 reads this before doing so.- The
ownerSeedverification gap (environment-provisioning.ts:1064-1071never readsemail_verified;environment-owner-seed.ts:91stampsemail_verified: true) is part of the same referral and is not carved out.
State.
needs-user-decision→pm:awaiting-maintainerin the same stroke (the same disposition #13564 took in batch #11);repo:cloudkept; unassigned. Ledger: objectstack#12708, batch #24 ledger comment.
Generated by Claude Code
- ⛔ No cloud card is filed and no framework card is filed on this fork until the maintainer rules on it here or on [Design] Re-anchor platform-admin:
状态转换:
pm:awaiting-maintainer→needs-user-decision(2026-09-09)维护者回批逐字:「B 桶 · 要你的判断,应转 needs-user-decision —— 23 张 转决策卡」。
判据:欠判断不是动作 —— 卡面自陈 cloud 座位那条腿是「designed blind」(控制面 env 注入 + 仅邀请交互)。⇒ 它要的是维护者手里的 cloud 侧真实形状,据以定设计;⛔ 不是一次可执行的人工动作,也不是可由席位测量出来的读数。
按
SKILL.md:110/:126:决定待做 =needs-user-decision。⇒ 此前为误分类。同笔摘
pm:awaiting-maintainer;repo:cloud留下。⚠️ 根因见 #17017。
Generated by Claude Code
维护者速读(2026-09-09 更新稿;四棱块与选项 A/B/C 的原分析在 5521221594)
事情:托管云上每个租户环境的「平台管理员」资格,今天靠控制面在建环境时按创建者邮箱写入的一行
admin_full_access授权行撑着;#11663 的重锚设计要退役这类行,替代物「每个部署注入一个OS_PLATFORM_OWNER_EMAIL」在 cloud 的运行时里做不出来(一个容器同进程托管最多 50 个租户内核,环境变量只能是进程级)。cloud 席 09-03 把这一分叉转决策箱,您当时「转维护者」接手未裁。此后的新事实:ADR-0131(您 09-04 接受)D5 直接写了单姿态部署的锚点:「
PLATFORM_ADMIN来自OS_PLATFORM_OWNER_EMAIL(配置);single姿态的首用户晋升(Choice 4A)继续写授权行,改为由 Default Organization 拥有;带墙姿态不写行」——即托管租户运行时(单姿态)的锚点就是那行授权行,只是不再是 NULL 组织。#11979(4B「晋升改为仅开发用」)目前传递阻塞,且 hotlong 09-04 在其上记明 ADR-0131 保留了single下的首用户晋升(#15204 C3 验收原文),所以 cloud 席担心的「4B 一落地两扇门静默失效」今天不会发生。选项:A′(推荐) 按 ADR-0131 D5 关本卡(被取代):cloud 租户运行时的锚点 = Default Organization 拥有的首用户晋升行,不需要 per-environment 变量;剩下一件真实缺陷单独立 cloud 缝卡——控制面
ownerSeed把email_verified: true直接盖进租户库、从不读email_verified(前提 3),需改为只复制已验证的邮箱或只在验证后授予。B(cloud 席原推荐)另建「声明并核验的环境 owner」单一派生点——要在框架 L2 增一个非 env 的配置源,与 D5「配置或 Default-Org 行」的形状重叠,零额外拉动。C 每租户一进程——推翻运行时经济模型,否决。你要做的:回一个字母,A′ / B / C。
- ① 项目长远合理性:A′ 让锚点由 ADR-0131 一处定义(配置,或
single下的 Default-Org 行),缩小特例;B 加第三种派生源。 - ② 实际业务拉动:今天每个托管租户都靠这行进入环境——拉动为实;A′ 不改它,只把它从 NULL 组织改为有主(ADR-0131 迁移承担)。
- ③ 防 AI 犯错:真正的静默失败是验证缺口(cloud 声称已验证 ≠ 做过验证)——A′ 把它单独立卡响亮修;B 不修它也不成立。
- ④ 创业阶段不扩散:A′ 零新机制;B 新配置源;C 出局。
推荐 A′(回退 B)。置信缺口:cloud 仓本会话不可达,ownerSeed 现状按 cloud 席 09-03 实测(environment-provisioning.ts:1064-1071、environment-owner-seed.ts:91)采信,未重测。
裁后执行
- A′ ⇒ 本卡关 not planned(superseded by ADR-0131 D5),摘
needs-user-decision;同笔立缝卡(objectstack,pm:queue+repo:cloud,具名读者 cloud 席):「ownerSeed 验证缺口」;platform-admin re-anchor follow-up (Choice 4B): config-anchor thesingleposture — first-user promotion becomes development-only fallback #11979 上不加动作(已阻塞,ADR-0131 D5 保留 4A)。 - B ⇒ 立框架卡(
domain:services)+ cloud 缝卡,本卡pm:blocked于其后。 - C ⇒ 升级 ADR 级设计卡。
总监席第 20 场(
session_01Tep4AYXZvyBA7jsvne5KZV)按决策箱勤务补齐速读,2026-09-09T05:4xZ;⛔ 非裁决。
Generated by Claude Code
- ① 项目长远合理性:A′ 让锚点由 ADR-0131 一处定义(配置,或
Ruling recorded — A′: superseded by ADR-0131 D5; the one real defect (ownerSeed verification gap) goes to the cloud seat as its own seam card (director seat, summon #20, decision batch #109, 2026-09-09T05:5xZ)
Provenance (who / verbatim / where): maintainer, live PM chat with this seat (
session_01Tep4AYXZvyBA7jsvne5KZV,os-bill), 2026-09-09T05:5xZ, replying to batch #109 in which this card was the single item with the updated 速读 and four-facet block at 5596431581 recommending A′. Reply, verbatim: 「11977 同意,然后处理契约复审」 — A′.Ruled. For a hosted tenant runtime (a
single-posture kernel among up to 50 in one process, no per-environment environment variable), the platform-admin anchor is what ADR-0131 D5 states:PLATFORM_ADMINderives from configuration where configuration exists, and undersinglethe first-user promotion (Choice 4A) keeps writing theadmin_full_accessgrant row — owned by the Default Organization, never NULL. No per-deploymentOS_PLATFORM_OWNER_EMAILinjection into tenant runtimes is required or possible; L8's control-plane half (injection + invite-only on the control plane itself) is already in place per the cloud seat's 09-03 measurement (5521221594 premise 1). B (a new declared-owner derivation source in the framework) and C (one process per tenant) refused. #11979 (4B) stays as it is — transitively blocked, and, per hotlong's 09-04 pointer there, not made dev-only by ADR-0131 — so the cloud doors are not disabled by anything scheduled.Residual defect, split out: the control plane copies the creator's email into the tenant's owner seed without reading
email_verifiedand stampsemail_verified: trueunconditionally (environment-provisioning.ts:1064-1071,environment-owner-seed.ts:91, cloud seat 09-03). That is a cloud-repo bug independent of this fork ⇒ seam card filed in this repo withrepo:cloud(linked below).State, one write: closed
not_planned(superseded by ADR-0131 D5);needs-user-decisionremoved;repo:cloudkept. Parent #11663's L8 row is answered by D5; the epic's own checklist is the epic seat's to update.
Generated by Claude Code
Leg L8 of the accepted #11663 platform-admin re-anchor design — a seam card: the fix lands in the
cloudrepo, which is not reachable from the filing session, so per the cross-repo rule it lives here withrepo:cloud. Named reader: the cloud execution seat, at its queue-scan step — this card is its instruction to open the cloud-side issue and link it back here. Provenance: design document = #11663 comment 5394453215 (§6 row L8, §9 NOT MEASURED disclosure); maintainer acceptance = #11663 comment 5404675670 (2026-08-25, verbatim 「接受你的建议,继续」). Filed by PM sessionsession_01KWRU3s15AJz7PGW7a7wdCh.Blocked-by: #11970
Blocked-by: #11974
Content (cloud side): control-plane injection of
OS_PLATFORM_OWNER_EMAILper deployment (list form, Choice 2B); the invite-only interaction — self-registration must never confer platform admin, only configured verified emails do (this is the structural fix for cloud#1509's class); coordinate with the cloud seat's #1614→#1509 train, ⛔ do not collide with its in-flight acceptance.Acceptance criterion: a cloud-repo issue exists carrying this leg with a back-link here and
Blocked-by:on its own repo's spellings; this card then flips to track it and closes when the cloud leg lands.