fix(admin-v2): Restore complete admin-v2 application

The admin-v2 application was incomplete in the repository. This commit
restores all missing components:

- Admin pages (76 pages): dashboard, ai, compliance, dsgvo, education,
  infrastructure, communication, development, onboarding, rbac
- SDK pages (45 pages): tom, dsfa, vvt, loeschfristen, einwilligungen,
  vendor-compliance, tom-generator, dsr, and more
- Developer portal (25 pages): API docs, SDK guides, frameworks
- All components, lib files, hooks, and types
- Updated package.json with all dependencies

The issue was caused by incomplete initial repository state - the full
admin-v2 codebase existed in backend/admin-v2 and docs-src/admin-v2
but was never fully synced to the main admin-v2 directory.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
BreakPilot Dev
2026-02-08 23:40:15 -08:00
parent f28244753f
commit 660295e218
385 changed files with 138126 additions and 3079 deletions

View File

@@ -0,0 +1,107 @@
import { NextRequest, NextResponse } from 'next/server'
import { TOMRulesEngine } from '@/lib/sdk/tom-generator/rules-engine'
import { TOMGeneratorState } from '@/lib/sdk/tom-generator/types'
/**
* TOM Generator Controls Evaluation API
*
* POST /api/sdk/v1/tom-generator/controls/evaluate - Evaluate controls for given state
*
* Request body:
* {
* state: TOMGeneratorState
* }
*
* Response:
* {
* evaluations: RulesEngineResult[]
* derivedTOMs: DerivedTOM[]
* summary: {
* total: number
* required: number
* recommended: number
* optional: number
* notApplicable: number
* }
* }
*/
export async function POST(request: NextRequest) {
try {
const body = await request.json()
const { state } = body
if (!state) {
return NextResponse.json(
{ success: false, error: 'state is required in request body' },
{ status: 400 }
)
}
// Parse dates in state
const parsedState: TOMGeneratorState = {
...state,
createdAt: new Date(state.createdAt),
updatedAt: new Date(state.updatedAt),
steps: state.steps?.map((step: { id: string; completed: boolean; data: unknown; validatedAt: string | null }) => ({
...step,
validatedAt: step.validatedAt ? new Date(step.validatedAt) : null,
})) || [],
documents: [],
derivedTOMs: [],
gapAnalysis: null,
exports: [],
}
// Initialize rules engine and evaluate
const engine = new TOMRulesEngine()
const evaluations = engine.evaluateControls(parsedState)
const derivedTOMs = engine.deriveAllTOMs(parsedState)
// Calculate summary
const summary = {
total: evaluations.length,
required: evaluations.filter((e) => e.applicability === 'REQUIRED').length,
recommended: evaluations.filter((e) => e.applicability === 'RECOMMENDED').length,
optional: evaluations.filter((e) => e.applicability === 'OPTIONAL').length,
notApplicable: evaluations.filter((e) => e.applicability === 'NOT_APPLICABLE').length,
}
// Group by category
const byCategory: Record<string, typeof evaluations> = {}
evaluations.forEach((e) => {
const category = e.controlId.split('-')[1] // Extract category from ID like TOM-AC-01
if (!byCategory[category]) {
byCategory[category] = []
}
byCategory[category].push(e)
})
return NextResponse.json({
success: true,
data: {
evaluations,
derivedTOMs,
summary,
byCategory,
},
})
} catch (error) {
console.error('Failed to evaluate controls:', error)
return NextResponse.json(
{ success: false, error: 'Failed to evaluate controls' },
{ status: 500 }
)
}
}
export async function OPTIONS() {
return NextResponse.json(
{ status: 'ok' },
{
headers: {
Allow: 'POST, OPTIONS',
},
}
)
}

View File

@@ -0,0 +1,128 @@
import { NextRequest, NextResponse } from 'next/server'
import {
getAllControls,
getControlById,
getControlsByCategory,
searchControls,
getCategories,
} from '@/lib/sdk/tom-generator/controls/loader'
import { ControlCategory } from '@/lib/sdk/tom-generator/types'
/**
* TOM Generator Controls API
*
* GET /api/sdk/v1/tom-generator/controls - List all controls
* GET /api/sdk/v1/tom-generator/controls?id=xxx - Get single control
* GET /api/sdk/v1/tom-generator/controls?category=xxx - Filter by category
* GET /api/sdk/v1/tom-generator/controls?search=xxx - Search controls
* GET /api/sdk/v1/tom-generator/controls?categories=true - Get categories list
*/
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)
const id = searchParams.get('id')
const category = searchParams.get('category')
const search = searchParams.get('search')
const categoriesOnly = searchParams.get('categories')
const language = (searchParams.get('language') || 'de') as 'de' | 'en'
// Get categories list
if (categoriesOnly === 'true') {
const categories = getCategories()
return NextResponse.json({
success: true,
data: categories,
})
}
// Get single control by ID
if (id) {
const control = getControlById(id)
if (!control) {
return NextResponse.json(
{ success: false, error: `Control not found: ${id}` },
{ status: 404 }
)
}
return NextResponse.json({
success: true,
data: {
...control,
// Return localized name and description
localizedName: control.name[language],
localizedDescription: control.description[language],
},
})
}
// Filter by category
if (category) {
const controls = getControlsByCategory(category as ControlCategory)
return NextResponse.json({
success: true,
data: controls.map((c) => ({
...c,
localizedName: c.name[language],
localizedDescription: c.description[language],
})),
meta: {
category,
count: controls.length,
},
})
}
// Search controls
if (search) {
const controls = searchControls(search, language)
return NextResponse.json({
success: true,
data: controls.map((c) => ({
...c,
localizedName: c.name[language],
localizedDescription: c.description[language],
})),
meta: {
query: search,
count: controls.length,
},
})
}
// Return all controls
const controls = getAllControls()
const categories = getCategories()
return NextResponse.json({
success: true,
data: controls.map((c) => ({
...c,
localizedName: c.name[language],
localizedDescription: c.description[language],
})),
meta: {
totalControls: controls.length,
categories: categories.length,
language,
},
})
} catch (error) {
console.error('Failed to fetch controls:', error)
return NextResponse.json(
{ success: false, error: 'Failed to fetch controls' },
{ status: 500 }
)
}
}
export async function OPTIONS() {
return NextResponse.json(
{ status: 'ok' },
{
headers: {
Allow: 'GET, OPTIONS',
},
}
)
}