Filing gate: ① a product defect with a measured reach:. Finding class (a).
reach: the public door POST /api/v1/analytics/query, on a query the ObjectQL strategy serves (a date-bucketed query, or a host with no raw SQL). #20887's dev measured it at 5bb764181 (PR #20916's branch, report 5916988260 on #20887, out_of_scope_findings[1]). The readings are the dev's, and this seat did not re-run them.
Filed by the domain:services execution seat (#6021, session_01XY5uCwTjZj7884yYtyur4H) from #20887's dev report. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.
What happens
On a fixture with owners, a multiple lookup:
- The ObjectQL strategy refuses:
where: { $not: { owners: { $contains: 'u1' } } } answers 400 INVALID_FILTER ("Operator $ne on field owners WAS NOT APPLIED ... JSON TEXT column").
- The engine answers:
engine.find answers d2, d4 for the same filter.
- The native strategy answers: b, d.
Mechanism, as the dev read it:
- The analytics
where door adds a NULL-safe guard under $not, { owners: { $null: false } }, and it becomes a set leaf.
ObjectQLStrategy.convertFilter (packages/services/service-analytics/src/strategies/objectql-strategy.ts) hands that leaf to the engine as { $ne: null }.
driver-sql refuses $ne over a multi-valued JSON column.
PR #20916 routes the nested-relation form around the guard (shieldNestedRelations). A direct operator on a multi-valued column still meets it.
Scope for whoever takes it (⛔ not a ruling)
Reader who acts
Triage (grade and route; the files are domain:services' service-analytics), then the owning seat.
Dedupe
mcp__github__search_issues, repo-scoped, open and closed, in the act that filed this card:
Dedupe words: analytics $not multiple lookup refused · convertFilter $ne null JSON column · analytics NULL guard multi-valued
Generated by Claude Code
Filing gate: ① a product defect with a measured
reach:. Finding class (a).reach:the public doorPOST /api/v1/analytics/query, on a query the ObjectQL strategy serves (a date-bucketed query, or a host with no raw SQL). #20887's dev measured it at5bb764181(PR #20916's branch, report5916988260on #20887,out_of_scope_findings[1]). The readings are the dev's, and this seat did not re-run them.Filed by the
domain:servicesexecution seat (#6021,session_01XY5uCwTjZj7884yYtyur4H) from #20887's dev report. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.What happens
On a fixture with
owners, a multiple lookup:where: { $not: { owners: { $contains: 'u1' } } }answers400 INVALID_FILTER("Operator $ne on field owners WAS NOT APPLIED ... JSON TEXT column").engine.findanswers d2, d4 for the same filter.Mechanism, as the dev read it:
wheredoor adds a NULL-safe guard under$not,{ owners: { $null: false } }, and it becomes a set leaf.ObjectQLStrategy.convertFilter(packages/services/service-analytics/src/strategies/objectql-strategy.ts) hands that leaf to the engine as{ $ne: null }.driver-sqlrefuses$neover a multi-valued JSON column.PR #20916 routes the nested-relation form around the guard (
shieldNestedRelations). A direct operator on a multi-valued column still meets it.Scope for whoever takes it (⛔ not a ruling)
$notover a multi-valued column. The guard reaches the engine in a formdriver-sqlapplies, or the strategy does not add a guard the engine already carries. ⛔ No driver change to accept$ne: nullon a JSON column as a special case.$notover$containson a multiple lookup answers the engine's rows on both strategies, plus a single-valued control.domain:services): the cube read and the analytics read scope answer{ relation: { field: value } }as the engine seam now serves it — as the caller, capped, one answer on every face #20887, in flight) editsfilter-normalizer.tsandobjectql-strategy.ts. This card is dispatched after it lands.Reader who acts
Triage (grade and route; the files are
domain:services'service-analytics), then the owning seat.Dedupe
mcp__github__search_issues, repo-scoped, open and closed, in the act that filed this card:filterwith$containson a multiple lookup counts 0 on every driver while the samewherefinds the rows: the engine's aggregation evaluator never matches a stored array #20873 (open) is the per-aggregationfilter's$containson a multiple lookup counting 0 in the engine's aggregation evaluator: a neighbour at another position.multiple: true(JSON array) column silently answers wrong —$in/$eqalways zero rows,$ninreturns the rows it was asked to EXCLUDE #7398, driver-sql (PG): every DELETE of an object targeted by amultiple: truereference 500s — the cascade probe's$containscompiles toLIKEagainst ajsoncolumn (42883) #18172, analytics: read-scope-sql's ruled $not-over-$in-empty residue has no open card — and #13640 turned it into an echo-vs-execution disagreement on the ObjectQL strategy #13926 andObjectQLStrategy.executecannot see a cross-object filter nested in a conjunct, so it accepts a set/analytics/sqlrejects #10759 are closed, at other positions.$notguard.Dedupe words:
analytics $not multiple lookup refused·convertFilter $ne null JSON column·analytics NULL guard multi-valuedGenerated by Claude Code