Initial commit: breakpilot-compliance - Compliance SDK Platform

Services: Admin-Compliance, Backend-Compliance,
AI-Compliance-SDK, Consent-SDK, Developer-Portal,
PCA-Platform, DSMS

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Boenisch
2026-02-11 23:47:28 +01:00
commit 4435e7ea0a
734 changed files with 251369 additions and 0 deletions

View File

@@ -0,0 +1,129 @@
'use client'
import React from 'react'
import { useRouter } from 'next/navigation'
import { useTOMGenerator } from '@/lib/sdk/tom-generator'
import { ArchitectureStep } from '@/components/sdk/tom-generator/steps/ArchitectureStep'
import { TOM_GENERATOR_STEPS } from '@/lib/sdk/tom-generator/types'
/**
* Step 3: Architecture & Hosting
*
* Collects infrastructure information including:
* - Hosting model (On-Premise/Cloud/Hybrid)
* - Location (DE/EU/Third country)
* - Cloud providers with certifications
* - Multi-tenancy
* - Encryption (at rest / in transit)
*/
export default function ArchitecturePage() {
const router = useRouter()
const { state, goToNextStep, goToPreviousStep } = useTOMGenerator()
const currentStepIndex = TOM_GENERATOR_STEPS.findIndex((s) => s.id === 'architecture-hosting')
const prevStep = TOM_GENERATOR_STEPS[currentStepIndex - 1]
const nextStep = TOM_GENERATOR_STEPS[currentStepIndex + 1]
const handleNext = () => {
goToNextStep()
if (nextStep) {
router.push(nextStep.url)
}
}
const handleBack = () => {
goToPreviousStep()
if (prevStep) {
router.push(prevStep.url)
}
}
return (
<div className="max-w-4xl mx-auto px-4 py-8">
{/* Step Header */}
<div className="mb-8">
<div className="flex items-center gap-2 text-sm text-gray-500 mb-2">
<span>Schritt 3 von 6</span>
<span className="text-gray-300">|</span>
<span>Architektur & Hosting</span>
</div>
<h1 className="text-2xl font-bold text-gray-900">
IT-Architektur & Hosting
</h1>
<p className="mt-2 text-gray-600">
Beschreiben Sie Ihre technische Infrastruktur. Die Hosting-Umgebung
beeinflusst wesentlich die erforderlichen Sicherheitsmassnahmen.
</p>
</div>
{/* Progress Indicator */}
<div className="mb-8">
<div className="flex items-center gap-2">
{TOM_GENERATOR_STEPS.map((step, index) => {
const stepState = state.steps.find((s) => s.id === step.id)
const isCompleted = stepState?.completed
const isCurrent = state.currentStep === step.id
return (
<React.Fragment key={step.id}>
<button
onClick={() => router.push(step.url)}
className={`w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium transition-all ${
isCompleted
? 'bg-green-500 text-white'
: isCurrent
? 'bg-blue-500 text-white'
: 'bg-gray-200 text-gray-500 hover:bg-gray-300'
}`}
title={step.name}
>
{isCompleted ? (
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
) : (
index + 1
)}
</button>
{index < TOM_GENERATOR_STEPS.length - 1 && (
<div
className={`flex-1 h-1 rounded ${
isCompleted ? 'bg-green-500' : 'bg-gray-200'
}`}
/>
)}
</React.Fragment>
)
})}
</div>
</div>
{/* Step Content */}
<div className="bg-white rounded-xl border border-gray-200 p-6">
<ArchitectureStep />
</div>
{/* Navigation */}
<div className="flex justify-between mt-6">
<button
onClick={handleBack}
className="px-4 py-2 text-gray-600 hover:text-gray-900 transition-colors flex items-center gap-2"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
Zurueck
</button>
<button
onClick={handleNext}
className="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-2"
>
Weiter
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</button>
</div>
</div>
)
}

View File

