//! Local CA-bundle freshness check storage. //! //! Same shape as `systemd_checks`: the latest result per target is read from the //! ledger rather than shelling out to `apt-cache` on every viewer poll, and the //! issue lines ride along as a JSON blob. use super::{CaBundleCheckResult, Result, SqlitePool}; use tracing::instrument; #[instrument(skip_all)] pub async fn insert_ca_bundle_check( pool: &SqlitePool, result: &CaBundleCheckResult, ) -> Result { let issues = serde_json::to_string(&result.issues).unwrap_or_default(); let row = sqlx::query( "INSERT INTO ca_bundle_checks (target, status, package, installed, candidate, cert_count, lists_age_hours, issues, checked_at, error) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", ) .bind(&result.target) .bind(&result.status) .bind(&result.package) .bind(&result.installed) .bind(&result.candidate) .bind(result.cert_count) .bind(result.lists_age_hours) .bind(&issues) .bind(&result.checked_at) .bind(&result.error) .execute(pool) .await?; Ok(row.last_insert_rowid()) } /// The latest CA-bundle check for a target, if one has been recorded. #[instrument(skip_all)] pub async fn get_latest_ca_bundle_check( pool: &SqlitePool, target: &str, ) -> Result> { Ok(sqlx::query_as::<_, CaBundleCheckRow>( "SELECT id, target, status, package, installed, candidate, cert_count, lists_age_hours, issues, checked_at, error FROM ca_bundle_checks WHERE target = ? ORDER BY id DESC LIMIT 1", ) .bind(target) .fetch_optional(pool) .await?) } #[derive(Debug, Clone, sqlx::FromRow, serde::Serialize)] pub struct CaBundleCheckRow { pub id: i64, pub target: String, pub status: String, pub package: String, pub installed: Option, pub candidate: Option, pub cert_count: Option, pub lists_age_hours: Option, /// JSON array of the fired issue lines. Use [`Self::issue_list`]. pub issues: String, pub checked_at: String, pub error: Option, } impl CaBundleCheckRow { /// Decode the stored issue lines, tolerating a malformed blob as empty. pub fn issue_list(&self) -> Vec { serde_json::from_str(&self.issues).unwrap_or_default() } }