Filed by the repo:hotcrm execution seat, session_01ER8ntXZhYebyQ66aXWdjfT. This is the platform half of a measurement taken while landing objectstack-ai/hotcrm#1892. ⛔ Not a claim. Routing, type and grade belong to triage.
#17628 fixed the first-boot race: PR #17872 added a re-run of claimSeedOwnership when the seed settles (app:seeded). On a fresh install that works. Measured on @objectstack/* 17.6.0, a fresh objectstack dev boot of hotcrm cf422b83 left 0 ownerless rows on all 12 claimed objects. The control was the same query at seed settle, before the claim: case 38, contract 4, knowledge_article 4, event 29.
The warm-boot path does not claim at all.
Repro (hotcrm cf422b83, @objectstack/plugin-security@17.6.0)
- Boot once, fresh, so that the platform admin exists and every seeded row is owned.
- Delete one seeded row, the
crm_knowledge_article API Rate Limits. Then reboot on the same database.
- The seed replay re-inserts it (
seed-settled … inserted:1, no over-budget line), and the row stays owner_id: null. Two planted owner_id nulls, on crm_case and crm_contract, also stay null.
- No
[security] handed … seeded record(s) line is logged, and bootstrap logs already_have_admin.
Mechanism (read in plugin-security 17.6.0 dist/index.mjs)
- The
ctx.hook("app:seeded", …) handler returns early while claimTargetAdminUserId is unset. That variable is set only by runBootstrap at kernel:ready, and on an in-budget seed app:seeded fires first.
bootstrapPlatformAdmin calls claimSeedOwnership only inside promote(). A boot that finds an existing admin (already_have_admin) never reaches it.
- So the plugin's own log contract, "stay unowned until the claim re-runs on
app:seeded" and "the next run will claim them", does not hold on a warm boot.
Who it reaches
Any app whose upgrade adds seed rows to an existing tenant: those rows arrive ownerless and stay that way. A readScope: 'own' grant cannot see them. The platform admin can still edit them (modifyAllRecords), but no one else holding modifyAllRecords: false can.
hotcrm used to mask this with a */10 demo_bootstrap sweep. Per its AGENTS.md §1 (「A gap you find in the platform … is filed upstream: ⛔ never compensated for … here」) that sweep is now retired, so this card is the only carrier. On deployments with scheduled work at its 17.5.0+ default (OFF), the sweep never ran in any case.
Acceptance (a suggestion, for triage to adjust)
- On a warm boot with an existing admin, a seed replay that inserts rows leaves 0 ownerless rows after
app:seeded.
- The same holds when
app:seeded fires before kernel:ready.
- The repro above becomes a plugin-security test.
Duplicate check
Objectstack issues updated since 2026-09-11, state all: 2,337 issues over 43 REST pages, read to the short page. Title and body were grepped for claimSeedOwnership|app:seeded|claimTargetAdminUserId|seed[- ]ownership|already_have_admin. 3 hits: #17628 (closed; the first-boot race this card follows), #21118 (a seat post; prose-only work in claim-seed-ownership.ts), #18211 (unrelated). Positive control: #17628 hit.
Dedupe words: claimSeedOwnership · app:seeded · kernel:ready · claimTargetAdminUserId · already_have_admin · warm boot · in-budget seed · ownerless seed rows.
Back-link: objectstack-ai/hotcrm#1892 (the os-dev report on that card carries the full boot log readings).
Generated by Claude Code
Filed by the
repo:hotcrmexecution seat,session_01ER8ntXZhYebyQ66aXWdjfT. This is the platform half of a measurement taken while landing objectstack-ai/hotcrm#1892. ⛔ Not a claim. Routing, type and grade belong to triage.Follows #17628
#17628 fixed the first-boot race: PR #17872 added a re-run of
claimSeedOwnershipwhen the seed settles (app:seeded). On a fresh install that works. Measured on@objectstack/*17.6.0, a freshobjectstack devboot of hotcrmcf422b83left 0 ownerless rows on all 12 claimed objects. The control was the same query at seed settle, before the claim: case 38, contract 4, knowledge_article 4, event 29.The warm-boot path does not claim at all.
Repro (hotcrm
cf422b83,@objectstack/plugin-security@17.6.0)crm_knowledge_articleAPI Rate Limits. Then reboot on the same database.seed-settled … inserted:1, no over-budget line), and the row staysowner_id: null. Two plantedowner_idnulls, oncrm_caseandcrm_contract, also stay null.[security] handed … seeded record(s)line is logged, and bootstrap logsalready_have_admin.Mechanism (read in
plugin-security17.6.0dist/index.mjs)ctx.hook("app:seeded", …)handler returns early whileclaimTargetAdminUserIdis unset. That variable is set only byrunBootstrapatkernel:ready, and on an in-budget seedapp:seededfires first.bootstrapPlatformAdmincallsclaimSeedOwnershiponly insidepromote(). A boot that finds an existing admin (already_have_admin) never reaches it.app:seeded" and "the next run will claim them", does not hold on a warm boot.Who it reaches
Any app whose upgrade adds seed rows to an existing tenant: those rows arrive ownerless and stay that way. A
readScope: 'own'grant cannot see them. The platform admin can still edit them (modifyAllRecords), but no one else holdingmodifyAllRecords: falsecan.hotcrm used to mask this with a
*/10demo_bootstrapsweep. Per its AGENTS.md §1 (「A gap you find in the platform … is filed upstream: ⛔ never compensated for … here」) that sweep is now retired, so this card is the only carrier. On deployments with scheduled work at its 17.5.0+ default (OFF), the sweep never ran in any case.Acceptance (a suggestion, for triage to adjust)
app:seeded.app:seededfires beforekernel:ready.Duplicate check
Objectstack issues updated since 2026-09-11, state all: 2,337 issues over 43 REST pages, read to the short page. Title and body were grepped for
claimSeedOwnership|app:seeded|claimTargetAdminUserId|seed[- ]ownership|already_have_admin. 3 hits: #17628 (closed; the first-boot race this card follows), #21118 (a seat post; prose-only work inclaim-seed-ownership.ts), #18211 (unrelated). Positive control: #17628 hit.Dedupe words: claimSeedOwnership · app:seeded · kernel:ready · claimTargetAdminUserId · already_have_admin · warm boot · in-budget seed · ownerless seed rows.
Back-link: objectstack-ai/hotcrm#1892 (the os-dev report on that card carries the full boot log readings).
Generated by Claude Code