pub enum HaltScope {
Tenant,
Agent {
name: String,
},
Revision {
digest: Digest,
},
Subject {
id: String,
},
}Expand description
What an emergency stop covers.
A plane hosts many agents, and agent 12 of 28 is misbehaving at three in the morning is the ordinary incident — a switch that can only stop all 28 is not an emergency stop for it. So a halt names its scope. Every standing halt is checked together and a run is refused if any matches, so a broad stop and a narrow one coexist and lifting the narrow one leaves the broad one standing.
Revision names exact reviewed bytes, so a fix published
as a new version runs while the broken revision stays stopped — prefer it
when a deploy is the incident. Agent covers every revision
of a declared name. Tenant is the power switch.
Subject is keyed on the other axis, and it is the one
to reach for when the incident is not the workload but the authority: a
credential somebody has withdrawn, a service account that turned out to be
shared, a person who has left. The three scopes above ask what is running;
this one asks who it is running for: any principal on the delegation chain
bound at admission and carried on every run’s IdentityBound record — the
person at its root, each workload it was delegated through, and the one
acting. Authority flows down the chain, so withdrawing any link withdraws
everything below it. A run with no chain of its own is covered by none of
them — there is nothing to key on, and inventing a match would stop work for
a reason nobody could look up.
A name is a string the manifest’s author typed, and a halt is still keyed
on one because it is a refusal: a name-keyed refusal at worst stops
work somebody did not mean to stop, which an operator sees at once and
lifts — the opposite of a name-keyed grant, which context.agent.name is
therefore never used for.
Variants§
Tenant
Everything this tenant would start. The power switch.
Agent
Every revision of one declared agent, by metadata.name.
Revision
One exact reviewed revision, by manifest digest.
The form that is precise about which revision is stopped, so a fix published as a new version is not stopped with it.
Subject
Everything acting for one principal, wherever it stands on the run’s delegation chain.
The authority axis rather than the workload axis. Ordered last so that it wins the message when several scopes cover one run: an operator who withdrew a credential and whoever is refused are looking for different sentences, and “the tenant is halted” sends the second one to the wrong incident.
Implementations§
Source§impl HaltScope
impl HaltScope
Sourcepub const FORMS: [&'static str; 4]
pub const FORMS: [&'static str; 4]
Every form parse accepts, written the way an operator
types it.
One list, because a scope an operator cannot learn the spelling of is a control they cannot reach — and the CLI’s help, its refusal and the operator API all have to say the same thing this parser accepts. Held to the list rather than to the variant count: a count agrees with itself while a form is missing.
Sourcepub fn subject(id: impl Into<String>) -> Self
pub fn subject(id: impl Into<String>) -> Self
Everything acting for one principal on a run’s delegation chain.
Sourcepub fn key(&self) -> String
pub fn key(&self) -> String
The durable key, and the form an operator types on the command line.
Round-trips through parse. One column rather than a
discriminant beside a value, because a scope stored in two columns is a
scope two backends can disagree about the emptiness rules of.
Sourcepub fn parse(key: &str) -> Option<Self>
pub fn parse(key: &str) -> Option<Self>
Read back a stored key.
None for anything this build does not understand — a scope written by
a newer version, say. A caller reading standing halts must treat that as
corruption rather than skipping the row: a halt this instance cannot
read is one it must not run through.
Sourcepub fn withdraws_from(&self, chain: &Delegation) -> Option<&str>
pub fn withdraws_from(&self, chain: &Delegation) -> Option<&str>
The principal this halt withdraws, if it is anywhere on chain.
The one scope that reaches work already running. The others stop admission, because cutting a saga mid-flight leaves reversals unrun; here the incident is the authority, and a run carrying on under a withdrawn credential is the harm. It pauses: the run stops at its next step boundary, its mutations stand, and lifting the halt continues it.
Sourcepub fn withdrawn_subject(&self) -> Option<&str>
pub fn withdrawn_subject(&self) -> Option<&str>
The principal this halt names, when it names one.
Sourcepub fn covers(
&self,
agent: Option<&AgentIdentity>,
chain: Option<&Delegation>,
) -> bool
pub fn covers( &self, agent: Option<&AgentIdentity>, chain: Option<&Delegation>, ) -> bool
Whether this halt stops a run governed by agent and acting under
chain.
Both, because the scopes ask different questions. Three of them ask what is running and one asks who it runs for, so a caller that passed only the agent would silently never match a withdrawn authority — the worst failure available here, since it is a refusal that does not happen and therefore leaves no trace at all.
A run with neither — a skill registered directly on the plane, with no
manifest and no chain — is stopped only by Tenant.
There is nothing narrower to key it on, and inventing a match would stop
work for a reason nobody could look up.
Trait Implementations§
impl Eq for HaltScope
Source§impl Ord for HaltScope
impl Ord for HaltScope
1.21.0 (const: unstable) · Source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
1.21.0 (const: unstable) · Source§fn min(self, other: Self) -> Selfwhere
Self: Sized,
fn min(self, other: Self) -> Selfwhere
Self: Sized,
Source§impl PartialOrd for HaltScope
impl PartialOrd for HaltScope
impl StructuralPartialEq for HaltScope
Auto Trait Implementations§
impl Freeze for HaltScope
impl RefUnwindSafe for HaltScope
impl Send for HaltScope
impl Sync for HaltScope
impl Unpin for HaltScope
impl UnsafeUnpin for HaltScope
impl UnwindSafe for HaltScope
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
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Comparable<K> for Q
impl<Q, K> Comparable<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> 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