Audit Trail
Immutable record of all governance decisions
Last reviewed: 2025-01-25
Audit Trail
The audit trail is the immutable record of all governance decisions. Every Intent and Judgment is recorded with full context.
Every Intent and its Judgment are recorded. Records cannot be modified or deleted. The audit chain is cryptographically verifiable.
How It Works
Hash Chain
Each audit entry references the previous entry's hash:
Entry 1 Entry 2 Entry 3
┌────────────┐ ┌────────────┐ ┌────────────┐
│ payload │ │ payload │ │ payload │
│ timestamp │ │ timestamp │ │ timestamp │
│ prevHash:∅ │──▶│ prevHash:A │──▶│ prevHash:B │
│ hash: A │ │ hash: B │ │ hash: C │
└────────────┘ └────────────┘ └────────────┘
This creates a tamper-evident chain. Any modification breaks the chain.
Entry Types
| Type | What's Recorded |
|---|---|
intent.submitted | Intent creation with full payload |
judgment.issued | Judgment with LIM evaluations |
escalation.created | Escalation routing |
escalation.resolved | Human decision |
override.applied | Human override |
policy.changed | Policy modifications |
Entry Structure
interface AuditEntry {
id: string; // Unique entry ID
type: AuditEntryType; // Entry type
timestamp: string; // ISO 8601 timestamp
// Payload varies by type
payload: {
intentId?: string;
judgment?: Judgment;
evidence?: EvidenceBundle;
actor?: string;
reason?: string;
};
// Chain integrity
sequenceNumber: number; // Monotonic sequence
previousHash: string; // SHA-256 of previous entry
hash: string; // SHA-256 of this entry
}
Immutability Guarantees
No Modification
The audit system has no UPDATE operations:
// These operations don't exist
auditStore.update(); // ❌ Not possible
auditStore.delete(); // ❌ Not possible
// Only append
auditStore.append(entry); // ✓ Only operation
No Deletion
Audit entries cannot be deleted:
- No DELETE API endpoint
- No internal deletion capability
- No TTL-based expiration (configurable retention, archival only)
Cryptographic Verification
Any entry can be verified:
const entry = await deltaos.audit.get(entryId);
// Verify hash
const computed = sha256(JSON.stringify({
id: entry.id,
type: entry.type,
timestamp: entry.timestamp,
payload: entry.payload,
sequenceNumber: entry.sequenceNumber,
previousHash: entry.previousHash
}));
assert(computed === entry.hash);
// Verify chain
const previous = await deltaos.audit.get(entry.previousId);
assert(previous.hash === entry.previousHash);
Querying the Audit Trail
Get Single Entry
const entry = await deltaos.audit.get(entryId);
Query by Intent
const entries = await deltaos.audit.list({
intentId: 'int_abc123'
});
// Returns all entries related to this Intent
// - Intent submission
// - Evidence collection
// - LIM evaluations
// - Judgment
// - Any overrides or escalations
Query by Time Range
const entries = await deltaos.audit.list({
since: '2025-01-01T00:00:00Z',
until: '2025-01-31T23:59:59Z',
type: 'override.applied'
});
Query by Actor
const entries = await deltaos.audit.list({
actor: 'user_123',
type: ['override.applied', 'escalation.resolved']
});
Verification
Chain Validation
Validate a range of entries:
const validation = await deltaos.audit.validateChain({
from: '2025-01-01T00:00:00Z',
to: '2025-01-31T23:59:59Z'
});
console.log(validation);
// {
// valid: true,
// entriesChecked: 50000,
// firstEntry: 'aud_first',
// lastEntry: 'aud_last',
// gapsFound: 0
// }
Single Entry Verification
const result = await deltaos.audit.verify(entryId);
console.log(result);
// {
// valid: true,
// hashMatches: true,
// chainIntact: true,
// previousEntry: 'aud_prev'
// }
Independent Verification
Entries can be verified without ΔOS:
import hashlib
import json
def verify_entry(entry, previous_entry):
# Verify hash
payload = json.dumps({
'id': entry['id'],
'type': entry['type'],
'timestamp': entry['timestamp'],
'payload': entry['payload'],
'sequenceNumber': entry['sequenceNumber'],
'previousHash': entry['previousHash']
}, sort_keys=True)
computed = hashlib.sha256(payload.encode()).hexdigest()
if computed != entry['hash']:
return False
# Verify chain
if entry['previousHash'] != previous_entry['hash']:
return False
return True
Replay
Re-evaluate historical decisions:
const replay = await deltaos.audit.replay(intentId);
console.log(replay);
// {
// originalJudgment: 'allow',
// replayJudgment: 'allow',
// match: true,
// evaluations: [
// { lim: 'rate-limiter', original: 'allow', replay: 'allow' },
// { lim: 'threshold-gate', original: 'allow', replay: 'allow' }
// ]
// }
Replay uses the evidence snapshot recorded at the time of original evaluation.
Retention
Default Retention
| Data Type | Hot Storage | Archive |
|---|---|---|
| Audit entries | 90 days | 7 years |
| Evidence snapshots | 90 days | 7 years |
| Intent data | 90 days | 7 years |
Custom Retention
Enterprise customers can configure retention:
await deltaos.retention.configure({
auditEntries: { hot: '1y', archive: '10y' },
evidenceSnapshots: { hot: '90d', archive: '7y' }
});
Compliance Holds
Prevent deletion for legal or compliance:
await deltaos.audit.hold({
reason: 'Legal hold - case #12345',
entries: { since: '2024-01-01', until: '2024-12-31' },
expiresAt: null // Indefinite
});
Export
Bulk Export
const export = await deltaos.audit.export({
since: '2025-01-01T00:00:00Z',
until: '2025-01-31T23:59:59Z',
format: 'json', // or 'csv', 'parquet'
destination: 's3://your-bucket/audit-export/'
});
Streaming Export
const stream = deltaos.audit.stream({
since: '2025-01-01T00:00:00Z',
types: ['judgment.issued', 'override.applied']
});
for await (const entry of stream) {
await sendToDataWarehouse(entry);
}
See Also
- Guarantees — Audit guarantees
- Components — System architecture
- Compliance — Compliance features