#[non_exhaustive]pub enum PolicyError {
Show 18 variants
Denied {
principal: String,
action: String,
resource: String,
},
Recorded {
reason: String,
},
TaintGate {
sink: String,
},
UnboundSinkArguments {
sink: String,
},
SinkGateRequired {
sink: String,
},
SinkArgumentsMismatch {
sink: String,
at: String,
bound: Digest,
sent: Digest,
},
ProtectedFieldMissing {
sink: String,
path: String,
},
ProtectedFieldTaint {
sink: String,
path: String,
},
ReleaseDestination {
sink: String,
granted: String,
actual: String,
},
ProtectedFieldReleaseDestination {
sink: String,
path: String,
granted: String,
actual: String,
},
ProtectedFieldSource {
sink: String,
path: String,
actual_source: String,
},
ProtectedFieldValue {
sink: String,
path: String,
},
ProtectedFieldSensitivity {
sink: String,
path: String,
actual: Sensitivity,
ceiling: Sensitivity,
},
UntrackedReleaseField,
InvalidRelease {
detail: String,
},
JournalCeiling {
sink: String,
actual: Sensitivity,
ceiling: Sensitivity,
},
EgressCeiling {
sink: String,
actual: Sensitivity,
ceiling: Sensitivity,
},
DelegationDepth {
sink: String,
actual: usize,
ceiling: usize,
},
}Expand description
Authorization failure.
Evaluation is total and side-effect free, so this never means “the policy engine was unreachable” — that state cannot arise.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Denied
Recorded
A sink-gate refusal read back from the journal.
Carries the recorded wording rather than re-deriving a variant from it,
for the reason BudgetExceeded::Recorded
does: the run stopped for the reason it recorded, and a replay that
re-worded it makes an auditor compare a run’s status against its own
replay and find a difference that means nothing.
It is a PolicyError rather than a
StepError::Denied because which
gate refused survives the round trip and matters: a sink gate refuses
one call, and a tool-calling loop may tell the model and try another
route, where an authorization denial ends the run. Collapsing the two on
the way back would end a run the original finished.
TaintGate
An argument derived from untrusted data reached a mutating sink without an explicit, policy-authorized release.
UnboundSinkArguments
A sink did not expose the value it will send, so the runtime cannot bind the information-flow decision to the outbound call.
SinkGateRequired
A caller tried to dispatch an outbound-value effect through the generic effect API, bypassing information-flow enforcement.
SinkArgumentsMismatch
The labeled value presented to the gate differs from the value the sink will send.
The rule is exact equality, so that they differ is the whole verdict;
the reader also needs where, or is left with two documents and a diff
by eye — and the commonest case, a bound payload still at its null
default beside a labelled object, is the least visible. So the refusal
names the first differing RFC 6901 pointer ("" at the root) and both
canonical digests. Neither value is printed: the labelled one is the
data these gates exist to keep out of a log, and a digest identifies it
to whoever already holds it while disclosing nothing to anyone else.
Fields
ProtectedFieldMissing
A field the sink declares security-sensitive is absent from the value.
ProtectedFieldTaint
Untrusted data attempted to choose a protected sink argument.
ReleaseDestination
A destination-scoped release covers this value — but for a different sink. Named explicitly, because “untrusted” alone would send the operator hunting for a missing release that in fact exists and was simply granted somewhere else. The message names only the two destinations — never the release’s basis or evidence, which would hand a probing model the reviewer’s reasoning.
ProtectedFieldReleaseDestination
The field-scoped twin of ReleaseDestination.
ProtectedFieldSource
A protected field derives from a source outside its operator declaration.
ProtectedFieldValue
A protected field carries a value outside its declared set.
The message names the constraint and deliberately not the value: the value is untrusted-influenced by construction, and echoing it hands an injected payload a path into logs and refusal channels. The manifest is where a reader sees what is permitted.
ProtectedFieldSensitivity
A protected field exceeds its own sensitivity ceiling.
UntrackedReleaseField
A field-specific release was requested for a value whose field lineage was never tracked.
InvalidRelease
A serialized release bypassed the safe constructors and violated the typed-release invariants.
JournalCeiling
A value’s sensitivity exceeds what this agent may write into the journal.
Distinct from EgressCeiling, and the
distinction is the whole point: egress asks may this leave, this asks
may this be written down forever. The journal is append-only, so an
argument recorded there — a prompt, a tool call’s arguments — is never
removed. A deployment with an erasure obligation has two answers and
this ceiling is the first: refuse the data at dispatch, rather than
meet an impossibility at the erasure request. The second is to seal
it — RuntimeBuilder::keyring puts payloads under a per-case key that
erase_case destroys — and the two compose: a deployment may seal
everything and still refuse the classes it would rather never hold.
The message names both, because a reader who has configured a key ring and then meets this refusal would otherwise conclude the seal is not working.
EgressCeiling
A value’s sensitivity exceeds what the sink is allowed to receive. This is the exfiltration path that matters: not the network, but a legitimate-looking tool call carrying a secret read three steps ago.
DelegationDepth
A handoff would make the authority chain deeper than this agent’s reviewed declaration permits.
Implementations§
Trait Implementations§
Source§impl Debug for PolicyError
impl Debug for PolicyError
Source§impl Display for PolicyError
impl Display for PolicyError
Source§impl Error for PolicyError
impl Error for PolicyError
1.30.0 · Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
Source§impl From<PolicyError> for RuntimeError
impl From<PolicyError> for RuntimeError
Source§fn from(source: PolicyError) -> Self
fn from(source: PolicyError) -> Self
Source§impl From<PolicyError> for StepError
impl From<PolicyError> for StepError
Source§fn from(source: PolicyError) -> Self
fn from(source: PolicyError) -> Self
Auto Trait Implementations§
impl Freeze for PolicyError
impl RefUnwindSafe for PolicyError
impl Send for PolicyError
impl Sync for PolicyError
impl Unpin for PolicyError
impl UnsafeUnpin for PolicyError
impl UnwindSafe for PolicyError
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> 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