pub struct EnforcementEvent {Show 17 fields
pub event_id: String,
pub schema_version: u8,
pub seq_no: u64,
pub recorded_at_ms: u64,
pub event_type: EnforcementEventType,
pub event_hash: String,
pub prev_hash: String,
pub installation_id: String,
pub actor_local: Option<ActorLocal>,
pub agent_type: String,
pub subject_kind: SubjectKind,
pub subject_key: String,
pub canonical_subject_hash: Option<String>,
pub receipt_id: Option<String>,
pub decision_reason_code: String,
pub decision_basis_hash: Option<String>,
pub agent_session: Option<String>,
}Expand description
The canonical enforcement event envelope.
Every enforcement decision (deny, allow-after-receipt, bypass detection, control changes) is recorded as one of these events. They form a hash-chained, sequenced stream for tamper-evident audit.
Fields§
§event_id: StringGlobally unique event identifier. UUIDv7 (time-ordered).
schema_version: u8Schema version. Always SCHEMA_VERSION for v1.
seq_no: u64Global durable monotonic sequence number within this store. Allocated atomically. Never reused. Never gaps except after crash (which produces a RecordingGap event on recovery).
recorded_at_ms: u64Unix milliseconds UTC when this event was recorded.
event_type: EnforcementEventTypeThe type of event. Determines which optional fields are populated.
event_hash: StringSHA-256 hash of this event’s canonical serialization (see hash contract). Computed AFTER all other fields are set, stored as lowercase hex.
prev_hash: StringSHA-256 hash of the previous event in the stream. Empty string for the first event in the store. Forms a hash chain for tamper detection.
installation_id: StringStable installation identifier. UUID generated once at first init, persisted in the store, never changes. NOT derived from hostname.
actor_local: Option<ActorLocal>Local OS identity of the actor. Structured, explicitly labeled as unverified. None if identity cannot be determined.
agent_type: StringThe AI agent type that triggered this event.
subject_kind: SubjectKindWhat kind of subject this event pertains to.
subject_key: StringCanonical identifier of the subject. For files: the canonical file key (normalized, symlink-resolved, case-folded where applicable). For controls: the gotcha or config key.
canonical_subject_hash: Option<String>Hash of the canonical file path for file-backed subjects. Allows cross-referencing even if paths are later renamed.
receipt_id: Option<String>Links events back to the receipt that authorized them.
decision_reason_code: StringStable enum string for the reason. NOT freeform prose. Examples: “gotcha_above_threshold”, “receipt_valid”, “receipt_expired”, “daemon_unreachable”, “control_created”, “control_deleted”
decision_basis_hash: Option<String>Hash of the gotcha/config state that was used to make this decision. Proves which rule text and thresholds were in force at decision time.
agent_session: Option<String>The AI agent SESSION that triggered this event (Claude Code session_id).
Enables per-actor audit attribution — proving the same session that
consulted a file also acted on it. None for events with no session
(Codex, config changes, gaps). Added in schema_version 2; hashed only for
v2+ events (see compute_hash).
Implementations§
Source§impl EnforcementEvent
impl EnforcementEvent
Sourcepub fn compute_hash(&self) -> String
pub fn compute_hash(&self) -> String
Compute the canonical hash of this event.
The hash covers all fields EXCEPT event_hash itself.
This function is frozen for schema_version 1 — do not modify
without incrementing SCHEMA_VERSION.
Trait Implementations§
Source§impl Clone for EnforcementEvent
impl Clone for EnforcementEvent
Source§fn clone(&self) -> EnforcementEvent
fn clone(&self) -> EnforcementEvent
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for EnforcementEvent
impl Debug for EnforcementEvent
Source§impl<'de> Deserialize<'de> for EnforcementEvent
impl<'de> Deserialize<'de> for EnforcementEvent
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for EnforcementEvent
impl RefUnwindSafe for EnforcementEvent
impl Send for EnforcementEvent
impl Sync for EnforcementEvent
impl Unpin for EnforcementEvent
impl UnsafeUnpin for EnforcementEvent
impl UnwindSafe for EnforcementEvent
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
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&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)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&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> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<T> Fruit for T
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