Skip to main content

Audit Trail

Every action in Anvil produces an auditable record. This page explains how provenance works and why it matters.

Why Audit Trails?

When AI generates code, you need to answer:

  • What was validated? — which checks ran on which files
  • When was it validated? — timestamps for compliance
  • What was the result? — pass, fail, warnings
  • Can I reproduce it? — same inputs, same outputs

Anvil's audit trail answers all of these.

Provenance Model

Provenance tracks the origin and lineage of every artefact:

┌─────────────────────────────────────────────────────┐
│ Evidence │
├─────────────────────────────────────────────────────┤
│ What: run_abc123 validated src/auth/login.ts │
│ When: 2024-01-15T10:30:00Z │
│ Who: developer@example.com │
│ How: anvil run (watch mode) │
│ Config: sha256:config123 │
│ Result: PASS (all 4 checks) │
│ Signature: sha256:evidence789 │
└─────────────────────────────────────────────────────┘

Provenance Fields

FieldDescription
subjectWhat was validated (files, commits)
timestampWhen validation occurred
actorWho triggered validation
methodHow validation was triggered
configurationConfig hash at time of validation
resultValidation outcome
signatureCryptographic integrity hash

Trust Model

Anvil's trust model is based on verifiable claims:

1. Configuration is Versioned

Every run records the configuration hash:

{
"config_version": "1.0",
"config_hash": "sha256:abc123",
"gates_enabled": ["architecture", "anti-patterns", "secrets"]
}

If configuration changes, the hash changes. You can prove what rules were active.

2. Inputs are Recorded

Every run records input file hashes:

{
"inputs": [
{ "path": "src/auth/login.ts", "hash": "sha256:file123" },
{ "path": "src/auth/types.ts", "hash": "sha256:file456" }
]
}

3. Results are Signed

Evidence is cryptographically signed:

{
"evidence_hash": "sha256:evidence789",
"signature_algorithm": "sha256",
"signed_at": "2024-01-15T10:30:00Z"
}

Tampering with evidence changes the hash, invalidating the signature.

4. Chain of Custody

Sessions link runs together:

Session: session_abc123
├── Run 1: run_001 (10:30:00) → PASS
├── Run 2: run_002 (10:35:00) → FAIL (fixed)
├── Run 3: run_003 (10:36:00) → PASS
└── Commit: abc123def456

Querying the Audit Trail

List Recent Evidence

anvil evidence list --since 7d

Output:

ID              RUN         TIMESTAMP              STATUS  FILES
evidence_001 run_abc123 2024-01-15T10:30:00Z PASS 3
evidence_002 run_def456 2024-01-15T11:00:00Z FAIL 1
evidence_003 run_ghi789 2024-01-15T11:05:00Z PASS 1

View Evidence Details

anvil evidence show evidence_001

Verify Evidence Integrity

anvil evidence verify evidence_001

Output:

Verifying evidence_001...
✓ Hash matches content
✓ Inputs recorded
✓ Configuration referenced
✓ Signature valid

Evidence is valid.

Export for Compliance

anvil evidence export --session session_abc123 --format json > audit.json

Integration with Git

Anvil can attach evidence to commits:

# Include evidence reference in commit
git commit -m "feat: add login endpoint" \
--trailer "Anvil-Evidence: evidence_001"

# Or use Anvil's commit helper
anvil commit -m "feat: add login endpoint"

The evidence ID in the commit trailer links to the full audit record.

Retention and Storage

Default Storage

Evidence is stored in .anvil/evidence/:

.anvil/
└── evidence/
├── 2024-01/
│ ├── evidence_001.json
│ └── evidence_002.json
└── 2024-02/
└── evidence_003.json

Retention Policy

Configure retention:

{
"evidence": {
"retention": {
"duration": "90d",
"keep_failures": true,
"compress_after": "7d"
}
}
}

Remote Storage

For compliance, evidence can be pushed to remote storage:

{
"evidence": {
"remote": {
"type": "s3",
"bucket": "company-anvil-evidence"
}
}
}

Next: Solo dev workflow →