Measured while implementing #15866 (restoring the compile-time check on the REST layer's protocol dispatch sites). Handed back rather than acted on: closing it is a contract decision, not a door fix. ⛔ No severity asserted, no domain routing — that is triage's.
What was measured
#15866 retired the as any casts on 22 protocol-dispatch sites in packages/rest/src/rest-server.ts, typing each request literal against its declared spec contract. 19 of them compiled clean on the first try. Three did not, and all three failed on the same slot:
src/rest-server.ts(8992,34): error TS2353: Object literal may only specify known properties,
and '$filter' does not exist in type 'QueryInput'.
src/rest-server.ts(9302,33): error TS2561: Object literal may only specify known properties,
but '$top' does not exist in type 'QueryInput'. Did you mean to write 'top'?
src/rest-server.ts(10167,29): error TS2353: Object literal may only specify known properties,
and 'filters' does not exist in type 'QueryInput'.
The three doors are the import-job listing, the export chunk loop, and the public reference picker.
The gap, stated from both ends
- Declared.
FindDataRequestSchema.query is QuerySchema, i.e. the QueryAST (packages/spec/src/api/protocol.zod.ts). That is the whole declared vocabulary for the slot.
- Shipped.
@objectstack/metadata-protocol's findData accepts a second dialect through the same slot and folds it: WIRE_QUERY_ALIAS_SLOTS and WIRE_DOLLAR_ALIASES in packages/metadata-protocol/src/protocol.ts map $top to top to limit, $orderby to orderBy, filter / filters / $filter to where, $expand to expand, and so on.
The normalizer's own comment names the situation exactly, which is why this is a gap and not a discovery:
The spec's alias table extended with the wire-only spellings no schema declares: filters (documented plural alias of the filter transport param) and the OData $filter / $expand.
⇒ Two dialects, one slot, one of them declared. Every caller of findData that speaks the wire dialect is unverifiable at build time, and there is no runtime rejection either — the fold accepts it.
⚠️ Why the two obvious repairs are both wrong
So the question this card actually asks is: does the wire dialect belong in the declared contract as its own named input type, or should these three server-built literals be rewritten to speak the canonical AST? Both are defensible and neither is a door's call to make.
What #15866 did in the meantime
It did not widen anything and did not rewrite the doors. It confined the erasure from one call wide to one slot wide, behind a named, greppable wireDialectQuery helper that carries this card's reasoning. At those three sites the method name, the arity and every other request member are now compiled; only the query value is not.
Not claimed
Not swept: whether callers of findData outside packages/rest speak the wire dialect too, and whether getData / the *Many siblings have an equivalent split. This was scoped to what restoring the check in rest-server.ts surfaced.
Measured while implementing #15866 (restoring the compile-time check on the REST layer's protocol dispatch sites). Handed back rather than acted on: closing it is a contract decision, not a door fix. ⛔ No severity asserted, no domain routing — that is triage's.
What was measured
#15866 retired the
as anycasts on 22 protocol-dispatch sites inpackages/rest/src/rest-server.ts, typing each request literal against its declared spec contract. 19 of them compiled clean on the first try. Three did not, and all three failed on the same slot:The three doors are the import-job listing, the export chunk loop, and the public reference picker.
The gap, stated from both ends
FindDataRequestSchema.queryisQuerySchema, i.e. the QueryAST (packages/spec/src/api/protocol.zod.ts). That is the whole declared vocabulary for the slot.@objectstack/metadata-protocol'sfindDataaccepts a second dialect through the same slot and folds it:WIRE_QUERY_ALIAS_SLOTSandWIRE_DOLLAR_ALIASESinpackages/metadata-protocol/src/protocol.tsmap$toptotoptolimit,$orderbytoorderBy,filter/filters/$filtertowhere,$expandtoexpand, and so on.The normalizer's own comment names the situation exactly, which is why this is a gap and not a discovery:
⇒ Two dialects, one slot, one of them declared. Every caller of
findDatathat speaks the wire dialect is unverifiable at build time, and there is no runtime rejection either — the fold accepts it.QuerySchemato admit the$forms would make the second de-facto contract official, which is what Prime Directive Add comprehensive test suite for Zod schema validation #12 forbids and what the normalizer's sibling hint table is explicitly documented as avoiding ("This is a HINT table, not an alias table: nothing here is accepted as input … so it does not create the second de-facto contract Prime Directive Add comprehensive test suite for Zod schema validation #12 warns about").safeParseon the slot is closed by the same reasoning that closed it on [finding]p.deleteData({...} as any)/p.updateData({...} as any)erase the compile-time check of the assembled request againstDeleteDataRequest/UpdateDataRequest#15866's parent thread: a newly-required member would400live traffic rather than gate a drift.So the question this card actually asks is: does the wire dialect belong in the declared contract as its own named input type, or should these three server-built literals be rewritten to speak the canonical AST? Both are defensible and neither is a door's call to make.
What #15866 did in the meantime
It did not widen anything and did not rewrite the doors. It confined the erasure from one call wide to one slot wide, behind a named, greppable
wireDialectQueryhelper that carries this card's reasoning. At those three sites the method name, the arity and every other request member are now compiled; only thequeryvalue is not.Not claimed
Not swept: whether callers of
findDataoutsidepackages/restspeak the wire dialect too, and whethergetData/ the*Manysiblings have an equivalent split. This was scoped to what restoring the check inrest-server.tssurfaced.