fix(admin-v2): Restore complete admin-v2 application
The admin-v2 application was incomplete in the repository. This commit restores all missing components: - Admin pages (76 pages): dashboard, ai, compliance, dsgvo, education, infrastructure, communication, development, onboarding, rbac - SDK pages (45 pages): tom, dsfa, vvt, loeschfristen, einwilligungen, vendor-compliance, tom-generator, dsr, and more - Developer portal (25 pages): API docs, SDK guides, frameworks - All components, lib files, hooks, and types - Updated package.json with all dependencies The issue was caused by incomplete initial repository state - the full admin-v2 codebase existed in backend/admin-v2 and docs-src/admin-v2 but was never fully synced to the main admin-v2 directory. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
643
admin-v2/app/(admin)/dsgvo/advisory-board/documentation/page.tsx
Normal file
643
admin-v2/app/(admin)/dsgvo/advisory-board/documentation/page.tsx
Normal file
@@ -0,0 +1,643 @@
|
||||
'use client'
|
||||
|
||||
/**
|
||||
* UCCA - System Documentation Page
|
||||
*
|
||||
* Displays architecture documentation, auditor information,
|
||||
* and transparency data for the UCCA compliance system.
|
||||
*/
|
||||
|
||||
import { useState, useEffect } from 'react'
|
||||
import { PagePurpose } from '@/components/common/PagePurpose'
|
||||
import Link from 'next/link'
|
||||
|
||||
// ============================================================================
|
||||
// Types
|
||||
// ============================================================================
|
||||
|
||||
type DocTab = 'overview' | 'architecture' | 'auditor' | 'rules' | 'legal-corpus'
|
||||
|
||||
interface Rule {
|
||||
code: string
|
||||
category: string
|
||||
title: string
|
||||
description: string
|
||||
severity: string
|
||||
gdpr_ref: string
|
||||
rationale?: string
|
||||
risk_add?: number
|
||||
}
|
||||
|
||||
interface Pattern {
|
||||
id: string
|
||||
title: string
|
||||
description: string
|
||||
benefit?: string
|
||||
effort?: string
|
||||
risk_reduction?: number
|
||||
}
|
||||
|
||||
interface Control {
|
||||
id: string
|
||||
title: string
|
||||
description: string
|
||||
gdpr_ref?: string
|
||||
effort?: string
|
||||
}
|
||||
|
||||
interface LegalCorpusStats {
|
||||
total_chunks: number
|
||||
regulations: {
|
||||
code: string
|
||||
name: string
|
||||
chunks: number
|
||||
type: string
|
||||
}[]
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// API Configuration
|
||||
// ============================================================================
|
||||
|
||||
const API_BASE = process.env.NEXT_PUBLIC_SDK_API_URL || 'https://macmini:8090'
|
||||
|
||||
// ============================================================================
|
||||
// Main Component
|
||||
// ============================================================================
|
||||
|
||||
export default function DocumentationPage() {
|
||||
const [activeTab, setActiveTab] = useState<DocTab>('overview')
|
||||
const [rules, setRules] = useState<Rule[]>([])
|
||||
const [patterns, setPatterns] = useState<Pattern[]>([])
|
||||
const [controls, setControls] = useState<Control[]>([])
|
||||
const [policyVersion, setPolicyVersion] = useState<string>('')
|
||||
const [legalStats, setLegalStats] = useState<LegalCorpusStats | null>(null)
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
// Fetch rules, patterns, and controls for transparency
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
setLoading(true)
|
||||
try {
|
||||
// Fetch rules
|
||||
const rulesRes = await fetch(`${API_BASE}/sdk/v1/ucca/rules`, {
|
||||
headers: { 'X-Tenant-ID': '00000000-0000-0000-0000-000000000000' }
|
||||
})
|
||||
if (rulesRes.ok) {
|
||||
const rulesData = await rulesRes.json()
|
||||
setRules(rulesData.rules || [])
|
||||
setPolicyVersion(rulesData.policy_version || '')
|
||||
}
|
||||
|
||||
// Fetch patterns
|
||||
const patternsRes = await fetch(`${API_BASE}/sdk/v1/ucca/patterns`, {
|
||||
headers: { 'X-Tenant-ID': '00000000-0000-0000-0000-000000000000' }
|
||||
})
|
||||
if (patternsRes.ok) {
|
||||
const patternsData = await patternsRes.json()
|
||||
setPatterns(patternsData.patterns || [])
|
||||
}
|
||||
|
||||
// Fetch controls
|
||||
const controlsRes = await fetch(`${API_BASE}/sdk/v1/ucca/controls`, {
|
||||
headers: { 'X-Tenant-ID': '00000000-0000-0000-0000-000000000000' }
|
||||
})
|
||||
if (controlsRes.ok) {
|
||||
const controlsData = await controlsRes.json()
|
||||
setControls(controlsData.controls || [])
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch documentation data:', error)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
fetchData()
|
||||
}, [])
|
||||
|
||||
// ============================================================================
|
||||
// Tab Content Renderers
|
||||
// ============================================================================
|
||||
|
||||
const renderOverview = () => (
|
||||
<div className="space-y-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<div className="text-4xl mb-3">📋</div>
|
||||
<h3 className="font-semibold text-slate-800 mb-2">Deterministische Regeln</h3>
|
||||
<div className="text-3xl font-bold text-primary-600">{rules.length}</div>
|
||||
<p className="text-sm text-slate-500 mt-2">
|
||||
Alle Entscheidungen basieren auf transparenten, nachvollziehbaren Regeln.
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<div className="text-4xl mb-3">🏗️</div>
|
||||
<h3 className="font-semibold text-slate-800 mb-2">Architektur-Patterns</h3>
|
||||
<div className="text-3xl font-bold text-green-600">{patterns.length}</div>
|
||||
<p className="text-sm text-slate-500 mt-2">
|
||||
Best-Practice-Loesungen fuer datenschutzkonforme KI-Systeme.
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<div className="text-4xl mb-3">🛡️</div>
|
||||
<h3 className="font-semibold text-slate-800 mb-2">Compliance-Kontrollen</h3>
|
||||
<div className="text-3xl font-bold text-blue-600">{controls.length}</div>
|
||||
<p className="text-sm text-slate-500 mt-2">
|
||||
Technische und organisatorische Massnahmen.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-gradient-to-br from-primary-50 to-blue-50 rounded-xl border border-primary-200 p-6">
|
||||
<h3 className="font-semibold text-primary-800 text-lg mb-4">Was ist UCCA?</h3>
|
||||
<div className="prose prose-sm max-w-none text-slate-700">
|
||||
<p>
|
||||
<strong>UCCA (Use-Case Compliance & Feasibility Advisor)</strong> ist ein deterministisches
|
||||
Compliance-Pruefwerkzeug, das Organisationen bei der Bewertung geplanter KI-Anwendungsfaelle
|
||||
hinsichtlich ihrer datenschutzrechtlichen Zulaessigkeit unterstuetzt.
|
||||
</p>
|
||||
<h4 className="text-primary-700 mt-4">Kernprinzipien</h4>
|
||||
<ul className="space-y-2">
|
||||
<li>
|
||||
<strong>Determinismus:</strong> Alle Entscheidungen basieren auf transparenten Regeln.
|
||||
Die KI trifft KEINE autonomen Entscheidungen.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Transparenz:</strong> Alle Regeln, Kontrollen und Patterns sind einsehbar.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Human-in-the-Loop:</strong> Kritische Entscheidungen erfordern immer
|
||||
menschliche Pruefung durch DSB oder Legal.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Rechtsgrundlage:</strong> Jede Regel referenziert konkrete DSGVO-Artikel.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-amber-50 border border-amber-200 rounded-xl p-6">
|
||||
<h3 className="font-semibold text-amber-800 mb-3 flex items-center gap-2">
|
||||
<span>⚠️</span>
|
||||
Wichtiger Hinweis zur KI-Nutzung
|
||||
</h3>
|
||||
<p className="text-amber-700">
|
||||
Das System verwendet KI (LLM) <strong>ausschliesslich zur Erklaerung</strong> bereits
|
||||
getroffener Regelentscheidungen. Die eigentliche Compliance-Bewertung erfolgt
|
||||
<strong> rein deterministisch</strong> durch die Policy Engine. BLOCK-Entscheidungen
|
||||
koennen NICHT durch KI ueberschrieben werden.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const renderArchitecture = () => (
|
||||
<div className="space-y-6">
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
||||
<h3 className="font-semibold text-slate-800 text-lg mb-4">Systemarchitektur</h3>
|
||||
|
||||
{/* ASCII Diagram */}
|
||||
<div className="bg-slate-900 text-green-400 p-6 rounded-lg font-mono text-sm overflow-x-auto">
|
||||
<pre>{`
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ Frontend (Next.js) │
|
||||
│ admin-v2:3000/dsgvo/advisory-board │
|
||||
└───────────────────────────────┬─────────────────────────────────────┘
|
||||
│ HTTPS
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ AI Compliance SDK (Go) │
|
||||
│ Port 8090 │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Policy Engine │ │
|
||||
│ │ ┌───────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ YAML-basierte Regeln (ucca_policy_v1.yaml) │ │ │
|
||||
│ │ │ ~45 Regeln in 7 Kategorien │ │ │
|
||||
│ │ │ Deterministisch - Kein LLM in Entscheidungslogik │ │ │
|
||||
│ │ └───────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │ │
|
||||
│ │ ▼ │ │
|
||||
│ │ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │ │
|
||||
│ │ │ Controls │ │ Patterns │ │ Examples │ │ │
|
||||
│ │ │ Library │ │ Library │ │ Library │ │ │
|
||||
│ │ └────────────────┘ └────────────────┘ └────────────────┘ │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────┐ ┌──────────────────┐ │
|
||||
│ │ LLM Integration │ │ Legal RAG │──────┐ │
|
||||
│ │ (nur Explain) │ │ Client │ │ │
|
||||
│ └──────────────────┘ └──────────────────┘ │ │
|
||||
└─────────────────────────────┬────────────────────┼──────────────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ Datenschicht │
|
||||
│ ┌────────────────────┐ ┌────────────────────┐ │
|
||||
│ │ PostgreSQL │ │ Qdrant │ │
|
||||
│ │ (Assessments, │ │ (Legal Corpus, │ │
|
||||
│ │ Escalations) │ │ 2,274 Chunks) │ │
|
||||
│ └────────────────────┘ └────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
`}</pre>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="p-4 bg-blue-50 rounded-lg border border-blue-200">
|
||||
<h4 className="font-medium text-blue-800 mb-2">Datenfluss</h4>
|
||||
<ol className="text-sm text-blue-700 list-decimal list-inside space-y-1">
|
||||
<li>Benutzer beschreibt Use Case im Frontend</li>
|
||||
<li>Policy Engine evaluiert gegen alle Regeln</li>
|
||||
<li>Ergebnis mit Controls + Patterns zurueck</li>
|
||||
<li>Optional: LLM erklaert das Ergebnis</li>
|
||||
<li>Bei Risiko: Automatische Eskalation</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div className="p-4 bg-green-50 rounded-lg border border-green-200">
|
||||
<h4 className="font-medium text-green-800 mb-2">Sicherheitsmerkmale</h4>
|
||||
<ul className="text-sm text-green-700 list-disc list-inside space-y-1">
|
||||
<li>TLS 1.3 Verschluesselung</li>
|
||||
<li>RBAC mit Tenant-Isolation</li>
|
||||
<li>JWT-basierte Authentifizierung</li>
|
||||
<li>Audit-Trail aller Aktionen</li>
|
||||
<li>Keine Rohtext-Speicherung (nur Hash)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
||||
<h3 className="font-semibold text-slate-800 text-lg mb-4">Eskalations-Workflow</h3>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-sm">
|
||||
<thead>
|
||||
<tr className="border-b border-slate-200">
|
||||
<th className="text-left py-2 px-3 font-medium text-slate-600">Level</th>
|
||||
<th className="text-left py-2 px-3 font-medium text-slate-600">Ausloeser</th>
|
||||
<th className="text-left py-2 px-3 font-medium text-slate-600">Pruefer</th>
|
||||
<th className="text-left py-2 px-3 font-medium text-slate-600">SLA</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr className="border-b border-slate-100 bg-green-50">
|
||||
<td className="py-2 px-3 font-medium text-green-700">E0</td>
|
||||
<td className="py-2 px-3 text-slate-600">Nur INFO-Regeln, Risiko < 20</td>
|
||||
<td className="py-2 px-3 text-slate-600">Automatisch</td>
|
||||
<td className="py-2 px-3 text-slate-600">-</td>
|
||||
</tr>
|
||||
<tr className="border-b border-slate-100 bg-yellow-50">
|
||||
<td className="py-2 px-3 font-medium text-yellow-700">E1</td>
|
||||
<td className="py-2 px-3 text-slate-600">WARN-Regeln, Risiko 20-40</td>
|
||||
<td className="py-2 px-3 text-slate-600">Team-Lead</td>
|
||||
<td className="py-2 px-3 text-slate-600">24h / 72h</td>
|
||||
</tr>
|
||||
<tr className="border-b border-slate-100 bg-orange-50">
|
||||
<td className="py-2 px-3 font-medium text-orange-700">E2</td>
|
||||
<td className="py-2 px-3 text-slate-600">Art. 9 Daten, DSFA empfohlen, Risiko 40-60</td>
|
||||
<td className="py-2 px-3 text-slate-600">DSB</td>
|
||||
<td className="py-2 px-3 text-slate-600">8h / 48h</td>
|
||||
</tr>
|
||||
<tr className="bg-red-50">
|
||||
<td className="py-2 px-3 font-medium text-red-700">E3</td>
|
||||
<td className="py-2 px-3 text-slate-600">BLOCK-Regeln, Art. 22, Risiko > 60</td>
|
||||
<td className="py-2 px-3 text-slate-600">DSB + Legal</td>
|
||||
<td className="py-2 px-3 text-slate-600">4h / 24h</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const renderAuditorInfo = () => (
|
||||
<div className="space-y-6">
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
||||
<h3 className="font-semibold text-slate-800 text-lg mb-4">
|
||||
Dokumentation fuer externe Auditoren
|
||||
</h3>
|
||||
<p className="text-slate-600 mb-4">
|
||||
Diese Dokumentation erfuellt die Anforderungen nach Art. 30 DSGVO (Verzeichnis von
|
||||
Verarbeitungstaetigkeiten) und dient als Grundlage fuer Audits nach Art. 32 DSGVO.
|
||||
</p>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="p-4 bg-slate-50 rounded-lg border border-slate-200">
|
||||
<h4 className="font-medium text-slate-800 mb-2">1. Zweck des Systems</h4>
|
||||
<p className="text-sm text-slate-600">
|
||||
UCCA ist ein Compliance-Pruefwerkzeug zur Bewertung geplanter KI-Anwendungsfaelle
|
||||
hinsichtlich ihrer datenschutzrechtlichen Zulaessigkeit. Es unterstuetzt Organisationen
|
||||
bei der Einhaltung der DSGVO und des AI Acts.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="p-4 bg-slate-50 rounded-lg border border-slate-200">
|
||||
<h4 className="font-medium text-slate-800 mb-2">2. Rechtsgrundlage</h4>
|
||||
<ul className="text-sm text-slate-600 list-disc list-inside space-y-1">
|
||||
<li><strong>Art. 6 Abs. 1 lit. c DSGVO</strong> - Erfuellung rechtlicher Verpflichtungen</li>
|
||||
<li><strong>Art. 6 Abs. 1 lit. f DSGVO</strong> - Berechtigte Interessen (Compliance-Management)</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="p-4 bg-slate-50 rounded-lg border border-slate-200">
|
||||
<h4 className="font-medium text-slate-800 mb-2">3. Verarbeitete Datenkategorien</h4>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-sm mt-2">
|
||||
<thead>
|
||||
<tr className="border-b border-slate-200">
|
||||
<th className="text-left py-2 px-2 font-medium text-slate-600">Kategorie</th>
|
||||
<th className="text-left py-2 px-2 font-medium text-slate-600">Speicherung</th>
|
||||
<th className="text-left py-2 px-2 font-medium text-slate-600">Aufbewahrung</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="text-slate-600">
|
||||
<tr className="border-b border-slate-100">
|
||||
<td className="py-2 px-2">Use-Case-Beschreibung</td>
|
||||
<td className="py-2 px-2">Nur Hash (SHA-256)</td>
|
||||
<td className="py-2 px-2">10 Jahre</td>
|
||||
</tr>
|
||||
<tr className="border-b border-slate-100">
|
||||
<td className="py-2 px-2">Bewertungsergebnis</td>
|
||||
<td className="py-2 px-2">Vollstaendig</td>
|
||||
<td className="py-2 px-2">10 Jahre</td>
|
||||
</tr>
|
||||
<tr className="border-b border-slate-100">
|
||||
<td className="py-2 px-2">Audit-Trail</td>
|
||||
<td className="py-2 px-2">Vollstaendig</td>
|
||||
<td className="py-2 px-2">10 Jahre</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="py-2 px-2">Eskalations-Historie</td>
|
||||
<td className="py-2 px-2">Vollstaendig</td>
|
||||
<td className="py-2 px-2">10 Jahre</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-4 bg-slate-50 rounded-lg border border-slate-200">
|
||||
<h4 className="font-medium text-slate-800 mb-2">4. Keine autonomen KI-Entscheidungen</h4>
|
||||
<p className="text-sm text-slate-600">
|
||||
Das System trifft <strong>KEINE automatisierten Einzelentscheidungen</strong> im Sinne
|
||||
von Art. 22 DSGVO, da:
|
||||
</p>
|
||||
<ul className="text-sm text-slate-600 list-disc list-inside mt-2 space-y-1">
|
||||
<li>Regelauswertung ist keine rechtlich bindende Entscheidung</li>
|
||||
<li>Alle kritischen Faelle werden menschlich geprueft (E1-E3)</li>
|
||||
<li>BLOCK-Entscheidungen erfordern immer menschliche Freigabe</li>
|
||||
<li>Betroffene haben Anfechtungsmoeglichkeit ueber Eskalation</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="p-4 bg-green-50 rounded-lg border border-green-200">
|
||||
<h4 className="font-medium text-green-800 mb-2">5. Technische und Organisatorische Massnahmen</h4>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm">
|
||||
<div>
|
||||
<strong className="text-green-700">Vertraulichkeit</strong>
|
||||
<ul className="text-green-700 list-disc list-inside mt-1">
|
||||
<li>RBAC mit Tenant-Isolation</li>
|
||||
<li>TLS 1.3 Verschluesselung</li>
|
||||
<li>AES-256 at rest</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<strong className="text-green-700">Integritaet</strong>
|
||||
<ul className="text-green-700 list-disc list-inside mt-1">
|
||||
<li>Unveraenderlicher Audit-Trail</li>
|
||||
<li>Policy-Versionierung</li>
|
||||
<li>Input-Validierung</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-4">
|
||||
<a
|
||||
href="/api/ucca/documentation/architecture.md"
|
||||
download
|
||||
className="flex-1 p-4 bg-primary-50 rounded-lg border border-primary-200 text-center hover:bg-primary-100"
|
||||
>
|
||||
<div className="text-2xl mb-2">📄</div>
|
||||
<div className="font-medium text-primary-800">ARCHITECTURE.md herunterladen</div>
|
||||
<div className="text-sm text-primary-600">Technische Dokumentation</div>
|
||||
</a>
|
||||
<a
|
||||
href="/api/ucca/documentation/auditor.md"
|
||||
download
|
||||
className="flex-1 p-4 bg-green-50 rounded-lg border border-green-200 text-center hover:bg-green-100"
|
||||
>
|
||||
<div className="text-2xl mb-2">📋</div>
|
||||
<div className="font-medium text-green-800">AUDITOR_DOCUMENTATION.md</div>
|
||||
<div className="text-sm text-green-600">Art. 30 DSGVO konform</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const renderRulesTab = () => (
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h3 className="font-semibold text-slate-800 text-lg">Regel-Katalog</h3>
|
||||
<p className="text-sm text-slate-500">Policy Version: {policyVersion}</p>
|
||||
</div>
|
||||
<div className="text-sm text-slate-500">
|
||||
{rules.length} Regeln insgesamt
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{loading ? (
|
||||
<div className="text-center py-8 text-slate-500">Lade Regeln...</div>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
{/* Group by category */}
|
||||
{Array.from(new Set(rules.map(r => r.category))).map(category => (
|
||||
<div key={category} className="bg-white rounded-xl border border-slate-200 overflow-hidden">
|
||||
<div className="px-4 py-3 bg-slate-50 border-b border-slate-200">
|
||||
<h4 className="font-medium text-slate-800">{category}</h4>
|
||||
<p className="text-xs text-slate-500">
|
||||
{rules.filter(r => r.category === category).length} Regeln
|
||||
</p>
|
||||
</div>
|
||||
<div className="divide-y divide-slate-100">
|
||||
{rules.filter(r => r.category === category).map(rule => (
|
||||
<div key={rule.code} className="p-4">
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-mono text-sm text-slate-500">{rule.code}</span>
|
||||
<span className={`text-xs px-2 py-0.5 rounded ${
|
||||
rule.severity === 'BLOCK' ? 'bg-red-100 text-red-700' :
|
||||
rule.severity === 'WARN' ? 'bg-yellow-100 text-yellow-700' :
|
||||
'bg-blue-100 text-blue-700'
|
||||
}`}>
|
||||
{rule.severity}
|
||||
</span>
|
||||
</div>
|
||||
<div className="font-medium text-slate-800 mt-1">{rule.title}</div>
|
||||
<div className="text-sm text-slate-600 mt-1">{rule.description}</div>
|
||||
{rule.gdpr_ref && (
|
||||
<div className="text-xs text-slate-500 mt-2">{rule.gdpr_ref}</div>
|
||||
)}
|
||||
</div>
|
||||
{rule.risk_add && (
|
||||
<div className="text-sm font-medium text-red-600">
|
||||
+{rule.risk_add}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
const renderLegalCorpus = () => (
|
||||
<div className="space-y-6">
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
||||
<h3 className="font-semibold text-slate-800 text-lg mb-4">Legal RAG Corpus</h3>
|
||||
<p className="text-slate-600 mb-4">
|
||||
Das System verwendet einen semantischen Suchindex mit 2.274 Chunks aus 19 EU-Regulierungen
|
||||
fuer rechtsgrundlagenbasierte Erklaerungen.
|
||||
</p>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="p-4 bg-blue-50 rounded-lg border border-blue-200">
|
||||
<h4 className="font-medium text-blue-800 mb-2">Indexierte Regulierungen</h4>
|
||||
<ul className="text-sm text-blue-700 space-y-1">
|
||||
<li>DSGVO - Datenschutz-Grundverordnung</li>
|
||||
<li>AI Act - EU KI-Verordnung</li>
|
||||
<li>NIS2 - Cybersicherheits-Richtlinie</li>
|
||||
<li>CRA - Cyber Resilience Act</li>
|
||||
<li>Data Act - Datengesetz</li>
|
||||
<li>DSA/DMA - Digital Services/Markets Act</li>
|
||||
<li>DPF - EU-US Data Privacy Framework</li>
|
||||
<li>BSI-TR-03161 - Digitale Identitaeten</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="p-4 bg-green-50 rounded-lg border border-green-200">
|
||||
<h4 className="font-medium text-green-800 mb-2">RAG-Funktionalitaet</h4>
|
||||
<ul className="text-sm text-green-700 space-y-1">
|
||||
<li>Hybride Suche (Dense + BM25)</li>
|
||||
<li>Semantisches Chunking</li>
|
||||
<li>Cross-Encoder Reranking</li>
|
||||
<li>Artikel-Referenz-Extraktion</li>
|
||||
<li>Mehrsprachig (DE/EN)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
||||
<h3 className="font-semibold text-slate-800 mb-4">Verwendung im System</h3>
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="w-8 h-8 bg-primary-100 text-primary-700 rounded-full flex items-center justify-center flex-shrink-0">
|
||||
1
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-medium text-slate-800">Benutzer fordert Erklaerung an</div>
|
||||
<div className="text-sm text-slate-600">
|
||||
Nach der Bewertung kann eine LLM-basierte Erklaerung generiert werden.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="w-8 h-8 bg-primary-100 text-primary-700 rounded-full flex items-center justify-center flex-shrink-0">
|
||||
2
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-medium text-slate-800">Legal RAG Client sucht relevante Artikel</div>
|
||||
<div className="text-sm text-slate-600">
|
||||
Basierend auf den ausgeloesten Regeln werden passende Gesetzestexte gefunden.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="w-8 h-8 bg-primary-100 text-primary-700 rounded-full flex items-center justify-center flex-shrink-0">
|
||||
3
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-medium text-slate-800">LLM generiert Erklaerung mit Rechtsgrundlage</div>
|
||||
<div className="text-sm text-slate-600">
|
||||
Die Erklaerung referenziert konkrete Artikel aus DSGVO, AI Act etc.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
// ============================================================================
|
||||
// Tabs Configuration
|
||||
// ============================================================================
|
||||
|
||||
const tabs: { id: DocTab; label: string; icon: string }[] = [
|
||||
{ id: 'overview', label: 'Uebersicht', icon: '🏠' },
|
||||
{ id: 'architecture', label: 'Architektur', icon: '🏗️' },
|
||||
{ id: 'auditor', label: 'Fuer Auditoren', icon: '📋' },
|
||||
{ id: 'rules', label: 'Regel-Katalog', icon: '📜' },
|
||||
{ id: 'legal-corpus', label: 'Legal RAG', icon: '⚖️' },
|
||||
]
|
||||
|
||||
// ============================================================================
|
||||
// Main Render
|
||||
// ============================================================================
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<PagePurpose
|
||||
title="System-Dokumentation"
|
||||
purpose="Transparente Dokumentation des UCCA-Systems fuer Entwickler, Auditoren und Datenschutzbeauftragte. Alle Regeln, Kontrollen und Architektur-Details sind hier einsehbar."
|
||||
audience={['Entwickler', 'DSB', 'Externe Auditoren', 'Rechtsabteilung']}
|
||||
gdprArticles={['Art. 30', 'Art. 32', 'Art. 35']}
|
||||
collapsible={true}
|
||||
defaultCollapsed={true}
|
||||
/>
|
||||
<Link
|
||||
href="/dsgvo/advisory-board"
|
||||
className="px-4 py-2 text-sm text-slate-600 hover:text-slate-800 border border-slate-200 rounded-lg hover:bg-slate-50"
|
||||
>
|
||||
← Zurueck zum Advisory Board
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Tab Navigation */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 shadow-sm overflow-hidden">
|
||||
<div className="flex border-b border-slate-200 overflow-x-auto">
|
||||
{tabs.map(tab => (
|
||||
<button
|
||||
key={tab.id}
|
||||
onClick={() => setActiveTab(tab.id)}
|
||||
className={`flex items-center gap-2 px-4 py-3 text-sm font-medium whitespace-nowrap transition-colors ${
|
||||
activeTab === tab.id
|
||||
? 'text-primary-600 border-b-2 border-primary-600 bg-primary-50'
|
||||
: 'text-slate-600 hover:text-slate-800 hover:bg-slate-50'
|
||||
}`}
|
||||
>
|
||||
<span>{tab.icon}</span>
|
||||
{tab.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="p-6">
|
||||
{activeTab === 'overview' && renderOverview()}
|
||||
{activeTab === 'architecture' && renderArchitecture()}
|
||||
{activeTab === 'auditor' && renderAuditorInfo()}
|
||||
{activeTab === 'rules' && renderRulesTab()}
|
||||
{activeTab === 'legal-corpus' && renderLegalCorpus()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
992
admin-v2/app/(admin)/dsgvo/advisory-board/legal-metadata.ts
Normal file
992
admin-v2/app/(admin)/dsgvo/advisory-board/legal-metadata.ts
Normal file
@@ -0,0 +1,992 @@
|
||||
/**
|
||||
* UCCA Legal Metadata - Kompositorisches Bewertungssystem
|
||||
*
|
||||
* Jedes Feld trägt seine eigene Rechtsgrundlage.
|
||||
* Das Ergebnis ist die Aggregation aller ausgewählten Felder.
|
||||
* Bei Problemen werden Lösungsvorschläge angezeigt.
|
||||
*/
|
||||
|
||||
// ============================================================================
|
||||
// Types
|
||||
// ============================================================================
|
||||
|
||||
export interface LegalReference {
|
||||
article: string // z.B. "Art. 9 DSGVO"
|
||||
title: string // z.B. "Besondere Kategorien personenbezogener Daten"
|
||||
relevance: string // Warum relevant für dieses Feld
|
||||
}
|
||||
|
||||
export interface RequiredControl {
|
||||
id: string
|
||||
title: string
|
||||
description: string
|
||||
effort: 'low' | 'medium' | 'high'
|
||||
}
|
||||
|
||||
export interface FieldMetadata {
|
||||
// Identifikation
|
||||
id: string
|
||||
label: string
|
||||
labelSimple: string // Einfache Sprache
|
||||
|
||||
// Rechtliche Einordnung
|
||||
legalRefs: LegalReference[]
|
||||
|
||||
// Risikobewertung
|
||||
riskScore: number // 0-30 pro Feld
|
||||
severity: 'INFO' | 'WARN' | 'BLOCK'
|
||||
|
||||
// Erforderliche Maßnahmen wenn ausgewählt
|
||||
requiredControls: string[]
|
||||
|
||||
// Erklärungen
|
||||
explanation: string // Fachsprache
|
||||
explanationSimple: string // Einfache Sprache
|
||||
|
||||
// Hinweis für Nutzer
|
||||
userHint?: string
|
||||
}
|
||||
|
||||
export interface ProblemSolution {
|
||||
id: string
|
||||
title: string
|
||||
description: string
|
||||
// Was ändert sich wenn Lösung akzeptiert wird
|
||||
removes_fields?: string[] // Diese Felder werden "entschärft"
|
||||
adds_controls?: string[] // Diese Kontrollen werden hinzugefügt
|
||||
new_risk_score?: number // Neuer Risiko-Beitrag (meist 0)
|
||||
effort: 'low' | 'medium' | 'high'
|
||||
// Frage an das Team
|
||||
team_question: string
|
||||
}
|
||||
|
||||
export interface Problem {
|
||||
id: string
|
||||
title: string
|
||||
description: string
|
||||
severity: 'WARN' | 'BLOCK'
|
||||
// Welche Feld-Kombination löst das Problem aus
|
||||
triggered_by: {
|
||||
all_of?: string[] // Alle müssen ausgewählt sein
|
||||
any_of?: string[] // Mindestens eins muss ausgewählt sein
|
||||
none_of?: string[] // Keins darf ausgewählt sein (z.B. fehlende Einwilligung)
|
||||
}
|
||||
// Rechtliche Grundlage
|
||||
legalRefs: LegalReference[]
|
||||
// Mögliche Lösungen
|
||||
solutions: ProblemSolution[]
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Erforderliche Kontrollen / Maßnahmen
|
||||
// ============================================================================
|
||||
|
||||
export const CONTROLS: Record<string, RequiredControl> = {
|
||||
explicit_consent: {
|
||||
id: 'explicit_consent',
|
||||
title: 'Ausdrückliche Einwilligung',
|
||||
description: 'Betroffene müssen aktiv und informiert einwilligen (Opt-in, keine vorausgefüllten Checkboxen).',
|
||||
effort: 'medium',
|
||||
},
|
||||
parental_consent: {
|
||||
id: 'parental_consent',
|
||||
title: 'Einwilligung der Erziehungsberechtigten',
|
||||
description: 'Bei Minderjährigen muss die Einwilligung der Eltern/Erziehungsberechtigten eingeholt werden.',
|
||||
effort: 'high',
|
||||
},
|
||||
age_verification: {
|
||||
id: 'age_verification',
|
||||
title: 'Altersverifikation',
|
||||
description: 'Mechanismus zur Prüfung des Alters der Nutzer implementieren.',
|
||||
effort: 'medium',
|
||||
},
|
||||
dsfa: {
|
||||
id: 'dsfa',
|
||||
title: 'Datenschutz-Folgenabschätzung (DSFA)',
|
||||
description: 'Formale DSFA nach Art. 35 DSGVO durchführen und dokumentieren.',
|
||||
effort: 'high',
|
||||
},
|
||||
human_in_the_loop: {
|
||||
id: 'human_in_the_loop',
|
||||
title: 'Menschliche Überprüfung (HITL)',
|
||||
description: 'Jede automatisierte Entscheidung muss von einem Menschen überprüft werden können.',
|
||||
effort: 'medium',
|
||||
},
|
||||
contestation_right: {
|
||||
id: 'contestation_right',
|
||||
title: 'Anfechtungsrecht',
|
||||
description: 'Betroffene müssen automatisierte Entscheidungen anfechten können.',
|
||||
effort: 'low',
|
||||
},
|
||||
data_minimization: {
|
||||
id: 'data_minimization',
|
||||
title: 'Datenminimierung',
|
||||
description: 'Nur die unbedingt notwendigen Daten erheben und verarbeiten.',
|
||||
effort: 'low',
|
||||
},
|
||||
anonymization: {
|
||||
id: 'anonymization',
|
||||
title: 'Anonymisierung',
|
||||
description: 'Personenbezogene Daten vor der Verarbeitung anonymisieren.',
|
||||
effort: 'medium',
|
||||
},
|
||||
pseudonymization: {
|
||||
id: 'pseudonymization',
|
||||
title: 'Pseudonymisierung',
|
||||
description: 'Direkte Identifikatoren durch Pseudonyme ersetzen.',
|
||||
effort: 'medium',
|
||||
},
|
||||
encryption: {
|
||||
id: 'encryption',
|
||||
title: 'Verschlüsselung',
|
||||
description: 'Daten bei Übertragung und Speicherung verschlüsseln.',
|
||||
effort: 'low',
|
||||
},
|
||||
access_logging: {
|
||||
id: 'access_logging',
|
||||
title: 'Zugriffs-Protokollierung',
|
||||
description: 'Alle Zugriffe auf personenbezogene Daten protokollieren.',
|
||||
effort: 'low',
|
||||
},
|
||||
retention_policy: {
|
||||
id: 'retention_policy',
|
||||
title: 'Löschkonzept',
|
||||
description: 'Automatische Löschung nach definierter Aufbewahrungsfrist.',
|
||||
effort: 'medium',
|
||||
},
|
||||
scc: {
|
||||
id: 'scc',
|
||||
title: 'Standardvertragsklauseln (SCC)',
|
||||
description: 'EU-Standardvertragsklauseln mit Drittland-Anbieter abschließen.',
|
||||
effort: 'medium',
|
||||
},
|
||||
tia: {
|
||||
id: 'tia',
|
||||
title: 'Transfer Impact Assessment',
|
||||
description: 'Bewertung der Datenschutzrisiken bei Drittlandtransfer.',
|
||||
effort: 'high',
|
||||
},
|
||||
purpose_limitation: {
|
||||
id: 'purpose_limitation',
|
||||
title: 'Zweckbindung dokumentieren',
|
||||
description: 'Verarbeitungszweck klar definieren und dokumentieren.',
|
||||
effort: 'low',
|
||||
},
|
||||
transparency: {
|
||||
id: 'transparency',
|
||||
title: 'Transparenz-Information',
|
||||
description: 'Betroffene über die Verarbeitung informieren (Datenschutzerklärung).',
|
||||
effort: 'low',
|
||||
},
|
||||
pixelization: {
|
||||
id: 'pixelization',
|
||||
title: 'Verpixelung/Unkenntlichmachung',
|
||||
description: 'Identifizierende Merkmale (Gesichter, Kennzeichen) automatisch verpixeln.',
|
||||
effort: 'medium',
|
||||
},
|
||||
no_training: {
|
||||
id: 'no_training',
|
||||
title: 'Kein KI-Training mit Daten',
|
||||
description: 'Daten dürfen nur für Inferenz, nicht für Training verwendet werden.',
|
||||
effort: 'low',
|
||||
},
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Feld-Metadaten: Datentypen
|
||||
// ============================================================================
|
||||
|
||||
export const DATA_TYPE_METADATA: Record<string, FieldMetadata> = {
|
||||
personal_data: {
|
||||
id: 'personal_data',
|
||||
label: 'Personenbezogene Daten',
|
||||
labelSimple: 'Namen, E-Mails, Adressen',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 4(1) DSGVO', title: 'Definition personenbezogener Daten', relevance: 'Grundlegende Definition' },
|
||||
{ article: 'Art. 6 DSGVO', title: 'Rechtmäßigkeit der Verarbeitung', relevance: 'Rechtsgrundlage erforderlich' },
|
||||
],
|
||||
riskScore: 10,
|
||||
severity: 'INFO',
|
||||
requiredControls: ['purpose_limitation', 'transparency'],
|
||||
explanation: 'Personenbezogene Daten erfordern eine Rechtsgrundlage nach Art. 6 DSGVO.',
|
||||
explanationSimple: 'Wenn Sie Daten verarbeiten, mit denen man Personen identifizieren kann, brauchen Sie einen guten Grund dafür.',
|
||||
},
|
||||
|
||||
article_9_data: {
|
||||
id: 'article_9_data',
|
||||
label: 'Besondere Kategorien (Art. 9)',
|
||||
labelSimple: 'Gesundheit, Religion, politische Meinung',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 9 DSGVO', title: 'Besondere Kategorien personenbezogener Daten', relevance: 'Grundsätzliches Verarbeitungsverbot' },
|
||||
{ article: 'Art. 9(2) DSGVO', title: 'Ausnahmen vom Verbot', relevance: 'Ausdrückliche Einwilligung oder andere Ausnahme erforderlich' },
|
||||
],
|
||||
riskScore: 25,
|
||||
severity: 'WARN',
|
||||
requiredControls: ['explicit_consent', 'dsfa', 'encryption'],
|
||||
explanation: 'Besondere Kategorien personenbezogener Daten sind grundsätzlich verboten. Ausnahmen nur bei ausdrücklicher Einwilligung oder anderen Art. 9(2) Gründen.',
|
||||
explanationSimple: 'Gesundheitsdaten, religiöse Überzeugungen und ähnlich sensible Daten dürfen nur in Ausnahmefällen verarbeitet werden.',
|
||||
userHint: '⚠️ Hohes Risiko - DSFA wahrscheinlich erforderlich',
|
||||
},
|
||||
|
||||
minor_data: {
|
||||
id: 'minor_data',
|
||||
label: 'Daten von Minderjährigen',
|
||||
labelSimple: 'Daten von Kindern/Jugendlichen (unter 18)',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 8 DSGVO', title: 'Bedingungen für die Einwilligung eines Kindes', relevance: 'Besondere Anforderungen an Einwilligung' },
|
||||
{ article: 'ErwGr. 38', title: 'Besonderer Schutz für Kinder', relevance: 'Kinder verdienen besonderen Schutz' },
|
||||
],
|
||||
riskScore: 20,
|
||||
severity: 'WARN',
|
||||
requiredControls: ['parental_consent', 'age_verification', 'data_minimization'],
|
||||
explanation: 'Daten von Minderjährigen erfordern besondere Schutzmaßnahmen. Bei Onlinediensten: Einwilligung ab 16 Jahren (in DE), darunter Elterneinwilligung.',
|
||||
explanationSimple: 'Bei Kindern und Jugendlichen gelten strengere Regeln. Oft müssen die Eltern zustimmen.',
|
||||
userHint: '👶 Besonderer Schutz für Minderjährige erforderlich',
|
||||
},
|
||||
|
||||
license_plates: {
|
||||
id: 'license_plates',
|
||||
label: 'KFZ-Kennzeichen',
|
||||
labelSimple: 'Auto-Kennzeichen',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 4(1) DSGVO', title: 'Personenbezogene Daten', relevance: 'Kennzeichen ermöglichen Identifikation des Halters' },
|
||||
{ article: 'Art. 6 DSGVO', title: 'Rechtmäßigkeit', relevance: 'Rechtsgrundlage für Verarbeitung erforderlich' },
|
||||
],
|
||||
riskScore: 15,
|
||||
severity: 'WARN',
|
||||
requiredControls: ['purpose_limitation', 'retention_policy'],
|
||||
explanation: 'KFZ-Kennzeichen sind personenbezogene Daten, da sie die Identifikation des Halters ermöglichen.',
|
||||
explanationSimple: 'Über ein Kennzeichen kann man den Fahrzeughalter herausfinden - daher sind es persönliche Daten.',
|
||||
userHint: '🚗 Kennzeichen = personenbezogene Daten',
|
||||
},
|
||||
|
||||
images: {
|
||||
id: 'images',
|
||||
label: 'Bilder von Personen',
|
||||
labelSimple: 'Fotos mit erkennbaren Gesichtern',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 4(14) DSGVO', title: 'Biometrische Daten', relevance: 'Gesichtsbilder können biometrische Daten sein' },
|
||||
{ article: '§ 22 KUG', title: 'Recht am eigenen Bild', relevance: 'Einwilligung für Bildveröffentlichung' },
|
||||
],
|
||||
riskScore: 15,
|
||||
severity: 'WARN',
|
||||
requiredControls: ['explicit_consent', 'purpose_limitation'],
|
||||
explanation: 'Bilder von Personen sind personenbezogene Daten. Bei Gesichtserkennung: biometrische Daten (Art. 9).',
|
||||
explanationSimple: 'Fotos von Menschen brauchen deren Erlaubnis. Gesichtserkennung hat noch strengere Regeln.',
|
||||
},
|
||||
|
||||
audio: {
|
||||
id: 'audio',
|
||||
label: 'Sprachaufnahmen',
|
||||
labelSimple: 'Gespräche, Telefonate, Sprachnachrichten',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 4(1) DSGVO', title: 'Personenbezogene Daten', relevance: 'Stimme ermöglicht Identifikation' },
|
||||
{ article: '§ 201 StGB', title: 'Vertraulichkeit des Wortes', relevance: 'Heimliche Aufnahmen sind strafbar' },
|
||||
],
|
||||
riskScore: 15,
|
||||
severity: 'WARN',
|
||||
requiredControls: ['explicit_consent', 'transparency'],
|
||||
explanation: 'Sprachaufnahmen sind personenbezogene Daten. Heimliche Aufnahmen können strafbar sein.',
|
||||
explanationSimple: 'Gespräche aufzunehmen erfordert die Zustimmung aller Beteiligten.',
|
||||
userHint: '🎤 Aufnahme nur mit Wissen der Betroffenen',
|
||||
},
|
||||
|
||||
location_data: {
|
||||
id: 'location_data',
|
||||
label: 'Standortdaten',
|
||||
labelSimple: 'GPS, Aufenthaltsorte, Bewegungsdaten',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 4(1) DSGVO', title: 'Personenbezogene Daten', relevance: 'Standorte ermöglichen Profilbildung' },
|
||||
{ article: 'ErwGr. 75', title: 'Risiken für Betroffene', relevance: 'Bewegungsprofile sind risikobehaftet' },
|
||||
],
|
||||
riskScore: 20,
|
||||
severity: 'WARN',
|
||||
requiredControls: ['explicit_consent', 'data_minimization', 'retention_policy'],
|
||||
explanation: 'Standortdaten ermöglichen detaillierte Bewegungsprofile. Hohes Risiko für Betroffene.',
|
||||
explanationSimple: 'Standortdaten zeigen, wo jemand wann war. Das ist sehr persönlich.',
|
||||
},
|
||||
|
||||
biometric_data: {
|
||||
id: 'biometric_data',
|
||||
label: 'Biometrische Daten',
|
||||
labelSimple: 'Fingerabdrücke, Gesichtserkennung',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 9(1) DSGVO', title: 'Besondere Kategorien', relevance: 'Biometrische Daten zur Identifikation' },
|
||||
{ article: 'Art. 4(14) DSGVO', title: 'Definition biometrischer Daten', relevance: 'Technische Verarbeitung physischer Merkmale' },
|
||||
],
|
||||
riskScore: 30,
|
||||
severity: 'WARN',
|
||||
requiredControls: ['explicit_consent', 'dsfa', 'encryption', 'access_logging'],
|
||||
explanation: 'Biometrische Daten zur eindeutigen Identifikation fallen unter Art. 9 DSGVO.',
|
||||
explanationSimple: 'Fingerabdrücke und Gesichtserkennung sind besonders geschützt.',
|
||||
userHint: '⚠️ Art. 9 DSGVO - Besondere Kategorie',
|
||||
},
|
||||
|
||||
financial_data: {
|
||||
id: 'financial_data',
|
||||
label: 'Finanzdaten',
|
||||
labelSimple: 'Gehälter, Kontodaten, Kreditwürdigkeit',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 6 DSGVO', title: 'Rechtmäßigkeit', relevance: 'Rechtsgrundlage erforderlich' },
|
||||
{ article: '§ 31 BDSG', title: 'Schutz des Wirtschaftsverkehrs', relevance: 'Scoring-Regelungen' },
|
||||
],
|
||||
riskScore: 15,
|
||||
severity: 'INFO',
|
||||
requiredControls: ['encryption', 'access_logging', 'purpose_limitation'],
|
||||
explanation: 'Finanzdaten erfordern besondere Sicherheitsmaßnahmen.',
|
||||
explanationSimple: 'Kontodaten und Gehälter müssen besonders geschützt werden.',
|
||||
},
|
||||
|
||||
employee_data: {
|
||||
id: 'employee_data',
|
||||
label: 'Mitarbeiterdaten',
|
||||
labelSimple: 'Personalakten, Bewertungen, Gehälter',
|
||||
legalRefs: [
|
||||
{ article: '§ 26 BDSG', title: 'Beschäftigtendatenschutz', relevance: 'Besondere Regelungen für Arbeitsverhältnisse' },
|
||||
{ article: 'Art. 88 DSGVO', title: 'Datenverarbeitung im Beschäftigungskontext', relevance: 'Nationale Regelungen möglich' },
|
||||
],
|
||||
riskScore: 15,
|
||||
severity: 'INFO',
|
||||
requiredControls: ['purpose_limitation', 'access_logging', 'transparency'],
|
||||
explanation: 'Beschäftigtendaten unterliegen dem § 26 BDSG. Betriebsrat ggf. einzubinden.',
|
||||
explanationSimple: 'Bei Mitarbeiterdaten gelten besondere Regeln. Der Betriebsrat hat Mitspracherecht.',
|
||||
userHint: '👔 Betriebsrat einbinden',
|
||||
},
|
||||
|
||||
customer_data: {
|
||||
id: 'customer_data',
|
||||
label: 'Kundendaten',
|
||||
labelSimple: 'Bestellungen, Kontaktdaten, Kaufhistorie',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 6(1)(b) DSGVO', title: 'Vertragserfüllung', relevance: 'Oft Rechtsgrundlage für Kundendaten' },
|
||||
],
|
||||
riskScore: 10,
|
||||
severity: 'INFO',
|
||||
requiredControls: ['transparency', 'retention_policy'],
|
||||
explanation: 'Kundendaten können oft auf Basis der Vertragserfüllung verarbeitet werden.',
|
||||
explanationSimple: 'Kundendaten brauchen Sie für Bestellungen - das ist meist erlaubt.',
|
||||
},
|
||||
|
||||
public_data: {
|
||||
id: 'public_data',
|
||||
label: 'Nur öffentliche Daten',
|
||||
labelSimple: 'Keine personenbezogenen Daten',
|
||||
legalRefs: [
|
||||
{ article: 'ErwGr. 26', title: 'Anonyme Informationen', relevance: 'DSGVO gilt nicht für anonyme Daten' },
|
||||
],
|
||||
riskScore: 0,
|
||||
severity: 'INFO',
|
||||
requiredControls: [],
|
||||
explanation: 'Wenn keine personenbezogenen Daten verarbeitet werden, ist die DSGVO nicht anwendbar.',
|
||||
explanationSimple: 'Ohne persönliche Daten gelten die strengen Regeln nicht.',
|
||||
userHint: '✅ Geringes Risiko',
|
||||
},
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Feld-Metadaten: Automatisierung
|
||||
// ============================================================================
|
||||
|
||||
export const AUTOMATION_METADATA: Record<string, FieldMetadata> = {
|
||||
assistive: {
|
||||
id: 'assistive',
|
||||
label: 'Assistierend (KI macht Vorschläge)',
|
||||
labelSimple: 'KI macht Vorschläge, Mensch entscheidet',
|
||||
legalRefs: [],
|
||||
riskScore: 0,
|
||||
severity: 'INFO',
|
||||
requiredControls: [],
|
||||
explanation: 'Bei assistierender KI bleibt der Mensch Entscheider. Art. 22 DSGVO nicht betroffen.',
|
||||
explanationSimple: 'Die KI schlägt vor, Sie entscheiden. Das ist die sicherste Variante.',
|
||||
userHint: '✅ Empfohlen',
|
||||
},
|
||||
|
||||
semi_automated: {
|
||||
id: 'semi_automated',
|
||||
label: 'Teilautomatisiert (Mensch prüft)',
|
||||
labelSimple: 'KI filtert vor, Mensch prüft',
|
||||
legalRefs: [
|
||||
{ article: 'ErwGr. 71', title: 'Profiling und automatisierte Entscheidungen', relevance: 'Menschliche Überprüfung empfohlen' },
|
||||
],
|
||||
riskScore: 10,
|
||||
severity: 'INFO',
|
||||
requiredControls: ['human_in_the_loop'],
|
||||
explanation: 'Teilautomatisierung mit menschlicher Kontrolle ist meist unproblematisch.',
|
||||
explanationSimple: 'Die KI arbeitet vor, aber ein Mensch schaut drüber.',
|
||||
},
|
||||
|
||||
fully_automated: {
|
||||
id: 'fully_automated',
|
||||
label: 'Vollautomatisiert (keine menschliche Prüfung)',
|
||||
labelSimple: 'KI entscheidet alleine',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 22(1) DSGVO', title: 'Automatisierte Einzelentscheidungen', relevance: 'Grundsätzliches Verbot bei rechtlicher Wirkung' },
|
||||
{ article: 'Art. 22(2) DSGVO', title: 'Ausnahmen', relevance: 'Erlaubt bei Vertrag, Gesetz oder Einwilligung' },
|
||||
],
|
||||
riskScore: 25,
|
||||
severity: 'WARN',
|
||||
requiredControls: ['human_in_the_loop', 'contestation_right', 'transparency'],
|
||||
explanation: 'Vollautomatisierte Entscheidungen mit rechtlicher Wirkung sind nach Art. 22 DSGVO grundsätzlich verboten.',
|
||||
explanationSimple: 'Wenn die KI alleine entscheidet und das Auswirkungen auf Menschen hat, ist das problematisch.',
|
||||
userHint: '⚠️ Art. 22 DSGVO beachten',
|
||||
},
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Feld-Metadaten: Zweck
|
||||
// ============================================================================
|
||||
|
||||
export const PURPOSE_METADATA: Record<string, FieldMetadata> = {
|
||||
customer_support: {
|
||||
id: 'customer_support',
|
||||
label: 'Kundenservice',
|
||||
labelSimple: 'Fragen beantworten, Hilfe anbieten',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 6(1)(b) DSGVO', title: 'Vertragserfüllung', relevance: 'Oft Rechtsgrundlage' },
|
||||
],
|
||||
riskScore: 5,
|
||||
severity: 'INFO',
|
||||
requiredControls: ['transparency'],
|
||||
explanation: 'Kundenservice kann meist auf Vertragserfüllung gestützt werden.',
|
||||
explanationSimple: 'Kunden zu helfen ist meist erlaubt.',
|
||||
},
|
||||
|
||||
evaluation_scoring: {
|
||||
id: 'evaluation_scoring',
|
||||
label: 'Bewertung/Scoring von Personen',
|
||||
labelSimple: 'Personen bewerten, Punkte vergeben, einstufen',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 22 DSGVO', title: 'Automatisierte Einzelentscheidungen', relevance: 'Bei automatischem Scoring relevant' },
|
||||
{ article: '§ 31 BDSG', title: 'Scoring', relevance: 'Besondere Regelungen für Scoring' },
|
||||
],
|
||||
riskScore: 20,
|
||||
severity: 'WARN',
|
||||
requiredControls: ['transparency', 'contestation_right', 'dsfa'],
|
||||
explanation: 'Scoring von Personen unterliegt strengen Anforderungen. Bei automatisierten Entscheidungen: Art. 22.',
|
||||
explanationSimple: 'Menschen zu bewerten oder einzustufen ist sensibel. Betroffene müssen das anfechten können.',
|
||||
userHint: '⚠️ Scoring ist risikobehaftet',
|
||||
},
|
||||
|
||||
decision_making: {
|
||||
id: 'decision_making',
|
||||
label: 'Automatisierte Entscheidungen',
|
||||
labelSimple: 'Genehmigungen, Ablehnungen, Zugang',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 22 DSGVO', title: 'Automatisierte Einzelentscheidungen', relevance: 'Kernartikel für automatisierte Entscheidungen' },
|
||||
],
|
||||
riskScore: 25,
|
||||
severity: 'WARN',
|
||||
requiredControls: ['human_in_the_loop', 'contestation_right', 'transparency'],
|
||||
explanation: 'Automatisierte Entscheidungen mit rechtlicher Wirkung erfordern besondere Schutzmaßnahmen.',
|
||||
explanationSimple: 'Wenn die KI über Menschen entscheidet (Kredit, Bewerbung, etc.), gelten strenge Regeln.',
|
||||
userHint: '⚠️ Art. 22 DSGVO prüfen',
|
||||
},
|
||||
|
||||
profiling: {
|
||||
id: 'profiling',
|
||||
label: 'Profiling',
|
||||
labelSimple: 'Personenprofile erstellen, Verhalten analysieren',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 4(4) DSGVO', title: 'Definition Profiling', relevance: 'Automatisierte Verarbeitung zur Bewertung' },
|
||||
{ article: 'Art. 22 DSGVO', title: 'Automatisierte Entscheidungen einschl. Profiling', relevance: 'Bei Entscheidungen aufgrund von Profiling' },
|
||||
],
|
||||
riskScore: 20,
|
||||
severity: 'WARN',
|
||||
requiredControls: ['transparency', 'dsfa'],
|
||||
explanation: 'Profiling ist die automatisierte Bewertung persönlicher Aspekte. Erfordert Transparenz und oft DSFA.',
|
||||
explanationSimple: 'Profile über Menschen zu erstellen erfordert besondere Vorsicht.',
|
||||
},
|
||||
|
||||
marketing: {
|
||||
id: 'marketing',
|
||||
label: 'Marketing/Werbung',
|
||||
labelSimple: 'Werbung, Newsletter, Kampagnen',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 6(1)(f) DSGVO', title: 'Berechtigte Interessen', relevance: 'Direktwerbung kann berechtigtes Interesse sein' },
|
||||
{ article: '§ 7 UWG', title: 'Unzumutbare Belästigung', relevance: 'E-Mail-Werbung nur mit Einwilligung' },
|
||||
],
|
||||
riskScore: 10,
|
||||
severity: 'INFO',
|
||||
requiredControls: ['explicit_consent', 'transparency'],
|
||||
explanation: 'E-Mail-Marketing erfordert i.d.R. Einwilligung (Opt-in).',
|
||||
explanationSimple: 'Für Werbe-E-Mails brauchen Sie die Erlaubnis der Empfänger.',
|
||||
},
|
||||
|
||||
analytics: {
|
||||
id: 'analytics',
|
||||
label: 'Analyse/Statistik',
|
||||
labelSimple: 'Auswertungen, Berichte, Trends',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 6(1)(f) DSGVO', title: 'Berechtigte Interessen', relevance: 'Analysen oft auf berechtigtes Interesse stützbar' },
|
||||
],
|
||||
riskScore: 5,
|
||||
severity: 'INFO',
|
||||
requiredControls: ['data_minimization'],
|
||||
explanation: 'Statistische Analysen sind oft auf berechtigtes Interesse stützbar, wenn datenminimiert.',
|
||||
explanationSimple: 'Auswertungen für interne Zwecke sind meist unproblematisch.',
|
||||
},
|
||||
|
||||
research: {
|
||||
id: 'research',
|
||||
label: 'Forschung',
|
||||
labelSimple: 'Wissenschaftliche Untersuchungen',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 89 DSGVO', title: 'Garantien für Forschungszwecke', relevance: 'Privilegierung von Forschung' },
|
||||
],
|
||||
riskScore: 5,
|
||||
severity: 'INFO',
|
||||
requiredControls: ['data_minimization', 'pseudonymization'],
|
||||
explanation: 'Forschung genießt gewisse Privilegien, erfordert aber Schutzmaßnahmen.',
|
||||
explanationSimple: 'Forschung hat Sonderregeln, wenn die Daten geschützt werden.',
|
||||
},
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Feld-Metadaten: Hosting
|
||||
// ============================================================================
|
||||
|
||||
export const HOSTING_METADATA: Record<string, FieldMetadata> = {
|
||||
eu: {
|
||||
id: 'eu',
|
||||
label: 'EU/EWR',
|
||||
labelSimple: 'In Deutschland oder EU',
|
||||
legalRefs: [],
|
||||
riskScore: 0,
|
||||
severity: 'INFO',
|
||||
requiredControls: [],
|
||||
explanation: 'Hosting in der EU ist datenschutzrechtlich unproblematisch.',
|
||||
explanationSimple: 'Daten in Europa zu speichern ist die einfachste Lösung.',
|
||||
userHint: '✅ Empfohlen',
|
||||
},
|
||||
|
||||
third_country: {
|
||||
id: 'third_country',
|
||||
label: 'Drittland (außerhalb EU)',
|
||||
labelSimple: 'USA, Schweiz, UK, andere',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 44 DSGVO', title: 'Grundsatz für Übermittlung', relevance: 'Besondere Anforderungen an Drittlandtransfer' },
|
||||
{ article: 'Art. 46 DSGVO', title: 'Geeignete Garantien', relevance: 'SCC oder andere Garantien erforderlich' },
|
||||
],
|
||||
riskScore: 15,
|
||||
severity: 'WARN',
|
||||
requiredControls: ['scc', 'tia'],
|
||||
explanation: 'Drittlandtransfer erfordert zusätzliche Garantien (z.B. SCC) und ein Transfer Impact Assessment.',
|
||||
explanationSimple: 'Daten außerhalb der EU zu speichern braucht extra Verträge und Prüfungen.',
|
||||
userHint: '⚠️ Zusätzliche Maßnahmen erforderlich',
|
||||
},
|
||||
|
||||
on_prem: {
|
||||
id: 'on_prem',
|
||||
label: 'On-Premise (eigene Server)',
|
||||
labelSimple: 'Auf unseren eigenen Servern',
|
||||
legalRefs: [],
|
||||
riskScore: 0,
|
||||
severity: 'INFO',
|
||||
requiredControls: ['encryption'],
|
||||
explanation: 'On-Premise bietet volle Kontrolle, erfordert aber eigene Sicherheitsmaßnahmen.',
|
||||
explanationSimple: 'Eigene Server geben volle Kontrolle, aber Sie sind für die Sicherheit verantwortlich.',
|
||||
},
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Feld-Metadaten: Modell-Nutzung
|
||||
// ============================================================================
|
||||
|
||||
export const MODEL_USAGE_METADATA: Record<string, FieldMetadata> = {
|
||||
rag: {
|
||||
id: 'rag',
|
||||
label: 'RAG (Dokumentensuche)',
|
||||
labelSimple: 'KI durchsucht meine Dokumente',
|
||||
legalRefs: [],
|
||||
riskScore: 5,
|
||||
severity: 'INFO',
|
||||
requiredControls: [],
|
||||
explanation: 'RAG-Ansätze sind datenschutzfreundlich, da keine Daten ins Modell fließen.',
|
||||
explanationSimple: 'Die KI sucht in Ihren Dokumenten, lernt aber nicht daraus. Das ist sicher.',
|
||||
userHint: '✅ Datenschutzfreundlich',
|
||||
},
|
||||
|
||||
inference: {
|
||||
id: 'inference',
|
||||
label: 'Nur Inferenz',
|
||||
labelSimple: 'KI nur nutzen, ohne eigene Daten',
|
||||
legalRefs: [],
|
||||
riskScore: 0,
|
||||
severity: 'INFO',
|
||||
requiredControls: [],
|
||||
explanation: 'Reine Inferenz ohne Datenspeicherung ist unproblematisch.',
|
||||
explanationSimple: 'Die KI nutzen ohne eigene Daten einzugeben ist sicher.',
|
||||
userHint: '✅ Geringes Risiko',
|
||||
},
|
||||
|
||||
finetune: {
|
||||
id: 'finetune',
|
||||
label: 'Fine-Tuning',
|
||||
labelSimple: 'KI mit meinen Daten anpassen',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 5(1)(b) DSGVO', title: 'Zweckbindung', relevance: 'Training ist neuer Zweck' },
|
||||
],
|
||||
riskScore: 20,
|
||||
severity: 'WARN',
|
||||
requiredControls: ['explicit_consent', 'purpose_limitation', 'no_training'],
|
||||
explanation: 'Fine-Tuning mit personenbezogenen Daten erfordert eigene Rechtsgrundlage.',
|
||||
explanationSimple: 'Wenn die KI aus Ihren Daten lernt, ist das ein eigener Verarbeitungsschritt.',
|
||||
userHint: '⚠️ Eigene Rechtsgrundlage erforderlich',
|
||||
},
|
||||
|
||||
training: {
|
||||
id: 'training',
|
||||
label: 'Vollständiges Training',
|
||||
labelSimple: 'KI komplett mit meinen Daten trainieren',
|
||||
legalRefs: [
|
||||
{ article: 'Art. 5(1)(b) DSGVO', title: 'Zweckbindung', relevance: 'Training ist neuer Zweck' },
|
||||
{ article: 'Art. 6 DSGVO', title: 'Rechtmäßigkeit', relevance: 'Eigene Rechtsgrundlage erforderlich' },
|
||||
],
|
||||
riskScore: 25,
|
||||
severity: 'WARN',
|
||||
requiredControls: ['explicit_consent', 'dsfa', 'purpose_limitation'],
|
||||
explanation: 'KI-Training mit personenbezogenen Daten ist ein eigenständiger Verarbeitungszweck.',
|
||||
explanationSimple: 'Die KI komplett mit Ihren Daten zu trainieren braucht klare Einwilligung.',
|
||||
userHint: '⚠️ Hohes Risiko',
|
||||
},
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Probleme & Lösungen
|
||||
// ============================================================================
|
||||
|
||||
export const PROBLEMS: Problem[] = [
|
||||
// KFZ-Kennzeichen ohne Einwilligung
|
||||
{
|
||||
id: 'license_plates_no_consent',
|
||||
title: 'KFZ-Kennzeichen ohne Einwilligung',
|
||||
description: 'Sie möchten KFZ-Kennzeichen verarbeiten, aber haben keine Einwilligung der Fahrzeughalter.',
|
||||
severity: 'BLOCK',
|
||||
triggered_by: {
|
||||
all_of: ['license_plates'],
|
||||
none_of: ['explicit_consent_obtained'],
|
||||
},
|
||||
legalRefs: [
|
||||
{ article: 'Art. 6 DSGVO', title: 'Rechtmäßigkeit', relevance: 'Keine Rechtsgrundlage vorhanden' },
|
||||
],
|
||||
solutions: [
|
||||
{
|
||||
id: 'pixelize_plates',
|
||||
title: 'Kennzeichen automatisch verpixeln',
|
||||
description: 'Die Kennzeichen werden vor der Speicherung automatisch unkenntlich gemacht. Dadurch sind es keine personenbezogenen Daten mehr.',
|
||||
removes_fields: ['license_plates'],
|
||||
adds_controls: ['pixelization'],
|
||||
new_risk_score: 0,
|
||||
effort: 'medium',
|
||||
team_question: 'Ist das Projekt auch mit verpixelten Kennzeichen (nicht lesbar) sinnvoll?',
|
||||
},
|
||||
{
|
||||
id: 'obtain_consent',
|
||||
title: 'Einwilligung einholen',
|
||||
description: 'Die Fahrzeughalter um Einwilligung bitten (z.B. bei Parkhausbetreibern mit Dauerparker-Verträgen).',
|
||||
adds_controls: ['explicit_consent'],
|
||||
new_risk_score: 10,
|
||||
effort: 'high',
|
||||
team_question: 'Können Sie die Einwilligung der Fahrzeughalter einholen?',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Gesichtserkennung ohne Einwilligung
|
||||
{
|
||||
id: 'biometrics_no_consent',
|
||||
title: 'Biometrische Daten ohne Einwilligung',
|
||||
description: 'Sie möchten biometrische Daten (z.B. Gesichtserkennung) verarbeiten, aber haben keine ausdrückliche Einwilligung.',
|
||||
severity: 'BLOCK',
|
||||
triggered_by: {
|
||||
all_of: ['biometric_data'],
|
||||
none_of: ['explicit_consent_obtained'],
|
||||
},
|
||||
legalRefs: [
|
||||
{ article: 'Art. 9(1) DSGVO', title: 'Verarbeitungsverbot', relevance: 'Biometrische Daten sind besondere Kategorie' },
|
||||
{ article: 'Art. 9(2)(a) DSGVO', title: 'Ausdrückliche Einwilligung', relevance: 'Einwilligung als Ausnahme' },
|
||||
],
|
||||
solutions: [
|
||||
{
|
||||
id: 'anonymize_faces',
|
||||
title: 'Gesichter automatisch verpixeln/anonymisieren',
|
||||
description: 'Gesichter werden vor der Speicherung automatisch unkenntlich gemacht.',
|
||||
removes_fields: ['biometric_data'],
|
||||
adds_controls: ['pixelization'],
|
||||
new_risk_score: 0,
|
||||
effort: 'medium',
|
||||
team_question: 'Funktioniert Ihr Projekt auch ohne erkennbare Gesichter?',
|
||||
},
|
||||
{
|
||||
id: 'explicit_biometric_consent',
|
||||
title: 'Ausdrückliche Einwilligung einholen',
|
||||
description: 'Betroffene müssen aktiv und informiert in die Gesichtserkennung einwilligen.',
|
||||
adds_controls: ['explicit_consent', 'dsfa'],
|
||||
new_risk_score: 20,
|
||||
effort: 'high',
|
||||
team_question: 'Können Sie eine ausdrückliche Einwilligung aller Betroffenen sicherstellen?',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Minderjährige + automatisiertes Scoring
|
||||
{
|
||||
id: 'minor_automated_scoring',
|
||||
title: 'Automatisiertes Scoring von Minderjährigen',
|
||||
description: 'Sie möchten Minderjährige automatisiert bewerten oder einstufen. Das ist besonders problematisch.',
|
||||
severity: 'BLOCK',
|
||||
triggered_by: {
|
||||
all_of: ['minor_data', 'evaluation_scoring', 'fully_automated'],
|
||||
},
|
||||
legalRefs: [
|
||||
{ article: 'Art. 22(1) DSGVO', title: 'Verbot automatisierter Entscheidungen', relevance: 'Grundsätzliches Verbot' },
|
||||
{ article: 'Art. 8 DSGVO', title: 'Schutz von Kindern', relevance: 'Besonderer Schutz für Minderjährige' },
|
||||
],
|
||||
solutions: [
|
||||
{
|
||||
id: 'add_human_review',
|
||||
title: 'Menschliche Überprüfung einführen',
|
||||
description: 'Jede Bewertung wird von einem Menschen geprüft bevor sie wirksam wird.',
|
||||
removes_fields: ['fully_automated'],
|
||||
adds_controls: ['human_in_the_loop'],
|
||||
new_risk_score: 15,
|
||||
effort: 'medium',
|
||||
team_question: 'Können Sie sicherstellen, dass ein Mensch jede Bewertung prüft?',
|
||||
},
|
||||
{
|
||||
id: 'remove_scoring',
|
||||
title: 'Auf Scoring verzichten',
|
||||
description: 'Statt Scoring nur informative Auswertungen ohne Entscheidungscharakter.',
|
||||
removes_fields: ['evaluation_scoring'],
|
||||
new_risk_score: 10,
|
||||
effort: 'low',
|
||||
team_question: 'Funktioniert Ihr Projekt auch ohne Bewertung/Scoring der Minderjährigen?',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Drittland + sensible Daten
|
||||
{
|
||||
id: 'third_country_sensitive',
|
||||
title: 'Sensible Daten im Drittland',
|
||||
description: 'Sie möchten besonders sensible Daten außerhalb der EU verarbeiten. Das erfordert umfangreiche Schutzmaßnahmen.',
|
||||
severity: 'WARN',
|
||||
triggered_by: {
|
||||
all_of: ['third_country'],
|
||||
any_of: ['article_9_data', 'biometric_data', 'minor_data'],
|
||||
},
|
||||
legalRefs: [
|
||||
{ article: 'Art. 44 DSGVO', title: 'Drittlandtransfer', relevance: 'Besondere Anforderungen' },
|
||||
{ article: 'Art. 9 DSGVO', title: 'Sensible Daten', relevance: 'Zusätzlicher Schutz erforderlich' },
|
||||
],
|
||||
solutions: [
|
||||
{
|
||||
id: 'move_to_eu',
|
||||
title: 'Hosting in der EU',
|
||||
description: 'Wählen Sie einen Anbieter mit Rechenzentren in der EU.',
|
||||
removes_fields: ['third_country'],
|
||||
new_risk_score: 0,
|
||||
effort: 'medium',
|
||||
team_question: 'Können Sie zu einem EU-Anbieter wechseln?',
|
||||
},
|
||||
{
|
||||
id: 'implement_safeguards',
|
||||
title: 'Umfangreiche Schutzmaßnahmen implementieren',
|
||||
description: 'SCC, TIA, zusätzliche technische Maßnahmen implementieren.',
|
||||
adds_controls: ['scc', 'tia', 'encryption'],
|
||||
new_risk_score: 15,
|
||||
effort: 'high',
|
||||
team_question: 'Können Sie die erforderlichen Verträge und Maßnahmen umsetzen?',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// KI-Training mit personenbezogenen Daten
|
||||
{
|
||||
id: 'training_with_pii',
|
||||
title: 'KI-Training mit personenbezogenen Daten',
|
||||
description: 'Sie möchten ein KI-Modell mit personenbezogenen Daten trainieren. Das erfordert besondere Rechtsgrundlagen.',
|
||||
severity: 'WARN',
|
||||
triggered_by: {
|
||||
all_of: ['training'],
|
||||
any_of: ['personal_data', 'article_9_data', 'employee_data', 'customer_data'],
|
||||
},
|
||||
legalRefs: [
|
||||
{ article: 'Art. 5(1)(b) DSGVO', title: 'Zweckbindung', relevance: 'Training ist eigener Zweck' },
|
||||
{ article: 'Art. 6 DSGVO', title: 'Rechtmäßigkeit', relevance: 'Eigene Rechtsgrundlage erforderlich' },
|
||||
],
|
||||
solutions: [
|
||||
{
|
||||
id: 'use_rag_instead',
|
||||
title: 'RAG statt Training verwenden',
|
||||
description: 'Statt Training: Dokumente in Vektordatenbank ablegen und bei Anfragen durchsuchen.',
|
||||
removes_fields: ['training'],
|
||||
new_risk_score: 5,
|
||||
effort: 'low',
|
||||
team_question: 'Reicht es, wenn die KI Ihre Dokumente durchsuchen kann statt daraus zu lernen?',
|
||||
},
|
||||
{
|
||||
id: 'anonymize_training_data',
|
||||
title: 'Trainingsdaten anonymisieren',
|
||||
description: 'Personenbezogene Daten vor dem Training vollständig anonymisieren.',
|
||||
adds_controls: ['anonymization'],
|
||||
new_risk_score: 5,
|
||||
effort: 'high',
|
||||
team_question: 'Können die Trainingsdaten vor dem Training anonymisiert werden?',
|
||||
},
|
||||
{
|
||||
id: 'get_training_consent',
|
||||
title: 'Einwilligung für Training einholen',
|
||||
description: 'Betroffene explizit um Einwilligung für das KI-Training bitten.',
|
||||
adds_controls: ['explicit_consent', 'dsfa'],
|
||||
new_risk_score: 15,
|
||||
effort: 'high',
|
||||
team_question: 'Können Sie die Einwilligung aller Betroffenen für das KI-Training einholen?',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
// ============================================================================
|
||||
// Hilfsfunktionen
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Aggregiert alle ausgewählten Felder und berechnet das Ergebnis
|
||||
*/
|
||||
export function evaluateSelection(selection: {
|
||||
dataTypes: string[]
|
||||
automation: string
|
||||
purposes: string[]
|
||||
hosting: string
|
||||
modelUsage: string[]
|
||||
acceptedSolutions: string[]
|
||||
}): {
|
||||
totalRiskScore: number
|
||||
allLegalRefs: LegalReference[]
|
||||
allRequiredControls: string[]
|
||||
problems: Problem[]
|
||||
severity: 'INFO' | 'WARN' | 'BLOCK'
|
||||
} {
|
||||
const allLegalRefs: LegalReference[] = []
|
||||
const allRequiredControls: Set<string> = new Set()
|
||||
let totalRiskScore = 0
|
||||
let maxSeverity: 'INFO' | 'WARN' | 'BLOCK' = 'INFO'
|
||||
|
||||
// Aggregiere Datentypen
|
||||
for (const dt of selection.dataTypes) {
|
||||
const meta = DATA_TYPE_METADATA[dt]
|
||||
if (meta) {
|
||||
totalRiskScore += meta.riskScore
|
||||
allLegalRefs.push(...meta.legalRefs)
|
||||
meta.requiredControls.forEach(c => allRequiredControls.add(c))
|
||||
if (meta.severity === 'BLOCK') maxSeverity = 'BLOCK'
|
||||
else if (meta.severity === 'WARN' && maxSeverity !== 'BLOCK') maxSeverity = 'WARN'
|
||||
}
|
||||
}
|
||||
|
||||
// Aggregiere Automatisierung
|
||||
const autoMeta = AUTOMATION_METADATA[selection.automation]
|
||||
if (autoMeta) {
|
||||
totalRiskScore += autoMeta.riskScore
|
||||
allLegalRefs.push(...autoMeta.legalRefs)
|
||||
autoMeta.requiredControls.forEach(c => allRequiredControls.add(c))
|
||||
if (autoMeta.severity === 'BLOCK') maxSeverity = 'BLOCK'
|
||||
else if (autoMeta.severity === 'WARN' && maxSeverity !== 'BLOCK') maxSeverity = 'WARN'
|
||||
}
|
||||
|
||||
// Aggregiere Zwecke
|
||||
for (const p of selection.purposes) {
|
||||
const meta = PURPOSE_METADATA[p]
|
||||
if (meta) {
|
||||
totalRiskScore += meta.riskScore
|
||||
allLegalRefs.push(...meta.legalRefs)
|
||||
meta.requiredControls.forEach(c => allRequiredControls.add(c))
|
||||
if (meta.severity === 'BLOCK') maxSeverity = 'BLOCK'
|
||||
else if (meta.severity === 'WARN' && maxSeverity !== 'BLOCK') maxSeverity = 'WARN'
|
||||
}
|
||||
}
|
||||
|
||||
// Aggregiere Hosting
|
||||
const hostMeta = HOSTING_METADATA[selection.hosting]
|
||||
if (hostMeta) {
|
||||
totalRiskScore += hostMeta.riskScore
|
||||
allLegalRefs.push(...hostMeta.legalRefs)
|
||||
hostMeta.requiredControls.forEach(c => allRequiredControls.add(c))
|
||||
if (hostMeta.severity === 'BLOCK') maxSeverity = 'BLOCK'
|
||||
else if (hostMeta.severity === 'WARN' && maxSeverity !== 'BLOCK') maxSeverity = 'WARN'
|
||||
}
|
||||
|
||||
// Aggregiere Model Usage
|
||||
for (const mu of selection.modelUsage) {
|
||||
const meta = MODEL_USAGE_METADATA[mu]
|
||||
if (meta) {
|
||||
totalRiskScore += meta.riskScore
|
||||
allLegalRefs.push(...meta.legalRefs)
|
||||
meta.requiredControls.forEach(c => allRequiredControls.add(c))
|
||||
if (meta.severity === 'BLOCK') maxSeverity = 'BLOCK'
|
||||
else if (meta.severity === 'WARN' && maxSeverity !== 'BLOCK') maxSeverity = 'WARN'
|
||||
}
|
||||
}
|
||||
|
||||
// Finde zutreffende Probleme
|
||||
const allSelectedFields = [
|
||||
...selection.dataTypes,
|
||||
selection.automation,
|
||||
...selection.purposes,
|
||||
selection.hosting,
|
||||
...selection.modelUsage,
|
||||
]
|
||||
|
||||
const triggeredProblems = PROBLEMS.filter(problem => {
|
||||
// Prüfe all_of: alle müssen ausgewählt sein
|
||||
if (problem.triggered_by.all_of) {
|
||||
if (!problem.triggered_by.all_of.every(f => allSelectedFields.includes(f))) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Prüfe any_of: mindestens eins muss ausgewählt sein
|
||||
if (problem.triggered_by.any_of) {
|
||||
if (!problem.triggered_by.any_of.some(f => allSelectedFields.includes(f))) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Prüfe none_of: keins darf ausgewählt sein (außer durch Lösung)
|
||||
if (problem.triggered_by.none_of) {
|
||||
const hasNoneOf = problem.triggered_by.none_of.some(f =>
|
||||
allSelectedFields.includes(f) || selection.acceptedSolutions.includes(f)
|
||||
)
|
||||
if (hasNoneOf) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Prüfe ob Problem durch akzeptierte Lösung gelöst wurde
|
||||
const isSolved = problem.solutions.some(solution =>
|
||||
selection.acceptedSolutions.includes(solution.id)
|
||||
)
|
||||
|
||||
return !isSolved
|
||||
})
|
||||
|
||||
// Probleme beeinflussen Severity
|
||||
for (const problem of triggeredProblems) {
|
||||
if (problem.severity === 'BLOCK') maxSeverity = 'BLOCK'
|
||||
else if (problem.severity === 'WARN' && maxSeverity !== 'BLOCK') maxSeverity = 'WARN'
|
||||
}
|
||||
|
||||
// Dedupliziere Legal Refs
|
||||
const uniqueLegalRefs = allLegalRefs.filter((ref, index, self) =>
|
||||
index === self.findIndex(r => r.article === ref.article)
|
||||
)
|
||||
|
||||
return {
|
||||
totalRiskScore: Math.min(totalRiskScore, 100),
|
||||
allLegalRefs: uniqueLegalRefs,
|
||||
allRequiredControls: Array.from(allRequiredControls),
|
||||
problems: triggeredProblems,
|
||||
severity: maxSeverity,
|
||||
}
|
||||
}
|
||||
1954
admin-v2/app/(admin)/dsgvo/advisory-board/page.tsx
Normal file
1954
admin-v2/app/(admin)/dsgvo/advisory-board/page.tsx
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user