feat(ucca): Pflichtendatenbank v2 (325 Obligations), Trigger-Engine, TOM-Control-Mapping
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 32s
CI / test-python-backend-compliance (push) Successful in 29s
CI / test-python-document-crawler (push) Successful in 20s
CI / test-python-dsms-gateway (push) Successful in 18s

- 9 Regulation-JSON-Dateien (DSGVO 80, AI Act 60, NIS2 40, BDSG 30, TTDSG 20, DSA 35, Data Act 25, EU-Maschinen 15, DORA 20)
- Condition-Tree-Engine fuer automatische Pflichtenselektion (all_of/any_of, 80+ Field-Paths)
- Generischer JSONRegulationModule-Loader mit YAML-Fallback
- Bidirektionales TOM-Control-Mapping (291 Obligation→Control, 92 Control→Obligation)
- Gap-Analyse-Engine (Compliance-%, Priority Actions, Domain Breakdown)
- ScopeDecision→UnifiedFacts Bridge fuer Auto-Profiling
- 4 neue API-Endpoints (assess-from-scope, tom-controls, gap-analysis, reverse-lookup)
- Frontend: Auto-Profiling Button, Regulation-Filter Chips, TOM-Panel, Gap-Analyse-View
- 18 Unit Tests (Condition Engine, v2 Loader, TOM Mapper)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-05 14:51:44 +01:00
parent 2540a2189a
commit 38e278ee3c
32 changed files with 22870 additions and 41 deletions

View File

@@ -0,0 +1,34 @@
import { NextRequest, NextResponse } from 'next/server'
const SDK_BASE_URL = process.env.SDK_BASE_URL || 'http://localhost:8085'
async function proxyRequest(request: NextRequest, method: string) {
try {
const pathSegments = request.nextUrl.pathname.replace('/api/sdk/v1/ucca/obligations/', '')
const targetUrl = `${SDK_BASE_URL}/sdk/v1/ucca/obligations/${pathSegments}${request.nextUrl.search}`
const headers: Record<string, string> = { 'Content-Type': 'application/json' }
const tenantId = request.headers.get('X-Tenant-ID')
if (tenantId) headers['X-Tenant-ID'] = tenantId
const fetchOptions: RequestInit = { method, headers }
if (method === 'POST' || method === 'PUT' || method === 'PATCH') {
fetchOptions.body = await request.text()
}
const response = await fetch(targetUrl, fetchOptions)
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json({ error: 'SDK backend error', details: errorText }, { status: response.status })
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('UCCA obligations proxy error:', error)
return NextResponse.json({ error: 'Failed to connect to SDK backend' }, { status: 503 })
}
}
export async function GET(request: NextRequest) { return proxyRequest(request, 'GET') }
export async function POST(request: NextRequest) { return proxyRequest(request, 'POST') }

View File

