use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ForgeGuardConfig {
#[serde(default)]
pub deployment: DeploymentConfig,
#[serde(default)]
pub security: SecurityConfig,
#[serde(default)]
pub report: ReportConfig,
#[serde(default)]
pub cache: CacheConfig,
#[serde(default)]
pub plugins: PluginConfig,
#[serde(default)]
pub ai: AiConfig,
#[serde(default)]
pub notifications: NotificationConfig,
#[serde(default)]
pub history: HistoryConfig,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct HistoryConfig {
#[serde(default)]
pub enabled: bool,
#[serde(default)]
pub db_path: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeploymentConfig {
#[serde(default = "default_min_score")]
pub min_score: u8,
#[serde(default = "default_true")]
pub block_on_high: bool,
#[serde(default)]
pub block_on_medium: bool,
#[serde(default = "default_true")]
pub block_on_critical: bool,
#[serde(default = "default_true")]
pub require_fuzzing: bool,
#[serde(default = "default_true")]
pub require_invariants: bool,
#[serde(default = "default_true")]
pub simulate_deployment: bool,
#[serde(default)]
pub require_verification: bool,
#[serde(default)]
pub auto_verify: bool,
#[serde(default)]
pub explorer_api_key: Option<String>,
}
fn default_min_score() -> u8 {
70
}
fn default_true() -> bool {
true
}
impl Default for DeploymentConfig {
fn default() -> Self {
Self {
min_score: 70,
block_on_high: true,
block_on_medium: false,
block_on_critical: true,
require_fuzzing: true,
require_invariants: true,
simulate_deployment: true,
require_verification: false,
auto_verify: false,
explorer_api_key: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SecurityConfig {
#[serde(default = "default_true")]
pub enable_high: bool,
#[serde(default = "default_true")]
pub enable_medium: bool,
#[serde(default = "default_true")]
pub enable_low: bool,
#[serde(default)]
pub enable_info: bool,
#[serde(default = "default_true")]
pub exploit_analysis: bool,
#[serde(default)]
pub gas_analysis: bool,
#[serde(default)]
pub bytecode_analysis: bool,
#[serde(default = "default_max_findings")]
pub max_findings_per_check: usize,
#[serde(default)]
pub severity_overrides: std::collections::HashMap<String, String>,
#[serde(default)]
pub enabled_checks: Vec<String>,
#[serde(default)]
pub disabled_checks: Vec<String>,
}
fn default_max_findings() -> usize {
50
}
impl Default for SecurityConfig {
fn default() -> Self {
Self {
enable_high: true,
enable_medium: true,
enable_low: true,
enable_info: false,
exploit_analysis: true,
gas_analysis: false,
bytecode_analysis: false,
max_findings_per_check: 50,
severity_overrides: std::collections::HashMap::new(),
enabled_checks: Vec::new(),
disabled_checks: Vec::new(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReportConfig {
#[serde(default = "default_true")]
pub include_snippets: bool,
#[serde(default = "default_true")]
pub include_exploit_paths: bool,
#[serde(default = "default_true")]
pub include_recommendations: bool,
#[serde(default = "default_report_dir")]
pub output_dir: String,
#[serde(default)]
pub summary_only: bool,
}
fn default_report_dir() -> String {
"reports".into()
}
impl Default for ReportConfig {
fn default() -> Self {
Self {
include_snippets: true,
include_exploit_paths: true,
include_recommendations: true,
output_dir: default_report_dir(),
summary_only: false,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CacheConfig {
#[serde(default = "default_true")]
pub enabled: bool,
#[serde(default = "default_cache_dir")]
pub directory: String,
#[serde(default = "default_cache_size")]
pub max_size_mb: u64,
#[serde(default = "default_cache_ttl")]
pub ttl_seconds: u64,
}
fn default_cache_dir() -> String {
".forge-guard-cache".into()
}
fn default_cache_size() -> u64 {
500
}
fn default_cache_ttl() -> u64 {
3600
}
impl Default for CacheConfig {
fn default() -> Self {
Self {
enabled: true,
directory: default_cache_dir(),
max_size_mb: 500,
ttl_seconds: 3600,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AiConfig {
#[serde(default = "default_ai_provider")]
pub provider: String,
#[serde(default = "default_ai_model")]
pub model: String,
#[serde(default = "default_ai_temperature")]
pub temperature: f64,
#[serde(default = "default_ai_max_tokens")]
pub max_tokens: u32,
#[serde(default = "default_ai_min_confidence")]
pub min_confidence: f64,
#[serde(default)]
pub full_audit: bool,
}
fn default_ai_provider() -> String {
"openai".into()
}
fn default_ai_model() -> String {
"gpt-4".into()
}
fn default_ai_temperature() -> f64 {
0.1
}
fn default_ai_max_tokens() -> u32 {
4000
}
fn default_ai_min_confidence() -> f64 {
0.5
}
impl Default for AiConfig {
fn default() -> Self {
Self {
provider: default_ai_provider(),
model: default_ai_model(),
temperature: default_ai_temperature(),
max_tokens: default_ai_max_tokens(),
min_confidence: default_ai_min_confidence(),
full_audit: false,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PluginConfig {
#[serde(default = "default_plugin_dirs")]
pub directories: Vec<String>,
#[serde(default)]
pub enabled: Vec<String>,
#[serde(default)]
pub disabled: Vec<String>,
#[serde(default)]
pub allow_external: bool,
}
fn default_plugin_dirs() -> Vec<String> {
vec![".forge-guard/plugins".into()]
}
impl Default for PluginConfig {
fn default() -> Self {
Self {
directories: default_plugin_dirs(),
enabled: Vec::new(),
disabled: Vec::new(),
allow_external: false,
}
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct NotificationConfig {
#[serde(default)]
pub slack: NotificationEndpoint,
#[serde(default)]
pub discord: NotificationEndpoint,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NotificationEndpoint {
#[serde(default)]
pub webhook: Option<String>,
#[serde(default = "default_notify_min_severity")]
pub min_severity: String,
}
fn default_notify_min_severity() -> String {
"high".into()
}
impl Default for NotificationEndpoint {
fn default() -> Self {
Self {
webhook: None,
min_severity: default_notify_min_severity(),
}
}
}