feat(gci): add Gesamt-Compliance-Index scoring engine and dashboard
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 34s
CI / test-python-backend-compliance (push) Successful in 28s
CI / test-python-document-crawler (push) Successful in 24s
CI / test-python-dsms-gateway (push) Successful in 17s

Implements the 4-level GCI scoring model (Module -> Risk-Weighted -> Regulation Area -> Final GCI)
with DSGVO, NIS2, ISO 27001, and EU AI Act integration.

Backend:
- 9 Go files: engine, models, weights, validity, NIS2 roles/scoring, ISO mapping/gap-analysis, mock data
- GCI handlers with 13 API endpoints under /sdk/v1/gci/
- Routes registered in main.go

Frontend:
- TypeScript types, API client, Next.js API proxy
- Dashboard page with 6 tabs (Overview, Breakdown, NIS2, ISO 27001, Matrix, Audit Trail)
- Sidebar navigation entry

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Boenisch
2026-02-15 22:20:17 +01:00
parent 2d909a8f8e
commit 7a09086930
16 changed files with 2703 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
/**
* GCI API Client
* Communicates with the Go backend via Next.js API proxy at /api/sdk/v1/gci/*
*/
import type {
GCIResult,
GCIBreakdown,
GCIHistoryResponse,
GCIMatrixResponse,
NIS2Score,
NIS2Role,
ISOGapAnalysis,
WeightProfile,
} from './types'
const BASE_URL = '/api/sdk/v1/gci'
async function apiFetch<T>(path: string, options?: RequestInit): Promise<T> {
const res = await fetch(`${BASE_URL}${path}`, {
...options,
headers: {
'Content-Type': 'application/json',
'X-Tenant-ID': typeof window !== 'undefined'
? (localStorage.getItem('bp-tenant-id') || 'default')
: 'default',
...options?.headers,
},
})
if (!res.ok) {
const error = await res.json().catch(() => ({ error: res.statusText }))
throw new Error(error.error || `API Error: ${res.status}`)
}
return res.json()
}
/** GCI Score abrufen */
export async function getGCIScore(profile?: string): Promise<GCIResult> {
const params = profile ? `?profile=${profile}` : ''
return apiFetch<GCIResult>(`/score${params}`)
}
/** Detailliertes 4-Level Breakdown abrufen */
export async function getGCIBreakdown(profile?: string): Promise<GCIBreakdown> {
const params = profile ? `?profile=${profile}` : ''
return apiFetch<GCIBreakdown>(`/score/breakdown${params}`)
}
/** GCI History abrufen */
export async function getGCIHistory(): Promise<GCIHistoryResponse> {
return apiFetch<GCIHistoryResponse>('/score/history')
}
/** Compliance Matrix abrufen */
export async function getGCIMatrix(): Promise<GCIMatrixResponse> {
return apiFetch<GCIMatrixResponse>('/matrix')
}
/** Audit Trail abrufen */
export async function getGCIAuditTrail(profile?: string): Promise<{ tenant_id: string; gci_score: number; audit_trail: any[] }> {
const params = profile ? `?profile=${profile}` : ''
return apiFetch(`/audit-trail${params}`)
}
/** Gewichtungsprofile abrufen */
export async function getWeightProfiles(): Promise<{ profiles: WeightProfile[] }> {
return apiFetch<{ profiles: WeightProfile[] }>('/profiles')
}
/** NIS2 Score abrufen */
export async function getNIS2Score(): Promise<NIS2Score> {
return apiFetch<NIS2Score>('/nis2/score')
}
/** NIS2 Rollen auflisten */
export async function getNIS2Roles(): Promise<{ roles: NIS2Role[]; total: number }> {
return apiFetch<{ roles: NIS2Role[]; total: number }>('/nis2/roles')
}
/** NIS2 Rolle zuweisen */
export async function assignNIS2Role(roleId: string, userId: string): Promise<any> {
return apiFetch('/nis2/roles/assign', {
method: 'POST',
body: JSON.stringify({ role_id: roleId, user_id: userId }),
})
}
/** ISO Gap-Analyse abrufen */
export async function getISOGapAnalysis(): Promise<ISOGapAnalysis> {
return apiFetch<ISOGapAnalysis>('/iso/gap-analysis')
}
/** ISO Mappings abrufen */
export async function getISOMappings(category?: string): Promise<any> {
const params = category ? `?category=${category}` : ''
return apiFetch(`/iso/mappings${params}`)
}

View File

