feat(regulations): Automatische Ableitung anwendbarer Gesetze & Aufsichtsbehoerden
Some checks failed
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) Failing after 35s
CI / test-python-backend-compliance (push) Successful in 37s
CI / test-python-document-crawler (push) Successful in 27s
CI / test-python-dsms-gateway (push) Successful in 21s

Nach Abschluss von Profil + Scope werden jetzt automatisch die anwendbaren
Regulierungen (DSGVO, NIS2, AI Act, DORA) ermittelt und die zustaendigen
Aufsichtsbehoerden (Landes-DSB, BSI, BaFin) aus Bundesland + Branche abgeleitet.

- Neues scope-to-facts.ts: Mapping CompanyProfile+Scope → Go SDK Payload
- Neues supervisory-authority-resolver.ts: 16 Landes-DSB + nationale Behoerden
- ScopeDecisionTab: Regulierungs-Report mit Aufsichtsbehoerden-Karten
- Obligations-Seite: Echte Daten statt Dummy in handleAutoProfiling()
- Neue Types: ApplicableRegulation, RegulationAssessmentResult, SupervisoryAuthorityInfo

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-10 10:29:24 +01:00
parent fa4cda7627
commit 5da93c5d10
6 changed files with 665 additions and 16 deletions

View File

@@ -12,7 +12,9 @@ import {
import type {
ComplianceScopeState,
ScopeProfilingAnswer,
ScopeDecision
ScopeDecision,
ApplicableRegulation,
SupervisoryAuthorityInfo
} from '@/lib/sdk/compliance-scope-types'
import {
createEmptyScopeState,
@@ -20,6 +22,8 @@ import {
} from '@/lib/sdk/compliance-scope-types'
import { complianceScopeEngine } from '@/lib/sdk/compliance-scope-engine'
import { getAllQuestions } from '@/lib/sdk/compliance-scope-profiling'
import { buildAssessmentPayload } from '@/lib/sdk/scope-to-facts'
import { resolveAuthorities } from '@/lib/sdk/supervisory-authority-resolver'
type TabId = 'overview' | 'wizard' | 'decision' | 'export'
@@ -49,6 +53,11 @@ export default function ComplianceScopePage() {
const [isLoading, setIsLoading] = useState(true)
const [isEvaluating, setIsEvaluating] = useState(false)
// Regulation assessment state
const [applicableRegulations, setApplicableRegulations] = useState<ApplicableRegulation[]>([])
const [supervisoryAuthorities, setSupervisoryAuthorities] = useState<SupervisoryAuthorityInfo[]>([])
const [regulationAssessmentLoading, setRegulationAssessmentLoading] = useState(false)
// Load from SDK context first (persisted via State API), then localStorage as fallback.
// Runs ONCE on mount only — empty deps breaks the dispatch→sdkState→setScopeState→dispatch loop.
useEffect(() => {
@@ -75,6 +84,14 @@ export default function ComplianceScopePage() {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
// Fetch regulation assessment if decision exists on mount
useEffect(() => {
if (!isLoading && scopeState.decision && applicableRegulations.length === 0 && sdkState.companyProfile) {
fetchRegulationAssessment(scopeState.decision)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isLoading])
// Save to localStorage and SDK context whenever state changes
useEffect(() => {
if (!isLoading) {
@@ -96,6 +113,41 @@ export default function ComplianceScopePage() {
}))
}, [])
// Fetch regulation assessment from Go AI SDK
const fetchRegulationAssessment = useCallback(async (decision: ScopeDecision) => {
const profile = sdkState.companyProfile
if (!profile) return
setRegulationAssessmentLoading(true)
try {
const payload = buildAssessmentPayload(profile, scopeState.answers, decision)
const res = await fetch('/api/sdk/v1/ucca/obligations/assess-from-scope', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
})
if (!res.ok) throw new Error(`HTTP ${res.status}`)
const data = await res.json()
// Set applicable regulations from response
const regs: ApplicableRegulation[] = data.overview?.applicable_regulations || data.applicable_regulations || []
setApplicableRegulations(regs)
// Derive supervisory authorities
const regIds = regs.map(r => r.id)
const authorities = resolveAuthorities(
profile.headquartersState,
profile.headquartersCountry || 'DE',
regIds
)
setSupervisoryAuthorities(authorities)
} catch (error) {
console.error('Failed to fetch regulation assessment:', error)
} finally {
setRegulationAssessmentLoading(false)
}
}, [sdkState.companyProfile, scopeState.answers])
// Handle evaluate button click
const handleEvaluate = useCallback(async () => {
setIsEvaluating(true)
@@ -112,13 +164,15 @@ export default function ComplianceScopePage() {
// Switch to decision tab to show results
setActiveTab('decision')
// Fetch regulation assessment in the background
fetchRegulationAssessment(decision)
} catch (error) {
console.error('Failed to evaluate compliance scope:', error)
// Optionally show error toast/notification
} finally {
setIsEvaluating(false)
}
}, [scopeState.answers])
}, [scopeState.answers, fetchRegulationAssessment])
// Handle start profiling from overview
const handleStartProfiling = useCallback(() => {
@@ -283,6 +337,10 @@ export default function ComplianceScopePage() {
canEvaluate={canEvaluate}
onEvaluate={handleEvaluate}
isEvaluating={isEvaluating}
applicableRegulations={applicableRegulations}
supervisoryAuthorities={supervisoryAuthorities}
regulationAssessmentLoading={regulationAssessmentLoading}
onGoToObligations={() => { window.location.href = '/sdk/obligations' }}
/>
)}