pub struct CapDecisionRecord {
pub cap_id: String,
pub key: String,
pub action: String,
pub decision: Decision4,
pub mode: String,
pub actor: Actor,
pub reason: Option<String>,
pub rule: Option<String>,
pub never_rollup: bool,
}Expand description
One capability decision, emitted as an event inside the tool-call span.
Fields§
§cap_id: String§key: String§action: String§decision: Decision4§mode: String§actor: Actor§reason: Option<String>§rule: Option<String>The ceiling rule that matched, when the provider can attribute one. Drives rollup grouping (Task 2).
never_rollup: boolTrue for a decision on a semantic class (act:consent), which must
never fold into the per-call rollup even when it resolves to Allow.
A physical class’s rollup is right for what it is: nobody wants a
line per filesystem read. A semantic class is the opposite — there
are few of them, each is a distinct, consequential act (DROP DATABASE analytics), and which subject is the whole content of the
decision. Rolling one into db:drop: 1 request throws away the one
fact the line exists to carry, the same way folding a credential
issue into a count would (see render_credential_issue’s doc, which
states the identical rule for that record).
An explicit flag, not action == "request": consent::gate::ACTION
is a private constant, and string-matching it across the module
boundary between consent::gate and audit::layer is fragile —
renaming or repurposing the action string would silently start
folding consent decisions again with no test failing until someone
noticed the missing audit line.
false for every physical-class decision (fs/http/sockets/
credentials); true only where consent::gate::ConsentGate::decide
sets it before emitting.
Implementations§
Source§impl CapDecisionRecord
impl CapDecisionRecord
Sourcepub fn statik(
cap_id: &str,
key: &str,
action: &str,
decision: Decision4,
mode: &str,
rule: Option<String>,
) -> Self
pub fn statik( cap_id: &str, key: &str, action: &str, decision: Decision4, mode: &str, rule: Option<String>, ) -> Self
A statically-resolved decision (ceiling x grant, no human involved). Shared by every capability class so the record shape cannot drift between providers.
Sourcepub fn statik_with_reason(
cap_id: &str,
key: &str,
action: &str,
decision: Decision4,
mode: &str,
rule: Option<String>,
reason: Option<&str>,
) -> Self
pub fn statik_with_reason( cap_id: &str, key: &str, action: &str, decision: Decision4, mode: &str, rule: Option<String>, reason: Option<&str>, ) -> Self
statik, but lets the caller override the default Deny reason
(“outside ceiling”). Some decision points deny for a reason other
than “the operation didn’t match the ceiling” — a redirect hop
leaving the allowed host, a DNS-resolved address landing in a
deny-CIDR — and an operator reading “outside ceiling” for both would
not be able to tell them apart from an ordinary allow/deny-list
mismatch. None reproduces statik’s default exactly. Still the
same shared shape and still no per-class builder: any capability
class can call this, not just HTTP.
Sourcepub fn answered(
cap_id: &str,
key: &str,
allowed: bool,
has_channel: bool,
) -> Self
pub fn answered( cap_id: &str, key: &str, allowed: bool, has_channel: bool, ) -> Self
An ask that has resolved — either a human actually answered it, or
there was no channel to ask on at all and it degraded to deny (§5).
has_channel is what tells the two apart, and it changes both actor
and reason: a real human refusal is actor: User, reason: "denied by user", but a no-channel degrade never consulted anyone, so
recording it identically would make the trail lie about who decided.
DenyPrompter (the only prompter with has_channel() == false)
always resolves allowed = false, so has_channel: false in
practice always pairs with allowed: false — but the reason is
driven by has_channel alone, not inferred from allowed, so the
record stays correct even if that pairing ever changes.
Trait Implementations§
Source§impl Clone for CapDecisionRecord
impl Clone for CapDecisionRecord
Source§fn clone(&self) -> CapDecisionRecord
fn clone(&self) -> CapDecisionRecord
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for CapDecisionRecord
impl RefUnwindSafe for CapDecisionRecord
impl Send for CapDecisionRecord
impl Sync for CapDecisionRecord
impl Unpin for CapDecisionRecord
impl UnsafeUnpin for CapDecisionRecord
impl UnwindSafe for CapDecisionRecord
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,
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