//! tls alert/recovery messages. Domain half of the Alerter split; //! shared dispatch/cooldown plumbing lives in the parent module. use tracing::instrument; use super::{AlertCategory, AlertMeta, Alerter, tls_expiry_priority}; impl Alerter { #[instrument(skip_all)] pub async fn send_tls_expiry_alert( &self, target: &str, host: &str, days_remaining: i64, not_after: &str, ) { let alert_key = format!("tls:{target}"); let subject = format!("[PoM] {target}: TLS cert expires in {days_remaining} days"); let body = format!( "Target: {target}\n\ Host: {host}\n\ Days remaining: {days_remaining}\n\ Expires: {not_after}\n\ Instance: {}\n\ Time: {}\n\n\ - PoM", self.instance_name, chrono::Utc::now().to_rfc3339(), ); let priority = tls_expiry_priority(days_remaining); self.fire_failure( &subject, &body, priority, "pom-tls", Some(&format!("{target}:{host}")), AlertMeta { key: &alert_key, category: AlertCategory::TlsExpiry, from: None, to: None, error: None, }, ) .await; } #[instrument(skip_all)] pub async fn send_tls_error_alert(&self, target: &str, host: &str, error: &str) { let alert_key = format!("tls:{target}"); let subject = format!("[PoM] {target}: TLS check failed"); let body = format!( "Target: {target}\n\ Host: {host}\n\ Error: {error}\n\ Instance: {}\n\ Time: {}\n\n\ - PoM", self.instance_name, chrono::Utc::now().to_rfc3339(), ); self.fire_failure( &subject, &body, "high", "pom-tls", Some(&format!("{target}:{host}")), AlertMeta { key: &alert_key, category: AlertCategory::TlsError, from: None, to: None, error: Some(error), }, ) .await; } #[instrument(skip_all)] pub async fn send_tls_recovery(&self, target: &str, label: &str, days_remaining: i64) { let alert_key = format!("tls:{target}"); let subject = format!("[PoM] {target}: TLS cert renewed"); let body = format!( "Target: {label} ({target})\n\ Days remaining: {days_remaining}\n\ Instance: {}\n\ Time: {}\n\n\ - PoM", self.instance_name, chrono::Utc::now().to_rfc3339(), ); self.fire_recovery( &subject, &body, AlertMeta { key: &alert_key, category: AlertCategory::TlsRecovery, from: None, to: None, error: None, }, ) .await; } }