pub struct EventLog { /* private fields */ }Implementations§
Source§impl EventLog
impl EventLog
Sourcepub fn open(path: impl AsRef<Path>) -> Result<Self, EventLogError>
pub fn open(path: impl AsRef<Path>) -> Result<Self, EventLogError>
Opens (creating if needed) the event log and applies pending migration steps in order, idempotently.
§Errors
Returns EventLogError::Storage on any SQLite failure.
Sourcepub fn begin_session(&self) -> Result<SessionId, EventLogError>
pub fn begin_session(&self) -> Result<SessionId, EventLogError>
Starts a new session (fresh UUID; seq restarts at 1 within it).
§Errors
Currently infallible in practice; Result for API stability.
Sourcepub fn append(
&self,
session: &SessionId,
result: &CheckResult,
) -> Result<GateEvent, EventLogError>
pub fn append( &self, session: &SessionId, result: &CheckResult, ) -> Result<GateEvent, EventLogError>
Appends one gate decision as an event and returns its envelope.
§Errors
Returns EventLogError on storage or serialization failure.
Sourcepub fn append_failopen(
&self,
session: &SessionId,
detail: &str,
) -> Result<GateEvent, EventLogError>
pub fn append_failopen( &self, session: &SessionId, detail: &str, ) -> Result<GateEvent, EventLogError>
Records a fail-open occurrence (review directive: visible, queryable).
§Errors
Returns EventLogError on storage failure.
Sourcepub fn append_escalation(
&self,
session: &SessionId,
detail: &str,
) -> Result<GateEvent, EventLogError>
pub fn append_escalation( &self, session: &SessionId, detail: &str, ) -> Result<GateEvent, EventLogError>
Records a ladder escalation (attempt cap reached — addendum §7/§8).
§Errors
Returns EventLogError on storage failure.
Sourcepub fn append_telemetry(
&self,
session: &SessionId,
telemetry: Telemetry<'_>,
) -> Result<GateEvent, EventLogError>
pub fn append_telemetry( &self, session: &SessionId, telemetry: Telemetry<'_>, ) -> Result<GateEvent, EventLogError>
Records a non-decision telemetry event (spec §14: delivery, nudge
arms, and compression tiers ride the same stream as gate
decisions, distinguished by decision = "telemetry").
§Errors
Returns EventLogError on storage failure.
Sourcepub fn attempts(
&self,
session: &SessionId,
rule: &str,
file: &str,
) -> Result<u64, EventLogError>
pub fn attempts( &self, session: &SessionId, rule: &str, file: &str, ) -> Result<u64, EventLogError>
Session-scoped rule-hit counter — the Phase 2 escalation-ladder substrate (attempt N derives from this).
§Errors
Returns EventLogError::Storage on query failure.
Sourcepub fn denied_since(
&self,
rule: &str,
file: &str,
since: &str,
) -> Result<bool, EventLogError>
pub fn denied_since( &self, rule: &str, file: &str, since: &str, ) -> Result<bool, EventLogError>
Has an agent write to file ever been denied under rule? The
evidence half of the amended charter option B: a recorded deny plus a
staged change means the write happened through a surface PreToolUse
never saw.
Deliberately CROSS-SESSION, unlike Self::attempts. The ladder
counts within one agent conversation; this answers “did any agent get
told no about this path”, and the shell running git commit is never
the session that was denied.
since is the commit time of the last commit that TOUCHED file,
not HEAD’s. That difference is the whole design: the question is
not “when was the deny” but “is the denied change still
uncommitted”, and only a per-path boundary answers it. Once a human
commits the file, the boundary moves past the deny and later edits
pass — resolution is committing the change, which is what a human
owning the edit actually does.
Comparison is on WHOLE SECONDS, because a git commit time resolves
to the second while ts carries microseconds. substr(x, 1, 19) is
exactly YYYY-MM-DDTHH:MM:SS — the whole second and nothing after
it — so both sides normalize to the one shape they share, however
each spells what follows: the time crate writes a fraction only
when it is nonzero and renders UTC as a literal Z, while git may
render the offset as Z or as +00:00.
The earlier 20-character form is what made this fragile. At that
length the deciding character was whichever of . (0x2e), Z
(0x5a), or + (0x2b) the two formatters happened to emit, so the
verdict rode a formatting accident rather than time. Executed
evidence: with git rendering Z, a deny in the same second as the
commit compared as OLDER and was silently dropped.
Both sides must therefore be UTC before they arrive: comparing a
local-time since against a UTC ts would be wrong by the offset.
last_commit_touching pins TZ=UTC on its git log for exactly
this reason, and that pin is load-bearing here.
>= counts a deny in the same second as the boundary commit. That
direction is deliberate: git’s second resolution cannot tell before
from after within a second, and the tie must fall toward blocking,
because a false block is visible and recoverable (commit the file,
or --no-verify) while a false pass silently defeats the gate. A
deny in a strictly earlier second is resolved history and does not
count.
§Errors
Returns EventLogError::Storage on query failure.
Sourcepub fn block_count(&self, session: &SessionId) -> Result<u64, EventLogError>
pub fn block_count(&self, session: &SessionId) -> Result<u64, EventLogError>
Count of block decisions in a session (any rule, any file).
§Errors
Returns EventLogError::Storage on query failure.
Sourcepub fn rule_count(
&self,
session: &SessionId,
rule: &str,
) -> Result<u64, EventLogError>
pub fn rule_count( &self, session: &SessionId, rule: &str, ) -> Result<u64, EventLogError>
Count of events in a session filed under rule (telemetry included).
§Errors
Returns EventLogError::Storage on query failure.
Sourcepub fn failopen_count(&self, session: &SessionId) -> Result<u64, EventLogError>
pub fn failopen_count(&self, session: &SessionId) -> Result<u64, EventLogError>
Sourcepub fn stats(&self) -> Result<StatsSummary, EventLogError>
pub fn stats(&self) -> Result<StatsSummary, EventLogError>
Aggregates for pushkin stats (spec §14): blocks by rule,
compression savings, nudge arms, fail-opens — across all sessions
in this repo’s log. Historical rows keep their legacy-prefixed
ids (append-only); aggregation normalizes so the mixed population
groups as one rule (remediation pass 3, PART B2).
§Errors
Returns EventLogError::Storage on query failure.
Sourcepub fn decision_counts(&self) -> Result<(u64, u64), EventLogError>
pub fn decision_counts(&self) -> Result<(u64, u64), EventLogError>
Decision counts for the compact statusline segment: (checks, denials) — real gate decisions only, escalation marker rows excluded so three denials read as three, not four.
§Errors
Returns EventLogError::Storage on query failure.
Sourcepub fn latest_session_escalated(&self) -> Result<bool, EventLogError>
pub fn latest_session_escalated(&self) -> Result<bool, EventLogError>
Whether the most recent session has hit the escalation ladder cap.
§Errors
Returns EventLogError::Storage on query failure.
Sourcepub fn mean_attempts_to_compliance(&self) -> Result<Option<f64>, EventLogError>
pub fn mean_attempts_to_compliance(&self) -> Result<Option<f64>, EventLogError>
Mean-time-to-compliance (integration doc §8): across sessions that
recovered (a block followed by an allow), the average number of
attempts — denials before the allow, plus the complying write.
None when no session has recovered yet.
§Errors
Returns EventLogError::Storage on query failure.