bacnet_objects/access_control/authorization_context.rs
1//! Mandatory application-owned facts for local authorization.
2
3use super::{
4 AccompanimentDeadline, AccompanimentTiming, AccompanimentWitness, AuthorizationOrder,
5 AuthorizationRightsPolicy, CredentialPresentation, DisableReasonPriority,
6};
7use crate::clock::ClockFrame;
8use bacnet_types::enums::AccessPassbackMode;
9use bacnet_types::primitives::ObjectIdentifier;
10use core::time::Duration;
11
12/// A known application fact or an explicit lack of evidence. No default exists.
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum AuthorizationFact<T> {
15 /// The application supplies this value for a genuinely absent property.
16 Known(T),
17 /// Required evidence is unavailable; this does not mean disabled or zero.
18 Unknown,
19}
20
21/// Which occupancy boundary a presentation crosses for one relevant zone.
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum AuthorizationDirection {
24 /// Entry is checked against a nonzero upper bound.
25 Entering,
26 /// Exit is checked against a nonzero lower bound.
27 Leaving,
28}
29
30/// One application-selected relevant zone and its enforcement fallback.
31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub struct AuthorizationOccupancyZone {
33 /// Local Access Zone whose topology/count/limits are read from the database.
34 pub zone: ObjectIdentifier,
35 /// Established direction; the matching zone point list must contain the point.
36 pub direction: AuthorizationDirection,
37 /// Used only when the point omits the direction's enforcement property.
38 pub fallback_enforced: AuthorizationFact<bool>,
39}
40
41/// The application's complete relevant-zone set; the helper invents no topology.
42#[derive(Debug, Clone, Copy, PartialEq, Eq)]
43pub enum AuthorizationOccupancy<'a> {
44 /// The application establishes that this presentation affects no zone bound.
45 NotApplicable,
46 /// Relevant direction/zones are not established.
47 Unknown,
48 /// All relevant zones, evaluated in this explicit order. Empty is unresolved;
49 /// use NotApplicable to state that no zone check is needed.
50 Zones(&'a [AuthorizationOccupancyZone]),
51}
52
53/// An already established passback observation bound to this transaction/zone.
54/// This helper does not reconstruct a location history.
55#[derive(Debug, Clone, Copy, PartialEq, Eq)]
56pub struct AuthorizationPassbackObservation {
57 /// Complete original tuple to which the observation belongs.
58 pub presentation: CredentialPresentation,
59 /// The local zone in which the observation was established.
60 pub zone: ObjectIdentifier,
61 /// Whether a violation was established before applying timeout/exemption.
62 pub violation: bool,
63 /// Last successful entry of this credential into this zone, sharing the
64 /// monotonic origin. This is not Last_Use_Time. Required to expire a violation
65 /// under a nonzero timeout; a future entry is inconsistent.
66 pub last_successful_entry: Option<Duration>,
67}
68
69/// Passback applicability and missing-property inputs (Clauses 12.32.21–22).
70/// A PASSBACK-exempt credential still reports an established SOFT violation.
71/// Unusable optional reporting evidence is retained in
72/// [`super::AuthorizationEvaluation::passback_reporting_problem`] without
73/// imposing enforcement or another required criterion on the exempt request.
74#[derive(Debug, Clone, Copy, PartialEq, Eq)]
75pub enum AuthorizationPassback {
76 /// The application establishes no relevant passback check for this presentation.
77 NotApplicable,
78 /// The relevant zone or passback facts are unknown.
79 Unknown,
80 /// One established local zone, its settings, and presentation observation.
81 Zone {
82 /// Local Access Zone used for the check.
83 zone: ObjectIdentifier,
84 /// Used only if Passback_Mode is genuinely absent.
85 fallback_mode: AuthorizationFact<AccessPassbackMode>,
86 /// Missing Passback_Timeout is specified to mean no expiry. This
87 /// optional fallback allows application configuration where the property
88 /// is absent; None and zero both mean no expiry, in minutes.
89 fallback_timeout_minutes: Option<u32>,
90 /// Required for unexempted HARD/SOFT enforcement/reporting. Exempt SOFT
91 /// reporting uses it when available; exempt HARD and OFF do not need it.
92 observation: AuthorizationFact<AuthorizationPassbackObservation>,
93 },
94}
95
96/// Authentication outcome for one exact companion presentation.
97#[derive(Debug, Clone, Copy, PartialEq, Eq)]
98pub enum CompanionAuthentication {
99 /// Authentication completed for this tuple; no rights grant is asserted.
100 Authenticated,
101 /// Authentication was conclusively rejected for this tuple.
102 Rejected,
103 /// Authentication has not been established.
104 Unknown,
105}
106
107/// An application attestation bound to sequence, credential, point, and time.
108#[derive(Debug, Clone, Copy, PartialEq, Eq)]
109pub struct CompanionAuthenticationAttestation {
110 /// Full presentation tuple. Matching only credential identity is insufficient.
111 pub presentation: CredentialPresentation,
112 /// Authentication evidence, without a caller-provided access-rights decision.
113 pub authentication: CompanionAuthentication,
114}
115
116/// External verification/delay evidence at a supplied observation time.
117#[derive(Debug, Clone, Copy, PartialEq, Eq)]
118pub enum AuthorizationVerdict {
119 /// No external verdict has arrived; the verified deadline determines expiry.
120 Waiting,
121 /// The application explicitly observed expiry; an early claim is unresolved.
122 DeadlineReached,
123 /// An approval arrived at this monotonic time. It never shortens a delay.
124 Approved(Duration),
125 /// A rejection arrived at this monotonic time.
126 Rejected(Duration),
127}
128
129/// Explicit external-phase correlation and timing, when the mode requires it.
130#[derive(Debug, Clone, Copy, PartialEq, Eq)]
131pub enum AuthorizationExternalPhase {
132 /// No phase evidence supplied; unresolved when an unexempted mode needs it.
133 NotSupplied,
134 /// Evidence for one application-owned phase of this exact presentation.
135 Observed {
136 /// Complete original presentation tuple.
137 presentation: CredentialPresentation,
138 /// Phase start, at or after presentation and no later than `now`.
139 started: Duration,
140 /// Used only if the point omits Verification_Time, in seconds when served.
141 fallback_period: AuthorizationFact<Duration>,
142 /// Explicit boundary policy, reused from accompaniment timing.
143 deadline: AccompanimentDeadline,
144 /// Waiting, a dated verdict, or an explicit expiry claim.
145 verdict: AuthorizationVerdict,
146 },
147}
148
149/// One already-authenticated local presentation and every application-owned
150/// authorization choice. There is no Default implementation or installed policy.
151///
152/// Database properties take precedence over their narrow absent-property
153/// fallbacks. Malformed, denied, or otherwise failed reads never use a fallback.
154/// All observations belong to one coherent application context; this API does
155/// not authenticate hardware, discover remote facts, or publish events.
156#[derive(Debug, Clone, Copy)]
157pub struct AuthorizationRequest<'a> {
158 /// Authenticated original tuple; this helper is not the factor engine.
159 pub original: CredentialPresentation,
160 /// Supplied local wall-clock frame used for all credential validity checks.
161 /// Finite limits require a valid coherent frame. Two open limits do not.
162 pub wall_time: Option<ClockFrame>,
163 /// Monotonic observation time, separate from BACnet wall-clock time.
164 pub now: Duration,
165 /// Every required criterion in the caller's explicit order.
166 pub order: AuthorizationOrder,
167 /// Explicit precedence among multiple coherent disable reasons.
168 pub disable_reason_priority: DisableReasonPriority,
169 /// Explicit treatment of original and companion excluded assignments.
170 pub rights_policy: AuthorizationRightsPolicy,
171 /// Point threat level if its property is genuinely absent; range 0..100.
172 /// Zero disables the comparison without reading credential authority.
173 /// Otherwise absent credential Threat_Authority means zero by specification.
174 pub fallback_threat_level: AuthorizationFact<u32>,
175 /// Point Lockout if its property is genuinely absent.
176 pub fallback_lockout: AuthorizationFact<bool>,
177 /// Complete relevant occupancy context.
178 pub occupancy: AuthorizationOccupancy<'a>,
179 /// Passback applicability, settings, and observed successful-entry evidence.
180 pub passback: AuthorizationPassback,
181 /// Witnesses consumed by the existing bounded accompaniment stage.
182 pub accompaniment_witnesses: &'a [AccompanimentWitness],
183 /// Explicit order/period/boundary policy for selected accompaniment.
184 pub accompaniment_timing: AccompanimentTiming,
185 /// Existing accompaniment traversal bound; exhaustion cannot grant access.
186 pub max_accompaniment_links: usize,
187 /// Authentication results for each companion actually relied upon.
188 pub companion_authentication: &'a [CompanionAuthenticationAttestation],
189 /// External verification/delay observation if needed by the served mode.
190 pub external_phase: AuthorizationExternalPhase,
191}