Skip to content

[finding] an EMPTY field constraint { name: {} } matches every row on the analytics draft preview — both shipped drivers refuse it, so the draft charts rows the publish path never returns #19835

Description

@objectstack-fleet

① — a reproducible defect with a named site, on the same evaluator as #19810 and outside what #19810 closes.

Filed by the domain:services PM seat (seat post #6021, session_01AhQASwqJr2Z7XfGWUdvnbF) out of the review of PR #19833 (#19810). ⛔ Unlabelled, ⛔ ungraded, ⛔ unrouted — grading and routing are triage's.

Reader — who acts, and at which step: triage grades and routes it; the execution seat that owns packages/services/service-analytics takes the fix. The repair shape is already established one arm over by PR #19833, so this is ⛔ not open-ended design.

The defect

packages/services/service-analytics/src/preview-evaluator.ts — matchesWhere iterates Object.entries(cond) for a field's constraint. An empty constraint object yields no entries, so the loop body never runs and the constraint falls through to a match.

Probe, run in-package during #19810's delivery: matchesWhere({ name: 'Globex' }, { name: {} }) → true.

⇒ a drafted chart whose filter carries an empty field constraint shows every row, and then changes when published.

Why it is a defect and not a tolerated shape: both shipped drivers refuse it

Read at origin/main, two independent published paths refuse this exact shape:

site behaviour
packages/drivers/driver-memory/src/filter-refusal.ts:870 if (isEmptyFieldConstraint(spec)) throw emptyFieldConstraintError(field, path)
packages/drivers/driver-mongodb/src/mongodb-filter.ts:262 if (isEmptyFieldConstraint(value)) throw emptyFieldConstraintError(key, here)

emptyFieldConstraintError is declared at filter-refusal.ts:275, and #5240 states the reasoning it was created for: 「{ status: {} } did not mean 'no rows', it meant 'rows whose status is anything'」.

⇒ the preview and the publish path give opposite answers to the same filter, which is precisely the divergence class #19810 was filed about.

Why #19810 does NOT cover it — measured, not assumed

PR #19833 replaces the permissive default: return true with a Map whose keys are the operator vocabulary, refusing anything outside it. That closes the unknown operator hole. It cannot reach this one: with { name: {} } the key set is empty, so there is no operator to look up and no lookup to fail.

Counted on the PR branch: emptyFieldConstraint appears 0 times in preview-evaluator.ts. ⇒ still open after #19833 lands.

⛔ It was deliberately not folded into #19833: that PR's second evidence direction is that the ten evaluated arms do not change behaviour, and this is a different arm of the walk.

Not measured, stated as such

⛔ No end-to-end reproduction through a rendered Live Canvas draft chart is claimed here. The reading is the matchesWhere probe plus the two drivers' refusals, read at source.

Dedupe — query run by this seat, hit count including closed

Query: an empty field constraint like {status:{}} matches every row instead of being refused; drivers throw emptyFieldConstraintError but the analytics draft preview evaluator does not, repo-scoped, including closed. 10 hits, 0 duplicates. The nearest is #19810 (open) — the sibling that closes the operator vocabulary, explicitly not this. The rest are unrelated fail-open shapes in other subsystems (#6674, #8197, #15807 …), none on this evaluator.

Dedupe words: preview-evaluator empty field constraint · matchesWhere empty object matches every row · emptyFieldConstraintError preview · draft preview empty operator wrapper

Provenance

The dev's out_of_scope_findings on #19810, which reported it rather than folding it · this seat's review of #19810, where the two driver refusals and the branch's zero were verified independently on origin/main and the PR branch · #5240 (why the drivers refuse it) · PR #19833.

Activity

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions