mati_core/store/
durability.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum Durability {
20 Immediate,
23 Eventual,
26}
27
28impl Durability {
29 pub fn for_key(key: &str) -> Self {
33 if key.starts_with("session:")
34 || key.starts_with("analytics:")
35 || key.starts_with("hook_event:")
36 || key.starts_with("compliance:")
37 || key.starts_with("graph:edge:")
38 || key.starts_with("health:") || key.starts_with("parse:") || key.starts_with("audit:session:")
41 {
43 Self::Eventual
44 } else {
45 Self::Immediate
46 }
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 #[test]
55 fn immediate_keys() {
56 assert_eq!(
57 Durability::for_key("gotcha:inference-async"),
58 Durability::Immediate
59 );
60 assert_eq!(
61 Durability::for_key("decision:storage-engine"),
62 Durability::Immediate
63 );
64 assert_eq!(
65 Durability::for_key("file:src/main.rs"),
66 Durability::Immediate
67 );
68 assert_eq!(Durability::for_key("stage:current"), Durability::Immediate);
69 assert_eq!(
70 Durability::for_key("dev_note:dont-refactor"),
71 Durability::Immediate
72 );
73 }
74
75 #[test]
76 fn eventual_keys() {
77 assert_eq!(
78 Durability::for_key("session:1710520800"),
79 Durability::Eventual
80 );
81 assert_eq!(
82 Durability::for_key("analytics:tokens_saved_total"),
83 Durability::Eventual
84 );
85 assert_eq!(
86 Durability::for_key("hook_event:pre_read"),
87 Durability::Eventual
88 );
89 assert_eq!(
90 Durability::for_key("compliance:2026-03-15"),
91 Durability::Eventual
92 );
93 }
94
95 #[test]
96 fn unknown_prefix_defaults_to_immediate() {
97 assert_eq!(
98 Durability::for_key("unknown:something"),
99 Durability::Immediate
100 );
101 }
102
103 #[test]
106 fn graph_edge_key_is_eventual() {
107 assert_eq!(
109 Durability::for_key("graph:edge:src/main.rs:HasGotcha:gotcha:inference-async"),
110 Durability::Eventual
111 );
112 }
113
114 #[test]
115 fn empty_key_defaults_to_immediate() {
116 assert_eq!(Durability::for_key(""), Durability::Immediate);
118 }
119
120 #[test]
121 fn key_without_colon_defaults_to_immediate() {
122 assert_eq!(Durability::for_key("gotcha"), Durability::Immediate);
124 assert_eq!(Durability::for_key("session"), Durability::Immediate);
125 }
126
127 #[test]
128 fn prefix_only_eventual_keys_are_eventual() {
129 assert_eq!(Durability::for_key("session:"), Durability::Eventual);
131 assert_eq!(Durability::for_key("analytics:"), Durability::Eventual);
132 assert_eq!(Durability::for_key("hook_event:"), Durability::Eventual);
133 assert_eq!(Durability::for_key("compliance:"), Durability::Eventual);
134 }
135
136 #[test]
137 fn all_immediate_prefixes_from_architecture_doc() {
138 let cases = [
140 "gotcha:inference-async",
141 "decision:storage-engine",
142 "file:src/store/db.rs",
143 "stage:current",
144 "dev_note:no-refactor",
145 "dep:cargo:tokio",
146 ];
147 for key in cases {
148 assert_eq!(
149 Durability::for_key(key),
150 Durability::Immediate,
151 "expected Immediate for '{key}'"
152 );
153 }
154 }
155
156 #[test]
157 fn eventual_prefix_requires_exact_colon_boundary() {
158 assert_eq!(
161 Durability::for_key("session_v2:something"),
162 Durability::Immediate
163 );
164 assert_eq!(
165 Durability::for_key("analytics_v2:something"),
166 Durability::Immediate
167 );
168 assert_eq!(
169 Durability::for_key("hook_event_extra:x"),
170 Durability::Immediate
171 );
172 }
173
174 #[test]
175 fn all_eventual_prefixes_from_architecture_doc() {
176 let cases = [
177 "session:1710520800",
178 "analytics:tokens_saved_total",
179 "hook_event:pre_read",
180 "compliance:2026-03-15",
181 "graph:edge:file:src/main.rs:imports:file:src/lib.rs",
182 ];
183 for key in cases {
184 assert_eq!(
185 Durability::for_key(key),
186 Durability::Eventual,
187 "expected Eventual for '{key}'"
188 );
189 }
190 }
191
192 #[test]
193 fn key_containing_eventual_prefix_as_embedded_substring_is_immediate() {
194 assert_eq!(
197 Durability::for_key("gotcha:session:something"),
198 Durability::Immediate,
199 "embedded 'session:' must not trigger Eventual routing"
200 );
201 assert_eq!(
202 Durability::for_key("file:analytics:performance.rs"),
203 Durability::Immediate,
204 "embedded 'analytics:' must not trigger Eventual routing"
205 );
206 assert_eq!(
207 Durability::for_key("decision:hook_event:design"),
208 Durability::Immediate,
209 "embedded 'hook_event:' must not trigger Eventual routing"
210 );
211 }
212
213 #[test]
216 fn audit_session_is_eventual() {
217 assert_eq!(
219 Durability::for_key("audit:session:1234567890"),
220 Durability::Eventual,
221 "audit:session:* must route to sessions tree"
222 );
223 }
224
225 #[test]
226 fn audit_knowledge_is_immediate() {
227 assert_eq!(
230 Durability::for_key("audit:knowledge:1234567890"),
231 Durability::Immediate,
232 "audit:knowledge:* must route to knowledge tree"
233 );
234 }
235
236 #[test]
237 fn audit_bare_prefix_is_immediate() {
238 assert_eq!(
240 Durability::for_key("audit:something"),
241 Durability::Immediate,
242 "unknown audit prefix must default to Immediate"
243 );
244 }
245}