use serde::{Deserialize, Serialize};
use sublime_standard_tools::config::{ConfigResult, Configurable};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(default)]
pub struct AuditConfig {
pub enabled: bool,
pub min_severity: String,
pub sections: AuditSectionsConfig,
pub upgrades: UpgradeAuditConfig,
pub dependencies: DependencyAuditConfig,
pub breaking_changes: BreakingChangesAuditConfig,
pub version_consistency: VersionConsistencyAuditConfig,
pub health_score_weights: HealthScoreWeightsConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(default)]
pub struct AuditSectionsConfig {
pub upgrades: bool,
pub dependencies: bool,
pub breaking_changes: bool,
pub categorization: bool,
pub version_consistency: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(default)]
pub struct UpgradeAuditConfig {
pub include_patch: bool,
pub include_minor: bool,
pub include_major: bool,
pub deprecated_as_critical: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(default)]
pub struct DependencyAuditConfig {
pub check_circular: bool,
pub check_missing: bool,
pub check_unused: bool,
pub check_version_conflicts: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(default)]
pub struct BreakingChangesAuditConfig {
pub check_conventional_commits: bool,
pub check_changelog: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(default)]
pub struct VersionConsistencyAuditConfig {
pub fail_on_inconsistency: bool,
pub warn_on_inconsistency: bool,
}
impl Default for AuditConfig {
fn default() -> Self {
Self {
enabled: true,
min_severity: "warning".to_string(),
sections: AuditSectionsConfig::default(),
upgrades: UpgradeAuditConfig::default(),
dependencies: DependencyAuditConfig::default(),
breaking_changes: BreakingChangesAuditConfig::default(),
version_consistency: VersionConsistencyAuditConfig::default(),
health_score_weights: HealthScoreWeightsConfig::default(),
}
}
}
impl Default for AuditSectionsConfig {
fn default() -> Self {
Self {
upgrades: true,
dependencies: true,
breaking_changes: true,
categorization: true,
version_consistency: true,
}
}
}
impl Default for UpgradeAuditConfig {
fn default() -> Self {
Self {
include_patch: true,
include_minor: true,
include_major: true,
deprecated_as_critical: true,
}
}
}
impl Default for DependencyAuditConfig {
fn default() -> Self {
Self {
check_circular: true,
check_missing: false,
check_unused: false,
check_version_conflicts: true,
}
}
}
impl Default for BreakingChangesAuditConfig {
fn default() -> Self {
Self { check_conventional_commits: true, check_changelog: true }
}
}
impl Default for VersionConsistencyAuditConfig {
fn default() -> Self {
Self { fail_on_inconsistency: false, warn_on_inconsistency: true }
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(default)]
pub struct HealthScoreWeightsConfig {
pub critical_weight: f64,
pub warning_weight: f64,
pub info_weight: f64,
pub security_multiplier: f64,
pub breaking_changes_multiplier: f64,
pub dependencies_multiplier: f64,
pub version_consistency_multiplier: f64,
pub upgrades_multiplier: f64,
pub other_multiplier: f64,
}
impl Default for HealthScoreWeightsConfig {
fn default() -> Self {
Self {
critical_weight: 15.0,
warning_weight: 5.0,
info_weight: 1.0,
security_multiplier: 1.5,
breaking_changes_multiplier: 1.3,
dependencies_multiplier: 1.2,
version_consistency_multiplier: 1.0,
upgrades_multiplier: 0.8,
other_multiplier: 1.0,
}
}
}
impl Configurable for AuditConfig {
fn validate(&self) -> ConfigResult<()> {
match self.min_severity.as_str() {
"critical" | "warning" | "info" => {}
_ => {
return Err(sublime_standard_tools::config::ConfigError::ValidationError {
message: format!(
"audit.min_severity: Invalid severity '{}'. Must be one of: critical, warning, info",
self.min_severity
),
});
}
}
self.sections.validate()?;
self.upgrades.validate()?;
self.dependencies.validate()?;
self.breaking_changes.validate()?;
self.version_consistency.validate()?;
self.health_score_weights.validate()?;
Ok(())
}
fn merge_with(&mut self, other: Self) -> ConfigResult<()> {
self.enabled = other.enabled;
self.min_severity = other.min_severity;
self.sections.merge_with(other.sections)?;
self.upgrades.merge_with(other.upgrades)?;
self.dependencies.merge_with(other.dependencies)?;
self.breaking_changes.merge_with(other.breaking_changes)?;
self.version_consistency.merge_with(other.version_consistency)?;
self.health_score_weights.merge_with(other.health_score_weights)?;
Ok(())
}
}
impl Configurable for AuditSectionsConfig {
fn validate(&self) -> ConfigResult<()> {
Ok(())
}
fn merge_with(&mut self, other: Self) -> ConfigResult<()> {
self.upgrades = other.upgrades;
self.dependencies = other.dependencies;
self.breaking_changes = other.breaking_changes;
self.categorization = other.categorization;
self.version_consistency = other.version_consistency;
Ok(())
}
}
impl Configurable for UpgradeAuditConfig {
fn validate(&self) -> ConfigResult<()> {
Ok(())
}
fn merge_with(&mut self, other: Self) -> ConfigResult<()> {
self.include_patch = other.include_patch;
self.include_minor = other.include_minor;
self.include_major = other.include_major;
self.deprecated_as_critical = other.deprecated_as_critical;
Ok(())
}
}
impl Configurable for DependencyAuditConfig {
fn validate(&self) -> ConfigResult<()> {
Ok(())
}
fn merge_with(&mut self, other: Self) -> ConfigResult<()> {
self.check_circular = other.check_circular;
self.check_missing = other.check_missing;
self.check_unused = other.check_unused;
self.check_version_conflicts = other.check_version_conflicts;
Ok(())
}
}
impl Configurable for BreakingChangesAuditConfig {
fn validate(&self) -> ConfigResult<()> {
Ok(())
}
fn merge_with(&mut self, other: Self) -> ConfigResult<()> {
self.check_conventional_commits = other.check_conventional_commits;
self.check_changelog = other.check_changelog;
Ok(())
}
}
impl Configurable for VersionConsistencyAuditConfig {
fn validate(&self) -> ConfigResult<()> {
Ok(())
}
fn merge_with(&mut self, other: Self) -> ConfigResult<()> {
self.fail_on_inconsistency = other.fail_on_inconsistency;
self.warn_on_inconsistency = other.warn_on_inconsistency;
Ok(())
}
}
impl Configurable for HealthScoreWeightsConfig {
fn validate(&self) -> ConfigResult<()> {
let weights = [
("critical_weight", self.critical_weight),
("warning_weight", self.warning_weight),
("info_weight", self.info_weight),
("security_multiplier", self.security_multiplier),
("breaking_changes_multiplier", self.breaking_changes_multiplier),
("dependencies_multiplier", self.dependencies_multiplier),
("version_consistency_multiplier", self.version_consistency_multiplier),
("upgrades_multiplier", self.upgrades_multiplier),
("other_multiplier", self.other_multiplier),
];
for (name, value) in &weights {
if *value < 0.0 {
return Err(sublime_standard_tools::config::ConfigError::ValidationError {
message: format!(
"audit.health_score_weights.{}: Must be non-negative, got {}",
name, value
),
});
}
}
Ok(())
}
fn merge_with(&mut self, other: Self) -> ConfigResult<()> {
self.critical_weight = other.critical_weight;
self.warning_weight = other.warning_weight;
self.info_weight = other.info_weight;
self.security_multiplier = other.security_multiplier;
self.breaking_changes_multiplier = other.breaking_changes_multiplier;
self.dependencies_multiplier = other.dependencies_multiplier;
self.version_consistency_multiplier = other.version_consistency_multiplier;
self.upgrades_multiplier = other.upgrades_multiplier;
self.other_multiplier = other.other_multiplier;
Ok(())
}
}