Skip to content

Commit b0d7d54

Browse files
claude[bot]claude
andauthored
fix(analytics): refuse a non-binding read scope before the ObjectQL engine (#13924)
* wip: objectql read-scope vacancy guard * fix(analytics): refuse a non-binding read scope before the ObjectQL engine ObjectQLStrategy merges StrategyContext.getReadScope output straight into the FilterCondition it hands engine.aggregate, so the scope never reaches compileScopedFilterToSql — the empty-$nin refusal that compiler carries guards the NativeSQL path and the /analytics/sql echo only. Measured against a real engine (driver-sqlite-wasm over driver-sql), a non-RLS scope provider handing an emptied membership that is constant TRUE in effective polarity received the whole table on any query this strategy served. assertReadScopeCannotVacate is exported from read-scope-sql.ts, next to the compiler whose disposition it matches, and called at both engine-bound merges: withReadScope and resolveFkAttr. The ruled $in: [] reduction is untouched, so the live RLS composite still admits exactly the own rows, and neither other route moves. --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 11a64cd commit b0d7d54

4 files changed

Lines changed: 629 additions & 1 deletion

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@objectstack/service-analytics': patch
3+
---
4+
5+
`ObjectQLStrategy` now refuses a read scope that does not bind, before handing it to the engine (`READ_SCOPE_COMPILE_FAILED` / 500). That strategy merges `StrategyContext.getReadScope` output straight into the `FilterCondition` it gives `engine.aggregate` and never reaches `compileScopedFilterToSql`, so the empty-`$nin` refusal that compiler gained guarded the NativeSQL path and the `/analytics/sql` echo only. Measured against a real engine, a non-RLS scope provider handing `{ f: { $nin: [] } }`, `{ $not: { f: { $in: [] } } }`, `{ $not: { f: [] } }` or `{ $not: { f: { $in: [], $ne: 'x' } } }` received the WHOLE TABLE on any query this strategy served; all four are now refused, at both engine-bound merges (the aggregate filter and the FK→attribute resolution). Deliberately unchanged: `$in: []` keeps its ruled constant-FALSE fold, so the RLS compiler's live composite — an emptied membership `$or`-ed beside an own-rows grant — still admits exactly the own rows; and the NativeSQL path and the SQL echo keep the disposition they already had.

0 commit comments

Comments
 (0)