Compare commits

...

5 Commits

Author SHA1 Message Date
Benjamin Admin b39c1d5dce feat: DSR Prozessbeschreibungen Art. 15-21 mit Swim-Lane-Diagrammen
Build + Deploy / build-admin-compliance (push) Successful in 1m56s
Build + Deploy / build-backend-compliance (push) Successful in 3m5s
Build + Deploy / build-ai-sdk (push) Successful in 47s
Build + Deploy / build-developer-portal (push) Successful in 1m5s
Build + Deploy / build-tts (push) Successful in 1m23s
Build + Deploy / build-document-crawler (push) Successful in 33s
Build + Deploy / build-dsms-gateway (push) Successful in 23s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / loc-budget (push) Failing after 17s
CI / secret-scan (push) Has been skipped
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Successful in 2m40s
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / test-go (push) Successful in 42s
CI / test-python-backend (push) Successful in 47s
CI / test-python-document-crawler (push) Successful in 33s
CI / test-python-dsms-gateway (push) Successful in 22s
CI / validate-canonical-controls (push) Successful in 18s
Build + Deploy / trigger-orca (push) Successful in 2m53s
7 vollstaendige Prozessbeschreibungen fuer den Document Generator:
- Art. 15: Auskunftsrecht (30 Tage, 6 Schritte, Informationskatalog)
- Art. 16: Berichtigungsrecht (14 Tage, inkl. Art. 19 Mitteilung)
- Art. 17: Loeschungsrecht (14 Tage, Art. 17(3) Ausnahmen-Checkliste)
- Art. 18: Einschraenkungsrecht (14 Tage, erlaubte Verarbeitung)
- Art. 19: Mitteilungspflicht (automatisch bei Art. 16/17/18)
- Art. 20: Datenuebertragbarkeit (30 Tage, JSON/CSV/XML Export)
- Art. 21: Widerspruchsrecht (30 Tage, Sonderfall Direktwerbung)

Jede Beschreibung enthaelt:
- Mermaid Swim-Lane-Diagramm (Betroffener/Sachbearbeitung/Fachabteilung/DSB)
- Detaillierte Schritt-Tabelle mit Verantwortlichkeiten und Fristen
- Rechtsgrundlagen-Verweise
- Firmen-Platzhalter (FIRMENNAME, VERSION, DATUM, DSB_NAME)

Integration:
- 7 neue Typen in VALID_DOCUMENT_TYPES (legal_template_routes.py)
- Neue Kategorie "DSR-Prozesse" im Document Generator Frontend
- DSR types-core.ts: templateType Feld verknuepft DSR → Document Generator
- Migration 085 seeded die Templates in die legal_templates Tabelle

