use std::path::PathBuf;
use crate::enforce::{finding_result, EnforceCtx, Finding, RegisteredEnforcer};
include!(concat!(env!("OUT_DIR"), "/enforcers_registry.rs"));
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LayerStatus {
Pass,
Fail,
}
#[derive(Clone)]
pub struct LayerFinding {
pub layer: &'static str,
pub message: String,
pub source: Option<std::sync::Arc<dyn std::error::Error + Send + Sync>>,
}
impl PartialEq for LayerFinding {
fn eq(&self, other: &Self) -> bool {
self.layer == other.layer
&& self.message == other.message
&& self.source.as_ref().map(std::string::ToString::to_string)
== other.source.as_ref().map(std::string::ToString::to_string)
}
}
impl core::fmt::Debug for LayerFinding {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("LayerFinding")
.field("layer", &self.layer)
.field("message", &self.message)
.field("source", &self.source.as_ref().map(|err| err.to_string()))
.finish()
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct LayerCheck {
pub layer: &'static str,
pub status: LayerStatus,
pub findings: Vec<LayerFinding>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct EnforcementReport {
pub checks: Vec<LayerCheck>,
}
impl EnforcementReport {
#[inline]
pub fn is_success(&self) -> bool {
self.checks
.iter()
.all(|check| check.status == LayerStatus::Pass)
}
#[inline]
pub fn failures(&self) -> Vec<&LayerFinding> {
self.checks
.iter()
.filter(|check| check.status == LayerStatus::Fail)
.flat_map(|check| check.findings.iter())
.collect()
}
}
#[inline]
pub fn registered() -> &'static [&'static dyn RegisteredEnforcer] {
ALL_ENFORCERS
}
#[inline]
pub fn enforce(ctx: &EnforceCtx<'_>) -> Vec<Finding> {
let gpu_span = tracing::info_span!(
"vyre_conform.gpu_mandatory",
gate = "enforcer_gpu_mandatory",
findings = tracing::field::Empty,
verdict = tracing::field::Empty
);
let _entered = gpu_span.enter();
let gpu_findings =
crate::enforce::enforcers::enforcer_gpu_mandatory::REGISTERED.run_registered(ctx);
gpu_span.record("findings", gpu_findings.len());
if !gpu_findings.is_empty() {
gpu_span.record("verdict", "fail");
tracing::warn!(
gate = "enforcer_gpu_mandatory",
findings = gpu_findings.len(),
"Fix: remove Category C CPU fallbacks before running downstream enforcement."
);
return gpu_findings;
}
gpu_span.record("verdict", "pass");
drop(_entered);
registered()
.iter()
.filter(|enforcer| enforcer.id() != "enforcer_gpu_mandatory")
.flat_map(|enforcer| enforcer.run_registered(ctx))
.collect()
}
#[must_use]
#[inline]
pub fn enforce_all() -> EnforcementReport {
let span = tracing::info_span!("vyre_conform.enforce_all", verdict = tracing::field::Empty);
let _entered = span.enter();
let specs = crate::spec::op_registry::all_specs();
let workspace = crate::enforce::workspace_root();
let ctx = EnforceCtx::new(&specs, None, &workspace);
let gpu_mandatory = &crate::enforce::enforcers::enforcer_gpu_mandatory::REGISTERED;
let gpu_span = tracing::info_span!(
"vyre_conform.gpu_mandatory",
gate = gpu_mandatory.id(),
findings = tracing::field::Empty,
verdict = tracing::field::Empty
);
let _gpu_entered = gpu_span.enter();
let gpu_findings = gpu_mandatory.run_registered(&ctx);
gpu_span.record("findings", gpu_findings.len());
if !gpu_findings.is_empty() {
gpu_span.record("verdict", "fail");
tracing::warn!(
gate = gpu_mandatory.id(),
findings = gpu_findings.len(),
"Fix: remove Category C CPU fallbacks before issuing a certificate."
);
let report = EnforcementReport {
checks: vec![fail(
gpu_mandatory.id(),
gpu_findings
.into_iter()
.map(|finding| finding.message())
.collect(),
)],
};
span.record("verdict", "fail");
return report;
}
gpu_span.record("verdict", "pass");
drop(_gpu_entered);
let mut checks = vec![pass(gpu_mandatory.id())];
checks.extend(
registered()
.iter()
.filter(|enforcer| enforcer.id() != "enforcer_gpu_mandatory")
.map(|enforcer| {
let findings = enforcer.run_registered(&ctx);
if findings.is_empty() {
pass(enforcer.id())
} else {
fail(
enforcer.id(),
findings
.into_iter()
.map(|finding| finding.message())
.collect(),
)
}
}),
);
let report = EnforcementReport { checks };
span.record("verdict", if report.is_success() { "pass" } else { "fail" });
report
}
#[inline]
pub(crate) fn pass(layer: &'static str) -> LayerCheck {
LayerCheck {
layer,
status: LayerStatus::Pass,
findings: Vec::new(),
}
}
#[inline]
pub(crate) fn fail(layer: &'static str, messages: Vec<String>) -> LayerCheck {
LayerCheck {
layer,
status: LayerStatus::Fail,
findings: messages
.into_iter()
.map(|message| LayerFinding {
layer,
message,
source: None,
})
.collect(),
}
}
#[inline]
pub(crate) fn push_per_op_check(
checks: &mut Vec<LayerCheck>,
layer: &'static str,
specs: &[crate::OpSpec],
mut run: impl FnMut(&crate::OpSpec) -> Vec<String>,
) {
let mut findings = Vec::new();
for spec in specs {
let span = tracing::info_span!(
"vyre_conform.layer",
layer_id = layer,
op_id = spec.id,
verdict = tracing::field::Empty
);
let _entered = span.enter();
let op_findings = run(spec);
span.record(
"verdict",
if op_findings.is_empty() {
"pass"
} else {
"fail"
},
);
findings.extend(op_findings);
}
checks.push(if findings.is_empty() {
pass(layer)
} else {
fail(layer, findings)
});
}
#[inline]
pub(crate) fn replace_layer_check(
checks: &mut [LayerCheck],
layer: &'static str,
messages: Vec<String>,
) {
if let Some(check) = checks.iter_mut().find(|check| check.layer == layer) {
*check = if messages.is_empty() {
pass(layer)
} else {
fail(layer, messages)
};
}
}
#[inline]
pub(crate) fn layer_findings(checks: &[LayerCheck], layer: &'static str) -> Vec<String> {
checks
.iter()
.filter(|check| check.layer == layer)
.flat_map(|check| check.findings.iter().map(|finding| finding.message.clone()))
.collect()
}
#[inline]
pub(crate) fn zero_stub_roots() -> Result<Vec<PathBuf>, String> {
match std::env::var("VYRE_CONFORM_ZERO_STUB_ROOTS") {
Ok(explicit) => Ok(explicit
.split(':')
.filter(|piece| !piece.is_empty())
.map(PathBuf::from)
.collect()),
Err(_) => Ok(Vec::new()),
}
}
#[inline]
pub fn result(source: &'static str, messages: Vec<String>) -> Vec<Finding> {
finding_result(source, messages)
}