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 {
127 key: "storage.binary_document_body",
128 tier: Tier::Optional,
129 default: || JsonValue::Bool(true),
130 },
131 ConfigDefault {
133 key: "durability.mode",
134 tier: Tier::Critical,
135 default: || text("sync"),
136 },
137 ConfigDefault {
139 key: "runtime.result_cache.backend",
140 tier: Tier::Critical,
141 default: || text("legacy"),
142 },
143 ConfigDefault {
147 key: "runtime.result_cache.enabled",
148 tier: Tier::Critical,
149 default: || JsonValue::Bool(true),
150 },
151 ConfigDefault {
154 key: "runtime.result_cache.ttl_seconds",
155 tier: Tier::Optional,
156 default: || num(30.0),
157 },
158 ConfigDefault {
161 key: "runtime.result_cache.capacity_entries",
162 tier: Tier::Optional,
163 default: || num(1000.0),
164 },
165 ConfigDefault {
167 key: "concurrency.locking.enabled",
168 tier: Tier::Critical,
169 default: || JsonValue::Bool(true),
170 },
171 ConfigDefault {
172 key: "concurrency.locking.deadlock_timeout_ms",
173 tier: Tier::Optional,
174 default: || num(5000.0),
175 },
176 ConfigDefault {
178 key: "storage.wal.max_interval_ms",
179 tier: Tier::Critical,
180 default: || num(10.0),
181 },
182 ConfigDefault {
183 key: "storage.wal.min_batch_size",
184 tier: Tier::Optional,
185 default: || num(4.0),
186 },
187 ConfigDefault {
189 key: "storage.deploy.profile",
190 tier: Tier::Critical,
191 default: || text("embedded"),
192 },
193 ConfigDefault {
194 key: "storage.deploy.packaging",
195 tier: Tier::Critical,
196 default: || text("single-file"),
197 },
198 ConfigDefault {
199 key: "storage.deploy.preset",
200 tier: Tier::Critical,
201 default: || text("embedded"),
202 },
203 ConfigDefault {
204 key: "storage.deploy.replica_count",
205 tier: Tier::Critical,
206 default: || num(0.0),
207 },
208 ConfigDefault {
209 key: "storage.deploy.managed_backup",
210 tier: Tier::Critical,
211 default: || JsonValue::Bool(false),
212 },
213 ConfigDefault {
214 key: "storage.deploy.wal_retention",
215 tier: Tier::Critical,
216 default: || JsonValue::Bool(false),
217 },
218 ConfigDefault {
220 key: "storage.bgwriter.delay_ms",
221 tier: Tier::Critical,
222 default: || num(200.0),
223 },
224 ConfigDefault {
225 key: "storage.bgwriter.max_pages_per_round",
226 tier: Tier::Optional,
227 default: || num(100.0),
228 },
229 ConfigDefault {
230 key: "storage.bgwriter.lru_multiplier",
231 tier: Tier::Optional,
232 default: || num(2.0),
233 },
234 ConfigDefault {
236 key: "storage.bulk_insert.max_buffered_rows",
237 tier: Tier::Optional,
238 default: || num(1000.0),
239 },
240 ConfigDefault {
241 key: "storage.bulk_insert.max_buffered_bytes",
242 tier: Tier::Optional,
243 default: || num(65536.0),
244 },
245 ConfigDefault {
247 key: "storage.hot_update.max_chain_hops",
248 tier: Tier::Optional,
249 default: || num(32.0),
250 },
251 ConfigDefault {
253 key: "storage.time_series.max_series_per_collection",
254 tier: Tier::Optional,
255 default: || num(1_000_000.0),
256 },
257 ConfigDefault {
259 key: "storage.btree.lehman_yao",
260 tier: Tier::Critical,
261 default: || JsonValue::Bool(true),
262 },
263 ConfigDefault {
267 key: "ai.ner.backend",
268 tier: Tier::Optional,
269 default: || text("heuristic"),
270 },
271 ConfigDefault {
272 key: "ai.ner.endpoint",
273 tier: Tier::Optional,
274 default: || text(""),
275 },
276 ConfigDefault {
277 key: "ai.ner.model",
278 tier: Tier::Optional,
279 default: || text(""),
280 },
281 ConfigDefault {
282 key: "ai.ner.timeout_ms",
283 tier: Tier::Optional,
284 default: || num(5000.0),
285 },
286 ConfigDefault {
287 key: "ai.ner.fallback",
288 tier: Tier::Optional,
289 default: || text("use_heuristic"),
290 },
291 ConfigDefault {
295 key: "runtime.ai.transport_pool_size",
296 tier: Tier::Optional,
297 default: || num(16.0),
298 },
299 ConfigDefault {
300 key: "runtime.ai.transport_timeout_ms",
301 tier: Tier::Optional,
302 default: || num(30000.0),
303 },
304 ConfigDefault {
305 key: "runtime.ai.transport_retry_max_attempts",
306 tier: Tier::Optional,
307 default: || num(3.0),
308 },
309 ConfigDefault {
310 key: "runtime.ai.transport_retry_base_ms",
311 tier: Tier::Optional,
312 default: || num(500.0),
313 },
314 ConfigDefault {
316 key: "cache.blob.policy.extended",
317 tier: Tier::Optional,
318 default: || text("off"),
319 },
320 ConfigDefault {
325 key: "cache.blob.async_promotion",
326 tier: Tier::Optional,
327 default: || text("off"),
328 },
329];
330
331pub fn default_for(key: &str) -> Option<JsonValue> {
335 MATRIX
336 .iter()
337 .find(|entry| entry.key == key)
338 .map(|entry| (entry.default)())
339}
340
341pub fn tier_for(key: &str) -> Option<Tier> {
344 MATRIX
345 .iter()
346 .find(|entry| entry.key == key)
347 .map(|entry| entry.tier)
348}
349
350pub fn heal_critical_keys(store: &UnifiedStore) {
357 for entry in MATRIX {
360 if entry.tier != Tier::Critical {
361 continue;
362 }
363 if is_key_present(store, entry.key) {
364 continue;
365 }
366 store.set_config_tree(entry.key, &(entry.default)());
367 }
368}
369
370fn is_key_present(store: &UnifiedStore, key: &str) -> bool {
373 let Some(manager) = store.get_collection("red_config") else {
374 return false;
375 };
376 let mut found = false;
377 manager.for_each_entity(|entity| {
378 if let Some(row) = entity.data.as_row() {
379 let entry_key = row.get_field("key").and_then(|v| match v {
380 crate::storage::schema::Value::Text(s) => Some(s.as_ref()),
381 _ => None,
382 });
383 if entry_key == Some(key) {
384 found = true;
385 return false; }
387 }
388 true
389 });
390 found
391}
392
393#[cfg(test)]
394mod tests {
395 use super::*;
396
397 #[test]
398 fn every_matrix_entry_has_a_default_that_resolves() {
399 for entry in MATRIX {
400 let value = (entry.default)();
401 assert!(
402 !matches!(value, JsonValue::Null),
403 "matrix key {} has a null default, defeats self-heal",
404 entry.key
405 );
406 }
407 }
408
409 #[test]
410 fn critical_keys_cover_the_core_guarantees() {
411 let required_critical = [
414 "cache.blob.l1_bytes_max",
415 "cache.blob.l2_bytes_max",
416 "cache.blob.max_namespaces",
417 "durability.mode",
418 "runtime.result_cache.backend",
419 "concurrency.locking.enabled",
420 "storage.wal.max_interval_ms",
421 "storage.deploy.profile",
422 "storage.deploy.packaging",
423 "storage.deploy.preset",
424 "storage.deploy.replica_count",
425 "storage.deploy.managed_backup",
426 "storage.deploy.wal_retention",
427 "storage.bgwriter.delay_ms",
428 "storage.btree.lehman_yao",
429 ];
430 for key in required_critical {
431 assert_eq!(
432 tier_for(key),
433 Some(Tier::Critical),
434 "{key} must be a Tier A (Critical) key",
435 );
436 }
437 }
438
439 #[test]
440 fn optional_keys_are_not_self_healed() {
441 let must_be_optional = [
442 "concurrency.locking.deadlock_timeout_ms",
443 "storage.wal.min_batch_size",
444 "storage.bgwriter.max_pages_per_round",
445 "storage.bgwriter.lru_multiplier",
446 "storage.bulk_insert.max_buffered_rows",
447 "storage.bulk_insert.max_buffered_bytes",
448 "storage.hot_update.max_chain_hops",
449 "storage.time_series.max_series_per_collection",
450 ];
451 for key in must_be_optional {
452 assert_eq!(tier_for(key), Some(Tier::Optional), "{key} tier mismatch");
453 }
454 }
455
456 #[test]
457 fn unknown_key_returns_none() {
458 assert!(default_for("nonexistent.key").is_none());
459 assert!(tier_for("nonexistent.key").is_none());
460 }
461}