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
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>
202 lines
7.2 KiB
Markdown
202 lines
7.2 KiB
Markdown
# 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).
|