|
| 1 | +--- |
| 2 | +"@objectstack/spec": minor |
| 3 | +--- |
| 4 | + |
| 5 | +feat(spec)!: a `tree` field's `reference`, when present, must name the declaring object — any other target is refused at parse (#14892) |
| 6 | + |
| 7 | +<!-- adr-0087: not-required (no-migration-prescription) No authorable key is renamed, retired or re-typed: `reference` keeps its name, its type and its optionality on a `tree` field, and every self-referencing or reference-less `tree` parses byte-identically to before. What is newly refused is a `tree` whose `reference` names a different object — a shape no prose surface ever documented, that no runtime reader consumed as a cross-object link, and whose one in-repo author (the showcase field zoo) hedged in its own label. The remedy is authoring intent, not a mechanical rewrite: the author decides whether the field is this object's own hierarchy (a self-reference, or no `reference` at all) or a link to another object (a `lookup`), so `objectstack migrate meta` has nothing to rewrite and this changeset carries no rewrite instructions. --> |
| 8 | + |
| 9 | +**BREAKING** in the accept-set sense, landing in the launch window as `minor` |
| 10 | +(the lockstep convention). Maintainer ruling 2026-09-05 on #14892, option A. |
| 11 | + |
| 12 | +**What changes.** `ObjectSchema` (and `ObjectExtensionSchema`, judged against |
| 13 | +the object it extends) now refuses a field declared `type: 'tree'` whose |
| 14 | +`reference` names any object other than the declaring one. The refusal is a |
| 15 | +located parse issue at `fields.<field>.reference` whose message names both |
| 16 | +objects and the three ways out: drop `reference` (it is optional on a `tree`), |
| 17 | +name the object itself, or declare a `lookup` if a link to a different object |
| 18 | +was meant. `FieldSchema` alone is unchanged — a field does not know which |
| 19 | +object declares it, so the judgment lives on the object door. |
| 20 | + |
| 21 | +**Why.** A hierarchy is parent/child within one object, and that is what every |
| 22 | +reader of the type already assumed: the tree renderer's parent-pointer |
| 23 | +auto-detection takes the first `tree` field as the object's own parent column, |
| 24 | +four prose surfaces said self-reference, and `deleteBehavior` materialises on |
| 25 | +`tree` beside `lookup` because a self-referential hierarchy is a relation whose |
| 26 | +cascade is exactly the intended semantics. The designer's shared `reference` |
| 27 | +input reused one "Target object name" help text for three types, and the one |
| 28 | +shipped `tree` example pointed at another object under a hedging label — two |
| 29 | +spellings parsed silently, and an example taught a third. The key is now |
| 30 | +enforced with one meaning; `reference` stays optional on a `tree` as a |
| 31 | +redundant self-annotation, which is also what makes a reference-less `tree` |
| 32 | +being classified `relation` (and materialising `deleteBehavior`) coherent. |
| 33 | + |
| 34 | +**Alongside.** `checkViewCompleteness`'s parent-pointer predicate reads the |
| 35 | +same rule: a `tree` field is a detectable parent pointer only when its |
| 36 | +`reference` is absent or the object's own name, so a `tree` view bound to an |
| 37 | +object whose only `tree` field points elsewhere is reported `view/tree-without- |
| 38 | +parent-field` rather than blessed. The designer help text for the shared |
| 39 | +`reference` row now says so for `tree`, the showcase `showcase_field_zoo.f_tree` |
| 40 | +is a self-reference, and the data-modeling docs say "optional and, if given, |
| 41 | +must be this object". |
| 42 | + |
| 43 | +```ts |
| 44 | +// accepted — a self-reference, or no reference at all |
| 45 | +parent: { type: 'tree', reference: 'category' } |
| 46 | +parent: { type: 'tree' } |
| 47 | +// refused at parse — `fields.parent.reference` on object `category` |
| 48 | +parent: { type: 'tree', reference: 'department' } |
| 49 | +``` |
| 50 | + |
| 51 | +**Not measured.** Out-of-repo cross-object trees are NOT MEASURED: no customer |
| 52 | +application was surveyed for a `tree` field pointing at a different object. |
| 53 | +In-repo, every other `tree` author is a self-reference or carries no |
| 54 | +`reference`; the objectui pin's unit fixtures are outside this schema's reach |
| 55 | +and are listed on the card. |
0 commit comments