/** * 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 = { 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() 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 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', ]