6523286af6
User-Entscheidung 2026-07-01 zum Scope-Audit: Adressat der Norm != Handlungspflicht des Herstellers. Neue `scope`-Attribut-Achse (Enum, KEINE neue Objektklasse -> Freeze v1.0 unberuehrt): in_scope (default) / out_of_scope / derived_obligation. - sanctions + market_surveillance_safeguard -> out_of_scope (reine Staats-/Durchsetzungs- bestimmungen; Praezedenz CSIRT/ENISA im CRA-Vuln-Cut). Aus join_keys gefiltert. - notified_body_requirements -> derived_obligation (Norm adressiert primaer die notifizierte Stelle, erzeugt aber mittelbare Herstellerpflichten: NB einbeziehen + Unterlagen + Konformitaetsbewertung) + scope_split_candidate (spaetere Aufspaltung Normadressat <-> abgeleitete Herstellerpflicht). BLEIBT im Set (Prinzip: Wissen nicht zu frueh verwerfen). - export_join_keys.py filtert scope==out_of_scope + fuehrt scope je Eintrag -> join_keys 126->124 (MaschVO 31->29; 123 in_scope + 1 derived_obligation). - scope_audit.py jetzt 3-Wege-klassifikations-bewusst (0 unklassifizierte Reste) + apply_scope_classification.py (deterministisch). Fuer jeden kuenftigen Cut mitlaufen. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
54 lines
2.5 KiB
Python
54 lines
2.5 KiB
Python
"""Scope-Klassifikation anwenden (User-Entscheidung 2026-07-01, Option 2 + derived_obligation).
|
|
|
|
Neue `scope`-Attribut-Achse (KEINE neue Objektklasse — Enum-Wert, freeze-safe):
|
|
in_scope (default/implizit) · out_of_scope · derived_obligation
|
|
|
|
Prinzip (User): Adressat der Norm ⊥ Handlungspflicht des Herstellers. Reine Staats-/
|
|
Durchsetzungs-/Institutions-Bestimmungen = out_of_scope. Norm, die primär eine andere Rolle
|
|
adressiert ABER mittelbar eine Hersteller-Handlungspflicht erzeugt = derived_obligation
|
|
(bleibt im Hersteller-Set, wird NICHT verworfen — 'im Zweifel nicht zu früh Wissen verwerfen').
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import glob
|
|
import json
|
|
|
|
SCOPE = {
|
|
"sanctions": {
|
|
"scope": "out_of_scope",
|
|
"scope_reason": "Adressat = Mitgliedstaaten (legen Sanktionen fest); keine Hersteller-Handlungspflicht. Präzedenz CSIRT/ENISA (CRA-Vuln-Cut).",
|
|
},
|
|
"market_surveillance_safeguard": {
|
|
"scope": "out_of_scope",
|
|
"scope_reason": "Adressat = Marktüberwachungsbehörden/Kommission (Schutzmaßnahmen, Schutzklauselverfahren); keine Hersteller-Handlungspflicht. Präzedenz CSIRT/ENISA.",
|
|
},
|
|
"notified_body_requirements": {
|
|
"scope": "derived_obligation",
|
|
"scope_reason": "Norm adressiert primär die notifizierte Stelle (Unabhängigkeit/Kompetenz/Unparteilichkeit), erzeugt aber mittelbare Hersteller-Pflichten: notifizierte Stelle einbeziehen, erforderliche Unterlagen bereitstellen, Konformitätsbewertung korrekt durchführen.",
|
|
"scope_split_candidate": True,
|
|
"scope_split_note": "Kandidat für spätere Aufspaltung: 'Normadressat' (Anforderungen AN die notifizierte Stelle = institutional/out_of_scope) ↔ 'abgeleitete Herstellerpflicht' (NB einbeziehen + Unterlagen + Konformitätsbewertung = in_scope). NICHT vorzeitig festziehen.",
|
|
},
|
|
}
|
|
|
|
|
|
def main() -> None:
|
|
applied = []
|
|
for f in sorted(glob.glob("obligations/cra*.json")):
|
|
d = json.load(open(f, encoding="utf-8"))
|
|
changed = False
|
|
for o in d.get("obligations", []):
|
|
spec = SCOPE.get(o.get("id"))
|
|
if spec:
|
|
o.update(spec)
|
|
applied.append((o["id"], spec["scope"]))
|
|
changed = True
|
|
if changed:
|
|
json.dump(d, open(f, "w", encoding="utf-8"), ensure_ascii=False, indent=1)
|
|
for oid, sc in applied:
|
|
print(f" {oid:32} scope={sc}")
|
|
print(f"angewendet: {len(applied)} (erwartet 3)")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|