Measured while implementing the observability half of #13639 (PR #13942), which repaired the same shape one seam over. Filed unassigned; no severity asserted, routing is triage's.
Measured, at 577e49e00
compileCelToFilter returns a discriminated result — { ok: false, reason, detail } — where detail names the concrete fault: the CEL shape that would not lower, the current_user.* path that did not resolve, the parse bound that was overrun. celToFilter in the sharing seeder collapses the whole thing to null:
// packages/plugins/plugin-sharing/src/bootstrap-declared-sharing-rules.ts:131exportfunctioncelToFilter(cel: unknown): Record<string,unknown>|null{constresult=compileCelToFilter(celasstring|{source?: string},{variables: {}});returnresult.ok ? (result.filterasRecord<string,unknown>) : null;}Its one caller then logs the fact without the reason:
// same file, ~line 202logger?.warn?.('[sharing-rule] skipped (missing or untranslatable CEL condition — never seeded as match-all) [experimental]',{rule: r.name,condition: r.condition});So an operator whose declared sharing rule is silently not granting learns that the condition did not translate, and gets the source text back, but not which part of it the compiler refused or why — the one fact that ends the search, computed and discarded one line earlier.
The !ok consumer census this came from
Every non-test call site of the compile-result family (compileCelToFilter, isPushdownableCel, lowerCelAst), excluding dist/, comments and the defining module:
| call site | reads reason | reads detail |
|---|
packages/plugins/plugin-security/src/rls-compiler.ts | ✅ (PR #13942) | ✅ (PR #13942) |
packages/plugins/plugin-sharing/src/bootstrap-declared-sharing-rules.ts:132 | ❌ | ❌ |
packages/formula/src/rls-predicate.ts:59 (isSupportedRlsExpression) | ❌ | ❌ |
packages/lint/scripts/check-doc-formula-expressions.mjs:962 | ✅ | ❌ |
packages/lint/src/validate-rls-predicate-enforceability.ts:283 | ✅ | ✅ |
packages/lint/src/validate-sharing-rule-enforceability.ts:438 | ✅ | ✅ |
Reverse control: the last two rows are what makes the zeroes readable — the same scan that reports celToFilter as discarding finds two consumers that carry detail into user-facing text, so "discards" is a reading, not a blind spot.
Why this is materially LESS severe than #13639, and what is left open
⛔ Not established here: whether any deployment has actually been bitten, and whether the seeder's WARN should carry reason, detail, or both. What is measured is that the information exists at the call site and is dropped.
Related
#13639 / PR #13942 (the same shape in plugin-security/rls-compiler.ts, repaired) · ADR-0058 D1 (compileCelToFilter is the one canonical lowering) · ADR-0049 (an unlowerable condition is never seeded as a permissive match-all — that half is correct and unchanged)
Generated by Claude Code
Measured while implementing the observability half of #13639 (PR #13942), which repaired the same shape one seam over. Filed unassigned; no severity asserted, routing is triage's.
Measured, at
577e49e00compileCelToFilterreturns a discriminated result —{ ok: false, reason, detail }— wheredetailnames the concrete fault: the CEL shape that would not lower, thecurrent_user.*path that did not resolve, the parse bound that was overrun.celToFilterin the sharing seeder collapses the whole thing tonull:Its one caller then logs the fact without the reason:
So an operator whose declared sharing rule is silently not granting learns that the condition did not translate, and gets the source text back, but not which part of it the compiler refused or why — the one fact that ends the search, computed and discarded one line earlier.
The
!okconsumer census this came fromEvery non-test call site of the compile-result family (
compileCelToFilter,isPushdownableCel,lowerCelAst), excludingdist/, comments and the defining module:reasondetailpackages/plugins/plugin-security/src/rls-compiler.tspackages/plugins/plugin-sharing/src/bootstrap-declared-sharing-rules.ts:132packages/formula/src/rls-predicate.ts:59(isSupportedRlsExpression)packages/lint/scripts/check-doc-formula-expressions.mjs:962packages/lint/src/validate-rls-predicate-enforceability.ts:283packages/lint/src/validate-sharing-rule-enforceability.ts:438Reverse control: the last two rows are what makes the zeroes readable — the same scan that reports
celToFilteras discarding finds two consumers that carrydetailinto user-facing text, so "discards" is a reading, not a blind spot.Why this is materially LESS severe than #13639, and what is left open
explainreports it asnarrowsrather thandenies— the operator debugging "this user sees no rows" gets no signal #13639's seam ran on every read.isSupportedRlsExpressionreturningbooleanis its published contract, not a defect: it is a shape gate, and both of its own consumers re-derive the explanation fromisPushdownableCelwhen they need one.⛔ Not established here: whether any deployment has actually been bitten, and whether the seeder's WARN should carry
reason,detail, or both. What is measured is that the information exists at the call site and is dropped.Related
#13639 / PR #13942 (the same shape in
plugin-security/rls-compiler.ts, repaired) · ADR-0058 D1 (compileCelToFilteris the one canonical lowering) · ADR-0049 (an unlowerable condition is never seeded as a permissive match-all — that half is correct and unchanged)Generated by Claude Code