feat: Document Templates V2 — DSFA, TOM, VVT, AVV, Verpflichtung, Art.13/14
Erweiterte Compliance-Vorlagen fuer den Document Generator: - DSFA V2: Schwellwertanalyse (9 WP248-Kriterien), SDM-basierte TOM, strukturierte Risikobewertung, KI-Modul (AI Act), Art.36-Pruefung - TOM V2: 7 SDM-Gewaehrleistungsziele, Sektor-Erweiterungen, NIS2/ISO27001/AI Act Varianten - VVT V2: 6 Branchen-Muster (IT/SaaS, Gesundheit, Handel, Handwerk, Bildung, Beratung) + allgemeine Art.30-Vorlage - AVV V2: Vollstaendiger Art.28-Vertrag mit TOM-Anlage - Verpflichtungserklaerung: Mitarbeiter-Vertraulichkeit - Art.13/14 Informationspflichten-Muster Enthalt SQL-Migrations (compliance_legal_templates), Python-Generatoren und Qdrant-Cleanup-Skript. Feature-Branch fuer spaetere Integration in breakpilot-compliance. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
285
document-templates/generators/tom_template.py
Normal file
285
document-templates/generators/tom_template.py
Normal file
@@ -0,0 +1,285 @@
|
||||
"""TOM template generator V2 — SDM-structured TOM catalog.
|
||||
|
||||
Replaces the flat 17-measure list with a hierarchical structure based on
|
||||
the 7 SDM Gewaehrleistungsziele (Standard-Datenschutzmodell V3.1a).
|
||||
"""
|
||||
|
||||
# -- SDM-structured TOM catalog ---------------------------------------------
|
||||
|
||||
SDM_TOM_CATALOG = {
|
||||
"verfuegbarkeit": {
|
||||
"label": "Verfuegbarkeit",
|
||||
"sdm_baustein": "SDM-B11 (Aufbewahren)",
|
||||
"measures": [
|
||||
{"name": "Redundante Datenhaltung", "description": "RAID, Replikation, Geo-Redundanz", "type": "technical"},
|
||||
{"name": "Backup-Strategie", "description": "Taeglich inkrementell, woechentlich voll, verschluesselt", "type": "technical"},
|
||||
{"name": "Disaster-Recovery-Plan", "description": "Dokumentierte RTO/RPO-Werte, jaehrliche Tests", "type": "organizational"},
|
||||
{"name": "USV / Notstromversorgung", "description": "Unterbrechungsfreie Stromversorgung fuer kritische Systeme", "type": "technical"},
|
||||
],
|
||||
},
|
||||
"integritaet": {
|
||||
"label": "Integritaet",
|
||||
"sdm_baustein": "SDM-B61 (Berichtigen)",
|
||||
"measures": [
|
||||
{"name": "Pruefsummen und Signaturen", "description": "Digitale Signaturen fuer Datenuebertragungen", "type": "technical"},
|
||||
{"name": "Eingabevalidierung", "description": "Plausibilitaetspruefungen auf allen Eingabeschnittstellen", "type": "technical"},
|
||||
{"name": "Change Management", "description": "Dokumentierte Aenderungsverfahren mit Freigabeprozess", "type": "organizational"},
|
||||
{"name": "Versionierung", "description": "Versionierung von Datensaetzen und Konfigurationen", "type": "technical"},
|
||||
],
|
||||
},
|
||||
"vertraulichkeit": {
|
||||
"label": "Vertraulichkeit",
|
||||
"sdm_baustein": "SDM-B51 (Zugriffe regeln)",
|
||||
"measures": [
|
||||
{"name": "Verschluesselung im Transit", "description": "TLS 1.3 fuer alle Verbindungen", "type": "technical"},
|
||||
{"name": "Verschluesselung at Rest", "description": "AES-256 fuer gespeicherte Daten", "type": "technical"},
|
||||
{"name": "Zugriffskonzept (RBAC)", "description": "Rollenbasiert, Least-Privilege-Prinzip, regelmaessige Reviews", "type": "technical"},
|
||||
{"name": "Multi-Faktor-Authentifizierung", "description": "MFA fuer alle administrativen Zugaenge", "type": "technical"},
|
||||
{"name": "Physische Zutrittskontrolle", "description": "Schluessel, Kartenleser, Besucherprotokoll", "type": "technical"},
|
||||
{"name": "Vertraulichkeitsverpflichtung", "description": "Schriftliche Verpflichtung aller Mitarbeitenden", "type": "organizational"},
|
||||
],
|
||||
},
|
||||
"nichtverkettung": {
|
||||
"label": "Nichtverkettung",
|
||||
"sdm_baustein": "SDM-B50 (Trennen)",
|
||||
"measures": [
|
||||
{"name": "Mandantentrennung", "description": "Logische Datentrennung nach Mandanten/Zweck", "type": "technical"},
|
||||
{"name": "Pseudonymisierung", "description": "Wo fachlich moeglich, Einsatz von Pseudonymen", "type": "technical"},
|
||||
{"name": "Zweckbindungspruefung", "description": "Pruefung bei jeder neuen Datennutzung", "type": "organizational"},
|
||||
],
|
||||
},
|
||||
"transparenz": {
|
||||
"label": "Transparenz",
|
||||
"sdm_baustein": "SDM-B42 (Dokumentieren), SDM-B43 (Protokollieren)",
|
||||
"measures": [
|
||||
{"name": "Verarbeitungsverzeichnis", "description": "Art. 30 DS-GVO konformes VVT", "type": "organizational"},
|
||||
{"name": "Audit-Logging", "description": "Vollstaendige Protokollierung aller Datenzugriffe", "type": "technical"},
|
||||
{"name": "Informationspflichten", "description": "Art. 13/14 DS-GVO Datenschutzerklaerung", "type": "organizational"},
|
||||
{"name": "Datenpannen-Prozess", "description": "Dokumentierter Meldeprozess Art. 33/34 DS-GVO", "type": "organizational"},
|
||||
],
|
||||
},
|
||||
"intervenierbarkeit": {
|
||||
"label": "Intervenierbarkeit",
|
||||
"sdm_baustein": "SDM-B60 (Loeschen), SDM-B61 (Berichtigen), SDM-B62 (Einschraenken)",
|
||||
"measures": [
|
||||
{"name": "Betroffenenanfragen-Prozess", "description": "Auskunft, Loeschung, Berichtigung, Widerspruch", "type": "organizational"},
|
||||
{"name": "Technische Loeschfaehigkeit", "description": "Loeschung mit Nachweis (Loeschprotokoll)", "type": "technical"},
|
||||
{"name": "Datenportabilitaet", "description": "Export in maschinenlesbarem Format (Art. 20)", "type": "technical"},
|
||||
{"name": "Sperrfunktion", "description": "Einschraenkung der Verarbeitung moeglich", "type": "technical"},
|
||||
],
|
||||
},
|
||||
"datenminimierung": {
|
||||
"label": "Datenminimierung",
|
||||
"sdm_baustein": "SDM-B41 (Planen und Spezifizieren)",
|
||||
"measures": [
|
||||
{"name": "Erforderlichkeitspruefung", "description": "Regelmaessige Pruefung der erhobenen Datenfelder", "type": "organizational"},
|
||||
{"name": "Automatisierte Loeschung", "description": "Fristgerechte Loeschung nach Aufbewahrungsfrist", "type": "technical"},
|
||||
{"name": "Anonymisierung", "description": "Anonymisierung/Aggregation fuer Statistik", "type": "technical"},
|
||||
{"name": "Privacy by Design", "description": "Datenschutz ab Entwurfsphase neuer Verarbeitungen", "type": "organizational"},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
# -- Sector-specific extensions ----------------------------------------------
|
||||
|
||||
SECTOR_TOMS = {
|
||||
"it_saas": {
|
||||
"label": "IT / SaaS",
|
||||
"measures": [
|
||||
{"name": "Container-Isolation", "description": "Workload-Isolation zwischen Mandanten (Kubernetes Namespaces)", "type": "technical", "sdm_goal": "nichtverkettung"},
|
||||
{"name": "API-Security", "description": "Rate Limiting, OAuth 2.0, API-Key-Rotation", "type": "technical", "sdm_goal": "vertraulichkeit"},
|
||||
{"name": "DevSecOps Pipeline", "description": "SAST/DAST in CI/CD, Dependency Scanning", "type": "technical", "sdm_goal": "integritaet"},
|
||||
{"name": "Secrets Management", "description": "Vault/KMS fuer Credentials, keine Hardcoded Secrets", "type": "technical", "sdm_goal": "vertraulichkeit"},
|
||||
],
|
||||
},
|
||||
"gesundheitswesen": {
|
||||
"label": "Gesundheitswesen",
|
||||
"measures": [
|
||||
{"name": "Patientenakten-Verschluesselung", "description": "Ende-zu-Ende-Verschluesselung fuer Gesundheitsdaten (Art. 9)", "type": "technical", "sdm_goal": "vertraulichkeit"},
|
||||
{"name": "Notfallzugriff", "description": "Break-the-Glass-Verfahren fuer medizinische Notfaelle", "type": "organizational", "sdm_goal": "verfuegbarkeit"},
|
||||
{"name": "Forschungsdaten-Anonymisierung", "description": "Vollstaendige Anonymisierung vor Forschungsnutzung", "type": "technical", "sdm_goal": "datenminimierung"},
|
||||
],
|
||||
},
|
||||
"finanzdienstleistungen": {
|
||||
"label": "Finanzdienstleistungen",
|
||||
"measures": [
|
||||
{"name": "Transaktions-Monitoring", "description": "Echtzeit-Ueberwachung auf Unregelmaessigkeiten (GwG)", "type": "technical", "sdm_goal": "integritaet"},
|
||||
{"name": "Aufbewahrungspflichten", "description": "10 Jahre Aufbewahrung gemaess AO/HGB, danach Loeschung", "type": "organizational", "sdm_goal": "datenminimierung"},
|
||||
{"name": "PCI-DSS Compliance", "description": "Payment Card Industry Standards fuer Kartendaten", "type": "technical", "sdm_goal": "vertraulichkeit"},
|
||||
],
|
||||
},
|
||||
"handel": {
|
||||
"label": "Handel / E-Commerce",
|
||||
"measures": [
|
||||
{"name": "Cookie-Consent-Management", "description": "TDDDG-konformes Einwilligungsmanagement", "type": "technical", "sdm_goal": "transparenz"},
|
||||
{"name": "Gastzugang-Option", "description": "Bestellung ohne Pflicht-Kundenkonto (Datenminimierung)", "type": "organizational", "sdm_goal": "datenminimierung"},
|
||||
{"name": "Zahlungsdaten-Tokenisierung", "description": "Keine direkte Speicherung von Zahlungsdaten", "type": "technical", "sdm_goal": "vertraulichkeit"},
|
||||
],
|
||||
},
|
||||
"handwerk": {
|
||||
"label": "Handwerk",
|
||||
"measures": [
|
||||
{"name": "Mobile-Device-Management", "description": "Absicherung mobiler Endgeraete auf Baustellen", "type": "technical", "sdm_goal": "vertraulichkeit"},
|
||||
{"name": "Papierakten-Sicherung", "description": "Verschlossene Schraenke fuer physische Kundenakten", "type": "technical", "sdm_goal": "vertraulichkeit"},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
# -- NIS2 / ISO 27001 / AI Act extensions -----------------------------------
|
||||
|
||||
NIS2_TOMS = [
|
||||
{"name": "Incident-Response-Plan", "description": "NIS2-konformer Vorfallreaktionsplan (72h Meldepflicht an BSI)", "type": "organizational", "sdm_goal": "verfuegbarkeit"},
|
||||
{"name": "Supply-Chain-Security", "description": "Bewertung der Lieferkettensicherheit (BSIG 2025)", "type": "organizational", "sdm_goal": "integritaet"},
|
||||
{"name": "Vulnerability Management", "description": "Regelmaessige Schwachstellenscans, Patch-Management", "type": "technical", "sdm_goal": "integritaet"},
|
||||
{"name": "Security Awareness", "description": "Pflicht-Schulungen Cybersicherheit fuer Geschaeftsleitung", "type": "organizational", "sdm_goal": "vertraulichkeit"},
|
||||
]
|
||||
|
||||
ISO27001_TOMS = [
|
||||
{"name": "ISMS Risikomanagement", "description": "ISO 27001 Anhang A — Informationssicherheits-Risikobewertung", "type": "organizational", "sdm_goal": "verfuegbarkeit"},
|
||||
{"name": "Dokumentenlenkung", "description": "Versionierte Sicherheitsrichtlinien und -verfahren", "type": "organizational", "sdm_goal": "transparenz"},
|
||||
{"name": "Management Review", "description": "Jaehrliche Ueberprufung des ISMS durch Geschaeftsleitung", "type": "organizational", "sdm_goal": "transparenz"},
|
||||
]
|
||||
|
||||
AI_ACT_TOMS = [
|
||||
{"name": "KI-Risikoklassifizierung", "description": "Bewertung aller KI-Systeme nach EU AI Act Risikokategorien", "type": "organizational", "sdm_goal": "transparenz"},
|
||||
{"name": "Human Oversight", "description": "Menschliche Aufsicht fuer Hochrisiko-KI-Systeme (Art. 14 KI-VO)", "type": "organizational", "sdm_goal": "intervenierbarkeit"},
|
||||
{"name": "KI-Transparenz", "description": "Transparenzpflichten bei KI-Einsatz gegenueber Betroffenen (Art. 13 KI-VO)", "type": "organizational", "sdm_goal": "transparenz"},
|
||||
{"name": "KI-Bias-Monitoring", "description": "Ueberwachung auf diskriminierende Ergebnisse", "type": "technical", "sdm_goal": "integritaet"},
|
||||
]
|
||||
|
||||
|
||||
def generate_tom_drafts(ctx: dict) -> list[dict]:
|
||||
"""Generate TOM measure drafts structured by SDM Gewaehrleistungsziele.
|
||||
|
||||
Args:
|
||||
ctx: Flat dict from company-profile/template-context.
|
||||
|
||||
Returns:
|
||||
List of TOM measure dicts with SDM goal assignment.
|
||||
"""
|
||||
measures = []
|
||||
control_counter = 0
|
||||
|
||||
# Base SDM measures
|
||||
for goal_key, goal_data in SDM_TOM_CATALOG.items():
|
||||
for m in goal_data["measures"]:
|
||||
control_counter += 1
|
||||
measures.append(_build_measure(
|
||||
counter=control_counter,
|
||||
measure=m,
|
||||
sdm_goal=goal_key,
|
||||
sdm_baustein=goal_data["sdm_baustein"],
|
||||
category=goal_data["label"],
|
||||
ctx=ctx,
|
||||
))
|
||||
|
||||
# Regulatory extensions
|
||||
if ctx.get("subject_to_nis2"):
|
||||
for m in NIS2_TOMS:
|
||||
control_counter += 1
|
||||
measures.append(_build_measure(
|
||||
counter=control_counter,
|
||||
measure=m,
|
||||
sdm_goal=m["sdm_goal"],
|
||||
sdm_baustein="NIS2 / BSIG 2025",
|
||||
category="Cybersicherheit (NIS2)",
|
||||
ctx=ctx,
|
||||
))
|
||||
|
||||
if ctx.get("subject_to_iso27001"):
|
||||
for m in ISO27001_TOMS:
|
||||
control_counter += 1
|
||||
measures.append(_build_measure(
|
||||
counter=control_counter,
|
||||
measure=m,
|
||||
sdm_goal=m["sdm_goal"],
|
||||
sdm_baustein="ISO 27001 Anhang A",
|
||||
category="ISMS (ISO 27001)",
|
||||
ctx=ctx,
|
||||
))
|
||||
|
||||
if ctx.get("subject_to_ai_act") or ctx.get("has_ai_systems"):
|
||||
for m in AI_ACT_TOMS:
|
||||
control_counter += 1
|
||||
measures.append(_build_measure(
|
||||
counter=control_counter,
|
||||
measure=m,
|
||||
sdm_goal=m["sdm_goal"],
|
||||
sdm_baustein="EU AI Act (2024/1689)",
|
||||
category="KI-Compliance",
|
||||
ctx=ctx,
|
||||
))
|
||||
|
||||
# Sector-specific extensions
|
||||
sector = _detect_sector(ctx)
|
||||
if sector and sector in SECTOR_TOMS:
|
||||
sector_data = SECTOR_TOMS[sector]
|
||||
for m in sector_data["measures"]:
|
||||
control_counter += 1
|
||||
measures.append(_build_measure(
|
||||
counter=control_counter,
|
||||
measure=m,
|
||||
sdm_goal=m.get("sdm_goal", "vertraulichkeit"),
|
||||
sdm_baustein=f"Sektor: {sector_data['label']}",
|
||||
category=f"Sektor ({sector_data['label']})",
|
||||
ctx=ctx,
|
||||
))
|
||||
|
||||
return measures
|
||||
|
||||
|
||||
def sdm_coverage_summary(measures: list[dict]) -> dict:
|
||||
"""Return coverage matrix: SDM goal -> measure count."""
|
||||
summary = {}
|
||||
for goal_key in SDM_TOM_CATALOG:
|
||||
count = sum(1 for m in measures if m.get("sdm_goal") == goal_key)
|
||||
summary[goal_key] = {
|
||||
"label": SDM_TOM_CATALOG[goal_key]["label"],
|
||||
"count": count,
|
||||
}
|
||||
return summary
|
||||
|
||||
|
||||
# -- Internal helpers --------------------------------------------------------
|
||||
|
||||
def _build_measure(counter: int, measure: dict, sdm_goal: str,
|
||||
sdm_baustein: str, category: str, ctx: dict) -> dict:
|
||||
return {
|
||||
"control_id": f"TOM-SDM-{counter:03d}",
|
||||
"name": measure["name"],
|
||||
"description": measure["description"],
|
||||
"category": category,
|
||||
"type": measure.get("type", "organizational"),
|
||||
"sdm_goal": sdm_goal,
|
||||
"sdm_baustein_ref": sdm_baustein,
|
||||
"implementation_status": "not_implemented",
|
||||
"effectiveness_rating": "not_assessed",
|
||||
"responsible_department": "IT-Sicherheit",
|
||||
"priority": _assess_priority(measure, ctx),
|
||||
"review_frequency": f"{ctx.get('review_cycle_months', 12)} Monate",
|
||||
}
|
||||
|
||||
|
||||
def _assess_priority(measure: dict, ctx: dict) -> str:
|
||||
name_lower = measure.get("name", "").lower()
|
||||
if any(kw in name_lower for kw in ["verschluesselung", "mfa", "incident", "ki-risiko"]):
|
||||
return "high"
|
||||
if any(kw in name_lower for kw in ["backup", "zugriff", "logging", "loeschung"]):
|
||||
return "high"
|
||||
return "medium"
|
||||
|
||||
|
||||
def _detect_sector(ctx: dict) -> str | None:
|
||||
"""Map company industry to sector key."""
|
||||
industry = (ctx.get("industry") or "").lower()
|
||||
mapping = {
|
||||
"technologie": "it_saas", "it": "it_saas", "saas": "it_saas", "software": "it_saas",
|
||||
"gesundheit": "gesundheitswesen", "pharma": "gesundheitswesen", "medizin": "gesundheitswesen",
|
||||
"finanz": "finanzdienstleistungen", "bank": "finanzdienstleistungen", "versicherung": "finanzdienstleistungen",
|
||||
"handel": "handel", "e-commerce": "handel", "einzelhandel": "handel", "shop": "handel",
|
||||
"handwerk": "handwerk", "bau": "handwerk", "kfz": "handwerk",
|
||||
}
|
||||
for keyword, sector in mapping.items():
|
||||
if keyword in industry:
|
||||
return sector
|
||||
return None
|
||||
Reference in New Issue
Block a user