Expand description
Append-only conversation event log on a commonware-storage journal.
This crate persists the ordered stream of events that make up a conversation (user messages, planner decisions, tool calls, …) to an append-only log backed by the Commonware storage stack — keeping persistence on the Commonware primitives rather than a relational store.
§Storage primitive
EventLog wraps
commonware_storage::journal::contiguous::variable::Journal: a
contiguous, position-based, variable-length append-only journal. It is
the natural fit here:
- Append-only.
EventLog::appendwrites oneEventand returns the monotonically increasingu64position the journal assigned it. Positions start at0and never reused; pruning earlier entries does not shift later positions. - Ordered replay.
EventLog::replayreturns every event in append order, each paired with its position. Append order is the ordering contract: the caller appends events in conversation order (turn, then sequence within a turn), and replay yields them back in exactly that order. The position therefore is the (turn, seq) ordinal flattened into one strictly increasing sequence — there is no separate sort key to maintain, which is precisely what an append-only log buys us. - Variable-length items. Each event’s
payloadis an opaque, buffa-encoded byte blob of arbitrary size; thevariablejournal stores variable-length items natively (thecontiguous::fixedsibling is for fixed-width records and would not fit).
§Runtime genericity (tokio vs. deterministic)
The journal — and therefore EventLog — is generic over a
commonware_storage::Context (the Storage + Clock + Metrics bound every
Commonware storage type carries). Production drives it on the
commonware_runtime::tokio backend; tests drive it on the
commonware_runtime::deterministic backend for seeded, reproducible runs.
The two never nest: per the prior commonware-transport spike, the
Commonware runtime cannot be started from inside a live tokio runtime, so
every tokio process that embeds this crate runs it on a dedicated thread.
The state plane does so for the conversation journal it alone writes; the
control plane does so for the non-conversation logs it keeps of its own.
This crate stays runtime-agnostic and leaves that hosting decision to the
caller.
§Conversation scoping
One EventLog instance maps to one conversation’s log, identified by the
storage partition name passed to EventLog::open (derive it from the
conversation id, e.g. format!("conv-{uid}")). Distinct conversations use
distinct partitions and so are fully isolated on disk.
§Example
use commonware_runtime::{deterministic, Runner};
use polyc_eventlog::{Event, EventLog, EventLogConfig};
let executor = deterministic::Runner::default();
executor.start(|context| async move {
let log = EventLog::open(context, EventLogConfig::for_partition("conv-1"))
.await
.expect("open log");
log.append(&Event::new("user_msg", b"hello".to_vec())).await.unwrap();
log.append(&Event::new("tool_call", b"\x01\x02".to_vec())).await.unwrap();
log.commit().await.unwrap();
let events = log.replay().await.unwrap();
assert_eq!(events.len(), 2);
assert_eq!(events[0].kind, "user_msg");
});Re-exports§
pub use checkpoint::EventCountCheckpoint;pub use error::EventLogError;
Modules§
- checkpoint
- Durable “expected event count” side-channel (
#799hardening). - error
- Errors surfaced by the event log.
- integrity
- Per-conversation tamper-evidence over the event log (#799).
- nav
- Storage-agnostic lexical navigation over a conversation’s own history.
- taint
- Storage-agnostic trust/provenance tags and the “lethal trifecta” detector.
Structs§
- Bounded
Replay - A replay that may stop before the partition tail at a caller byte budget.
- Event
- A single conversation event: a
kindtag, aTrustTagprovenance capability, and an opaque encoded payload. - Event
Cfg - Decode-time bounds for an
Event, supplied as the journal’scodec_config. - Event
Log - An append-only, ordered log of conversation
Events. - Event
LogConfig - Configuration for opening an
EventLog. - Granted
Capabilities - Capabilities granted to a turn that cannot yet be derived from the tagged event substrate alone — they require knowledge of the live tool catalog.
- Quarantined
Item - One event
EventLog::replay_quarantiningcould not decode, and why. - Trifecta
Legs - The three independent capability legs whose simultaneous presence in one conversation forms the “lethal trifecta” data-exfiltration path.
Enums§
- Integrity
Error - Failures from extending, signing, or verifying a partition’s MMR.
- Trust
Tag - Trust/provenance capability tag attached to every conversation event at ingress.
Constants§
- MMR_
SIGNED_ ROOT_ KIND - Event kind naming a persisted
SignedRootmarker. Namespaced so it cannot collide with any conversation-content kind (every real kind inpolyc-proto’sevents.protois a bare identifier with no__wrapping).
Functions§
- any_
untrusted - Whether any event in
eventscarries untrusted (TrustTag::QuarantinedContent) provenance — the durable form of the trifecta’s untrusted-content-in-context leg, read straight from the trust tags. - any_
untrusted_ excluding any_untrustedover position-carrying events, excluding the journal positions a verified taint-excision marker covers (#590).- extend_
and_ sign - Extend
logwith each ofnew_events’s(kind, payload)leaves, sign the resulting root withsigner, and return theEventto append (kindMMR_SIGNED_ROOT_KIND) — the caller places it in the SAME journal batch asnew_events(e.g. right beforeturn_complete) so the signature is atomic with the content it covers. - init_
metrics - Force-register this crate’s Prometheus append-latency histogram.
- rebuild_
from_ events - Reconstruct a partition’s running MMR from a full replay, for a caller
that wants to keep extending it (the eventlog host, on first touching a
partition after a restart). Root-marker events themselves are not MMR
leaves — only real conversation events are — so this filters them out
before delegating to
VerifiableLog::rebuild. - trifecta_
legs - Compute the
TrifectaLegsfor a conversation from its tagged event log and the capabilities granted to the turn. - verify_
extension_ with_ trust - Verifies
eventsas the CONTINUATION of the partitionlogalready covers, extendinglogleaf by leaf exactly as a replay of the whole partition would, and checking everyMMR_SIGNED_ROOT_KINDmarker it meets against the tree at that point. - verify_
replay - Verify a full partition replay’s tamper-evidence: rebuild the MMR leaf by
leaf in append order, and at every
MMR_SIGNED_ROOT_KINDmarker check that (a) its signature verifies underexpected_signer_pk_hexand (b) the tree’s root and leaf count at that point match what the marker claims. Returns on the FIRST violation found, naming exactly where it occurred. - verify_
replay_ with_ trust - Replays and verifies every root against current and retired role keys.