Skip to content

finding: ObjectQL test doubles ignore limit, so a limit regression is invisible to every suite that uses one #10978

Description

@os-elon

Filed from #10825 (batching resolveUserAuthzGrants); not fixed there — out of that card's scope.

The observation

The in-memory ql doubles used across the suite match where and return rows, but
drop opts.limit on the floor. The one in
packages/core/src/security/resolve-authz-context.test.ts is representative:

functionmakeQl(tables: Record<string,any[]>){return{asyncfind(object: string,opts: any){constrows=tables[object]??[];constwhere=opts?.where??{};returnrows.filter((r)=>/* … where matching … */);// opts.limit never read},};}

A double that ignores limit cannot distinguish a read bounded at 200 from the same
read bounded at 1000, or from one with no bound at all. Any change to a limit —
raising it, lowering it, or merging two reads that carry different ones — is
therefore green by construction in every test that uses such a double, and the
symptom in production is a silently truncated result set, not an error.

This is the same failure shape as #7620 (doubles that short-circuited $or and
dropped sibling filters), which produced the check:where-matcher gate. That gate
polices combinator-blindness. Nothing polices limit-blindness.

How it surfaced

resolveUserAuthzGrants issues two sys_member reads — {user_id} at limit 200 and
{organization_id} at limit 1000 — and the obvious "same object, fold them" cleanup
truncates the fellow-org peer list (org_user_ids, an RLS input) at 200 for any
organization with more members. Under the existing double that cleanup passes every
test in the file. #10825 had to build a limit-honouring probe of its own to make the
divergence observable, which is a reasonable thing for one card to do once and an
unreasonable thing for every card to rediscover.

Not asserted here

Whether any test in the tree is currently vacuous because of this — that is the
measurement the work would start with, and it may well be zero today. The claim is
only that the class is unobservable, which is what #7620 established is worth
closing rather than trusting.

Possible directions (not a decision)

  • Teach the shared doubles to honour limit (a one-line slice), and let whatever
    breaks be the measurement.
  • Or a gate in the check:where-matcher family that fails a double whose find
    never reads opts.limit, against a shrink-only baseline.

Either way it is a testing-instrument card, not a runtime one: no shipped behaviour
is wrong, the ability to notice it going wrong is missing.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions