1use crate::serde_json::Value as JsonValue;
20use crate::storage::UnifiedStore;
21
22#[inline]
23fn num(v: f64) -> JsonValue {
24 JsonValue::Number(v)
25}
26
27#[inline]
28fn text(s: &str) -> JsonValue {
29 JsonValue::String(s.to_string())
30}
31
32#[derive(Debug, Clone)]
35pub struct ConfigDefault {
36 pub key: &'static str,
37 pub tier: Tier,
38 pub default: fn() -> JsonValue,
42}
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq)]
45pub enum Tier {
46 Critical,
48 Optional,
50}
51
52pub const MATRIX: &[ConfigDefault] = &[
54 ConfigDefault {
56 key: "ask.max_prompt_tokens",
57 tier: Tier::Optional,
58 default: || num(8192.0),
59 },
60 ConfigDefault {
61 key: "ask.max_completion_tokens",
62 tier: Tier::Optional,
63 default: || num(1024.0),
64 },
65 ConfigDefault {
66 key: "ask.max_sources_bytes",
67 tier: Tier::Optional,
68 default: || num(262_144.0),
69 },
70 ConfigDefault {
71 key: "ask.timeout_ms",
72 tier: Tier::Optional,
73 default: || num(30_000.0),
74 },
75 ConfigDefault {
76 key: "ask.daily_cost_cap_usd",
77 tier: Tier::Optional,
78 default: || text(""),
79 },
80 ConfigDefault {
81 key: "ask.audit.include_answer",
82 tier: Tier::Optional,
83 default: || JsonValue::Bool(false),
84 },
85 ConfigDefault {
86 key: "ask.audit.retention_days",
87 tier: Tier::Optional,
88 default: || num(90.0),
89 },
90 ConfigDefault {
91 key: "ask.cache.enabled",
92 tier: Tier::Optional,
93 default: || JsonValue::Bool(false),
94 },
95 ConfigDefault {
96 key: "ask.cache.default_ttl",
97 tier: Tier::Optional,
98 default: || text(""),
99 },
100 ConfigDefault {
101 key: "ask.cache.max_entries",
102 tier: Tier::Optional,
103 default: || num(1024.0),
104 },
105 ConfigDefault {
107 key: "cache.blob.l1_bytes_max",
108 tier: Tier::Critical,
109 default: || num(crate::storage::cache::DEFAULT_BLOB_L1_BYTES_MAX as f64),
110 },
111 ConfigDefault {
112 key: "cache.blob.l2_bytes_max",
113 tier: Tier::Critical,
114 default: || num(crate::storage::cache::DEFAULT_BLOB_L2_BYTES_MAX as f64),
115 },
116 ConfigDefault {
117 key: "cache.blob.max_namespaces",
118 tier: Tier::Critical,
119 default: || num(crate::storage::cache::DEFAULT_BLOB_MAX_NAMESPACES as f64),
120 },
121 ConfigDefault {
128 key: "storage.binary_document_body",
129 tier: Tier::Optional,
130 default: || JsonValue::Bool(false),
131 },
132 ConfigDefault {
134 key: "durability.mode",
135 tier: Tier::Critical,
136 default: || text("sync"),
137 },
138 ConfigDefault {
140 key: "runtime.result_cache.backend",
141 tier: Tier::Critical,
142 default: || text("legacy"),
143 },
144 ConfigDefault {
148 key: "runtime.result_cache.enabled",
149 tier: Tier::Critical,
150 default: || JsonValue::Bool(true),
151 },
152 ConfigDefault {
155 key: "runtime.result_cache.ttl_seconds",
156 tier: Tier::Optional,
157 default: || num(30.0),
158 },
159 ConfigDefault {
162 key: "runtime.result_cache.capacity_entries",
163 tier: Tier::Optional,
164 default: || num(1000.0),
165 },
166 ConfigDefault {
168 key: "concurrency.locking.enabled",
169 tier: Tier::Critical,
170 default: || JsonValue::Bool(true),
171 },
172 ConfigDefault {
173 key: "concurrency.locking.deadlock_timeout_ms",
174 tier: Tier::Optional,
175 default: || num(5000.0),
176 },
177 ConfigDefault {
179 key: "storage.wal.max_interval_ms",
180 tier: Tier::Critical,
181 default: || num(10.0),
182 },
183 ConfigDefault {
184 key: "storage.wal.min_batch_size",
185 tier: Tier::Optional,
186 default: || num(4.0),
187 },
188 ConfigDefault {
190 key: "storage.deploy.profile",
191 tier: Tier::Critical,
192 default: || text("embedded"),
193 },
194 ConfigDefault {
195 key: "storage.deploy.packaging",
196 tier: Tier::Critical,
197 default: || text("single-file"),
198 },
199 ConfigDefault {
200 key: "storage.deploy.preset",
201 tier: Tier::Critical,
202 default: || text("embedded"),
203 },
204 ConfigDefault {
205 key: "storage.deploy.replica_count",
206 tier: Tier::Critical,
207 default: || num(0.0),
208 },
209 ConfigDefault {
210 key: "storage.deploy.managed_backup",
211 tier: Tier::Critical,
212 default: || JsonValue::Bool(false),
213 },
214 ConfigDefault {
215 key: "storage.deploy.wal_retention",
216 tier: Tier::Critical,
217 default: || JsonValue::Bool(false),
218 },
219 ConfigDefault {
221 key: "storage.bgwriter.delay_ms",
222 tier: Tier::Critical,
223 default: || num(200.0),
224 },
225 ConfigDefault {
226 key: "storage.bgwriter.max_pages_per_round",
227 tier: Tier::Optional,
228 default: || num(100.0),
229 },
230 ConfigDefault {
231 key: "storage.bgwriter.lru_multiplier",
232 tier: Tier::Optional,
233 default: || num(2.0),
234 },
235 ConfigDefault {
237 key: "storage.bulk_insert.max_buffered_rows",
238 tier: Tier::Optional,
239 default: || num(1000.0),
240 },
241 ConfigDefault {
242 key: "storage.bulk_insert.max_buffered_bytes",
243 tier: Tier::Optional,
244 default: || num(65536.0),
245 },
246 ConfigDefault {
248 key: "storage.hot_update.max_chain_hops",
249 tier: Tier::Optional,
250 default: || num(32.0),
251 },
252 ConfigDefault {
254 key: "storage.btree.lehman_yao",
255 tier: Tier::Critical,
256 default: || JsonValue::Bool(true),
257 },
258 ConfigDefault {
262 key: "ai.ner.backend",
263 tier: Tier::Optional,
264 default: || text("heuristic"),
265 },
266 ConfigDefault {
267 key: "ai.ner.endpoint",
268 tier: Tier::Optional,
269 default: || text(""),
270 },
271 ConfigDefault {
272 key: "ai.ner.model",
273 tier: Tier::Optional,
274 default: || text(""),
275 },
276 ConfigDefault {
277 key: "ai.ner.timeout_ms",
278 tier: Tier::Optional,
279 default: || num(5000.0),
280 },
281 ConfigDefault {
282 key: "ai.ner.fallback",
283 tier: Tier::Optional,
284 default: || text("use_heuristic"),
285 },
286 ConfigDefault {
290 key: "runtime.ai.transport_pool_size",
291 tier: Tier::Optional,
292 default: || num(16.0),
293 },
294 ConfigDefault {
295 key: "runtime.ai.transport_timeout_ms",
296 tier: Tier::Optional,
297 default: || num(30000.0),
298 },
299 ConfigDefault {
300 key: "runtime.ai.transport_retry_max_attempts",
301 tier: Tier::Optional,
302 default: || num(3.0),
303 },
304 ConfigDefault {
305 key: "runtime.ai.transport_retry_base_ms",
306 tier: Tier::Optional,
307 default: || num(500.0),
308 },
309 ConfigDefault {
311 key: "cache.blob.policy.extended",
312 tier: Tier::Optional,
313 default: || text("off"),
314 },
315 ConfigDefault {
320 key: "cache.blob.async_promotion",
321 tier: Tier::Optional,
322 default: || text("off"),
323 },
324];
325
326pub fn default_for(key: &str) -> Option<JsonValue> {
330 MATRIX
331 .iter()
332 .find(|entry| entry.key == key)
333 .map(|entry| (entry.default)())
334}
335
336pub fn tier_for(key: &str) -> Option<Tier> {
339 MATRIX
340 .iter()
341 .find(|entry| entry.key == key)
342 .map(|entry| entry.tier)
343}
344
345pub fn heal_critical_keys(store: &UnifiedStore) {
352 for entry in MATRIX {
355 if entry.tier != Tier::Critical {
356 continue;
357 }
358 if is_key_present(store, entry.key) {
359 continue;
360 }
361 store.set_config_tree(entry.key, &(entry.default)());
362 }
363}
364
365fn is_key_present(store: &UnifiedStore, key: &str) -> bool {
368 let Some(manager) = store.get_collection("red_config") else {
369 return false;
370 };
371 let mut found = false;
372 manager.for_each_entity(|entity| {
373 if let Some(row) = entity.data.as_row() {
374 let entry_key = row.get_field("key").and_then(|v| match v {
375 crate::storage::schema::Value::Text(s) => Some(s.as_ref()),
376 _ => None,
377 });
378 if entry_key == Some(key) {
379 found = true;
380 return false; }
382 }
383 true
384 });
385 found
386}
387
388#[cfg(test)]
389mod tests {
390 use super::*;
391
392 #[test]
393 fn every_matrix_entry_has_a_default_that_resolves() {
394 for entry in MATRIX {
395 let value = (entry.default)();
396 assert!(
397 !matches!(value, JsonValue::Null),
398 "matrix key {} has a null default, defeats self-heal",
399 entry.key
400 );
401 }
402 }
403
404 #[test]
405 fn critical_keys_cover_the_core_guarantees() {
406 let required_critical = [
409 "cache.blob.l1_bytes_max",
410 "cache.blob.l2_bytes_max",
411 "cache.blob.max_namespaces",
412 "durability.mode",
413 "runtime.result_cache.backend",
414 "concurrency.locking.enabled",
415 "storage.wal.max_interval_ms",
416 "storage.deploy.profile",
417 "storage.deploy.packaging",
418 "storage.deploy.preset",
419 "storage.deploy.replica_count",
420 "storage.deploy.managed_backup",
421 "storage.deploy.wal_retention",
422 "storage.bgwriter.delay_ms",
423 "storage.btree.lehman_yao",
424 ];
425 for key in required_critical {
426 assert_eq!(
427 tier_for(key),
428 Some(Tier::Critical),
429 "{key} must be a Tier A (Critical) key",
430 );
431 }
432 }
433
434 #[test]
435 fn optional_keys_are_not_self_healed() {
436 let must_be_optional = [
437 "concurrency.locking.deadlock_timeout_ms",
438 "storage.wal.min_batch_size",
439 "storage.bgwriter.max_pages_per_round",
440 "storage.bgwriter.lru_multiplier",
441 "storage.bulk_insert.max_buffered_rows",
442 "storage.bulk_insert.max_buffered_bytes",
443 "storage.hot_update.max_chain_hops",
444 ];
445 for key in must_be_optional {
446 assert_eq!(tier_for(key), Some(Tier::Optional), "{key} tier mismatch");
447 }
448 }
449
450 #[test]
451 fn unknown_key_returns_none() {
452 assert!(default_for("nonexistent.key").is_none());
453 assert!(tier_for("nonexistent.key").is_none());
454 }
455}