fix(cra): Konformitätspfad-Kacheln korrekt benennen + Gating nach CRA Art. 32
(a) Labels: Module korrekt zugeordnet — Modul A = Selbstbewertung, Modul B+C =
benannte Stelle, EUCC = eigenes Zertifikat (nicht Modul H), "harmonisierte
Norm" ist kein Modul sondern Konformitätsvermutung. Für den CRA noch KEINE
harmonisierte Norm veröffentlicht → Kachel als "noch nicht verfügbar"
(erwartet ~2027), nicht wählbar, mit Hinweis. (page/path/documents-Labels.)
(b) Gating: wichtige Klasse II + kritische Produkte dürfen NICHT selbst bewerten;
harmonisierte Norm allein genügt dort nicht → ALLOWED_PATHS IMPORTANT_II/
CRITICAL = {eucc, notified_body}; DEFAULT_FOR II = notified_body. _PATH_HINT
entsprechend. Regressionstest test_cra_conformity_paths.py.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -135,10 +135,10 @@ class ReadinessRequest(BaseModel):
|
||||
# CRA Annex I evidence_type -> guideline bucket (Code / Prozess / Dokumentation).
|
||||
_GUIDELINE_BUCKET = {"code": "code", "hybrid": "code", "process": "process", "document": "document"}
|
||||
_PATH_HINT = {
|
||||
"CRITICAL": "Konformitaet ueber benannte Stelle / EUCC (Modul H/C)",
|
||||
"IMPORTANT_II": "Modul B+C oder harmonisierte Norm",
|
||||
"IMPORTANT_I": "Self-Assessment bei harmonisierten Normen, sonst Modul B",
|
||||
"STANDARD": "Self-Assessment (Modul A)",
|
||||
"CRITICAL": "Benannte Stelle (Modul B+C/H) oder EUCC — keine Selbstbewertung",
|
||||
"IMPORTANT_II": "Benannte Stelle (Modul B+C/H) oder EUCC — keine Selbstbewertung",
|
||||
"IMPORTANT_I": "Selbstbewertung nur mit harmonisierter Norm (noch nicht verfuegbar), sonst benannte Stelle/EUCC",
|
||||
"STANDARD": "Selbstbewertung (Modul A)",
|
||||
"NOT_IN_SCOPE": "—",
|
||||
}
|
||||
|
||||
|
||||
@@ -17,10 +17,10 @@ from typing import Optional
|
||||
|
||||
|
||||
PATH_LABELS = {
|
||||
"self_assessment": "Modul A — Self-Assessment durch Hersteller",
|
||||
"harmonized_standard": "Modul B — Harmonisierte Norm",
|
||||
"eucc": "Modul H — EUCC-Zertifizierung",
|
||||
"notified_body": "Modul C — Konformitaetsbewertung durch Notified Body",
|
||||
"self_assessment": "Modul A — Interne Kontrolle (Selbstbewertung durch Hersteller)",
|
||||
"harmonized_standard": "Harmonisierte Normen — Konformitaetsvermutung (noch nicht verfuegbar)",
|
||||
"eucc": "EUCC — EU-Cybersicherheitszertifikat",
|
||||
"notified_body": "Modul B+C — Pruefung durch benannte Stelle (Baumusterpruefung)",
|
||||
}
|
||||
|
||||
CLASS_LABELS = {
|
||||
|
||||
@@ -67,13 +67,16 @@ ANNEX_III_CLASS_I = [
|
||||
CLASSIFICATIONS = {"NOT_IN_SCOPE", "STANDARD", "IMPORTANT_I", "IMPORTANT_II", "CRITICAL"}
|
||||
CONFORMITY_PATHS = {"self_assessment", "harmonized_standard", "eucc", "notified_body"}
|
||||
|
||||
# Allowed paths per classification (CRITICAL must use notified_body)
|
||||
# Allowed paths per classification (CRA Art. 32 / Anhang VIII).
|
||||
# IMPORTANT_II darf NICHT selbst bewerten — eine harmonisierte Norm allein genuegt
|
||||
# hier nicht; es braucht benannte Stelle (Modul B+C/H) oder EUCC. CRITICAL ebenso,
|
||||
# mit EUCC als regulaerem Weg.
|
||||
ALLOWED_PATHS = {
|
||||
"NOT_IN_SCOPE": set(),
|
||||
"STANDARD": {"self_assessment", "harmonized_standard", "eucc", "notified_body"},
|
||||
"IMPORTANT_I": {"self_assessment", "harmonized_standard", "eucc", "notified_body"},
|
||||
"IMPORTANT_II": {"harmonized_standard", "eucc", "notified_body"},
|
||||
"CRITICAL": {"notified_body"},
|
||||
"IMPORTANT_II": {"eucc", "notified_body"},
|
||||
"CRITICAL": {"eucc", "notified_body"},
|
||||
}
|
||||
|
||||
STATUS_WHITELIST = {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
"""Pin the CRA conformity-path gating (CRA Art. 32 / Anhang VIII).
|
||||
|
||||
Regression: wichtige Klasse-II- und kritische Produkte duerfen NICHT selbst
|
||||
bewerten — eine harmonisierte Norm allein genuegt dort nicht.
|
||||
"""
|
||||
from compliance.api.cra_routes import ALLOWED_PATHS, CONFORMITY_PATHS
|
||||
|
||||
|
||||
def test_self_assessment_only_for_standard_and_important_i():
|
||||
assert "self_assessment" in ALLOWED_PATHS["STANDARD"]
|
||||
assert "self_assessment" in ALLOWED_PATHS["IMPORTANT_I"]
|
||||
assert "self_assessment" not in ALLOWED_PATHS["IMPORTANT_II"]
|
||||
assert "self_assessment" not in ALLOWED_PATHS["CRITICAL"]
|
||||
|
||||
|
||||
def test_important_ii_needs_notified_body_or_eucc():
|
||||
# Klasse II: harmonisierte Norm allein ist KEIN gueltiger Pfad.
|
||||
assert ALLOWED_PATHS["IMPORTANT_II"] == {"eucc", "notified_body"}
|
||||
|
||||
|
||||
def test_critical_allows_eucc_and_notified_body():
|
||||
assert ALLOWED_PATHS["CRITICAL"] == {"eucc", "notified_body"}
|
||||
|
||||
|
||||
def test_not_in_scope_has_no_paths():
|
||||
assert ALLOWED_PATHS["NOT_IN_SCOPE"] == set()
|
||||
|
||||
|
||||
def test_all_allowed_paths_are_known():
|
||||
for paths in ALLOWED_PATHS.values():
|
||||
assert paths <= CONFORMITY_PATHS
|
||||
Reference in New Issue
Block a user