"""Known customer interpretation patterns (spec Modus 4). Deterministic: a customer interpretation is matched by lowercase substring triggers against a curated library of common misconceptions. No match -> the engine returns `uncertain` and asks for the missing context (no false security, spec §6.3). """ from __future__ import annotations from dataclasses import dataclass, field from typing import List from .enums import Confidence, InterpretationVerdict @dataclass(frozen=True) class InterpretationPattern: pattern_id: str triggers: List[str] verdict: InterpretationVerdict corrected_interpretation: str explanation: str affected_regulations: List[str] = field(default_factory=list) affected_obligations: List[str] = field(default_factory=list) risks: List[str] = field(default_factory=list) legal_basis_refs: List[str] = field(default_factory=list) confidence: Confidence = Confidence.MEDIUM INTERPRETATION_PATTERNS: List[InterpretationPattern] = [ InterpretationPattern( pattern_id="cra_only_new_products", triggers=[ "nur für neue", "nur fuer neue", "nur neu entwickelt", "nur neuentwicklung", "nur bei neuentwicklung", "only new product", "gilt nur für neue produkte", ], verdict=InterpretationVerdict.TOO_NARROW, corrected_interpretation=( "CRA-Pflichten knüpfen primär an Produkt, Rolle, Marktzugang, Bereitstellung und " "Übergangsfristen an, nicht nur an Neuentwicklung. Ein fertig entwickeltes " "Katalogprodukt kann betroffen sein, wenn es nach dem maßgeblichen Zeitpunkt weiter " "auf dem EU-Markt bereitgestellt wird." ), explanation=( "Die relevante Frage ist nicht nur, ob das Produkt neu entwickelt wurde, sondern ob es " "nach dem Anwendungszeitpunkt weiterhin bereitgestellt oder in Verkehr gebracht wird." ), affected_regulations=["CRA"], risks=["Katalog-/Bestandsprodukt fällt trotz abgeschlossener Entwicklung unter den CRA."], legal_basis_refs=["CRA Art. 2", "CRA Art. 69 (Übergangsbestimmungen)"], confidence=Confidence.HIGH, ), InterpretationPattern( pattern_id="cra_b2b_exempt", triggers=[ "gilt nicht für b2b", "nur für verbraucher", "nur b2c", "nicht im b2b", "only consumer", "b2b ist ausgenommen", ], verdict=InterpretationVerdict.TOO_NARROW, corrected_interpretation=( "Der CRA gilt produkt- und marktbezogen, unabhängig von B2B oder B2C. Eine generelle " "B2B-Ausnahme existiert nicht; Industrieprodukte mit digitalen Elementen sind erfasst." ), explanation="Der Anwendungsbereich knüpft an 'Produkte mit digitalen Elementen' an, nicht an die Kundengruppe.", affected_regulations=["CRA"], risks=["Industrielle B2B-Steuerungen werden fälschlich als ausgenommen behandelt."], legal_basis_refs=["CRA Art. 2", "CRA Art. 3(1)"], confidence=Confidence.HIGH, ), InterpretationPattern( pattern_id="sbom_is_enough", triggers=[ "sbom reicht", "mit sbom sind wir", "sbom genügt", "sbom genuegt", "nur eine sbom", "sbom allein", ], verdict=InterpretationVerdict.TOO_NARROW, corrected_interpretation=( "Eine SBOM erfüllt nur einen Teil der Komponenten-Transparenz. Schwachstellen-" "überwachung, Update-/Patch-Prozess und technische Dokumentation bleiben eigenständige Pflichten." ), explanation="SBOM ist Voraussetzung, ersetzt aber nicht Vulnerability-Handling und Updates.", affected_regulations=["CRA"], affected_obligations=["sbom_creation", "vuln_handling_process", "provide_security_updates"], risks=["Falsche Annahme vollständiger Erfüllung trotz fehlendem Vulnerability-Prozess."], legal_basis_refs=["CRA Annex I Part II (1)", "CRA Annex I Part II (2)"], confidence=Confidence.HIGH, ), InterpretationPattern( pattern_id="open_source_exempt", triggers=[ "open source ist ausgenommen", "open-source ist ausgenommen", "oss ist ausgenommen", "freie software ist ausgenommen", "open source fällt nicht", ], verdict=InterpretationVerdict.PARTIALLY_CORRECT, corrected_interpretation=( "Nur nicht-kommerziell bereitgestellte Open-Source-Software ist ausgenommen. Sobald OSS " "kommerziell in ein Produkt integriert und auf dem Markt bereitgestellt wird, greift der CRA." ), explanation="Die Ausnahme zielt auf nicht-kommerzielle OSS-Bereitstellung, nicht auf kommerzielle Produktintegration.", affected_regulations=["CRA"], risks=["Kommerziell integrierte OSS-Komponenten werden fälschlich als ausgenommen behandelt."], legal_basis_refs=["CRA Art. 2", "CRA Erwägungsgründe (Open-Source-Stewards)"], confidence=Confidence.MEDIUM, ), InterpretationPattern( pattern_id="reactive_updates_ok", triggers=[ "updates nur wenn", "reaktive updates reichen", "wenn kunden melden reicht", "updates wenn fehler gemeldet", ], verdict=InterpretationVerdict.TOO_NARROW, corrected_interpretation=( "Der CRA verlangt aktive Schwachstellenüberwachung und zeitnahe Sicherheitsupdates über " "den Supportzeitraum, nicht nur reaktive Updates nach Kundenmeldung." ), explanation="Ein rein reaktiver Updateprozess erfüllt die Pflicht zur aktiven Schwachstellenbehandlung nicht.", affected_regulations=["CRA"], affected_obligations=["provide_security_updates", "vuln_handling_process"], risks=["Verzögerte Reaktion auf öffentlich bekannte Schwachstellen; Pflichtverletzung."], legal_basis_refs=["CRA Annex I Part II (1)", "CRA Annex I (2)(c)"], confidence=Confidence.HIGH, ), InterpretationPattern( pattern_id="machinery_covers_cyber", triggers=[ "maschinenrichtlinie deckt cyber", "maschinenvo deckt alles", "ce der maschine reicht", "ce maschine reicht für cyber", "maschinen-ce reicht", ], verdict=InterpretationVerdict.PARTIALLY_CORRECT, corrected_interpretation=( "Die MaschinenVO deckt die sicherheitsrelevante Korrumpierung ab (Anhang III 1.1.9), " "ersetzt aber nicht die produktbezogenen CRA-Security-Pflichten. Beide Regime gelten parallel." ), explanation="Maschinen-CE und CRA überschneiden sich nur dort, wo Cyber eine Sicherheitsfunktion betrifft.", affected_regulations=["CRA", "MaschinenVO"], affected_obligations=["machine_protection_against_corruption", "vuln_handling_process"], risks=["CRA-Pflichten werden übersehen, weil die Maschine bereits CE-gekennzeichnet ist."], legal_basis_refs=["MaschinenVO Anhang III (1.1.9)", "CRA Art. 13"], confidence=Confidence.MEDIUM, ), InterpretationPattern( pattern_id="no_radio_no_cyber", triggers=[ "ohne funkmodul kein cyber", "kein funk also kein cra", "ohne funk keine security", "ohne funkmodul keine cyber", ], verdict=InterpretationVerdict.TOO_NARROW, corrected_interpretation=( "Der CRA knüpft an digitale Elemente an, nicht an ein Funkmodul. Ohne Funk entfällt die " "RED, der CRA bleibt jedoch anwendbar, sobald Software vorhanden ist." ), explanation="Funkmodul ist nur für die RED relevant; die CRA-Anwendbarkeit folgt aus der Software.", affected_regulations=["CRA", "RED"], risks=["CRA wird fälschlich verneint, weil kein Funkmodul vorhanden ist."], legal_basis_refs=["CRA Art. 3(1)", "RED 2014/53/EU Art. 1"], confidence=Confidence.HIGH, ), ]