@@ -0,0 +1,128 @@
'use client'
import React from 'react'
import { useRouter } from 'next/navigation'
import { useTOMGenerator } from '@/lib/sdk/tom-generator'
import { DataCategoriesStep } from '@/components/sdk/tom-generator/steps/DataCategoriesStep'
import { TOM_GENERATOR_STEPS } from '@/lib/sdk/tom-generator/types'
/**
* Step 2: Data Categories
*
* Collects data processing information including:
* - Data categories (with warnings for special categories)
* - Data subjects (with warnings for minors)
* - Data volume
* - Third country transfers
*/
export default function DataPage() {
const router = useRouter()
const { state, goToNextStep, goToPreviousStep } = useTOMGenerator()
const currentStepIndex = TOM_GENERATOR_STEPS.findIndex((s) => s.id === 'data-categories')
const prevStep = TOM_GENERATOR_STEPS[currentStepIndex - 1]
const nextStep = TOM_GENERATOR_STEPS[currentStepIndex + 1]
const handleNext = () => {
goToNextStep()
if (nextStep) {
router.push(nextStep.url)
}
}
const handleBack = () => {
goToPreviousStep()
if (prevStep) {
router.push(prevStep.url)
}
}
return (
<div className="max-w-4xl mx-auto px-4 py-8">
{/* Step Header */}
<div className="mb-8">
<div className="flex items-center gap-2 text-sm text-gray-500 mb-2">
<span>Schritt 2 von 6</span>
<span className="text-gray-300">|</span>
<span>Datenkategorien</span>
</div>
<h1 className="text-2xl font-bold text-gray-900">
Datenkategorien & Betroffene
</h1>
<p className="mt-2 text-gray-600">
Welche Arten von personenbezogenen Daten verarbeiten Sie?
Die Sensitivitaet der Daten bestimmt die erforderlichen Schutzmassnahmen.
</p>
</div>
{/* Progress Indicator */}
<div className="mb-8">
<div className="flex items-center gap-2">
{TOM_GENERATOR_STEPS.map((step, index) => {
const stepState = state.steps.find((s) => s.id === step.id)
const isCompleted = stepState?.completed
const isCurrent = state.currentStep === step.id
return (
<React.Fragment key={step.id}>
<button
onClick={() => router.push(step.url)}
className={`w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium transition-all ${
isCompleted
? 'bg-green-500 text-white'
: isCurrent
? 'bg-blue-500 text-white'
: 'bg-gray-200 text-gray-500 hover:bg-gray-300'
}`}
title={step.name}
>
{isCompleted ? (
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
) : (
index + 1
)}
</button>
{index < TOM_GENERATOR_STEPS.length - 1 && (
<div
className={`flex-1 h-1 rounded ${
isCompleted ? 'bg-green-500' : 'bg-gray-200'
}`}
/>
)}
</React.Fragment>
)
})}
</div>
</div>
{/* Step Content */}
<div className="bg-white rounded-xl border border-gray-200 p-6">
<DataCategoriesStep />
</div>
{/* Navigation */}
<div className="flex justify-between mt-6">
<button
onClick={handleBack}
className="px-4 py-2 text-gray-600 hover:text-gray-900 transition-colors flex items-center gap-2"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
Zurueck
</button>
<button
onClick={handleNext}
className="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-2"
>
Weiter
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</button>
</div>
</div>
)
}

View File

@@ -0,0 +1,30 @@
'use client'
import React from 'react'
import { TOMGeneratorProvider } from '@/lib/sdk/tom-generator'
/**
* TOM Generator Layout
*
* Wraps all TOM Generator pages with the TOMGeneratorProvider
* to share state across all wizard steps.
*
* Note: In production, tenantId would come from authentication/session.
* For development, we use a default demo tenant ID.
*/
export default function TOMGeneratorLayout({
children,
}: {
children: React.ReactNode
}) {
// TODO: In production, get tenantId from authentication context
const tenantId = 'demo-tenant'
return (
<TOMGeneratorProvider tenantId={tenantId}>
<div className="min-h-screen bg-gray-50">
{children}
</div>
</TOMGeneratorProvider>
)
}

View File

