audit-trail 1.0.1

Structured audit logging with tamper-evident chaining. Every write produces a cryptographically linked record (hash chain). Compliance-grade output (who, what, when, where, result). Pluggable backends. Foundation for HIPAA, SOC 2, and PCI-DSS compliance.
Documentation

What it does

Structured audit logging with tamper-evident chaining. Every write produces a cryptographically linked record (hash chain). Compliance-grade output (who, what, when, where, result). Pluggable backends. Foundation for HIPAA, SOC 2, and PCI-DSS compliance.


Quick start

[dependencies]
audit-trail = { version = "1", features = ["sha2"] }
use audit_trail::{
    Action, Actor, Chain, MemorySink, Outcome, Sha256Hasher, SystemClock, Target, Verifier,
};

let mut chain = Chain::new(Sha256Hasher::new(), MemorySink::new(), SystemClock::new());

chain.append(
    Actor::new("user-42"),
    Action::new("record.delete"),
    Target::new("record:1337"),
    Outcome::Denied,
).expect("append");

// Later, prove the chain is untampered.
let (_, sink, _) = chain.into_parts();
let mut verifier = Verifier::new(Sha256Hasher::new());
for r in sink.records() {
    verifier.verify(&r.as_record()).expect("chain must verify");
}

Persisting to a file

use audit_trail::{Chain, FileSink, FileReader, Sha256Hasher, SystemClock, Verifier};

let sink = FileSink::open_or_create("audit.log").expect("open");
let mut chain = Chain::new(Sha256Hasher::new(), sink, SystemClock::new());
// ... chain.append(...) ...

// Replay and verify the on-disk log.
let mut verifier = Verifier::new(Sha256Hasher::new());
for record in FileReader::open("audit.log").expect("open") {
    let r = record.expect("decode");
    verifier.verify(&r.as_record()).expect("verify");
}

FileSink writes a versioned 16-byte header on a fresh file, then length-prefixed records using the stable [codec] encoding. Reopening the same path appends after validating the header.

Features

Feature Default What it adds
std yes FileSink, FileReader, std::error::Error impls. Implies alloc.
alloc yes (via std) OwnedRecord, MemorySink, codec module
sha2 no Sha256Hasher (reference SHA-256, FIPS 180-4)
blake3 no Blake3Hasher (reference BLAKE3, faster on modern CPUs)

For no_std use default-features = false and supply your own hasher, sink, and clock.

Examples

Runnable demonstrations under examples/:

cargo run --example in_memory --features sha2
cargo run --example file_log --features sha2
cargo run --example tamper_detection --features sha2

Documentation

  • docs/API.md — full public API reference: every type, trait, function, with descriptions and code examples.
  • docs.rs/audit-trail — generated rustdoc.

Benchmarks

cargo bench --features sha2,blake3

Two suites are provided:

  • benches/append.rs — chain append throughput per hasher (XOR / SHA-256 / BLAKE3).
  • benches/verify.rs — 1 000-record chain replay through Verifier.

Standards

  • REPS governs every decision. See REPS.md.
  • MSRV: Rust 1.85.
  • Edition: 2024.
  • Cross-platform: Linux, macOS, Windows.

License

Dual-licensed under either of:

at your option.