"""Regulation-level applicability trigger rules (scope discovery, spec Modus 1). Each rule is pure data consumed by `scope_engine`. Triggers reference `ProductProfile` fields through the safe predicate evaluator. `required_facts` that are unknown turn the verdict *uncertain* and surface `fact_prompts`. """ from __future__ import annotations from dataclasses import dataclass, field from typing import Dict, List, Optional from .enums import Confidence from .predicates import Condition # Positive, human-readable label per profile fact (for trigger_facts output). FIELD_LABELS: Dict[str, str] = { "has_software": "Produkt enthält Software / digitale Elemente", "has_embedded_software": "Produkt enthält eingebettete Software", "has_remote_access": "Produkt besitzt Fernzugriff / Fernwartung", "has_cloud_connection": "Produkt ist mit einer Cloud verbunden", "has_radio_module": "Produkt enthält ein Funkmodul", "has_safety_function": "Produkt erfüllt eine Sicherheitsfunktion", "generates_usage_data": "Vernetztes Produkt erzeugt nutzbare Produktdaten", "is_machine": "Produkt ist eine Maschine", "is_component": "Produkt ist ein (Sicherheits-)Bauteil", "eu_market": "Produkt wird auf dem EU-Markt bereitgestellt", "is_essential_or_important_entity": "Unternehmen ist wesentliche/wichtige Einrichtung", "manufacturer_role": "Wirtschaftsakteur-Rolle (Hersteller/Importeur/Händler)", } @dataclass(frozen=True) class RegulationRule: regulation_id: str name: str trigger: Condition required_facts: List[str] fact_prompts: Dict[str, str] legal_basis_refs: List[str] summary: str confidence_when_applicable: Confidence = Confidence.HIGH exclusion: Optional[Condition] = None # Status is downgraded to PARTIALLY_APPLICABLE / MEDIUM when the trigger # fires only via inference rather than a directly stated fact. inferred: bool = False excludable_roles: List[str] = field(default_factory=list) _ECONOMIC_ROLES = ["manufacturer", "importer", "distributor"] REGULATION_RULES: List[RegulationRule] = [ RegulationRule( regulation_id="CRA", name="Cyber Resilience Act (EU) 2024/2847", trigger={ "all": [ {"any": [("has_software", "eq", True), ("has_embedded_software", "eq", True)]}, ("eu_market", "eq", True), ] }, required_facts=["has_software", "eu_market", "manufacturer_role"], fact_prompts={ "has_software": "Enthält das Produkt Software / digitale Elemente?", "eu_market": "Wird das Produkt auf dem EU-Markt bereitgestellt oder in Verkehr gebracht?", "manufacturer_role": "Welche Rolle nehmen Sie ein (Hersteller / Importeur / Händler)?", }, legal_basis_refs=["CRA Art. 2(1)", "CRA Art. 3(1)"], summary="Produkte mit digitalen Elementen, die auf dem EU-Markt bereitgestellt werden.", confidence_when_applicable=Confidence.HIGH, excludable_roles=["operator"], ), RegulationRule( regulation_id="MaschinenVO", name="Maschinenverordnung (EU) 2023/1230", trigger={ "any": [ ("is_machine", "eq", True), {"all": [("is_component", "eq", True), ("has_safety_function", "eq", True)]}, ] }, required_facts=["is_machine", "eu_market"], fact_prompts={ "is_machine": "Ist das Produkt eine Maschine oder ein Sicherheitsbauteil?", "has_safety_function": "Erfüllt das Bauteil eine Sicherheitsfunktion?", }, legal_basis_refs=["MaschinenVO (EU) 2023/1230 Art. 2", "Anhang III"], summary="Maschinen oder Sicherheitsbauteile, ggf. mit sicherheitsrelevanter Steuerung.", confidence_when_applicable=Confidence.MEDIUM, ), RegulationRule( regulation_id="RED", name="Radio Equipment Directive 2014/53/EU", trigger=("has_radio_module", "eq", True), required_facts=["has_radio_module"], fact_prompts={ "has_radio_module": "Besitzt das Produkt ein Funkmodul (WLAN, Bluetooth, Mobilfunk)?", }, legal_basis_refs=["RED 2014/53/EU Art. 1", "Art. 3(3)(d-f)"], summary="Funkanlagen; Art. 3(3) deckt zusätzlich Cybersecurity-Anforderungen ab.", confidence_when_applicable=Confidence.HIGH, ), RegulationRule( regulation_id="EMV", name="EMV-Richtlinie 2014/30/EU", trigger={ "any": [ ("has_software", "eq", True), ("has_embedded_software", "eq", True), ("has_radio_module", "eq", True), ] }, required_facts=[], fact_prompts={ "is_electrical": "Ist das Produkt ein elektrisches / elektronisches Betriebsmittel?", }, legal_basis_refs=["EMV-RL 2014/30/EU Art. 2"], summary="Elektrische/elektronische Betriebsmittel (hier aus den digitalen Elementen abgeleitet).", confidence_when_applicable=Confidence.MEDIUM, inferred=True, ), RegulationRule( regulation_id="DataAct", name="Data Act (EU) 2023/2854", trigger={ "all": [ {"any": [("has_cloud_connection", "eq", True), ("has_remote_access", "eq", True)]}, ("generates_usage_data", "eq", True), ] }, required_facts=["generates_usage_data"], fact_prompts={ "generates_usage_data": "Erzeugt das vernetzte Produkt nutzbare Produkt-/Nutzungsdaten?", }, legal_basis_refs=["Data Act (EU) 2023/2854 Art. 2(5)", "Art. 3-5"], summary="Vernetzte Produkte, die Nutzungsdaten erzeugen und zugänglich machen.", confidence_when_applicable=Confidence.HIGH, ), RegulationRule( regulation_id="NIS2", name="NIS2-Richtlinie (EU) 2022/2555", trigger=("is_essential_or_important_entity", "eq", True), required_facts=["company_size", "sector", "is_essential_or_important_entity"], fact_prompts={ "company_size": "Unternehmensgröße (Mitarbeiterzahl / Umsatz)?", "sector": "In welchem Sektor ist das Unternehmen tätig (Anhang I/II)?", "is_essential_or_important_entity": "Fällt das Unternehmen als wesentliche/wichtige Einrichtung unter NIS2?", }, legal_basis_refs=["NIS2-RL (EU) 2022/2555 Art. 2", "Art. 3"], summary="Adressiert die ORGANISATION (Größe/Sektor/Rolle), nicht das Produkt.", confidence_when_applicable=Confidence.MEDIUM, ), ] def regulation_rule(regulation_id: str) -> Optional[RegulationRule]: for rule in REGULATION_RULES: if rule.regulation_id == regulation_id: return rule return None