qorzen_oxide/config/
tiered.rs

1// src/config/tiered.rs - Enhanced tiered configuration system
2
3use std::collections::HashMap;
4use std::sync::Arc;
5use std::time::Duration;
6
7use crate::utils::Time;
8use async_trait::async_trait;
9use chrono::{DateTime, Utc};
10use serde::{Deserialize, Serialize};
11use serde_json::Value;
12use tokio::sync::{broadcast, RwLock};
13use uuid::Uuid;
14
15use crate::error::{Error, Result};
16use crate::manager::{ManagedState, Manager, ManagerStatus, PlatformRequirements};
17
18/// Configuration tiers in order of precedence (lowest to highest)
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
20pub enum ConfigurationTier {
21    System,  // System defaults (built-in)
22    Global,  // Organization-wide (from server)
23    User,    // User preferences (synced)
24    Local,   // Device-specific overrides
25    Runtime, // Temporary runtime changes
26}
27
28impl ConfigurationTier {
29    /// Returns all tiers in precedence order
30    pub fn all_tiers() -> Vec<Self> {
31        vec![
32            Self::System,
33            Self::Global,
34            Self::User,
35            Self::Local,
36            Self::Runtime,
37        ]
38    }
39
40    /// Returns the precedence value (higher = more important)
41    pub fn precedence(&self) -> u8 {
42        match self {
43            Self::System => 0,
44            Self::Global => 1,
45            Self::User => 2,
46            Self::Local => 3,
47            Self::Runtime => 4,
48        }
49    }
50}
51
52/// Configuration store trait - conditional Send requirement
53#[cfg(not(target_arch = "wasm32"))]
54#[async_trait]
55pub trait ConfigStore: Send + Sync {
56    async fn get(&self, key: &str) -> Result<Option<Value>>;
57    async fn set(&self, key: &str, value: Value) -> Result<()>;
58    async fn delete(&self, key: &str) -> Result<()>;
59    async fn list_keys(&self, prefix: &str) -> Result<Vec<String>>;
60    async fn watch(&self, key: &str) -> Result<ConfigWatcher>;
61    fn tier(&self) -> ConfigurationTier;
62}
63
64#[cfg(target_arch = "wasm32")]
65#[async_trait(?Send)]
66pub trait ConfigStore: Sync {
67    async fn get(&self, key: &str) -> Result<Option<Value>>;
68    async fn set(&self, key: &str, value: Value) -> Result<()>;
69    async fn delete(&self, key: &str) -> Result<()>;
70    async fn list_keys(&self, prefix: &str) -> Result<Vec<String>>;
71    async fn watch(&self, key: &str) -> Result<ConfigWatcher>;
72    fn tier(&self) -> ConfigurationTier;
73}
74
75/// Configuration watcher for change notifications
76pub struct ConfigWatcher {
77    receiver: broadcast::Receiver<ConfigChangeEvent>,
78}
79
80impl ConfigWatcher {
81    pub fn new(receiver: broadcast::Receiver<ConfigChangeEvent>) -> Self {
82        Self { receiver }
83    }
84
85    pub async fn recv(&mut self) -> Result<ConfigChangeEvent> {
86        self.receiver
87            .recv()
88            .await
89            .map_err(|_| Error::config("Config watch channel closed"))
90    }
91}
92
93/// Configuration change event
94#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct ConfigChangeEvent {
96    pub key: String,
97    pub value: Option<Value>,
98    pub old_value: Option<Value>,
99    pub tier: ConfigurationTier,
100    pub timestamp: DateTime<Utc>,
101    pub source: String,
102    pub correlation_id: Option<Uuid>,
103}
104
105/// Configuration merger handles merging values from multiple tiers
106pub struct ConfigMerger {
107    // Strategies for merging different value types
108}
109
110impl Default for ConfigMerger {
111    fn default() -> Self {
112        Self::new()
113    }
114}
115
116fn merge_values(base: Value, override_value: Value) -> Value {
117    match (base, override_value) {
118        // If override is null, keep base
119        (base, Value::Null) => base,
120
121        // If base is null, use override
122        (Value::Null, override_val) => override_val,
123
124        // Merge objects recursively
125        (Value::Object(mut base_obj), Value::Object(override_obj)) => {
126            for (key, value) in override_obj {
127                match base_obj.get(&key) {
128                    Some(base_value) => {
129                        base_obj.insert(key, merge_values(base_value.clone(), value));
130                    }
131                    None => {
132                        base_obj.insert(key, value);
133                    }
134                }
135            }
136            Value::Object(base_obj)
137        }
138
139        // For arrays, override completely (could be made configurable)
140        (_, Value::Array(override_arr)) => Value::Array(override_arr),
141
142        // For primitive values, override completely
143        (_, override_val) => override_val,
144    }
145}
146
147impl ConfigMerger {
148    pub fn new() -> Self {
149        Self {}
150    }
151
152    /// Merges configuration values from multiple tiers
153    pub fn merge(&self, values: Vec<(ConfigurationTier, Value)>) -> Value {
154        if values.is_empty() {
155            return Value::Null;
156        }
157
158        // Sort by precedence (lowest first)
159        let mut sorted_values = values;
160        sorted_values.sort_by_key(|(tier, _)| tier.precedence());
161
162        // Start with the lowest precedence value
163        let mut result = sorted_values[0].1.clone();
164
165        // Merge higher precedence values
166        for (_, value) in sorted_values.into_iter().skip(1) {
167            result = merge_values(result, value);
168        }
169
170        result
171    }
172}
173
174/// Configuration change detector
175pub struct ConfigChangeDetector {
176    previous_values: HashMap<String, Value>,
177    change_sender: broadcast::Sender<ConfigChangeEvent>,
178}
179
180impl Default for ConfigChangeDetector {
181    fn default() -> Self {
182        Self::new()
183    }
184}
185
186impl ConfigChangeDetector {
187    pub fn new() -> Self {
188        let (change_sender, _) = broadcast::channel(1000);
189        Self {
190            previous_values: HashMap::new(),
191            change_sender,
192        }
193    }
194
195    pub fn subscribe(&self) -> broadcast::Receiver<ConfigChangeEvent> {
196        self.change_sender.subscribe()
197    }
198
199    pub fn detect_change(
200        &mut self,
201        key: &str,
202        new_value: &Value,
203        tier: ConfigurationTier,
204        source: &str,
205    ) {
206        let old_value = self.previous_values.get(key).cloned();
207
208        if old_value.as_ref() != Some(new_value) {
209            let change_event = ConfigChangeEvent {
210                key: key.to_string(),
211                value: Some(new_value.clone()),
212                old_value,
213                tier,
214                timestamp: Time::now(),
215                source: source.to_string(),
216                correlation_id: None,
217            };
218
219            let _ = self.change_sender.send(change_event);
220            self.previous_values
221                .insert(key.to_string(), new_value.clone());
222        }
223    }
224}
225
226/// Configuration synchronization manager
227pub struct ConfigSyncManager {
228    #[allow(dead_code)]
229    sync_interval: Duration,
230    last_sync: RwLock<DateTime<Utc>>,
231    sync_enabled: bool,
232}
233
234impl ConfigSyncManager {
235    pub fn new(sync_interval: Duration) -> Self {
236        Self {
237            sync_interval,
238            last_sync: RwLock::new(Time::now()),
239            sync_enabled: true,
240        }
241    }
242
243    pub async fn sync_with_server(&self, _store: &dyn ConfigStore) -> Result<()> {
244        if !self.sync_enabled {
245            return Ok(());
246        }
247
248        // Implementation would sync with remote server
249        *self.last_sync.write().await = Time::now();
250        Ok(())
251    }
252
253    pub async fn last_sync_time(&self) -> DateTime<Utc> {
254        *self.last_sync.read().await
255    }
256}
257
258/// Validation rule set for configuration values
259pub struct ValidationRuleSet {
260    rules: HashMap<String, Vec<ValidationRule>>,
261}
262
263/// Configuration validation rule
264#[derive(Debug, Clone, Serialize, Deserialize)]
265pub struct ValidationRule {
266    pub rule_type: ValidationRuleType,
267    pub message: String,
268    pub severity: ValidationSeverity,
269}
270
271#[derive(Debug, Clone, Serialize, Deserialize)]
272pub enum ValidationRuleType {
273    Required,
274    Type(String),
275    Range { min: f64, max: f64 },
276    Length { min: usize, max: usize },
277    Pattern(String),
278    Enum(Vec<String>),
279    Custom(String),
280}
281
282#[derive(Debug, Clone, Serialize, Deserialize)]
283pub enum ValidationSeverity {
284    Error,
285    Warning,
286    Info,
287}
288
289impl Default for ValidationRuleType {
290    fn default() -> Self {
291        Self::Required
292    }
293}
294
295impl Default for ValidationRuleSet {
296    fn default() -> Self {
297        Self::new()
298    }
299}
300
301impl ValidationRuleSet {
302    pub fn new() -> Self {
303        Self {
304            rules: HashMap::new(),
305        }
306    }
307
308    pub fn add_rule(&mut self, key: String, rule: ValidationRule) {
309        self.rules.entry(key).or_default().push(rule);
310    }
311
312    pub fn validate(&self, key: &str, value: &Value) -> Vec<ValidationError> {
313        let mut errors = Vec::new();
314
315        if let Some(rules) = self.rules.get(key) {
316            for rule in rules {
317                if let Some(error) = self.validate_rule(key, value, rule) {
318                    errors.push(error);
319                }
320            }
321        }
322
323        errors
324    }
325
326    fn validate_rule(
327        &self,
328        key: &str,
329        value: &Value,
330        rule: &ValidationRule,
331    ) -> Option<ValidationError> {
332        let is_valid = match &rule.rule_type {
333            ValidationRuleType::Required => !value.is_null(),
334            ValidationRuleType::Type(expected_type) => self.check_type(value, expected_type),
335            ValidationRuleType::Range { min, max } => self.check_range(value, *min, *max),
336            ValidationRuleType::Length { min, max } => self.check_length(value, *min, *max),
337            ValidationRuleType::Pattern(pattern) => self.check_pattern(value, pattern),
338            ValidationRuleType::Enum(options) => self.check_enum(value, options),
339            ValidationRuleType::Custom(_) => true, // Custom validation would be implemented
340        };
341
342        if !is_valid {
343            Some(ValidationError {
344                key: key.to_string(),
345                message: rule.message.clone(),
346                severity: rule.severity.clone(),
347                rule_type: rule.rule_type.clone(),
348            })
349        } else {
350            None
351        }
352    }
353
354    fn check_type(&self, value: &Value, expected_type: &str) -> bool {
355        match expected_type {
356            "string" => value.is_string(),
357            "number" => value.is_number(),
358            "boolean" => value.is_boolean(),
359            "array" => value.is_array(),
360            "object" => value.is_object(),
361            _ => true,
362        }
363    }
364
365    fn check_range(&self, value: &Value, min: f64, max: f64) -> bool {
366        if let Some(num) = value.as_f64() {
367            num >= min && num <= max
368        } else {
369            false
370        }
371    }
372
373    fn check_length(&self, value: &Value, min: usize, max: usize) -> bool {
374        let length = if let Some(s) = value.as_str() {
375            s.len()
376        } else if let Some(arr) = value.as_array() {
377            arr.len()
378        } else if let Some(obj) = value.as_object() {
379            obj.len()
380        } else {
381            return false;
382        };
383
384        length >= min && length <= max
385    }
386
387    fn check_pattern(&self, value: &Value, _pattern: &str) -> bool {
388        // Would implement regex pattern matching
389        value.is_string()
390    }
391
392    fn check_enum(&self, value: &Value, options: &[String]) -> bool {
393        if let Some(s) = value.as_str() {
394            options.contains(&s.to_string())
395        } else {
396            false
397        }
398    }
399}
400
401/// Configuration validation error
402#[derive(Debug, Clone, Serialize, Deserialize)]
403pub struct ValidationError {
404    pub key: String,
405    pub message: String,
406    pub severity: ValidationSeverity,
407    pub rule_type: ValidationRuleType,
408}
409
410/// Main tiered configuration manager
411pub struct TieredConfigManager {
412    state: ManagedState,
413    stores: HashMap<ConfigurationTier, Box<dyn ConfigStore>>,
414    merger: ConfigMerger,
415    sync_manager: Option<ConfigSyncManager>,
416    change_detector: ConfigChangeDetector,
417    validation_rules: ValidationRuleSet,
418    cache: Arc<RwLock<HashMap<String, Value>>>,
419    cache_ttl: Duration,
420}
421
422impl std::fmt::Debug for TieredConfigManager {
423    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
424        f.debug_struct("TieredConfigManager")
425            .field("stores", &self.stores.len())
426            .field("cache_ttl", &self.cache_ttl)
427            .finish()
428    }
429}
430
431impl Default for TieredConfigManager {
432    fn default() -> Self {
433        Self::new()
434    }
435}
436
437impl TieredConfigManager {
438    /// Creates a new tiered configuration manager
439    pub fn new() -> Self {
440        Self {
441            state: ManagedState::new(Uuid::new_v4(), "tiered_config_manager"),
442            stores: HashMap::new(),
443            merger: ConfigMerger::new(),
444            sync_manager: Some(ConfigSyncManager::new(Duration::from_secs(300))), // 5 minutes
445            change_detector: ConfigChangeDetector::new(),
446            validation_rules: ValidationRuleSet::new(),
447            cache: Arc::new(RwLock::new(HashMap::new())),
448            cache_ttl: Duration::from_secs(60),
449        }
450    }
451
452    /// Adds a configuration store for a specific tier
453    pub fn add_store(&mut self, tier: ConfigurationTier, store: Box<dyn ConfigStore>) {
454        self.stores.insert(tier, store);
455    }
456
457    /// Gets a configuration value by merging across all tiers
458    pub async fn get<T>(&self, key: &str) -> Result<Option<T>>
459    where
460        T: for<'de> Deserialize<'de>,
461    {
462        // Check cache first
463        if let Some(cached_value) = self.cache.read().await.get(key) {
464            return Ok(Some(serde_json::from_value(cached_value.clone()).map_err(
465                |e| Error::config(format!("Deserialization failed: {e}")),
466            )?));
467        }
468
469        // Collect values from all tiers
470        let mut tier_values = Vec::new();
471
472        for tier in ConfigurationTier::all_tiers() {
473            if let Some(store) = self.stores.get(&tier) {
474                if let Some(value) = store.get(key).await? {
475                    tier_values.push((tier, value));
476                }
477            }
478        }
479
480        if tier_values.is_empty() {
481            return Ok(None);
482        }
483
484        // Merge values
485        let merged_value = self.merger.merge(tier_values);
486
487        // Cache the result
488        self.cache
489            .write()
490            .await
491            .insert(key.to_string(), merged_value.clone());
492
493        // Deserialize and return
494        let result: T = serde_json::from_value(merged_value)
495            .map_err(|_e| Error::config("Failed to deserialize merged value"))?;
496        Ok(Some(result))
497    }
498
499    /// Sets a configuration value in a specific tier
500    pub async fn set(&mut self, key: &str, value: Value, tier: ConfigurationTier) -> Result<()> {
501        // Validate the value
502        let validation_errors = self.validation_rules.validate(key, &value);
503        if validation_errors
504            .iter()
505            .any(|e| matches!(e.severity, ValidationSeverity::Error))
506        {
507            return Err(Error::config(format!(
508                "Validation failed for key '{}': {:?}",
509                key, validation_errors
510            )));
511        }
512
513        // Get the store for this tier
514        let store = self
515            .stores
516            .get(&tier)
517            .ok_or_else(|| Error::config(format!("No store configured for tier {:?}", tier)))?;
518
519        // Set the value
520        store.set(key, value.clone()).await?;
521
522        // Invalidate cache
523        self.cache.write().await.remove(key);
524
525        // Detect and broadcast change
526        self.change_detector
527            .detect_change(key, &value, tier, "tiered_config_manager");
528
529        Ok(())
530    }
531
532    /// Deletes a configuration value from a specific tier
533    pub async fn delete(&self, key: &str, tier: ConfigurationTier) -> Result<()> {
534        let store = self
535            .stores
536            .get(&tier)
537            .ok_or_else(|| Error::config(format!("No store configured for tier {:?}", tier)))?;
538
539        store.delete(key).await?;
540
541        // Invalidate cache
542        self.cache.write().await.remove(key);
543
544        Ok(())
545    }
546
547    /// Lists all keys with a given prefix
548    pub async fn list_keys(&self, prefix: &str) -> Result<Vec<String>> {
549        let mut all_keys = std::collections::HashSet::new();
550
551        for store in self.stores.values() {
552            let keys = store.list_keys(prefix).await?;
553            all_keys.extend(keys);
554        }
555
556        Ok(all_keys.into_iter().collect())
557    }
558
559    /// Subscribes to configuration changes
560    pub fn subscribe_to_changes(&self) -> broadcast::Receiver<ConfigChangeEvent> {
561        self.change_detector.subscribe()
562    }
563
564    /// Adds a validation rule
565    pub fn add_validation_rule(&mut self, key: String, rule: ValidationRule) {
566        self.validation_rules.add_rule(key, rule);
567    }
568
569    /// Validates all configuration values
570    pub async fn validate_all(&self) -> Result<Vec<ValidationError>> {
571        let mut all_errors = Vec::new();
572
573        for store in self.stores.values() {
574            let keys = store.list_keys("").await?;
575            for key in keys {
576                if let Some(value) = store.get(&key).await? {
577                    let errors = self.validation_rules.validate(&key, &value);
578                    all_errors.extend(errors);
579                }
580            }
581        }
582
583        Ok(all_errors)
584    }
585
586    /// Clears the configuration cache
587    pub async fn clear_cache(&self) {
588        self.cache.write().await.clear();
589    }
590
591    /// Syncs configuration with remote server
592    pub async fn sync(&self) -> Result<()> {
593        if let Some(sync_manager) = &self.sync_manager {
594            for store in self.stores.values() {
595                sync_manager.sync_with_server(store.as_ref()).await?;
596            }
597        }
598        Ok(())
599    }
600}
601
602/// Conditional Manager implementation for TieredConfigManager
603#[cfg(not(target_arch = "wasm32"))]
604#[async_trait]
605impl Manager for TieredConfigManager {
606    fn name(&self) -> &str {
607        "tiered_config_manager"
608    }
609
610    fn id(&self) -> Uuid {
611        self.state.id()
612    }
613
614    async fn initialize(&mut self) -> Result<()> {
615        self.state
616            .set_state(crate::manager::ManagerState::Initializing)
617            .await;
618        self.state
619            .set_state(crate::manager::ManagerState::Running)
620            .await;
621        Ok(())
622    }
623
624    async fn shutdown(&mut self) -> Result<()> {
625        self.state
626            .set_state(crate::manager::ManagerState::ShuttingDown)
627            .await;
628        let _ = self.sync().await;
629        self.state
630            .set_state(crate::manager::ManagerState::Shutdown)
631            .await;
632        Ok(())
633    }
634
635    async fn status(&self) -> ManagerStatus {
636        let mut status = self.state.status().await;
637        status.add_metadata("stores_count", Value::from(self.stores.len()));
638        status.add_metadata("cache_size", Value::from(self.cache.read().await.len()));
639        status.add_metadata("cache_ttl_seconds", Value::from(self.cache_ttl.as_secs()));
640        if let Some(sync_manager) = &self.sync_manager {
641            status.add_metadata(
642                "last_sync",
643                Value::String(sync_manager.last_sync_time().await.to_rfc3339()),
644            );
645        }
646        status
647    }
648
649    fn supports_runtime_reload(&self) -> bool {
650        true
651    }
652
653    async fn reload_config(&mut self, config: serde_json::Value) -> Result<()> {
654        if let serde_json::Value::Object(config_obj) = config {
655            for (key, value) in config_obj {
656                self.set(&key, value, ConfigurationTier::Runtime).await?;
657            }
658        }
659        Ok(())
660    }
661
662    fn platform_requirements(&self) -> PlatformRequirements {
663        PlatformRequirements {
664            requires_filesystem: true,
665            requires_network: true,
666            requires_database: false,
667            requires_native_apis: false,
668            minimum_permissions: vec!["config.read".to_string(), "config.write".to_string()],
669        }
670    }
671}
672
673#[cfg(target_arch = "wasm32")]
674#[async_trait(?Send)]
675impl Manager for TieredConfigManager {
676    fn name(&self) -> &str {
677        "tiered_config_manager"
678    }
679
680    fn id(&self) -> Uuid {
681        self.state.id()
682    }
683
684    async fn initialize(&mut self) -> Result<()> {
685        self.state
686            .set_state(crate::manager::ManagerState::Initializing)
687            .await;
688        self.state
689            .set_state(crate::manager::ManagerState::Running)
690            .await;
691        Ok(())
692    }
693
694    async fn shutdown(&mut self) -> Result<()> {
695        self.state
696            .set_state(crate::manager::ManagerState::ShuttingDown)
697            .await;
698        let _ = self.sync().await;
699        self.state
700            .set_state(crate::manager::ManagerState::Shutdown)
701            .await;
702        Ok(())
703    }
704
705    async fn status(&self) -> ManagerStatus {
706        let mut status = self.state.status().await;
707        status.add_metadata("stores_count", Value::from(self.stores.len()));
708        status.add_metadata("cache_size", Value::from(self.cache.read().await.len()));
709        status.add_metadata("cache_ttl_seconds", Value::from(self.cache_ttl.as_secs()));
710        if let Some(sync_manager) = &self.sync_manager {
711            status.add_metadata(
712                "last_sync",
713                Value::String(sync_manager.last_sync_time().await.to_rfc3339()),
714            );
715        }
716        status
717    }
718
719    fn supports_runtime_reload(&self) -> bool {
720        true
721    }
722
723    async fn reload_config(&mut self, config: serde_json::Value) -> Result<()> {
724        if let serde_json::Value::Object(config_obj) = config {
725            for (key, value) in config_obj {
726                self.set(&key, value, ConfigurationTier::Runtime).await?;
727            }
728        }
729        Ok(())
730    }
731
732    fn platform_requirements(&self) -> PlatformRequirements {
733        PlatformRequirements {
734            requires_filesystem: true,
735            requires_network: true,
736            requires_database: false,
737            requires_native_apis: false,
738            minimum_permissions: vec!["config.read".to_string(), "config.write".to_string()],
739        }
740    }
741}
742
743/// Memory-based configuration store for runtime values
744pub struct MemoryConfigStore {
745    tier: ConfigurationTier,
746    data: Arc<RwLock<HashMap<String, Value>>>,
747    change_sender: broadcast::Sender<ConfigChangeEvent>,
748}
749
750impl MemoryConfigStore {
751    pub fn new(tier: ConfigurationTier) -> Self {
752        let (change_sender, _) = broadcast::channel(100);
753        Self {
754            tier,
755            data: Arc::new(RwLock::new(HashMap::new())),
756            change_sender,
757        }
758    }
759}
760
761/// Conditional ConfigStore implementation for MemoryConfigStore
762#[cfg(not(target_arch = "wasm32"))]
763#[async_trait]
764impl ConfigStore for MemoryConfigStore {
765    async fn get(&self, key: &str) -> Result<Option<Value>> {
766        Ok(self.data.read().await.get(key).cloned())
767    }
768
769    async fn set(&self, key: &str, value: Value) -> Result<()> {
770        let old_value = self
771            .data
772            .write()
773            .await
774            .insert(key.to_string(), value.clone());
775
776        let change_event = ConfigChangeEvent {
777            key: key.to_string(),
778            value: Some(value),
779            old_value,
780            tier: self.tier,
781            timestamp: Time::now(),
782            source: "memory_store".to_string(),
783            correlation_id: None,
784        };
785
786        let _ = self.change_sender.send(change_event);
787        Ok(())
788    }
789
790    async fn delete(&self, key: &str) -> Result<()> {
791        self.data.write().await.remove(key);
792        Ok(())
793    }
794
795    async fn list_keys(&self, prefix: &str) -> Result<Vec<String>> {
796        let data = self.data.read().await;
797        let keys: Vec<String> = data
798            .keys()
799            .filter(|k| k.starts_with(prefix))
800            .cloned()
801            .collect();
802        Ok(keys)
803    }
804
805    async fn watch(&self, _key: &str) -> Result<ConfigWatcher> {
806        Ok(ConfigWatcher::new(self.change_sender.subscribe()))
807    }
808
809    fn tier(&self) -> ConfigurationTier {
810        self.tier
811    }
812}
813
814#[cfg(target_arch = "wasm32")]
815#[async_trait(?Send)]
816impl ConfigStore for MemoryConfigStore {
817    async fn get(&self, key: &str) -> Result<Option<Value>> {
818        Ok(self.data.read().await.get(key).cloned())
819    }
820
821    async fn set(&self, key: &str, value: Value) -> Result<()> {
822        let old_value = self
823            .data
824            .write()
825            .await
826            .insert(key.to_string(), value.clone());
827
828        let change_event = ConfigChangeEvent {
829            key: key.to_string(),
830            value: Some(value),
831            old_value,
832            tier: self.tier,
833            timestamp: Time::now(),
834            source: "memory_store".to_string(),
835            correlation_id: None,
836        };
837
838        let _ = self.change_sender.send(change_event);
839        Ok(())
840    }
841
842    async fn delete(&self, key: &str) -> Result<()> {
843        self.data.write().await.remove(key);
844        Ok(())
845    }
846
847    async fn list_keys(&self, prefix: &str) -> Result<Vec<String>> {
848        let data = self.data.read().await;
849        let keys: Vec<String> = data
850            .keys()
851            .filter(|k| k.starts_with(prefix))
852            .cloned()
853            .collect();
854        Ok(keys)
855    }
856
857    async fn watch(&self, _key: &str) -> Result<ConfigWatcher> {
858        Ok(ConfigWatcher::new(self.change_sender.subscribe()))
859    }
860
861    fn tier(&self) -> ConfigurationTier {
862        self.tier
863    }
864}
865
866#[cfg(test)]
867mod tests {
868    use super::*;
869
870    #[tokio::test]
871    async fn test_config_merging() {
872        let merger = ConfigMerger::new();
873
874        let base = serde_json::json!({
875            "app": {
876                "name": "Test App",
877                "version": "1.0.0"
878            },
879            "features": {
880                "feature1": true
881            }
882        });
883
884        let override_val = serde_json::json!({
885            "app": {
886                "version": "1.1.0"
887            },
888            "features": {
889                "feature2": true
890            }
891        });
892
893        let values = vec![
894            (ConfigurationTier::System, base),
895            (ConfigurationTier::User, override_val),
896        ];
897
898        let merged = merger.merge(values);
899
900        assert_eq!(merged["app"]["name"], "Test App");
901        assert_eq!(merged["app"]["version"], "1.1.0");
902        assert_eq!(merged["features"]["feature1"], true);
903        assert_eq!(merged["features"]["feature2"], true);
904    }
905
906    #[tokio::test]
907    async fn test_tiered_config_manager() {
908        let mut manager = TieredConfigManager::new();
909
910        // Add memory stores for testing
911        manager.add_store(
912            ConfigurationTier::System,
913            Box::new(MemoryConfigStore::new(ConfigurationTier::System)),
914        );
915        manager.add_store(
916            ConfigurationTier::User,
917            Box::new(MemoryConfigStore::new(ConfigurationTier::User)),
918        );
919
920        // Set values in different tiers
921        manager
922            .set(
923                "app.name",
924                Value::String("System App".to_string()),
925                ConfigurationTier::System,
926            )
927            .await
928            .unwrap();
929        manager
930            .set(
931                "app.name",
932                Value::String("User App".to_string()),
933                ConfigurationTier::User,
934            )
935            .await
936            .unwrap();
937
938        // Get merged value (user tier should override system)
939        let app_name: Option<String> = manager.get("app.name").await.unwrap();
940        assert_eq!(app_name, Some("User App".to_string()));
941    }
942
943    #[test]
944    fn test_validation_rules() {
945        let mut rule_set = ValidationRuleSet::new();
946
947        rule_set.add_rule(
948            "app.port".to_string(),
949            ValidationRule {
950                rule_type: ValidationRuleType::Range {
951                    min: 1.0,
952                    max: 65535.0,
953                },
954                message: "Port must be between 1 and 65535".to_string(),
955                severity: ValidationSeverity::Error,
956            },
957        );
958
959        // Valid value
960        let valid_errors =
961            rule_set.validate("app.port", &Value::Number(serde_json::Number::from(8080)));
962        assert!(valid_errors.is_empty());
963
964        // Invalid value
965        let invalid_errors =
966            rule_set.validate("app.port", &Value::Number(serde_json::Number::from(70000)));
967        assert!(!invalid_errors.is_empty());
968    }
969}