ogentic-audit
HMAC-SHA256 chained, append-only audit log library. Tamper-evident, language-agnostic on-disk format, built for evidence.
Status: v0.3.0. The on-disk format is specified in
docs/spec/v0.1.mdand the wire bytes are pinned by committed golden vectors. The format is the stable surface (0x0001, unchanged since v0.1); the Rust / Python APIs follow semantic versioning. See Status & versioning.
Why
Regulated industries and audit-grade AI tooling need an audit log that:
- Cannot be silently edited — every record is HMAC-chained to the previous, so an edit by anyone without the key is detectable. The verifier reports the exact
(segment, record_id)of the first violation, with a structured evidence payload an auditor can act on. - Can prove it wasn't rewritten — but only with a checkpoint. Chained HMACs verify the log against itself, which someone holding the key also satisfies after re-chaining fabricated history.
ogentic-audit checkpointpins the current head;ogentic-audit verify --checkpointproves the log still extends the head you saw before. That only helps if the checkpoint is held by someone who can't rewrite the log — see the threat model, andcargo run -p ogentic-audit-core --example rewrite_attackto see the attack and the detection. - Survives crashes — append-only with atomic flush +
F_FULLFSYNCon macOS; partial writes never produce a half-record. On reopen, the writer detects any torn tail (len_trailer != len_prefix) and truncates to the last fully-written record, surfacing a structuredRecoveryReportto the caller. - Travels across languages — the on-disk format is documented byte-by-byte, with golden vectors that conforming implementations MUST round-trip. v0.1 ships Rust + Python; the format is intentionally implementable in any language that has HMAC-SHA256.
- Is court-defensible — paired threat model and court-defensibility brief; the CLI ships a bit-reproducible
export --pdfcommand for self-contained evidence packages.
Components
crates/ogentic-audit-core— Rust core library (writer, reader, verifier, key handle, crash recovery)crates/ogentic-audit-cli—ogentic-auditCLI binary (verify/show/head/checkpoint/export)crates/ogentic-audit-keychain— optional OS-keychain key source (macOS / Linux / Windows)crates/ogentic-audit-kms— optional KMS-backed key source (AWS KMS in v0.1; GCP / Azure in v0.2)python/ogentic_audit— PyO3-based Python bindings (built with maturin; not yet on PyPI)
Quickstart
Rust
Add to Cargo.toml:
[dependencies]
# Not on crates.io yet — depend on the repo until the release lands:
ogentic-audit-core = { git = "https://github.com/OgenticAI/ogentic-audit" }
use ogentic_audit_core::{InMemoryKey, RecordInput, Writer, Verifier, PayloadValue};
use std::collections::BTreeMap;
fn main() -> anyhow::Result<()> {
// 32 raw bytes; in real use load via ogentic-audit-keychain or a vault.
let key = InMemoryKey::from_bytes([0u8; 32]);
let session_id = [0u8; 16]; // UUIDv4 in real use
let mut writer = Writer::open("./audit-logs", Box::new(key), session_id)?;
let mut payload = BTreeMap::new();
payload.insert("vault_id".into(), PayloadValue::Text("v-001".into()));
writer.append(RecordInput {
ts_wall: "2026-05-21T05:00:00.000Z".into(),
ts_mono_delta: 0,
actor: "user:alice".into(),
event: "vault.unlocked".into(),
payload,
schema_version: 1,
})?;
writer.flush()?;
drop(writer);
// Verify the log end-to-end.
let key = InMemoryKey::from_bytes([0u8; 32]);
let verifier = Verifier::new(Box::new(key));
let report = verifier.verify("./audit-logs")?;
assert_eq!(report.compact_verdict(), "Verified");
Ok(())
}
Python
# Not on PyPI yet — build the bindings from this repo:
pip install maturin && maturin develop -m python/ogentic-audit-py/Cargo.toml
from ogentic_audit import Writer, Reader, KeyHandle, verify
key = KeyHandle.from_env("OGENTIC_AUDIT_KEY_HEX") # 64 hex chars
with Writer.open("./audit-logs", key=key) as w:
w.append({"actor": "user:alice", "event": "vault.unlocked",
"payload": {"vault_id": "v-001"}})
for record in Reader.open("./audit-logs"):
print(record["record_id"], record["actor"], record["event"])
report = verify("./audit-logs", key=key)
assert report.ok
CLI — quick start
Not yet on Homebrew or crates.io. Until the release lands (OGE-1407), build the CLI from a clone:
cargo build --release --bin ogentic-audit. Thebrew install ogenticai/tap/ogentic-auditandcargo install ogentic-auditpaths below are what will work once it ships.
macOS (Homebrew) — after release
brew install ogenticai/tap/ogentic-audit
Linux / cross-platform (Cargo) — after release
cargo install ogentic-audit
Codesigning status (v0.1.0)
macOS binaries are sigstore-keyless-signed (cosign + GitHub OIDC) but not Apple Developer ID signed in v0.1.0. First launch on macOS may show a Gatekeeper dialog — right-click → Open to bypass. Apple Developer ID + notarization lands in v0.1.1.
Verify the sample log shipped with the project
The sample uses the public all-zeros fixture key; the CLI reads it
from OGENTIC_AUDIT_KEY_HEX under the default --key-source=env. Set
it first, then run the verify:
export OGENTIC_AUDIT_KEY_HEX=0000000000000000000000000000000000000000000000000000000000000000
ogentic-audit verify ./samples/matter-2024-CV-3047/matter-2024-CV-3047.log/ --summary
# ✓ Verified · 4 events · chain head 5c643f56
A tampered companion is also shipped — same four events with one byte flipped inside record 2's HMAC field — so you can see a failing verification end-to-end:
ogentic-audit verify ./samples/matter-2024-CV-3047-tampered/matter-2024-CV-3047.log/ --summary
# ✗ Verification failed · HmacMismatch at segment 0 record 2
echo $?
# 1
Prove the log was not rewritten
Chain verification alone cannot detect a rewrite by someone holding the key — it validates the log against itself. Pin the head, hand the pin to someone who does not control the log, and check against it later:
# Observe the current head and store it somewhere the writer can't reach.
ogentic-audit checkpoint ./samples/matter-2024-CV-3047/matter-2024-CV-3047.log/ --out head.json
# Later: prove the log still contains that history.
ogentic-audit verify ./samples/matter-2024-CV-3047/matter-2024-CV-3047.log/ --checkpoint head.json --summary
A rewritten log reports CheckpointMismatch; a truncated one reports
CheckpointTruncated. Both exit 1. Keeping head.json next to the log
achieves nothing — whoever can rewrite one can rewrite the other.
Exit codes (CI-friendly): 0 success, 1 verification failed, 2 I/O
error, 3 argument error, 64 clap usage error.
The
samples/directory ships inside the release tarball (ogentic-audit-<target>.tar.gz) and inside the source repo.brew installandcargo installusers get the binary only; either download the tarball, orgit clonethe repo, to follow the demo block above against the shipped sample.
Verify cosign signatures on the released binaries
Every release artifact is sigstore-keyless-signed (cosign + GitHub
OIDC). The workflow uploads a split .sig + .pem pair alongside
each tarball/zip; the certificate anchors the signature back to the
GitHub Actions workflow that built it.
For the macOS arm64 build of v0.1.0:
cosign verify-blob \
--certificate-identity "https://github.com/OgenticAI/ogentic-audit/.github/workflows/release-cli.yml@refs/tags/v0.1.0" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--signature ogentic-audit-macos-arm64.tar.gz.sig \
--certificate ogentic-audit-macos-arm64.tar.gz.pem \
ogentic-audit-macos-arm64.tar.gz
Swap the artifact filename for the target you downloaded:
ogentic-audit-macos-arm64.tar.gz, ogentic-audit-macos-x86_64.tar.gz,
ogentic-audit-linux-x86_64.tar.gz, ogentic-audit-linux-aarch64.tar.gz,
or ogentic-audit-windows-x86_64.zip. Each ships with a sibling
.sig + .pem.
Daily-driver subcommands
# verify a vault's log (64 hex chars = 32 raw bytes)
export OGENTIC_AUDIT_KEY_HEX=$(openssl rand -hex 32)
ogentic-audit verify ./audit-logs # exit 0 verified, 1 violation
# verify only segment 0 (useful for spot-checking a specific segment)
ogentic-audit verify ./audit-logs --segment 0
# machine-readable output (see "verify JSON output" below)
ogentic-audit verify ./audit-logs --format json
# pretty-print the last 100 records
ogentic-audit show ./audit-logs --from 0 --to 100
# spot-check the chain head
ogentic-audit head ./audit-logs --format json
verify JSON output (v0.2 shape — OGE-1063)
The --format json output uses status (not verdict) and segments_verified
(not compact). If you have automation that reads the old keys, update it:
| Old key | New key | Notes |
|---|---|---|
verdict |
status |
Values: "ok" or "tampered" |
compact |
removed | Use status instead |
| — | segments_verified |
Count of segments walked |
Clean example:
{
"status": "ok",
"format_version": 1,
"segments_verified": 1,
"log": { "segments_inspected": 1, "records_inspected": 1, ... }
}
Tampered example:
{
"status": "tampered",
"format_version": 1,
"segments_verified": 1,
"violation": { "kind": "HmacMismatch", "segment_index": 0, "record_id": 2, ... },
"additional_violations": [],
"log": { ... }
}
Violation detail text (kind, message, coordinates) is written to stderr;
the JSON summary on stdout is clean for jq-based pipelines.
--segment <id> flag
Verify a single named segment. Useful for forensic spot-checks on large logs:
ogentic-audit verify ./audit-logs --segment 0 # verify segment 0 only
ogentic-audit verify ./audit-logs --segment 42 # verify segment 42 only
Exit codes for --segment:
0— segment verified clean1— segment has a chain violation2— segment index> 65535, or the segment file does not exist in the log directory
Design
The format is HMAC-SHA256 chained records framed inside per-segment files. Every record carries its prev_hash (the previous record's HMAC) inside the canonical-CBOR-encoded payload, and the segment header binds the genesis HMAC to the header bytes themselves. The verifier walks records, recomputes HMACs against the running chain, and short-circuits at the first deviation with structured evidence.
- Hash: HMAC-SHA256 (FIPS 198-1)
- Encoding: Canonical CBOR per RFC 8949 §4.2 (deterministic)
- Segment header CRC: CRC32 (IEEE 802.3)
- Key fingerprint: BLAKE3-256
- Constant-time comparison:
subtleon HMAC and key_id
Full spec: docs/spec/v0.1.md. Architecture rationale: docs/adr/0001-on-disk-format.md.
Comparative positioning
| ogentic-audit | Database audit logs (PostgreSQL, MySQL audit plugin) | syslog / journald | Blockchain (Hyperledger, Ethereum) | |
|---|---|---|---|---|
| Tamper evidence | HMAC chained; every record links to previous | None — DB admin can rewrite | None — root can rewrite | Distributed consensus |
| Crash safety | Atomic per-record framing, F_FULLFSYNC, structured recovery report | Depends on the underlying storage engine | Best-effort; rotation can drop records | Block-level atomicity |
| Cross-language | Spec'd byte format + golden vectors | Vendor-specific | Vendor-specific (rsyslog vs systemd-journald) | EVM / chaincode-specific |
| Independent verifier | verify is a 10-line function; CLI ships a JSON report |
Trust the DB | Trust the OS | Trust the chain |
| Latency / cost | Microseconds per record, no network | Microseconds; coupled to DB load | Microseconds | Seconds to minutes per record, gas fees |
| Court-defensibility narrative | First-class: paired threat model + brief + PDF export | Requires expert testimony per vendor | Requires expert testimony | Requires expert testimony + chain explanation |
Use ogentic-audit when you need a portable, tamper-evident audit log for a single product (a vault, an AI agent, a compliance event stream) and you want the option to swap implementations later without rewriting the wire format. Skip ogentic-audit when you need distributed consensus across multiple writers (use a blockchain) or you're fine extending the DB you already operate (just turn on its audit plugin).
Court-defensibility
The legal narrative is documented in docs/legal/court-defensibility.md and pairs with the threat model. Three pieces in combination:
- Cryptographic invariants — HMAC chain, constant-time compare,
subtlecrate; refuses to resume from in-place-tampered logs. - Operational invariants — append-only, F_FULLFSYNC on macOS, structured
RecoveryReportfor crash recovery, golden-vector conformance asserted in CI. - Independent verification — verifier is a thin function (Rust + Python today, format-spec'd for any language); not a black box.
⚖️ The court-defensibility brief is currently engineering's read; the legal-team sign-off lands before v0.1.0 GA.
Status & versioning
- Library API (Rust + Python): alpha until v0.1.0. Pre-
v0.1.0, the surface MAY change between alpha tags; we'll call out breaking moves in CHANGELOG. - On-disk format: the segment-header layout, record schema, and HMAC chain are pinned by the committed golden vectors. Once v0.1.0 ships, the format is frozen until v0.2 (which lands under
tests/vectors/v0.2/so v0.1 readers continue to compile and pass). - MSRV: Rust 1.85 (edition 2024).
- Python: 3.9 + (abi3 wheels per
pyo3's abi3-py39 feature).
Choose your key source
Three options, all implementing the same KeyHandle trait:
| Source | Crate | Best for |
|---|---|---|
| In-memory | ogentic-audit-core |
Tests, CI, transient workloads |
| OS keychain | ogentic-audit-keychain |
Desktop apps (macOS / Linux / Windows) |
| KMS (server-side) | ogentic-audit-kms |
Server-side, containerised, multi-tenant deployments |
// KMS (server-side):
// let key = KmsKey::new(AwsKmsProvider::from_arn(arn).await?)?;
Full integration guide for the KMS option:
docs/integrations/server-side-kms.md.
Documentation
docs/spec/v0.1.md— language-agnostic on-disk format specdocs/spec/violation-report.md— normative JSON schema for verifier outputdocs/security/threat-model.md— adversaries, invariants, accepted residual riskdocs/security/key-rotation.md— customer-facing rotation policydocs/legal/court-defensibility.md— court-defensibility brief (draft)docs/adr/0001-on-disk-format.md— on-disk format rationale (ADR)docs/adr/0002-server-side-kms-key-sourcing.md— KMS key sourcing rationale (ADR)tests/vectors/v0.1/README.md— golden-vector layout + procedure for adding new vectorsdocs/integrations/sotto-desktop.md— embeddingogentic-audit-coreinside the Sotto Desktop Tauri shelldocs/integrations/server-side-kms.md— KMS integration guide (AWS KMSGenerateMac)examples/sotto-desktop-tauri/— minimal Tauri sample code
License
Apache License 2.0 — see LICENSE and NOTICE.
Security
SECURITY.md— responsible-disclosure address for vulnerability reports. Do not open public issues for tamper-evidence, HMAC, or cryptographic findings; email the listed address.
Contributing
See CONTRIBUTING.md and CODE_OF_CONDUCT.md. The project plan and open tickets live on Linear.
Release files for ogentic-audit 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ogentic_audit-0.3.0.tar.gz | 154.7 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| ogentic_audit-0.3.0-cp39-abi3-win_amd64.whl | CPython 3.9 | abi3 | Windows x86-64 | Details |
| ogentic_audit-0.3.0-cp39-abi3-manylinux_2_28_x86_64.whl | CPython 3.9 | abi3 | Linux glibc 2.28+ x86-64 | Details |
| ogentic_audit-0.3.0-cp39-abi3-manylinux_2_28_aarch64.whl | CPython 3.9 | abi3 | Linux glibc 2.28+ ARM64 | Details |
| ogentic_audit-0.3.0-cp39-abi3-macosx_11_0_arm64.whl | CPython 3.9 | abi3 | macOS 11.0+ ARM64 | Details |
| ogentic_audit-0.3.0-cp39-abi3-macosx_10_12_x86_64.whl | CPython 3.9 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 4.2 MB
Release files / ogentic_audit-0.3.0.tar.gz
| Download URL | ogentic_audit-0.3.0.tar.gz |
|---|---|
| Size | 154.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b6d2f54315a3087c86c0396af4720308f775e5dcf0afbbe738b2e0839e939347
|
|
BLAKE2b-256 checksum How to use checksums |
8a4c170beab9c623c3243a3399002a2e3c1a4eb71728fd2cdbddd90a4cd0be96
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.
Transparency logRelease files / ogentic_audit-0.3.0-cp39-abi3-win_amd64.whl
| Download URL | ogentic_audit-0.3.0-cp39-abi3-win_amd64.whl |
|---|---|
| Size | 834.1 kB |
| Tags | CPython 3.9 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
f5d3271731f15d19e258fd0f21c8843e67335deba38ffb991958908036c115bd
|
|
BLAKE2b-256 checksum How to use checksums |
0850f25e81b7370ab350f1552629a12f3842068e06a2c3d2c8b50761df29ad09
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.
Transparency logRelease files / ogentic_audit-0.3.0-cp39-abi3-manylinux_2_28_x86_64.whl
| Download URL | ogentic_audit-0.3.0-cp39-abi3-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 1.2 MB |
| Tags | CPython 3.9 Linux glibc 2.28+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
da2994ffba4b7c5016d53f08c89ef7f751dcf86cff0a2aca36486333a44290e8
|
|
BLAKE2b-256 checksum How to use checksums |
80baeda97b2f5181d55e6dc47dcd53f9990d1a4c8b0389fe72d03a81b1618786
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.
Transparency logRelease files / ogentic_audit-0.3.0-cp39-abi3-manylinux_2_28_aarch64.whl
| Download URL | ogentic_audit-0.3.0-cp39-abi3-manylinux_2_28_aarch64.whl |
|---|---|
| Size | 1.2 MB |
| Tags | CPython 3.9 Linux glibc 2.28+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
9689a3a666fd7b08b9723a46e1034ae0162a6dcaad58014b6f5108d236c87547
|
|
BLAKE2b-256 checksum How to use checksums |
6e34273aa162f51049f32040c2b5aa73f2b3ff7449207d440e64be65b4f134c7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.
Transparency logRelease files / ogentic_audit-0.3.0-cp39-abi3-macosx_11_0_arm64.whl
| Download URL | ogentic_audit-0.3.0-cp39-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 389.2 kB |
| Tags | CPython 3.9 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
9ba39fee39da445b899f488ff58a2a72afcedb545be8a29d00e9bbcadb2bcb5e
|
|
BLAKE2b-256 checksum How to use checksums |
eb11fbb9ef8a2b3ee5748fae9f04370125b4e02e29d2fe474cebdd8d041972c2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.
Transparency logRelease files / ogentic_audit-0.3.0-cp39-abi3-macosx_10_12_x86_64.whl
| Download URL | ogentic_audit-0.3.0-cp39-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 423.7 kB |
| Tags | CPython 3.9 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
26ce61471b2d25ee8635efd578c10dad6f14b93089fe9832140aefef527a640f
|
|
BLAKE2b-256 checksum How to use checksums |
8a47426451df9acefa221b3144e2b1a2d908bd1f33832629e6cf4df8cf0f1336
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.
Transparency log