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
Found while fixing #638 (seeding billing addresses so the territory rules match records); filed unassigned per Prime Directive #10, and deliberately not fixed there — it needs demo-user/member design, not seed data.
What happens
#621 made the two territory rules install. #638 gave them accounts to match. The third layer is still empty: no user holds any position, so a matching account still materialises no share.
Measured on a fresh install (pnpm dev, empty .objectstack/data, 17.0.0-rc.1), reading the SQLite file directly:
sys_position 18 rows (all 12 declared positions exist, incl. na_sales_team / eu_sales_team)
sys_sharing_rule 9 rows (all declared rules seeded — seeded: 9, skipped: 0)
crm_account 9 rows (6 match north_america_territory, 2 match europe_territory, 1 neither)
sys_user_position 0 rows ← nobody holds anything
sys_member 1 row (the dev admin, role "owner")
sys_record_share 0 rows ← so nothing is granted to anyone
So the chain is: rules installed ✅ → criteria match real records ✅ → recipients staffed ❌ → grants 0.
Why it matters
This is the last layer of the same declared-vs-delivered gap as #621 / #638, and it is wider than territories:
Seven other positions are equally unstaffed (sales_manager, sales_director, executive, service_manager, service_director, marketing_manager, marketing_director), so every position-based sharing rule this app ships grants nobody anything on a fresh install.
pnpm lint already warns about the same hole on the approval side, at four nodes:
approval-approvers-may-resolve-empty — flow "opportunity_approval" · node "manager_review": every approver on this node routes to a group (position/team/department) whose members are runtime data — if none is staffed, the request resolves to an empty slate and waits forever, and (lockRecord) the record stays locked with no in-product recovery.
So an evaluator who submits a deal for approval on a fresh demo locks the record with nobody able to act on it.
Why it is not a one-liner in demo_bootstrap
The obvious patch — have the bootstrap sweep put the first user into na_sales_team and eu_sales_team — is a fix in appearance only:
On a fresh install there is exactly one user, and demo_bootstrap has already claimed every seeded record for them (owner + platform owner_id, Seeded contracts are ownerless at the platform level (owner_id null) — nobody, admin included, can edit one #622). A share to that same user widens nothing: the OWD baseline already admits the record's owner, and an admin bypasses sharing anyway. sys_record_share would gain rows nobody can observe the effect of.
Demonstrating territory sharing requires a user who does not own the accounts — i.e. at least one non-admin NA rep and one non-admin EU rep, which means creating demo users, deciding who holds which of the twelve positions, and reckoning with the fact that the same decision drives the other seven positions, the four approval nodes and lead_assignment's sales_rep pool (lead.hook.ts already documents its empty-pool fallback).
That is a design decision about the demo org's people, not a seed record, which is why #638 stops at the data.
What is needed
Roughly, and for a maintainer to confirm before anyone builds it:
Whether the demo org should ship synthetic users at all (e.g. na.rep@objectos.ai, eu.rep@objectos.ai, a sales manager, a service agent), given that seeds cannot name a user — creation would have to happen in demo_bootstrap or an equivalent first-boot path, the same constraint that forced that flow to exist (see the note at the foot of src/data/index.ts).
Which positions each demo user holds, so the sharing rules and the approval routes both become demonstrable.
Whether staffing should be dev/demo-only (a real deployment staffs its own people, and shipping fake users into a customer org would be worse than shipping none).
Related: #621 (the rules), #638 (the data they match), #488 (a position no rule and no permission set names grants nothing), #622 (demo_bootstrap and the two ownership columns).
Found while fixing #638 (seeding billing addresses so the territory rules match records); filed unassigned per Prime Directive #10, and deliberately not fixed there — it needs demo-user/member design, not seed data.
What happens
#621 made the two territory rules install. #638 gave them accounts to match. The third layer is still empty: no user holds any position, so a matching account still materialises no share.
Measured on a fresh install (
pnpm dev, empty.objectstack/data, 17.0.0-rc.1), reading the SQLite file directly:So the chain is: rules installed ✅ → criteria match real records ✅ → recipients staffed ❌ → grants 0.
Why it matters
This is the last layer of the same declared-vs-delivered gap as #621 / #638, and it is wider than territories:
Seven other positions are equally unstaffed (
sales_manager,sales_director,executive,service_manager,service_director,marketing_manager,marketing_director), so every position-based sharing rule this app ships grants nobody anything on a fresh install.pnpm lintalready warns about the same hole on the approval side, at four nodes:So an evaluator who submits a deal for approval on a fresh demo locks the record with nobody able to act on it.
Why it is not a one-liner in
demo_bootstrapThe obvious patch — have the bootstrap sweep put the first user into
na_sales_teamandeu_sales_team— is a fix in appearance only:demo_bootstraphas already claimed every seeded record for them (owner+ platformowner_id, Seeded contracts are ownerless at the platform level (owner_idnull) — nobody, admin included, can edit one #622). A share to that same user widens nothing: the OWD baseline already admits the record's owner, and an admin bypasses sharing anyway.sys_record_sharewould gain rows nobody can observe the effect of.lead_assignment'ssales_reppool (lead.hook.tsalready documents its empty-pool fallback).That is a design decision about the demo org's people, not a seed record, which is why #638 stops at the data.
What is needed
Roughly, and for a maintainer to confirm before anyone builds it:
na.rep@objectos.ai,eu.rep@objectos.ai, a sales manager, a service agent), given that seeds cannot name a user — creation would have to happen indemo_bootstrapor an equivalent first-boot path, the same constraint that forced that flow to exist (see the note at the foot ofsrc/data/index.ts).Related: #621 (the rules), #638 (the data they match), #488 (a position no rule and no permission set names grants nothing), #622 (
demo_bootstrapand the two ownership columns).