@@ -0,0 +1,215 @@
'use client'
import React from 'react'
import { useRouter } from 'next/navigation'
import { useTOMGenerator } from '@/lib/sdk/tom-generator'
import { TOM_GENERATOR_STEPS } from '@/lib/sdk/tom-generator/types'
/**
* TOM Generator Landing Page
*
* Shows overview of the wizard and allows starting or resuming.
*/
export default function TOMGeneratorPage() {
const router = useRouter()
const { state, resetState } = useTOMGenerator()
// Calculate progress
const completedSteps = state.steps.filter((s) => s.completed).length
const totalSteps = state.steps.length
const progressPercent = totalSteps > 0 ? Math.round((completedSteps / totalSteps) * 100) : 0
// Determine the current step URL
const currentStepConfig = TOM_GENERATOR_STEPS.find((s) => s.id === state.currentStep)
const currentStepUrl = currentStepConfig?.url || '/sdk/tom-generator/scope'
const handleStartNew = () => {
resetState()
router.push('/sdk/tom-generator/scope')
}
const handleResume = () => {
router.push(currentStepUrl)
}
const hasProgress = completedSteps > 0
return (
<div className="max-w-4xl mx-auto px-4 py-8">
{/* Header */}
<div className="mb-8">
<h1 className="text-3xl font-bold text-gray-900">TOM Generator</h1>
<p className="mt-2 text-gray-600">
Leiten Sie Ihre Technischen und Organisatorischen Massnahmen (TOMs) nach Art. 32 DSGVO
systematisch ab und dokumentieren Sie diese.
</p>
</div>
{/* Progress Card */}
{hasProgress && (
<div className="bg-white rounded-xl border border-gray-200 p-6 mb-8">
<div className="flex items-center justify-between mb-4">
<h2 className="text-lg font-semibold text-gray-900">Ihr Fortschritt</h2>
<span className="text-sm text-gray-500">
{completedSteps} von {totalSteps} Schritten abgeschlossen
</span>
</div>
{/* Progress Bar */}
<div className="h-3 bg-gray-100 rounded-full overflow-hidden mb-4">
<div
className="h-full bg-gradient-to-r from-blue-500 to-purple-500 transition-all duration-500"
style={{ width: `${progressPercent}%` }}
/>
</div>
{/* Steps Overview */}
<div className="grid grid-cols-2 md:grid-cols-3 gap-3">
{TOM_GENERATOR_STEPS.map((step, index) => {
const stepState = state.steps.find((s) => s.id === step.id)
const isCompleted = stepState?.completed
const isCurrent = state.currentStep === step.id
return (
<button
key={step.id}
onClick={() => router.push(step.url)}
className={`flex items-center gap-3 p-3 rounded-lg border transition-all ${
isCompleted
? 'bg-green-50 border-green-200 text-green-700'
: isCurrent
? 'bg-blue-50 border-blue-200 text-blue-700'
: 'bg-gray-50 border-gray-200 text-gray-500 hover:bg-gray-100'
}`}
>
<div
className={`w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium ${
isCompleted
? 'bg-green-500 text-white'
: isCurrent
? 'bg-blue-500 text-white'
: 'bg-gray-200 text-gray-500'
}`}
>
{isCompleted ? (
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
) : (
index + 1
)}
</div>
<span className="text-sm font-medium">{step.name}</span>
</button>
)
})}
</div>
{/* Actions */}
<div className="flex gap-3 mt-6">
<button
onClick={handleResume}
className="flex-1 px-4 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors font-medium"
>
Fortfahren
</button>
<button
onClick={handleStartNew}
className="px-4 py-3 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors"
>
Neu starten
</button>
</div>
</div>
)}
{/* Introduction Card */}
<div className="bg-white rounded-xl border border-gray-200 p-6 mb-8">
<h2 className="text-lg font-semibold text-gray-900 mb-4">Was ist der TOM Generator?</h2>
<p className="text-gray-600 mb-4">
Der TOM Generator fuehrt Sie in 6 Schritten durch die Erstellung Ihrer DSGVO-konformen
Technischen und Organisatorischen Massnahmen:
</p>
<div className="space-y-3">
{TOM_GENERATOR_STEPS.map((step, index) => (
<div key={step.id} className="flex items-start gap-3">
<div className="w-6 h-6 rounded-full bg-blue-100 text-blue-600 flex items-center justify-center text-sm font-medium flex-shrink-0">
{index + 1}
</div>
<div>
<div className="font-medium text-gray-900">{step.name}</div>
<div className="text-sm text-gray-500">{step.description.de}</div>
</div>
</div>
))}
</div>
{!hasProgress && (
<button
onClick={handleStartNew}
className="w-full mt-6 px-4 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors font-medium"
>
Jetzt starten
</button>
)}
</div>
{/* Features */}
<div className="grid md:grid-cols-3 gap-4">
<div className="bg-white rounded-xl border border-gray-200 p-6">
<div className="w-10 h-10 rounded-lg bg-purple-100 flex items-center justify-center mb-4">
<svg className="w-5 h-5 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
</svg>
</div>
<h3 className="font-semibold text-gray-900 mb-2">60+ Kontrollen</h3>
<p className="text-sm text-gray-500">
Vordefinierte Kontrollen mit Mapping zu DSGVO, ISO 27001 und BSI-Grundschutz
</p>
</div>
<div className="bg-white rounded-xl border border-gray-200 p-6">
<div className="w-10 h-10 rounded-lg bg-green-100 flex items-center justify-center mb-4">
<svg className="w-5 h-5 text-green-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="font-semibold text-gray-900 mb-2">Lueckenanalyse</h3>
<p className="text-sm text-gray-500">
Automatische Identifikation fehlender Massnahmen mit Handlungsempfehlungen
</p>
</div>
<div className="bg-white rounded-xl border border-gray-200 p-6">
<div className="w-10 h-10 rounded-lg bg-blue-100 flex items-center justify-center mb-4">
<svg className="w-5 h-5 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
</div>
<h3 className="font-semibold text-gray-900 mb-2">Export</h3>
<p className="text-sm text-gray-500">
Generieren Sie Ihre TOM-Dokumentation als Word, PDF oder strukturiertes JSON
</p>
</div>
</div>
{/* Legal Note */}
<div className="mt-8 p-4 bg-blue-50 rounded-lg border border-blue-200">
<div className="flex gap-3">
<svg className="w-5 h-5 text-blue-600 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<div>
<div className="font-medium text-blue-900">Hinweis zur Rechtsgrundlage</div>
<p className="text-sm text-blue-700 mt-1">
Die generierten TOMs basieren auf Art. 32 DSGVO. Die Auswahl der konkreten Massnahmen
sollte immer unter Beruecksichtigung des Stands der Technik, der Implementierungskosten
und der Art, des Umfangs und der Zwecke der Verarbeitung erfolgen.
</p>
</div>
</div>
</div>
</div>
)
}

