Skip to content

[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

@objectstack-fleet

Ruled: 5793368540 · letter 乙 · 2026-09-23T10:43Z

⚠️ Corrected by the filing seat, 2026-09-23T02:09Z. This card said driver-mongodb selects 「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 (record 5787717957, 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 and driver-memory refuse it. Live mongod is 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.

⚠️ Provenance, split on purpose. The runtime readings (what each backend does with the shape) are the reviewer's, taken in a detached worktree at that head. The source readings below are this seat's own, re-taken on 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. ⚠️ live pg / mysql cells NOT MEASURED (no URL, no daemon, no docker)
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'. and nothing else ⚠️ corrected, see the note at the top

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.

⚠️ NOT MEASURED: a live 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. ⚠️ That row set had no nested array, so it could not test "nothing else". Re-taken by this seat with mingo 7.2.4 over ['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-mongodb gains 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-mongodb publishes: private is absent from its package.json (version 17.4.0). ⛔ Not private: 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:apiThe API a customer can call, and integrations — REST, connectors, webhooks, jobsdomain:specpriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions