Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Failing after 36s
CI / test-python-backend-compliance (push) Successful in 42s
CI / test-python-document-crawler (push) Successful in 27s
CI / test-python-dsms-gateway (push) Successful in 25s
- compliance-scope-engine: answerValue→value (Property existierte nicht, Crash bei Evaluierung) - company-profile: saveProfileDraft synct jetzt Redux-State (Daten bleiben bei Navigation) - Scope-Bloecke umbenannt: Kunden & Nutzer, Datenverarbeitung, Hosting & Verarbeitung, Website und Services - org_cert_target + data_volume als Hidden Scoring Questions (Duplikate entfernt) - ai_risk_assessment: boolean→single mit Ja/Nein/Noch nicht - 6 neue Abteilungs-Datenkategorien: IT, Recht, Produktion, Logistik, Einkauf, Facility Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
660 lines
26 KiB
TypeScript
660 lines
26 KiB
TypeScript
/**
|
|
* VVT Profiling — Generator-Fragebogen
|
|
*
|
|
* ~25 Fragen in 6 Schritten, die auf Basis der Antworten
|
|
* Baseline-Verarbeitungstaetigkeiten generieren.
|
|
*/
|
|
|
|
import { VVT_BASELINE_CATALOG, templateToActivity } from './vvt-baseline-catalog'
|
|
import { generateVVTId } from './vvt-types'
|
|
import type { VVTActivity, BusinessFunction } from './vvt-types'
|
|
|
|
// =============================================================================
|
|
// TYPES
|
|
// =============================================================================
|
|
|
|
export interface ProfilingQuestion {
|
|
id: string
|
|
step: number
|
|
question: string
|
|
type: 'single_choice' | 'multi_choice' | 'number' | 'text' | 'boolean'
|
|
options?: { value: string; label: string }[]
|
|
helpText?: string
|
|
triggersTemplates: string[] // Template-IDs that get activated when answered positively
|
|
}
|
|
|
|
export interface ProfilingStep {
|
|
step: number
|
|
title: string
|
|
description: string
|
|
}
|
|
|
|
export interface ProfilingAnswers {
|
|
[questionId: string]: string | string[] | number | boolean
|
|
}
|
|
|
|
export interface ProfilingResult {
|
|
answers: ProfilingAnswers
|
|
generatedActivities: VVTActivity[]
|
|
coverageScore: number
|
|
art30Abs5Exempt: boolean
|
|
}
|
|
|
|
// =============================================================================
|
|
// STEPS
|
|
// =============================================================================
|
|
|
|
export const PROFILING_STEPS: ProfilingStep[] = [
|
|
{ step: 1, title: 'Organisation', description: 'Grunddaten zu Ihrem Unternehmen' },
|
|
{ step: 2, title: 'Geschaeftsbereiche', description: 'Welche Bereiche sind aktiv?' },
|
|
{ step: 3, title: 'Systeme & Tools', description: 'Welche IT-Systeme nutzen Sie?' },
|
|
{ step: 4, title: 'Datenkategorien', description: 'Welche besonderen Daten verarbeiten Sie?' },
|
|
{ step: 5, title: 'Drittlandtransfers', description: 'Transfers ausserhalb der EU/EWR' },
|
|
{ step: 6, title: 'Besondere Verarbeitungen', description: 'KI, Scoring, Ueberwachung' },
|
|
]
|
|
|
|
// =============================================================================
|
|
// QUESTIONS
|
|
// =============================================================================
|
|
|
|
export const PROFILING_QUESTIONS: ProfilingQuestion[] = [
|
|
// === STEP 1: Organisation ===
|
|
{
|
|
id: 'org_industry',
|
|
step: 1,
|
|
question: 'In welcher Branche ist Ihr Unternehmen taetig?',
|
|
type: 'single_choice',
|
|
options: [
|
|
{ value: 'it_software', label: 'IT & Software' },
|
|
{ value: 'healthcare', label: 'Gesundheitswesen' },
|
|
{ value: 'education', label: 'Bildung & Erziehung' },
|
|
{ value: 'finance', label: 'Finanzdienstleistungen' },
|
|
{ value: 'retail', label: 'Handel & E-Commerce' },
|
|
{ value: 'manufacturing', label: 'Produktion & Industrie' },
|
|
{ value: 'consulting', label: 'Beratung & Dienstleistung' },
|
|
{ value: 'public', label: 'Oeffentlicher Sektor' },
|
|
{ value: 'other', label: 'Sonstige' },
|
|
],
|
|
triggersTemplates: [],
|
|
},
|
|
{
|
|
id: 'org_employees',
|
|
step: 1,
|
|
question: 'Wie viele Mitarbeiter hat Ihr Unternehmen?',
|
|
type: 'number',
|
|
helpText: 'Relevant fuer Art. 30 Abs. 5 DSGVO (Ausnahme < 250 Mitarbeiter)',
|
|
triggersTemplates: [],
|
|
},
|
|
{
|
|
id: 'org_locations',
|
|
step: 1,
|
|
question: 'An wie vielen Standorten ist Ihr Unternehmen taetig?',
|
|
type: 'single_choice',
|
|
options: [
|
|
{ value: '1', label: '1 Standort' },
|
|
{ value: '2-5', label: '2-5 Standorte' },
|
|
{ value: '6-20', label: '6-20 Standorte' },
|
|
{ value: '20+', label: 'Mehr als 20 Standorte' },
|
|
],
|
|
triggersTemplates: [],
|
|
},
|
|
{
|
|
id: 'org_b2b_b2c',
|
|
step: 1,
|
|
question: 'Welches Geschaeftsmodell betreiben Sie?',
|
|
type: 'single_choice',
|
|
options: [
|
|
{ value: 'b2b', label: 'B2B (Geschaeftskunden)' },
|
|
{ value: 'b2c', label: 'B2C (Endkunden)' },
|
|
{ value: 'both', label: 'Beides (B2B + B2C)' },
|
|
{ value: 'b2g', label: 'B2G (Oeffentlicher Sektor)' },
|
|
],
|
|
triggersTemplates: [],
|
|
},
|
|
|
|
// === STEP 2: Geschaeftsbereiche ===
|
|
{
|
|
id: 'dept_hr',
|
|
step: 2,
|
|
question: 'Haben Sie eine Personalabteilung / HR?',
|
|
type: 'boolean',
|
|
triggersTemplates: ['hr-mitarbeiterverwaltung', 'hr-gehaltsabrechnung', 'hr-zeiterfassung'],
|
|
},
|
|
{
|
|
id: 'dept_recruiting',
|
|
step: 2,
|
|
question: 'Betreiben Sie aktives Recruiting / Bewerbermanagement?',
|
|
type: 'boolean',
|
|
triggersTemplates: ['hr-bewerbermanagement'],
|
|
},
|
|
{
|
|
id: 'dept_finance',
|
|
step: 2,
|
|
question: 'Haben Sie eine Finanz-/Buchhaltungsabteilung?',
|
|
type: 'boolean',
|
|
triggersTemplates: ['finance-buchhaltung', 'finance-zahlungsverkehr'],
|
|
},
|
|
{
|
|
id: 'dept_sales',
|
|
step: 2,
|
|
question: 'Haben Sie einen Vertrieb / Kundenverwaltung?',
|
|
type: 'boolean',
|
|
triggersTemplates: ['sales-kundenverwaltung', 'sales-vertriebssteuerung'],
|
|
},
|
|
{
|
|
id: 'dept_marketing',
|
|
step: 2,
|
|
question: 'Betreiben Sie Marketing-Aktivitaeten?',
|
|
type: 'boolean',
|
|
triggersTemplates: ['marketing-social-media'],
|
|
},
|
|
{
|
|
id: 'dept_support',
|
|
step: 2,
|
|
question: 'Haben Sie einen Kundenservice / Support?',
|
|
type: 'boolean',
|
|
triggersTemplates: ['support-ticketsystem'],
|
|
},
|
|
|
|
// === STEP 3: Systeme & Tools ===
|
|
{
|
|
id: 'sys_crm',
|
|
step: 3,
|
|
question: 'Nutzen Sie ein CRM-System (z.B. Salesforce, HubSpot, Pipedrive)?',
|
|
type: 'boolean',
|
|
triggersTemplates: ['sales-kundenverwaltung'],
|
|
},
|
|
{
|
|
id: 'sys_website_analytics',
|
|
step: 3,
|
|
question: 'Nutzen Sie Website-Analytics (z.B. Matomo, Google Analytics)?',
|
|
type: 'boolean',
|
|
triggersTemplates: ['marketing-website-analytics'],
|
|
},
|
|
{
|
|
id: 'sys_newsletter',
|
|
step: 3,
|
|
question: 'Versenden Sie Newsletter (z.B. Mailchimp, CleverReach)?',
|
|
type: 'boolean',
|
|
triggersTemplates: ['marketing-newsletter'],
|
|
},
|
|
{
|
|
id: 'sys_video',
|
|
step: 3,
|
|
question: 'Nutzen Sie Videokonferenz-Tools (z.B. Zoom, Teams, Jitsi)?',
|
|
type: 'boolean',
|
|
triggersTemplates: ['other-videokonferenz'],
|
|
},
|
|
{
|
|
id: 'sys_erp',
|
|
step: 3,
|
|
question: 'Nutzen Sie ein ERP-System?',
|
|
type: 'boolean',
|
|
helpText: 'z.B. SAP, ERPNext, Microsoft Dynamics',
|
|
triggersTemplates: ['finance-buchhaltung'],
|
|
},
|
|
{
|
|
id: 'sys_visitor',
|
|
step: 3,
|
|
question: 'Haben Sie ein Besuchermanagement-System?',
|
|
type: 'boolean',
|
|
triggersTemplates: ['other-besuchermanagement'],
|
|
},
|
|
|
|
// === STEP 4: Datenkategorien ===
|
|
{
|
|
id: 'data_health',
|
|
step: 4,
|
|
question: 'Verarbeiten Sie Gesundheitsdaten (Art. 9 DSGVO)?',
|
|
type: 'boolean',
|
|
helpText: 'z.B. Krankmeldungen, Arbeitsmedizin, Gesundheitsversorgung',
|
|
triggersTemplates: [],
|
|
},
|
|
{
|
|
id: 'data_minors',
|
|
step: 4,
|
|
question: 'Verarbeiten Sie Daten von Minderjaehrigen?',
|
|
type: 'boolean',
|
|
helpText: 'z.B. Schueler, Kinder unter 16 Jahren',
|
|
triggersTemplates: [],
|
|
},
|
|
{
|
|
id: 'data_biometric',
|
|
step: 4,
|
|
question: 'Verarbeiten Sie biometrische Daten zur Identifizierung?',
|
|
type: 'boolean',
|
|
helpText: 'z.B. Fingerabdruck, Gesichtserkennung, Stimmerkennung',
|
|
triggersTemplates: [],
|
|
},
|
|
{
|
|
id: 'data_criminal',
|
|
step: 4,
|
|
question: 'Verarbeiten Sie Daten ueber strafrechtliche Verurteilungen (Art. 10 DSGVO)?',
|
|
type: 'boolean',
|
|
helpText: 'z.B. Fuehrungszeugnisse',
|
|
triggersTemplates: [],
|
|
},
|
|
|
|
// === STEP 5: Drittlandtransfers ===
|
|
{
|
|
id: 'transfer_cloud_us',
|
|
step: 5,
|
|
question: 'Nutzen Sie Cloud-Dienste mit Sitz in den USA?',
|
|
type: 'boolean',
|
|
helpText: 'z.B. AWS, Azure, Google Cloud, Microsoft 365',
|
|
triggersTemplates: [],
|
|
},
|
|
{
|
|
id: 'transfer_support_non_eu',
|
|
step: 5,
|
|
question: 'Haben Sie Support-Mitarbeiter oder Dienstleister ausserhalb der EU?',
|
|
type: 'boolean',
|
|
triggersTemplates: [],
|
|
},
|
|
{
|
|
id: 'transfer_subprocessor',
|
|
step: 5,
|
|
question: 'Nutzen Sie Auftragsverarbeiter mit Unteraufragnehmern in Drittlaendern?',
|
|
type: 'boolean',
|
|
triggersTemplates: [],
|
|
},
|
|
|
|
// === STEP 6: Besondere Verarbeitungen ===
|
|
{
|
|
id: 'special_ai',
|
|
step: 6,
|
|
question: 'Setzen Sie KI oder automatisierte Entscheidungsfindung ein?',
|
|
type: 'boolean',
|
|
helpText: 'z.B. Chatbots, Scoring, Profiling, automatische Bewertungen',
|
|
triggersTemplates: [],
|
|
},
|
|
{
|
|
id: 'special_video_surveillance',
|
|
step: 6,
|
|
question: 'Betreiben Sie Videoueberwachung?',
|
|
type: 'boolean',
|
|
triggersTemplates: [],
|
|
},
|
|
{
|
|
id: 'special_tracking',
|
|
step: 6,
|
|
question: 'Betreiben Sie umfangreiches Nutzer-Tracking oder Profiling?',
|
|
type: 'boolean',
|
|
helpText: 'z.B. Verhaltensprofiling, Cross-Device-Tracking',
|
|
triggersTemplates: [],
|
|
},
|
|
]
|
|
|
|
// =============================================================================
|
|
// DEPARTMENT DATA CATEGORIES (Aufklappbare Kacheln Step 2)
|
|
// =============================================================================
|
|
|
|
export interface DepartmentCategory {
|
|
id: string
|
|
label: string
|
|
info: string
|
|
isArt9?: boolean
|
|
isTypical?: boolean
|
|
}
|
|
|
|
export interface DepartmentDataConfig {
|
|
label: string
|
|
icon: string
|
|
categories: DepartmentCategory[]
|
|
}
|
|
|
|
export const DEPARTMENT_DATA_CATEGORIES: Record<string, DepartmentDataConfig> = {
|
|
dept_hr: {
|
|
label: 'Personal (HR)',
|
|
icon: '👥',
|
|
categories: [
|
|
{ id: 'NAME', label: 'Stammdaten', info: 'Vor-/Nachname, Titel, Geschlecht, Geburtsdatum', isTypical: true },
|
|
{ id: 'ADDRESS', label: 'Adressdaten', info: 'Wohn-/Melde-/Lieferadresse, Telefon, E-Mail', isTypical: true },
|
|
{ id: 'SOCIAL_SECURITY', label: 'Sozialversicherungsnr.', info: 'SV-Nummer fuer Meldungen an DRV, Krankenkasse', isTypical: true },
|
|
{ id: 'TAX_ID', label: 'Steuer-ID', info: 'Steueridentifikationsnummer, Steuerklasse, Freibetraege', isTypical: true },
|
|
{ id: 'BANK_ACCOUNT', label: 'Bankverbindung', info: 'IBAN, BIC fuer Gehaltsueberweisungen', isTypical: true },
|
|
{ id: 'SALARY_DATA', label: 'Gehaltsdaten', info: 'Bruttogehalt, Zulagen, Praemien, VWL, Abzuege', isTypical: true },
|
|
{ id: 'EMPLOYMENT_DATA', label: 'Beschaeftigungsdaten', info: 'Vertrag, Eintrittsdatum, Abteilung, Position, Arbeitszeitmodell', isTypical: true },
|
|
{ id: 'HEALTH_DATA', label: 'Gesundheitsdaten', info: 'Krankheitstage (AU-Bescheinigungen), BEM-Daten, Schwerbehinderung', isArt9: true },
|
|
{ id: 'RELIGIOUS_BELIEFS', label: 'Religionszugehoerigkeit', info: 'Konfession fuer Kirchensteuer-Abfuehrung', isArt9: true },
|
|
{ id: 'EDUCATION_DATA', label: 'Qualifikationen', info: 'Abschluesse, Zertifikate, Weiterbildungen, Schulungsnachweise' },
|
|
{ id: 'PHOTO_VIDEO', label: 'Mitarbeiterfotos', info: 'Passbilder fuer Ausweise, Intranet-Profilbilder' },
|
|
]
|
|
},
|
|
dept_recruiting: {
|
|
label: 'Recruiting / Bewerbermanagement',
|
|
icon: '📋',
|
|
categories: [
|
|
{ id: 'NAME', label: 'Bewerberstammdaten', info: 'Name, Anschrift, Kontaktdaten der Bewerber', isTypical: true },
|
|
{ id: 'APPLICATION_DATA', label: 'Bewerbungsunterlagen', info: 'Lebenslauf, Anschreiben, Zeugnisse, Zertifikate', isTypical: true },
|
|
{ id: 'EDUCATION_DATA', label: 'Qualifikationen', info: 'Abschluesse, Berufserfahrung, Sprachkenntnisse', isTypical: true },
|
|
{ id: 'ASSESSMENT_DATA', label: 'Bewertungsdaten', info: 'Interviewnotizen, Assessment-Ergebnisse, Eignungstests' },
|
|
{ id: 'HEALTH_DATA', label: 'Gesundheitsdaten', info: 'Schwerbehinderung (freiwillige Angabe), Eignungsuntersuchung', isArt9: true },
|
|
{ id: 'PHOTO_VIDEO', label: 'Bewerbungsfotos', info: 'Bewerbungsfoto (freiwillig), Video-Interview-Aufnahmen' },
|
|
]
|
|
},
|
|
dept_finance: {
|
|
label: 'Finanzen & Buchhaltung',
|
|
icon: '💰',
|
|
categories: [
|
|
{ id: 'NAME', label: 'Kunden-/Lieferantenstammdaten', info: 'Firmenname, Ansprechpartner, Kontaktdaten', isTypical: true },
|
|
{ id: 'ADDRESS', label: 'Rechnungsadressen', info: 'Rechnungs-/Lieferadressen, USt-IdNr.', isTypical: true },
|
|
{ id: 'BANK_ACCOUNT', label: 'Bankverbindungen', info: 'IBAN, BIC, SEPA-Mandate, Zahlungsbedingungen', isTypical: true },
|
|
{ id: 'TAX_ID', label: 'Steuer-IDs', info: 'Steuernummer, USt-IdNr., Steueridentifikationsnr.', isTypical: true },
|
|
{ id: 'INVOICE_DATA', label: 'Rechnungsdaten', info: 'Rechnungen, Gutschriften, Mahnungen, Zahlungshistorie', isTypical: true },
|
|
{ id: 'CONTRACT_DATA', label: 'Vertragsdaten', info: 'Vertragskonditionen, Laufzeiten, Kuendigungsfristen' },
|
|
]
|
|
},
|
|
dept_sales: {
|
|
label: 'Vertrieb & CRM',
|
|
icon: '🤝',
|
|
categories: [
|
|
{ id: 'NAME', label: 'Kontaktdaten', info: 'Name, E-Mail, Telefon, Position der Ansprechpartner', isTypical: true },
|
|
{ id: 'ADDRESS', label: 'Firmenadresse', info: 'Firmenanschrift, Standorte', isTypical: true },
|
|
{ id: 'CRM_DATA', label: 'CRM-Daten', info: 'Lead-Status, Opportunities, Sales-Pipeline, Umsatzhistorie', isTypical: true },
|
|
{ id: 'COMMUNICATION_DATA', label: 'Kommunikation', info: 'E-Mail-Verlauf, Gespraechsnotizen, Meeting-Protokolle', isTypical: true },
|
|
{ id: 'CONTRACT_DATA', label: 'Vertragsdaten', info: 'Angebote, Bestellungen, Rahmenvertraege' },
|
|
{ id: 'PREFERENCE_DATA', label: 'Praeferenzen', info: 'Produktinteressen, Kaufhistorie, Kundensegmentierung' },
|
|
]
|
|
},
|
|
dept_marketing: {
|
|
label: 'Marketing',
|
|
icon: '📢',
|
|
categories: [
|
|
{ id: 'EMAIL', label: 'E-Mail-Adressen', info: 'Newsletter-Abonnenten, Kampagnen-Empfaenger', isTypical: true },
|
|
{ id: 'TRACKING_DATA', label: 'Tracking-/Analytics-Daten', info: 'IP-Adressen, Cookies, Seitenaufrufe, Klickpfade', isTypical: true },
|
|
{ id: 'CONSENT_DATA', label: 'Einwilligungsdaten', info: 'Cookie-Consent, Newsletter-Opt-in, Widerrufe', isTypical: true },
|
|
{ id: 'SOCIAL_MEDIA_DATA', label: 'Social-Media-Daten', info: 'Follower-Interaktionen, Kommentare, Reichweitendaten' },
|
|
{ id: 'PREFERENCE_DATA', label: 'Interessenprofil', info: 'Produktinteressen, Segmentierung, A/B-Test-Zuordnungen' },
|
|
{ id: 'PHOTO_VIDEO', label: 'Bild-/Videomaterial', info: 'Kundenfotos (Testimonials), Event-Aufnahmen, UGC' },
|
|
]
|
|
},
|
|
dept_support: {
|
|
label: 'Kundenservice / Support',
|
|
icon: '🎧',
|
|
categories: [
|
|
{ id: 'NAME', label: 'Kundenstammdaten', info: 'Name, E-Mail, Telefon, Kundennummer', isTypical: true },
|
|
{ id: 'TICKET_DATA', label: 'Ticket-/Anfragedaten', info: 'Ticketnummer, Betreff, Beschreibung, Status, Prioritaet', isTypical: true },
|
|
{ id: 'COMMUNICATION_DATA', label: 'Kommunikationsverlauf', info: 'E-Mails, Chat-Protokolle, Anrufnotizen', isTypical: true },
|
|
{ id: 'CONTRACT_DATA', label: 'Vertragsdaten', info: 'Produktversion, Lizenz, SLA-Status', isTypical: true },
|
|
{ id: 'TECHNICAL_DATA', label: 'Technische Daten', info: 'Systeminfos, Logdateien, Screenshots bei Fehlermeldungen' },
|
|
]
|
|
},
|
|
dept_it: {
|
|
label: 'IT / Administration',
|
|
icon: '💻',
|
|
categories: [
|
|
{ id: 'USER_ACCOUNTS', label: 'Benutzerkonten', info: 'Benutzernamen, Passwort-Hashes, Rollen, Berechtigungen', isTypical: true },
|
|
{ id: 'LOG_DATA', label: 'Log-/Protokolldaten', info: 'System-Logs, Zugriffsprotokolle, Fehlerprotokolle, IP-Adressen', isTypical: true },
|
|
{ id: 'DEVICE_DATA', label: 'Geraetedaten', info: 'Inventar, Seriennummern, MAC-Adressen, zugewiesene Geraete', isTypical: true },
|
|
{ id: 'NETWORK_DATA', label: 'Netzwerkdaten', info: 'IP-Adressen, VPN-Verbindungen, Firewall-Logs', isTypical: true },
|
|
{ id: 'EMAIL_DATA', label: 'E-Mail-/Kommunikation', info: 'E-Mail-Konten, Verteiler, Archivierung', isTypical: true },
|
|
{ id: 'BACKUP_DATA', label: 'Backup-Daten', info: 'Sicherungskopien mit personenbezogenen Inhalten' },
|
|
{ id: 'MONITORING_DATA', label: 'Monitoring-Daten', info: 'Systemueberwachung, Performance-Metriken mit Nutzerbezug' },
|
|
]
|
|
},
|
|
dept_recht: {
|
|
label: 'Recht / Compliance',
|
|
icon: '⚖️',
|
|
categories: [
|
|
{ id: 'CONTRACT_DATA', label: 'Vertragsdaten', info: 'Vertraege, NDAs, AVVs, Rahmenvereinbarungen', isTypical: true },
|
|
{ id: 'NAME', label: 'Ansprechpartner', info: 'Namen, Kontaktdaten von Vertragspartnern und Anwaelten', isTypical: true },
|
|
{ id: 'COMPLIANCE_DATA', label: 'Compliance-Daten', info: 'Datenschutzanfragen, Meldungen, Audit-Ergebnisse', isTypical: true },
|
|
{ id: 'INCIDENT_DATA', label: 'Vorfallsdaten', info: 'Datenschutzvorfaelle, Beschwerden, Meldungen an Aufsichtsbehoerden' },
|
|
{ id: 'CONSENT_DATA', label: 'Einwilligungsdaten', info: 'Consent-Nachweise, Widerrufe, Opt-in/Opt-out-Protokolle' },
|
|
{ id: 'CRIMINAL_DATA', label: 'Strafrechtliche Daten', info: 'Fuehrungszeugnisse, Compliance-Pruefungen (Art. 10 DSGVO)', isArt9: true },
|
|
]
|
|
},
|
|
dept_produktion: {
|
|
label: 'Produktion / Fertigung',
|
|
icon: '🏭',
|
|
categories: [
|
|
{ id: 'EMPLOYMENT_DATA', label: 'Schichtplaene', info: 'Schichtzuordnung, Arbeitszeiten, Anwesenheitslisten', isTypical: true },
|
|
{ id: 'NAME', label: 'Mitarbeiterstammdaten', info: 'Name, Personalnummer, Qualifikation, Maschinenberechtigungen', isTypical: true },
|
|
{ id: 'HEALTH_DATA', label: 'Arbeitsschutzdaten', info: 'Arbeitsmedizinische Vorsorge, Unfallmeldungen, Gefahrstoff-Expositionen', isArt9: true },
|
|
{ id: 'ACCESS_DATA', label: 'Zugangsdaten', info: 'Zutrittskontrolle, Badge-Protokolle, Bereichsberechtigungen', isTypical: true },
|
|
{ id: 'QUALITY_DATA', label: 'Qualitaetsdaten', info: 'Pruefprotokolle mit Pruefernamen, Fehlerberichte' },
|
|
{ id: 'PHOTO_VIDEO', label: 'Bild-/Videodaten', info: 'Kameraueberwachung in Produktionsbereichen' },
|
|
]
|
|
},
|
|
dept_logistik: {
|
|
label: 'Logistik / Versand',
|
|
icon: '🚚',
|
|
categories: [
|
|
{ id: 'NAME', label: 'Empfaengerdaten', info: 'Name, Lieferadresse, Telefon fuer Zustellung', isTypical: true },
|
|
{ id: 'ADDRESS', label: 'Versandadressen', info: 'Liefer-/Abholadressen, Paketshop-Zuordnung', isTypical: true },
|
|
{ id: 'TRACKING_DATA', label: 'Sendungsverfolgung', info: 'Tracking-Nummern, Zustellstatus, Lieferzeitfenster', isTypical: true },
|
|
{ id: 'DRIVER_DATA', label: 'Fahrerdaten', info: 'Fahrerlaubnis, Touren, GPS-Standortdaten', isTypical: true },
|
|
{ id: 'CUSTOMS_DATA', label: 'Zolldaten', info: 'Zollerklaerungen, EORI-Nummern bei internationalem Versand' },
|
|
]
|
|
},
|
|
dept_einkauf: {
|
|
label: 'Einkauf / Beschaffung',
|
|
icon: '🛒',
|
|
categories: [
|
|
{ id: 'NAME', label: 'Lieferantenkontakte', info: 'Ansprechpartner, E-Mail, Telefon der Lieferanten', isTypical: true },
|
|
{ id: 'CONTRACT_DATA', label: 'Vertragsdaten', info: 'Rahmenvertraege, Bestellungen, Konditionen, Laufzeiten', isTypical: true },
|
|
{ id: 'BANK_ACCOUNT', label: 'Bankverbindungen', info: 'IBAN, BIC der Lieferanten fuer Zahlungsabwicklung', isTypical: true },
|
|
{ id: 'TAX_ID', label: 'Steuer-IDs', info: 'USt-IdNr., Steuernummer der Lieferanten', isTypical: true },
|
|
{ id: 'COMPLIANCE_DATA', label: 'Lieferantenbewertung', info: 'Qualitaetsbewertungen, Audit-Ergebnisse, Zertifizierungen' },
|
|
]
|
|
},
|
|
dept_facility: {
|
|
label: 'Facility Management',
|
|
icon: '🏢',
|
|
categories: [
|
|
{ id: 'ACCESS_DATA', label: 'Zutrittsdaten', info: 'Schluesselausgaben, Badge-Protokolle, Zutrittslisten', isTypical: true },
|
|
{ id: 'NAME', label: 'Dienstleisterkontakte', info: 'Reinigung, Wartung, Sicherheitsdienst — Namen und Kontaktdaten', isTypical: true },
|
|
{ id: 'PHOTO_VIDEO', label: 'Videoueberwachung', info: 'Kameraaufnahmen in/an Gebaeuden, Parkplaetzen', isTypical: true },
|
|
{ id: 'VISITOR_DATA', label: 'Besucherdaten', info: 'Name, Firma, Besuchsgrund, Ein-/Austrittszeiten', isTypical: true },
|
|
{ id: 'HEALTH_DATA', label: 'Gesundheits-/Sicherheitsdaten', info: 'Unfallmeldungen, Evakuierungslisten, Ersthelfer-Register', isArt9: true },
|
|
]
|
|
},
|
|
}
|
|
|
|
// =============================================================================
|
|
// GENERATOR LOGIC
|
|
// =============================================================================
|
|
|
|
export function generateActivities(answers: ProfilingAnswers): ProfilingResult {
|
|
// Collect all triggered template IDs
|
|
const triggeredIds = new Set<string>()
|
|
|
|
for (const question of PROFILING_QUESTIONS) {
|
|
const answer = answers[question.id]
|
|
if (!answer) continue
|
|
|
|
// Boolean questions: if true, trigger templates
|
|
if (question.type === 'boolean' && answer === true) {
|
|
question.triggersTemplates.forEach(id => triggeredIds.add(id))
|
|
}
|
|
}
|
|
|
|
// Always add IT baseline templates (every company needs these)
|
|
triggeredIds.add('it-systemadministration')
|
|
triggeredIds.add('it-backup')
|
|
triggeredIds.add('it-logging')
|
|
triggeredIds.add('it-iam')
|
|
|
|
// Generate activities from triggered templates
|
|
const existingIds: string[] = []
|
|
const activities: VVTActivity[] = []
|
|
|
|
for (const templateId of triggeredIds) {
|
|
const template = VVT_BASELINE_CATALOG.find(t => t.templateId === templateId)
|
|
if (!template) continue
|
|
|
|
const vvtId = generateVVTId(existingIds)
|
|
existingIds.push(vvtId)
|
|
|
|
const activity = templateToActivity(template, vvtId)
|
|
|
|
// Enrich with profiling answers
|
|
enrichActivityFromAnswers(activity, answers)
|
|
|
|
activities.push(activity)
|
|
}
|
|
|
|
// Calculate coverage score
|
|
const totalFields = activities.length * 12 // 12 key fields per activity
|
|
let filledFields = 0
|
|
for (const a of activities) {
|
|
if (a.name) filledFields++
|
|
if (a.description) filledFields++
|
|
if (a.purposes.length > 0) filledFields++
|
|
if (a.legalBases.length > 0) filledFields++
|
|
if (a.dataSubjectCategories.length > 0) filledFields++
|
|
if (a.personalDataCategories.length > 0) filledFields++
|
|
if (a.recipientCategories.length > 0) filledFields++
|
|
if (a.retentionPeriod.description) filledFields++
|
|
if (a.tomDescription) filledFields++
|
|
if (a.businessFunction !== 'other') filledFields++
|
|
if (a.structuredToms.accessControl.length > 0) filledFields++
|
|
if (a.responsible || a.owner) filledFields++
|
|
}
|
|
|
|
const coverageScore = totalFields > 0 ? Math.round((filledFields / totalFields) * 100) : 0
|
|
|
|
// Art. 30 Abs. 5 check
|
|
const employeeCount = typeof answers.org_employees === 'number' ? answers.org_employees : 0
|
|
const hasSpecialCategories = answers.data_health === true || answers.data_biometric === true || answers.data_criminal === true
|
|
const art30Abs5Exempt = employeeCount < 250 && !hasSpecialCategories
|
|
|
|
return {
|
|
answers,
|
|
generatedActivities: activities,
|
|
coverageScore,
|
|
art30Abs5Exempt,
|
|
}
|
|
}
|
|
|
|
// =============================================================================
|
|
// ENRICHMENT
|
|
// =============================================================================
|
|
|
|
function enrichActivityFromAnswers(activity: VVTActivity, answers: ProfilingAnswers): void {
|
|
// Add third-country transfers if US cloud is used
|
|
if (answers.transfer_cloud_us === true) {
|
|
activity.thirdCountryTransfers.push({
|
|
country: 'US',
|
|
recipient: 'Cloud-Dienstleister (USA)',
|
|
transferMechanism: 'SCC_PROCESSOR',
|
|
additionalMeasures: ['Verschluesselung at-rest', 'Transfer Impact Assessment'],
|
|
})
|
|
}
|
|
|
|
// Add special data categories if applicable
|
|
if (answers.data_health === true) {
|
|
if (!activity.personalDataCategories.includes('HEALTH_DATA')) {
|
|
// Only add to HR activities
|
|
if (activity.businessFunction === 'hr') {
|
|
activity.personalDataCategories.push('HEALTH_DATA')
|
|
// Ensure Art. 9 legal basis
|
|
if (!activity.legalBases.some(lb => lb.type.startsWith('ART9_'))) {
|
|
activity.legalBases.push({
|
|
type: 'ART9_EMPLOYMENT',
|
|
description: 'Arbeitsrechtliche Verarbeitung',
|
|
reference: 'Art. 9 Abs. 2 lit. b DSGVO',
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (answers.data_minors === true) {
|
|
if (!activity.dataSubjectCategories.includes('MINORS')) {
|
|
// Add to relevant activities (education, app users)
|
|
if (activity.businessFunction === 'support' || activity.businessFunction === 'product_engineering') {
|
|
activity.dataSubjectCategories.push('MINORS')
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set DPIA required for special processing
|
|
if (answers.special_ai === true || answers.special_video_surveillance === true || answers.special_tracking === true) {
|
|
if (answers.special_ai === true && activity.businessFunction === 'product_engineering') {
|
|
activity.dpiaRequired = true
|
|
}
|
|
}
|
|
}
|
|
|
|
// =============================================================================
|
|
// HELPERS
|
|
// =============================================================================
|
|
|
|
export function getQuestionsForStep(step: number): ProfilingQuestion[] {
|
|
return PROFILING_QUESTIONS.filter(q => q.step === step)
|
|
}
|
|
|
|
export function getStepProgress(answers: ProfilingAnswers, step: number): number {
|
|
const questions = getQuestionsForStep(step)
|
|
if (questions.length === 0) return 100
|
|
|
|
const answered = questions.filter(q => {
|
|
const a = answers[q.id]
|
|
return a !== undefined && a !== null && a !== ''
|
|
}).length
|
|
|
|
return Math.round((answered / questions.length) * 100)
|
|
}
|
|
|
|
export function getTotalProgress(answers: ProfilingAnswers): number {
|
|
const total = PROFILING_QUESTIONS.length
|
|
if (total === 0) return 100
|
|
|
|
const answered = PROFILING_QUESTIONS.filter(q => {
|
|
const a = answers[q.id]
|
|
return a !== undefined && a !== null && a !== ''
|
|
}).length
|
|
|
|
return Math.round((answered / total) * 100)
|
|
}
|
|
|
|
// =============================================================================
|
|
// COMPLIANCE SCOPE INTEGRATION
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Prefill VVT profiling answers from Compliance Scope Engine answers.
|
|
* The Scope Engine acts as the "Single Source of Truth" for organizational questions.
|
|
* Redundant questions are auto-filled with a "prefilled" marker.
|
|
*/
|
|
export function prefillFromScopeAnswers(
|
|
scopeAnswers: import('./compliance-scope-types').ScopeProfilingAnswer[]
|
|
): ProfilingAnswers {
|
|
const { exportToVVTAnswers } = require('./compliance-scope-profiling')
|
|
const exported = exportToVVTAnswers(scopeAnswers) as Record<string, unknown>
|
|
const prefilled: ProfilingAnswers = {}
|
|
|
|
for (const [key, value] of Object.entries(exported)) {
|
|
if (value !== undefined && value !== null) {
|
|
prefilled[key] = value as string | string[] | number | boolean
|
|
}
|
|
}
|
|
|
|
return prefilled
|
|
}
|
|
|
|
/**
|
|
* Get the list of VVT question IDs that are prefilled from Scope answers.
|
|
* These questions should show "Aus Scope-Analyse uebernommen" hint.
|
|
*/
|
|
export const SCOPE_PREFILLED_VVT_QUESTIONS = [
|
|
'org_industry',
|
|
'org_employees',
|
|
'org_b2b_b2c',
|
|
'dept_hr',
|
|
'dept_finance',
|
|
'dept_marketing',
|
|
'data_health',
|
|
'data_minors',
|
|
'data_biometric',
|
|
'data_criminal',
|
|
'special_ai',
|
|
'special_video_surveillance',
|
|
'special_tracking',
|
|
'transfer_cloud_us',
|
|
'transfer_subprocessor',
|
|
'transfer_support_non_eu',
|
|
]
|