Skip to main content

ExecutionGate

Struct ExecutionGate 

Source
pub struct ExecutionGate;
Expand description

The spec §7.1 execution gate: a pure, reusable authorization component evaluated immediately before tool implementation lookup/execution.

Order of checks (each fails typed, closed, without acquiring anything):

  1. resolve wire name → exact live ToolId (deterministic reverse mapping; aliases cannot pick a different identity);
  2. the identity must be cataloged;
  3. the identity must be core (pinned digest intact) or hold an exact session activation grant covering (session, tool, digest) — see [grant_covers_execution]: catalog generation drift alone does NOT deny at execution time; only a real change to the called tool’s record (digest, presence, provenance) does;
  4. the record’s CURRENT trust provenance must equal the provenance the session PINNED at core-build/activation time — this closes the coherent-imposter hole (same ToolId, schema-identical body, different but internally consistent source/provenance);
  5. source trust is re-evaluated conservatively — see the honesty note on [check_source_trust]: this re-checks typed source/provenance consistency and denies Unknown/Unverified, but does NOT yet consult live manifest permission/revocation state (Task 20 integrates the permission/revocation policy);
  6. side-effect/confirmation policy (interim: Unclassified is allowed only for verified-provenance capabilities — Task 24 adds real effect classes);
  7. only then is the implementation acquired.

TOCTOU: callers must resolve, authorize, and acquire against ONE consistent registry borrow/lock guard — ExecutionGate::authorize_wire_call does exactly that for a &ToolRegistry held under the caller’s read lock.

Implementations§

Source§

impl ExecutionGate

Source

pub fn resolve( registry: &ToolRegistry, wire_name: &str, ) -> Result<ResolvedToolCall, ToolAuthorizationError>

Resolve an incoming API/wire name against one registry snapshot.

Source

pub fn authorize( catalog: &ToolCatalog, session: &SessionToolSet, resolved: ResolvedToolCall, ) -> Result<AuthorizedToolCall, ToolAuthorizationError>

Authorize a resolved identity against one catalog snapshot and one session tool set. On success — and only then — the implementation is acquired from the catalog record’s factory and returned inside the typed AuthorizedToolCall. Failure acquires nothing and leaves the session set untouched (the gate never mutates it).

SECURITY INVARIANT (per-tool digest + provenance validation): no tool executes unless its CURRENT catalog record — presence of the exact ToolId, schema digest, and source/trust provenance — exactly matches what the session pinned at core-build/activation time. Catalog generation inequality ALONE is no longer a denial reason at execution time: an unrelated background mutation (e.g. a plugin load mid-round) must not kill in-flight calls to schema-identical tools. Any REAL drift of the called tool’s record — changed digest, removal, changed provenance (even to an internally coherent one) — still denies typed and closed.

ACCEPTED RESIDUAL RISK: SchemaDigest hashes the schema JSON only, not the implementation factory. A record replaced in place with an identical schema AND identical pinned provenance but a different implementation passes this gate; the exposure is bounded by the deterministic round-top rebuild (runtime/stream.rs), which re-pins the set against the current catalog between provider rounds.

Source

pub fn authorize_wire_call( registry: &ToolRegistry, session: &SessionToolSet, wire_name: &str, ) -> Result<AuthorizedToolCall, ToolAuthorizationError>

Resolve + authorize + acquire against ONE registry borrow (one consistent snapshot under the caller’s read lock — no TOCTOU between resolution and implementation acquisition).

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync> ⓘ

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ThreadSafetyMarker for T
where T: Send,

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more