auth_framework/security/
presets.rs

1//! Security presets for the Auth Framework
2//!
3//! This module provides pre-configured security levels that automatically
4//! apply appropriate security settings for different environments and use cases.
5//!
6//! # Security Presets
7//!
8//! - **Development**: Convenient settings for development environments
9//! - **Balanced**: Good security with reasonable performance (default)
10//! - **HighSecurity**: Strong security for sensitive applications
11//! - **Paranoid**: Maximum security settings for high-risk environments
12//!
13//! # Usage
14//!
15//! ```rust,no_run
16//! use auth_framework::prelude::*;
17//!
18//! # #[tokio::main]
19//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
20//! // Quick setup with security preset
21//! let auth = AuthFramework::quick_start()
22//!     .jwt_auth_from_env()
23//!     .security_level(SecurityPreset::HighSecurity)
24//!     .build().await?;
25//! # Ok(())
26//! # }
27//!
28//! // Or apply to existing configuration
29//! let config = AuthConfig::new()
30//!     .security(SecurityPreset::Paranoid.to_config());
31//! ```
32//!
33//! # Security Validation
34//!
35//! Each preset includes built-in validation to ensure security requirements
36//! are met for the target environment:
37//!
38//! ```rust,no_run
39//! use auth_framework::prelude::*;
40//!
41//! # #[tokio::main]
42//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
43//! // Validate security configuration
44//! let issues = SecurityPreset::HighSecurity
45//!     .validate_environment()
46//!     .await?;
47//!
48//! for issue in issues {
49//!     println!("âš ī¸  {}: {}", issue.severity, issue.description);
50//!     println!("💡 Fix: {}", issue.suggestion);
51//! }
52//! # Ok(())
53//! # }
54//! ```
55
56use crate::{
57    config::{
58        AuditConfig, AuditStorage, CookieSameSite, JwtAlgorithm, LockoutConfig,
59        OAuth2SecurityConfig, PasswordHashAlgorithm, RateLimitConfig, SecurityConfig,
60    },
61    prelude::{AuthFrameworkResult, hours, minutes},
62};
63use std::time::Duration;
64
65/// Security presets for common configurations
66#[derive(Debug, Clone, PartialEq)]
67pub enum SecurityPreset {
68    /// Development-friendly settings (lower security, more convenient)
69    ///
70    /// **USE ONLY FOR DEVELOPMENT - NOT PRODUCTION SAFE**
71    ///
72    /// - Shorter passwords allowed (6+ chars)
73    /// - Weaker password requirements
74    /// - Less strict cookie settings
75    /// - Disabled CSRF protection for easier testing
76    /// - Longer session timeouts for convenience
77    Development,
78
79    /// Balanced settings for most applications
80    ///
81    /// Good balance of security and usability suitable for most production
82    /// applications that don't handle highly sensitive data.
83    ///
84    /// - Standard password requirements (8+ chars)
85    /// - Secure cookies and CSRF protection
86    /// - Reasonable rate limiting
87    /// - Basic audit logging
88    Balanced,
89
90    /// High security settings for sensitive applications
91    ///
92    /// Strong security settings suitable for applications handling
93    /// sensitive data like financial information, healthcare records,
94    /// or personal data subject to compliance requirements.
95    ///
96    /// - Strict password requirements (12+ chars, complexity)
97    /// - Strong JWT algorithms (RSA-256)
98    /// - Aggressive rate limiting
99    /// - Comprehensive audit logging
100    /// - Short session timeouts
101    HighSecurity,
102
103    /// Maximum security (paranoid mode)
104    ///
105    /// Extremely strict security settings for high-risk environments
106    /// where security is paramount over convenience.
107    ///
108    /// - Very strict password requirements (16+ chars)
109    /// - Strongest cryptographic algorithms
110    /// - Very aggressive rate limiting
111    /// - Extensive audit logging and monitoring
112    /// - Very short session timeouts
113    /// - Constant-time operations
114    Paranoid,
115}
116
117/// Security validation issue
118#[derive(Debug, Clone)]
119pub struct SecurityIssue {
120    /// Severity level of the issue
121    pub severity: SecuritySeverity,
122    /// Component that has the issue
123    pub component: String,
124    /// Description of the security issue
125    pub description: String,
126    /// Suggested fix for the issue
127    pub suggestion: String,
128    /// Whether this issue blocks production deployment
129    pub blocks_production: bool,
130}
131
132/// Security issue severity levels
133#[derive(Debug, Clone, PartialEq, PartialOrd)]
134pub enum SecuritySeverity {
135    /// Information about security configuration
136    Info,
137    /// Security recommendation that should be addressed
138    Warning,
139    /// Security issue that should be fixed
140    Error,
141    /// Critical security issue that must be fixed
142    Critical,
143}
144
145impl SecurityPreset {
146    /// Convert the security preset to a SecurityConfig
147    pub fn to_config(&self) -> SecurityConfig {
148        match self {
149            SecurityPreset::Development => SecurityConfig {
150                min_password_length: 6,
151                require_password_complexity: false,
152                require_uppercase: false,
153                require_lowercase: false,
154                require_digit: false,
155                require_special: false,
156                min_complexity_criteria: 0,
157                password_hash_algorithm: PasswordHashAlgorithm::Bcrypt, // Faster for development
158                jwt_algorithm: JwtAlgorithm::HS256,
159                secret_key: None,      // Must be set externally
160                secure_cookies: false, // Allow HTTP for local development
161                cookie_same_site: CookieSameSite::Lax,
162                csrf_protection: false,     // Easier API testing
163                session_timeout: hours(24), // Long timeout for development convenience
164                lockout: LockoutConfig {
165                    enabled: false, // Disabled for development convenience
166                    ..Default::default()
167                },
168                max_api_keys_per_user: 0, // Unlimited for development
169                oauth2: OAuth2SecurityConfig {
170                    require_user_authentication: false,
171                    validate_redirect_uri: false,
172                    require_client_secret: false,
173                    require_pkce: false,
174                },
175            },
176            SecurityPreset::Balanced => SecurityConfig {
177                min_password_length: 8,
178                require_password_complexity: true,
179                require_uppercase: true,
180                require_lowercase: true,
181                require_digit: true,
182                require_special: false, // Optional for balanced approach
183                min_complexity_criteria: 3,
184                password_hash_algorithm: PasswordHashAlgorithm::Argon2,
185                jwt_algorithm: JwtAlgorithm::HS256,
186                secret_key: None,
187                secure_cookies: true,
188                cookie_same_site: CookieSameSite::Lax,
189                csrf_protection: true,
190                session_timeout: hours(8),
191                lockout: LockoutConfig {
192                    enabled: true,
193                    max_failed_attempts: 5,
194                    lockout_duration_seconds: 900, // 15 minutes
195                    progressive_lockout: false,
196                    ..Default::default()
197                },
198                max_api_keys_per_user: 10,
199                oauth2: OAuth2SecurityConfig {
200                    require_user_authentication: true,
201                    validate_redirect_uri: true,
202                    require_client_secret: true,
203                    require_pkce: false, // Optional for balanced
204                },
205            },
206            SecurityPreset::HighSecurity => SecurityConfig {
207                min_password_length: 12,
208                require_password_complexity: true,
209                require_uppercase: true,
210                require_lowercase: true,
211                require_digit: true,
212                require_special: true,
213                min_complexity_criteria: 4, // All criteria required
214                password_hash_algorithm: PasswordHashAlgorithm::Argon2,
215                jwt_algorithm: JwtAlgorithm::RS256, // RSA for better security
216                secret_key: None,
217                secure_cookies: true,
218                cookie_same_site: CookieSameSite::Strict,
219                csrf_protection: true,
220                session_timeout: hours(2), // Shorter sessions
221                lockout: LockoutConfig {
222                    enabled: true,
223                    max_failed_attempts: 3,         // Stricter limit
224                    lockout_duration_seconds: 1800, // 30 minutes
225                    progressive_lockout: true,
226                    ..Default::default()
227                },
228                max_api_keys_per_user: 5,                // Limited keys
229                oauth2: OAuth2SecurityConfig::default(), // All requirements enabled
230            },
231            SecurityPreset::Paranoid => SecurityConfig {
232                min_password_length: 16,
233                require_password_complexity: true,
234                require_uppercase: true,
235                require_lowercase: true,
236                require_digit: true,
237                require_special: true,
238                min_complexity_criteria: 4, // All criteria required
239                password_hash_algorithm: PasswordHashAlgorithm::Argon2,
240                jwt_algorithm: JwtAlgorithm::RS512, // Strongest RSA
241                secret_key: None,
242                secure_cookies: true,
243                cookie_same_site: CookieSameSite::Strict,
244                csrf_protection: true,
245                session_timeout: minutes(30), // Very short sessions
246                lockout: LockoutConfig {
247                    enabled: true,
248                    max_failed_attempts: 3,
249                    lockout_duration_seconds: 3600, // 1 hour
250                    progressive_lockout: true,
251                    max_lockout_duration_seconds: 86400, // 24 hours max
252                    ..Default::default()
253                },
254                max_api_keys_per_user: 3,                // Very limited
255                oauth2: OAuth2SecurityConfig::default(), // All requirements enabled
256            },
257        }
258    }
259
260    /// Get rate limiting configuration for this security preset
261    pub fn to_rate_limit_config(&self) -> RateLimitConfig {
262        match self {
263            SecurityPreset::Development => RateLimitConfig {
264                enabled: false, // Disabled for easier development
265                max_requests: 1000,
266                window: Duration::from_secs(60),
267                burst: 100,
268                per_user_enabled: false,
269                max_requests_per_user: 0,
270                per_user_window: Duration::from_secs(60),
271            },
272            SecurityPreset::Balanced => RateLimitConfig {
273                enabled: true,
274                max_requests: 100,
275                window: Duration::from_secs(60),
276                burst: 20,
277                per_user_enabled: true,
278                max_requests_per_user: 120, // Slightly more permissive per-user
279                per_user_window: Duration::from_secs(60),
280            },
281            SecurityPreset::HighSecurity => RateLimitConfig {
282                enabled: true,
283                max_requests: 60, // 1 per second average
284                window: Duration::from_secs(60),
285                burst: 10,
286                per_user_enabled: true,
287                max_requests_per_user: 60,
288                per_user_window: Duration::from_secs(60),
289            },
290            SecurityPreset::Paranoid => RateLimitConfig {
291                enabled: true,
292                max_requests: 30, // 0.5 per second average
293                window: Duration::from_secs(60),
294                burst: 5,
295                per_user_enabled: true,
296                max_requests_per_user: 30,
297                per_user_window: Duration::from_secs(60),
298            },
299        }
300    }
301
302    /// Get audit configuration for this security preset
303    pub fn to_audit_config(&self) -> AuditConfig {
304        match self {
305            SecurityPreset::Development => AuditConfig {
306                enabled: false, // Disabled for cleaner development logs
307                log_success: false,
308                log_failures: true, // Still log failures for debugging
309                log_permissions: false,
310                log_tokens: false,
311                storage: AuditStorage::Tracing,
312            },
313            SecurityPreset::Balanced => AuditConfig {
314                enabled: true,
315                log_success: false, // Don't log every success to reduce noise
316                log_failures: true,
317                log_permissions: true,
318                log_tokens: false, // Tokens can be sensitive
319                storage: AuditStorage::Tracing,
320            },
321            SecurityPreset::HighSecurity => AuditConfig {
322                enabled: true,
323                log_success: true,
324                log_failures: true,
325                log_permissions: true,
326                log_tokens: false,
327                storage: AuditStorage::Tracing, // Should be database in real deployment
328            },
329            SecurityPreset::Paranoid => AuditConfig {
330                enabled: true,
331                log_success: true,
332                log_failures: true,
333                log_permissions: true,
334                log_tokens: true,               // Log everything in paranoid mode
335                storage: AuditStorage::Tracing, // Should be secure external service
336            },
337        }
338    }
339
340    /// Validate the current environment against this security preset
341    pub async fn validate_environment(&self) -> AuthFrameworkResult<Vec<SecurityIssue>> {
342        let mut issues = Vec::new();
343
344        // Check environment type
345        let is_production = self.is_production_environment();
346        let is_development = self.is_development_environment();
347
348        // Validate preset appropriateness for environment
349        match (self, is_production, is_development) {
350            (SecurityPreset::Development, true, false) => {
351                issues.push(SecurityIssue {
352                    severity: SecuritySeverity::Critical,
353                    component: "Security Preset".to_string(),
354                    description: "Development security preset used in production environment".to_string(),
355                    suggestion: "Use SecurityPreset::HighSecurity or SecurityPreset::Paranoid for production".to_string(),
356                    blocks_production: true,
357                });
358            }
359            (SecurityPreset::Balanced, true, false) => {
360                issues.push(SecurityIssue {
361                    severity: SecuritySeverity::Warning,
362                    component: "Security Preset".to_string(),
363                    description:
364                        "Balanced security preset in production - consider higher security"
365                            .to_string(),
366                    suggestion: "Consider SecurityPreset::HighSecurity for better protection"
367                        .to_string(),
368                    blocks_production: false,
369                });
370            }
371            _ => {} // Other combinations are acceptable
372        }
373
374        // Check JWT secret
375        self.validate_jwt_secret(&mut issues);
376
377        // Check HTTPS in production
378        if is_production && self.requires_secure_cookies() {
379            self.validate_https_requirement(&mut issues);
380        }
381
382        // Check database configuration
383        self.validate_storage_security(&mut issues);
384
385        // Check environment variables
386        self.validate_environment_variables(&mut issues);
387
388        Ok(issues)
389    }
390
391    /// Perform a security audit of the current configuration
392    pub async fn security_audit(&self) -> AuthFrameworkResult<SecurityAuditReport> {
393        let issues = self.validate_environment().await?;
394
395        let critical_count = issues
396            .iter()
397            .filter(|i| i.severity == SecuritySeverity::Critical)
398            .count();
399        let error_count = issues
400            .iter()
401            .filter(|i| i.severity == SecuritySeverity::Error)
402            .count();
403        let warning_count = issues
404            .iter()
405            .filter(|i| i.severity == SecuritySeverity::Warning)
406            .count();
407
408        let overall_status = if critical_count > 0 {
409            SecurityAuditStatus::Critical
410        } else if error_count > 0 {
411            SecurityAuditStatus::Failed
412        } else if warning_count > 0 {
413            SecurityAuditStatus::Warning
414        } else {
415            SecurityAuditStatus::Passed
416        };
417
418        Ok(SecurityAuditReport {
419            preset: self.clone(),
420            status: overall_status,
421            issues,
422            critical_count,
423            error_count,
424            warning_count,
425            recommendations: self.get_security_recommendations(),
426        })
427    }
428
429    /// Get security recommendations for this preset
430    pub fn get_security_recommendations(&self) -> Vec<String> {
431        let mut recommendations = Vec::new();
432
433        match self {
434            SecurityPreset::Development => {
435                recommendations.push(
436                    "âš ī¸  Development preset detected - ensure this is not used in production"
437                        .to_string(),
438                );
439                recommendations
440                    .push("🔐 Set JWT_SECRET environment variable with a secure value".to_string());
441                recommendations
442                    .push("📝 Enable audit logging when moving to production".to_string());
443            }
444            SecurityPreset::Balanced => {
445                recommendations.push(
446                    "🔒 Consider upgrading to HighSecurity for sensitive applications".to_string(),
447                );
448                recommendations
449                    .push("📊 Monitor authentication patterns for suspicious activity".to_string());
450                recommendations.push("🔄 Regularly rotate JWT secrets and API keys".to_string());
451            }
452            SecurityPreset::HighSecurity => {
453                recommendations
454                    .push("✅ Good security configuration for production use".to_string());
455                recommendations
456                    .push("🔐 Ensure RSA keys are properly managed and rotated".to_string());
457                recommendations.push("📈 Monitor failed authentication attempts".to_string());
458                recommendations.push(
459                    "đŸ›Ąī¸  Consider multi-factor authentication for admin accounts".to_string(),
460                );
461            }
462            SecurityPreset::Paranoid => {
463                recommendations
464                    .push("đŸ›Ąī¸  Maximum security enabled - monitor performance impact".to_string());
465                recommendations.push(
466                    "⚡ Consider connection pooling to handle strict rate limits".to_string(),
467                );
468                recommendations.push("🔍 Implement comprehensive security monitoring".to_string());
469                recommendations
470                    .push("🚨 Set up alerting for all authentication failures".to_string());
471            }
472        }
473
474        recommendations
475    }
476
477    // Helper methods for validation
478
479    fn is_production_environment(&self) -> bool {
480        std::env::var("ENVIRONMENT").as_deref() == Ok("production")
481            || std::env::var("ENV").as_deref() == Ok("production")
482            || std::env::var("NODE_ENV").as_deref() == Ok("production")
483            || std::env::var("RUST_ENV").as_deref() == Ok("production")
484            || std::env::var("KUBERNETES_SERVICE_HOST").is_ok()
485    }
486
487    fn is_development_environment(&self) -> bool {
488        std::env::var("ENVIRONMENT").as_deref() == Ok("development")
489            || std::env::var("ENV").as_deref() == Ok("development")
490            || std::env::var("NODE_ENV").as_deref() == Ok("development")
491            || std::env::var("RUST_ENV").as_deref() == Ok("development")
492            || cfg!(debug_assertions)
493    }
494
495    fn requires_secure_cookies(&self) -> bool {
496        matches!(
497            self,
498            SecurityPreset::Balanced | SecurityPreset::HighSecurity | SecurityPreset::Paranoid
499        )
500    }
501
502    fn validate_jwt_secret(&self, issues: &mut Vec<SecurityIssue>) {
503        if let Ok(secret) = std::env::var("JWT_SECRET") {
504            let min_length = match self {
505                SecurityPreset::Development => 16,
506                SecurityPreset::Balanced => 32,
507                SecurityPreset::HighSecurity => 64,
508                SecurityPreset::Paranoid => 128,
509            };
510
511            if secret.len() < min_length {
512                issues.push(SecurityIssue {
513                    severity: if matches!(self, SecurityPreset::Development) {
514                        SecuritySeverity::Warning
515                    } else {
516                        SecuritySeverity::Error
517                    },
518                    component: "JWT Secret".to_string(),
519                    description: format!(
520                        "JWT secret too short ({} chars, need {}+)",
521                        secret.len(),
522                        min_length
523                    ),
524                    suggestion: format!(
525                        "Generate a longer secret: `openssl rand -base64 {}`",
526                        min_length * 3 / 4
527                    ),
528                    blocks_production: !matches!(self, SecurityPreset::Development),
529                });
530            }
531
532            // Check for weak patterns
533            if secret.to_lowercase().contains("secret")
534                || secret.to_lowercase().contains("password")
535                || secret.contains("123")
536            {
537                issues.push(SecurityIssue {
538                    severity: SecuritySeverity::Error,
539                    component: "JWT Secret".to_string(),
540                    description: "JWT secret contains weak patterns or common words".to_string(),
541                    suggestion:
542                        "Use a cryptographically secure random string: `openssl rand -base64 64`"
543                            .to_string(),
544                    blocks_production: true,
545                });
546            }
547        } else {
548            issues.push(SecurityIssue {
549                severity: SecuritySeverity::Critical,
550                component: "JWT Secret".to_string(),
551                description: "JWT_SECRET environment variable not set".to_string(),
552                suggestion: "Set JWT_SECRET environment variable with a secure random value"
553                    .to_string(),
554                blocks_production: true,
555            });
556        }
557    }
558
559    fn validate_https_requirement(&self, issues: &mut Vec<SecurityIssue>) {
560        // In a real implementation, this would check if HTTPS is properly configured
561        // For now, we'll check for common HTTPS indicators
562        let has_tls_cert =
563            std::env::var("TLS_CERT_PATH").is_ok() || std::env::var("SSL_CERT_PATH").is_ok();
564        let behind_proxy = std::env::var("HTTPS").as_deref() == Ok("on")
565            || std::env::var("HTTP_X_FORWARDED_PROTO").as_deref() == Ok("https");
566
567        if !has_tls_cert && !behind_proxy {
568            issues.push(SecurityIssue {
569                severity: SecuritySeverity::Warning,
570                component: "HTTPS".to_string(),
571                description: "HTTPS configuration not detected".to_string(),
572                suggestion: "Ensure HTTPS is properly configured for secure cookie transmission"
573                    .to_string(),
574                blocks_production: false,
575            });
576        }
577    }
578
579    fn validate_storage_security(&self, issues: &mut Vec<SecurityIssue>) {
580        // Check for database connection security
581        if let Ok(db_url) = std::env::var("DATABASE_URL")
582            && db_url.starts_with("postgresql://")
583            && !db_url.contains("sslmode=require")
584        {
585            issues.push(SecurityIssue {
586                severity: SecuritySeverity::Warning,
587                component: "Database".to_string(),
588                description: "Database connection may not be using SSL".to_string(),
589                suggestion: "Add sslmode=require to DATABASE_URL for encrypted connections"
590                    .to_string(),
591                blocks_production: false,
592            });
593        }
594
595        if let Ok(redis_url) = std::env::var("REDIS_URL")
596            && !redis_url.starts_with("rediss://")
597            && !redis_url.contains("tls")
598        {
599            issues.push(SecurityIssue {
600                severity: SecuritySeverity::Info,
601                component: "Redis".to_string(),
602                description: "Redis connection may not be using TLS".to_string(),
603                suggestion: "Consider using rediss:// URL or enabling TLS for Redis connections"
604                    .to_string(),
605                blocks_production: false,
606            });
607        }
608    }
609
610    fn validate_environment_variables(&self, issues: &mut Vec<SecurityIssue>) {
611        let sensitive_vars = [
612            "JWT_SECRET",
613            "DATABASE_URL",
614            "REDIS_URL",
615            "OAUTH_CLIENT_SECRET",
616        ];
617
618        for var in &sensitive_vars {
619            if let Ok(value) = std::env::var(var)
620                && value.len() < 20
621            {
622                issues.push(SecurityIssue {
623                    severity: SecuritySeverity::Warning,
624                    component: "Environment Variables".to_string(),
625                    description: format!("{} appears to be too short", var),
626                    suggestion: format!(
627                        "Ensure {} contains a sufficiently long, secure value",
628                        var
629                    ),
630                    blocks_production: false,
631                });
632            }
633        }
634    }
635}
636
637/// Security audit report
638#[derive(Debug, Clone)]
639pub struct SecurityAuditReport {
640    pub preset: SecurityPreset,
641    pub status: SecurityAuditStatus,
642    pub issues: Vec<SecurityIssue>,
643    pub critical_count: usize,
644    pub error_count: usize,
645    pub warning_count: usize,
646    pub recommendations: Vec<String>,
647}
648
649/// Overall security audit status
650#[derive(Debug, Clone, PartialEq)]
651pub enum SecurityAuditStatus {
652    /// All security checks passed
653    Passed,
654    /// Non-critical warnings found
655    Warning,
656    /// Security errors found that should be addressed
657    Failed,
658    /// Critical security issues that block production deployment
659    Critical,
660}
661
662impl SecurityAuditReport {
663    /// Print a formatted security report to stdout
664    pub fn print_report(&self) {
665        println!("🔒 Security Audit Report");
666        println!("========================");
667        println!("Preset: {:?}", self.preset);
668        println!("Status: {}", self.status_emoji());
669        println!();
670
671        if self.issues.is_empty() {
672            println!("✅ No security issues found!");
673        } else {
674            println!("📊 Issues Summary:");
675            println!("   Critical: {}", self.critical_count);
676            println!("   Errors: {}", self.error_count);
677            println!("   Warnings: {}", self.warning_count);
678            println!();
679
680            for issue in &self.issues {
681                println!(
682                    "{} {}: {}",
683                    issue.severity.emoji(),
684                    issue.component,
685                    issue.description
686                );
687                println!("   💡 {}", issue.suggestion);
688                println!();
689            }
690        }
691
692        if !self.recommendations.is_empty() {
693            println!("📋 Recommendations:");
694            for rec in &self.recommendations {
695                println!("   {}", rec);
696            }
697            println!();
698        }
699
700        println!("{}", self.get_summary_message());
701    }
702
703    fn status_emoji(&self) -> &str {
704        match self.status {
705            SecurityAuditStatus::Passed => "✅ Passed",
706            SecurityAuditStatus::Warning => "âš ī¸  Warning",
707            SecurityAuditStatus::Failed => "❌ Failed",
708            SecurityAuditStatus::Critical => "🚨 Critical",
709        }
710    }
711
712    fn get_summary_message(&self) -> String {
713        match self.status {
714            SecurityAuditStatus::Passed => "🎉 Security audit passed! Your configuration meets security requirements.".to_string(),
715            SecurityAuditStatus::Warning => "âš ī¸  Security audit completed with warnings. Consider addressing the issues above.".to_string(),
716            SecurityAuditStatus::Failed => "❌ Security audit failed. Please address the errors before deploying to production.".to_string(),
717            SecurityAuditStatus::Critical => "🚨 Critical security issues found! Do not deploy to production until these are resolved.".to_string(),
718        }
719    }
720
721    /// Check if the configuration is safe for production deployment
722    pub fn is_production_ready(&self) -> bool {
723        matches!(
724            self.status,
725            SecurityAuditStatus::Passed | SecurityAuditStatus::Warning
726        )
727    }
728
729    /// Get all blocking issues that prevent production deployment
730    pub fn get_blocking_issues(&self) -> Vec<&SecurityIssue> {
731        self.issues
732            .iter()
733            .filter(|issue| issue.blocks_production)
734            .collect()
735    }
736}
737
738impl SecuritySeverity {
739    fn emoji(&self) -> &str {
740        match self {
741            SecuritySeverity::Info => "â„šī¸ ",
742            SecuritySeverity::Warning => "âš ī¸ ",
743            SecuritySeverity::Error => "❌",
744            SecuritySeverity::Critical => "🚨",
745        }
746    }
747}
748
749impl std::fmt::Display for SecuritySeverity {
750    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
751        match self {
752            SecuritySeverity::Info => write!(f, "INFO"),
753            SecuritySeverity::Warning => write!(f, "WARNING"),
754            SecuritySeverity::Error => write!(f, "ERROR"),
755            SecuritySeverity::Critical => write!(f, "CRITICAL"),
756        }
757    }
758}