feat(pitch): add SDK demo slide with screenshot gallery + inline preview
- New annex slide 'annex-sdk-demo' with auto-scrolling screenshot gallery (22 real screenshots from Müller Maschinenbau demo project) - Browser chrome mockup, fullscreen view, thumbnail strip navigation - Inline SDK dashboard preview on Product slide - Seed script for creating demo data + taking Playwright screenshots - Presenter script for SDK demo narration Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@@ -28,6 +28,7 @@ const SLIDE_DISPLAY_NAMES: Record<string, { de: string; en: string }> = {
|
||||
'annex-regulatory': { de: 'Anhang: Regulatorik', en: 'Appendix: Regulatory' },
|
||||
'annex-engineering': { de: 'Anhang: Engineering', en: 'Appendix: Engineering' },
|
||||
'annex-aipipeline': { de: 'Anhang: KI-Pipeline', en: 'Appendix: AI Pipeline' },
|
||||
'annex-sdk-demo': { de: 'Anhang: SDK Demo', en: 'Appendix: SDK Demo' },
|
||||
}
|
||||
|
||||
const slideCount = SLIDE_ORDER.length
|
||||
|
||||
@@ -38,6 +38,7 @@ import GTMSlide from './slides/GTMSlide'
|
||||
import RegulatorySlide from './slides/RegulatorySlide'
|
||||
import EngineeringSlide from './slides/EngineeringSlide'
|
||||
import AIPipelineSlide from './slides/AIPipelineSlide'
|
||||
import SDKDemoSlide from './slides/SDKDemoSlide'
|
||||
|
||||
interface PitchDeckProps {
|
||||
lang: Language
|
||||
@@ -154,6 +155,8 @@ export default function PitchDeck({ lang, onToggleLanguage }: PitchDeckProps) {
|
||||
return <EngineeringSlide lang={lang} />
|
||||
case 'annex-aipipeline':
|
||||
return <AIPipelineSlide lang={lang} />
|
||||
case 'annex-sdk-demo':
|
||||
return <SDKDemoSlide lang={lang} />
|
||||
default:
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import Image from 'next/image'
|
||||
import { Language, PitchProduct } from '@/lib/types'
|
||||
import { t } from '@/lib/i18n'
|
||||
import GradientText from '../ui/GradientText'
|
||||
@@ -13,21 +14,48 @@ interface ProductSlideProps {
|
||||
|
||||
export default function ProductSlide({ lang, products }: ProductSlideProps) {
|
||||
const i = t(lang)
|
||||
const de = lang === 'de'
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FadeInView className="text-center mb-12">
|
||||
<FadeInView className="text-center mb-8">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-3">
|
||||
<GradientText>{i.product.title}</GradientText>
|
||||
</h2>
|
||||
<p className="text-lg text-white/50 max-w-2xl mx-auto">{i.product.subtitle}</p>
|
||||
</FadeInView>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
<div className="grid md:grid-cols-3 gap-6 mb-8">
|
||||
{products.map((product, idx) => (
|
||||
<PricingCard key={product.id} product={product} lang={lang} delay={0.2 + idx * 0.15} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* SDK Preview */}
|
||||
<FadeInView delay={0.6}>
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<div className="rounded-xl overflow-hidden border border-white/10 bg-black/20 shadow-lg shadow-indigo-500/5">
|
||||
<div className="flex items-center gap-2 px-3 py-1.5 bg-white/[0.03] border-b border-white/10">
|
||||
<div className="flex gap-1">
|
||||
<div className="w-2 h-2 rounded-full bg-red-500/50" />
|
||||
<div className="w-2 h-2 rounded-full bg-yellow-500/50" />
|
||||
<div className="w-2 h-2 rounded-full bg-green-500/50" />
|
||||
</div>
|
||||
<span className="text-[10px] text-white/20 font-mono ml-2">admin.breakpilot.ai/sdk</span>
|
||||
</div>
|
||||
<Image
|
||||
src="/screenshots/01-dashboard.png"
|
||||
alt={de ? 'SDK Dashboard' : 'SDK Dashboard'}
|
||||
width={1920}
|
||||
height={1080}
|
||||
className="w-full h-auto opacity-80"
|
||||
/>
|
||||
</div>
|
||||
<p className="text-center text-xs text-white/30 mt-2 font-mono">
|
||||
{de ? '65+ Module · Live-Plattform · Details im Anhang' : '65+ Modules · Live Platform · Details in Appendix'}
|
||||
</p>
|
||||
</div>
|
||||
</FadeInView>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
204
pitch-deck/components/slides/SDKDemoSlide.tsx
Normal file
@@ -0,0 +1,204 @@
|
||||
'use client'
|
||||
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { motion, AnimatePresence } from 'framer-motion'
|
||||
import Image from 'next/image'
|
||||
import { Language } from '@/lib/types'
|
||||
import GradientText from '../ui/GradientText'
|
||||
import FadeInView from '../ui/FadeInView'
|
||||
import { ChevronLeft, ChevronRight, Maximize2 } from 'lucide-react'
|
||||
|
||||
interface SDKDemoSlideProps {
|
||||
lang: Language
|
||||
}
|
||||
|
||||
const SCREENSHOTS = [
|
||||
{ file: '01-dashboard.png', de: 'SDK Dashboard', en: 'SDK Dashboard', category: 'overview' },
|
||||
{ file: '21-sdk-flow.png', de: 'SDK Flow — 36 Steps', en: 'SDK Flow — 36 Steps', category: 'overview' },
|
||||
{ file: '02-company-profile.png', de: 'Unternehmensprofil', en: 'Company Profile', category: 'setup' },
|
||||
{ file: '03-compliance-scope.png', de: 'Compliance-Scope', en: 'Compliance Scope', category: 'setup' },
|
||||
{ file: '04-vvt.png', de: 'Verarbeitungsverzeichnis (Art. 30)', en: 'Processing Register (Art. 30)', category: 'docs' },
|
||||
{ file: '05-tom.png', de: 'TOM — Maßnahmen (Art. 32)', en: 'TOM — Measures (Art. 32)', category: 'docs' },
|
||||
{ file: '06-dsfa.png', de: 'Datenschutz-Folgenabschätzung', en: 'Data Protection Impact Assessment', category: 'docs' },
|
||||
{ file: '07-risks.png', de: 'Risikomatrix', en: 'Risk Matrix', category: 'analysis' },
|
||||
{ file: '08-obligations.png', de: 'Pflichtenübersicht', en: 'Obligations Overview', category: 'docs' },
|
||||
{ file: '09-loeschfristen.png', de: 'Löschfristen', en: 'Retention Policies', category: 'docs' },
|
||||
{ file: '10-controls.png', de: 'Controls', en: 'Controls', category: 'analysis' },
|
||||
{ file: '11-ai-act.png', de: 'AI Act Compliance', en: 'AI Act Compliance', category: 'analysis' },
|
||||
{ file: '12-requirements.png', de: 'Anforderungen', en: 'Requirements', category: 'analysis' },
|
||||
{ file: '13-evidence.png', de: 'Nachweise', en: 'Evidence', category: 'analysis' },
|
||||
{ file: '14-audit-report.png', de: 'Audit-Report', en: 'Audit Report', category: 'analysis' },
|
||||
{ file: '15-document-generator.png', de: 'Dokumenten-Generator', en: 'Document Generator', category: 'docs' },
|
||||
{ file: '16-einwilligungen.png', de: 'Einwilligungsmanagement', en: 'Consent Management', category: 'legal' },
|
||||
{ file: '22-iace.png', de: 'CE-Compliance (IACE)', en: 'CE Compliance (IACE)', category: 'analysis' },
|
||||
{ file: '20-rag.png', de: 'Legal RAG — 2.274 Rechtstexte', en: 'Legal RAG — 2,274 Legal Texts', category: 'ai' },
|
||||
{ file: '19-training.png', de: 'Compliance-Schulungen', en: 'Compliance Training', category: 'ops' },
|
||||
{ file: '23-incidents.png', de: 'Incident Response', en: 'Incident Response', category: 'ops' },
|
||||
{ file: '24-reporting.png', de: 'Reporting', en: 'Reporting', category: 'ops' },
|
||||
]
|
||||
|
||||
export default function SDKDemoSlide({ lang }: SDKDemoSlideProps) {
|
||||
const de = lang === 'de'
|
||||
const [current, setCurrent] = useState(0)
|
||||
const [fullscreen, setFullscreen] = useState(false)
|
||||
const [autoPlay, setAutoPlay] = useState(true)
|
||||
|
||||
const next = useCallback(() => {
|
||||
setCurrent(i => (i + 1) % SCREENSHOTS.length)
|
||||
}, [])
|
||||
|
||||
const prev = useCallback(() => {
|
||||
setCurrent(i => (i - 1 + SCREENSHOTS.length) % SCREENSHOTS.length)
|
||||
}, [])
|
||||
|
||||
// Auto-advance every 3s when not in fullscreen
|
||||
useEffect(() => {
|
||||
if (!autoPlay || fullscreen) return
|
||||
const timer = setInterval(next, 3000)
|
||||
return () => clearInterval(timer)
|
||||
}, [autoPlay, fullscreen, next])
|
||||
|
||||
const shot = SCREENSHOTS[current]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FadeInView className="text-center mb-6">
|
||||
<p className="text-xs font-mono text-indigo-400/60 uppercase tracking-widest mb-2">
|
||||
{de ? 'Anhang' : 'Appendix'}
|
||||
</p>
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-2">
|
||||
<GradientText>{de ? 'SDK Live-Demo' : 'SDK Live Demo'}</GradientText>
|
||||
</h2>
|
||||
<p className="text-base text-white/50 max-w-2xl mx-auto">
|
||||
{de
|
||||
? 'Echte Screenshots aus dem Compliance SDK — Kundenprojekt: Müller Maschinenbau GmbH'
|
||||
: 'Real screenshots from the Compliance SDK — Customer project: Müller Maschinenbau GmbH'}
|
||||
</p>
|
||||
</FadeInView>
|
||||
|
||||
<FadeInView delay={0.15}>
|
||||
<div className="max-w-5xl mx-auto">
|
||||
{/* Main screenshot viewer */}
|
||||
<div className="relative group">
|
||||
<div className="relative rounded-xl overflow-hidden border border-white/10 bg-black/30 shadow-2xl shadow-indigo-500/10">
|
||||
{/* Browser chrome mockup */}
|
||||
<div className="flex items-center gap-2 px-4 py-2 bg-white/[0.04] border-b border-white/10">
|
||||
<div className="flex gap-1.5">
|
||||
<div className="w-2.5 h-2.5 rounded-full bg-red-500/60" />
|
||||
<div className="w-2.5 h-2.5 rounded-full bg-yellow-500/60" />
|
||||
<div className="w-2.5 h-2.5 rounded-full bg-green-500/60" />
|
||||
</div>
|
||||
<div className="flex-1 ml-3">
|
||||
<div className="bg-white/[0.06] rounded-md px-3 py-1 text-xs text-white/30 font-mono max-w-md">
|
||||
admin.breakpilot.ai/sdk/{shot.file.replace(/^\d+-/, '').replace('.png', '')}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setFullscreen(true)}
|
||||
className="text-white/30 hover:text-white/60 transition"
|
||||
>
|
||||
<Maximize2 className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Screenshot */}
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.div
|
||||
key={current}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
>
|
||||
<Image
|
||||
src={`/screenshots/${shot.file}`}
|
||||
alt={de ? shot.de : shot.en}
|
||||
width={1920}
|
||||
height={1080}
|
||||
className="w-full h-auto"
|
||||
priority={current < 3}
|
||||
/>
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
{/* Navigation arrows */}
|
||||
<button
|
||||
onClick={() => { prev(); setAutoPlay(false) }}
|
||||
className="absolute left-3 top-1/2 -translate-y-1/2 w-10 h-10 rounded-full bg-black/60 border border-white/10 flex items-center justify-center text-white/60 hover:text-white hover:bg-black/80 transition opacity-0 group-hover:opacity-100"
|
||||
>
|
||||
<ChevronLeft className="w-5 h-5" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => { next(); setAutoPlay(false) }}
|
||||
className="absolute right-3 top-1/2 -translate-y-1/2 w-10 h-10 rounded-full bg-black/60 border border-white/10 flex items-center justify-center text-white/60 hover:text-white hover:bg-black/80 transition opacity-0 group-hover:opacity-100"
|
||||
>
|
||||
<ChevronRight className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Caption + Progress */}
|
||||
<div className="flex items-center justify-between mt-4">
|
||||
<div>
|
||||
<p className="text-white font-medium">{de ? shot.de : shot.en}</p>
|
||||
<p className="text-xs text-white/30 font-mono">{current + 1} / {SCREENSHOTS.length}</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setAutoPlay(!autoPlay)}
|
||||
className="text-xs text-white/40 hover:text-white/60 transition font-mono"
|
||||
>
|
||||
{autoPlay ? (de ? '⏸ Pause' : '⏸ Pause') : (de ? '▶ Auto' : '▶ Auto')}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Thumbnail strip */}
|
||||
<div className="flex gap-1.5 mt-3 overflow-x-auto pb-2 scrollbar-thin">
|
||||
{SCREENSHOTS.map((s, idx) => (
|
||||
<button
|
||||
key={idx}
|
||||
onClick={() => { setCurrent(idx); setAutoPlay(false) }}
|
||||
className={`shrink-0 w-16 h-9 rounded overflow-hidden border transition ${
|
||||
idx === current
|
||||
? 'border-indigo-500 ring-1 ring-indigo-500/50'
|
||||
: 'border-white/10 opacity-50 hover:opacity-80'
|
||||
}`}
|
||||
>
|
||||
<Image
|
||||
src={`/screenshots/${s.file}`}
|
||||
alt=""
|
||||
width={64}
|
||||
height={36}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
{/* Fullscreen overlay */}
|
||||
<AnimatePresence>
|
||||
{fullscreen && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
className="fixed inset-0 z-50 bg-black/95 flex items-center justify-center cursor-pointer"
|
||||
onClick={() => setFullscreen(false)}
|
||||
>
|
||||
<Image
|
||||
src={`/screenshots/${shot.file}`}
|
||||
alt={de ? shot.de : shot.en}
|
||||
width={1920}
|
||||
height={1080}
|
||||
className="max-w-[95vw] max-h-[90vh] object-contain"
|
||||
/>
|
||||
<p className="absolute bottom-6 text-white/50 text-sm">
|
||||
{de ? shot.de : shot.en} — {de ? 'Klicken zum Schließen' : 'Click to close'}
|
||||
</p>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -28,6 +28,7 @@ const translations = {
|
||||
'Anhang: Regulatorik',
|
||||
'Anhang: Engineering',
|
||||
'Anhang: KI-Pipeline',
|
||||
'Anhang: SDK Demo',
|
||||
],
|
||||
cover: {
|
||||
tagline: 'Compliance & Code-Security für den Maschinenbau',
|
||||
@@ -251,6 +252,7 @@ const translations = {
|
||||
'Appendix: Regulatory',
|
||||
'Appendix: Engineering',
|
||||
'Appendix: AI Pipeline',
|
||||
'Appendix: SDK Demo',
|
||||
],
|
||||
cover: {
|
||||
tagline: 'Compliance & Code Security for Machine Manufacturers',
|
||||
|
||||
@@ -478,6 +478,24 @@ export const PRESENTER_SCRIPT: SlideScript[] = [
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// 20 — annex-sdk-demo (45s)
|
||||
{
|
||||
slideId: 'annex-sdk-demo',
|
||||
duration: 45,
|
||||
paragraphs: [
|
||||
{
|
||||
text_de: 'Zum Abschluss: Echte Screenshots aus unserem Compliance SDK. Sie sehen hier das Projekt der Müller Maschinenbau GmbH — ein typischer mittelständischer Maschinenbauer mit KI-Projekten.',
|
||||
text_en: 'To conclude: Real screenshots from our Compliance SDK. You can see the project of Müller Maschinenbau GmbH — a typical mid-sized machine builder with AI projects.',
|
||||
pause_after: 2500,
|
||||
},
|
||||
{
|
||||
text_de: 'Von der Risikomatrix über das Verarbeitungsverzeichnis bis zum Dokumenten-Generator — alle 65 Module arbeiten zusammen. Das ist keine Mockup-Präsentation, sondern eine produktive Plattform.',
|
||||
text_en: 'From the risk matrix to the processing register to the document generator — all 65 modules work together. This is not a mockup presentation, but a productive platform.',
|
||||
pause_after: 2000,
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
export function getScriptForSlide(slideId: string): SlideScript | undefined {
|
||||
|
||||
@@ -21,6 +21,7 @@ export const SLIDE_ORDER: SlideId[] = [
|
||||
'annex-regulatory',
|
||||
'annex-engineering',
|
||||
'annex-aipipeline',
|
||||
'annex-sdk-demo',
|
||||
]
|
||||
|
||||
export const TOTAL_SLIDES = SLIDE_ORDER.length
|
||||
|
||||
@@ -221,3 +221,4 @@ export type SlideId =
|
||||
| 'annex-regulatory'
|
||||
| 'annex-engineering'
|
||||
| 'annex-aipipeline'
|
||||
| 'annex-sdk-demo'
|
||||
|
||||
BIN
pitch-deck/public/screenshots/01-dashboard.png
Normal file
|
After Width: | Height: | Size: 488 KiB |
BIN
pitch-deck/public/screenshots/02-company-profile.png
Normal file
|
After Width: | Height: | Size: 393 KiB |
BIN
pitch-deck/public/screenshots/03-compliance-scope.png
Normal file
|
After Width: | Height: | Size: 449 KiB |
BIN
pitch-deck/public/screenshots/04-vvt.png
Normal file
|
After Width: | Height: | Size: 544 KiB |
BIN
pitch-deck/public/screenshots/05-tom.png
Normal file
|
After Width: | Height: | Size: 460 KiB |
BIN
pitch-deck/public/screenshots/06-dsfa.png
Normal file
|
After Width: | Height: | Size: 394 KiB |
BIN
pitch-deck/public/screenshots/07-risks.png
Normal file
|
After Width: | Height: | Size: 370 KiB |
BIN
pitch-deck/public/screenshots/08-obligations.png
Normal file
|
After Width: | Height: | Size: 470 KiB |
BIN
pitch-deck/public/screenshots/09-loeschfristen.png
Normal file
|
After Width: | Height: | Size: 470 KiB |
BIN
pitch-deck/public/screenshots/10-controls.png
Normal file
|
After Width: | Height: | Size: 412 KiB |
BIN
pitch-deck/public/screenshots/11-ai-act.png
Normal file
|
After Width: | Height: | Size: 406 KiB |
BIN
pitch-deck/public/screenshots/12-requirements.png
Normal file
|
After Width: | Height: | Size: 418 KiB |
BIN
pitch-deck/public/screenshots/13-evidence.png
Normal file
|
After Width: | Height: | Size: 415 KiB |
BIN
pitch-deck/public/screenshots/14-audit-report.png
Normal file
|
After Width: | Height: | Size: 374 KiB |
BIN
pitch-deck/public/screenshots/15-document-generator.png
Normal file
|
After Width: | Height: | Size: 470 KiB |
BIN
pitch-deck/public/screenshots/16-einwilligungen.png
Normal file
|
After Width: | Height: | Size: 528 KiB |
BIN
pitch-deck/public/screenshots/18-security-backlog.png
Normal file
|
After Width: | Height: | Size: 300 KiB |
BIN
pitch-deck/public/screenshots/19-training.png
Normal file
|
After Width: | Height: | Size: 380 KiB |
BIN
pitch-deck/public/screenshots/20-rag.png
Normal file
|
After Width: | Height: | Size: 358 KiB |
BIN
pitch-deck/public/screenshots/21-sdk-flow.png
Normal file
|
After Width: | Height: | Size: 634 KiB |
BIN
pitch-deck/public/screenshots/22-iace.png
Normal file
|
After Width: | Height: | Size: 375 KiB |
BIN
pitch-deck/public/screenshots/23-incidents.png
Normal file
|
After Width: | Height: | Size: 484 KiB |
BIN
pitch-deck/public/screenshots/24-reporting.png
Normal file
|
After Width: | Height: | Size: 331 KiB |
613
scripts/seed-demo-and-screenshot.py
Normal file
@@ -0,0 +1,613 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Seed demo data for "Müller Maschinenbau GmbH" and take SDK screenshots.
|
||||
|
||||
Usage:
|
||||
python3 scripts/seed-demo-and-screenshot.py
|
||||
|
||||
Requires: pip3 install requests playwright
|
||||
python3 -m playwright install chromium
|
||||
"""
|
||||
|
||||
import json
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
import urllib3
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import requests
|
||||
from playwright.sync_api import sync_playwright
|
||||
|
||||
# Suppress SSL warnings for self-signed certs
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Configuration
|
||||
# ---------------------------------------------------------------------------
|
||||
BACKEND = "https://macmini:8002"
|
||||
FRONTEND = "https://macmini:3007"
|
||||
TENANT_ID = "9282a473-5c95-4b3a-bf78-0ecc0ec71d3e"
|
||||
SCREENSHOT_DIR = os.path.join(os.path.dirname(__file__),
|
||||
"..", "pitch-deck", "public", "screenshots")
|
||||
os.makedirs(SCREENSHOT_DIR, exist_ok=True)
|
||||
|
||||
HEADERS = {
|
||||
"Content-Type": "application/json",
|
||||
"X-Tenant-ID": TENANT_ID,
|
||||
}
|
||||
|
||||
PROJECT_ID = None # filled after creation
|
||||
|
||||
|
||||
def api(method, path, body=None, params=None):
|
||||
"""Call backend API."""
|
||||
url = f"{BACKEND}{path}"
|
||||
p = params or {}
|
||||
if PROJECT_ID:
|
||||
p["project_id"] = PROJECT_ID
|
||||
p["tenant_id"] = TENANT_ID
|
||||
r = requests.request(method, url, headers=HEADERS, json=body,
|
||||
params=p, verify=False, timeout=30)
|
||||
if r.status_code >= 400:
|
||||
print(f" !! {method} {path} → {r.status_code}: {r.text[:300]}")
|
||||
return r
|
||||
|
||||
|
||||
# =========================================================================
|
||||
# PHASE 1: Seed Data
|
||||
# =========================================================================
|
||||
|
||||
def create_project():
|
||||
global PROJECT_ID
|
||||
print("\n=== 1. Creating project ===")
|
||||
r = api("POST", "/api/compliance/v1/projects", {
|
||||
"name": "Müller Maschinenbau GmbH — KI-Compliance",
|
||||
"description": "Vollständiges Compliance-Projekt für einen mittelständischen Maschinenbauer mit KI-gestützter Qualitätskontrolle, Predictive Maintenance und autonomen Robotersystemen.",
|
||||
"customer_type": "new",
|
||||
})
|
||||
if r.status_code in (200, 201):
|
||||
data = r.json()
|
||||
PROJECT_ID = data.get("id") or data.get("project_id")
|
||||
print(f" ✓ Project created: {PROJECT_ID}")
|
||||
else:
|
||||
print(" Trying to find existing project...")
|
||||
r2 = api("GET", "/api/compliance/v1/projects")
|
||||
if r2.ok:
|
||||
projects = r2.json().get("projects", r2.json() if isinstance(r2.json(), list) else [])
|
||||
for p in projects:
|
||||
if "Müller" in p.get("name", ""):
|
||||
PROJECT_ID = p["id"]
|
||||
print(f" ✓ Using existing project: {PROJECT_ID}")
|
||||
return
|
||||
print(" !! Could not create or find project")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def create_company_profile():
|
||||
print("\n=== 2. Company Profile ===")
|
||||
profile = {
|
||||
"company_name": "Müller Maschinenbau GmbH",
|
||||
"legal_form": "GmbH",
|
||||
"industry": ["Maschinenbau", "Automatisierung", "KI/Machine Learning"],
|
||||
"founded_year": 2008,
|
||||
"business_model": "B2B",
|
||||
"offerings": ["hardware", "software_saas"],
|
||||
"offering_urls": {
|
||||
"website": "https://mueller-maschinenbau.de",
|
||||
"support": "https://support.mueller-maschinenbau.de"
|
||||
},
|
||||
"company_size": "medium",
|
||||
"employee_count": "50-249",
|
||||
"annual_revenue": "10-50 Mio",
|
||||
"headquarters_country": "DE",
|
||||
"headquarters_street": "Industriestraße 42",
|
||||
"headquarters_zip": "70565",
|
||||
"headquarters_city": "Stuttgart",
|
||||
"headquarters_state": "Baden-Württemberg",
|
||||
"has_international_locations": True,
|
||||
"international_countries": ["AT", "CH", "CZ"],
|
||||
"target_markets": ["DE", "AT", "CH", "EU"],
|
||||
"primary_jurisdiction": "DE",
|
||||
"is_data_controller": True,
|
||||
"is_data_processor": True,
|
||||
"uses_ai": True,
|
||||
"ai_use_cases": [
|
||||
"Visuelle Qualitätskontrolle (Kamera + CNN)",
|
||||
"Predictive Maintenance (Vibrationssensoren + LSTM)",
|
||||
"Autonome Robotersteuerung (Reinforcement Learning)",
|
||||
"Prozessoptimierung (Bayesian Optimization)"
|
||||
],
|
||||
"dpo_name": "Dr. Katharina Weber",
|
||||
"dpo_email": "datenschutz@mueller-maschinenbau.de",
|
||||
"legal_contact_name": "Thomas Hartmann",
|
||||
"legal_contact_email": "recht@mueller-maschinenbau.de",
|
||||
"subject_to_nis2": True,
|
||||
"subject_to_ai_act": True,
|
||||
"subject_to_iso27001": True,
|
||||
"supervisory_authority": "Landesbeauftragte für Datenschutz und Informationsfreiheit Baden-Württemberg",
|
||||
"review_cycle_months": 12,
|
||||
"machine_builder": {
|
||||
"product_types": ["robot_cell", "production_line", "special_machine", "test_stand"],
|
||||
"product_description": "CNC-Bearbeitungszentren, Roboter-Schweißzellen und automatisierte Montagelinien mit integrierter KI-gestützter Bildverarbeitung für Qualitätskontrolle in der Automobilindustrie.",
|
||||
"product_pride": "Höchste Präzision bei 99,97% Erkennungsrate in der visuellen Qualitätskontrolle — schneller und genauer als manuelle Inspektion.",
|
||||
"contains_software": True,
|
||||
"contains_firmware": True,
|
||||
"contains_ai": True,
|
||||
"ai_integration_type": ["vision", "predictive_maintenance", "quality_control", "robot_control", "process_optimization"],
|
||||
"has_safety_function": True,
|
||||
"safety_function_description": "SIL-2 zertifizierter Notfall-Stopp, Laser-Scanner für Arbeitsraumüberwachung, Lichtvorhänge an Roboterzellen, kraftbegrenzte Cobots nach ISO/TS 15066",
|
||||
"autonomous_behavior": True,
|
||||
"human_oversight_level": "partial",
|
||||
"is_networked": True,
|
||||
"has_remote_access": True,
|
||||
"has_ota_updates": True,
|
||||
"update_mechanism": "Signierte OTA-Updates über VPN-Tunnel, Rollback-fähig, Dual-Partition-Schema",
|
||||
"export_markets": ["DE", "AT", "CH", "FR", "NL", "CZ", "PL"],
|
||||
"critical_sector_clients": True,
|
||||
"critical_sectors": ["automotive", "energy", "pharma"],
|
||||
"oem_clients": True,
|
||||
"ce_marking_required": True,
|
||||
"existing_ce_process": True,
|
||||
"has_risk_assessment": True,
|
||||
},
|
||||
"repos": [
|
||||
{"url": "https://git.mueller-maschinenbau.de/firmware/cnc-controller", "name": "CNC Controller Firmware"},
|
||||
{"url": "https://git.mueller-maschinenbau.de/ai/vision-qc", "name": "Vision Quality Control"},
|
||||
{"url": "https://git.mueller-maschinenbau.de/cloud/customer-portal", "name": "Kundenportal"},
|
||||
],
|
||||
"processing_systems": [
|
||||
{"name": "ERP (SAP S/4HANA)", "type": "erp", "hosting": "on-premise"},
|
||||
{"name": "MES (MPDV Hydra X)", "type": "mes", "hosting": "on-premise"},
|
||||
{"name": "Kundenportal", "type": "web_app", "hosting": "cloud_eu"},
|
||||
{"name": "Predictive Maintenance Platform", "type": "ai_platform", "hosting": "cloud_eu"},
|
||||
],
|
||||
"ai_systems": [
|
||||
{"name": "QualityVision AI", "purpose": "Visuelle Fehlererkennung", "risk_level": "high", "model_type": "CNN (ResNet-50)"},
|
||||
{"name": "PredMaint Engine", "purpose": "Predictive Maintenance", "risk_level": "limited", "model_type": "LSTM + Anomaly Detection"},
|
||||
{"name": "RoboControl AI", "purpose": "Autonome Robotersteuerung", "risk_level": "high", "model_type": "Reinforcement Learning (PPO)"},
|
||||
],
|
||||
"technical_contacts": [
|
||||
{"name": "Stefan Braun", "role": "CTO", "email": "braun@mueller-maschinenbau.de"},
|
||||
{"name": "Lisa Chen", "role": "Head of AI", "email": "chen@mueller-maschinenbau.de"},
|
||||
{"name": "Markus Hoffmann", "role": "CISO", "email": "hoffmann@mueller-maschinenbau.de"},
|
||||
],
|
||||
"is_complete": True,
|
||||
"project_id": PROJECT_ID,
|
||||
}
|
||||
r = api("POST", "/api/v1/company-profile", profile)
|
||||
if r.status_code in (200, 201):
|
||||
print(" ✓ Company profile created")
|
||||
else:
|
||||
# Try PATCH
|
||||
r2 = api("PATCH", "/api/v1/company-profile", profile)
|
||||
print(f" → PATCH: {r2.status_code}")
|
||||
|
||||
|
||||
def create_vvt():
|
||||
print("\n=== 3. VVT (Verarbeitungsverzeichnis) ===")
|
||||
|
||||
# Organization header
|
||||
api("PUT", "/api/compliance/vvt/organization", {
|
||||
"organization_name": "Müller Maschinenbau GmbH",
|
||||
"industry": "Maschinenbau & Automatisierung",
|
||||
"locations": ["Stuttgart (Hauptsitz)", "Pilsen (CZ, Fertigung)", "Wien (AT, Vertrieb)"],
|
||||
"employee_count": 187,
|
||||
"dpo_name": "Dr. Katharina Weber",
|
||||
"dpo_contact": "datenschutz@mueller-maschinenbau.de",
|
||||
"vvt_version": "3.2",
|
||||
"review_interval": "annual",
|
||||
})
|
||||
print(" ✓ VVT Organization header")
|
||||
|
||||
activities = [
|
||||
{
|
||||
"vvt_id": "VVT-HR-001",
|
||||
"name": "Personalverwaltung und Lohnabrechnung",
|
||||
"description": "Verarbeitung von Mitarbeiterdaten für Personalverwaltung, Gehaltsabrechnung, Arbeitszeiterfassung und betriebliche Altersvorsorge.",
|
||||
"purposes": ["Vertragserfüllung Arbeitsvertrag", "Lohn- und Gehaltsabrechnung", "Arbeitszeiterfassung", "Betriebliche Altersvorsorge"],
|
||||
"legal_bases": ["Art. 6 Abs. 1b DSGVO — Vertragserfüllung", "Art. 6 Abs. 1c DSGVO — Rechtliche Verpflichtung (SGB, EStG)"],
|
||||
"data_subject_categories": ["Mitarbeiter", "Auszubildende", "Praktikanten"],
|
||||
"personal_data_categories": ["Stammdaten (Name, Adresse, Geburtsdatum)", "Bankverbindung", "Steuer-ID", "Sozialversicherungsnummer", "Arbeitszeiten", "Gehaltsdaten", "Krankmeldungen"],
|
||||
"recipient_categories": ["Lohnbüro (extern)", "Finanzamt", "Krankenkassen", "Berufsgenossenschaft"],
|
||||
"third_country_transfers": [],
|
||||
"retention_period": {"description": "10 Jahre nach Ende des Arbeitsverhältnisses (steuerrechtlich)", "duration_months": 120},
|
||||
"tom_description": "Verschlüsselte Übertragung, rollenbasierte Zugriffskontrolle, Audit-Logging",
|
||||
"business_function": "hr",
|
||||
"systems": ["SAP S/4HANA HR", "DATEV Lohnabrechnung"],
|
||||
"deployment_model": "on-premise",
|
||||
"protection_level": "HIGH",
|
||||
"dpia_required": False,
|
||||
"status": "APPROVED",
|
||||
"responsible": "Personalabteilung — Maria Schmidt",
|
||||
"owner": "Geschäftsführung",
|
||||
},
|
||||
{
|
||||
"vvt_id": "VVT-PROD-001",
|
||||
"name": "KI-gestützte visuelle Qualitätskontrolle",
|
||||
"description": "Einsatz von Computer Vision (CNN) zur automatisierten Fehlererkennung an CNC-gefertigten Bauteilen. Kamerabilder werden in Echtzeit analysiert. Keine personenbezogenen Daten in Kamerabildern, aber Zuordnung zu Maschinenbediener über Schichtplan.",
|
||||
"purposes": ["Qualitätssicherung nach ISO 9001", "Fehlerfrüherkennung", "Ausschussreduzierung"],
|
||||
"legal_bases": ["Art. 6 Abs. 1f DSGVO — Berechtigtes Interesse (Qualitätssicherung)"],
|
||||
"data_subject_categories": ["Maschinenbediener (indirekt über Schichtplan)"],
|
||||
"personal_data_categories": ["Bediener-ID (pseudonymisiert)", "Schichtzuordnung", "Fehlerquoten pro Schicht"],
|
||||
"recipient_categories": ["Qualitätsmanagement intern", "Produktionsleitung"],
|
||||
"third_country_transfers": [],
|
||||
"retention_period": {"description": "Bilddaten 30 Tage, Qualitätsstatistiken 5 Jahre", "duration_months": 60},
|
||||
"tom_description": "Pseudonymisierung der Bediener-ID, verschlüsselte Speicherung, Air-Gap zum Internet",
|
||||
"business_function": "production",
|
||||
"systems": ["QualityVision AI", "MES Hydra X", "Edge-Server Produktion"],
|
||||
"deployment_model": "on-premise",
|
||||
"protection_level": "HIGH",
|
||||
"dpia_required": True,
|
||||
"status": "APPROVED",
|
||||
"responsible": "Qualitätsmanagement — Dr. Frank Lehmann",
|
||||
"owner": "CTO Stefan Braun",
|
||||
},
|
||||
{
|
||||
"vvt_id": "VVT-PROD-002",
|
||||
"name": "Predictive Maintenance — Maschinensensorik",
|
||||
"description": "Erfassung und Analyse von Vibrations-, Temperatur- und Stromverbrauchsdaten der CNC-Maschinen zur vorausschauenden Wartung. KI-Modell (LSTM) erkennt Anomalien und prognostiziert Ausfälle.",
|
||||
"purposes": ["Vorausschauende Wartung", "Vermeidung ungeplanter Stillstände", "Optimierung Wartungszyklen"],
|
||||
"legal_bases": ["Art. 6 Abs. 1f DSGVO — Berechtigtes Interesse"],
|
||||
"data_subject_categories": ["Maschinenbediener (indirekt)", "Wartungstechniker"],
|
||||
"personal_data_categories": ["Techniker-ID bei Wartungseinsätzen", "Maschinenbelegungsplan"],
|
||||
"recipient_categories": ["Instandhaltung intern", "Maschinenhersteller (anonymisiert, für Garantie)"],
|
||||
"third_country_transfers": [],
|
||||
"retention_period": {"description": "Sensordaten 2 Jahre, Wartungshistorie 10 Jahre", "duration_months": 120},
|
||||
"tom_description": "Netzwerksegmentierung (OT/IT-Trennung), TLS 1.3, rollenbasierter Zugriff",
|
||||
"business_function": "production",
|
||||
"systems": ["PredMaint Engine", "Siemens MindSphere", "OPC-UA Gateway"],
|
||||
"deployment_model": "hybrid",
|
||||
"protection_level": "MEDIUM",
|
||||
"dpia_required": False,
|
||||
"status": "APPROVED",
|
||||
"responsible": "Instandhaltung — Michael Richter",
|
||||
"owner": "CTO Stefan Braun",
|
||||
},
|
||||
{
|
||||
"vvt_id": "VVT-SALES-001",
|
||||
"name": "Kundenportal und CRM",
|
||||
"description": "Verarbeitung von Kundendaten im B2B-Kundenportal: Angebote, Aufträge, Serviceanfragen, Maschinenstatus. CRM-Daten für Vertrieb und After-Sales.",
|
||||
"purposes": ["Vertragsanbahnung und -erfüllung", "After-Sales-Service", "Kundenkommunikation"],
|
||||
"legal_bases": ["Art. 6 Abs. 1b DSGVO — Vertragserfüllung", "Art. 6 Abs. 1f DSGVO — Berechtigtes Interesse (Vertrieb)"],
|
||||
"data_subject_categories": ["Ansprechpartner bei Geschäftskunden", "Einkäufer", "Servicetechniker der Kunden"],
|
||||
"personal_data_categories": ["Geschäftliche Kontaktdaten", "Bestellhistorie", "Support-Tickets", "Maschinenstandortdaten"],
|
||||
"recipient_categories": ["Vertrieb intern", "Service intern", "Cloud-Provider (EU)"],
|
||||
"third_country_transfers": [],
|
||||
"retention_period": {"description": "Während Geschäftsbeziehung + 6 Jahre (HGB)", "duration_months": 72},
|
||||
"tom_description": "TLS 1.3, MFA für Portal-Zugang, verschlüsselte Datenbank, regelmäßige Pentests",
|
||||
"business_function": "sales",
|
||||
"systems": ["Kundenportal (Next.js)", "Salesforce CRM", "Jira Service Management"],
|
||||
"deployment_model": "cloud",
|
||||
"protection_level": "MEDIUM",
|
||||
"dpia_required": False,
|
||||
"status": "APPROVED",
|
||||
"responsible": "Vertrieb — Andreas Müller",
|
||||
"owner": "Geschäftsführung",
|
||||
},
|
||||
{
|
||||
"vvt_id": "VVT-IT-001",
|
||||
"name": "IT-Infrastruktur und Netzwerküberwachung",
|
||||
"description": "Protokollierung von Netzwerkverkehr, Zugriffsprotokollen und Sicherheitsereignissen für IT-Sicherheit und Incident Response.",
|
||||
"purposes": ["IT-Sicherheit", "Angriffserkennung", "Forensik bei Sicherheitsvorfällen"],
|
||||
"legal_bases": ["Art. 6 Abs. 1f DSGVO — Berechtigtes Interesse (IT-Sicherheit)", "Art. 6 Abs. 1c DSGVO — NIS2-Pflicht"],
|
||||
"data_subject_categories": ["Mitarbeiter", "Externe Dienstleister mit Netzwerkzugang"],
|
||||
"personal_data_categories": ["IP-Adressen", "Login-Timestamps", "Zugriffsversuche", "E-Mail-Metadaten"],
|
||||
"recipient_categories": ["IT-Sicherheit intern", "SOC-Provider (EU)", "Behörden bei Sicherheitsvorfällen"],
|
||||
"third_country_transfers": [],
|
||||
"retention_period": {"description": "Logs 90 Tage, Sicherheitsvorfälle 3 Jahre", "duration_months": 36},
|
||||
"tom_description": "SIEM mit automatischer Anomalieerkennung, verschlüsselte Log-Speicherung, Zugriff nur IT-Security",
|
||||
"business_function": "it",
|
||||
"systems": ["Graylog SIEM", "Fortinet Firewall", "CrowdStrike EDR"],
|
||||
"deployment_model": "on-premise",
|
||||
"protection_level": "HIGH",
|
||||
"dpia_required": False,
|
||||
"status": "APPROVED",
|
||||
"responsible": "IT-Sicherheit — Markus Hoffmann",
|
||||
"owner": "CTO Stefan Braun",
|
||||
},
|
||||
{
|
||||
"vvt_id": "VVT-ROBOT-001",
|
||||
"name": "Autonome Robotersteuerung (Reinforcement Learning)",
|
||||
"description": "KI-gesteuerte Schweißroboter nutzen Reinforcement Learning für adaptive Schweißparameter. Trainingsdaten enthalten keine personenbezogenen Daten, aber Betriebsdaten werden pro Schicht/Bediener aggregiert.",
|
||||
"purposes": ["Adaptive Schweißparameteroptimierung", "Qualitätsverbesserung", "Ausschussreduktion"],
|
||||
"legal_bases": ["Art. 6 Abs. 1f DSGVO — Berechtigtes Interesse"],
|
||||
"data_subject_categories": ["Schweißer/Bediener (indirekt über Schichtplan)"],
|
||||
"personal_data_categories": ["Bediener-ID (anonymisiert)", "Schichtleistungskennzahlen"],
|
||||
"recipient_categories": ["Produktionsleitung intern"],
|
||||
"third_country_transfers": [],
|
||||
"retention_period": {"description": "Modelltrainings-Logs 1 Jahr, Produktionsdaten 5 Jahre", "duration_months": 60},
|
||||
"tom_description": "Air-Gap Roboterzelle, SIL-2 Safety Controller, physische Zugangskontrollen",
|
||||
"business_function": "production",
|
||||
"systems": ["RoboControl AI", "KUKA KR QUANTEC", "Safety PLC (Pilz)"],
|
||||
"deployment_model": "on-premise",
|
||||
"protection_level": "HIGH",
|
||||
"dpia_required": True,
|
||||
"status": "DRAFT",
|
||||
"responsible": "Robotik — Dr. Jan Kessler",
|
||||
"owner": "Head of AI — Lisa Chen",
|
||||
},
|
||||
]
|
||||
|
||||
for act in activities:
|
||||
r = api("POST", "/api/compliance/vvt/activities", act)
|
||||
status = "✓" if r.status_code in (200, 201) else f"✗ {r.status_code}"
|
||||
print(f" {status} {act['vvt_id']} — {act['name'][:50]}")
|
||||
|
||||
|
||||
def create_tom_measures():
|
||||
print("\n=== 4. TOM Measures ===")
|
||||
|
||||
measures = [
|
||||
{"control_id": "TOM-ENC-001", "name": "Verschlüsselung in Transit (TLS 1.3)", "description": "Alle internen und externen Datenübertragungen nutzen TLS 1.3 mit HSTS. OPC-UA Verbindungen in der Produktion nutzen TLS mit Client-Zertifikaten.", "category": "encryption", "type": "technical", "applicability": "REQUIRED", "implementation_status": "IMPLEMENTED", "responsible_person": "Markus Hoffmann (CISO)", "responsible_department": "IT-Sicherheit", "priority": "CRITICAL", "complexity": "LOW", "review_frequency": "quarterly", "effectiveness_rating": "EFFECTIVE"},
|
||||
{"control_id": "TOM-ENC-002", "name": "Verschlüsselung at Rest (AES-256)", "description": "Alle Datenbanken und Backups sind mit AES-256 verschlüsselt. Schlüsselmanagement über HashiCorp Vault.", "category": "encryption", "type": "technical", "applicability": "REQUIRED", "implementation_status": "IMPLEMENTED", "responsible_person": "Stefan Braun (CTO)", "responsible_department": "IT", "priority": "CRITICAL", "complexity": "MEDIUM", "review_frequency": "annual", "effectiveness_rating": "EFFECTIVE"},
|
||||
{"control_id": "TOM-AC-001", "name": "Rollenbasierte Zugriffskontrolle (RBAC)", "description": "Alle Systeme nutzen RBAC mit Least-Privilege-Prinzip. MFA für alle Admin-Zugänge und externe Zugänge. Vierteljährliche Access Reviews.", "category": "access_control", "type": "technical", "applicability": "REQUIRED", "implementation_status": "IMPLEMENTED", "responsible_person": "Markus Hoffmann (CISO)", "responsible_department": "IT-Sicherheit", "priority": "CRITICAL", "complexity": "MEDIUM", "review_frequency": "quarterly", "effectiveness_rating": "EFFECTIVE"},
|
||||
{"control_id": "TOM-AC-002", "name": "Netzwerksegmentierung (OT/IT-Trennung)", "description": "Strikte Trennung zwischen IT-Netzwerk und OT-Netzwerk (Produktion). DMZ für Kundenportal. Firewall-Regeln nach Whitelist-Prinzip.", "category": "access_control", "type": "technical", "applicability": "REQUIRED", "implementation_status": "IMPLEMENTED", "responsible_person": "IT-Infrastruktur Team", "responsible_department": "IT", "priority": "CRITICAL", "complexity": "HIGH", "review_frequency": "quarterly", "effectiveness_rating": "EFFECTIVE"},
|
||||
{"control_id": "TOM-LOG-001", "name": "Zentrales Audit-Logging (SIEM)", "description": "Graylog SIEM erfasst alle sicherheitsrelevanten Ereignisse. Automatische Alerts bei Anomalien. Logs unveränderlich gespeichert.", "category": "logging", "type": "technical", "applicability": "REQUIRED", "implementation_status": "IMPLEMENTED", "responsible_person": "SOC Team", "responsible_department": "IT-Sicherheit", "priority": "HIGH", "complexity": "MEDIUM", "review_frequency": "monthly", "effectiveness_rating": "EFFECTIVE"},
|
||||
{"control_id": "TOM-BAK-001", "name": "Backup & Disaster Recovery", "description": "Tägliche inkrementelle Backups, wöchentliche Vollbackups. Geo-redundante Speicherung (Stuttgart + Frankfurt). RTO: 4h, RPO: 1h.", "category": "backup", "type": "technical", "applicability": "REQUIRED", "implementation_status": "IMPLEMENTED", "responsible_person": "IT-Betrieb", "responsible_department": "IT", "priority": "HIGH", "complexity": "MEDIUM", "review_frequency": "quarterly", "effectiveness_rating": "EFFECTIVE"},
|
||||
{"control_id": "TOM-PHY-001", "name": "Physische Zugangskontrollen", "description": "Zutrittskontrolle per RFID-Badge, Videoüberwachung an Eingängen, Serverraum mit biometrischer Zugangskontrolle, Besucherprotokoll.", "category": "physical", "type": "technical", "applicability": "REQUIRED", "implementation_status": "IMPLEMENTED", "responsible_person": "Facility Management", "responsible_department": "Verwaltung", "priority": "HIGH", "complexity": "LOW", "review_frequency": "annual", "effectiveness_rating": "EFFECTIVE"},
|
||||
{"control_id": "TOM-ORG-001", "name": "Datenschutz-Schulungen", "description": "Jährliche Pflichtschulung für alle Mitarbeiter. Zusätzliche Spezialschulungen für IT, HR und Produktion. Nachweispflicht dokumentiert.", "category": "organizational", "type": "organizational", "applicability": "REQUIRED", "implementation_status": "IMPLEMENTED", "responsible_person": "Dr. Katharina Weber (DSB)", "responsible_department": "Compliance", "priority": "HIGH", "complexity": "LOW", "review_frequency": "annual", "effectiveness_rating": "EFFECTIVE"},
|
||||
{"control_id": "TOM-ORG-002", "name": "Incident-Response-Plan", "description": "Dokumentierter Notfallplan für Datenschutzvorfälle. 72h-Meldefrist an Aufsichtsbehörde. Eskalationsmatrix. Regelmäßige Übungen.", "category": "organizational", "type": "organizational", "applicability": "REQUIRED", "implementation_status": "IMPLEMENTED", "responsible_person": "Markus Hoffmann (CISO)", "responsible_department": "IT-Sicherheit", "priority": "CRITICAL", "complexity": "MEDIUM", "review_frequency": "annual", "effectiveness_rating": "EFFECTIVE"},
|
||||
{"control_id": "TOM-AI-001", "name": "KI-Modell-Governance", "description": "Dokumentation aller KI-Modelle (Model Cards), regelmäßige Bias-Prüfung, Versionierung der Trainingsdaten, Human-in-the-Loop bei kritischen Entscheidungen.", "category": "ai_governance", "type": "technical", "applicability": "REQUIRED", "implementation_status": "PARTIAL", "responsible_person": "Lisa Chen (Head of AI)", "responsible_department": "KI-Abteilung", "priority": "HIGH", "complexity": "HIGH", "review_frequency": "quarterly", "effectiveness_rating": "PARTIALLY_EFFECTIVE"},
|
||||
{"control_id": "TOM-AI-002", "name": "KI-Transparenz und Erklärbarkeit", "description": "SHAP/LIME Erklärungen für QualityVision-Entscheidungen. Dashboard für Produktionsleiter zeigt Konfidenzwerte und Entscheidungsgründe.", "category": "ai_governance", "type": "technical", "applicability": "REQUIRED", "implementation_status": "PARTIAL", "responsible_person": "Lisa Chen (Head of AI)", "responsible_department": "KI-Abteilung", "priority": "HIGH", "complexity": "HIGH", "review_frequency": "quarterly", "effectiveness_rating": "PARTIALLY_EFFECTIVE"},
|
||||
{"control_id": "TOM-SDLC-001", "name": "Secure Development Lifecycle", "description": "SAST (SonarQube) + DAST (OWASP ZAP) in CI/CD Pipeline. Code Reviews, Dependency Scanning (Snyk), SBOM-Generierung für jedes Release.", "category": "sdlc", "type": "technical", "applicability": "REQUIRED", "implementation_status": "IMPLEMENTED", "responsible_person": "Stefan Braun (CTO)", "responsible_department": "Entwicklung", "priority": "HIGH", "complexity": "MEDIUM", "review_frequency": "monthly", "effectiveness_rating": "EFFECTIVE"},
|
||||
]
|
||||
|
||||
for m in measures:
|
||||
r = api("POST", "/api/compliance/tom/measures", m)
|
||||
status = "✓" if r.status_code in (200, 201) else f"✗ {r.status_code}"
|
||||
print(f" {status} {m['control_id']} — {m['name'][:50]}")
|
||||
|
||||
|
||||
def create_dsfas():
|
||||
print("\n=== 5. DSFAs ===")
|
||||
|
||||
dsfas = [
|
||||
{
|
||||
"title": "DSFA — KI-gestützte Qualitätskontrolle (QualityVision AI)",
|
||||
"description": "Datenschutz-Folgenabschätzung für den Einsatz von Computer Vision zur automatisierten Fehlererkennung an CNC-Bauteilen. Indirekte Mitarbeiterüberwachung durch Schichtzuordnung der Fehlerquoten.",
|
||||
"status": "approved",
|
||||
"risk_level": "high",
|
||||
"processing_activity": "Automatisierte Bildanalyse von Werkstücken mit Zuordnung zu Maschinenbediener über Schichtplan",
|
||||
"data_categories": ["Kamerabilder (keine Personen)", "Bediener-ID (pseudonymisiert)", "Fehlerquoten pro Schicht", "Maschinenparameter"],
|
||||
"recipients": ["Qualitätsmanagement", "Produktionsleitung", "KI-Team (Modelltraining)"],
|
||||
"measures": ["Pseudonymisierung", "Air-Gap zum Internet", "Zugriffsbeschränkung", "Audit-Logging", "Löschfristen"],
|
||||
"created_by": "Dr. Katharina Weber (DSB)",
|
||||
"processing_description": "CNN-basiertes Modell analysiert Kamerabilder von CNC-Bauteilen in Echtzeit. Fehlerhafte Teile werden automatisch aussortiert. Fehlerstatistiken werden pro Schicht aggregiert.",
|
||||
"processing_purpose": "Qualitätssicherung nach ISO 9001, Reduktion der Ausschussquote von 3,2% auf 0,8%",
|
||||
"legal_basis": "Art. 6 Abs. 1f DSGVO",
|
||||
"legal_basis_details": "Berechtigtes Interesse an Qualitätssicherung und wirtschaftlichem Betrieb. Mitarbeiterinteressen berücksichtigt durch Pseudonymisierung und Betriebsratsvereinbarung.",
|
||||
"necessity_assessment": "Manuelle Qualitätskontrolle erreicht nur 92% Erkennungsrate vs. 99,97% durch KI. Wirtschaftlich erforderlich für Automotive-Zulieferer (IATF 16949).",
|
||||
"proportionality_assessment": "Nur pseudonymisierte Bediener-IDs, keine Videoüberwachung von Personen, Bilddaten nach 30 Tagen gelöscht.",
|
||||
"data_minimization": "Kein Personenbezug in Kamerabildern. Schichtzuordnung nur für aggregierte Statistiken, nicht für individuelle Leistungsbewertung.",
|
||||
"involves_ai": True,
|
||||
"overall_risk_level": "high",
|
||||
"risk_score": 68,
|
||||
"dpo_consulted": True,
|
||||
"dpo_name": "Dr. Katharina Weber",
|
||||
"dpo_opinion": "Hohes Risiko durch indirekte Leistungsüberwachung, aber durch Pseudonymisierung und BV ausreichend mitigiert. Genehmigt mit Auflagen.",
|
||||
"dpo_approved": True,
|
||||
"data_subjects": ["Maschinenbediener", "Schichtleiter"],
|
||||
"affected_rights": ["Auskunft", "Widerspruch", "Einschränkung der Verarbeitung"],
|
||||
"risks": [
|
||||
{"id": "dsfa-r1", "description": "Re-Identifizierung über Schichtplan", "likelihood": 2, "impact": 3, "mitigation": "Minimale Datenpunkte, keine direkte Verknüpfung ohne Freigabe"},
|
||||
{"id": "dsfa-r2", "description": "Zweckentfremdung für Leistungsbewertung", "likelihood": 2, "impact": 4, "mitigation": "Betriebsvereinbarung, technische Zugriffsbeschränkung"},
|
||||
],
|
||||
},
|
||||
{
|
||||
"title": "DSFA — Predictive Maintenance Sensorplattform",
|
||||
"description": "Bewertung der Datenverarbeitung durch IoT-Sensoren an Produktionsmaschinen für vorausschauende Wartung.",
|
||||
"status": "approved",
|
||||
"risk_level": "medium",
|
||||
"processing_activity": "Erfassung von Vibrations-, Temperatur- und Stromdaten, KI-basierte Anomalieerkennung",
|
||||
"data_categories": ["Maschinensensordaten", "Wartungsprotokolle", "Techniker-IDs"],
|
||||
"measures": ["OT/IT-Trennung", "Verschlüsselung", "Zugriffskontrolle", "Datenminimierung"],
|
||||
"created_by": "Dr. Katharina Weber (DSB)",
|
||||
"processing_description": "IoT-Sensoren erfassen kontinuierlich Maschinenzustandsdaten. LSTM-Modell erkennt Anomalien und prognostiziert Wartungsbedarf.",
|
||||
"processing_purpose": "Vermeidung ungeplanter Stillstände, Optimierung der Wartungsintervalle, Reduktion der Wartungskosten um 35%",
|
||||
"legal_basis": "Art. 6 Abs. 1f DSGVO",
|
||||
"legal_basis_details": "Berechtigtes Interesse an effizientem Maschinenbetrieb. Personenbezug minimal (nur Techniker-IDs bei Wartungseinsätzen).",
|
||||
"necessity_assessment": "Ungeplante Stillstände kosten 15.000€/Stunde. Predictive Maintenance reduziert ungeplante Ausfälle um 73%.",
|
||||
"involves_ai": True,
|
||||
"overall_risk_level": "medium",
|
||||
"risk_score": 42,
|
||||
"dpo_consulted": True,
|
||||
"dpo_name": "Dr. Katharina Weber",
|
||||
"dpo_approved": True,
|
||||
"data_subjects": ["Wartungstechniker", "Maschinenbediener (indirekt)"],
|
||||
},
|
||||
{
|
||||
"title": "DSFA — Autonome Robotersteuerung (RoboControl AI)",
|
||||
"description": "Folgenabschätzung für Reinforcement-Learning-gesteuerte Schweißroboter mit Sicherheitsrelevanz (SIL-2).",
|
||||
"status": "in-review",
|
||||
"risk_level": "high",
|
||||
"processing_activity": "RL-Agent steuert Schweißparameter adaptiv, Betriebsdaten werden pro Schicht aggregiert",
|
||||
"data_categories": ["Schweißparameter", "Bediener-ID (anonymisiert)", "Schichtleistungsdaten", "Safety-Events"],
|
||||
"measures": ["SIL-2 Safety Controller", "Air-Gap", "Human-in-the-Loop", "Notfall-Stopp"],
|
||||
"created_by": "Dr. Katharina Weber (DSB)",
|
||||
"processing_description": "RL-Agent (PPO) optimiert Schweißparameter in Echtzeit basierend auf Materialdicke, Temperatur und Nahtqualität.",
|
||||
"processing_purpose": "Adaptive Qualitätsoptimierung, Reduktion von Nacharbeit um 45%",
|
||||
"legal_basis": "Art. 6 Abs. 1f DSGVO",
|
||||
"involves_ai": True,
|
||||
"overall_risk_level": "high",
|
||||
"risk_score": 78,
|
||||
"dpo_consulted": True,
|
||||
"dpo_name": "Dr. Katharina Weber",
|
||||
"dpo_approved": False,
|
||||
"dpo_opinion": "Noch offene Fragen zur Erklärbarkeit der RL-Entscheidungen. Empfehlung: XAI-Dashboard implementieren vor Genehmigung.",
|
||||
"data_subjects": ["Schweißer", "Schichtleiter", "Wartungstechniker"],
|
||||
},
|
||||
]
|
||||
|
||||
for d in dsfas:
|
||||
r = api("POST", "/api/compliance/dsfa", d)
|
||||
status = "✓" if r.status_code in (200, 201) else f"✗ {r.status_code}"
|
||||
print(f" {status} {d['title'][:60]}")
|
||||
|
||||
|
||||
def create_risks():
|
||||
print("\n=== 6. Risks ===")
|
||||
|
||||
risks = [
|
||||
{"risk_id": "RISK-AI-001", "title": "KI-Modell-Bias in Qualitätskontrolle", "description": "CNN-Modell könnte systematische Fehler bei bestimmten Materialien/Chargen aufweisen, was zu unerkannten Qualitätsproblemen führt.", "category": "ai_risk", "likelihood": "3", "impact": "4", "mitigating_controls": ["Regelmäßige Bias-Audits", "Diversifiziertes Trainingsdaten-Set", "Human-in-the-Loop bei grenzwertigen Fällen", "A/B-Tests mit manueller Kontrolle"], "owner": "Lisa Chen (Head of AI)", "treatment_plan": "Quartalsweise Bias-Audit, Erweiterung des Trainingsdatensatzes um Edge Cases, XAI-Dashboard"},
|
||||
{"risk_id": "RISK-AI-002", "title": "Sicherheitsversagen autonomer Roboter", "description": "RL-gesteuerter Schweißroboter könnte bei unvorhergesehenen Situationen unsichere Parameter wählen. Safety-Controller als Backup, aber Restrisiko.", "category": "safety", "likelihood": "2", "impact": "5", "mitigating_controls": ["SIL-2 Safety Controller", "Physische Schutzzäune", "Geschwindigkeitsbegrenzung", "Notfall-Stopp", "Simulation vor Deployment"], "owner": "Dr. Jan Kessler (Robotik)", "treatment_plan": "Erweiterte Simulation mit adversarial Szenarien, monatliche Safety-Reviews"},
|
||||
{"risk_id": "RISK-CYBER-001", "title": "Ransomware-Angriff auf Produktionsnetzwerk", "description": "Verschlüsselung von Produktionsdaten und MES-System könnte mehrtägigen Produktionsausfall verursachen. Schaden: ca. 500k€/Tag.", "category": "information_security", "likelihood": "3", "impact": "5", "mitigating_controls": ["Netzwerksegmentierung", "EDR (CrowdStrike)", "Offline-Backups", "Incident-Response-Plan", "Security Awareness Training"], "owner": "Markus Hoffmann (CISO)", "treatment_plan": "Air-Gap für kritische Backups, Red-Team-Übung Q3/2026, Cyber-Versicherung"},
|
||||
{"risk_id": "RISK-DSGVO-001", "title": "Datenpanne im Kundenportal", "description": "Unbefugter Zugriff auf Kundendaten (Kontakte, Bestellhistorie, Maschinenstandorte) durch Schwachstelle im Web-Portal.", "category": "privacy", "likelihood": "2", "impact": "4", "mitigating_controls": ["WAF", "Regelmäßige Pentests", "MFA", "Verschlüsselte DB", "Bug-Bounty-Programm"], "owner": "Stefan Braun (CTO)", "treatment_plan": "Quartalspentests, OWASP ZAP in CI/CD, Responsible Disclosure Programm"},
|
||||
{"risk_id": "RISK-COMP-001", "title": "Nicht-Konformität mit EU AI Act", "description": "QualityVision AI und RoboControl AI könnten als Hochrisiko-KI eingestuft werden. Fehlende Dokumentation oder Konformitätsbewertung.", "category": "compliance", "likelihood": "3", "impact": "4", "mitigating_controls": ["AI Act Compliance Assessment", "Model Cards", "Risikomanagementsystem", "Externe Beratung"], "owner": "Dr. Katharina Weber (DSB)", "treatment_plan": "BreakPilot ComplAI SDK für vollständige AI-Act-Dokumentation, externe Konformitätsprüfung bis Q2/2027"},
|
||||
{"risk_id": "RISK-SUPPLY-001", "title": "Supply-Chain-Angriff auf OTA-Updates", "description": "Kompromittierung des Firmware-Update-Mechanismus könnte manipulierten Code auf Kundenmaschinen ausliefern.", "category": "information_security", "likelihood": "2", "impact": "5", "mitigating_controls": ["Code Signing", "Secure Boot", "Dual-Partition", "SBOM", "Dependency Scanning"], "owner": "Stefan Braun (CTO)", "treatment_plan": "Hardware Security Module (HSM) für Signierung, CycloneDX SBOM für jedes Release"},
|
||||
]
|
||||
|
||||
for risk in risks:
|
||||
r = api("POST", "/api/compliance/risks", risk)
|
||||
status = "✓" if r.status_code in (200, 201) else f"✗ {r.status_code}"
|
||||
print(f" {status} {risk['risk_id']} — {risk['title'][:50]}")
|
||||
|
||||
|
||||
def create_obligations():
|
||||
print("\n=== 7. Obligations ===")
|
||||
|
||||
obligations = [
|
||||
{"title": "Verzeichnis der Verarbeitungstätigkeiten führen", "description": "Vollständiges VVT nach Art. 30 DSGVO für alle Verarbeitungstätigkeiten inkl. KI-Systeme.", "source": "DSGVO", "source_article": "Art. 30", "status": "completed", "priority": "critical", "responsible": "Dr. Katharina Weber (DSB)", "linked_systems": ["SAP HR", "Kundenportal", "QualityVision AI", "PredMaint Engine"]},
|
||||
{"title": "Datenschutz-Folgenabschätzung für KI-Systeme", "description": "DSFA für alle KI-Systeme mit Personenbezug: QualityVision, PredMaint, RoboControl.", "source": "DSGVO", "source_article": "Art. 35", "status": "in-progress", "priority": "critical", "responsible": "Dr. Katharina Weber (DSB)", "linked_systems": ["QualityVision AI", "PredMaint Engine", "RoboControl AI"]},
|
||||
{"title": "Technisch-Organisatorische Maßnahmen dokumentieren", "description": "TOM-Katalog nach Art. 32 DSGVO mit regelmäßiger Überprüfung und Anpassung.", "source": "DSGVO", "source_article": "Art. 32", "status": "completed", "priority": "high", "responsible": "Markus Hoffmann (CISO)"},
|
||||
{"title": "AI Act Hochrisiko-Konformitätsbewertung", "description": "Konformitätsbewertung für QualityVision AI und RoboControl AI als potenzielle Hochrisiko-KI-Systeme.", "source": "EU AI Act", "source_article": "Art. 6, Annex III", "status": "pending", "priority": "critical", "responsible": "Lisa Chen (Head of AI)", "deadline": "2027-08-01T00:00:00Z"},
|
||||
{"title": "NIS2 Risikomanagement implementieren", "description": "Cybersecurity-Risikomanagement nach NIS2 Richtlinie für wesentliche Einrichtungen.", "source": "NIS2", "source_article": "Art. 21", "status": "in-progress", "priority": "high", "responsible": "Markus Hoffmann (CISO)"},
|
||||
{"title": "CE-Konformitätserklärung mit KI-Komponenten", "description": "CE-Kennzeichnung unter Berücksichtigung der neuen Maschinenverordnung 2023/1230 für Maschinen mit KI-Sicherheitsfunktionen.", "source": "Maschinenverordnung", "source_article": "2023/1230", "status": "in-progress", "priority": "critical", "responsible": "Dr. Frank Lehmann (QM)"},
|
||||
{"title": "Meldepflicht bei Datenschutzvorfällen", "description": "Prozess für 72h-Meldung an Aufsichtsbehörde bei Datenschutzverletzungen.", "source": "DSGVO", "source_article": "Art. 33/34", "status": "completed", "priority": "critical", "responsible": "Dr. Katharina Weber (DSB)"},
|
||||
{"title": "Auftragsverarbeitungsverträge prüfen", "description": "AVV mit allen Dienstleistern (Cloud-Provider, SOC, Lohnbüro) prüfen und aktualisieren.", "source": "DSGVO", "source_article": "Art. 28", "status": "in-progress", "priority": "high", "responsible": "Thomas Hartmann (Rechtsabteilung)", "linked_systems": ["Salesforce", "AWS", "Graylog Cloud"]},
|
||||
{"title": "Löschkonzept implementieren", "description": "Technische Umsetzung der definierten Löschfristen für alle Datenkategorien.", "source": "DSGVO", "source_article": "Art. 17", "status": "in-progress", "priority": "high", "responsible": "Stefan Braun (CTO)"},
|
||||
{"title": "Betroffenenrechte-Prozess", "description": "Prozess für Auskunft, Berichtigung, Löschung, Datenportabilität innerhalb der gesetzlichen Fristen.", "source": "DSGVO", "source_article": "Art. 15-21", "status": "completed", "priority": "high", "responsible": "Dr. Katharina Weber (DSB)"},
|
||||
]
|
||||
|
||||
for o in obligations:
|
||||
r = api("POST", "/api/compliance/obligations", o)
|
||||
status = "✓" if r.status_code in (200, 201) else f"✗ {r.status_code}"
|
||||
print(f" {status} {o['title'][:55]}")
|
||||
|
||||
|
||||
def create_loeschfristen():
|
||||
print("\n=== 8. Löschfristen ===")
|
||||
|
||||
policies = [
|
||||
{"data_object_name": "Personalakten und Gehaltsabrechnungen", "description": "Mitarbeiterstammdaten, Gehaltsabrechnungen, Arbeitsverträge, Zeugnisse", "data_categories": ["Stammdaten", "Gehaltsdaten", "Steuer-ID", "SV-Nummer", "Arbeitsverträge"], "primary_purpose": "Personalverwaltung und gesetzliche Aufbewahrung", "deletion_trigger": "PURPOSE_END", "retention_driver": "LEGAL_REQUIREMENT", "retention_driver_detail": "§257 HGB (6 Jahre), §147 AO (10 Jahre), Steuerrecht", "retention_duration": 10, "retention_unit": "years", "status": "ACTIVE", "responsible_role": "Personalabteilung", "responsible_person": "Maria Schmidt", "deletion_method": "SECURE_DELETE", "deletion_method_detail": "Zertifizierte Löschung nach DIN 66399, Protokollierung", "storage_locations": ["SAP HR (on-premise)", "Papierarchiv Stuttgart"]},
|
||||
{"data_object_name": "Kamerabilder Qualitätskontrolle", "description": "Aufnahmen der QualityVision-Kameras von CNC-Werkstücken (keine Personenaufnahmen)", "data_categories": ["Werkstückbilder", "Fehlerklassifikation", "Maschinenparameter"], "primary_purpose": "Qualitätssicherung und KI-Modelltraining", "deletion_trigger": "RETENTION_PERIOD", "retention_driver": "BUSINESS_REQUIREMENT", "retention_driver_detail": "30 Tage Produktionsbilder, 6 Monate Trainingsextrakte", "retention_duration": 30, "retention_unit": "days", "status": "ACTIVE", "responsible_role": "KI-Team", "responsible_person": "Lisa Chen", "deletion_method": "AUTOMATED_DELETION", "deletion_method_detail": "Cronjob löscht Bilder älter 30 Tage, Trainingsextrakte nach 6 Monaten", "storage_locations": ["Edge-Server Produktion", "NAS Training-Data"]},
|
||||
{"data_object_name": "Sensordaten Predictive Maintenance", "description": "Vibrations-, Temperatur- und Stromverbrauchsdaten der CNC-Maschinen", "data_categories": ["Vibrationsmessungen", "Temperaturprofile", "Energieverbrauch", "Anomalie-Scores"], "primary_purpose": "Vorausschauende Wartung", "deletion_trigger": "RETENTION_PERIOD", "retention_driver": "BUSINESS_REQUIREMENT", "retention_driver_detail": "2 Jahre für Trendanalysen, Wartungshistorie 10 Jahre (Gewährleistung)", "retention_duration": 2, "retention_unit": "years", "status": "ACTIVE", "responsible_role": "Instandhaltung", "responsible_person": "Michael Richter", "deletion_method": "ANONYMIZATION_THEN_DELETION", "storage_locations": ["PredMaint Platform (EU-Cloud)", "Backup Stuttgart"]},
|
||||
{"data_object_name": "Kundendaten (B2B-Portal)", "description": "Geschäftskontakte, Bestellhistorie, Service-Tickets, Maschinenstandorte", "data_categories": ["Geschäftliche Kontaktdaten", "Bestellungen", "Support-Tickets", "Maschinenkonfigurationen"], "primary_purpose": "Vertragserfüllung und After-Sales", "deletion_trigger": "PURPOSE_END", "retention_driver": "LEGAL_REQUIREMENT", "retention_driver_detail": "§257 HGB (6 Jahre nach Ende der Geschäftsbeziehung)", "retention_duration": 6, "retention_unit": "years", "status": "ACTIVE", "responsible_role": "Vertrieb", "responsible_person": "Andreas Müller", "deletion_method": "SECURE_DELETE", "storage_locations": ["Kundenportal (EU-Cloud)", "Salesforce CRM"]},
|
||||
{"data_object_name": "IT-Security-Logs und Audit-Trails", "description": "Netzwerk-Logs, Zugriffsprotokolle, SIEM-Events, Firewall-Logs", "data_categories": ["IP-Adressen", "Login-Events", "Firewall-Logs", "SIEM-Alerts"], "primary_purpose": "IT-Sicherheit und Forensik", "deletion_trigger": "RETENTION_PERIOD", "retention_driver": "LEGAL_REQUIREMENT", "retention_driver_detail": "90 Tage Standard-Logs, 3 Jahre bei Sicherheitsvorfällen (NIS2)", "retention_duration": 90, "retention_unit": "days", "status": "ACTIVE", "responsible_role": "IT-Sicherheit", "responsible_person": "Markus Hoffmann", "deletion_method": "AUTOMATED_DELETION", "deletion_method_detail": "Automatische Rotation nach 90 Tagen, manuelle Aufbewahrung bei Incidents", "storage_locations": ["Graylog SIEM", "Backup (verschlüsselt)"]},
|
||||
{"data_object_name": "Bewerbungsunterlagen", "description": "Lebensläufe, Anschreiben, Zeugnisse von Stellenbewerbern", "data_categories": ["Lebenslauf", "Anschreiben", "Zeugnisse", "Kontaktdaten"], "primary_purpose": "Stellenbesetzung", "deletion_trigger": "PURPOSE_END", "retention_driver": "LEGAL_REQUIREMENT", "retention_driver_detail": "6 Monate nach Besetzung/Absage (AGG-Klagefrist)", "retention_duration": 6, "retention_unit": "months", "status": "ACTIVE", "responsible_role": "Personalabteilung", "responsible_person": "Maria Schmidt", "deletion_method": "SECURE_DELETE", "storage_locations": ["HR-System", "E-Mail-Archiv"]},
|
||||
]
|
||||
|
||||
for p in policies:
|
||||
r = api("POST", "/api/compliance/loeschfristen", p)
|
||||
status = "✓" if r.status_code in (200, 201) else f"✗ {r.status_code}"
|
||||
print(f" {status} {p['data_object_name'][:55]}")
|
||||
|
||||
|
||||
# =========================================================================
|
||||
# PHASE 2: Screenshots
|
||||
# =========================================================================
|
||||
|
||||
SCREENSHOT_PAGES = [
|
||||
# (filename, path_suffix, description, wait_ms)
|
||||
("01-dashboard", "/sdk", "SDK Dashboard / Projektübersicht", 3000),
|
||||
("02-company-profile", "/sdk/company-profile", "Firmenprofil", 2000),
|
||||
("03-compliance-scope", "/sdk/compliance-scope", "Compliance-Scope", 2000),
|
||||
("04-vvt", "/sdk/vvt", "Verarbeitungsverzeichnis", 2000),
|
||||
("05-tom", "/sdk/tom", "TOM — Technisch-Organisatorische Maßnahmen", 2000),
|
||||
("06-dsfa", "/sdk/dsfa", "Datenschutz-Folgenabschätzung", 2000),
|
||||
("07-risks", "/sdk/risks", "Risikobewertung", 2000),
|
||||
("08-obligations", "/sdk/obligations", "Pflichtenübersicht", 2000),
|
||||
("09-loeschfristen", "/sdk/loeschfristen", "Löschfristen", 2000),
|
||||
("10-controls", "/sdk/controls", "Controls", 2000),
|
||||
("11-ai-act", "/sdk/ai-act", "AI Act Compliance", 2000),
|
||||
("12-requirements", "/sdk/requirements", "Anforderungen", 2000),
|
||||
("13-evidence", "/sdk/evidence", "Nachweise", 2000),
|
||||
("14-audit-report", "/sdk/audit-report", "Audit-Report", 2000),
|
||||
("15-document-generator", "/sdk/document-generator", "Dokumenten-Generator", 2000),
|
||||
("16-einwilligungen", "/sdk/einwilligungen", "Einwilligungen", 2000),
|
||||
("17-vendor-compliance", "/sdk/vendor-compliance", "Auftragsverarbeitung", 2000),
|
||||
("18-security-backlog", "/sdk/security-backlog", "Security Backlog", 2000),
|
||||
("19-training", "/sdk/training", "Schulungen", 2000),
|
||||
("20-rag", "/sdk/rag", "Legal RAG", 2000),
|
||||
("21-sdk-flow", "/sdk/sdk-flow", "SDK Flow", 2000),
|
||||
("22-iace", "/sdk/iace", "IACE — CE-Compliance", 2000),
|
||||
("23-incidents", "/sdk/incidents", "Incident Response", 2000),
|
||||
("24-reporting", "/sdk/reporting", "Reporting", 2000),
|
||||
]
|
||||
|
||||
|
||||
def take_screenshots():
|
||||
print("\n\n=== PHASE 2: Taking Screenshots ===")
|
||||
print(f" Project ID: {PROJECT_ID}")
|
||||
print(f" Output dir: {SCREENSHOT_DIR}")
|
||||
|
||||
with sync_playwright() as p:
|
||||
browser = p.chromium.launch(
|
||||
headless=True,
|
||||
args=["--ignore-certificate-errors", "--no-sandbox"],
|
||||
)
|
||||
context = browser.new_context(
|
||||
viewport={"width": 1920, "height": 1080},
|
||||
device_scale_factor=2, # Retina quality
|
||||
ignore_https_errors=True,
|
||||
)
|
||||
page = context.new_page()
|
||||
|
||||
for filename, path, desc, wait_ms in SCREENSHOT_PAGES:
|
||||
url = f"{FRONTEND}{path}?project={PROJECT_ID}"
|
||||
print(f" 📸 {filename} — {desc}...")
|
||||
try:
|
||||
page.goto(url, wait_until="networkidle", timeout=30000)
|
||||
page.wait_for_timeout(wait_ms)
|
||||
|
||||
# Close any modals/toasts that might obscure the view
|
||||
try:
|
||||
page.keyboard.press("Escape")
|
||||
page.wait_for_timeout(300)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
filepath = os.path.join(SCREENSHOT_DIR, f"{filename}.png")
|
||||
page.screenshot(path=filepath, full_page=False)
|
||||
size_kb = os.path.getsize(filepath) / 1024
|
||||
print(f" ✓ {size_kb:.0f} KB")
|
||||
except Exception as e:
|
||||
print(f" ✗ Error: {e}")
|
||||
|
||||
browser.close()
|
||||
|
||||
print(f"\n Done! {len(SCREENSHOT_PAGES)} screenshots saved to {SCREENSHOT_DIR}")
|
||||
|
||||
|
||||
# =========================================================================
|
||||
# Main
|
||||
# =========================================================================
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("=" * 60)
|
||||
print("BreakPilot SDK Demo Data Seeder + Screenshot Tool")
|
||||
print("=" * 60)
|
||||
print(f"Backend: {BACKEND}")
|
||||
print(f"Frontend: {FRONTEND}")
|
||||
print(f"Tenant: {TENANT_ID}")
|
||||
|
||||
# Phase 1: Seed data
|
||||
create_project()
|
||||
create_company_profile()
|
||||
create_vvt()
|
||||
create_tom_measures()
|
||||
create_dsfas()
|
||||
create_risks()
|
||||
create_obligations()
|
||||
create_loeschfristen()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("PHASE 1 COMPLETE — All demo data seeded")
|
||||
print("=" * 60)
|
||||
|
||||
# Phase 2: Screenshots
|
||||
take_screenshots()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("ALL DONE!")
|
||||
print("=" * 60)
|
||||