You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
analytics: a non-RLS getReadScope scope bypasses read-scope-sql on the ObjectQL engine path — driver-sql lowers $nin: [] to constant TRUE (whole table), so a lowering-site refusal cannot guard this route #13640
Filed unassigned by the #13571 dev while measuring that card's PM mechanism assumption 1 ("check who actually calls this compiler"). Recording only — severity and routing are triage's. This finding is decision-material for #13571 but does not block it and is not resolved by it.
What was measured, on eb64351
ObjectQLStrategy merges StrategyContext.getReadScope output into the FilterCondition it hands the engine (packages/services/service-analytics/src/strategies/objectql-strategy.ts, the ctx.getReadScope(objectName) merge near the userFilter return, ~:601-602). On that execution path the scope never reaches compileScopedFilterToSql — read-scope-sql compiles the scope only on the NativeSQL path (applyReadScope) and for the /analytics/sql echo (generateSql).
driver-sql lowers $nin: [] via whereNotIn(field, []) wrapped null-safe (packages/drivers/driver-sql/src/sql-driver.ts, the $nin case near :13314) — constant TRUE. Live in-repo pin of the semantics: packages/services/service-analytics/src/__tests__/filter-normalizer-not-null-safe.test.ts:534 (stage: { $nin: [] } admits ALL rows on a real backend).
Identical protection profile to #13571's: in-repo the only scope producer is the RLS compiler, and since PR #13570 its polarity-aware guard drops both shapes before they are emitted; the CEL lowering never emits $nin at all. The vacancy is the same as #13571's, one strategy over: no mechanical guard stands between a spec-contract producer and the engine lowering.
Related
#13571 (the lowering-site card — whatever disposition it lands covers the NativeSQL path + echo only) · #13552 / PR #13570 (the producer-side polarity guard) · #3597 (closed — ObjectQLStrategy not consuming getReadScope at all; this is the residue on the consuming side) · ADR-0021 (read-scope contract)
Filed unassigned by the #13571 dev while measuring that card's PM mechanism assumption 1 ("check who actually calls this compiler"). Recording only — severity and routing are triage's. This finding is decision-material for #13571 but does not block it and is not resolved by it.
What was measured, on
eb64351ObjectQLStrategymergesStrategyContext.getReadScopeoutput into theFilterConditionit hands the engine (packages/services/service-analytics/src/strategies/objectql-strategy.ts, thectx.getReadScope(objectName)merge near theuserFilterreturn, ~:601-602). On that execution path the scope never reachescompileScopedFilterToSql— read-scope-sql compiles the scope only on the NativeSQL path (applyReadScope) and for the/analytics/sqlecho (generateSql).driver-sqllowers$nin: []viawhereNotIn(field, [])wrapped null-safe (packages/drivers/driver-sql/src/sql-driver.ts, the$nincase near :13314) — constant TRUE. Live in-repo pin of the semantics:packages/services/service-analytics/src/__tests__/filter-normalizer-not-null-safe.test.ts:534(stage: { $nin: [] }admits ALL rows on a real backend).getReadScopeprovider (StrategyContext.getReadScopeis a spec contract —packages/spec/src/contracts/analytics-service.ts~:385 carries a hand-written example) handing{ f: { $nin: [] } }or{ $not: { f: { $in: [] } } }gets the whole table on any query the ObjectQL strategy serves, regardless of what read-scope-sql's emptied-membership folds are polarity-dependent at the lowering site itself:$in: []folds to1 = 0one arm from$not, and$nin: []folds to1 = 1(constant TRUE) #13571 ships in read-scope-sql — a compile refusal there can only ever guard the NativeSQL path and the echo.What keeps it from biting today
Identical protection profile to #13571's: in-repo the only scope producer is the RLS compiler, and since PR #13570 its polarity-aware guard drops both shapes before they are emitted; the CEL lowering never emits
$ninat all. The vacancy is the same as #13571's, one strategy over: no mechanical guard stands between a spec-contract producer and the engine lowering.Related
#13571 (the lowering-site card — whatever disposition it lands covers the NativeSQL path + echo only) · #13552 / PR #13570 (the producer-side polarity guard) · #3597 (closed —
ObjectQLStrategynot consuminggetReadScopeat all; this is the residue on the consuming side) · ADR-0021 (read-scope contract)