# 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

```mermaid
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:

```mermaid
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

## Multi-Parent-Links

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:

```python
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

```python
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).
