use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Verdict {
pub approved: bool,
pub command_hash: String,
pub command_sequence: u64,
pub timestamp: DateTime<Utc>,
pub checks: Vec<CheckResult>,
pub profile_name: String,
pub profile_hash: String,
pub authority_summary: AuthoritySummary,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub threat_analysis: Option<ThreatAnalysis>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ThreatAnalysis {
pub boundary_clustering_score: f64,
pub authority_probing_score: f64,
pub replay_similarity_score: f64,
pub drift_score: f64,
pub anomaly_score: f64,
pub composite_threat_score: f64,
pub alert: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct CheckResult {
pub name: String,
pub category: String,
pub passed: bool,
pub details: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub derating: Option<DeratingAdvice>,
}
impl CheckResult {
pub fn new(
name: impl Into<String>,
category: impl Into<String>,
passed: bool,
details: impl Into<String>,
) -> Self {
Self {
name: name.into(),
category: category.into(),
passed,
details: details.into(),
derating: None,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DeratingAdvice {
pub velocity_scale: f64,
pub intensity_scale: f64,
pub reason: String,
}
impl Eq for DeratingAdvice {}
impl std::hash::Hash for DeratingAdvice {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.reason.hash(state);
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct AuthoritySummary {
pub origin_principal: String,
pub hop_count: usize,
pub operations_granted: Vec<String>,
pub operations_required: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SignedVerdict {
#[serde(flatten)]
pub verdict: Verdict,
pub verdict_signature: String,
pub signer_kid: String,
}