use super::LinuxBackend;
use crate::backend::linux::launch::LaunchObservation;
use crate::contract::backend::Backend;
use crate::contract::budget_witness::BudgetWitnesses;
use crate::contract::capability::{Capability, Enforcement, FsAccess, PathSet};
use crate::contract::plan::{BoundaryPlan, BoundaryRequirement};
use crate::contract::report::{
BoundaryReportBody, CaptureRefs, ExitStatus, ObservedFact, Outcome,
BOUNDARY_REPORT_SCHEMA_VERSION,
};
pub(super) fn map_observation(
backend: &LinuxBackend,
plan: &BoundaryPlan,
exe: &str,
confined: bool,
obs: &LaunchObservation,
mut observed: Vec<ObservedFact>,
process_peak: Option<u64>,
) -> BoundaryReportBody {
observed.push(ObservedFact {
kind: "workload_launched".to_string(),
detail: format!("launcher exec {exe} (confined={confined})"),
});
observed.push(ObservedFact {
kind: "launcher_terminal".to_string(),
detail: format!(
"terminal={:?} confinement_installed={} launcher_exit={:?}",
obs.terminal, obs.confinement_installed, obs.launcher_exit
),
});
for note in &obs.notes {
observed.push(ObservedFact {
kind: "launcher_note".to_string(),
detail: note.clone(),
});
}
if confined && !obs.confinement_installed {
observed.push(ObservedFact {
kind: "confinement_not_installed".to_string(),
detail: "a Filesystem-scoped plan ran but the launcher reported no \
landlock install"
.to_string(),
});
}
observed.push(ObservedFact {
kind: "stream_captured".to_string(),
detail: format!(
"captured {} stdout byte(s), {} stderr byte(s) via the launcher's \
inherited piped stdio",
obs.captured_stdout.len(),
obs.captured_stderr.len()
),
});
let captured = CaptureRefs {
stdout: Some(format!("inline:{}b", obs.captured_stdout.len())),
stderr: Some(format!("inline:{}b", obs.captured_stderr.len())),
};
let process_enforced = plan.budgets.process_count.selected_guarantee == Enforcement::Enforced;
let budget = match process_peak {
Some(peak) if process_enforced => {
observed.push(ObservedFact {
kind: "process_count_witnessed".to_string(),
detail: format!(
"cgroup pids.peak={peak} against pids.max={} (cgroup_v2_pids: Hard cap)",
plan.budgets.process_count.effective_limit
),
});
BudgetWitnesses::with_process_count(&plan.budgets, peak)
}
_ => BudgetWitnesses::unwitnessed(&plan.budgets),
};
let outcome = obs.outcome().unwrap_or(Outcome::SupervisorFault);
let exit = exec_exit(outcome);
body(backend, plan, outcome, exit, captured, observed, budget)
}
fn exec_exit(outcome: Outcome) -> Option<ExitStatus> {
match outcome {
Outcome::Completed => Some(ExitStatus::Code(0)),
Outcome::Denied
| Outcome::Failed
| Outcome::Timeout
| Outcome::Killed
| Outcome::Unsupported
| Outcome::SupervisorFault => None,
}
}
pub(super) fn filesystem_capability(plan: &BoundaryPlan) -> Option<(FsAccess, PathSet)> {
plan.admitted.iter().find_map(|a| match &a.requirement {
BoundaryRequirement::Capability(Capability::Filesystem { access, scope, .. }) => {
Some((*access, scope.clone()))
}
BoundaryRequirement::Capability(_) | BoundaryRequirement::HostControl(_) => None,
})
}
pub(super) fn fail_closed(
backend: &LinuxBackend,
plan: &BoundaryPlan,
outcome: Outcome,
observed: Vec<ObservedFact>,
) -> BoundaryReportBody {
body(
backend,
plan,
outcome,
None,
CaptureRefs::default(),
observed,
BudgetWitnesses::unwitnessed(&plan.budgets),
)
}
fn body(
backend: &LinuxBackend,
plan: &BoundaryPlan,
outcome: Outcome,
exit: Option<ExitStatus>,
captured: CaptureRefs,
observed: Vec<ObservedFact>,
budget: BudgetWitnesses,
) -> BoundaryReportBody {
BoundaryReportBody {
schema_version: BOUNDARY_REPORT_SCHEMA_VERSION,
plan_id: plan.plan_id,
backend: backend.id.clone(),
profile: backend.probe(),
outcome,
admitted: plan.admitted.clone(),
observed,
denied: Vec::new(),
exit,
captured,
budget,
artifacts: Vec::new(),
findings: Vec::new(),
}
}