pub enum ActScope {
None,
All,
Contexts(Vec<String>),
}Expand description
A DID’s authority to act — the contexts in which it may make a change.
The sibling axis to ApproveScope, with deliberately identical variants,
an identical covers predicate, and the same
fail-closed None default.
§Why this exists
Unlike ApproveScope, this is not a stored or wire field. The act
axis is stored as (role, allowed_contexts), where an empty
allowed_contexts means opposite things depending on the role: unrestricted
for an admin (that is how a super-admin is spelled), and nothing at all
for every other role. Reading the raw field without the role is therefore a
bug, and has repeatedly been one — a display that called a least-privilege
approver (unrestricted), two acl list --context filters that disagreed
on whether an empty list matches every context or none, and a vault scope
gate that granted cross-context reads to an entry authorized nowhere.
This type makes the three cases distinguishable so that decode happens in
one place instead of at every call site. The decode itself is server-side
(vti_common::acl::act_scope_for), because it needs Role; only the shape
and the predicate are shared, exactly as for ApproveScope.
It lives beside ApproveScope so the two axes — what a DID may do and
what it may confer — read as one model rather than an enum and a
convention.
Variants§
None
Authorized in no context at all (the fail-closed default). The shape of
a least-privilege approver: acts nowhere, may still confer via its
ApproveScope.
All
Authorized in every context. Combined with the admin role this is a super-admin.
Contexts(Vec<String>)
Authorized in these contexts and their subtrees, and only these.
Implementations§
Source§impl ActScope
impl ActScope
Sourcepub fn covers(&self, context_id: &str) -> bool
pub fn covers(&self, context_id: &str) -> bool
Whether a holder of this scope may act in context_id.
Segment-aware ancestry, identical to ApproveScope::covers, so
authority over a parent context covers its whole subtree.
Sourcepub fn acts_within(&self, context_id: &str) -> bool
pub fn acts_within(&self, context_id: &str) -> bool
Whether this scope names a context at or beneath context_id — the
mirror of covers, with the ancestry test’s
arguments swapped.
covers answers “may this entry act in the
context?”; this answers “does this entry hold a grant inside the
context’s subtree?”. They are different questions and a caller sweeping
a subtree — to revoke it, or to audit it — wants this one: a grant at
acme/eng/team-a is invisible to covers("acme/eng") because it holds
no authority over acme/eng, yet it is precisely what the sweep exists
to find.
Two deliberate edges:
Allis not a match. An unrestricted entry names no context, so it is not a grant of this subtree — it is authority everywhere, whichcoversalready reports. A subtree sweep that returned it would invite a caller revoking a compromised branch to delete its own super-admin. AskContextDirection::Anyfor “everyone whose authority touches this subtree”, which includes it.- A
Contextsscope matches if any named context is inside the subtree, even when it also names contexts outside it. Such an entry does hold a grant in the subtree, so omitting it would under-report; whether to delete the entry or narrow its scope is then the caller’s decision, made with the entry in hand.
Sourcepub fn matches_context(
&self,
context_id: &str,
direction: ContextDirection,
) -> bool
pub fn matches_context( &self, context_id: &str, direction: ContextDirection, ) -> bool
Whether this scope matches context_id when read in direction — the
single predicate behind every context-filtered ACL listing.
Sourcepub fn is_unrestricted(&self) -> bool
pub fn is_unrestricted(&self) -> bool
Whether this scope authorizes every context (the super-admin condition when paired with the admin role).
Sourcepub fn acts_nowhere(&self) -> bool
pub fn acts_nowhere(&self) -> bool
Whether this scope authorizes nothing.
Sourcepub fn named_contexts(&self) -> &[String]
pub fn named_contexts(&self) -> &[String]
Trait Implementations§
Source§impl Display for ActScope
impl Display for ActScope
Source§fn fmt(&self, f: &mut Formatter<'_>) -> Result
fn fmt(&self, f: &mut Formatter<'_>) -> Result
Operator-facing rendering. The unrestricted and acts-nowhere cases are
spelled out rather than both collapsing to (unrestricted), which is
what made them indistinguishable on ACL displays. The wording matches
what vta-cli-common’s format_contexts already prints.