refactor: remove 473 lines of dead code across 5 SDK modules

- obligations: unused vendors state/fetch, unreachable filter==='ai' path
- tom: unused vendorControlsLoading state, unused bulkUpdateTOMs import
- loeschfristen: unused BASELINE_TEMPLATES imports, sdk hook, managingLegalHolds state
- vvt: unused apiGetCompleteness/apiGetLibrary, 7 unused VVTLib* interfaces
- vendor-compliance: 11 unused context methods, 6 unused selector hooks, ContractUploadData type

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-20 06:57:01 +01:00
parent 9b0f25c105
commit 24f02b52ed
8 changed files with 2 additions and 473 deletions

View File

@@ -2,7 +2,6 @@
import React, { useState, useEffect, useCallback, useMemo } from 'react'
import { useRouter } from 'next/navigation'
import { useSDK } from '@/lib/sdk'
import { StepHeader, STEP_EXPLANATIONS } from '@/components/sdk/StepHeader'
import {
LoeschfristPolicy, LegalHold, StorageLocation,
@@ -15,7 +14,6 @@ import {
formatRetentionDuration, isPolicyOverdue, getActiveLegalHolds,
getEffectiveDeletionTrigger,
} from '@/lib/sdk/loeschfristen-types'
import { BASELINE_TEMPLATES, templateToPolicy, getTemplateById, getAllTemplateTags } from '@/lib/sdk/loeschfristen-baseline-catalog'
import {
PROFILING_STEPS, ProfilingAnswer, ProfilingStep,
isStepComplete, getProfilingProgress, generatePoliciesFromProfile,
@@ -107,7 +105,6 @@ function TagInput({
export default function LoeschfristenPage() {
const router = useRouter()
const sdk = useSDK()
// ---- Core state ----
const [tab, setTab] = useState<Tab>('uebersicht')
@@ -127,9 +124,6 @@ export default function LoeschfristenPage() {
// ---- Compliance state ----
const [complianceResult, setComplianceResult] = useState<ComplianceCheckResult | null>(null)
// ---- Legal Hold management ----
const [managingLegalHolds, setManagingLegalHolds] = useState(false)
// ---- Saving state ----
const [saving, setSaving] = useState(false)

View File

@@ -588,17 +588,6 @@ export default function ObligationsPage() {
const [profiling, setProfiling] = useState(false)
const [applicableRegs, setApplicableRegs] = useState<ApplicableRegulation[]>([])
const [activeTab, setActiveTab] = useState<Tab>('uebersicht')
const [vendors, setVendors] = useState<Array<{id: string, name: string, role: string}>>([])
useEffect(() => {
fetch('/api/sdk/v1/vendor-compliance/vendors?limit=500')
.then(r => r.ok ? r.json() : null)
.then(data => {
const items = data?.data?.items || []
setVendors(items.map((v: any) => ({ id: v.id, name: v.name, role: v.role })))
})
.catch(() => {})
}, [])
// Compliance check result — auto-computed when obligations change
const complianceResult = useMemo<ObligationComplianceCheckResult | null>(() => {
@@ -777,9 +766,6 @@ export default function ObligationsPage() {
const stepInfo = STEP_EXPLANATIONS['obligations']
const filteredObligations = obligations.filter(o => {
if (filter === 'ai') {
if (!o.source.toLowerCase().includes('ai')) return false
}
if (regulationFilter !== 'all') {
const src = o.source?.toLowerCase() || ''
const key = regulationFilter.toLowerCase()

View File

@@ -35,7 +35,7 @@ const TABS: TabDefinition[] = [
export default function TOMPage() {
const router = useRouter()
const sdk = useSDK()
const { state, dispatch, bulkUpdateTOMs, runGapAnalysis } = useTOMGenerator()
const { state, dispatch, runGapAnalysis } = useTOMGenerator()
// ---------------------------------------------------------------------------
// Local state
@@ -53,7 +53,6 @@ export default function TOMPage() {
status: string
lastTestedAt?: string
}>>([])
const [vendorControlsLoading, setVendorControlsLoading] = useState(false)
// ---------------------------------------------------------------------------
// Compliance check (auto-run when derivedTOMs change)
@@ -71,7 +70,6 @@ export default function TOMPage() {
useEffect(() => {
if (tab !== 'uebersicht') return
setVendorControlsLoading(true)
Promise.all([
fetch('/api/sdk/v1/vendor-compliance/control-instances?limit=500').then(r => r.ok ? r.json() : null),
fetch('/api/sdk/v1/vendor-compliance/vendors?limit=500').then(r => r.ok ? r.json() : null),
@@ -95,7 +93,7 @@ export default function TOMPage() {
lastTestedAt: ci.lastTestedAt || ci.last_tested_at,
}))
setVendorControls(tomControls)
}).catch(() => {}).finally(() => setVendorControlsLoading(false))
}).catch(() => {})
}, [tab])
// ---------------------------------------------------------------------------

View File

@@ -235,21 +235,6 @@ async function apiInstantiateTemplate(templateId: string): Promise<VVTActivity>
return activityFromApi(await res.json())
}
async function apiGetCompleteness(activityId: string): Promise<{ score: number; missing: string[]; warnings: string[] }> {
const res = await fetch(`${VVT_API_BASE}/activities/${activityId}/completeness`)
if (!res.ok) return { score: 0, missing: [], warnings: [] }
return res.json()
}
interface LibraryItem { id: string; label_de: string; description_de?: string; [key: string]: any }
async function apiGetLibrary(type: string): Promise<LibraryItem[]> {
const res = await fetch(`${VVT_API_BASE}/libraries/${type}`)
if (!res.ok) return []
const data = await res.json()
return Array.isArray(data) ? data : []
}
// =============================================================================
// MAIN PAGE
// =============================================================================

View File

@@ -15,16 +15,9 @@ import {
VendorComplianceAction,
VendorComplianceContextValue,
ProcessingActivity,
Vendor,
ContractDocument,
Finding,
Control,
ControlInstance,
RiskAssessment,
VendorStatistics,
ComplianceStatistics,
RiskOverview,
ExportFormat,
VendorStatus,
VendorRole,
RiskLevel,
@@ -475,24 +468,6 @@ export function VendorComplianceProvider({
[apiBase]
)
const updateProcessingActivity = useCallback(
async (id: string, data: Partial<ProcessingActivity>): Promise<void> => {
const response = await fetch(`${apiBase}/processing-activities/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
})
if (!response.ok) {
const error = await response.json()
throw new Error(error.error || 'Fehler beim Aktualisieren der Verarbeitungstätigkeit')
}
dispatch({ type: 'UPDATE_PROCESSING_ACTIVITY', payload: { id, data } })
},
[apiBase]
)
const deleteProcessingActivity = useCallback(
async (id: string): Promise<void> => {
const response = await fetch(`${apiBase}/processing-activities/${id}`, {
@@ -537,49 +512,6 @@ export function VendorComplianceProvider({
// VENDOR ACTIONS
// ==========================================
const createVendor = useCallback(
async (
data: Omit<Vendor, 'id' | 'tenantId' | 'createdAt' | 'updatedAt'>
): Promise<Vendor> => {
const response = await fetch(`${apiBase}/vendors`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
})
if (!response.ok) {
const error = await response.json()
throw new Error(error.error || 'Fehler beim Erstellen des Vendors')
}
const result = await response.json()
const vendor = result.data
dispatch({ type: 'ADD_VENDOR', payload: vendor })
return vendor
},
[apiBase]
)
const updateVendor = useCallback(
async (id: string, data: Partial<Vendor>): Promise<void> => {
const response = await fetch(`${apiBase}/vendors/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
})
if (!response.ok) {
const error = await response.json()
throw new Error(error.error || 'Fehler beim Aktualisieren des Vendors')
}
dispatch({ type: 'UPDATE_VENDOR', payload: { id, data } })
},
[apiBase]
)
const deleteVendor = useCallback(
async (id: string): Promise<void> => {
const response = await fetch(`${apiBase}/vendors/${id}`, {
@@ -600,67 +532,6 @@ export function VendorComplianceProvider({
// CONTRACT ACTIONS
// ==========================================
const uploadContract = useCallback(
async (
vendorId: string,
file: File,
metadata: Partial<ContractDocument>
): Promise<ContractDocument> => {
const formData = new FormData()
formData.append('file', file)
formData.append('vendorId', vendorId)
formData.append('metadata', JSON.stringify(metadata))
const response = await fetch(`${apiBase}/contracts`, {
method: 'POST',
body: formData,
})
if (!response.ok) {
const error = await response.json()
throw new Error(error.error || 'Fehler beim Hochladen des Vertrags')
}
const result = await response.json()
const contract = result.data
dispatch({ type: 'ADD_CONTRACT', payload: contract })
// Update vendor's contracts list
const vendor = state.vendors.find((v) => v.id === vendorId)
if (vendor) {
dispatch({
type: 'UPDATE_VENDOR',
payload: {
id: vendorId,
data: { contracts: [...vendor.contracts, contract.id] },
},
})
}
return contract
},
[apiBase, state.vendors]
)
const updateContract = useCallback(
async (id: string, data: Partial<ContractDocument>): Promise<void> => {
const response = await fetch(`${apiBase}/contracts/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
})
if (!response.ok) {
const error = await response.json()
throw new Error(error.error || 'Fehler beim Aktualisieren des Vertrags')
}
dispatch({ type: 'UPDATE_CONTRACT', payload: { id, data } })
},
[apiBase]
)
const deleteContract = useCallback(
async (id: string): Promise<void> => {
const contract = state.contracts.find((c) => c.id === id)
@@ -736,125 +607,6 @@ export function VendorComplianceProvider({
[apiBase]
)
// ==========================================
// FINDINGS ACTIONS
// ==========================================
const updateFinding = useCallback(
async (id: string, data: Partial<Finding>): Promise<void> => {
const response = await fetch(`${apiBase}/findings/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
})
if (!response.ok) {
const error = await response.json()
throw new Error(error.error || 'Fehler beim Aktualisieren des Findings')
}
dispatch({ type: 'UPDATE_FINDING', payload: { id, data } })
},
[apiBase]
)
const resolveFinding = useCallback(
async (id: string, resolution: string): Promise<void> => {
await updateFinding(id, {
status: 'RESOLVED',
resolution,
resolvedAt: new Date(),
})
},
[updateFinding]
)
// ==========================================
// CONTROL ACTIONS
// ==========================================
const updateControlInstance = useCallback(
async (id: string, data: Partial<ControlInstance>): Promise<void> => {
const response = await fetch(`${apiBase}/control-instances/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
})
if (!response.ok) {
const error = await response.json()
throw new Error(error.error || 'Fehler beim Aktualisieren des Control-Status')
}
dispatch({ type: 'UPDATE_CONTROL_INSTANCE', payload: { id, data } })
},
[apiBase]
)
// ==========================================
// EXPORT ACTIONS
// ==========================================
const exportVVT = useCallback(
async (format: ExportFormat, activityIds?: string[]): Promise<string> => {
const params = new URLSearchParams({ format })
if (activityIds && activityIds.length > 0) {
params.append('activityIds', activityIds.join(','))
}
const response = await fetch(`${apiBase}/export/vvt?${params}`)
if (!response.ok) {
const error = await response.json()
throw new Error(error.error || 'Fehler beim Exportieren des VVT')
}
const blob = await response.blob()
const url = URL.createObjectURL(blob)
return url
},
[apiBase]
)
const exportVendorAuditPack = useCallback(
async (vendorId: string, format: ExportFormat): Promise<string> => {
const params = new URLSearchParams({ format, vendorId })
const response = await fetch(`${apiBase}/export/vendor-audit?${params}`)
if (!response.ok) {
const error = await response.json()
throw new Error(error.error || 'Fehler beim Exportieren des Vendor Audit Packs')
}
const blob = await response.blob()
const url = URL.createObjectURL(blob)
return url
},
[apiBase]
)
const exportRoPA = useCallback(
async (format: ExportFormat): Promise<string> => {
const params = new URLSearchParams({ format })
const response = await fetch(`${apiBase}/export/ropa?${params}`)
if (!response.ok) {
const error = await response.json()
throw new Error(error.error || 'Fehler beim Exportieren des RoPA')
}
const blob = await response.blob()
const url = URL.createObjectURL(blob)
return url
},
[apiBase]
)
// ==========================================
// INITIALIZATION
// ==========================================
@@ -877,23 +629,11 @@ export function VendorComplianceProvider({
vendorStats,
complianceStats,
riskOverview,
createProcessingActivity,
updateProcessingActivity,
deleteProcessingActivity,
duplicateProcessingActivity,
createVendor,
updateVendor,
deleteVendor,
uploadContract,
updateContract,
deleteContract,
startContractReview,
updateFinding,
resolveFinding,
updateControlInstance,
exportVVT,
exportVendorAuditPack,
exportRoPA,
loadData,
refresh,
}),
@@ -902,23 +642,11 @@ export function VendorComplianceProvider({
vendorStats,
complianceStats,
riskOverview,
createProcessingActivity,
updateProcessingActivity,
deleteProcessingActivity,
duplicateProcessingActivity,
createVendor,
updateVendor,
deleteVendor,
uploadContract,
updateContract,
deleteContract,
startContractReview,
updateFinding,
resolveFinding,
updateControlInstance,
exportVVT,
exportVendorAuditPack,
exportRoPA,
loadData,
refresh,
]
@@ -947,64 +675,3 @@ export function useVendorCompliance(): VendorComplianceContextValue {
return context
}
// ==========================================
// SELECTORS
// ==========================================
export function useVendor(vendorId: string | null) {
const { vendors } = useVendorCompliance()
return useMemo(
() => vendors.find((v) => v.id === vendorId) ?? null,
[vendors, vendorId]
)
}
export function useProcessingActivity(activityId: string | null) {
const { processingActivities } = useVendorCompliance()
return useMemo(
() => processingActivities.find((a) => a.id === activityId) ?? null,
[processingActivities, activityId]
)
}
export function useVendorContracts(vendorId: string | null) {
const { contracts } = useVendorCompliance()
return useMemo(
() => contracts.filter((c) => c.vendorId === vendorId),
[contracts, vendorId]
)
}
export function useVendorFindings(vendorId: string | null) {
const { findings } = useVendorCompliance()
return useMemo(
() => findings.filter((f) => f.vendorId === vendorId),
[findings, vendorId]
)
}
export function useContractFindings(contractId: string | null) {
const { findings } = useVendorCompliance()
return useMemo(
() => findings.filter((f) => f.contractId === contractId),
[findings, contractId]
)
}
export function useControlInstancesForEntity(
entityType: 'VENDOR' | 'PROCESSING_ACTIVITY',
entityId: string | null
) {
const { controlInstances, controls } = useVendorCompliance()
return useMemo(() => {
if (!entityId) return []
return controlInstances
.filter((ci) => ci.entityType === entityType && ci.entityId === entityId)
.map((ci) => ({
...ci,
control: controls.find((c) => c.id === ci.controlId),
}))
}, [controlInstances, controls, entityType, entityId])
}

View File

@@ -21,12 +21,6 @@ export * from './types'
export {
VendorComplianceProvider,
useVendorCompliance,
useVendor,
useProcessingActivity,
useVendorContracts,
useVendorFindings,
useContractFindings,
useControlInstancesForEntity,
} from './context'
// ==========================================

View File

@@ -828,34 +828,16 @@ export interface VendorComplianceContextValue extends VendorComplianceState {
riskOverview: RiskOverview
// Actions - Processing Activities
createProcessingActivity: (data: Omit<ProcessingActivity, 'id' | 'tenantId' | 'createdAt' | 'updatedAt'>) => Promise<ProcessingActivity>
updateProcessingActivity: (id: string, data: Partial<ProcessingActivity>) => Promise<void>
deleteProcessingActivity: (id: string) => Promise<void>
duplicateProcessingActivity: (id: string) => Promise<ProcessingActivity>
// Actions - Vendors
createVendor: (data: Omit<Vendor, 'id' | 'tenantId' | 'createdAt' | 'updatedAt'>) => Promise<Vendor>
updateVendor: (id: string, data: Partial<Vendor>) => Promise<void>
deleteVendor: (id: string) => Promise<void>
// Actions - Contracts
uploadContract: (vendorId: string, file: File, metadata: Partial<ContractDocument>) => Promise<ContractDocument>
updateContract: (id: string, data: Partial<ContractDocument>) => Promise<void>
deleteContract: (id: string) => Promise<void>
startContractReview: (contractId: string) => Promise<void>
// Actions - Findings
updateFinding: (id: string, data: Partial<Finding>) => Promise<void>
resolveFinding: (id: string, resolution: string) => Promise<void>
// Actions - Controls
updateControlInstance: (id: string, data: Partial<ControlInstance>) => Promise<void>
// Actions - Export
exportVVT: (format: ExportFormat, activityIds?: string[]) => Promise<string>
exportVendorAuditPack: (vendorId: string, format: ExportFormat) => Promise<string>
exportRoPA: (format: ExportFormat) => Promise<string>
// Data Loading
loadData: () => Promise<void>
refresh: () => Promise<void>
@@ -959,15 +941,6 @@ export interface VendorFormData {
notes?: string
}
export interface ContractUploadData {
vendorId: string
documentType: DocumentType
version: string
effectiveDate?: Date
expirationDate?: Date
autoRenewal?: boolean
}
// ==========================================
// HELPER FUNCTIONS
// ==========================================

View File

@@ -182,74 +182,6 @@ export const ART9_CATEGORIES: string[] = [
'CRIMINAL_DATA',
]
// =============================================================================
// LIBRARY TYPES (Master Libraries)
// =============================================================================
export interface VVTLibraryItem {
id: string
labelDe: string
descriptionDe?: string
sortOrder?: number
}
export interface VVTDataCategory extends VVTLibraryItem {
parentId?: string | null
isArt9: boolean
isArt10?: boolean
riskWeight: number
defaultRetentionRule?: string
defaultLegalBasis?: string
children?: VVTDataCategory[]
}
export interface VVTLibRecipient extends VVTLibraryItem {
type: 'INTERNAL' | 'PROCESSOR' | 'CONTROLLER' | 'AUTHORITY'
isThirdCountry?: boolean
country?: string
}
export interface VVTLibLegalBasis extends VVTLibraryItem {
article: string
type: string
isArt9?: boolean
}
export interface VVTLibRetentionRule extends VVTLibraryItem {
legalBasis?: string
duration: number
durationUnit: 'DAYS' | 'MONTHS' | 'YEARS'
startEvent?: string
deletionProcedure?: string
}
export interface VVTLibTom extends VVTLibraryItem {
category: 'accessControl' | 'confidentiality' | 'integrity' | 'availability' | 'separation'
art32Reference?: string
}
export interface VVTProcessTemplate {
id: string
name: string
description?: string
businessFunction: BusinessFunction
purposeRefs: string[]
legalBasisRefs: string[]
dataSubjectRefs: string[]
dataCategoryRefs: string[]
recipientRefs: string[]
tomRefs: string[]
transferMechanismRefs: string[]
retentionRuleRef?: string
typicalSystems: string[]
protectionLevel: string
dpiaRequired: boolean
riskScore?: number
tags: string[]
isSystem: boolean
sortOrder: number
}
export interface VVTCompleteness {
score: number
missing: string[]