Found while implementing #14107 (list-view field-reference integrity in packages/lint). Filed rather than folded in: it is a wider accept-set narrowing than that card gates, and its failure mode is the opposite one.
What is still unchecked
A list view field position may be written as a dotted path (owner.name). #14107's rule judges the head segment only, so a dotted path whose head resolves to a real relationship field passes author time:
columns: [{ field: 'owner.name' }] -- clean through os validate and os build.
At query time, all three axes a list view reaches refuse it by name:
- projection:
assertProjectionHasNoDottedPaths in packages/objectql/src/engine.ts, plus assertProjectionFieldsExist at the REST ingress;
- filter: the dotted-head door, on the reasoning that no backend serves the path so the predicate can only match zero records;
- sort:
assertSortFieldsExist's unknown / dotted / unmaterializable ladder.
A ListViewSchema declares no ADR-0021 include, so a list view compiles no joins and there is no declaration that could make a relationship prefix joinable.
Why it was left out of #14107
That card gates the silent class -- a misspelt name that renders blank while every gate reports success. A dotted path whose head resolves fails loudly instead (a refused fetch, a 400), which is a different severity argument and a different accept-set change. #14107 records the split in the rule's module docblock and pins both halves in tests, so a later change that starts reporting this case has to delete a test that states the reason.
Suggested shape
Extend the #14107 rule with a second finding class -- "a list view compiles no joins, so a dotted reference is refused at query time" -- at warning or error per the family's own severity line, reusing the same object-graph seam. No new resolution mechanism is needed. One deliberate exception to check first: gantt.quickFilters[].field is described in the spec as "Record field / dot-path", so whether that position really accepts a dot-path at runtime needs measuring before it is refused.
Generated by Claude Code
Found while implementing #14107 (list-view field-reference integrity in
packages/lint). Filed rather than folded in: it is a wider accept-set narrowing than that card gates, and its failure mode is the opposite one.What is still unchecked
A list view field position may be written as a dotted path (
owner.name). #14107's rule judges the head segment only, so a dotted path whose head resolves to a real relationship field passes author time:columns: [{ field: 'owner.name' }]-- clean throughos validateandos build.At query time, all three axes a list view reaches refuse it by name:
assertProjectionHasNoDottedPathsinpackages/objectql/src/engine.ts, plusassertProjectionFieldsExistat the REST ingress;assertSortFieldsExist's unknown / dotted / unmaterializable ladder.A
ListViewSchemadeclares no ADR-0021include, so a list view compiles no joins and there is no declaration that could make a relationship prefix joinable.Why it was left out of #14107
That card gates the silent class -- a misspelt name that renders blank while every gate reports success. A dotted path whose head resolves fails loudly instead (a refused fetch, a 400), which is a different severity argument and a different accept-set change. #14107 records the split in the rule's module docblock and pins both halves in tests, so a later change that starts reporting this case has to delete a test that states the reason.
Suggested shape
Extend the #14107 rule with a second finding class -- "a list view compiles no joins, so a dotted reference is refused at query time" -- at
warningorerrorper the family's own severity line, reusing the same object-graph seam. No new resolution mechanism is needed. One deliberate exception to check first:gantt.quickFilters[].fieldis described in the spec as "Record field / dot-path", so whether that position really accepts a dot-path at runtime needs measuring before it is refused.Generated by Claude Code