fix: V1 Enrichment — Qdrant Collection + Parent-Resolution fuer regulatorische Matches
All checks were successful
CI/CD / go-lint (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Successful in 33s
CI/CD / test-python-backend-compliance (push) Successful in 30s
CI/CD / test-python-document-crawler (push) Successful in 21s
CI/CD / test-python-dsms-gateway (push) Successful in 16s
CI/CD / validate-canonical-controls (push) Successful in 9s
CI/CD / Deploy (push) Successful in 1s

Die atomic_controls_dedup Collection (51k Punkte) enthaelt nur atomare
Controls ohne source_citation. Jetzt wird der Parent-Control aufgeloest,
der die Rechtsgrundlage traegt. Deduplizierung nach Parent-UUID verhindert
mehrfache Eintraege fuer die gleiche Regulation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-26 10:52:41 +01:00
parent db7c207464
commit 81c9ce5de3
2 changed files with 68 additions and 25 deletions

View File

@@ -68,11 +68,24 @@ class TestV1EnrichmentExecution:
]
mock_count = MagicMock(cnt=1)
mock_matched_row = MagicMock(
# Atomic control found in Qdrant (has parent, no source_citation)
mock_atomic_row = MagicMock(
id="uuid-atomic-1",
control_id="SEC-042-A01",
title="Verschluesselung (atomar)",
source_citation=None, # Atomic controls don't have source_citation
parent_control_uuid="uuid-reg-1",
severity="high",
category="encryption",
)
# Parent control (has source_citation)
mock_parent_row = MagicMock(
id="uuid-reg-1",
control_id="SEC-042",
title="Verschluesselung personenbezogener Daten",
source_citation={"source": "DSGVO (EU) 2016/679", "article": "Art. 32"},
parent_control_uuid=None,
severity="high",
category="encryption",
)
@@ -81,9 +94,9 @@ class TestV1EnrichmentExecution:
{
"score": 0.89,
"payload": {
"control_uuid": "uuid-reg-1",
"control_id": "SEC-042",
"title": "Verschluesselung",
"control_uuid": "uuid-atomic-1",
"control_id": "SEC-042-A01",
"title": "Verschluesselung (atomar)",
},
},
{
@@ -100,18 +113,19 @@ class TestV1EnrichmentExecution:
mock_session.return_value.__enter__ = MagicMock(return_value=db)
mock_session.return_value.__exit__ = MagicMock(return_value=False)
# Multiple execute calls: v1 list, count, matched_row lookup, insert
call_count = [0]
# Route queries to correct mock data
def side_effect_execute(query, params=None):
call_count[0] += 1
result = MagicMock()
# fetchall for v1 controls list
query_str = str(query)
result.fetchall.return_value = mock_v1
# fetchone for count and matched row
if "COUNT" in str(query):
if "COUNT" in query_str:
result.fetchone.return_value = mock_count
elif "source_citation IS NOT NULL" in str(query):
result.fetchone.return_value = mock_matched_row
elif "source_citation IS NOT NULL" in query_str:
# Parent lookup
result.fetchone.return_value = mock_parent_row
elif "c.id = CAST" in query_str or "canonical_controls c" in query_str:
# Direct atomic control lookup
result.fetchone.return_value = mock_atomic_row
else:
result.fetchone.return_value = mock_count
return result