/** * Finding Types and Templates * * Pre-defined finding templates for contract reviews */ import { FindingType, FindingCategory, FindingSeverity, LocalizedText, } from '../types' export interface FindingTemplate { id: string type: FindingType category: FindingCategory severity: FindingSeverity title: LocalizedText description: LocalizedText recommendation: LocalizedText affectedRequirement: string triggerControls: string[] } // ========================================== // FINDING SEVERITY DEFINITIONS // ========================================== export const SEVERITY_DEFINITIONS: Record = { LOW: { label: { de: 'Niedrig', en: 'Low' }, description: { de: 'Geringfügige Abweichung ohne wesentliche Auswirkungen', en: 'Minor deviation without significant impact', }, responseTime: { de: 'Bei nächster Vertragserneuerung', en: 'At next contract renewal', }, color: 'blue', }, MEDIUM: { label: { de: 'Mittel', en: 'Medium' }, description: { de: 'Abweichung mit potenziellen Auswirkungen auf Compliance', en: 'Deviation with potential impact on compliance', }, responseTime: { de: 'Innerhalb von 90 Tagen', en: 'Within 90 days', }, color: 'yellow', }, HIGH: { label: { de: 'Hoch', en: 'High' }, description: { de: 'Erhebliche Abweichung mit Auswirkungen auf Datenschutz-Compliance', en: 'Significant deviation with impact on data protection compliance', }, responseTime: { de: 'Innerhalb von 30 Tagen', en: 'Within 30 days', }, color: 'orange', }, CRITICAL: { label: { de: 'Kritisch', en: 'Critical' }, description: { de: 'Schwerwiegende Abweichung - unmittelbarer Handlungsbedarf', en: 'Serious deviation - immediate action required', }, responseTime: { de: 'Sofort / vor Vertragsabschluss', en: 'Immediately / before contract signing', }, color: 'red', }, } // ========================================== // FINDING TYPE DEFINITIONS // ========================================== export const FINDING_TYPE_DEFINITIONS: Record = { OK: { label: { de: 'Erfüllt', en: 'Fulfilled' }, description: { de: 'Anforderung ist vollständig erfüllt', en: 'Requirement is fully met', }, icon: 'check-circle', }, GAP: { label: { de: 'Lücke', en: 'Gap' }, description: { de: 'Anforderung fehlt oder ist unvollständig', en: 'Requirement is missing or incomplete', }, icon: 'alert-circle', }, RISK: { label: { de: 'Risiko', en: 'Risk' }, description: { de: 'Potenzielles Risiko identifiziert', en: 'Potential risk identified', }, icon: 'alert-triangle', }, UNKNOWN: { label: { de: 'Unklar', en: 'Unknown' }, description: { de: 'Nicht eindeutig bestimmbar', en: 'Cannot be clearly determined', }, icon: 'help-circle', }, } // ========================================== // FINDING TEMPLATES // ========================================== export const FINDING_TEMPLATES: FindingTemplate[] = [ // AVV_CONTENT - Weisungsgebundenheit { id: 'tpl-avv-instruction-missing', type: 'GAP', category: 'AVV_CONTENT', severity: 'CRITICAL', title: { de: 'Weisungsgebundenheit fehlt', en: 'Instruction binding missing', }, description: { de: 'Der Vertrag enthält keine Regelung zur Weisungsgebundenheit des Auftragsverarbeiters.', en: 'The contract does not contain a provision on the processor\'s instruction binding.', }, recommendation: { de: 'Ergänzen Sie eine Klausel, die den Auftragsverarbeiter verpflichtet, personenbezogene Daten nur auf dokumentierte Weisung des Verantwortlichen zu verarbeiten.', en: 'Add a clause obligating the processor to process personal data only on documented instructions from the controller.', }, affectedRequirement: 'Art. 28 Abs. 3 lit. a DSGVO', triggerControls: ['VND-CON-01'], }, { id: 'tpl-avv-instruction-weak', type: 'RISK', category: 'AVV_CONTENT', severity: 'MEDIUM', title: { de: 'Weisungsgebundenheit unvollständig', en: 'Instruction binding incomplete', }, description: { de: 'Die Regelung zur Weisungsgebundenheit ist vorhanden, aber es fehlt die Hinweispflicht bei rechtswidrigen Weisungen.', en: 'The instruction binding provision exists, but the obligation to notify of unlawful instructions is missing.', }, recommendation: { de: 'Ergänzen Sie eine Pflicht des Auftragsverarbeiters, den Verantwortlichen unverzüglich zu informieren, wenn eine Weisung nach seiner Auffassung gegen Datenschutzrecht verstößt.', en: 'Add an obligation for the processor to immediately inform the controller if an instruction, in their opinion, violates data protection law.', }, affectedRequirement: 'Art. 28 Abs. 3 lit. a DSGVO', triggerControls: ['VND-CON-01'], }, // AVV_CONTENT - TOM { id: 'tpl-avv-tom-missing', type: 'GAP', category: 'TOM', severity: 'CRITICAL', title: { de: 'TOM-Anlage fehlt', en: 'TOM annex missing', }, description: { de: 'Der Vertrag enthält keine technischen und organisatorischen Maßnahmen (TOM) als Anlage.', en: 'The contract does not contain technical and organizational measures (TOM) as an annex.', }, recommendation: { de: 'Fordern Sie eine detaillierte TOM-Anlage an, die die Maßnahmen gemäß Art. 32 DSGVO beschreibt.', en: 'Request a detailed TOM annex describing the measures according to Art. 32 GDPR.', }, affectedRequirement: 'Art. 28 Abs. 3 lit. c DSGVO', triggerControls: ['VND-TOM-01'], }, { id: 'tpl-avv-tom-generic', type: 'RISK', category: 'TOM', severity: 'MEDIUM', title: { de: 'TOM zu unspezifisch', en: 'TOM too generic', }, description: { de: 'Die TOM-Anlage enthält nur allgemeine Aussagen ohne konkrete Maßnahmen.', en: 'The TOM annex contains only general statements without specific measures.', }, recommendation: { de: 'Fordern Sie eine konkretere Beschreibung der Maßnahmen mit Bezug zum spezifischen Verarbeitungskontext an.', en: 'Request a more specific description of measures with reference to the specific processing context.', }, affectedRequirement: 'Art. 28 Abs. 3 lit. c DSGVO', triggerControls: ['VND-TOM-01'], }, // SUBPROCESSOR { id: 'tpl-subprocessor-no-approval', type: 'GAP', category: 'SUBPROCESSOR', severity: 'CRITICAL', title: { de: 'Keine Genehmigungspflicht für Unterauftragnehmer', en: 'No approval requirement for sub-processors', }, description: { de: 'Der Vertrag regelt nicht, ob und wie der Einsatz von Unterauftragnehmern zu genehmigen ist.', en: 'The contract does not regulate whether and how the use of sub-processors must be approved.', }, recommendation: { de: 'Ergänzen Sie eine Klausel, die entweder eine spezifische oder allgemeine Genehmigung für Unterauftragnehmer vorsieht, einschließlich Informations- und Einspruchsrechten.', en: 'Add a clause providing either specific or general authorization for sub-processors, including information and objection rights.', }, affectedRequirement: 'Art. 28 Abs. 3 lit. d DSGVO', triggerControls: ['VND-SUB-01'], }, { id: 'tpl-subprocessor-no-list', type: 'RISK', category: 'SUBPROCESSOR', severity: 'HIGH', title: { de: 'Keine Liste der Unterauftragnehmer', en: 'No list of sub-processors', }, description: { de: 'Es liegt keine aktuelle Liste der eingesetzten Unterauftragnehmer vor.', en: 'There is no current list of sub-processors used.', }, recommendation: { de: 'Fordern Sie eine vollständige Liste aller Unterauftragnehmer mit Name, Sitz und Verarbeitungszweck an.', en: 'Request a complete list of all sub-processors with name, location, and processing purpose.', }, affectedRequirement: 'Art. 28 Abs. 3 lit. d DSGVO', triggerControls: ['VND-SUB-02'], }, // INCIDENT { id: 'tpl-incident-no-notification', type: 'GAP', category: 'INCIDENT', severity: 'CRITICAL', title: { de: 'Keine Meldepflicht bei Datenpannen', en: 'No notification obligation for data breaches', }, description: { de: 'Der Vertrag enthält keine Regelung zur Meldung von Datenschutzverletzungen.', en: 'The contract does not contain a provision for reporting data breaches.', }, recommendation: { de: 'Ergänzen Sie eine Klausel, die den Auftragsverarbeiter verpflichtet, Datenschutzverletzungen unverzüglich (innerhalb von 24-48h) zu melden.', en: 'Add a clause obligating the processor to report data breaches without undue delay (within 24-48h).', }, affectedRequirement: 'Art. 33 Abs. 2 DSGVO', triggerControls: ['VND-INC-01'], }, { id: 'tpl-incident-long-deadline', type: 'RISK', category: 'INCIDENT', severity: 'HIGH', title: { de: 'Zu lange Meldefrist', en: 'Notification deadline too long', }, description: { de: 'Die vereinbarte Meldefrist für Datenschutzverletzungen ist zu lang (>72h), um die eigene Meldepflicht einhalten zu können.', en: 'The agreed notification deadline for data breaches is too long (>72h) to meet own notification obligations.', }, recommendation: { de: 'Verkürzen Sie die Meldefrist auf maximal 24-48 Stunden, um ausreichend Zeit für die eigene Meldung an die Aufsichtsbehörde zu haben.', en: 'Reduce the notification deadline to a maximum of 24-48 hours to have sufficient time for own notification to the supervisory authority.', }, affectedRequirement: 'Art. 33 DSGVO', triggerControls: ['VND-INC-01'], }, // AUDIT_RIGHTS { id: 'tpl-audit-no-right', type: 'GAP', category: 'AUDIT_RIGHTS', severity: 'HIGH', title: { de: 'Kein Auditrecht vereinbart', en: 'No audit right agreed', }, description: { de: 'Der Vertrag enthält kein Recht des Verantwortlichen auf Prüfungen und Inspektionen.', en: 'The contract does not contain a right of the controller to audits and inspections.', }, recommendation: { de: 'Ergänzen Sie ein ausdrückliches Recht auf Vor-Ort-Inspektionen und die Einsicht in relevante Unterlagen.', en: 'Add an explicit right to on-site inspections and access to relevant documents.', }, affectedRequirement: 'Art. 28 Abs. 3 lit. h DSGVO', triggerControls: ['VND-AUD-01'], }, { id: 'tpl-audit-restricted', type: 'RISK', category: 'AUDIT_RIGHTS', severity: 'MEDIUM', title: { de: 'Auditrecht eingeschränkt', en: 'Audit right restricted', }, description: { de: 'Das Auditrecht ist durch unangemessene Einschränkungen (z.B. sehr lange Vorlaufzeit, Ausschluss von Vor-Ort-Inspektionen) begrenzt.', en: 'The audit right is limited by unreasonable restrictions (e.g., very long notice period, exclusion of on-site inspections).', }, recommendation: { de: 'Verhandeln Sie angemessene Bedingungen für Audits (max. 30 Tage Vorlaufzeit, Möglichkeit zur Vor-Ort-Inspektion).', en: 'Negotiate reasonable audit conditions (max. 30 days notice, possibility for on-site inspection).', }, affectedRequirement: 'Art. 28 Abs. 3 lit. h DSGVO', triggerControls: ['VND-AUD-01'], }, // DELETION { id: 'tpl-deletion-no-clause', type: 'GAP', category: 'DELETION', severity: 'CRITICAL', title: { de: 'Keine Lösch-/Rückgaberegelung', en: 'No deletion/return clause', }, description: { de: 'Der Vertrag regelt nicht, was mit den Daten nach Vertragsende geschieht.', en: 'The contract does not regulate what happens to the data after contract termination.', }, recommendation: { de: 'Ergänzen Sie eine Klausel zur Löschung oder Rückgabe aller personenbezogenen Daten nach Vertragsende (max. 30 Tage).', en: 'Add a clause for deletion or return of all personal data after contract end (max. 30 days).', }, affectedRequirement: 'Art. 28 Abs. 3 lit. g DSGVO', triggerControls: ['VND-DEL-01'], }, { id: 'tpl-deletion-no-confirmation', type: 'RISK', category: 'DELETION', severity: 'MEDIUM', title: { de: 'Keine Löschbestätigung vorgesehen', en: 'No deletion confirmation provided', }, description: { de: 'Der Vertrag sieht keine Bestätigung der Löschung durch den Auftragsverarbeiter vor.', en: 'The contract does not provide for confirmation of deletion by the processor.', }, recommendation: { de: 'Ergänzen Sie eine Pflicht zur schriftlichen Bestätigung der vollständigen Löschung.', en: 'Add an obligation for written confirmation of complete deletion.', }, affectedRequirement: 'Art. 28 Abs. 3 lit. g DSGVO', triggerControls: ['VND-DEL-01'], }, // TRANSFER { id: 'tpl-transfer-no-basis', type: 'GAP', category: 'TRANSFER', severity: 'CRITICAL', title: { de: 'Drittlandtransfer ohne Rechtsgrundlage', en: 'Third country transfer without legal basis', }, description: { de: 'Der Vertrag erlaubt oder impliziert Transfers in Drittländer ohne geeignete Garantien.', en: 'The contract allows or implies transfers to third countries without appropriate safeguards.', }, recommendation: { de: 'Vereinbaren Sie geeignete Garantien (SCC, BCR) oder beschränken Sie die Verarbeitung auf EU/EWR.', en: 'Agree on appropriate safeguards (SCC, BCR) or restrict processing to EU/EEA.', }, affectedRequirement: 'Art. 44-49 DSGVO', triggerControls: ['VND-TRF-01'], }, { id: 'tpl-transfer-old-scc', type: 'RISK', category: 'TRANSFER', severity: 'HIGH', title: { de: 'Veraltete Standardvertragsklauseln', en: 'Outdated Standard Contractual Clauses', }, description: { de: 'Der Vertrag verwendet die alten SCC (vor 2021), die nicht mehr gültig sind.', en: 'The contract uses old SCC (pre-2021) that are no longer valid.', }, recommendation: { de: 'Aktualisieren Sie auf die SCC 2021 (Durchführungsbeschluss (EU) 2021/914).', en: 'Update to SCC 2021 (Implementing Decision (EU) 2021/914).', }, affectedRequirement: 'Art. 46 Abs. 2 lit. c DSGVO', triggerControls: ['VND-TRF-02'], }, // LIABILITY { id: 'tpl-liability-excessive-cap', type: 'RISK', category: 'LIABILITY', severity: 'MEDIUM', title: { de: 'Unangemessene Haftungsbegrenzung', en: 'Inappropriate liability cap', }, description: { de: 'Die Haftungsbegrenzung ist sehr niedrig und könnte bei Datenschutzverletzungen problematisch sein.', en: 'The liability cap is very low and could be problematic in case of data protection violations.', }, recommendation: { de: 'Prüfen Sie, ob die Haftungsbegrenzung angemessen ist. Erwägen Sie eine Ausnahme für Datenschutzverletzungen oder eine höhere Obergrenze.', en: 'Check if the liability cap is appropriate. Consider an exception for data protection violations or a higher limit.', }, affectedRequirement: 'Vertragliche Vereinbarung', triggerControls: [], }, // DATA_SUBJECT_RIGHTS { id: 'tpl-dsr-no-support', type: 'GAP', category: 'DATA_SUBJECT_RIGHTS', severity: 'HIGH', title: { de: 'Keine Unterstützung bei Betroffenenrechten', en: 'No support for data subject rights', }, description: { de: 'Der Vertrag enthält keine Regelung zur Unterstützung bei der Erfüllung von Betroffenenrechten.', en: 'The contract does not contain a provision for support in fulfilling data subject rights.', }, recommendation: { de: 'Ergänzen Sie eine Klausel zur Unterstützung bei Auskunft, Berichtigung, Löschung und anderen Betroffenenrechten.', en: 'Add a clause for support with access, rectification, deletion, and other data subject rights.', }, affectedRequirement: 'Art. 28 Abs. 3 lit. e DSGVO', triggerControls: ['VND-DSR-01'], }, // CONFIDENTIALITY { id: 'tpl-confidentiality-missing', type: 'GAP', category: 'CONFIDENTIALITY', severity: 'HIGH', title: { de: 'Keine Vertraulichkeitsverpflichtung', en: 'No confidentiality obligation', }, description: { de: 'Der Vertrag enthält keine Verpflichtung zur Vertraulichkeit der Mitarbeiter.', en: 'The contract does not contain an obligation for employee confidentiality.', }, recommendation: { de: 'Ergänzen Sie eine Klausel, die die Verpflichtung der Mitarbeiter zur Vertraulichkeit sicherstellt.', en: 'Add a clause ensuring the obligation of employees to confidentiality.', }, affectedRequirement: 'Art. 28 Abs. 3 lit. b DSGVO', triggerControls: ['VND-CON-02'], }, ] // ========================================== // HELPER FUNCTIONS // ========================================== /** * Get finding template by ID */ export function getFindingTemplateById(id: string): FindingTemplate | undefined { return FINDING_TEMPLATES.find((t) => t.id === id) } /** * Get finding templates by category */ export function getFindingTemplatesByCategory(category: FindingCategory): FindingTemplate[] { return FINDING_TEMPLATES.filter((t) => t.category === category) } /** * Get finding templates by type */ export function getFindingTemplatesByType(type: FindingType): FindingTemplate[] { return FINDING_TEMPLATES.filter((t) => t.type === type) } /** * Get finding templates by severity */ export function getFindingTemplatesBySeverity(severity: FindingSeverity): FindingTemplate[] { return FINDING_TEMPLATES.filter((t) => t.severity === severity) } /** * Get severity color class */ export function getSeverityColorClass(severity: FindingSeverity): string { return SEVERITY_DEFINITIONS[severity].color } /** * Sort findings by severity (critical first) */ export function sortFindingsBySeverity( findings: T[] ): T[] { const order: Record = { CRITICAL: 0, HIGH: 1, MEDIUM: 2, LOW: 3, } return [...findings].sort((a, b) => order[a.severity] - order[b.severity]) } /** * Count findings by severity */ export function countFindingsBySeverity( findings: T[] ): Record { return findings.reduce( (acc, f) => { acc[f.severity] = (acc[f.severity] || 0) + 1 return acc }, { LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0 } as Record ) } /** * Get overall severity from list of findings */ export function getOverallSeverity(findings: { severity: FindingSeverity }[]): FindingSeverity { if (findings.some((f) => f.severity === 'CRITICAL')) return 'CRITICAL' if (findings.some((f) => f.severity === 'HIGH')) return 'HIGH' if (findings.some((f) => f.severity === 'MEDIUM')) return 'MEDIUM' return 'LOW' }