# Canonical Control Library (CP-CLIB) Eigenstaendig formulierte Security Controls basierend auf offenem Wissen (OWASP, NIST, ENISA). Unabhaengige Taxonomie — kein Bezug zu proprietaeren Frameworks. **Prefix:** `CP-CLIB` · **Frontend:** `https://macmini:3007/sdk/control-library` **Provenance Wiki:** `https://macmini:3007/sdk/control-provenance` **Proxy:** `/api/sdk/v1/canonical` → `backend-compliance:8002/api/compliance/v1/canonical/...` --- ## Motivation Wir benoetigen ein System, um aus verschiedenen Security-Guidelines **eigenstaendige, rechtlich defensible Controls** zu extrahieren, ohne proprietaere Texte im Produkt zu verwenden. ### Kernprinzipien 1. **Unabhaengige Taxonomie** — Eigene Domain-IDs (AUTH, NET, SUP, etc.), eigenes ID-Format (`DOMAIN-NNN`) 2. **Open-Source-Verankerung** — Jedes Control hat mindestens 1 Open Anchor (OWASP/NIST/ENISA) 3. **Strikte Quellentrennung** — Geschuetzte Quellen nur intern zur Analyse, nie im Produkt 4. **Automatisierte Pruefung** — Too-Close-Detektor + No-Leak-Scanner in CI/CD --- ## Rechtliche Basis | Gesetz | Bezug | |--------|-------| | UrhG §44b | Text & Data Mining — Kopien loeschen | | UrhG §23 | Hinreichender Abstand zum Originalwerk | | BSI Nutzungsbedingungen | Kommerziell nur mit Zustimmung | --- ## Domains (Unabhaengige Taxonomie) | Domain | Name | Beschreibung | |--------|------|-------------| | AUTH | Identity & Access Management | Authentisierung, MFA, Token-Management | | CRYP | Cryptographic Operations | Key Management, Rotation, HSM | | NET | Network & Transport Security | TLS, Zertifikate, Netzwerk-Haertung | | DATA | Data Governance & Classification | Datenklassifikation, Schutzmassnahmen | | LOG | Security Operations & Logging | Privacy-Aware Logging, SIEM | | ACC | Access Control | Zugriffskontrolle, Berechtigungen | | SEC | IT Security | Schwachstellen, Haertung, Konfiguration | | INC | Incident Management | Vorfallmanagement, Wiederherstellung | | AI | Artificial Intelligence | KI-Compliance, Bias, Transparenz | | COMP | Compliance | Konformitaet, Audit, Zertifizierung | | GOV | Government & Public Administration | Behoerden, Verwaltung, Aufsicht | | LAB | Labor Law | Arbeitsrecht, Arbeitsschutz, Betriebsverfassung | | FIN | Financial Regulation | Finanzregulierung, Rechnungslegung, BaFin | | TRD | Trade Regulation | Gewerbe, Handelsrecht, Produktsicherheit | | ENV | Environmental | Umweltschutz, Nachhaltigkeit, Emissionen | | HLT | Health | Gesundheit, Medizinprodukte, Hygiene | !!! warning "Keine BSI-Nomenklatur" Die Domains verwenden bewusst KEINE BSI-Bezeichner (O.Auth_*, O.Netz_*). Das ID-Format `DOMAIN-NNN` ist eine gaengige, nicht-proprietaere Konvention. --- ## Datenmodell (Migration 044) ```mermaid erDiagram canonical_control_licenses ||--o{ canonical_control_sources : "hat" canonical_control_frameworks ||--o{ canonical_controls : "enthaelt" canonical_controls ||--o{ canonical_control_mappings : "hat" canonical_control_sources ||--o{ canonical_control_mappings : "referenziert" canonical_control_licenses { varchar license_id PK varchar name varchar commercial_use boolean deletion_required } canonical_control_sources { uuid id PK varchar source_id UK varchar title boolean allowed_ship_in_product } canonical_control_frameworks { uuid id PK varchar framework_id UK varchar name varchar version } canonical_controls { uuid id PK uuid framework_id FK varchar control_id varchar severity varchar release_state varchar category varchar verification_method varchar target_audience varchar generation_strategy varchar obligation_type smallint pipeline_version integer license_rule jsonb source_citation jsonb open_anchors } canonical_control_mappings { uuid id PK uuid control_id FK uuid source_id FK varchar mapping_type varchar attribution_class } ``` ### Tabellen | Tabelle | Zweck | Produktfaehig? | |---------|-------|----------------| | `canonical_control_licenses` | Lizenz-Metadaten | Ja (read-only) | | `canonical_control_sources` | Quellen-Register | **Nein** (nur intern) | | `canonical_control_frameworks` | Framework-Registry | Ja | | `canonical_controls` | Die eigentlichen Controls | Ja | | `canonical_control_mappings` | Provenance-Trail | **Nein** (nur Audit) | --- ## API Endpoints | Methode | Pfad | Beschreibung | |---------|------|--------------| | `GET` | `/v1/canonical/frameworks` | Alle Frameworks | | `GET` | `/v1/canonical/frameworks/{id}` | Framework-Details | | `GET` | `/v1/canonical/frameworks/{id}/controls` | Controls eines Frameworks | | `GET` | `/v1/canonical/controls` | Alle Controls (Filter: `severity`, `domain`, `release_state`, `category`) | | `GET` | `/v1/canonical/controls/{control_id}` | Einzelnes Control (z.B. AUTH-001) | | `POST` | `/v1/canonical/controls` | Neues Control anlegen | | `PUT` | `/v1/canonical/controls/{control_id}` | Control aktualisieren | | `DELETE` | `/v1/canonical/controls/{control_id}` | Control loeschen (Soft Delete) | | `GET` | `/v1/canonical/controls-customer` | Kunden-View: verbirgt generation_metadata, Rule-3-Quellen | | `GET` | `/v1/canonical/sources` | Quellenregister mit Berechtigungen | | `GET` | `/v1/canonical/licenses` | Lizenz-Matrix | | `GET` | `/v1/canonical/categories` | Alle 23 Kategorien | | `POST` | `/v1/canonical/controls/{id}/similarity-check` | Too-Close-Pruefung | | `POST` | `/v1/canonical/generate` | Generator-Job starten | | `GET` | `/v1/canonical/generate/jobs` | Alle Generator-Jobs | | `GET` | `/v1/canonical/generate/status/{job_id}` | Einzelnen Job-Status abfragen | | `GET` | `/v1/canonical/generate/processed-stats` | Verarbeitungsstatistik pro Collection | | `GET` | `/v1/canonical/generate/review-queue` | Controls zur Pruefung (needs_review, too_close, duplicate) | | `POST` | `/v1/canonical/generate/review/{control_id}` | Review abschliessen (approve/reject) | | `POST` | `/v1/canonical/generate/bulk-review` | Bulk-Review (approve/reject nach State) | | `POST` | `/v1/canonical/generate/qa-reclassify` | QA-Reklassifizierung bestehender Controls | | `POST` | `/v1/canonical/generate/backfill-citations` | Article/Paragraph-Referenzen nachpflegen | | `POST` | `/v1/canonical/generate/backfill-domain` | Domain/Category/Target-Audience nachpflegen (Anthropic) | | `GET` | `/v1/canonical/blocked-sources` | Gesperrte Quellen (Rule 3) | | `POST` | `/v1/canonical/blocked-sources/cleanup` | Cleanup-Workflow starten | | `POST` | `/v1/canonical/obligations/dedup` | Obligation-Duplikate markieren (dry_run, batch_size, offset) | | `GET` | `/v1/canonical/obligations/dedup-stats` | Dedup-Statistik (total, by_state, pending) | ### Beispiel: Control abrufen ```bash curl -s https://macmini:8002/api/v1/canonical/controls/AUTH-001 | jq ``` ### Beispiel: Similarity Check ```bash curl -X POST https://macmini:8002/api/v1/canonical/controls/AUTH-001/similarity-check \ -H 'Content-Type: application/json' \ -d '{ "source_text": "Die Anwendung muss MFA implementieren.", "candidate_text": "Privileged accounts require multi-factor authentication." }' | jq ``` **Response:** ```json { "max_exact_run": 0, "token_overlap": 0.0714, "ngram_jaccard": 0.0323, "embedding_cosine": 0.0, "lcs_ratio": 0.0714, "status": "PASS", "details": { "max_exact_run": "PASS", "token_overlap": "PASS", "ngram_jaccard": "PASS", "embedding_cosine": "PASS", "lcs_ratio": "PASS" } } ``` --- ## Too-Close-Detektor 5 Metriken mit Schwellwerten: | Metrik | Warn | Fail | Beschreibung | |--------|------|------|-------------| | Exact Phrase | ≥8 Tokens | ≥12 Tokens | Laengste identische Token-Sequenz | | Token Overlap | ≥0.20 | ≥0.30 | Jaccard der Token-Mengen | | 3-Gram Jaccard | ≥0.10 | ≥0.18 | Zeichenketten-Aehnlichkeit | | Embedding Cosine | ≥0.86 | ≥0.92 | Semantische Aehnlichkeit (bge-m3) | | LCS Ratio | ≥0.35 | ≥0.50 | Longest Common Subsequence | **Entscheidungslogik:** - **PASS** — Kein Fail + max 1 Warn - **WARN** — Max 2 Warn, kein Fail → Human Review - **FAIL** — Irgendein Fail → Block, Umformulierung noetig --- ## License Gate Jede Quelle hat definierte Berechtigungen: | Nutzungsart | Spalte | Beispiel OWASP | Beispiel BSI | |-------------|--------|---------------|-------------| | Analyse | `allowed_analysis` | ✅ | ✅ | | Excerpt speichern | `allowed_store_excerpt` | ✅ | ❌ | | Embeddings shippen | `allowed_ship_embeddings` | ✅ | ❌ | | Im Produkt shippen | `allowed_ship_in_product` | ✅ | ❌ | --- ## Release States (7 Werte) | State | Frontend-Label | Farbe | Beschreibung | |-------|---------------|-------|-------------| | `draft` | Draft | Grau | Entwurf — noch nicht freigegeben | | `review` | Review | Blau | Wartet auf manuelle Pruefung | | `approved` | Approved | Gruen | Freigegeben fuer Kunden | | `needs_review` | Review noetig | Gelb | Vom Generator erzeugt, QA-Pruefung noetig | | `too_close` | Zu aehnlich | Rot | Too-Close-Detektor hat Warnung ausgeloest | | `duplicate` | Duplikat | Orange | Wurde als Duplikat eines bestehenden Controls erkannt | | `deprecated` | Deprecated | Rot | Veraltet/geloescht (Soft Delete) | !!! note "Pipeline-erzeugte States" `needs_review`, `too_close` und `duplicate` werden automatisch vom Generator vergeben. `draft`, `review` und `approved` sind manuelle Workflow-States. --- ## Target Audience (Zielgruppe) Jedes Control kann eine oder mehrere Zielgruppen haben. Die Zielgruppe bestimmt, fuer welchen Organisationstyp das Control relevant ist. | Key | Label | Farbe | |-----|-------|-------| | `enterprise` / `unternehmen` | Unternehmen | Cyan | | `authority` / `behoerden` | Behoerden | Rose | | `provider` | Anbieter | Violet | | `all` | Alle | Grau | | `entwickler` | Entwickler | Sky | | `datenschutzbeauftragte` | DSB | Purple | | `geschaeftsfuehrung` | GF | Amber | | `it-abteilung` | IT | Blau | | `rechtsabteilung` | Recht | Fuchsia | | `compliance-officer` | Compliance | Indigo | | `personalwesen` | Personal | Pink | | `einkauf` | Einkauf | Lime | | `produktion` | Produktion | Orange | | `vertrieb` | Vertrieb | Teal | | `gesundheitswesen` | Gesundheit | Rot | | `finanzwesen` | Finanzen | Emerald | | `oeffentlicher_dienst` | Oeffentl. Dienst | Rose | **DB-Feld:** `target_audience` (VARCHAR, kann Array sein als JSONB) **Migration:** 049_target_audience.sql --- ## Generation Strategy | Strategy | Badge | Farbe | Bedeutung | |----------|-------|-------|-----------| | `ungrouped` (Default/null) | v1 | Grau | Einzelverarbeitung (Original-Ansatz) | | `document_grouped` | v2 | Emerald | Dokumentgruppenweise Verarbeitung (v2 Pipeline) | **DB-Feld:** `generation_strategy` (TEXT, Default: `'ungrouped'`) **Migration:** 058_generation_strategy.sql --- ## CI/CD Validation Der Validator (`scripts/validate-controls.py`) prueft bei jedem Commit: 1. **Schema Validation** — Alle Pflichtfelder, ID-Format, Severity 2. **No-Leak Scanner** — Regex gegen BSI-Muster (`O.Auth_*`, `TR-03161`, etc.) 3. **Open Anchor Check** — Jedes Control hat ≥1 Open Anchor 4. **Taxonomy Check** — Keine BSI-style ID-Prefixe 5. **Evidence Structure** — Alle Evidence-Items haben `type` + `description` --- ## Frontend ### Control Library Browser (`/sdk/control-library`) **Listen-Ansicht:** - Framework-Info mit Version und Beschreibung - Filterable Control-Tabelle mit **7 Filter-Dropdowns:** 1. Schweregrad (critical, high, medium, low) 2. Domain (aus Meta-Daten, alle vorhandenen Domains) 3. Status (draft, approved, needs_review, too_close, duplicate, deprecated) 4. Nachweis (code_review, document, tool, hybrid) 5. Kategorie (23 thematische Kategorien) 6. Zielgruppe (17 Audience-Werte) 7. Dokumentenursprung (nach Quellen-Regulation) - Sortierung: ID, Quelle, Neueste/Aelteste - Pagination: 50 Controls pro Seite - Freitext-Suche (ID, Titel, Ziel) **Detail-Ansicht:** - Ziel, Begruendung, Geltungsbereich - Anforderungen, Pruefverfahren, Nachweise - **Quellennachweis** (dynamische Farbe): `source_type`-basiert — blau fuer Gesetze, indigo fuer Leitlinien, teal fuer Standards - **Open-Source-Referenzen** (gruener Kasten): Verlinkte Open Anchors - Generierungsdetails: processing_path, similarity_status - Tags, Risk Score, Implementation Effort - **Badges:** Severity, State, LicenseRule, VerificationMethod, Category, TargetAudience, GenerationStrategy **Review-Modus:** Der Review-Modus wird aktiviert wenn `needs_review`-Controls vorhanden sind. Er teilt die Review-Queue in zwei Tabs: | Tab | Inhalt | Ansicht | |-----|--------|---------| | **Duplikat-Verdacht** | Controls mit `similar_controls` in generation_metadata | Side-by-Side Vergleich (ReviewCompare) | | **Rule 3 ohne Anchor** | Controls ohne Open Anchors | Einzel-Detail-Ansicht | **Duplikat-Vergleich (ReviewCompare):** - Linke Seite: Zu pruefendes Control (gelb hervorgehoben) - Rechte Seite: Verdaechtiges Duplikat (aus `generation_metadata.similar_controls[0]`) - Aehnlichkeits-Prozentsatz im Header - Aktionen: Behalten (approve), Duplikat (reject), Bearbeiten **Weitere Aktionen:** - Generator-Modal: Job starten (Domain, Collections, Dry-Run, max_controls) - Bulk-Review: Alle gefilterten Controls genehmigen/ablehnen - Statistik-Dialog: Verarbeitungsstatistik pro Collection ### Control Provenance Wiki (`/sdk/control-provenance`) Wiki-artige Dokumentation der rechtlichen und methodischen Grundlage fuer die Control-Erstellung: **Statische Sektionen (10):** 1. **Methodik der Control-Erstellung** — Dreistufiger Prozess, rechtliche Basis (UrhG §44b, §23) 2. **Filter in der Control Library** — Erklaerung aller 7 Filter + Sortierung 3. **Badges & Lizenzregeln** — Rule 1/2/3, Processing Paths, Referenzen 4. **Unabhaengige Taxonomie** — Top-10 Domains, ID-Format, spezialisierte Domains 5. **Offene Referenzquellen** — OWASP, NIST, ENISA, SLSA, CIS 6. **Geschuetzte Quellen** — BSI, ISO, ETSI + Trennungsprinzip 7. **Verifikationsmethoden** — 4 Methoden + Kundenbedeutung 8. **Thematische Kategorien** — 17 Kategorien mit Beschreibung 9. **Master Library Strategie** — RAG-First, Dedup, Wellen-Ansatz 10. **Automatisierte Validierung** — CI/CD-Checks, Too-Close-Detektor **Live-Daten (API-gespeist):** - **Lizenz-Matrix:** Tabelle aller `canonical_control_licenses` mit Berechtigungsbadges - **Quellenregister:** Karten fuer jede `canonical_control_sources` mit 4 Berechtigungsstufen Siehe auch: [Control Provenance Dokumentation](control-provenance.md) --- ## Control Generator Pipeline Automatische Generierung von Controls aus dem gesamten RAG-Korpus (~105.000 Chunks aus Gesetzen, Verordnungen und Standards). Aktueller Stand: **~4.738 Controls** generiert. !!! tip "Ausfuehrliche Dokumentation" Siehe **[Control Generator Pipeline](control-generator-pipeline.md)** fuer die vollstaendige Referenz inkl. API-Endpoints, Konfiguration, Kosten und Pipeline-Versionen. ### 7-Stufen-Pipeline (v2) ```mermaid flowchart TD A[1. RAG Scan] -->|Alle Chunks laden| B[2. License Classify] B -->|Rule 1/2| C[3a. Structure Batch] B -->|Rule 3| D[3b. Reform Batch] C --> E[4. Harmonize] D --> E E -->|Duplikat| F[Als Duplikat markieren] E -->|Neu| G[5. Anchor Search] G --> H[6. Store Control] H --> I[7. Mark Processed] ``` !!! info "Pipeline-Version v2 (seit 2026-03-17)" - **Kein lokaler Vorfilter mehr** — Anthropic API entscheidet selbst ueber Chunk-Relevanz via null-Returns - **Annexe geschuetzt** — Technische Anforderungen in Anhaengen werden nicht mehr uebersprungen - **`pipeline_version`** Spalte in DB unterscheidet v1- von v2-Controls ### Stufe 1: RAG Scan Scrollt durch **ALLE** Chunks in den konfigurierten RAG-Collections mittels Qdrant Scroll-API. Optionaler `regulation_filter` beschraenkt auf bestimmte Regulierungen per Prefix-Matching. Bereits verarbeitete Chunks werden per SHA-256-Hash uebersprungen (`canonical_processed_chunks`). ### Stufe 3: Lizenz-Klassifikation (3-Regel-System) | Regel | Lizenz | Original erlaubt? | Beispiel | |-------|--------|-------------------|----------| | **Rule 1** (free_use) | EU-Gesetze, NIST, DE-Gesetze | Ja | DSGVO, BDSG, NIS2 | | **Rule 2** (citation_required) | CC-BY, CC-BY-SA | Ja, mit Zitation | OWASP ASVS | | **Rule 3** (restricted) | Proprietaer | Nein, volle Reformulierung | BSI TR-03161 | ### Stufe 4a/4b: Strukturierung / Reformulierung - **Rule 1+2:** Anthropic strukturiert den Originaltext in Control-Format (Titel, Ziel, Anforderungen) - **Rule 3:** Anthropic reformuliert vollstaendig — kein Originaltext, keine Quellennamen ### Batch Processing (Stufe 4 — Optimierung) Die Pipeline verarbeitet Chunks **nicht einzeln**, sondern sammelt sie in Batches von **5 Chunks pro API-Call**. Das reduziert die Anzahl der Anthropic-API-Aufrufe um ~80% und beschleunigt die Generierung erheblich. #### Ablauf 1. **Chunks sammeln:** Nach dem Prefilter werden relevante Chunks mit ihrer Lizenz-Info in `pending_batch` gesammelt 2. **Batch voll?** Sobald `batch_size` (Default: 5) erreicht ist, wird `_flush_batch()` aufgerufen 3. **`_process_batch()`** trennt den Batch nach Lizenzregel: - **Rule 1+2 Chunks** → `_structure_batch()` — ein einziger Anthropic-Call fuer alle - **Rule 3 Chunks** → `_reformulate_batch()` — ein einziger Anthropic-Call fuer alle 4. **Ergebnis:** JSON-Array mit genau N Controls, zurueck-gemappt per `chunk_index` #### `_structure_batch()` (Rule 1+2) Sendet alle freien/CC-BY Chunks in einem einzigen Prompt an Anthropic. Der Originaltext darf verwendet werden. Jeder Chunk wird als `--- CHUNK N ---` Block formatiert, das LLM gibt ein JSON-Array mit `chunk_index` zurueck. ```python # Prompt-Auszug: "Strukturiere die folgenden 5 Gesetzestexte jeweils als eigenstaendiges Control." "Gib ein JSON-Array zurueck mit GENAU 5 Objekten." ``` **Processing Path:** `structured_batch` (in `generation_metadata`) #### `_reformulate_batch()` (Rule 3) Sendet alle eingeschraenkten Chunks in einem Prompt. Der Originaltext darf **nicht kopiert** werden. Quellennamen und proprietaere Bezeichner werden im Prompt explizit verboten. ```python # Prompt-Auszug: "KOPIERE KEINE Saetze. Verwende eigene Begriffe und Struktur." "NENNE NICHT die Quellen. Keine proprietaeren Bezeichner." ``` **Processing Path:** `llm_reform_batch` (in `generation_metadata`) #### Fallback bei Batch-Fehler Falls ein Batch-Call fehlschlaegt (z.B. Timeout, Parsing-Error), faellt die Pipeline automatisch auf **Einzelverarbeitung** zurueck: ```python except Exception as e: logger.error("Batch processing failed: %s — falling back to single-chunk mode", e) for chunk, _lic in batch: ctrl = await self._process_single_chunk(chunk, config, job_id) ``` !!! info "Batch-Konfiguration" | Parameter | Wert | Beschreibung | |-----------|------|-------------| | `batch_size` | 5 (Default) | Chunks pro API-Call | | `max_tokens` | 8192 | Maximale Token-Laenge der LLM-Antwort | | `LLM_TIMEOUT` | 180s | Timeout pro Anthropic-Call | Die `batch_size` ist ueber `GeneratorConfig` konfigurierbar. Bei grosser Batch-Size steigt die Wahrscheinlichkeit fuer Parsing-Fehler. ### Stufe 5: QA Validation (Automatische Qualitaetspruefung) Die QA-Stufe validiert die Klassifizierung jedes Controls automatisch. Sie vergleicht die LLM-Klassifizierung mit Keyword-basierter Erkennung und loest bei Abweichungen eine Arbitrierung durch das lokale Ollama-Modell aus. #### Ablauf 1. **LLM-Category auswerten:** Der Anthropic-Prompt fragt jetzt explizit nach `category` und `domain` 2. **Keyword-Detection als Cross-Check:** `_detect_category(chunk.text)` liefert eine zweite Meinung 3. **Stimmen beide ueberein?** → Kein QA noetig (schneller Pfad) 4. **Bei Disagreement:** Lokales LLM (Ollama qwen3.5:35b-a3b) arbitriert 5. **Auto-Fix:** Bei hoher Konfidenz wird Category/Domain automatisch korrigiert #### Beispiel ``` Control: "Offenlegung von Risikokonzentrationen bei Finanzinstrumenten" LLM sagt: domain=AUTH, category=authentication Keyword sagt: domain=FIN, category=finance → QA via Ollama: domain=FIN, category=finance (Grund: IFRS-Thema) → Auto-Fix: AUTH-315 → FIN-xxx ``` #### QA-Metriken in generation_metadata ```json { "qa_category_fix": {"from": "authentication", "to": "finance", "reason": "IFRS-Thema"}, "qa_domain_fix": {"from": "AUTH", "to": "FIN", "reason": "Finanzregulierung"} } ``` #### QA-Reklassifizierung bestehender Controls Fuer bereits generierte Controls gibt es den Backfill-Endpoint: ```bash # Dry Run: Welche AUTH-Controls sind falsch klassifiziert? curl -X POST https://macmini:8002/api/compliance/v1/canonical/generate/qa-reclassify \ -H 'Content-Type: application/json' \ -d '{"limit": 50, "dry_run": true, "filter_domain_prefix": "AUTH"}' # Korrekturen anwenden: curl -X POST https://macmini:8002/api/compliance/v1/canonical/generate/qa-reclassify \ -H 'Content-Type: application/json' \ -d '{"limit": 50, "dry_run": false, "filter_domain_prefix": "AUTH"}' ``` !!! info "Performance" Die QA-Stufe nutzt das lokale Ollama-Modell (kostenlos, ~2s/Control). Sie wird nur bei Disagreement zwischen LLM und Keyword getriggert (~10-15% der Controls), sodass der Overhead minimal bleibt. ### Stufe 6: Harmonisierung (Embedding-basiert) Prueft per bge-m3 Embeddings (Cosine Similarity > 0.85), ob ein aehnliches Control existiert. Embeddings werden in Batches vorgeladen (32 Texte/Request) fuer maximale Performance. ### Stufe 7-9: Anchor Search, Store, Mark Processed - **Anchor Search:** Findet Open-Source-Referenzen (OWASP, NIST, ENISA) - **Store:** Persistiert Control mit `verification_method` und `category` - **Mark Processed:** Markiert **JEDEN** Chunk als verarbeitet (auch bei Skip/Error/Duplikat) ### Automatische Klassifikation Bei der Generierung werden automatisch zugewiesen: **Category** wird seit 2026-03-16 **dreigleisig** bestimmt: 1. **LLM-Klassifikation (primaer):** Anthropic liefert `category` im JSON-Response 2. **Keyword-Detection (fallback):** Falls LLM keine Category liefert, greift `_detect_category()` 3. **QA-Arbitrierung (bei Mismatch):** Lokales LLM entscheidet bei Widerspruch **Verification Method** (Nachweis-Methode): | Methode | Beschreibung | |---------|-------------| | `code_review` | Im Source Code pruefbar | | `document` | Dokument/Prozess-Nachweis | | `tool` | Tool-basierte Pruefung | | `hybrid` | Kombination mehrerer Methoden | **Category** (22 thematische Kategorien): | Kategorie | Beschreibung | |-----------|-------------| | `encryption` | Verschluesselung, Kryptographie | | `authentication` | Authentifizierung, Login, MFA | | `network` | Netzwerk, Firewall, VPN | | `data_protection` | Datenschutz, DSGVO | | `logging` | Protokollierung, Monitoring | | `incident` | Vorfallmanagement | | `continuity` | Business Continuity, Backup | | `compliance` | Konformitaet, Audit, Zertifizierung | | `supply_chain` | Lieferkette, Dienstleister | | `physical` | Physische Sicherheit | | `personnel` | Schulung, Mitarbeiter | | `application` | Software, Code Review, API | | `system` | Haertung, Patch, Konfiguration | | `risk` | Risikobewertung, -management | | `governance` | Sicherheitsorganisation, Richtlinien | | `hardware` | Hardware, Firmware, TPM | | `identity` | IAM, SSO, Verzeichnisdienste | | `public_administration` | Behoerden, Verwaltung | | `labor_law` | Arbeitsrecht, Arbeitsschutz | | `finance` | Finanzregulierung, Rechnungslegung | | `trade_regulation` | Gewerbe, Handelsrecht | | `environmental` | Umweltschutz, Nachhaltigkeit | | `health` | Gesundheit, Medizinprodukte | ### Konfiguration | ENV-Variable | Default | Beschreibung | |-------------|---------|-------------| | `ANTHROPIC_API_KEY` | — | API-Key fuer Anthropic Claude | | `CONTROL_GEN_ANTHROPIC_MODEL` | `claude-sonnet-4-6` | Anthropic-Modell fuer Formulierung | | `OLLAMA_URL` | `http://host.docker.internal:11434` | Lokaler Ollama-Server (Vorfilter) | | `CONTROL_GEN_OLLAMA_MODEL` | `qwen3.5:35b-a3b` | Lokales LLM fuer Vorfilter + QA | | `CONTROL_GEN_LLM_TIMEOUT` | `180` | Timeout in Sekunden (erhoet fuer Batch-Calls) | **Pipeline-Konfiguration (via `GeneratorConfig`):** | Parameter | Default | Beschreibung | |-----------|---------|-------------| | `batch_size` | `5` | Chunks pro Anthropic-API-Call | | `max_controls` | `0` | Limit (0 = alle Chunks verarbeiten) | | `max_chunks` | `1000` | Max Chunks pro Job (respektiert Dokumentgrenzen) | | `skip_processed` | `true` | Bereits verarbeitete Chunks ueberspringen | | `dry_run` | `false` | Trockenlauf ohne DB-Schreibzugriffe | | `skip_web_search` | `false` | Web-Suche fuer Anchor-Finder ueberspringen | ### Architektur-Entscheidung: Gesetzesverweise Controls leiten sich aus vier Quellentypen ab (Feld `source_citation.source_type`): | source_type | Beschreibung | Beispiele | Frontend-Darstellung | |-------------|-------------|-----------|---------------------| | `law` | Bindendes EU/DE/AT-Recht | DSGVO, AI Act, BDSG, NIS2 | Blaue Box "Gesetzliche Grundlage" + Badge "Direkte gesetzliche Pflicht" | | `guideline` | Behoerdliche Leitlinien (Soft Law) | EDPB, WP29, Blue Guide | Indigo Box "Behoerdliche Leitlinie" + Badge "Aufsichtsbehoerdliche Empfehlung" | | `standard` | Freiwillige Standards/Frameworks | NIST, OWASP, ENISA, CISA, OECD | Teal Box "Standard / Best Practice" + Badge "Freiwilliger Standard" | | `restricted` | Geschuetzte Normen (Rule 3) | BSI, ISO, ETSI | Amber Box "Abgeleitet aus regulatorischen Anforderungen" (kein Originaltext) | !!! warning "source_type vs license_rule" `source_type` klassifiziert die **rechtliche Verbindlichkeit** (Ist es ein Gesetz?). `license_rule` klassifiziert das **Urheberrecht** (Darf man den Text zitieren?). Beispiel: NIST ist Rule 1 (Public Domain = freie Nutzung) aber `source_type = "standard"` (kein EU-Gesetz). ### API ```bash # Job starten (laeuft im Hintergrund) curl -X POST https://macmini:8002/api/compliance/v1/canonical/generate \ -H 'Content-Type: application/json' \ -H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000' \ -d '{"collections": ["bp_compliance_gesetze"]}' # Job-Status abfragen curl https://macmini:8002/api/compliance/v1/canonical/generate/jobs \ -H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000' ``` ### RAG Collections | Collection | Inhalte | Erwartete Regel | |-----------|---------|----------------| | `bp_compliance_gesetze` | Deutsche Gesetze (BDSG, TTDSG, TKG etc.) | Rule 1 | | `bp_compliance_datenschutz` | Datenschutz-Leitlinien + EU-Verordnungen | Rule 1/2 | | `bp_compliance_ce` | CE/Sicherheitsstandards | Rule 1/2/3 | | `bp_dsfa_corpus` | DSFA-Korpus | Rule 1/2 | | `bp_legal_templates` | Rechtsvorlagen | Rule 1 | !!! warning "bp_compliance_recht entfernt (2026-03-16)" Die Collection `bp_compliance_recht` wurde geloescht, da sie mit `bp_compliance_datenschutz` ueberlappte (~20.000 Duplikat-Chunks). Alle relevanten EU-Verordnungen sind in den anderen Collections enthalten. --- ## Processed Chunks Tracking Die Tabelle `canonical_processed_chunks` trackt **JEDEN** verarbeiteten RAG-Chunk per SHA-256-Hash. Dadurch werden Chunks bei erneutem Pipeline-Lauf automatisch uebersprungen (`skip_processed: true`). ### Tabelle: `canonical_processed_chunks` (Migration 046 + 048) | Spalte | Typ | Beschreibung | |--------|-----|-------------| | `id` | UUID | Primary Key | | `chunk_hash` | VARCHAR(64) | SHA-256 Hash des Chunk-Textes | | `collection` | VARCHAR(100) | Qdrant-Collection (z.B. `bp_compliance_gesetze`) | | `regulation_code` | VARCHAR(100) | Quell-Regulation (z.B. `bdsg`, `eu_2016_679`) | | `document_version` | VARCHAR(50) | Versions-Tracking | | `source_license` | VARCHAR(50) | Lizenz der Quelle | | `license_rule` | INTEGER | 1, 2 oder 3 | | `processing_path` | VARCHAR(20) | Verarbeitungspfad (siehe unten) | | `generated_control_ids` | JSONB | UUIDs der generierten Controls | | `job_id` | UUID | Referenz auf `canonical_generation_jobs` | | `processed_at` | TIMESTAMPTZ | Zeitstempel | **UNIQUE Constraint:** `(chunk_hash, collection, document_version)` — verhindert Doppelverarbeitung. ### Processing Paths | Wert | Stufe | Bedeutung | |------|-------|-----------| | `prefilter_skip` | 2 | Lokaler LLM-Vorfilter: Chunk nicht sicherheitsrelevant | | `structured` | 4a | Einzelner Chunk strukturiert (Rule 1/2) | | `llm_reform` | 4b | Einzelner Chunk reformuliert (Rule 3) | | `structured_batch` | 4a | Batch-Strukturierung (Rule 1/2, in `generation_metadata`) | | `llm_reform_batch` | 4b | Batch-Reformulierung (Rule 3, in `generation_metadata`) | | `no_control` | 4 | LLM konnte kein Control ableiten | | `store_failed` | 7 | DB-Speichern fehlgeschlagen | | `error` | — | Unerwarteter Fehler bei der Verarbeitung | !!! note "Batch-Pfade in generation_metadata" Die Werte `structured_batch` und `llm_reform_batch` werden im `processing_path` der Datenbank gespeichert **und** im `generation_metadata` JSON-Feld des Controls. So ist nachvollziehbar, ob ein Control einzeln oder im Batch generiert wurde. ### Beispiel-Query: Verarbeitungsstatistik ```sql SELECT processing_path, COUNT(*) as count FROM canonical_processed_chunks GROUP BY processing_path ORDER BY count DESC; ``` --- ## Statistiken (processed-stats Endpoint) Der Endpoint `GET /v1/canonical/generate/processed-stats` liefert Verarbeitungsstatistiken pro RAG-Collection. ```bash curl -s https://macmini:8002/api/compliance/v1/canonical/generate/processed-stats | jq ``` **Response:** ```json { "stats": [ { "collection": "bp_compliance_gesetze", "processed_chunks": 45200, "direct_adopted": 1850, "llm_reformed": 120, "skipped": 43230, "total_chunks_estimated": 0, "pending_chunks": 0 } ] } ``` ### Aktuelle Groessenordnung | Metrik | Wert | |--------|------| | RAG-Chunks gesamt | ~105.000 (nach Dedup 2026-03-16) | | Verarbeitete Chunks | ~105.000 | | Generierte Controls | **~4.738** | | Konversionsrate | ~4,5% (nur sicherheitsrelevante Chunks erzeugen Controls) | !!! info "Warum so wenige Controls?" Die meisten RAG-Chunks sind Definitionen, Begriffsbestimmungen, Inhaltsverzeichnisse oder Uebergangsvorschriften. Der Prefilter (Stufe 2) sortiert >50% aus, die Harmonisierung (Stufe 5) entfernt weitere Duplikate. Nur konkrete, einzigartige Anforderungen werden zu Controls. --- ## Migration von Controls (Lokal → Production) Controls koennen ueber die REST-API von der lokalen Entwicklungsumgebung in die Production migriert werden. Jedes Control wird einzeln per `POST` mit der Referenz auf das Framework erstellt. ```bash # 1. Control aus lokaler Umgebung exportieren curl -s https://macmini:8002/api/compliance/v1/canonical/controls/AUTH-001 | jq > control.json # 2. In Production importieren (mit framework_id) curl -X POST https://api-dev.breakpilot.ai/api/compliance/v1/canonical/controls \ -H 'Content-Type: application/json' \ -d '{ "framework_id": "bp_security_v1", "control_id": "AUTH-001", "title": "Multi-Faktor-Authentifizierung", "objective": "...", "severity": "high", "open_anchors": [...] }' ``` !!! warning "Framework muss existieren" Das Ziel-Framework (`bp_security_v1`) muss in der Production-DB bereits angelegt sein. Falls nicht, zuerst das Framework erstellen: ```bash curl -X POST https://api-dev.breakpilot.ai/api/compliance/v1/canonical/frameworks \ -H 'Content-Type: application/json' \ -d '{"framework_id": "bp_security_v1", "name": "BreakPilot Security", "version": "1.0"}' ``` --- ## Dateien | Datei | Typ | Beschreibung | |-------|-----|-------------| | `backend-compliance/migrations/044_canonical_control_library.sql` | SQL | 5 Tabellen + Seed-Daten | | `backend-compliance/migrations/046_control_generator.sql` | SQL | Job-Tracking, Chunk-Tracking, Blocked Sources | | `backend-compliance/migrations/047_verification_method_category.sql` | SQL | verification_method + category Felder | | `backend-compliance/migrations/048_processing_path_expand.sql` | SQL | Erweiterte processing_path Werte | | `backend-compliance/compliance/api/canonical_control_routes.py` | Python | REST API (8+ Endpoints) | | `backend-compliance/compliance/api/control_generator_routes.py` | Python | Generator API (Start/Status/Jobs/Stats) | | `backend-compliance/compliance/services/control_generator.py` | Python | 8-Stufen-Pipeline mit Batch Processing | | `backend-compliance/compliance/services/license_gate.py` | Python | Lizenz-Gate-Logik | | `backend-compliance/compliance/services/similarity_detector.py` | Python | Too-Close-Detektor (5 Metriken) | | `backend-compliance/compliance/services/rag_client.py` | Python | RAG-Client (Search + Scroll) | | `ai-compliance-sdk/internal/ucca/legal_rag.go` | Go | RAG Search + Scroll (Qdrant) | | `ai-compliance-sdk/internal/api/handlers/rag_handlers.go` | Go | RAG HTTP-Handler | | `ai-compliance-sdk/policies/canonical_controls_v1.json` | JSON | 10 Seed Controls, 39 Open Anchors | | `ai-compliance-sdk/internal/ucca/canonical_control_loader.go` | Go | Control Loader mit Multi-Index | | `admin-compliance/app/sdk/control-library/page.tsx` | TSX | Control Library Browser | | `admin-compliance/app/sdk/control-provenance/page.tsx` | TSX | Provenance Wiki | | `admin-compliance/app/api/sdk/v1/canonical/route.ts` | TS | Next.js API Proxy | | `scripts/validate-controls.py` | Python | CI/CD Validator | --- ## Tests | Datei | Sprache | Tests | Schwerpunkt | |-------|---------|-------|-------------| | `ai-compliance-sdk/internal/ucca/canonical_control_loader_test.go` | Go | 8 Tests | Control Loader, Multi-Index | | `backend-compliance/compliance/tests/test_similarity_detector.py` | Python | 19 Tests | Too-Close-Detektor, 5 Metriken | | `backend-compliance/tests/test_canonical_control_routes.py` | Python | 14 Tests | REST API Endpoints | | `backend-compliance/tests/test_license_gate.py` | Python | 12 Tests | Lizenz-Klassifikation | | `backend-compliance/tests/test_validate_controls.py` | Python | 14 Tests | CI/CD Validator | | `backend-compliance/tests/test_control_generator.py` | Python | 98 Tests | Pipeline, Batch, Lizenzregeln, QA, Recital, Source-Type | | **Gesamt** | | **166+ Tests** | ### Control Generator Tests (test_control_generator.py) Die Generator-Tests decken folgende Bereiche ab: | Klasse | Tests | Prueft | |--------|-------|--------| | `TestLicenseMapping` | 13 | Lizenz-Klassifikation (Rule 1/2/3), Case-Insensitivitaet, source_type | | `TestDomainDetection` | 5 | Keyword-basierte Domain-Erkennung (AUTH, CRYP, NET, DATA) | | `TestJsonParsing` | 4 | JSON-Parser fuer LLM-Responses (Markdown-Fencing, Preamble) | | `TestGeneratedControlRules` | 3 | Rule-spezifische Felder (original_text, citation, source_info) | | `TestAnchorFinder` | 2 | RAG-Suche + Web-Framework-Erkennung | | `TestPipelineMocked` | 5 | End-to-End Pipeline mit Mocks (Lizenz, Hash-Dedup, Config) | | `TestParseJsonArray` | 15 | JSON-Array-Parser (Wrapper-Objekte, Bracket-Extraction, Fallbacks) | | `TestBatchSizeConfig` | 5 | Batch-Groesse-Konfiguration + Defaults | | `TestBatchProcessingLoop` | 10 | Batch-Verarbeitung (Rule-Split, Mixed-Rules, Too-Close, Null-Handling) | | `TestRegulationFilter` | 5 | regulation_filter Prefix-Matching, leere regulation_codes | | `TestPipelineVersion` | 5 | pipeline_version=2 in DB-Writes, null-Handling in Structure/Reform | | `TestRecitalDetection` | 10 | Erwaegungsgrund-Erkennung in Quelltexten (Regex, Phrasen, Kombiniert) | | `TestSourceTypeClassification` | 16 | law/guideline/standard/restricted Klassifizierung aller Quellentypen | --- ## Multi-Layer Control Architecture Erweitert die bestehende Pipeline um ein 5-Schichten-Modell: ``` Legal Source → Obligation → Control Pattern → Master Control → Customer Instance ``` ### Architektur-Uebersicht | Layer | Asset | Beschreibung | |-------|-------|-------------| | 1: Legal Sources | Qdrant 5 Collections, 105K+ Chunks | RAG-Rohdaten | | 2: Obligations | v2 Framework (325 Pflichten, 9 Verordnungen) | Rechtliche Pflichten | | 3: Control Patterns | 50 YAML Patterns (30 Core + 20 IT-Security) | Umsetzungsmuster | | 4: Master Controls | canonical_controls (atomare Controls nach Dedup) | Kanonische Controls | | 5: Customer Instance | TOM Controls + Gap Mapping | Kundenspezifisch | ### Control-Ebenen | Ebene | Beschreibung | Nutzen | |-------|-------------|--------| | **Rich Controls** | Narrativ, erklaerend, kontextreich (~25.000) | Schulung, Audit-Fragen, Massnahmenplaene | | **Atomare Controls** | 1 Pflicht = 1 Control (nach Decomposition + Dedup) | Systemaudits, Code-Checks, Gap-Analyse, Traceability | ### Pipeline-Erweiterung (10-Stage) ``` Stage 1: RAG SCAN (unveraendert) Stage 2: LICENSE CLASSIFY (unveraendert) Stage 3: PREFILTER (unveraendert) Stage 4: OBLIGATION EXTRACT (NEU — 3-Tier: exact → embedding → LLM) Stage 5: PATTERN MATCH (NEU — Keyword + Embedding + Domain-Bonus) Stage 6: CONTROL COMPOSE (NEU — Pattern + Obligation → Control) Stage 7: HARMONIZE (unveraendert) Stage 8: ANCHOR SEARCH (unveraendert) Stage 9: STORE + CROSSWALK (erweitert — Crosswalk-Matrix) Stage 10: MARK PROCESSED (unveraendert) ``` --- ### Obligation Extractor (Stage 4) 3-Tier Extraktion (schnellste zuerst): | Tier | Methode | Latenz | Trefferquote | |------|---------|--------|--------------| | 1 | Exact Match (regulation_code + article → obligation_id) | <1ms | ~40% | | 2 | Embedding Match (Cosine > 0.80 gegen 325 Obligations) | ~50ms | ~30% | | 3 | LLM Extraction (lokales Ollama, nur Fallback) | ~2s | ~25% | **Datei:** `compliance/services/obligation_extractor.py` ### Pattern Library (Stage 5) 50 YAML-basierte Control Patterns in 16 Domains: | Datei | Patterns | Domains | |-------|----------|---------| | `core_patterns.yaml` | 30 | AUTH, CRYP, NET, DATA, LOG, ACC, SEC, INC, COMP, GOV, RES | | `domain_it_security.yaml` | 20 | SEC, NET, AUTH, LOG, CRYP | **Pattern ID Format:** `CP-{DOMAIN}-{NNN}` (z.B. `CP-AUTH-001`) **Matching:** 2-Tier (Keyword-Index + Embedding), Domain-Bonus (+0.10) **Dateien:** - `ai-compliance-sdk/policies/control_patterns/core_patterns.yaml` - `ai-compliance-sdk/policies/control_patterns/domain_it_security.yaml` - `compliance/services/pattern_matcher.py` ### Control Composer (Stage 6) Drei Kompositions-Modi: | Modus | Wann | Qualitaet | |-------|------|-----------| | Pattern-guided | Pattern gefunden, LLM antwortet | Hoch | | Template-only | LLM-Fehler, aber Pattern vorhanden | Mittel | | Fallback | Kein Pattern-Match | Basis | **Datei:** `compliance/services/control_composer.py` --- ### Decomposition Pass (Pass 0) Zerlegt Rich Controls in atomare Controls. Laeuft VOR den Migration Passes 1-5. #### Pass 0a — Obligation Extraction + 3-Tier-Klassifizierung Extrahiert einzelne normative Pflichten aus einem Rich Control per LLM (Claude Sonnet 4.6). Jede Obligation wird als **pflicht**, **empfehlung** oder **kann** klassifiziert — nichts wird wegen fehlendem normativem Signal abgelehnt. **6 Guardrails:** 1. Nur normative Aussagen (müssen, sicherzustellen, verpflichtet, ...) 2. Ein Hauptverb pro Pflicht 3. Testpflichten separat 4. Meldepflichten separat 5. Nicht auf Evidence-Ebene zerlegen 6. Parent-Link immer erhalten **3-Tier Obligation Classification:** | obligation_type | Signal-Beispiele | Bedeutung | |---|---|---| | `pflicht` | müssen, ist zu, shall, must, required | Gesetzliche/regulatorische Pflicht | | `empfehlung` | soll, should, sicherstellen, dokumentieren | Best Practice, freiwillig | | `kann` | kann, darf, may, optional | Optionale Massnahme | Obligations ohne erkennbares Signal werden als `empfehlung` klassifiziert (nicht rejected). Empfehlungen helfen Firmen, Systeme ueber das Pflichtprogramm hinaus zu sichern. **Quality Gate — Kritische Checks:** | Flag | Kritisch? | Beschreibung | |---|---|---| | `obligation_type` | — | Klassifizierung (pflicht/empfehlung/kann) | | `not_evidence_only` | **Ja** | Kein reines Evidence-Fragment | | `min_length` | **Ja** | Mindestlaenge (20 Zeichen) | | `has_parent_link` | **Ja** | Referenz zum Rich Control | | `has_normative_signal` | Nein | Informativer Check (nicht mehr Ablehnungsgrund) | | `single_action` | Nein | Nur eine Handlung (heuristisch) | | `not_rationale` | Nein | Keine blosse Begruendung | #### Pass 0b — Atomic Control Composition Erstellt aus jedem validierten Obligation Candidate ein atomares Control (LLM-gestuetzt mit Template-Fallback). Das `obligation_type` Feld wird vom Parent-Obligation uebernommen. **Datei:** `compliance/services/decomposition_pass.py` **Test-Script:** `scripts/qa/test_pass0a.py` (standalone, speichert JSON) #### Obligation Deduplizierung Die Decomposition-Pipeline erzeugt pro Rich Control mehrere Obligation Candidates. Durch Wiederholungen in der Pipeline koennen identische `candidate_id`-Eintraege mehrfach existieren (z.B. 5x `OC-AUTH-839-01` mit leicht unterschiedlichem Text). **Dedup-Strategie:** Pro `candidate_id` wird der aelteste Eintrag (`MIN(created_at)`) behalten. Alle anderen erhalten: - `release_state = 'duplicate'` - `merged_into_id` → UUID des behaltenen Eintrags - `quality_flags.dedup_reason` → z.B. `"duplicate of OC-AUTH-839-01"` **Endpunkte:** ```bash # Dry Run — zaehlt betroffene Duplikat-Gruppen curl -X POST "https://macmini:8002/api/compliance/v1/canonical/obligations/dedup?dry_run=true" # Ausfuehren — markiert alle Duplikate curl -X POST "https://macmini:8002/api/compliance/v1/canonical/obligations/dedup?dry_run=false" # Statistiken curl "https://macmini:8002/api/compliance/v1/canonical/obligations/dedup-stats" ``` **Stand (2026-03-26):** 76.046 Obligations gesamt, davon 34.617 als `duplicate` markiert. 41.043 aktive Obligations verbleiben (composed + validated). **Migration:** `081_obligation_dedup_state.sql` — Fuegt `'duplicate'` zum `release_state` Constraint hinzu. --- ### Migration Passes (1-5) Nicht-destruktive Passes fuer bestehende Controls: | Pass | Beschreibung | Methode | |------|-------------|---------| | 1 | Obligation Linkage | source_citation → article → obligation_id (deterministisch) | | 2 | Pattern Classification | Keyword-Matching gegen Pattern Library | | 3 | Quality Triage | Kategorisierung: review / needs_obligation / needs_pattern / legacy_unlinked | | 4 | Crosswalk Backfill | crosswalk_matrix Zeilen fuer verlinkte Controls | | 5 | Deduplication | Gleiche obligation_id + pattern_id → Duplikat markieren | **Datei:** `compliance/services/pipeline_adapter.py` --- ### Crosswalk Matrix Der "goldene Faden" von Gesetz bis Umsetzung: ``` Regulation → Article → Obligation → Pattern → Master Control → TOM ``` Ein atomares Control kann von **mehreren Gesetzen** gleichzeitig gefordert sein. Die Crosswalk-Matrix bildet diese N:M-Beziehung ab. --- ### DB-Schema (Migrations 060 + 061) **Migration 060:** Multi-Layer Basistabellen | Tabelle | Beschreibung | |---------|-------------| | `obligation_extractions` | Chunk→Obligation Verknuepfungen (3-Tier Tracking) | | `control_patterns` | DB-Spiegel der YAML-Patterns fuer SQL-Queries | | `crosswalk_matrix` | Goldener Faden: Regulation→Obligation→Pattern→Control | | `canonical_controls.pattern_id` | Pattern-Zuordnung (neues Feld) | | `canonical_controls.obligation_ids` | Obligation-IDs als JSONB-Array (neues Feld) | **Migration 061:** Decomposition-Tabellen | Tabelle / Feld | Beschreibung | |---------|-------------| | `obligation_candidates` | Extrahierte atomare Pflichten aus Rich Controls | | `obligation_candidates.obligation_type` | `pflicht` / `empfehlung` / `kann` (3-Tier-Klassifizierung) | | `obligation_candidates.release_state` | `extracted` / `validated` / `rejected` / `composed` / `merged` / `duplicate` | | `obligation_candidates.merged_into_id` | UUID des behaltenen Eintrags (bei `duplicate`/`merged`) | | `obligation_candidates.quality_flags` | JSONB mit Metadaten (u.a. `dedup_reason`, `dedup_kept_id`) | | `canonical_controls.parent_control_uuid` | Self-Referenz zum Rich Control (neues Feld) | | `canonical_controls.decomposition_method` | Zerlegungsmethode (neues Feld) | | `canonical_controls.obligation_type` | Uebernommen von Obligation: pflicht/empfehlung/kann | --- ### API Endpoints (Crosswalk Routes) Alle Endpoints unter `/api/compliance/v1/canonical/`: #### Pattern Library | Methode | Pfad | Beschreibung | |---------|------|-------------| | GET | `/patterns` | Alle Patterns (Filter: domain, category, tag) | | GET | `/patterns/{pattern_id}` | Einzelnes Pattern mit Details | | GET | `/patterns/{pattern_id}/controls` | Controls aus einem Pattern | #### Obligation Extraction | Methode | Pfad | Beschreibung | |---------|------|-------------| | POST | `/obligations/extract` | Obligation aus Text extrahieren + Pattern matchen | #### Crosswalk Matrix | Methode | Pfad | Beschreibung | |---------|------|-------------| | GET | `/crosswalk` | Query (Filter: regulation, article, obligation, pattern) | | GET | `/crosswalk/stats` | Abdeckungs-Statistiken | #### Migration + Decomposition | Methode | Pfad | Beschreibung | |---------|------|-------------| | POST | `/migrate/decompose` | Pass 0a: Obligation Extraction aus Rich Controls | | POST | `/migrate/compose-atomic` | Pass 0b: Atomare Control-Komposition | | POST | `/migrate/link-obligations` | Pass 1: Obligation-Linkage | | POST | `/migrate/classify-patterns` | Pass 2: Pattern-Klassifikation | | POST | `/migrate/triage` | Pass 3: Quality Triage | | POST | `/migrate/backfill-crosswalk` | Pass 4: Crosswalk-Backfill | | POST | `/migrate/deduplicate` | Pass 5: Deduplizierung | | GET | `/migrate/status` | Migrations-Fortschritt | | GET | `/migrate/decomposition-status` | Decomposition-Fortschritt | **Route-Datei:** `compliance/api/crosswalk_routes.py` --- ### Multi-Layer Tests | Datei | Tests | Schwerpunkt | |-------|-------|-------------| | `tests/test_obligation_extractor.py` | 107 | 3-Tier Extraktion, Helpers, Regex | | `tests/test_pattern_matcher.py` | 72 | Keyword-Index, Embedding, Domain-Affinity | | `tests/test_control_composer.py` | 54 | Composition, Templates, License-Rules | | `tests/test_pipeline_adapter.py` | 36 | Pipeline Integration, 5 Migration Passes | | `tests/test_crosswalk_routes.py` | 57 | 15 API Endpoints, Pydantic Models | | `tests/test_decomposition_pass.py` | 68 | Pass 0a/0b, Quality Gate, 6 Guardrails | | `tests/test_migration_060.py` | 12 | Schema-Validierung | | `tests/test_control_patterns.py` | 18 | YAML-Validierung, Pattern-Schema | | **Gesamt Multi-Layer** | | **424 Tests** | ### Geplanter Migrationsflow ``` Rich Controls (~25.000, release_state=raw) ↓ Pass 0a: Obligation Extraction (LLM + Quality Gate) ↓ Pass 0b: Atomic Control Composition (LLM + Template Fallback) ↓ Pass 1: Obligation Linking (deterministisch) ↓ Pass 2: Pattern Classification (Keyword + Embedding) ↓ Pass 3: Quality Triage ↓ Pass 4: Crosswalk Backfill ↓ Pass 5: Dedup / Merge ↓ Master Controls (~15.000-20.000 mit voller Traceability) ```