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
fix(sharing,runtime): a sort passed straight to the engine never ordered anything (#4346) (#4370)
Sweeping every in-repo engine call site that still spoke a deprecated alias
turned up three that were not cosmetic.
#4346 made the engine fold `filter`→`where` and `top`→`limit` on all six
methods. The remaining four pairs in RPC_QUERY_ALIAS_SLOTS (select, sort,
skip, populate) fold at the RPC/wire layer only — their values need shape
lowering that belongs to those layers — and a DIRECT engine.find() never
crosses that layer. Three call sites passed `sort` there, so it rode onto the
AST untouched, every driver's `Array.isArray(query.orderBy)` guard declined to
emit an ORDER BY, and the read returned an ordinary-looking, arbitrarily
ordered result:
share-link-routes.ts shared AI conversation messages, created_at asc
runtime/domains/share-links.ts the same route, runtime-domain copy
share-link-service.ts listLinks: "the 200 most recent" share links
Each pairs the dropped sort with a limit — the "latest N" shape whose failure
#4226 spelled out, one layer below the normalizer #4226 fixed. listLinks had
no test at all, which is why it went unnoticed; it is pinned now on the option
bag the engine RECEIVES, not on row order, because the failure is that the key
never becomes `orderBy` and a double honouring either spelling passes either
way. Verified the pin fails against the pre-fix line before keeping it.
The other 27 sites are strict no-ops since #4346 folds `filter`: approvals 5,
auth 2, reports 6, sharing 11, webhooks 2, plus a spec doc example teaching
`filters` (a wire-only alias the engine does not fold at all, so the example
taught a call that matches every row). Renaming them stops the framework
depending on a spelling it asks users to migrate off. Service-level `filter`
PARAMETERS — each service's own public API — are deliberately untouched.
One test double had to move with them: approver-org-scope's fake engine read
`opts.filter`, so it kept passing only because both sides shared the
deprecated dialect. That is the mechanism that let the whole class persist.
Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
fix(sharing,runtime): a `sort` passed straight to the engine never ordered anything; migrate every in-repo engine call to canonical QueryAST keys (#4346)
12
+
13
+
Two changes with different weights, from one sweep of every in-repo engine
14
+
call site that still speaks a deprecated alias.
15
+
16
+
**The bug — three dropped sorts.**#4346 made the engine fold `filter`→`where`
17
+
and `top`→`limit` on all six methods. The other four pairs in
18
+
`RPC_QUERY_ALIAS_SLOTS` (`select`, `sort`, `skip`, `populate`) are folded at
19
+
the RPC/wire layer only — their values need shape lowering that belongs to
20
+
those layers — and a **direct `engine.find()` never crosses that layer**. Three
21
+
call sites passed `sort` there, so it rode onto the AST untouched, every
22
+
driver's `Array.isArray(query.orderBy)` guard declined to emit an ORDER BY, and
23
+
the query returned an ordinary-looking, arbitrarily-ordered result:
24
+
25
+
| call site | asked for | actually got |
26
+
|---|---|---|
27
+
|`share-link-routes.ts`| shared AI conversation messages, `created_at asc`| messages in arbitrary order |
28
+
|`runtime/domains/share-links.ts`| same route, runtime-domain copy | same |
29
+
|`share-link-service.ts``listLinks`| the 200 most recent share links | an arbitrary 200 |
30
+
31
+
All three combine the dropped sort with a `limit` — the "latest N" shape whose
32
+
failure #4226 spelled out: an unapplied sort returns rows in arbitrary order,
33
+
which `limit` then slices into an arbitrary page. #4226 fixed that in the wire
34
+
normalizer; these calls sit one layer below it. `listLinks` had no test at all,
35
+
which is why it went unnoticed. Now pinned — on the option bag the engine
36
+
receives, not on row order, because the failure is that the key never becomes
37
+
`orderBy` and a fake engine honouring either spelling would pass either way.
0 commit comments