[migration-approved]

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-28 17:53:44 +02:00
Benjamin Admin b06a33a5fe fix: syntax error — missing closing paren in scan summary builder 2026-04-28 17:41:11 +02:00
Benjamin Admin 6c0e76f96d feat: show scanned pages in email summary + frontend (expandable list)
Email now lists all scanned URLs with checkmark/cross status.
Frontend shows collapsible "X Seiten gescannt — Details anzeigen".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-28 17:26:03 +02:00
Benjamin Admin 0106f3b5b6 fix: use Ollama directly for correction generation (bypass SDK think-mode)
SDK LLM chat returns empty content due to Qwen think-mode. Direct Ollama
/api/generate call with stream:false gets the full response including
think tags which we strip.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-28 16:30:51 +02:00
Benjamin Admin b175ad2594 fix: increase LLM timeouts for scan corrections (90s) and DSE extraction (120s)
Qwen 3.5:35b needs ~30-60s per call. Multi-call scan was timing out.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-28 16:05:35 +02:00
7 changed files with 539 additions and 28 deletions
@@ -23,6 +23,7 @@ interface ScanFinding {
interface ScanData {
pages_scanned: number
pages_list: string[]
services: ServiceInfo[]
findings: ScanFinding[]
ai_detected: boolean
@@ -74,6 +75,25 @@ export function ScanResult({ data }: { data: ScanData }) {
</div>
</div>
{/* Scanned Pages */}
{data.pages_list?.length > 0 && (
<details className="text-sm">
<summary className="text-gray-600 cursor-pointer hover:text-gray-800">
{data.pages_scanned} Seiten gescannt Details anzeigen
</summary>
<ul className="mt-2 space-y-1 ml-4">
{data.pages_list.map((p, i) => {
const isMissing = data.missing_pages[p]
return (
<li key={i} className={`text-xs ${isMissing ? 'text-red-600' : 'text-gray-500'}`}>
{isMissing ? '✗' : '✓'} {p} {isMissing ? `(HTTP ${data.missing_pages[p]})` : ''}
</li>
)
})}
</ul>
</details>
)}
{/* AI / Chatbot Detection */}
<div className="flex gap-3">
<span className={`px-3 py-1 rounded-full text-xs font-medium ${data.ai_detected ? 'bg-purple-100 text-purple-800' : 'bg-gray-100 text-gray-600'}`}>
@@ -18,6 +18,10 @@ export const CATEGORIES: { key: string; label: string; types: string[] | null }[
{ key: 'cloud', label: 'Cloud', types: ['cloud_service_agreement'] },
{ key: 'misc', label: 'Weitere', types: ['community_guidelines', 'copyright_policy', 'data_usage_clause'] },
{ key: 'dsfa', label: 'DSFA', types: ['dsfa'] },
{ key: 'dsr', label: 'DSR-Prozesse', types: [
'dsr_process_art15', 'dsr_process_art16', 'dsr_process_art17',
'dsr_process_art18', 'dsr_process_art19', 'dsr_process_art20', 'dsr_process_art21',
]},
]
// =============================================================================
+14 -6
View File
@@ -52,6 +52,8 @@ export interface DSRTypeInfo {
color: string
bgColor: string
processDocument?: string
/** Document type in the legal_templates table for the Document Generator */
templateType?: string
}
export const DSR_TYPE_INFO: Record<DSRType, DSRTypeInfo> = {
@@ -60,41 +62,47 @@ export const DSR_TYPE_INFO: Record<DSRType, DSRTypeInfo> = {
description: 'Recht auf Auskunft ueber gespeicherte personenbezogene Daten',
defaultDeadlineDays: 30, maxExtensionMonths: 2,
color: 'text-blue-700', bgColor: 'bg-blue-100',
processDocument: 'Prozessbeschreibung Art. 15 DSGVO_v02.pdf'
processDocument: 'Prozessbeschreibung Art. 15 DSGVO_v02.pdf',
templateType: 'dsr_process_art15',
},
rectification: {
type: 'rectification', article: 'Art. 16', label: 'Berichtigungsrecht', labelShort: 'Berichtigung',
description: 'Recht auf Berichtigung unrichtiger personenbezogener Daten',
defaultDeadlineDays: 14, maxExtensionMonths: 2,
color: 'text-yellow-700', bgColor: 'bg-yellow-100',
processDocument: 'Prozessbeschriebung Art. 16 DSGVO_v02.pdf'
processDocument: 'Prozessbeschreibung Art. 16 DSGVO_v02.pdf',
templateType: 'dsr_process_art16',
},
erasure: {
type: 'erasure', article: 'Art. 17', label: 'Loeschungsrecht', labelShort: 'Loeschung',
description: 'Recht auf Loeschung personenbezogener Daten ("Recht auf Vergessenwerden")',
defaultDeadlineDays: 14, maxExtensionMonths: 2,
color: 'text-red-700', bgColor: 'bg-red-100',
processDocument: 'Prozessbeschreibung Art. 17 DSGVO_v03.pdf'
processDocument: 'Prozessbeschreibung Art. 17 DSGVO_v03.pdf',
templateType: 'dsr_process_art17',
},
restriction: {
type: 'restriction', article: 'Art. 18', label: 'Einschraenkungsrecht', labelShort: 'Einschraenkung',
description: 'Recht auf Einschraenkung der Verarbeitung',
defaultDeadlineDays: 14, maxExtensionMonths: 2,
color: 'text-orange-700', bgColor: 'bg-orange-100',
processDocument: 'Prozessbeschreibung Art. 18 DSGVO_v01.pdf'
processDocument: 'Prozessbeschreibung Art. 18 DSGVO_v01.pdf',
templateType: 'dsr_process_art18',
},
portability: {
type: 'portability', article: 'Art. 20', label: 'Datenuebertragbarkeit', labelShort: 'Uebertragung',
description: 'Recht auf Datenuebertragbarkeit in maschinenlesbarem Format',
defaultDeadlineDays: 30, maxExtensionMonths: 2,
color: 'text-purple-700', bgColor: 'bg-purple-100',
processDocument: 'Prozessbeschreibung Art. 20 DSGVO_v02.pdf'
processDocument: 'Prozessbeschreibung Art. 20 DSGVO_v02.pdf',
templateType: 'dsr_process_art20',
},
objection: {
type: 'objection', article: 'Art. 21', label: 'Widerspruchsrecht', labelShort: 'Widerspruch',
description: 'Recht auf Widerspruch gegen die Verarbeitung',
defaultDeadlineDays: 30, maxExtensionMonths: 0,
color: 'text-gray-700', bgColor: 'bg-gray-100'
color: 'text-gray-700', bgColor: 'bg-gray-100',
templateType: 'dsr_process_art21',
}
}
@@ -59,6 +59,7 @@ class ScanFinding(BaseModel):
class ScanResponse(BaseModel):
url: str
pages_scanned: int
pages_list: list[str] = []
services: list[ServiceInfo]
findings: list[ScanFinding]
ai_detected: bool
@@ -111,6 +112,7 @@ async def scan_website_endpoint(req: ScanRequest):
return ScanResponse(
url=req.url,
pages_scanned=len(scan.pages_scanned),
pages_list=scan.pages_scanned,
services=services_info,
findings=findings,
ai_detected=len(scan.ai_mentions) > 0,
@@ -233,30 +235,27 @@ async def _add_corrections(findings: list[ScanFinding], dse_text: str) -> None:
if finding.severity in ("HIGH", "MEDIUM") and "MISSING" in finding.code:
service_name = finding.code.replace("DSE-MISSING-", "").replace("_", " ").title()
try:
async with httpx.AsyncClient(timeout=30.0) as client:
resp = await client.post(f"{SDK_URL}/sdk/v1/llm/chat", headers=SDK_HEADERS, json={
"messages": [
{"role": "system", "content": (
"/no_think\n"
"Du bist Datenschutzexperte. Erstelle einen einbaufertigen "
"Textbaustein fuer eine deutsche Datenschutzerklaerung fuer "
f"den Dienst '{service_name}'. Enthalte: Ueberschrift, "
"Anbietername, Zweck, Rechtsgrundlage nach DSGVO, "
"Drittlandtransfer-Hinweis wenn noetig, "
"Widerspruchsmoeglichkeit. Max 150 Woerter."
)},
{"role": "user", "content": f"Erstelle DSE-Textbaustein fuer: {service_name}"},
],
# Call Ollama directly (bypasses SDK RBAC + Think-mode issues)
ollama_url = os.environ.get("OLLAMA_URL", "http://host.docker.internal:11434")
ollama_model = os.environ.get("OLLAMA_MODEL", "qwen3.5:35b-a3b")
async with httpx.AsyncClient(timeout=120.0) as client:
resp = await client.post(f"{ollama_url}/api/generate", json={
"model": ollama_model,
"prompt": (
f"Erstelle einen einbaufertigen Textbaustein fuer eine deutsche "
f"Datenschutzerklaerung fuer den Dienst '{service_name}'. "
f"Enthalte: Ueberschrift, Anbietername mit Sitz, Zweck der Verarbeitung, "
f"Rechtsgrundlage nach DSGVO, Drittlandtransfer-Hinweis wenn noetig, "
f"Widerspruchsmoeglichkeit. Max 150 Woerter. "
f"Antworte NUR mit dem fertigen Textbaustein."
),
"stream": False,
})
data = resp.json()
import re
raw = (
data.get("response", "")
or (data.get("message", {}) or {}).get("content", "")
or ""
).strip()
raw = data.get("response", "").strip()
raw = re.sub(r"<think>.*?</think>", "", raw, flags=re.DOTALL).strip()
if raw:
if raw and len(raw) > 50:
finding.correction = raw
except Exception as e:
logger.warning("Correction generation failed for %s: %s", service_name, e)
@@ -277,6 +276,12 @@ def _build_scan_summary(
f"{mode} — Website-Scan",
f"URL: {url}",
f"Seiten gescannt: {len(scan.pages_scanned)}",
]
for page in scan.pages_scanned:
status = scan.missing_pages.get(page, 200)
marker = "" if status >= 400 else ""
parts.append(f" {marker} {page}" + (f" (HTTP {status})" if status >= 400 else ""))
parts.extend([
"",
f"Dienstleister-Abgleich (DSE vs. Website):",
f" Korrekt dokumentiert: {n_ok}",
@@ -284,7 +289,7 @@ def _build_scan_summary(
f" Veraltet in DSE: {n_outdated}",
"",
f"Findings: {n_findings} ({high} mit hoher Prioritaet)",
]
])
if findings:
parts.append("")
@@ -101,6 +101,14 @@ VALID_DOCUMENT_TYPES = {
"tom_documentation",
"loeschkonzept",
"pflichtenregister",
# DSR Process Documents (Migration 085)
"dsr_process_art15",
"dsr_process_art16",
"dsr_process_art17",
"dsr_process_art18",
"dsr_process_art19",
"dsr_process_art20",
"dsr_process_art21",
}
VALID_STATUSES = {"published", "draft", "archived"}
@@ -40,7 +40,7 @@ async def extract_dse_services(dse_text: str) -> list[dict]:
"\"country\": \"USA\", \"legal_basis\": \"Einwilligung\"}]"
)
try:
async with httpx.AsyncClient(timeout=60.0) as client:
async with httpx.AsyncClient(timeout=120.0) as client:
resp = await client.post(f"{SDK_URL}/sdk/v1/llm/chat", headers=SDK_HEADERS, json={
"messages": [
{"role": "system", "content": prompt},
@@ -0,0 +1,466 @@
-- Migration 085: DSR Process Document Templates (Art. 15-21 DSGVO)
-- Prozessbeschreibungen mit Swim-Lane-Diagrammen fuer den Document Generator
INSERT INTO compliance_legal_templates (id, tenant_id, document_type, title, language, status, content, placeholders, created_at, updated_at)
VALUES
-- ============================================================================
-- Art. 15 DSGVO — Auskunftsrecht
-- ============================================================================
(gen_random_uuid(), '__default__', 'dsr_process_art15',
'Prozessbeschreibung: Auskunftsrecht (Art. 15 DSGVO)', 'de', 'published',
'<h1>Prozessbeschreibung: Auskunftsrecht nach Art. 15 DSGVO</h1>
<p><strong>Verantwortliche Stelle:</strong> {{FIRMENNAME}}<br/>
<strong>Version:</strong> {{VERSION}}<br/>
<strong>Stand:</strong> {{DATUM}}<br/>
<strong>Genehmigt durch:</strong> {{DSB_NAME}}</p>
<h2>1. Zweck und Geltungsbereich</h2>
<p>Diese Prozessbeschreibung regelt den Ablauf bei Auskunftsersuchen betroffener Personen nach Art. 15 DSGVO. Jede natuerliche Person hat das Recht, eine Bestaetigung darueber zu verlangen, ob personenbezogene Daten verarbeitet werden, und ggf. Auskunft ueber diese Daten zu erhalten.</p>
<h2>2. Rechtsgrundlage</h2>
<ul>
<li>Art. 15 DSGVO — Auskunftsrecht der betroffenen Person</li>
<li>Art. 12 DSGVO — Transparente Information und Kommunikation</li>
<li>Erwaegungsgrund 63 — Recht auf Zugang zu personenbezogenen Daten</li>
</ul>
<h2>3. Frist</h2>
<p><strong>30 Tage</strong> nach Eingang der Anfrage. Verlaengerung um weitere 2 Monate bei komplexen Anfragen moeglich (Art. 12 Abs. 3 DSGVO), mit Begruendung innerhalb der ersten 30 Tage.</p>
<h2>4. Prozessablauf (Swim Lane)</h2>
<pre class="mermaid">
graph TD
subgraph Betroffener
A1[Auskunftsersuchen einreichen]
A7[Auskunft erhalten und pruefen]
end
subgraph Empfang/Sachbearbeitung
B1[Anfrage erfassen und dokumentieren]
B2[Identitaet pruefen]
B3{Identitaet bestaetigt?}
end
subgraph Fachabteilung
C1[Alle Verarbeitungstaetigkeiten identifizieren]
C2[Personenbezogene Daten zusammenstellen]
C3[Daten auf Drittrechte pruefen]
C4[Auskunft erstellen]
end
subgraph Datenschutzbeauftragter
D1[Auskunft auf Vollstaendigkeit pruefen]
D2[Freigabe erteilen]
end
A1 --> B1 --> B2 --> B3
B3 -- Nein --> B2
B3 -- Ja --> C1 --> C2 --> C3 --> C4 --> D1 --> D2 --> A7
</pre>
<h2>5. Detaillierte Schritte</h2>
<table>
<tr><th>Schritt</th><th>Verantwortlich</th><th>Beschreibung</th><th>Frist</th></tr>
<tr><td>1. Eingang</td><td>Empfang</td><td>Anfrage dokumentieren, Eingangsbestaetigung senden</td><td>1 Tag</td></tr>
<tr><td>2. ID-Pruefung</td><td>Sachbearbeitung</td><td>Identitaet des Antragstellers verifizieren</td><td>3 Tage</td></tr>
<tr><td>3. Datenerhebung</td><td>Fachabteilung</td><td>Alle verarbeiteten Daten zusammenstellen</td><td>14 Tage</td></tr>
<tr><td>4. Pruefung Drittrechte</td><td>Fachabteilung</td><td>Rechte Dritter pruefen und ggf. schwaerzen</td><td>5 Tage</td></tr>
<tr><td>5. QS + Freigabe</td><td>DSB</td><td>Vollstaendigkeit und Richtigkeit pruefen</td><td>3 Tage</td></tr>
<tr><td>6. Versand</td><td>Sachbearbeitung</td><td>Auskunft an Betroffenen uebermitteln</td><td>1 Tag</td></tr>
</table>
<h2>6. Zu liefernde Informationen (Art. 15 Abs. 1)</h2>
<ul>
<li>Verarbeitungszwecke</li>
<li>Kategorien personenbezogener Daten</li>
<li>Empfaenger oder Kategorien von Empfaengern</li>
<li>Speicherdauer oder Kriterien fuer die Festlegung</li>
<li>Bestehen eines Rechts auf Berichtigung, Loeschung, Einschraenkung, Widerspruch</li>
<li>Beschwerderecht bei einer Aufsichtsbehoerde</li>
<li>Herkunft der Daten (wenn nicht beim Betroffenen erhoben)</li>
<li>Bestehen einer automatisierten Entscheidungsfindung inkl. Profiling</li>
<li>Bei Drittlanduebermittlung: geeignete Garantien</li>
</ul>
<h2>7. Dokumentation</h2>
<p>Alle Schritte werden im DSR-Modul von {{FIRMENNAME}} protokolliert inkl. Zeitstempel, Bearbeiter und Ergebnis.</p>',
'["FIRMENNAME", "VERSION", "DATUM", "DSB_NAME"]'::jsonb,
NOW(), NOW()),
-- ============================================================================
-- Art. 16 DSGVO — Recht auf Berichtigung
-- ============================================================================
(gen_random_uuid(), '__default__', 'dsr_process_art16',
'Prozessbeschreibung: Recht auf Berichtigung (Art. 16 DSGVO)', 'de', 'published',
'<h1>Prozessbeschreibung: Recht auf Berichtigung nach Art. 16 DSGVO</h1>
<p><strong>Verantwortliche Stelle:</strong> {{FIRMENNAME}}<br/>
<strong>Version:</strong> {{VERSION}}<br/>
<strong>Stand:</strong> {{DATUM}}<br/>
<strong>Genehmigt durch:</strong> {{DSB_NAME}}</p>
<h2>1. Zweck</h2>
<p>Regelung des Ablaufs bei Antraegen auf Berichtigung unrichtiger personenbezogener Daten nach Art. 16 DSGVO.</p>
<h2>2. Rechtsgrundlage</h2>
<ul>
<li>Art. 16 DSGVO — Recht auf Berichtigung</li>
<li>Art. 19 DSGVO — Mitteilungspflicht an Empfaenger</li>
<li>Art. 5 Abs. 1 lit. d DSGVO — Grundsatz der Richtigkeit</li>
</ul>
<h2>3. Frist</h2>
<p><strong>Unverzueglich</strong>, spaetestens innerhalb von <strong>14 Tagen</strong>.</p>
<h2>4. Prozessablauf</h2>
<pre class="mermaid">
graph TD
subgraph Betroffener
A1[Berichtigungsantrag stellen]
A5[Bestaetigung erhalten]
end
subgraph Sachbearbeitung
B1[Antrag erfassen]
B2[Identitaet pruefen]
B3[Unrichtigkeit pruefen]
B4{Berechtigt?}
end
subgraph Fachabteilung
C1[Daten in allen Systemen berichtigen]
C2[Empfaenger benachrichtigen Art. 19]
end
subgraph DSB
D1[Berichtigung dokumentieren]
end
A1 --> B1 --> B2 --> B3 --> B4
B4 -- Nein --> A5
B4 -- Ja --> C1 --> C2 --> D1 --> A5
</pre>
<h2>5. Schritte</h2>
<table>
<tr><th>Schritt</th><th>Verantwortlich</th><th>Beschreibung</th><th>Frist</th></tr>
<tr><td>1. Eingang</td><td>Empfang</td><td>Antrag dokumentieren</td><td>1 Tag</td></tr>
<tr><td>2. ID-Pruefung</td><td>Sachbearbeitung</td><td>Identitaet verifizieren</td><td>2 Tage</td></tr>
<tr><td>3. Sachpruefung</td><td>Sachbearbeitung</td><td>Unrichtigkeit der Daten bestaetigen</td><td>3 Tage</td></tr>
<tr><td>4. Berichtigung</td><td>Fachabteilung</td><td>Daten in allen Systemen korrigieren</td><td>3 Tage</td></tr>
<tr><td>5. Mitteilung Art. 19</td><td>Fachabteilung</td><td>Alle Empfaenger ueber Berichtigung informieren</td><td>3 Tage</td></tr>
<tr><td>6. Dokumentation</td><td>DSB</td><td>Berichtigung protokollieren</td><td>1 Tag</td></tr>
</table>',
'["FIRMENNAME", "VERSION", "DATUM", "DSB_NAME"]'::jsonb,
NOW(), NOW()),
-- ============================================================================
-- Art. 17 DSGVO — Recht auf Loeschung
-- ============================================================================
(gen_random_uuid(), '__default__', 'dsr_process_art17',
'Prozessbeschreibung: Recht auf Loeschung (Art. 17 DSGVO)', 'de', 'published',
'<h1>Prozessbeschreibung: Recht auf Loeschung nach Art. 17 DSGVO</h1>
<p><strong>Verantwortliche Stelle:</strong> {{FIRMENNAME}}<br/>
<strong>Version:</strong> {{VERSION}}<br/>
<strong>Stand:</strong> {{DATUM}}<br/>
<strong>Genehmigt durch:</strong> {{DSB_NAME}}</p>
<h2>1. Zweck</h2>
<p>Regelung des Ablaufs bei Loeschungsersuchen (Recht auf Vergessenwerden) nach Art. 17 DSGVO.</p>
<h2>2. Rechtsgrundlage</h2>
<ul>
<li>Art. 17 DSGVO — Recht auf Loeschung</li>
<li>Art. 17 Abs. 3 DSGVO — Ausnahmen (Meinungsfreiheit, rechtliche Verpflichtung, oeffentliches Interesse, Rechtsansprueche)</li>
<li>Art. 19 DSGVO — Mitteilungspflicht an Empfaenger</li>
</ul>
<h2>3. Frist</h2>
<p><strong>Unverzueglich</strong>, spaetestens innerhalb von <strong>14 Tagen</strong>.</p>
<h2>4. Prozessablauf</h2>
<pre class="mermaid">
graph TD
subgraph Betroffener
A1[Loeschungsantrag stellen]
A6[Bestaetigung erhalten]
end
subgraph Sachbearbeitung
B1[Antrag erfassen + ID pruefen]
B2[Loeschungsgrund pruefen]
end
subgraph DSB
C1[Art. 17 Abs. 3 Ausnahmen pruefen]
C2{Ausnahme greift?}
C3[Ablehnung mit Begruendung]
end
subgraph Fachabteilung
D1[Daten in allen Systemen loeschen]
D2[Backups markieren]
D3[Empfaenger benachrichtigen Art. 19]
D4[Loeschprotokoll erstellen]
end
A1 --> B1 --> B2 --> C1 --> C2
C2 -- Ja --> C3 --> A6
C2 -- Nein --> D1 --> D2 --> D3 --> D4 --> A6
</pre>
<h2>5. Art. 17 Abs. 3 Ausnahmen (Checkliste)</h2>
<table>
<tr><th>Ausnahme</th><th>Beschreibung</th></tr>
<tr><td>a) Meinungsfreiheit</td><td>Ausuebung des Rechts auf freie Meinungsaeusserung und Information</td></tr>
<tr><td>b) Rechtliche Verpflichtung</td><td>Erfuellung einer rechtlichen Verpflichtung (z.B. Aufbewahrungspflichten)</td></tr>
<tr><td>c) Oeffentliches Interesse</td><td>Gruende des oeffentlichen Interesses im Bereich Gesundheit</td></tr>
<tr><td>d) Archivzwecke</td><td>Im oeffentlichen Interesse liegende Archivzwecke, Forschung, Statistik</td></tr>
<tr><td>e) Rechtsansprueche</td><td>Geltendmachung, Ausuebung oder Verteidigung von Rechtsanspruechen</td></tr>
</table>
<h2>6. Schritte</h2>
<table>
<tr><th>Schritt</th><th>Verantwortlich</th><th>Beschreibung</th><th>Frist</th></tr>
<tr><td>1. Eingang + ID</td><td>Sachbearbeitung</td><td>Antrag dokumentieren, Identitaet verifizieren</td><td>3 Tage</td></tr>
<tr><td>2. Ausnahmepruefung</td><td>DSB</td><td>Art. 17 Abs. 3 Checkliste durchgehen</td><td>3 Tage</td></tr>
<tr><td>3. Loeschung</td><td>Fachabteilung</td><td>Daten in allen Systemen loeschen</td><td>3 Tage</td></tr>
<tr><td>4. Backup-Handling</td><td>IT</td><td>Backups markieren, bei naechstem Zyklus loeschen</td><td>3 Tage</td></tr>
<tr><td>5. Mitteilung Art. 19</td><td>Fachabteilung</td><td>Empfaenger ueber Loeschung informieren</td><td>2 Tage</td></tr>
</table>',
'["FIRMENNAME", "VERSION", "DATUM", "DSB_NAME"]'::jsonb,
NOW(), NOW()),
-- ============================================================================
-- Art. 18 DSGVO — Recht auf Einschraenkung der Verarbeitung
-- ============================================================================
(gen_random_uuid(), '__default__', 'dsr_process_art18',
'Prozessbeschreibung: Einschraenkung der Verarbeitung (Art. 18 DSGVO)', 'de', 'published',
'<h1>Prozessbeschreibung: Einschraenkung der Verarbeitung nach Art. 18 DSGVO</h1>
<p><strong>Verantwortliche Stelle:</strong> {{FIRMENNAME}}<br/>
<strong>Version:</strong> {{VERSION}}<br/>
<strong>Stand:</strong> {{DATUM}}<br/>
<strong>Genehmigt durch:</strong> {{DSB_NAME}}</p>
<h2>1. Zweck</h2>
<p>Regelung des Ablaufs bei Antraegen auf Einschraenkung der Verarbeitung personenbezogener Daten nach Art. 18 DSGVO.</p>
<h2>2. Rechtsgrundlage und Voraussetzungen</h2>
<p>Die betroffene Person kann die Einschraenkung verlangen wenn:</p>
<ul>
<li>a) Richtigkeit der Daten bestritten wird (fuer die Dauer der Ueberpruefung)</li>
<li>b) Verarbeitung unrechtmaessig ist und Betroffener Loeschung ablehnt</li>
<li>c) Verantwortlicher Daten nicht mehr benoetigt, Betroffener aber fuer Rechtsansprueche</li>
<li>d) Widerspruch nach Art. 21 eingelegt wurde (fuer die Dauer der Pruefung)</li>
</ul>
<h2>3. Frist</h2>
<p><strong>Unverzueglich</strong>, spaetestens innerhalb von <strong>14 Tagen</strong>.</p>
<h2>4. Prozessablauf</h2>
<pre class="mermaid">
graph TD
subgraph Betroffener
A1[Antrag auf Einschraenkung]
A5[Bestaetigung erhalten]
end
subgraph Sachbearbeitung
B1[Antrag erfassen + ID pruefen]
B2[Voraussetzung nach Art. 18 Abs. 1 pruefen]
B3{Berechtigt?}
end
subgraph IT/Fachabteilung
C1[Daten markieren/sperren]
C2[Verarbeitung einschraenken]
C3[Empfaenger benachrichtigen Art. 19]
end
subgraph DSB
D1[Dokumentation + Wiedervorlage]
end
A1 --> B1 --> B2 --> B3
B3 -- Nein --> A5
B3 -- Ja --> C1 --> C2 --> C3 --> D1 --> A5
</pre>
<h2>5. Erlaubte Verarbeitung bei Einschraenkung (Art. 18 Abs. 2)</h2>
<p>Eingeschraenkte Daten duerfen nur noch verarbeitet werden fuer:</p>
<ul>
<li>Speicherung</li>
<li>Mit Einwilligung der betroffenen Person</li>
<li>Zur Geltendmachung von Rechtsanspruechen</li>
<li>Zum Schutz der Rechte einer anderen Person</li>
<li>Aus Gruenden eines wichtigen oeffentlichen Interesses</li>
</ul>',
'["FIRMENNAME", "VERSION", "DATUM", "DSB_NAME"]'::jsonb,
NOW(), NOW()),
-- ============================================================================
-- Art. 19 DSGVO — Mitteilungspflicht
-- ============================================================================
(gen_random_uuid(), '__default__', 'dsr_process_art19',
'Prozessbeschreibung: Mitteilungspflicht (Art. 19 DSGVO)', 'de', 'published',
'<h1>Prozessbeschreibung: Mitteilungspflicht nach Art. 19 DSGVO</h1>
<p><strong>Verantwortliche Stelle:</strong> {{FIRMENNAME}}<br/>
<strong>Version:</strong> {{VERSION}}<br/>
<strong>Stand:</strong> {{DATUM}}<br/>
<strong>Genehmigt durch:</strong> {{DSB_NAME}}</p>
<h2>1. Zweck</h2>
<p>Art. 19 DSGVO verpflichtet den Verantwortlichen, alle Empfaenger, denen personenbezogene Daten offengelegt wurden, ueber jede Berichtigung (Art. 16), Loeschung (Art. 17) oder Einschraenkung (Art. 18) zu informieren — es sei denn, dies ist unverhaeltnismaessig.</p>
<h2>2. Rechtsgrundlage</h2>
<ul>
<li>Art. 19 DSGVO — Mitteilungspflicht im Zusammenhang mit der Berichtigung oder Loeschung personenbezogener Daten oder der Einschraenkung der Verarbeitung</li>
</ul>
<h2>3. Ausloeser</h2>
<p>Art. 19 wird automatisch ausgeloest bei:</p>
<ul>
<li>Erfolgreicher Berichtigung nach Art. 16</li>
<li>Erfolgreicher Loeschung nach Art. 17</li>
<li>Einschraenkung der Verarbeitung nach Art. 18</li>
</ul>
<h2>4. Prozessablauf</h2>
<pre class="mermaid">
graph TD
subgraph Ausloeser
A1[Berichtigung/Loeschung/Einschraenkung durchgefuehrt]
end
subgraph Sachbearbeitung
B1[Alle Empfaenger aus VVT identifizieren]
B2[Auftragsverarbeiter identifizieren]
B3{Mitteilung verhaeltnismaessig?}
B4[Mitteilung an jeden Empfaenger senden]
B5[Unverhaeltnismaessigkeit dokumentieren]
end
subgraph DSB
C1[Mitteilung dokumentieren]
C2[Betroffenen ueber Empfaenger informieren auf Verlangen]
end
A1 --> B1 --> B2 --> B3
B3 -- Nein --> B5 --> C1
B3 -- Ja --> B4 --> C1 --> C2
</pre>
<h2>5. Pflicht zur Auskunft ueber Empfaenger</h2>
<p>Der Verantwortliche muss dem Betroffenen auf Verlangen die Empfaenger mitteilen, an die die Daten offengelegt wurden.</p>',
'["FIRMENNAME", "VERSION", "DATUM", "DSB_NAME"]'::jsonb,
NOW(), NOW()),
-- ============================================================================
-- Art. 20 DSGVO — Recht auf Datenuebertragbarkeit
-- ============================================================================
(gen_random_uuid(), '__default__', 'dsr_process_art20',
'Prozessbeschreibung: Datenuebertragbarkeit (Art. 20 DSGVO)', 'de', 'published',
'<h1>Prozessbeschreibung: Recht auf Datenuebertragbarkeit nach Art. 20 DSGVO</h1>
<p><strong>Verantwortliche Stelle:</strong> {{FIRMENNAME}}<br/>
<strong>Version:</strong> {{VERSION}}<br/>
<strong>Stand:</strong> {{DATUM}}<br/>
<strong>Genehmigt durch:</strong> {{DSB_NAME}}</p>
<h2>1. Zweck</h2>
<p>Regelung des Ablaufs bei Antraegen auf Datenuebertragbarkeit. Die betroffene Person hat das Recht, die sie betreffenden personenbezogenen Daten in einem strukturierten, gaengigen und maschinenlesbaren Format zu erhalten.</p>
<h2>2. Rechtsgrundlage und Voraussetzungen</h2>
<ul>
<li>Art. 20 DSGVO — Recht auf Datenuebertragbarkeit</li>
<li>Gilt nur fuer Daten, die auf Einwilligung (Art. 6 Abs. 1 lit. a) oder Vertrag (Art. 6 Abs. 1 lit. b) basieren</li>
<li>Gilt nur fuer automatisiert verarbeitete Daten</li>
<li>Nur vom Betroffenen selbst bereitgestellte Daten</li>
</ul>
<h2>3. Frist</h2>
<p><strong>30 Tage</strong> nach Eingang der Anfrage.</p>
<h2>4. Prozessablauf</h2>
<pre class="mermaid">
graph TD
subgraph Betroffener
A1[Antrag auf Datenuebertragung]
A5[Daten erhalten / Direktuebertragung bestaetigt]
end
subgraph Sachbearbeitung
B1[Antrag erfassen + ID pruefen]
B2[Rechtsgrundlage pruefen - Einwilligung oder Vertrag?]
B3{Voraussetzungen erfuellt?}
end
subgraph IT
C1[Daten identifizieren und extrahieren]
C2[In maschinenlesbares Format konvertieren - JSON/CSV/XML]
C3{Direktuebertragung gewuenscht?}
C4[Daten an Betroffenen uebergeben]
C5[Daten an anderen Verantwortlichen uebertragen]
end
A1 --> B1 --> B2 --> B3
B3 -- Nein --> A5
B3 -- Ja --> C1 --> C2 --> C3
C3 -- Nein --> C4 --> A5
C3 -- Ja --> C5 --> A5
</pre>
<h2>5. Exportformate</h2>
<ul>
<li>JSON (bevorzugt)</li>
<li>CSV (fuer tabellarische Daten)</li>
<li>XML (bei Bedarf)</li>
</ul>',
'["FIRMENNAME", "VERSION", "DATUM", "DSB_NAME"]'::jsonb,
NOW(), NOW()),
-- ============================================================================
-- Art. 21 DSGVO — Widerspruchsrecht
-- ============================================================================
(gen_random_uuid(), '__default__', 'dsr_process_art21',
'Prozessbeschreibung: Widerspruchsrecht (Art. 21 DSGVO)', 'de', 'published',
'<h1>Prozessbeschreibung: Widerspruchsrecht nach Art. 21 DSGVO</h1>
<p><strong>Verantwortliche Stelle:</strong> {{FIRMENNAME}}<br/>
<strong>Version:</strong> {{VERSION}}<br/>
<strong>Stand:</strong> {{DATUM}}<br/>
<strong>Genehmigt durch:</strong> {{DSB_NAME}}</p>
<h2>1. Zweck</h2>
<p>Regelung des Ablaufs bei Widerspruechen gegen die Verarbeitung personenbezogener Daten nach Art. 21 DSGVO.</p>
<h2>2. Rechtsgrundlage</h2>
<ul>
<li>Art. 21 Abs. 1 DSGVO — Allgemeines Widerspruchsrecht (bei Verarbeitung nach Art. 6 Abs. 1 lit. e oder f)</li>
<li>Art. 21 Abs. 2 DSGVO — Widerspruch gegen Direktwerbung (absolutes Recht, keine Abwaegung)</li>
<li>Art. 21 Abs. 6 DSGVO — Widerspruch gegen wissenschaftliche/historische Forschung</li>
</ul>
<h2>3. Frist</h2>
<p><strong>30 Tage</strong> nach Eingang des Widerspruchs.</p>
<h2>4. Prozessablauf</h2>
<pre class="mermaid">
graph TD
subgraph Betroffener
A1[Widerspruch einlegen]
A6[Ergebnis erhalten]
end
subgraph Sachbearbeitung
B1[Widerspruch erfassen + ID pruefen]
B2{Art des Widerspruchs?}
end
subgraph Fall: Direktwerbung
C1[Verarbeitung fuer Direktwerbung SOFORT einstellen]
C2[Bestaetigung senden]
end
subgraph Fall: Allgemeiner Widerspruch
D1[Zwingende schutzwuerdige Gruende pruefen]
D2{Zwingende Gruende vorhanden?}
D3[Verarbeitung einstellen]
D4[Widerspruch ablehnen mit Begruendung]
end
A1 --> B1 --> B2
B2 -- Direktwerbung Art. 21 Abs. 2 --> C1 --> C2 --> A6
B2 -- Allgemein Art. 21 Abs. 1 --> D1 --> D2
D2 -- Nein --> D3 --> A6
D2 -- Ja --> D4 --> A6
</pre>
<h2>5. Besonderheit: Widerspruch gegen Direktwerbung</h2>
<p><strong>Absolutes Recht — keine Interessenabwaegung erforderlich.</strong> Bei Widerspruch gegen Direktwerbung muss die Verarbeitung sofort eingestellt werden. Dies umfasst auch Profiling, soweit es mit Direktwerbung zusammenhaengt.</p>
<h2>6. Interessenabwaegung bei allgemeinem Widerspruch</h2>
<p>Bei Widerspruch nach Art. 21 Abs. 1 muss der Verantwortliche nachweisen, dass zwingende schutzwuerdige Gruende fuer die Verarbeitung vorliegen, die die Interessen des Betroffenen ueberwiegen.</p>',
'["FIRMENNAME", "VERSION", "DATUM", "DSB_NAME"]'::jsonb,
NOW(), NOW())
ON CONFLICT DO NOTHING;