batpak 0.8.2

Event sourcing with causal graphs and caller-defined gates. Sync API, no async runtime.
Documentation

batpak

batpak is an embedded, sync-first event store for Rust: an append-only log with typed payloads, Blake3 hash-chained ancestry, verifiable (optionally Ed25519-signed) receipts, deterministic replay, and derived projections — in one process, with no server and no async runtime.

Use it when you need a tamper-evident, replayable record of what happened: agent action audit trails, local-first app logs, compliance evidence, event-sourced application state.

use batpak::prelude::*;

#[derive(serde::Serialize, serde::Deserialize, EventPayload)]
#[batpak(category = 0xF, type_id = 1)]
struct PlayerMoved {
    x: i32,
    y: i32,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let dir = tempfile::tempdir()?;

    // The Store owns this directory and nothing else.
    let store = Store::open(StoreConfig::new(dir.path()))?;

    // A Coordinate names where events belong: an entity within a scope.
    let coord = Coordinate::new("player:alice", "room:dungeon")?;

    // Append source truth. The receipt is verifiable evidence of what
    // was accepted.
    let receipt = store.append_typed(&coord, &PlayerMoved { x: 10, y: 20 })?;

    // Accepted events are immutable.
    let fetched = store.get(receipt.event_id)?;
    println!("stored {} at sequence {}", fetched.event.header.event_id, receipt.sequence);

    store.close()?;
    Ok(())
}

Why not SQLite with an events table?

SQLite gives you durable rows. batpak gives you durable rows plus proof: every event is hash-bound to its per-entity ancestor with Blake3, every accepted write returns a receipt you can verify later, and projections are derived views rebuilt from the log by construction — read models cannot silently drift from source truth.

When batpak is the wrong tool: ad-hoc SQL over relational data, many writer processes sharing one store, raw write throughput over verifiable history, or distributed replication. batpak is a local truth boundary, on purpose.

Trust

Judge the evidence, not the 0.x version number: roughly one line of tests per line of source, deterministic concurrency proofs with loom, property-based tests over hash-chain integrity and canonical encoding, crash-recovery and fault-injection suites, mutation testing on critical seams, and 71 named invariants enforced by an executable integrity gate.

Docs

Full documentation lives in the repository: the README for the evaluator path, the COOKBOOK for task-shaped recipes, and MODEL / INVARIANTS / CONFORMANCE for the mental model and the guarantees.

This is the substrate crate in the batpak family. TypeScript clients talk to a networked batpak host through @batpak/sdk.

bp records.