1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Default, Serialize, Deserialize)]
5pub struct ForgeGuardConfig {
6 #[serde(default)]
8 pub deployment: DeploymentConfig,
9 #[serde(default)]
11 pub security: SecurityConfig,
12 #[serde(default)]
14 pub report: ReportConfig,
15 #[serde(default)]
17 pub cache: CacheConfig,
18 #[serde(default)]
20 pub plugins: PluginConfig,
21 #[serde(default)]
23 pub ai: AiConfig,
24 #[serde(default)]
26 pub notifications: NotificationConfig,
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct DeploymentConfig {
32 #[serde(default = "default_min_score")]
34 pub min_score: u8,
35 #[serde(default = "default_true")]
37 pub block_on_high: bool,
38 #[serde(default)]
40 pub block_on_medium: bool,
41 #[serde(default = "default_true")]
43 pub block_on_critical: bool,
44 #[serde(default = "default_true")]
46 pub require_fuzzing: bool,
47 #[serde(default = "default_true")]
49 pub require_invariants: bool,
50 #[serde(default = "default_true")]
52 pub simulate_deployment: bool,
53 #[serde(default)]
55 pub require_verification: bool,
56 #[serde(default)]
58 pub auto_verify: bool,
59 #[serde(default)]
61 pub explorer_api_key: Option<String>,
62}
63
64fn default_min_score() -> u8 {
65 70
66}
67fn default_true() -> bool {
68 true
69}
70
71impl Default for DeploymentConfig {
72 fn default() -> Self {
73 Self {
74 min_score: 70,
75 block_on_high: true,
76 block_on_medium: false,
77 block_on_critical: true,
78 require_fuzzing: true,
79 require_invariants: true,
80 simulate_deployment: true,
81 require_verification: false,
82 auto_verify: false,
83 explorer_api_key: None,
84 }
85 }
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct SecurityConfig {
91 #[serde(default = "default_true")]
93 pub enable_high: bool,
94 #[serde(default = "default_true")]
96 pub enable_medium: bool,
97 #[serde(default = "default_true")]
99 pub enable_low: bool,
100 #[serde(default)]
102 pub enable_info: bool,
103 #[serde(default = "default_true")]
105 pub exploit_analysis: bool,
106 #[serde(default)]
108 pub gas_analysis: bool,
109 #[serde(default)]
111 pub bytecode_analysis: bool,
112 #[serde(default = "default_max_findings")]
114 pub max_findings_per_check: usize,
115 #[serde(default)]
117 pub severity_overrides: std::collections::HashMap<String, String>,
118 #[serde(default)]
121 pub enabled_checks: Vec<String>,
122 #[serde(default)]
124 pub disabled_checks: Vec<String>,
125}
126
127fn default_max_findings() -> usize {
128 50
129}
130
131impl Default for SecurityConfig {
132 fn default() -> Self {
133 Self {
134 enable_high: true,
135 enable_medium: true,
136 enable_low: true,
137 enable_info: false,
138 exploit_analysis: true,
139 gas_analysis: false,
140 bytecode_analysis: false,
141 max_findings_per_check: 50,
142 severity_overrides: std::collections::HashMap::new(),
143 enabled_checks: Vec::new(),
144 disabled_checks: Vec::new(),
145 }
146 }
147}
148
149#[derive(Debug, Clone, Serialize, Deserialize)]
151pub struct ReportConfig {
152 #[serde(default = "default_true")]
154 pub include_snippets: bool,
155 #[serde(default = "default_true")]
157 pub include_exploit_paths: bool,
158 #[serde(default = "default_true")]
160 pub include_recommendations: bool,
161 #[serde(default = "default_report_dir")]
163 pub output_dir: String,
164 #[serde(default)]
166 pub summary_only: bool,
167}
168
169fn default_report_dir() -> String {
170 "reports".into()
171}
172
173impl Default for ReportConfig {
174 fn default() -> Self {
175 Self {
176 include_snippets: true,
177 include_exploit_paths: true,
178 include_recommendations: true,
179 output_dir: default_report_dir(),
180 summary_only: false,
181 }
182 }
183}
184
185#[derive(Debug, Clone, Serialize, Deserialize)]
187pub struct CacheConfig {
188 #[serde(default = "default_true")]
190 pub enabled: bool,
191 #[serde(default = "default_cache_dir")]
193 pub directory: String,
194 #[serde(default = "default_cache_size")]
196 pub max_size_mb: u64,
197 #[serde(default = "default_cache_ttl")]
199 pub ttl_seconds: u64,
200}
201
202fn default_cache_dir() -> String {
203 ".forge-guard-cache".into()
204}
205fn default_cache_size() -> u64 {
206 500
207}
208fn default_cache_ttl() -> u64 {
209 3600
210}
211
212impl Default for CacheConfig {
213 fn default() -> Self {
214 Self {
215 enabled: true,
216 directory: default_cache_dir(),
217 max_size_mb: 500,
218 ttl_seconds: 3600,
219 }
220 }
221}
222
223#[derive(Debug, Clone, Serialize, Deserialize)]
225pub struct AiConfig {
226 #[serde(default = "default_ai_provider")]
228 pub provider: String,
229 #[serde(default = "default_ai_model")]
231 pub model: String,
232 #[serde(default = "default_ai_temperature")]
234 pub temperature: f64,
235 #[serde(default = "default_ai_max_tokens")]
237 pub max_tokens: u32,
238 #[serde(default = "default_ai_min_confidence")]
240 pub min_confidence: f64,
241 #[serde(default)]
243 pub full_audit: bool,
244}
245
246fn default_ai_provider() -> String {
247 "openai".into()
248}
249fn default_ai_model() -> String {
250 "gpt-4".into()
251}
252fn default_ai_temperature() -> f64 {
253 0.1
254}
255fn default_ai_max_tokens() -> u32 {
256 4000
257}
258fn default_ai_min_confidence() -> f64 {
259 0.5
260}
261
262impl Default for AiConfig {
263 fn default() -> Self {
264 Self {
265 provider: default_ai_provider(),
266 model: default_ai_model(),
267 temperature: default_ai_temperature(),
268 max_tokens: default_ai_max_tokens(),
269 min_confidence: default_ai_min_confidence(),
270 full_audit: false,
271 }
272 }
273}
274
275#[derive(Debug, Clone, Serialize, Deserialize)]
277pub struct PluginConfig {
278 #[serde(default = "default_plugin_dirs")]
280 pub directories: Vec<String>,
281 #[serde(default)]
283 pub enabled: Vec<String>,
284 #[serde(default)]
286 pub disabled: Vec<String>,
287 #[serde(default)]
289 pub allow_external: bool,
290}
291
292fn default_plugin_dirs() -> Vec<String> {
293 vec![".forge-guard/plugins".into()]
294}
295
296impl Default for PluginConfig {
297 fn default() -> Self {
298 Self {
299 directories: default_plugin_dirs(),
300 enabled: Vec::new(),
301 disabled: Vec::new(),
302 allow_external: false,
303 }
304 }
305}
306
307#[derive(Debug, Clone, Default, Serialize, Deserialize)]
319pub struct NotificationConfig {
320 #[serde(default)]
322 pub slack: NotificationEndpoint,
323 #[serde(default)]
325 pub discord: NotificationEndpoint,
326}
327
328#[derive(Debug, Clone, Serialize, Deserialize)]
330pub struct NotificationEndpoint {
331 #[serde(default)]
333 pub webhook: Option<String>,
334 #[serde(default = "default_notify_min_severity")]
337 pub min_severity: String,
338}
339
340fn default_notify_min_severity() -> String {
341 "high".into()
342}
343
344impl Default for NotificationEndpoint {
345 fn default() -> Self {
346 Self {
347 webhook: None,
348 min_severity: default_notify_min_severity(),
349 }
350 }
351}