@@ -0,0 +1,246 @@
/**
* GCI (Gesamt-Compliance-Index) Types
* TypeScript definitions for the 4-level compliance scoring model
*/
// =============================================================================
// MATURITY LEVELS
// =============================================================================
export type MaturityLevel = 'OPTIMIZED' | 'MANAGED' | 'DEFINED' | 'REACTIVE' | 'HIGH_RISK'
export const MATURITY_INFO: Record<MaturityLevel, { label: string; color: string; bgColor: string; borderColor: string; description: string }> = {
OPTIMIZED: { label: 'Optimiert', color: 'text-green-700', bgColor: 'bg-green-100', borderColor: 'border-green-300', description: 'Kontinuierliche Verbesserung, proaktive Compliance' },
MANAGED: { label: 'Gesteuert', color: 'text-blue-700', bgColor: 'bg-blue-100', borderColor: 'border-blue-300', description: 'Messbare Prozesse, regelmaessige Reviews' },
DEFINED: { label: 'Definiert', color: 'text-yellow-700', bgColor: 'bg-yellow-100', borderColor: 'border-yellow-300', description: 'Dokumentierte Prozesse, erste Strukturen' },
REACTIVE: { label: 'Reaktiv', color: 'text-orange-700', bgColor: 'bg-orange-100', borderColor: 'border-orange-300', description: 'Ad-hoc Massnahmen, wenig Struktur' },
HIGH_RISK: { label: 'Hohes Risiko', color: 'text-red-700', bgColor: 'bg-red-100', borderColor: 'border-red-300', description: 'Erheblicher Handlungsbedarf, Compliance-Luecken' },
}
// =============================================================================
// LEVEL 1: MODULE SCORE
// =============================================================================
export interface ModuleScore {
module_id: string
module_name: string
assigned: number
completed: number
raw_score: number
validity_factor: number
final_score: number
risk_weight: number
category: string
}
// =============================================================================
// LEVEL 2: RISK-WEIGHTED AREA SCORE
// =============================================================================
export interface RiskWeightedScore {
area_id: string
area_name: string
modules: ModuleScore[]
weighted_sum: number
total_weight: number
area_score: number
}
// =============================================================================
// LEVEL 3: REGULATION AREA SCORE
// =============================================================================
export interface RegulationAreaScore {
regulation_id: string
regulation_name: string
score: number
weight: number
weighted_score: number
module_count: number
completed_count: number
}
// =============================================================================
// LEVEL 4: GCI RESULT
// =============================================================================
export interface AuditEntry {
timestamp: string
factor: string
description: string
value: number
impact: 'positive' | 'negative' | 'neutral'
}
export interface GCIResult {
tenant_id: string
gci_score: number
maturity_level: MaturityLevel
maturity_label: string
calculated_at: string
profile: string
area_scores: RegulationAreaScore[]
criticality_multiplier: number
incident_adjustment: number
audit_trail: AuditEntry[]
}
export interface GCIBreakdown extends GCIResult {
level1_modules: ModuleScore[]
level2_areas: RiskWeightedScore[]
}
// =============================================================================
// GCI HISTORY
// =============================================================================
export interface GCISnapshot {
tenant_id: string
score: number
maturity_level: MaturityLevel
area_scores: Record<string, number>
calculated_at: string
}
export interface GCIHistoryResponse {
tenant_id: string
snapshots: GCISnapshot[]
total: number
}
// =============================================================================
// COMPLIANCE MATRIX
// =============================================================================
export interface ComplianceMatrixEntry {
role: string
role_name: string
regulations: Record<string, number>
overall_score: number
required_modules: number
completed_modules: number
}
export interface GCIMatrixResponse {
tenant_id: string
matrix: ComplianceMatrixEntry[]
}
// =============================================================================
// NIS2
// =============================================================================
export interface NIS2Role {
id: string
name: string
description: string
mandatory_modules: string[]
priority: number
}
export interface NIS2AreaScore {
area_id: string
area_name: string
weight: number
score: number
weighted_score: number
}
export interface NIS2RoleScore {
role_id: string
role_name: string
assigned_users: number
completion_rate: number
modules_completed: number
modules_required: number
}
export interface NIS2Score {
tenant_id: string
overall_score: number
maturity_level: string
areas: NIS2AreaScore[]
role_scores: NIS2RoleScore[]
calculated_at: string
}
// =============================================================================
// ISO 27001
// =============================================================================
export interface ISOControl {
id: string
name: string
description: string
category_id: string
category_name: string
control_type: string
is_critical: boolean
sdk_modules: string[]
}
export interface ISOGap {
control_id: string
control_name: string
category: string
status: string
priority: string
recommendation: string
}
export interface ISOCategorySummary {
category_id: string
category_name: string
total_controls: number
covered_full: number
covered_partial: number
not_covered: number
}
export interface ISOGapAnalysis {
tenant_id: string
total_controls: number
covered_full: number
covered_partial: number
not_covered: number
coverage_percent: number
category_summaries: ISOCategorySummary[]
gaps: ISOGap[]
calculated_at: string
}
// =============================================================================
// WEIGHT PROFILES
// =============================================================================
export interface WeightProfile {
id: string
name: string
description: string
weights: Record<string, number>
}
// =============================================================================
// HELPERS
// =============================================================================
export function getScoreColor(score: number): string {
if (score >= 80) return 'text-green-600'
if (score >= 60) return 'text-yellow-600'
if (score >= 40) return 'text-orange-600'
return 'text-red-600'
}
export function getScoreBgColor(score: number): string {
if (score >= 80) return 'bg-green-500'
if (score >= 60) return 'bg-yellow-500'
if (score >= 40) return 'bg-orange-500'
return 'bg-red-500'
}
export function getScoreRingColor(score: number): string {
if (score >= 80) return '#22c55e'
if (score >= 60) return '#eab308'
if (score >= 40) return '#f97316'
return '#ef4444'
}