View File

@@ -0,0 +1,147 @@
'use client'
import React from 'react'
import { useRouter } from 'next/navigation'
import { useTOMGenerator } from '@/lib/sdk/tom-generator'
import { ReviewExportStep } from '@/components/sdk/tom-generator/steps/ReviewExportStep'
import { TOM_GENERATOR_STEPS } from '@/lib/sdk/tom-generator/types'
/**
* Step 6: Review & Export
*
* Final step including:
* - Summary of all steps
* - Derived TOMs table
* - Gap analysis visualization
* - Evidence Vault overview
* - Export (Word/PDF/JSON/ZIP)
*/
export default function ReviewPage() {
const router = useRouter()
const { state, goToPreviousStep } = useTOMGenerator()
const currentStepIndex = TOM_GENERATOR_STEPS.findIndex((s) => s.id === 'review-export')
const prevStep = TOM_GENERATOR_STEPS[currentStepIndex - 1]
const handleBack = () => {
goToPreviousStep()
if (prevStep) {
router.push(prevStep.url)
}
}
// Check if all previous steps are completed
const allPreviousStepsCompleted = TOM_GENERATOR_STEPS
.slice(0, currentStepIndex)
.every((step) => {
const stepState = state.steps.find((s) => s.id === step.id)
return stepState?.completed
})
return (
<div className="max-w-5xl mx-auto px-4 py-8">
{/* Step Header */}
<div className="mb-8">
<div className="flex items-center gap-2 text-sm text-gray-500 mb-2">
<span>Schritt 6 von 6</span>
<span className="text-gray-300">|</span>
<span>Review & Export</span>
</div>
<h1 className="text-2xl font-bold text-gray-900">
Zusammenfassung & Export
</h1>
<p className="mt-2 text-gray-600">
Pruefen Sie Ihre abgeleiteten TOMs, analysieren Sie Luecken und exportieren
Sie Ihre Dokumentation in verschiedenen Formaten.
</p>
</div>
{/* Progress Indicator */}
<div className="mb-8">
<div className="flex items-center gap-2">
{TOM_GENERATOR_STEPS.map((step, index) => {
const stepState = state.steps.find((s) => s.id === step.id)
const isCompleted = stepState?.completed
const isCurrent = state.currentStep === step.id
return (
<React.Fragment key={step.id}>
<button
onClick={() => router.push(step.url)}
className={`w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium transition-all ${
isCompleted
? 'bg-green-500 text-white'
: isCurrent
? 'bg-blue-500 text-white'
: 'bg-gray-200 text-gray-500 hover:bg-gray-300'
}`}
title={step.name}
>
{isCompleted ? (
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
) : (
index + 1
)}
</button>
{index < TOM_GENERATOR_STEPS.length - 1 && (
<div
className={`flex-1 h-1 rounded ${
isCompleted ? 'bg-green-500' : 'bg-gray-200'
}`}
/>
)}
</React.Fragment>
)
})}
</div>
</div>
{/* Warning if previous steps not completed */}
{!allPreviousStepsCompleted && (
<div className="mb-6 p-4 bg-yellow-50 rounded-lg border border-yellow-200">
<div className="flex gap-3">
<svg className="w-5 h-5 text-yellow-600 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
<div>
<div className="font-medium text-yellow-900">Nicht alle Schritte abgeschlossen</div>
<p className="text-sm text-yellow-700 mt-1">
Bitte schliessen Sie alle vorherigen Schritte ab, um eine vollstaendige TOM-Dokumentation
zu generieren. Fehlende Informationen fuehren zu unvollstaendigen Empfehlungen.
</p>
</div>
</div>
</div>
)}
{/* Step Content */}
<div className="bg-white rounded-xl border border-gray-200 p-6">
<ReviewExportStep />
</div>
{/* Navigation */}
<div className="flex justify-between mt-6">
<button
onClick={handleBack}
className="px-4 py-2 text-gray-600 hover:text-gray-900 transition-colors flex items-center gap-2"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
Zurueck
</button>
<button
onClick={() => router.push('/sdk/tom-generator')}
className="px-6 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors flex items-center gap-2"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
Abschliessen
</button>
</div>
</div>
)
}

