cortex_verifier/state.rs
1//! `VerifiedTrustState` — the output of the trusted-evidence reducer.
2
3use cortex_core::ClaimCeiling;
4use serde::{Deserialize, Serialize};
5
6use crate::witness::WitnessSummary;
7
8/// Failing edge for `VerifiedTrustState::Broken`. `invariant` is a stable
9/// string from [`crate::invariant`]; `detail` is a human-readable explanation
10/// for operators and logs.
11#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
12pub struct BrokenEdge {
13 /// Stable invariant name (e.g. `verifier.witness.disagreement`).
14 pub invariant: String,
15 /// Operator-readable detail string.
16 pub detail: String,
17}
18
19impl BrokenEdge {
20 /// Construct a `BrokenEdge` with a stable invariant name and a detail string.
21 #[must_use]
22 pub fn new(invariant: &'static str, detail: impl Into<String>) -> Self {
23 Self {
24 invariant: invariant.to_string(),
25 detail: detail.into(),
26 }
27 }
28}
29
30/// One of three outcomes per ADR 0041 §"Stable failure taxonomy".
31#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
32#[serde(tag = "state", rename_all = "snake_case")]
33pub enum VerifiedTrustState {
34 /// Every required witness class is present, disjoint, fresh, well-tiered,
35 /// and signature-valid. The verifier promotes the claim to the given
36 /// effective ceiling.
37 FullChainVerified {
38 /// Effective ceiling the claim is allowed at.
39 ceiling: ClaimCeiling,
40 /// Summary of every witness that contributed.
41 witnesses: Vec<WitnessSummary>,
42 },
43 /// Some required witness class is missing or insufficient, but no edge
44 /// outright failed. Advisory-only; cannot promote.
45 Partial {
46 /// Per-axis reasons the partial result was emitted.
47 reasons: Vec<String>,
48 /// Summary of every witness that did pass.
49 witnesses: Vec<WitnessSummary>,
50 },
51 /// A required axis outright failed (digest mismatch, stale, domain overlap,
52 /// signature invalid, ceiling below required, policy fail-closed).
53 Broken {
54 /// Exact failing edge with stable invariant name.
55 edge: BrokenEdge,
56 /// Summary of every witness that was supplied. Useful for diagnosis.
57 witnesses: Vec<WitnessSummary>,
58 },
59}
60
61impl VerifiedTrustState {
62 /// True iff this is `FullChainVerified`.
63 #[must_use]
64 pub const fn is_full_chain_verified(&self) -> bool {
65 matches!(self, Self::FullChainVerified { .. })
66 }
67
68 /// True iff this is `Broken { .. }`.
69 #[must_use]
70 pub const fn is_broken(&self) -> bool {
71 matches!(self, Self::Broken { .. })
72 }
73
74 /// True iff this is `Partial { .. }`.
75 #[must_use]
76 pub const fn is_partial(&self) -> bool {
77 matches!(self, Self::Partial { .. })
78 }
79
80 /// Stable wire string for the variant (`full_chain_verified`, `partial`,
81 /// or `broken`).
82 #[must_use]
83 pub const fn wire_str(&self) -> &'static str {
84 match self {
85 Self::FullChainVerified { .. } => "full_chain_verified",
86 Self::Partial { .. } => "partial",
87 Self::Broken { .. } => "broken",
88 }
89 }
90}