Skip to main content

auditchain

CI

Tamper-evident, hash-chained audit logging for Python. Async-first, zero runtime dependencies.

Every record commits to the hash of the previous one. Anyone who edits, inserts, removes or reorders records later breaks the chain — and verify tells you exactly where. Built for compliance (SOC 2, ISO 27001, PCI) and for any system where "who did what" must be provable after the fact.

How it works

record[0].hash = SHA-256(prev_hash(genesis) || payload[0])
record[1].hash = SHA-256(record[0].hash   || payload[1])
...

With a seal_key, records are signed with HMAC-SHA256 instead, so a party that does not hold the key cannot silently rewrite the log at all. Verification recomputes the whole chain in O(n) and reports the first broken link.

Features

  • Async-first API (AuditLog) plus thin sync wrappers (SyncAuditLog)
  • Backends: SqliteBackend, JsonlBackend, MemoryBackend (more planned)
  • HMAC-SHA256 sealing, or plain SHA-256 integrity without a key
  • verify() API and a verify CLI (exit code 1 on failure — CI friendly)
  • Zero runtime dependencies, Python 3.10+, fully typed (py.typed)

Install

pip install auditchain

Quickstart (async)

import asyncio
from auditchain import AuditLog, SqliteBackend

async def main():
    async with AuditLog(SqliteBackend("audit.sqlite")) as log:
        await log.append("sara", "login", "admin", metadata={"ip": "10.0.0.1"})
        await log.append("jawad", "payment.approve", "invoice:12", metadata={"amount": 1200})

        report = await log.verify()
        print(report)  # OK: 2 record(s) verified

asyncio.run(main())

Sealing records (HMAC)

from auditchain import AuditLog, SqliteBackend

key = secrets.token_bytes(32)
log = AuditLog(SqliteBackend("audit.sqlite"), seal_key=key)

Without a seal_key, tampering is still detected — but only by integrity; anyone who can write the log can rewrite it and re-seal it. Use a key when attackers might have write access. Keep the key outside the log (env var, secret manager, file).

Sync API

from auditchain import JsonlBackend, SyncAuditLog

log = SyncAuditLog(JsonlBackend("audit.jsonl"))
log.append("sara", "login")
assert log.verify().ok
log.close()

SyncAuditLog runs its own event loop per call; use the async API from inside an already-running loop.

Backends

Backend Used for
SqliteBackend Real applications (durable, queryable)
JsonlBackend Simple logs, git-friendly, streaming-friendly
MemoryBackend Short-lived processes, tests

Verify from the CLI

# format is auto-detected from the extension
python -m auditchain verify audit.sqlite
auditchain verify audit.jsonl --seal-key-file seal.key --expected-count 1000

Example output when the log was tampered with:

$ python -m auditchain verify audit.jsonl
FAILED at seq 1: hash mismatch: the record was modified

Exit code 0 on success, 1 when the chain is broken, 2 on usage/file errors — so it drops straight into CI.

Security model — be honest about limits

  • Detected: modification of any record, insertion, reordering, removal of middle records, sequence gaps, count mismatches (with --expected-count).
  • Not detectable from the chain alone: removal of the last records (tail truncation). Pass expected_count to verify() if that matters to you.
  • Single writer: one process appends at a time. Concurrent appends are not supported in 0.1.
  • Without a seal_key, records are integrity-protected, not authenticated.

Roadmap

  • 0.2: Postgres backend, key rotation, periodic checkpoints for huge logs

Why hash chains?

Read the full argument — threat model, honest limits, and when to anchor digests — in Why your audit log needs a hash chain.

خلاصهٔ فارسی

auditchain یک کتابخانهٔ پایتونی برای لاگ حسابرسیِ ضدتغییر است. هر رکورد با هشِ رکورد قبلی زنجیر می‌شود (و در صورت دادن seal_key با HMAC-SHA256 امضا می‌گردد)، بنابراین هر تغییر بعدی — ویرایش، جابه‌جایی، حذف یا درج — زنجیره را می‌شکند و verify دقیقاً نشان می‌دهد کجا. بدون وابستگی، async-first، با بک‌اندهای SQLite/JSONL و یک CLI که خروجی آن برای CI مناسب است (کد خروج ۱ یعنی زنجیره شکسته).

License

MIT — see LICENSE.


Made ❤️ by Mohammad — @llllxyz

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

auditchain-0.1.0.tar.gz (16.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

auditchain-0.1.0-py3-none-any.whl (15.5 kB view details)

Uploaded Python 3

File details

Details for the file auditchain-0.1.0.tar.gz.

File metadata

  • Download URL: auditchain-0.1.0.tar.gz
  • Upload date:
  • Size: 16.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for auditchain-0.1.0.tar.gz
Algorithm Hash digest
SHA256 df18a4f0404326857a3a449300b655ded04433013136326bc5291b9a91346bc5
MD5 0863d975a2294c945e8c53d6210e2387
BLAKE2b-256 b66b1f61132b5a4d33aedc278f0219762245de577f51350c2b11b6a528894176

See more details on using hashes here.

Provenance

The following attestation bundles were made for auditchain-0.1.0.tar.gz:

Publisher: release.yml on mmdverse/auditchain

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file auditchain-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: auditchain-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 15.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for auditchain-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0617b548ff1e7f5c31646895355118d322b2001c650573f44fab794b85a2b8fb
MD5 3baa6d66b0109500bac32bb9ae4f6c55
BLAKE2b-256 dd59284c709b5eabee983207b1a1d6afab55ddd234d97f0a73bdc2a724cfc11e

See more details on using hashes here.

Provenance

The following attestation bundles were made for auditchain-0.1.0-py3-none-any.whl:

Publisher: release.yml on mmdverse/auditchain

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.2.0

2 files

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page