Files
breakpilot-compliance/admin-compliance/lib/sdk/advisor/regulation-display.ts
T
Benjamin Admin 591cae5ebc feat(advisor): Case Workspace v2 — Evidence grouping, human names, 3-column, summary
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>
2026-07-01 10:38:06 +02:00

54 lines
2.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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',
}
}