Repository navigation
fix(cli): os migrate organization-ownership plans a v17 database still holding the retired sys_scim_provider, as fate 4 (ADR-0131 D10) - #23874
Conversation
…-ownership plan stops refusing v17 databases sys_scim_provider was retired before the first ADR-0131 D10 census, so neither census counted it and the inventory carried no row. Its ADR-0087 entry (scim-provider-object-retired) leaves the table in place untouched, by ruling, so every database that booted an earlier release still holds it with organization_id, and the plan threw uninventoried-platform-table. Add a fate-4 (report) row under a new census population, retired-before-census, citing the ADR-0087 entry, with notNullExempt: the object is retired, no declaration anchors tenancy on the column, and a connection scoped to no organization was a legitimate row. Pins: the inventory test freezes the population, checks it is uncounted and unregistered, that the cited ADR-0087 entry exists and still leaves the table untouched, and that the citation carries no tracker number. The plan integration test plans a v17-shaped sys_scim_provider under both postures as report, with the inventory-less control refusing it by name. Claude-Session: https://claude.ai/code/session_local_f4c0ec33-a0e1-425c-a1fd-59bcb3256ad8 Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): ⛔ 1 release-owned page(s) name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 29 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 1973be44c8fe35a72f9593a64c8ab6cc3c9cef5e && git checkout 1973be44c8fe35a72f9593a64c8ab6cc3c9cef5e
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 98ba1bf1d28d44bddd18b3dcff5db2502e8ad6a9 6137d10b22aa5cd68f99d7d8d33af59edc8445dc && git checkout -B drift-repro 98ba1bf1d28d44bddd18b3dcff5db2502e8ad6a9 && git merge --no-ff 6137d10b22aa5cd68f99d7d8d33af59edc8445dc
node scripts/docs-audit/affected-docs.mjs --json 98ba1bf1d28d44bddd18b3dcff5db2502e8ad6a9
|
main brought the legacy shipped-set seeds category into the same inventory file; the only conflict was the test file's import block, resolved by keeping both imports (MIGRATIONS_BY_MAJOR and securityDefaultPermissionSets). Claude-Session: https://claude.ai/code/session_local_f4c0ec33-a0e1-425c-a1fd-59bcb3256ad8 Co-authored-by: Claude <noreply@anthropic.com>
Clause-②: no
What was wrong
os migrate organization-ownershiprefuses a v17 database that still holds the retiredsys_scim_providertable:sys_scim_providerwas retired from the tree on 2026-08-28. The ADR-0087 entry ispackages/spec/src/migrations/entries/semantic/18.scim-provider-object-retired.ts. The first census was measured on 2026-08-31, so neither census counted the object, and the inventory got no row for it.organization_idincluded.uninventoried-platform-tablefor any platform-prefixed table that carries the column and has no row (organization-ownership-plan.ts, the loop inbuildOrganizationOwnershipPlan).--applybuilds the same plan, so the ceremony cannot run on such a database at all.os dev/os servethen stay refused, because the boot guard waits for the ceremony's marker.dev.db, a long-lived SQLite dev database first created on 17.x, on@objectstack/*18.0.0-next.2. The plan refused it. A one-row host fate supplement forsys_scim_providerwas the workaround there.What changed
A new census population,
retired-before-census. It holds platform objects retired from the tree before the first census, whose tables an upgraded database still holds. It is documented in the inventory's header with the other populations.A fate-4 row for
sys_scim_provider. It follows the precedent ofsys_view_definition,sys_saved_reportandsys_report_schedule(fatereport: rows listed, never attributed, never deleted). Its citation names the ADR-0087 entry and carries no tracker number.notNullExempton the row. The precedent rows do not carry one; this row does, for three reasons:organization_idasrequired: false, because better-auth's SCIM plugin scopes a connection to an organization only optionally. A connection with no organization was a legitimate row.Without the exemption, the plan would report that the table "will receive NOT NULL" once no NULL row remains, which is a promise about a table the ruling says nothing touches.
Pins
organization-ownership-inventory.test.ts. A new frozen list,RETIRED_BEFORE_CENSUS(sys_scim_provider→scim-provider-object-retired). For each entry, the test asserts:PLATFORM_OBJECTS_BY_PACKAGE;MIGRATIONS_BY_MAJOR, and its acceptance criteria still say the table is "left in place untouched", which is what licenses fate 4;retired-before-census, fatereport, a citation containing the entry id and no tracker number, and anotNullExempt;organization-ownership-plan.integration.test.ts. A v17-shapedsys_scim_provider(its last declared columns:id, provider_id, provider_key, scim_token, organization_id, user_id, created_at, updated_at), with one stamped row and one NULL row.isolatedandsingle, it plans assource: inventory, fatereport.singleit is not given to the Default Organization.notNull.willReceive: false, with the exemption's reason.uninventoried-platform-tablenamingsys_scim_provider.Verification
On
b0aca327bf(baseorigin/mainf7e836da1e):pnpm --filter @objectstack/cli typecheck: exit 0.vitest run src/utils/organization-ownership-inventory.test.ts src/utils/organization-ownership-plan.integration.test.ts):Test Files 2 passed,Tests 37 passed.pnpm --filter @objectstack/cli test(both projects):Test Files 13 failed | 430 passed | 1 skipped (444),Tests 11 failed | 5694 passed | 51 skipped. None of the 13 is an ownership-ceremony file. Five of them refused to load with "packages/cli is not built", because the run had built only the CLI's dependencies.pnpm exec turbo run build --filter=@objectstack/cli, the 13 re-run as7 failed | 6 passed,14 failedtests.f7e836da1e, the CLI was rebuilt, and those 7 re-run. The failing set is identical, test by test:7 failed (7),14 failed. The tree was then restored to HEAD and the CLI rebuilt.tmpdir()resolving to/private/var/…against an expected/var/…, and no util-linuxscript(1)foros devon a real terminal. The 7 are the twopublished-subpath-*pins,dev-boot-output-order,published-entry-node-env-source-reroute,serve-runtime-state-project-key,verify-dashboard-windowsandplan.reads-env-files. CI runs all of them.--no-inline-config: exit 0.node scripts/check-doc-authoring.mjs: clean.node scripts/check-cross-package-test-inputs.mjs: OK.origin/mainhas moved two commits past the base (6422da58e8,7a6ba03109). Neither touchespackages/cliorpackages/spec/src/migrations.Acceptance notes
inventoryDigestchanges. A plan file written by an earlier CLI no longer matches, and--apply --plan-filerefuses it withplan-digest-mismatch, as for any inventory change. The changeset says to re-plan.--apply;managed_by='admin';column-drops, and the ceremony never reads the sibling.Generated by Claude Code