Services: Admin-Compliance, Backend-Compliance, AI-Compliance-SDK, Consent-SDK, Developer-Portal, PCA-Platform, DSMS Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
236 lines
5.6 KiB
TypeScript
236 lines
5.6 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
|
|
/**
|
|
* SDK Checkpoints API
|
|
*
|
|
* GET /api/sdk/v1/checkpoints - Get all checkpoint statuses
|
|
* POST /api/sdk/v1/checkpoints - Validate a checkpoint
|
|
*/
|
|
|
|
// Checkpoint definitions
|
|
const CHECKPOINTS = {
|
|
'CP-PROF': {
|
|
id: 'CP-PROF',
|
|
step: 'company-profile',
|
|
name: 'Unternehmensprofil Checkpoint',
|
|
type: 'REQUIRED',
|
|
blocksProgress: true,
|
|
requiresReview: 'NONE',
|
|
},
|
|
'CP-UC': {
|
|
id: 'CP-UC',
|
|
step: 'use-case-assessment',
|
|
name: 'Anwendungsfall Checkpoint',
|
|
type: 'REQUIRED',
|
|
blocksProgress: true,
|
|
requiresReview: 'NONE',
|
|
},
|
|
'CP-SCAN': {
|
|
id: 'CP-SCAN',
|
|
step: 'screening',
|
|
name: 'Screening Checkpoint',
|
|
type: 'REQUIRED',
|
|
blocksProgress: true,
|
|
requiresReview: 'NONE',
|
|
},
|
|
'CP-MOD': {
|
|
id: 'CP-MOD',
|
|
step: 'modules',
|
|
name: 'Modules Checkpoint',
|
|
type: 'REQUIRED',
|
|
blocksProgress: true,
|
|
requiresReview: 'NONE',
|
|
},
|
|
'CP-REQ': {
|
|
id: 'CP-REQ',
|
|
step: 'requirements',
|
|
name: 'Requirements Checkpoint',
|
|
type: 'REQUIRED',
|
|
blocksProgress: true,
|
|
requiresReview: 'NONE',
|
|
},
|
|
'CP-CTRL': {
|
|
id: 'CP-CTRL',
|
|
step: 'controls',
|
|
name: 'Controls Checkpoint',
|
|
type: 'REQUIRED',
|
|
blocksProgress: true,
|
|
requiresReview: 'DSB',
|
|
},
|
|
'CP-EVI': {
|
|
id: 'CP-EVI',
|
|
step: 'evidence',
|
|
name: 'Evidence Checkpoint',
|
|
type: 'RECOMMENDED',
|
|
blocksProgress: false,
|
|
requiresReview: 'NONE',
|
|
},
|
|
'CP-CHK': {
|
|
id: 'CP-CHK',
|
|
step: 'audit-checklist',
|
|
name: 'Checklist Checkpoint',
|
|
type: 'RECOMMENDED',
|
|
blocksProgress: false,
|
|
requiresReview: 'NONE',
|
|
},
|
|
'CP-RISK': {
|
|
id: 'CP-RISK',
|
|
step: 'risks',
|
|
name: 'Risk Matrix Checkpoint',
|
|
type: 'REQUIRED',
|
|
blocksProgress: true,
|
|
requiresReview: 'DSB',
|
|
},
|
|
'CP-AI': {
|
|
id: 'CP-AI',
|
|
step: 'ai-act',
|
|
name: 'AI Act Checkpoint',
|
|
type: 'REQUIRED',
|
|
blocksProgress: true,
|
|
requiresReview: 'LEGAL',
|
|
},
|
|
'CP-DSFA': {
|
|
id: 'CP-DSFA',
|
|
step: 'dsfa',
|
|
name: 'DSFA Checkpoint',
|
|
type: 'REQUIRED',
|
|
blocksProgress: true,
|
|
requiresReview: 'DSB',
|
|
},
|
|
'CP-TOM': {
|
|
id: 'CP-TOM',
|
|
step: 'tom',
|
|
name: 'TOMs Checkpoint',
|
|
type: 'REQUIRED',
|
|
blocksProgress: true,
|
|
requiresReview: 'NONE',
|
|
},
|
|
'CP-VVT': {
|
|
id: 'CP-VVT',
|
|
step: 'vvt',
|
|
name: 'VVT Checkpoint',
|
|
type: 'REQUIRED',
|
|
blocksProgress: true,
|
|
requiresReview: 'DSB',
|
|
},
|
|
}
|
|
|
|
export async function GET() {
|
|
try {
|
|
return NextResponse.json({
|
|
success: true,
|
|
checkpoints: CHECKPOINTS,
|
|
count: Object.keys(CHECKPOINTS).length,
|
|
})
|
|
} catch (error) {
|
|
console.error('Failed to get checkpoints:', error)
|
|
return NextResponse.json(
|
|
{ error: 'Failed to get checkpoints' },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
}
|
|
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
const body = await request.json()
|
|
const { checkpointId, state, context } = body
|
|
|
|
if (!checkpointId) {
|
|
return NextResponse.json(
|
|
{ error: 'checkpointId is required' },
|
|
{ status: 400 }
|
|
)
|
|
}
|
|
|
|
const checkpoint = CHECKPOINTS[checkpointId as keyof typeof CHECKPOINTS]
|
|
|
|
if (!checkpoint) {
|
|
return NextResponse.json(
|
|
{ error: 'Checkpoint not found', checkpointId },
|
|
{ status: 404 }
|
|
)
|
|
}
|
|
|
|
// Perform validation based on checkpoint
|
|
const errors: Array<{ ruleId: string; field: string; message: string; severity: string }> = []
|
|
const warnings: Array<{ ruleId: string; field: string; message: string; severity: string }> = []
|
|
|
|
// Basic validation rules
|
|
switch (checkpointId) {
|
|
case 'CP-UC':
|
|
if (!state?.useCases || state.useCases.length === 0) {
|
|
errors.push({
|
|
ruleId: 'uc-min-count',
|
|
field: 'useCases',
|
|
message: 'Mindestens ein Use Case muss erstellt werden',
|
|
severity: 'ERROR',
|
|
})
|
|
}
|
|
break
|
|
|
|
case 'CP-SCAN':
|
|
if (!state?.screening || state.screening.status !== 'COMPLETED') {
|
|
errors.push({
|
|
ruleId: 'scan-complete',
|
|
field: 'screening',
|
|
message: 'Security Scan muss abgeschlossen sein',
|
|
severity: 'ERROR',
|
|
})
|
|
}
|
|
break
|
|
|
|
case 'CP-MOD':
|
|
if (!state?.modules || state.modules.length === 0) {
|
|
errors.push({
|
|
ruleId: 'mod-min-count',
|
|
field: 'modules',
|
|
message: 'Mindestens ein Modul muss zugewiesen werden',
|
|
severity: 'ERROR',
|
|
})
|
|
}
|
|
break
|
|
|
|
case 'CP-RISK':
|
|
if (state?.risks) {
|
|
const criticalRisks = state.risks.filter(
|
|
(r: { severity: string; mitigation: unknown[] }) =>
|
|
(r.severity === 'CRITICAL' || r.severity === 'HIGH') && r.mitigation.length === 0
|
|
)
|
|
if (criticalRisks.length > 0) {
|
|
errors.push({
|
|
ruleId: 'critical-risks-mitigated',
|
|
field: 'risks',
|
|
message: `${criticalRisks.length} kritische Risiken ohne Mitigationsmaßnahmen`,
|
|
severity: 'ERROR',
|
|
})
|
|
}
|
|
}
|
|
break
|
|
}
|
|
|
|
const passed = errors.length === 0
|
|
|
|
const result = {
|
|
checkpointId,
|
|
passed,
|
|
validatedAt: new Date().toISOString(),
|
|
validatedBy: context?.userId || 'SYSTEM',
|
|
errors,
|
|
warnings,
|
|
checkpoint,
|
|
}
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
...result,
|
|
})
|
|
} catch (error) {
|
|
console.error('Failed to validate checkpoint:', error)
|
|
return NextResponse.json(
|
|
{ error: 'Failed to validate checkpoint' },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
}
|