Skip to main content

sim_lib_web_core/
policy.rs

1use crate::WebRecordError;
2
3/// Every independent policy question; a complete decision set contains all ten.
4#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
5pub enum PolicyKind {
6    EgressZone,
7    Robots,
8    Method,
9    Domain,
10    Media,
11    Bytes,
12    Redirects,
13    Rate,
14    CacheMode,
15    ResearchBudget,
16}
17impl PolicyKind {
18    pub const ALL: [Self; 10] = [
19        Self::EgressZone,
20        Self::Robots,
21        Self::Method,
22        Self::Domain,
23        Self::Media,
24        Self::Bytes,
25        Self::Redirects,
26        Self::Rate,
27        Self::CacheMode,
28        Self::ResearchBudget,
29    ];
30}
31#[derive(Clone, Debug, PartialEq, Eq)]
32pub enum PolicyVerdict {
33    Allow,
34    Deny,
35}
36#[derive(Clone, Debug, PartialEq, Eq)]
37pub struct PolicyDecision {
38    pub kind: PolicyKind,
39    pub verdict: PolicyVerdict,
40    pub rule: String,
41    pub limit: Option<u64>,
42}
43#[derive(Clone, Debug, PartialEq, Eq)]
44pub struct PolicyReceipt {
45    pub decisions: Vec<PolicyDecision>,
46}
47impl PolicyReceipt {
48    pub fn checked(decisions: Vec<PolicyDecision>) -> Result<Self, WebRecordError> {
49        for kind in PolicyKind::ALL {
50            if decisions.iter().filter(|d| d.kind == kind).count() != 1 {
51                return Err(WebRecordError::MissingDecision(kind));
52            }
53        }
54        Ok(Self { decisions })
55    }
56    pub fn permits(&self) -> bool {
57        PolicyKind::ALL.into_iter().all(|kind| {
58            self.decisions
59                .iter()
60                .any(|d| d.kind == kind && d.verdict == PolicyVerdict::Allow)
61        })
62    }
63}