pub mod execution;
pub mod ids;
pub mod operator;
pub mod plan;
use std::collections::BTreeMap;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::card::drift::DriftMethod;
use crate::card::trigger::TriggerDuration;
use crate::card::verifier::SourceText;
use crate::ids::{BindingId, CardUid, ExecutionId, FeatureName, OperatorDispatchId, SlotName};
pub use ids::{JsonPath, TaskId};
pub use operator::{ComparisonOperator, DivergenceMetric, JsonValueType};
pub use plan::{DagError, ExecutionPlan, Stage, plan_stages};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ContextCapture {
Full,
Hash,
Redact,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(rename_all = "snake_case")]
pub enum FrozenTarget {
Uid(CardUid),
Digest(String),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(deny_unknown_fields)]
pub struct DriftWindow {
pub start: DateTime<Utc>,
pub end: DateTime<Utc>,
}
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
Serialize,
Deserialize,
schemars::JsonSchema,
strum::EnumString,
strum::IntoStaticStr,
)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum VerifierReadiness {
Ready,
BaselineNotReady,
VerifierUnavailable,
}
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
Serialize,
Deserialize,
schemars::JsonSchema,
strum::EnumString,
strum::IntoStaticStr,
)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum VerificationExecutionStatus {
Pending,
Running,
Retrying,
Completed,
Cancelled,
TimedOut,
Errored,
}
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
Serialize,
Deserialize,
schemars::JsonSchema,
strum::EnumString,
strum::IntoStaticStr,
)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum VerificationVerdict {
Passed,
Failed,
Inconclusive,
}
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
Serialize,
Deserialize,
schemars::JsonSchema,
strum::EnumString,
strum::IntoStaticStr,
)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum OperatorDispatchStatus {
Pending,
Running,
Retrying,
Delivered,
Failed,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
pub struct VerificationError {
pub code: String,
pub message: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
pub struct VerificationBindingStatus {
pub binding_id: BindingId,
pub owner_card_uid: CardUid,
pub card_uid: CardUid,
pub verifier_card_uid: CardUid,
pub active: bool,
pub readiness: VerifierReadiness,
pub next_run_at: Option<DateTime<Utc>>,
pub last_activated_at: Option<DateTime<Utc>>,
pub last_execution_id: Option<ExecutionId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub group_end: Option<GroupEndSettings>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
pub struct GroupEndSettings {
pub after: TriggerDuration,
pub sources: BTreeMap<SlotName, GroupSource>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
pub struct GroupSource {
pub reference: SourceText,
pub subject_occurrence_key: String,
pub card_uid: CardUid,
pub verifier_card_uid: CardUid,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
pub struct GroupSnapshot {
pub sources: BTreeMap<SlotName, GroupSourceSnapshot>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
pub struct GroupSourceSnapshot {
pub reference: SourceText,
pub execution_ids: Vec<ExecutionId>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
pub struct OperatorDispatchState {
pub dispatch_id: OperatorDispatchId,
pub operator: FrozenTarget,
pub status: OperatorDispatchStatus,
pub error: Option<VerificationError>,
}
pub const MAX_EXECUTE_BODY_BYTES: usize = 1024 * 1024;
pub const EXECUTION_DEADLINE: std::time::Duration = std::time::Duration::from_mins(1);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
pub enum DriftVerdict {
NoDrift,
Drift,
Inconclusive,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
pub struct DriftReport {
pub method: DriftMethod,
pub features: BTreeMap<FeatureName, FeatureDriftReport>,
pub verdict: DriftVerdict,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
pub struct FeatureDriftReport {
pub feature: FeatureName,
#[serde(default)]
pub score: Option<f64>,
#[serde(default)]
pub threshold: Option<f64>,
pub verdict: DriftVerdict,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "server", schema(value_type = Option<Object>))]
pub evidence: Option<serde_json::Value>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn status_names_round_trip() {
for status in [
VerificationExecutionStatus::Pending,
VerificationExecutionStatus::TimedOut,
VerificationExecutionStatus::Errored,
] {
let name: &'static str = status.into();
assert_eq!(
name.parse::<VerificationExecutionStatus>().ok(),
Some(status)
);
}
let readiness: &'static str = VerifierReadiness::BaselineNotReady.into();
assert_eq!(readiness, "baseline_not_ready");
}
}