dvUnscopedTablesIn function
The scoped tables a statement names without scoping by tenant.
Generated model queries carry the predicate. Everything else does not: a report, a dashboard count, a join the generator cannot express, a query written before the model was scoped. Each returns rows, the numbers look plausible, and one tenant is shown another tenant's data.
Deliberately coarse. It knows which tables are scoped because the generator registered them, and it looks for the column in the statement. A false positive is a refusal somebody reads and fixes; a false negative leaves today's behaviour exactly as it is. What it must never do is guess quietly in the direction of allowing.
Only under DVTenantIsolation.sharedDatabase. Under the other two the separation is the schema or the connection, and a predicate on a column that is not there would fail every query.
Implementation
List<String> dvUnscopedTablesIn(String sql) {
if (const DVTenants().isolation != DVTenantIsolation.sharedDatabase) {
return const <String>[];
}
if (_scopedTables.isEmpty) return const <String>[];
final String lower = sql.toLowerCase();
if (lower.contains(dvTenantColumnName)) return const <String>[];
return <String>[
for (final String table in _scopedTables)
// On a word boundary: "orders" inside "workorders" is a different
// table, and refusing it would teach people to reach for the escape
// hatch out of habit.
if (RegExp('(?<![A-Za-z0-9_])${RegExp.escape(table.toLowerCase())}'
'(?![A-Za-z0-9_])')
.hasMatch(lower))
table,
];
}