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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//! Audit-event sink trait + plumbing.
//!
//! [`FoldKind::audit_event`](super::FoldKind::audit_event) is
//! called on every applied transition; the returned
//! [`AuditEvent`] is forwarded to the
//! installed [`FoldAuditSink`]. Default install is `None`, in
//! which case audit emission is effectively a no-op; sinks can
//! be installed at any time via
//! [`super::Fold::set_audit_sink`] — `tracing` adapter, the
//! project's signed-audit chain, a Prometheus counter exporter,
//! an in-memory ring for tests, etc.
use AuditEvent;
/// Sink that consumes audit events emitted by a fold's
/// transitions.
///
/// Implementors are typically:
/// - A `tracing` adapter that emits via `tracing::info!` /
/// `tracing::warn!` on the appropriate level.
/// - A bridge to the project's existing signed-audit chain
/// (writes to the same `FoldAuditSink` interface used by the
/// safety / replication layers).
/// - A `Vec<AuditEvent>`-backed ring buffer for tests + Deck
/// panel "recent transitions" view.
///
/// The `record` hook is fire-and-forget by contract: a slow
/// sink slows the apply (or expiry) path because the call sites
/// invoke `record` synchronously under the fold's locks. Real
/// implementations push to a channel and drain in a worker.
/// No-op audit sink. Constructed implicitly when no sink is
/// installed via [`super::Fold::set_audit_sink`]; surfaced
/// publicly for tests / call sites that want an explicit
/// "discard" sink without an `Option` wrapper.
;
/// `Vec<AuditEvent>`-backed sink for tests. Records every event
/// in insertion order; tests inspect the stored vec to assert
/// the apply / evict / expiry paths emit the right transitions.
///
/// Thread-safe — the inner storage is wrapped in a
/// `parking_lot::Mutex` so `record` is callable from concurrent
/// fold operations. Use [`Self::snapshot`] to read the recorded
/// events at any point.
/// Bounded ring-buffer audit sink. Keeps the most recent
/// `capacity` events; oldest are dropped first when full. This
/// is the sink the Deck FOLDS panel's "recent transitions" view
/// consumes — operators want the last N events, not a complete
/// history. Bounded capacity also makes this safe to install on
/// a high-throughput fold without unbounded memory growth.