View File

@@ -0,0 +1,146 @@
'use client'
import React from 'react'
import { useRouter } from 'next/navigation'
import { useTOMGenerator } from '@/lib/sdk/tom-generator'
import { RiskProtectionStep } from '@/components/sdk/tom-generator/steps/RiskProtectionStep'
import { TOM_GENERATOR_STEPS } from '@/lib/sdk/tom-generator/types'
/**
* Step 5: Risk & Protection Level
*
* Assesses risk and protection requirements including:
* - CIA Assessment (Confidentiality/Integrity/Availability, 1-5 each)
* - Calculated protection level
* - Special risks
* - Regulatory requirements
* - DSFA indicator (automatic)
*/
export default function RiskPage() {
const router = useRouter()
const { state, goToNextStep, goToPreviousStep } = useTOMGenerator()
const currentStepIndex = TOM_GENERATOR_STEPS.findIndex((s) => s.id === 'risk-protection')
const prevStep = TOM_GENERATOR_STEPS[currentStepIndex - 1]
const nextStep = TOM_GENERATOR_STEPS[currentStepIndex + 1]
const handleNext = () => {
goToNextStep()
if (nextStep) {
router.push(nextStep.url)
}
}
const handleBack = () => {
goToPreviousStep()
if (prevStep) {
router.push(prevStep.url)
}
}
return (
<div className="max-w-4xl mx-auto px-4 py-8">
{/* Step Header */}
<div className="mb-8">
<div className="flex items-center gap-2 text-sm text-gray-500 mb-2">
<span>Schritt 5 von 6</span>
<span className="text-gray-300">|</span>
<span>Risiko & Schutzbedarf</span>
</div>
<h1 className="text-2xl font-bold text-gray-900">
Risikobewertung & Schutzbedarf
</h1>
<p className="mt-2 text-gray-600">
Bewerten Sie die Schutzziele (CIA) fuer Ihre Datenverarbeitung.
Der ermittelte Schutzbedarf bestimmt die Intensitaet der erforderlichen Massnahmen.
</p>
</div>
{/* Progress Indicator */}
<div className="mb-8">
<div className="flex items-center gap-2">
{TOM_GENERATOR_STEPS.map((step, index) => {
const stepState = state.steps.find((s) => s.id === step.id)
const isCompleted = stepState?.completed
const isCurrent = state.currentStep === step.id
return (
<React.Fragment key={step.id}>
<button
onClick={() => router.push(step.url)}
className={`w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium transition-all ${
isCompleted
? 'bg-green-500 text-white'
: isCurrent
? 'bg-blue-500 text-white'
: 'bg-gray-200 text-gray-500 hover:bg-gray-300'
}`}
title={step.name}
>
{isCompleted ? (
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
) : (
index + 1
)}
</button>
{index < TOM_GENERATOR_STEPS.length - 1 && (
<div
className={`flex-1 h-1 rounded ${
isCompleted ? 'bg-green-500' : 'bg-gray-200'
}`}
/>
)}
</React.Fragment>
)
})}
</div>
</div>
{/* CIA Info Box */}
<div className="mb-6 p-4 bg-blue-50 rounded-lg border border-blue-200">
<div className="flex gap-3">
<svg className="w-5 h-5 text-blue-600 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<div>
<div className="font-medium text-blue-900">CIA-Triade</div>
<p className="text-sm text-blue-700 mt-1">
<strong>Vertraulichkeit</strong>: Schutz vor unbefugtem Zugriff |
<strong> Integritaet</strong>: Schutz vor unbefugter Aenderung |
<strong> Verfuegbarkeit</strong>: Sicherstellung des Zugriffs
</p>
</div>
</div>
</div>
{/* Step Content */}
<div className="bg-white rounded-xl border border-gray-200 p-6">
<RiskProtectionStep />
</div>
{/* Navigation */}
<div className="flex justify-between mt-6">
<button
onClick={handleBack}
className="px-4 py-2 text-gray-600 hover:text-gray-900 transition-colors flex items-center gap-2"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
Zurueck
</button>
<button
onClick={handleNext}
className="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-2"
>
Weiter
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</button>
</div>
</div>
)
}

