Skip to main content

dpp_domain/disclosure/
audience.rs

1//! [`Audience`] — who is asking for passport data.
2
3use serde::{Deserialize, Serialize};
4
5use super::class::{DISCLOSURE_ORDER, Disclosure, disclosure_key};
6
7/// Who is asking for passport data.
8///
9/// Regulation (EU) 2023/1542 Art. 77(2) names three audiences and assigns each
10/// a set of Annex XIII data points:
11///
12/// | Audience | Annex XIII |
13/// |---|---|
14/// | (a) general public | 1 |
15/// | (b) notified bodies, market surveillance authorities, the Commission | 2 and 3 |
16/// | (c) persons with a legitimate interest | 2 and 4 |
17///
18/// **This is a lattice, not a ranking.** Point 3 (conformity test reports) is
19/// authority-only; point 4 (individual-item use history) is
20/// legitimate-interest-only. Neither audience contains the other, so no integer
21/// ordering can express the assignment: any `>=` comparison necessarily either
22/// hands authorities the individual-item data Art. 77(2)(b) withholds, or hides
23/// point-2 data from someone entitled to it.
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
25#[serde(rename_all = "snake_case")]
26#[non_exhaustive]
27pub enum Audience {
28    /// Anyone, with no credential. Art. 77(2)(a).
29    Public,
30    /// A repairer, remanufacturer, second-life operator or recycler holding a
31    /// credential that proves the interest. Art. 77(2)(c).
32    LegitimateInterest,
33    /// Notified body, market surveillance authority, customs, or the
34    /// Commission. Art. 77(2)(b).
35    Authority,
36}
37
38impl Audience {
39    /// The disclosure classes this audience may see, in Annex XIII order.
40    #[must_use]
41    pub fn disclosure_set(self) -> Vec<Disclosure> {
42        DISCLOSURE_ORDER
43            .iter()
44            .copied()
45            .filter(|d| self.may_see(*d))
46            .collect()
47    }
48
49    /// The [`disclosure_key`] for this audience's classes — the name under which
50    /// a view served to it is signed and audited.
51    ///
52    /// Two audiences with the same class set would share a key, and that is
53    /// correct: the artefact describes the data it covers, not who asked.
54    #[must_use]
55    pub fn disclosure_key(self) -> String {
56        disclosure_key(&self.disclosure_set())
57    }
58
59    /// Whether this audience may see a field of class `disclosure`.
60    ///
61    /// The whole Art. 77(2) assignment, in one table.
62    #[must_use]
63    pub const fn may_see(self, disclosure: Disclosure) -> bool {
64        matches!(
65            (self, disclosure),
66            (Self::Public, Disclosure::Public)
67                | (
68                    Self::LegitimateInterest,
69                    Disclosure::Public | Disclosure::Restricted | Disclosure::Individual
70                )
71                | (
72                    Self::Authority,
73                    Disclosure::Public | Disclosure::Restricted | Disclosure::Conformity
74                )
75        )
76    }
77}