Files
breakpilot-compliance/docs-src/services/sdk-modules/normative-verbindlichkeit.md
Benjamin Admin a29bfdd588
Some checks failed
CI/CD / go-lint (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Failing after 34s
CI/CD / test-python-backend-compliance (push) Successful in 30s
CI/CD / test-python-document-crawler (push) Successful in 19s
CI/CD / test-python-dsms-gateway (push) Successful in 17s
CI/CD / validate-canonical-controls (push) Successful in 11s
CI/CD / Deploy (push) Has been skipped
fix: normative_strength 'may' statt 'can' (DB-Constraint)
DB-Constraint erlaubt nur must/should/may. 'can' gibt es nicht.
Alle Referenzen auf 'can' durch 'may' ersetzt.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 08:35:16 +01:00

7.2 KiB

Normative Verbindlichkeit — Dreistufenmodell

Uebersicht

Nicht jede Quelle, aus der Controls abgeleitet werden, hat die gleiche rechtliche Verbindlichkeit. Ein Control, das aus einem EU-Gesetz stammt, hat ein anderes Gewicht als eines aus einem freiwilligen Framework.

Das Dreistufenmodell klassifiziert jede Quell-Regulierung und leitet daraus die effektive normative Staerke der daraus erzeugten Obligations ab.

Die drei Stufen

graph TB
    subgraph "Stufe 1 — GESETZ (law)"
        direction LR
        A1["DSGVO, NIS2, AI Act, CRA..."]
        A2["Rechtlich bindend"]
        A3["Bussgeld bei Verstoss"]
        A4["normative_strength: must/should/may"]
    end

    subgraph "Stufe 2 — LEITLINIE (guideline)"
        direction LR
        B1["EDPB-Leitlinien, BSI-TR, WP29"]
        B2["Offizielle Auslegungshilfe"]
        B3["Beweislastumkehr"]
        B4["max normative_strength: should"]
    end

    subgraph "Stufe 3 — FRAMEWORK (framework)"
        direction LR
        C1["ENISA, NIST, OWASP, OECD"]
        C2["Freiwillige Best Practice"]
        C3["Stand der Technik"]
        C4["max normative_strength: can"]
    end

    A1 --> A2 --> A3 --> A4
    B1 --> B2 --> B3 --> B4
    C1 --> C2 --> C3 --> C4

Stufe 1: Gesetz (law)

Eigenschaft Beschreibung
Verbindlichkeit Rechtlich bindend, Bussgeld bei Verstoss
normative_strength Bleibt wie im Gesetzestext: must, should oder may
Beispiele DSGVO (EU) 2016/679, NIS2-Richtlinie, KI-Verordnung, CRA, BDSG
Warum relevant "Sie MUESSEN angemessene technische Massnahmen ergreifen" (Art. 32 DSGVO)

!!! warning "Wichtig" Gesetze formulieren Pflichten abstrakt. Art. 32 DSGVO sagt: "dem Stand der Technik entsprechende Massnahmen" — aber NICHT "verwende AES-256". Das WAS ist Pflicht, das WIE bleibt offen.

Stufe 2: Leitlinie (guideline)

Eigenschaft Beschreibung
Verbindlichkeit Nicht direkt bindend, aber Beweislastumkehr
normative_strength Maximal should — auch wenn die Leitlinie intern "must" schreibt
Beispiele EDPB-Leitlinien, BSI Technische Richtlinien, WP29-Dokumente
Warum relevant "Daten at rest muessen verschluesselt werden" (BSI-TR) → should

!!! info "Beweislastumkehr" Wenn eine Aufsichtsbehoerde fragt "Warum verschluesselt ihr nicht?", muss die Firma begruenden, warum sie von der Leitlinie abweicht. Die Firma muss aber nicht genau so verschluesseln wie die BSI vorschlaegt.

Stufe 3: Framework (framework)

Eigenschaft Beschreibung
Verbindlichkeit Freiwillig, nicht rechtsverbindlich
normative_strength Maximal can — unabhaengig von interner Sprache
Beispiele ENISA CCM, NIST CSF, OWASP Top 10, OECD KI-Empfehlung
Warum relevant "Organizations SHALL implement..." (ENISA) → can fuer den Anwender

!!! tip "Stand der Technik" NIS2 Art. 21 verweist auf ENISA-Leitlinien als Referenz fuer den "Stand der Technik". Das hebt ENISA-Controls faktisch auf Stufe 2 (should) — aber nur im Kontext von NIS2-pflichtigen Unternehmen, nicht generell.

Ableitungskette

Die vollstaendige Kette von der Rechtsquelle zum atomaren Control:

graph LR
    R["Regulierung<br/>(DSGVO Art. 32)"] -->|"MUSS"| O["Obligation<br/>(Daten schuetzen)"]
    O -->|decomposition| RC["Rich Control<br/>(Verschluesselung)"]
    RC -->|pass0b| AC["Atomares Control<br/>(AES-256 at rest)"]

    R2["Framework<br/>(ENISA CCM)"] -->|"KANN"| AC

    style R fill:#fee2e2,stroke:#dc2626
    style R2 fill:#dbeafe,stroke:#2563eb
    style O fill:#fef3c7,stroke:#d97706
    style RC fill:#e0e7ff,stroke:#4f46e5
    style AC fill:#d1fae5,stroke:#059669

Beispiel: Das atomare Control "AES-256 Verschluesselung at rest"

  • Aus DSGVO Art. 32 abgeleitet → Obligation "must secure data" → MUSS (die Pflicht zu schuetzen)
  • Aus ENISA CCM konkretisiert → KANN (AES-256 ist eine moegliche Umsetzung)
  • Resultat: Die Firma MUSS verschluesseln, KANN aber waehlen wie

Ein atomares Control kann aus mehreren Quellen stammen:

Control Parent 1 Parent 2 Parent 3 Effektive Staerke
SEC-042 (Encrypt at rest) DSGVO Art. 32 (law) NIS2 Art. 21 (law) ENISA CCM (framework) must (Gesetz uebertrumpft)
NET-015 (Zero Trust) NIST SP 800-207 (framework) CISA (framework) can (nur Frameworks)
AUTH-003 (MFA) DSGVO Art. 32 (law) BSI-TR (guideline) OWASP ASVS (framework) must (Gesetz vorhanden)

Regel: Der hoechste source_type bestimmt, ob die normative_strength begrenzt wird. Wenn mindestens ein Parent-Link ein Gesetz ist, bleibt die Staerke wie extrahiert.

Technische Umsetzung

Klassifikations-Map

Datei: backend-compliance/compliance/data/source_type_classification.py

Jeder source_regulation-Wert aus control_parent_links wird klassifiziert:

SOURCE_REGULATION_CLASSIFICATION = {
    "DSGVO (EU) 2016/679": "law",
    "EDPB Leitlinien 01/2020 (Datentransfers)": "guideline",
    "NIST Cybersecurity Framework 2.0": "framework",
    # ... 55+ Eintraege
}

Backfill-Endpoint

POST /api/compliance/v1/canonical/controls/backfill-normative-strength?dry_run=true

Ablauf:

  1. Alle aktiven obligation_candidates laden
  2. Fuer jede Obligation den Parent-Control finden
  3. Ueber control_parent_links die source_regulations ermitteln
  4. Hoechsten source_type bestimmen
  5. normative_strength begrenzen falls noetig
  6. Bei dry_run=false: Aenderungen in die DB schreiben

Cap-Funktion

def cap_normative_strength(original: str, source_type: str) -> str:
    """
    cap_normative_strength("must", "framework") → "may"
    cap_normative_strength("should", "law")     → "should"
    cap_normative_strength("must", "guideline") → "should"
    """

Frontend-Anzeige

In der Control-Detail-Ansicht werden Obligations mit farbcodierten Badges angezeigt:

normative_strength Badge Farbe Bedeutung
must MUSS Rot Gesetzliche Pflicht
should SOLL Gelb/Amber Empfohlen, Begruendungspflicht bei Abweichung
may KANN Gruen Freiwillige Best Practice

Haeufige Fragen

Warum steht bei einem ENISA-Control "MUSS"?

Vor dem Backfill: Das System uebernahm die Sprache des Quelldokuments 1:1. ENISA schreibt intern "shall/must" weil es innerhalb seines Frameworks verbindlich formuliert. Fuer den Anwender ist das ENISA-Dokument aber nicht rechtsverbindlich.

Nach dem Backfill: ENISA-Controls zeigen maximal "KANN", es sei denn ein Gesetz (z.B. NIS2) referenziert dasselbe Control — dann gilt die gesetzliche Verbindlichkeit.

Was bedeutet "Stand der Technik"?

NIS2 und DSGVO verweisen auf den "Stand der Technik", ohne ihn zu definieren. In der Praxis werden ENISA- und BSI-Dokumente als Referenz herangezogen. Das macht ihre Empfehlungen relevant ("SOLL"), aber nicht zu Gesetzen ("MUSS").

Wie gehe ich mit unbekannten Quellen um?

Neue Regulierungen muessen in der SOURCE_REGULATION_CLASSIFICATION Map eingetragen werden. Der Fallback fuer unbekannte Quellen ist framework (konservativstes Ergebnis — geringste Verbindlichkeit zugewiesen).