View File

@@ -0,0 +1,130 @@
'use client'
import React from 'react'
import { useRouter } from 'next/navigation'
import { useTOMGenerator } from '@/lib/sdk/tom-generator'
import { ScopeRolesStep } from '@/components/sdk/tom-generator/steps/ScopeRolesStep'
import { TOM_GENERATOR_STEPS } from '@/lib/sdk/tom-generator/types'
/**
* Step 1: Scope & Roles
*
* Collects company profile information including:
* - Company name, industry, size
* - GDPR role (Controller/Processor/Joint Controller)
* - Products/Services
* - DPO and IT Security contacts
*/
export default function ScopePage() {
const router = useRouter()
const { state, goToNextStep } = useTOMGenerator()
const currentStepIndex = TOM_GENERATOR_STEPS.findIndex((s) => s.id === 'scope-roles')
const nextStep = TOM_GENERATOR_STEPS[currentStepIndex + 1]
// Handle step completion
const handleStepComplete = () => {
goToNextStep()
if (nextStep) {
router.push(nextStep.url)
}
}
return (
<div className="max-w-4xl mx-auto px-4 py-8">
{/* Step Header */}
<div className="mb-8">
<div className="flex items-center gap-2 text-sm text-gray-500 mb-2">
<span>Schritt 1 von 6</span>
<span className="text-gray-300">|</span>
<span>Scope & Rollen</span>
</div>
<h1 className="text-2xl font-bold text-gray-900">
Unternehmens- und Rollendefinition
</h1>
<p className="mt-2 text-gray-600">
Definieren Sie Ihr Unternehmen und Ihre Rolle in der Datenverarbeitung.
Diese Informationen bestimmen, welche TOMs fuer Sie relevant sind.
</p>
</div>
{/* Progress Indicator */}
<div className="mb-8">
<div className="flex items-center gap-2">
{TOM_GENERATOR_STEPS.map((step, index) => {
const stepState = state.steps.find((s) => s.id === step.id)
const isCompleted = stepState?.completed
const isCurrent = state.currentStep === step.id
return (
<React.Fragment key={step.id}>
<button
onClick={() => router.push(step.url)}
className={`w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium transition-all ${
isCompleted
? 'bg-green-500 text-white'
: isCurrent
? 'bg-blue-500 text-white'
: 'bg-gray-200 text-gray-500 hover:bg-gray-300'
}`}
title={step.name}
>
{isCompleted ? (
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
) : (
index + 1
)}
</button>
{index < TOM_GENERATOR_STEPS.length - 1 && (
<div
className={`flex-1 h-1 rounded ${
isCompleted ? 'bg-green-500' : 'bg-gray-200'
}`}
/>
)}
</React.Fragment>
)
})}
</div>
</div>
{/* Scope Prefill Hint */}
<div className="bg-purple-50 border border-purple-200 rounded-xl p-4 mb-4">
<div className="flex items-start gap-3">
<svg className="w-5 h-5 text-purple-600 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<div>
<p className="text-sm text-purple-800">
<span className="font-semibold">Tipp:</span> Wenn Sie bereits die Scope-Analyse ausgefuellt haben, werden relevante Felder
(Branche, Groesse, Hosting, Verschluesselung) automatisch vorausgefuellt. Anpassungen sind jederzeit moeglich.
</p>
</div>
</div>
</div>
{/* Step Content */}
<div className="bg-white rounded-xl border border-gray-200 p-6">
<ScopeRolesStep />
</div>
{/* Navigation */}
<div className="flex justify-between mt-6">
<button
onClick={() => router.push('/sdk/tom-generator')}
className="px-4 py-2 text-gray-600 hover:text-gray-900 transition-colors"
>
Zurueck zur Uebersicht
</button>
<button
onClick={handleStepComplete}
className="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
>
Weiter
</button>
</div>
</div>
)
}

View File

@@ -0,0 +1,129 @@
'use client'
import React from 'react'
import { useRouter } from 'next/navigation'
import { useTOMGenerator } from '@/lib/sdk/tom-generator'
import { SecurityProfileStep } from '@/components/sdk/tom-generator/steps/SecurityProfileStep'
import { TOM_GENERATOR_STEPS } from '@/lib/sdk/tom-generator/types'
/**
* Step 4: Security Profile
*
* Collects security measures including:
* - Authentication (Password, MFA, SSO)
* - IAM/PAM
* - Logging & Retention
* - Backup & DR
* - Vulnerability Management, Pentests, Training
*/
export default function SecurityPage() {
const router = useRouter()
const { state, goToNextStep, goToPreviousStep } = useTOMGenerator()
const currentStepIndex = TOM_GENERATOR_STEPS.findIndex((s) => s.id === 'security-profile')
const prevStep = TOM_GENERATOR_STEPS[currentStepIndex - 1]
const nextStep = TOM_GENERATOR_STEPS[currentStepIndex + 1]
const handleNext = () => {
goToNextStep()
if (nextStep) {
router.push(nextStep.url)
}
}
const handleBack = () => {
goToPreviousStep()
if (prevStep) {
router.push(prevStep.url)
}
}
return (
<div className="max-w-4xl mx-auto px-4 py-8">
{/* Step Header */}
<div className="mb-8">
<div className="flex items-center gap-2 text-sm text-gray-500 mb-2">
<span>Schritt 4 von 6</span>
<span className="text-gray-300">|</span>
<span>Security-Profil</span>
</div>
<h1 className="text-2xl font-bold text-gray-900">
Sicherheitsmassnahmen
</h1>
<p className="mt-2 text-gray-600">
Erfassen Sie Ihre bestehenden Sicherheitsmassnahmen. Diese Informationen
helfen bei der Identifikation von Luecken und Verbesserungspotenzialen.
</p>
</div>
{/* Progress Indicator */}
<div className="mb-8">
<div className="flex items-center gap-2">
{TOM_GENERATOR_STEPS.map((step, index) => {
const stepState = state.steps.find((s) => s.id === step.id)
const isCompleted = stepState?.completed
const isCurrent = state.currentStep === step.id
return (
<React.Fragment key={step.id}>
<button
onClick={() => router.push(step.url)}
className={`w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium transition-all ${
isCompleted
? 'bg-green-500 text-white'
: isCurrent
? 'bg-blue-500 text-white'
: 'bg-gray-200 text-gray-500 hover:bg-gray-300'
}`}
title={step.name}
>
{isCompleted ? (
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
) : (
index + 1
)}
</button>
{index < TOM_GENERATOR_STEPS.length - 1 && (
<div
className={`flex-1 h-1 rounded ${
isCompleted ? 'bg-green-500' : 'bg-gray-200'
}`}
/>
)}
</React.Fragment>
)
})}
</div>
</div>
{/* Step Content */}
<div className="bg-white rounded-xl border border-gray-200 p-6">
<SecurityProfileStep />
</div>
{/* Navigation */}
<div className="flex justify-between mt-6">
<button
onClick={handleBack}
className="px-4 py-2 text-gray-600 hover:text-gray-900 transition-colors flex items-center gap-2"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
Zurueck
</button>
<button
onClick={handleNext}
className="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-2"
>
Weiter
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</button>
</div>
</div>
)
}