feat(sdk): VVT master libraries, process templates, Loeschfristen profiling + document
VVT: Master library tables (7 catalogs), 500+ seed entries, process templates with instantiation, library API endpoints + 18 tests. Loeschfristen: Baseline catalog, compliance checks, profiling engine, HTML document generator, MkDocs documentation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,8 +6,10 @@
|
||||
import {
|
||||
LoeschfristPolicy,
|
||||
PolicyStatus,
|
||||
RetentionDriverType,
|
||||
isPolicyOverdue,
|
||||
getActiveLegalHolds,
|
||||
RETENTION_DRIVER_META,
|
||||
} from './loeschfristen-types'
|
||||
|
||||
// =============================================================================
|
||||
@@ -22,6 +24,10 @@ export type ComplianceIssueType =
|
||||
| 'LEGAL_HOLD_CONFLICT'
|
||||
| 'STALE_DRAFT'
|
||||
| 'UNCOVERED_VVT_CATEGORY'
|
||||
| 'MISSING_DELETION_METHOD'
|
||||
| 'MISSING_STORAGE_LOCATIONS'
|
||||
| 'EXCESSIVE_RETENTION'
|
||||
| 'MISSING_DATA_CATEGORIES'
|
||||
|
||||
export type ComplianceIssueSeverity = 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL'
|
||||
|
||||
@@ -219,6 +225,108 @@ function checkStaleDraft(policy: LoeschfristPolicy): ComplianceIssue | null {
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Check 8: MISSING_DELETION_METHOD (MEDIUM)
|
||||
* Active policy without a deletion method detail description.
|
||||
*/
|
||||
function checkMissingDeletionMethod(policy: LoeschfristPolicy): ComplianceIssue | null {
|
||||
if (policy.status === 'ACTIVE' && !policy.deletionMethodDetail.trim()) {
|
||||
return createIssue(
|
||||
policy,
|
||||
'MISSING_DELETION_METHOD',
|
||||
'MEDIUM',
|
||||
'Keine Loeschmethode beschrieben',
|
||||
`Die aktive Policy "${policy.dataObjectName}" hat keine detaillierte Beschreibung der Loeschmethode. Fuer ein auditfaehiges Loeschkonzept muss dokumentiert sein, wie die Loeschung technisch durchgefuehrt wird.`,
|
||||
'Ergaenzen Sie eine detaillierte Beschreibung der Loeschmethode (z.B. automatisches Loeschen durch Datenbank-Job, manuelle Pruefung durch Fachabteilung, kryptographische Loeschung).'
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Check 9: MISSING_STORAGE_LOCATIONS (MEDIUM)
|
||||
* Active policy without any documented storage locations.
|
||||
*/
|
||||
function checkMissingStorageLocations(policy: LoeschfristPolicy): ComplianceIssue | null {
|
||||
if (policy.status === 'ACTIVE' && policy.storageLocations.length === 0) {
|
||||
return createIssue(
|
||||
policy,
|
||||
'MISSING_STORAGE_LOCATIONS',
|
||||
'MEDIUM',
|
||||
'Keine Speicherorte dokumentiert',
|
||||
`Die aktive Policy "${policy.dataObjectName}" hat keine Speicherorte hinterlegt. Ohne Speicherort-Dokumentation ist unklar, wo die Daten gespeichert sind und wo die Loeschung durchgefuehrt werden muss.`,
|
||||
'Dokumentieren Sie mindestens einen Speicherort (z.B. Datenbank, Cloud-Speicher, E-Mail-System, Papierarchiv).'
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Check 10: EXCESSIVE_RETENTION (HIGH)
|
||||
* Retention duration exceeds 2x the legal default for the driver.
|
||||
*/
|
||||
function checkExcessiveRetention(policy: LoeschfristPolicy): ComplianceIssue | null {
|
||||
if (
|
||||
policy.retentionDriver &&
|
||||
policy.retentionDriver !== 'CUSTOM' &&
|
||||
policy.retentionDuration !== null &&
|
||||
policy.retentionUnit !== null
|
||||
) {
|
||||
const meta = RETENTION_DRIVER_META[policy.retentionDriver]
|
||||
if (meta.defaultDuration !== null && meta.defaultUnit !== null) {
|
||||
// Normalize both to days for comparison
|
||||
const policyDays = toDays(policy.retentionDuration, policy.retentionUnit)
|
||||
const legalDays = toDays(meta.defaultDuration, meta.defaultUnit)
|
||||
|
||||
if (legalDays > 0 && policyDays > legalDays * 2) {
|
||||
return createIssue(
|
||||
policy,
|
||||
'EXCESSIVE_RETENTION',
|
||||
'HIGH',
|
||||
'Ueberschreitung der gesetzlichen Aufbewahrungsfrist',
|
||||
`Die Policy "${policy.dataObjectName}" hat eine Aufbewahrungsdauer von ${policy.retentionDuration} ${policy.retentionUnit === 'YEARS' ? 'Jahren' : policy.retentionUnit === 'MONTHS' ? 'Monaten' : 'Tagen'}, die mehr als das Doppelte der gesetzlichen Frist (${meta.defaultDuration} ${meta.defaultUnit === 'YEARS' ? 'Jahre' : meta.defaultUnit === 'MONTHS' ? 'Monate' : 'Tage'} nach ${meta.statute}) betraegt. Ueberlange Speicherung widerspricht dem Grundsatz der Speicherbegrenzung (Art. 5 Abs. 1 lit. e DSGVO).`,
|
||||
'Pruefen Sie, ob die verlaengerte Aufbewahrungsdauer gerechtfertigt ist. Falls nicht, reduzieren Sie sie auf die gesetzliche Mindestfrist.'
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Check 11: MISSING_DATA_CATEGORIES (LOW)
|
||||
* Non-draft policy without any data categories assigned.
|
||||
*/
|
||||
function checkMissingDataCategories(policy: LoeschfristPolicy): ComplianceIssue | null {
|
||||
if (policy.status !== 'DRAFT' && policy.dataCategories.length === 0) {
|
||||
return createIssue(
|
||||
policy,
|
||||
'MISSING_DATA_CATEGORIES',
|
||||
'LOW',
|
||||
'Keine Datenkategorien zugeordnet',
|
||||
`Die Policy "${policy.dataObjectName}" (Status: ${policy.status}) hat keine Datenkategorien zugeordnet. Ohne Datenkategorien ist unklar, welche personenbezogenen Daten von dieser Loeschregel betroffen sind.`,
|
||||
'Ordnen Sie mindestens eine Datenkategorie zu (z.B. Stammdaten, Kontaktdaten, Finanzdaten, Gesundheitsdaten).'
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper: convert retention duration to days for comparison.
|
||||
*/
|
||||
function toDays(duration: number, unit: string): number {
|
||||
switch (unit) {
|
||||
case 'DAYS': return duration
|
||||
case 'MONTHS': return duration * 30
|
||||
case 'YEARS': return duration * 365
|
||||
default: return duration
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// MAIN COMPLIANCE CHECK
|
||||
// =============================================================================
|
||||
@@ -248,6 +356,10 @@ export function runComplianceCheck(
|
||||
checkNoResponsible(policy),
|
||||
checkLegalHoldConflict(policy),
|
||||
checkStaleDraft(policy),
|
||||
checkMissingDeletionMethod(policy),
|
||||
checkMissingStorageLocations(policy),
|
||||
checkExcessiveRetention(policy),
|
||||
checkMissingDataCategories(policy),
|
||||
]
|
||||
|
||||
for (const issue of checks) {
|
||||
|
||||
Reference in New Issue
Block a user