Skip to main content

Cryptographically verifiable audit trail for AI systems — Ed25519 signed, hash-chained Decision Receipts with ISO 42001 / NIST AI RMF compliance mappings

Project description

ai-audit-trail

PyPI version Python License: MIT CI Downloads Tests mypy Ruff OpenSSF Scorecard

Prove what your AI did, why, and that nobody changed the record.

Tamper-evident Decision Receipts with Ed25519 signatures, SHA-256 hash-chains, and formal compliance mappings. No blockchain, no SaaS, no lock-in. Self-hosted, offline-verifiable, Python-native.


Why this exists

The EU AI Act becomes mandatory for high-risk AI systems in August 2026. It requires tamper-evident logs proving every decision was made correctly (Art. 12). Most teams are solving this with normal logging — which is neither tamper-evident nor legally defensible in an audit.

ai-audit-trail closes this gap with cryptographic receipts that any auditor can verify offline, without accessing your systems. Same principle as a blockchain — without the blockchain overhead, the SaaS dependency, or the vendor lock-in.

Who is this for

  • Regulated AI teams (FinTech, HealthTech, LegalTech, InsurTech) who must prove compliance
  • Enterprise platform teams deploying LLM agents with tool access
  • Security and compliance officers who need audit-ready evidence packages
  • Developers who want pip install and 3 lines of code, not a platform migration

What this library provides

ai-audit-trail provides the technical building blocks that support EU AI Act, ISO 42001, and NIST AI RMF compliance. It does not, by itself, guarantee regulatory compliance — compliance is an organizational obligation that extends beyond any single software component. See our Shared Responsibility Model below.


Installation

pip install ai-audit-trail                    # Core (Ed25519 + SHA-256 + PII)
pip install "ai-audit-trail[redis]"           # + Redis persistence
pip install "ai-audit-trail[otel]"            # + OpenTelemetry metrics
pip install "ai-audit-trail[all]"             # Everything

Requirements: Python 3.11+ | No external services required | Works air-gapped


Quickstart

from ai_audit import (
    AuditConfig, init_audit_config,
    ReceiptCollector, ReceiptStore, ReceiptAction,
    verify_chain, get_verify_key_hex,
)

# 1. Configure once at startup
init_audit_config(AuditConfig(is_production=False))
store = ReceiptStore()

# 2. Wrap every AI request
collector = ReceiptCollector(trace_id="req-1", tenant_id="acme")
collector.set_input("What is our GDPR policy?")
collector.add_check("safety", score=0.02, threshold=0.8, fired=False)
collector.set_output("Our GDPR policy states that...")
collector.set_action(ReceiptAction.ALLOW)
collector.emit(store)
collector.cleanup()

# 3. Verify tamper-evidence
result = verify_chain(store.get_by_tenant("acme"), get_verify_key_hex())
assert result.valid  # Ed25519 + SHA-256 + hash-chain verified

Architecture Overview

Receipt Creation        Verification & Compliance       Agentic AI Audit
─────────────────       ──────────────────────────      ──────────────────
ReceiptCollector   ──>  verify_chain()                  ToolCallReceipt
  set_input()           build_compliance_summary()      TraceGraph (DAG)
  add_check()           build_crosswalk()               BehavioralContract
  set_output()          export_evidence_package()       ProvenanceChain
  set_action()          SPRTMonitor
  emit()                DriftMonitor
       │                EpochManager
       v
  ReceiptStore     ──>  StorageBackend ABC
  (in-memory LRU)       InMemoryBackend
  + Redis (optional)    (your custom backends)
  + AuditBuffer

Core Features

Decision Receipts (Ed25519 + SHA-256 + Hash-Chain)

Every AI pipeline decision produces a Decision Receipt — a cryptographically sealed, hash-chained record:

What's proven How
Input integrity SHA-256 of NFKC-normalized, PII-stripped input
Output integrity SHA-256 of generated output
Check results Ordered check records with scores and thresholds
Decision Action taken (ALLOW / REJECT / ESCALATE / ...)
Model provenance Model ID + config digest
Non-repudiation Ed25519 signature (libsodium)
Ordering Hash-chain linkage (prev_receipt_hash)

Three-stage verification (< 0.1 ms per receipt):

Ed25519 signature  →  detects forgery
SHA-256 self-hash  →  detects corruption
Hash-chain link    →  detects insertions / deletions / reordering

PII Redaction (GDPR Art. 17)

Personal data is stripped before hashing — the audit log never contains raw PII.

from ai_audit import PiiConfig, PiiMode, PiiType

