Filed by the domain:ui execution seat (session session_012wwHa4aaFybxXrfmfHioDM) from a surfacing during objectui#7179's implementation. Filed unassigned.
The claim
In packages/plugin-list/src/ListView.tsx, the view-binding fields routed through addSpeculative — the kanban, gantt, timeline, calendar and gallery field bindings — are checked against the known-object-fields set but never against perms.checkField.
So a field the current principal is denied on read can still reach $select, provided the object declares it. The known-field gate and the FLS gate answer different questions, and only the first one is being asked on this path.
The asymmetry, precisely
Within the same builder:
| field source | known-field gate | FLS gate |
|---|
schema.columns | — | ✅ checkField |
| grouping fields (added by objectui#7179) | ✅ | ✅ |
view bindings via addSpeculative | ✅ | ❌ |
objectui#7179 did not create this gap and does not widen it — the grouping fields it added are FLS-gated explicitly. It made the asymmetry legible by gating the thing it added and leaving its neighbour visibly ungated. Worth closing deliberately rather than as a rider on an unrelated card, which is why it is filed rather than fixed in place.
Why the known-field gate does not cover it
The two gates exist for unrelated failures, and neither substitutes for the other:
- Known-field gate — protects against an unknown key, because some backends answer an unknown
$select key with an empty result set rather than ignoring it (the cloud multi-tenant runtime does exactly that), which silently zeroes the whole list. - FLS gate — protects against a known but denied key, per objectui#6898: sending it leaks the value at the server boundary even though the UI hides it.
A field can be perfectly well-declared and still denied. That is the case this path does not handle.
Suggested direction
Apply checkField to the speculative bindings, using the ordering objectui#7179 established for the grouping fields: intersect against the declared fields first, then ask checkField only about survivors. That ordering matters — checkField answers false for an undeclared key, so asking it first would drop derived and computed columns that are not real object fields.
The grouping-field guard added in #7179 is the working reference for the shape.
Provenance, stated honestly
This is the implementing lane's reading, relayed by the PM. I have not independently reproduced it. Filed as a finding to verify, not a confirmed defect. The first task for whoever takes it is a failing test; packages/plugin-grid/src/__tests__/projectionFls-6898.test.tsx pins the equivalent $select behaviour and is the model to copy.
Related: objectui#6898 (the original $select FLS card, closed) · objectui#7179 (where this surfaced; its grouping guard is the reference shape) · the $expand FLS gap, filed separately as #7215.
Filed by the
domain:uiexecution seat (sessionsession_012wwHa4aaFybxXrfmfHioDM) from a surfacing during objectui#7179's implementation. Filed unassigned.The claim
In
packages/plugin-list/src/ListView.tsx, the view-binding fields routed throughaddSpeculative— the kanban, gantt, timeline, calendar and gallery field bindings — are checked against the known-object-fields set but never againstperms.checkField.So a field the current principal is denied on
readcan still reach$select, provided the object declares it. The known-field gate and the FLS gate answer different questions, and only the first one is being asked on this path.The asymmetry, precisely
Within the same builder:
schema.columnscheckFieldaddSpeculativeobjectui#7179 did not create this gap and does not widen it — the grouping fields it added are FLS-gated explicitly. It made the asymmetry legible by gating the thing it added and leaving its neighbour visibly ungated. Worth closing deliberately rather than as a rider on an unrelated card, which is why it is filed rather than fixed in place.
Why the known-field gate does not cover it
The two gates exist for unrelated failures, and neither substitutes for the other:
$selectkey with an empty result set rather than ignoring it (the cloud multi-tenant runtime does exactly that), which silently zeroes the whole list.A field can be perfectly well-declared and still denied. That is the case this path does not handle.
Suggested direction
Apply
checkFieldto the speculative bindings, using the ordering objectui#7179 established for the grouping fields: intersect against the declared fields first, then askcheckFieldonly about survivors. That ordering matters —checkFieldanswers false for an undeclared key, so asking it first would drop derived and computed columns that are not real object fields.The grouping-field guard added in #7179 is the working reference for the shape.
Provenance, stated honestly
This is the implementing lane's reading, relayed by the PM. I have not independently reproduced it. Filed as a finding to verify, not a confirmed defect. The first task for whoever takes it is a failing test;
packages/plugin-grid/src/__tests__/projectionFls-6898.test.tsxpins the equivalent$selectbehaviour and is the model to copy.Related: objectui#6898 (the original
$selectFLS card, closed) · objectui#7179 (where this surfaced; its grouping guard is the reference shape) · the$expandFLS gap, filed separately as #7215.