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.

Audit Guarantee

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

TypeWhat's Recorded
intent.submittedIntent creation with full payload
judgment.issuedJudgment with LIM evaluations
escalation.createdEscalation routing
escalation.resolvedHuman decision
override.appliedHuman override
policy.changedPolicy 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 TypeHot StorageArchive
Audit entries90 days7 years
Evidence snapshots90 days7 years
Intent data90 days7 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