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 matchesFilterConditionfalse 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

Labels

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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions