Skip to main content

sim_lib_compute_auto/
evidence.rs

1//! Physical evidence discriminators and acceptance checks.
2
3use sim_lib_compute_model::ModeledComputeProfile;
4
5use crate::profile::ComputeDeviceIdentity;
6
7/// Discriminator for compute evidence that might otherwise look physical.
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9pub enum ComputeEvidenceKind {
10    /// Deterministic model evidence; never proves a physical device.
11    Modeled,
12    /// Host-side emulation of a device-shaped provider; never proves physical execution.
13    HostEmulated,
14    /// Evidence captured from a physical device path.
15    PhysicalDevice,
16}
17
18impl ComputeEvidenceKind {
19    /// Stable profile encoding label.
20    pub fn as_str(self) -> &'static str {
21        match self {
22            Self::Modeled => "modeled",
23            Self::HostEmulated => "host-emulated",
24            Self::PhysicalDevice => "physical-device",
25        }
26    }
27}
28
29impl TryFrom<&str> for ComputeEvidenceKind {
30    type Error = PhysicalEvidenceError;
31
32    fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
33        match value {
34            "modeled" => Ok(Self::Modeled),
35            "host-emulated" => Ok(Self::HostEmulated),
36            "physical-device" => Ok(Self::PhysicalDevice),
37            other => Err(PhysicalEvidenceError::new(format!(
38                "unknown compute evidence kind: {other}"
39            ))),
40        }
41    }
42}
43
44/// Evidence that can be checked before accepting a physical-device claim.
45pub trait ComputePhysicalEvidence {
46    /// Reported evidence kind.
47    fn evidence_kind(&self) -> ComputeEvidenceKind;
48
49    /// Claimed device identity, when the record carries one.
50    fn claimed_identity(&self) -> Option<&ComputeDeviceIdentity> {
51        None
52    }
53
54    /// Observed device identity captured by the producer, when available.
55    fn observed_identity(&self) -> Option<&ComputeDeviceIdentity> {
56        None
57    }
58}
59
60impl ComputePhysicalEvidence for ModeledComputeProfile {
61    fn evidence_kind(&self) -> ComputeEvidenceKind {
62        ComputeEvidenceKind::Modeled
63    }
64}
65
66/// Failure returned when evidence is not acceptable as physical-device proof.
67#[derive(Clone, Debug, PartialEq, Eq)]
68pub struct PhysicalEvidenceError {
69    message: String,
70}
71
72impl PhysicalEvidenceError {
73    fn new(message: impl Into<String>) -> Self {
74        Self {
75            message: message.into(),
76        }
77    }
78}
79
80impl std::fmt::Display for PhysicalEvidenceError {
81    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82        formatter.write_str(&self.message)
83    }
84}
85
86impl std::error::Error for PhysicalEvidenceError {}
87
88/// Verifies that evidence can satisfy a physical-device acceptance boundary.
89pub fn verify_physical(
90    evidence: &(impl ComputePhysicalEvidence + ?Sized),
91) -> std::result::Result<(), PhysicalEvidenceError> {
92    if evidence.evidence_kind() != ComputeEvidenceKind::PhysicalDevice {
93        return Err(PhysicalEvidenceError::new(format!(
94            "compute evidence is {}, not physical-device",
95            evidence.evidence_kind().as_str()
96        )));
97    }
98    match (evidence.claimed_identity(), evidence.observed_identity()) {
99        (Some(claimed), Some(observed)) if claimed == observed => Ok(()),
100        (Some(_), Some(_)) => Err(PhysicalEvidenceError::new(
101            "compute evidence identity was renamed after capture",
102        )),
103        _ => Err(PhysicalEvidenceError::new(
104            "compute physical evidence is missing observed identity",
105        )),
106    }
107}