Files
breakpilot-compliance/admin-compliance/lib/sdk/vendor-compliance/risk/controls-library.ts
Sharang Parnerkar e58af8aa30 refactor(admin): split tom-generator controls loader and vendor risk controls-library
Split loader.ts (3163 LOC) into categories/ subdir (8 files, each <500 LOC):
- access.ts (ACCESS_CONTROL + ADMISSION_CONTROL + ACCESS_AUTHORIZATION)
- transfer-input.ts (TRANSFER_CONTROL + INPUT_CONTROL)
- order-availability.ts (ORDER_CONTROL + AVAILABILITY)
- separation-encryption.ts (SEPARATION incl. DL-* + ENCRYPTION)
- pseudonymization.ts (PSEUDONYMIZATION)
- resilience-recovery.ts (RESILIENCE + RECOVERY)
- review.ts (REVIEW + training/TR-* controls)
- category-map.ts (category metadata Map)

Split controls-library.ts (943 LOC) into domain files:
- transfer-audit.ts (TRANSFER + AUDIT)
- deletion-incident.ts (DELETION + INCIDENT)
- subprocessor-tom.ts (SUBPROCESSOR + TOM)
- contract-data-subject.ts (CONTRACT + DATA_SUBJECT)
- security-governance.ts (SECURITY + GOVERNANCE)

Both barrel files preserved their full public API. No consumer imports changed.
Zero new TypeScript errors introduced (305 pre-existing errors unchanged).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 09:20:22 +02:00

144 lines
4.1 KiB
TypeScript

/**
* Controls Library
*
* Standard controls for vendor and processing activity compliance.
* Data is split by domain into sibling files — each <500 LOC.
* This file re-assembles them and provides all helper functions.
*/
import { Control, ControlDomain, ReviewFrequency, LocalizedText } from '../types'
import { TRANSFER_CONTROLS, AUDIT_CONTROLS } from './transfer-audit'
import { DELETION_CONTROLS, INCIDENT_CONTROLS } from './deletion-incident'
import { SUBPROCESSOR_CONTROLS, TOM_CONTROLS } from './subprocessor-tom'
import { CONTRACT_CONTROLS, DATA_SUBJECT_CONTROLS } from './contract-data-subject'
import { SECURITY_CONTROLS, GOVERNANCE_CONTROLS } from './security-governance'
// ==========================================
// ASSEMBLED CONTROLS LIBRARY
// ==========================================
export const CONTROLS_LIBRARY: Control[] = [
...TRANSFER_CONTROLS,
...AUDIT_CONTROLS,
...DELETION_CONTROLS,
...INCIDENT_CONTROLS,
...SUBPROCESSOR_CONTROLS,
...TOM_CONTROLS,
...CONTRACT_CONTROLS,
...DATA_SUBJECT_CONTROLS,
...SECURITY_CONTROLS,
...GOVERNANCE_CONTROLS,
]
// ==========================================
// HELPER FUNCTIONS
// ==========================================
/**
* Get all controls
*/
export function getAllControls(): Control[] {
return CONTROLS_LIBRARY
}
/**
* Get controls by domain
*/
export function getControlsByDomain(domain: ControlDomain): Control[] {
return CONTROLS_LIBRARY.filter((c) => c.domain === domain)
}
/**
* Get control by ID
*/
export function getControlById(id: string): Control | undefined {
return CONTROLS_LIBRARY.find((c) => c.id === id)
}
/**
* Get required controls
*/
export function getRequiredControls(): Control[] {
return CONTROLS_LIBRARY.filter((c) => c.isRequired)
}
/**
* Get controls by frequency
*/
export function getControlsByFrequency(frequency: ReviewFrequency): Control[] {
return CONTROLS_LIBRARY.filter((c) => c.defaultFrequency === frequency)
}
/**
* Get controls applicable to vendors
*/
export function getVendorControls(): Control[] {
return CONTROLS_LIBRARY.filter((c) =>
['TRANSFER', 'AUDIT', 'DELETION', 'INCIDENT', 'SUBPROCESSOR', 'TOM', 'CONTRACT', 'DATA_SUBJECT', 'SECURITY', 'GOVERNANCE'].includes(c.domain)
)
}
/**
* Get controls applicable to processing activities
*/
export function getProcessingActivityControls(): Control[] {
return CONTROLS_LIBRARY.filter((c) =>
['TOM', 'DATA_SUBJECT', 'GOVERNANCE', 'SECURITY'].includes(c.domain)
)
}
/**
* Group controls by domain
*/
export function getControlsGroupedByDomain(): Map<ControlDomain, Control[]> {
const grouped = new Map<ControlDomain, Control[]>()
for (const control of CONTROLS_LIBRARY) {
const existing = grouped.get(control.domain) || []
grouped.set(control.domain, [...existing, control])
}
return grouped
}
/**
* Get domain metadata
*/
export function getControlDomainMeta(domain: ControlDomain): LocalizedText {
const meta: Record<ControlDomain, LocalizedText> = {
TRANSFER: { de: 'Drittlandtransfer', en: 'Third Country Transfer' },
AUDIT: { de: 'Audit & Prüfung', en: 'Audit & Review' },
DELETION: { de: 'Löschung', en: 'Deletion' },
INCIDENT: { de: 'Incident Response', en: 'Incident Response' },
SUBPROCESSOR: { de: 'Unterauftragnehmer', en: 'Sub-Processors' },
TOM: { de: 'Technische/Org. Maßnahmen', en: 'Technical/Org. Measures' },
CONTRACT: { de: 'Vertragliche Grundlagen', en: 'Contractual Basics' },
DATA_SUBJECT: { de: 'Betroffenenrechte', en: 'Data Subject Rights' },
SECURITY: { de: 'Sicherheit', en: 'Security' },
GOVERNANCE: { de: 'Governance', en: 'Governance' },
}
return meta[domain]
}
/**
* Calculate control coverage
*/
export function calculateControlCoverage(
controlIds: string[],
domain?: ControlDomain
): { covered: number; total: number; percentage: number } {
const targetControls = domain
? getControlsByDomain(domain)
: getRequiredControls()
const covered = targetControls.filter((c) => controlIds.includes(c.id)).length
return {
covered,
total: targetControls.length,
percentage: targetControls.length > 0 ? Math.round((covered / targetControls.length) * 100) : 0,
}
}