Neue Endpunkte POST /obligations/dedup und GET /obligations/dedup-stats. Pro candidate_id wird der aelteste Eintrag behalten, alle weiteren erhalten release_state='duplicate' mit merged_into_id + quality_flags fuer Traceability. Detail-View filtert Duplikate aus. MKDocs aktualisiert. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
46 KiB
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
- Unabhaengige Taxonomie — Eigene Domain-IDs (AUTH, NET, SUP, etc.), eigenes ID-Format (
DOMAIN-NNN) - Open-Source-Verankerung — Jedes Control hat mindestens 1 Open Anchor (OWASP/NIST/ENISA)
- Strikte Quellentrennung — Geschuetzte Quellen nur intern zur Analyse, nie im Produkt
- 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)
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
curl -s https://macmini:8002/api/v1/canonical/controls/AUTH-001 | jq
Beispiel: Similarity Check
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:
{
"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:
- Schema Validation — Alle Pflichtfelder, ID-Format, Severity
- No-Leak Scanner — Regex gegen BSI-Muster (
O.Auth_*,TR-03161, etc.) - Open Anchor Check — Jedes Control hat ≥1 Open Anchor
- Taxonomy Check — Keine BSI-style ID-Prefixe
- 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:
- Schweregrad (critical, high, medium, low)
- Domain (aus Meta-Daten, alle vorhandenen Domains)
- Status (draft, approved, needs_review, too_close, duplicate, deprecated)
- Nachweis (code_review, document, tool, hybrid)
- Kategorie (23 thematische Kategorien)
- Zielgruppe (17 Audience-Werte)
- 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):
- Methodik der Control-Erstellung — Dreistufiger Prozess, rechtliche Basis (UrhG §44b, §23)
- Filter in der Control Library — Erklaerung aller 7 Filter + Sortierung
- Badges & Lizenzregeln — Rule 1/2/3, Processing Paths, Referenzen
- Unabhaengige Taxonomie — Top-10 Domains, ID-Format, spezialisierte Domains
- Offene Referenzquellen — OWASP, NIST, ENISA, SLSA, CIS
- Geschuetzte Quellen — BSI, ISO, ETSI + Trennungsprinzip
- Verifikationsmethoden — 4 Methoden + Kundenbedeutung
- Thematische Kategorien — 17 Kategorien mit Beschreibung
- Master Library Strategie — RAG-First, Dedup, Wellen-Ansatz
- Automatisierte Validierung — CI/CD-Checks, Too-Close-Detektor
Live-Daten (API-gespeist):
- Lizenz-Matrix: Tabelle aller
canonical_control_licensesmit Berechtigungsbadges - Quellenregister: Karten fuer jede
canonical_control_sourcesmit 4 Berechtigungsstufen
Siehe auch: Control Provenance Dokumentation
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 fuer die vollstaendige Referenz inkl. API-Endpoints, Konfiguration, Kosten und Pipeline-Versionen.
7-Stufen-Pipeline (v2)
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
- Chunks sammeln: Nach dem Prefilter werden relevante Chunks mit ihrer Lizenz-Info in
pending_batchgesammelt - Batch voll? Sobald
batch_size(Default: 5) erreicht ist, wird_flush_batch()aufgerufen _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
- Rule 1+2 Chunks →
- 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.
# 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.
# 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:
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
- LLM-Category auswerten: Der Anthropic-Prompt fragt jetzt explizit nach
categoryunddomain - Keyword-Detection als Cross-Check:
_detect_category(chunk.text)liefert eine zweite Meinung - Stimmen beide ueberein? → Kein QA noetig (schneller Pfad)
- Bei Disagreement: Lokales LLM (Ollama qwen3.5:35b-a3b) arbitriert
- 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
{
"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:
# 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_methodundcategory - 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:
- LLM-Klassifikation (primaer): Anthropic liefert
categoryim JSON-Response - Keyword-Detection (fallback): Falls LLM keine Category liefert, greift
_detect_category() - 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
# 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
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.
curl -s https://macmini:8002/api/compliance/v1/canonical/generate/processed-stats | jq
Response:
{
"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.
# 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.yamlai-compliance-sdk/policies/control_patterns/domain_it_security.yamlcompliance/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:
- Nur normative Aussagen (müssen, sicherzustellen, verpflichtet, ...)
- Ein Hauptverb pro Pflicht
- Testpflichten separat
- Meldepflichten separat
- Nicht auf Evidence-Ebene zerlegen
- 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 Eintragsquality_flags.dedup_reason→ z.B."duplicate of OC-AUTH-839-01"
Endpunkte:
# 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)