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.
Filed from #10825 (batching
resolveUserAuthzGrants); not fixed there — out of that card's scope.The observation
The in-memory
qldoubles used across the suite matchwhereand return rows, butdrop
opts.limiton the floor. The one inpackages/core/src/security/resolve-authz-context.test.tsis representative:A double that ignores
limitcannot distinguish a read bounded at 200 from the sameread 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
$oranddropped sibling filters), which produced the
check:where-matchergate. That gatepolices combinator-blindness. Nothing polices limit-blindness.
How it surfaced
resolveUserAuthzGrantsissues twosys_memberreads —{user_id}at limit 200 and{organization_id}at limit 1000 — and the obvious "same object, fold them" cleanuptruncates the fellow-org peer list (
org_user_ids, an RLS input) at 200 for anyorganization 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)
limit(a one-lineslice), and let whateverbreaks be the measurement.
check:where-matcherfamily that fails a double whosefindnever 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.