Skip to content

spec: record:reference_rail has no ComponentPropsMap row — an entry filter parses, typechecks, validates, ships, and silently does nothing #8691

Description

@hotlong

Measured on @objectstack/spec 17.0.0 GA and @objectstack/console 17.0.0 GA, statically and on a rendered page in a browser. Downstream at objectstack-ai/hotcrm#986 (GA close-out probe objectstack-ai/hotcrm#1154).

Scope note up front: the downstream card records three gaps in record:reference_rail. This mirror carries only the first — the missing spec declaration. The other two (rail title cannot reach pluralLabel; title is an untranslatable literal) are console renderer behaviour and genuine capability expansion, so they belong to the console seat and to a maintainer ruling on business pull; they are named at the bottom, not folded in here.

The gap

ComponentPropsMap (@objectstack/spec/ui, 17.0.0 GA)
  total component keys = 37
  record:* keys = ["record:details","record:related_list","record:highlights",
                   "record:activity","record:chatter","record:path"]
  has record:reference_rail = false

grep reference_rail dist/ui/index.d.ts → 0 hits; there is no ReferenceRailEntry type either. With no row in the map, PageComponent.properties stays an open bag (z.record(z.string(), z.unknown())) and nothing on any path parses a rail entry.

The rail actually consumes only objectName / relationshipField / limit / title (plus icon, displayField for row rendering), issuing one query per entry:

find(objectName, { $filter: { [relationshipField]: parentId }, $top: limit ?? 3, $count: true })

Why it matters: the authored key is accepted everywhere and honoured nowhere

Reverse verification on a real app, with the expected direction fixed before running. Planted on a rail entry whose object has 3 related rows, 2 of them not completed:

filter: [{ field: 'status', op: 'neq', value: 'completed' }]
stage result
tsc --noEmit exit 0
objectstack validate passedreference_rail appears 0 times in the output
objectstack build exit 0reference_rail appears 0 times
shipped artifact filter present verbatim in dist/objectstack.json
rendered rail badge unchanged at 3; the completed row still listed

The contrast is the finding: the same build run emits loud component-props-unknown-key / component-props-invalid warnings for record:related_list, record:activity and page:accordion in the very same file — because those components have rows in ComponentPropsMap. The rail is silent purely because it is undeclared.

Control confirming the mechanism rather than assuming it: ComponentPropsMap['record:related_list'].safeParse({ … bogus key … }) rejects.

So an author — most importantly an AI author — can add filter to a rail entry, watch it pass typecheck, validate, build and publish, and ship source that claims to filter while the badge keeps counting everything. This is the failure shape #4001 was closed to eliminate, still open on this one component.

Suggested fix

Add a strict record:reference_rail row to ComponentPropsMap describing the shape the renderer actually reads (objectName, relationshipField, limit, title, icon, displayField, and the component-level hideEmpty). This tightens an existing shape rather than expanding the authorization surface: it needs no judgement about whether a rail filter has business pull, and it converts today's silent no-op into a loud publish-time rejection. If a rail filter is later granted, the row is where it gets declared and enforced.

Explicitly not in this card

  • rail title resolves objects.*.label, never pluralLabel, on a card that carries a total-count badge (cosmetic);
  • rail title is rendered as a raw React child, so unlike record:alert it cannot take an inline translation map — the only options are "omit" or "a literal that overrides every locale".

Both are console-side and both are capability expansion; the downstream card notes the only consumer found by a repo-wide grep is a single rail on one detail page, so the pull question is genuinely open. Recommend splitting them to the console seat only if the maintainer rules there is pull.

Downstream: objectstack-ai/hotcrm#986 (see also hotcrm#972, hotcrm#733).

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

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions