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
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:
@@ -358,108 +358,105 @@ export default function ImportPage() {
|
||||
if (files.length === 0) return
|
||||
|
||||
setIsAnalyzing(true)
|
||||
const allGaps: GapItem[] = []
|
||||
|
||||
// Simulate upload and analysis
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = files[i]
|
||||
|
||||
// Update to uploading
|
||||
setFiles(prev => prev.map(f => (f.id === file.id ? { ...f, status: 'uploading' as const } : f)))
|
||||
|
||||
// Simulate upload progress
|
||||
for (let p = 0; p <= 100; p += 20) {
|
||||
await new Promise(resolve => setTimeout(resolve, 100))
|
||||
setFiles(prev => prev.map(f => (f.id === file.id ? { ...f, progress: p } : f)))
|
||||
// Upload progress
|
||||
setFiles(prev => prev.map(f => (f.id === file.id ? { ...f, progress: 30 } : f)))
|
||||
|
||||
// Prepare form data for backend
|
||||
const formData = new FormData()
|
||||
formData.append('file', file.file)
|
||||
formData.append('document_type', file.type)
|
||||
formData.append('tenant_id', 'default')
|
||||
|
||||
setFiles(prev => prev.map(f => (f.id === file.id ? { ...f, progress: 60, status: 'analyzing' as const } : f)))
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/sdk/v1/import/analyze', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
})
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json()
|
||||
|
||||
// Create imported document from backend response
|
||||
const doc: ImportedDocument = {
|
||||
id: result.document_id || file.id,
|
||||
name: file.file.name,
|
||||
type: result.detected_type || file.type,
|
||||
fileUrl: URL.createObjectURL(file.file),
|
||||
uploadedAt: new Date(),
|
||||
analyzedAt: new Date(),
|
||||
analysisResult: {
|
||||
detectedType: result.detected_type || file.type,
|
||||
confidence: result.confidence || 0.85,
|
||||
extractedEntities: result.extracted_entities || [],
|
||||
gaps: result.gap_analysis?.gaps || [],
|
||||
recommendations: result.recommendations || [],
|
||||
},
|
||||
}
|
||||
|
||||
addImportedDocument(doc)
|
||||
|
||||
// Collect gaps
|
||||
if (result.gap_analysis?.gaps) {
|
||||
for (const gap of result.gap_analysis.gaps) {
|
||||
allGaps.push({
|
||||
id: gap.id,
|
||||
category: gap.category,
|
||||
description: gap.description,
|
||||
severity: gap.severity,
|
||||
regulation: gap.regulation,
|
||||
requiredAction: gap.required_action,
|
||||
relatedStepId: gap.related_step_id || '',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
setFiles(prev => prev.map(f => (f.id === file.id ? { ...f, progress: 100, status: 'complete' as const } : f)))
|
||||
} else {
|
||||
setFiles(prev => prev.map(f => (f.id === file.id ? { ...f, status: 'error' as const, error: 'Analyse fehlgeschlagen' } : f)))
|
||||
}
|
||||
} catch {
|
||||
// Fallback: create basic document without backend analysis
|
||||
const doc: ImportedDocument = {
|
||||
id: file.id,
|
||||
name: file.file.name,
|
||||
type: file.type,
|
||||
fileUrl: URL.createObjectURL(file.file),
|
||||
uploadedAt: new Date(),
|
||||
analyzedAt: new Date(),
|
||||
analysisResult: {
|
||||
detectedType: file.type,
|
||||
confidence: 0.5,
|
||||
extractedEntities: [],
|
||||
gaps: [],
|
||||
recommendations: ['Backend nicht erreichbar — manuelle Pruefung empfohlen'],
|
||||
},
|
||||
}
|
||||
addImportedDocument(doc)
|
||||
setFiles(prev => prev.map(f => (f.id === file.id ? { ...f, progress: 100, status: 'complete' as const } : f)))
|
||||
}
|
||||
|
||||
// Update to analyzing
|
||||
setFiles(prev => prev.map(f => (f.id === file.id ? { ...f, status: 'analyzing' as const } : f)))
|
||||
|
||||
// Simulate analysis
|
||||
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||
|
||||
// Create imported document
|
||||
const doc: ImportedDocument = {
|
||||
id: file.id,
|
||||
name: file.file.name,
|
||||
type: file.type,
|
||||
fileUrl: URL.createObjectURL(file.file),
|
||||
uploadedAt: new Date(),
|
||||
analyzedAt: new Date(),
|
||||
analysisResult: {
|
||||
detectedType: file.type,
|
||||
confidence: 0.85 + Math.random() * 0.15,
|
||||
extractedEntities: ['DSGVO', 'AI Act', 'Personenbezogene Daten'],
|
||||
gaps: [],
|
||||
recommendations: ['KI-spezifische Klauseln ergaenzen', 'AI Act Anforderungen pruefen'],
|
||||
},
|
||||
}
|
||||
|
||||
addImportedDocument(doc)
|
||||
|
||||
// Update to complete
|
||||
setFiles(prev => prev.map(f => (f.id === file.id ? { ...f, status: 'complete' as const } : f)))
|
||||
}
|
||||
|
||||
// Generate mock gap analysis
|
||||
const gaps: GapItem[] = [
|
||||
{
|
||||
id: 'gap-1',
|
||||
category: 'AI Act Compliance',
|
||||
description: 'Keine Risikoklassifizierung fuer KI-Systeme vorhanden',
|
||||
severity: 'CRITICAL',
|
||||
regulation: 'EU AI Act Art. 6',
|
||||
requiredAction: 'Risikoklassifizierung durchfuehren',
|
||||
relatedStepId: 'ai-act',
|
||||
},
|
||||
{
|
||||
id: 'gap-2',
|
||||
category: 'Transparenz',
|
||||
description: 'Informationspflichten bei automatisierten Entscheidungen fehlen',
|
||||
severity: 'HIGH',
|
||||
regulation: 'DSGVO Art. 13, 14, 22',
|
||||
requiredAction: 'Datenschutzerklaerung erweitern',
|
||||
relatedStepId: 'einwilligungen',
|
||||
},
|
||||
{
|
||||
id: 'gap-3',
|
||||
category: 'TOMs',
|
||||
description: 'KI-spezifische technische Massnahmen nicht dokumentiert',
|
||||
severity: 'MEDIUM',
|
||||
regulation: 'DSGVO Art. 32',
|
||||
requiredAction: 'TOMs um KI-Aspekte erweitern',
|
||||
relatedStepId: 'tom',
|
||||
},
|
||||
{
|
||||
id: 'gap-4',
|
||||
category: 'VVT',
|
||||
description: 'KI-basierte Verarbeitungstaetigkeiten nicht erfasst',
|
||||
severity: 'HIGH',
|
||||
regulation: 'DSGVO Art. 30',
|
||||
requiredAction: 'VVT aktualisieren',
|
||||
relatedStepId: 'vvt',
|
||||
},
|
||||
{
|
||||
id: 'gap-5',
|
||||
category: 'Aufsicht',
|
||||
description: 'Menschliche Aufsicht nicht definiert',
|
||||
severity: 'MEDIUM',
|
||||
regulation: 'EU AI Act Art. 14',
|
||||
requiredAction: 'Aufsichtsprozesse definieren',
|
||||
relatedStepId: 'controls',
|
||||
},
|
||||
]
|
||||
|
||||
// Build gap analysis summary
|
||||
const gapAnalysis: GapAnalysis = {
|
||||
id: `analysis-${Date.now()}`,
|
||||
createdAt: new Date(),
|
||||
totalGaps: gaps.length,
|
||||
criticalGaps: gaps.filter(g => g.severity === 'CRITICAL').length,
|
||||
highGaps: gaps.filter(g => g.severity === 'HIGH').length,
|
||||
mediumGaps: gaps.filter(g => g.severity === 'MEDIUM').length,
|
||||
lowGaps: gaps.filter(g => g.severity === 'LOW').length,
|
||||
gaps,
|
||||
recommendedPackages: ['analyse', 'dokumentation'],
|
||||
totalGaps: allGaps.length,
|
||||
criticalGaps: allGaps.filter(g => g.severity === 'CRITICAL').length,
|
||||
highGaps: allGaps.filter(g => g.severity === 'HIGH').length,
|
||||
mediumGaps: allGaps.filter(g => g.severity === 'MEDIUM').length,
|
||||
lowGaps: allGaps.filter(g => g.severity === 'LOW').length,
|
||||
gaps: allGaps,
|
||||
recommendedPackages: allGaps.length > 0 ? ['analyse', 'dokumentation'] : [],
|
||||
}
|
||||
|
||||
setAnalysisResult(gapAnalysis)
|
||||
|
||||
Reference in New Issue
Block a user