From 5fad2d420ddc2644250a41d614a405129886efcc Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Wed, 15 Apr 2026 20:47:54 +0200 Subject: [PATCH] test+docs(rag): Tests und Entwicklerdoku fuer RAG Landkarte - 44 Vitest-Tests: JSON-Struktur, Branchen-Zuordnung, Applicability Notes, Dokumenttyp-Verteilung, keine Duplikate - MkDocs-Seite: Architektur, 10 Branchen, Zuordnungslogik, Integration in andere Projekte, Datenquellen Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ai/rag/__tests__/rag-documents.test.ts | 252 ++++++++++++++++++ .../services/klausur-service/RAG-Landkarte.md | 204 ++++++++++++++ mkdocs.yml | 1 + 3 files changed, 457 insertions(+) create mode 100644 admin-lehrer/app/(admin)/ai/rag/__tests__/rag-documents.test.ts create mode 100644 docs-src/services/klausur-service/RAG-Landkarte.md diff --git a/admin-lehrer/app/(admin)/ai/rag/__tests__/rag-documents.test.ts b/admin-lehrer/app/(admin)/ai/rag/__tests__/rag-documents.test.ts new file mode 100644 index 0000000..f61f57b --- /dev/null +++ b/admin-lehrer/app/(admin)/ai/rag/__tests__/rag-documents.test.ts @@ -0,0 +1,252 @@ +import { describe, it, expect } from 'vitest' +import ragData from '../rag-documents.json' + +/** + * Tests fuer rag-documents.json — Branchen-Regulierungs-Matrix + * + * Validiert die JSON-Struktur, Branchen-Zuordnung und Datenintegritaet + * der 320 Dokumente fuer die RAG Landkarte. + */ + +const VALID_INDUSTRY_IDS = ragData.industries.map((i: any) => i.id) +const VALID_DOC_TYPE_IDS = ragData.doc_types.map((dt: any) => dt.id) + +describe('rag-documents.json — Struktur', () => { + it('sollte doc_types, industries und documents enthalten', () => { + expect(ragData).toHaveProperty('doc_types') + expect(ragData).toHaveProperty('industries') + expect(ragData).toHaveProperty('documents') + expect(Array.isArray(ragData.doc_types)).toBe(true) + expect(Array.isArray(ragData.industries)).toBe(true) + expect(Array.isArray(ragData.documents)).toBe(true) + }) + + it('sollte genau 10 Branchen haben (VDMA/VDA/BDI)', () => { + expect(ragData.industries).toHaveLength(10) + const ids = ragData.industries.map((i: any) => i.id) + expect(ids).toContain('automotive') + expect(ids).toContain('maschinenbau') + expect(ids).toContain('elektrotechnik') + expect(ids).toContain('chemie') + expect(ids).toContain('metall') + expect(ids).toContain('energie') + expect(ids).toContain('transport') + expect(ids).toContain('handel') + expect(ids).toContain('konsumgueter') + expect(ids).toContain('bau') + }) + + it('sollte keine Pseudo-Branchen enthalten (IoT, KI, HR, KRITIS, etc.)', () => { + const ids = ragData.industries.map((i: any) => i.id) + expect(ids).not.toContain('iot') + expect(ids).not.toContain('ai') + expect(ids).not.toContain('hr') + expect(ids).not.toContain('kritis') + expect(ids).not.toContain('ecommerce') + expect(ids).not.toContain('tech') + expect(ids).not.toContain('media') + expect(ids).not.toContain('public') + }) + + it('sollte 17 Dokumenttypen haben', () => { + expect(ragData.doc_types.length).toBe(17) + }) + + it('sollte mindestens 300 Dokumente haben', () => { + expect(ragData.documents.length).toBeGreaterThanOrEqual(300) + }) + + it('sollte jede Branche name und icon haben', () => { + ragData.industries.forEach((ind: any) => { + expect(ind).toHaveProperty('id') + expect(ind).toHaveProperty('name') + expect(ind).toHaveProperty('icon') + expect(ind.name.length).toBeGreaterThan(0) + }) + }) + + it('sollte jeden doc_type mit id, label, icon und sort haben', () => { + ragData.doc_types.forEach((dt: any) => { + expect(dt).toHaveProperty('id') + expect(dt).toHaveProperty('label') + expect(dt).toHaveProperty('icon') + expect(dt).toHaveProperty('sort') + }) + }) +}) + +describe('rag-documents.json — Dokument-Validierung', () => { + it('sollte keine doppelten Codes haben', () => { + const codes = ragData.documents.map((d: any) => d.code) + const unique = new Set(codes) + expect(unique.size).toBe(codes.length) + }) + + it('sollte Pflichtfelder bei jedem Dokument haben', () => { + ragData.documents.forEach((doc: any) => { + expect(doc).toHaveProperty('code') + expect(doc).toHaveProperty('name') + expect(doc).toHaveProperty('doc_type') + expect(doc).toHaveProperty('industries') + expect(doc).toHaveProperty('in_rag') + expect(doc).toHaveProperty('rag_collection') + expect(doc.code.length).toBeGreaterThan(0) + expect(doc.name.length).toBeGreaterThan(0) + expect(Array.isArray(doc.industries)).toBe(true) + }) + }) + + it('sollte nur gueltige doc_type IDs verwenden', () => { + ragData.documents.forEach((doc: any) => { + expect(VALID_DOC_TYPE_IDS).toContain(doc.doc_type) + }) + }) + + it('sollte nur gueltige industry IDs verwenden (oder "all")', () => { + ragData.documents.forEach((doc: any) => { + doc.industries.forEach((ind: string) => { + if (ind !== 'all') { + expect(VALID_INDUSTRY_IDS).toContain(ind) + } + }) + }) + }) + + it('sollte gueltige rag_collection Namen verwenden', () => { + const validCollections = [ + 'bp_compliance_ce', + 'bp_compliance_gesetze', + 'bp_compliance_datenschutz', + 'bp_dsfa_corpus', + 'bp_legal_templates', + 'bp_compliance_recht', + 'bp_nibis_eh', + ] + ragData.documents.forEach((doc: any) => { + expect(validCollections).toContain(doc.rag_collection) + }) + }) +}) + +describe('rag-documents.json — Branchen-Zuordnungslogik', () => { + const findDoc = (code: string) => ragData.documents.find((d: any) => d.code === code) + + describe('Horizontale Regulierungen (alle Branchen)', () => { + const horizontalCodes = [ + 'GDPR', 'BDSG_FULL', 'EPRIVACY', 'TDDDG', 'AIACT', 'CRA', + 'NIS2', 'GPSR', 'PLD', 'EUCSA', 'DATAACT', + ] + + horizontalCodes.forEach((code) => { + it(`${code} sollte fuer alle Branchen gelten`, () => { + const doc = findDoc(code) + if (doc) { + expect(doc.industries).toContain('all') + } + }) + }) + }) + + describe('Sektorspezifische Regulierungen', () => { + it('Maschinenverordnung sollte Maschinenbau, Automotive, Elektrotechnik enthalten', () => { + const doc = findDoc('MACHINERY_REG') + if (doc) { + expect(doc.industries).toContain('maschinenbau') + expect(doc.industries).toContain('automotive') + expect(doc.industries).toContain('elektrotechnik') + expect(doc.industries).not.toContain('all') + } + }) + + it('ElektroG sollte Elektrotechnik und Automotive enthalten', () => { + const doc = findDoc('DE_ELEKTROG') + if (doc) { + expect(doc.industries).toContain('elektrotechnik') + expect(doc.industries).toContain('automotive') + } + }) + + it('BattDG sollte Automotive und Elektrotechnik enthalten', () => { + const doc = findDoc('DE_BATTDG') + if (doc) { + expect(doc.industries).toContain('automotive') + expect(doc.industries).toContain('elektrotechnik') + } + }) + + it('ENISA ICS/SCADA sollte Energie, Maschinenbau, Chemie enthalten', () => { + const doc = findDoc('ENISA_ICS_SCADA') + if (doc) { + expect(doc.industries).toContain('energie') + expect(doc.industries).toContain('maschinenbau') + expect(doc.industries).toContain('chemie') + } + }) + }) + + describe('Nicht zutreffende Regulierungen (Finanz/Medizin/Plattformen)', () => { + const emptyIndustryCodes = ['DORA', 'PSD2', 'MiCA', 'AMLR', 'EHDS', 'DSA', 'DMA', 'MDR'] + + emptyIndustryCodes.forEach((code) => { + it(`${code} sollte keine Branchen-Zuordnung haben`, () => { + const doc = findDoc(code) + if (doc) { + expect(doc.industries).toHaveLength(0) + } + }) + }) + }) + + describe('BSI-TR-03161 (DiGA) sollte nicht zutreffend sein', () => { + ['BSI-TR-03161-1', 'BSI-TR-03161-2', 'BSI-TR-03161-3'].forEach((code) => { + it(`${code} sollte keine Branchen-Zuordnung haben`, () => { + const doc = findDoc(code) + if (doc) { + expect(doc.industries).toHaveLength(0) + } + }) + }) + }) +}) + +describe('rag-documents.json — Applicability Notes', () => { + it('sollte applicability_note bei Dokumenten mit description haben', () => { + const withDescription = ragData.documents.filter((d: any) => d.description) + const withNote = withDescription.filter((d: any) => d.applicability_note) + // Mindestens 90% der Dokumente mit Beschreibung sollten eine Note haben + expect(withNote.length / withDescription.length).toBeGreaterThan(0.9) + }) + + it('horizontale Regulierungen sollten "alle Branchen" in der Note erwaehnen', () => { + const gdpr = ragData.documents.find((d: any) => d.code === 'GDPR') + if (gdpr?.applicability_note) { + expect(gdpr.applicability_note.toLowerCase()).toContain('alle branchen') + } + }) + + it('nicht zutreffende sollten "nicht zutreffend" in der Note erwaehnen', () => { + const dora = ragData.documents.find((d: any) => d.code === 'DORA') + if (dora?.applicability_note) { + expect(dora.applicability_note.toLowerCase()).toContain('nicht zutreffend') + } + }) +}) + +describe('rag-documents.json — Dokumenttyp-Verteilung', () => { + it('sollte Dokumente in jedem doc_type haben', () => { + ragData.doc_types.forEach((dt: any) => { + const count = ragData.documents.filter((d: any) => d.doc_type === dt.id).length + expect(count).toBeGreaterThan(0) + }) + }) + + it('sollte EU-Verordnungen als groesste Kategorie haben (mind. 15)', () => { + const euRegs = ragData.documents.filter((d: any) => d.doc_type === 'eu_regulation') + expect(euRegs.length).toBeGreaterThanOrEqual(15) + }) + + it('sollte EDPB Leitlinien als umfangreichste Kategorie haben (mind. 40)', () => { + const edpb = ragData.documents.filter((d: any) => d.doc_type === 'edpb_guideline') + expect(edpb.length).toBeGreaterThanOrEqual(40) + }) +}) diff --git a/docs-src/services/klausur-service/RAG-Landkarte.md b/docs-src/services/klausur-service/RAG-Landkarte.md new file mode 100644 index 0000000..96be067 --- /dev/null +++ b/docs-src/services/klausur-service/RAG-Landkarte.md @@ -0,0 +1,204 @@ +# RAG Landkarte — Branchen-Regulierungs-Matrix + +## Uebersicht + +Die RAG Landkarte zeigt eine interaktive Matrix aller 320 Compliance-Dokumente im RAG-System, gruppiert nach Dokumenttyp und zugeordnet zu 10 Industriebranchen. + +**URL**: `https://macmini:3002/ai/rag` → Tab "Landkarte" + +**Letzte Aktualisierung**: 2026-04-15 + +## Architektur + +``` +rag-documents.json ← Zentrale Datendatei (320 Dokumente) + ├── doc_types[] ← 17 Dokumenttypen (EU-VO, DE-Gesetz, etc.) + ├── industries[] ← 10 Branchen (VDMA/VDA/BDI) + └── documents[] ← Alle Dokumente mit Branchen-Mapping + ├── code ← Eindeutiger Identifier + ├── name ← Anzeigename + ├── doc_type ← Verweis auf doc_types.id + ├── industries[] ← ["all"] oder ["automotive", "chemie", ...] + ├── in_rag ← true (alle im RAG) + ├── rag_collection ← Qdrant Collection Name + ├── description? ← Beschreibung (fuer ~100 Hauptregulierungen) + ├── applicability_note? ← Begruendung der Branchenzuordnung + └── effective_date? ← Gueltigkeitsdatum + +rag-constants.ts ← RAG-Metadaten (Chunks, Qdrant-IDs) +page.tsx ← Frontend (importiert aus JSON) +``` + +## Dateien + +| Pfad | Beschreibung | +|------|--------------| +| `admin-lehrer/app/(admin)/ai/rag/rag-documents.json` | Alle 320 Dokumente mit Branchen-Mapping | +| `admin-lehrer/app/(admin)/ai/rag/rag-constants.ts` | REGULATIONS_IN_RAG (Chunk-Counts, Qdrant-IDs) | +| `admin-lehrer/app/(admin)/ai/rag/page.tsx` | Frontend-Rendering | +| `admin-lehrer/app/(admin)/ai/rag/__tests__/rag-documents.test.ts` | 44 Tests fuer JSON-Validierung | + +## Branchen (10 Industriesektoren) + +Die Branchen orientieren sich an den Mitgliedsverbaenden von VDMA, VDA und BDI: + +| ID | Branche | Icon | Typische Kunden | +|----|---------|------|-----------------| +| `automotive` | Automobilindustrie | 🚗 | OEMs, Tier-1/2 Zulieferer | +| `maschinenbau` | Maschinen- & Anlagenbau | ⚙️ | Werkzeugmaschinen, Automatisierung | +| `elektrotechnik` | Elektro- & Digitalindustrie | ⚡ | Embedded Systems, Steuerungstechnik | +| `chemie` | Chemie- & Prozessindustrie | 🧪 | Grundstoffchemie, Spezialchemie | +| `metall` | Metallindustrie | 🔩 | Stahl, Aluminium, Metallverarbeitung | +| `energie` | Energie & Versorgung | 🔋 | Energieerzeugung, Netzbetreiber | +| `transport` | Transport & Logistik | 🚚 | Gueterverkehr, Schiene, Luftfahrt | +| `handel` | Handel | 🏪 | Einzel-/Grosshandel, E-Commerce | +| `konsumgueter` | Konsumgueter & Lebensmittel | 📦 | FMCG, Lebensmittel, Verpackung | +| `bau` | Bauwirtschaft | 🏗️ | Hoch-/Tiefbau, Gebaeudeautomation | + +!!! warning "Keine Pseudo-Branchen" + Es werden bewusst **keine** Querschnittsthemen wie IoT, KI, HR, KRITIS oder E-Commerce als "Branchen" gefuehrt. Diese sind Technologien, Abteilungen oder Klassifizierungen — keine Wirtschaftssektoren. + +## Zuordnungslogik + +### Drei Ebenen + +| Ebene | `industries` Wert | Anzahl | Beispiele | +|-------|-------------------|--------|-----------| +| **Horizontal** | `["all"]` | 264 | DSGVO, AI Act, CRA, NIS2, BetrVG | +| **Sektorspezifisch** | `["automotive", "chemie", ...]` | 42 | Maschinenverordnung, ElektroG, BattDG | +| **Nicht zutreffend** | `[]` | 14 | DORA, MiCA, EHDS, DSA | + +### Horizontal (alle Branchen) + +Regulierungen die **branchenuebergreifend** gelten: + +- **Datenschutz**: DSGVO, BDSG, ePrivacy, TDDDG, SCC, DPF +- **KI**: AI Act (jedes Unternehmen das KI einsetzt) +- **Cybersecurity**: CRA (jedes Produkt mit digitalen Elementen), NIS2, EUCSA +- **Produktsicherheit**: GPSR, Produkthaftungs-RL +- **Arbeitsrecht**: BetrVG, AGG, KSchG, ArbSchG, LkSG +- **Handels-/Steuerrecht**: HGB, AO, UStG +- **Software-Security**: OWASP Top 10, NIST SSDF, CISA Secure by Design +- **Supply Chain**: CycloneDX, SPDX, SLSA (CRA verlangt SBOM) +- **Alle Leitlinien**: EDPB, DSK, DSFA-Listen, Gerichtsurteile + +### Sektorspezifisch + +| Regulierung | Branchen | Begruendung | +|-------------|----------|-------------| +| Maschinenverordnung | Maschinenbau, Automotive, Elektrotechnik, Metall, Bau | Hersteller von Maschinen und zugehoerigen Produkten | +| ElektroG | Elektrotechnik, Automotive, Konsumgueter | Elektro-/Elektronikgeraete | +| BattDG/BattVO | Automotive, Elektrotechnik, Energie | Batterien und Akkumulatoren | +| VerpackG | Konsumgueter, Handel, Chemie | Verpackungspflichtige Produkte | +| PAngV, UWG, VSBG | Handel, Konsumgueter | Verbraucherschutz im Verkauf | +| BSI-KritisV, KRITIS-Dachgesetz | Energie, Transport, Chemie | KRITIS-Sektoren | +| ENISA ICS/SCADA | Maschinenbau, Elektrotechnik, Automotive, Chemie, Energie, Transport | Industrielle Steuerungstechnik | +| NIST SP 800-82 (OT) | Maschinenbau, Automotive, Elektrotechnik, Chemie, Energie, Metall | Operational Technology | + +### Nicht zutreffend + +Dokumente die **im RAG bleiben** aber fuer keine der 10 Zielbranchen relevant sind: + +| Code | Name | Grund | +|------|------|-------| +| DORA | Digital Operational Resilience Act | Finanzsektor | +| PSD2 | Zahlungsdiensterichtlinie | Zahlungsdienstleister | +| MiCA | Markets in Crypto-Assets | Krypto-Maerkte | +| AMLR | AML-Verordnung | Geldwaesche-Bekaempfung | +| EHDS | Europaeischer Gesundheitsdatenraum | Gesundheitswesen | +| DSA | Digital Services Act | Online-Plattformen | +| DMA | Digital Markets Act | Gatekeeper-Plattformen | +| MDR | Medizinprodukteverordnung | Medizintechnik | +| BSI-TR-03161 | DiGA-Sicherheit (3 Teile) | Digitale Gesundheitsanwendungen | + +## Dokumenttypen (17) + +| doc_type | Label | Anzahl | Beispiele | +|----------|-------|--------|-----------| +| `eu_regulation` | EU-Verordnungen | 22 | DSGVO, AI Act, CRA, DORA | +| `eu_directive` | EU-Richtlinien | 14 | ePrivacy, NIS2, PSD2 | +| `eu_guidance` | EU-Leitfaeden | 9 | Blue Guide, GPAI CoP | +| `de_law` | Deutsche Gesetze | 41 | BDSG, BGB, HGB, BetrVG | +| `at_law` | Oesterreichische Gesetze | 11 | DSG AT, ECG, KSchG | +| `ch_law` | Schweizer Gesetze | 8 | revDSG, DSV, OR | +| `national_law` | Nationale Datenschutzgesetze | 17 | UK DPA, LOPDGDD, UAVG | +| `bsi_standard` | BSI Standards & TR | 4 | BSI 200-4, BSI-TR-03161 | +| `edpb_guideline` | EDPB/WP29 Leitlinien | 50 | Consent, Controller/Processor | +| `dsk_guidance` | DSK Orientierungshilfen | 57 | Kurzpapiere, OH Telemedien | +| `court_decision` | Gerichtsurteile | 20 | BAG M365, BGH Planet49 | +| `dsfa_list` | DSFA Muss-Listen | 20 | Pro Bundesland + DSK | +| `nist_standard` | NIST Standards | 11 | CSF 2.0, SSDF, AI RMF | +| `owasp_standard` | OWASP Standards | 6 | Top 10, ASVS, API Security | +| `enisa_guidance` | ENISA Guidance | 6 | Supply Chain, ICS/SCADA | +| `international` | Internationale Standards | 7 | CVSS, CycloneDX, SPDX | +| `legal_template` | Vorlagen & Muster | 17 | GitHub Policies, VVT-Muster | + +## Integration in andere Projekte + +### JSON importieren + +```typescript +import ragData from './rag-documents.json' + +const documents = ragData.documents // 320 Dokumente +const docTypes = ragData.doc_types // 17 Kategorien +const industries = ragData.industries // 10 Branchen +``` + +### Matrix-Logik + +```typescript +// Pruefen ob Dokument fuer Branche gilt +const applies = (doc, industryId) => + doc.industries.includes(industryId) || doc.industries.includes('all') + +// Dokumente nach Typ gruppieren +const grouped = Object.groupBy(documents, d => d.doc_type) + +// Nur sektorspezifische Dokumente fuer eine Branche +const forAutomotive = documents.filter(d => + d.industries.includes('automotive') && !d.industries.includes('all') +) +``` + +### RAG-Status pruefen + +```typescript +import { REGULATIONS_IN_RAG } from './rag-constants' + +const isInRag = (code: string) => code in REGULATIONS_IN_RAG +const chunks = REGULATIONS_IN_RAG['GDPR']?.chunks // 423 +``` + +## Datenquellen + +| Quelle | Pfad | Beschreibung | +|--------|------|--------------| +| RAG-Inventar | `~/Desktop/RAG-Dokumenten-Inventar.md` | 386 Quelldateien | +| rag-documents.json | `admin-lehrer/.../rag/rag-documents.json` | 320 konsolidierte Dokumente | +| rag-constants.ts | `admin-lehrer/.../rag/rag-constants.ts` | Qdrant-Metadaten | + +## Tests + +```bash +cd admin-lehrer +npx vitest run app/\(admin\)/ai/rag/__tests__/rag-documents.test.ts +``` + +44 Tests validieren: + +- JSON-Struktur (doc_types, industries, documents) +- 10 echte Branchen (keine Pseudo-Branchen) +- Pflichtfelder und gueltige Referenzen +- Horizontale Regulierungen (DSGVO, AI Act, CRA → "all") +- Sektorspezifische Zuordnungen (Maschinenverordnung, ElektroG) +- Nicht zutreffende Regulierungen (DORA, MiCA → leer) +- Applicability Notes vorhanden und korrekt + +## Aenderungshistorie + +| Datum | Aenderung | +|-------|-----------| +| 2026-04-15 | Initiale Implementierung: 320 Dokumente, 10 Branchen, 17 Typen | +| 2026-04-15 | Branchen-Review: OWASP/SBOM → alle, BSI-TR-03161 → leer | +| 2026-04-15 | Applicability Notes UI: Aufklappbare Erklaerungen pro Dokument | diff --git a/mkdocs.yml b/mkdocs.yml index 49d83ec..0d06f2c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -77,6 +77,7 @@ nav: - RAG Admin: services/klausur-service/RAG-Admin-Spec.md - Worksheet Editor: services/klausur-service/Worksheet-Editor-Architecture.md - Chunk-Browser: services/klausur-service/Chunk-Browser.md + - RAG Landkarte: services/klausur-service/RAG-Landkarte.md - Voice-Service: - Uebersicht: services/voice-service/index.md - Agent-Core: