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) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-04-15 20:47:54 +02:00
parent c8e5e498b5
commit 5fad2d420d
3 changed files with 457 additions and 0 deletions

View File

@@ -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)
})
})

View File

@@ -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 |

View File

@@ -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: