Skip to content

platform-admin re-anchor follow-up (Choice 4B): config-anchor the single posture — first-user promotion becomes development-only fallback #11979

Description

@os-support-ai

Sequenced follow-up ruled, not optional, in #11663's acceptance (Choice 4: 「4A for the first landing, with 4B filed as the sequenced follow-up」). Provenance: design document = #11663 comment 5394453215 (§4 Choice 4, migration step 8); maintainer acceptance = #11663 comment 5404675670 (2026-08-25, verbatim 「接受你的建议,继续」). Filed by PM session session_01KWRU3s15AJz7PGW7a7wdCh.

Re-derived by the epic seat (epic:#15194): the Blocked-by: #15204 line that stood here is removed. C3's code this card depends on has landed, and the one C3 item left for it, the Default-Organization ownership of the promotion grant, is this card's own acceptance. It is dispatched as C8 stage 8b-0a (plan 6251466182 on #15212).

⛔ Blocked-by: #11974 was struck 2026-09-01 — that leg is SPENT. #11974 closed 2026-08-31T01:36:53Z, so the edge could never fire again while it sat here advertising an unmet dependency. Struck by the domain:engine seat (session session_01Q5WBDtaUnoz5XuJ6jk8pQ5) on the half-state patrol's H19 row, which reads a partial discharge and reports it rather than deciding it.

⚠️ The remaining wait is TRANSITIVE (patrol row H26), so this card is NOT dispatchable: #11978 is itself pm:blocked — on #11975, which is in turn the sound half of a mutual-Blocked-by deadlock with #13515 that was repaired on #13515 on 2026-09-01. ⇒ This card waits on a card that is waiting on a card. A single-level unlock predicate cannot see past one hop, so re-derive this blocker when the #11978 → #11975 → #13515 chain clears — ⛔ do not read #11978's closure alone as this card's release without re-reading the chain.

Content: ⚠️ REWRITTEN 2026-09-18T05:39Z to ADR-0131 D5 under the maintainer's ruling on #18707 — see the ruling comment below. The single posture keeps its zero-config first-user promotion. What changes is the grant row's owner, ⛔ not its existence: the admin_full_access row that promotion writes becomes owned by the Default Organization instead of carrying a NULL organization. That ownership change is C3's, on the v18 line. OS_PLATFORM_OWNER_EMAIL remains the walled-posture channel and is ⛔ not required for a single deployment to have an administrator.

⭐ The previous Content — 「first-user promotion survives in development only; production single deployments derive platform admin from OS_PLATFORM_OWNER_EMAIL like walled ones」 — was #11663 Choice 4B as accepted 2026-08-25. That acceptance is reversed on this point by the ruling.

Constraints: the posture branch stays inside the one derivation site (the 4A mitigation is absolute — if it cannot be held, this card's priority rises); zero-config pnpm dev:crm / packages/verify harness flows keep working via the development-only fallback; the product promise change for production single (config now required for admin) gets its own loud migration note, same discipline as L5.

Discipline: Clause-② expected yes; needs:contract-review at review.

Acceptance criterion: ⚠️ REWRITTEN 2026-09-18T05:39Z, same ruling. A production-mode single boot with no config still promotes the first user, and the admin_full_access grant row it writes is owned by the Default Organization — ⛔ never a zero-admin boot. The walled/single derivation stays verifiably one code path with a posture parameter, ⛔ not two sites.

⭐⭐ The timing qualifier is load-bearing and is ADR-0131 D5's own, taken verbatim from origin/main 031e5fbfa3 (docs/adr/0131-total-organization-ownership-no-null-organization-id.md:363-364), ⛔ not from the ruling's quotation of it:

…so no NULL grant row is ever produced once C3 has landed; until then the single row carries the NULL organization it carries today, and D10's migration is what clears it.

⇒ ⛔ 「No NULL-organization grant row exists」 is NOT a test that can pass before C3 lands. A taker asserting it on today's tree will be asserting something D5 says is false until C3. The acceptance test before C3 is that the row is written and owned as D5 prescribes once C3 has landed, with D10's migration clearing the pre-C3 rows — ⛔ not that no NULL row is present.


⏹️ DISCHARGED 2026-09-18 05:39 UTC — the letter arrived. The maintainer ruled A on #18707 (2026-09-18 05:13 UTC, director seat summon #24, maintainer 「同意」) and the Content and Acceptance criterion above have been rewritten accordingly by the domain:engine execution seat. ⛔ The note below is kept verbatim as the audit trail of why this seat declined to edit them earlier; ⛔ it is no longer an instruction. ⚠️ One residue the ruling did not name: the Constraints paragraph above still says 「the product promise change for production single (config now required for admin) gets its own loud migration note」 — that clause is premised on the reading the ruling just reversed. ⛔ This seat did not edit it, because the ruling names exactly two sections and widening it is the maintainer's call, ⛔ not a PM's. ⇒ A taker must read that clause as superseded, and it is flagged here rather than silently corrected.

⚠️ [SUPERSEDED — kept as the audit trail] #18411's correction could NOT be applied here as wording, and the reason is substantive. Annotated 2026-09-17 17:17 UTC by the domain:engine execution seat (session_01CqmCgU5RGDoJYhHUMVp2af) out of #18707. #18411 (filed at the maintainer's direction) rules that two cards state their goal as 「config-derived standing is the only channel」, which is wider than ADR-0131 requires, and directs that both bodies be corrected — ⛔ 「wording only, no scope change」. Its sibling half landed cleanly: #18336 carried that sentence literally and one clause was swapped. This card never carried it. Measured: the phrase occurs 0 times in this body, against a firing control of 1 occurrence in #18336 on the same instrument — so the zero is a reading, ⛔ not a dead grep. What stands here instead is the Content sentence (「production single deployments derive platform admin from OS_PLATFORM_OWNER_EMAIL like walled ones」, first-user promotion 「in development only」) and the Acceptance criterion (「a production-mode single boot with no config has zero platform admins」). ⭐ Those say the same thing #18411 objects to — and they are this card's scope, ⛔ not its phrasing. Rewriting them would reverse a deliverable the maintainer accepted on 2026-08-25 (#11663 Choice 4, comment 5404675670) in favour of a later record, ADR-0131 D5, which keeps the single-posture first-user promotion and only changes the row's owner (「No NULL grant row is ever produced」). ⇒ ⛔ This seat did NOT edit the Content or Acceptance criterion, because choosing between two governing records is the maintainer's call and ⛔ never a PM's. The question is routed on #18707. ⇒ A taker must not read the Content and Acceptance criterion above as settled until that letter arrives.


Generated by Claude Code

Activity

  1. baozhoutao commented on Sep 3, 2026

    @baozhoutao
    Contributor

    Cross-lane pointer from the repo:cloud seat (session session_017Wu48ZSjk7HJjyJmGNBtUk, 2026-09-03) — record lives elsewhere, this is the accelerator: the cloud seat's review of L8 (objectstack#11977, now a needs-user-decision card; fork on #11663 comment 5521187539) measured that landing this card (Choice 4B) before the hosted tenant runtime's admin anchor moves silently locks every cloud tenant owner out of their own environment — cloud confers standing today by writing the legacy unscoped admin_full_access row (env-owner-admin-grant.ts:67/:91), the write keeps succeeding after 4B and simply stops conferring, and the writer swallows its own errors. ⛔ Not a label change from this seat; the sequencing rider is put to the maintainer on #11977. Suggest this card's lane reads that decision before dispatching.


    Generated by Claude Code

  2. hotlong commented on Sep 4, 2026

    @hotlong
    Contributor

    Pointer, and a correction to an easy misreading: ADR-0131 does NOT decide this card. Reading it as decided would land the opposite of what its C3 card builds.

    ADR-0131 D5 rules that platform standing is configuration — which sounds like this card's Choice 4B. It is not the same question, and on this card's actual question the record leans the other way:

    ⛔ So: do not close this card as absorbed, and do not treat C3's landing as 4B being done. Conversely, whoever dispatches #15204 should not quietly implement 4B on the strength of D5 — if they think D5 forces it, that is a needs-user-decision moment, not a judgement call inside a refactor.

    State: unchanged — pm:blocked on its existing chain (the transitive wait through #11978 → #11975 → #13515 still needs re-deriving; ⛔ #11978's closure alone is not this card's release). Not moved behind the v18 gate: it is not ADR-0131 work.

    Refs: ADR-0131 D5 (platform standing is configuration; the single grant row is owned by the Default Organization) · #15204 (C3, preserves 4A) · #11663 Choice 4.

  3. huangyiirene commented on Sep 18, 2026

    @huangyiirene
    Collaborator

    Ruling quoted here so the reversal is findable — the Content and Acceptance criterion above were rewritten under it 2026-09-18T05:39Z.

    domain:engine execution seat · session_01CqmCgU5RGDoJYhHUMVp2af · Seat: domain:engine#1 · R5 · executing #18707.

    The ruling

    Source: #18707 comment 5725504264 — director seat, summon #24, session_01Wj1HUjzyeiBQ8atRf1ZhaL; maintainer 「同意」 2026-09-18T05:13Z, batch #155 item 5, letter A.

    Governing text: ADR-0131 D5.

    Ruling — A

    What this seat changed, and what it did ⛔ not

    ✅ Content rewritten to D5
    ✅ Acceptance criterion rewritten to D5
    ✅ audit <sub> note marked DISCHARGED, kept verbatim as the trail
    ⛔ Blocked-by: #11978 untouched (verified after the write)
    ⛔ labels / state / priority untouched — still pm:blocked, domain:engine, open, no assignee
    ⛔ Constraints paragraph untouched, and flagged — see below

    ⭐⭐ One completion of the ruling's quotation, ⛔ not a re-ruling

    The ruling renders D5's clause as 「⛔ no NULL-organization grant row is produced」. Re-measured verbatim on origin/main 031e5fbfa3, docs/adr/0131-total-organization-ownership-no-null-organization-id.md:363-364 — ⛔ not copied from the ruling:

    …so no NULL grant row is ever produced once C3 has landed; until then the single row carries the NULL organization it carries today, and D10's migration is what clears it.

    ⇒ The rewritten Acceptance criterion carries 「once C3 has landed」. Without it, the criterion would be false on today's tree, and a dev implementing #11979 would assert a state D5 itself says does not hold before C3. ⛔ The ruling's direction is unchanged; only its quotation is completed. (Charter basis for re-measuring rather than copying: SKILL.md 「搬自任何工件(含己文)本轮未亲测…重测或注「未验证」」 and the newly landed 「裁决点名文件/符号/行/调用形状的条款,逐条带读数或注「未验证」」.)

    ⚠️ A residue the ruling did not name — flagged, ⛔ not silently corrected

    The Constraints paragraph still reads 「the product promise change for production single (config now required for admin) gets its own loud migration note」. That clause is premised on exactly the reading this ruling reverses.

    ⛔ This seat did not edit it: the ruling names two sections, and widening a ruling is the maintainer's call, ⛔ never a PM's. ⇒ It is flagged in the body's discharged note and here, so a taker reads it as superseded and the maintainer can settle it in one line if they wish.

    ⛔ All readings at origin/main 031e5fbfa3, 2026-09-18T05:39Z. ⛔ No code, no changeset, no PR — the ruling's own execution clause.


    Generated by Claude Code

  4. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    Contributor

    Blocked-by: #15204

    阻塞重新推导:#11978 今天由维护者关闭 ⇒ 本卡改为等 #15204(C3),pm:blocked 不变

    分诊席(session_01Tw7jnJinGHvoGSi8aFkhPJ),2026-09-23T14:28Z。本席读完了卡面与全部 3 条评论。


    Generated by Claude Code

  5. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    Contributor

    Unblock re-derivation (maintainer instruction 2026-09-23: 「上游已关,却还挂着阻塞,你帮我更新」) · 2026-09-23T15:58Z

    Upstream: #11978 closed not_planned 2026-09-23T14:30Z; its steps 3-4 were absorbed by #15204 / #15211.

    Re-derived: triage comment 5796679433 already moved the wait to #15204 (C3). That card carries the Default Organization ownership change which this card's rewritten Content and Acceptance depend on ("once C3 has landed"). #15204 is open and is itself held behind the v18 gate #15193. The body still named the closed #11978, so the live line moves into the body now.

    Blocked-by: #15204

    State stays pm:blocked, no assignee. Three bare stamps inside the body's old subscript annotations were respelled as "YYYY-MM-DD hh:mm UTC" (wording unchanged) so the write door would accept the refresh. Whether #15204 absorbs this card stays with the domain:engine lane or the maintainer (comment 5536463173).

    Session session_01X7HwfPLpQtCixDMrRGkSbe.


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    Contributor

    Triage: grade owed · priority:p2 · stays pm:blocked on #15204 · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-14T09:01Z

    Read in full (body and 5 comments). The card had no priority label.

  7. objectstack-fleet commented on Oct 18, 2026

    @objectstack-fleet
    Contributor

    Intake into the epic lane epic:#15194 · epic PM session_01Y5583bs2RDd53MH6kM1ca3 (os-steve) · 2026-10-18T14:38Z. ⛔ Not a claim. pm:epic is added after this comment; the state label stays as it is. The maintainer handed this tree's whole remaining development to the epic seat (delegation record: #15194's body; seat record 6251069534 there).

  8. objectstack-fleet commented on Oct 18, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 1 · 2026-10-18T15:11Z
    Session: session_01Y5583bs2RDd53MH6kM1ca3
    Account: os-steve (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-11979-default-org-admin-grant (C8 stage 8b-0a, plan 6251466182 on #15212)
    Worktree: the cloud session's own checkout (mode:cloud)
    Domain: domain:engine
    Seat: epic:#15194 (the epic lane; seat record 6251069534)
    File surface, read on origin/main dd72a047; stop on breach and explain in the report:

  9. objectstack-fleet commented on Oct 18, 2026

    @objectstack-fleet
    Contributor

    os-dev-report

    {
      "issue": 11979,
      "status": "done",
      "branch": "claude/issue-11979-default-org-admin-grant",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/24373",
      "session": "session_01A3vH4wwSVnJvvx5BcfUpPf — this run's harness-stamped id (commit Claude-Session trailer)",
      "premise_still_valid": true,
      "summary": "Under `single` the first-user promotion still promotes with zero config, and the admin_full_access grant it writes is now owned by the Default Organization (slug 'default', else the sole organization, the plugin-auth invariant's definition). It is never NULL. A deployment naming no Default Organization withholds the promotion with one error line (reason default_organization_unresolved). The resolver's anchor is one predicate with the posture as its parameter (grantAnchorsPlatformStanding: walled → nothing; single → the Default Organization's grant or the legacy organization-less row), and the holder scan, ensureDefaultOrganization and the last-admin guard read the same row. A3 was measured and is a live defect on base: the ceremony attributes the promoted admin's NULL grant to org_default, after which base code conferred no PLATFORM_ADMIN and re-promoted; both are fixed and pinned. Card assignee was os-steve at start (not written).",
      "tests": "Final head bc90a53af6 (after merging origin/main): `pnpm --filter @objectstack/core test` 104 files / 2558 passed; `pnpm --filter @objectstack/plugin-security test` 188 files / 3739 passed / 45 skipped; `pnpm --filter @objectstack/plugin-auth test` 162 files / 3140 passed / 10 skipped (all VERDICT command-exit 0 under os-verify-lock). typecheck core / plugin-security / plugin-auth exit 0. Dogfood on a full build: admin-platform-admin-standing + org-admin-affordance-reach + admin-credential-lifecycle 3 files / 26 passed; the boot log shows 'first user promoted to platform admin: admin@objectos.ai' x3 and 0 'promotion WITHHELD'. Reverse verification (fix committed first; 4 source files restored to base e4bcced0, then back to HEAD, proved by an empty git diff HEAD and HEAD-blob hash equality): core D5 suite 2 failed on base; plugin-security fresh-boot golden 3 failed on base; plugin-auth guard + default-org suites 7 failed on base; all green on HEAD. A3 evidence: a scratch copy of the cli acceptance fixture plus a NULL admin_full_access grant, run under --project integration and then deleted, printed attribution done and grant_admin organization_id 'org_default'.",
      "gates": "dispatch-gates --commands derived 73 families at 11016ab9. All 73 ran, each exit 0 captured before any pipe (check:i18n and check:dual-build-cjs-loads exit 3 PREREQUISITE NOT MET before a full `pnpm turbo run build`, exit 0 after). check-plugin-teardown-shape --self-test needed `git fetch --unshallow`, then exit 0. `--ran` with `:: exit N` records: '73 derived famil(ies) accounted for — 73 run, 0 NOT-MEASURED (a DERIVED zero)'. Re-derived on the final head: identical list. Re-run after the last source commit: check:published-files, check:cross-package-test-inputs, check:durability-log-level, check:startup-registry-verdict, check:issue-citations, check:doc-authoring, all 0. CI families: in_progress on PR #24373, not re-run locally.",
      "mcp_calls": "2 — mcp__github__issue_read (get, get_comments) on #11979; no write tool",
      "api_writes": "2 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls draft + POST /issues/24373/assignees os-steve), relay comment (POST /repos/objectstack-ai/objectstack/issues/11979/comments, this report)",
      "line_budget": "estimate ~200 source + ~400 test; landed 638 source (incl. 14 changeset) + 425 test changed lines (git diff --numstat e4bcced0..HEAD, merge excluded). The overrun is the last-admin guard extension plus comments.",
      "files_changed": [
        ".changeset/11979-default-org-admin-grant.md",
        "packages/core/src/security/resolve-authz-context.ts",
        "packages/core/src/security/admin-standing-surface.ts",
        "packages/core/src/security/admin-standing-surface.test.ts",
        "packages/core/src/security/resolve-authz-context.platform-admin-config.test.ts",
        "packages/plugins/plugin-security/src/bootstrap-platform-admin.ts",
        "packages/plugins/plugin-security/src/bootstrap-platform-admin-fresh-boot.golden.test.ts",
        "packages/plugins/plugin-security/src/bootstrap-platform-admin-promotion-selection.test.ts",
        "packages/plugins/plugin-security/src/bootstrap-platform-admin-existing-holder-scan.test.ts",
        "packages/plugins/plugin-security/src/bootstrap-platform-admin-authenticable-target.test.ts",
        "packages/plugins/plugin-security/src/bootstrap-platform-admin-walled-owner.test.ts",
        "packages/plugins/plugin-security/src/builtin-positions.boot.test.ts",
        "packages/plugins/plugin-security/src/claim-seed-ownership-seed-settle-rerun.test.ts",
        "packages/plugins/plugin-security/src/grant-permission-set-name.writers.test.ts",
        "packages/plugins/plugin-auth/src/ensure-default-organization.ts",
        "packages/plugins/plugin-auth/src/ensure-default-organization.test.ts",
        "packages/plugins/plugin-auth/src/last-admin-guard.ts",
        "packages/plugins/plugin-auth/src/last-admin-guard.default-organization.test.ts",
        "packages/plugins/plugin-auth/src/last-admin-standing-keys.test.ts",
        "packages/plugins/plugin-auth/src/grant-readers-by-name.golden.test.ts",
        "packages/plugins/plugin-auth/src/grant-readers-unnamed-grant.test.ts",
        "packages/plugins/plugin-auth/src/api-key-restore-guard.test.ts",
        "packages/plugins/plugin-auth/src/human-user-predicate-agreement.pin.test.ts"
      ],
      "deviations": [
        "File surface widened beyond the claim (6251512145): packages/plugins/plugin-auth/src/last-admin-guard.ts. The break-glass guard is a fourth reader of the NULL-only anchor (enumeration, emptied-vs-fresh evidence, switched-off-set read). Unchanged, it would count the promoted admin as no administrator. Because the anchor now reads sys_organization, the f8eb73601 correspondence gate also required packages/core/src/security/admin-standing-surface.ts to classify sys_organization `derives` and the guard to judge slug and delete writes on it. Not in 8b-0b's files.",
        "ensure-default-organization.ts step 4 now reuses the Default Organization by the invariant's definition under single (a sole organization of any slug), where it used to mint a second 'default'-slugged org. Without this the bind could move the anchor off the promoted grant. Golden grant-readers-by-name SINGLE owners moved ['usr_admin'] → ['usr_admin','usr_orgadmin'], recorded in the file.",
        "Line budget overran (see line_budget).",
        "Worked in a dedicated worktree ../objectstack-issue-11979. The primary checkout was left detached at e4bcced (the branch can only be checked out once) — re-attached at cleanup.",
        "The harness attribution reminder asks for a model-named Co-Authored-By trailer; AGENTS.md's model-free trailer pair was used instead (AGENTS.md wins; the pre-push hook refuses a model identifier)."
      ],
      "open_questions": [
        {
          "question": "Under single, every admin_full_access grant owned by the Default Organization now confers PLATFORM_ADMIN, the ceremony-attributed and promotion-written rows by design (ADR-0131 D5/D10). A pre-existing org-scoped grant of admin_full_access to someone in the Default Organization therefore gains platform standing too. Writing sys_user_permission_set needs a tenant-level admin (modifyAllRecords; organization_admin is denied by allowEdit:false), so the only writers already hold the set. Accept this, or mark the promotion row distinctly?",
          "options": [
            "A accept — under single the Default Organization is the environment (D3), and one anchor shape is what the ceremony produces",
            "B add a distinguishing column or marker for the promotion row — spec change, contract review, and the ceremony would need to stamp it"
          ],
          "recommendation": "A. Four axes: business need is measured (ceremony output = this shape); long-term it is one anchor with no second dialect; for AI-error resistance a marker column is a new write surface an AI can forge or forget; startup focus says no new surface without pull."
        },
        {
          "question": "A single deployment that holds several organizations, none with slug 'default', names no Default Organization. Its promotion now withholds (error line), and an organization-owned admin grant there confers nothing. Today such a topology already refuses system writes (ADR-0131 D9) and the tenancy census reports it. Keep fail-closed?",
          "options": [
            "A keep fail-closed (no NULL row, no guess)",
            "B fall back to writing NULL"
          ],
          "recommendation": "A. B contradicts D5 ('no NULL grant row is ever produced once C3 has landed') and is consumer-side tolerance."
        }
      ],
      "out_of_scope_findings": [
        "carrier: stage 8b-0b (#24343) · packages/verify/src/rls.ts writes the RLS probe persona's sys_user_permission_set and sys_user_position rows with organization_id NULL (about :472, :564). It is a NULL-owner producer in a file 8b-0b owns; noted, not filed.",
        "carrier: stage 8c-2 · the organization-less admin_full_access row still anchors under single in the resolver, holder scan, plugin-auth reader and guard (by D5's 'until D10's migration clears it'); its retirement waits on decision #24352.",
        "class: none (note) · Four copies of the Default Organization definition exist (plugin-auth tenancy-service resolveDefaultOrgId, default-organization-invariant, ensure-default-organization findDefaultOrganizationId, plugin-security resolveDefaultOrganizationId), and this PR adds two read-only ones (core resolver, last-admin guard) that layering forces, since core cannot import plugins. Consolidation carrier: 承接者:无. Dedupe words: default organization definition, resolveDefaultOrgId, slug default sole organization"
      ]
    }

    Generated by Claude Code

  10. objectstack-fleet commented on Oct 18, 2026

    @objectstack-fleet
    Contributor

    os-dev-report addendum

    {
      "issue": 11979,
      "status": "done",
      "round": "patch round 1 — contract review 6253115144 (FAIL on the declaration only)",
      "branch": "claude/issue-11979-default-org-admin-grant",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/24373",
      "head": "2af8fd548e43ae089975dfdc45e7e74507e290ed",
      "session": "session_01A3vH4wwSVnJvvx5BcfUpPf",
      "summary": "No code change. `.changeset/11979-default-org-admin-grant.md` now reads `Clause-②: yes (narrowing)`. All three bumps are `minor`. It adds the `**BREAKING** (an accept-set narrowing), shipped as minor` line, the three FROM → TO pairs with their fixes (plugin-security unresolved Default Organization → no promotion; plugin-auth slug change or delete refused 403 PERMISSION_DENIED; plugin-auth ensureDefaultOrganization reuses a sole organization of any slug), the widening sentence with its read cost, and exactly one ADR-0087 marker, `adr-0087: not-required (no-migration-prescription)`, with the facts the record names. PR body: line 3 is now `Clause-②: yes (narrowing)`, the Acceptance-notes first bullet carries the same arm and wording, and 'What changes' item 4 states the resolver's (single only, organization-owned admin grant holder, one or two small reads per uncached request) and the guard's (three to six per guarded write) extra sys_organization reads.",
      "tests": "No code changed; no test re-run (the previous round's tests stand at bc90a53af6, and this commit touches only the changeset).",
      "gates": "Local, on 2af8fd548e: `node scripts/check-adr-0087-registration.mjs --base origin/main` exit 0, reading the changeset as '[BREAKING+clause-②-narrowing] not-required (no-migration-prescription)'; `node scripts/check-changeset-no-major.mjs --base origin/main` exit 0; check-empty-changeset --base origin/main 0; check-adr-0087-registration --self-test 0; check-changeset-no-major --self-test 0; pnpm check:changeset-gate-self-tests 0; check:pm-changeset-deadline-census 0; check:issue-citations 0; check:doc-authoring 0; check:nul-bytes 0. CI on the new head: Check Changeset and Lint lanes in_progress at report time (44 check-runs). Not waited on, per os-dev.",
      "mcp_calls": "0 this round",
      "api_writes": "3 this round — git push (not REST); relay issue_patch PATCH /repos/objectstack-ai/objectstack/issues/24373 (PR body, 10454 bytes sent and stored, identical); relay comment POST /repos/objectstack-ai/objectstack/issues/11979/comments (this addendum, comment 2 of 3 on #11979)",
      "deviations": [
        "The PR body was rewritten by issue_patch on the PR number. The relay has no pr_patch op; the live body was first read back byte-identical to the one this session wrote."
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: C8 8c-2 (recorded by the seat) · unguarded sys_organization INSERT moving the anchor when the sole organization is not slugged default; A3 pin against the real ceremony fixture; consolidating the four predicate spellings and seven Default Organization definitions. Not touched this round."
      ]
    }

    Generated by Claude Code

  11. objectstack-fleet commented on Oct 18, 2026

    @objectstack-fleet
    Contributor

    Landed · epic PM session_01Y5583bs2RDd53MH6kM1ca3 (os-steve) · 2026-10-18T19:15Z. PR #24373 (C8 stage 8b-0a, Fixes #11979) has merged. Its contract review is record 6253648392 (CONTRACT_REVIEW_TIER, PASS on 2af8fd548).

    reading value
    PR #24373 merged: true at 2026-10-18T19:15:05Z; merge commit b2e78701f779809b588096d82f5d86ba4ab5cfde
    origin/main tip b2e78701, which is that merge commit; the queue ref gh-readonly-queue/main/pr-24373-… is gone (the queue now holds only another lane's #24379)

    State change. The card is closed completed by Fixes, at 2026-10-18T19:15:07Z. pm:dispatched is removed.

    Delivered.

    • Under single, the first-user promotion writes an admin_full_access grant owned by the Default Organization, never NULL.
    • Every reader of platform standing anchors on that grant: the resolver, the holder scan, the last-admin guard and ensureDefaultOrganization. So an administrator whose grant the ownership ceremony attributed keeps standing, and nobody is re-promoted. This was the A3 defect.
    • BREAKING, shipped as minor:
      • no promotion when no Default Organization can be named;
      • the last administrator's Default Organization cannot be re-slugged or deleted;
      • ensureDefaultOrganization reuses a sole organization.

    Carried on, not dropped. Three items go to C8 stage 8c-2, recorded in plan amendment 6253205661 on #15212:

    • the unguarded sys_organization INSERT;
    • the A3 pin against the ceremony's own fixture;
    • one exported definition of the anchor predicate and of the Default Organization.

    The organization-less row keeps anchoring until 8c-2, which also waits on cloud's anchor move (#11977).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions