Skip to main content

typesec_odrl/
audit.rs

1//! Audit log types for ODRL policy decisions.
2
3use tracing::info;
4
5use crate::model::{ConstraintOperand, OdrlRuleType};
6
7/// A structured audit record for a single ODRL policy check.
8#[derive(Debug)]
9pub struct OdrlAuditEvent {
10    /// The policy UID that produced this verdict.
11    pub policy_uid: String,
12    /// The matched rule type (or `None` if no rule matched).
13    pub matched_rule: Option<OdrlRuleType>,
14    /// The subject making the request.
15    pub subject: String,
16    /// The action requested.
17    pub action: String,
18    /// The target resource.
19    pub target: String,
20    /// The final verdict.
21    pub verdict: OdrlVerdict,
22    /// Constraint evaluation results.
23    pub constraint_results: Vec<ConstraintEval>,
24}
25
26/// Verdict of an ODRL check.
27#[derive(Debug, Clone)]
28#[non_exhaustive]
29pub enum OdrlVerdict {
30    /// A permission rule matched and all constraints passed.
31    Permitted,
32    /// A prohibition rule matched and all constraints passed (action blocked).
33    Prohibited {
34        /// Human-readable reason explaining why the action is prohibited.
35        reason: String,
36    },
37    /// A permission rule matched but was overridden by a prohibition.
38    Overridden {
39        /// The policy UID containing the prohibition that took priority.
40        by_policy: String,
41        /// Human-readable reason explaining the override.
42        reason: String,
43    },
44    /// No matching rule found.
45    NotApplicable,
46    /// A permission rule matched but one or more constraints failed.
47    ConstraintFailed {
48        /// Description of the constraint that failed.
49        constraint: String,
50    },
51}
52
53/// Record of a single constraint's evaluation.
54#[derive(Debug, Clone)]
55pub struct ConstraintEval {
56    /// The left operand (e.g., `"purpose"`).
57    pub operand: ConstraintOperand,
58    /// Whether it passed.
59    pub passed: bool,
60}
61
62impl OdrlAuditEvent {
63    /// Emit this event to the `tracing` subscriber.
64    pub fn log(&self) {
65        let verdict_str = match &self.verdict {
66            OdrlVerdict::Permitted => "permitted".to_owned(),
67            OdrlVerdict::Prohibited { reason } => format!("prohibited: {reason}"),
68            OdrlVerdict::Overridden { by_policy, reason } => {
69                format!("overridden by {by_policy}: {reason}")
70            }
71            OdrlVerdict::NotApplicable => "not_applicable".to_owned(),
72            OdrlVerdict::ConstraintFailed { constraint } => {
73                format!("constraint_failed: {constraint}")
74            }
75        };
76
77        info!(
78            policy = %self.policy_uid,
79            subject = %self.subject,
80            action = %self.action,
81            target = %self.target,
82            verdict = %verdict_str,
83            "odrl policy decision"
84        );
85    }
86}