Files
breakpilot-compliance/admin-compliance/lib/sdk/einwilligungen/generator/privacy-policy-sections-part2.ts
Sharang Parnerkar 7d8e5667c9 refactor(admin-compliance): split 7 oversized files under 500 LOC hard cap (batch 3)
- tom-generator/export/zip.ts: extract private helpers to zip-helpers.ts (544→342 LOC)
- tom-generator/export/docx.ts: extract private helpers to docx-helpers.ts (525→378 LOC)
- tom-generator/export/pdf.ts: extract private helpers to pdf-helpers.ts (517→446 LOC)
- tom-generator/demo-data/index.ts: extract DEMO_RISK_PROFILES + DEMO_EVIDENCE_DOCUMENTS to demo-data-part2.ts (518→360 LOC)
- einwilligungen/generator/privacy-policy-sections.ts: extract sections 5-7 to part2 (559→313 LOC)
- einwilligungen/export/pdf.ts: extract HTML/CSS helpers to pdf-helpers.ts (505→296 LOC)
- vendor-compliance/context.tsx: extract API action hooks to context-actions.tsx (509→286 LOC)

All originals re-export from sibling files — zero consumer import changes needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 00:43:41 +02:00

300 lines
11 KiB
TypeScript

/**
* Privacy Policy Section Generators (Part 2)
*
* Sections 5-7: recipients, retention, special-categories, rights
* Extracted from privacy-policy-sections.ts to stay under 500 LOC hard cap.
*/
import {
DataPoint,
DataPointCategory,
CompanyInfo,
PrivacyPolicySection,
SupportedLanguage,
LocalizedText,
RetentionMatrixEntry,
LegalBasis,
CATEGORY_METADATA,
LEGAL_BASIS_INFO,
RETENTION_PERIOD_INFO,
} from '../types'
// Private helpers (duplicated locally to avoid cross-file private import)
function t(text: LocalizedText, language: SupportedLanguage): string {
return text[language]
}
function groupByCategory(dataPoints: DataPoint[]): Map<DataPointCategory, DataPoint[]> {
const grouped = new Map<DataPointCategory, DataPoint[]>()
for (const dp of dataPoints) {
const existing = grouped.get(dp.category) || []
grouped.set(dp.category, [...existing, dp])
}
return grouped
}
function extractThirdParties(dataPoints: DataPoint[]): string[] {
const thirdParties = new Set<string>()
for (const dp of dataPoints) {
for (const recipient of dp.thirdPartyRecipients) {
thirdParties.add(recipient)
}
}
return Array.from(thirdParties).sort()
}
export function generateRecipientsSection(
dataPoints: DataPoint[],
language: SupportedLanguage
): PrivacyPolicySection {
const title: LocalizedText = {
de: '5. Empfaenger und Datenweitergabe',
en: '5. Recipients and Data Sharing',
}
const thirdParties = extractThirdParties(dataPoints)
if (thirdParties.length === 0) {
const content: LocalizedText = {
de: 'Wir geben Ihre personenbezogenen Daten grundsaetzlich nicht an Dritte weiter, es sei denn, dies ist zur Vertragserfuellung erforderlich oder Sie haben ausdruecklich eingewilligt.',
en: 'We generally do not share your personal data with third parties unless this is necessary for contract performance or you have expressly consented.',
}
return {
id: 'recipients',
order: 5,
title,
content,
dataPointIds: [],
isRequired: true,
isGenerated: false,
}
}
const recipientDetails = new Map<string, DataPoint[]>()
for (const dp of dataPoints) {
for (const recipient of dp.thirdPartyRecipients) {
const existing = recipientDetails.get(recipient) || []
recipientDetails.set(recipient, [...existing, dp])
}
}
const recipientList = Array.from(recipientDetails.entries())
.map(([recipient, dps]) => {
const dataNames = dps.map((dp) => t(dp.name, language)).join(', ')
return `- **${recipient}**: ${dataNames}`
})
.join('\n')
const content: LocalizedText = {
de: `Wir uebermitteln Ihre personenbezogenen Daten an folgende Empfaenger bzw. Kategorien von Empfaengern:\n\n${recipientList}\n\nMit allen Auftragsverarbeitern haben wir Auftragsverarbeitungsvertraege nach Art. 28 DSGVO abgeschlossen.`,
en: `We share your personal data with the following recipients or categories of recipients:\n\n${recipientList}\n\nWe have concluded data processing agreements pursuant to Art. 28 GDPR with all processors.`,
}
return {
id: 'recipients',
order: 5,
title,
content,
dataPointIds: dataPoints.filter((dp) => dp.thirdPartyRecipients.length > 0).map((dp) => dp.id),
isRequired: true,
isGenerated: true,
}
}
export function generateRetentionSection(
dataPoints: DataPoint[],
retentionMatrix: RetentionMatrixEntry[],
language: SupportedLanguage
): PrivacyPolicySection {
const title: LocalizedText = {
de: '6. Speicherdauer',
en: '6. Data Retention',
}
const grouped = groupByCategory(dataPoints)
const sections: string[] = []
for (const entry of retentionMatrix) {
const categoryData = grouped.get(entry.category)
if (!categoryData || categoryData.length === 0) continue
const categoryName = t(entry.categoryName, language)
const standardPeriod = t(RETENTION_PERIOD_INFO[entry.standardPeriod].label, language)
const dataRetention = categoryData
.map((dp) => {
const period = t(RETENTION_PERIOD_INFO[dp.retentionPeriod].label, language)
return `- ${t(dp.name, language)}: ${period}`
})
.join('\n')
sections.push(`### ${categoryName}\n\n**Standardfrist:** ${standardPeriod}\n\n${dataRetention}`)
}
const content: LocalizedText = {
de: `Wir speichern Ihre personenbezogenen Daten nur so lange, wie dies fuer die jeweiligen Zwecke erforderlich ist oder gesetzliche Aufbewahrungsfristen bestehen.\n\n${sections.join('\n\n')}`,
en: `We store your personal data only for as long as is necessary for the respective purposes or as required by statutory retention periods.\n\n${sections.join('\n\n')}`,
}
return {
id: 'retention',
order: 6,
title,
content,
dataPointIds: dataPoints.map((dp) => dp.id),
isRequired: true,
isGenerated: true,
}
}
export function generateSpecialCategoriesSection(
dataPoints: DataPoint[],
language: SupportedLanguage
): PrivacyPolicySection | null {
const specialCategoryDataPoints = dataPoints.filter(dp => dp.isSpecialCategory || dp.category === 'HEALTH_DATA')
if (specialCategoryDataPoints.length === 0) {
return null
}
const title: LocalizedText = {
de: '6a. Besondere Kategorien personenbezogener Daten (Art. 9 DSGVO)',
en: '6a. Special Categories of Personal Data (Art. 9 GDPR)',
}
const dataList = specialCategoryDataPoints
.map((dp) => `- **${t(dp.name, language)}**: ${t(dp.description, language)}`)
.join('\n')
const content: LocalizedText = {
de: `Gemaess Art. 9 DSGVO verarbeiten wir auch besondere Kategorien personenbezogener Daten, die einen erhoehten Schutz geniessen. Diese Daten umfassen:
${dataList}
### Ihre ausdrueckliche Einwilligung
Die Verarbeitung dieser besonderen Kategorien personenbezogener Daten erfolgt nur auf Grundlage Ihrer **ausdruecklichen Einwilligung** gemaess Art. 9 Abs. 2 lit. a DSGVO.
### Ihre Rechte bei Art. 9 Daten
- Sie koennen Ihre Einwilligung **jederzeit widerrufen**
- Der Widerruf beruehrt nicht die Rechtmaessigkeit der bisherigen Verarbeitung
- Bei Widerruf werden Ihre Daten unverzueglich geloescht
- Sie haben das Recht auf **Auskunft, Berichtigung und Loeschung**
### Besondere Schutzmassnahmen
Fuer diese sensiblen Daten haben wir besondere technische und organisatorische Massnahmen implementiert:
- Ende-zu-Ende-Verschluesselung
- Strenge Zugriffskontrolle (Need-to-Know-Prinzip)
- Audit-Logging aller Zugriffe
- Regelmaessige Datenschutz-Folgenabschaetzungen`,
en: `In accordance with Art. 9 GDPR, we also process special categories of personal data that enjoy enhanced protection. This data includes:
${dataList}
### Your Explicit Consent
Processing of these special categories of personal data only takes place on the basis of your **explicit consent** pursuant to Art. 9(2)(a) GDPR.
### Your Rights Regarding Art. 9 Data
- You can **withdraw your consent at any time**
- Withdrawal does not affect the lawfulness of previous processing
- Upon withdrawal, your data will be deleted immediately
- You have the right to **access, rectification, and erasure**
### Special Protection Measures
For this sensitive data, we have implemented special technical and organizational measures:
- End-to-end encryption
- Strict access control (need-to-know principle)
- Audit logging of all access
- Regular data protection impact assessments`,
}
return {
id: 'special-categories',
order: 6.5,
title,
content,
dataPointIds: specialCategoryDataPoints.map((dp) => dp.id),
isRequired: false,
isGenerated: true,
}
}
export function generateRightsSection(language: SupportedLanguage): PrivacyPolicySection {
const title: LocalizedText = {
de: '7. Ihre Rechte als betroffene Person',
en: '7. Your Rights as a Data Subject',
}
const content: LocalizedText = {
de: `Sie haben gegenueber uns folgende Rechte hinsichtlich der Sie betreffenden personenbezogenen Daten:
### Auskunftsrecht (Art. 15 DSGVO)
Sie haben das Recht, Auskunft ueber die von uns verarbeiteten personenbezogenen Daten zu verlangen.
### Recht auf Berichtigung (Art. 16 DSGVO)
Sie haben das Recht, die Berichtigung unrichtiger oder die Vervollstaendigung unvollstaendiger Daten zu verlangen.
### Recht auf Loeschung (Art. 17 DSGVO)
Sie haben das Recht, die Loeschung Ihrer personenbezogenen Daten zu verlangen, sofern keine gesetzlichen Aufbewahrungspflichten entgegenstehen.
### Recht auf Einschraenkung der Verarbeitung (Art. 18 DSGVO)
Sie haben das Recht, die Einschraenkung der Verarbeitung Ihrer Daten zu verlangen.
### Recht auf Datenuebertragbarkeit (Art. 20 DSGVO)
Sie haben das Recht, Ihre Daten in einem strukturierten, gaengigen und maschinenlesbaren Format zu erhalten.
### Widerspruchsrecht (Art. 21 DSGVO)
Sie haben das Recht, der Verarbeitung Ihrer Daten jederzeit zu widersprechen, soweit die Verarbeitung auf berechtigtem Interesse beruht.
### Recht auf Widerruf der Einwilligung (Art. 7 Abs. 3 DSGVO)
Sie haben das Recht, Ihre erteilte Einwilligung jederzeit zu widerrufen. Die Rechtmaessigkeit der aufgrund der Einwilligung bis zum Widerruf erfolgten Verarbeitung wird dadurch nicht beruehrt.
### Beschwerderecht bei der Aufsichtsbehoerde (Art. 77 DSGVO)
Sie haben das Recht, sich bei einer Datenschutz-Aufsichtsbehoerde ueber die Verarbeitung Ihrer personenbezogenen Daten zu beschweren.
**Zur Ausuebung Ihrer Rechte wenden Sie sich bitte an die oben angegebenen Kontaktdaten.**`,
en: `You have the following rights regarding your personal data:
### Right of Access (Art. 15 GDPR)
You have the right to request information about the personal data we process about you.
### Right to Rectification (Art. 16 GDPR)
You have the right to request the correction of inaccurate data or the completion of incomplete data.
### Right to Erasure (Art. 17 GDPR)
You have the right to request the deletion of your personal data, unless statutory retention obligations apply.
### Right to Restriction of Processing (Art. 18 GDPR)
You have the right to request the restriction of processing of your data.
### Right to Data Portability (Art. 20 GDPR)
You have the right to receive your data in a structured, commonly used, and machine-readable format.
### Right to Object (Art. 21 GDPR)
You have the right to object to the processing of your data at any time, insofar as the processing is based on legitimate interest.
### Right to Withdraw Consent (Art. 7(3) GDPR)
You have the right to withdraw your consent at any time. The lawfulness of processing based on consent before its withdrawal is not affected.
### Right to Lodge a Complaint with a Supervisory Authority (Art. 77 GDPR)
You have the right to lodge a complaint with a data protection supervisory authority about the processing of your personal data.
**To exercise your rights, please contact us using the contact details provided above.**`,
}
return {
id: 'rights',
order: 7,
title,
content,
dataPointIds: [],
isRequired: true,
isGenerated: false,
}
}