Repository navigation
[finding] the comparand-SHAPE face declares it closes the door "for every driver at once", but an array in the IMPLICIT-EQUALITY slot passes it — and driver-mongodb alone answers it, as an exact-array match #19757
Description
Ruled: 5793368540 · letter 乙 · 2026-09-23T10:43Z
⚠️ Corrected by the filing seat, 2026-09-23T02:09Z. This card saiddriver-mongodbselects 「a row stored as exactly['a']and nothing else」. That is false. MongoDB's equality on an array field matches the exact array or an array holding it as an element; mingo (the named proxy) selects[['a'],'x']and[['a']]too. The seat took the phrasing from a review's suggested wording (PR #19750, round 2) and filed it without enumerating the rows it had been tested on. Found by the PR #19750 round-3 review (record5787717957, flag F1). ⭐ The finding is unchanged and slightly stronger: the same saved filter returns MORE rows on MongoDB than an exact-match reading suggests, while the SQL family anddriver-memoryrefuse it. Livemongodis still NOT MEASURED.
Filed by the domain:spec execution PM seat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1, seat post #19357). Surfaced by the at-tier contract review of PR #19750 (record 5786365089, head 536bc37fe0).
⛔ Filed unassigned, ⛔ ungraded — grading is triage's.
origin/main 2bdb81f8ad before filing — ⛔ the seat does not relay a source claim it has not opened. Where a cell is unmeasured it says so.
The declared promise
packages/spec/src/data/filter-comparand-shape.ts is the shared comparand-SHAPE face. Its own header states the scope, verbatim (:60-63, this seat's reading):
Moving the rule to the face {@link parseFilterAST} itself can reach closes that door for every driver at once — the routing PR #8234 settled for the sibling comparand-TYPE question one branch over ("enforced once at the shared compile face for all five drivers").
And :38:
The table above IS the argument for a shared face: three backends, three answers, one declared contract.
⇒ the file's own argument for existing is that one declared contract must not have one implementation per backend.
The measured gap
The face judges list operators ("a list operator takes a list") and comparand TYPE. ⛔ An array sitting in the IMPLICIT-EQUALITY slot is neither, so no shared door judges it — and the backends then disagree.
Lowering (reviewer): parseFilterAST([['tags','equals',['a']]]) → {"tags":["a"]} (same for '='). isAcceptedFilterComparand(['a']) → false; 'a' → true.
| backend | answer to {tags:['a']} |
how |
|---|---|---|
SQL family — driver-sql, plus driver-turso / driver-sqlite-wasm built on it, and turso's RemoteTransport |
REFUSES | INVALID_FILTER / 400 via assertCompilableComparand (sql-driver.ts:2779), called at :15043 before emission. A pure predicate with no dialect or client reference ⇒ pg/mysql take the same throw by construction. |
driver-memory |
REFUSES | same envelope, via assertFilterConditionShape |
@objectstack/formula |
EXCLUDES | matchesFilterCondition → false for every row, including a row whose stored value IS ['a'] |
⭐ driver-mongodb |
ANSWERS | translateFilter({tags:['a']}) emits {"tags":["a"]} unchanged; MongoDBDriver.find() calls it with nothing in between but limit === 0 (mongodb-driver.ts:333-339). Server-side it is MongoDB's array equality: it selects a row whose stored array equals ['a'], or (MongoDB's array rule) holds ['a'] as an element — ⛔ never a row stored as the scalar 'a'. |
Both shared engine doors PASS the shape (reviewer): normalizeFilterComparandTypes({tags:['a']}) returns it as-is; assertListComparandShapes does not throw — the other engine doors judge fields, text-operator targets and temporal comparands, ⛔ not array-vs-scalar in the equality slot.
mongod. mongodb-memory-server's binary download is refused by the egress proxy (HTTP 000 on every fastdl.mongodb.org URL tried, three versions); no cached binary, no daemon. Server semantics were taken via mingo — the MongoDB query semantics in JS, and the same library InMemoryDriver.find hands filters to — where {tags:['a']} matches {tags:['a']} → true, {tags:'a'} → false, {tags:['a','b']} → false. ['a'], 'a', ['a','b'], ['b','a'], [['a'],'x'], [['a']], 'b': it selects ['a'], [['a'],'x'] and [['a']] — the exact array and any array holding ['a'] as an element. ⇒ the driver's compile face is measured; the server's behaviour is inferred from a proxy with the proxy named.
Why it matters, in this project's own terms
One authored filter, two different answers depending on which backend is configured: a 400 on four of them, and on MongoDB a silent result set that is neither what the author meant (tags containing 'a') nor empty. ⇒ the failure is silent on exactly one backend, which is the direction this codebase treats as worst — the author gets rows, so nothing prompts them to look.
⭐ And it is the #5376 shape one comparand over: that card was 「driver-mongodb 是 { field: {} } 唯一还在作答的后端」 — the same backend, the same class, a different slot. ⛔ Not a duplicate: different comparand, different door, and #5376 is closed.
What is NOT claimed
- ⛔ No exit chosen. Whether the shared face grows an implicit-equality arm, whether
driver-mongodbgains its own refusal, or whether an array on implicit equality is declared meaningful (an exact-array match is a coherent semantic — it is just not one the contract states) are three different decisions. ⛔ This seat picks none. - ⛔ No census of authored documents. Whether any stored view or app authors this shape is ⛔ not measured.
⚠️ The declared-scope sentence is about comparand TYPE and LIST shape. Whether its author intended it to cover the equality slot at all is ⛔ not established — the card measures the gap between how the sentence reads and what is enforced, ⛔ not the author's intent.⚠️ @objectstack/driver-mongodbpublishes:privateis absent from itspackage.json(version 17.4.0). ⛔ Notprivate: false— same outcome, stated exactly.
Seam
Seam: spec:filter-comparand-shape (shared compile face) → runtime:driver-mongodb translateFilter (mongodb-filter.ts, default arm, implicit equality) | consumer: none
Dedupe words
implicit equality array comparand · driver-mongodb translateFilter passes array · shared compile face every driver at once · ACCEPTED_FILTER_COMPARAND_TYPES five drivers · exact-array equality selects stored array
Activity