config = PiiConfig(
    enabled_types=frozenset({PiiType.EMAIL, PiiType.PHONE, PiiType.IP}),
    mode=PiiMode.REDACT,  # or HASH (SHA-256) or MASK (a***m)
)
collector = ReceiptCollector(tenant_id="acme", pii_config=config)
Mode alice@corp.com becomes
REDACT [EMAIL]
HASH 3d4e5f8a... (deterministic SHA-256)
MASK a***@c***.com

Crypto-Shredding (GDPR Right to Erasure)

Encrypt PII fields with per-tenant AES-256-GCM keys. Destroy the key = data permanently unreadable, hash-chain intact.

from ai_audit.shredding import AESGCMDEKStore, encrypt_field, shred_tenant

dek_store = AESGCMDEKStore()
dek_store.create_dek("tenant-acme")

field = encrypt_field("sensitive PII", dek_store, "tenant-acme")
shred_tenant("tenant-acme", dek_store)  # Key destroyed — data unrecoverable
# Hash-chain remains mathematically intact (hashes ciphertext, not plaintext)

Compliance & Governance

ISO 42001 / NIST AI RMF Crosswalk

Maps receipt data directly to recognized management controls with evidence pointers.

from ai_audit.crosswalk import build_crosswalk, nist_function_map

crosswalk = build_crosswalk(receipts, chain_intact=True)
for entry in crosswalk:
    print(f"[{entry.status}] {entry.framework} {entry.control_id}{entry.control_name}")

nist = nist_function_map(receipts)
print(nist["GOVERN"].coverage)   # 0.0–1.0
print(nist["MEASURE"].status)    # PASS / PARTIAL / FAIL

ISO 42001 Controls: A.6.2.8 (Logging), A.7.5 (Provenance), A.6.2.6 (Performance), A.8.4 (Output), A.5.3 (Risk) NIST AI RMF: GOVERN, MAP, MEASURE, MANAGE — with quantitative coverage scores

EU AI Act Compliance Reports

from ai_audit.report import ComplianceReportGenerator

gen = ComplianceReportGenerator(summary, verify_key_hex=get_verify_key_hex())
gen.to_markdown()   # Documentation portals
gen.to_json()       # Automated pipelines
gen.to_html()       # Air-gapped servers

Covers Art. 9 (Risk), Art. 12 (Record-Keeping), Art. 13 (Transparency), Art. 17 (Quality), Art. 18 (Logging).

Evidence Package Export (Offline Verification)

Self-contained signed ZIP for external auditors — no system access required.

from ai_audit.export import export_evidence_package, verify_evidence_package

export_evidence_package(receipts, verify_key_hex, signing_key, "audit_2026.zip")
# Bundle: receipts.jsonl + chain_metadata.json + public_key.hex + manifest.json (signed) + verify.py

# Auditor verifies offline:
# python -m ai_audit verify audit_2026.zip

Continuous Certification (SPRT)

Sequential Probability Ratio Test — live compliance status per tenant.

from ai_audit.sprt import SPRTMonitor

monitor = SPRTMonitor(tenant_id="acme")
for receipt in receipts:
    state = monitor.update(is_reject=(receipt.action == "reject"))
print(state.status)      # CERTIFIED | MONITORING | FLAGGED
print(state.confidence)  # 0.0–1.0

Drift Detection (Jensen-Shannon Divergence)

Detects behavioral shifts in real-time — pure Python, no scipy required.

from ai_audit.drift import DriftMonitor

monitor = DriftMonitor(window_size=100)
for receipt in receipts:
    state = monitor.update(receipt.action.value)
print(state.status)       # STABLE | DRIFTING | CRITICAL_DRIFT
print(state.drift_score)  # JSD 0.0–1.0

Agentic AI Audit (World-First)

Agent Behavioral Contracts

Formal (p, delta, k)-Satisfaction with Reliability Index Theta — transforms EU AI Act requirements into testable specifications.

from ai_audit.contracts import BehavioralContract, Constraint, ContractMonitor

contract = BehavioralContract(
    contract_id="safety-v1",
    constraints=[
        Constraint(name="no_pii_leak", kind="hard", field="action", operator="!=", value="reject"),
        Constraint(name="quality", kind="soft", field="checks.safety.score", operator="<=", value=0.1, delta=0.5),
    ],
)
monitor = ContractMonitor(contract)
for receipt in receipts:
    state = monitor.evaluate(receipt)

print(state.p)                   # Hard constraint satisfaction probability
print(state.delta)               # Maximum soft deviation observed
print(state.k)                   # Recovery steps after last violation
print(state.reliability_index)   # Theta: single compliance metric (0.0–1.0)
print(state.status)              # COMPLIANT | DEGRADED | VIOLATED

Cryptographic Tool-Call Receipts

Every agent API call Ed25519-signed — no existing framework provides this.

