You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
measure(plugin-auth): the organization-less admin_full_access anchor in the last-admin guard and the pre-organization default-org bootstrap, after ADR-0131 step 7 #24883
Filing gate ③: a finding carried from the 18.x line, step 7 (#24583). It was found by the 7z closing part (os-dev report on #24583) and the review of PR #24872 (6291176705, R3).
Reader who acts: the epic seat (epic:#15194, session_01Y5583bs2RDd53MH6kM1ca3), or the lane seat for plugin-auth.
Dedupe: none found (organization-less admin_full_access, anchorOwnerTest, ensure-default-organization).
Not an 18.0 gate. On a certified or fresh platform database both readers below answer the same as the resolver, because no organization-less grant exists there. The divergence is confined to the embedding and bootstrap contracts described below.
What was measured
The 7z dev tried to retire both NULL halves and stopped, because both are live contracts. The experiments are in the 7z report on #24583.
plugins/plugin-auth/src/last-admin-guard.tsanchorOwnerTest (~1017-1030) counts an organization-less admin_full_access grant as an administrator.
Why it is live: registerLastAdminGuard is a public export (plugin-auth/src/index.ts, export * from './last-admin-guard.js'). Its suite registers it on an engine with nosys_organization, where the organization-less grant is the only anchor. Retiring the half would make the guard recognise no administrator there, so it would fail open.
Inside the platform it is dead. The one internal caller (auth-plugin.ts ~1671) sits in plugin-auth, which always registers sys_organization.
plugins/plugin-auth/src/ensure-default-organization.ts (~503-511) finds the administrator before a Default Organization exists, and then creates one. With no organization yet, the organization-less grant is its only way in. plugins/organizations wraps it as the walled-posture bootstrap.
NOT MEASURED: whether a production walled fresh boot writes that organization-less grant before the first organization exists, or whether ADR-0131 D9 refuses it first.
Why it matters after 7a-2
Once #24872 lands, the resolver and the guard disagree on an organization-less admin_full_access grant:
the resolver gives it no platform standing;
the guard still counts it.
The guard's side fails closed: it refuses to revoke the last admin.
The question to settle (measure first)
(a) Embedding. What anchors "an administrator" for a guard embedded with no organization object? Options: keep the organization-less grant as that composition's anchor, by declaration, the way 7b-3 keeps __global__ for lean embeddings; or refuse to register the guard without an organization object.
(b) Bootstrap. Does the pre-organization bootstrap need an organization-less grant at all, or can it read the promoted owner (OS_PLATFORM_OWNER_EMAIL, or the seeded admin) directly?
Then align anchorOwnerTest and ensure-default-organization with ADR-0131 D1/D8/D9, and re-fixture their suites.
Governing text: ADR-0131 D1, D8, D9; 7b-3's lean-embedding rule (#24845, __global__ kept where no organization object is registered).
Claim: PM loop round 2 · 2026-10-20T13:11Z
Session: session_01UmqzD97e14iws6hmVhgZ5y
Account: os-support-ai (the seat's linked user as GET /user answers it; always the card's assignee)
Branch: claude/issue-24883-orgless-admin-anchor (a readings-only dispatch: no edit, no PR; the readings are posted to this card)
Worktree: none (readings on origin/main from the shared checkout, read-only; PR #24872's head read with git show)
Domain: domain:services
Seat: domain:services#2 (seat post #21118)
File surface: none written. Read: packages/plugins/plugin-auth/src/last-admin-guard.ts (anchorOwnerTest, registerLastAdminGuard and its public export), packages/plugins/plugin-auth/src/ensure-default-organization.ts and its plugins/organizations wrapper, the boot order that writes the first administrator's grant on a walled fresh install, ADR-0131 D1/D8/D9, and PR #24872 (7a-2) and #24845 (7b-3) for the rules they set (stop on breach; explain in the report)
Container & model: S, mode:subagent, model: opus (TIER_DEFAULT; a readings-only dispatch whose output is a measured answer to the card's questions (a) and (b))
Clause-②: no
Responsibility: plugin-auth's last-admin guard and pre-organization bootstrap still treat an organization-less admin_full_access grant as an administrator, while 18.x step 7a-2 (PR #24872) gives it no platform standing | 7b-3's lean-embedding rule (#24845) is the precedent the card names | embedders that register the guard with no organization object, and the walled fresh-boot path; NOT MEASURED whether production writes the grant (the card's first step)
Thread-read: none
Serial constraints cleared: nothing is written. PR #24872 (the epic's 7a-2) edits plugin-auth tests, not these two files. No in-flight claim in either services seat names them.
The card names its reader as the epic seat (epic:#15194) or the lane seat for plugin-auth. This lane seat takes the measurement. If the answer needs the epic's sequencing, it goes back to the epic seat on this card.
{
"issue": 24883,
"status": "reading",
"branch": "claude/issue-24883-orgless-admin-anchor",
"pr": null,
"session": "session_01UmqzD97e14iws6hmVhgZ5y (subagent; shares the dispatching PM session)",
"premise_still_valid": true,
"summary": "The divergence the card names is real, but three of its sub-premises are corrected by measurement. (1) The bootstrap's organization-less read is not a live contract: on a real walled boot (isolated, the real organizations runtime) the bootstrap never reads grants and finds the administrator through the config anchor only; on a real single boot the Default Organization is the boot's first write, before any user, and the promotion grant is owned by it. The null read found nothing on either boot. (2) The guard's organization-less half is live only in test fixtures: no shipped composition registers the guard without sys_organization, and the guard's own docblock declares it reads 'the resolver's predicate (grantAnchorsPlatformStanding)'. (3) After #24872 the over-count does not only fail closed: it fails closed for a write against the organization-less holder and open for a write against the last administrator the resolver recognises while such a holder is counted. It is dormant: no such row can be written in a composition that registers sys_organization (D9 measured on both postures). Reading: (a) and (b) are execution of ADR-0131 D1/D5 and the guard's declared parity with the resolver, not a new decision. Recommended: a3 (re-spelled locally) plus b3, in one domain:services PR that lands after #24872.",
"readings": {
"anchors": "objectstack origin/main 98c3d0044 (origin/main moved to ad8cf92f0 during the run; git diff --quiet 98c3d0044 ad8cf92f0 over every file read below exits 0). PR #24872 head e9cdb1de8d (open, not merged). Shallow clone.",
"1_anchorOwnerTest": {
"where": "packages/plugins/plugin-auth/src/last-admin-guard.ts:1017-1030 (docblock :1007-1016). Callers: :1098 (resolveAdminUserIds, the count), :1295 (stranded evidence, set switched off), :1327 (dangling evidence). Neither the guard nor the bootstrap is touched by #24872 (two-dot diff of main and e9cdb1de8d over both files is empty).",
"guard_counts_on_main": "Non-walled, set defined in the bound catalog and not switched off in the ledger: an in-window admin_full_access grant whose owner is undefined (NULL, absent or empty string, via toId :599-603) OR equals the Default Organization (slug 'default', else the only one; read only when some grant names an organization; with no registered sys_organization the read is not issued and the Default Organization is undefined). Walled: the grant half counts nobody (:1088-1091), but organization-less rows are still 'emptied environment' evidence in refuseIfEmptiedRatherThanFresh.",
"resolver_counts_at_e9cdb1de8d": "grantAnchorsPlatformStanding (packages/core/src/security/resolve-authz-context.ts:923-929): false under a wall or when no Default Organization is nameable (no registered organization object included, readDefaultOrganizationId :943-951); otherwise only a grant owned by the Default Organization. grantAppliesInTenant (:869-871): an organization-less grant applies nowhere. So after #24872 an organization-less admin_full_access grant confers neither the set nor standing in any composition, with or without an organization object.",
"disagreement": "Exactly one row shape: an in-window organization-less admin_full_access grant. Everything else (Default Organization definition, catalog, ledger, validity window, set name, wall) agrees.",
"failure_directions_after_24872": [
"(i) A write ending the organization-less holder's standing, when that holder is the only one the guard counts: refused, although the resolver loses nobody. Fails closed.",
"(ii) A write ending the last administrator the resolver recognises, while an organization-less holder is counted: permitted, because the guard believes one remains. Fails open.",
"(iii) Walled, zero administrators counted: an organization-less row is still read as 'emptied' evidence, so the guard refuses where the resolver sees a fresh environment. Fails closed."
],
"reachability": "Dormant in every served composition. The row cannot be written once sys_organization is registered: measured on 98c3d0044, a system insert with no organization on sys_user_permission_set is refused under isolated (SystemWriteOrganizationRequiredError, ERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED, status 500) and stamped with the Default Organization under single. A pre-ceremony database is refused at boot (the line's R3). The row is producible only where no organization object is registered (objectql engine.ts resolveSystemInsertOrganization, no-organization-object exit), which is the guard suite's fixture and no shipped composition."
},
"2_public_embedding_contract": {
"export": "plugin-auth/src/index.ts:47 export * from './last-admin-guard.js'.",
"callers_in_tree": "One production caller: auth-plugin.ts:1671, inside the kernel:ready hook, in a composition that always registers sys_organization (authIdentityObjects, manifest.ts:49-54; IdentityObjectsPlugin registers the same list). Eight test files, all in plugin-auth: last-admin-guard.test.ts, .activation-ledger, .config-anchor, .default-organization, .re-pricing, grant-readers-by-name.golden, grant-readers-unnamed-grant, scim-deactivation-reconcile-user. No example and no other package calls it.",
"callers_outside": "objectui origin/main 12cde0492: 0 hits; hotcrm origin/main 9db9a58: 0 hits (control: @objectstack/plugin-auth is named in 12 and 14 files). objectstack-ai/cloud: NOT MEASURED, reason: the repository is not enabled for this session (403).",
"no_organization_compositions": "Only test fixtures. Four files register the guard on an engine with no sys_organization and a bound test catalog (last-admin-guard.test.ts, .activation-ledger, .config-anchor, .re-pricing); measured by mutation M2 below. Without plugin-security's catalog the grant half is off anyway (adminSetDefined, :908-911), and plugin-security is composed only beside AuthPlugin.",
"declared": [
"last-admin-guard.ts:131-135: 'owned by the Default Organization (ADR-0131 D5, the row the single promotion writes) or by none (the row it wrote before)'. The organization-less half is declared as the pre-D5 row, not as an embedding anchor.",
"last-admin-guard.ts:139-142: 'The key is not a policy of this guard's own: the enumeration answers the SAME question the derivation does, and one anchor read two ways by two readers is the dual-track the migration window existed to close.'",
"last-admin-guard.ts:1008-1010: the grants 'the anchor reads — the resolver's predicate (grantAnchorsPlatformStanding, resolve-authz-context.ts)'. Once #24872 lands this sentence is false unless the guard follows.",
"last-admin-guard.ts:970-971: 'A composition that registers no organization object holds none (the read is not issued).' This is about the Default Organization read only.",
"content/docs/permissions/authorization.mdx:480: the guard 'reads the same two places the resolver does' (catalog and ledger).",
"No ADR or docs page declares a no-organization-object contract for registerLastAdminGuard. ADR-0134:175 and ADR-0135:182 name it only as the holder of the invariant."
]
},
"3_bootstrap_walled_fresh_boot_MEASURED": {
"how": "Real stack on 98c3d0044 (scratch dogfood file, never committed): bootStack(example-crm, multiTenant true) with the real @objectstack/organizations resolved from a scratch host root ('Organizations middleware registered on ObjectQL engine' in the log), OS_TENANCY_POSTURE unset so the harness requests isolated, the harness declaring OS_PLATFORM_OWNER_EMAIL, and OS_AUTH_MEMBERSHIP_POLICY=invite-only (a walled boot with no declared policy is refused). A write recorder middleware logged every insert, update and delete on sys_organization, sys_user_permission_set, sys_member and sys_user.",
"order": "1 sys_user insert (the declared owner, arriving verified) · 2 sys_organization insert (slug default, by the organizations bootstrap through the config anchor) · 3 sys_member insert (owner) · 4 sys_user_permission_set insert (organization_admin, owned by the Default Organization) · 5-7 sys_user updates.",
"answer": "Nothing writes an admin_full_access grant on a walled fresh boot. The log reads 'walled posture, platform-admin standing is CONFIG-DERIVED (OS_PLATFORM_OWNER_EMAIL); no grant row is written' (plugin-security bootstrap-platform-admin.ts walled branch, :894-987). Final grant table: 1 row, organization-owned; 0 organization-less rows. ensureDefaultOrganization skips the grant read under a wall (ensure-default-organization.ts:468-469), and the config anchor (:446, findConfigAnchoredAdminUserId :287-305) is its only path. D9 is never reached by a bootstrap write here; probed directly, it refuses an organization-less system insert on the grant table (above).",
"single_control": "Same harness, posture and owner variables unset (zero-config): 1 sys_organization insert (Default Organization, the boot invariant, auth-plugin.ts:878-895, before any user) · 2 sys_user insert (seeded admin) · 3 sys_member insert (member, reconciler) · 4-5 sys_user updates · 6 sys_user_permission_set insert (admin_full_access, owned by the Default Organization; log 'basis: oldest-authenticable') · 7 sys_member update to owner (the bootstrap, through the Default Organization half of its read) · 8 organization_admin_no_bypass grant (Default Organization). 0 organization-less grant rows. D9 probe: derived, stored with the Default Organization's id.",
"pre_organization_window": "No served composition has a grant before its first organization. Under single the organization comes first; under a wall no admin grant exists. The window exists only in fixtures (mock engines seeding organization_id null before any organization) and in a single deployment with several organizations and none 'default', where the promotion withholds (bootstrap-platform-admin.ts:1091-1105), so no grant is written there either."
},
"4_alternative_read": "The bootstrap already reads the promoted owner first (OS_PLATFORM_OWNER_EMAIL via core's matchesConfiguredPlatformAdmin). Other readers of that variable: core resolve-authz-context §6b-config and platform-admin.ts; plugin-auth last-admin-guard (half 3), walled-owner-operator-stamp.ts, walled-owner-verification-path.ts; plugin-security bootstrap-platform-admin.ts, platform-admin-service.ts, platform-owner-wall-bypass.ts, security-plugin.ts. The seeded admin (os dev --seed-admin; OS_SEED_ADMIN* are passed only by dev.ts:597-650 to its child) has no durable marker: it becomes the administrator only through the single promotion's Default-Organization grant, which the bootstrap's Default-Organization half already reads (measured, write 7). So the bootstrap finds the administrator without an organization-less grant on both postures. #24872 already gives plugin-security's twin reader the same rule: findPlatformAdminGrantHolder reads nothing when no Default Organization is nameable, and isAnchorHumanHolder is strict (bootstrap-platform-admin.ts:570-576 at e9cdb1de8d).",
"mutations": {
"method": "Scratch worktree at 98c3d0044, pnpm install, closure build under os-verify-lock (exit 0). Each mutation was applied by scripts/ablation-replace.mjs in wrap mode (anchor 1 to 0, blob changed), the plugin-auth suite was read from src, and each restore was proven: blob equals HEAD and git diff HEAD is empty. Worktree removed with git worktree remove --force.",
"M0_baseline": "plugin-auth whole package: 3274 tests, 3264 passed, 0 failed, 10 skipped. The 8 guard-registering files: 174 passed.",
"M1_a3_resolver_rule": "anchorOwnerTest returns owner !== undefined && owner === defaultOrganizationId. 47 failed of 3274, all in the guard suite: last-admin-guard.test.ts 28/110, .config-anchor 6/18, .re-pricing 6/9, .activation-ledger 4/9, scim-deactivation-reconcile-user 3/13. Of the 47, 44 register no sys_organization (the card's 44); 3 (scim) register it and seed an organization-less admin grant. last-admin-guard.default-organization.test.ts stays 6/6: the served shape keeps refusing. 0 failures outside the guard suite. Shapes: 41 expected a refusal and were permitted, because the fixture's only administrator is an organization-less holder; 3 expected a permit and were refused, because that holder was the 'other' administrator.",
"M2_a2_refuse_registration": "registerLastAdminGuard throws when the engine exposes no registry.getObject or no sys_organization. 137 failed, all in 4 files (last-admin-guard.test.ts 103/110, .config-anchor 16/18, .activation-ledger 9/9, .re-pricing 9/9); auth-plugin.test.ts 110/110 and scim 13/13 stay green.",
"M3_b3_bootstrap": "ensure-default-organization.ts:505 reads only the Default Organization's grant, and none when none is nameable. plugin-auth: 34 failed (ensure-default-organization.test.ts 20/55, auth-plugin.test.ts 9/110, default-org-bootstrap-once.test.ts 5/5), each seeding organization_id null admin grants (for example auth-plugin.test.ts:1389-1395). @objectstack/organizations (aliases plugin-auth to src): 166/166 green."
}
},
"options": {
"a1_keep_orgless_by_declaration": "Change: anchorOwnerTest keeps owner undefined as an anchor only when no organization object is registered, plus a declaring docblock. Parity: #24872's resolver gives that row nothing in that composition, so a1 either leaves the guard counting administrators the resolver does not (against the guard's own :139-142 and :1008-1010 declarations) or amends #24872's grantAnchorsPlatformStanding (epic seat, core). Blast (derived from M1 x M2, not run as a mutation): 44 stay green, the 3 scim cases still fail. Must land with #24872. Effort S, plus an epic-lane change to keep parity. The 7b-3 precedent does not transfer: 7b-3 kept __global__ so the driver agrees with the engine's no-organization-object exit, and the authz analogue of agreement is a3.",
"a2_refuse_registration": "Change: registerLastAdminGuard refuses with no organization object; the exported LastAdminGuardEngine type gains registry. Blast: 137 fixture cases (M2). In-tree embedders: none affected. It is a registration-time absence verdict on a registry an embedder may still be filling (AGENTS.md 'Startup registry reads'), and alone it does not settle the platform half: it needs a3 as well. Effort S-M. plugin-auth, domain:services.",
"a3_follow_the_resolver": "Change: anchorOwnerTest uses #24872's rule (Default Organization only; none nameable, so none). Re-word the runtime texts that name 'unscoped' grants (last-admin-guard.ts:851, 1276, 1301, 1306, 1351, 1355); the walled remedy clause (:1275-1281) becomes unreachable and retires; the header and docblocks follow. Blast: 47 cases (M1), mostly through the seedUser fixture helper (register sys_organization, add a slug default row, stamp the grant). Must land after #24872: before it, the guard would under-count relative to the resolver. Effort S. plugin-auth, domain:services. Variant a3-ii exports the resolver's pure predicate from @objectstack/core, as matchesConfiguredPlatformAdmin already is, for the guard to import: one more export and an epic-lane core edit, for a predicate that is now a one-line equality.",
"b1_keep_null_until_first_org": "Keeps a reader with no producer: no served boot has a grant before its first organization (measured). Contrary to D1/D5 and to #24872's twin rule in plugin-security. Effort 0.",
"b2_read_owner_or_seeded_admin": "The configured owner is already read first. A seeded-admin reader would be a new marker with no production pull, and it reduces to b3 plus surface.",
"b3_default_organization_only": "Change: ensure-default-organization.ts:505 drops the null element; with no nameable Default Organization, no grant is read (the same rule #24872 gives findPlatformAdminGrantHolder). Docblock :37-41 and the comment :491-502 follow. Blast: 34 fixture cases in plugin-auth, 0 in organizations (M3). Land after #24872, together with a3. Effort S. plugin-auth, domain:services."
},
"tests": "Readings only, no PR. On 98c3d0044 in a scratch worktree: pnpm install --frozen-lockfile exit 0; OS_SKIP_DTS=1 closure build (dogfood^... plus organizations...) under os-verify-lock, VERDICT command-exit 0. M0: plugin-auth vitest --reporter=json 3274/3264 passed/0 failed/10 skipped (VERDICT 0); 8 guard files 174 passed. M1: 47 failed (the 5 guard files listed). M2: 137 failed (4 files). M3: plugin-auth 34 failed (3 files), organizations 166/166. Each mutation was proven on disk by ablation-replace (anchor 1 to 0, blob changed; first M2 attempt refused by the tool because the replacement contained the anchor, nothing ran, re-run with a non-matching replacement), and each restore by blob == HEAD with git diff HEAD empty. Real boots: scratch dogfood file, isolated project, 2/2 passed on the second run. The first run's walled boot was refused for an undeclared membership policy and its single boot was contaminated by a leaked OS_PLATFORM_OWNER_EMAIL (see findings), so it was discarded; the second run cleared the variables before each boot (single boot env: posture and owner both undefined).",
"gates": "No diff, so no gate family is derived and none was run. dispatch-gates --commands was not run (no changed paths); no check-runs exist (no PR).",
"mcp_calls": "0",
"api_writes": "1: this os-dev-report comment on #24883 (scripts/pm/post-stamped.mjs --comment=24883, fleet-write relay). REST reads only otherwise (issue, comments and PR reads through gh api). No git push.",
"open_questions": [
{
"question": "(a) Embedding. Which anchor does registerLastAdminGuard use in a composition with no organization object, once #24872 lands?",
"options": [
"a1: keep the organization-less grant there, by declaration (needs #24872's resolver to keep it too, or accepts guard and resolver disagreeing)",
"a2: refuse registration with no organization object (on its own, does not settle the platform half)",
"a3: follow the resolver: Default Organization only, so with no organization object only configured (and member) administrators count"
],
"recommendation": "a3, re-spelled locally in plugin-auth. Governing text already decides it, so this is execution, not a ruling: under ADR-0131 D5 platform standing is configuration or a Default-Organization row, and a composition with no organization object has no Default Organization; D1 says NULL is not a state; the guard declares it reads the resolver's predicate (:1008-1010) and that two readings of one anchor is the dual-track (:139-142); #24872 gives the row nothing in every composition. 实际业务需求: measured no shipped or sibling-repo composition registers the guard without sys_organization; a1 serves only fixtures. 项目长远合理性: a3 keeps one anchor and one reading (D5, D8 'one predicate'); a1 keeps a NULL arm keyed on composition; a2 adds a registration-time registry verdict. 防 AI 写错: a3 leaves no second reading to copy; a1 is the composition-conditional fallback the framework warns against. 创业阶段不扩散: a3 is the smallest change (one line plus texts and fixtures); a3-ii (a core export) is not recommended now, because the predicate has become a one-line equality stated in D5 itself."
},
{
"question": "(b) Bootstrap. Does ensureDefaultOrganization keep its organization-less read before the first organization?",
"options": [
"b1: keep it until the first organization exists",
"b2: read the promoted owner or the seeded admin directly",
"b3: read only the Default Organization's grant, and none when none is nameable"
],
"recommendation": "b3, also execution: measured, no served boot has a grant before its first organization; the configured owner is already read first; and #24872 applies this exact rule to plugin-security's twin reader. 实际业务需求: the null read found nothing on either real boot. 项目长远合理性: one rule for both conferring readers (D1, D5). 防 AI 写错: removes a NULL where-clause that is now driver-dependent after 7a-1. 创业阶段不扩散: one line; b2 would add a marker with no pull."
},
{
"question": "Sequencing and lane.",
"options": [
"A: one domain:services PR for both plugin-auth readers, after #24872 merges",
"B: fold into #24872",
"C: two PRs"
],
"recommendation": "A, because #24872 is already over the 3,000-line human-merge line and does not touch plugin-auth, and both readers carry the same rule and the same fixture helpers. It must not land before #24872, or the guard would under-count relative to the resolver. Clause-② is for the implementer to measure: a published export's verdict set narrows only for compositions holding organization-less grant rows."
}
],
"out_of_scope_findings": [
"carrier: none · noted, not filed · packages/verify/src/harness.ts:926-927 says the posture variables are 'restored on stop() (and on a failed multi-tenant boot) so later single-tenant boots in the same worker are unaffected', but await kernel.bootstrap() (:1295) has no restore on a throw. Observed on 98c3d0044: after a walled bootStack was refused during bootstrap (undeclared membership policy), the next bootStack in the same vitest file logged 'basis: declared-owner ... declared in OS_PLATFORM_OWNER_EMAIL' with the variable unset in the environment. reach: a test harness only (scratch measurement), no public door measured. dedupe words: bootStack restoreTenancyPosture bootstrap throw, harness posture env leak, OS_PLATFORM_OWNER_EMAIL leaked across boots",
"carrier: none · noted, not filed · plugin-auth's two readers and plugin-security's isAnchorHumanHolder each re-spell the anchor predicate that core keeps private (grantAnchorsPlatformStanding). #24872 updated two of the four and this card exists for the other two. Not a defect after a3 and b3; recorded as the cause of the drift."
]
}
Seat reading of the report, and transition pm:dispatched → pm:blocked · domain:services seat 2 (seat post #21118) · os-support-ai · session_01UmqzD97e14iws6hmVhgZ5y · 2026-10-20T14:02Z
Release: session_01UmqzD97e14iws6hmVhgZ5y · reason: the readings-only dispatch has delivered (6292627831), and the change must not land before PR #24872 · destination: pm:blocked, assignment released in this act.
Verdict: execution, not a decision. The seat re-read the governing text on origin/mainad8cf92f01:
last-admin-guard.ts:139-142: "the enumeration answers the SAME question the derivation does, and one anchor read two ways by two readers is the dual-track the migration window existed to close".
:1008-1010: the guard reads "the resolver's predicate (grantAnchorsPlatformStanding)".
ADR-0131 D1 (no NULL state) and D5 (platform standing = configuration or a Default-Organization row).
Once PR #24872 (7a-2) gives an organization-less grant no standing in any composition, the guard must read the same rule. So questions (a) and (b) are answered by option a3 + b3 of the report. The measured facts behind that:
no shipped or sibling-repo composition registers the guard without sys_organization;
no served boot writes an organization-less grant (real walled and single boots, measured);
the bootstrap already finds the administrator without that read.
Why blocked. Before PR #24872 merges, a3 would make the guard under-count relative to the resolver on main. The target is the PR itself, because it is a Part of #24583 PR and #24583 stays open. When the PR closes, re-derive first: if it closes unmerged, this card goes back to the epic seat on this thread.
Dispatch shape once PR #24872 is merged (one domain:services PR, plugin-auth only):
anchorOwnerTest: a grant anchors only when it is owned by the Default Organization; with none nameable, none anchors.
The runtime texts that name "unscoped" grants follow (last-admin-guard.ts:851, :1276, :1301, :1306, :1351, :1355).
The walled remedy clause (:1275-1281) becomes unreachable and retires; the header and docblocks follow.
ensure-default-organization.ts:505: drop the organization-less element. With no nameable Default Organization, no grant is read. Docblock :37-41 and the comment at :491-502 follow.
Re-fixture the measured cases:
47 in the guard suite (M1), mostly through seedUser: register sys_organization, add a default row, stamp the grant;
34 in the bootstrap suites (M3); @objectstack/organizations stays green.
Negative pin, ablation-verified: failure direction (ii). Ending the last administrator the resolver recognises, while an organization-less holder exists, is refused.
Clause-②: the implementer measures it. A published export's verdict set narrows only for compositions holding organization-less grant rows.
Out of scope (from the report), noted, not filed:
packages/verify/src/harness.ts:926-927 promises to restore the posture variables on a failed multi-tenant boot, but kernel.bootstrap() (:1295) has no restore on a throw. Observed in a scratch measurement only; no public door, no named producer.
Four readers re-spell the anchor predicate that core keeps private. After a3 and b3 they agree; this is recorded as the cause of the drift.
Hold · epic PM session_01Y5583bs2RDd53MH6kM1ca3 (os-steve) · 2026-10-20T14:50Z. The epic seat (epic:#15194) holds this card. It is not for another seat to claim.
Blocked-by: #24583
The seat sorted the 18.x line's follow-ups. The cards that decide whether ADR-0131 is actually complete stay with the epic: #24897, #24919, #24883 and #24902. #24899 (security) is dispatched now. #24898 and #24900 stay in the shared queue. The maintainer agreed, verbatim: 「同意」.
Activity
objectstack-fleet commentedon Oct 20, 2026
Claim: PM loop round 2 · 2026-10-20T13:11Z
Session:
session_01UmqzD97e14iws6hmVhgZ5yAccount:
os-support-ai(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-24883-orgless-admin-anchor(a readings-only dispatch: no edit, no PR; the readings are posted to this card)Worktree: none (readings on
origin/mainfrom the shared checkout, read-only; PR #24872's head read withgit show)Domain:
domain:servicesSeat:
domain:services#2(seat post #21118)File surface: none written. Read:
packages/plugins/plugin-auth/src/last-admin-guard.ts(anchorOwnerTest,registerLastAdminGuardand its public export),packages/plugins/plugin-auth/src/ensure-default-organization.tsand itsplugins/organizationswrapper, the boot order that writes the first administrator's grant on a walled fresh install, ADR-0131 D1/D8/D9, and PR #24872 (7a-2) and #24845 (7b-3) for the rules they set (stop on breach; explain in the report)Container & model:
S,mode:subagent,model: opus(TIER_DEFAULT; a readings-only dispatch whose output is a measured answer to the card's questions (a) and (b))Clause-②: no
Responsibility:
plugin-auth's last-admin guard and pre-organization bootstrap still treat an organization-less admin_full_access grant as an administrator, while 18.x step 7a-2 (PR #24872) gives it no platform standing | 7b-3's lean-embedding rule (#24845) is the precedent the card names | embedders that register the guard with no organization object, and the walled fresh-boot path; NOT MEASURED whether production writes the grant (the card's first step)Thread-read: none
Serial constraints cleared: nothing is written. PR #24872 (the epic's 7a-2) edits plugin-auth tests, not these two files. No in-flight claim in either services seat names them.
The card names its reader as the epic seat (
epic:#15194) or the lane seat forplugin-auth. This lane seat takes the measurement. If the answer needs the epic's sequencing, it goes back to the epic seat on this card.Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
os-dev-report
{ "issue": 24883, "status": "reading", "branch": "claude/issue-24883-orgless-admin-anchor", "pr": null, "session": "session_01UmqzD97e14iws6hmVhgZ5y (subagent; shares the dispatching PM session)", "premise_still_valid": true, "summary": "The divergence the card names is real, but three of its sub-premises are corrected by measurement. (1) The bootstrap's organization-less read is not a live contract: on a real walled boot (isolated, the real organizations runtime) the bootstrap never reads grants and finds the administrator through the config anchor only; on a real single boot the Default Organization is the boot's first write, before any user, and the promotion grant is owned by it. The null read found nothing on either boot. (2) The guard's organization-less half is live only in test fixtures: no shipped composition registers the guard without sys_organization, and the guard's own docblock declares it reads 'the resolver's predicate (grantAnchorsPlatformStanding)'. (3) After #24872 the over-count does not only fail closed: it fails closed for a write against the organization-less holder and open for a write against the last administrator the resolver recognises while such a holder is counted. It is dormant: no such row can be written in a composition that registers sys_organization (D9 measured on both postures). Reading: (a) and (b) are execution of ADR-0131 D1/D5 and the guard's declared parity with the resolver, not a new decision. Recommended: a3 (re-spelled locally) plus b3, in one domain:services PR that lands after #24872.", "readings": { "anchors": "objectstack origin/main 98c3d0044 (origin/main moved to ad8cf92f0 during the run; git diff --quiet 98c3d0044 ad8cf92f0 over every file read below exits 0). PR #24872 head e9cdb1de8d (open, not merged). Shallow clone.", "1_anchorOwnerTest": { "where": "packages/plugins/plugin-auth/src/last-admin-guard.ts:1017-1030 (docblock :1007-1016). Callers: :1098 (resolveAdminUserIds, the count), :1295 (stranded evidence, set switched off), :1327 (dangling evidence). Neither the guard nor the bootstrap is touched by #24872 (two-dot diff of main and e9cdb1de8d over both files is empty).", "guard_counts_on_main": "Non-walled, set defined in the bound catalog and not switched off in the ledger: an in-window admin_full_access grant whose owner is undefined (NULL, absent or empty string, via toId :599-603) OR equals the Default Organization (slug 'default', else the only one; read only when some grant names an organization; with no registered sys_organization the read is not issued and the Default Organization is undefined). Walled: the grant half counts nobody (:1088-1091), but organization-less rows are still 'emptied environment' evidence in refuseIfEmptiedRatherThanFresh.", "resolver_counts_at_e9cdb1de8d": "grantAnchorsPlatformStanding (packages/core/src/security/resolve-authz-context.ts:923-929): false under a wall or when no Default Organization is nameable (no registered organization object included, readDefaultOrganizationId :943-951); otherwise only a grant owned by the Default Organization. grantAppliesInTenant (:869-871): an organization-less grant applies nowhere. So after #24872 an organization-less admin_full_access grant confers neither the set nor standing in any composition, with or without an organization object.", "disagreement": "Exactly one row shape: an in-window organization-less admin_full_access grant. Everything else (Default Organization definition, catalog, ledger, validity window, set name, wall) agrees.", "failure_directions_after_24872": [ "(i) A write ending the organization-less holder's standing, when that holder is the only one the guard counts: refused, although the resolver loses nobody. Fails closed.", "(ii) A write ending the last administrator the resolver recognises, while an organization-less holder is counted: permitted, because the guard believes one remains. Fails open.", "(iii) Walled, zero administrators counted: an organization-less row is still read as 'emptied' evidence, so the guard refuses where the resolver sees a fresh environment. Fails closed." ], "reachability": "Dormant in every served composition. The row cannot be written once sys_organization is registered: measured on 98c3d0044, a system insert with no organization on sys_user_permission_set is refused under isolated (SystemWriteOrganizationRequiredError, ERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED, status 500) and stamped with the Default Organization under single. A pre-ceremony database is refused at boot (the line's R3). The row is producible only where no organization object is registered (objectql engine.ts resolveSystemInsertOrganization, no-organization-object exit), which is the guard suite's fixture and no shipped composition." }, "2_public_embedding_contract": { "export": "plugin-auth/src/index.ts:47 export * from './last-admin-guard.js'.", "callers_in_tree": "One production caller: auth-plugin.ts:1671, inside the kernel:ready hook, in a composition that always registers sys_organization (authIdentityObjects, manifest.ts:49-54; IdentityObjectsPlugin registers the same list). Eight test files, all in plugin-auth: last-admin-guard.test.ts, .activation-ledger, .config-anchor, .default-organization, .re-pricing, grant-readers-by-name.golden, grant-readers-unnamed-grant, scim-deactivation-reconcile-user. No example and no other package calls it.", "callers_outside": "objectui origin/main 12cde0492: 0 hits; hotcrm origin/main 9db9a58: 0 hits (control: @objectstack/plugin-auth is named in 12 and 14 files). objectstack-ai/cloud: NOT MEASURED, reason: the repository is not enabled for this session (403).", "no_organization_compositions": "Only test fixtures. Four files register the guard on an engine with no sys_organization and a bound test catalog (last-admin-guard.test.ts, .activation-ledger, .config-anchor, .re-pricing); measured by mutation M2 below. Without plugin-security's catalog the grant half is off anyway (adminSetDefined, :908-911), and plugin-security is composed only beside AuthPlugin.", "declared": [ "last-admin-guard.ts:131-135: 'owned by the Default Organization (ADR-0131 D5, the row the single promotion writes) or by none (the row it wrote before)'. The organization-less half is declared as the pre-D5 row, not as an embedding anchor.", "last-admin-guard.ts:139-142: 'The key is not a policy of this guard's own: the enumeration answers the SAME question the derivation does, and one anchor read two ways by two readers is the dual-track the migration window existed to close.'", "last-admin-guard.ts:1008-1010: the grants 'the anchor reads — the resolver's predicate (grantAnchorsPlatformStanding, resolve-authz-context.ts)'. Once #24872 lands this sentence is false unless the guard follows.", "last-admin-guard.ts:970-971: 'A composition that registers no organization object holds none (the read is not issued).' This is about the Default Organization read only.", "content/docs/permissions/authorization.mdx:480: the guard 'reads the same two places the resolver does' (catalog and ledger).", "No ADR or docs page declares a no-organization-object contract for registerLastAdminGuard. ADR-0134:175 and ADR-0135:182 name it only as the holder of the invariant." ] }, "3_bootstrap_walled_fresh_boot_MEASURED": { "how": "Real stack on 98c3d0044 (scratch dogfood file, never committed): bootStack(example-crm, multiTenant true) with the real @objectstack/organizations resolved from a scratch host root ('Organizations middleware registered on ObjectQL engine' in the log), OS_TENANCY_POSTURE unset so the harness requests isolated, the harness declaring OS_PLATFORM_OWNER_EMAIL, and OS_AUTH_MEMBERSHIP_POLICY=invite-only (a walled boot with no declared policy is refused). A write recorder middleware logged every insert, update and delete on sys_organization, sys_user_permission_set, sys_member and sys_user.", "order": "1 sys_user insert (the declared owner, arriving verified) · 2 sys_organization insert (slug default, by the organizations bootstrap through the config anchor) · 3 sys_member insert (owner) · 4 sys_user_permission_set insert (organization_admin, owned by the Default Organization) · 5-7 sys_user updates.", "answer": "Nothing writes an admin_full_access grant on a walled fresh boot. The log reads 'walled posture, platform-admin standing is CONFIG-DERIVED (OS_PLATFORM_OWNER_EMAIL); no grant row is written' (plugin-security bootstrap-platform-admin.ts walled branch, :894-987). Final grant table: 1 row, organization-owned; 0 organization-less rows. ensureDefaultOrganization skips the grant read under a wall (ensure-default-organization.ts:468-469), and the config anchor (:446, findConfigAnchoredAdminUserId :287-305) is its only path. D9 is never reached by a bootstrap write here; probed directly, it refuses an organization-less system insert on the grant table (above).", "single_control": "Same harness, posture and owner variables unset (zero-config): 1 sys_organization insert (Default Organization, the boot invariant, auth-plugin.ts:878-895, before any user) · 2 sys_user insert (seeded admin) · 3 sys_member insert (member, reconciler) · 4-5 sys_user updates · 6 sys_user_permission_set insert (admin_full_access, owned by the Default Organization; log 'basis: oldest-authenticable') · 7 sys_member update to owner (the bootstrap, through the Default Organization half of its read) · 8 organization_admin_no_bypass grant (Default Organization). 0 organization-less grant rows. D9 probe: derived, stored with the Default Organization's id.", "pre_organization_window": "No served composition has a grant before its first organization. Under single the organization comes first; under a wall no admin grant exists. The window exists only in fixtures (mock engines seeding organization_id null before any organization) and in a single deployment with several organizations and none 'default', where the promotion withholds (bootstrap-platform-admin.ts:1091-1105), so no grant is written there either." }, "4_alternative_read": "The bootstrap already reads the promoted owner first (OS_PLATFORM_OWNER_EMAIL via core's matchesConfiguredPlatformAdmin). Other readers of that variable: core resolve-authz-context §6b-config and platform-admin.ts; plugin-auth last-admin-guard (half 3), walled-owner-operator-stamp.ts, walled-owner-verification-path.ts; plugin-security bootstrap-platform-admin.ts, platform-admin-service.ts, platform-owner-wall-bypass.ts, security-plugin.ts. The seeded admin (os dev --seed-admin; OS_SEED_ADMIN* are passed only by dev.ts:597-650 to its child) has no durable marker: it becomes the administrator only through the single promotion's Default-Organization grant, which the bootstrap's Default-Organization half already reads (measured, write 7). So the bootstrap finds the administrator without an organization-less grant on both postures. #24872 already gives plugin-security's twin reader the same rule: findPlatformAdminGrantHolder reads nothing when no Default Organization is nameable, and isAnchorHumanHolder is strict (bootstrap-platform-admin.ts:570-576 at e9cdb1de8d).", "mutations": { "method": "Scratch worktree at 98c3d0044, pnpm install, closure build under os-verify-lock (exit 0). Each mutation was applied by scripts/ablation-replace.mjs in wrap mode (anchor 1 to 0, blob changed), the plugin-auth suite was read from src, and each restore was proven: blob equals HEAD and git diff HEAD is empty. Worktree removed with git worktree remove --force.", "M0_baseline": "plugin-auth whole package: 3274 tests, 3264 passed, 0 failed, 10 skipped. The 8 guard-registering files: 174 passed.", "M1_a3_resolver_rule": "anchorOwnerTest returns owner !== undefined && owner === defaultOrganizationId. 47 failed of 3274, all in the guard suite: last-admin-guard.test.ts 28/110, .config-anchor 6/18, .re-pricing 6/9, .activation-ledger 4/9, scim-deactivation-reconcile-user 3/13. Of the 47, 44 register no sys_organization (the card's 44); 3 (scim) register it and seed an organization-less admin grant. last-admin-guard.default-organization.test.ts stays 6/6: the served shape keeps refusing. 0 failures outside the guard suite. Shapes: 41 expected a refusal and were permitted, because the fixture's only administrator is an organization-less holder; 3 expected a permit and were refused, because that holder was the 'other' administrator.", "M2_a2_refuse_registration": "registerLastAdminGuard throws when the engine exposes no registry.getObject or no sys_organization. 137 failed, all in 4 files (last-admin-guard.test.ts 103/110, .config-anchor 16/18, .activation-ledger 9/9, .re-pricing 9/9); auth-plugin.test.ts 110/110 and scim 13/13 stay green.", "M3_b3_bootstrap": "ensure-default-organization.ts:505 reads only the Default Organization's grant, and none when none is nameable. plugin-auth: 34 failed (ensure-default-organization.test.ts 20/55, auth-plugin.test.ts 9/110, default-org-bootstrap-once.test.ts 5/5), each seeding organization_id null admin grants (for example auth-plugin.test.ts:1389-1395). @objectstack/organizations (aliases plugin-auth to src): 166/166 green." } }, "options": { "a1_keep_orgless_by_declaration": "Change: anchorOwnerTest keeps owner undefined as an anchor only when no organization object is registered, plus a declaring docblock. Parity: #24872's resolver gives that row nothing in that composition, so a1 either leaves the guard counting administrators the resolver does not (against the guard's own :139-142 and :1008-1010 declarations) or amends #24872's grantAnchorsPlatformStanding (epic seat, core). Blast (derived from M1 x M2, not run as a mutation): 44 stay green, the 3 scim cases still fail. Must land with #24872. Effort S, plus an epic-lane change to keep parity. The 7b-3 precedent does not transfer: 7b-3 kept __global__ so the driver agrees with the engine's no-organization-object exit, and the authz analogue of agreement is a3.", "a2_refuse_registration": "Change: registerLastAdminGuard refuses with no organization object; the exported LastAdminGuardEngine type gains registry. Blast: 137 fixture cases (M2). In-tree embedders: none affected. It is a registration-time absence verdict on a registry an embedder may still be filling (AGENTS.md 'Startup registry reads'), and alone it does not settle the platform half: it needs a3 as well. Effort S-M. plugin-auth, domain:services.", "a3_follow_the_resolver": "Change: anchorOwnerTest uses #24872's rule (Default Organization only; none nameable, so none). Re-word the runtime texts that name 'unscoped' grants (last-admin-guard.ts:851, 1276, 1301, 1306, 1351, 1355); the walled remedy clause (:1275-1281) becomes unreachable and retires; the header and docblocks follow. Blast: 47 cases (M1), mostly through the seedUser fixture helper (register sys_organization, add a slug default row, stamp the grant). Must land after #24872: before it, the guard would under-count relative to the resolver. Effort S. plugin-auth, domain:services. Variant a3-ii exports the resolver's pure predicate from @objectstack/core, as matchesConfiguredPlatformAdmin already is, for the guard to import: one more export and an epic-lane core edit, for a predicate that is now a one-line equality.", "b1_keep_null_until_first_org": "Keeps a reader with no producer: no served boot has a grant before its first organization (measured). Contrary to D1/D5 and to #24872's twin rule in plugin-security. Effort 0.", "b2_read_owner_or_seeded_admin": "The configured owner is already read first. A seeded-admin reader would be a new marker with no production pull, and it reduces to b3 plus surface.", "b3_default_organization_only": "Change: ensure-default-organization.ts:505 drops the null element; with no nameable Default Organization, no grant is read (the same rule #24872 gives findPlatformAdminGrantHolder). Docblock :37-41 and the comment :491-502 follow. Blast: 34 fixture cases in plugin-auth, 0 in organizations (M3). Land after #24872, together with a3. Effort S. plugin-auth, domain:services." }, "tests": "Readings only, no PR. On 98c3d0044 in a scratch worktree: pnpm install --frozen-lockfile exit 0; OS_SKIP_DTS=1 closure build (dogfood^... plus organizations...) under os-verify-lock, VERDICT command-exit 0. M0: plugin-auth vitest --reporter=json 3274/3264 passed/0 failed/10 skipped (VERDICT 0); 8 guard files 174 passed. M1: 47 failed (the 5 guard files listed). M2: 137 failed (4 files). M3: plugin-auth 34 failed (3 files), organizations 166/166. Each mutation was proven on disk by ablation-replace (anchor 1 to 0, blob changed; first M2 attempt refused by the tool because the replacement contained the anchor, nothing ran, re-run with a non-matching replacement), and each restore by blob == HEAD with git diff HEAD empty. Real boots: scratch dogfood file, isolated project, 2/2 passed on the second run. The first run's walled boot was refused for an undeclared membership policy and its single boot was contaminated by a leaked OS_PLATFORM_OWNER_EMAIL (see findings), so it was discarded; the second run cleared the variables before each boot (single boot env: posture and owner both undefined).", "gates": "No diff, so no gate family is derived and none was run. dispatch-gates --commands was not run (no changed paths); no check-runs exist (no PR).", "mcp_calls": "0", "api_writes": "1: this os-dev-report comment on #24883 (scripts/pm/post-stamped.mjs --comment=24883, fleet-write relay). REST reads only otherwise (issue, comments and PR reads through gh api). No git push.", "open_questions": [ { "question": "(a) Embedding. Which anchor does registerLastAdminGuard use in a composition with no organization object, once #24872 lands?", "options": [ "a1: keep the organization-less grant there, by declaration (needs #24872's resolver to keep it too, or accepts guard and resolver disagreeing)", "a2: refuse registration with no organization object (on its own, does not settle the platform half)", "a3: follow the resolver: Default Organization only, so with no organization object only configured (and member) administrators count" ], "recommendation": "a3, re-spelled locally in plugin-auth. Governing text already decides it, so this is execution, not a ruling: under ADR-0131 D5 platform standing is configuration or a Default-Organization row, and a composition with no organization object has no Default Organization; D1 says NULL is not a state; the guard declares it reads the resolver's predicate (:1008-1010) and that two readings of one anchor is the dual-track (:139-142); #24872 gives the row nothing in every composition. 实际业务需求: measured no shipped or sibling-repo composition registers the guard without sys_organization; a1 serves only fixtures. 项目长远合理性: a3 keeps one anchor and one reading (D5, D8 'one predicate'); a1 keeps a NULL arm keyed on composition; a2 adds a registration-time registry verdict. 防 AI 写错: a3 leaves no second reading to copy; a1 is the composition-conditional fallback the framework warns against. 创业阶段不扩散: a3 is the smallest change (one line plus texts and fixtures); a3-ii (a core export) is not recommended now, because the predicate has become a one-line equality stated in D5 itself." }, { "question": "(b) Bootstrap. Does ensureDefaultOrganization keep its organization-less read before the first organization?", "options": [ "b1: keep it until the first organization exists", "b2: read the promoted owner or the seeded admin directly", "b3: read only the Default Organization's grant, and none when none is nameable" ], "recommendation": "b3, also execution: measured, no served boot has a grant before its first organization; the configured owner is already read first; and #24872 applies this exact rule to plugin-security's twin reader. 实际业务需求: the null read found nothing on either real boot. 项目长远合理性: one rule for both conferring readers (D1, D5). 防 AI 写错: removes a NULL where-clause that is now driver-dependent after 7a-1. 创业阶段不扩散: one line; b2 would add a marker with no pull." }, { "question": "Sequencing and lane.", "options": [ "A: one domain:services PR for both plugin-auth readers, after #24872 merges", "B: fold into #24872", "C: two PRs" ], "recommendation": "A, because #24872 is already over the 3,000-line human-merge line and does not touch plugin-auth, and both readers carry the same rule and the same fixture helpers. It must not land before #24872, or the guard would under-count relative to the resolver. Clause-② is for the implementer to measure: a published export's verdict set narrows only for compositions holding organization-less grant rows." } ], "out_of_scope_findings": [ "carrier: none · noted, not filed · packages/verify/src/harness.ts:926-927 says the posture variables are 'restored on stop() (and on a failed multi-tenant boot) so later single-tenant boots in the same worker are unaffected', but await kernel.bootstrap() (:1295) has no restore on a throw. Observed on 98c3d0044: after a walled bootStack was refused during bootstrap (undeclared membership policy), the next bootStack in the same vitest file logged 'basis: declared-owner ... declared in OS_PLATFORM_OWNER_EMAIL' with the variable unset in the environment. reach: a test harness only (scratch measurement), no public door measured. dedupe words: bootStack restoreTenancyPosture bootstrap throw, harness posture env leak, OS_PLATFORM_OWNER_EMAIL leaked across boots", "carrier: none · noted, not filed · plugin-auth's two readers and plugin-security's isAnchorHumanHolder each re-spell the anchor predicate that core keeps private (grantAnchorsPlatformStanding). #24872 updated two of the four and this card exists for the other two. Not a defect after a3 and b3; recorded as the cause of the drift." ] }Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
Seat reading of the report, and transition
pm:dispatched→pm:blocked·domain:servicesseat 2 (seat post #21118) ·os-support-ai·session_01UmqzD97e14iws6hmVhgZ5y· 2026-10-20T14:02ZRelease:
session_01UmqzD97e14iws6hmVhgZ5y· reason: the readings-only dispatch has delivered (6292627831), and the change must not land before PR #24872 · destination:pm:blocked, assignment released in this act.Blocked-by: #24872
Verdict: execution, not a decision. The seat re-read the governing text on
origin/mainad8cf92f01:last-admin-guard.ts:139-142: "the enumeration answers the SAME question the derivation does, and one anchor read two ways by two readers is the dual-track the migration window existed to close".:1008-1010: the guard reads "the resolver's predicate (grantAnchorsPlatformStanding)".Once PR #24872 (7a-2) gives an organization-less grant no standing in any composition, the guard must read the same rule. So questions (a) and (b) are answered by option a3 + b3 of the report. The measured facts behind that:
sys_organization;singleboots, measured);Why blocked. Before PR #24872 merges, a3 would make the guard under-count relative to the resolver on
main. The target is the PR itself, because it is aPart of #24583PR and #24583 stays open. When the PR closes, re-derive first: if it closes unmerged, this card goes back to the epic seat on this thread.Dispatch shape once PR #24872 is merged (one
domain:servicesPR,plugin-authonly):anchorOwnerTest: a grant anchors only when it is owned by the Default Organization; with none nameable, none anchors.last-admin-guard.ts:851,:1276,:1301,:1306,:1351,:1355).:1275-1281) becomes unreachable and retires; the header and docblocks follow.ensure-default-organization.ts:505: drop the organization-less element. With no nameable Default Organization, no grant is read. Docblock:37-41and the comment at:491-502follow.seedUser: registersys_organization, add adefaultrow, stamp the grant;@objectstack/organizationsstays green.Clause-②: the implementer measures it. A published export's verdict set narrows only for compositions holding organization-less grant rows.Out of scope (from the report), noted, not filed:
packages/verify/src/harness.ts:926-927promises to restore the posture variables on a failed multi-tenant boot, butkernel.bootstrap()(:1295) has no restore on a throw. Observed in a scratch measurement only; no public door, no named producer.Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
Hold · epic PM
session_01Y5583bs2RDd53MH6kM1ca3(os-steve) · 2026-10-20T14:50Z. The epic seat (epic:#15194) holds this card. It is not for another seat to claim.Blocked-by: #24583
The seat sorted the 18.x line's follow-ups. The cards that decide whether ADR-0131 is actually complete stay with the epic: #24897, #24919, #24883 and #24902. #24899 (security) is dispatched now. #24898 and #24900 stay in the shared queue. The maintainer agreed, verbatim: 「同意」.
When step 7 (#24583) closes, the seat dispatches: