pub struct AudienceGuard { /* private fields */ }Expand description
The whole guard: pure decision (is_readable) plus async resolution (AudienceIndex),
fail-closed throughout. One instance is built per request (in query.rs’s
register_lakehouse_functions) and shared, via Arc, across every arg-addressed UDTF/UDF the
request’s session registers.
Implementations§
Source§impl AudienceGuard
impl AudienceGuard
pub fn new( read_scope: ReadScope, lakehouse_admin: bool, public_view_sets: Vec<String>, index: Arc<AudienceIndex>, ) -> AudienceGuard
Sourcepub fn read_scope(&self) -> &ReadScope
pub fn read_scope(&self) -> &ReadScope
The caller’s scope. Exposed so callers with their own row-level filtering
(list_partitions) can decide up front whether to even attempt an optimization (e.g.
LIMIT pushdown) that’s only valid under ReadScope::All.
ReadScope::All ⇒ Ok with no I/O at all. Otherwise resolves id’s owning process’s
audience and denies with a uniform, existence-oracle-proof message
({fname}: '{id}' not found or not accessible) on anything but a readable verdict – a
resolution error included, never a pass. The real reason (resolved OwnerAudience, the
caller’s scope) is logged at debug!, for operators only.
Sourcepub async fn readable_ids(
&self,
ids: &[Uuid],
kind: IdKind,
) -> Result<HashSet<Uuid>, DataFusionError>
pub async fn readable_ids( &self, ids: &[Uuid], kind: IdKind, ) -> Result<HashSet<Uuid>, DataFusionError>
Batch form of the same rule, for the callers that row-filter (list_partitions) or need
an all-or-nothing verdict over a batch (get_payload) rather than a single witness.
ReadScope::All ⇒ every id is readable, with no I/O.
Sourcepub fn is_public_view_set(&self, view_set_name: &str) -> bool
pub fn is_public_view_set(&self, view_set_name: &str) -> bool
Whether view_set_name is on the MICROMEGAS_PUBLIC_VIEW_SETS allowlist – an operator
declaring every row of a view set readable by any authenticated caller. Shared by
Self::global_rows_visible and Self::authorize_view_instance’s rule (2) so the two
read the same allowlist through one accessor.
Sourcepub fn global_rows_visible(&self, view_set_name: &str) -> bool
pub fn global_rows_visible(&self, view_set_name: &str) -> bool
list_partitions’ 'global'-row rule: a global partition is a multi-audience
file – it has no single owning audience to check against the caller’s scope. Visible
under ReadScope::All, when view_set_name is on the public allowlist, or when the
caller passes the lakehouse admin gate (the same boolean that already governs the
mutating UDTFs/UDFs: a caller who can retire_partitions/regenerate_partitions a global
file can see it – no new authority, no new knob).
The view_instance(view_set_name, view_instance_id) scan-time check, run by
MaterializedView::scan before jit_update – so a caller scoped to one audience cannot
trigger JIT materialization of an instance it cannot read.
Rules, in order:
ReadScope::All->Ok(()), no I/O. Internal, maintenance,--disable-auth, and every inner session built from anAuthorized::internal_caller()take this arm.view_set_nameonpublic_view_sets->Ok(()). Matches the row-level filter: an operator who declared a view set public has said every row of it is readable, so denying materialization of one of its instances would be incoherent. Confidentiality-only: this leaves the cost/availability residual this method exists to close fully open for any view set an operator puts on the allowlist – any authenticated caller can still forcejit_updatefor arbitrary process/stream ids of a public view set. Deliberate.view_instance_id == "global"->Ok(()). Global instances are row-filtered, not call-guarded:jit_updateis a no-op for every'global'instance today (LogView/MetricsView, the only two view sets that accept'global'), so there is no materialization to protect against, and denying the call would break the legalview_instance('log_entries', 'global')spelling ofSELECT * FROM log_entriesfor no security gain – the row-level filter already filters its rows one at a time. This is a different rule fromlist_partitions’global_rows_visible, which gates visibility of partition metadata about a'global'file with no per-row filter available; reusing it here would deny thelog_entries/measures'global'instances to every non-admin scoped caller, a regression. The invariant that makes this rule sound –'global'never triggers JIT – lives in each view set’sjit_updateimpl; a future view set whose'global'instance does materialize would need to revisit this rule.view_instance_idparses as aUuid->Self::authorizeunderIdKind::ProcessOrStream, discarding the returnedAuthorized. The witness exists to gate construction of an inner unscoped session; this call site builds none –jit_update’sCallerContext::internal()is unchanged and stays where it is.- anything else -> the same uniform denial as (4). Fail-closed, matching
list_partitions’s “anything else is dropped” rule. Unreachable for today’s view sets (everymake_vieweither accepts'global'orUuid::parse_strs, failing at plan time otherwise), so this is a safety net against a future view set with a different id vocabulary.
Trait Implementations§
Auto Trait Implementations§
impl !RefUnwindSafe for AudienceGuard
impl !UnwindSafe for AudienceGuard
impl Freeze for AudienceGuard
impl Send for AudienceGuard
impl Sync for AudienceGuard
impl Unpin for AudienceGuard
impl UnsafeUnpin for AudienceGuard
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
§impl<T> FutureExt for T
impl<T> FutureExt for T
§fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
§fn with_current_context(self) -> WithContext<Self> ⓘ
fn with_current_context(self) -> WithContext<Self> ⓘ
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request§impl<L> LayerExt<L> for L
impl<L> LayerExt<L> for L
§fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
Layered].