Skip to main content

PolicyGate

Struct PolicyGate 

Source
pub struct PolicyGate { /* private fields */ }
Expand description

The tool authorizer a long-lived host installs on each of its sessions: the same filter basis’s ApprovalGate applies, plus the one answer that has to be terminal.

§Why the refusal is here and the rest is not

ApprovalGate answers nothing — every consequential call comes back as a Prompt — and that is what lets the policy be read per call, one layer up, where session/set_mode arrives. mentra resolves a Prompt against the conversation’s remembered rules before the approver is consulted, so a durable Global- or Project-scope allow seeded through the session’s permission handle answers ahead of the policy. For Always and Prompt that is unremarkable: both permit consequential work, and a standing allow is a host saying so in advance. For Never it is a standing override of the one thing that mode promises.

So this gate answers Never itself, with a Deny mentra returns unchanged — no rule is read, no PermissionRequested is emitted, and the approver is never reached. Every other policy still surfaces the call exactly as ApprovalGate did, remembered rules and all.

The policy is read from the shared SessionApproval on each call, so one installed gate follows a session across every switch. It is deliberately read per call rather than per turn: a gate that cached the policy it was installed under would be the stale answer this whole module exists to prevent.

§What it does not close

A durable rule still answers ahead of the client under Always and Prompt, because under those policies the gate still says Prompt. Revoking one is mentra’s business (mentra#43), not something a posture can express. And a rule remembered against a read-only tool is never consulted under any policy — this gate allows a non-consequential call outright, exactly as ApprovalGate does, for the reason written on basis::approval::is_consequential.

§And why it carries no timeout

ApprovalGate has a with_timeout, and installing this gate replaces the runtime’s, so the obvious thing is to mirror the knob so a host can restate a bound it would otherwise lose. That knob does not do what its name suggests, so this gate does not offer one.

A ToolAuthorizer’s timeout is mentra’s bound on mentra’s own wait. When it fires, mentra drops the authorization, denies that call, and lets the turn carry on. It does not touch basis’s side: basis’s event forwarder is parked inside Approver::approve for the same request (basis/src/run/prepared/forward.rs), and nothing wakes it, so a run whose approver never answers never returns, bound or no bound — measured, not assumed. What a bound really buys is an earlier refusal for an approver that answers late; what it is reached for is the approver that never answers, and there it buys nothing.

So the recourse for an unanswered request is the one that actually unparks the approver, and every host that installs this gate already needs it: over ACP the client sends session/cancel — which the protocol requires of a client abandoning a session/request_permission, and which basis-acp implements and pins (tests/acp/permission.rs) — and a host on another transport bounds its own approver, which is the layer that is genuinely waiting. Adding a knob here would have offered a guarantee that reads like that one and is not.

Cloneable for the same reason SessionApproval is, and not Debug for the same reason either: what it holds is one session’s live policy, shared.

Implementations§

Source§

impl PolicyGate

Source

pub fn new(approval: SessionApproval) -> Self

Gates a session on approval, reading it live.

Trait Implementations§

Source§

impl Clone for PolicyGate

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl ToolAuthorizer for PolicyGate

Source§

fn authorize<'life0, 'life1, 'async_trait>( &'life0 self, request: &'life1 ToolAuthorizationRequest, ) -> Pin<Box<dyn Future<Output = Result<ToolAuthorizationDecision, RuntimeError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Source§

fn timeout(&self) -> Option<Duration>

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
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> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. 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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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