feat: Vorbereitung-Module auf 100% — Persistenz, Backend-Services, UCCA Frontend
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 37s
CI / test-python-backend-compliance (push) Successful in 32s
CI / test-python-document-crawler (push) Successful in 22s
CI / test-python-dsms-gateway (push) Successful in 18s

Phase A: PostgreSQL State Store (sdk_states Tabelle, InMemory-Fallback)
Phase B: Modules dynamisch vom Backend, Scope DB-Persistenz, Source Policy State
Phase C: UCCA Frontend (3 Seiten, Wizard, RiskScoreGauge), Obligations Live-Daten
Phase D: Document Import (PDF/LLM/Gap-Analyse), System Screening (SBOM/OSV.dev)
Phase E: Company Profile CRUD mit Audit-Logging
Phase F: Tests (Python + TypeScript), flow-data.ts DB-Tabellen aktualisiert

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-02 11:04:31 +01:00
parent cd15ab0932
commit e6d666b89b
38 changed files with 4195 additions and 420 deletions

View File

@@ -1,6 +1,6 @@
'use client'
import React, { useState } from 'react'
import React, { useState, useEffect } from 'react'
import { useSDK } from '@/lib/sdk'
import { StepHeader, STEP_EXPLANATIONS } from '@/components/sdk/StepHeader'
@@ -21,73 +21,6 @@ interface Obligation {
linkedSystems: string[]
}
// =============================================================================
// MOCK DATA
// =============================================================================
const mockObligations: Obligation[] = [
{
id: 'obl-1',
title: 'Risikomanagementsystem implementieren',
description: 'Ein Risikomanagementsystem fuer das Hochrisiko-KI-System muss implementiert werden.',
source: 'AI Act',
sourceArticle: 'Art. 9',
deadline: new Date('2024-06-01'),
status: 'in-progress',
priority: 'critical',
responsible: 'IT Security',
linkedSystems: ['Bewerber-Screening'],
},
{
id: 'obl-2',
title: 'Technische Dokumentation erstellen',
description: 'Umfassende technische Dokumentation fuer alle Hochrisiko-KI-Systeme.',
source: 'AI Act',
sourceArticle: 'Art. 11',
deadline: new Date('2024-05-15'),
status: 'pending',
priority: 'high',
responsible: 'Entwicklung',
linkedSystems: ['Bewerber-Screening'],
},
{
id: 'obl-3',
title: 'Datenschutzerklaerung aktualisieren',
description: 'Die Datenschutzerklaerung muss an die neuen KI-Verarbeitungen angepasst werden.',
source: 'DSGVO',
sourceArticle: 'Art. 13/14',
deadline: new Date('2024-02-01'),
status: 'overdue',
priority: 'high',
responsible: 'Datenschutz',
linkedSystems: ['Kundenservice Chatbot', 'Empfehlungsalgorithmus'],
},
{
id: 'obl-4',
title: 'KI-Kennzeichnung implementieren',
description: 'Nutzer muessen informiert werden, dass sie mit einem KI-System interagieren.',
source: 'AI Act',
sourceArticle: 'Art. 52',
deadline: new Date('2024-03-01'),
status: 'completed',
priority: 'medium',
responsible: 'UX Team',
linkedSystems: ['Kundenservice Chatbot'],
},
{
id: 'obl-5',
title: 'Menschliche Aufsicht sicherstellen',
description: 'Prozesse fuer menschliche Aufsicht bei automatisierten Entscheidungen.',
source: 'AI Act',
sourceArticle: 'Art. 14',
deadline: new Date('2024-04-01'),
status: 'pending',
priority: 'critical',
responsible: 'Operations',
linkedSystems: ['Bewerber-Screening'],
},
]
// =============================================================================
// COMPONENTS
// =============================================================================
@@ -188,14 +121,124 @@ function ObligationCard({ obligation }: { obligation: Obligation }) {
)
}
// =============================================================================
// HELPERS
// =============================================================================
function mapControlsToObligations(assessments: Array<{
id: string
title?: string
domain?: string
result?: {
required_controls?: Array<{
id: string
title: string
description: string
gdpr_ref?: string
effort?: string
}>
triggered_rules?: Array<{
rule_code: string
title: string
severity: string
gdpr_ref: string
}>
risk_level?: string
}
}>): Obligation[] {
const obligations: Obligation[] = []
for (const assessment of assessments) {
// Map triggered rules to obligations
const rules = assessment.result?.triggered_rules || []
for (const rule of rules) {
const severity = rule.severity
obligations.push({
id: `${assessment.id}-${rule.rule_code}`,
title: rule.title,
description: `Aus Assessment: ${assessment.title || assessment.id.slice(0, 8)}`,
source: rule.gdpr_ref?.includes('AI Act') ? 'AI Act' : 'DSGVO',
sourceArticle: rule.gdpr_ref || '',
deadline: null,
status: 'pending',
priority: severity === 'BLOCK' ? 'critical' : severity === 'WARN' ? 'high' : 'medium',
responsible: 'Compliance Team',
linkedSystems: assessment.title ? [assessment.title] : [],
})
}
// Map required controls to obligations
const controls = assessment.result?.required_controls || []
for (const control of controls) {
obligations.push({
id: `${assessment.id}-ctrl-${control.id}`,
title: control.title,
description: control.description,
source: control.gdpr_ref?.includes('AI Act') ? 'AI Act' : 'DSGVO',
sourceArticle: control.gdpr_ref || '',
deadline: null,
status: 'pending',
priority: assessment.result?.risk_level === 'HIGH' || assessment.result?.risk_level === 'UNACCEPTABLE' ? 'high' : 'medium',
responsible: 'IT / Compliance',
linkedSystems: assessment.title ? [assessment.title] : [],
})
}
}
return obligations
}
// =============================================================================
// MAIN PAGE
// =============================================================================
export default function ObligationsPage() {
const { state } = useSDK()
const [obligations] = useState<Obligation[]>(mockObligations)
const [obligations, setObligations] = useState<Obligation[]>([])
const [filter, setFilter] = useState<string>('all')
const [loading, setLoading] = useState(true)
const [backendAvailable, setBackendAvailable] = useState(false)
useEffect(() => {
async function loadObligations() {
try {
const response = await fetch('/api/sdk/v1/ucca/assessments')
if (response.ok) {
const data = await response.json()
const assessments = data.assessments || []
if (assessments.length > 0) {
const mapped = mapControlsToObligations(assessments)
setObligations(mapped)
setBackendAvailable(true)
setLoading(false)
return
}
}
} catch {
// Backend unavailable, use SDK state obligations
}
// Fallback: use obligations from SDK state
if (state.obligations && state.obligations.length > 0) {
setObligations(state.obligations.map(o => ({
id: o.id,
title: o.title,
description: o.description || '',
source: o.source || 'DSGVO',
sourceArticle: o.sourceArticle || '',
deadline: o.deadline ? new Date(o.deadline) : null,
status: (o.status as Obligation['status']) || 'pending',
priority: (o.priority as Obligation['priority']) || 'medium',
responsible: o.responsible || 'Compliance Team',
linkedSystems: o.linkedSystems || [],
})))
}
setLoading(false)
}
loadObligations()
}, [state.obligations])
const filteredObligations = filter === 'all'
? obligations
@@ -226,6 +269,18 @@ export default function ObligationsPage() {
</button>
</StepHeader>
{/* Backend Status */}
{backendAvailable && (
<div className="bg-green-50 border border-green-200 rounded-lg p-3 text-sm text-green-700">
Pflichten aus UCCA-Assessments geladen (Live-Daten)
</div>
)}
{/* Loading */}
{loading && (
<div className="text-center py-8 text-gray-500">Lade Pflichten...</div>
)}
{/* Stats */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
<div className="bg-white rounded-xl border border-gray-200 p-6">
@@ -288,7 +343,6 @@ export default function ObligationsPage() {
<div className="space-y-4">
{filteredObligations
.sort((a, b) => {
// Sort by status priority: overdue > in-progress > pending > completed
const statusOrder = { overdue: 0, 'in-progress': 1, pending: 2, completed: 3 }
return statusOrder[a.status] - statusOrder[b.status]
})
@@ -297,7 +351,7 @@ export default function ObligationsPage() {
))}
</div>
{filteredObligations.length === 0 && (
{filteredObligations.length === 0 && !loading && (
<div className="bg-white rounded-xl border border-gray-200 p-12 text-center">
<div className="w-16 h-16 mx-auto bg-gray-100 rounded-full flex items-center justify-center mb-4">
<svg className="w-8 h-8 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -305,7 +359,9 @@ export default function ObligationsPage() {
</svg>
</div>
<h3 className="text-lg font-semibold text-gray-900">Keine Pflichten gefunden</h3>
<p className="mt-2 text-gray-500">Passen Sie den Filter an oder fuegen Sie neue Pflichten hinzu.</p>
<p className="mt-2 text-gray-500">
Erstellen Sie zuerst ein Use Case Assessment, um automatisch Pflichten abzuleiten.
</p>
</div>
)}
</div>