from ai_audit.toolcall import seal_tool_call, verify_tool_call_chain

receipt = seal_tool_call(
    agent_id="researcher",
    tool_name="web_search",
    tool_args={"query": "EU AI Act compliance"},
    tool_result="Found 5 relevant documents...",
    private_key=signing_key,
    tenant_id="acme",
)
assert receipt.verify(signing_key.verify_key)

Multi-Agent Trace-Graphs (DAG)

Audit delegation, handoff, and parallel orchestration — not just linear logs.

from ai_audit.tracegraph import TraceGraph

graph = TraceGraph(trace_id="workflow-1", tenant_id="acme")
root = graph.add_node(agent_id="orchestrator", action="plan")
graph.add_node(agent_id="researcher", action="search", parent_id=root.node_id)
graph.add_node(agent_id="writer", action="draft", parent_id=root.node_id)

assert graph.verify_integrity()  # Hash-based tamper detection
assert not graph.has_cycles()    # DAG validation
lineage = graph.get_agent_lineage(leaf_node.node_id)  # Root-to-leaf trace

Epistemische Integritat / Unforgeable Provenance

Track WHERE every piece of information came from — proves a decision was not influenced by prompt injection.

from ai_audit.provenance import ProvenanceChain, ProvenanceRecord, SourceType

chain = ProvenanceChain(receipt_id="r1", tenant_id="acme")
chain.add(ProvenanceRecord(source_type=SourceType.SYSTEM, source_id="prompt", trust_level=1.0, content_hash="..."))
chain.add(ProvenanceRecord(source_type=SourceType.DOCUMENT, source_id="doc-123", trust_level=0.8, content_hash="..."))
chain.add(ProvenanceRecord(source_type=SourceType.UNKNOWN, source_id="???", trust_level=0.0, content_hash="..."))

summary = chain.trust_summary()
print(summary.system_grounded)       # True — has SYSTEM source
print(summary.potentially_injected)  # True — has UNKNOWN source
print(summary.min_trust)             # 0.0 — weakest link

High-Throughput Architecture

Merkle-Tree Batch Sealing (RFC 6962)

Chain-of-Roots instead of chain-of-receipts — O(log N) verification per batch.

from ai_audit.batch import MerkleBatcher

batcher = MerkleBatcher(tenant_id="acme", private_key=key, max_batch_size=2048)
for receipt in receipts:
    seal = batcher.add(receipt.receipt_id, receipt.seal_payload())
    if seal:  # Auto-flushed at 2048 receipts
        print(f"Batch sealed: {seal.merkle_root[:16]}...")

assert batcher.verify_chain_of_roots(key.verify_key)

Chain Epochs / Rollover

Prevent unbounded chain growth. Old epochs can be archived or deleted.

from ai_audit.epochs import EpochManager

mgr = EpochManager(tenant_id="acme", private_key=key, max_epoch_size=10_000)
for receipt in receipts:
    seal = mgr.add_receipt(receipt)  # Auto-seals at 10k
mgr.seal_epoch()                     # Or explicit rollover
assert mgr.verify_epoch_chain(key.verify_key)

Ring-Buffer with Backpressure

Bounded buffer for high-throughput ingestion — fail-closed, no silent data loss.

from ai_audit.buffer import AuditBuffer, AuditBufferFullError

buffer = AuditBuffer(maxsize=50_000)  # ~5 seconds at 10k req/s
try:
    buffer.put(receipt)
except AuditBufferFullError:
    # Backpressure — reject the request rather than lose audit data
    pass
batch = buffer.drain(max_items=2048)

Storage Backend ABCs

Pluggable persistence — bring your own database.

from ai_audit.storage import StorageBackend, InMemoryBackend

# Use the reference implementation for dev/test
backend = InMemoryBackend(max_receipts=50_000)

# Or implement your own:
class PostgresBackend(StorageBackend):
    def write_receipt(self, receipt): ...
    def read_receipt(self, receipt_id): ...
    def query_by_tenant(self, tenant_id, limit=100): ...
    def healthcheck(self) -> bool: ...

OpenTelemetry Instrumentation

Native metrics for SRE dashboards — graceful no-op without OTel SDK.

# pip install "ai-audit-trail[otel]"
from ai_audit.telemetry import record_seal, record_append, record_drift

record_seal(duration_seconds=0.000045, tenant_id="acme")
record_append(tenant_id="acme", async_mode=True)
record_drift(score=0.03, tenant_id="acme")

Metrics: ai_audit.seal_duration_seconds, ai_audit.append_total, ai_audit.redis_fallback_total, ai_audit.chain_break_total, ai_audit.drift_score, ai_audit.buffer_size, ai_audit.epoch_sealed_total


Production Setup

