dpp_domain/operator/basis.rs
1//! [`ResponsibilityBasis`] — which law makes an operator answerable for a product.
2
3use serde::{Deserialize, Serialize};
4
5/// The legal basis under which an economic operator is the one responsible for
6/// a product.
7///
8/// # Why this is recorded rather than derived
9///
10/// **ESPR Annex III, point (k)** does not name one law. Confirmed against the
11/// verbatim OJ text, it asks for the operator "responsible for carrying out the
12/// tasks set out in Article 4 of Regulation (EU) 2019/1020 **or** Article 15 of
13/// Regulation (EU) 2023/988, **or similar tasks pursuant to other Union law
14/// applicable to the product**" — a disjunction over three bases, and which one
15/// applies is a fact about the product.
16///
17/// It is not derivable in general. **Art. 4(5) of Regulation (EU) 2019/1020**
18/// limits that article to a closed list of instruments — verbatim from the
19/// consolidated text (`02019R1020 — EN — 12.08.2026 — 003.001`): Regulations
20/// (EU) No 305/2011, (EU) 2016/425, (EU) 2016/426, **(EU) 2023/1542** and
21/// **(EU) 2024/1252**, and Directives 2000/14/EC, 2006/42/EC, 2009/48/EC,
22/// 2009/125/EC, 2011/65/EU, 2013/29/EU, 2013/53/EU, 2014/29/EU, 2014/30/EU,
23/// 2014/31/EU, 2014/32/EU, 2014/34/EU, 2014/35/EU, 2014/53/EU and 2014/68/EU.
24///
25/// The two emphasised Regulations put themselves on that list: batteries by
26/// Reg. (EU) 2023/1542 (amendment marker `M1`, **28 July 2023**) and the
27/// Critical Raw Materials Act by Reg. (EU) 2024/1252 (marker `M2`, 3 May 2024).
28///
29/// An earlier version of this note omitted both and concluded that "construction
30/// (305/2011) and toys (2009/48/EC) fall inside it; the rest do not". It was
31/// read off the **original** 2019/1020 rather than the consolidation, and it is
32/// false: of the product groups this crate models, construction, toys **and
33/// battery** fall inside, battery since 28 July 2023.
34///
35/// So the Art. 4 limb reaches more passports than that note implied. It is still
36/// not derivable in general, which is the reason the basis is stated rather than
37/// inferred — the correction narrows how wrong an inference would be, it does
38/// not make inference safe.
39///
40/// Stating the basis is cheap and checkable. Inferring it from the product group
41/// works for two groups and is a guess for every other.
42#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
43#[serde(rename_all = "camelCase")]
44#[non_exhaustive]
45pub enum ResponsibilityBasis {
46 /// Article 4 of Regulation (EU) 2019/1020 (market surveillance).
47 ///
48 /// Applies only to products subject to the instruments listed in Art. 4(5) —
49 /// see the type-level note. The tasks are those in Art. 4(3): verifying the
50 /// declaration of conformity and technical documentation, answering reasoned
51 /// requests from market surveillance authorities, reporting a product
52 /// believed to present a risk, and cooperating on corrective action.
53 MarketSurveillanceArt4,
54 /// Regulation (EU) 2023/988 (general product safety).
55 ///
56 /// **Annex III(k) cites "Article 15"**, and that is what the OJ prints —
57 /// checked in both the original and the consolidated text. Article 15 of
58 /// 2023/988 is *Cooperation of economic operators with market surveillance
59 /// authorities*; the responsible-person provision is **Article 16**,
60 /// *Responsible person for products placed on the Union market*.
61 ///
62 /// The discrepancy changes nothing here, because Art. 16(1) imports the
63 /// other basis wholesale: "Article 4(2) and (3) of that Regulation shall
64 /// apply to products covered by this Regulation." Both limbs therefore land
65 /// on the same person performing the same tasks. This variant is named for
66 /// the regulation rather than an article number so it does not have to
67 /// choose between the citation as printed and the provision as intended.
68 GeneralProductSafety,
69 /// "Similar tasks pursuant to other Union law applicable to the product" —
70 /// Annex III(k)'s own catch-all.
71 ///
72 /// Carries the citation because the whole point of the variant is that the
73 /// law is not one of the two named, and a basis that cannot say which law it
74 /// is says nothing at all.
75 OtherUnionLaw {
76 /// The instrument and provision, as it would be cited — for example
77 /// `"Article 7 of Regulation (EU) 2017/745"`.
78 citation: String,
79 },
80}
81
82impl ResponsibilityBasis {
83 /// Every basis this build models, for exhaustive iteration.
84 ///
85 /// Same contract as [`OperatorRole::ALL`](super::OperatorRole::ALL): the
86 /// type is `#[non_exhaustive]`, so a consumer publishing an API description
87 /// cannot enumerate it otherwise. [`Self::OtherUnionLaw`] appears with an
88 /// empty citation — it is a shape, not a usable value.
89 #[must_use]
90 pub fn all() -> Vec<Self> {
91 vec![
92 Self::MarketSurveillanceArt4,
93 Self::GeneralProductSafety,
94 Self::OtherUnionLaw {
95 citation: String::new(),
96 },
97 ]
98 }
99}