@@ -2,6 +2,8 @@
import React, { useState, useEffect, useCallback } from 'react'
import { StepHeader, STEP_EXPLANATIONS } from '@/components/sdk/StepHeader'
import TOMControlPanel from '@/components/sdk/obligations/TOMControlPanel'
import GapAnalysisView from '@/components/sdk/obligations/GapAnalysisView'
// =============================================================================
// Types
@@ -178,7 +180,7 @@ function ObligationModal({
onChange={e => update('source', e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm"
>
{['DSGVO', 'AI Act', 'NIS2', 'BDSG', 'TTDSG', 'Sonstig'].map(s => (
{['DSGVO', 'AI Act', 'NIS2', 'BDSG', 'TTDSG', 'DSA', 'Data Act', 'DORA', 'EU-Maschinen', 'Sonstig'].map(s => (
<option key={s}>{s}</option>
))}
</select>
@@ -426,6 +428,7 @@ function ObligationCard({
onDetails: () => void
}) {
const [saving, setSaving] = useState(false)
const [showTOM, setShowTOM] = useState(false)
const daysUntil = obligation.deadline
? Math.ceil((new Date(obligation.deadline).getTime() - Date.now()) / 86400000)
@@ -480,6 +483,13 @@ function ObligationCard({
)}
</div>
<div className="flex items-center gap-2" onClick={e => e.stopPropagation()}>
<button
onClick={(e) => { e.stopPropagation(); setShowTOM(v => !v) }}
className="px-2 py-1 text-purple-600 hover:bg-purple-50 rounded-lg transition-colors"
title="TOM Controls anzeigen"
>
TOM
</button>
<button
onClick={onDetails}
className="text-purple-600 hover:text-purple-700 font-medium"
@@ -497,6 +507,12 @@ function ObligationCard({
)}
</div>
</div>
{showTOM && (
<div className="mt-3" onClick={e => e.stopPropagation()}>
<TOMControlPanel obligationId={obligation.id} onClose={() => setShowTOM(false)} />
</div>
)}
</div>
)
}
@@ -505,16 +521,42 @@ function ObligationCard({
// Main Page
// =============================================================================
function mapPriority(p: string): 'critical' | 'high' | 'medium' | 'low' {
const map: Record<string, 'critical' | 'high' | 'medium' | 'low'> = {
kritisch: 'critical', hoch: 'high', mittel: 'medium', niedrig: 'low',
critical: 'critical', high: 'high', medium: 'medium', low: 'low',
}
return map[p?.toLowerCase()] || 'medium'
}
const REGULATION_CHIPS = [
{ key: 'all', label: 'Alle' },
{ key: 'DSGVO', label: 'DSGVO' },
{ key: 'AI Act', label: 'AI Act' },
{ key: 'NIS2', label: 'NIS2' },
{ key: 'BDSG', label: 'BDSG' },
{ key: 'TTDSG', label: 'TTDSG' },
{ key: 'DSA', label: 'DSA' },
{ key: 'Data Act', label: 'Data Act' },
{ key: 'DORA', label: 'DORA' },
{ key: 'EU-Maschinen', label: 'EU-Maschinen' },
]
const UCCA_API = '/api/sdk/v1/ucca/obligations'
export default function ObligationsPage() {
const [obligations, setObligations] = useState<Obligation[]>([])
const [stats, setStats] = useState<ObligationStats | null>(null)
const [filter, setFilter] = useState('all')
const [regulationFilter, setRegulationFilter] = useState('all')
const [searchQuery, setSearchQuery] = useState('')
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
const [showModal, setShowModal] = useState(false)
const [editObligation, setEditObligation] = useState<Obligation | null>(null)
const [detailObligation, setDetailObligation] = useState<Obligation | null>(null)
const [showGapAnalysis, setShowGapAnalysis] = useState(false)
const [profiling, setProfiling] = useState(false)
const loadData = useCallback(async () => {
setLoading(true)
@@ -621,10 +663,68 @@ export default function ObligationsPage() {
fetch(`${API}/stats`).then(r => r.json()).then(setStats).catch(() => {})
}
const handleAutoProfiling = async () => {
setProfiling(true)
setError(null)
try {
const res = await fetch(`${UCCA_API}/assess-from-scope`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
employee_count: 50,
industry: 'technology',
processes_personal_data: true,
is_controller: true,
uses_processors: true,
processes_special_categories: false,
cross_border_transfer: true,
uses_ai: true,
determined_level: 'L2',
}),
})
if (!res.ok) throw new Error(`HTTP ${res.status}`)
const data = await res.json()
if (data.obligations?.length > 0) {
// Merge auto-profiled obligations into the view
const autoObls: Obligation[] = data.obligations.map((o: Record<string, unknown>) => ({
id: o.id as string,
title: o.title as string,
description: (o.description as string) || '',
source: (o.regulation_id as string || '').toUpperCase(),
source_article: '',
deadline: null,
status: 'pending' as const,
priority: mapPriority(o.priority as string),
responsible: (o.responsible as string) || '',
linked_systems: [],
rule_code: 'auto-profiled',
}))
setObligations(prev => {
const existingIds = new Set(prev.map(p => p.id))
const newOnes = autoObls.filter(a => !existingIds.has(a.id))
return [...prev, ...newOnes]
})
}
} catch (e) {
setError(e instanceof Error ? e.message : 'Auto-Profiling fehlgeschlagen')
} finally {
setProfiling(false)
}
}
const stepInfo = STEP_EXPLANATIONS['obligations']
const filteredObligations = obligations.filter(o => {
if (filter === 'ai') return o.source.toLowerCase().includes('ai')
// Status/priority filter
if (filter === 'ai') {
if (!o.source.toLowerCase().includes('ai')) return false
}
// Regulation filter
if (regulationFilter !== 'all') {
const src = o.source?.toLowerCase() || ''
const key = regulationFilter.toLowerCase()
if (!src.includes(key)) return false
}
return true
})
@@ -679,15 +779,38 @@ export default function ObligationsPage() {
explanation={stepInfo?.explanation || ''}
tips={stepInfo?.tips || []}
>
<button
onClick={() => setShowModal(true)}
className="flex items-center gap-2 px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors text-sm"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
</svg>
Pflicht hinzufuegen
</button>
<div className="flex items-center gap-2">
<button
onClick={handleAutoProfiling}
disabled={profiling}
className="flex items-center gap-2 px-4 py-2 bg-white border border-purple-300 text-purple-700 rounded-lg hover:bg-purple-50 transition-colors text-sm disabled:opacity-50"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
</svg>
{profiling ? 'Profiling...' : 'Auto-Profiling'}
</button>
<button
onClick={() => setShowGapAnalysis(v => !v)}
className={`flex items-center gap-2 px-4 py-2 rounded-lg transition-colors text-sm ${
showGapAnalysis ? 'bg-purple-100 text-purple-700' : 'bg-white border border-gray-300 text-gray-700 hover:bg-gray-50'
}`}
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
</svg>
Gap-Analyse
</button>
<button
onClick={() => setShowModal(true)}
className="flex items-center gap-2 px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors text-sm"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
</svg>
Pflicht hinzufuegen
</button>
</div>
</StepHeader>
{/* Error */}
@@ -725,7 +848,28 @@ export default function ObligationsPage() {
</div>
)}
{/* Search + Filter */}
{/* Gap Analysis View */}
{showGapAnalysis && (
<GapAnalysisView />
)}
{/* Regulation Filter Chips */}
<div className="flex items-center gap-2 flex-wrap">
<span className="text-xs text-gray-500 mr-1">Regulation:</span>
{REGULATION_CHIPS.map(r => (
<button
key={r.key}
onClick={() => setRegulationFilter(r.key)}
className={`px-3 py-1 text-xs rounded-full transition-colors ${
regulationFilter === r.key ? 'bg-purple-600 text-white' : 'bg-purple-50 text-purple-700 hover:bg-purple-100'
}`}
>
{r.label}
</button>
))}
</div>
{/* Search + Status Filter */}
<div className="flex flex-col sm:flex-row items-start sm:items-center gap-3">
<input
type="text"
@@ -735,7 +879,7 @@ export default function ObligationsPage() {
className="flex-1 px-4 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-purple-500"
/>
<div className="flex items-center gap-2 flex-wrap">
{['all', 'overdue', 'pending', 'in-progress', 'completed', 'critical', 'ai'].map(f => (
{['all', 'overdue', 'pending', 'in-progress', 'completed', 'critical'].map(f => (
<button
key={f}
onClick={() => setFilter(f)}
@@ -743,7 +887,7 @@ export default function ObligationsPage() {
filter === f ? 'bg-purple-600 text-white' : 'bg-gray-100 text-gray-600 hover:bg-gray-200'
}`}
>
{f === 'all' ? 'Alle' : f === 'in-progress' ? 'In Bearbeitung' : f === 'overdue' ? 'Ueberfaellig' : f === 'pending' ? 'Ausstehend' : f === 'completed' ? 'Abgeschlossen' : f === 'critical' ? 'Kritisch' : 'AI Act'}
{f === 'all' ? 'Alle' : f === 'in-progress' ? 'In Bearbeitung' : f === 'overdue' ? 'Ueberfaellig' : f === 'pending' ? 'Ausstehend' : f === 'completed' ? 'Abgeschlossen' : 'Kritisch'}
</button>
))}
</div>

View File

@@ -0,0 +1,226 @@
'use client'
import React, { useState } from 'react'
interface GapItem {
control_id: string
control_title: string
control_domain: string
status: string
priority: string
obligation_ids: string[]
required_by_count: number
}
interface PriorityAction {
rank: number
action: string
control_ids: string[]
impact: string
effort: string
}
interface DomainGap {
domain_id: string
domain_name: string
total_controls: number
implemented_controls: number
compliance_percent: number
}
interface GapAnalysisResult {
compliance_percent: number
total_controls: number
implemented_controls: number
partial_controls: number
missing_controls: number
gaps: GapItem[]
priority_actions: PriorityAction[]
by_domain: Record<string, DomainGap>
}
const UCCA_API = '/api/sdk/v1/ucca/obligations'
const DOMAIN_LABELS: Record<string, string> = {
GOV: 'Governance', HR: 'Human Resources', IAM: 'Identity & Access',
AC: 'Access Control', CRYPTO: 'Kryptographie', LOG: 'Logging & Monitoring',
SDLC: 'Softwareentwicklung', OPS: 'Betrieb', NET: 'Netzwerk',
BCP: 'Business Continuity', VENDOR: 'Lieferanten', DATA: 'Datenschutz',
}
const IMPACT_COLORS: Record<string, string> = {
critical: 'text-red-700 bg-red-50',
high: 'text-orange-700 bg-orange-50',
medium: 'text-yellow-700 bg-yellow-50',
low: 'text-green-700 bg-green-50',
}
export default function GapAnalysisView() {
const [result, setResult] = useState<GapAnalysisResult | null>(null)
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const runAnalysis = async () => {
setLoading(true)
setError(null)
try {
const res = await fetch(`${UCCA_API}/gap-analysis`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ control_status_map: {} }),
})
if (!res.ok) throw new Error(`HTTP ${res.status}`)
setResult(await res.json())
} catch (e) {
setError(e instanceof Error ? e.message : 'Analyse fehlgeschlagen')
} finally {
setLoading(false)
}
}
if (!result) {
return (
<div className="bg-white rounded-xl border border-gray-200 p-6 text-center">
<div className="w-12 h-12 mx-auto bg-purple-50 rounded-full flex items-center justify-center mb-3">
<svg className="w-6 h-6 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
</svg>
</div>
<h3 className="text-sm font-semibold text-gray-900">TOM Gap-Analyse</h3>
<p className="text-xs text-gray-500 mt-1 mb-4">
Vergleicht erforderliche TOM Controls mit dem aktuellen Implementierungsstatus.
</p>
{error && <p className="text-xs text-red-600 mb-3">{error}</p>}
<button
onClick={runAnalysis}
disabled={loading}
className="px-5 py-2 bg-purple-600 text-white text-sm rounded-lg hover:bg-purple-700 disabled:opacity-50"
>
{loading ? 'Analysiere...' : 'Gap-Analyse starten'}
</button>
</div>
)
}
const domains = Object.values(result.by_domain).sort((a, b) => a.compliance_percent - b.compliance_percent)
return (
<div className="space-y-4">
{/* Compliance Score */}
<div className="bg-white rounded-xl border border-gray-200 p-6">
<div className="flex items-center justify-between mb-4">
<h3 className="text-sm font-semibold text-gray-900">Compliance-Status</h3>
<button
onClick={runAnalysis}
disabled={loading}
className="text-xs text-purple-600 hover:text-purple-700"
>
{loading ? 'Aktualisiere...' : 'Aktualisieren'}
</button>
</div>
<div className="flex items-center gap-6">
<div className="flex-shrink-0">
<div className={`text-4xl font-bold ${result.compliance_percent >= 80 ? 'text-green-600' : result.compliance_percent >= 50 ? 'text-yellow-600' : 'text-red-600'}`}>
{Math.round(result.compliance_percent)}%
</div>
<p className="text-xs text-gray-500">Compliance</p>
</div>
<div className="flex-1">
<div className="w-full bg-gray-200 rounded-full h-3">
<div
className={`h-3 rounded-full transition-all ${result.compliance_percent >= 80 ? 'bg-green-500' : result.compliance_percent >= 50 ? 'bg-yellow-500' : 'bg-red-500'}`}
style={{ width: `${Math.min(result.compliance_percent, 100)}%` }}
/>
</div>
<div className="flex justify-between mt-2 text-xs text-gray-500">
<span>{result.implemented_controls} implementiert</span>
<span>{result.partial_controls} teilweise</span>
<span>{result.missing_controls} fehlend</span>
</div>
</div>
</div>
</div>
{/* Domain Breakdown */}
{domains.length > 0 && (
<div className="bg-white rounded-xl border border-gray-200 p-5">
<h4 className="text-sm font-semibold text-gray-900 mb-3">Nach Domaene</h4>
<div className="space-y-2">
{domains.map(d => (
<div key={d.domain_id} className="flex items-center gap-3">
<span className="text-xs text-gray-600 w-32 flex-shrink-0 truncate">
{DOMAIN_LABELS[d.domain_id] || d.domain_id}
</span>
<div className="flex-1 bg-gray-100 rounded-full h-2">
<div
className={`h-2 rounded-full ${d.compliance_percent >= 80 ? 'bg-green-400' : d.compliance_percent >= 50 ? 'bg-yellow-400' : 'bg-red-400'}`}
style={{ width: `${Math.min(d.compliance_percent, 100)}%` }}
/>
</div>
<span className="text-xs text-gray-500 w-14 text-right">
{d.implemented_controls}/{d.total_controls}
</span>
</div>
))}
</div>
</div>
)}
{/* Priority Actions */}
{result.priority_actions.length > 0 && (
<div className="bg-white rounded-xl border border-gray-200 p-5">
<h4 className="text-sm font-semibold text-gray-900 mb-3">Prioritaere Massnahmen</h4>
<div className="space-y-2">
{result.priority_actions.slice(0, 5).map(a => (
<div key={a.rank} className="flex items-start gap-3 p-3 bg-gray-50 rounded-lg">
<span className="text-xs font-bold text-purple-600 bg-purple-50 rounded-full w-6 h-6 flex items-center justify-center flex-shrink-0">
{a.rank}
</span>
<div className="flex-1 min-w-0">
<p className="text-sm text-gray-900">{a.action}</p>
<div className="flex items-center gap-2 mt-1">
<span className={`text-[10px] px-1.5 py-0.5 rounded ${IMPACT_COLORS[a.impact] || 'bg-gray-100 text-gray-600'}`}>
{a.impact}
</span>
<span className="text-[10px] text-gray-400">
Aufwand: {a.effort}
</span>
<span className="text-[10px] text-gray-400">
{a.control_ids.length} Controls
</span>
</div>
</div>
</div>
))}
</div>
</div>
)}
{/* Gap List */}
{result.gaps.length > 0 && (
<div className="bg-white rounded-xl border border-gray-200 p-5">
<h4 className="text-sm font-semibold text-gray-900 mb-3">
Offene Gaps ({result.gaps.length})
</h4>
<div className="space-y-1 max-h-64 overflow-y-auto">
{result.gaps.map(g => (
<div key={g.control_id} className="flex items-center justify-between py-2 px-3 hover:bg-gray-50 rounded text-xs">
<div className="flex items-center gap-2 min-w-0">
<span className="font-mono text-purple-600 flex-shrink-0">{g.control_id}</span>
<span className="text-gray-700 truncate">{g.control_title}</span>
</div>
<div className="flex items-center gap-2 flex-shrink-0">
<span className={`px-1.5 py-0.5 rounded ${g.status === 'NOT_IMPLEMENTED' ? 'bg-red-50 text-red-600' : 'bg-yellow-50 text-yellow-600'}`}>
{g.status === 'NOT_IMPLEMENTED' ? 'Fehlend' : 'Teilweise'}
</span>
<span className="text-gray-400">{g.required_by_count}x</span>
</div>
</div>
))}
</div>
</div>
)}
</div>
)
}

View File

@@ -0,0 +1,105 @@
'use client'
import React, { useState, useEffect } from 'react'
interface TOMControl {
id: string
title: string
description: string
domain_id: string
priority: string
gdpr_articles: string[]
}
interface TOMControlPanelProps {
obligationId: string
onClose: () => void
}
const UCCA_API = '/api/sdk/v1/ucca/obligations'
const DOMAIN_LABELS: Record<string, string> = {
GOV: 'Governance',
HR: 'Human Resources',
IAM: 'Identity & Access',
AC: 'Access Control',
CRYPTO: 'Kryptographie',
LOG: 'Logging & Monitoring',
SDLC: 'Softwareentwicklung',
OPS: 'Betrieb',
NET: 'Netzwerk',
BCP: 'Business Continuity',
VENDOR: 'Lieferanten',
DATA: 'Datenschutz',
}
const PRIORITY_COLORS: Record<string, string> = {
kritisch: 'bg-red-100 text-red-700',
hoch: 'bg-orange-100 text-orange-700',
mittel: 'bg-yellow-100 text-yellow-700',
niedrig: 'bg-green-100 text-green-700',
}
export default function TOMControlPanel({ obligationId, onClose }: TOMControlPanelProps) {
const [controls, setControls] = useState<TOMControl[]>([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
useEffect(() => {
async function load() {
setLoading(true)
setError(null)
try {
const res = await fetch(`${UCCA_API}/${obligationId}/tom-controls`)
if (!res.ok) throw new Error(`HTTP ${res.status}`)
const data = await res.json()
setControls(data.controls || [])
} catch (e) {
setError(e instanceof Error ? e.message : 'Laden fehlgeschlagen')
} finally {
setLoading(false)
}
}
load()
}, [obligationId])
return (
<div className="bg-white border border-gray-200 rounded-xl overflow-hidden">
<div className="flex items-center justify-between px-5 py-3 bg-gray-50 border-b">
<h3 className="text-sm font-semibold text-gray-900">TOM Controls</h3>
<button onClick={onClose} className="text-gray-400 hover:text-gray-600 text-xs">Schliessen</button>
</div>
<div className="p-4">
{loading && <p className="text-xs text-gray-500">Lade Controls...</p>}
{error && <p className="text-xs text-red-600">{error}</p>}
{!loading && !error && controls.length === 0 && (
<p className="text-xs text-gray-400">Keine TOM Controls verknuepft</p>
)}
{!loading && controls.length > 0 && (
<div className="space-y-2">
{controls.map(c => (
<div key={c.id} className="border border-gray-100 rounded-lg p-3 hover:bg-gray-50 transition-colors">
<div className="flex items-center gap-2 mb-1">
<span className="text-xs font-mono text-purple-600">{c.id}</span>
<span className="text-xs text-gray-400">{DOMAIN_LABELS[c.domain_id] || c.domain_id}</span>
{c.priority && (
<span className={`px-1.5 py-0.5 text-[10px] rounded ${PRIORITY_COLORS[c.priority] || 'bg-gray-100 text-gray-600'}`}>
{c.priority}
</span>
)}
</div>
<p className="text-sm font-medium text-gray-900">{c.title}</p>
{c.description && (
<p className="text-xs text-gray-500 mt-1 line-clamp-2">{c.description}</p>
)}
</div>
))}
</div>
)}
</div>
</div>
)
}

View File

@@ -123,6 +123,10 @@ func main() {
trainingHandlers := handlers.NewTrainingHandlers(trainingStore, contentGenerator)
ragHandlers := handlers.NewRAGHandlers(corpusVersionStore)
// Initialize obligations framework (v2 with TOM mapping)
obligationsStore := ucca.NewObligationsStore(pool)
obligationsHandlers := handlers.NewObligationsHandlersWithStore(obligationsStore)
// Initialize middleware
rbacMiddleware := rbac.NewMiddleware(rbacService, policyEngine)
@@ -346,6 +350,9 @@ func main() {
// DSB Pool management
uccaRoutes.GET("/dsb-pool", escalationHandlers.ListDSBPool)
uccaRoutes.POST("/dsb-pool", escalationHandlers.AddDSBPoolMember)
// Obligations framework (v2 with TOM mapping)
obligationsHandlers.RegisterRoutes(uccaRoutes)
}
// RAG routes - Legal Corpus Search & Versioning

View File

@@ -1,6 +1,7 @@
package handlers
import (
"fmt"
"net/http"
"strconv"
"time"
@@ -14,23 +15,60 @@ import (
// ObligationsHandlers handles API requests for the generic obligations framework
type ObligationsHandlers struct {
registry *ucca.ObligationsRegistry
store *ucca.ObligationsStore // Optional: for persisting assessments
registry *ucca.ObligationsRegistry
store *ucca.ObligationsStore // Optional: for persisting assessments
tomIndex *ucca.TOMControlIndex
tomMapper *ucca.TOMObligationMapper
gapAnalyzer *ucca.TOMGapAnalyzer
}
// NewObligationsHandlers creates a new ObligationsHandlers instance
func NewObligationsHandlers() *ObligationsHandlers {
return &ObligationsHandlers{
h := &ObligationsHandlers{
registry: ucca.NewObligationsRegistry(),
}
h.initTOM()
return h
}
// NewObligationsHandlersWithStore creates a new ObligationsHandlers with a store
func NewObligationsHandlersWithStore(store *ucca.ObligationsStore) *ObligationsHandlers {
return &ObligationsHandlers{
h := &ObligationsHandlers{
registry: ucca.NewObligationsRegistry(),
store: store,
}
h.initTOM()
return h
}
// initTOM initializes TOM control index, mapper, and gap analyzer
func (h *ObligationsHandlers) initTOM() {
tomIndex, err := ucca.LoadTOMControls()
if err != nil {
fmt.Printf("Warning: Could not load TOM controls: %v\n", err)
return
}
h.tomIndex = tomIndex
// Try to load v2 TOM mapping
mapping, err := ucca.LoadV2TOMMapping()
if err != nil {
// Build mapping from v2 regulation files
regs, err2 := ucca.LoadAllV2Regulations()
if err2 == nil {
var allObligations []ucca.V2Obligation
for _, reg := range regs {
allObligations = append(allObligations, reg.Obligations...)
}
h.tomMapper = ucca.NewTOMObligationMapperFromObligations(tomIndex, allObligations)
}
} else {
h.tomMapper = ucca.NewTOMObligationMapper(tomIndex, mapping)
}
if h.tomMapper != nil {
h.gapAnalyzer = ucca.NewTOMGapAnalyzer(h.tomMapper, tomIndex)
}
}
// RegisterRoutes registers all obligations-related routes
@@ -56,6 +94,14 @@ func (h *ObligationsHandlers) RegisterRoutes(r *gin.RouterGroup) {
// Quick check endpoint (no persistence)
obligations.POST("/quick-check", h.QuickCheck)
// v2: Scope-based assessment
obligations.POST("/assess-from-scope", h.AssessFromScope)
// v2: TOM Control endpoints
obligations.GET("/:id/tom-controls", h.GetTOMControlsForObligation)
obligations.POST("/gap-analysis", h.GapAnalysis)
obligations.GET("/tom-controls/:controlId/obligations", h.GetObligationsForControl)
}
}
@@ -423,6 +469,106 @@ func (h *ObligationsHandlers) QuickCheck(c *gin.Context) {
})
}
// AssessFromScope assesses obligations from a ScopeDecision
// POST /sdk/v1/ucca/obligations/assess-from-scope
func (h *ObligationsHandlers) AssessFromScope(c *gin.Context) {
tenantID := rbac.GetTenantID(c)
if tenantID == uuid.Nil {
tenantID = uuid.New()
}
var scope ucca.ScopeDecision
if err := c.ShouldBindJSON(&scope); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body", "details": err.Error()})
return
}
// Convert scope to facts
facts := ucca.MapScopeToFacts(&scope)
// Evaluate
overview := h.registry.EvaluateAll(tenantID, facts, "")
// Enrich with TOM control requirements if available
if h.tomMapper != nil {
overview.TOMControlRequirements = h.tomMapper.DeriveControlsFromObligations(overview.Obligations)
}
var warnings []string
if len(overview.ApplicableRegulations) == 0 {
warnings = append(warnings, "Keine anwendbaren Regulierungen gefunden. Pruefen Sie die Scope-Angaben.")
}
c.JSON(http.StatusOK, ucca.ObligationsAssessResponse{
Overview: overview,
Warnings: warnings,
})
}
// GetTOMControlsForObligation returns TOM controls linked to an obligation
// GET /sdk/v1/ucca/obligations/:id/tom-controls
func (h *ObligationsHandlers) GetTOMControlsForObligation(c *gin.Context) {
obligationID := c.Param("id")
if h.tomMapper == nil {
c.JSON(http.StatusNotImplemented, gin.H{"error": "TOM mapping not available"})
return
}
controls := h.tomMapper.GetControlsForObligation(obligationID)
controlIDs := h.tomMapper.GetControlIDsForObligation(obligationID)
c.JSON(http.StatusOK, gin.H{
"obligation_id": obligationID,
"control_ids": controlIDs,
"controls": controls,
"count": len(controls),
})
}
// GapAnalysis performs a TOM control gap analysis
// POST /sdk/v1/ucca/obligations/gap-analysis
func (h *ObligationsHandlers) GapAnalysis(c *gin.Context) {
if h.gapAnalyzer == nil {
c.JSON(http.StatusNotImplemented, gin.H{"error": "Gap analysis not available"})
return
}
var req ucca.GapAnalysisRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body", "details": err.Error()})
return
}
result := h.gapAnalyzer.Analyze(&req)
c.JSON(http.StatusOK, result)
}
// GetObligationsForControl returns obligations linked to a TOM control
// GET /sdk/v1/ucca/obligations/tom-controls/:controlId/obligations
func (h *ObligationsHandlers) GetObligationsForControl(c *gin.Context) {
controlID := c.Param("controlId")
if h.tomMapper == nil {
c.JSON(http.StatusNotImplemented, gin.H{"error": "TOM mapping not available"})
return
}
obligationIDs := h.tomMapper.GetObligationsForControl(controlID)
var control *ucca.TOMControl
if h.tomIndex != nil {
control, _ = h.tomIndex.GetControl(controlID)
}
c.JSON(http.StatusOK, gin.H{
"control_id": controlID,
"control": control,
"obligation_ids": obligationIDs,
"count": len(obligationIDs),
})
}
// ============================================================================
// Helper Functions
// ============================================================================

View File

@@ -0,0 +1,301 @@
package ucca
import (
"fmt"
"time"
)
// JSONRegulationModule implements RegulationModule from a v2 JSON file
type JSONRegulationModule struct {
regFile *V2RegulationFile
conditionEngine *ObligationConditionEngine
applicability func(*UnifiedFacts) bool
}
// NewJSONRegulationModule creates a RegulationModule from a v2 JSON regulation file
func NewJSONRegulationModule(regFile *V2RegulationFile) *JSONRegulationModule {
m := &JSONRegulationModule{
regFile: regFile,
conditionEngine: NewObligationConditionEngine(),
}
// Set regulation-level applicability check
m.applicability = m.defaultApplicability
return m
}
func (m *JSONRegulationModule) ID() string { return m.regFile.Regulation }
func (m *JSONRegulationModule) Name() string { return m.regFile.Name }
func (m *JSONRegulationModule) Description() string { return m.regFile.Description }
// IsApplicable checks regulation-level applicability
func (m *JSONRegulationModule) IsApplicable(facts *UnifiedFacts) bool {
return m.applicability(facts)
}
// defaultApplicability determines if the regulation applies based on regulation ID
func (m *JSONRegulationModule) defaultApplicability(facts *UnifiedFacts) bool {
switch m.regFile.Regulation {
case "dsgvo":
return facts.DataProtection.ProcessesPersonalData &&
(facts.Organization.EUMember || facts.DataProtection.OffersToEU || facts.DataProtection.MonitorsEUIndividuals)
case "ai_act":
return facts.AIUsage.UsesAI
case "nis2":
return facts.Sector.PrimarySector != "" && facts.Sector.PrimarySector != "other" &&
(facts.Organization.MeetsNIS2SizeThreshold() || len(facts.Sector.SpecialServices) > 0)
case "bdsg":
return facts.DataProtection.ProcessesPersonalData && facts.Organization.Country == "DE"
case "ttdsg":
return (facts.DataProtection.UsesCookies || facts.DataProtection.UsesTracking) &&
facts.Organization.Country == "DE"
case "dsa":
return facts.DataProtection.OperatesPlatform && facts.Organization.EUMember
case "data_act":
return facts.Organization.EUMember
case "eu_machinery":
return facts.Organization.EUMember && facts.AIUsage.UsesAI
case "dora":
return facts.Financial.DORAApplies || facts.Financial.IsRegulated
default:
return true
}
}
// DeriveObligations derives applicable obligations from the JSON data
func (m *JSONRegulationModule) DeriveObligations(facts *UnifiedFacts) []Obligation {
var result []Obligation
for _, v2Obl := range m.regFile.Obligations {
// Check condition
if v2Obl.AppliesWhenCondition != nil {
if !m.conditionEngine.Evaluate(v2Obl.AppliesWhenCondition, facts) {
continue
}
} else {
// Fall back to legacy applies_when string matching
if !m.evaluateLegacyCondition(v2Obl.AppliesWhen, facts) {
continue
}
}
result = append(result, m.convertObligation(v2Obl))
}
return result
}
// DeriveControls derives applicable controls
func (m *JSONRegulationModule) DeriveControls(facts *UnifiedFacts) []ObligationControl {
var result []ObligationControl
for _, ctrl := range m.regFile.Controls {
result = append(result, ObligationControl{
ID: ctrl.ID,
RegulationID: m.regFile.Regulation,
Name: ctrl.Name,
Description: ctrl.Description,
Category: ctrl.Category,
WhatToDo: ctrl.WhatToDo,
ISO27001Mapping: ctrl.ISO27001Mapping,
Priority: ObligationPriority(mapPriority(ctrl.Priority)),
})
}
return result
}
func (m *JSONRegulationModule) GetDecisionTree() *DecisionTree { return nil }
func (m *JSONRegulationModule) GetIncidentDeadlines(facts *UnifiedFacts) []IncidentDeadline {
var result []IncidentDeadline
for _, dl := range m.regFile.IncidentDL {
var legalBasis []LegalReference
for _, lb := range dl.LegalBasis {
legalBasis = append(legalBasis, LegalReference{
Norm: lb.Norm,
Article: lb.Article,
Title: lb.Title,
})
}
result = append(result, IncidentDeadline{
RegulationID: m.regFile.Regulation,
Phase: dl.Phase,
Deadline: dl.Deadline,
Content: dl.Content,
Recipient: dl.Recipient,
LegalBasis: legalBasis,
})
}
return result
}
func (m *JSONRegulationModule) GetClassification(facts *UnifiedFacts) string {
switch m.regFile.Regulation {
case "nis2":
if facts.Organization.MeetsNIS2LargeThreshold() || facts.Sector.IsKRITIS {
return string(NIS2EssentialEntity)
}
if facts.Organization.MeetsNIS2SizeThreshold() {
return string(NIS2ImportantEntity)
}
if len(facts.Sector.SpecialServices) > 0 {
return string(NIS2EssentialEntity)
}
return string(NIS2NotAffected)
case "ai_act":
if facts.AIUsage.HasHighRiskAI {
return "hochrisiko"
}
if facts.AIUsage.HasLimitedRiskAI {
return "begrenztes_risiko"
}
return "minimales_risiko"
case "dsgvo":
if facts.DataProtection.IsController {
if facts.DataProtection.LargeScaleProcessing || facts.DataProtection.ProcessesSpecialCategories {
return "verantwortlicher_hochrisiko"
}
return "verantwortlicher"
}
return "auftragsverarbeiter"
default:
return "anwendbar"
}
}
// convertObligation converts a V2Obligation to the framework Obligation struct
func (m *JSONRegulationModule) convertObligation(v2 V2Obligation) Obligation {
obl := Obligation{
ID: v2.ID,
RegulationID: m.regFile.Regulation,
Title: v2.Title,
Description: v2.Description,
Category: ObligationCategory(v2.Category),
Responsible: ResponsibleRole(v2.Responsible),
Priority: ObligationPriority(mapPriority(v2.Priority)),
AppliesWhen: v2.AppliesWhen,
ISO27001Mapping: v2.ISO27001Mapping,
HowToImplement: v2.HowToImplement,
BreakpilotFeature: v2.BreakpilotFeature,
}
// Legal basis
for _, lb := range v2.LegalBasis {
obl.LegalBasis = append(obl.LegalBasis, LegalReference{
Norm: lb.Norm,
Article: lb.Article,
Title: lb.Title,
})
}
// Sanctions
if v2.Sanctions != nil {
obl.Sanctions = &SanctionInfo{
MaxFine: v2.Sanctions.MaxFine,
PersonalLiability: v2.Sanctions.PersonalLiability,
CriminalLiability: v2.Sanctions.CriminalLiability,
Description: v2.Sanctions.Description,
}
}
// Deadline
if v2.Deadline != nil {
obl.Deadline = m.convertDeadline(v2.Deadline)
}
// Evidence
for _, ev := range v2.Evidence {
switch e := ev.(type) {
case string:
obl.Evidence = append(obl.Evidence, EvidenceItem{Name: e, Required: true})
case map[string]interface{}:
name, _ := e["name"].(string)
required, _ := e["required"].(bool)
format, _ := e["format"].(string)
obl.Evidence = append(obl.Evidence, EvidenceItem{
Name: name,
Required: required,
Format: format,
})
}
}
// Store TOM control IDs in ExternalResources for now
obl.ExternalResources = v2.TOMControlIDs
return obl
}
func (m *JSONRegulationModule) convertDeadline(dl *V2Deadline) *Deadline {
d := &Deadline{
Type: DeadlineType(dl.Type),
Duration: dl.Duration,
Interval: dl.Interval,
Event: dl.Event,
}
if dl.Date != "" {
t, err := time.Parse("2006-01-02", dl.Date)
if err == nil {
d.Date = &t
}
}
return d
}
// evaluateLegacyCondition evaluates the legacy applies_when string
func (m *JSONRegulationModule) evaluateLegacyCondition(condition string, facts *UnifiedFacts) bool {
switch condition {
case "always":
return true
case "controller":
return facts.DataProtection.IsController
case "processor":
return facts.DataProtection.IsProcessor
case "high_risk":
return facts.DataProtection.LargeScaleProcessing || facts.DataProtection.SystematicMonitoring || facts.DataProtection.ProcessesSpecialCategories
case "needs_dpo":
return facts.DataProtection.RequiresDSBByLaw || facts.Organization.IsPublicAuthority || facts.Organization.EmployeeCount >= 20
case "uses_processors":
return facts.DataProtection.UsesExternalProcessor
case "cross_border":
return facts.DataProtection.TransfersToThirdCountries || facts.DataProtection.CrossBorderProcessing
case "uses_ai":
return facts.AIUsage.UsesAI
case "high_risk_provider":
return facts.AIUsage.HasHighRiskAI && facts.AIUsage.IsAIProvider
case "high_risk_deployer":
return facts.AIUsage.HasHighRiskAI && facts.AIUsage.IsAIDeployer
case "high_risk_deployer_fria":
return facts.AIUsage.HasHighRiskAI && facts.AIUsage.IsAIDeployer && (facts.Organization.IsPublicAuthority || facts.AIUsage.EducationAccess || facts.AIUsage.EmploymentDecisions)
case "limited_risk":
return facts.AIUsage.HasLimitedRiskAI || facts.AIUsage.AIInteractsWithNaturalPersons
case "gpai_provider":
return facts.AIUsage.UsesGPAI && facts.AIUsage.IsAIProvider
case "gpai_systemic_risk":
return facts.AIUsage.GPAIWithSystemicRisk
default:
// For NIS2-style conditions with classification
if condition == "classification != 'nicht_betroffen'" {
return true // if module is applicable, classification is not "nicht_betroffen"
}
if condition == "classification == 'besonders_wichtige_einrichtung'" {
return facts.Organization.MeetsNIS2LargeThreshold() || facts.Sector.IsKRITIS
}
fmt.Printf("Warning: unknown legacy condition: %s\n", condition)
return true
}
}
// mapPriority normalizes priority strings to standard enum values
func mapPriority(p string) string {
switch p {
case "kritisch", "critical":
return "critical"
case "hoch", "high":
return "high"
case "mittel", "medium":
return "medium"
case "niedrig", "low":
return "low"
default:
return p
}
}

View File

@@ -0,0 +1,300 @@
package ucca
import (
"encoding/json"
"fmt"
"strings"
)
// ObligationConditionEngine evaluates condition trees against UnifiedFacts
type ObligationConditionEngine struct {
fieldMap map[string]func(*UnifiedFacts) interface{}
}
// NewObligationConditionEngine creates a new condition engine with all field mappings
func NewObligationConditionEngine() *ObligationConditionEngine {
e := &ObligationConditionEngine{}
e.fieldMap = e.buildFieldMap()
return e
}
// Evaluate evaluates a condition node against facts
func (e *ObligationConditionEngine) Evaluate(node *ConditionNode, facts *UnifiedFacts) bool {
if node == nil {
return true // nil condition = always applies
}
// Composite: all_of (AND)
if len(node.AllOf) > 0 {
for _, child := range node.AllOf {
if !e.Evaluate(&child, facts) {
return false
}
}
return true
}
// Composite: any_of (OR)
if len(node.AnyOf) > 0 {
for _, child := range node.AnyOf {
if e.Evaluate(&child, facts) {
return true
}
}
return false
}
// Leaf node: field + operator + value
if node.Field != "" {
return e.evaluateLeaf(node, facts)
}
return true
}
func (e *ObligationConditionEngine) evaluateLeaf(node *ConditionNode, facts *UnifiedFacts) bool {
getter, ok := e.fieldMap[node.Field]
if !ok {
fmt.Printf("Warning: unknown field in condition: %s\n", node.Field)
return false
}
actual := getter(facts)
return e.compare(actual, node.Operator, node.Value)
}
func (e *ObligationConditionEngine) compare(actual interface{}, operator string, expected interface{}) bool {
switch strings.ToUpper(operator) {
case "EQUALS":
return e.equals(actual, expected)
case "NOT_EQUALS":
return !e.equals(actual, expected)
case "GREATER_THAN":
return e.toFloat(actual) > e.toFloat(expected)
case "LESS_THAN":
return e.toFloat(actual) < e.toFloat(expected)
case "GREATER_OR_EQUAL":
return e.toFloat(actual) >= e.toFloat(expected)
case "LESS_OR_EQUAL":
return e.toFloat(actual) <= e.toFloat(expected)
case "IN":
return e.inSlice(actual, expected)
case "NOT_IN":
return !e.inSlice(actual, expected)
case "CONTAINS":
return e.contains(actual, expected)
case "EXISTS":
return actual != nil && actual != "" && actual != false && actual != 0
default:
fmt.Printf("Warning: unknown operator: %s\n", operator)
return false
}
}
func (e *ObligationConditionEngine) equals(a, b interface{}) bool {
// Handle bool comparisons
aBool, aIsBool := e.toBool(a)
bBool, bIsBool := e.toBool(b)
if aIsBool && bIsBool {
return aBool == bBool
}
// Handle numeric comparisons
aFloat, aIsNum := e.toFloatOk(a)
bFloat, bIsNum := e.toFloatOk(b)
if aIsNum && bIsNum {
return aFloat == bFloat
}
// String comparison
return fmt.Sprintf("%v", a) == fmt.Sprintf("%v", b)
}
func (e *ObligationConditionEngine) toBool(v interface{}) (bool, bool) {
switch b := v.(type) {
case bool:
return b, true
}
return false, false
}
func (e *ObligationConditionEngine) toFloat(v interface{}) float64 {
f, _ := e.toFloatOk(v)
return f
}
func (e *ObligationConditionEngine) toFloatOk(v interface{}) (float64, bool) {
switch n := v.(type) {
case int:
return float64(n), true
case int64:
return float64(n), true
case float64:
return n, true
case float32:
return float64(n), true
case json.Number:
f, err := n.Float64()
return f, err == nil
}
return 0, false
}
func (e *ObligationConditionEngine) inSlice(actual, expected interface{}) bool {
actualStr := fmt.Sprintf("%v", actual)
switch v := expected.(type) {
case []interface{}:
for _, item := range v {
if fmt.Sprintf("%v", item) == actualStr {
return true
}
}
case []string:
for _, item := range v {
if item == actualStr {
return true
}
}
}
return false
}
func (e *ObligationConditionEngine) contains(actual, expected interface{}) bool {
// Check if actual (slice) contains expected
switch v := actual.(type) {
case []string:
exp := fmt.Sprintf("%v", expected)
for _, item := range v {
if item == exp {
return true
}
}
case string:
return strings.Contains(v, fmt.Sprintf("%v", expected))
}
return false
}
// buildFieldMap creates the mapping from JSON field paths to Go struct accessors
func (e *ObligationConditionEngine) buildFieldMap() map[string]func(*UnifiedFacts) interface{} {
return map[string]func(*UnifiedFacts) interface{}{
// Organization
"organization.employee_count": func(f *UnifiedFacts) interface{} { return f.Organization.EmployeeCount },
"organization.annual_revenue": func(f *UnifiedFacts) interface{} { return f.Organization.AnnualRevenue },
"organization.country": func(f *UnifiedFacts) interface{} { return f.Organization.Country },
"organization.eu_member": func(f *UnifiedFacts) interface{} { return f.Organization.EUMember },
"organization.is_public_authority": func(f *UnifiedFacts) interface{} { return f.Organization.IsPublicAuthority },
"organization.legal_form": func(f *UnifiedFacts) interface{} { return f.Organization.LegalForm },
"organization.size_category": func(f *UnifiedFacts) interface{} { return f.Organization.CalculateSizeCategory() },
"organization.is_part_of_group": func(f *UnifiedFacts) interface{} { return f.Organization.IsPartOfGroup },
// Data Protection
"data_protection.processes_personal_data": func(f *UnifiedFacts) interface{} { return f.DataProtection.ProcessesPersonalData },
"data_protection.is_controller": func(f *UnifiedFacts) interface{} { return f.DataProtection.IsController },
"data_protection.is_processor": func(f *UnifiedFacts) interface{} { return f.DataProtection.IsProcessor },
"data_protection.processes_special_categories": func(f *UnifiedFacts) interface{} { return f.DataProtection.ProcessesSpecialCategories },
"data_protection.processes_children_data": func(f *UnifiedFacts) interface{} { return f.DataProtection.ProcessesMinorData },
"data_protection.processes_minor_data": func(f *UnifiedFacts) interface{} { return f.DataProtection.ProcessesMinorData },
"data_protection.processes_criminal_data": func(f *UnifiedFacts) interface{} { return f.DataProtection.ProcessesCriminalData },
"data_protection.large_scale": func(f *UnifiedFacts) interface{} { return f.DataProtection.LargeScaleProcessing },
"data_protection.large_scale_processing": func(f *UnifiedFacts) interface{} { return f.DataProtection.LargeScaleProcessing },
"data_protection.systematic_monitoring": func(f *UnifiedFacts) interface{} { return f.DataProtection.SystematicMonitoring },
"data_protection.uses_automated_decisions": func(f *UnifiedFacts) interface{} { return f.DataProtection.AutomatedDecisionMaking },
"data_protection.automated_decision_making": func(f *UnifiedFacts) interface{} { return f.DataProtection.AutomatedDecisionMaking },
"data_protection.cross_border_transfer": func(f *UnifiedFacts) interface{} { return f.DataProtection.TransfersToThirdCountries },
"data_protection.transfers_to_third_countries": func(f *UnifiedFacts) interface{} { return f.DataProtection.TransfersToThirdCountries },
"data_protection.cross_border_processing": func(f *UnifiedFacts) interface{} { return f.DataProtection.CrossBorderProcessing },
"data_protection.uses_processors": func(f *UnifiedFacts) interface{} { return f.DataProtection.UsesExternalProcessor },
"data_protection.uses_external_processor": func(f *UnifiedFacts) interface{} { return f.DataProtection.UsesExternalProcessor },
"data_protection.high_risk": func(f *UnifiedFacts) interface{} { return f.DataProtection.LargeScaleProcessing || f.DataProtection.SystematicMonitoring || f.DataProtection.ProcessesSpecialCategories },
"data_protection.uses_profiling": func(f *UnifiedFacts) interface{} { return f.DataProtection.Profiling },
"data_protection.profiling": func(f *UnifiedFacts) interface{} { return f.DataProtection.Profiling },
"data_protection.requires_dsb": func(f *UnifiedFacts) interface{} { return f.DataProtection.RequiresDSBByLaw },
"data_protection.needs_dpo": func(f *UnifiedFacts) interface{} { return f.DataProtection.RequiresDSBByLaw },
"data_protection.has_appointed_dsb": func(f *UnifiedFacts) interface{} { return f.DataProtection.HasAppointedDSB },
"data_protection.data_subject_count": func(f *UnifiedFacts) interface{} { return f.DataProtection.DataSubjectCount },
"data_protection.sccs_in_place": func(f *UnifiedFacts) interface{} { return f.DataProtection.SCCsInPlace },
"data_protection.binding_corporate_rules": func(f *UnifiedFacts) interface{} { return f.DataProtection.BindingCorporateRules },
"data_protection.special_categories": func(f *UnifiedFacts) interface{} { return f.DataProtection.SpecialCategories },
"data_protection.processes_employee_data": func(f *UnifiedFacts) interface{} { return f.DataProtection.ProcessesEmployeeData },
"data_protection.processes_health_data": func(f *UnifiedFacts) interface{} { return f.DataProtection.ProcessesHealthData },
"data_protection.processes_financial_data": func(f *UnifiedFacts) interface{} { return f.DataProtection.ProcessesFinancialData },
"data_protection.uses_cookies": func(f *UnifiedFacts) interface{} { return f.DataProtection.UsesCookies },
"data_protection.uses_tracking": func(f *UnifiedFacts) interface{} { return f.DataProtection.UsesTracking },
"data_protection.uses_video_surveillance": func(f *UnifiedFacts) interface{} { return f.DataProtection.UsesVideoSurveillance },
"data_protection.processes_biometric_data": func(f *UnifiedFacts) interface{} { return f.DataProtection.ProcessesBiometricData },
"data_protection.operates_platform": func(f *UnifiedFacts) interface{} { return f.DataProtection.OperatesPlatform },
"data_protection.platform_user_count": func(f *UnifiedFacts) interface{} { return f.DataProtection.PlatformUserCount },
// AI Usage
"ai_usage.uses_ai": func(f *UnifiedFacts) interface{} { return f.AIUsage.UsesAI },
"ai_usage.is_ai_provider": func(f *UnifiedFacts) interface{} { return f.AIUsage.IsAIProvider },
"ai_usage.is_ai_deployer": func(f *UnifiedFacts) interface{} { return f.AIUsage.IsAIDeployer },
"ai_usage.is_ai_distributor": func(f *UnifiedFacts) interface{} { return f.AIUsage.IsAIDistributor },
"ai_usage.is_ai_importer": func(f *UnifiedFacts) interface{} { return f.AIUsage.IsAIImporter },
"ai_usage.high_risk_ai": func(f *UnifiedFacts) interface{} { return f.AIUsage.HasHighRiskAI },
"ai_usage.has_high_risk_ai": func(f *UnifiedFacts) interface{} { return f.AIUsage.HasHighRiskAI },
"ai_usage.limited_risk_ai": func(f *UnifiedFacts) interface{} { return f.AIUsage.HasLimitedRiskAI },
"ai_usage.has_limited_risk_ai": func(f *UnifiedFacts) interface{} { return f.AIUsage.HasLimitedRiskAI },
"ai_usage.minimal_risk_ai": func(f *UnifiedFacts) interface{} { return f.AIUsage.HasMinimalRiskAI },
"ai_usage.is_gpai_provider": func(f *UnifiedFacts) interface{} { return f.AIUsage.UsesGPAI },
"ai_usage.gpai_systemic_risk": func(f *UnifiedFacts) interface{} { return f.AIUsage.GPAIWithSystemicRisk },
"ai_usage.uses_biometric_ai": func(f *UnifiedFacts) interface{} { return f.AIUsage.BiometricIdentification },
"ai_usage.biometric_identification": func(f *UnifiedFacts) interface{} { return f.AIUsage.BiometricIdentification },
"ai_usage.uses_emotion_recognition": func(f *UnifiedFacts) interface{} { return f.AIUsage.EmotionRecognition },
"ai_usage.ai_in_education": func(f *UnifiedFacts) interface{} { return f.AIUsage.EducationAccess },
"ai_usage.ai_in_employment": func(f *UnifiedFacts) interface{} { return f.AIUsage.EmploymentDecisions },
"ai_usage.ai_in_critical_infrastructure": func(f *UnifiedFacts) interface{} { return f.AIUsage.CriticalInfrastructure },
"ai_usage.ai_in_law_enforcement": func(f *UnifiedFacts) interface{} { return f.AIUsage.LawEnforcement },
"ai_usage.ai_in_justice": func(f *UnifiedFacts) interface{} { return f.AIUsage.JusticeAdministration },
"ai_usage.uses_generative_ai": func(f *UnifiedFacts) interface{} { return f.AIUsage.AIInteractsWithNaturalPersons },
"ai_usage.uses_deepfakes": func(f *UnifiedFacts) interface{} { return f.AIUsage.GeneratesDeepfakes },
"ai_usage.ai_makes_decisions": func(f *UnifiedFacts) interface{} { return f.DataProtection.AutomatedDecisionMaking },
"ai_usage.ai_interacts_with_persons": func(f *UnifiedFacts) interface{} { return f.AIUsage.AIInteractsWithNaturalPersons },
// Sector
"sector.primary_sector": func(f *UnifiedFacts) interface{} { return f.Sector.PrimarySector },
"sector.is_kritis": func(f *UnifiedFacts) interface{} { return f.Sector.IsKRITIS },
"sector.nis2_applicable": func(f *UnifiedFacts) interface{} { return f.Sector.PrimarySector != "" && f.Sector.PrimarySector != "other" },
"sector.nis2_classification": func(f *UnifiedFacts) interface{} { return f.Sector.NIS2Classification },
"sector.is_annex_i": func(f *UnifiedFacts) interface{} { return f.Sector.IsAnnexI },
"sector.is_annex_ii": func(f *UnifiedFacts) interface{} { return f.Sector.IsAnnexII },
"sector.provides_dns": func(f *UnifiedFacts) interface{} { return containsString(f.Sector.SpecialServices, "dns") },
"sector.provides_cloud": func(f *UnifiedFacts) interface{} { return containsString(f.Sector.SpecialServices, "cloud") },
"sector.provides_cdn": func(f *UnifiedFacts) interface{} { return containsString(f.Sector.SpecialServices, "cdn") },
"sector.provides_data_center": func(f *UnifiedFacts) interface{} { return containsString(f.Sector.SpecialServices, "datacenter") },
"sector.provides_managed_services": func(f *UnifiedFacts) interface{} { return containsString(f.Sector.SpecialServices, "msp") || containsString(f.Sector.SpecialServices, "mssp") },
"sector.is_financial_institution": func(f *UnifiedFacts) interface{} { return f.Sector.IsFinancialInstitution },
"sector.is_healthcare_provider": func(f *UnifiedFacts) interface{} { return f.Sector.IsHealthcareProvider },
// IT Security
"it_security.has_isms": func(f *UnifiedFacts) interface{} { return f.ITSecurity.HasISMS },
"it_security.iso27001_certified": func(f *UnifiedFacts) interface{} { return f.ITSecurity.ISO27001Certified },
"it_security.has_incident_process": func(f *UnifiedFacts) interface{} { return f.ITSecurity.HasIncidentProcess },
"it_security.has_mfa": func(f *UnifiedFacts) interface{} { return f.ITSecurity.HasMFA },
"it_security.has_encryption": func(f *UnifiedFacts) interface{} { return f.ITSecurity.HasEncryption },
"it_security.has_backup": func(f *UnifiedFacts) interface{} { return f.ITSecurity.HasBackup },
"it_security.has_bcm": func(f *UnifiedFacts) interface{} { return f.ITSecurity.HasBCM },
"it_security.has_siem": func(f *UnifiedFacts) interface{} { return f.ITSecurity.HasSecurityMonitoring },
"it_security.has_network_segmentation": func(f *UnifiedFacts) interface{} { return f.ITSecurity.HasNetworkSegmentation },
"it_security.has_vulnerability_mgmt": func(f *UnifiedFacts) interface{} { return f.ITSecurity.HasVulnerabilityMgmt },
// Financial
"financial.dora_applies": func(f *UnifiedFacts) interface{} { return f.Financial.DORAApplies },
"financial.is_regulated": func(f *UnifiedFacts) interface{} { return f.Financial.IsRegulated },
"financial.has_critical_ict": func(f *UnifiedFacts) interface{} { return f.Financial.HasCriticalICT },
"financial.ict_outsourced": func(f *UnifiedFacts) interface{} { return f.Financial.ICTOutsourced },
"financial.concentration_risk": func(f *UnifiedFacts) interface{} { return f.Financial.ConcentrationRisk },
// Supply Chain
"supply_chain.has_risk_management": func(f *UnifiedFacts) interface{} { return f.SupplyChain.HasSupplyChainRiskMgmt },
"supply_chain.supplier_count": func(f *UnifiedFacts) interface{} { return f.SupplyChain.SupplierCount },
// Personnel
"personnel.has_ciso": func(f *UnifiedFacts) interface{} { return f.Personnel.HasCISO },
"personnel.has_dpo": func(f *UnifiedFacts) interface{} { return f.Personnel.HasDPO },
"personnel.has_ai_competence": func(f *UnifiedFacts) interface{} { return f.Personnel.HasAICompetence },
"personnel.has_ai_governance": func(f *UnifiedFacts) interface{} { return f.Personnel.HasAIGovernance },
"personnel.has_compliance_officer": func(f *UnifiedFacts) interface{} { return f.Personnel.HasComplianceOfficer },
}
}

View File

@@ -0,0 +1,176 @@
package ucca
import (
"testing"
)
func TestConditionEngine_NilNode(t *testing.T) {
engine := NewObligationConditionEngine()
facts := NewUnifiedFacts()
if !engine.Evaluate(nil, facts) {
t.Error("nil node should return true (always applies)")
}
}
func TestConditionEngine_LeafEquals(t *testing.T) {
engine := NewObligationConditionEngine()
tests := []struct {
name string
field string
value interface{}
facts func() *UnifiedFacts
expected bool
}{
{
name: "is_controller true",
field: "data_protection.is_controller", value: true,
facts: func() *UnifiedFacts {
f := NewUnifiedFacts()
f.DataProtection.IsController = true
return f
},
expected: true,
},
{
name: "is_controller false mismatch",
field: "data_protection.is_controller", value: true,
facts: func() *UnifiedFacts { return NewUnifiedFacts() },
expected: false,
},
{
name: "employee_count equals",
field: "organization.employee_count", value: float64(50),
facts: func() *UnifiedFacts {
f := NewUnifiedFacts()
f.Organization.EmployeeCount = 50
return f
},
expected: true,
},
{
name: "uses_ai true",
field: "ai_usage.uses_ai", value: true,
facts: func() *UnifiedFacts {
f := NewUnifiedFacts()
f.AIUsage.UsesAI = true
return f
},
expected: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
node := &ConditionNode{
Field: tt.field,
Operator: "EQUALS",
Value: tt.value,
}
result := engine.Evaluate(node, tt.facts())
if result != tt.expected {
t.Errorf("expected %v, got %v", tt.expected, result)
}
})
}
}
func TestConditionEngine_GreaterThan(t *testing.T) {
engine := NewObligationConditionEngine()
facts := NewUnifiedFacts()
facts.Organization.EmployeeCount = 50
node := &ConditionNode{
Field: "organization.employee_count",
Operator: "GREATER_THAN",
Value: float64(19),
}
if !engine.Evaluate(node, facts) {
t.Error("50 > 19 should be true")
}
facts.Organization.EmployeeCount = 10
if engine.Evaluate(node, facts) {
t.Error("10 > 19 should be false")
}
}
func TestConditionEngine_AllOf(t *testing.T) {
engine := NewObligationConditionEngine()
facts := NewUnifiedFacts()
facts.DataProtection.IsController = true
facts.DataProtection.ProcessesSpecialCategories = true
node := &ConditionNode{
AllOf: []ConditionNode{
{Field: "data_protection.is_controller", Operator: "EQUALS", Value: true},
{Field: "data_protection.processes_special_categories", Operator: "EQUALS", Value: true},
},
}
if !engine.Evaluate(node, facts) {
t.Error("all_of with both true should be true")
}
facts.DataProtection.ProcessesSpecialCategories = false
if engine.Evaluate(node, facts) {
t.Error("all_of with one false should be false")
}
}
func TestConditionEngine_AnyOf(t *testing.T) {
engine := NewObligationConditionEngine()
facts := NewUnifiedFacts()
facts.DataProtection.RequiresDSBByLaw = false
node := &ConditionNode{
AnyOf: []ConditionNode{
{Field: "data_protection.needs_dpo", Operator: "EQUALS", Value: true},
{Field: "organization.employee_count", Operator: "GREATER_THAN", Value: float64(19)},
},
}
if engine.Evaluate(node, facts) {
t.Error("any_of with both false should be false")
}
facts.Organization.EmployeeCount = 25
if !engine.Evaluate(node, facts) {
t.Error("any_of with one true should be true")
}
}
func TestConditionEngine_UnknownField(t *testing.T) {
engine := NewObligationConditionEngine()
facts := NewUnifiedFacts()
node := &ConditionNode{
Field: "nonexistent.field",
Operator: "EQUALS",
Value: true,
}
if engine.Evaluate(node, facts) {
t.Error("unknown field should return false")
}
}
func TestConditionEngine_NotEquals(t *testing.T) {
engine := NewObligationConditionEngine()
facts := NewUnifiedFacts()
facts.Organization.Country = "DE"
node := &ConditionNode{
Field: "organization.country",
Operator: "NOT_EQUALS",
Value: "US",
}
if !engine.Evaluate(node, facts) {
t.Error("DE != US should be true")
}
node.Value = "DE"
if engine.Evaluate(node, facts) {
t.Error("DE != DE should be false")
}
}

View File

@@ -296,6 +296,9 @@ type ManagementObligationsOverview struct {
// Executive summary for C-Level
ExecutiveSummary ExecutiveSummary `json:"executive_summary"`
// TOM Control Requirements (derived from obligations, v2)
TOMControlRequirements []TOMControlRequirement `json:"tom_control_requirements,omitempty"`
}
// ============================================================================

View File

@@ -22,43 +22,64 @@ type ObligationsRegistry struct {
modules map[string]RegulationModule
}
// NewObligationsRegistry creates a new registry and registers all default modules
// NewObligationsRegistry creates a new registry and registers all default modules.
// It loads v2 JSON modules first; for regulations without v2 JSON, falls back to YAML modules.
func NewObligationsRegistry() *ObligationsRegistry {
r := &ObligationsRegistry{
modules: make(map[string]RegulationModule),
}
// Register default modules
// NIS2 module
nis2Module, err := NewNIS2Module()
if err != nil {
fmt.Printf("Warning: Could not load NIS2 module: %v\n", err)
} else {
r.Register(nis2Module)
// Try to load v2 JSON modules first
v2Loaded := r.loadV2Modules()
// Fall back to YAML modules for regulations not covered by v2
if !v2Loaded["nis2"] {
if nis2Module, err := NewNIS2Module(); err == nil {
r.Register(nis2Module)
} else {
fmt.Printf("Warning: Could not load NIS2 module: %v\n", err)
}
}
// DSGVO module
dsgvoModule, err := NewDSGVOModule()
if err != nil {
fmt.Printf("Warning: Could not load DSGVO module: %v\n", err)
} else {
r.Register(dsgvoModule)
if !v2Loaded["dsgvo"] {
if dsgvoModule, err := NewDSGVOModule(); err == nil {
r.Register(dsgvoModule)
} else {
fmt.Printf("Warning: Could not load DSGVO module: %v\n", err)
}
}
// AI Act module
aiActModule, err := NewAIActModule()
if err != nil {
fmt.Printf("Warning: Could not load AI Act module: %v\n", err)
} else {
r.Register(aiActModule)
if !v2Loaded["ai_act"] {
if aiActModule, err := NewAIActModule(); err == nil {
r.Register(aiActModule)
} else {
fmt.Printf("Warning: Could not load AI Act module: %v\n", err)
}
}
// Future modules will be registered here:
// r.Register(NewDORAModule())
return r
}
// loadV2Modules attempts to load all v2 JSON regulation modules
func (r *ObligationsRegistry) loadV2Modules() map[string]bool {
loaded := make(map[string]bool)
regulations, err := LoadAllV2Regulations()
if err != nil {
fmt.Printf("Info: No v2 regulations found, using YAML modules: %v\n", err)
return loaded
}
for regID, regFile := range regulations {
module := NewJSONRegulationModule(regFile)
r.Register(module)
loaded[regID] = true
fmt.Printf("Loaded v2 regulation module: %s (%d obligations)\n", regID, len(regFile.Obligations))
}
return loaded
}
// NewObligationsRegistryWithModules creates a registry with specific modules
func NewObligationsRegistryWithModules(modules ...RegulationModule) *ObligationsRegistry {
r := &ObligationsRegistry{

View File

@@ -0,0 +1,128 @@
package ucca
// ScopeDecision represents the output from the frontend Scope Wizard
type ScopeDecision struct {
// Company profile
EmployeeCount int `json:"employee_count"`
AnnualRevenue float64 `json:"annual_revenue"`
Country string `json:"country"`
Industry string `json:"industry"`
LegalForm string `json:"legal_form,omitempty"`
// Scope wizard answers
ProcessesPersonalData bool `json:"processes_personal_data"`
IsController bool `json:"is_controller"`
IsProcessor bool `json:"is_processor"`
DataArt9 bool `json:"data_art9"`
DataMinors bool `json:"data_minors"`
LargeScale bool `json:"large_scale"`
SystematicMonitoring bool `json:"systematic_monitoring"`
CrossBorderTransfer bool `json:"cross_border_transfer"`
UsesProcessors bool `json:"uses_processors"`
AutomatedDecisions bool `json:"automated_decisions"`
ProcessesEmployeeData bool `json:"processes_employee_data"`
ProcessesHealthData bool `json:"processes_health_data"`
ProcessesFinancialData bool `json:"processes_financial_data"`
UsesCookies bool `json:"uses_cookies"`
UsesTracking bool `json:"uses_tracking"`
UsesVideoSurveillance bool `json:"uses_video_surveillance"`
OperatesPlatform bool `json:"operates_platform"`
PlatformUserCount int `json:"platform_user_count,omitempty"`
// AI usage
ProcAIUsage bool `json:"proc_ai_usage"`
IsAIProvider bool `json:"is_ai_provider"`
IsAIDeployer bool `json:"is_ai_deployer"`
HighRiskAI bool `json:"high_risk_ai"`
LimitedRiskAI bool `json:"limited_risk_ai"`
// Sector / NIS2
Sector string `json:"sector,omitempty"`
SpecialServices []string `json:"special_services,omitempty"`
IsKRITIS bool `json:"is_kritis"`
IsFinancialInstitution bool `json:"is_financial_institution"`
// Scope engine results
DeterminedLevel string `json:"determined_level,omitempty"` // L1-L4
TriggeredRules []string `json:"triggered_rules,omitempty"`
RequiredDocuments []string `json:"required_documents,omitempty"`
CertTarget string `json:"cert_target,omitempty"`
}
// MapScopeToFacts converts a ScopeDecision to UnifiedFacts
func MapScopeToFacts(scope *ScopeDecision) *UnifiedFacts {
facts := NewUnifiedFacts()
// Organization
facts.Organization.EmployeeCount = scope.EmployeeCount
facts.Organization.AnnualRevenue = scope.AnnualRevenue
facts.Organization.Country = scope.Country
facts.Organization.LegalForm = scope.LegalForm
if scope.Country != "" {
facts.Organization.EUMember = isEUCountryScope(scope.Country)
}
// Data Protection
facts.DataProtection.ProcessesPersonalData = scope.ProcessesPersonalData
facts.DataProtection.IsController = scope.IsController
facts.DataProtection.IsProcessor = scope.IsProcessor
facts.DataProtection.ProcessesSpecialCategories = scope.DataArt9
facts.DataProtection.ProcessesMinorData = scope.DataMinors
facts.DataProtection.LargeScaleProcessing = scope.LargeScale
facts.DataProtection.SystematicMonitoring = scope.SystematicMonitoring
facts.DataProtection.TransfersToThirdCountries = scope.CrossBorderTransfer
facts.DataProtection.CrossBorderProcessing = scope.CrossBorderTransfer
facts.DataProtection.UsesExternalProcessor = scope.UsesProcessors
facts.DataProtection.AutomatedDecisionMaking = scope.AutomatedDecisions
facts.DataProtection.AutomatedDecisions = scope.AutomatedDecisions
facts.DataProtection.ProcessesEmployeeData = scope.ProcessesEmployeeData
facts.DataProtection.ProcessesHealthData = scope.ProcessesHealthData
facts.DataProtection.ProcessesFinancialData = scope.ProcessesFinancialData
facts.DataProtection.UsesCookies = scope.UsesCookies
facts.DataProtection.UsesTracking = scope.UsesTracking
facts.DataProtection.UsesVideoSurveillance = scope.UsesVideoSurveillance
facts.DataProtection.OperatesPlatform = scope.OperatesPlatform
facts.DataProtection.PlatformUserCount = scope.PlatformUserCount
// DPO requirement (German law: >= 20 employees processing personal data)
if scope.EmployeeCount >= 20 && scope.ProcessesPersonalData {
facts.DataProtection.RequiresDSBByLaw = true
}
// AI Usage
facts.AIUsage.UsesAI = scope.ProcAIUsage
facts.AIUsage.IsAIProvider = scope.IsAIProvider
facts.AIUsage.IsAIDeployer = scope.IsAIDeployer
facts.AIUsage.HasHighRiskAI = scope.HighRiskAI
facts.AIUsage.HasLimitedRiskAI = scope.LimitedRiskAI
// Sector
if scope.Sector != "" {
facts.Sector.PrimarySector = scope.Sector
} else if scope.Industry != "" {
facts.MapDomainToSector(scope.Industry)
}
facts.Sector.SpecialServices = scope.SpecialServices
facts.Sector.IsKRITIS = scope.IsKRITIS
facts.Sector.KRITISThresholdMet = scope.IsKRITIS
facts.Sector.IsFinancialInstitution = scope.IsFinancialInstitution
// Financial
if scope.IsFinancialInstitution {
facts.Financial.IsRegulated = true
facts.Financial.DORAApplies = true
}
return facts
}
func isEUCountryScope(country string) bool {
euCountries := map[string]bool{
"DE": true, "AT": true, "BE": true, "BG": true, "HR": true, "CY": true,
"CZ": true, "DK": true, "EE": true, "FI": true, "FR": true, "GR": true,
"HU": true, "IE": true, "IT": true, "LV": true, "LT": true, "LU": true,
"MT": true, "NL": true, "PL": true, "PT": true, "RO": true, "SK": true,
"SI": true, "ES": true, "SE": true,
}
return euCountries[country]
}

View File

@@ -0,0 +1,160 @@
package ucca
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"runtime"
)
// TOMControl represents a single TOM control from the control library
type TOMControl struct {
ID string `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
Type string `json:"type"` // ORGANIZATIONAL, TECHNICAL
ImplementationGuidance string `json:"implementation_guidance,omitempty"`
Evidence []string `json:"evidence,omitempty"`
AppliesIf *TOMAppliesIf `json:"applies_if,omitempty"`
RiskTier string `json:"risk_tier"` // BASELINE, ENHANCED, ADVANCED
Mappings TOMControlMapping `json:"mappings,omitempty"`
ReviewFrequency string `json:"review_frequency,omitempty"`
Priority string `json:"priority"` // CRITICAL, HIGH, MEDIUM, LOW
Complexity string `json:"complexity,omitempty"`
DomainID string `json:"domain_id,omitempty"` // set during loading
}
// TOMAppliesIf defines when a control applies
type TOMAppliesIf struct {
Field string `json:"field"`
Operator string `json:"operator"`
Value interface{} `json:"value"`
}
// TOMControlMapping maps a control to various standards
type TOMControlMapping struct {
GDPR []string `json:"gdpr,omitempty"`
ISO27001 []string `json:"iso27001,omitempty"`
BSI []string `json:"bsi,omitempty"`
SDM []string `json:"sdm,omitempty"`
NIS2 []string `json:"nis2,omitempty"`
}
// TOMControlDomain represents a domain of controls
type TOMControlDomain struct {
ID string `json:"id"`
Name string `json:"name"`
Objective string `json:"objective"`
Controls []TOMControl `json:"controls"`
}
// TOMControlLibrary is the top-level structure of the control library
type TOMControlLibrary struct {
Schema string `json:"schema"`
Version string `json:"version"`
Domains []TOMControlDomain `json:"domains"`
}
// TOMControlIndex provides fast lookup of controls
type TOMControlIndex struct {
ByID map[string]*TOMControl
ByDomain map[string][]*TOMControl
ByGDPRArticle map[string][]*TOMControl
AllControls []*TOMControl
}
// LoadTOMControls loads the TOM control library from JSON
func LoadTOMControls() (*TOMControlIndex, error) {
data, err := readTOMControlsFile()
if err != nil {
return nil, err
}
var library TOMControlLibrary
if err := json.Unmarshal(data, &library); err != nil {
return nil, fmt.Errorf("failed to parse TOM controls: %w", err)
}
return buildTOMIndex(&library), nil
}
func readTOMControlsFile() ([]byte, error) {
// Try multiple candidate paths
candidates := []string{
"policies/tom_controls_v1.json",
"../policies/tom_controls_v1.json",
"../../policies/tom_controls_v1.json",
}
// Also try relative to source file
_, filename, _, ok := runtime.Caller(0)
if ok {
srcDir := filepath.Dir(filename)
candidates = append(candidates,
filepath.Join(srcDir, "../../policies/tom_controls_v1.json"),
)
}
for _, p := range candidates {
abs, err := filepath.Abs(p)
if err != nil {
continue
}
data, err := os.ReadFile(abs)
if err == nil {
return data, nil
}
}
return nil, fmt.Errorf("tom_controls_v1.json not found in any candidate path")
}
func buildTOMIndex(library *TOMControlLibrary) *TOMControlIndex {
idx := &TOMControlIndex{
ByID: make(map[string]*TOMControl),
ByDomain: make(map[string][]*TOMControl),
ByGDPRArticle: make(map[string][]*TOMControl),
}
for i := range library.Domains {
domain := &library.Domains[i]
for j := range domain.Controls {
ctrl := &domain.Controls[j]
ctrl.DomainID = domain.ID
idx.ByID[ctrl.ID] = ctrl
idx.ByDomain[domain.ID] = append(idx.ByDomain[domain.ID], ctrl)
idx.AllControls = append(idx.AllControls, ctrl)
// Index by GDPR article
for _, article := range ctrl.Mappings.GDPR {
idx.ByGDPRArticle[article] = append(idx.ByGDPRArticle[article], ctrl)
}
}
}
return idx
}
// GetControl returns a control by ID
func (idx *TOMControlIndex) GetControl(id string) (*TOMControl, bool) {
ctrl, ok := idx.ByID[id]
return ctrl, ok
}
// GetControlsByDomain returns all controls for a domain
func (idx *TOMControlIndex) GetControlsByDomain(domain string) []*TOMControl {
return idx.ByDomain[domain]
}
// GetControlsByGDPRArticle returns controls mapped to a GDPR article
func (idx *TOMControlIndex) GetControlsByGDPRArticle(article string) []*TOMControl {
return idx.ByGDPRArticle[article]
}
// ValidateControlID checks if a control ID exists
func (idx *TOMControlIndex) ValidateControlID(id string) bool {
_, ok := idx.ByID[id]
return ok
}

View File

@@ -0,0 +1,259 @@
package ucca
import (
"fmt"
"sort"
)
// ControlStatus represents the implementation status of a control
type ControlStatus string
const (
ControlImplemented ControlStatus = "IMPLEMENTED"
ControlPartial ControlStatus = "PARTIAL"
ControlNotImplemented ControlStatus = "NOT_IMPLEMENTED"
ControlNotApplicable ControlStatus = "NOT_APPLICABLE"
)
// GapAnalysisRequest is the input for gap analysis
type GapAnalysisRequest struct {
// Obligations that apply (from assessment)
Obligations []Obligation `json:"obligations"`
// Current implementation status of controls
ControlStatusMap map[string]ControlStatus `json:"control_status_map"` // control_id -> status
}
// GapAnalysisResult is the output of gap analysis
type GapAnalysisResult struct {
CompliancePercent float64 `json:"compliance_percent"` // 0-100
TotalControls int `json:"total_controls"`
ImplementedControls int `json:"implemented_controls"`
PartialControls int `json:"partial_controls"`
MissingControls int `json:"missing_controls"`
Gaps []GapItem `json:"gaps"`
PriorityActions []PriorityAction `json:"priority_actions"`
ByDomain map[string]DomainGap `json:"by_domain"`
}
// GapItem represents a single compliance gap
type GapItem struct {
ControlID string `json:"control_id"`
ControlTitle string `json:"control_title"`
ControlDomain string `json:"control_domain"`
Status ControlStatus `json:"status"`
Priority string `json:"priority"`
ObligationIDs []string `json:"obligation_ids"`
RequiredByCount int `json:"required_by_count"`
Impact string `json:"impact"` // "critical", "high", "medium", "low"
}
// PriorityAction is a recommended action to close gaps
type PriorityAction struct {
Rank int `json:"rank"`
Action string `json:"action"`
ControlIDs []string `json:"control_ids"`
Impact string `json:"impact"`
Effort string `json:"effort"` // "low", "medium", "high"
}
// DomainGap summarizes gaps per TOM domain
type DomainGap struct {
DomainID string `json:"domain_id"`
DomainName string `json:"domain_name"`
TotalControls int `json:"total_controls"`
ImplementedControls int `json:"implemented_controls"`
CompliancePercent float64 `json:"compliance_percent"`
}
// TOMGapAnalyzer performs gap analysis between obligations and control implementation
type TOMGapAnalyzer struct {
mapper *TOMObligationMapper
tomIndex *TOMControlIndex
}
// NewTOMGapAnalyzer creates a new gap analyzer
func NewTOMGapAnalyzer(mapper *TOMObligationMapper, tomIndex *TOMControlIndex) *TOMGapAnalyzer {
return &TOMGapAnalyzer{
mapper: mapper,
tomIndex: tomIndex,
}
}
// Analyze performs gap analysis
func (g *TOMGapAnalyzer) Analyze(req *GapAnalysisRequest) *GapAnalysisResult {
result := &GapAnalysisResult{
Gaps: []GapItem{},
PriorityActions: []PriorityAction{},
ByDomain: make(map[string]DomainGap),
}
// Derive required controls from obligations
requirements := g.mapper.DeriveControlsFromObligations(req.Obligations)
result.TotalControls = len(requirements)
// Track domain stats
domainTotal := make(map[string]int)
domainImplemented := make(map[string]int)
for _, ctrl := range requirements {
controlID := ctrl.Control.ID
domain := ctrl.Control.DomainID
domainTotal[domain]++
status, hasStatus := req.ControlStatusMap[controlID]
if !hasStatus {
status = ControlNotImplemented
}
switch status {
case ControlImplemented:
result.ImplementedControls++
domainImplemented[domain]++
case ControlPartial:
result.PartialControls++
// Count partial as 0.5 for domain
domainImplemented[domain]++ // simplified
result.Gaps = append(result.Gaps, GapItem{
ControlID: controlID,
ControlTitle: ctrl.Control.Title,
ControlDomain: domain,
Status: ControlPartial,
Priority: ctrl.Priority,
ObligationIDs: ctrl.ObligationIDs,
RequiredByCount: ctrl.RequiredByCount,
Impact: ctrl.Priority,
})
case ControlNotImplemented:
result.MissingControls++
result.Gaps = append(result.Gaps, GapItem{
ControlID: controlID,
ControlTitle: ctrl.Control.Title,
ControlDomain: domain,
Status: ControlNotImplemented,
Priority: ctrl.Priority,
ObligationIDs: ctrl.ObligationIDs,
RequiredByCount: ctrl.RequiredByCount,
Impact: ctrl.Priority,
})
case ControlNotApplicable:
result.TotalControls-- // Don't count N/A
domainTotal[domain]--
}
}
// Calculate compliance percent
if result.TotalControls > 0 {
implemented := float64(result.ImplementedControls) + float64(result.PartialControls)*0.5
result.CompliancePercent = (implemented / float64(result.TotalControls)) * 100
} else {
result.CompliancePercent = 100
}
// Sort gaps by priority
priorityRank := map[string]int{"critical": 0, "high": 1, "medium": 2, "low": 3}
sort.Slice(result.Gaps, func(i, j int) bool {
ri := priorityRank[result.Gaps[i].Priority]
rj := priorityRank[result.Gaps[j].Priority]
if ri != rj {
return ri < rj
}
return result.Gaps[i].RequiredByCount > result.Gaps[j].RequiredByCount
})
// Build domain gaps
for domain, total := range domainTotal {
if total <= 0 {
continue
}
impl := domainImplemented[domain]
pct := float64(impl) / float64(total) * 100
domainName := domain
if ctrls := g.tomIndex.GetControlsByDomain(domain); len(ctrls) > 0 {
domainName = domain // Use domain ID as name
}
result.ByDomain[domain] = DomainGap{
DomainID: domain,
DomainName: domainName,
TotalControls: total,
ImplementedControls: impl,
CompliancePercent: pct,
}
}
// Generate priority actions
result.PriorityActions = g.generatePriorityActions(result.Gaps)
return result
}
func (g *TOMGapAnalyzer) generatePriorityActions(gaps []GapItem) []PriorityAction {
var actions []PriorityAction
rank := 1
// Group critical gaps by domain
domainGaps := make(map[string][]GapItem)
for _, gap := range gaps {
if gap.Status == ControlNotImplemented {
domainGaps[gap.ControlDomain] = append(domainGaps[gap.ControlDomain], gap)
}
}
// Generate actions for domains with most critical gaps
type domainPriority struct {
domain string
gaps []GapItem
critCount int
}
var dp []domainPriority
for domain, gs := range domainGaps {
crit := 0
for _, g := range gs {
if g.Priority == "critical" {
crit++
}
}
dp = append(dp, domainPriority{domain, gs, crit})
}
sort.Slice(dp, func(i, j int) bool {
if dp[i].critCount != dp[j].critCount {
return dp[i].critCount > dp[j].critCount
}
return len(dp[i].gaps) > len(dp[j].gaps)
})
for _, d := range dp {
if rank > 10 {
break
}
var controlIDs []string
for _, g := range d.gaps {
controlIDs = append(controlIDs, g.ControlID)
}
impact := "medium"
if d.critCount > 0 {
impact = "critical"
} else if len(d.gaps) > 3 {
impact = "high"
}
effort := "medium"
if len(d.gaps) > 5 {
effort = "high"
} else if len(d.gaps) <= 2 {
effort = "low"
}
actions = append(actions, PriorityAction{
Rank: rank,
Action: fmt.Sprintf("Domain %s: %d fehlende Controls implementieren", d.domain, len(d.gaps)),
ControlIDs: controlIDs,
Impact: impact,
Effort: effort,
})
rank++
}
return actions
}

View File

@@ -0,0 +1,175 @@
package ucca
import (
"testing"
)
func TestTOMControlLoader(t *testing.T) {
index, err := LoadTOMControls()
if err != nil {
t.Skipf("TOM controls not found: %v", err)
}
if len(index.ByID) == 0 {
t.Error("expected controls indexed by ID")
}
if len(index.ByDomain) == 0 {
t.Error("expected controls indexed by domain")
}
t.Logf("Loaded %d TOM controls across %d domains", len(index.ByID), len(index.ByDomain))
// Check known control
ctrl, ok := index.GetControl("TOM.GOV.01")
if !ok || ctrl == nil {
t.Error("expected TOM.GOV.01 to exist")
} else if ctrl.Title == "" {
t.Error("expected TOM.GOV.01 to have a title")
}
// Check domain
govCtrls := index.GetControlsByDomain("GOV")
if len(govCtrls) == 0 {
t.Error("expected GOV domain to have controls")
}
// Validate known ID
if !index.ValidateControlID("TOM.GOV.01") {
t.Error("TOM.GOV.01 should be valid")
}
if index.ValidateControlID("TOM.FAKE.99") {
t.Error("TOM.FAKE.99 should be invalid")
}
}
func TestTOMObligationMapper_FromObligations(t *testing.T) {
index, err := LoadTOMControls()
if err != nil {
t.Skipf("TOM controls not found: %v", err)
}
// Create test obligations with tom_control_ids
obligations := []V2Obligation{
{
ID: "TEST-OBL-001",
TOMControlIDs: []string{"TOM.GOV.01", "TOM.GOV.02"},
Priority: "kritisch",
},
{
ID: "TEST-OBL-002",
TOMControlIDs: []string{"TOM.GOV.01", "TOM.CRYPTO.01"},
Priority: "hoch",
},
}
mapper := NewTOMObligationMapperFromObligations(index, obligations)
// Check obligation->control
controls := mapper.GetControlsForObligation("TEST-OBL-001")
if len(controls) != 2 {
t.Errorf("expected 2 controls for TEST-OBL-001, got %d", len(controls))
}
// Check control->obligation (reverse)
oblIDs := mapper.GetObligationsForControl("TOM.GOV.01")
if len(oblIDs) != 2 {
t.Errorf("expected 2 obligations for TOM.GOV.01, got %d", len(oblIDs))
}
// Check deduplicated requirements
frameworkObls := make([]Obligation, len(obligations))
for i, o := range obligations {
frameworkObls[i] = Obligation{
ID: o.ID,
Priority: ObligationPriority(o.Priority),
ExternalResources: o.TOMControlIDs,
}
}
reqs := mapper.DeriveControlsFromObligations(frameworkObls)
if len(reqs) == 0 {
t.Error("expected derived control requirements")
}
// GOV.01 should appear once but with 2 obligation references
for _, req := range reqs {
if req.Control != nil && req.Control.ID == "TOM.GOV.01" {
if req.RequiredByCount != 2 {
t.Errorf("expected TOM.GOV.01 required by 2, got %d", req.RequiredByCount)
}
if req.Priority != "kritisch" {
t.Errorf("expected highest priority 'kritisch', got '%s'", req.Priority)
}
return
}
}
t.Error("TOM.GOV.01 not found in derived requirements")
}
func TestTOMGapAnalysis(t *testing.T) {
index, err := LoadTOMControls()
if err != nil {
t.Skipf("TOM controls not found: %v", err)
}
obligations := []V2Obligation{
{ID: "T-001", TOMControlIDs: []string{"TOM.GOV.01"}, Priority: "kritisch"},
{ID: "T-002", TOMControlIDs: []string{"TOM.GOV.01", "TOM.CRYPTO.01"}, Priority: "hoch"},
}
mapper := NewTOMObligationMapperFromObligations(index, obligations)
analyzer := NewTOMGapAnalyzer(mapper, index)
frameworkObls := []Obligation{
{ID: "T-001", Priority: "kritisch", ExternalResources: []string{"TOM.GOV.01"}},
{ID: "T-002", Priority: "hoch", ExternalResources: []string{"TOM.GOV.01", "TOM.CRYPTO.01"}},
}
result := analyzer.Analyze(&GapAnalysisRequest{
Obligations: frameworkObls,
ControlStatusMap: map[string]ControlStatus{
"TOM.GOV.01": ControlImplemented,
"TOM.CRYPTO.01": ControlNotImplemented,
},
})
if result.TotalControls != 2 {
t.Errorf("expected 2 total controls, got %d", result.TotalControls)
}
if result.ImplementedControls != 1 {
t.Errorf("expected 1 implemented, got %d", result.ImplementedControls)
}
if result.MissingControls != 1 {
t.Errorf("expected 1 missing, got %d", result.MissingControls)
}
if result.CompliancePercent != 50 {
t.Errorf("expected 50%% compliance, got %.1f%%", result.CompliancePercent)
}
if len(result.Gaps) != 1 {
t.Errorf("expected 1 gap, got %d", len(result.Gaps))
}
}
func TestTOMGapAnalysis_AllImplemented(t *testing.T) {
index, err := LoadTOMControls()
if err != nil {
t.Skipf("TOM controls not found: %v", err)
}
obligations := []V2Obligation{
{ID: "T-001", TOMControlIDs: []string{"TOM.GOV.01"}, Priority: "hoch"},
}
mapper := NewTOMObligationMapperFromObligations(index, obligations)
analyzer := NewTOMGapAnalyzer(mapper, index)
result := analyzer.Analyze(&GapAnalysisRequest{
Obligations: []Obligation{{ID: "T-001", Priority: "hoch", ExternalResources: []string{"TOM.GOV.01"}}},
ControlStatusMap: map[string]ControlStatus{
"TOM.GOV.01": ControlImplemented,
},
})
if result.CompliancePercent != 100 {
t.Errorf("expected 100%% compliance, got %.1f%%", result.CompliancePercent)
}
if len(result.Gaps) != 0 {
t.Errorf("expected 0 gaps, got %d", len(result.Gaps))
}
}

View File

@@ -0,0 +1,150 @@
package ucca
import (
"sort"
)
// TOMObligationMapper provides bidirectional mapping between obligations and TOM controls
type TOMObligationMapper struct {
tomIndex *TOMControlIndex
obligationToControl map[string][]string // obligation_id -> []control_id
controlToObligation map[string][]string // control_id -> []obligation_id
}
// TOMControlRequirement represents a required TOM control with context
type TOMControlRequirement struct {
Control *TOMControl `json:"control"`
ObligationIDs []string `json:"obligation_ids"`
Priority string `json:"priority"` // highest priority from linked obligations
RequiredByCount int `json:"required_by_count"` // number of obligations requiring this
}
// NewTOMObligationMapper creates a new mapper from TOM index and v2 mapping
func NewTOMObligationMapper(tomIndex *TOMControlIndex, mapping *V2TOMMapping) *TOMObligationMapper {
m := &TOMObligationMapper{
tomIndex: tomIndex,
obligationToControl: make(map[string][]string),
controlToObligation: make(map[string][]string),
}
if mapping != nil {
m.obligationToControl = mapping.ObligationToControl
m.controlToObligation = mapping.ControlToObligation
}
return m
}
// NewTOMObligationMapperFromObligations builds the mapper from obligations' tom_control_ids
func NewTOMObligationMapperFromObligations(tomIndex *TOMControlIndex, obligations []V2Obligation) *TOMObligationMapper {
m := &TOMObligationMapper{
tomIndex: tomIndex,
obligationToControl: make(map[string][]string),
controlToObligation: make(map[string][]string),
}
for _, obl := range obligations {
for _, controlID := range obl.TOMControlIDs {
m.obligationToControl[obl.ID] = append(m.obligationToControl[obl.ID], controlID)
m.controlToObligation[controlID] = append(m.controlToObligation[controlID], obl.ID)
}
}
return m
}
// GetControlsForObligation returns TOM controls linked to an obligation
func (m *TOMObligationMapper) GetControlsForObligation(obligationID string) []*TOMControl {
controlIDs := m.obligationToControl[obligationID]
var result []*TOMControl
for _, id := range controlIDs {
if ctrl, ok := m.tomIndex.GetControl(id); ok {
result = append(result, ctrl)
}
}
return result
}
// GetControlIDsForObligation returns control IDs for an obligation
func (m *TOMObligationMapper) GetControlIDsForObligation(obligationID string) []string {
return m.obligationToControl[obligationID]
}
// GetObligationsForControl returns obligation IDs linked to a control
func (m *TOMObligationMapper) GetObligationsForControl(controlID string) []string {
return m.controlToObligation[controlID]
}
// DeriveControlsFromObligations takes a list of applicable obligations and returns
// deduplicated, priority-sorted TOM control requirements
func (m *TOMObligationMapper) DeriveControlsFromObligations(obligations []Obligation) []TOMControlRequirement {
// Collect all required controls with their linking obligations
controlMap := make(map[string]*TOMControlRequirement)
priorityRank := map[string]int{"critical": 0, "high": 1, "medium": 2, "low": 3}
for _, obl := range obligations {
// Get control IDs from ExternalResources (where tom_control_ids are stored)
controlIDs := obl.ExternalResources
if len(controlIDs) == 0 {
controlIDs = m.obligationToControl[obl.ID]
}
for _, controlID := range controlIDs {
ctrl, ok := m.tomIndex.GetControl(controlID)
if !ok {
continue
}
if existing, found := controlMap[controlID]; found {
existing.ObligationIDs = append(existing.ObligationIDs, obl.ID)
existing.RequiredByCount++
// Keep highest priority
if rank, ok := priorityRank[string(obl.Priority)]; ok {
if existingRank, ok2 := priorityRank[existing.Priority]; ok2 && rank < existingRank {
existing.Priority = string(obl.Priority)
}
}
} else {
controlMap[controlID] = &TOMControlRequirement{
Control: ctrl,
ObligationIDs: []string{obl.ID},
Priority: string(obl.Priority),
RequiredByCount: 1,
}
}
}
}
// Convert to slice and sort by priority then required_by_count
var result []TOMControlRequirement
for _, req := range controlMap {
result = append(result, *req)
}
sort.Slice(result, func(i, j int) bool {
ri := priorityRank[result[i].Priority]
rj := priorityRank[result[j].Priority]
if ri != rj {
return ri < rj
}
return result[i].RequiredByCount > result[j].RequiredByCount
})
return result
}
// AddMapping adds a single obligation->control mapping
func (m *TOMObligationMapper) AddMapping(obligationID, controlID string) {
m.obligationToControl[obligationID] = appendUnique(m.obligationToControl[obligationID], controlID)
m.controlToObligation[controlID] = appendUnique(m.controlToObligation[controlID], obligationID)
}
func appendUnique(slice []string, item string) []string {
for _, s := range slice {
if s == item {
return slice
}
}
return append(slice, item)
}

View File

@@ -85,6 +85,11 @@ type SectorFacts struct {
IsPublicAdministration bool `json:"is_public_administration"`
PublicAdminLevel string `json:"public_admin_level,omitempty"` // "federal", "state", "municipal"
// NIS2 classification (v2)
NIS2Classification string `json:"nis2_classification,omitempty"` // wichtige_einrichtung, besonders_wichtige_einrichtung, nicht_betroffen
IsAnnexI bool `json:"is_annex_i"`
IsAnnexII bool `json:"is_annex_ii"`
// Healthcare specific
IsHealthcareProvider bool `json:"is_healthcare_provider"`
HasPatientData bool `json:"has_patient_data"`
@@ -141,6 +146,19 @@ type DataProtectionFacts struct {
RequiresDSBByLaw bool `json:"requires_dsb_by_law"`
HasAppointedDSB bool `json:"has_appointed_dsb"`
DSBIsInternal bool `json:"dsb_is_internal"`
// Extended data categories (v2)
ProcessesEmployeeData bool `json:"processes_employee_data"`
ProcessesFinancialData bool `json:"processes_financial_data"`
ProcessesHealthData bool `json:"processes_health_data"`
ProcessesBiometricData bool `json:"processes_biometric_data"`
// Online / Platform processing (v2)
UsesCookies bool `json:"uses_cookies"`
UsesTracking bool `json:"uses_tracking"`
UsesVideoSurveillance bool `json:"uses_video_surveillance"`
OperatesPlatform bool `json:"operates_platform"`
PlatformUserCount int `json:"platform_user_count,omitempty"`
}
// AIUsageFacts contains AI Act relevant information

View File

@@ -0,0 +1,233 @@
package ucca
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"runtime"
)
// V2Manifest represents the registry of all v2 obligation files
type V2Manifest struct {
SchemaVersion string `json:"schema_version"`
Regulations []V2RegulationEntry `json:"regulations"`
TOMMappingFile string `json:"tom_mapping_file"`
TotalObl int `json:"total_obligations"`
}
// V2RegulationEntry is a single regulation in the manifest
type V2RegulationEntry struct {
ID string `json:"id"`
File string `json:"file"`
Version string `json:"version"`
Count int `json:"count"`
}
// V2RegulationFile is the top-level structure of a v2 regulation JSON file
type V2RegulationFile struct {
Regulation string `json:"regulation"`
Name string `json:"name"`
Description string `json:"description"`
Version string `json:"version"`
EffectiveDate string `json:"effective_date,omitempty"`
Obligations []V2Obligation `json:"obligations"`
Controls []V2Control `json:"controls,omitempty"`
IncidentDL []V2IncidentDL `json:"incident_deadlines,omitempty"`
}
// V2Obligation is the extended obligation structure
type V2Obligation struct {
ID string `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
AppliesWhen string `json:"applies_when"`
AppliesWhenCondition *ConditionNode `json:"applies_when_condition,omitempty"`
LegalBasis []V2LegalBasis `json:"legal_basis"`
Sources []V2Source `json:"sources,omitempty"`
Category string `json:"category"`
Responsible string `json:"responsible"`
Deadline *V2Deadline `json:"deadline,omitempty"`
Sanctions *V2Sanctions `json:"sanctions,omitempty"`
Evidence []interface{} `json:"evidence,omitempty"`
Priority string `json:"priority"`
TOMControlIDs []string `json:"tom_control_ids,omitempty"`
BreakpilotFeature string `json:"breakpilot_feature,omitempty"`
ValidFrom string `json:"valid_from,omitempty"`
ValidUntil *string `json:"valid_until"`
Version string `json:"version,omitempty"`
ISO27001Mapping []string `json:"iso27001_mapping,omitempty"`
HowToImplement string `json:"how_to_implement,omitempty"`
}
// V2LegalBasis is a legal reference in v2 format
type V2LegalBasis struct {
Norm string `json:"norm"`
Article string `json:"article"`
Title string `json:"title,omitempty"`
Erwaegungsgrund string `json:"erwaegungsgrund,omitempty"`
}
// V2Source is an external source reference
type V2Source struct {
Type string `json:"type"`
Ref string `json:"ref"`
}
// V2Deadline is a deadline in v2 format
type V2Deadline struct {
Type string `json:"type"`
Date string `json:"date,omitempty"`
Duration string `json:"duration,omitempty"`
Interval string `json:"interval,omitempty"`
Event string `json:"event,omitempty"`
}
// V2Sanctions is sanctions info in v2 format
type V2Sanctions struct {
MaxFine string `json:"max_fine,omitempty"`
PersonalLiability bool `json:"personal_liability,omitempty"`
CriminalLiability bool `json:"criminal_liability,omitempty"`
Description string `json:"description,omitempty"`
}
// V2Control is a control in v2 format
type V2Control struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
Category string `json:"category"`
WhatToDo string `json:"what_to_do,omitempty"`
ISO27001Mapping []string `json:"iso27001_mapping,omitempty"`
Priority string `json:"priority,omitempty"`
}
// V2IncidentDL is an incident deadline in v2 format
type V2IncidentDL struct {
Phase string `json:"phase"`
Deadline string `json:"deadline"`
Content string `json:"content,omitempty"`
Recipient string `json:"recipient,omitempty"`
LegalBasis []V2LegalBasis `json:"legal_basis,omitempty"`
}
// ConditionNode represents a condition tree node for obligation applicability
type ConditionNode struct {
AllOf []ConditionNode `json:"all_of,omitempty"`
AnyOf []ConditionNode `json:"any_of,omitempty"`
Field string `json:"field,omitempty"`
Operator string `json:"operator,omitempty"`
Value interface{} `json:"value,omitempty"`
}
// V2TOMMapping is the bidirectional mapping file
type V2TOMMapping struct {
SchemaVersion string `json:"schema_version"`
ObligationToControl map[string][]string `json:"obligation_to_control"`
ControlToObligation map[string][]string `json:"control_to_obligation"`
}
// getV2BasePath returns the base path for v2 obligation files
func getV2BasePath() string {
// Try relative to the binary
candidates := []string{
"policies/obligations/v2",
"../policies/obligations/v2",
"../../policies/obligations/v2",
}
// Also try relative to the source file
_, filename, _, ok := runtime.Caller(0)
if ok {
srcDir := filepath.Dir(filename)
candidates = append(candidates,
filepath.Join(srcDir, "../../policies/obligations/v2"),
)
}
for _, p := range candidates {
abs, err := filepath.Abs(p)
if err != nil {
continue
}
if info, err := os.Stat(abs); err == nil && info.IsDir() {
return abs
}
}
return "policies/obligations/v2"
}
// LoadV2Manifest loads the v2 manifest file
func LoadV2Manifest() (*V2Manifest, error) {
basePath := getV2BasePath()
manifestPath := filepath.Join(basePath, "_manifest.json")
data, err := os.ReadFile(manifestPath)
if err != nil {
return nil, fmt.Errorf("failed to read v2 manifest: %w", err)
}
var manifest V2Manifest
if err := json.Unmarshal(data, &manifest); err != nil {
return nil, fmt.Errorf("failed to parse v2 manifest: %w", err)
}
return &manifest, nil
}
// LoadV2RegulationFile loads a single v2 regulation JSON file
func LoadV2RegulationFile(filename string) (*V2RegulationFile, error) {
basePath := getV2BasePath()
filePath := filepath.Join(basePath, filename)
data, err := os.ReadFile(filePath)
if err != nil {
return nil, fmt.Errorf("failed to read v2 regulation file %s: %w", filename, err)
}
var regFile V2RegulationFile
if err := json.Unmarshal(data, &regFile); err != nil {
return nil, fmt.Errorf("failed to parse v2 regulation file %s: %w", filename, err)
}
return &regFile, nil
}
// LoadV2TOMMapping loads the bidirectional TOM mapping
func LoadV2TOMMapping() (*V2TOMMapping, error) {
basePath := getV2BasePath()
mappingPath := filepath.Join(basePath, "_tom_mapping.json")
data, err := os.ReadFile(mappingPath)
if err != nil {
return nil, fmt.Errorf("failed to read TOM mapping: %w", err)
}
var mapping V2TOMMapping
if err := json.Unmarshal(data, &mapping); err != nil {
return nil, fmt.Errorf("failed to parse TOM mapping: %w", err)
}
return &mapping, nil
}
// LoadAllV2Regulations loads all v2 regulation files from the manifest
func LoadAllV2Regulations() (map[string]*V2RegulationFile, error) {
manifest, err := LoadV2Manifest()
if err != nil {
return nil, err
}
result := make(map[string]*V2RegulationFile)
for _, entry := range manifest.Regulations {
regFile, err := LoadV2RegulationFile(entry.File)
if err != nil {
fmt.Printf("Warning: Could not load v2 regulation %s: %v\n", entry.ID, err)
continue
}
result[entry.ID] = regFile
}
return result, nil
}

View File

@@ -0,0 +1,137 @@
package ucca
import (
"os"
"testing"
)
func TestLoadV2Manifest(t *testing.T) {
manifest, err := LoadV2Manifest()
if err != nil {
t.Skipf("v2 manifest not found (expected in CI): %v", err)
}
if manifest.SchemaVersion != "2.0" {
t.Errorf("expected schema_version 2.0, got %s", manifest.SchemaVersion)
}
if len(manifest.Regulations) == 0 {
t.Error("expected at least one regulation in manifest")
}
// Check known regulations
regIDs := make(map[string]bool)
for _, r := range manifest.Regulations {
regIDs[r.ID] = true
}
for _, expected := range []string{"dsgvo", "ai_act", "nis2"} {
if !regIDs[expected] {
t.Errorf("expected regulation %s in manifest", expected)
}
}
}
func TestLoadV2RegulationFile_DSGVO(t *testing.T) {
basePath := getV2BasePath()
if _, err := os.Stat(basePath + "/dsgvo_v2.json"); os.IsNotExist(err) {
t.Skip("dsgvo_v2.json not found")
}
data, err := LoadV2RegulationFile("dsgvo_v2.json")
if err != nil {
t.Fatalf("failed to load dsgvo_v2.json: %v", err)
}
if data.Regulation != "dsgvo" {
t.Errorf("expected regulation dsgvo, got %s", data.Regulation)
}
if len(data.Obligations) < 11 {
t.Errorf("expected at least 11 DSGVO obligations (existing), got %d", len(data.Obligations))
}
// Verify first obligation preserves existing ID
if data.Obligations[0].ID != "DSGVO-OBL-001" {
t.Errorf("expected first obligation DSGVO-OBL-001, got %s", data.Obligations[0].ID)
}
// Verify v2 fields are present
obl := data.Obligations[0]
if obl.ValidFrom == "" {
t.Error("expected valid_from on first obligation")
}
if len(obl.TOMControlIDs) == 0 {
t.Error("expected tom_control_ids on first obligation")
}
}
func TestLoadV2RegulationFile_AIAct(t *testing.T) {
basePath := getV2BasePath()
if _, err := os.Stat(basePath + "/ai_act_v2.json"); os.IsNotExist(err) {
t.Skip("ai_act_v2.json not found")
}
data, err := LoadV2RegulationFile("ai_act_v2.json")
if err != nil {
t.Fatalf("failed to load: %v", err)
}
if len(data.Obligations) < 15 {
t.Errorf("expected at least 15 AI Act obligations (existing), got %d", len(data.Obligations))
}
}
func TestLoadV2RegulationFile_NIS2(t *testing.T) {
basePath := getV2BasePath()
if _, err := os.Stat(basePath + "/nis2_v2.json"); os.IsNotExist(err) {
t.Skip("nis2_v2.json not found")
}
data, err := LoadV2RegulationFile("nis2_v2.json")
if err != nil {
t.Fatalf("failed to load: %v", err)
}
if len(data.Obligations) < 14 {
t.Errorf("expected at least 14 NIS2 obligations (existing), got %d", len(data.Obligations))
}
}
func TestLoadAllV2Regulations(t *testing.T) {
regs, err := LoadAllV2Regulations()
if err != nil {
t.Skipf("v2 regulations not found: %v", err)
}
if len(regs) < 3 {
t.Errorf("expected at least 3 loaded regulations, got %d", len(regs))
}
totalObl := 0
for _, r := range regs {
totalObl += len(r.Obligations)
}
if totalObl < 40 {
t.Errorf("expected at least 40 total obligations, got %d", totalObl)
}
t.Logf("Loaded %d regulations with %d total obligations", len(regs), totalObl)
}
func TestLoadV2TOMMapping(t *testing.T) {
basePath := getV2BasePath()
if _, err := os.Stat(basePath + "/_tom_mapping.json"); os.IsNotExist(err) {
t.Skip("_tom_mapping.json not found")
}
mapping, err := LoadV2TOMMapping()
if err != nil {
t.Fatalf("failed to load TOM mapping: %v", err)
}
if len(mapping.ObligationToControl) == 0 {
t.Error("expected obligation_to_control mappings")
}
if len(mapping.ControlToObligation) == 0 {
t.Error("expected control_to_obligation mappings")
}
t.Logf("TOM mapping: %d obligation->control, %d control->obligation",
len(mapping.ObligationToControl), len(mapping.ControlToObligation))
}

View File

@@ -0,0 +1,61 @@
{
"schema_version": "2.0",
"regulations": [
{
"id": "dsgvo",
"file": "dsgvo_v2.json",
"version": "1.0",
"count": 80
},
{
"id": "ai_act",
"file": "ai_act_v2.json",
"version": "1.0",
"count": 60
},
{
"id": "nis2",
"file": "nis2_v2.json",
"version": "1.0",
"count": 40
},
{
"id": "bdsg",
"file": "bdsg_v2.json",
"version": "1.0",
"count": 30
},
{
"id": "ttdsg",
"file": "ttdsg_v2.json",
"version": "1.0",
"count": 20
},
{
"id": "dsa",
"file": "dsa_v2.json",
"version": "1.0",
"count": 35
},
{
"id": "data_act",
"file": "data_act_v2.json",
"version": "1.0",
"count": 25
},
{
"id": "eu_machinery",
"file": "eu_machinery_v2.json",
"version": "1.0",
"count": 15
},
{
"id": "dora",
"file": "dora_v2.json",
"version": "1.0",
"count": 20
}
],
"tom_mapping_file": "_tom_mapping.json",
"total_obligations": 325
}

View File

@@ -0,0 +1,162 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Obligation v2 Schema",
"description": "Schema fuer maschinenlesbare Compliance-Pflichten",
"type": "object",
"required": ["regulation", "name", "version", "obligations"],
"properties": {
"regulation": { "type": "string", "description": "Regulation-Key (z.B. dsgvo, ai_act, nis2)" },
"name": { "type": "string" },
"description": { "type": "string" },
"version": { "type": "string" },
"effective_date": { "type": "string", "format": "date" },
"obligations": {
"type": "array",
"items": { "$ref": "#/$defs/obligation" }
},
"controls": {
"type": "array",
"items": { "$ref": "#/$defs/control" }
},
"incident_deadlines": {
"type": "array",
"items": { "$ref": "#/$defs/incident_deadline" }
}
},
"$defs": {
"obligation": {
"type": "object",
"required": ["id", "title", "description", "applies_when", "legal_basis", "category", "priority"],
"properties": {
"id": { "type": "string", "pattern": "^[A-Z0-9_-]+-OBL-[0-9]{3}$" },
"title": { "type": "string" },
"description": { "type": "string" },
"applies_when": { "type": "string", "description": "Legacy condition string for backwards compat" },
"applies_when_condition": { "$ref": "#/$defs/condition_node" },
"legal_basis": {
"type": "array",
"items": {
"type": "object",
"required": ["norm", "article"],
"properties": {
"norm": { "type": "string" },
"article": { "type": "string" },
"title": { "type": "string" },
"erwaegungsgrund": { "type": "string" }
}
}
},
"sources": {
"type": "array",
"items": {
"type": "object",
"required": ["type", "ref"],
"properties": {
"type": { "type": "string", "enum": ["article", "erwaegungsgrund", "edpb_guideline", "dsk_kurzpapier", "bsi_standard", "eu_guidance", "national_law", "case_law"] },
"ref": { "type": "string" }
}
}
},
"category": { "type": "string", "enum": ["Governance", "Technisch", "Organisatorisch", "Meldepflicht", "Dokumentation", "Schulung", "Audit", "Compliance"] },
"responsible": { "type": "string" },
"deadline": {
"type": "object",
"properties": {
"type": { "type": "string", "enum": ["absolute", "relative", "recurring", "on_event"] },
"date": { "type": "string", "format": "date" },
"duration": { "type": "string" },
"interval": { "type": "string" },
"event": { "type": "string" }
}
},
"sanctions": {
"type": "object",
"properties": {
"max_fine": { "type": "string" },
"min_fine": { "type": "string" },
"personal_liability": { "type": "boolean" },
"criminal_liability": { "type": "boolean" },
"description": { "type": "string" }
}
},
"evidence": {
"type": "array",
"items": {
"oneOf": [
{ "type": "string" },
{
"type": "object",
"required": ["name"],
"properties": {
"name": { "type": "string" },
"required": { "type": "boolean" },
"format": { "type": "string" }
}
}
]
}
},
"priority": { "type": "string", "enum": ["kritisch", "hoch", "mittel", "niedrig"] },
"tom_control_ids": {
"type": "array",
"items": { "type": "string", "pattern": "^TOM\\.[A-Z]+\\.[0-9]{2}$" }
},
"breakpilot_feature": { "type": "string", "description": "Link to SDK module (e.g. /sdk/dsfa)" },
"valid_from": { "type": "string", "format": "date" },
"valid_until": { "type": ["string", "null"], "format": "date" },
"version": { "type": "string" },
"iso27001_mapping": { "type": "array", "items": { "type": "string" } },
"how_to_implement": { "type": "string" }
}
},
"condition_node": {
"type": "object",
"oneOf": [
{
"properties": {
"all_of": { "type": "array", "items": { "$ref": "#/$defs/condition_node" } }
},
"required": ["all_of"]
},
{
"properties": {
"any_of": { "type": "array", "items": { "$ref": "#/$defs/condition_node" } }
},
"required": ["any_of"]
},
{
"properties": {
"field": { "type": "string" },
"operator": { "type": "string", "enum": ["EQUALS", "NOT_EQUALS", "GREATER_THAN", "LESS_THAN", "GREATER_OR_EQUAL", "LESS_OR_EQUAL", "IN", "NOT_IN", "CONTAINS", "EXISTS"] },
"value": {}
},
"required": ["field", "operator", "value"]
}
]
},
"control": {
"type": "object",
"required": ["id", "name", "category"],
"properties": {
"id": { "type": "string" },
"name": { "type": "string" },
"description": { "type": "string" },
"category": { "type": "string" },
"what_to_do": { "type": "string" },
"iso27001_mapping": { "type": "array", "items": { "type": "string" } },
"priority": { "type": "string" }
}
},
"incident_deadline": {
"type": "object",
"required": ["phase", "deadline"],
"properties": {
"phase": { "type": "string" },
"deadline": { "type": "string" },
"content": { "type": "string" },
"recipient": { "type": "string" },
"legal_basis": { "type": "array", "items": { "type": "object" } }
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,668 @@
{
"regulation": "bdsg",
"regulation_full_name": "Bundesdatenschutzgesetz (BDSG)",
"version": "1.0",
"obligations": [
{
"id": "BDSG-OBL-001",
"title": "Videoueberwachung oeffentlicher Raeume",
"description": "Videoueberwachung oeffentlich zugaenglicher Raeume ist nur zulaessig, wenn sie zur Aufgabenerfuellung oeffentlicher Stellen, zur Wahrnehmung des Hausrechts oder zur Wahrnehmung berechtigter Interessen erforderlich ist.",
"applies_when": "organization uses video surveillance in public areas",
"applies_when_condition": { "all_of": [{ "field": "data_protection.video_surveillance", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 4 Abs. 1", "title": "Videoueberwachung oeffentlich zugaenglicher Raeume" }],
"sources": [{ "type": "national_law", "ref": "§ 4 BDSG" }],
"category": "Governance",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "on_event", "event": "Vor Inbetriebnahme der Videoueberwachung" },
"sanctions": { "max_fine": "50.000 EUR (§ 43 BDSG a.F.) bzw. DSGVO-Bussgeld" },
"evidence": [{ "name": "Videoueberwachungskonzept", "required": true }, "Beschilderung/Hinweisschilder"],
"priority": "hoch",
"tom_control_ids": ["TOM.PHY.01", "TOM.GOV.03"],
"breakpilot_feature": "/sdk/tom",
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-002",
"title": "Kennzeichnungspflicht Videoueberwachung",
"description": "Der Umstand der Beobachtung und der Verantwortliche sind durch geeignete Massnahmen zum fruehestmoeglichen Zeitpunkt erkennbar zu machen.",
"applies_when": "organization uses video surveillance",
"applies_when_condition": { "all_of": [{ "field": "data_protection.video_surveillance", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 4 Abs. 2", "title": "Kennzeichnungspflicht bei Videoueberwachung" }],
"sources": [{ "type": "national_law", "ref": "§ 4 Abs. 2 BDSG" }],
"category": "Organisatorisch",
"responsible": "Verantwortlicher",
"deadline": { "type": "on_event", "event": "Vor Inbetriebnahme" },
"sanctions": { "max_fine": "10 Mio. EUR oder 2% Jahresumsatz" },
"evidence": [{ "name": "Fotodokumentation Beschilderung", "required": true }],
"priority": "hoch",
"tom_control_ids": ["TOM.PHY.01"],
"breakpilot_feature": null,
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-003",
"title": "Loeschpflicht Videomaterial",
"description": "Videoaufzeichnungen sind unverzueglich zu loeschen, wenn sie zur Erreichung des Zwecks nicht mehr erforderlich sind oder schutzwuerdige Interessen der Betroffenen entgegenstehen.",
"applies_when": "organization stores video surveillance recordings",
"applies_when_condition": { "all_of": [{ "field": "data_protection.video_surveillance", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 4 Abs. 5", "title": "Loeschung von Videomaterial" }],
"sources": [{ "type": "national_law", "ref": "§ 4 Abs. 5 BDSG" }],
"category": "Technisch",
"responsible": "IT-Sicherheitsbeauftragter",
"deadline": { "type": "relative", "duration": "P72H" },
"sanctions": { "max_fine": "10 Mio. EUR oder 2% Jahresumsatz" },
"evidence": [{ "name": "Loeschkonzept Videodaten", "required": true }],
"priority": "hoch",
"tom_control_ids": ["TOM.PHY.01", "TOM.DEL.01"],
"breakpilot_feature": "/sdk/loeschfristen",
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-004",
"title": "Verarbeitung besonderer Kategorien — Angemessene Massnahmen",
"description": "Bei Verarbeitung besonderer Kategorien personenbezogener Daten sind angemessene und spezifische Massnahmen zur Wahrung der Interessen der betroffenen Person vorzusehen.",
"applies_when": "organization processes special category data",
"applies_when_condition": { "all_of": [{ "field": "data_protection.special_categories", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 22 Abs. 1", "title": "Verarbeitung besonderer Kategorien personenbezogener Daten" }],
"sources": [{ "type": "national_law", "ref": "§ 22 BDSG" }],
"category": "Governance",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "20 Mio. EUR oder 4% Jahresumsatz" },
"evidence": [{ "name": "Schutzkonzept besondere Datenkategorien", "required": true }, "DSFA"],
"priority": "kritisch",
"tom_control_ids": ["TOM.AC.01", "TOM.CRY.01", "TOM.GOV.04"],
"breakpilot_feature": "/sdk/dsfa",
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-005",
"title": "Massnahmenkatalog § 22 Abs. 2",
"description": "Der Verantwortliche hat technische und organisatorische Massnahmen nach § 22 Abs. 2 BDSG umzusetzen, darunter Pseudonymisierung, Verschluesselung, Zugriffskontrolle und Sensibilisierung.",
"applies_when": "organization processes special category data under BDSG",
"applies_when_condition": { "all_of": [{ "field": "data_protection.special_categories", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 22 Abs. 2", "title": "Spezifische Massnahmen" }],
"sources": [{ "type": "national_law", "ref": "§ 22 Abs. 2 BDSG" }],
"category": "Technisch",
"responsible": "IT-Sicherheitsbeauftragter",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "20 Mio. EUR oder 4% Jahresumsatz" },
"evidence": [{ "name": "TOM-Dokumentation § 22", "required": true }, "Pseudonymisierungskonzept"],
"priority": "kritisch",
"tom_control_ids": ["TOM.CRY.01", "TOM.CRY.02", "TOM.AC.01"],
"breakpilot_feature": "/sdk/tom",
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-006",
"title": "Datenverarbeitung fuer Zwecke des Beschaeftigungsverhaeltnisses",
"description": "Personenbezogene Daten von Beschaeftigten duerfen nur verarbeitet werden, wenn dies fuer die Begruendung, Durchfuehrung oder Beendigung des Beschaeftigungsverhaeltnisses erforderlich ist.",
"applies_when": "organization processes employee data",
"applies_when_condition": { "all_of": [{ "field": "organization.has_employees", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 26 Abs. 1", "title": "Datenverarbeitung fuer Zwecke des Beschaeftigungsverhaeltnisses" }],
"sources": [{ "type": "national_law", "ref": "§ 26 BDSG" }, { "type": "case_law", "ref": "BAG Urt. v. 29.06.2023 2 AZR 296/22" }],
"category": "Governance",
"responsible": "Personalleitung",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "20 Mio. EUR oder 4% Jahresumsatz" },
"evidence": [{ "name": "Beschaeftigtendatenschutzkonzept", "required": true }],
"priority": "hoch",
"tom_control_ids": ["TOM.HR.01", "TOM.GOV.01"],
"breakpilot_feature": null,
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-007",
"title": "Einwilligung im Beschaeftigungsverhaeltnis",
"description": "Einwilligungen von Beschaeftigten sind nur wirksam, wenn sie auf Freiwilligkeit beruhen. Die Freiwilligkeit ist besonders zu dokumentieren und zu pruefen.",
"applies_when": "organization collects consent from employees",
"applies_when_condition": { "all_of": [{ "field": "organization.has_employees", "operator": "EQUALS", "value": true }, { "field": "data_protection.employee_consent", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 26 Abs. 2", "title": "Einwilligung Beschaeftigte" }],
"sources": [{ "type": "national_law", "ref": "§ 26 Abs. 2 BDSG" }],
"category": "Organisatorisch",
"responsible": "Personalleitung",
"deadline": { "type": "on_event", "event": "Vor Datenerhebung" },
"sanctions": { "max_fine": "20 Mio. EUR oder 4% Jahresumsatz" },
"evidence": [{ "name": "Einwilligungsformulare Beschaeftigte", "required": true }, "Freiwilligkeitsnachweis"],
"priority": "hoch",
"tom_control_ids": ["TOM.HR.01", "TOM.HR.02"],
"breakpilot_feature": "/sdk/consent",
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-008",
"title": "Kollektivvereinbarungen Beschaeftigtendatenschutz",
"description": "Verarbeitung von Beschaeftigtendaten kann auf Grundlage von Kollektivvereinbarungen (Betriebsvereinbarung, Tarifvertrag) erfolgen, sofern diese Art. 88 Abs. 2 DSGVO genuegen.",
"applies_when": "organization has collective agreements for data processing",
"applies_when_condition": { "all_of": [{ "field": "organization.has_employees", "operator": "EQUALS", "value": true }, { "field": "organization.has_works_council", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 26 Abs. 4", "title": "Kollektivvereinbarungen" }],
"sources": [{ "type": "national_law", "ref": "§ 26 Abs. 4 BDSG" }],
"category": "Governance",
"responsible": "Personalleitung",
"deadline": { "type": "recurring", "interval": "jaehrlich" },
"sanctions": { "max_fine": "20 Mio. EUR oder 4% Jahresumsatz" },
"evidence": [{ "name": "Betriebsvereinbarung Datenschutz", "required": true }],
"priority": "mittel",
"tom_control_ids": ["TOM.HR.01", "TOM.GOV.01"],
"breakpilot_feature": null,
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-009",
"title": "Aufbewahrung Beschaeftigtendaten nach Verhaeltnisende",
"description": "Personenbezogene Daten von Beschaeftigten sind nach Beendigung des Beschaeftigungsverhaeltnisses zu loeschen, soweit keine gesetzlichen Aufbewahrungspflichten bestehen.",
"applies_when": "organization stores former employee data",
"applies_when_condition": { "all_of": [{ "field": "organization.has_employees", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 26 Abs. 1", "title": "Zweckbindung Beschaeftigtendaten" }, { "norm": "DSGVO", "article": "Art. 17", "title": "Recht auf Loeschung" }],
"sources": [{ "type": "national_law", "ref": "§ 26 BDSG" }],
"category": "Organisatorisch",
"responsible": "Personalleitung",
"deadline": { "type": "on_event", "event": "Beendigung Beschaeftigungsverhaeltnis" },
"sanctions": { "max_fine": "20 Mio. EUR oder 4% Jahresumsatz" },
"evidence": [{ "name": "Loeschkonzept Personalakten", "required": true }],
"priority": "hoch",
"tom_control_ids": ["TOM.HR.01", "TOM.DEL.01"],
"breakpilot_feature": "/sdk/loeschfristen",
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-010",
"title": "Informationspflicht gegenueber Betroffenen",
"description": "Die betroffene Person ist ueber die Verarbeitung ihrer Daten gemaess §§ 32-33 BDSG zu informieren, sofern keine Ausnahmen nach § 29 greifen.",
"applies_when": "always",
"applies_when_condition": { "all_of": [{ "field": "data_protection.processes_personal_data", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 29", "title": "Rechte der betroffenen Person und aufsichtsbehoerdliche Befugnisse" }],
"sources": [{ "type": "national_law", "ref": "§ 29 BDSG" }],
"category": "Organisatorisch",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "on_event", "event": "Bei Datenerhebung" },
"sanctions": { "max_fine": "20 Mio. EUR oder 4% Jahresumsatz" },
"evidence": [{ "name": "Datenschutzerklaerung", "required": true }, "Informationsblaetter"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.02"],
"breakpilot_feature": "/sdk/dsr",
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-011",
"title": "Ausnahmen von Betroffenenrechten dokumentieren",
"description": "Einschraenkungen der Betroffenenrechte nach § 29 BDSG (z.B. bei oeffentlichem Interesse, Strafverfolgung) muessen dokumentiert und begruendet werden.",
"applies_when": "organization restricts data subject rights under BDSG § 29",
"applies_when_condition": { "all_of": [{ "field": "data_protection.restricts_data_subject_rights", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 29 Abs. 1", "title": "Beschraenkung Betroffenenrechte" }],
"sources": [{ "type": "national_law", "ref": "§ 29 BDSG" }],
"category": "Dokumentation",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "on_event", "event": "Bei Einschraenkung der Rechte" },
"sanctions": { "max_fine": "20 Mio. EUR oder 4% Jahresumsatz" },
"evidence": [{ "name": "Dokumentation Rechteeinschraenkung", "required": true }],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.02", "TOM.GOV.03"],
"breakpilot_feature": "/sdk/dsr",
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-012",
"title": "Recht auf Loeschung — BDSG-Einschraenkungen",
"description": "Das Recht auf Loeschung kann nach § 35 BDSG eingeschraenkt sein, wenn die Loeschung wegen der besonderen Art der Speicherung nicht oder nur mit unverhaeltnismaessigem Aufwand moeglich ist.",
"applies_when": "organization processes data where deletion is disproportionate",
"applies_when_condition": { "all_of": [{ "field": "data_protection.complex_storage", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 35 Abs. 1", "title": "Recht auf Loeschung" }],
"sources": [{ "type": "national_law", "ref": "§ 35 BDSG" }],
"category": "Technisch",
"responsible": "IT-Leitung",
"deadline": { "type": "on_event", "event": "Bei Loeschantrag" },
"sanctions": { "max_fine": "20 Mio. EUR oder 4% Jahresumsatz" },
"evidence": [{ "name": "Nachweis unverhaeltnismaessiger Aufwand", "required": true }],
"priority": "hoch",
"tom_control_ids": ["TOM.DEL.01"],
"breakpilot_feature": "/sdk/loeschfristen",
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-013",
"title": "Verarbeitungseinschraenkung statt Loeschung",
"description": "Wenn die Loeschung nicht moeglich ist, tritt an die Stelle der Loeschung die Einschraenkung der Verarbeitung gemaess § 35 Abs. 1 BDSG.",
"applies_when": "organization cannot delete data due to storage constraints",
"applies_when_condition": { "all_of": [{ "field": "data_protection.complex_storage", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 35 Abs. 1 S. 2", "title": "Verarbeitungseinschraenkung" }],
"sources": [{ "type": "national_law", "ref": "§ 35 BDSG" }],
"category": "Technisch",
"responsible": "IT-Leitung",
"deadline": { "type": "on_event", "event": "Bei Loeschantrag" },
"sanctions": { "max_fine": "20 Mio. EUR oder 4% Jahresumsatz" },
"evidence": [{ "name": "Sperrkonzept/Einschraenkungskonzept", "required": true }],
"priority": "mittel",
"tom_control_ids": ["TOM.DEL.01", "TOM.AC.02"],
"breakpilot_feature": "/sdk/loeschfristen",
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-014",
"title": "Benennung Datenschutzbeauftragter",
"description": "Der Verantwortliche hat einen Datenschutzbeauftragten zu benennen, wenn mindestens 20 Personen staendig mit der automatisierten Verarbeitung personenbezogener Daten beschaeftigt sind.",
"applies_when": "organization has 20+ employees processing personal data",
"applies_when_condition": { "any_of": [{ "field": "organization.employees_processing_data", "operator": "GREATER_OR_EQUAL", "value": 20 }, { "field": "data_protection.special_categories", "operator": "EQUALS", "value": true }, { "field": "data_protection.core_activity_monitoring", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 38 Abs. 1", "title": "Datenschutzbeauftragte nichtoeffentlicher Stellen" }],
"sources": [{ "type": "national_law", "ref": "§ 38 BDSG" }, { "type": "dsk_kurzpapier", "ref": "DSK KP Nr. 12" }],
"category": "Governance",
"responsible": "Geschaeftsfuehrung",
"deadline": { "type": "on_event", "event": "Unverzueglich bei Erreichen der Schwelle" },
"sanctions": { "max_fine": "10 Mio. EUR oder 2% Jahresumsatz", "personal_liability": true },
"evidence": [{ "name": "Benennungsurkunde DSB", "required": true }, { "name": "Meldung an Aufsichtsbehoerde", "required": true }],
"priority": "kritisch",
"tom_control_ids": ["TOM.GOV.01", "TOM.GOV.05"],
"breakpilot_feature": "/sdk/dsb-portal",
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-015",
"title": "Kuendigungsschutz DSB",
"description": "Der Datenschutzbeauftragte darf wegen der Erfuellung seiner Aufgaben nicht abberufen oder benachteiligt werden. Ein besonderer Kuendigungsschutz gilt nach § 38 Abs. 2 i.V.m. § 6 Abs. 4 BDSG.",
"applies_when": "organization has appointed a DPO",
"applies_when_condition": { "all_of": [{ "field": "organization.has_dpo", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 38 Abs. 2", "title": "Kuendigungsschutz DSB" }, { "norm": "BDSG", "article": "§ 6 Abs. 4", "title": "Stellung des DSB" }],
"sources": [{ "type": "national_law", "ref": "§ 38 Abs. 2 BDSG" }],
"category": "Governance",
"responsible": "Geschaeftsfuehrung",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "10 Mio. EUR oder 2% Jahresumsatz", "personal_liability": true },
"evidence": [{ "name": "Arbeitsvertrag/Bestellungsurkunde DSB", "required": true }],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.05"],
"breakpilot_feature": null,
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-016",
"title": "Geheimhaltungspflicht DSB",
"description": "Der Datenschutzbeauftragte ist zur Geheimhaltung ueber die Identitaet betroffener Personen und Umstaende verpflichtet, die Rueckschluesse auf diese zulassen (§ 38 Abs. 2 i.V.m. § 6 Abs. 5 BDSG).",
"applies_when": "organization has appointed a DPO",
"applies_when_condition": { "all_of": [{ "field": "organization.has_dpo", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 6 Abs. 5", "title": "Geheimhaltungspflicht DSB" }],
"sources": [{ "type": "national_law", "ref": "§ 6 Abs. 5 BDSG" }],
"category": "Organisatorisch",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "personal_liability": true, "criminal_liability": true },
"evidence": [{ "name": "Verschwiegenheitserklaerung DSB", "required": true }],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.05"],
"breakpilot_feature": null,
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-017",
"title": "Zustaendigkeit der Aufsichtsbehoerden",
"description": "Die Aufsichtsbehoerden ueberwachen die Einhaltung des BDSG und der DSGVO. Der Verantwortliche muss mit der zustaendigen Aufsichtsbehoerde kooperieren (§§ 40-41 BDSG).",
"applies_when": "always",
"applies_when_condition": { "all_of": [{ "field": "data_protection.processes_personal_data", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 40", "title": "Aufsichtsbehoerden der Laender" }],
"sources": [{ "type": "national_law", "ref": "§ 40 BDSG" }],
"category": "Compliance",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "10 Mio. EUR oder 2% Jahresumsatz" },
"evidence": [{ "name": "Dokumentierte Aufsichtsbehoerdenkontakte", "required": false }],
"priority": "mittel",
"tom_control_ids": ["TOM.GOV.01"],
"breakpilot_feature": null,
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-018",
"title": "Anwendung der Bussgeldvorschriften",
"description": "Ordnungswidrig handelt, wer gegen Vorschriften des BDSG verstoesst. Die Aufsichtsbehoerden koennen Bussgelder verhaengen (§ 43 BDSG ergaenzend zu Art. 83 DSGVO).",
"applies_when": "always",
"applies_when_condition": { "all_of": [{ "field": "data_protection.processes_personal_data", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 43", "title": "Bussgeldvorschriften" }],
"sources": [{ "type": "national_law", "ref": "§ 43 BDSG" }],
"category": "Compliance",
"responsible": "Geschaeftsfuehrung",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "50.000 EUR (national) bzw. 20 Mio. EUR (DSGVO)", "personal_liability": true },
"evidence": [{ "name": "Compliance-Management-System", "required": true }],
"priority": "kritisch",
"tom_control_ids": ["TOM.GOV.01", "TOM.GOV.02"],
"breakpilot_feature": "/sdk/risk-assessment",
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-019",
"title": "Verarbeitung fuer Forschungszwecke",
"description": "Bei Verarbeitung personenbezogener Daten fuer wissenschaftliche oder historische Forschungszwecke gelten die Sonderregelungen des § 27 BDSG einschliesslich Pseudonymisierung.",
"applies_when": "organization processes data for research purposes",
"applies_when_condition": { "all_of": [{ "field": "data_protection.research_processing", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 27", "title": "Datenverarbeitung zu Forschungszwecken" }],
"sources": [{ "type": "national_law", "ref": "§ 27 BDSG" }],
"category": "Governance",
"responsible": "Forschungsleitung",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "20 Mio. EUR oder 4% Jahresumsatz" },
"evidence": [{ "name": "Forschungsdatenschutzkonzept", "required": true }, "Pseudonymisierungsnachweis"],
"priority": "mittel",
"tom_control_ids": ["TOM.CRY.02", "TOM.GOV.04"],
"breakpilot_feature": null,
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-020",
"title": "Verarbeitung fuer statistische Zwecke",
"description": "Bei Verarbeitung fuer statistische Zwecke sind die besonderen Anforderungen des § 27 Abs. 1 BDSG zu beachten, insbesondere Pseudonymisierung und Anonymisierung.",
"applies_when": "organization processes data for statistical purposes",
"applies_when_condition": { "all_of": [{ "field": "data_protection.statistical_processing", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 27 Abs. 1", "title": "Statistische Zwecke" }],
"sources": [{ "type": "national_law", "ref": "§ 27 BDSG" }],
"category": "Technisch",
"responsible": "Datenanalyst",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "10 Mio. EUR oder 2% Jahresumsatz" },
"evidence": [{ "name": "Anonymisierungskonzept", "required": true }],
"priority": "mittel",
"tom_control_ids": ["TOM.CRY.02"],
"breakpilot_feature": null,
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-021",
"title": "Verarbeitung durch Polizei/Strafverfolgung — Rechtsgrundlage",
"description": "Personenbezogene Daten duerfen von Polizei und Strafverfolgungsbehoerden nur verarbeitet werden, wenn dies fuer die Erfuellung ihrer Aufgaben erforderlich ist (§§ 46 ff. BDSG).",
"applies_when": "organization is law enforcement or cooperates with law enforcement",
"applies_when_condition": { "all_of": [{ "field": "organization.sector", "operator": "IN", "value": ["law_enforcement", "public_authority"] }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 46", "title": "Begriffsbestimmungen Strafverfolgung" }, { "norm": "BDSG", "article": "§ 47", "title": "Allgemeine Grundsaetze" }],
"sources": [{ "type": "national_law", "ref": "§§ 46-47 BDSG" }],
"category": "Governance",
"responsible": "Behoerdenleitung",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "Disziplinarmassnahmen", "personal_liability": true },
"evidence": [{ "name": "Verarbeitungskonzept Strafverfolgung", "required": true }],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01", "TOM.AC.01"],
"breakpilot_feature": null,
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-022",
"title": "Protokollierungspflicht bei Strafverfolgung",
"description": "Zugriffe und Uebermittlungen personenbezogener Daten zu Strafverfolgungszwecken sind zu protokollieren (§ 51 BDSG).",
"applies_when": "organization processes data for law enforcement purposes",
"applies_when_condition": { "all_of": [{ "field": "organization.sector", "operator": "IN", "value": ["law_enforcement", "public_authority"] }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 51", "title": "Verarbeitungssicherheit" }],
"sources": [{ "type": "national_law", "ref": "§ 51 BDSG" }],
"category": "Technisch",
"responsible": "IT-Sicherheitsbeauftragter",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "personal_liability": true },
"evidence": [{ "name": "Protokollierungsrichtlinie", "required": true }, "Zugriffsprotokolle"],
"priority": "hoch",
"tom_control_ids": ["TOM.LOG.01", "TOM.AC.01"],
"breakpilot_feature": "/sdk/audit",
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-023",
"title": "Betroffenenrechte bei Strafverfolgung",
"description": "Auch im Bereich der Strafverfolgung bestehen Auskunfts-, Berichtigungs- und Loeschungsrechte der Betroffenen nach §§ 53-54 BDSG, ggf. mit Einschraenkungen.",
"applies_when": "law enforcement data processing",
"applies_when_condition": { "all_of": [{ "field": "organization.sector", "operator": "IN", "value": ["law_enforcement", "public_authority"] }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 53", "title": "Auskunftsrecht" }, { "norm": "BDSG", "article": "§ 54", "title": "Berichtigung und Loeschung" }],
"sources": [{ "type": "national_law", "ref": "§§ 53-54 BDSG" }],
"category": "Organisatorisch",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "relative", "duration": "P30D" },
"sanctions": { "personal_liability": true },
"evidence": [{ "name": "Betroffenenrechte-Prozess Strafverfolgung", "required": true }],
"priority": "mittel",
"tom_control_ids": ["TOM.GOV.02"],
"breakpilot_feature": "/sdk/dsr",
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-024",
"title": "Datenuebermittlung an Drittstaaten — besondere Voraussetzungen",
"description": "Die Uebermittlung personenbezogener Daten an Drittstaaten durch Polizei-/Justizbehoerden ist nur bei Vorliegen eines Angemessenheitsbeschlusses oder geeigneter Garantien zulaessig (§§ 62 ff. BDSG).",
"applies_when": "law enforcement transfers data to third countries",
"applies_when_condition": { "all_of": [{ "field": "organization.sector", "operator": "IN", "value": ["law_enforcement", "public_authority"] }, { "field": "data_protection.third_country_transfer", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 62", "title": "Uebermittlung bei Angemessenheitsbeschluss" }],
"sources": [{ "type": "national_law", "ref": "§§ 62-66 BDSG" }],
"category": "Compliance",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "on_event", "event": "Vor jeder Drittstaatenuebermittlung" },
"sanctions": { "personal_liability": true, "criminal_liability": true },
"evidence": [{ "name": "Angemessenheitsbeschluss-Pruefung", "required": true }],
"priority": "kritisch",
"tom_control_ids": ["TOM.GOV.03", "TOM.CRY.01"],
"breakpilot_feature": null,
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-025",
"title": "Datenuebermittlung ohne Angemessenheitsbeschluss",
"description": "Ohne Angemessenheitsbeschluss ist eine Uebermittlung an Drittstaaten nur bei geeigneten Garantien oder in Ausnahmefaellen nach § 63 BDSG zulaessig.",
"applies_when": "law enforcement transfers data to third country without adequacy decision",
"applies_when_condition": { "all_of": [{ "field": "organization.sector", "operator": "IN", "value": ["law_enforcement", "public_authority"] }, { "field": "data_protection.third_country_transfer", "operator": "EQUALS", "value": true }, { "field": "data_protection.adequacy_decision", "operator": "EQUALS", "value": false }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 63", "title": "Uebermittlung bei geeigneten Garantien" }],
"sources": [{ "type": "national_law", "ref": "§ 63 BDSG" }],
"category": "Compliance",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "on_event", "event": "Vor jeder Uebermittlung" },
"sanctions": { "personal_liability": true, "criminal_liability": true },
"evidence": [{ "name": "Geeignete Garantien dokumentiert", "required": true }],
"priority": "kritisch",
"tom_control_ids": ["TOM.GOV.03"],
"breakpilot_feature": null,
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-026",
"title": "Strafvorschriften — unbefugte Datenverarbeitung",
"description": "Wer wissentlich nicht allgemein zugaengliche personenbezogene Daten unbefugt verarbeitet, wird mit Freiheitsstrafe bis zu drei Jahren oder Geldstrafe bestraft (§ 42 BDSG).",
"applies_when": "always",
"applies_when_condition": { "all_of": [{ "field": "data_protection.processes_personal_data", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 42", "title": "Strafvorschriften" }],
"sources": [{ "type": "national_law", "ref": "§ 42 BDSG" }],
"category": "Compliance",
"responsible": "Geschaeftsfuehrung",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "Freiheitsstrafe bis 3 Jahre oder Geldstrafe", "personal_liability": true, "criminal_liability": true },
"evidence": [{ "name": "Datenschutzschulungsnachweis", "required": true }, "Zugriffsberechtigungskonzept"],
"priority": "kritisch",
"tom_control_ids": ["TOM.AC.01", "TOM.GOV.01"],
"breakpilot_feature": "/sdk/training",
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-027",
"title": "Bussgeld bei Verstoessen gegen Auskunftspflicht",
"description": "Ordnungswidrig handelt, wer einer vollziehbaren Anordnung der Aufsichtsbehoerde nach § 43 Abs. 1 BDSG zuwiderhandelt. Bussgelder bis 50.000 EUR.",
"applies_when": "always",
"applies_when_condition": { "all_of": [{ "field": "data_protection.processes_personal_data", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 43 Abs. 1", "title": "Bussgeldvorschriften" }],
"sources": [{ "type": "national_law", "ref": "§ 43 BDSG" }],
"category": "Compliance",
"responsible": "Geschaeftsfuehrung",
"deadline": { "type": "on_event", "event": "Bei Anordnung der Aufsichtsbehoerde" },
"sanctions": { "max_fine": "50.000 EUR" },
"evidence": [{ "name": "Korrespondenz Aufsichtsbehoerde", "required": false }],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01"],
"breakpilot_feature": null,
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-028",
"title": "Akkreditierung Zertifizierungsstellen",
"description": "Zertifizierungsstellen nach Art. 43 DSGVO beduerfern der Akkreditierung durch die zustaendige Aufsichtsbehoerde oder die DAkkS (§ 39 BDSG).",
"applies_when": "organization is or uses a certification body",
"applies_when_condition": { "all_of": [{ "field": "organization.certification_body", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 39", "title": "Akkreditierung" }],
"sources": [{ "type": "national_law", "ref": "§ 39 BDSG" }],
"category": "Audit",
"responsible": "Geschaeftsfuehrung",
"deadline": { "type": "recurring", "interval": "5 Jahre" },
"sanctions": { "max_fine": "10 Mio. EUR oder 2% Jahresumsatz" },
"evidence": [{ "name": "Akkreditierungsurkunde", "required": true }],
"priority": "niedrig",
"tom_control_ids": ["TOM.GOV.01"],
"breakpilot_feature": "/sdk/audit",
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-029",
"title": "Geheimhaltungspflicht und Datengeheimnis",
"description": "Personen, die bei der Datenverarbeitung taetig sind, duerfen personenbezogene Daten nicht unbefugt verarbeiten. Sie sind auf das Datengeheimnis zu verpflichten (§ 53 BDSG analog).",
"applies_when": "always",
"applies_when_condition": { "all_of": [{ "field": "organization.has_employees", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 53", "title": "Datengeheimnis" }],
"sources": [{ "type": "national_law", "ref": "§ 53 BDSG" }],
"category": "Schulung",
"responsible": "Personalleitung",
"deadline": { "type": "on_event", "event": "Bei Arbeitsaufnahme" },
"sanctions": { "personal_liability": true, "criminal_liability": true },
"evidence": [{ "name": "Verpflichtungserklaerung Datengeheimnis", "required": true }],
"priority": "hoch",
"tom_control_ids": ["TOM.HR.02", "TOM.GOV.05"],
"breakpilot_feature": "/sdk/training",
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
},
{
"id": "BDSG-OBL-030",
"title": "Verarbeitung im Auftrag — Vertragspflicht",
"description": "Die Auftragsverarbeitung ist durch einen Vertrag nach Art. 28 DSGVO i.V.m. § 29 BDSG zu regeln. Der Auftraggeber muss die TOM des Auftragsverarbeiters ueberpruefen.",
"applies_when": "organization uses data processors",
"applies_when_condition": { "all_of": [{ "field": "data_protection.uses_processors", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "BDSG", "article": "§ 29", "title": "Auftragsverarbeitung" }, { "norm": "DSGVO", "article": "Art. 28", "title": "Auftragsverarbeiter" }],
"sources": [{ "type": "national_law", "ref": "§ 29 BDSG" }, { "type": "article", "ref": "Art. 28 DSGVO" }],
"category": "Governance",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "on_event", "event": "Vor Beginn der Auftragsverarbeitung" },
"sanctions": { "max_fine": "10 Mio. EUR oder 2% Jahresumsatz" },
"evidence": [{ "name": "Auftragsverarbeitungsvertrag (AVV)", "required": true }, { "name": "TOM-Pruefbericht Auftragsverarbeiter", "required": true }],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.03", "TOM.VEN.01"],
"breakpilot_feature": "/sdk/vendor-compliance",
"valid_from": "2018-05-25",
"valid_until": null,
"version": "1.0"
}
],
"controls": [
{
"id": "BDSG-CTRL-001",
"name": "Videoueberwachungs-Compliance",
"description": "Kontrolle zur Sicherstellung der Einhaltung der Anforderungen an Videoueberwachung nach § 4 BDSG.",
"category": "Technisch",
"what_to_do": "Videoueberwachungskonzept erstellen, Beschilderung pruefen, Loeschfristen einhalten, DSFA durchfuehren.",
"iso27001_mapping": ["A.7.4"],
"priority": "hoch"
},
{
"id": "BDSG-CTRL-002",
"name": "Beschaeftigtendatenschutz-Kontrolle",
"description": "Kontrolle zur Pruefung der Einhaltung des § 26 BDSG bei der Verarbeitung von Beschaeftigtendaten.",
"category": "Organisatorisch",
"what_to_do": "Beschaeftigtendatenschutzrichtlinie erstellen, Einwilligungen pruefen, Betriebsvereinbarungen aktualisieren.",
"iso27001_mapping": ["A.6.1", "A.6.2"],
"priority": "hoch"
},
{
"id": "BDSG-CTRL-003",
"name": "DSB-Governance-Kontrolle",
"description": "Kontrolle zur Sicherstellung der ordnungsgemaessen Benennung und Unterstuetzung des Datenschutzbeauftragten.",
"category": "Governance",
"what_to_do": "DSB-Benennung pruefen, Ressourcen sicherstellen, Unabhaengigkeit gewaehrleisten, Schulung nachweisen.",
"iso27001_mapping": ["A.5.1"],
"priority": "kritisch"
},
{
"id": "BDSG-CTRL-004",
"name": "Bussgeld-Praevention und Compliance-Monitoring",
"description": "Kontrolle zur Vermeidung von Bussgeldern und strafrechtlichen Konsequenzen durch proaktives Compliance-Monitoring.",
"category": "Compliance",
"what_to_do": "Regelmaessige Compliance-Audits durchfuehren, Schulungen sicherstellen, Aufsichtsbehoerden-Anfragen zeitnah bearbeiten.",
"iso27001_mapping": ["A.5.36"],
"priority": "kritisch"
}
],
"incident_deadlines": [
{
"phase": "Erstmeldung an Aufsichtsbehoerde",
"deadline": "72 Stunden (gemaess DSGVO Art. 33, konkretisiert durch BDSG)",
"content": "Art der Verletzung, betroffene Datenkategorien und Personen, wahrscheinliche Folgen, ergriffene Massnahmen",
"recipient": "Zustaendige Landesdatenschutzbehoerde",
"legal_basis": [{ "norm": "DSGVO", "article": "Art. 33" }, { "norm": "BDSG", "article": "§ 40" }]
},
{
"phase": "Benachrichtigung Betroffener",
"deadline": "Unverzueglich bei hohem Risiko",
"content": "Art der Verletzung, Kontaktdaten DSB, wahrscheinliche Folgen, ergriffene Massnahmen",
"recipient": "Betroffene Personen",
"legal_basis": [{ "norm": "DSGVO", "article": "Art. 34" }]
},
{
"phase": "Meldung Strafverfolgungsbehoerden",
"deadline": "Unverzueglich bei Verdacht auf Straftat nach § 42 BDSG",
"content": "Sachverhaltsbeschreibung, beteiligte Personen, betroffene Daten",
"recipient": "Staatsanwaltschaft",
"legal_basis": [{ "norm": "BDSG", "article": "§ 42" }]
}
]
}

View File

@@ -0,0 +1,535 @@
{
"regulation": "data_act",
"name": "Data Act (EU) 2023/2854",
"description": "Verordnung ueber harmonisierte Vorschriften fuer einen fairen Datenzugang und eine faire Datennutzung — Regelt den Zugang zu und die Nutzung von Daten, die durch vernetzte Produkte und verbundene Dienste erzeugt werden",
"version": "2.0",
"effective_date": "2025-09-12",
"obligations": [
{
"id": "DATAACT-OBL-001",
"title": "Datenzugangsrecht fuer Nutzer — Design-Pflicht",
"description": "Vernetzte Produkte und verbundene Dienste muessen so konzipiert und hergestellt werden, dass die bei der Nutzung erzeugten Daten dem Nutzer standardmaessig leicht, sicher und unentgeltlich zugaenglich sind.",
"applies_when": "organization.manufactures_connected_products == true",
"applies_when_condition": {"field": "organization.manufactures_connected_products", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 3", "title": "Pflicht zur Zugaenglichmachung von Daten"}],
"sources": [{"type": "article", "ref": "Art. 3 Data Act"}],
"category": "Technisch",
"responsible": "Produktmanagement",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Design-Dokumentation Data-by-Design", "Technische Zugangsspezifikation"],
"priority": "kritisch",
"tom_control_ids": ["TOM.OPS.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-002",
"title": "Vorvertragliche Informationspflicht",
"description": "Vor Vertragsschluss muessen Nutzer klar und verstaendlich darueber informiert werden, welche Daten erzeugt werden, wie sie darauf zugreifen koennen und ob der Dateninhaber die Daten fuer eigene Zwecke nutzt.",
"applies_when": "organization.manufactures_connected_products == true",
"applies_when_condition": {"field": "organization.manufactures_connected_products", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 4", "title": "Vorvertragliche Informationspflichten"}],
"sources": [{"type": "article", "ref": "Art. 4 Data Act"}],
"category": "Dokumentation",
"responsible": "Rechtsabteilung",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Produktinformationsblatt", "AGB mit Dateninformationen"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-003",
"title": "Recht auf Datenzugang des Nutzers",
"description": "Nutzer haben das Recht, auf die durch die Nutzung eines vernetzten Produkts erzeugten Daten unverzueglich, unentgeltlich und in einem umfassenden, strukturierten, gaengigen und maschinenlesbaren Format zuzugreifen.",
"applies_when": "organization.manufactures_connected_products == true",
"applies_when_condition": {"field": "organization.manufactures_connected_products", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 5", "title": "Recht auf Zugang zu Daten"}],
"sources": [{"type": "article", "ref": "Art. 5 Data Act"}],
"category": "Technisch",
"responsible": "CTO",
"deadline": {"type": "on_event", "event": "Anfrage des Nutzers"},
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Datenzugangs-API", "Exportfunktion im Produkt", "Nachweis maschinenlesbares Format"],
"priority": "kritisch",
"tom_control_ids": ["TOM.OPS.01", "TOM.OPS.02"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-004",
"title": "Schutz von Geschaeftsgeheimnissen beim Datenzugang",
"description": "Dateninhaber duerfen den Datenzugang nur einschraenken, soweit dies zum Schutz von Geschaeftsgeheimnissen erforderlich ist. Massnahmen muessen verhaeltnismaessig sein und duerfen den Zugang nicht unzumutbar erschweren.",
"applies_when": "organization.manufactures_connected_products == true",
"applies_when_condition": {"field": "organization.manufactures_connected_products", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 5 Abs. 8", "title": "Schutz von Geschaeftsgeheimnissen"}],
"sources": [{"type": "article", "ref": "Art. 5 Abs. 8 Data Act"}],
"category": "Governance",
"responsible": "Rechtsabteilung",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Geschaeftsgeheimnis-Schutzkonzept", "Verhaeltnismaessigkeitspruefung"],
"priority": "mittel",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-005",
"title": "Datenweitergabe an Dritte auf Wunsch des Nutzers",
"description": "Auf Antrag des Nutzers muessen Dateninhaber die erzeugten Daten an einen vom Nutzer benannten Dritten unverzueglich, unentgeltlich und in gleicher Qualitaet wie dem Nutzer bereitstellen.",
"applies_when": "organization.manufactures_connected_products == true",
"applies_when_condition": {"field": "organization.manufactures_connected_products", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 6", "title": "Pflicht zur Bereitstellung von Daten an Dritte"}],
"sources": [{"type": "article", "ref": "Art. 6 Data Act"}],
"category": "Technisch",
"responsible": "CTO",
"deadline": {"type": "on_event", "event": "Antrag des Nutzers auf Datenweitergabe"},
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Datenweitergabe-Prozess", "Nutzerantragsformular", "Weitergabeprotokoll"],
"priority": "hoch",
"tom_control_ids": ["TOM.OPS.01", "TOM.OPS.02"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-006",
"title": "Pflichten des Datenempfaengers (Dritter)",
"description": "Datenempfaenger duerfen die erhaltenen Daten nur fuer die vereinbarten Zwecke nutzen. Sie duerfen die Daten nicht zur Entwicklung eines konkurrierenden Produkts verwenden und muessen sie nach Zweckerfuellung loeschen.",
"applies_when": "organization.receives_product_data == true",
"applies_when_condition": {"field": "organization.receives_product_data", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 7", "title": "Pflichten der Datenempfaenger"}],
"sources": [{"type": "article", "ref": "Art. 7 Data Act"}],
"category": "Compliance",
"responsible": "Rechtsabteilung",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Zweckbindungsvereinbarung", "Loeschnachweis nach Zweckerfuellung"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-007",
"title": "Angemessene Verguetung fuer Datenweitergabe",
"description": "Bei Datenweitergabe an Dritte duerfen Dateninhaber eine angemessene Verguetung verlangen. Gegenueber KMU darf die Verguetung die Kosten der Bereitstellung nicht uebersteigen.",
"applies_when": "organization.manufactures_connected_products == true",
"applies_when_condition": {"field": "organization.manufactures_connected_products", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 8", "title": "Verguetung fuer die Bereitstellung von Daten"}],
"sources": [{"type": "article", "ref": "Art. 8 Data Act"}],
"category": "Governance",
"responsible": "Finanzabteilung",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Verguetungsmodell", "Kostenkalkulation", "KMU-Sondertarife"],
"priority": "mittel",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-008",
"title": "Faire Vertragsbedingungen fuer Datenzugang",
"description": "Vertragsbedingungen fuer den Datenzugang und die Datennutzung muessen fair, angemessen und nicht-diskriminierend sein. Einseitig benachteiligende Klauseln sind unwirksam.",
"applies_when": "organization.manufactures_connected_products == true",
"applies_when_condition": {"field": "organization.manufactures_connected_products", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 9", "title": "Missbr. Vertragsklauseln in Bezug auf Datenzugang und -nutzung"}],
"sources": [{"type": "article", "ref": "Art. 9 Data Act"}],
"category": "Governance",
"responsible": "Rechtsabteilung",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Vertragspruefung auf Fairness", "AGB-Klauselkontrolle"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-009",
"title": "Unwirksamkeit missbraeuchlicher Vertragsklauseln",
"description": "Vertragsklauseln, die den Datenzugang oder die Datennutzung unangemessen einschraenken, sind nicht bindend. Die Beweislast fuer die Angemessenheit liegt beim Dateninhaber.",
"applies_when": "organization.manufactures_connected_products == true",
"applies_when_condition": {"field": "organization.manufactures_connected_products", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 10", "title": "Anwendung der Vorschriften fuer missbr. Vertragsklauseln"}],
"sources": [{"type": "article", "ref": "Art. 10 Data Act"}],
"category": "Compliance",
"responsible": "Rechtsabteilung",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Klauselregister mit Fairness-Bewertung"],
"priority": "mittel",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-010",
"title": "Mustervertragsbedingungen beachten",
"description": "Die Kommission erstellt Mustervertragsbedingungen fuer faire Datenzugangsvereinbarungen. Dateninhaber sollten diese bei der Gestaltung ihrer Vertraege beruecksichtigen.",
"applies_when": "organization.manufactures_connected_products == true",
"applies_when_condition": {"field": "organization.manufactures_connected_products", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 12", "title": "Mustervertragsbedingungen"}],
"sources": [{"type": "article", "ref": "Art. 12 Data Act"}],
"category": "Dokumentation",
"responsible": "Rechtsabteilung",
"sanctions": {"max_fine": "Keine direkte Sanktion (empfohlen)", "personal_liability": false},
"evidence": ["Verwendung von EU-Musterklauseln", "Dokumentation Abweichungen"],
"priority": "niedrig",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-011",
"title": "Wechsel von Cloud-Diensten — Vertragliche Mindestanforderungen",
"description": "Vertraege ueber Datenverarbeitungsdienste (Cloud, SaaS, IaaS, PaaS) muessen klare Bestimmungen zum Anbieterwechsel enthalten, einschliesslich Kuendigungsfristen, Datenexport und Uebergangsunterstuetzung.",
"applies_when": "organization.provides_cloud_services == true",
"applies_when_condition": {"field": "organization.provides_cloud_services", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 13", "title": "Vertragliche Rechte betreffend den Wechsel"}],
"sources": [{"type": "article", "ref": "Art. 13 Data Act"}],
"category": "Dokumentation",
"responsible": "Rechtsabteilung",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Vertragliche Wechselklauseln", "Datenexport-SLA"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01", "TOM.OPS.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-012",
"title": "Technische Pflichten beim Cloud-Wechsel",
"description": "Cloud-Anbieter muessen technische Massnahmen bereitstellen, um den Wechsel zu erleichtern: Datenexport in strukturiertem Format, API-Zugang waehrend der Uebergangsphase und Loeschung nach Abschluss des Wechsels.",
"applies_when": "organization.provides_cloud_services == true",
"applies_when_condition": {"field": "organization.provides_cloud_services", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 14", "title": "Technische Aspekte des Wechsels"}],
"sources": [{"type": "article", "ref": "Art. 14 Data Act"}],
"category": "Technisch",
"responsible": "CTO",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Datenexport-API-Dokumentation", "Migrationsleitfaden", "Loeschbestaetigung"],
"priority": "hoch",
"tom_control_ids": ["TOM.OPS.01", "TOM.OPS.02"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-013",
"title": "Schrittweiser Abbau von Wechselgebuehren",
"description": "Wechselgebuehren muessen ab dem 12. Januar 2027 schrittweise abgebaut und ab dem 12. Januar 2027 vollstaendig abgeschafft werden. Bis dahin duerfen nur kostenbasierte Gebuehren erhoben werden.",
"applies_when": "organization.provides_cloud_services == true",
"applies_when_condition": {"field": "organization.provides_cloud_services", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 16", "title": "Wechselgebuehren"}],
"sources": [{"type": "article", "ref": "Art. 16 Data Act"}],
"category": "Compliance",
"responsible": "Finanzabteilung",
"deadline": {"type": "absolute", "date": "2027-01-12"},
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Gebuehrenmodell-Dokumentation", "Nachweis schrittweiser Abbau"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-014",
"title": "Interoperabilitaet von Datenverarbeitungsdiensten",
"description": "Anbieter von Datenverarbeitungsdiensten muessen offene Schnittstellen und Standards unterstuetzen, um die Interoperabilitaet zwischen verschiedenen Diensten zu gewaehrleisten.",
"applies_when": "organization.provides_cloud_services == true",
"applies_when_condition": {"field": "organization.provides_cloud_services", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 17", "title": "Offene Interoperabilitaetsspezifikationen"}],
"sources": [{"type": "article", "ref": "Art. 17 Data Act"}],
"category": "Technisch",
"responsible": "CTO",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Interoperabilitaets-Spezifikation", "Offene API-Dokumentation"],
"priority": "hoch",
"tom_control_ids": ["TOM.OPS.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-015",
"title": "Wesentliche Anforderungen an Interoperabilitaet",
"description": "Interoperabilitaetsspezifikationen muessen transparent, offen, fair und nicht-diskriminierend sein. Sie muessen die Portabilitaet von Daten, Anwendungen und digitalen Assets ermoeglichen.",
"applies_when": "organization.provides_cloud_services == true",
"applies_when_condition": {"field": "organization.provides_cloud_services", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 18", "title": "Wesentliche Anforderungen fuer Interoperabilitaet"}],
"sources": [{"type": "article", "ref": "Art. 18 Data Act"}],
"category": "Technisch",
"responsible": "CTO",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Konformitaetsbewertung Interoperabilitaet", "Standardkonformitaet"],
"priority": "mittel",
"tom_control_ids": ["TOM.OPS.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-016",
"title": "Datenzugang fuer oeffentliche Stellen bei aussergewoehnlichem Bedarf",
"description": "Dateninhaber muessen oeffentlichen Stellen und EU-Organen bei aussergewoehnlichem Bedarf (Notfaelle, Statistiken) Daten zur Verfuegung stellen. Der Bedarf muss begruendet und verhaeltnismaessig sein.",
"applies_when": "organization.manufactures_connected_products == true",
"applies_when_condition": {"field": "organization.manufactures_connected_products", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 20", "title": "Recht auf Zugang fuer oeffentliche Stellen"}],
"sources": [{"type": "article", "ref": "Art. 20 Data Act"}],
"category": "Compliance",
"responsible": "Geschaeftsfuehrung",
"deadline": {"type": "on_event", "event": "Begruendetes Ersuchen einer oeffentlichen Stelle"},
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Prozess fuer Behoerdenanfragen", "Anfragenregister"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01", "TOM.OPS.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-017",
"title": "Begruendungspflicht bei Ablehnung des Datenzugangs",
"description": "Dateninhaber koennen ein Ersuchen einer oeffentlichen Stelle nur aus eng begrenzten Gruenden ablehnen. Die Ablehnung muss begruendet werden und der oeffentlichen Stelle mitgeteilt werden.",
"applies_when": "organization.manufactures_connected_products == true",
"applies_when_condition": {"field": "organization.manufactures_connected_products", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 21", "title": "Pflichten bei der Bereitstellung an oeffentliche Stellen"}],
"sources": [{"type": "article", "ref": "Art. 21 Data Act"}],
"category": "Compliance",
"responsible": "Rechtsabteilung",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Ablehnungsbegruendungen dokumentiert", "Kommunikationsprotokoll mit Behoerden"],
"priority": "mittel",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-018",
"title": "Unentgeltlichkeit bei Notfaellen",
"description": "Bei oeffentlichen Notfaellen (Pandemie, Naturkatastrophe) muessen Daten oeffentlichen Stellen unentgeltlich bereitgestellt werden. In anderen Faellen kann eine angemessene Verguetung verlangt werden.",
"applies_when": "organization.manufactures_connected_products == true",
"applies_when_condition": {"field": "organization.manufactures_connected_products", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 22", "title": "Verguetung bei aussergewoehnlichem Bedarf"}],
"sources": [{"type": "article", "ref": "Art. 22 Data Act"}],
"category": "Governance",
"responsible": "Finanzabteilung",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Notfall-Datenzugangs-Protokoll", "Verguetungsmodell fuer Nicht-Notfaelle"],
"priority": "mittel",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-019",
"title": "Schutz vor internationalem Datenzugriff",
"description": "Anbieter von Datenverarbeitungsdiensten muessen angemessene Massnahmen ergreifen, um den unrechtmaessigen internationalen Zugriff auf nicht-personenbezogene Daten durch Drittstaaten zu verhindern.",
"applies_when": "organization.provides_cloud_services == true",
"applies_when_condition": {"field": "organization.provides_cloud_services", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 23", "title": "Internationale Datenuebermittlung — Schutzmassnahmen"}],
"sources": [{"type": "article", "ref": "Art. 23 Data Act"}],
"category": "Technisch",
"responsible": "CISO",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Schutzkonzept gegen Drittstaaten-Zugriff", "Standortdokumentation der Datenzentren"],
"priority": "kritisch",
"tom_control_ids": ["TOM.OPS.01", "TOM.GOV.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-020",
"title": "Beachtung internationaler Abkommen",
"description": "Datenuebermittlungen an Drittstaaten duerfen nur auf Grundlage internationaler Abkommen oder anerkannter Angemessenheitsbeschluesse erfolgen. Anfragen von Drittstaaten-Gerichten oder -Behoerden muessen dem EU-Recht entsprechen.",
"applies_when": "organization.provides_cloud_services == true",
"applies_when_condition": {"field": "organization.provides_cloud_services", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 25", "title": "Internationale Zusammenarbeit"}],
"sources": [{"type": "article", "ref": "Art. 25 Data Act"}],
"category": "Compliance",
"responsible": "Rechtsabteilung",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Pruefung internationaler Anfragen", "Dokumentation der Rechtsgrundlagen"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-021",
"title": "Benennung einer zustaendigen Behoerde",
"description": "Unternehmen muessen die fuer sie zustaendige nationale Durchsetzungsbehoerde kennen und mit ihr kooperieren. Anfragen der Behoerde muessen fristgerecht beantwortet werden.",
"applies_when": "organization.manufactures_connected_products == true OR organization.provides_cloud_services == true",
"applies_when_condition": {
"any_of": [
{"field": "organization.manufactures_connected_products", "operator": "EQUALS", "value": true},
{"field": "organization.provides_cloud_services", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [{"norm": "Data Act", "article": "Art. 27", "title": "Zustaendige Behoerden"}],
"sources": [{"type": "article", "ref": "Art. 27 Data Act"}],
"category": "Governance",
"responsible": "Compliance-Beauftragter",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Kenntnis der zustaendigen Behoerde", "Kooperationsprotokoll"],
"priority": "mittel",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-022",
"title": "Sanktionsvermeidung — Rechtskonformitaetsprogramm",
"description": "Mitgliedstaaten legen wirksame, verhaeltnismaessige und abschreckende Sanktionen fest. Unternehmen muessen ein Rechtskonformitaetsprogramm implementieren, um Verstoesse zu vermeiden.",
"applies_when": "organization.manufactures_connected_products == true OR organization.provides_cloud_services == true",
"applies_when_condition": {
"any_of": [
{"field": "organization.manufactures_connected_products", "operator": "EQUALS", "value": true},
{"field": "organization.provides_cloud_services", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [{"norm": "Data Act", "article": "Art. 30", "title": "Sanktionen"}],
"sources": [{"type": "article", "ref": "Art. 30 Data Act"}],
"category": "Governance",
"responsible": "Compliance-Beauftragter",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Compliance-Programm-Dokumentation", "Schulungsnachweise"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01", "TOM.GOV.02"],
"breakpilot_feature": "/sdk/compliance-hub",
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-023",
"title": "Smart-Contract-Konformitaet",
"description": "Anbieter von Smart Contracts fuer die Datenweitergabe muessen sicherstellen, dass diese den Anforderungen des Data Act entsprechen, einschliesslich Zugangskontrollen, Kuendigungsmoeglichkeiten und Datensicherheit.",
"applies_when": "organization.uses_smart_contracts_for_data == true",
"applies_when_condition": {"field": "organization.uses_smart_contracts_for_data", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 28", "title": "Wesentliche Anforderungen an Smart Contracts"}],
"sources": [{"type": "article", "ref": "Art. 28 Data Act"}],
"category": "Technisch",
"responsible": "CTO",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Smart-Contract-Audit", "Konformitaetsbewertung"],
"priority": "mittel",
"tom_control_ids": ["TOM.OPS.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-024",
"title": "Verbot von Gatekeeper-Verhalten bei Daten",
"description": "Dateninhaber duerfen den Datenzugang nicht nutzen, um ihre Marktposition zu missbrauchen. Insbesondere darf der Zugang zu Reparatur- und Wartungsdaten fuer vernetzte Produkte nicht unangemessen verweigert werden.",
"applies_when": "organization.manufactures_connected_products == true",
"applies_when_condition": {"field": "organization.manufactures_connected_products", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "Data Act", "article": "Art. 6 Abs. 2", "title": "Verbot des Missbrauchs der Datenposition"}],
"sources": [{"type": "article", "ref": "Art. 6 Abs. 2 Data Act"}],
"category": "Compliance",
"responsible": "Rechtsabteilung",
"sanctions": {"max_fine": "Wirksam, verhaeltnismaessig und abschreckend (nationale Festlegung)", "personal_liability": false},
"evidence": ["Marktmissbrauchs-Pruefung", "Zugangsrichtlinie fuer Reparaturdaten"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
},
{
"id": "DATAACT-OBL-025",
"title": "Streitbeilegungsmechanismus",
"description": "Dateninhaber und Datenempfaenger muessen Zugang zu Streitbeilegungsstellen haben. Die Mitgliedstaaten benennen zertifizierte Stellen fuer aussergerichtliche Streitbeilegung bei Data-Act-Streitigkeiten.",
"applies_when": "organization.manufactures_connected_products == true OR organization.provides_cloud_services == true",
"applies_when_condition": {
"any_of": [
{"field": "organization.manufactures_connected_products", "operator": "EQUALS", "value": true},
{"field": "organization.provides_cloud_services", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [{"norm": "Data Act", "article": "Art. 29", "title": "Streitbeilegung"}],
"sources": [{"type": "article", "ref": "Art. 29 Data Act"}],
"category": "Organisatorisch",
"responsible": "Rechtsabteilung",
"sanctions": {"max_fine": "Keine direkte Sanktion (Verfahrensrecht)", "personal_liability": false},
"evidence": ["Hinweis auf Streitbeilegungsstellen", "Interne Eskalationsprozesse"],
"priority": "mittel",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2025-09-12",
"valid_until": null,
"version": "1.0"
}
],
"controls": [
{
"id": "DATAACT-CTRL-001",
"name": "Data-by-Design-Produktentwicklung",
"description": "Systematischer Prozess zur Sicherstellung, dass vernetzte Produkte den Datenzugang standardmaessig ermoeglichen",
"category": "Technisch",
"what_to_do": "Integration von Datenzugangs-APIs in die Produktarchitektur, maschinenlesbare Exportformate und Zugangsmanagement ab der Design-Phase",
"priority": "kritisch"
},
{
"id": "DATAACT-CTRL-002",
"name": "Cloud-Portabilitaets-Framework",
"description": "Technisches und vertragliches Framework zur Erleichterung des Wechsels zwischen Cloud-Anbietern",
"category": "Technisch",
"what_to_do": "Bereitstellung von Datenexport-APIs, Migrationswerkzeugen, standardisierten Formaten und Uebergangsunterstuetzung gemaess den Data-Act-Anforderungen",
"priority": "hoch"
},
{
"id": "DATAACT-CTRL-003",
"name": "Behoerden-Datenzugangs-Prozess",
"description": "Standardisierter Prozess zur Bearbeitung von Datenzugangsanfragen oeffentlicher Stellen",
"category": "Organisatorisch",
"what_to_do": "Einrichtung eines Anfragenmanagements mit Pruefung der Rechtsgrundlage, Verhaeltnismaessigkeitstest, Anonymisierung und fristgerechter Bereitstellung",
"priority": "hoch"
}
],
"incident_deadlines": [
{
"phase": "Datenzugangsanfrage des Nutzers",
"deadline": "Unverzueglich, ohne ungebuehrliche Verzoegerung",
"content": "Bereitstellung der angeforderten Daten in maschinenlesbarem Format",
"recipient": "Antragstellender Nutzer",
"legal_basis": [{"norm": "Data Act", "article": "Art. 5"}]
},
{
"phase": "Datenweitergabe an Dritte",
"deadline": "Unverzueglich nach Antrag des Nutzers",
"content": "Weitergabe der Daten an den vom Nutzer benannten Dritten",
"recipient": "Benannter Dritter",
"legal_basis": [{"norm": "Data Act", "article": "Art. 6"}]
},
{
"phase": "Ersuchen einer oeffentlichen Stelle (Notfall)",
"deadline": "Unverzueglich, spaetestens innerhalb der in der Anfrage gesetzten Frist",
"content": "Bereitstellung der angeforderten Daten an die oeffentliche Stelle",
"recipient": "Ersuchende oeffentliche Stelle",
"legal_basis": [{"norm": "Data Act", "article": "Art. 20"}]
},
{
"phase": "Cloud-Wechsel — Datenexport",
"deadline": "Maximal 30 Tage nach Kuendigung",
"content": "Vollstaendiger Export aller Daten, Anwendungen und digitalen Assets an den neuen Anbieter",
"recipient": "Kunde / neuer Cloud-Anbieter",
"legal_basis": [{"norm": "Data Act", "article": "Art. 14"}]
}
]
}

View File

@@ -0,0 +1,569 @@
{
"regulation": "dora",
"name": "Digital Operational Resilience Act (EU) 2022/2554",
"description": "Verordnung (EU) 2022/2554 ueber die digitale operationale Resilienz im Finanzsektor — einheitliche Anforderungen an IKT-Risikomanagement, Vorfallmeldung, Resilienz-Tests und Drittparteienrisiko",
"version": "1.0",
"effective_date": "2025-01-17",
"obligations": [
{
"id": "DORA-OBL-001",
"title": "IKT-Risikomanagement-Rahmen einrichten",
"description": "Einrichtung eines umfassenden IKT-Risikomanagement-Rahmens mit Strategien, Leitlinien und Verfahren zum Schutz aller IKT-Assets. Der Rahmen muss jaehrlich ueberprueft und nach schwerwiegenden Vorfaellen aktualisiert werden.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 5", "title": "Governance und Organisation"}
],
"sources": [
{"type": "article", "ref": "Art. 5 VO (EU) 2022/2554"}
],
"category": "Governance",
"responsible": "Geschaeftsfuehrung",
"deadline": {"type": "recurring", "interval": "P1Y"},
"sanctions": {"max_fine": "Bussgeld nach nationalem Recht", "personal_liability": true},
"evidence": ["IKT-Risikomanagement-Rahmen", "Jaehrlicher Review-Bericht"],
"priority": "kritisch",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-002",
"title": "IKT-Governance durch Leitungsorgan",
"description": "Das Leitungsorgan traegt die Gesamtverantwortung fuer das IKT-Risikomanagement. Es muss IKT-Strategien genehmigen, Rollen definieren, Budget zuweisen und sich regelmaessig ueber IKT-Risiken informieren lassen.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 5 Abs. 2", "title": "Verantwortung des Leitungsorgans"}
],
"sources": [
{"type": "article", "ref": "Art. 5 VO (EU) 2022/2554"}
],
"category": "Governance",
"responsible": "Vorstand/Geschaeftsfuehrung",
"evidence": ["Vorstandsbeschluss IKT-Strategie", "Schulungsnachweise Leitungsorgan"],
"priority": "kritisch",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-003",
"title": "IKT-Risikomanagement-Funktion einrichten",
"description": "Einrichtung einer unabhaengigen IKT-Risikomanagement-Kontrollfunktion (oder Beauftragung eines externen Dienstleisters bei kleinen Instituten). Die Funktion muss ueber ausreichende Ressourcen und Befugnisse verfuegen.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true},
{"field": "financial.is_regulated", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 6", "title": "IKT-Risikomanagement-Rahmen"}
],
"sources": [
{"type": "article", "ref": "Art. 6 VO (EU) 2022/2554"}
],
"category": "Organisatorisch",
"responsible": "CISO/IKT-Risikomanager",
"evidence": ["Stellenbeschreibung IKT-Risikomanager", "Organigramm", "Ressourcenplan"],
"priority": "hoch",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-004",
"title": "Identifikation aller IKT-Assets und -Risiken",
"description": "Vollstaendige Identifikation, Klassifizierung und Dokumentation aller IKT-gestuetzten Geschaeftsfunktionen, IKT-Assets, Informationsquellen und deren Abhaengigkeiten. Regelmnaessige Aktualisierung des IKT-Asset-Inventars.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 7", "title": "IKT-Systeme, -Protokolle und -Tools"}
],
"sources": [
{"type": "article", "ref": "Art. 7 VO (EU) 2022/2554"}
],
"category": "Technisch",
"responsible": "IT-Leiter",
"deadline": {"type": "recurring", "interval": "P1Y"},
"evidence": ["IKT-Asset-Inventar", "Abhaengigkeitsanalyse", "Klassifizierungsmatrix"],
"priority": "hoch",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-005",
"title": "IKT-Schutzmassnahmen implementieren",
"description": "Implementierung von Schutz- und Praeventionsmassnahmen fuer IKT-Systeme: Sicherheitsrichtlinien, Zugriffskontrollen, Verschluesselung, Netzwerksicherheit, Patch-Management und sichere Konfiguration.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 8", "title": "Schutz und Praevention"},
{"norm": "DORA", "article": "Art. 9", "title": "Erkennung"}
],
"sources": [
{"type": "article", "ref": "Art. 8-9 VO (EU) 2022/2554"}
],
"category": "Technisch",
"responsible": "CISO",
"evidence": ["Sicherheitsrichtlinien", "Zugriffsmatrix", "Patch-Management-Bericht"],
"priority": "kritisch",
"tom_control_ids": ["TOM.CRY.01", "TOM.ACC.01"],
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-006",
"title": "Anomalie-Erkennung und -Ueberwachung",
"description": "Einrichtung von Mechanismen zur Erkennung anomaler Aktivitaeten in IKT-Systemen einschliesslich Netzwerk-Performance, IKT-bezogener Vorfaelle und potenzieller Cyberbedrohungen. Mehrere Kontrollschichten implementieren.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 9", "title": "Erkennung"}
],
"sources": [
{"type": "article", "ref": "Art. 9 VO (EU) 2022/2554"}
],
"category": "Technisch",
"responsible": "SOC-Leiter",
"evidence": ["SIEM-Konfiguration", "Anomalie-Erkennungs-Berichte", "Monitoring-Dashboard"],
"priority": "hoch",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-007",
"title": "IKT-Vorfall-Reaktionsplaene",
"description": "Festlegung von Reaktions- und Wiederherstellungsplaenen fuer IKT-bezogene Vorfaelle mit klaren Rollen, Eskalationsverfahren und Kommunikationsplaenen. Regelmaessige Tests der Plaene durch Simulationen.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 10", "title": "Reaktion und Wiederherstellung"}
],
"sources": [
{"type": "article", "ref": "Art. 10 VO (EU) 2022/2554"}
],
"category": "Organisatorisch",
"responsible": "CISO",
"deadline": {"type": "recurring", "interval": "P1Y", "event": "Jaehrlicher Test"},
"evidence": ["Incident-Response-Plan", "Testbericht Simulation", "Eskalationsmatrix"],
"priority": "kritisch",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-008",
"title": "Backup- und Wiederherstellungsrichtlinien",
"description": "Erstellung und Umsetzung von Backup-Richtlinien mit festgelegten Umfang, Haeufigkeit und Aufbewahrungsfristen. Regelmaessige Tests der Wiederherstellung einschliesslich Systemwiederanlauf und Datenintegritaetspruefung.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 11", "title": "Backup-Strategien und Wiederherstellung"}
],
"sources": [
{"type": "article", "ref": "Art. 11 VO (EU) 2022/2554"}
],
"category": "Technisch",
"responsible": "IT-Leiter",
"deadline": {"type": "recurring", "interval": "P1Y"},
"evidence": ["Backup-Richtlinie", "Wiederherstellungstest-Protokoll", "RPO/RTO-Dokumentation"],
"priority": "kritisch",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-009",
"title": "Redundanz und Geschaeftskontinuitaet",
"description": "Sicherstellung der Geschaeftskontinuitaet durch redundante IKT-Kapazitaeten. Business-Continuity-Plaene muessen IKT-Ausfallszenarien abdecken und regelmaessig getestet werden.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true},
{"field": "financial.has_critical_ict", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 12", "title": "Geschaeftskontinuitaetsmanagement"}
],
"sources": [
{"type": "article", "ref": "Art. 12 VO (EU) 2022/2554"}
],
"category": "Technisch",
"responsible": "IT-Leiter",
"evidence": ["BCP-Plan", "Redundanz-Architektur", "BCP-Testbericht"],
"priority": "hoch",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-010",
"title": "Krisenkommunikation bei IKT-Vorfaellen",
"description": "Etablierung von Kommunikationsplaenen fuer IKT-bezogene Vorfaelle und Krisen: interne Kommunikation, Kommunikation mit Kunden und Gegenparteien, Medien und Aufsichtsbehoerden.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 13", "title": "Kommunikation"}
],
"sources": [
{"type": "article", "ref": "Art. 13 VO (EU) 2022/2554"}
],
"category": "Organisatorisch",
"responsible": "Kommunikationsabteilung",
"evidence": ["Krisenkommunikationsplan", "Kontaktlisten Behoerden", "Vorlagen Kundeninformation"],
"priority": "hoch",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-011",
"title": "Lessons Learned aus IKT-Vorfaellen",
"description": "Systematische Analyse und Aufarbeitung von IKT-bezogenen Vorfaellen. Erkenntnisse muessen dokumentiert und in die Verbesserung des IKT-Risikomanagement-Rahmens einfliessen.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 14", "title": "Lernen und Weiterentwicklung"}
],
"sources": [
{"type": "article", "ref": "Art. 14 VO (EU) 2022/2554"}
],
"category": "Organisatorisch",
"responsible": "CISO",
"evidence": ["Post-Incident-Reviews", "Massnahmenplan", "Schulungsunterlagen"],
"priority": "mittel",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-012",
"title": "IKT-Vorfallmanagement-Prozess",
"description": "Einrichtung eines Prozesses zur Erkennung, Verwaltung und Meldung IKT-bezogener Vorfaelle mit Fruehwarnindikatoren, Klassifizierungskriterien und Eskalationsverfahren.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 15", "title": "IKT-bezogenes Vorfallmanagement"}
],
"sources": [
{"type": "article", "ref": "Art. 15 VO (EU) 2022/2554"}
],
"category": "Organisatorisch",
"responsible": "CISO",
"evidence": ["Vorfallmanagement-Prozess", "Klassifizierungsschema", "Eskalationsmatrix"],
"priority": "kritisch",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-013",
"title": "Klassifizierung von IKT-Vorfaellen",
"description": "Klassifizierung aller IKT-bezogenen Vorfaelle nach definierten Kriterien: betroffene Kunden, Dauer, geografische Ausbreitung, Datenverluste, Kritikalitaet der Dienste und wirtschaftliche Auswirkungen.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 16", "title": "Klassifizierung IKT-bezogener Vorfaelle"}
],
"sources": [
{"type": "article", "ref": "Art. 16 VO (EU) 2022/2554"}
],
"category": "Organisatorisch",
"responsible": "CISO",
"evidence": ["Klassifizierungskriterien", "Vorfall-Register", "Schwellenwert-Dokumentation"],
"priority": "hoch",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-014",
"title": "Schwerwiegende IKT-Vorfaelle melden",
"description": "Schwerwiegende IKT-bezogene Vorfaelle muessen der zustaendigen Aufsichtsbehoerde gemeldet werden: Erstmeldung, Zwischenmeldung und Abschlussbericht innerhalb der vorgegebenen Fristen.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true},
{"field": "financial.is_regulated", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 17", "title": "Meldung schwerwiegender IKT-bezogener Vorfaelle"}
],
"sources": [
{"type": "article", "ref": "Art. 17 VO (EU) 2022/2554"}
],
"category": "Meldepflicht",
"responsible": "CISO",
"deadline": {"type": "on_event", "event": "Schwerwiegender IKT-Vorfall", "duration": "PT4H"},
"sanctions": {"max_fine": "Bussgeld nach nationalem Recht", "personal_liability": true},
"evidence": ["Erstmeldung", "Zwischenmeldung", "Abschlussbericht"],
"priority": "kritisch",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-015",
"title": "Freiwillige Meldung erheblicher Cyberbedrohungen",
"description": "Finanzunternehmen koennen erhebliche Cyberbedrohungen freiwillig der Aufsichtsbehoerde melden, wenn sie die Bedrohung als relevant fuer das Finanzsystem erachten. Standardisiertes Meldeformat verwenden.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 18", "title": "Freiwillige Meldung erheblicher Cyberbedrohungen"}
],
"sources": [
{"type": "article", "ref": "Art. 18 VO (EU) 2022/2554"}
],
"category": "Meldepflicht",
"responsible": "CISO",
"evidence": ["Meldeformular Cyberbedrohung", "Bedrohungsanalyse"],
"priority": "niedrig",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-016",
"title": "Programm fuer Tests der digitalen Resilienz",
"description": "Einrichtung eines umfassenden Programms fuer Tests der digitalen operationalen Resilienz: Schwachstellenscans, Open-Source-Analysen, Netzwerksicherheitsbewertungen, Penetrationstests und szenariobasierte Tests.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 19", "title": "Allgemeine Anforderungen an Tests"}
],
"sources": [
{"type": "article", "ref": "Art. 19 VO (EU) 2022/2554"}
],
"category": "Audit",
"responsible": "CISO",
"deadline": {"type": "recurring", "interval": "P1Y"},
"evidence": ["Testprogramm", "Schwachstellenscan-Berichte", "Penetrationstest-Bericht"],
"priority": "hoch",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-017",
"title": "Bedrohungsorientierte Penetrationstests (TLPT)",
"description": "Durchfuehrung bedrohungsorientierter Penetrationstests (Threat-Led Penetration Testing) mindestens alle 3 Jahre fuer bedeutende Finanzunternehmen. Tests muessen von qualifizierten externen Pruefern durchgefuehrt werden.",
"applies_when": "significant_financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true},
{"field": "financial.has_critical_ict", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 22", "title": "Bedrohungsorientierte Penetrationstests"}
],
"sources": [
{"type": "article", "ref": "Art. 22 VO (EU) 2022/2554"},
{"type": "eu_guidance", "ref": "TIBER-EU Framework"}
],
"category": "Audit",
"responsible": "CISO",
"deadline": {"type": "recurring", "interval": "P3Y"},
"evidence": ["TLPT-Bericht", "Qualifikationsnachweis Pruefer", "Massnahmenplan"],
"priority": "hoch",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-018",
"title": "IKT-Drittparteienrisiko-Management",
"description": "Verwaltung der Risiken aus der Nutzung von IKT-Drittdienstleistern: Risikoanalyse vor Vertragsschluss, vertragliche Mindestanforderungen, laufende Ueberwachung und Exit-Strategien fuer kritische IKT-Dienste.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 28", "title": "Allgemeine Grundsaetze"}
],
"sources": [
{"type": "article", "ref": "Art. 28 VO (EU) 2022/2554"}
],
"category": "Governance",
"responsible": "Einkauf/Vendor-Management",
"evidence": ["IKT-Drittanbieter-Register", "Risikoanalyse je Anbieter", "Exit-Strategie"],
"priority": "kritisch",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-019",
"title": "Vertragliche Anforderungen an IKT-Drittanbieter",
"description": "IKT-Dienstleistungsvertraege muessen Mindestanforderungen enthalten: SLA-Definitionen, Zugriffsrechte, Datenlokalisierung, Unterstuetzung bei Vorfaellen, Kuendigungsrechte und Audit-Rechte.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 28 Abs. 7-8", "title": "Vertragliche Anforderungen"},
{"norm": "DORA", "article": "Art. 30", "title": "Wesentliche Vertragsbestimmungen"}
],
"sources": [
{"type": "article", "ref": "Art. 28, 30 VO (EU) 2022/2554"}
],
"category": "Governance",
"responsible": "Rechtsabteilung",
"evidence": ["Vertragsvorlage IKT-Dienste", "SLA-Dokumentation", "Audit-Klausel"],
"priority": "hoch",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DORA-OBL-020",
"title": "Register aller IKT-Drittanbieter-Vertraege",
"description": "Fuehrung eines vollstaendigen Registers aller vertraglichen Vereinbarungen ueber IKT-Dienstleistungen. Das Register muss auf Anfrage der Aufsichtsbehoerde bereitgestellt werden und kritische IKT-Drittanbieter kennzeichnen.",
"applies_when": "financial_institution",
"applies_when_condition": {
"all_of": [
{"field": "financial.dora_applies", "operator": "EQUALS", "value": true},
{"field": "sector.is_financial_institution", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "DORA", "article": "Art. 28 Abs. 3", "title": "Informationsregister"}
],
"sources": [
{"type": "article", "ref": "Art. 28 VO (EU) 2022/2554"}
],
"category": "Dokumentation",
"responsible": "Vendor-Management",
"deadline": {"type": "recurring", "interval": "P1Y"},
"evidence": ["IKT-Vertragsregister", "Kritikalitaetsbewertung Anbieter"],
"priority": "hoch",
"valid_from": "2025-01-17",
"valid_until": null,
"version": "1.0"
}
],
"controls": [
{
"id": "DORA-CTRL-001",
"name": "IKT-Risikobewertung und -Ueberwachung",
"description": "Kontinuierliche Bewertung und Ueberwachung von IKT-Risiken mit automatisiertem Monitoring, regelmaessigen Schwachstellenscans und Risiko-Reporting an das Leitungsorgan.",
"category": "Governance",
"what_to_do": "SIEM/SOC einrichten, Risiko-Dashboard implementieren, quartalsweises Reporting an Vorstand etablieren.",
"iso27001_mapping": ["A.5.7", "A.8.8", "A.8.16"],
"priority": "kritisch"
},
{
"id": "DORA-CTRL-002",
"name": "IKT-Vorfallmelde-Prozess",
"description": "Standardisierter Prozess fuer die Klassifizierung und Meldung schwerwiegender IKT-Vorfaelle an die zustaendige Aufsichtsbehoerde innerhalb der vorgeschriebenen Fristen.",
"category": "Meldepflicht",
"what_to_do": "Meldevorlagen erstellen, Eskalationsketten definieren, Klassifizierungskriterien dokumentieren, Testmeldungen durchfuehren.",
"iso27001_mapping": ["A.5.24", "A.5.25", "A.5.26"],
"priority": "kritisch"
},
{
"id": "DORA-CTRL-003",
"name": "Resilienz-Testprogramm",
"description": "Jaehrliches Programm zur Pruefung der digitalen operationalen Resilienz: Vulnerability Assessments, Penetrationstests, Szenario-Tests und fuer bedeutende Institute TLPT alle 3 Jahre.",
"category": "Audit",
"what_to_do": "Testplan erstellen, qualifizierte Pruefer beauftragen, Ergebnisse dokumentieren und Massnahmen nachverfolgen.",
"iso27001_mapping": ["A.5.35", "A.5.36", "A.8.8"],
"priority": "hoch"
},
{
"id": "DORA-CTRL-004",
"name": "IKT-Drittanbieter-Due-Diligence",
"description": "Strukturierter Prozess zur Bewertung und laufenden Ueberwachung von IKT-Drittdienstleistern: Risikobewertung vor Vertragsschluss, SLA-Monitoring, Audit-Rechte und Exit-Planung.",
"category": "Governance",
"what_to_do": "Vendor-Assessment-Framework einrichten, Kritikalitaets-Klassifizierung durchfuehren, jaehrliche Reviews durchfuehren.",
"iso27001_mapping": ["A.5.19", "A.5.20", "A.5.21", "A.5.22"],
"priority": "hoch"
}
],
"incident_deadlines": [
{
"phase": "Erstmeldung",
"deadline": "4 Stunden nach Klassifizierung als schwerwiegend",
"content": "Erste Meldung mit grundlegenden Informationen: Art des Vorfalls, betroffene Dienste, erste Auswirkungseinschaetzung",
"recipient": "Zustaendige Aufsichtsbehoerde (BaFin/EZB)",
"legal_basis": [{"norm": "DORA", "article": "Art. 17"}]
},
{
"phase": "Zwischenmeldung",
"deadline": "72 Stunden nach Erstmeldung (oder bei wesentlicher Aenderung)",
"content": "Aktualisierte Informationen zu Ursache, Auswirkungen, ergriffenen Massnahmen und voraussichtlicher Wiederherstellung",
"recipient": "Zustaendige Aufsichtsbehoerde (BaFin/EZB)",
"legal_basis": [{"norm": "DORA", "article": "Art. 17"}]
},
{
"phase": "Abschlussbericht",
"deadline": "1 Monat nach Wiederherstellung des Normalbetriebs",
"content": "Vollstaendiger Bericht: Ursachenanalyse, Gesamtauswirkungen, ergriffene und geplante Massnahmen, Lessons Learned",
"recipient": "Zustaendige Aufsichtsbehoerde (BaFin/EZB)",
"legal_basis": [{"norm": "DORA", "article": "Art. 17"}]
}
]
}

View File

@@ -0,0 +1,742 @@
{
"regulation": "dsa",
"name": "Digital Services Act (EU) 2022/2065",
"description": "Verordnung ueber einen Binnenmarkt fuer digitale Dienste — Pflichten fuer Anbieter digitaler Dienste, Plattformen und sehr grosse Online-Plattformen (VLOPs/VLOSEs)",
"version": "2.0",
"effective_date": "2024-02-17",
"obligations": [
{
"id": "DSA-OBL-001",
"title": "Haftungsprivileg — Mere Conduit",
"description": "Vermittlungsdienste (reine Durchleitung) muessen sicherstellen, dass sie keine Kenntnis von rechtswidrigen Inhalten haben und bei Kenntnis unverzueglich handeln, um das Haftungsprivileg zu bewahren.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 6", "title": "Reine Durchleitung (Mere Conduit)"}],
"sources": [{"type": "article", "ref": "Art. 6 DSA"}],
"category": "Compliance",
"responsible": "Rechtsabteilung",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Dokumentation der Vermittlungstaetigkeiten", "Nachweise ueber fehlende Kenntnis"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-002",
"title": "Haftungsprivileg — Caching",
"description": "Caching-Dienste muessen bei Kenntniserlangung rechtswidriger Inhalte unverzueglich taetig werden, um diese zu entfernen oder den Zugang zu sperren.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 7", "title": "Caching"}],
"sources": [{"type": "article", "ref": "Art. 7 DSA"}],
"category": "Compliance",
"responsible": "Rechtsabteilung",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Caching-Richtlinie", "Reaktionsprotokolle bei Kenntniserlangung"],
"priority": "mittel",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-003",
"title": "Haftungsprivileg — Hosting",
"description": "Hosting-Dienste muessen bei tatsaechlicher Kenntnis rechtswidriger Inhalte oder Taetigkeiten unverzueglich handeln, um diese zu entfernen oder den Zugang zu sperren.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 8", "title": "Hosting"}],
"sources": [{"type": "article", "ref": "Art. 8 DSA"}],
"category": "Compliance",
"responsible": "Rechtsabteilung",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Notice-and-Action-Protokolle", "Nachweis unverzueglicher Reaktion"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01", "TOM.OPS.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-004",
"title": "Keine allgemeine Ueberwachungspflicht",
"description": "Anbietern darf keine allgemeine Verpflichtung zur Ueberwachung der uebermittelten oder gespeicherten Informationen auferlegt werden. Freiwillige Eigeninitiative fuehrt nicht zum Verlust des Haftungsprivilegs.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 9", "title": "Keine allgemeine Ueberwachungspflicht"}],
"sources": [{"type": "article", "ref": "Art. 9 DSA"}],
"category": "Governance",
"responsible": "Rechtsabteilung",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Dokumentation Moderationsrichtlinie", "Nachweis keine allgemeine Ueberwachung"],
"priority": "mittel",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-005",
"title": "Zentrale Kontaktstelle",
"description": "Benennung einer zentralen Kontaktstelle fuer die Kommunikation mit Behoerden der Mitgliedstaaten, der Kommission und dem Gremium fuer digitale Dienste. Die Kontaktstelle muss in einer Amtssprache erreichbar sein.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 11", "title": "Kontaktstellen fuer Behoerden"}],
"sources": [{"type": "article", "ref": "Art. 11 DSA"}],
"category": "Organisatorisch",
"responsible": "Geschaeftsfuehrung",
"sanctions": {"max_fine": "1% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Benennungsdokument Kontaktstelle", "Veroeffentlichte Kontaktdaten"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01", "TOM.GOV.02"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-006",
"title": "Gesetzlicher Vertreter",
"description": "Anbieter ohne Niederlassung in der EU muessen einen gesetzlichen Vertreter in einem Mitgliedstaat benennen, in dem sie Dienste anbieten.",
"applies_when": "organization.eu_member == false AND organization.operates_platform == true",
"applies_when_condition": {
"all_of": [
{"field": "organization.eu_member", "operator": "EQUALS", "value": false},
{"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [{"norm": "DSA", "article": "Art. 12", "title": "Gesetzlicher Vertreter"}],
"sources": [{"type": "article", "ref": "Art. 12 DSA"}],
"category": "Organisatorisch",
"responsible": "Geschaeftsfuehrung",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Benennungsurkunde gesetzlicher Vertreter", "Veroeffentlichung auf der Webseite"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-007",
"title": "Allgemeine Geschaeftsbedingungen — Inhaltsmoderation",
"description": "In den AGB muessen Informationen zu Beschraenkungen enthalten sein, die Anbieter in Bezug auf von Nutzern bereitgestellte Inhalte auferlegen. Dies umfasst Moderationsrichtlinien, algorithmische Entscheidungsfindung und Beschwerdemechanismen.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 13", "title": "Allgemeine Geschaeftsbedingungen"}],
"sources": [{"type": "article", "ref": "Art. 13 DSA"}],
"category": "Dokumentation",
"responsible": "Rechtsabteilung",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Aktuelle AGB mit Moderationsrichtlinien", "Verstaendliche Darstellung der Beschraenkungen"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01"],
"breakpilot_feature": "/sdk/policy-generator",
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-008",
"title": "Transparenzbericht — Vermittlungsdienste",
"description": "Jaehrliche Veroeffentlichung eines Transparenzberichts ueber Inhaltsmoderation, behoerdliche Anordnungen und Notice-and-Action-Verfahren. Der Bericht muss maschinenlesbar und oeffentlich zugaenglich sein.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 14", "title": "Transparenzberichterstattungspflichten fuer Anbieter von Vermittlungsdiensten"}],
"sources": [{"type": "article", "ref": "Art. 14 DSA"}],
"category": "Dokumentation",
"responsible": "Compliance-Beauftragter",
"deadline": {"type": "recurring", "interval": "P1Y"},
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Veroeffentlichter Transparenzbericht", "Maschinenlesbares Format"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01", "TOM.GOV.03"],
"breakpilot_feature": "/sdk/reporting",
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-009",
"title": "Transparenzbericht — erweitert fuer Online-Plattformen",
"description": "Online-Plattformen muessen zusaetzlich Informationen ueber Streitbeilegungsverfahren, Aussetzungen, automatisierte Inhaltserkennung und Trusted Flagger in ihren Transparenzbericht aufnehmen.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 15", "title": "Transparenzberichterstattungspflichten fuer Anbieter von Online-Plattformen"}],
"sources": [{"type": "article", "ref": "Art. 15 DSA"}],
"category": "Dokumentation",
"responsible": "Compliance-Beauftragter",
"deadline": {"type": "recurring", "interval": "P6M"},
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Erweiterter Transparenzbericht", "Statistik automatisierter Moderation"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01", "TOM.GOV.03"],
"breakpilot_feature": "/sdk/reporting",
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-010",
"title": "Melde- und Abhilfeverfahren (Notice-and-Action)",
"description": "Einrichtung eines leicht zugaenglichen und benutzerfreundlichen Mechanismus, der es jeder Person ermoeglicht, mutmasslich rechtswidrige Inhalte zu melden. Meldungen muessen elektronisch moeglich sein und eine Bestaetigung ausloesen.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 16", "title": "Melde- und Abhilfeverfahren"}],
"sources": [{"type": "article", "ref": "Art. 16 DSA"}],
"category": "Technisch",
"responsible": "Produktmanagement",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Implementiertes Meldeformular", "Bestaetigung der Eingangsbehandlung", "Verarbeitungsprotokoll"],
"priority": "kritisch",
"tom_control_ids": ["TOM.OPS.01", "TOM.OPS.02"],
"breakpilot_feature": "/sdk/incident-response",
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-011",
"title": "Begruendungspflicht bei Inhaltsentfernung",
"description": "Bei Entfernung oder Sperrung von Inhalten muss dem betroffenen Nutzer eine klare und spezifische Begruendung mitgeteilt werden, einschliesslich der angewandten Rechtsgrundlage und der Rechtsbehelfsmoeglichkeiten.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 17", "title": "Begruendung"}],
"sources": [{"type": "article", "ref": "Art. 17 DSA"}],
"category": "Organisatorisch",
"responsible": "Content-Moderation-Team",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Begruendungsvorlagen", "Muster-Benachrichtigungen", "Zustellungsnachweise"],
"priority": "hoch",
"tom_control_ids": ["TOM.OPS.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-012",
"title": "Meldung strafbarer Inhalte an Behoerden",
"description": "Bei Verdacht auf Straftaten, die das Leben oder die Sicherheit von Personen bedrohen, muessen die zustaendigen Strafverfolgungsbehoerden des betreffenden Mitgliedstaats unverzueglich informiert werden.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 18", "title": "Meldung von Verdacht auf Straftaten"}],
"sources": [{"type": "article", "ref": "Art. 18 DSA"}],
"category": "Meldepflicht",
"responsible": "Rechtsabteilung",
"deadline": {"type": "on_event", "event": "Kenntniserlangung strafbarer Inhalte"},
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": true, "criminal_liability": true},
"evidence": ["Eskalationsprozess-Dokumentation", "Meldungsprotokolle an Behoerden"],
"priority": "kritisch",
"tom_control_ids": ["TOM.OPS.01", "TOM.GOV.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-013",
"title": "Trusted Flaggers",
"description": "Vorrangige Bearbeitung von Meldungen vertrauenswuerdiger Hinweisgeber (Trusted Flaggers), die vom Koordinator fuer digitale Dienste zertifiziert wurden. Entscheidungen ueber Meldungen von Trusted Flaggers muessen zeitnah erfolgen.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 19", "title": "Vertrauenswuerdige Hinweisgeber"}],
"sources": [{"type": "article", "ref": "Art. 19 DSA"}],
"category": "Organisatorisch",
"responsible": "Content-Moderation-Team",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Priorisierungsprozess fuer Trusted Flaggers", "SLA-Dokumentation"],
"priority": "hoch",
"tom_control_ids": ["TOM.OPS.01", "TOM.OPS.02"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-014",
"title": "Schutz vor Missbrauch des Meldesystems",
"description": "Aussetzung der Bearbeitung von Meldungen und Beschwerden von Personen oder Stellen, die haeufig offensichtlich unbegruendete Meldungen oder Beschwerden einreichen.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 20", "title": "Schutz vor Missbrauch"}],
"sources": [{"type": "article", "ref": "Art. 20 DSA"}],
"category": "Organisatorisch",
"responsible": "Content-Moderation-Team",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Anti-Missbrauchs-Richtlinie", "Dokumentation der Aussetzungsentscheidungen"],
"priority": "mittel",
"tom_control_ids": ["TOM.OPS.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-015",
"title": "Aussetzung wegen Missbrauch durch Nutzer",
"description": "Anbieter von Online-Plattformen setzen die Erbringung ihrer Dienste fuer Nutzer aus, die haeufig offensichtlich rechtswidrige Inhalte bereitstellen. Vorherige Warnung erforderlich.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 21", "title": "Aussetzung"}],
"sources": [{"type": "article", "ref": "Art. 21 DSA"}],
"category": "Organisatorisch",
"responsible": "Content-Moderation-Team",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Eskalationsstufenmodell", "Warnprotokolle", "Aussetzungsentscheidungen"],
"priority": "mittel",
"tom_control_ids": ["TOM.OPS.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-016",
"title": "Internes Beschwerdemanagementsystem",
"description": "Bereitstellung eines elektronischen und benutzerfreundlichen internen Beschwerdemanagementsystems, ueber das Nutzer Entscheidungen zur Inhaltsmoderation anfechten koennen. Entscheidungen duerfen nicht ausschliesslich automatisiert getroffen werden.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 22", "title": "Internes Beschwerdemanagementsystem"}],
"sources": [{"type": "article", "ref": "Art. 22 DSA"}],
"category": "Technisch",
"responsible": "Produktmanagement",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Implementiertes Beschwerdesystem", "Verarbeitungsstatistik", "Human-Review-Nachweis"],
"priority": "kritisch",
"tom_control_ids": ["TOM.OPS.01", "TOM.OPS.02"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-017",
"title": "Aussergerichtliche Streitbeilegung",
"description": "Nutzer muessen die Moeglichkeit haben, sich an eine zertifizierte aussergerichtliche Streitbeilegungsstelle zu wenden. Plattformen muessen mit diesen Stellen zusammenarbeiten.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 23", "title": "Aussergerichtliche Streitbeilegung"}],
"sources": [{"type": "article", "ref": "Art. 23 DSA"}],
"category": "Organisatorisch",
"responsible": "Rechtsabteilung",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Hinweis auf Streitbeilegungsstellen in AGB", "Kooperationsvereinbarungen"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-018",
"title": "Vorrang behoerdlicher Anordnungen",
"description": "Online-Plattformen muessen behoerdliche Anordnungen gegen rechtswidrige Inhalte vorrangig bearbeiten und den behoerdlichen Anweisungen fristgerecht Folge leisten.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 24", "title": "Pflichten im Zusammenhang mit Anordnungen"}],
"sources": [{"type": "article", "ref": "Art. 24 DSA"}],
"category": "Compliance",
"responsible": "Rechtsabteilung",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": true},
"evidence": ["Anordnungsregister", "Fristeinhaltungsprotokolle"],
"priority": "kritisch",
"tom_control_ids": ["TOM.GOV.01", "TOM.OPS.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-019",
"title": "Werbetransparenz — Kennzeichnungspflicht",
"description": "Jede Werbung auf der Plattform muss klar und eindeutig als Werbung gekennzeichnet sein. Der Auftraggeber und die Finanzierungsquelle muessen erkennbar sein.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 26", "title": "Werbung auf Online-Plattformen"}],
"sources": [{"type": "article", "ref": "Art. 26 DSA"}],
"category": "Technisch",
"responsible": "Produktmanagement",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Werbekennzeichnungs-Implementierung", "Audit der Werbeanzeigen"],
"priority": "hoch",
"tom_control_ids": ["TOM.OPS.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-020",
"title": "Verbot von Dark Patterns",
"description": "Gestaltung der Online-Schnittstelle darf Nutzer nicht taueschen, manipulieren oder in ihrer Entscheidungsfreiheit beeintraechtigen (Verbot von Dark Patterns).",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 27", "title": "Verbot taeuschender Gestaltung"}],
"sources": [{"type": "article", "ref": "Art. 27 DSA"}],
"category": "Technisch",
"responsible": "UX-Team",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["UX-Audit auf Dark Patterns", "Design-Review-Protokolle"],
"priority": "hoch",
"tom_control_ids": ["TOM.OPS.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-021",
"title": "Transparenz von Empfehlungssystemen",
"description": "Plattformen muessen in ihren AGB die Hauptparameter der Empfehlungssysteme und die Moeglichkeit fuer Nutzer, diese zu beeinflussen, darlegen. Mindestens eine nicht-profilbasierte Option muss angeboten werden.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 28", "title": "Empfehlungssysteme"}],
"sources": [{"type": "article", "ref": "Art. 28 DSA"}],
"category": "Technisch",
"responsible": "Produktmanagement",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Dokumentation der Empfehlungsparameter", "Nutzerwahlmoeglichkeit implementiert"],
"priority": "hoch",
"tom_control_ids": ["TOM.OPS.01", "TOM.GOV.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-022",
"title": "Minderjaehrigenschutz auf Plattformen",
"description": "Online-Plattformen muessen geeignete Massnahmen zum Schutz Minderjaehriger treffen, einschliesslich altersgerechter Datenschutzeinstellungen. Werbung auf Basis von Profiling Minderjaehriger ist verboten.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 29", "title": "Schutz Minderjaehriger"}],
"sources": [{"type": "article", "ref": "Art. 29 DSA"}],
"category": "Technisch",
"responsible": "Produktmanagement",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Jugendschutzkonzept", "Altersverifikationslogik", "Profiling-Ausschluss fuer Minderjaehrige"],
"priority": "kritisch",
"tom_control_ids": ["TOM.OPS.01", "TOM.GOV.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-023",
"title": "VLOP/VLOSE — Zusaetzliche Transparenz Werbearchiv",
"description": "Sehr grosse Online-Plattformen muessen ein oeffentlich zugaengliches Werbearchiv fuehren, das alle geschalteten Werbeanzeigen mit Targeting-Parametern, Auftraggeber und Laufzeit enthaelt.",
"applies_when": "platform_user_count >= 45000000",
"applies_when_condition": {"field": "data_protection.platform_user_count", "operator": "GREATER_OR_EQUAL", "value": 45000000},
"legal_basis": [{"norm": "DSA", "article": "Art. 30", "title": "Zusaetzliche Transparenz der Online-Werbung"}],
"sources": [{"type": "article", "ref": "Art. 30 DSA"}],
"category": "Technisch",
"responsible": "Produktmanagement",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Implementiertes Werbearchiv", "API-Zugang fuer Forscher"],
"priority": "kritisch",
"tom_control_ids": ["TOM.OPS.01", "TOM.GOV.03"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-024",
"title": "VLOP/VLOSE — Empfehlungssystem Nutzerwahlrecht",
"description": "Sehr grosse Plattformen muessen Nutzern mindestens eine Option zur Verfuegung stellen, bei der das Empfehlungssystem nicht auf Profiling basiert.",
"applies_when": "platform_user_count >= 45000000",
"applies_when_condition": {"field": "data_protection.platform_user_count", "operator": "GREATER_OR_EQUAL", "value": 45000000},
"legal_basis": [{"norm": "DSA", "article": "Art. 31", "title": "Empfehlungssysteme fuer VLOPs"}],
"sources": [{"type": "article", "ref": "Art. 31 DSA"}],
"category": "Technisch",
"responsible": "Produktmanagement",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Nicht-profilbasierte Empfehlungsoption", "Nutzerauswahl-UI"],
"priority": "hoch",
"tom_control_ids": ["TOM.OPS.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-025",
"title": "VLOP/VLOSE — Datenzugang fuer Forscher",
"description": "Sehr grosse Plattformen muessen zugelassenen Forschern auf Antrag Zugang zu Daten gewaehren, um systemische Risiken zu erforschen. Der Zugang erfolgt ueber technische Schnittstellen.",
"applies_when": "platform_user_count >= 45000000",
"applies_when_condition": {"field": "data_protection.platform_user_count", "operator": "GREATER_OR_EQUAL", "value": 45000000},
"legal_basis": [{"norm": "DSA", "article": "Art. 32", "title": "Datenzugang fuer Forscher"}],
"sources": [{"type": "article", "ref": "Art. 32 DSA"}],
"category": "Technisch",
"responsible": "CTO",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Forschungsdaten-API", "Antragsverfahren dokumentiert", "Datenschutzkonzept fuer Forschungsdaten"],
"priority": "hoch",
"tom_control_ids": ["TOM.OPS.01", "TOM.GOV.03"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-026",
"title": "VLOP/VLOSE — Systemische Risikobewertung",
"description": "Jaehrliche Bewertung systemischer Risiken wie illegale Inhalte, Grundrechtsbeeintraechtigungen, Manipulation von Wahlen und Auswirkungen auf Minderjaehrige. Die Bewertung muss dokumentiert und der Aufsichtsbehoerde vorgelegt werden.",
"applies_when": "platform_user_count >= 45000000",
"applies_when_condition": {"field": "data_protection.platform_user_count", "operator": "GREATER_OR_EQUAL", "value": 45000000},
"legal_basis": [{"norm": "DSA", "article": "Art. 33", "title": "Bewertung systemischer Risiken"}],
"sources": [{"type": "article", "ref": "Art. 33 DSA"}],
"category": "Governance",
"responsible": "Compliance-Beauftragter",
"deadline": {"type": "recurring", "interval": "P1Y"},
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": true},
"evidence": ["Systemische Risikobewertung", "Massnahmenplan", "Vorlage bei Aufsichtsbehoerde"],
"priority": "kritisch",
"tom_control_ids": ["TOM.GOV.01", "TOM.GOV.02", "TOM.GOV.03"],
"breakpilot_feature": "/sdk/risk-assessment",
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-027",
"title": "VLOP/VLOSE — Risikominderungsmassnahmen",
"description": "Ergreifung angemessener, verhaeltnismaessiger und wirksamer Risikominderungsmassnahmen fuer die identifizierten systemischen Risiken. Massnahmen muessen regelmaessig ueberprueft und angepasst werden.",
"applies_when": "platform_user_count >= 45000000",
"applies_when_condition": {"field": "data_protection.platform_user_count", "operator": "GREATER_OR_EQUAL", "value": 45000000},
"legal_basis": [{"norm": "DSA", "article": "Art. 34", "title": "Risikominderung"}],
"sources": [{"type": "article", "ref": "Art. 34 DSA"}],
"category": "Governance",
"responsible": "Compliance-Beauftragter",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": true},
"evidence": ["Risikominderungsplan", "Wirksamkeitsbewertung", "Anpassungsdokumentation"],
"priority": "kritisch",
"tom_control_ids": ["TOM.GOV.01", "TOM.GOV.02"],
"breakpilot_feature": "/sdk/risk-assessment",
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-028",
"title": "VLOP/VLOSE — Unabhaengige Audits",
"description": "Jaehrliche unabhaengige Audits auf eigene Kosten zur Bewertung der Einhaltung der DSA-Pflichten. Der Auditbericht wird der Aufsichtsbehoerde uebermittelt und ein Zusammenfassung veroeffentlicht.",
"applies_when": "platform_user_count >= 45000000",
"applies_when_condition": {"field": "data_protection.platform_user_count", "operator": "GREATER_OR_EQUAL", "value": 45000000},
"legal_basis": [{"norm": "DSA", "article": "Art. 35", "title": "Unabhaengige Pruefung"}],
"sources": [{"type": "article", "ref": "Art. 35 DSA"}],
"category": "Audit",
"responsible": "Geschaeftsfuehrung",
"deadline": {"type": "recurring", "interval": "P1Y"},
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": true},
"evidence": ["Auditbericht", "Massnahmenplan aus Audit-Ergebnissen", "Veroeffentlichte Zusammenfassung"],
"priority": "kritisch",
"tom_control_ids": ["TOM.GOV.01", "TOM.GOV.03"],
"breakpilot_feature": "/sdk/audit",
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-029",
"title": "Compliance-Beauftragter (VLOP/VLOSE)",
"description": "Sehr grosse Plattformen muessen einen oder mehrere Compliance-Beauftragte benennen, die die Einhaltung des DSA ueberwachen. Der Beauftragte berichtet direkt an die Leitungsebene.",
"applies_when": "platform_user_count >= 45000000",
"applies_when_condition": {"field": "data_protection.platform_user_count", "operator": "GREATER_OR_EQUAL", "value": 45000000},
"legal_basis": [{"norm": "DSA", "article": "Art. 37", "title": "Compliance-Funktion"}],
"sources": [{"type": "article", "ref": "Art. 37 DSA"}],
"category": "Governance",
"responsible": "Geschaeftsfuehrung",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Benennungsurkunde", "Berichtsstruktur", "Kompetenznachweis"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01", "TOM.GOV.02"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-030",
"title": "Datenzugang fuer Aufsichtsbehoerden",
"description": "Auf Anfrage muessen Plattformen den Koordinatoren fuer digitale Dienste und der Kommission Zugang zu relevanten Daten gewaehren, die zur Ueberwachung der DSA-Einhaltung erforderlich sind.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 38", "title": "Datenzugang und Datenueberpruefung"}],
"sources": [{"type": "article", "ref": "Art. 38 DSA"}],
"category": "Compliance",
"responsible": "Compliance-Beauftragter",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Datenzugangsprozess dokumentiert", "Technische Schnittstelle fuer Behoerden"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01", "TOM.OPS.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-031",
"title": "VLOP/VLOSE — Datenzugang fuer ueberprueften Forscher",
"description": "Gewaehrung eines angemessenen Datenzugangs fuer von der Aufsichtsbehoerde ueberprueften Forscher zur Erforschung systemischer Risiken. Personenbezogene Daten nur anonymisiert oder pseudonymisiert.",
"applies_when": "platform_user_count >= 45000000",
"applies_when_condition": {"field": "data_protection.platform_user_count", "operator": "GREATER_OR_EQUAL", "value": 45000000},
"legal_basis": [{"norm": "DSA", "article": "Art. 39", "title": "Datenzugang fuer ueberprueften Forscher"}],
"sources": [{"type": "article", "ref": "Art. 39 DSA"}],
"category": "Technisch",
"responsible": "CTO",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Pseudonymisierungskonzept", "Forschungsdaten-Zugangsverfahren"],
"priority": "hoch",
"tom_control_ids": ["TOM.OPS.01", "TOM.GOV.03"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-032",
"title": "Verhaltenskodizes",
"description": "Unterstuetzung und Einhaltung freiwilliger Verhaltenskodizes auf EU-Ebene zur Bekaempfung rechtswidriger Inhalte und zum Schutz der Nutzer. Die Kommission foerdert die Erarbeitung solcher Kodizes.",
"applies_when": "organization.operates_platform == true",
"applies_when_condition": {"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
"legal_basis": [{"norm": "DSA", "article": "Art. 40", "title": "Verhaltenskodizes"}],
"sources": [{"type": "article", "ref": "Art. 40 DSA"}],
"category": "Governance",
"responsible": "Compliance-Beauftragter",
"sanctions": {"max_fine": "1% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Beitrittserklarung zu Verhaltenskodizes", "Umsetzungsbericht"],
"priority": "mittel",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-033",
"title": "Krisenreaktionsprotokolle",
"description": "Bei aussergewoehnlichen Umstaenden (z.B. Pandemie, bewaffnete Konflikte) kann die Kommission VLOPs/VLOSEs zur Teilnahme an Krisenprotokollen verpflichten. Schnelle Reaktionsmechanismen muessen vorbereitet sein.",
"applies_when": "platform_user_count >= 45000000",
"applies_when_condition": {"field": "data_protection.platform_user_count", "operator": "GREATER_OR_EQUAL", "value": 45000000},
"legal_basis": [{"norm": "DSA", "article": "Art. 42", "title": "Krisenreaktionsprotokolle"}],
"sources": [{"type": "article", "ref": "Art. 42 DSA"}],
"category": "Governance",
"responsible": "Geschaeftsfuehrung",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": true},
"evidence": ["Krisenreaktionsplan", "Ansprechpartner fuer Krisenkoordination"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01", "TOM.OPS.01"],
"breakpilot_feature": "/sdk/notfallplan",
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-034",
"title": "Koordinator fuer digitale Dienste — Kooperation",
"description": "Plattformen muessen mit dem nationalen Koordinator fuer digitale Dienste (DSC) kooperieren, Informationen bereitstellen und Anordnungen fristgerecht umsetzen.",
"applies_when": "organization.operates_platform == true AND organization.eu_member == true",
"applies_when_condition": {
"all_of": [
{"field": "data_protection.operates_platform", "operator": "EQUALS", "value": true},
{"field": "organization.eu_member", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [{"norm": "DSA", "article": "Art. 44", "title": "Koordinatoren fuer digitale Dienste"}],
"sources": [{"type": "article", "ref": "Art. 44 DSA"}],
"category": "Compliance",
"responsible": "Compliance-Beauftragter",
"sanctions": {"max_fine": "6% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Kooperationsprotokolle mit DSC", "Fristenkontrolle fuer Anordnungen"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
},
{
"id": "DSA-OBL-035",
"title": "Aufsichtsgebuehr (VLOP/VLOSE)",
"description": "Sehr grosse Plattformen und Suchmaschinen muessen eine jaehrliche Aufsichtsgebuehr an die Kommission entrichten. Die Hoehe wird auf Basis des Umsatzes berechnet.",
"applies_when": "platform_user_count >= 45000000",
"applies_when_condition": {"field": "data_protection.platform_user_count", "operator": "GREATER_OR_EQUAL", "value": 45000000},
"legal_basis": [{"norm": "DSA", "article": "Art. 47", "title": "Aufsichtsgebuehr"}],
"sources": [{"type": "article", "ref": "Art. 47 DSA"}],
"category": "Compliance",
"responsible": "Finanzabteilung",
"deadline": {"type": "recurring", "interval": "P1Y"},
"sanctions": {"max_fine": "1% des weltweiten Jahresumsatzes", "personal_liability": false},
"evidence": ["Zahlungsnachweis Aufsichtsgebuehr", "Umsatzberechnung"],
"priority": "mittel",
"tom_control_ids": ["TOM.GOV.01"],
"valid_from": "2024-02-17",
"valid_until": null,
"version": "1.0"
}
],
"controls": [
{
"id": "DSA-CTRL-001",
"name": "Notice-and-Action-System",
"description": "Technisches System zur Entgegennahme, Bearbeitung und Dokumentation von Meldungen rechtswidriger Inhalte",
"category": "Technisch",
"what_to_do": "Implementierung eines elektronischen Meldeformulars mit Eingangsbestaetigung, Bearbeitungs-Tracking und Begruendungsgenerierung",
"priority": "kritisch"
},
{
"id": "DSA-CTRL-002",
"name": "Transparenzberichts-Framework",
"description": "Prozess und Tooling fuer die regelmaessige Erstellung und Veroeffentlichung von Transparenzberichten",
"category": "Organisatorisch",
"what_to_do": "Aufbau eines Daten-Pipelines zur automatisierten Erfassung von Moderationsstatistiken, Beschwerden und behoerdlichen Anordnungen",
"priority": "hoch"
},
{
"id": "DSA-CTRL-003",
"name": "Internes Beschwerdemanagement",
"description": "Elektronisches System fuer Nutzerbeschwerden gegen Moderationsentscheidungen mit Human-Review-Garantie",
"category": "Technisch",
"what_to_do": "Bereitstellung eines Beschwerdeformulars mit Eskalationsstufen, SLA-Tracking und Nachweis menschlicher Ueberpruefung",
"priority": "kritisch"
},
{
"id": "DSA-CTRL-004",
"name": "Werbetransparenz-Archiv",
"description": "Oeffentlich zugaengliches Repository aller geschalteten Werbeanzeigen mit Targeting- und Auftraggeberinformationen",
"category": "Technisch",
"what_to_do": "Implementierung eines durchsuchbaren Werbearchivs mit API-Zugang, Aufbewahrungsfrist mindestens 1 Jahr nach letzter Ausspielung",
"priority": "hoch"
},
{
"id": "DSA-CTRL-005",
"name": "Systemische Risikobewertung",
"description": "Jaehrlicher Prozess zur Identifikation und Bewertung systemischer Risiken fuer VLOPs/VLOSEs",
"category": "Governance",
"what_to_do": "Durchfuehrung einer strukturierten Risikobewertung zu illegalen Inhalten, Grundrechtsbeeintraechtigungen, Wahlmanipulation und Auswirkungen auf Minderjaehrige",
"priority": "kritisch"
}
],
"incident_deadlines": [
{
"phase": "Kenntniserlangung rechtswidriger Inhalte",
"deadline": "Unverzueglich (ohne schuldhaftes Zoegern)",
"content": "Entfernung oder Sperrung des Zugangs zu rechtswidrigen Inhalten",
"recipient": "Intern — Content-Moderation-Team",
"legal_basis": [{"norm": "DSA", "article": "Art. 8"}]
},
{
"phase": "Meldung strafbarer Inhalte",
"deadline": "Unverzueglich nach Kenntniserlangung",
"content": "Information der zustaendigen Strafverfolgungsbehoerden bei Verdacht auf Straftaten gegen Leben oder Sicherheit",
"recipient": "Zustaendige Strafverfolgungsbehoerde",
"legal_basis": [{"norm": "DSA", "article": "Art. 18"}]
},
{
"phase": "Reaktion auf behoerdliche Anordnung",
"deadline": "Frist gemaess Anordnung, spaetestens 72 Stunden",
"content": "Umsetzung der angeordneten Massnahme und Bestaetigung an die anordnende Behoerde",
"recipient": "Anordnende Behoerde / DSC",
"legal_basis": [{"norm": "DSA", "article": "Art. 24"}]
},
{
"phase": "Transparenzbericht (Vermittlungsdienste)",
"deadline": "Jaehrlich, spaetestens 2 Monate nach Berichtszeitraum",
"content": "Veroeffentlichung des Transparenzberichts zu Inhaltsmoderation, Anordnungen und Beschwerden",
"recipient": "Oeffentlichkeit / DSC",
"legal_basis": [{"norm": "DSA", "article": "Art. 14"}]
},
{
"phase": "Transparenzbericht (VLOP/VLOSE)",
"deadline": "Halbjaehrlich",
"content": "Erweiterter Transparenzbericht mit automatisierter Moderation, Trusted Flagger und Forschungsdaten",
"recipient": "Oeffentlichkeit / Kommission / DSC",
"legal_basis": [{"norm": "DSA", "article": "Art. 15"}]
}
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,426 @@
{
"regulation": "eu_machinery",
"name": "EU-Maschinenverordnung (EU) 2023/1230",
"description": "Verordnung (EU) 2023/1230 ueber Maschinen und zur Aufhebung der Richtlinie 2006/42/EG — harmonisierte Vorschriften fuer das Inverkehrbringen und die Inbetriebnahme von Maschinen und zugehoerigen Produkten im Binnenmarkt",
"version": "1.0",
"effective_date": "2027-01-20",
"obligations": [
{
"id": "EUMACH-OBL-001",
"title": "Inverkehrbringen von Maschinen",
"description": "Sicherstellung, dass nur konforme Maschinen auf dem Unionsmarkt bereitgestellt werden. Maschinen duerfen nur in Verkehr gebracht werden, wenn sie bei ordnungsgemaesser Installation, Wartung und bestimmungsgemaesser Verwendung die Sicherheits- und Gesundheitsanforderungen erfuellen.",
"applies_when": "manufacturer_or_importer",
"applies_when_condition": {
"all_of": [
{"field": "organization.industry", "operator": "IN", "value": ["manufacturing", "machinery", "industrial_equipment"]}
]
},
"legal_basis": [
{"norm": "EU-Maschinenverordnung", "article": "Art. 4", "title": "Anforderungen an das Inverkehrbringen"}
],
"sources": [
{"type": "article", "ref": "Art. 4 VO (EU) 2023/1230"}
],
"category": "Compliance",
"responsible": "Geschaeftsfuehrung",
"sanctions": {"max_fine": "Marktzuruecknahme, Vertriebsverbot", "personal_liability": true},
"evidence": ["Konformitaetsbewertung", "Technische Dokumentation"],
"priority": "kritisch",
"valid_from": "2027-01-20",
"valid_until": null,
"version": "1.0"
},
{
"id": "EUMACH-OBL-002",
"title": "Inbetriebnahme konformer Maschinen",
"description": "Maschinen duerfen erst in Betrieb genommen werden, wenn die Konformitaet nachgewiesen ist und alle Sicherheitsanforderungen laut Anhang III erfuellt sind. Betreiber muessen vor der Inbetriebnahme die Konformitaetserklaerung und CE-Kennzeichnung pruefen.",
"applies_when": "operator",
"applies_when_condition": {
"all_of": [
{"field": "organization.industry", "operator": "IN", "value": ["manufacturing", "machinery", "industrial_equipment"]}
]
},
"legal_basis": [
{"norm": "EU-Maschinenverordnung", "article": "Art. 5", "title": "Inbetriebnahme"}
],
"sources": [
{"type": "article", "ref": "Art. 5 VO (EU) 2023/1230"}
],
"category": "Compliance",
"responsible": "Betriebsleiter",
"evidence": ["Inbetriebnahmeprotokoll", "CE-Konformitaetserklaerung"],
"priority": "kritisch",
"valid_from": "2027-01-20",
"valid_until": null,
"version": "1.0"
},
{
"id": "EUMACH-OBL-003",
"title": "Freier Warenverkehr sicherstellen",
"description": "Mitgliedstaaten duerfen das Inverkehrbringen konformer Maschinen nicht behindern. Hersteller muessen sicherstellen, dass ihre Produkte die harmonisierten Normen einhalten, um den freien Warenverkehr zu gewaehrleisten.",
"applies_when": "manufacturer_eu_market",
"applies_when_condition": {
"all_of": [
{"field": "organization.industry", "operator": "IN", "value": ["manufacturing", "machinery", "industrial_equipment"]}
]
},
"legal_basis": [
{"norm": "EU-Maschinenverordnung", "article": "Art. 6", "title": "Freier Warenverkehr"}
],
"sources": [
{"type": "article", "ref": "Art. 6 VO (EU) 2023/1230"}
],
"category": "Compliance",
"responsible": "Regulatory-Affairs",
"evidence": ["Nachweis harmonisierter Normen", "EU-Konformitaetserklaerung"],
"priority": "mittel",
"valid_from": "2027-01-20",
"valid_until": null,
"version": "1.0"
},
{
"id": "EUMACH-OBL-004",
"title": "Konformitaetsvermutung durch harmonisierte Normen",
"description": "Anwendung harmonisierter Normen begruendet eine Konformitaetsvermutung. Hersteller sollen relevante EN-Normen anwenden und dokumentieren, welche Normen angewandt wurden und wo Abweichungen bestehen.",
"applies_when": "manufacturer",
"applies_when_condition": {
"all_of": [
{"field": "organization.industry", "operator": "IN", "value": ["manufacturing", "machinery", "industrial_equipment"]}
]
},
"legal_basis": [
{"norm": "EU-Maschinenverordnung", "article": "Art. 7", "title": "Konformitaetsvermutung"}
],
"sources": [
{"type": "article", "ref": "Art. 7 VO (EU) 2023/1230"}
],
"category": "Dokumentation",
"responsible": "Qualitaetsmanagement",
"evidence": ["Normenverzeichnis", "Abweichungsanalyse"],
"priority": "hoch",
"valid_from": "2027-01-20",
"valid_until": null,
"version": "1.0"
},
{
"id": "EUMACH-OBL-005",
"title": "Allgemeine Herstellerpflichten",
"description": "Hersteller muessen sicherstellen, dass Maschinen in Uebereinstimmung mit den grundlegenden Sicherheits- und Gesundheitsanforderungen entworfen und gebaut werden. Erstellung der technischen Dokumentation, Konformitaetsbewertung und CE-Kennzeichnung.",
"applies_when": "manufacturer",
"applies_when_condition": {
"all_of": [
{"field": "organization.industry", "operator": "IN", "value": ["manufacturing", "machinery", "industrial_equipment"]}
]
},
"legal_basis": [
{"norm": "EU-Maschinenverordnung", "article": "Art. 10", "title": "Pflichten der Hersteller"}
],
"sources": [
{"type": "article", "ref": "Art. 10 VO (EU) 2023/1230"}
],
"category": "Governance",
"responsible": "Geschaeftsfuehrung",
"sanctions": {"max_fine": "Marktzuruecknahme, Bussgeld nach nationalem Recht", "personal_liability": true},
"evidence": ["Technische Dokumentation", "Konformitaetsbewertung", "Betriebsanleitung"],
"priority": "kritisch",
"valid_from": "2027-01-20",
"valid_until": null,
"version": "1.0"
},
{
"id": "EUMACH-OBL-006",
"title": "Technische Dokumentation erstellen",
"description": "Erstellung und Pflege der technischen Dokumentation gemaess Anhang IV: Konstruktionsunterlagen, Risikobeurteilung, angewandte Normen, Pruefberichte. Dokumentation muss 10 Jahre nach Inverkehrbringen aufbewahrt werden.",
"applies_when": "manufacturer",
"applies_when_condition": {
"all_of": [
{"field": "organization.industry", "operator": "IN", "value": ["manufacturing", "machinery", "industrial_equipment"]}
]
},
"legal_basis": [
{"norm": "EU-Maschinenverordnung", "article": "Art. 10 Abs. 2", "title": "Technische Dokumentation"},
{"norm": "EU-Maschinenverordnung", "article": "Art. 11", "title": "Verfahren der Konformitaetsbewertung"}
],
"sources": [
{"type": "article", "ref": "Art. 10-11 VO (EU) 2023/1230"}
],
"category": "Dokumentation",
"responsible": "Konstruktionsleiter",
"deadline": {"type": "recurring", "interval": "P1Y", "event": "Jaehrliche Aktualisierung"},
"evidence": ["Technische Dokumentation Anhang IV", "Risikobeurteilung", "Pruefberichte"],
"priority": "kritisch",
"valid_from": "2027-01-20",
"valid_until": null,
"version": "1.0"
},
{
"id": "EUMACH-OBL-007",
"title": "Konformitaetsbewertung durchfuehren",
"description": "Durchfuehrung des geeigneten Konformitaetsbewertungsverfahrens gemaess Art. 12 und Anhang V-IX. Fuer bestimmte Maschinenkategorien (Anhang I) ist die Einschaltung einer notifizierten Stelle erforderlich.",
"applies_when": "manufacturer",
"applies_when_condition": {
"all_of": [
{"field": "organization.industry", "operator": "IN", "value": ["manufacturing", "machinery", "industrial_equipment"]}
]
},
"legal_basis": [
{"norm": "EU-Maschinenverordnung", "article": "Art. 12", "title": "Konformitaetsbewertungsverfahren"}
],
"sources": [
{"type": "article", "ref": "Art. 12 VO (EU) 2023/1230"}
],
"category": "Audit",
"responsible": "Qualitaetsmanagement",
"evidence": ["Konformitaetszertifikat", "Pruefbericht notifizierte Stelle"],
"priority": "kritisch",
"valid_from": "2027-01-20",
"valid_until": null,
"version": "1.0"
},
{
"id": "EUMACH-OBL-008",
"title": "Bevollmaechtigter im EU-Raum",
"description": "Hersteller ausserhalb der EU muessen einen Bevollmaechtigten in der Union benennen. Dieser ist verantwortlich fuer die Bereitstellung der Konformitaetserklaerung und technischen Dokumentation an Marktaufsichtsbehoerden.",
"applies_when": "non_eu_manufacturer",
"applies_when_condition": {
"all_of": [
{"field": "organization.industry", "operator": "IN", "value": ["manufacturing", "machinery", "industrial_equipment"]},
{"field": "organization.hq_outside_eu", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "EU-Maschinenverordnung", "article": "Art. 13", "title": "Bevollmaechtigte"}
],
"sources": [
{"type": "article", "ref": "Art. 13 VO (EU) 2023/1230"}
],
"category": "Governance",
"responsible": "Regulatory-Affairs",
"evidence": ["Bevollmaechtigungsvertrag", "Kontaktdaten Bevollmaechtigter"],
"priority": "hoch",
"valid_from": "2027-01-20",
"valid_until": null,
"version": "1.0"
},
{
"id": "EUMACH-OBL-009",
"title": "Einfuehrerpflichten",
"description": "Einfuehrer muessen vor dem Inverkehrbringen pruefen, dass der Hersteller die Konformitaetsbewertung durchgefuehrt hat, die technische Dokumentation vorliegt und die CE-Kennzeichnung angebracht ist. Name und Anschrift des Einfuehrers muessen auf der Maschine angegeben sein.",
"applies_when": "importer",
"applies_when_condition": {
"all_of": [
{"field": "organization.industry", "operator": "IN", "value": ["manufacturing", "machinery", "import_trade"]}
]
},
"legal_basis": [
{"norm": "EU-Maschinenverordnung", "article": "Art. 14", "title": "Pflichten der Einfuehrer"}
],
"sources": [
{"type": "article", "ref": "Art. 14 VO (EU) 2023/1230"}
],
"category": "Compliance",
"responsible": "Importleiter",
"evidence": ["Einfuehrerpruefprotokoll", "Kopie der Konformitaetserklaerung"],
"priority": "hoch",
"valid_from": "2027-01-20",
"valid_until": null,
"version": "1.0"
},
{
"id": "EUMACH-OBL-010",
"title": "EU-Konformitaetserklaerung ausstellen",
"description": "Ausstellung der EU-Konformitaetserklaerung gemaess Anhang V mit Angaben zu Hersteller, Maschine, angewandten Normen und notifizierter Stelle. Die Erklaerung muss in der Amtssprache des Mitgliedstaats verfuegbar sein.",
"applies_when": "manufacturer",
"applies_when_condition": {
"all_of": [
{"field": "organization.industry", "operator": "IN", "value": ["manufacturing", "machinery", "industrial_equipment"]}
]
},
"legal_basis": [
{"norm": "EU-Maschinenverordnung", "article": "Art. 18", "title": "EU-Konformitaetserklaerung"}
],
"sources": [
{"type": "article", "ref": "Art. 18 VO (EU) 2023/1230"}
],
"category": "Dokumentation",
"responsible": "Qualitaetsmanagement",
"evidence": ["EU-Konformitaetserklaerung", "Uebersetzungen Amtssprachen"],
"priority": "kritisch",
"valid_from": "2027-01-20",
"valid_until": null,
"version": "1.0"
},
{
"id": "EUMACH-OBL-011",
"title": "CE-Kennzeichnung anbringen",
"description": "Anbringung der CE-Kennzeichnung auf der Maschine gemaess Art. 19 — sichtbar, lesbar und dauerhaft. Die CE-Kennzeichnung wird vor dem Inverkehrbringen angebracht und setzt die Konformitaetsbewertung voraus.",
"applies_when": "manufacturer",
"applies_when_condition": {
"all_of": [
{"field": "organization.industry", "operator": "IN", "value": ["manufacturing", "machinery", "industrial_equipment"]}
]
},
"legal_basis": [
{"norm": "EU-Maschinenverordnung", "article": "Art. 19", "title": "CE-Kennzeichnung"}
],
"sources": [
{"type": "article", "ref": "Art. 19 VO (EU) 2023/1230"}
],
"category": "Compliance",
"responsible": "Produktion",
"evidence": ["Foto CE-Kennzeichnung", "Pruefprotokoll Kennzeichnung"],
"priority": "kritisch",
"valid_from": "2027-01-20",
"valid_until": null,
"version": "1.0"
},
{
"id": "EUMACH-OBL-012",
"title": "KI-Systeme in Maschinen — besondere Anforderungen",
"description": "Maschinen mit eingebetteten KI-Systemen muessen zusaetzliche Anforderungen erfuellen: Sicherheitsfunktionen duerfen nicht allein von KI abhaengen, Mensch-Maschine-Interaktion muss transparent sein, KI-bedingte Risiken muessen in der Risikobeurteilung beruecksichtigt werden.",
"applies_when": "ai_machinery",
"applies_when_condition": {
"all_of": [
{"field": "organization.industry", "operator": "IN", "value": ["manufacturing", "machinery", "industrial_equipment"]},
{"field": "ai_usage.uses_ai", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "EU-Maschinenverordnung", "article": "Art. 21", "title": "KI-Systeme in Maschinen"},
{"norm": "AI Act", "article": "Art. 6", "title": "Klassifikation Hochrisiko-KI"}
],
"sources": [
{"type": "article", "ref": "Art. 21 VO (EU) 2023/1230"},
{"type": "eu_guidance", "ref": "Leitlinien KI in Maschinen"}
],
"category": "Technisch",
"responsible": "KI-Verantwortlicher",
"sanctions": {"max_fine": "Marktzuruecknahme, Bussgeld", "personal_liability": true},
"evidence": ["KI-Risikobeurteilung", "Sicherheitskonzept KI-Funktionen", "Human-Oversight-Nachweis"],
"priority": "kritisch",
"valid_from": "2027-01-20",
"valid_until": null,
"version": "1.0"
},
{
"id": "EUMACH-OBL-013",
"title": "Sicherheitsbauteile mit digitaler Funktion",
"description": "Sicherheitsbauteile mit Software oder digitalen Elementen muessen ueber ihren Lebenszyklus aktuell gehalten werden. Sicherheitsupdates sind bereitzustellen und Cybersecurity-Risiken in der Risikobeurteilung zu beruecksichtigen.",
"applies_when": "digital_safety_components",
"applies_when_condition": {
"all_of": [
{"field": "organization.industry", "operator": "IN", "value": ["manufacturing", "machinery", "industrial_equipment"]},
{"field": "ai_usage.uses_ai", "operator": "EQUALS", "value": true}
]
},
"legal_basis": [
{"norm": "EU-Maschinenverordnung", "article": "Art. 22", "title": "Sicherheitsbauteile"}
],
"sources": [
{"type": "article", "ref": "Art. 22 VO (EU) 2023/1230"}
],
"category": "Technisch",
"responsible": "Entwicklungsleiter",
"evidence": ["Sicherheitsbauteil-Register", "Update-Konzept", "Cybersecurity-Risikobeurteilung"],
"priority": "hoch",
"valid_from": "2027-01-20",
"valid_until": null,
"version": "1.0"
},
{
"id": "EUMACH-OBL-014",
"title": "Zusammenarbeit mit Marktueberwachungsbehoerden",
"description": "Wirtschaftsakteure muessen mit Marktueberwachungsbehoerden zusammenarbeiten und auf Verlangen alle erforderlichen Informationen und Unterlagen bereitstellen. Bei Nichtkonformitaet sind unverzueglich Korrekturmassnahmen zu ergreifen.",
"applies_when": "all_economic_operators",
"applies_when_condition": {
"all_of": [
{"field": "organization.industry", "operator": "IN", "value": ["manufacturing", "machinery", "industrial_equipment", "import_trade"]}
]
},
"legal_basis": [
{"norm": "EU-Maschinenverordnung", "article": "Art. 25", "title": "Marktueberwachung"}
],
"sources": [
{"type": "article", "ref": "Art. 25 VO (EU) 2023/1230"}
],
"category": "Organisatorisch",
"responsible": "Regulatory-Affairs",
"evidence": ["Kommunikationsprotokoll Behoerden", "Korrekturmassnahmenplan"],
"priority": "hoch",
"valid_from": "2027-01-20",
"valid_until": null,
"version": "1.0"
},
{
"id": "EUMACH-OBL-015",
"title": "Meldepflicht bei Nichtkonformitaet",
"description": "Hersteller und Einfuehrer muessen die Marktueberwachungsbehoerden unverzueglich informieren, wenn sie Grund zur Annahme haben, dass eine Maschine nicht konform ist oder ein Risiko darstellt. Dokumentation aller Korrekturmassnahmen.",
"applies_when": "manufacturer_or_importer",
"applies_when_condition": {
"all_of": [
{"field": "organization.industry", "operator": "IN", "value": ["manufacturing", "machinery", "industrial_equipment", "import_trade"]}
]
},
"legal_basis": [
{"norm": "EU-Maschinenverordnung", "article": "Art. 25 Abs. 4", "title": "Meldepflicht Nichtkonformitaet"}
],
"sources": [
{"type": "article", "ref": "Art. 25 VO (EU) 2023/1230"}
],
"category": "Meldepflicht",
"responsible": "Geschaeftsfuehrung",
"deadline": {"type": "on_event", "event": "Feststellung der Nichtkonformitaet", "duration": "P0D"},
"sanctions": {"max_fine": "Bussgeld nach nationalem Recht, Marktzuruecknahme", "personal_liability": true},
"evidence": ["Meldung an Behoerde", "Korrekturmassnahmen-Dokumentation"],
"priority": "kritisch",
"valid_from": "2027-01-20",
"valid_until": null,
"version": "1.0"
}
],
"controls": [
{
"id": "EUMACH-CTRL-001",
"name": "Risikobeurteilung Maschinen",
"description": "Systematische Risikobeurteilung aller Maschinen nach EN ISO 12100 mit Dokumentation der Gefahrenanalyse, Risikoeinschaetzung und Risikominderungsmassnahmen.",
"category": "Technisch",
"what_to_do": "EN ISO 12100 Risikobeurteilung fuer jede Maschine durchfuehren, Ergebnisse dokumentieren und Schutzmassnahmen implementieren.",
"iso27001_mapping": [],
"priority": "kritisch"
},
{
"id": "EUMACH-CTRL-002",
"name": "Technische Dokumentation Lifecycle",
"description": "Verwaltung der technischen Dokumentation ueber den gesamten Produktlebenszyklus: Erstellung, Aktualisierung, Archivierung (mind. 10 Jahre), Bereitstellung fuer Behoerden.",
"category": "Dokumentation",
"what_to_do": "Dokumentenmanagementsystem einrichten, Verantwortlichkeiten definieren, Aufbewahrungsfristen ueberwachen.",
"iso27001_mapping": ["A.5.37"],
"priority": "hoch"
},
{
"id": "EUMACH-CTRL-003",
"name": "KI-Sicherheitsvalidierung",
"description": "Spezifische Validierung von KI-Komponenten in Maschinen: Funktionale Sicherheit, Robustheit gegen Stoerungen, Nachvollziehbarkeit von KI-Entscheidungen in sicherheitsrelevanten Funktionen.",
"category": "Technisch",
"what_to_do": "KI-Sicherheitstests definieren und durchfuehren, Human-Oversight fuer sicherheitskritische KI-Funktionen implementieren.",
"iso27001_mapping": ["A.8.25", "A.8.29"],
"priority": "kritisch"
}
],
"incident_deadlines": [
{
"phase": "Sofortmeldung",
"deadline": "Unverzueglich nach Kenntnis",
"content": "Meldung an zustaendige Marktueberwachungsbehoerde bei Kenntnis eines schwerwiegenden Unfalls oder einer Nichtkonformitaet",
"recipient": "Marktueberwachungsbehoerde",
"legal_basis": [{"norm": "EU-Maschinenverordnung", "article": "Art. 25"}]
},
{
"phase": "Korrekturmassnahmen",
"deadline": "Ohne ungebuerliche Verzoegerung",
"content": "Ergreifen aller erforderlichen Korrekturmassnahmen zur Herstellung der Konformitaet oder Ruecknahme/Rueckruf",
"recipient": "Marktueberwachungsbehoerde + betroffene Wirtschaftsakteure",
"legal_basis": [{"norm": "EU-Maschinenverordnung", "article": "Art. 25"}]
}
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,459 @@
{
"regulation": "ttdsg",
"regulation_full_name": "Telekommunikation-Telemedien-Datenschutz-Gesetz (TTDSG)",
"version": "1.0",
"obligations": [
{
"id": "TTDSG-OBL-001",
"title": "Wahrung des Fernmeldegeheimnisses",
"description": "Der Inhalt der Telekommunikation und ihre naeheren Umstaende unterliegen dem Fernmeldegeheimnis. Diensteanbieter sind zur Wahrung verpflichtet.",
"applies_when": "organization provides telecommunication services",
"applies_when_condition": { "all_of": [{ "field": "organization.provides_telecom_services", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 3", "title": "Vertraulichkeit der Kommunikation" }],
"sources": [{ "type": "national_law", "ref": "§ 3 TTDSG" }],
"category": "Governance",
"responsible": "Geschaeftsfuehrung",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "300.000 EUR", "criminal_liability": true },
"evidence": [{ "name": "Fernmeldegeheimnis-Richtlinie", "required": true }],
"priority": "kritisch",
"tom_control_ids": ["TOM.CRY.01", "TOM.AC.01"],
"breakpilot_feature": null,
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-002",
"title": "Technische Schutzmassnahmen Fernmeldegeheimnis",
"description": "Diensteanbieter muessen technische Vorkehrungen zum Schutz des Fernmeldegeheimnisses treffen, insbesondere gegen unbefugtes Abhoeren und Mitlesen.",
"applies_when": "organization provides telecommunication services",
"applies_when_condition": { "all_of": [{ "field": "organization.provides_telecom_services", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 4", "title": "Durchsetzung des Fernmeldegeheimnisses" }],
"sources": [{ "type": "national_law", "ref": "§ 4 TTDSG" }],
"category": "Technisch",
"responsible": "IT-Sicherheitsbeauftragter",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "300.000 EUR" },
"evidence": [{ "name": "Verschluesselungskonzept TK", "required": true }, "Penetrationstest-Bericht"],
"priority": "kritisch",
"tom_control_ids": ["TOM.CRY.01", "TOM.NET.01"],
"breakpilot_feature": "/sdk/tom",
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-003",
"title": "Bestandsdatenauskunft TK-Dienste",
"description": "Bestandsdaten der Teilnehmer duerfen nur erhoben und verwendet werden, soweit dies zur Begruendung, Ausgestaltung oder Aenderung eines Vertragsverhaeltnisses erforderlich ist.",
"applies_when": "organization provides telecommunication services with subscriber data",
"applies_when_condition": { "all_of": [{ "field": "organization.provides_telecom_services", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 7", "title": "Bestandsdaten TK-Anbieter" }],
"sources": [{ "type": "national_law", "ref": "§ 7 TTDSG" }],
"category": "Governance",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "300.000 EUR" },
"evidence": [{ "name": "Bestandsdaten-Verarbeitungskonzept", "required": true }],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01", "TOM.AC.01"],
"breakpilot_feature": null,
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-004",
"title": "Bestandsdatenauskunft an Behoerden",
"description": "Die Erteilung von Auskuenften ueber Bestandsdaten an Sicherheitsbehoerden ist nur unter den Voraussetzungen des § 8 TTDSG zulaessig.",
"applies_when": "organization provides telecom and receives authority requests",
"applies_when_condition": { "all_of": [{ "field": "organization.provides_telecom_services", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 8", "title": "Bestandsdatenauskunft Behoerden" }],
"sources": [{ "type": "national_law", "ref": "§ 8 TTDSG" }],
"category": "Organisatorisch",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "on_event", "event": "Bei Behoerdenanfrage" },
"sanctions": { "max_fine": "300.000 EUR", "personal_liability": true },
"evidence": [{ "name": "Auskunftserteilungs-Protokoll", "required": true }],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.02", "TOM.LOG.01"],
"breakpilot_feature": null,
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-005",
"title": "Verkehrsdaten — Zweckbindung und Loeschung",
"description": "Verkehrsdaten duerfen nur fuer Abrechnungszwecke, Stoerungsbeseitigung und Missbrauchsbekaempfung gespeichert werden und sind nach Zweckerfuellung unverzueglich zu loeschen.",
"applies_when": "organization collects traffic data from telecom services",
"applies_when_condition": { "all_of": [{ "field": "organization.provides_telecom_services", "operator": "EQUALS", "value": true }, { "field": "data_protection.collects_traffic_data", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 9", "title": "Verkehrsdaten" }],
"sources": [{ "type": "national_law", "ref": "§ 9 TTDSG" }],
"category": "Technisch",
"responsible": "IT-Leitung",
"deadline": { "type": "on_event", "event": "Nach Rechnungsstellung/Zweckerfuellung" },
"sanctions": { "max_fine": "300.000 EUR" },
"evidence": [{ "name": "Loeschkonzept Verkehrsdaten", "required": true }],
"priority": "hoch",
"tom_control_ids": ["TOM.DEL.01", "TOM.GOV.01"],
"breakpilot_feature": "/sdk/loeschfristen",
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-006",
"title": "Standortdaten — Einwilligung erforderlich",
"description": "Standortdaten duerfen nur mit ausdruecklicher Einwilligung des Nutzers verarbeitet werden. Die Einwilligung muss jederzeit widerrufbar sein.",
"applies_when": "organization processes location data",
"applies_when_condition": { "all_of": [{ "field": "data_protection.processes_location_data", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 10", "title": "Standortdaten" }],
"sources": [{ "type": "national_law", "ref": "§ 10 TTDSG" }],
"category": "Organisatorisch",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "on_event", "event": "Vor Verarbeitung von Standortdaten" },
"sanctions": { "max_fine": "300.000 EUR" },
"evidence": [{ "name": "Einwilligungsnachweis Standortdaten", "required": true }, "Widerrufsmechanismus"],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.02"],
"breakpilot_feature": "/sdk/consent",
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-007",
"title": "Anonymisierung von Standortdaten",
"description": "Wenn Standortdaten fuer Mehrwertdienste verwendet werden, muessen sie anonymisiert oder pseudonymisiert werden, sofern der Zweck dies erlaubt.",
"applies_when": "organization uses location data for value-added services",
"applies_when_condition": { "all_of": [{ "field": "data_protection.processes_location_data", "operator": "EQUALS", "value": true }, { "field": "organization.offers_value_added_services", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 10 Abs. 2", "title": "Standortdaten Mehrwertdienste" }],
"sources": [{ "type": "national_law", "ref": "§ 10 TTDSG" }],
"category": "Technisch",
"responsible": "IT-Sicherheitsbeauftragter",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "300.000 EUR" },
"evidence": [{ "name": "Anonymisierungskonzept Standortdaten", "required": true }],
"priority": "mittel",
"tom_control_ids": ["TOM.CRY.02"],
"breakpilot_feature": null,
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-008",
"title": "Bestandsdaten Telemedien — Erhebung und Verwendung",
"description": "Anbieter von Telemedien duerfen Bestandsdaten nur erheben und verwenden, soweit sie fuer die Begruendung, Ausgestaltung oder Aenderung eines Vertragsverhaeltnisses erforderlich sind.",
"applies_when": "organization provides telemedia services",
"applies_when_condition": { "all_of": [{ "field": "organization.provides_telemedia_services", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 13", "title": "Bestandsdaten Telemedien" }],
"sources": [{ "type": "national_law", "ref": "§ 13 TTDSG" }],
"category": "Governance",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "300.000 EUR" },
"evidence": [{ "name": "Datenschutzerklaerung Telemedien", "required": true }],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01"],
"breakpilot_feature": null,
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-009",
"title": "Nutzungsdaten Telemedien — Zweckbindung",
"description": "Nutzungsdaten duerfen nur erhoben werden, soweit dies zur Ermogeglichung der Inanspruchnahme von Telemedien erforderlich ist. Profilerstellung bedarf der Einwilligung.",
"applies_when": "organization collects telemedia usage data",
"applies_when_condition": { "all_of": [{ "field": "organization.provides_telemedia_services", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 15", "title": "Nutzungsdaten Telemedien" }],
"sources": [{ "type": "national_law", "ref": "§ 15 TTDSG" }],
"category": "Governance",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "300.000 EUR" },
"evidence": [{ "name": "Nutzungsdaten-Konzept", "required": true }],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01", "TOM.DEL.01"],
"breakpilot_feature": null,
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-010",
"title": "Vertraulichkeit Nachrichteninhalte",
"description": "Anbieter von interpersonellen TK-Diensten muessen die Vertraulichkeit der uebermittelten Nachrichteninhalte gewaehrleisten (§ 19 TTDSG).",
"applies_when": "organization provides messaging or communication services",
"applies_when_condition": { "all_of": [{ "field": "organization.provides_messaging_services", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 19", "title": "Nachrichteninhalte" }],
"sources": [{ "type": "national_law", "ref": "§ 19 TTDSG" }],
"category": "Technisch",
"responsible": "IT-Sicherheitsbeauftragter",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "300.000 EUR", "criminal_liability": true },
"evidence": [{ "name": "Ende-zu-Ende-Verschluesselungsnachweis", "required": true }],
"priority": "kritisch",
"tom_control_ids": ["TOM.CRY.01", "TOM.NET.01"],
"breakpilot_feature": "/sdk/tom",
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-011",
"title": "Schutz vor Spam und unerwuenschten Nachrichten",
"description": "Anbieter nummernunabhaengiger interpersoneller TK-Dienste muessen Massnahmen gegen unerwuenschte Nachrichten (Spam) ergreifen.",
"applies_when": "organization provides interpersonal communication services",
"applies_when_condition": { "all_of": [{ "field": "organization.provides_messaging_services", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 19 Abs. 2", "title": "Spam-Schutz" }],
"sources": [{ "type": "national_law", "ref": "§ 19 TTDSG" }],
"category": "Technisch",
"responsible": "IT-Leitung",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "300.000 EUR" },
"evidence": [{ "name": "Anti-Spam-Massnahmen Dokumentation", "required": true }],
"priority": "mittel",
"tom_control_ids": ["TOM.NET.01"],
"breakpilot_feature": null,
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-012",
"title": "Einwilligung fuer Cookies und Tracking",
"description": "Die Speicherung von Informationen in der Endeinrichtung des Nutzers oder der Zugriff auf dort gespeicherte Informationen ist nur mit Einwilligung des Nutzers zulaessig (§ 25 Abs. 1 TTDSG).",
"applies_when": "organization uses cookies or similar tracking technologies",
"applies_when_condition": { "any_of": [{ "field": "data_protection.uses_cookies", "operator": "EQUALS", "value": true }, { "field": "data_protection.uses_tracking", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 25 Abs. 1", "title": "Schutz der Privatsphaere bei Endeinrichtungen" }],
"sources": [{ "type": "national_law", "ref": "§ 25 TTDSG" }, { "type": "eu_guidance", "ref": "ePrivacy-Richtlinie Art. 5 Abs. 3" }],
"category": "Organisatorisch",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "on_event", "event": "Vor Setzen von Cookies/Trackern" },
"sanctions": { "max_fine": "300.000 EUR" },
"evidence": [{ "name": "Cookie-Consent-Banner", "required": true }, { "name": "Consent-Management-Platform Nachweis", "required": true }],
"priority": "kritisch",
"tom_control_ids": ["TOM.GOV.02", "TOM.WEB.01"],
"breakpilot_feature": "/sdk/cookie-banner",
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-013",
"title": "Ausnahmen von der Cookie-Einwilligung",
"description": "Keine Einwilligung ist erforderlich, wenn die Speicherung/der Zugriff technisch erforderlich ist, um den vom Nutzer ausdruecklich gewuenschten Dienst bereitzustellen (§ 25 Abs. 2 TTDSG).",
"applies_when": "organization uses technically necessary cookies",
"applies_when_condition": { "all_of": [{ "field": "data_protection.uses_cookies", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 25 Abs. 2", "title": "Ausnahme technisch notwendige Cookies" }],
"sources": [{ "type": "national_law", "ref": "§ 25 Abs. 2 TTDSG" }, { "type": "dsk_kurzpapier", "ref": "DSK Orientierungshilfe Telemedien 2021" }],
"category": "Dokumentation",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "recurring", "interval": "jaehrlich" },
"sanctions": { "max_fine": "300.000 EUR" },
"evidence": [{ "name": "Cookie-Klassifizierung (notwendig vs. optional)", "required": true }],
"priority": "hoch",
"tom_control_ids": ["TOM.WEB.01"],
"breakpilot_feature": "/sdk/cookie-banner",
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-014",
"title": "Cookie-Consent Anforderungen — Informiertheit",
"description": "Die Einwilligung nach § 25 Abs. 1 TTDSG muss informiert erfolgen. Der Nutzer muss klar und umfassend ueber Zweck, Dauer und Empfaenger informiert werden.",
"applies_when": "organization collects cookie consent",
"applies_when_condition": { "all_of": [{ "field": "data_protection.uses_cookies", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 25 Abs. 1", "title": "Informierte Einwilligung" }, { "norm": "DSGVO", "article": "Art. 7", "title": "Bedingungen fuer die Einwilligung" }],
"sources": [{ "type": "national_law", "ref": "§ 25 TTDSG" }, { "type": "case_law", "ref": "BGH I ZR 7/16 — Planet49" }],
"category": "Organisatorisch",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "300.000 EUR" },
"evidence": [{ "name": "Cookie-Banner mit vollstaendiger Information", "required": true }, "Dokumentation Consent-Flow"],
"priority": "kritisch",
"tom_control_ids": ["TOM.WEB.01", "TOM.GOV.02"],
"breakpilot_feature": "/sdk/cookie-banner",
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-015",
"title": "Anerkannte Dienste zur Einwilligungsverwaltung",
"description": "Die Bundesregierung kann durch Rechtsverordnung Anforderungen an anerkannte Dienste zur Einwilligungsverwaltung (PIMS) festlegen (§ 26 TTDSG).",
"applies_when": "organization provides or uses a Personal Information Management Service",
"applies_when_condition": { "all_of": [{ "field": "organization.uses_pims", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 26", "title": "Anerkannte Dienste zur Einwilligungsverwaltung" }],
"sources": [{ "type": "national_law", "ref": "§ 26 TTDSG" }],
"category": "Compliance",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "recurring", "interval": "jaehrlich" },
"sanctions": { "max_fine": "300.000 EUR" },
"evidence": [{ "name": "PIMS-Zertifizierung/Anerkennung", "required": false }],
"priority": "niedrig",
"tom_control_ids": ["TOM.GOV.02"],
"breakpilot_feature": "/sdk/consent",
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-016",
"title": "Endnutzerinformation bei Rufnummernanzeige",
"description": "Bei der Anzeige von Rufnummern muessen Diensteanbieter den Endnutzer ueber die Moeglichkeit der Unterdrueckung informieren (§ 11 TTDSG).",
"applies_when": "organization provides telephony services with caller ID",
"applies_when_condition": { "all_of": [{ "field": "organization.provides_telecom_services", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 11", "title": "Rufnummernanzeige" }],
"sources": [{ "type": "national_law", "ref": "§ 11 TTDSG" }],
"category": "Organisatorisch",
"responsible": "Produktmanagement",
"deadline": { "type": "on_event", "event": "Bei Vertragsschluss" },
"sanctions": { "max_fine": "300.000 EUR" },
"evidence": [{ "name": "Kundeninformation Rufnummernanzeige", "required": true }],
"priority": "mittel",
"tom_control_ids": ["TOM.GOV.02"],
"breakpilot_feature": null,
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-017",
"title": "Automatische Anrufweiterleitung — Einwilligung",
"description": "Automatische Anrufweiterleitungen duerfen nur mit Einwilligung des Anschlussinhabers eingerichtet werden (§ 12 TTDSG).",
"applies_when": "organization provides call forwarding services",
"applies_when_condition": { "all_of": [{ "field": "organization.provides_telecom_services", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 12", "title": "Anrufweiterschaltung" }],
"sources": [{ "type": "national_law", "ref": "§ 12 TTDSG" }],
"category": "Organisatorisch",
"responsible": "Produktmanagement",
"deadline": { "type": "on_event", "event": "Vor Einrichtung der Weiterleitung" },
"sanctions": { "max_fine": "300.000 EUR" },
"evidence": [{ "name": "Einwilligungsnachweis Anrufweiterleitung", "required": true }],
"priority": "niedrig",
"tom_control_ids": ["TOM.GOV.02"],
"breakpilot_feature": null,
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-018",
"title": "Bussgeldvorschriften TTDSG",
"description": "Verstoesse gegen die Vorschriften des TTDSG koennen als Ordnungswidrigkeiten mit Bussgeldern bis zu 300.000 EUR geahndet werden (§ 28 TTDSG).",
"applies_when": "always for organizations under TTDSG scope",
"applies_when_condition": { "any_of": [{ "field": "organization.provides_telecom_services", "operator": "EQUALS", "value": true }, { "field": "organization.provides_telemedia_services", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 28", "title": "Bussgeldvorschriften" }],
"sources": [{ "type": "national_law", "ref": "§ 28 TTDSG" }],
"category": "Compliance",
"responsible": "Geschaeftsfuehrung",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "300.000 EUR", "personal_liability": true },
"evidence": [{ "name": "TTDSG-Compliance-Pruefbericht", "required": true }],
"priority": "hoch",
"tom_control_ids": ["TOM.GOV.01"],
"breakpilot_feature": "/sdk/risk-assessment",
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-019",
"title": "Strafvorschriften — Verstoesse Fernmeldegeheimnis",
"description": "Wer unbefugt einer anderen Person Kenntnis vom Inhalt oder den naeheren Umstaenden der Telekommunikation verschafft, wird strafrechtlich verfolgt (§ 27 TTDSG).",
"applies_when": "organization handles telecommunication data",
"applies_when_condition": { "all_of": [{ "field": "organization.provides_telecom_services", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 27", "title": "Strafvorschriften" }],
"sources": [{ "type": "national_law", "ref": "§ 27 TTDSG" }],
"category": "Compliance",
"responsible": "Geschaeftsfuehrung",
"deadline": { "type": "recurring", "interval": "laufend" },
"sanctions": { "max_fine": "Freiheitsstrafe bis 2 Jahre oder Geldstrafe", "personal_liability": true, "criminal_liability": true },
"evidence": [{ "name": "Schulungsnachweis Fernmeldegeheimnis", "required": true }],
"priority": "kritisch",
"tom_control_ids": ["TOM.HR.02", "TOM.AC.01"],
"breakpilot_feature": "/sdk/training",
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
},
{
"id": "TTDSG-OBL-020",
"title": "Teilnehmerverzeichnisse — Einwilligung",
"description": "Die Aufnahme in oeffentliche Teilnehmerverzeichnisse und die Bereitstellung von Auskunftsdiensten bedarf der vorherigen Einwilligung des Teilnehmers (§ 17 TTDSG).",
"applies_when": "organization maintains subscriber directories",
"applies_when_condition": { "all_of": [{ "field": "organization.provides_telecom_services", "operator": "EQUALS", "value": true }, { "field": "organization.maintains_directories", "operator": "EQUALS", "value": true }] },
"legal_basis": [{ "norm": "TTDSG", "article": "§ 17", "title": "Teilnehmerverzeichnisse" }],
"sources": [{ "type": "national_law", "ref": "§ 17 TTDSG" }],
"category": "Organisatorisch",
"responsible": "Datenschutzbeauftragter",
"deadline": { "type": "on_event", "event": "Vor Aufnahme in Verzeichnis" },
"sanctions": { "max_fine": "300.000 EUR" },
"evidence": [{ "name": "Einwilligungsnachweis Verzeichniseintrag", "required": true }],
"priority": "mittel",
"tom_control_ids": ["TOM.GOV.02"],
"breakpilot_feature": "/sdk/consent",
"valid_from": "2021-12-01",
"valid_until": null,
"version": "1.0"
}
],
"controls": [
{
"id": "TTDSG-CTRL-001",
"name": "Cookie-Consent-Management",
"description": "Kontrolle zur Sicherstellung der gesetzeskonformen Einholung und Verwaltung von Cookie-Einwilligungen nach § 25 TTDSG.",
"category": "Organisatorisch",
"what_to_do": "Cookie-Banner implementieren, Cookie-Klassifizierung durchfuehren, Consent-Log fuehren, regelmaessige Audits der Cookie-Nutzung.",
"iso27001_mapping": ["A.5.34"],
"priority": "kritisch"
},
{
"id": "TTDSG-CTRL-002",
"name": "Fernmeldegeheimnis-Schutz",
"description": "Kontrolle zur Gewaehrleistung des Fernmeldegeheimnisses durch technische und organisatorische Massnahmen.",
"category": "Technisch",
"what_to_do": "Verschluesselung implementieren, Zugriffskontrolle auf TK-Daten, Mitarbeiterschulung zum Fernmeldegeheimnis, Protokollierung.",
"iso27001_mapping": ["A.8.24", "A.5.14"],
"priority": "kritisch"
},
{
"id": "TTDSG-CTRL-003",
"name": "Verkehrs- und Standortdaten-Governance",
"description": "Kontrolle zur Einhaltung der Zweckbindung und Loeschpflichten fuer Verkehrs- und Standortdaten.",
"category": "Governance",
"what_to_do": "Datenklassifizierung erstellen, automatische Loeschmechanismen implementieren, Einwilligungsprozesse fuer Standortdaten pruefen.",
"iso27001_mapping": ["A.5.33", "A.8.10"],
"priority": "hoch"
}
],
"incident_deadlines": [
{
"phase": "Meldung TK-Sicherheitsvorfall an BNetzA",
"deadline": "Unverzueglich (i.d.R. 24 Stunden)",
"content": "Art und Umfang des Vorfalls, betroffene Dienste, ergriffene Massnahmen",
"recipient": "Bundesnetzagentur (BNetzA)",
"legal_basis": [{ "norm": "TKG", "article": "§ 168" }]
},
{
"phase": "Benachrichtigung betroffener Teilnehmer",
"deadline": "Unverzueglich bei Risiko fuer persoenliche Daten",
"content": "Art des Vorfalls, Kontaktdaten, empfohlene Schutzmassnahmen",
"recipient": "Betroffene Teilnehmer",
"legal_basis": [{ "norm": "DSGVO", "article": "Art. 34" }]
},
{
"phase": "Meldung an BSI bei erheblichen Stoerungen",
"deadline": "Unverzueglich",
"content": "Technische Rahmenbedingungen, vermutete Ursache, Auswirkungen",
"recipient": "Bundesamt fuer Sicherheit in der Informationstechnik (BSI)",
"legal_basis": [{ "norm": "TKG", "article": "§ 169" }]
}
]
}

File diff suppressed because it is too large Load Diff