Persistent Signing Key

python -c "import nacl.signing; print(nacl.signing.SigningKey.generate().encode().hex())"
init_audit_config(AuditConfig(is_production=True, signing_key_hex="your-64-char-hex-key"))

KMS Integration

from ai_audit import KeyProvider, init_key_provider

class VaultKeyProvider(KeyProvider):
    def get_signing_key(self) -> nacl.signing.SigningKey:
        secret = vault_client.secrets.kv.read_secret("secret/ai-audit/key")
        return nacl.signing.SigningKey(bytes.fromhex(secret["data"]["key"]))
    def get_verify_key_hex(self) -> str:
        return self.get_signing_key().verify_key.encode().hex()

init_key_provider(VaultKeyProvider())

Redis Persistence

import redis
store = ReceiptStore(redis_client=redis.Redis(), use_lua=True)  # Lua mode: 10k+ req/s

Shared Responsibility Model

Responsibility Library Deployer
Ed25519 + SHA-256 signing and hashing X
Hash-chain integrity X
PII redaction (REDACT/HASH/MASK) X
Merkle-Tree batch sealing (RFC 6962) X
SPRT compliance certification X
ISO 42001 / NIST AI RMF mapping X
Evidence Package export + verification X
Crypto-Shredding (AES-256-GCM) X
Agent Behavioral Contracts X
OpenTelemetry metrics X
Secure key storage (HSM/Vault) X
PII type configuration X
Durable storage backend X
Access controls / RBAC X
Human oversight (EU AI Act Art. 14) X
Clock synchronization (NTP) X
Incident response X
Regulatory compliance certification X

Examples

See the examples/ directory:


Performance

Operation Typical Latency Notes
seal() (hash + sign) < 100 us Ed25519 via libsodium C
verify_chain(1000) < 50 ms Scales linearly
merkle_root(2048) < 5 ms RFC 6962 SHA-256
Memory per receipt ~1 KB Pydantic V2 + orjson

Run benchmarks: pytest tests/test_benchmark.py -v -s


Project Stats

Metric Value
Tests 196
Source modules 26
__all__ exports 60
Type checking mypy --strict, 0 errors
Linting ruff, 0 errors
Python versions 3.11, 3.12, 3.13
Security scans 3 completed, 6 fixes applied
NB validators consulted 5 (Architecture, Enterprise, Performance, Agentic, Branding)

Security

See SECURITY.md for the full threat model, vulnerability reporting process, and supported versions.

See CONTRIBUTING.md for architecture invariants, the shared responsibility model, and contribution guidelines.


License

MIT — free for commercial use.


Created and maintained by

S&S Connect — Building trust infrastructure for autonomous AI systems.

If you use ai-audit-trail in production or research, we'd love to hear about it.

Project details


Download files

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

Source Distribution

ai_audit_trail-0.4.5.tar.gz (240.5 kB view details)

Uploaded Source

Built Distribution

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

ai_audit_trail-0.4.5-py3-none-any.whl (90.9 kB view details)

Uploaded Python 3

File details

Details for the file ai_audit_trail-0.4.5.tar.gz.

File metadata

  • Download URL: ai_audit_trail-0.4.5.tar.gz
  • Upload date:
  • Size: 240.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ai_audit_trail-0.4.5.tar.gz
Algorithm Hash digest
SHA256 18d9c1299dc564c407cd000db28ab873f420d694d6ac0665c5530cc89521e5b0
MD5 36fbb2f74ba2a646f75deb1d24ff152a
BLAKE2b-256 4384c7a85af08bab2ee6c0fa1997e8330ae0f8c1e82d42c1b0b4577f26b2eca4

See more details on using hashes here.

Provenance

The following attestation bundles were made for ai_audit_trail-0.4.5.tar.gz:

Publisher: publish.yml on sundsoffice-tech/ai-audit-trail

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

File details

Details for the file ai_audit_trail-0.4.5-py3-none-any.whl.

File metadata

  • Download URL: ai_audit_trail-0.4.5-py3-none-any.whl
  • Upload date:
  • Size: 90.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ai_audit_trail-0.4.5-py3-none-any.whl
Algorithm Hash digest
SHA256 599753b9f0b6973d37114a25a5caffe5ab1193039b8743fdbcf87107b7645197
MD5 ae3831e09f2484ba1cb9c33bea162f1f
BLAKE2b-256 ce5ab2e1ed06d5a21d4d0334806e9bf5e4926d8e87837351990da8d4d976a876

See more details on using hashes here.

Provenance

The following attestation bundles were made for ai_audit_trail-0.4.5-py3-none-any.whl:

Publisher: publish.yml on sundsoffice-tech/ai-audit-trail

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

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page