You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Found while implementing #5091 (the per-key ruling on four (schema as any) keys). Filed unassigned, not claiming.
The correction
#5091's body offered bulkActionDefs and userActions as the two cast-read keys that are already declared, and rested its "these four are just an omission" reading on that pair. Measured on origin/main @ 118419214:
key
in GRID_QUERY_INPUTS?
in ObjectGridSchema (packages/types/src/objectql.ts)?
ComponentPropsMap['object-grid'] (spec 17.0.0)?
bulkActionDefs
✅ yes
✅ yes (:874)
✅ accepted
userActions
❌ no
❌ no
❌ rejected by name (unrecognized_keys)
So only bulkActionDefs was ever the symmetry. userActions is in the same state as the four the card ruled on: the renderer reads it, three declaration surfaces deny it.
Reproduce:
grep -n "userActions" packages/plugin-grid/src/index.tsx # no hit — not in GRID_QUERY_INPUTS
grep -n "userActions" packages/plugin-grid/src/ObjectGrid.tsx # :864, :1066 (plus prose)
node --input-type=module -e "import {ComponentPropsMap} from '@objectstack/spec/ui';
console.log(ComponentPropsMap['object-grid'].safeParse({objectName:'a',userActions:{}}).success)" # false
The two read sites are NOT the same channel — that is the whole question
// packages/plugin-grid/src/ObjectGrid.tsx:864 — the OBJECT's block
userActions: (objectSchema as any)?.userActions,
// packages/plugin-grid/src/ObjectGrid.tsx:1066 — a VIEW-level override, first
userActions: (schema as any).userActions ?? (resolvedSchema as any)?.userActions,
:864 feeds resolveRowCrudAffordances and is documented throughout rowCrudAffordances.ts as the object'suserActions.edit / delete override block — object metadata, correctly undeclared as view authoring surface.
:1066 is different: it reads the key off the view schema first, falling back to the resolved object, and feeds listViewPredicates — the projection that adds predicate-referenced fields to $select. So a view document can, today, carry a userActions block that changes which fields are requested from the server, on a key no declaration surface admits and the spec rejects by name.
Why this needs the same per-key ruling the four just got
Three readings, and picking one is a contract decision, not an implementation detail:
Non-author surface, deliberately unlisted (what :864 clearly is) — then :1066's schema-first read is the odd one out and should read the object block only, since a view-level override of an object's CRUD affordances is a permissions-shaped decision.
Author surface — then it needs the upstream spec key first: ObjectGridPropsSchema is a strictObject, so declaring it in GRID_QUERY_INPUTS alone would publish a key the save gate refuses (measured in ObjectGrid 用 (schema as any) 读的 4 个键不在 GRID_QUERY_INPUTS 里 —— #4648 要消除的「渲染器读得到、声明面否认」在这些键上仍然存在 #5091's implementation; apps/console/src/__tests__/registry-inputs-spec-parity.test.ts fails on exactly this).
Dead override — if nothing writes schema.userActions, ADR-0049 enforce-or-remove applies to the read at :1066. I did not find a producer: app-shell/src/views/ObjectView.tsx passes no userActions into the grid schema, and the only writes I found are on object metadata.
Scope note
Out of scope for #5091, whose maintainer ruling of 2026-08-18 enumerates exactly four keys. Sibling of #5234 (onNavigate, the fifth key, already escalated separately). Same family as #5097 / #5102 one and two packages over.
Found while implementing #5091 (the per-key ruling on four
(schema as any)keys). Filed unassigned, not claiming.The correction
#5091's body offered
bulkActionDefsanduserActionsas the two cast-read keys that are already declared, and rested its "these four are just an omission" reading on that pair. Measured onorigin/main@118419214:GRID_QUERY_INPUTS?ObjectGridSchema(packages/types/src/objectql.ts)?ComponentPropsMap['object-grid'](spec 17.0.0)?bulkActionDefs:874)userActionsunrecognized_keys)So only
bulkActionDefswas ever the symmetry.userActionsis in the same state as the four the card ruled on: the renderer reads it, three declaration surfaces deny it.Reproduce:
The two read sites are NOT the same channel — that is the whole question
:864feedsresolveRowCrudAffordancesand is documented throughoutrowCrudAffordances.tsas the object'suserActions.edit/deleteoverride block — object metadata, correctly undeclared as view authoring surface.:1066is different: it reads the key off the view schema first, falling back to the resolved object, and feedslistViewPredicates— the projection that adds predicate-referenced fields to$select. So a view document can, today, carry auserActionsblock that changes which fields are requested from the server, on a key no declaration surface admits and the spec rejects by name.Why this needs the same per-key ruling the four just got
Three readings, and picking one is a contract decision, not an implementation detail:
:864clearly is) — then:1066's schema-first read is the odd one out and should read the object block only, since a view-level override of an object's CRUD affordances is a permissions-shaped decision.ObjectGridPropsSchemais astrictObject, so declaring it inGRID_QUERY_INPUTSalone would publish a key the save gate refuses (measured in ObjectGrid 用(schema as any)读的 4 个键不在GRID_QUERY_INPUTS里 —— #4648 要消除的「渲染器读得到、声明面否认」在这些键上仍然存在 #5091's implementation;apps/console/src/__tests__/registry-inputs-spec-parity.test.tsfails on exactly this).schema.userActions, ADR-0049 enforce-or-remove applies to the read at:1066. I did not find a producer:app-shell/src/views/ObjectView.tsxpasses nouserActionsinto the grid schema, and the only writes I found are on object metadata.Scope note
Out of scope for #5091, whose maintainer ruling of 2026-08-18 enumerates exactly four keys. Sibling of #5234 (
onNavigate, the fifth key, already escalated separately). Same family as #5097 / #5102 one and two packages over.Generated by Claude Code