Skip to content

[finding] Both field-resolution gates for a list view (searchableFields and sort) are CLI-only — the reference-integrity suite dispatches at the runtime publish gate for flow alone, so a Studio/MCP view write gets neither #9313

Description

@os-steve

Recorded while implementing #9257 (PR adding validateSortableFields). Not claimed. Filed as a sub-issue of #4716 because it is one concrete item of that card's "全量 runtime-safe 规则快照" half, not a separate direction.

What is measured

REFERENCE_INTEGRITY_RULES is one entry in the authoring-rule registry, and that entry declares:

surfaces: CLI_AND_RUNTIME,
runtimeTypes: ['flow'],

So on the runtime publish gate the suite runs only for a flow snapshot. Two of its members judge a list view's field references and neither can fire there:

Both surfaces they walk are reachable through the metadata door. A standalone list view is written as ViewMetadataSchema's flattened list-overlay member (packages/spec/src/ui/view.zod.ts, ListViewOverlayWireSchemaListViewSchema.extend(flattenedViewOverlayFields()).strip(), with object + viewKind required since #7741), which carries sort and searchableFields at its top level. That door is PUT /api/v1/meta/view, i.e. the only door a Studio tenant or an MCP/AI author has.

Net effect: an author who writes the exact declaration both rules exist to refuse gets it accepted, because the author who would have been stopped is the one who never runs a CLI command. That is #4463's own founding shape ("the runtime write path, the only door a Studio tenant or an MCP/AI author has, ran none of the 26 rules at all"), surviving on this one registry entry.

Note the two halves are independent: even with runtimeTypes widened to view, the metadata walk in validateSearchableFields / validateSortableFields reads objects[].listViews.* and views[].list / views[].listViews.* — it does not read a top-level flattened overlay. So this needs both a dispatch widening and a rung in the walk, and doing only the first would be a silent no-op that reads as coverage.

Why it was not fixed in the #9257 PR

authoring-rules.ts records the decision boundary in the suite's own entry — widening the gate's dispatch surface "would widen the gate's dispatch surface on this rule's authority, which is P2's decision". A new rule joining the suite inherits the entry; it does not get to change it. The #9257 PR therefore documents the gap in its module docblock and leaves it here.

The false-positive budget applies unchanged

#4716's ruling that this is not a one-line runtimeTypes edit holds here too: view writes are hot (every console column-sort PUT is one), and both rules gate at error. A tenant-metadata replay is owed before either reaches the runtime door — with the added wrinkle that a console sort PUT persists sort: [{ id, field, order }] rows carrying objectui's crypto.randomUUID() row id (view.zod.ts's #5074 note), so the replay must run against the shape saveMetaItem really stores, not the authoring shape.

Refs

#4716 (parent, P2), #4463 (P1), #9257 (the SORT gate), #6674 (the SEARCH gate), #7741 (the overlay's required pair), #7220 and #6715 (the same shape for two other rule families).

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions