Skip to main content

audit.proto

Every intercepted tool call produces one or more audit entries. Each entry is signed with Ed25519 and chain-linked via SHA-256 hash of the previous entry’s signature, providing tamper-evident audit trails.

AuditEntry

message AuditEntry {
  string id = 1;                  // Unique entry ID
  string timestamp = 2;          // ISO-8601
  string server_name = 3;
  Direction direction = 4;       // REQUEST or RESPONSE
  string method = 5;             // JSON-RPC method
  string message_id = 6;
  string tool_name = 7;
  bytes arguments_json = 8;      // Tool call arguments
  bytes response_json = 9;       // Tool response (if RESPONSE)
  Verdict verdict = 10;          // Policy decision
  string policy_hash = 11;       // Hash of active policy at decision time
  bytes prev_hash = 12;          // SHA-256 of previous entry's signature
  bytes signature = 13;          // Ed25519 signature over canonical entry
  string public_key = 14;        // SPKI PEM of signing key
  string nonce = 15;             // UUID for replay protection
}

Integrity Model

Entry 1                Entry 2                Entry 3
┌──────────┐          ┌──────────┐          ┌──────────┐
│ data     │          │ data     │          │ data     │
│ nonce    │          │ nonce    │          │ nonce    │
│ prev: ∅  │──sig──→  │ prev:    │──sig──→  │ prev:    │
│ sig: S1  │          │  H(S1)   │          │  H(S2)   │
└──────────┘          │ sig: S2  │          │ sig: S3  │
                      └──────────┘          └──────────┘
  • Ed25519 signatures: Each entry signed over its canonical representation
  • Chain linking: prev_hash = SHA-256(previous_entry.signature)
  • Replay protection: UUID nonce per entry prevents replay attacks
  • Policy snapshot: policy_hash records which policy version was active when the decision was made

AuditBundle

Collection of entries for export and offline verification.
message AuditBundle {
  repeated AuditEntry entries = 1;
  string public_key = 2;        // Signing key for the bundle
  string exported_at = 3;       // ISO-8601 export timestamp
}

Verification

To verify an audit trail:
  1. For each entry, verify the Ed25519 signature against the entry’s public key
  2. For each entry after the first, verify prev_hash == SHA-256(previous_entry.signature)
  3. Verify each nonce is unique (no replays)
  4. Verify timestamps are monotonically increasing
The QuintProxyService.VerifyAuditLog RPC performs this verification server-side. Bundles can also be verified offline using the exported public key.