Skip to main content

typesec_odrl/
audit.rs

1//! Audit log types for ODRL policy decisions.
2
3use tracing::info;
4
5use crate::model::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)]
28pub enum OdrlVerdict {
29    /// A permission rule matched and all constraints passed.
30    Permitted,
31    /// A prohibition rule matched and all constraints passed (action blocked).
32    Prohibited {
33        /// Human-readable reason explaining why the action is prohibited.
34        reason: String,
35    },
36    /// No matching rule found.
37    NotApplicable,
38    /// A permission rule matched but one or more constraints failed.
39    ConstraintFailed {
40        /// Description of the constraint that failed.
41        constraint: String,
42    },
43}
44
45/// Record of a single constraint's evaluation.
46#[derive(Debug, Clone)]
47pub struct ConstraintEval {
48    /// The left operand (e.g., `"purpose"`).
49    pub operand: String,
50    /// Whether it passed.
51    pub passed: bool,
52}
53
54impl OdrlAuditEvent {
55    /// Emit this event to the `tracing` subscriber.
56    pub fn log(&self) {
57        let verdict_str = match &self.verdict {
58            OdrlVerdict::Permitted => "permitted".to_owned(),
59            OdrlVerdict::Prohibited { reason } => format!("prohibited: {reason}"),
60            OdrlVerdict::NotApplicable => "not_applicable".to_owned(),
61            OdrlVerdict::ConstraintFailed { constraint } => {
62                format!("constraint_failed: {constraint}")
63            }
64        };
65
66        info!(
67            policy = %self.policy_uid,
68            subject = %self.subject,
69            action = %self.action,
70            target = %self.target,
71            verdict = %verdict_str,
72            "odrl policy decision"
73        );
74    }
75}