Skip to main content

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}