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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//! Abstract storage backend trait.
//!
//! The [`StorageBackend`] trait extracts the pure I/O surface that
//! [`crate::Storage`] exposes to its consumers — the kernel's effect
//! executor in `kimberlite::KimberliteInner`, primarily. It exists so
//! that the same `Kimberlite` facade can run on-disk (production,
//! default) or entirely in RAM (tests, ephemeral workers, fuzzers),
//! without the outer API being polluted by backend-specific details.
//!
//! ## What this trait is
//!
//! - A pure I/O surface: append, read, chain-hash recovery, segment
//! accounting, and a best-effort flush.
//! - Dyn-compatible (object-safe): consumers hold `Box<dyn
//! StorageBackend>` so they can swap backends at runtime without a
//! generic parameter leaking into the rest of the codebase.
//!
//! ## What this trait is NOT
//!
//! - The kernel's `kimberlite-kernel::traits::Storage` trait — that
//! one models a much simpler key/value style API used by the
//! effect-executor prototype and is separate. Don't confuse them.
//! - A fault-injection surface. `kimberlite-sim::SimStorage` has its
//! own shape with explicit failure modes (torn writes, latency,
//! corruption) and is intentionally not a `StorageBackend`.
//!
//! ## Implementations
//!
//! - [`crate::Storage`]: the production on-disk implementation.
//! Segment files, CRC32, hash chain, checkpoint index.
//! - [`crate::MemoryStorage`]: a pure in-memory backend that preserves
//! hash-chain determinism (same append sequence → same chain hash).
//! No fsync, no mmap, no disk. Intended for tests, sandboxes, and
//! short-lived worker processes.
//!
//! ## FCIS compliance
//!
//! The trait is deliberately narrow — no runtime, no clock, no
//! `Effect` types cross this boundary. It exposes only the
//! read/write/chain-state primitives the imperative shell needs. Pure
//! kernel code never touches it.
//!
//! ## Why `&mut self` everywhere
//!
//! Both the on-disk and in-memory backends maintain mutable caches
//! (offset index, manifest, chain state). `&mut` keeps the trait
//! faithful to that reality; callers already hold the backend behind
//! a `RwLock` in `Kimberlite::submit`, so this isn't a meaningful
//! constraint in practice.
//!
//! ## Stability
//!
//! Public for downstream users to implement their own backends (e.g.
//! test doubles), but the method set may grow between minor versions
//! as more of `Storage`'s surface is pulled behind the trait.
//! Changes will be additive — existing impls won't break.
use Bytes;
use ChainHash;
use ;
use crateStorageError;
/// Abstract storage backend used by `KimberliteInner`'s effect executor.
///
/// See module-level docs for scope and semantics. Implementations must
/// uphold:
///
/// 1. **Append-only**: `append_batch` never overwrites existing records.
/// 2. **Hash-chain determinism**: given the same `(stream_id, events,
/// expected_offset, prev_hash)` sequence, two different backends
/// must produce the same final `ChainHash`. Tests enforce this
/// between [`crate::Storage`] and [`crate::MemoryStorage`].
/// 3. **Offset monotonicity**: the returned offset must equal
/// `expected_offset + events.len()`.
/// 4. **Read visibility**: records become visible to `read_from`
/// immediately after `append_batch` returns.