Skip to content

record:reference_rail cannot bind to a multi-value relationship field either — same bare-equality parent filter as objectui#7299, plus a "View all" link the URL grammar cannot express #8883

Description

@claude

Found while fixing objectui#7299 (dev seat, enumeration axis: who else compiles a parent-relationship condition). Filed separately rather than folded in, because it is a different block, a different authoring key and a different code path — objectui#7299's ruling scopes it to RelatedList.

The measurement, on origin/main

record:reference_rail takes an author-supplied relationshipField per entry and compiles it as bare equality — twice, in two different grammars:

packages/plugin-detail/src/renderers/record-reference-rail.tsx:187
    $filter: { [entry.relationshipField]: parentId },

packages/plugin-detail/src/renderers/record-reference-rail.tsx:285
    to={`/apps/${appName}/${entry.objectName}?filter%5B${entry.relationshipField}%5D=...`}

That is objectui#7299's defect, on another block. When the named field is multiple: trueField.user({ multiple: true }) is the platform's own shape — the stored value is a JSON-valued array, = compares the whole serialized array against one id, and driver-sql refuses with 400 INVALID_FILTER naming the field and prescribing $contains. The author is naming a relationship; nothing on the authoring surface lets them say "membership".

Positive control for the negative result: git grep '\$contains' packages/plugin-detail/src/renderers/record-reference-rail.tsx → 0 hits, with relationshipField at 4 hits in the same read. The absence is measured, not a probe failure.

The second spelling is the harder half

:187 is fixable the way objectui#7299 fixed RelatedList: read the child object's declared arity and compile { [field]: { $contains: parentId } }.

:285 is NOT. It builds a link into the ADR-0055 bare data surface, whose one operator contract is drillUrlFilters' URL_FILTER_OPS (objectui#1752) — gte / lte / gt / lt and nothing else — and whose parser DROPS an unrecognised operator suffix rather than downgrading it. So filter[<field>][contains]= would arrive as no condition at all, i.e. the "View all" link would open the child object UNSCOPED: every row of the table, presented as this parent's related records. That is strictly worse than the 400 and it is why this needs a decision rather than a patch — the same reasoning objectui#7299 recorded for RelatedList's raw-URL fallback, where the answer was to refuse loudly instead.

So this card carries a real question: does the URL filter grammar grow a membership operator (a change to URL_FILTER_OPS, both sides, plus its pin), or does the rail suppress / re-target "View all" for a multi-value relationship?

Deliberately NOT claimed here

packages/plugin-form/src/LineItemsPanel.tsx:200 and packages/plugin-form/src/MasterDetailForm.tsx:762 compile the same bare-equality parent scope. They are NOT asserted as defects on this card: their relationship is a master_detail FK, and whether that field type can legally carry multiple: true was not verified. Whoever takes this card should answer that first — if it can, they belong here; if it cannot, they are correct as written and the sweep ends at the rail.


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpackage: plugin-detailpriority:p2

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions