Found while triaging @object-ui/types:ActionParam for the objectstack#4115 ledger burn-down (batch 2, objectui#3156). Recording only — not fixed there, because the fix changes what the resolver reads, and a behavior change should not ride on a symbol-derivation PR.
The gap
Two spellings for one concept, on two sides of resolveActionParams():
- authoring side —
resolveActionParams() (packages/app-shell/src/utils/resolveActionParams.ts) reads param.reference for an inline lookup/master_detail target, and nothing else. Its own local input interface documents this: "Spelled reference to match FieldSchema.reference / ActionParamSchema.reference."
- resolved side — it emits
@object-ui/core's ActionParamDef with referenceTo, which paramToField.ts maps to the picker's reference_to.
@object-ui/types' public ActionParam — the type a host app authors against — declared referenceTo and did not declare reference at all (until batch 2 derived the type from the spec's ActionParamSchema, which restores reference).
So an author who followed the public type and wrote:
{ name: 'account_id', type: 'lookup', referenceTo: 'account' }
got a param whose picker target was silently dropped: the picker degrades to a plain record-id text input. The dev-mode warning in paramToField.ts then says:
Declare reference: '<object>' on the param, or make it field-backed …
i.e. it names a key the public type did not have. The two halves of the contract disagreed about the spelling, and the type was the half that was wrong.
Now
After objectui#3156's derivation, ActionParam carries both: reference (inherited from the spec, and the one the resolver reads) and referenceTo (the resolved-side spelling, declared for parity with ActionParamDef and documented as such, pointing here).
The decision this needs
Pick one, and make declaration and runtime agree:
reference is the authoring key (matches the spec and FieldSchema). Then referenceTo and the rest of the picker group (displayField, idField, descriptionField, titleFormat, lookupColumns, lookupFilters, lookupPageSize, dependsOn) should be removed from the authoring ActionParam — they belong to the resolved ActionParamDef only. That is a breaking change to a published type and needs a changeset.
- Accept both at authoring time.
resolveActionParams() reads param.reference ?? param.referenceTo, and the same for the rest of the group, with a test per key.
Either way the gate should be a test that authors a param through the public type and asserts the picker gets its target — the current tests exercise the resolver's own local input interface, which is why the mismatch survived.
Found while triaging
@object-ui/types:ActionParamfor the objectstack#4115 ledger burn-down (batch 2, objectui#3156). Recording only — not fixed there, because the fix changes what the resolver reads, and a behavior change should not ride on a symbol-derivation PR.The gap
Two spellings for one concept, on two sides of
resolveActionParams():resolveActionParams()(packages/app-shell/src/utils/resolveActionParams.ts) readsparam.referencefor an inlinelookup/master_detailtarget, and nothing else. Its own local input interface documents this: "Spelledreferenceto matchFieldSchema.reference/ActionParamSchema.reference."@object-ui/core'sActionParamDefwithreferenceTo, whichparamToField.tsmaps to the picker'sreference_to.@object-ui/types' publicActionParam— the type a host app authors against — declaredreferenceToand did not declarereferenceat all (until batch 2 derived the type from the spec'sActionParamSchema, which restoresreference).So an author who followed the public type and wrote:
got a param whose picker target was silently dropped: the picker degrades to a plain record-id text input. The dev-mode warning in
paramToField.tsthen says:i.e. it names a key the public type did not have. The two halves of the contract disagreed about the spelling, and the type was the half that was wrong.
Now
After objectui#3156's derivation,
ActionParamcarries both:reference(inherited from the spec, and the one the resolver reads) andreferenceTo(the resolved-side spelling, declared for parity withActionParamDefand documented as such, pointing here).The decision this needs
Pick one, and make declaration and runtime agree:
referenceis the authoring key (matches the spec andFieldSchema). ThenreferenceToand the rest of the picker group (displayField,idField,descriptionField,titleFormat,lookupColumns,lookupFilters,lookupPageSize,dependsOn) should be removed from the authoringActionParam— they belong to the resolvedActionParamDefonly. That is a breaking change to a published type and needs a changeset.resolveActionParams()readsparam.reference ?? param.referenceTo, and the same for the rest of the group, with a test per key.Either way the gate should be a test that authors a param through the public type and asserts the picker gets its target — the current tests exercise the resolver's own local input interface, which is why the mismatch survived.