refactor(admin): split lib/sdk/context.tsx (1280 LOC) into focused modules
Extract the monolithic SDK context provider into seven focused modules: - context-types.ts (203 LOC): SDKContextValue interface, initialState, ExtendedSDKAction - context-reducer.ts (353 LOC): sdkReducer with all action handlers - context-provider.tsx (495 LOC): SDKProvider component + SDKContext - context-hooks.ts (17 LOC): useSDK hook - context-validators.ts (94 LOC): local checkpoint validation logic - context-projects.ts (67 LOC): project management API helpers - context-sync-helpers.ts (145 LOC): sync infrastructure init/cleanup/callbacks - context.tsx (23 LOC): barrel re-export preserving existing import paths All files under the 500-line hard cap. Build verified with `npx next build`. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
import { SDKState, CheckpointStatus } from './types'
|
||||
|
||||
// =============================================================================
|
||||
// LOCAL CHECKPOINT VALIDATION
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Performs local (client-side) checkpoint validation against the current SDK state.
|
||||
* Returns a CheckpointStatus with errors/warnings populated.
|
||||
*/
|
||||
export function validateCheckpointLocally(
|
||||
checkpointId: string,
|
||||
state: SDKState
|
||||
): CheckpointStatus {
|
||||
const status: CheckpointStatus = {
|
||||
checkpointId,
|
||||
passed: true,
|
||||
validatedAt: new Date(),
|
||||
validatedBy: 'SYSTEM',
|
||||
errors: [],
|
||||
warnings: [],
|
||||
}
|
||||
|
||||
switch (checkpointId) {
|
||||
case 'CP-PROF':
|
||||
if (!state.companyProfile || !state.companyProfile.isComplete) {
|
||||
status.passed = false
|
||||
status.errors.push({
|
||||
ruleId: 'prof-complete',
|
||||
field: 'companyProfile',
|
||||
message: 'Unternehmensprofil muss vollständig ausgefüllt werden',
|
||||
severity: 'ERROR',
|
||||
})
|
||||
}
|
||||
break
|
||||
|
||||
case 'CP-UC':
|
||||
if (state.useCases.length === 0) {
|
||||
status.passed = false
|
||||
status.errors.push({
|
||||
ruleId: 'uc-min-count',
|
||||
field: 'useCases',
|
||||
message: 'Mindestens ein Anwendungsfall muss erstellt werden',
|
||||
severity: 'ERROR',
|
||||
})
|
||||
}
|
||||
break
|
||||
|
||||
case 'CP-SCAN':
|
||||
if (!state.screening || state.screening.status !== 'COMPLETED') {
|
||||
status.passed = false
|
||||
status.errors.push({
|
||||
ruleId: 'scan-complete',
|
||||
field: 'screening',
|
||||
message: 'Security Scan muss abgeschlossen sein',
|
||||
severity: 'ERROR',
|
||||
})
|
||||
}
|
||||
break
|
||||
|
||||
case 'CP-MOD':
|
||||
if (state.modules.length === 0) {
|
||||
status.passed = false
|
||||
status.errors.push({
|
||||
ruleId: 'mod-min-count',
|
||||
field: 'modules',
|
||||
message: 'Mindestens ein Modul muss zugewiesen werden',
|
||||
severity: 'ERROR',
|
||||
})
|
||||
}
|
||||
break
|
||||
|
||||
case 'CP-RISK': {
|
||||
const criticalRisks = state.risks.filter(
|
||||
r => r.severity === 'CRITICAL' || r.severity === 'HIGH'
|
||||
)
|
||||
const unmitigatedRisks = criticalRisks.filter(
|
||||
r => r.mitigation.length === 0
|
||||
)
|
||||
if (unmitigatedRisks.length > 0) {
|
||||
status.passed = false
|
||||
status.errors.push({
|
||||
ruleId: 'critical-risks-mitigated',
|
||||
field: 'risks',
|
||||
message: `${unmitigatedRisks.length} kritische Risiken ohne Mitigationsmaßnahmen`,
|
||||
severity: 'ERROR',
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return status
|
||||
}
|
||||
Reference in New Issue
Block a user