feat(registry-quality): Scope-Audit-Tool — Adressaten-Prüfung (Hersteller vs Behörde)
Generalisiert den Zitierfähigkeits-Befund (2 Kapitel-Obligations authority-facing) zu einem wiederverwendbaren Review-Stage-Werkzeug: flaggt Obligations, deren applicability an Behörde/notifizierte Stelle/Mitgliedstaat adressiert ist = out_of_scope-Kandidaten (Registry modelliert Hersteller-Pflichten; Präzedenz CSIRT/ENISA im CRA-Vuln-Cut). - scope_audit.py: deterministisch, key't auf applicability (Adressat), NICHT auf Behörden-Nennung im Namen → Melde-AN-Behörde-Pflichten bleiben korrekt IN-SCOPE (False-Positive-Guard, verifiziert an exploited_vuln_reporting_authorities). - 126 Obligations gescannt → 3 Kandidaten (alle MaschVO LEGAL_MINIMUM): notified_body_requirements (domain:notified_body) · market_surveillance_safeguard (domain:authority) · sanctions (domain:authority). - scope_audit_findings.json = Findings-Artefakt. Audit FLAGGT nur; Reklassifizierung = User/Owner-Entscheidung (ändert join_keys, cross-session). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
"""Scope-Audit: Adressaten-Prüfung der Obligation-Registry (Review-Stage-Werkzeug).
|
||||
|
||||
Prinzip (etabliert im CRA-Vuln-Cut, CSIRT/ENISA out_of_scope): die Registry modelliert
|
||||
**Hersteller-Pflichten**. Bestimmungen, die an BEHÖRDEN / notifizierte Stellen / Mitgliedstaaten
|
||||
adressiert sind (Marktüberwachung, Sanktionen, Anforderungen an Konformitätsbewertungsstellen),
|
||||
sind Enforcement-/Institutions-Recht → out_of_scope-KANDIDATEN.
|
||||
|
||||
WICHTIG (False-Positive-Abgrenzung): eine Hersteller-Pflicht, Etwas AN eine Behörde zu MELDEN
|
||||
(z.B. `exploited_vuln_reporting_authorities`, applicability=products_with_digital_elements) ist
|
||||
IN-SCOPE — Adressat der Pflicht = Hersteller, Behörde = nur Empfänger. Der Audit key't daher auf
|
||||
`applicability` (Adressat), NICHT auf Behörden-Nennung im Namen.
|
||||
|
||||
Deterministisch, kein LLM. Reklassifizierung = Owner-/User-Entscheidung (dieser Audit FLAGGT nur).
|
||||
Für jeden künftigen Regulierungs-Cut mitlaufen lassen.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import glob
|
||||
import json
|
||||
|
||||
# applicability-Präfixe, die einen NICHT-Hersteller-Adressaten bezeichnen
|
||||
NON_MANUFACTURER_DOMAINS = {
|
||||
"domain:authority",
|
||||
"domain:notified_body",
|
||||
"domain:market_surveillance",
|
||||
"domain:member_state",
|
||||
"domain:commission",
|
||||
}
|
||||
|
||||
|
||||
def main() -> None:
|
||||
findings = []
|
||||
total = 0
|
||||
for f in sorted(glob.glob("obligations/cra*.json")):
|
||||
d = json.load(open(f, encoding="utf-8"))
|
||||
for o in d.get("obligations", []):
|
||||
total += 1
|
||||
appl = (o.get("applicability") or "").strip()
|
||||
if appl in NON_MANUFACTURER_DOMAINS:
|
||||
findings.append({
|
||||
"file": f.split("/")[-1],
|
||||
"id": o.get("id") or o.get("obligation_id"),
|
||||
"name": o.get("name"),
|
||||
"tier": o.get("tier"),
|
||||
"applicability": appl,
|
||||
"subdomain": o.get("subdomain"),
|
||||
"member_count": o.get("member_count"),
|
||||
"reason": "Adressat ist Behörde/notifizierte Stelle/Mitgliedstaat, nicht Hersteller",
|
||||
"precedent": "CRA-Vuln-Cut: CSIRT/ENISA out_of_scope (Adressat != Hersteller)",
|
||||
"recommendation": "out_of_scope ODER eigene Kategorie 'institutional/enforcement'",
|
||||
})
|
||||
out = {
|
||||
"audit": "obligation scope audit (Adressat: Hersteller vs Behörde/notified_body)",
|
||||
"principle": "Registry modelliert Hersteller-Pflichten; Enforcement/Institutions-Recht = out_of_scope-Kandidat",
|
||||
"false_positive_guard": "Melde-AN-Behörde-Pflichten (applicability=domain:products…) bleiben IN-SCOPE",
|
||||
"obligations_scanned": total,
|
||||
"out_of_scope_candidates": findings,
|
||||
"decision_owner": "User/Registry-Owner — Audit FLAGGT nur, reklassifiziert nicht",
|
||||
}
|
||||
json.dump(out, open("obligations/scope_audit_findings.json", "w", encoding="utf-8"),
|
||||
ensure_ascii=False, indent=1)
|
||||
print(f"gescannt {total} Obligations | out_of_scope-Kandidaten: {len(findings)}")
|
||||
for fnd in findings:
|
||||
print(f" [{fnd['file']}] {fnd['id']:32} tier={fnd['tier']} appl={fnd['applicability']}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user