pub struct PermissionGate { /* private fields */ }Expand description
The permission gate: a session’s standing authority plus the classifier and the durable approval ledger. Pure and synchronous so it can be embedded anywhere; the engine wraps it for its async pipeline.
Implementations§
Source§impl PermissionGate
impl PermissionGate
Sourcepub fn new(granted: PermissionTier) -> PermissionGate
pub fn new(granted: PermissionTier) -> PermissionGate
A gate with the given standing tier, default classifier, mandatory
approval at FullAccess, and an in-memory ledger.
pub fn with_classifier(self, classifier: RiskClassifier) -> PermissionGate
pub fn with_ledger(self, ledger: ApprovalLedger) -> PermissionGate
Sourcepub fn with_mandatory_approval_at(self, tier: PermissionTier) -> PermissionGate
pub fn with_mandatory_approval_at(self, tier: PermissionTier) -> PermissionGate
Override the tier at and above which approval is mandatory.
pub fn granted_tier(&self) -> PermissionTier
pub fn set_granted_tier(&mut self, tier: PermissionTier)
pub fn classifier(&self) -> &RiskClassifier
pub fn ledger(&self) -> &ApprovalLedger
Sourcepub fn evaluate(&self, action: &Action) -> GateDecision
pub fn evaluate(&self, action: &Action) -> GateDecision
Evaluate an action. Precedence:
- A prior rejection denies (a human said no).
- A prior approval allows (a human elevated this operation).
- Actions at/above the mandatory-approval tier need approval.
- Otherwise the granted tier must cover the required tier.
- Exceeding standing authority escalates to a human, not a hard deny — autonomy is suspended, not the task abandoned.
Sourcepub fn evaluate_against(
&self,
action: &Action,
ledger: &ApprovalLedger,
) -> GateDecision
pub fn evaluate_against( &self, action: &Action, ledger: &ApprovalLedger, ) -> GateDecision
Self::evaluate, but consulting an external ledger instead of the
gate’s own. For deployments that share ONE approval ledger across many
per-session gates (per-session tier, shared approvals): the daemon
keeps a single journal-backed ledger on its server state so an approval
recorded on one connection is visible to every other and survives
restart — a per-connection in-memory ledger would strand the approver’s
decision where the runner never reads it.
Sourcepub fn evaluate_with_ceiling(
&self,
action: &Action,
ceiling: Option<PermissionTier>,
) -> GateDecision
pub fn evaluate_with_ceiling( &self, action: &Action, ceiling: Option<PermissionTier>, ) -> GateDecision
Evaluate an action as if the session’s standing authority were capped at
ceiling — the join between skill-trust governance (arXiv 2602.12430) and
the action-level gate. The effective authority is min(granted, ceiling),
so an action driven by a skill whose deployment ceiling is read_only
cannot perform a sandbox_edit operation even in a full_access session;
it escalates to a human instead. A None ceiling is identical to
Self::evaluate.
The caller supplies the ceiling — it is the persisted
SkillMeta::deployment_tier of the skill that drove the action, which the
caller already knows (it retrieved the skill). The gate does not invent
action→skill provenance; it honours the ceiling it is handed.
Sourcepub fn evaluate_with_ceiling_against(
&self,
action: &Action,
ceiling: Option<PermissionTier>,
ledger: &ApprovalLedger,
) -> GateDecision
pub fn evaluate_with_ceiling_against( &self, action: &Action, ceiling: Option<PermissionTier>, ledger: &ApprovalLedger, ) -> GateDecision
Self::evaluate_with_ceiling against an external ledger — see
Self::evaluate_against for when a shared ledger is the substrate.
Sourcepub fn evaluate_axes(
&self,
action: &Action,
ceiling: Option<PermissionTier>,
ledger: Option<&ApprovalLedger>,
) -> ActionAxes
pub fn evaluate_axes( &self, action: &Action, ceiling: Option<PermissionTier>, ledger: Option<&ApprovalLedger>, ) -> ActionAxes
Both authorization axes for one action, flattening its parameters once.
Every caller that records a PermissionDecision needs both: the gate’s
verdict (may this run?) and the rollback contract (could it be taken
back?). Computed separately they each call action_text, which walks
every nested string in Action::parameters into a String and then
allocates a lowercase copy — twice, per action, on the execution path,
for payloads that can be a whole document or diff. Parslee-ai/car#856.
ceiling caps standing authority the way
Self::evaluate_with_ceiling does; ledger selects an external
approval ledger the way Self::evaluate_against does, or None to
use the gate’s own.
The two fields answer independent questions and neither is derived from
the other — see classify_reversibility. They travel together here
only because they read the same text.
Sourcepub fn approve(
&mut self,
action: &Action,
reviewer: &str,
reason: &str,
evidence: Option<String>,
) -> Result<ApprovalRecord, Error>
pub fn approve( &mut self, action: &Action, reviewer: &str, reason: &str, evidence: Option<String>, ) -> Result<ApprovalRecord, Error>
Record a human approval for the operation action represents.
Errs when the ledger journal write fails (the decision is then NOT
recorded — see ApprovalLedger::record).
Sourcepub fn reject(
&mut self,
action: &Action,
reviewer: &str,
reason: &str,
evidence: Option<String>,
) -> Result<ApprovalRecord, Error>
pub fn reject( &mut self, action: &Action, reviewer: &str, reason: &str, evidence: Option<String>, ) -> Result<ApprovalRecord, Error>
Record a human rejection for the operation action represents.
Errs when the ledger journal write fails (the decision is then NOT
recorded — see ApprovalLedger::record).
Sourcepub fn record_for_fingerprint(
&mut self,
fingerprint: &str,
required_tier: PermissionTier,
decision: ApprovalDecision,
reviewer: &str,
reason: &str,
evidence: Option<String>,
) -> Result<ApprovalRecord, Error>
pub fn record_for_fingerprint( &mut self, fingerprint: &str, required_tier: PermissionTier, decision: ApprovalDecision, reviewer: &str, reason: &str, evidence: Option<String>, ) -> Result<ApprovalRecord, Error>
Record a decision against an explicit fingerprint (when the caller
holds the fingerprint from a prior NeedsApproval, not the action).
Errs when the ledger journal write fails (the decision is then NOT
recorded — see ApprovalLedger::record).
Sourcepub fn decision_record(
&self,
action: &Action,
decision: ApprovalDecision,
reviewer: &str,
reason: &str,
evidence: Option<String>,
) -> ApprovalRecord
pub fn decision_record( &self, action: &Action, decision: ApprovalDecision, reviewer: &str, reason: &str, evidence: Option<String>, ) -> ApprovalRecord
Build (but do NOT store) the ApprovalRecord for a decision on
action — the gate classifies the action and derives its fingerprint;
the caller records the result on whichever ledger is the substrate
(its own via ApprovalLedger::record, or a shared daemon ledger).
This is what lets a per-session gate keep its tier/classifier while the
approval store is shared.
Trait Implementations§
Auto Trait Implementations§
impl !RefUnwindSafe for PermissionGate
impl !UnwindSafe for PermissionGate
impl Freeze for PermissionGate
impl Send for PermissionGate
impl Sync for PermissionGate
impl Unpin for PermissionGate
impl UnsafeUnpin for PermissionGate
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
impl<T> ErasedDestructor for Twhere
T: 'static,
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