use std::collections::{BTreeMap, BTreeSet};
use super::types::{
Anomaly, Contribution, Decision, EvalContext, OptimizeCandidate, OptimizeContext, Rewrite,
};
use crate::generated::types::Verdict;
pub fn rank(verdict: &Verdict) -> u8 {
match verdict {
Verdict::Allow => 0,
Verdict::Optimize => 1,
Verdict::Ask => 2,
Verdict::Block => 3,
}
}
pub fn join(contributions: &[Contribution]) -> Option<&Contribution> {
best(contributions.iter())
}
fn best<'a>(contributions: impl Iterator<Item = &'a Contribution>) -> Option<&'a Contribution> {
contributions.min_by(|left, right| {
rank(&right.verdict)
.cmp(&rank(&left.verdict))
.then_with(|| artifact_id(left).cmp(artifact_id(right)))
})
}
pub fn assemble(contributions: &[Contribution], ctx: &EvalContext<'_>) -> Decision {
let active = without_same_layer_conflicts(contributions);
let enforcing: Vec<&Contribution> = active
.iter()
.copied()
.filter(|c| c.is_enforcing())
.collect();
let monitoring: Vec<&Contribution> = active
.iter()
.copied()
.filter(|c| !c.is_enforcing())
.collect();
let joined = best(enforcing.iter().copied());
let shadow = best(monitoring.iter().copied());
let (actual_optimize, mut optimize_shadowed) =
if joined.is_some_and(|c| c.verdict == Verdict::Optimize) {
select_optimize(&enforcing)
} else {
(None, Vec::new())
};
let (monitor_optimize, monitor_shadowed) =
if shadow.is_some_and(|c| c.verdict == Verdict::Optimize) {
select_optimize(&monitoring)
} else {
(None, Vec::new())
};
optimize_shadowed.extend(monitor_shadowed);
optimize_shadowed.truncate(32);
let decided = actual_optimize.or(joined);
let record_source = match decided {
Some(candidate) if matches!(candidate.verdict, Verdict::Block | Verdict::Ask) => {
Some(candidate)
}
Some(candidate) if candidate.verdict == Verdict::Allow && monitor_optimize.is_some() => {
monitor_optimize
}
Some(candidate) => Some(candidate),
None => shadow
.filter(|candidate| matches!(candidate.verdict, Verdict::Block | Verdict::Ask))
.or(monitor_optimize),
};
let inconclusive_facts: Vec<String> = active
.iter()
.flat_map(|c| c.inconclusive.iter().cloned())
.collect::<BTreeSet<String>>()
.into_iter()
.collect();
let anomalies: Vec<Anomaly> = active
.iter()
.flat_map(|c| {
c.anomalies.iter().map(|code| Anomaly {
code: code.clone(),
artifact_id: c.artifact_id.clone(),
atom_id: c.atom_id.clone(),
})
})
.collect();
Decision {
verdict: decided.map(|c| c.verdict).unwrap_or(Verdict::Allow),
artifact_id: record_source.and_then(|c| c.artifact_id.clone()),
atom_id: record_source.and_then(|c| c.atom_id.clone()),
policy_public_id: record_source.and_then(|c| c.policy_public_id.clone()),
dimension: record_source.and_then(|c| c.dimension.clone()),
mode: record_source.map(|c| c.mode.clone()),
tier: record_source.and_then(|c| c.tier),
reason: record_source.map(|c| c.reason.clone()).unwrap_or_default(),
would_have_verdict: shadow.map(|c| c.verdict),
inconclusive_facts,
rewrite: rewrite(enforcing.iter().copied()),
optimize: (actual_optimize.is_some() || monitor_optimize.is_some()).then(|| {
OptimizeContext {
actual: actual_optimize.and_then(selected_evidence),
monitor: monitor_optimize.and_then(selected_evidence),
shadowed: optimize_shadowed,
}
}),
hold: decided.and_then(|c| c.hold.clone()),
effects: ctx.classification.effects.clone(),
undecided: active.is_empty(),
unknown: ctx.classification.unknown.clone(),
anomalies,
ground_key: decided.and_then(|c| c.exception_ground_key.clone()),
warnings: ctx.warnings.clone(),
}
}
fn without_same_layer_conflicts(contributions: &[Contribution]) -> Vec<&Contribution> {
type GroupKey = (Vec<String>, String);
let mut groups: BTreeMap<GroupKey, Vec<&super::types::OptimizeCandidateInternal>> =
BTreeMap::new();
for contribution in contributions {
let Some(optimize) = contribution.optimize.as_ref() else {
continue;
};
groups
.entry((optimize.layer_path.clone(), contribution.mode.0.clone()))
.or_default()
.push(optimize);
}
let conflicted: BTreeSet<GroupKey> = groups
.into_iter()
.filter_map(|(key, candidates)| {
let first = candidates.first()?;
candidates
.iter()
.skip(1)
.any(|candidate| {
candidate.evidence.lever != first.evidence.lever
|| candidate.params.canonical_value() != first.params.canonical_value()
})
.then_some(key)
})
.collect();
contributions
.iter()
.filter(|contribution| {
contribution.optimize.as_ref().is_none_or(|optimize| {
!conflicted.contains(&(optimize.layer_path.clone(), contribution.mode.0.clone()))
})
})
.collect()
}
fn select_optimize<'a>(
contributions: &[&'a Contribution],
) -> (Option<&'a Contribution>, Vec<OptimizeCandidate>) {
let mut candidates: Vec<&Contribution> = contributions
.iter()
.copied()
.filter(|contribution| {
contribution.verdict == Verdict::Optimize && contribution.optimize.is_some()
})
.collect();
candidates.sort_by(|left, right| {
candidate_path(left)
.len()
.cmp(&candidate_path(right).len())
.then_with(|| candidate_path(left).cmp(candidate_path(right)))
.then_with(|| artifact_id(left).cmp(artifact_id(right)))
});
let Some(selected) = candidates.first().copied() else {
return (None, Vec::new());
};
let selected_path = candidate_path(selected).to_vec();
let shadowed = candidates
.into_iter()
.skip(1)
.filter_map(|candidate| {
let optimize = candidate.optimize.as_ref()?;
let mut evidence = optimize.evidence.clone();
evidence.reason = if optimize.layer_path == selected_path {
"same_layer_equivalent"
} else {
"parent_overlap"
}
.to_string();
Some(evidence)
})
.collect();
(Some(selected), shadowed)
}
fn selected_evidence(contribution: &Contribution) -> Option<OptimizeCandidate> {
contribution
.optimize
.as_ref()
.map(|optimize| optimize.evidence.clone())
}
fn candidate_path(contribution: &Contribution) -> &[String] {
contribution
.optimize
.as_ref()
.map(|candidate| candidate.layer_path.as_slice())
.unwrap_or_default()
}
fn rewrite<'a>(enforcing: impl Iterator<Item = &'a Contribution>) -> Option<Rewrite> {
enforcing
.filter(|c| c.verdict == Verdict::Optimize && c.optimize.is_none())
.find_map(|c| {
c.lever.clone().map(|lever| Rewrite {
lever,
artifact_id: c.artifact_id.clone(),
steer_instruction: c.steer_instruction.clone(),
})
})
}
fn artifact_id(contribution: &Contribution) -> &str {
contribution.artifact_id.as_deref().unwrap_or("")
}
#[cfg(test)]
mod tests {
use super::*;
use crate::generated::types::{Lever, PolicyMode};
use crate::zone_eval::facts::FactSet;
use crate::zone_eval::types::{Classification, Event, MODE_ENFORCE, MODE_MONITOR};
const NOW: i64 = 1_756_742_400_000;
fn contribution(artifact_id: &str, mode: &str, verdict: Verdict) -> Contribution {
Contribution {
artifact_id: Some(artifact_id.to_string()),
atom_id: Some(format!("atom-{artifact_id}")),
policy_public_id: None,
dimension: None,
mode: PolicyMode(mode.to_string()),
tier: Some(1),
verdict,
reason: artifact_id.to_string(),
inconclusive: Vec::new(),
anomalies: Vec::new(),
hold: None,
exception_ground_key: None,
lever: None,
steer_instruction: None,
optimize: None,
}
}
fn decision(contributions: &[Contribution]) -> Decision {
let event = Event::default();
let classification = Classification::default();
let facts = FactSet::default();
let ctx = EvalContext::new(&event, &classification, &facts, NOW);
assemble(contributions, &ctx)
}
#[test]
fn the_lattice_is_block_over_ask_over_optimize_over_allow() {
assert!(rank(&Verdict::Block) > rank(&Verdict::Ask));
assert!(rank(&Verdict::Ask) > rank(&Verdict::Optimize));
assert!(rank(&Verdict::Optimize) > rank(&Verdict::Allow));
}
#[test]
fn monitor_never_joins() {
let decision = decision(&[
contribution("m", MODE_MONITOR, Verdict::Block),
contribution("e", MODE_ENFORCE, Verdict::Allow),
]);
assert_eq!(decision.verdict, Verdict::Allow);
assert_eq!(decision.artifact_id.as_deref(), Some("e"));
assert_eq!(decision.would_have_verdict, Some(Verdict::Block));
assert!(
!decision.undecided,
"it was not silent, it just did not decide"
);
}
#[test]
fn an_all_monitor_ask_or_block_keeps_its_shadow_record_source() {
for verdict in [Verdict::Ask, Verdict::Block] {
let decision = decision(&[contribution("m", MODE_MONITOR, verdict)]);
assert_eq!(decision.verdict, Verdict::Allow);
assert_eq!(decision.artifact_id.as_deref(), Some("m"));
assert_eq!(decision.atom_id.as_deref(), Some("atom-m"));
assert_eq!(
decision.mode.as_ref().map(|mode| mode.0.as_str()),
Some(MODE_MONITOR)
);
assert_eq!(decision.tier, Some(1));
assert_eq!(decision.reason, "m");
assert_eq!(decision.would_have_verdict, Some(verdict));
assert!(!decision.undecided);
}
}
#[test]
fn an_all_monitor_allow_still_names_nobody() {
let decision = decision(&[contribution("m", MODE_MONITOR, Verdict::Allow)]);
assert_eq!(decision.verdict, Verdict::Allow);
assert_eq!(decision.artifact_id, None);
assert_eq!(decision.mode, None);
assert_eq!(decision.would_have_verdict, Some(Verdict::Allow));
assert!(!decision.undecided);
}
#[test]
fn nothing_at_all_is_undecided_and_an_allow_is_not() {
assert!(decision(&[]).undecided);
assert!(
!decision(&[contribution("a", MODE_ENFORCE, Verdict::Allow)]).undecided,
"an artifact may allow on purpose"
);
}
#[test]
fn a_tie_breaks_on_artifact_id_and_not_on_iteration_order() {
let forward = decision(&[
contribution("a", MODE_ENFORCE, Verdict::Block),
contribution("b", MODE_ENFORCE, Verdict::Block),
]);
let reversed = decision(&[
contribution("b", MODE_ENFORCE, Verdict::Block),
contribution("a", MODE_ENFORCE, Verdict::Block),
]);
assert_eq!(forward.artifact_id.as_deref(), Some("a"));
assert_eq!(forward, reversed, "a replay names the same rule");
}
#[test]
fn r10_gives_the_single_rewrite_to_the_first_enforcing_optimize_with_a_lever() {
let mut without = contribution("a-no-lever", MODE_ENFORCE, Verdict::Optimize);
without.lever = None;
let mut first = contribution("b-steer", MODE_ENFORCE, Verdict::Optimize);
first.lever = Some(Lever("steer".to_string()));
first.steer_instruction = Some("push a branch instead".to_string());
let mut second = contribution("c-clamp", MODE_ENFORCE, Verdict::Optimize);
second.lever = Some(Lever("effort_clamp".to_string()));
let rewrite = decision(&[without, first, second])
.rewrite
.expect("the first lever-bearing optimize owns it");
assert_eq!(rewrite.lever.0, "steer");
assert_eq!(rewrite.artifact_id.as_deref(), Some("b-steer"));
assert_eq!(
rewrite.steer_instruction.as_deref(),
Some("push a branch instead")
);
}
#[test]
fn a_monitor_artifact_never_spends_r10s_single_slot() {
let mut monitored = contribution("a-monitor", MODE_MONITOR, Verdict::Optimize);
monitored.lever = Some(Lever("effort_clamp".to_string()));
let mut enforced = contribution("b-steer", MODE_ENFORCE, Verdict::Optimize);
enforced.lever = Some(Lever("steer".to_string()));
let rewrite = decision(&[monitored.clone(), enforced])
.rewrite
.expect("the enforcing one owns it");
assert_eq!(rewrite.artifact_id.as_deref(), Some("b-steer"));
assert_eq!(
decision(&[monitored]).rewrite,
None,
"a monitor-only bundle applies nothing to the agent"
);
}
#[test]
fn the_hold_and_the_ground_key_come_from_the_artifact_that_decided() {
let mut monitored = contribution("a-monitor", MODE_MONITOR, Verdict::Block);
monitored.exception_ground_key = Some("m".repeat(64));
let mut enforced = contribution("b-enforce", MODE_ENFORCE, Verdict::Ask);
enforced.exception_ground_key = Some("e".repeat(64));
let decision = decision(&[monitored, enforced]);
assert_eq!(decision.ground_key, Some("e".repeat(64)));
assert_eq!(decision.hold, None);
}
#[test]
fn inconclusive_facts_are_sorted_deduplicated_and_gathered_from_every_artifact() {
let mut monitored = contribution("a", MODE_MONITOR, Verdict::Allow);
monitored.inconclusive = vec!["change_ticket".to_string(), "approved_domains".to_string()];
let mut enforced = contribution("b", MODE_ENFORCE, Verdict::Allow);
enforced.inconclusive = vec!["change_ticket".to_string()];
assert_eq!(
decision(&[monitored, enforced]).inconclusive_facts,
vec!["approved_domains".to_string(), "change_ticket".to_string()],
"a monitor artifact that could not read a fact still found the gap"
);
}
#[test]
fn anomalies_record_from_every_artifact_and_carry_their_own_provenance() {
let mut monitored = contribution("a", MODE_MONITOR, Verdict::Allow);
monitored.anomalies = vec!["burst".to_string()];
let anomalies = decision(&[monitored]).anomalies;
assert_eq!(anomalies.len(), 1);
assert_eq!(anomalies[0].code, "burst");
assert_eq!(anomalies[0].artifact_id.as_deref(), Some("a"));
assert_eq!(anomalies[0].atom_id.as_deref(), Some("atom-a"));
}
}