QA-source: #21330 · api-backend.filter-comparand-conformance · outside the item's clauses (found while driving it)
What fails
A boolean field compared with a string comparand is neither refused nor narrowed: the engine compares text against the stored 1/0 and answers 200 with the wrong rows. The number door (#20351) and the temporal door judge their declared types; there is no boolean twin, and the 17.6.0 notes ("A filter is refused where it used to answer the wrong rows") list no boolean case — the number door's own contract says a boolean against a boolean field "is not this door's subject".
Reproduction (stock showcase on 17.6.0 617f25f8, admin; showcase_field_zoo has 2 rows, one f_boolean=true, one false)
All POST /api/v1/data/showcase_field_zoo/query:
where |
status |
rows |
correct answer |
{"f_boolean":"true"} |
200 |
0 |
1 (or a 400) |
{"f_boolean":{"$eq":"true"}} |
200 |
0 |
1 (or a 400) |
{"f_boolean":{"$in":["true"]}} |
200 |
0 |
1 (or a 400) |
{"f_boolean":{"$ne":"true"}} |
200 |
2 — includes the true row |
1 (or a 400) |
{"f_boolean":"false"} |
200 |
0 |
1 (or a 400) |
{"f_boolean":"yes"} |
200 |
0 |
a 400 |
controls true, 1, "1" |
200 |
1 |
— |
control false |
200 |
1 |
— |
Other doors give the same wrong answers:
GET /api/v1/data/showcase_field_zoo?filter={"f_boolean":"true"}, ?$filter=…, ?filter=[["f_boolean","=","true"]] → 0 rows each.
- Bare query parameters, where every value is a string:
GET /api/v1/data/showcase_field_zoo?f_boolean=true → 0 rows, ?f_boolean=false → 0 rows; only ?f_boolean=1 / 0 work.
- Aggregate:
{"where":{"f_boolean":"true"},"aggregations":[{"function":"count","alias":"n"}]} → {n:0}.
Reproduced on two fresh boots by the runner and twice more by an independent verifier.
Expected
Either refuse a non-boolean comparand on a boolean field (400 INVALID_FILTER, as the number door does for numbers), or narrow "true"/"false" to booleans at a declared-type door — never a silent wrong answer. The $ne cell (returns the row it should exclude) and the bare ?f=true GET door are the most harmful.
Where
objectstack — a boolean twin of packages/objectql/src/number-comparand-declared-type-door.ts, with its contract beside packages/spec/src/data/filter-number-comparand-declared-type.ts. Severity (verifier): major — wrong data, no error. Not a 17.6.0 regression.
Full run evidence: #21330.
Generated by Claude Code
QA-source: #21330 · api-backend.filter-comparand-conformance · outside the item's clauses (found while driving it)
What fails
A boolean field compared with a string comparand is neither refused nor narrowed: the engine compares text against the stored 1/0 and answers 200 with the wrong rows. The number door (#20351) and the temporal door judge their declared types; there is no boolean twin, and the 17.6.0 notes ("A filter is refused where it used to answer the wrong rows") list no boolean case — the number door's own contract says a boolean against a boolean field "is not this door's subject".
Reproduction (stock showcase on 17.6.0
617f25f8, admin;showcase_field_zoohas 2 rows, onef_boolean=true, onefalse)All
POST /api/v1/data/showcase_field_zoo/query:where{"f_boolean":"true"}{"f_boolean":{"$eq":"true"}}{"f_boolean":{"$in":["true"]}}{"f_boolean":{"$ne":"true"}}{"f_boolean":"false"}{"f_boolean":"yes"}true,1,"1"falseOther doors give the same wrong answers:
GET /api/v1/data/showcase_field_zoo?filter={"f_boolean":"true"},?$filter=…,?filter=[["f_boolean","=","true"]]→ 0 rows each.GET /api/v1/data/showcase_field_zoo?f_boolean=true→ 0 rows,?f_boolean=false→ 0 rows; only?f_boolean=1/0work.{"where":{"f_boolean":"true"},"aggregations":[{"function":"count","alias":"n"}]}→{n:0}.Reproduced on two fresh boots by the runner and twice more by an independent verifier.
Expected
Either refuse a non-boolean comparand on a boolean field (
400 INVALID_FILTER, as the number door does for numbers), or narrow"true"/"false"to booleans at a declared-type door — never a silent wrong answer. The$necell (returns the row it should exclude) and the bare?f=trueGET door are the most harmful.Where
objectstack— a boolean twin ofpackages/objectql/src/number-comparand-declared-type-door.ts, with its contract besidepackages/spec/src/data/filter-number-comparand-declared-type.ts. Severity (verifier): major — wrong data, no error. Not a 17.6.0 regression.Full run evidence: #21330.
Generated by Claude Code