- Control Library: parent control display, ObligationTypeBadge, GenerationStrategyBadge variants, evidence string fallback - API: expose parent_control_uuid/id/title in canonical controls - Fix: DSFA SQLAlchemy 2.0 Row._mapping compatibility - Migration 074: control_parent_links + control_dedup_reviews tables - QA scripts: benchmark, gap analysis, OSCAL import, OWASP cleanup, phase5 normalize, phase74 gap fill, sync_db, run_job - Docs: dedup engine, RAG benchmark, lessons learned, pipeline docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
23 KiB
Control Generator Pipeline
Automatische Generierung von Canonical Controls aus dem gesamten RAG-Korpus (~105.000 Chunks aus Gesetzen, Verordnungen und Standards).
Backend: backend-compliance/compliance/services/control_generator.py
Routes: backend-compliance/compliance/api/control_generator_routes.py
API-Prefix: /api/compliance/v1/canonical/generate
Pipeline-Uebersicht
Die Pipeline durchlaeuft 7 Stufen, um aus RAG-Chunks eigenstaendige Security/Compliance Controls zu erzeugen:
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]
| Stufe | Name | Beschreibung |
|---|---|---|
| 1 | RAG Scan | Laedt unverarbeitete Chunks aus Qdrant (Scroll-API), filtert per SHA-256-Hash |
| 2 | License Classify | Bestimmt die Lizenzregel (Rule 1/2/3) anhand regulation_code |
| 3a | Structure (Batch) | Rule 1+2: Strukturiert Originaltext als Control (Anthropic API) |
| 3b | Reform (Batch) | Rule 3: Vollstaendige Reformulierung ohne Originaltext (Anthropic API) |
| 4 | Harmonize | Embedding-basierte Duplikaterkennung (bge-m3, Cosine > 0.85) |
| 5 | Anchor Search | Findet Open-Source-Referenzen (OWASP, NIST, ENISA) |
| 6 | Store | Persistiert Control in canonical_controls mit Metadaten |
| 7 | Mark Processed | Markiert jeden Chunk als verarbeitet (auch bei Skip/Error/Duplikat) |
Pipeline-Versionen
Die Pipeline hat zwei Versionen. Die Version wird als pipeline_version auf canonical_controls und canonical_processed_chunks gespeichert.
v1 (Original)
| Eigenschaft | Wert |
|---|---|
| Vorfilter | Lokales LLM (llama3.2 3B) entscheidet ob Chunk relevant |
| Anthropic-Prompt | Alter Prompt ohne null-Skip |
| Annexe/Anhaenge | Kein Schutz — wurden haeufig faelschlich als irrelevant uebersprungen |
pipeline_version |
1 |
v2 (Aktuell)
| Eigenschaft | Wert |
|---|---|
| Vorfilter | Optional (skip_prefilter). Wenn aktiviert, entscheidet Anthropic API selbst |
| Anthropic-Prompt | Neuer Prompt mit null-Skip: API gibt null fuer Chunks ohne Anforderung zurueck |
| Annexe/Anhaenge | Explizit geschuetzt — Prompt-Anweisung: "Anhaenge/Annexe enthalten oft KONKRETE technische Anforderungen — diese MUESSEN als Control erfasst werden!" |
pipeline_version |
2 |
Wesentliche Aenderungen v1 → v2
- Relevanz-Entscheidung an Anthropic delegiert — Das lokale LLM (Vorfilter) ist optional. Die Anthropic API entscheidet selbst, welche Chunks Controls enthalten, indem sie
nullfuer irrelevante Chunks zurueckgibt. - null-Skip im JSON-Array — Das Ergebnis-Array enthaelt
null-Eintraege fuer Chunks ohne umsetzbare Anforderung. Kein separater Vorfilter-Schritt noetig. - Annexe/Anhaenge geschuetzt — Explizite Prompt-Anweisung verhindert, dass technische Anforderungen in Anhaengen uebersprungen werden.
Datenbank-Feld
-- Migration 062
ALTER TABLE canonical_controls
ADD COLUMN pipeline_version smallint NOT NULL DEFAULT 1;
ALTER TABLE canonical_processed_chunks
ADD COLUMN pipeline_version smallint NOT NULL DEFAULT 1;
Neue Controls erhalten automatisch pipeline_version = 2. Bestehende (v1) behalten 1, damit sie spaeter identifiziert und ggf. reprocessiert werden koennen.
Konfiguration
Request-Parameter (GenerateRequest)
| Parameter | Typ | Default | Beschreibung |
|---|---|---|---|
collections |
List[str] |
Alle 5 Collections | Qdrant-Collections zum Durchsuchen |
domain |
str |
— | Filter auf eine Domain (z.B. AUTH, NET) |
regulation_filter |
List[str] |
— | Prefix-Matching auf regulation_code (z.B. ["eu_2023_1230", "owasp_"]) |
skip_prefilter |
bool |
false |
Ueberspringt lokalen LLM-Vorfilter, sendet alle Chunks an die Anthropic API |
batch_size |
int |
5 |
Chunks pro Anthropic-API-Call |
max_controls |
int |
50 |
Maximale Anzahl Controls pro Job (0 = unbegrenzt) |
max_chunks |
int |
1000 |
Maximale Chunks pro Job (0 = unbegrenzt, respektiert Dokumentgrenzen) |
skip_web_search |
bool |
false |
Ueberspringt Web-Suche in der Anchor-Findung (Stufe 5) |
dry_run |
bool |
false |
Trockenlauf ohne DB-Schreibzugriffe (synchron, mit Controls im Response) |
!!! info "regulation_filter — Prefix-Matching"
Der Filter vergleicht den regulation_code jedes Chunks per Prefix.
Beispiel: ["eu_2023_1230"] erfasst nur Chunks aus der Maschinenverordnung.
["owasp_"] erfasst alle OWASP-Dokumente (OWASP ASVS, OWASP SAMM, etc.).
Gross-/Kleinschreibung wird ignoriert.
Umgebungsvariablen
| Variable | Default | Beschreibung |
|---|---|---|
ANTHROPIC_API_KEY |
— | API-Key fuer Anthropic Claude (Pflicht) |
CONTROL_GEN_ANTHROPIC_MODEL |
claude-sonnet-4-6 |
Anthropic-Modell fuer Strukturierung/Reformulierung |
OLLAMA_URL |
http://host.docker.internal:11434 |
Lokaler Ollama-Server (Vorfilter + QA) |
CONTROL_GEN_OLLAMA_MODEL |
qwen3.5:35b-a3b |
Lokales LLM-Modell fuer Vorfilter und QA-Arbitrierung |
CONTROL_GEN_LLM_TIMEOUT |
180 |
Timeout in Sekunden pro Anthropic-API-Call |
Pipeline-interne Konstanten
| Konstante | Wert | Beschreibung |
|---|---|---|
PIPELINE_VERSION |
2 |
Aktuelle Pipeline-Version |
HARMONIZATION_THRESHOLD |
0.85 |
Cosine-Similarity-Schwelle fuer Duplikaterkennung |
max_tokens |
8192 |
Maximale Token-Laenge der LLM-Antwort |
API Endpoints
Alle Endpoints unter /api/compliance/v1/canonical/.
Uebersicht
| Methode | Pfad | Beschreibung |
|---|---|---|
POST |
/generate |
Generierungs-Job starten (laeuft im Hintergrund) |
GET |
/generate/status/{job_id} |
Status eines laufenden Jobs abfragen |
GET |
/generate/jobs |
Alle Jobs auflisten (paginiert) |
GET |
/generate/processed-stats |
Verarbeitungsstatistik pro Collection |
GET |
/generate/review-queue |
Controls zur manuellen Pruefung |
POST |
/generate/review/{control_id} |
Review eines einzelnen Controls abschliessen |
POST |
/generate/bulk-review |
Bulk-Review nach release_state |
POST |
/generate/qa-reclassify |
QA-Reklassifizierung bestehender Controls |
GET |
/blocked-sources |
Gesperrte Quellen (Rule 3) auflisten |
POST |
/blocked-sources/cleanup |
Cleanup-Workflow fuer gesperrte Quellen starten |
POST /v1/canonical/generate — Job starten
Startet einen Generierungs-Job im Hintergrund. Gibt sofort eine job_id zurueck.
Request:
{
"collections": ["bp_compliance_gesetze"],
"regulation_filter": ["eu_2023_1230"],
"skip_prefilter": false,
"batch_size": 5,
"max_chunks": 500,
"max_controls": 0,
"skip_web_search": false,
"dry_run": false
}
Response (200):
{
"job_id": "a1b2c3d4-...",
"status": "running",
"message": "Generation started in background. Poll /generate/status/{job_id} for progress."
}
Beispiel:
# Alle Chunks der Maschinenverordnung verarbeiten
curl -X POST https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate \
-H 'Content-Type: application/json' \
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000' \
-d '{
"collections": ["bp_compliance_ce"],
"regulation_filter": ["eu_2023_1230"],
"max_chunks": 200,
"batch_size": 5
}'
# Dry Run: Keine DB-Aenderungen, Controls im Response
curl -X POST https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate \
-H 'Content-Type: application/json' \
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000' \
-d '{
"collections": ["bp_compliance_gesetze"],
"max_chunks": 10,
"dry_run": true
}'
# Ohne Vorfilter: Alle Chunks direkt an Anthropic API
curl -X POST https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate \
-H 'Content-Type: application/json' \
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000' \
-d '{
"collections": ["bp_compliance_gesetze"],
"regulation_filter": ["bdsg"],
"skip_prefilter": true,
"max_chunks": 100
}'
!!! warning "Kosten beachten"
Ohne regulation_filter und mit max_chunks: 0 werden alle 105.000 Chunks verarbeitet.
Das verursacht erhebliche Anthropic-API-Kosten ($700).
GET /v1/canonical/generate/status/{job_id} — Job-Status
Gibt den vollstaendigen Status eines Jobs zurueck inkl. Metriken und Fehler.
Beispiel:
curl https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate/status/a1b2c3d4-... \
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000'
Response:
{
"id": "a1b2c3d4-...",
"status": "completed",
"total_chunks_scanned": 500,
"controls_generated": 48,
"controls_verified": 45,
"controls_needs_review": 3,
"controls_too_close": 0,
"controls_duplicates_found": 12,
"controls_qa_fixed": 5,
"config": { "..." },
"started_at": "2026-03-17T10:00:00+00:00",
"completed_at": "2026-03-17T10:15:32+00:00"
}
GET /v1/canonical/generate/jobs — Alle Jobs
Paginierte Liste aller Generierungs-Jobs.
Query-Parameter:
| Parameter | Default | Beschreibung |
|---|---|---|
limit |
20 |
Anzahl Jobs (1-100) |
offset |
0 |
Offset fuer Paginierung |
Beispiel:
curl "https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate/jobs?limit=5" \
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000'
GET /v1/canonical/generate/review-queue — Review-Queue
Listet Controls auf, die eine manuelle Pruefung benoetigen.
Query-Parameter:
| Parameter | Default | Beschreibung |
|---|---|---|
release_state |
needs_review |
Filter: needs_review, too_close, duplicate |
limit |
50 |
Anzahl (1-200) |
Beispiel:
curl "https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate/review-queue?release_state=needs_review&limit=10" \
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000'
POST /v1/canonical/generate/review/{control_id} — Review abschliessen
Schliesst die manuelle Pruefung eines Controls ab.
Request:
{
"action": "approve",
"release_state": "draft",
"notes": "Inhaltlich korrekt, Severity passt."
}
Moegliche action-Werte:
| Action | Neuer State | Beschreibung |
|---|---|---|
approve |
draft (oder per release_state ueberschreiben) |
Control freigeben |
reject |
deprecated |
Control verwerfen |
needs_rework |
needs_review |
Zurueck in die Queue |
Beispiel:
curl -X POST https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate/review/AUTH-042 \
-H 'Content-Type: application/json' \
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000' \
-d '{"action": "approve", "release_state": "draft"}'
POST /v1/canonical/generate/bulk-review — Bulk-Review
Aendert den release_state aller Controls, die einen bestimmten State haben.
Request:
{
"release_state": "needs_review",
"action": "approve",
"new_state": "draft"
}
Beispiel:
# Alle needs_review Controls auf draft setzen
curl -X POST https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate/bulk-review \
-H 'Content-Type: application/json' \
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000' \
-d '{"release_state": "needs_review", "action": "approve", "new_state": "draft"}'
GET /v1/canonical/generate/processed-stats — Verarbeitungsstatistik
Liefert Statistiken pro RAG-Collection.
Beispiel:
curl https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate/processed-stats \
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000'
Response:
{
"stats": [
{
"collection": "bp_compliance_gesetze",
"processed_chunks": 45200,
"direct_adopted": 1850,
"llm_reformed": 120,
"skipped": 43230,
"total_chunks_estimated": 0,
"pending_chunks": 0
}
]
}
Kosten und Performance
Kostenabschaetzung
| Metrik | Wert |
|---|---|
| Kosten pro Chunk | ~$0.0067 (Anthropic API, Batch-Modus) |
| Yield (Controls/Chunks) | ~4.5-10% (nur Chunks mit konkreten Anforderungen erzeugen Controls) |
| Vorfilter-Ersparnis | ~55% der API-Kosten wenn aktiviert (irrelevante Chunks werden lokal aussortiert) |
Performance-Kennzahlen
| Metrik | Wert |
|---|---|
| Batch-Groesse | 5 Chunks pro API-Call (Default) |
| API-Aufrufe Reduktion | ~80% weniger Aufrufe durch Batching |
| LLM-Timeout | 180 Sekunden pro Call |
| QA-Overhead | ~2s pro Control (nur bei Disagreement, ~10-15% der Controls) |
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 |
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% |
Lizenz-Klassifikation (3-Regel-System)
Jeder Chunk wird basierend auf regulation_code einer Lizenzregel zugeordnet:
| Regel | Typ | Original erlaubt? | Beispiele |
|---|---|---|---|
| Rule 1 (free_use) | EU-Gesetze, NIST, DE-Gesetze, Public Domain | Ja | DSGVO, BDSG, NIS2, AI Act |
| Rule 2 (citation_required) | CC-BY, CC-BY-SA | Ja, mit Zitation | OWASP ASVS, OWASP SAMM |
| Rule 3 (restricted) | Proprietaer | Nein, volle Reformulierung | BSI TR-03161, ISO 27001 |
Verarbeitung nach Regel
- Rule 1+2 →
_structure_batch(): Anthropic strukturiert den Originaltext als Control. Ein API-Call fuer den gesamten Batch. - Rule 3 →
_reformulate_batch(): Anthropic reformuliert vollstaendig — kein Originaltext, keine Quellennamen. Ein API-Call fuer den gesamten Batch.
Batch Processing
Die Pipeline sammelt Chunks in Batches (Default: 5 Chunks) und sendet sie in einem einzigen Anthropic-API-Call.
- Relevante Chunks werden mit Lizenz-Info in
pending_batchgesammelt - Bei
batch_sizeerreicht →_flush_batch() - Batch wird nach Lizenzregel getrennt: Rule 1+2 →
_structure_batch(), Rule 3 →_reformulate_batch() - Ergebnis: JSON-Array mit genau N Elementen (
nullfuer irrelevante Chunks)
Fallback: Bei Batch-Fehler (Timeout, Parsing-Error) wird automatisch auf Einzelverarbeitung zurueckgefallen.
Chunk-Tracking (Processed Chunks)
Tabelle canonical_processed_chunks
| Spalte | Typ | Beschreibung |
|---|---|---|
chunk_hash |
VARCHAR(64) | SHA-256 Hash des Chunk-Textes |
collection |
VARCHAR(100) | Qdrant-Collection |
regulation_code |
VARCHAR(100) | Quell-Regulation (z.B. bdsg, eu_2016_679) |
license_rule |
INTEGER | 1, 2 oder 3 |
processing_path |
VARCHAR(20) | Wie der Chunk verarbeitet wurde |
generated_control_ids |
JSONB | UUIDs der generierten Controls |
pipeline_version |
SMALLINT | Pipeline-Version (1 oder 2) |
job_id |
UUID | Referenz auf den Generierungs-Job |
UNIQUE Constraint: (chunk_hash, collection, document_version) — verhindert Doppelverarbeitung.
Processing Paths
| Wert | Stufe | Bedeutung |
|---|---|---|
prefilter_skip |
2 | Lokaler LLM-Vorfilter: Chunk nicht relevant |
structured |
3a | Einzelner Chunk strukturiert (Rule 1/2) |
structured_batch |
3a | Batch-Strukturierung (Rule 1/2) |
llm_reform |
3b | Einzelner Chunk reformuliert (Rule 3) |
llm_reform_batch |
3b | Batch-Reformulierung (Rule 3) |
no_control |
3 | LLM konnte kein Control ableiten (null im Array) |
store_failed |
6 | DB-Speichern fehlgeschlagen |
error |
— | Unerwarteter Fehler |
QA Validation (Automatische Qualitaetspruefung)
Die QA-Stufe validiert die Klassifizierung jedes generierten Controls:
- LLM-Category: Anthropic liefert
categoryunddomainim JSON-Response - Keyword-Detection:
_detect_category(chunk.text)liefert eine zweite Meinung - Stimmen beide ueberein? → Schneller Pfad (kein QA noetig)
- Bei Disagreement: Lokales LLM (Ollama) arbitriert
- Auto-Fix: Category/Domain werden automatisch korrigiert
Die QA-Metriken werden in generation_metadata gespeichert:
{
"qa_category_fix": {"from": "authentication", "to": "finance", "reason": "IFRS-Thema"},
"qa_domain_fix": {"from": "AUTH", "to": "FIN", "reason": "Finanzregulierung"}
}
Recital-Erkennung (Erwägungsgrund-Detektion)
Die QA-Stufe prueft zusaetzlich, ob der source_original_text eines Controls tatsaechlich aus einem Gesetzesartikel stammt — oder aus einem Erwaegungsgrund (Recital). Erwaegungsgruende enthalten keine normativen Pflichten und fuehren zu falsch zugeordneten Controls.
Erkennungsmethoden:
| Methode | Pattern | Beispiel |
|---|---|---|
| Regex | \((\d{1,3})\)\s*\n — Erwaegungsgrund-Nummern |
(126)\nUm den Verwaltungsaufwand... |
| Phrasen | Typische Recital-Formulierungen (≥2 Treffer) | "daher sollte", "in Erwägung nachstehender Gründe" |
Ergebnis bei Verdacht:
release_statewird aufneeds_reviewgesetztgeneration_metadata.recital_suspect = truegeneration_metadata.recital_detectionenthaelt Details:
{
"recital_suspect": true,
"recital_detection": {
"recital_suspect": true,
"recital_numbers": ["126", "127"],
"recital_phrases": ["daher sollte"],
"detection_method": "regex+phrases"
}
}
Funktion: _detect_recital(text) in control_generator.py
Hintergrund: Bei der Analyse von ~5.500 Controls mit Quelltext wurden 1.555 (28%) als Erwaegungsgrund-Verdacht identifiziert. Der Document Crawler unterschied nicht zwischen Artikeltext und Erwaegungsgruenden, was zu falschen article/paragraph-Zuordnungen fuehrte.
QA-Reklassifizierung bestehender Controls
# Dry Run: Welche AUTH-Controls sind falsch klassifiziert?
curl -X POST https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate/qa-reclassify \
-H 'Content-Type: application/json' \
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000' \
-d '{"limit": 50, "dry_run": true, "filter_domain_prefix": "AUTH"}'
# Korrekturen anwenden:
curl -X POST https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate/qa-reclassify \
-H 'Content-Type: application/json' \
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000' \
-d '{"limit": 50, "dry_run": false, "filter_domain_prefix": "AUTH"}'
Quelldateien
| Datei | Beschreibung |
|---|---|
backend-compliance/compliance/services/control_generator.py |
7-Stufen-Pipeline mit Batch Processing |
backend-compliance/compliance/api/control_generator_routes.py |
REST API Endpoints |
backend-compliance/compliance/services/license_gate.py |
Lizenz-Gate-Logik |
backend-compliance/compliance/services/similarity_detector.py |
Too-Close-Detektor (5 Metriken) |
backend-compliance/compliance/services/rag_client.py |
RAG-Client (Qdrant Search + Scroll) |
backend-compliance/migrations/046_control_generator.sql |
Job-Tracking, Chunk-Tracking Tabellen |
backend-compliance/migrations/048_processing_path_expand.sql |
Erweiterte Processing-Path-Werte |
backend-compliance/migrations/062_pipeline_version.sql |
pipeline_version Spalte |
backend-compliance/tests/test_control_generator.py |
98+ Tests (Lizenz, Domain, Batch, Pipeline, Recital, Source-Type) |
Pass 0a/0b: Atomare Control-Zerlegung
Die Pipeline v3 erweitert die 7-Stufen-Pipeline um einen Vor-Pass, der Rich Controls in atomare Controls zerlegt.
Pass 0a: Obligation Extraction
Extrahiert individuelle normative Pflichten aus Rich Controls via LLM.
flowchart LR
A[Rich Control] -->|LLM| B[Obligations]
B --> C{Quality Gate}
C -->|Pass| D[validated]
C -->|Fail| E[rejected]
3-Tier Klassifikation:
| Typ | Erkennungsmuster | Beispiel |
|---|---|---|
| Pflicht | muss, ist verpflichtet, hat sicherzustellen | "Der Verantwortliche MUSS ein Verzeichnis fuehren" |
| Empfehlung | soll, sollte, wird empfohlen | "Es SOLLTE eine Risikobewertung durchgefuehrt werden" |
| Kann | kann, darf, ist berechtigt | "Die Aufsichtsbehoerde KANN Geldbussen verhaengen" |
Quality Gate (6 Regeln):
- Nur normative Aussagen (muss, sicherzustellen, verpflichtet)
- Ein Hauptverb pro Obligation
- Test-Obligations separat von operativen
- Reporting-Obligations separat
- Nicht auf Evidence-Ebene splitten
- Parent-Link immer erhalten
Pass 0b: Atomic Control Composition
Verwandelt jede validierte Obligation in ein eigenstaendiges atomares Control.
flowchart LR
A[Obligation] -->|LLM| B[Atomic Control]
B -->|Dedup Check| C{4-Stage Dedup}
C -->|NEW| D[Insert + Index]
C -->|LINK| E[Parent-Link]
C -->|REVIEW| F[Review-Queue]
Konfiguration:
| Variable | Default | Beschreibung |
|---|---|---|
DECOMPOSITION_LLM_MODEL |
claude-sonnet-4-6 |
LLM fuer Pass 0a/0b |
DECOMPOSITION_BATCH_SIZE |
5 |
Obligations pro LLM-Call |
DECOMPOSITION_LLM_TIMEOUT |
120 |
Timeout in Sekunden |
Ergebnisse (Stand 2026-03-21):
| Metrik | Wert |
|---|---|
| Rich Controls (technisch) | ~6.800 |
| Atomare Controls (bisher) | 30 (PoC: 10x CRYP, AUTH, SEC) |
| Ziel nach Full Run | ~18.000 unique Master Controls |
| Obligations pro Rich Control | ~10 |
| Dedup-Reduktion erwartet | ~70% |
Quelldateien (Pass 0a/0b)
| Datei | Beschreibung |
|---|---|
compliance/services/decomposition_pass.py |
Pass 0a + 0b Logik |
compliance/services/control_dedup.py |
4-Stufen Dedup-Engine |
migrations/061_obligation_candidates.sql |
Obligation-Tabelle |
migrations/074_control_dedup.sql |
Dedup-Tabellen (Parent-Links, Review-Queue) |
tests/test_decomposition_pass.py |
90 Tests |
tests/test_control_dedup.py |
56 Tests |
Verwandte Dokumentation
- Canonical Control Library (CP-CLIB) — Domains, Datenmodell, Too-Close-Detektor, CI/CD Validation
- Deduplizierungs-Engine — 4-Stufen Dedup, Multi-Parent-Linking, Review-Queue
- RAG Pipeline Benchmark — State-of-the-Art Vergleich, Optimierungsempfehlungen
- Multi-Layer Control Architecture — 10-Stage Pipeline-Erweiterung mit Obligations, Patterns, Crosswalk