1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Default, Serialize, Deserialize)]
4#[serde(default)]
5pub struct Config {
6 pub storage: StorageConfig,
7 pub search: SearchConfig,
8 pub validation: ValidationConfig,
9 pub privacy: PrivacyConfig,
10}
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13#[serde(default)]
14pub struct StorageConfig {
15 pub retention_days: u32,
16 pub vacuum_interval_secs: u64,
17 pub max_db_size_mb: u64,
18 pub busy_timeout_ms: u32,
19 pub cache_size_kb: u32,
20 pub dedup_window_secs: u64,
21}
22
23impl Default for StorageConfig {
24 fn default() -> Self {
25 Self {
26 retention_days: 90,
27 vacuum_interval_secs: 604800,
28 max_db_size_mb: 500,
29 busy_timeout_ms: 5000,
30 cache_size_kb: 2048,
31 dedup_window_secs: 900,
32 }
33 }
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
37#[serde(default)]
38pub struct SearchConfig {
39 pub default_limit: u32,
40 pub max_limit: u32,
41}
42
43impl Default for SearchConfig {
44 fn default() -> Self {
45 Self {
46 default_limit: 10,
47 max_limit: 50,
48 }
49 }
50}
51
52#[derive(Debug, Clone, Serialize, Deserialize)]
53#[serde(default)]
54pub struct ValidationConfig {
55 pub max_key_length: usize,
56 pub max_value_length: usize,
57 pub max_tags: usize,
58 pub max_tag_length: usize,
59}
60
61impl Default for ValidationConfig {
62 fn default() -> Self {
63 Self {
64 max_key_length: 256,
65 max_value_length: 2000,
66 max_tags: 20,
67 max_tag_length: 64,
68 }
69 }
70}
71
72#[derive(Debug, Clone, Serialize, Deserialize)]
73#[serde(default)]
74pub struct PrivacyConfig {
75 pub secret_patterns: Vec<String>,
76 pub extra_patterns: Vec<String>,
77 pub replace_defaults: bool,
78 pub file_deny_list: Vec<String>,
79}
80
81impl Default for PrivacyConfig {
82 fn default() -> Self {
83 Self {
84 secret_patterns: default_secret_patterns(),
85 extra_patterns: Vec::new(),
86 replace_defaults: false,
87 file_deny_list: vec![
88 ".env".into(),
89 ".env.*".into(),
90 "*.pem".into(),
91 "*.key".into(),
92 "*.p12".into(),
93 "*.pfx".into(),
94 "id_rsa".into(),
95 "id_ed25519".into(),
96 "id_ecdsa".into(),
97 "*.secret".into(),
98 "credentials.json".into(),
99 ],
100 }
101 }
102}
103
104pub fn default_secret_patterns() -> Vec<String> {
105 vec![
106 r"AKIA[0-9A-Z]{16}".into(),
107 r"-----BEGIN [A-Z ]*PRIVATE KEY-----".into(),
108 r"(?i)(api[_-]?key|token|secret|password)\s*[:=]\s*\S+".into(),
109 r"(?i)mongodb(\+srv)?://[^\s]+".into(),
110 r"(?i)postgres(ql)?://[^\s]+".into(),
111 r"(?i)mysql://[^\s]+".into(),
112 r"(?i)redis://[^\s]+".into(),
113 r"ghp_[a-zA-Z0-9]{36}".into(),
114 r"sk-[a-zA-Z0-9]{48}".into(),
115 r"xoxb-[0-9]+-[0-9]+-[a-zA-Z0-9]+".into(),
116 ]
117}