pub struct ExecutionPolicy {
pub effect: Effect,
pub cancellable: bool,
pub concurrency: Concurrency,
pub signed_input: bool,
}Expand description
What running a capability as an execution means: what it changes, whether asking it to stop achieves anything, and whether two of them may overlap.
The effect and the concurrency are classified from the kind by
ExecutionPolicy::classify, for the same reason Availability is: the facts are
already on the declaration, and asking each capability! block to restate them would be
one more thing that can disagree with itself.
Cancellability is the one thing the kind cannot decide, because it is a fact about the
handler: whether it looks at its cancellation flag and stops. A handler that does says
so with crate::capability::Executable::cancellable, and a client is then told
whether a Cancel button will achieve anything instead of being given one that lies.
Fields§
§effect: EffectWhat it changes.
cancellable: boolWhether asking it to stop does anything. A task looks at its cancellation flag; a query and a command do not, and a client is told so rather than being given a button that lies.
concurrency: ConcurrencyWhether two of them may overlap.
signed_input: boolWhether the input authenticates its caller.
A handler whose input is a signed message, and which verifies the signature against
the trust policy before anything changes, admits its caller by that signature and not
by the address the request came from. Only such a handler changes state for a caller
on another host; see ExecutionPolicy::admits_remote.
Implementations§
Source§impl ExecutionPolicy
impl ExecutionPolicy
Sourcepub fn classify(kind: CapabilityKind) -> Self
pub fn classify(kind: CapabilityKind) -> Self
The policy of a kind.
use majordomus_cli::capability::{CapabilityKind, Concurrency, Effect, ExecutionPolicy};
let query = ExecutionPolicy::classify(CapabilityKind::Query);
assert_eq!(query.effect, Effect::Read);
assert_eq!(query.concurrency, Concurrency::Unrestricted);
assert!(!query.cancellable, "until its handler says it looks at the flag");
assert!(query.stoppable().cancellable);
let command = ExecutionPolicy::classify(CapabilityKind::Command);
assert_eq!(command.effect, Effect::ProcessState);
assert_eq!(command.concurrency, Concurrency::Serial);Sourcepub fn stoppable(self) -> Self
pub fn stoppable(self) -> Self
The same policy, for a handler that looks at its cancellation flag and stops.
use majordomus_cli::capability::{CapabilityKind, ExecutionPolicy};
let p = ExecutionPolicy::classify(CapabilityKind::Query).stoppable();
assert!(p.cancellable);
assert_eq!(p.effect, ExecutionPolicy::classify(CapabilityKind::Query).effect);Sourcepub fn writes_repository(self) -> Self
pub fn writes_repository(self) -> Self
The same policy, for a handler that writes the repository’s own tracked files.
The second and last thing the kind cannot decide. Two commands are the same kind whether one announces a peer into this process’s memory and the other stamps a field into a record a commit will carry, and the difference is the whole of what a caller needs to know before saying yes. It is stated by the handler because only the handler knows it.
This is a widening and never a narrowing: a query cannot reach for it, because the registry accepts a declared policy only when it is the kind’s own or one of these two documented additions to it.
use majordomus_cli::capability::{CapabilityKind, Effect, ExecutionPolicy};
let p = ExecutionPolicy::classify(CapabilityKind::Command).writes_repository();
assert_eq!(p.effect, Effect::RepositoryMutation);
assert!(p.needs_confirmation());Sourcepub fn authenticates_its_input(self) -> Self
pub fn authenticates_its_input(self) -> Self
The same policy, for a command whose input is a signed message the handler verifies against the trust policy before it changes anything.
The third documented addition, and the narrowest: the mesh’s link and registration handlers, whose callers are other machines by design and are admitted by a key the trust policy names. It never combines with writing the repository: a signature proves who sent a message, not that its sender may change tracked files here.
use majordomus_cli::capability::{CapabilityKind, ExecutionPolicy};
let p = ExecutionPolicy::classify(CapabilityKind::Command).authenticates_its_input();
assert!(p.signed_input && p.admits_remote());Sourcepub fn admits_remote(self) -> bool
pub fn admits_remote(self) -> bool
May a caller on another host run this?
A request that arrives from an address that is not loopback has proved nothing about
who sent it: the server has no accounts and no tokens, and the Origin check stops a
browser, not a program. Such a caller reads, and changes nothing, unless the input
itself authenticates it (ExecutionPolicy::authenticates_its_input). A command
that only changes this process’s memory is refused too, because some of that memory
is signed by this node and replicated to every runtime that trusts it (ADR 0126).
use majordomus_cli::capability::{CapabilityKind, ExecutionPolicy};
assert!(ExecutionPolicy::classify(CapabilityKind::Query).admits_remote());
assert!(!ExecutionPolicy::classify(CapabilityKind::Command).admits_remote());
assert!(!ExecutionPolicy::classify(CapabilityKind::Command).writes_repository().admits_remote());Sourcepub fn needs_confirmation(self) -> bool
pub fn needs_confirmation(self) -> bool
Should a client ask before running this? True for anything that changes something.
use majordomus_cli::capability::{CapabilityKind, ExecutionPolicy};
assert!(!ExecutionPolicy::classify(CapabilityKind::Query).needs_confirmation());
assert!(ExecutionPolicy::classify(CapabilityKind::Command).needs_confirmation());Sourcepub fn hints(self) -> Hints
pub fn hints(self) -> Hints
What a caller may assume about a call before making it, classified from the effect.
A projection that tells a client how careful to be — MCP’s tool annotations, the
site’s table of tools, the Cockpit’s — renders this value and states none of its
own. Until it existed the MCP projection wrote destructiveHint: false and
idempotentHint: true as constants, which was true of every tool on the day they
were written and false of the first one that wrote the repository: a sweep that
unlinks files was announced as safe to repeat and unable to destroy anything.
The classification is conservative in the one direction a caller can survive. Anything that changes something is not assumed repeatable, because whether a second call is a no-op is a fact about the handler and no handler has declared it; and anything that writes the repository may overwrite or remove what was there. A change to this process’s own memory destroys nothing outside it.
use majordomus_cli::capability::{CapabilityKind, ExecutionPolicy};
let read = ExecutionPolicy::classify(CapabilityKind::Query).hints();
assert!(read.read_only && read.idempotent && !read.destructive);
let memory = ExecutionPolicy::classify(CapabilityKind::Command).hints();
assert!(!memory.read_only && !memory.idempotent && !memory.destructive);
let writer = ExecutionPolicy::classify(CapabilityKind::Command).writes_repository().hints();
assert!(!writer.read_only && !writer.idempotent && writer.destructive);
assert!(!writer.open_world, "no handler of this executable reaches beyond the machine");Trait Implementations§
Source§impl Clone for ExecutionPolicy
impl Clone for ExecutionPolicy
Source§fn clone(&self) -> ExecutionPolicy
fn clone(&self) -> ExecutionPolicy
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl Copy for ExecutionPolicy
Source§impl Debug for ExecutionPolicy
impl Debug for ExecutionPolicy
Source§impl<'de> Deserialize<'de> for ExecutionPolicy
impl<'de> Deserialize<'de> for ExecutionPolicy
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for ExecutionPolicy
Source§impl JsonSchema for ExecutionPolicy
impl JsonSchema for ExecutionPolicy
Source§fn schema_id() -> Cow<'static, str>
fn schema_id() -> Cow<'static, str>
Source§fn json_schema(generator: &mut SchemaGenerator) -> Schema
fn json_schema(generator: &mut SchemaGenerator) -> Schema
Source§fn inline_schema() -> bool
fn inline_schema() -> bool
$ref keyword. Read moreSource§impl PartialEq for ExecutionPolicy
impl PartialEq for ExecutionPolicy
Source§fn eq(&self, other: &ExecutionPolicy) -> bool
fn eq(&self, other: &ExecutionPolicy) -> bool
self and other values to be equal, and is used by ==.Source§impl Serialize for ExecutionPolicy
impl Serialize for ExecutionPolicy
impl StructuralPartialEq for ExecutionPolicy
Auto Trait Implementations§
impl Freeze for ExecutionPolicy
impl RefUnwindSafe for ExecutionPolicy
impl Send for ExecutionPolicy
impl Sync for ExecutionPolicy
impl Unpin for ExecutionPolicy
impl UnsafeUnpin for ExecutionPolicy
impl UnwindSafe for ExecutionPolicy
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,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.