feat(reasoning): Regulatory Reasoning Engine MVP (scope/obligations/implementation/interpretation)
Deterministic reasoning layer ON TOP of the Legal Knowledge Graph (obligation
registry) and the Compliance Execution Graph (control mapping/evidence). Answers
which regulations apply to a concrete product, which obligations follow, whether
the customer's implementation covers them, and whether a customer interpretation
is too narrow/broad/plausible.
- ProductProfile with tri-state facts (Optional[bool]=None => uncertain, never
false security); safe predicate evaluator (no eval).
- 6 regulation triggers (CRA/MaschinenVO/RED/EMV/DataAct/NIS2) with missing-fact
prompts; 24 obligation scope rules.
- CRA obligation_ids RE-USED verbatim from the registry (93 ids) — never re-minted
(control_uuid trap); Machine/Data-Act flagged proposed=True.
- required_evidence constrained to the framework-agnostic shared evidence catalog;
capabilities echo the planned Obligation->Capability layer.
- Overlap groups (CRA<->MaschinenVO cyber-safety) + evidence-for-multiple (USP).
- 4 endpoints POST /reasoning/{scope,obligations,implementation-assessment,
interpretation-assessment}; thin handlers, registered in api/__init__.py.
- 22 tests (5 machine-builder scenarios + 10 acceptance questions). No DB
migration, no RAG, no new controls.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,271 @@
|
||||
"""CRA obligation scope rules.
|
||||
|
||||
`obligation_id`s in the six CRA-P1 families (sbom/vuln/authentication/logging/
|
||||
remote_access/updates) are RE-USED verbatim from the Legal-KG registry
|
||||
(`obligations/obligation_join_keys.json`) — never re-minted (control_uuid trap,
|
||||
memory `project_compliance_graph.md`). Cross-cutting CRA *process* obligations
|
||||
(risk assessment, technical documentation, CE, instructions, secure-by-design
|
||||
umbrella) are not yet in the registry and are flagged `proposed=True`.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import List
|
||||
|
||||
from .enums import AuthorityLevel, Confidence
|
||||
from .rules_types import ObligationRule
|
||||
|
||||
_HAS_SW = ("has_software", "eq", True)
|
||||
_EU = ("eu_market", "eq", True)
|
||||
_REMOTE_OR_CLOUD = {"any": [("has_remote_access", "eq", True), ("has_cloud_connection", "eq", True)]}
|
||||
_LM = AuthorityLevel.LEGAL_TEXT
|
||||
|
||||
CRA_OBLIGATIONS: List[ObligationRule] = [
|
||||
ObligationRule(
|
||||
obligation_id="sbom_creation",
|
||||
title="Software Bill of Materials erstellen",
|
||||
source_regulation="CRA",
|
||||
obligation_text="Eine SBOM erstellen, die mindestens die obersten Abhängigkeiten des Produkts dokumentiert.",
|
||||
legal_basis_refs=["CRA Annex I Part II (1)"],
|
||||
authority_level=_LM,
|
||||
family="sbom",
|
||||
applies_if={"all": [_HAS_SW, _EU]},
|
||||
required_capabilities=["software_bill_of_materials"],
|
||||
required_evidence=["sbom", "repo_scan"],
|
||||
lifecycle_phase=["development", "placing_on_market", "maintenance"],
|
||||
registry_anchor=True,
|
||||
),
|
||||
ObligationRule(
|
||||
obligation_id="provide_security_updates",
|
||||
title="Sicherheitsupdates bereitstellen",
|
||||
source_regulation="CRA",
|
||||
obligation_text="Sicherheitsrelevante Updates zeitnah und über den Supportzeitraum bereitstellen.",
|
||||
legal_basis_refs=["CRA Annex I (2)(c)", "CRA Art. 13"],
|
||||
authority_level=_LM,
|
||||
family="updates",
|
||||
applies_if={"all": [_HAS_SW, _EU]},
|
||||
required_capabilities=["secure_updates"],
|
||||
required_evidence=["policy", "ticket", "test_report"],
|
||||
lifecycle_phase=["maintenance", "update"],
|
||||
overlap_group_id="SECURITY_UPDATES",
|
||||
registry_anchor=True,
|
||||
),
|
||||
ObligationRule(
|
||||
obligation_id="support_period_maintenance",
|
||||
title="Supportzeitraum definieren und einhalten",
|
||||
source_regulation="CRA",
|
||||
obligation_text="Einen angemessenen Supportzeitraum festlegen, in dem Schwachstellen behandelt werden.",
|
||||
legal_basis_refs=["CRA Art. 13(8)"],
|
||||
authority_level=_LM,
|
||||
family="updates",
|
||||
applies_if={"all": [_HAS_SW, _EU]},
|
||||
required_capabilities=["secure_updates"],
|
||||
required_evidence=["policy"],
|
||||
lifecycle_phase=["placing_on_market", "maintenance", "update"],
|
||||
registry_anchor=True,
|
||||
),
|
||||
ObligationRule(
|
||||
obligation_id="signed_update_integrity",
|
||||
title="Integrität von Updates sicherstellen",
|
||||
source_regulation="CRA",
|
||||
obligation_text="Updates signieren und ihre Integrität bei der Verteilung verifizieren.",
|
||||
legal_basis_refs=["CRA Annex I (1)(3)(f)"],
|
||||
authority_level=_LM,
|
||||
family="updates",
|
||||
applies_if={"all": [_HAS_SW, _EU]},
|
||||
required_capabilities=["software_integrity"],
|
||||
required_evidence=["config_export", "test_report"],
|
||||
lifecycle_phase=["development", "maintenance", "update"],
|
||||
overlap_group_id="SECURITY_UPDATES",
|
||||
registry_anchor=True,
|
||||
),
|
||||
ObligationRule(
|
||||
obligation_id="vuln_handling_process",
|
||||
title="Schwachstellenbehandlungs-Prozess",
|
||||
source_regulation="CRA",
|
||||
obligation_text="Einen dokumentierten Prozess zur Identifikation, Bewertung und Behebung von Schwachstellen betreiben.",
|
||||
legal_basis_refs=["CRA Art. 13(8)", "CRA Annex VII"],
|
||||
authority_level=_LM,
|
||||
family="vuln",
|
||||
applies_if={"all": [_HAS_SW, _EU]},
|
||||
required_capabilities=["vulnerability_management"],
|
||||
required_evidence=["policy", "ticket"],
|
||||
lifecycle_phase=["development", "operation", "maintenance"],
|
||||
overlap_group_id="VULNERABILITY_HANDLING",
|
||||
registry_anchor=True,
|
||||
),
|
||||
ObligationRule(
|
||||
obligation_id="coordinated_vulnerability_disclosure",
|
||||
title="Coordinated Vulnerability Disclosure",
|
||||
source_regulation="CRA",
|
||||
obligation_text="Eine Richtlinie zur koordinierten Offenlegung von Schwachstellen bereitstellen.",
|
||||
legal_basis_refs=["CRA Annex I Part II (5)"],
|
||||
authority_level=_LM,
|
||||
family="vuln",
|
||||
applies_if={"all": [_HAS_SW, _EU]},
|
||||
required_capabilities=["coordinated_disclosure"],
|
||||
required_evidence=["policy"],
|
||||
lifecycle_phase=["operation", "maintenance"],
|
||||
overlap_group_id="VULNERABILITY_HANDLING",
|
||||
registry_anchor=True,
|
||||
),
|
||||
ObligationRule(
|
||||
obligation_id="exploited_vuln_reporting_authorities",
|
||||
title="Meldung aktiv ausgenutzter Schwachstellen / Vorfälle",
|
||||
source_regulation="CRA",
|
||||
obligation_text="Aktiv ausgenutzte Schwachstellen und schwerwiegende Vorfälle an die zuständigen Behörden melden.",
|
||||
legal_basis_refs=["CRA Art. 14", "CRA Art. 16"],
|
||||
authority_level=_LM,
|
||||
family="vuln",
|
||||
applies_if={"all": [_HAS_SW, _EU]},
|
||||
required_capabilities=["incident_reporting"],
|
||||
required_evidence=["policy", "ticket"],
|
||||
lifecycle_phase=["operation", "maintenance"],
|
||||
registry_anchor=True,
|
||||
),
|
||||
ObligationRule(
|
||||
obligation_id="user_authentication_required",
|
||||
title="Authentifizierung vorsehen",
|
||||
source_regulation="CRA",
|
||||
obligation_text="Den Zugang über einen geeigneten Authentifizierungsmechanismus schützen.",
|
||||
legal_basis_refs=["CRA Annex I (2)(d)"],
|
||||
authority_level=_LM,
|
||||
family="authentication",
|
||||
applies_if={"all": [_HAS_SW, _EU]},
|
||||
required_capabilities=["authentication"],
|
||||
required_evidence=["config_export", "pentest"],
|
||||
lifecycle_phase=["development", "operation"],
|
||||
registry_anchor=True,
|
||||
),
|
||||
ObligationRule(
|
||||
obligation_id="no_default_credentials",
|
||||
title="Keine unveränderlichen Standard-Zugangsdaten",
|
||||
source_regulation="CRA",
|
||||
obligation_text="Sichere Standardkonfiguration; keine fest hinterlegten oder unveränderlichen Standard-Passwörter.",
|
||||
legal_basis_refs=["CRA Annex I (2)(a)", "CRA Annex I (2)(b)"],
|
||||
authority_level=_LM,
|
||||
family="authentication",
|
||||
applies_if={"all": [_HAS_SW, _EU]},
|
||||
required_capabilities=["secure_by_default"],
|
||||
required_evidence=["config_export", "test_report"],
|
||||
lifecycle_phase=["development", "placing_on_market"],
|
||||
registry_anchor=True,
|
||||
),
|
||||
ObligationRule(
|
||||
obligation_id="event_logging_security_events",
|
||||
title="Sicherheitsrelevante Ereignisse protokollieren",
|
||||
source_regulation="CRA",
|
||||
obligation_text="Sicherheitsrelevante Ereignisse und Zugriffe aufzeichnen, um Vorfälle nachvollziehen zu können.",
|
||||
legal_basis_refs=["CRA Annex I Part I (2)(k)"],
|
||||
authority_level=_LM,
|
||||
family="logging",
|
||||
applies_if={"all": [_HAS_SW, _EU]},
|
||||
required_capabilities=["security_logging"],
|
||||
required_evidence=["config_export", "audit_log"],
|
||||
lifecycle_phase=["operation", "maintenance"],
|
||||
registry_anchor=True,
|
||||
),
|
||||
ObligationRule(
|
||||
obligation_id="remote_access_attack_surface_min",
|
||||
title="Angriffsfläche minimieren",
|
||||
source_regulation="CRA",
|
||||
obligation_text="Die Angriffsfläche begrenzen, insbesondere exponierte Remote-/Cloud-Schnittstellen.",
|
||||
legal_basis_refs=["CRA Annex I (1)(2)(a)"],
|
||||
authority_level=_LM,
|
||||
family="remote_access",
|
||||
applies_if={"all": [_REMOTE_OR_CLOUD, _EU]},
|
||||
required_capabilities=["secure_by_default"],
|
||||
required_evidence=["config_export", "repo_scan", "pentest"],
|
||||
lifecycle_phase=["development", "operation"],
|
||||
registry_anchor=True,
|
||||
),
|
||||
ObligationRule(
|
||||
obligation_id="remote_access_confidentiality_integrity",
|
||||
title="Vertraulichkeit/Integrität der Fernverbindung",
|
||||
source_regulation="CRA",
|
||||
obligation_text="Daten bei Fernzugriff/Cloud-Anbindung verschlüsselt und integritätsgeschützt übertragen.",
|
||||
legal_basis_refs=["CRA Annex I (1)(2)(b)", "CRA Annex I (1)(2)(c)"],
|
||||
authority_level=_LM,
|
||||
family="remote_access",
|
||||
applies_if={"all": [_REMOTE_OR_CLOUD, _EU]},
|
||||
required_capabilities=["secure_communication"],
|
||||
required_evidence=["config_export", "pentest"],
|
||||
lifecycle_phase=["operation"],
|
||||
registry_anchor=True,
|
||||
),
|
||||
# --- Cross-cutting CRA process obligations (not yet in registry) ---------
|
||||
ObligationRule(
|
||||
obligation_id="cra_secure_by_design",
|
||||
title="Security by Design",
|
||||
source_regulation="CRA",
|
||||
obligation_text="Das Produkt so entwerfen, entwickeln und herstellen, dass ein angemessenes Cybersicherheitsniveau gewährleistet ist.",
|
||||
legal_basis_refs=["CRA Annex I Part I (1)"],
|
||||
authority_level=_LM,
|
||||
family="cra_process",
|
||||
applies_if={"all": [_HAS_SW, _EU]},
|
||||
required_capabilities=["secure_by_default", "risk_assessment"],
|
||||
required_evidence=["policy", "test_report"],
|
||||
lifecycle_phase=["development", "placing_on_market"],
|
||||
proposed=True,
|
||||
),
|
||||
ObligationRule(
|
||||
obligation_id="cra_risk_assessment",
|
||||
title="Cybersicherheits-Risikobewertung",
|
||||
source_regulation="CRA",
|
||||
obligation_text="Eine Cybersicherheits-Risikobewertung durchführen und dokumentieren; in die technische Dokumentation aufnehmen.",
|
||||
legal_basis_refs=["CRA Art. 13(2)", "CRA Annex I Part I (1)"],
|
||||
authority_level=_LM,
|
||||
family="cra_process",
|
||||
applies_if={"all": [_HAS_SW, _EU]},
|
||||
required_capabilities=["risk_assessment"],
|
||||
required_evidence=["policy"],
|
||||
lifecycle_phase=["development", "placing_on_market"],
|
||||
overlap_group_id="RISK_ASSESSMENT",
|
||||
proposed=True,
|
||||
),
|
||||
ObligationRule(
|
||||
obligation_id="cra_technical_documentation",
|
||||
title="Technische Dokumentation",
|
||||
source_regulation="CRA",
|
||||
obligation_text="Technische Dokumentation erstellen und aktuell halten, die Konformität mit den Anforderungen belegt.",
|
||||
legal_basis_refs=["CRA Art. 31", "CRA Annex VII"],
|
||||
authority_level=_LM,
|
||||
family="cra_process",
|
||||
applies_if={"all": [_HAS_SW, _EU]},
|
||||
required_capabilities=["technical_documentation"],
|
||||
required_evidence=["policy"],
|
||||
lifecycle_phase=["placing_on_market", "maintenance"],
|
||||
overlap_group_id="TECHNICAL_DOCUMENTATION",
|
||||
proposed=True,
|
||||
),
|
||||
ObligationRule(
|
||||
obligation_id="cra_ce_conformity_assessment",
|
||||
title="Konformitätsbewertung / CE-Kennzeichnung",
|
||||
source_regulation="CRA",
|
||||
obligation_text="Vor dem Inverkehrbringen das passende Konformitätsbewertungsverfahren durchlaufen und CE kennzeichnen.",
|
||||
legal_basis_refs=["CRA Art. 32", "CRA Art. 28"],
|
||||
authority_level=_LM,
|
||||
family="cra_process",
|
||||
applies_if={"all": [_HAS_SW, _EU]},
|
||||
required_capabilities=["conformity_assessment"],
|
||||
required_evidence=["test_report", "policy"],
|
||||
lifecycle_phase=["placing_on_market"],
|
||||
overlap_group_id="CE_CONFORMITY",
|
||||
proposed=True,
|
||||
),
|
||||
ObligationRule(
|
||||
obligation_id="cra_instructions_for_use",
|
||||
title="Informationen und Anweisungen für Nutzer",
|
||||
source_regulation="CRA",
|
||||
obligation_text="Nutzern verständliche Sicherheitsinformationen und -anweisungen bereitstellen (z. B. zu Updates und Support-Ende).",
|
||||
legal_basis_refs=["CRA Annex II"],
|
||||
authority_level=_LM,
|
||||
family="cra_process",
|
||||
applies_if={"all": [_HAS_SW, _EU]},
|
||||
required_capabilities=["technical_documentation"],
|
||||
required_evidence=["policy"],
|
||||
lifecycle_phase=["placing_on_market"],
|
||||
overlap_group_id="INSTRUCTIONS_FOR_USE",
|
||||
proposed=True,
|
||||
),
|
||||
]
|
||||
Reference in New Issue
Block a user