use crate::contract::budget_witness::BudgetWitnesses;
use crate::contract::capability::Enforcement;
use crate::contract::ids::{
ArtifactId, BackendId, BoundaryPlanHash, BoundaryReportHash, ContentHash,
};
use crate::contract::plan::{AdmittedRequirement, BoundaryRequirement};
use crate::contract::support::BackendProfileSnapshot;
use serde::{Deserialize, Serialize};
pub const BOUNDARY_REPORT_SCHEMA_VERSION: u16 = 1;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Outcome {
Completed,
Denied,
Failed,
Timeout,
Killed,
Unsupported,
SupervisorFault,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct ObservedFact {
pub kind: String,
pub detail: String,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct DeniedAttempt {
pub requirement: BoundaryRequirement,
pub detail: String,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct CaptureRefs {
pub stdout: Option<String>,
pub stderr: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct StagedArtifact {
pub artifact_id: ArtifactId,
pub content_hash: ContentHash,
pub name: String,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum ExitStatus {
Code(i32),
Signal(i32),
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum BoundaryFinding {
RequirementAdmitted {
requirement: BoundaryRequirement,
enforcement: Enforcement,
},
NoConfinement {
requirement: BoundaryRequirement,
},
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct BoundaryReportBody {
pub schema_version: u16,
pub plan_id: BoundaryPlanHash,
pub backend: BackendId,
pub profile: BackendProfileSnapshot,
pub outcome: Outcome,
pub admitted: Vec<AdmittedRequirement>,
pub observed: Vec<ObservedFact>,
pub denied: Vec<DeniedAttempt>,
pub exit: Option<ExitStatus>,
pub captured: CaptureRefs,
pub artifacts: Vec<StagedArtifact>,
pub budget: BudgetWitnesses,
pub findings: Vec<BoundaryFinding>,
}
impl BoundaryReportBody {
pub fn body_hash(&self) -> Result<BoundaryReportHash, rmp_serde::encode::Error> {
let mut body = self.clone();
body.findings.sort();
let bytes = batpak::canonical::to_bytes(&body)?;
Ok(BoundaryReportHash(batpak::event::hash::compute_hash(
&bytes,
)))
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct BoundaryReport {
pub body: BoundaryReportBody,
pub body_hash: BoundaryReportHash,
}