1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//! Tamper-evident audit log.
//!
//! Every business-meaningful action in the Agent Exchange Protocol (AEX) — agent
//! registration, transfer initiation, scanner verdict, policy decision,
//! delivery, revocation — writes an [`Event`] to an [`AuditLog`].
//!
//! # Integrity model
//!
//! Events are **hash-chained**: each event stores the hash of the previous
//! event. This means any retroactive modification of an event breaks the
//! chain for every event that followed — you cannot rewrite history without
//! producing a visibly different chain head.
//!
//! Chain-head hashes are the basis for future Merkle-batching and Sigstore
//! Rekor submission (Phase G1). When that lands, the interface here does
//! not change — [`AuditLog::current_head`] just starts being submitted to
//! Rekor periodically.
//!
//! # Implementations
//!
//! - [`MemoryAuditLog`] — in-memory, used by tests and M1 demo.
//! - [`FileAuditLog`] — append-only JSONL file, one line per event. Used
//! by the dev-tier control plane.
//! - *(Phase 2)* `PostgresAuditLog` — events in Postgres with a maintained
//! `chain_head` table for fast reads.
//! - *(Phase G1)* `RekorAnchoredAuditLog<Inner>` — wraps any inner log and
//! periodically submits chain heads to the Sigstore Rekor transparency
//! log.
pub use ;
pub use ;
pub use FileAuditLog;
pub use MemoryAuditLog;
pub use ;
use async_trait;
/// Core audit log trait.
///
/// Implementations must be internally synchronized — concurrent callers
/// must see a serialized view of the chain. No external locking required.
/// Sentinel value used as the `prev_hash` of the first event in a fresh
/// chain. Chosen as the all-zeros 32-byte hash encoded as hex — sha256 of
/// the empty string would also work, but all-zeros is unambiguous and does
/// not accidentally match any real event.
pub const GENESIS_HEAD: &str = "0000000000000000000000000000000000000000000000000000000000000000";