Skip to content

[finding] getUiView's list body still names a declared-hidden field in sort after that field is correctly withheld from columns #13328

Description

@os-zhuang

Found out of scope while implementing #13259 (the repair that makes getUiView's list priority pass honour hidden). ⛔ Reported, not touched — the repair direction here is a judgment call about what hidden governs, which is exactly the kind of thing #13259's triage ruled must not be smuggled into a card that only restores a stated invariant.

Ungraded and unrouted. Severity not judged here. Duplicate-checked before filing: all 354 open issues were listed through the REST list endpoint (the search endpoint answers 403 from this seat, so the read is list + local grep) and grepped for getUiView / ui view / ui/view / hidden / sort. The control passed — the grep returns #13259 itself, plus #13214, #13294, #12767 and #8113, none of which is this. So the zero is a reading, not an unverified silence.

Measured — driven, with a control arm, not read off the source

packages/metadata-protocol/src/protocol.ts, getUiView, the type === 'list' branch, builds its sort directive from presence alone:

sort: fields['created_at'] ? ([{ field: 'created_at', order: 'desc' }] as any) : undefined,

created_at is one of the nine priority names. With #13259's fix in place it is correctly withheld from columns when declared hidden — and sort names it anyway. Driven against the built dist of @objectstack/metadata-protocol at #13259's branch head, two arms:

--- created_at HIDDEN
columns : ["body"]
sort : [{"field":"created_at","order":"desc"}]
search : ["body"]
--- created_at VISIBLE (control)
columns : ["created_at","body"]
sort : [{"field":"created_at","order":"desc"}]
search : ["created_at","body"]

The control is the point: sort is byte-identical across the two arms, so it is unconditional on hidden rather than merely happening to agree. columns and searchableFields differ between the arms, so the probe is demonstrably able to observe a difference where one exists.

Why this is a card and not a comment

  1. It is a state that did not exist before [finding] getUiView list branch serves fields declared hidden when the field name is one of its nine priority names — declared, not enforced #13259. Before that fix, a hidden created_at was emitted as a column and named in sort — wrong, but internally consistent. After it, the body names an ordering field that is not among its own columns. That is a new shape, and it arrived as a side effect rather than a decision.
  2. The question it raises is genuinely open, which is why [finding] getUiView list branch serves fields declared hidden when the field name is one of its nine priority names — declared, not enforced #13259 did not answer it: FieldSchema.hidden is declared "Hidden from default UI". Sorting by a field is not displaying it, and sorting a grid by a column the grid does not show is ordinary, deliberate behaviour in list UIs. So this may be correct as it stands. ⛔ No claim is made here that it is a defect.
  3. It is the same producer and the same declaration, so whichever way it is answered, the answer belongs next to [finding] getUiView list branch serves fields declared hidden when the field name is one of its nine priority names — declared, not enforced #13259's rather than being re-derived later by whoever notices the asymmetry.

Not decided here

Three readings, left to triage:

  • hidden does not govern ordering — current behaviour is correct, and the right output is a one-line comment in the producer saying so, so the next reader does not read it as residue.
  • hidden governs everything the default UI derives — the sort directive should be omitted when created_at is hidden, matching how searchableFields already follows columns.
  • The sort field should be constrained to the emitted columns regardless of hidden — a broader statement about the body's internal consistency, and the one with the largest blast radius.

⚠️ Note for whoever takes it: ListViewSchema (packages/spec/src/ui/view.zod.ts) does not cross-reference sort against columns, so the current body parses GREEN against GetUiViewResponseSchema either way. Schema conformance is not the detector here and cannot be made to be one without a schema change.

Re-check

git grep -n "order: 'desc'" -- packages/metadata-protocol/src/protocol.ts
pnpm --filter @objectstack/metadata-protocol exec vitest run src/protocol.ui-view-hidden-columns.test.ts

⛔ Reverse-check any zero with a term known present in the same region: searchableFields sits three lines below the sort line, and priorityFields about twenty lines above it.

Refs

Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions