591cae5ebc
Reworks the advisor toward a Compliance Case Workspace (review feedback): - Rename user-facing "Quellen" -> "Evidence". - Evidence grouped by document/regulation family (count + expandable) — no more unsorted DSK/DSK/DPF/... jumble. - Human-readable regulation names via a display registry (DSK Sdm B51 -> "DSK Standard-Datenschutzmodell (SDM)" / Kapitel B51); generic, bridges G2. - Evidence summary "Antwort basiert auf" with meaningful counts; Regelwerke = distinct FAMILIES (fixes the inflated count). NO fabricated trust score (needs a defined basis). - Expanded mode = 3-column workspace (question+summary | answer | evidence, independent scroll) + history switcher; narrow mode stays stacked. - Prompt: push aggressive markdown structure (## per aspect, numbered phases). Deferred/coordinated on board: C8 diagrams (RAG contract), answer<->evidence coupling [1] (needs LLM citation anchors — phase 2), G1 retrieval relevance + G2 metadata (RAG). tsc clean, 17 vitest, check-loc 0. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
54 lines
2.2 KiB
TypeScript
54 lines
2.2 KiB
TypeScript
// Human-readable display for regulations. Maps messy codes/short-names to a stable FAMILY key +
|
||
// friendly label (+ chapter for multi-part works like the DSK SDM). Presentation layer only:
|
||
// it bridges G2 (clean RAG metadata) and keeps working once codes are clean. Extend the table freely.
|
||
|
||
import type { RegulationRef } from './evidence'
|
||
|
||
export interface RegulationDisplay {
|
||
familyKey: string // stable key used to GROUP evidence
|
||
familyLabel: string // human-readable regulation name
|
||
chapter?: string // e.g. "B51" for a DSK SDM building block
|
||
}
|
||
|
||
interface Rule {
|
||
test: RegExp
|
||
key: string
|
||
label: string
|
||
chapter?: RegExp
|
||
}
|
||
|
||
// Order matters: more specific patterns first.
|
||
const RULES: Rule[] = [
|
||
{
|
||
test: /dsk.?sdm|standard.?datenschutzmodell|(^|[^a-z])sdm([^a-z]|$)/i,
|
||
key: 'dsk_sdm',
|
||
label: 'DSK Standard-Datenschutzmodell (SDM)',
|
||
chapter: /\b([A-Z]\d{1,3})\b/,
|
||
},
|
||
{ test: /cyber.?resilience|(^|[^a-z])cra([^a-z]|$)/i, key: 'cra', label: 'Cyber Resilience Act (CRA)' },
|
||
{ test: /(^|[^a-z])nis.?2([^a-z]|$)/i, key: 'nis2', label: 'NIS2-Richtlinie' },
|
||
{ test: /data.?privacy.?framework|(^|[^a-z])dpf([^a-z]|$)/i, key: 'dpf', label: 'EU-US Data Privacy Framework' },
|
||
{ test: /maschinen|2023.?1230/i, key: 'maschinenvo', label: 'Maschinenverordnung (EU) 2023/1230' },
|
||
{ test: /ds.?gvo|gdpr/i, key: 'dsgvo', label: 'DSGVO – Datenschutz-Grundverordnung' },
|
||
{ test: /(^|[^a-z])bdsg([^a-z]|$)/i, key: 'bdsg', label: 'BDSG – Bundesdatenschutzgesetz' },
|
||
{ test: /tdddg|ttdsg/i, key: 'tddg', label: 'TDDDG (Digitale-Dienste-Datenschutz)' },
|
||
{ test: /edpb|edsa|(^|[^a-z])wp\s?\d+/i, key: 'edpb', label: 'EDPB / DSK Leitlinien' },
|
||
{ test: /(^|[^a-z])bsi([^a-z]|$)/i, key: 'bsi', label: 'BSI' },
|
||
]
|
||
|
||
export function resolveRegulation(reg: RegulationRef): RegulationDisplay {
|
||
const hay = `${reg.code || ''} ${reg.short || ''} ${reg.name || ''}`
|
||
for (const r of RULES) {
|
||
if (r.test.test(hay)) {
|
||
const chapter = r.chapter
|
||
? r.chapter.exec(reg.short || reg.code || '')?.[1] || undefined
|
||
: undefined
|
||
return { familyKey: r.key, familyLabel: r.label, chapter }
|
||
}
|
||
}
|
||
return {
|
||
familyKey: reg.code || reg.short || 'unknown',
|
||
familyLabel: reg.short || reg.name || reg.code || 'Regelwerk',
|
||
}
|
||
}
|