turbovault_core/
profiles.rs

1//! Pre-configured profiles for different deployment scenarios
2//!
3//! Provides 7 well-tuned configurations for common use cases:
4//! - Development: Verbose logging, all features enabled
5//! - Production: Optimized for reliability and security
6//! - ReadOnly: Analysis only, no mutations
7//! - HighPerformance: Tuned for 5000+ files
8//! - Minimal: Bare essentials only
9//! - MultiVault: Multiple vaults with sharing
10//! - Collaboration: Team features, webhooks
11
12use crate::config::ServerConfig;
13
14/// Profile selector for pre-configured deployments
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum ConfigProfile {
17    /// Development: Verbose logging, all operations, metrics enabled
18    Development,
19    /// Production: Security hardened, optimized, observability
20    Production,
21    /// ReadOnly: Search/analysis only, no write operations
22    ReadOnly,
23    /// HighPerformance: Optimized for large vaults (5000+ files)
24    HighPerformance,
25    /// Minimal: Bare essentials only
26    Minimal,
27    /// MultiVault: Multiple vault support with isolation
28    MultiVault,
29    /// Collaboration: Team features, webhooks, exports
30    Collaboration,
31}
32
33impl ConfigProfile {
34    /// Create a ServerConfig from this profile
35    pub fn create_config(self) -> ServerConfig {
36        let mut config = ServerConfig::new();
37
38        match self {
39            Self::Development => {
40                config.log_level = "DEBUG".to_string();
41                config.metrics_enabled = true;
42                config.debug_mode = true;
43                config.max_file_size = 50 * 1024 * 1024; // 50MB
44                config.cache_ttl = 60; // 1 minute (frequent refresh)
45                config.watch_for_changes = true;
46                config.link_graph_enabled = true;
47                config.full_text_search_enabled = true;
48            }
49
50            Self::Production => {
51                config.log_level = "INFO".to_string();
52                config.metrics_enabled = true;
53                config.debug_mode = false;
54                config.max_file_size = 10 * 1024 * 1024; // 10MB
55                config.cache_ttl = 3600; // 1 hour
56                config.watch_for_changes = true;
57                config.link_graph_enabled = true;
58                config.full_text_search_enabled = true;
59                config.editor_atomic_writes = true;
60                config.editor_backup_enabled = true;
61            }
62
63            Self::ReadOnly => {
64                config.log_level = "WARN".to_string();
65                config.metrics_enabled = true;
66                config.max_file_size = 10 * 1024 * 1024;
67                config.cache_ttl = 300; // 5 minutes
68                config.watch_for_changes = false;
69                config.link_graph_enabled = true;
70                config.full_text_search_enabled = true;
71                config.editor_atomic_writes = false;
72                config.editor_backup_enabled = false;
73            }
74
75            Self::HighPerformance => {
76                config.log_level = "WARN".to_string();
77                config.metrics_enabled = false; // Disable for performance
78                config.debug_mode = false;
79                config.cache_ttl = 7200; // 2 hours
80                config.watch_for_changes = true;
81                config.enable_caching = true;
82                config.link_suggestions_enabled = false; // Too expensive
83                config.full_text_search_enabled = false;
84            }
85
86            Self::Minimal => {
87                config.log_level = "ERROR".to_string();
88                config.metrics_enabled = false;
89                config.debug_mode = false;
90                config.cache_ttl = 10800; // 3 hours
91                config.watch_for_changes = false;
92                config.link_graph_enabled = false;
93                config.full_text_search_enabled = false;
94                config.link_suggestions_enabled = false;
95            }
96
97            Self::MultiVault => {
98                config.log_level = "INFO".to_string();
99                config.metrics_enabled = true;
100                config.debug_mode = false;
101                config.cache_ttl = 1800; // 30 minutes
102                config.watch_for_changes = true;
103                config.multi_vault_enabled = true;
104                // vaults will be populated externally
105            }
106
107            Self::Collaboration => {
108                config.log_level = "INFO".to_string();
109                config.metrics_enabled = true;
110                config.debug_mode = false;
111                config.watch_for_changes = true;
112                config.multi_vault_enabled = true;
113                config.link_graph_enabled = true;
114                config.full_text_search_enabled = true;
115                config.editor_backup_enabled = true;
116                // Collaboration features enabled
117            }
118        }
119
120        config
121    }
122
123    /// Recommend a profile based on vault size
124    pub fn recommend(vault_size: usize) -> Self {
125        match vault_size {
126            0..=100 => Self::Minimal,
127            101..=1000 => Self::Development,
128            1001..=5000 => Self::Production,
129            _ => Self::HighPerformance,
130        }
131    }
132
133    /// Get profile name
134    pub fn name(self) -> &'static str {
135        match self {
136            Self::Development => "development",
137            Self::Production => "production",
138            Self::ReadOnly => "read-only",
139            Self::HighPerformance => "high-performance",
140            Self::Minimal => "minimal",
141            Self::MultiVault => "multi-vault",
142            Self::Collaboration => "collaboration",
143        }
144    }
145
146    /// Get profile description
147    pub fn description(self) -> &'static str {
148        match self {
149            Self::Development => "Verbose logging, all operations enabled",
150            Self::Production => "Optimized for reliability and security",
151            Self::ReadOnly => "Search and analysis only, no mutations",
152            Self::HighPerformance => "Tuned for large vaults (5000+ files)",
153            Self::Minimal => "Bare essentials only",
154            Self::MultiVault => "Multiple vault support with isolation",
155            Self::Collaboration => "Team features, webhooks, and exports",
156        }
157    }
158}
159
160impl std::fmt::Display for ConfigProfile {
161    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162        write!(f, "{}", self.name())
163    }
164}
165
166#[cfg(test)]
167mod tests {
168    use super::*;
169
170    #[test]
171    fn test_development_profile() {
172        let config = ConfigProfile::Development.create_config();
173        assert_eq!(config.log_level, "DEBUG");
174        assert!(config.metrics_enabled);
175        assert!(config.watch_for_changes);
176    }
177
178    #[test]
179    fn test_production_profile() {
180        let config = ConfigProfile::Production.create_config();
181        assert_eq!(config.log_level, "INFO");
182        assert!(config.metrics_enabled);
183        assert!(config.watch_for_changes);
184        assert!(config.editor_atomic_writes);
185    }
186
187    #[test]
188    fn test_readonly_profile() {
189        let config = ConfigProfile::ReadOnly.create_config();
190        assert!(!config.editor_atomic_writes);
191        assert!(!config.editor_backup_enabled);
192        assert!(config.link_graph_enabled);
193    }
194
195    #[test]
196    fn test_high_performance_profile() {
197        let config = ConfigProfile::HighPerformance.create_config();
198        assert!(!config.metrics_enabled);
199        assert!(config.cache_ttl > 3600); // 2+ hours
200    }
201
202    #[test]
203    fn test_minimal_profile() {
204        let config = ConfigProfile::Minimal.create_config();
205        assert_eq!(config.log_level, "ERROR");
206        assert!(!config.metrics_enabled);
207    }
208
209    #[test]
210    fn test_recommend_small_vault() {
211        let profile = ConfigProfile::recommend(50);
212        assert_eq!(profile, ConfigProfile::Minimal);
213    }
214
215    #[test]
216    fn test_recommend_medium_vault() {
217        let profile = ConfigProfile::recommend(500);
218        assert_eq!(profile, ConfigProfile::Development);
219    }
220
221    #[test]
222    fn test_recommend_production_vault() {
223        let profile = ConfigProfile::recommend(2000);
224        assert_eq!(profile, ConfigProfile::Production);
225    }
226
227    #[test]
228    fn test_recommend_large_vault() {
229        let profile = ConfigProfile::recommend(10000);
230        assert_eq!(profile, ConfigProfile::HighPerformance);
231    }
232
233    #[test]
234    fn test_profile_names() {
235        assert_eq!(ConfigProfile::Development.name(), "development");
236        assert_eq!(ConfigProfile::Production.name(), "production");
237        assert_eq!(ConfigProfile::ReadOnly.name(), "read-only");
238    }
239
240    #[test]
241    fn test_profile_descriptions() {
242        assert!(!ConfigProfile::Development.description().is_empty());
243        assert!(!ConfigProfile::Production.description().is_empty());
244    }
245}