Found while scoping the D13 promotion tool (commercial side, cloud#874). This is a spec-level gap in what ADR-0105 D13 presumes, and its fix already exists as a Proposed ADR — the decision needed is which side moves.
The gap
ADR-0105 D13 prescribes the promotion tool's third step as: "backfill organization_id on scoped business data from the subtree's scoping field" — which presumes each scoped object declares which field carries BU ownership. No such declaration exists:
ownership on the object schema is 'user' | 'org' | 'none' (packages/spec/src/data/object.zod.ts:818) — no business-unit tier;
- depth scopes (
unit / unit_and_below) compile to owner_id IN (…) sets, not to a BU column (IHierarchyScopeResolver returns owner ids);
owning_business_unit_id appears nowhere in code — only in ADR-0117's text;
- Appendix A of ADR-0105 confirms the current shape is app-level convention only: "business objects carry a plant reference."
The consequence
The D13 tool cannot discover which rows belong to a promoted subtree. It must take an explicit per-object { object: field } map from the operator — fail-closed and safe (auto-guessing "any lookup → sys_business_unit" would conflate reference semantics with ownership semantics and silently move rows behind the wrong wall). But the promise in D13's text is then not machine-checkable: an object the operator forgets to list silently stays behind in the source org, and the tool's dry-run candidate report is advice, not semantics.
The fix already has a name
ADR-0117 (Proposed, 2026-07-31) introduces exactly the missing declaration: ownership: 'business_unit' + the owning_business_unit_id stamp, with D3's invariant record.organization_id == BU(owning_business_unit_id).organization_id — which is precisely the equation D13's backfill establishes. With 0117 landed, promotion gains a checkable postcondition: no row whose owning BU lies in the promoted subtree remains in the source org.
Decision needed (either/or)
- Accelerate ADR-0117 review/landing. The D13 tool then defaults its scoped-object map from
ownership metadata; the explicit map becomes an override. Recommended — it is what makes promotion verifiable rather than merely configurable.
- Amend ADR-0105 D13's text to state the scoping field is deployment-supplied, making the explicit per-object map the contract rather than a workaround.
The D13 tool ships either way with the explicit-map interface (it stays correct as an override under option 1 — no rework).
Refs: ADR-0105 D13 / Appendix A, ADR-0117, cloud#874 (D13 item), cloud#1006 (sibling finding).
Found while scoping the D13 promotion tool (commercial side, cloud#874). This is a spec-level gap in what ADR-0105 D13 presumes, and its fix already exists as a Proposed ADR — the decision needed is which side moves.
The gap
ADR-0105 D13 prescribes the promotion tool's third step as: "backfill
organization_idon scoped business data from the subtree's scoping field" — which presumes each scoped object declares which field carries BU ownership. No such declaration exists:ownershipon the object schema is'user' | 'org' | 'none'(packages/spec/src/data/object.zod.ts:818) — no business-unit tier;unit/unit_and_below) compile toowner_id IN (…)sets, not to a BU column (IHierarchyScopeResolverreturns owner ids);owning_business_unit_idappears nowhere in code — only in ADR-0117's text;The consequence
The D13 tool cannot discover which rows belong to a promoted subtree. It must take an explicit per-object
{ object: field }map from the operator — fail-closed and safe (auto-guessing "any lookup → sys_business_unit" would conflate reference semantics with ownership semantics and silently move rows behind the wrong wall). But the promise in D13's text is then not machine-checkable: an object the operator forgets to list silently stays behind in the source org, and the tool's dry-run candidate report is advice, not semantics.The fix already has a name
ADR-0117 (Proposed, 2026-07-31) introduces exactly the missing declaration:
ownership: 'business_unit'+ theowning_business_unit_idstamp, with D3's invariantrecord.organization_id == BU(owning_business_unit_id).organization_id— which is precisely the equation D13's backfill establishes. With 0117 landed, promotion gains a checkable postcondition: no row whose owning BU lies in the promoted subtree remains in the source org.Decision needed (either/or)
ownershipmetadata; the explicit map becomes an override. Recommended — it is what makes promotion verifiable rather than merely configurable.The D13 tool ships either way with the explicit-map interface (it stays correct as an override under option 1 — no rework).
Refs: ADR-0105 D13 / Appendix A, ADR-0117, cloud#874 (D13 item), cloud#1006 (sibling finding).