import Link from 'next/link' import { type ControlsResponse, type ControlItem, provenanceLabel, provenanceBadgeClass, severityBadgeClass, splitByTier, } from '../_helpers' const BACKEND_URL = process.env.COMPLIANCE_BACKEND_URL || 'http://backend-compliance:8002' export const dynamic = 'force-dynamic' async function getControls(useCase: string): Promise { try { const res = await fetch( `${BACKEND_URL}/api/compliance/v1/controls/use-cases/${encodeURIComponent( useCase, )}/controls?tier=all&limit=200`, { cache: 'no-store' }, ) return res.ok ? ((await res.json()) as ControlsResponse) : null } catch { return null } } function ControlsTable({ rows }: { rows: ControlItem[] }) { return (
{rows.map((c) => ( ))}
Prüfaspekt Sub-Thema Schwere Herkunft
{c.title} {c.sub_topic || '—'} {c.severity ? ( {c.severity} ) : null} {provenanceLabel(c)}
) } export default async function UseCaseControlsPage({ params, }: { params: Promise<{ useCase: string }> }) { const { useCase } = await params const data = await getControls(useCase) if (!data) { return (
← Abdeckung
Keine atom-grain-Daten für „{useCase}" gefunden.
) } const { core, review } = splitByTier(data.controls) return (
Abdeckung / {data.label}

{data.label}

{data.core_count.toLocaleString('de-DE')} {' '} Kern-Pflichten ·{' '} {data.review_count.toLocaleString('de-DE')} {' '} zur fachlichen Prüfung

Kern-Pflichten ({core.length})

{core.length ? ( ) : (

)}

Zur fachlichen Prüfung ({review.length})

Breiter gefasste Aspekte — bewusst eher zu viel als zu wenig. Fachlich prüfen; nicht zutreffende lassen sich (künftig) als unanwendbar markieren.

{review.length ? ( ) : (

)}
{data.total > data.controls.length ? (

Angezeigt: erste {data.controls.length.toLocaleString('de-DE')} von{' '} {data.total.toLocaleString('de-DE')} — Sub-Thema-Filter folgt.

) : null}
) }