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,85 @@
/**
* Audit Sign-off API Route - Proxy to Backend
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
// Sign off an item
export async function PUT(
request: NextRequest,
{ params }: { params: Promise<{ sessionId: string; requirementId: string }> }
) {
try {
const { sessionId, requirementId } = await params
const body = await request.json()
const response = await fetch(
`${BACKEND_URL}/api/v1/compliance/audit/checklist/${sessionId}/items/${requirementId}/sign-off`,
{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
signal: AbortSignal.timeout(30000)
}
)
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Audit sign-off proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen' },
{ status: 503 }
)
}
}
// Get sign-off status
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ sessionId: string; requirementId: string }> }
) {
try {
const { sessionId, requirementId } = await params
const response = await fetch(
`${BACKEND_URL}/api/v1/compliance/audit/checklist/${sessionId}/items/${requirementId}`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
signal: AbortSignal.timeout(30000)
}
)
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Get sign-off proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen' },
{ status: 503 }
)
}
}

View File

@@ -0,0 +1,57 @@
/**
* Audit Checklist API Route - Proxy to Backend
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ sessionId: string }> }
) {
try {
const { sessionId } = await params
const { searchParams } = new URL(request.url)
const queryParams = new URLSearchParams()
const page = searchParams.get('page')
const page_size = searchParams.get('page_size')
const status_filter = searchParams.get('status_filter')
const regulation_filter = searchParams.get('regulation_filter')
const search = searchParams.get('search')
if (page) queryParams.set('page', page)
if (page_size) queryParams.set('page_size', page_size)
if (status_filter) queryParams.set('status_filter', status_filter)
if (regulation_filter) queryParams.set('regulation_filter', regulation_filter)
if (search) queryParams.set('search', search)
const url = `${BACKEND_URL}/api/v1/compliance/audit/checklist/${sessionId}${queryParams.toString() ? `?${queryParams}` : ''}`
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
signal: AbortSignal.timeout(30000)
})
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Audit checklist proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen' },
{ status: 503 }
)
}
}

View File

@@ -0,0 +1,46 @@
/**
* Control Review API Route - Proxy to Backend
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
export async function PUT(
request: NextRequest,
{ params }: { params: Promise<{ controlId: string }> }
) {
try {
const { controlId } = await params
const body = await request.json()
const response = await fetch(
`${BACKEND_URL}/api/v1/compliance/controls/${controlId}/review`,
{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
signal: AbortSignal.timeout(30000)
}
)
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Control review proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen' },
{ status: 503 }
)
}
}

View File

@@ -0,0 +1,54 @@
/**
* Compliance Controls API Route - Proxy to Backend
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)
const queryParams = new URLSearchParams()
// Forward query parameters
const domain = searchParams.get('domain')
const status = searchParams.get('status')
const search = searchParams.get('search')
const page = searchParams.get('page')
const page_size = searchParams.get('page_size')
if (domain) queryParams.set('domain', domain)
if (status) queryParams.set('status', status)
if (search) queryParams.set('search', search)
if (page) queryParams.set('page', page)
if (page_size) queryParams.set('page_size', page_size)
const url = `${BACKEND_URL}/api/v1/compliance/controls${queryParams.toString() ? `?${queryParams}` : ''}`
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
signal: AbortSignal.timeout(30000)
})
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Compliance controls proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen', controls: [] },
{ status: 503 }
)
}
}

View File

@@ -0,0 +1,36 @@
/**
* Compliance Executive Dashboard API Route - Proxy to Backend
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
export async function GET(request: NextRequest) {
try {
const response = await fetch(`${BACKEND_URL}/api/v1/compliance/dashboard/executive`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
signal: AbortSignal.timeout(30000)
})
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Executive dashboard proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen' },
{ status: 503 }
)
}
}

View File

@@ -0,0 +1,36 @@
/**
* Compliance Dashboard API Route - Proxy to Backend
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
export async function GET(request: NextRequest) {
try {
const response = await fetch(`${BACKEND_URL}/api/v1/compliance/dashboard`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
signal: AbortSignal.timeout(30000)
})
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Compliance dashboard proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen' },
{ status: 503 }
)
}
}

View File

@@ -0,0 +1,81 @@
/**
* Compliance Evidence API Route - Proxy to Backend
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)
const queryParams = new URLSearchParams()
const control_id = searchParams.get('control_id')
const evidence_type = searchParams.get('evidence_type')
const status = searchParams.get('status')
if (control_id) queryParams.set('control_id', control_id)
if (evidence_type) queryParams.set('evidence_type', evidence_type)
if (status) queryParams.set('status', status)
const url = `${BACKEND_URL}/api/v1/compliance/evidence${queryParams.toString() ? `?${queryParams}` : ''}`
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
signal: AbortSignal.timeout(30000)
})
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Compliance evidence proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen', evidence: [] },
{ status: 503 }
)
}
}
export async function POST(request: NextRequest) {
try {
const body = await request.json()
const response = await fetch(`${BACKEND_URL}/api/v1/compliance/evidence`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
signal: AbortSignal.timeout(30000)
})
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Create evidence proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen' },
{ status: 503 }
)
}
}

View File

@@ -0,0 +1,53 @@
/**
* Evidence Upload API Route - Proxy to Backend
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
export async function POST(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)
const queryParams = new URLSearchParams()
const control_id = searchParams.get('control_id')
const evidence_type = searchParams.get('evidence_type')
const title = searchParams.get('title')
const description = searchParams.get('description')
if (control_id) queryParams.set('control_id', control_id)
if (evidence_type) queryParams.set('evidence_type', evidence_type)
if (title) queryParams.set('title', title)
if (description) queryParams.set('description', description)
// Forward the FormData directly
const formData = await request.formData()
const response = await fetch(
`${BACKEND_URL}/api/v1/compliance/evidence/upload?${queryParams}`,
{
method: 'POST',
body: formData,
signal: AbortSignal.timeout(60000) // 60 seconds for file upload
}
)
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Evidence upload proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen' },
{ status: 503 }
)
}
}

View File

@@ -0,0 +1,44 @@
/**
* Compliance Module Detail API Route - Proxy to Backend
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ moduleId: string }> }
) {
try {
const { moduleId } = await params
const response = await fetch(
`${BACKEND_URL}/api/v1/compliance/modules/${moduleId}`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
signal: AbortSignal.timeout(30000)
}
)
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Module detail proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen' },
{ status: 503 }
)
}
}

View File

@@ -0,0 +1,36 @@
/**
* Compliance Modules Overview API Route - Proxy to Backend
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
export async function GET(request: NextRequest) {
try {
const response = await fetch(`${BACKEND_URL}/api/v1/compliance/modules/overview`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
signal: AbortSignal.timeout(30000)
})
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Modules overview proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen' },
{ status: 503 }
)
}
}

View File

@@ -0,0 +1,51 @@
/**
* Compliance Modules API Route - Proxy to Backend
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)
const queryParams = new URLSearchParams()
const service_type = searchParams.get('service_type')
const criticality = searchParams.get('criticality')
const processes_pii = searchParams.get('processes_pii')
const ai_components = searchParams.get('ai_components')
if (service_type) queryParams.set('service_type', service_type)
if (criticality) queryParams.set('criticality', criticality)
if (processes_pii) queryParams.set('processes_pii', processes_pii)
if (ai_components) queryParams.set('ai_components', ai_components)
const url = `${BACKEND_URL}/api/v1/compliance/modules${queryParams.toString() ? `?${queryParams}` : ''}`
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
signal: AbortSignal.timeout(30000)
})
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Compliance modules proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen', modules: [] },
{ status: 503 }
)
}
}

View File

@@ -0,0 +1,39 @@
/**
* Compliance Modules Seed API Route - Proxy to Backend
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
export async function POST(request: NextRequest) {
try {
const body = await request.json()
const response = await fetch(`${BACKEND_URL}/api/v1/compliance/modules/seed`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
signal: AbortSignal.timeout(60000) // 60 seconds for seeding
})
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Modules seed proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen' },
{ status: 503 }
)
}
}

View File

@@ -0,0 +1,220 @@
/**
* Compliance Regulations API Route - Proxy to Backend
*
* Returns all 21 regulations with source URLs to original documents
* Includes: GDPR, ePrivacy, TDDDG, SCC, DPF, AI Act, CRA, NIS2, EU CSA,
* Data Act, DGA, DSA, EAA, DSM, PLD, GPSR, BSI-TR-03161 (1-3), BSI C5, DORA
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
export async function GET(request: NextRequest) {
try {
const response = await fetch(`${BACKEND_URL}/api/v1/compliance/regulations`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
signal: AbortSignal.timeout(30000)
})
if (!response.ok) {
// If backend doesn't have this endpoint yet, return seed data
if (response.status === 404) {
return NextResponse.json({
regulations: getStaticRegulations()
})
}
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Regulations proxy error:', error)
// Return static data as fallback
return NextResponse.json({
regulations: getStaticRegulations()
})
}
}
// Static seed data with source URLs - matches regulations.py
function getStaticRegulations() {
return [
{
id: '1', code: 'GDPR', name: 'DSGVO',
full_name: 'Verordnung (EU) 2016/679 - Datenschutz-Grundverordnung',
regulation_type: 'eu_regulation',
source_url: 'https://eur-lex.europa.eu/eli/reg/2016/679/oj/eng',
description: 'Grundverordnung zum Schutz natuerlicher Personen bei der Verarbeitung personenbezogener Daten.',
is_active: true, requirement_count: 99,
},
{
id: '2', code: 'EPRIVACY', name: 'ePrivacy-Richtlinie',
full_name: 'Richtlinie 2002/58/EG',
regulation_type: 'eu_directive',
source_url: 'https://eur-lex.europa.eu/eli/dir/2002/58/oj/eng',
description: 'Datenschutz in der elektronischen Kommunikation, Cookies und Tracking.',
is_active: true, requirement_count: 25,
},
{
id: '3', code: 'TDDDG', name: 'TDDDG',
full_name: 'Telekommunikation-Digitale-Dienste-Datenschutz-Gesetz',
regulation_type: 'de_law',
source_url: 'https://www.gesetze-im-internet.de/ttdsg/',
description: 'Deutsche Umsetzung der ePrivacy-Richtlinie.',
is_active: true, requirement_count: 15,
},
{
id: '4', code: 'SCC', name: 'Standardvertragsklauseln',
full_name: 'Durchfuehrungsbeschluss (EU) 2021/914',
regulation_type: 'eu_regulation',
source_url: 'https://eur-lex.europa.eu/eli/dec_impl/2021/914/oj/eng',
description: 'Standardvertragsklauseln fuer Drittlandtransfers.',
is_active: true, requirement_count: 18,
},
{
id: '5', code: 'DPF', name: 'EU-US Data Privacy Framework',
full_name: 'Durchfuehrungsbeschluss (EU) 2023/1795',
regulation_type: 'eu_regulation',
source_url: 'https://eur-lex.europa.eu/eli/dec_impl/2023/1795/oj',
description: 'Angemessenheitsbeschluss fuer USA-Transfers.',
is_active: true, requirement_count: 12,
},
{
id: '6', code: 'AIACT', name: 'EU AI Act',
full_name: 'Verordnung (EU) 2024/1689 - KI-Verordnung',
regulation_type: 'eu_regulation',
source_url: 'https://eur-lex.europa.eu/eli/reg/2024/1689/oj/eng',
description: 'EU-Verordnung zur Regulierung von KI-Systemen nach Risikostufen.',
is_active: true, requirement_count: 85,
},
{
id: '7', code: 'CRA', name: 'Cyber Resilience Act',
full_name: 'Verordnung (EU) 2024/2847',
regulation_type: 'eu_regulation',
source_url: 'https://eur-lex.europa.eu/eli/reg/2024/2847/oj/eng',
description: 'Cybersicherheitsanforderungen, SBOM-Pflicht.',
is_active: true, requirement_count: 45,
},
{
id: '8', code: 'NIS2', name: 'NIS2-Richtlinie',
full_name: 'Richtlinie (EU) 2022/2555',
regulation_type: 'eu_directive',
source_url: 'https://eur-lex.europa.eu/eli/dir/2022/2555/oj/eng',
description: 'Cybersicherheit fuer wesentliche Einrichtungen.',
is_active: true, requirement_count: 46,
},
{
id: '9', code: 'EUCSA', name: 'EU Cybersecurity Act',
full_name: 'Verordnung (EU) 2019/881',
regulation_type: 'eu_regulation',
source_url: 'https://eur-lex.europa.eu/eli/reg/2019/881/oj/eng',
description: 'ENISA und Cybersicherheitszertifizierung.',
is_active: true, requirement_count: 35,
},
{
id: '10', code: 'DATAACT', name: 'Data Act',
full_name: 'Verordnung (EU) 2023/2854',
regulation_type: 'eu_regulation',
source_url: 'https://eur-lex.europa.eu/eli/reg/2023/2854/oj/eng',
description: 'Fairer Datenzugang, IoT-Daten, Cloud-Wechsel.',
is_active: true, requirement_count: 42,
},
{
id: '11', code: 'DGA', name: 'Data Governance Act',
full_name: 'Verordnung (EU) 2022/868',
regulation_type: 'eu_regulation',
source_url: 'https://eur-lex.europa.eu/eli/reg/2022/868/oj/eng',
description: 'Weiterverwendung oeffentlicher Daten.',
is_active: true, requirement_count: 35,
},
{
id: '12', code: 'DSA', name: 'Digital Services Act',
full_name: 'Verordnung (EU) 2022/2065',
regulation_type: 'eu_regulation',
source_url: 'https://eur-lex.europa.eu/eli/reg/2022/2065/oj/eng',
description: 'Digitale Dienste, Transparenzpflichten.',
is_active: true, requirement_count: 93,
},
{
id: '13', code: 'EAA', name: 'European Accessibility Act',
full_name: 'Richtlinie (EU) 2019/882',
regulation_type: 'eu_directive',
source_url: 'https://eur-lex.europa.eu/eli/dir/2019/882/oj/eng',
description: 'Barrierefreiheit digitaler Produkte.',
is_active: true, requirement_count: 25,
},
{
id: '14', code: 'DSM', name: 'DSM-Urheberrechtsrichtlinie',
full_name: 'Richtlinie (EU) 2019/790',
regulation_type: 'eu_directive',
source_url: 'https://eur-lex.europa.eu/eli/dir/2019/790/oj/eng',
description: 'Urheberrecht, Text- und Data-Mining.',
is_active: true, requirement_count: 22,
},
{
id: '15', code: 'PLD', name: 'Produkthaftungsrichtlinie',
full_name: 'Richtlinie (EU) 2024/2853',
regulation_type: 'eu_directive',
source_url: 'https://eur-lex.europa.eu/eli/dir/2024/2853/oj/eng',
description: 'Produkthaftung inkl. Software und KI.',
is_active: true, requirement_count: 18,
},
{
id: '16', code: 'GPSR', name: 'General Product Safety',
full_name: 'Verordnung (EU) 2023/988',
regulation_type: 'eu_regulation',
source_url: 'https://eur-lex.europa.eu/eli/reg/2023/988/oj/eng',
description: 'Allgemeine Produktsicherheit.',
is_active: true, requirement_count: 30,
},
{
id: '17', code: 'BSI-TR-03161-1', name: 'BSI-TR-03161 Teil 1',
full_name: 'BSI Technische Richtlinie - Allgemeine Anforderungen',
regulation_type: 'bsi_standard',
source_url: 'https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Publikationen/TechnischeRichtlinien/TR03161/BSI-TR-03161-1.html',
description: 'Allgemeine Sicherheitsanforderungen (45 Pruefaspekte).',
is_active: true, requirement_count: 45,
},
{
id: '18', code: 'BSI-TR-03161-2', name: 'BSI-TR-03161 Teil 2',
full_name: 'BSI Technische Richtlinie - Web-Anwendungen',
regulation_type: 'bsi_standard',
source_url: 'https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Publikationen/TechnischeRichtlinien/TR03161/BSI-TR-03161-2.html',
description: 'Web-Sicherheit (40 Pruefaspekte).',
is_active: true, requirement_count: 40,
},
{
id: '19', code: 'BSI-TR-03161-3', name: 'BSI-TR-03161 Teil 3',
full_name: 'BSI Technische Richtlinie - Hintergrundsysteme',
regulation_type: 'bsi_standard',
source_url: 'https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Publikationen/TechnischeRichtlinien/TR03161/BSI-TR-03161-3.html',
description: 'Backend-Sicherheit (35 Pruefaspekte).',
is_active: true, requirement_count: 35,
},
{
id: '20', code: 'BSI-C5', name: 'BSI C5',
full_name: 'Cloud Computing Compliance Criteria Catalogue',
regulation_type: 'bsi_standard',
source_url: 'https://www.bsi.bund.de/DE/Themen/Unternehmen-und-Organisationen/Informationen-und-Empfehlungen/Empfehlungen-nach-Angriffszielen/Cloud-Computing/Kriterienkatalog-C5/kriterienkatalog-c5_node.html',
description: 'Deutscher Cloud-Sicherheitsstandard mit 121 Kriterien in 17 Bereichen (OIS, SP, HR, AM, PS, OPS, COS, IDM, CRY, SIM, BCM, COM, SA, SUA, PI).',
is_active: true, requirement_count: 121,
},
{
id: '21', code: 'DORA', name: 'DORA',
full_name: 'Verordnung (EU) 2022/2554 - Digital Operational Resilience Act',
regulation_type: 'eu_regulation',
source_url: 'https://eur-lex.europa.eu/eli/reg/2022/2554/oj/deu',
description: 'EU-Verordnung fuer digitale operationale Resilienz im Finanzsektor. IKT-Risikomanagement, Incident-Reporting, Resilienztests, Drittparteienrisiko.',
is_active: true, requirement_count: 64,
},
]
}

View File

@@ -0,0 +1,109 @@
/**
* Compliance Requirements API Route - Proxy to Backend
*
* Returns requirements for a specific regulation with implementation status
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
export async function GET(request: NextRequest) {
try {
const searchParams = request.nextUrl.searchParams
const regulationCode = searchParams.get('regulation_code')
if (!regulationCode) {
return NextResponse.json(
{ error: 'regulation_code parameter required' },
{ status: 400 }
)
}
// Build query string for backend
const params = new URLSearchParams()
params.set('regulation_code', regulationCode)
if (searchParams.get('status')) params.set('status', searchParams.get('status')!)
if (searchParams.get('priority')) params.set('priority', searchParams.get('priority')!)
if (searchParams.get('search')) params.set('search', searchParams.get('search')!)
const response = await fetch(
`${BACKEND_URL}/api/v1/compliance/requirements?${params}`,
{
method: 'GET',
headers: { 'Content-Type': 'application/json' },
signal: AbortSignal.timeout(30000)
}
)
if (!response.ok) {
// Return static BSI data as fallback if backend not available
if (response.status === 404 && regulationCode.startsWith('BSI')) {
return NextResponse.json({
requirements: getBSIRequirements(regulationCode)
})
}
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Requirements proxy error:', error)
// Return fallback data for BSI
const regulationCode = request.nextUrl.searchParams.get('regulation_code')
if (regulationCode?.startsWith('BSI')) {
return NextResponse.json({
requirements: getBSIRequirements(regulationCode)
})
}
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen', requirements: [] },
{ status: 503 }
)
}
}
// Static BSI requirements as fallback (subset)
function getBSIRequirements(code: string) {
if (code === 'BSI-TR-03161-1') {
return [
{ id: '1', regulation_code: code, article: 'O.Purp_1', title: 'Zweckbindung', description: 'Anwendungszweck klar definiert', implementation_status: 'implemented', priority: 1, controls_count: 2 },
{ id: '2', regulation_code: code, article: 'O.Data_1', title: 'Datenminimierung', description: 'Nur notwendige Daten erheben', implementation_status: 'implemented', priority: 1, controls_count: 3 },
{ id: '3', regulation_code: code, article: 'O.Auth_1', title: 'Authentifizierung', description: 'Sichere Authentifizierungsmechanismen', implementation_status: 'verified', priority: 1, controls_count: 4 },
{ id: '4', regulation_code: code, article: 'O.Auth_2', title: 'Passwortrichtlinie', description: 'Starke Passwoerter erzwingen', implementation_status: 'implemented', priority: 1, controls_count: 2 },
{ id: '5', regulation_code: code, article: 'O.Cryp_1', title: 'TLS-Verschluesselung', description: 'TLS 1.2+ fuer Transport', implementation_status: 'verified', priority: 1, controls_count: 2 },
{ id: '6', regulation_code: code, article: 'O.Cryp_2', title: 'Encryption at Rest', description: 'Sensible Daten verschluesseln', implementation_status: 'implemented', priority: 1, controls_count: 2 },
{ id: '7', regulation_code: code, article: 'O.Priv_1', title: 'Datenschutzerklaerung', description: 'Transparente Information', implementation_status: 'verified', priority: 1, controls_count: 1 },
{ id: '8', regulation_code: code, article: 'O.Log_1', title: 'Security Logging', description: 'Sicherheitsereignisse protokollieren', implementation_status: 'in_progress', priority: 1, controls_count: 2 },
]
}
if (code === 'BSI-TR-03161-2') {
return [
{ id: '20', regulation_code: code, article: 'O.Sess_1', title: 'Session-Timeout', description: 'Automatische Sitzungsbeendigung', implementation_status: 'implemented', priority: 1, controls_count: 2 },
{ id: '21', regulation_code: code, article: 'O.Input_1', title: 'Eingabevalidierung', description: 'Alle Eingaben validieren', implementation_status: 'verified', priority: 1, controls_count: 3 },
{ id: '22', regulation_code: code, article: 'O.SQL_1', title: 'SQL-Injection Schutz', description: 'Prepared Statements', implementation_status: 'verified', priority: 1, controls_count: 2 },
{ id: '23', regulation_code: code, article: 'O.XSS_1', title: 'XSS-Schutz', description: 'Output Encoding', implementation_status: 'verified', priority: 1, controls_count: 3 },
{ id: '24', regulation_code: code, article: 'O.CSRF_1', title: 'CSRF-Schutz', description: 'Anti-CSRF Token', implementation_status: 'implemented', priority: 1, controls_count: 2 },
{ id: '25', regulation_code: code, article: 'O.Head_1', title: 'Security Headers', description: 'X-Content-Type-Options', implementation_status: 'verified', priority: 1, controls_count: 1 },
{ id: '26', regulation_code: code, article: 'O.API_1', title: 'API-Authentifizierung', description: 'JWT/OAuth', implementation_status: 'verified', priority: 1, controls_count: 2 },
{ id: '27', regulation_code: code, article: 'O.API_2', title: 'Rate Limiting', description: 'Anfragen begrenzen', implementation_status: 'implemented', priority: 1, controls_count: 1 },
]
}
if (code === 'BSI-TR-03161-3') {
return [
{ id: '40', regulation_code: code, article: 'O.Arch_1', title: 'Defense in Depth', description: 'Mehrschichtige Sicherheit', implementation_status: 'implemented', priority: 1, controls_count: 3 },
{ id: '41', regulation_code: code, article: 'O.DB_1', title: 'Datenbank-Sicherheit', description: 'DB abhaerten', implementation_status: 'implemented', priority: 1, controls_count: 2 },
{ id: '42', regulation_code: code, article: 'O.Cont_1', title: 'Container-Sicherheit', description: 'Images scannen', implementation_status: 'in_progress', priority: 1, controls_count: 2 },
{ id: '43', regulation_code: code, article: 'O.Sec_1', title: 'Secrets Management', description: 'Zentrale Secrets-Verwaltung', implementation_status: 'verified', priority: 1, controls_count: 2 },
{ id: '44', regulation_code: code, article: 'O.Mon_1', title: 'Zentrale Logs', description: 'Log-Aggregation', implementation_status: 'implemented', priority: 1, controls_count: 1 },
{ id: '45', regulation_code: code, article: 'O.CI_1', title: 'Pipeline-Sicherheit', description: 'CI/CD absichern', implementation_status: 'in_progress', priority: 1, controls_count: 2 },
{ id: '46', regulation_code: code, article: 'O.DR_1', title: 'Backup-Strategie', description: '3-2-1 Backup-Regel', implementation_status: 'implemented', priority: 1, controls_count: 1 },
]
}
return []
}

View File

@@ -0,0 +1,83 @@
/**
* Risk Update API Route - Proxy to Backend
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
export async function PUT(
request: NextRequest,
{ params }: { params: Promise<{ riskId: string }> }
) {
try {
const { riskId } = await params
const body = await request.json()
const response = await fetch(
`${BACKEND_URL}/api/v1/compliance/risks/${riskId}`,
{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
signal: AbortSignal.timeout(30000)
}
)
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Risk update proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen' },
{ status: 503 }
)
}
}
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ riskId: string }> }
) {
try {
const { riskId } = await params
const response = await fetch(
`${BACKEND_URL}/api/v1/compliance/risks/${riskId}`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
signal: AbortSignal.timeout(30000)
}
)
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Get risk proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen' },
{ status: 503 }
)
}
}

View File

@@ -0,0 +1,81 @@
/**
* Compliance Risks API Route - Proxy to Backend
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)
const queryParams = new URLSearchParams()
const level = searchParams.get('level')
const status = searchParams.get('status')
const category = searchParams.get('category')
if (level) queryParams.set('level', level)
if (status) queryParams.set('status', status)
if (category) queryParams.set('category', category)
const url = `${BACKEND_URL}/api/v1/compliance/risks${queryParams.toString() ? `?${queryParams}` : ''}`
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
signal: AbortSignal.timeout(30000)
})
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Compliance risks proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen', risks: [] },
{ status: 503 }
)
}
}
export async function POST(request: NextRequest) {
try {
const body = await request.json()
const response = await fetch(`${BACKEND_URL}/api/v1/compliance/risks`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
signal: AbortSignal.timeout(30000)
})
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Create risk proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen' },
{ status: 503 }
)
}
}

View File

@@ -0,0 +1,39 @@
/**
* Compliance Seed API Route - Proxy to Backend
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
export async function POST(request: NextRequest) {
try {
const body = await request.json()
const response = await fetch(`${BACKEND_URL}/api/v1/compliance/seed`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
signal: AbortSignal.timeout(60000) // 60s timeout for seeding
})
if (!response.ok) {
const errorText = await response.text()
return NextResponse.json(
{ error: `Backend Error: ${response.status}`, details: errorText },
{ status: response.status }
)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Compliance seed proxy error:', error)
return NextResponse.json(
{ error: 'Verbindung zum Backend fehlgeschlagen' },
{ status: 503 }
)
}
}