Compare commits

..

1 Commits

Author SHA1 Message Date
Benjamin Admin 2e4c5c0907 docs(platform): Pruefer-Matrix / Meta-Modell einfrieren (verification_method + decision_method)
Routing-Prinzip aus 4 kalibrierten Modulen (DSE/Cookie/Impressum/AGB): Kontrolltyp bestimmt Pruefer. Zwei Achsen — verification_method (8 Klassen x Pruefer) + decision_method (KEYWORD->EMBEDDING->LLM) — plus durable Metadaten-Felder, Routing-Kette und die erarbeiteten Prinzipien. Vertrag fuer kommende Modul-Integrationen (AGB, Nutzungsbedingungen, Widerruf, CRA, NIS2).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-21 00:33:22 +02:00
16 changed files with 225 additions and 863 deletions
-13
View File
@@ -48,16 +48,3 @@ backups/*.backup
*.wav
ai-compliance-sdk/server
*.bak
# Build/test artifacts (2026-06-21 cleanup)
docs-site/
ux-screenshots/
**/test-results/
**/audit-reports/
admin-compliance/e2e/reports/
admin-compliance/e2e/e2e/
design/redesign/*-preview.png
admin-compliance/BreakPilot-Pitch-Submission.html
admin-compliance/shot-ds.mjs
admin-compliance/ux-shots.mjs
Neuer Ordner mit Objekten/
@@ -5,7 +5,6 @@
* Frueher: bp-core-rag-service:8097 — der existiert auf prod NICHT (nur macmini/dev),
* dadurch lieferte die Drafting-Engine dort keinen RAG-Kontext. Die ai-sdk embeddet
* mit bge-m3 und ist prod-erreichbar. Genutzt von draft-, chat- und vendor-review-Routes.
* Fundstellen via article_label sind live ab dem Prod-Re-Ingest 2026-06.
*/
const SDK_URL =
@@ -33,12 +33,6 @@ type RegulatoryNewsFilter struct {
// GetRegulatoryNews scans all v2 obligations for upcoming deadlines
// and returns formatted news items sorted by urgency.
func GetRegulatoryNews(regulations map[string]*V2RegulationFile, filter RegulatoryNewsFilter) []RegulatoryNewsItem {
return GetRegulatoryNewsAt(regulations, filter, time.Now().UTC())
}
// GetRegulatoryNewsAt is GetRegulatoryNews with an injectable reference time so the
// upcoming-deadline window is deterministic in tests (no time-bomb once a deadline passes).
func GetRegulatoryNewsAt(regulations map[string]*V2RegulationFile, filter RegulatoryNewsFilter, now time.Time) []RegulatoryNewsItem {
if filter.HorizonDays <= 0 {
filter.HorizonDays = 365
}
@@ -46,7 +40,7 @@ func GetRegulatoryNewsAt(regulations map[string]*V2RegulationFile, filter Regula
filter.Limit = 5
}
today := now.UTC().Truncate(24 * time.Hour)
today := time.Now().UTC().Truncate(24 * time.Hour)
horizon := today.AddDate(0, 0, filter.HorizonDays)
var items []RegulatoryNewsItem
@@ -174,10 +174,7 @@ func TestGetRegulatoryNews_FromRealFiles(t *testing.T) {
if err != nil {
t.Skipf("could not load v2 regulations: %v", err)
}
// Fixed reference date so the test is deterministic regardless of the wall clock:
// VBR-OBL-001 (deadline 2026-06-19) must fall within [ref, ref+730d].
ref := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
items := GetRegulatoryNewsAt(regs, RegulatoryNewsFilter{Limit: 20, HorizonDays: 730}, ref)
items := GetRegulatoryNews(regs, RegulatoryNewsFilter{Limit: 20, HorizonDays: 730})
// Should find at least the Widerrufsbutton obligation
found := false
for _, item := range items {
@@ -231,17 +231,6 @@ _USE_CASES: tuple[UseCase, ...] = (
UseCase("bafin_it", "BaFin IT-Aufsicht (VAIT/BAIT)", "security",
regulations=("VAIT", "BAIT"),
verification_methods=("it_process", "document", "network")),
UseCase("eidas", "eIDAS / Vertrauensdienste (VO 910/2014)", "product",
regulations=("eIDAS",), verification_methods=("document", "it_process"),
categories=("compliance", "security"),
keyword_tokens=("eidas", "vertrauensdienst", "signatur", "siegel",
"zeitstempel", "zertifikat")),
UseCase("geschaeftsgeheimnis", "Geschäftsgeheimnisse (GeschGehG)", "cross_cutting",
regulations=("GeschGehG",),
verification_methods=("document", "it_process", "manual"),
categories=("compliance", "security"),
keyword_tokens=("geschäftsgeheimnis", "vertraulichkeit", "geheimhaltung",
"betriebsgeheimnis")),
)
@@ -352,11 +341,6 @@ _REGULATION_RULES: tuple[tuple[str, str], ...] = (
("bait", "bafin_it"),
("gobd", "steuerrecht"),
("dienstleistungs-informationspflichten", "impressum"),
# eIDAS / Geschäftsgeheimnis (neue Use Cases 2026-06-17)
("eidas", "eidas"),
("910/2014", "eidas"),
("geschäftsgeheim", "geschaeftsgeheimnis"),
("geschgehg", "geschaeftsgeheimnis"),
# Datenschutz-Catch-alls (zuletzt)
("nist privacy framework", "dse"),
("dsgvo", "dse"),
@@ -182,18 +182,12 @@ def _filter_controls(
for c in controls:
cid = c.get("control_id") or ""
prefix = cid.split("-")[0].upper() if "-" in cid else ""
on_topic = criteria_on_topic(c.get("pass_criteria"),
c.get("fail_criteria"))
required = SECTOR_PREFIXES.get(prefix)
# Sektor-Gate nur fuer NICHT-on-topic Controls: ein klar
# impressum-thematischer Control (z.B. MStV §18(1) mit GOV-Prefix
# aus der Domain-Erkennung der Control-Generierung) darf nicht am
# Branchen-Prefix scheitern. Der Themen-Ueberlapp ist der staerkere
# Relevanz-Beweis als ein vererbter ID-Prefix.
if required and not (scope_lc & required) and not on_topic:
if required and not (scope_lc & required):
sector_dropped += 1
continue
if not on_topic:
if not criteria_on_topic(c.get("pass_criteria"),
c.get("fail_criteria")):
offtopic_dropped += 1
continue
kept.append(c)
@@ -1,18 +0,0 @@
-- Migration 154: control_pendants — self-written (license_rule=3) -> sourced
-- (license_rule 1/2) Pendant-Mapping aus dem Phase-2-Reconcile (Embedding-kNN +
-- Haiku-Adjudikation, 2026-06-15). Ein hier gelistetes self-written Atom hat ein
-- kommerziell nutzbares Quell-Control, das DIESELBE Pflicht ausdrueckt -> das
-- Retrieval soll das lizenzierte Quell-Control bevorzugen. Additiv, idempotent.
-- [migration-approved]
SET search_path TO compliance, public;
CREATE TABLE IF NOT EXISTS control_pendants (
control_uuid uuid PRIMARY KEY,
pendant_control_uuid uuid NOT NULL,
cosine numeric,
method varchar(40) NOT NULL DEFAULT 'embed_haiku',
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_control_pendants_pendant
ON control_pendants (pendant_control_uuid);
@@ -1,87 +0,0 @@
"""Tests for the audit-walk ZIP-builder."""
import io
import json
import zipfile
from unittest.mock import patch, MagicMock
from compliance.services.audit_walk_zip_builder import (
_readme,
build_audit_walk_zip,
)
_FAKE_WALK = {
"walk_id": "abc123def456",
"url": "https://example.com/",
"started_at": "2026-06-07T10:00:00+00:00",
"completed_at": "2026-06-07T10:00:30+00:00",
"video": {
"filename": "video.webm",
"size_bytes": 12345,
"sha256": "a" * 64,
"dsms": {"cid": "QmFakeCidVideo"},
},
"walk_json_dsms": {"cid": "QmFakeCidMeta"},
"actions": [
{"action": "navigate", "url": "https://example.com/dse"},
{"action": "navigate", "url": "https://example.com/imprint"},
{"action": "expand_accordions", "expanded": 3},
],
}
class TestReadme:
def test_contains_walk_id_and_url(self):
r = _readme(_FAKE_WALK)
assert "abc123def456" in r
assert "https://example.com/" in r
def test_contains_dsms_cids(self):
r = _readme(_FAKE_WALK)
assert "QmFakeCidVideo" in r
assert "QmFakeCidMeta" in r
def test_counts_navigates_and_accordions(self):
r = _readme(_FAKE_WALK)
assert "2 Compliance-Seiten" in r
assert "3 Akkordeon" in r
class TestBuildZip:
def test_empty_walk_returns_empty(self):
assert build_audit_walk_zip({}) == b""
def test_zip_contains_three_entries(self):
# Mock the video fetch to return tiny content
with patch(
"compliance.services.audit_walk_zip_builder.httpx.Client"
) as mock_client:
instance = mock_client.return_value.__enter__.return_value
instance.get.return_value = MagicMock(
status_code=200, content=b"fakevideo",
)
zip_bytes = build_audit_walk_zip(_FAKE_WALK)
assert zip_bytes
with zipfile.ZipFile(io.BytesIO(zip_bytes)) as z:
names = set(z.namelist())
assert {"video.webm", "walk.json", "README.txt"}.issubset(names)
walk_content = json.loads(z.read("walk.json"))
assert walk_content["walk_id"] == "abc123def456"
assert z.read("video.webm") == b"fakevideo"
def test_video_fetch_failure_still_produces_zip(self):
# consent-tester down → no video, but ZIP still contains
# walk.json + README so the recipient has the metadata.
with patch(
"compliance.services.audit_walk_zip_builder.httpx.Client"
) as mock_client:
instance = mock_client.return_value.__enter__.return_value
instance.get.side_effect = Exception("network down")
zip_bytes = build_audit_walk_zip(_FAKE_WALK)
assert zip_bytes
with zipfile.ZipFile(io.BytesIO(zip_bytes)) as z:
names = z.namelist()
assert "video.webm" not in names
assert "walk.json" in names
assert "README.txt" in names
@@ -159,13 +159,3 @@ def test_all_regulation_rules_point_to_valid_use_cases():
for _needle, uc in reg._REGULATION_RULES:
assert uc in reg.REGISTRY, uc
assert reg.REGISTRY[uc].enabled
def test_new_use_cases_eidas_geschaeftsgeheimnis():
# Korpus-Luecken 2026-06-17: eIDAS (VO 910/2014) + GeschGehG als eigene
# Use Cases ingestiert + klassifiziert.
assert reg.is_valid_use_case("eidas")
assert reg.is_valid_use_case("geschaeftsgeheimnis")
assert reg.use_case_for_regulation("eIDAS-Verordnung (EU) Nr. 910/2014") == "eidas"
assert reg.use_case_for_regulation(
"Gesetz zum Schutz von Geschäftsgeheimnissen") == "geschaeftsgeheimnis"
View File
@@ -1,62 +0,0 @@
# Benchmark-Archiv & RC-Freeze — `v1` (2026-06-19)
> **Zweck:** Reproduzierbarkeits-Record der Doc-Check-Kalibrierung (DSE / Cookie / Impressum).
> Diese Datei enthält **nur Metadaten + Hashes** — **kein** Drittanbieter-Dokumenttext (Urheber-/Datenbankrecht).
> Die vollständigen Artefakte (Korpora, GTs, Ergebnisse, Skripte) liegen im **internen Audit-Archiv**, getrennt von Repo / RAG / Produkt.
## 1. Daten-Klassen (Retention-Entscheidung 2026-06-19)
Drei Risikoklassen, drei Regeln:
| Klasse | Regel |
|---|---|
| **RAG-Korpus** | Control ableiten → Dokument **verwerfen**. Keine Volltexte als Wissensbasis. |
| **Kundendaten (Prod)** | Speichern: Finding · Evidence · Hash · Version · URL · Zeitpunkt. **Keine** Dauer-Volltextkopie. Datensparsamkeit. |
| **Benchmark/Validierung** | **Versioniert behalten** — sonst sind Messungen nicht reproduzierbar. Intern, off-RAG, off-Produkt. Wie ein Test-/Audit-Archiv, nicht wie eine Wissensbasis. |
Begründung: Das Risiko eines kleinen internen Benchmark-Archivs (öffentlich zugängliche Dokumente) ist geringer als das Risiko, die gesamte Validierung später nicht mehr belegen zu können.
## 2. Release-Candidates (eingefroren)
| RC | doc_type | Opus-GT (Archiv) | Testfirmen | FP / FN | Status |
|---|---|---|---|---|---|
| **DSE_RC_v1** | dse | `gt_opus_dse.json` (5 orig) + `gt_opus_dse_fresh.json` (3 frisch) | 8 (db, otto, ikea, ob, teamviewer + GT-Roster) | FP 11 %→**6 %**, FN ~7 %; frisch FP 7 % / FN 5 % | Release-Candidate |
| **COOKIE_RC_v1** | cookie | `gt_opus_cookie_v2.json` (Mehrfach-Sampling offen) | 7 (db, ikea, lieferando, mediamarkt, ob, tchibo, teamviewer) | Prec 0,81→**0,95**, Rec 0,26→**0,44**, verpasste Lücken→**0 %** | Wave-1 (GT-Rauschen-Vorbehalt) |
| **IMPRESSUM_RC_v1** | impressum | `gt_opus_impressum.json` | 9 (db, ikea, lieferando, mediamarkt, ob, otto, tchibo, teamviewer, zalando) | Text-Check FP **0 %** / FN **2 %** (81 anwendbar, 9 Faktenfeld-Controls) | Release-Candidate |
Detail-Methodik + Fehlerkarte: [`platform_validation_v1.md`](platform_validation_v1.md). Per-Modul-Zahlen: Gedächtnis `project_engine_quality.md`.
## 3. Archiv-Ort + Index
```
macmini:~/bp-benchmark-archive/v1_2026-06-19/
├── MANIFEST.json # 54 Dateien, je SHA256 + Bytes (autoritativ)
├── gt_<firma>_<doctype>.txt # Korpora (Drittanbieter-Volltext — NUR hier)
├── gt_opus_*.json # Opus-Oracle-GTs
├── *_candidates*.json, *_resid.json, *_falsefindings*.json
├── *_criteria_changelog.json / *_criteria_backup.json
└── scripts/ # 46 Mess-Skripte (cc_*.py) = "wie gemessen"
```
**Versionsdefinierende Hashes** (12-stellig gekürzt; voll in `MANIFEST.json`):
| Artefakt | sha256… | Rolle |
|---|---|---|
| `gt_opus_dse.json` | `c5c8975afa42` | DSE-GT (orig) |
| `gt_opus_dse_fresh.json` | `f3940da2e420` | DSE-GT (Anti-Overfit) |
| `gt_opus_cookie_v2.json` | `fcb61dc9b332` | Cookie-GT |
| `gt_opus_impressum.json` | `3e0f2f8d5f5f` | Impressum-GT |
| `dse_criteria_changelog.json` | `d8d461527f5b` | DSE-Kriterien-Diff |
| `cookie_criteria_changelog.json` | `9d29d7b515a5` | Cookie-Kriterien-Diff |
| `impressum_fp_by_cause.json` | `9477f98c0577` | Impressum SCOPE/JUDGE-Split |
## 4. Reproduktion
1. Archiv = Grundwahrheit (Korpus-Hash belegt die damalige Dokumentversion; ändert die Firma ihr Dokument → neuer Hash, alte Messung bleibt über das Archiv belegbar).
2. Mess-Skripte unter `scripts/` gegen die GTs laufen lassen (Pattern: `docker exec -i bp-compliance-backend python3 - < scripts/cc_engine_*.py`).
3. OVH ist stochastisch → Zahlen ±Rauschen; RC-Werte sind Mittel über den dokumentierten Lauf.
## 5. Was NICHT passiert
- Korpus-Volltexte gehen **nicht** ins Repo, **nicht** in Qdrant/RAG, **nicht** ins Produkt.
- Das Archiv ist read-only Referenz; Kalibrierungs-Änderungen sind über die Changelog-Artefakte reversibel.
@@ -0,0 +1,87 @@
# Prüfer-Matrix — Meta-Modell der Doc-Check-Plattform
> **Status:** Plattformkonzept, **eingefroren 2026-06-21**. Abgeleitet aus 4 kalibrierten Modulen (DSE, Cookie, Impressum, AGB). Erweitert `verification_method.md` (5→8 Klassen) und fügt die `decision_method`-Achse hinzu.
> **Kernsatz:** *Nicht jedes Control braucht denselben Richter.* Der **Kontrolltyp bestimmt den Prüfer** — nicht alles ist ein Text-/LLM-Problem.
## 0. Die Architektur-Verschiebung
**Vorher (implizit):** `Control → Embedding → LLM → Finding`.
**Jetzt (empirisch bewiesen):**
```
Control → [scope-gate] → artifact_type → verification_method → decision_method
→ passender Prüfer → Evidence → Finding (severity-getiert)
```
Vier strukturell verschiedene Dokumenttypen führten immer wieder auf dieselbe Meta-Struktur. Das ist größer als jeder Einzel-Fix: es ist mit hoher Wahrscheinlichkeit das Routing-Prinzip für alle ~14.000 Master Controls.
## 1. Empirische Basis (4 Module)
| Modul | dominanter Prüfer | Beleg |
|---|---|---|
| DSE | CONTENT (LLM/Embedding) | Kriterien-Kalibrierung, FP 11→6 % |
| Cookie-Banner | BEHAVIOR | Enforcement / Dark-Pattern (Playwright) |
| Cookie-Policy | CONTENT + REFERENCE | Inhalt + Verweise |
| Impressum | FIELD + PRESENTATION (+ SCOPE-Gate) | Feld-Matcher FP 0 %, Präsentation re-routed |
| AGB | CONTENT (KEYWORD→EMBEDDING→LLM) + REFERENCE (+ SCOPE-Gate) | 71 % FP → ~0; LLM nur 2/21 Items |
## 2. Achse 1 — `verification_method` (welcher Prüfer-TYP)
| verification_method | Prüfer | Leitfrage | Beleg | Reifegrad |
|---|---|---|---|---|
| **CONTENT** | Embedding + LLM-Kaskade | Was steht (als Offenlegung) im Text? | DSE, Cookie-Policy | kalibriert |
| **FIELD** | Regex / Extraktion (Feldmatrix) | Welche Pflichtfelder existieren + sind valide? | Impressum (HRB, USt-IdNr, Anschrift) | ✓ FP 0 % |
| **REFERENCE** | Link-Resolver | Gibt es einen klaren Verweis/Link, löst er auf? | AGB `data_protection` | ✓ 7/7 |
| **BEHAVIOR** | Playwright + API | Manipuliert die UI die Entscheidung? | Cookie-Banner (Reject=Accept, Pre-Consent-Cookies) | Matrix vorhanden |
| **PRESENTATION** | Playwright UI-Sensor | Auffindbar / sichtbar / erreichbar? | Impressum „leicht erkennbar" | re-routed |
| **PROCESS** | Audit / Evidence | Gibt es einen internen Nachweis? | VVT, TOM, interne Richtlinie | Checkliste |
| **TECHNICAL** | Scanner (Repo / Netz / Config) | Ist die technische Maßnahme implementiert? | geplant: CRA, NIS2, ISO 27001 | offen |
| **CONTRACTUAL** | Clause-Engine | Ist die Klausel vorhanden + rechtskonform? | AGB (delivery/warranty; Defekte → Stage 3) | teilweise |
**CONTENT vs CONTRACTUAL:** CONTENT = Offenlegungs-Prosa (DSE nennt Zwecke). CONTRACTUAL = Vertragsklauseln (AGB-Haftung/Lieferung). Beide können Embedding+LLM nutzen — die Trennung ist die Rechtsnatur + die spätere Defekt-Prüfung (Klausel rechtswidrig?).
**PRESENTATION ≠ BEHAVIOR:** beide Playwright, andere Rechtslogik. PRESENTATION = Auffindbarkeit/Sichtbarkeit; BEHAVIOR = Entscheidungs-Manipulation/Dark-Pattern.
## 3. Achse 2 — `decision_method` (WIE innerhalb CONTENT/CONTRACTUAL entschieden wird)
Die AGB-Entdeckung: **Controls INNERHALB eines Prüfer-Typs brauchen verschiedene Entscheider.** Eskalation nur bei Bedarf (Kostendisziplin):
| decision_method | Mechanismus | Wann | Beleg (AGB) |
|---|---|---|---|
| **KEYWORD** | Regex-Match | Pflicht eindeutig formuliert | Keyword-Layer |
| **EMBEDDING** | per-Item-Cosinus-Schwelle (Doc-Chunks × Item-Paraphrasen) | Prosa, semantisch trennbar | 13/21 Items, 0 Fehl-Rescue |
| **LLM** | Clause-Retrieval (**ganze §-Abschnitte**) + starkes Modell, present/absent | semantisch eng (Embedding trennt nicht) | 2/21 Items (delivery/warranty), 14/14 |
`CONTENT_SIMPLE` = KEYWORD/EMBEDDING reicht; `CONTENT_COMPLEX` = LLM nötig. AGB-Bilanz: **81 % deterministisch, 19 % LLM-fähig**, LLM real nur bei Keyword-Miss.
## 4. Durable Per-Control-Metadaten (das Routing-Vokabular)
| Feld | Zweck |
|---|---|
| `artifact_type` | gegen welches Artefakt geprüft wird → Scanner-Routing |
| `obligation_type` | Rechtsnatur: Pflicht / Empfehlung / Kann → Tier |
| `check_intent` | was die Prüfung bezweckt |
| `reference_allowed` | darf per Verweis erfüllt werden → REFERENCE statt CONTENT |
| `scope` / `scope_requires` | Applicability-Gate (Geschäftsmodell, Rechtsform) — **vor** allen Prüfern |
| `verification_method` | Achse 1 (Prüfer-Typ) |
| `decision_method` | Achse 2 (Entscheider innerhalb CONTENT/CONTRACTUAL) |
| `severity` | HIGH / MEDIUM / LOW → Finding vs Empfehlung |
## 5. Hart erarbeitete Plattform-Prinzipien
1. **Route, don't uniformly-LLM** — verschiedene Controls, verschiedene Prüfer.
2. Eskaliere **KEYWORD → EMBEDDING → LLM nur bei Bedarf** (AGB: 17/21 ohne LLM).
3. Embedding: **per-Item-Schwellen** (globale Schwelle scheitert bei juristischer Prosa — PASS/FAIL überlappen global, trennen per-Item).
4. LLM-Judge: **ganze §-Abschnitte** schlagen Top-k-Chunks; **starken Tier pinnen** (billig-zuerst-Kaskade eskaliert selbstbewusst-falsche Antworten NICHT, weil die Confidence-Heuristik genauigkeits-blind ist); **present/absent** trennen von der Defekt-Prüfung.
5. **REFERENCE (Link) ist ein eigener billiger Prüfer** — keinen „siehe Datenschutzerklärung"-Verweis durch ein LLM jagen.
6. **SCOPE-Gate (Applicability) ist vor allen Prüfern** — N/A-Controls werden nie geprüft.
7. **Severity → Finding vs Empfehlung** (Tier, nicht droppen).
8. *Was im Text nicht beweisbar ist, gehört nicht in den Text-Check.*
## 6. Schema-Status
Kein DB-Eingriff (DB eingefroren). `verification_method` + `decision_method` als **abgeleitete Tags** in `control_classification` (aus `artifact_type` / `obligation_type` / `check_intent` + Item-Kalibrierung). `canonical_controls.verification_method` existiert (~4 % befüllt, gröbere Enterprise-Taxonomie) — **nicht** das Doc-Check-Routing.
## 7. Verbindlichkeit
Dies ist der **Vertrag**, gegen den implementiert wird. Die AGB-Integration und die nächsten Module (Nutzungsbedingungen, Widerruf, CRA, MaschVO, DORA, NIS2, ISO 27001, AI-Act, VVT, TOM) bauen **dieselbe** Routing-Schicht — nicht modul-lokal. Reihenfolge: **(1) diese Matrix einfrieren → (2) AGB integrieren → (3) Nutzungsbedingungen → (4) Widerruf.**
@@ -0,0 +1,74 @@
# Plattform-Validierung der Doc-Check-Kalibrierung — `platform_validation_v1`
> **Status:** Plattform-Methodik validiert über 3 strukturell verschiedene Dokumentklassen (2026-06-19).
> **Zweck:** Nicht ein Modul dokumentieren, sondern den **Kalibrierungsprozess** und die **empirische Fehlerkarte** der Engine — damit die *Ursachen* erhalten bleiben (nicht nur die Messwerte). Erkenntnis > Metrik.
## 1. Was hier validiert wurde
Vor dieser Runde war unklar, ob der Restfehler der Doc-Check-Engine aus dem **LLM**, dem **Embedding**, dem **Prompt**, der **Applicability** oder dem **Control-Katalog** stammt — alles vermischt. Nach DSE + Cookie + Impressum existiert eine **belastbare Taxonomie der Fehlerursachen**, und der **Kalibrierungsprozess** hat in drei sehr unterschiedlichen Domänen geliefert. Das ist die eigentliche Errungenschaft — größer als jede einzelne Zahl.
## 2. Der Kalibrierungsprozess (wiederverwendbarer Kern)
1. **Opus-GT** je `(Firma × Control)` über 59 repräsentative Firmen (stärkstes Modell, NICHT Haiku).
2. **Engine-Messung** (Keyword → BGE-M3-Embedding → robuster LLM-Judge) vs GT.
3. **FP-Cluster** — wiederkehrende Controls statt Einzel-Findings (systematisch ≠ zufällig).
4. **Ursachen-Klassifikation** je FP: `SCOPE` / `ARTIFACT_TYPE` / `CRITERIA` / `JUDGE`.
5. **Fix** der dominanten Ursache (versioniert, mit Rechtsnotiz).
6. **Re-Messung** — Pflicht: FP↓ **und** FN stabil. Plus **Anti-Overfit** auf ungesehenen Firmen.
## 3. Plattform-Fehlerkarte (Kernergebnis)
| Modul | Dominante Ursache | Hebel | Ergebnis | Status |
|---|---|---|---|---|
| **DSE** | Kriterien zu streng | Kriterien-Kalibrierung (11 Controls) | FP 11 % → **6 %**, FN ~7 %; **generalisiert** (8 Firmen; fresh FP 7 % / FN 5 %) | Release-Candidate |
| **Cookie** | `artifact_type` (Banner ≠ Richtlinie) | 31 Banner-Controls → `COOKIE_BANNER`; 21 Kriterien (Kategorie statt Pro-Cookie, Zitat optional), Pro-Cookie = Best-Practice | Precision 0,81 → **0,95**, Recall 0,26 → **0,44**, verpasste Lücken → **0 %**, abs. FP 71 → 54 | Wave-1 (dev) |
| **Impressum** | **Scope** (GT-NA 48 %) + **Feld-Extraktion** + **Präsentation** | Scope-Gate (14 raus) + **Feldmatrix-Matcher** (Fakten) + **PRESENTATION_CHECK**-Re-Route (5) | roh: SCOPE-FP 105 / JUDGE-FP 66 → **Text-Check FP 0 % / FN 2 %** | Release-Candidate |
## 4. Meta-Befunde
- **Die generische Architektur bewährt sich.** Jede Domäne hat ein *anderes* dominantes Problem — `artifact_type` / `obligation_type` / `scope` tragen unterschiedlich stark. Eine gute generische Architektur erzeugt nicht überall denselben Effekt, sondern löst je Domäne ein anderes Problem. Genau das ist eingetreten.
- **Die Zielarchitektur ist domänen-adaptiv, nicht uniform.** „Embedding → OVH → Claude" ist nicht überall richtig: bei **Prosa** (DSE/Cookie) ist die LLM-Kaskade der Hebel; bei **strukturierten Faktendokumenten** (Impressum) ist das LLM sogar schwach (es verfehlt Adressen/Felder, die *dastehen*) → dort schlagen **Scope-Gate + deterministischer Feld-Matcher** den LLM-Judge.
- **Wiederkehrendes Anti-Muster:** „vermeintlicher Judge-Fehler → eigentlich Katalog-Fehler" (Scope, Präsentations-statt-Inhalt, Fehl-Typisierung). Erst NACH den Katalog-Fixes ist der Rest ein *echter* Judge-Fehler.
## 4b. Die `verification_method`-Achse (Synthese — die eigentliche Lehre)
Nicht jede Compliance-Pflicht ist ein Textproblem. Die 5 entdeckten Fehlerklassen mappen auf **5 Prüfer-Typen** — eine neue Routing-Metadaten-Achse `verification_method`, die einem Control sagt, *welcher Prüfer* zuständig ist (nicht alles an den LLM):
| `verification_method` | Prüfer | Frage | Beispiel | Status |
|---|---|---|---|---|
| **CONTENT** | Embedding + LLM-Kaskade (OVH→Claude) | Was steht da? | DSE nennt Zwecke; Cookie-Policy | DSE/Cookie kalibriert |
| **FIELD** | Regex/Parser (Feldmatrix) | Welche Felder existieren? | HRB, USt-IdNr, Adresse | Impressum-Fakten ✓ (FP 0 %) |
| **PRESENTATION** | Playwright (Sichtbarkeit/Erreichbarkeit) | Ist es auffindbar/wahrnehmbar? | Impressum leicht erkennbar, ständig verfügbar; Footer nicht verdeckt | Re-Route gemacht; Check offen |
| **BEHAVIOR** | Playwright + API (Interaktion) | Manipuliert es die Entscheidung? | Reject = Accept, Consent VOR Cookie, kein Dark Pattern | Cookie-Banner-Matrix existiert |
| **PROCESS** | Audit/Nachweis | Gibt es internen Nachweis? | VVT, interne Richtlinie, Audit-Entscheidung | Org-Checkliste |
**PRESENTATION ≠ BEHAVIOR** (beide Playwright, andere Rechtslogik): Präsentation = *Auffindbarkeit/Sichtbarkeit/Zugänglichkeit* (Impressum leicht erkennbar); Behavior = *Entscheidungs-Manipulation/Dark-Pattern* (Reject versteckt). Getrennt halten.
**Playwright wird damit vom Crawler zum Compliance-Sensor:** es prüft, was kein LLM kann — `display:none`, `font-size:4px`, Cookie-Layer verdeckt den Footer. LLM sieht `<a href="/impressum">` und sagt „erfüllt"; Playwright sieht die Verdeckung und sagt „nicht erfüllt".
**Kern-Regel der Architektur:** *Was im Text nicht beweisbar ist, gehört nicht in den Text-Check.* → route per `verification_method`. Sobald die Klassen sauber getrennt sind, sinken die FP fast automatisch (Impressum: SCOPE+JUDGE 171 → Text-Check-FP 0).
**Schema-Status:** `canonical_controls.verification_method` existiert (nur ~4 % befüllt, andere/gröbere Taxonomie document/code_review/tool/hybrid), `doc_check_controls` hat sie nicht. Die hier definierte Doc-Check-Routing-Achse ist **aus `control_classification` (artifact_type/obligation_type/check_intent) ableitbar** → kein Schema-Eingriff (eingefroren) nötig; als abgeleitetes Tag in `control_classification` führen.
## 5. Mess-Disziplin (prove-don't-handwave)
- GT mit dem stärksten Modell (`claude-opus-4-8`), nicht Haiku (zu lasch).
- Robust gegen LLM-Leerantworten: Retry + `INSUFFICIENT_EVIDENCE`/Eskalation statt FEHLT (ein realer Produktions-Bug, der die FP künstlich aufblähte).
- **Anti-Overfit:** Kriterien am Gesetz kalibrieren, dann auf *ungesehenen* Firmen gegenprüfen (DSE: 5 Original + 3 frische → stabile Zahlen = kein Overfit).
- OVH ist stochastisch (±~Rauschen je Lauf) und strenger als Opus → der Rest-FP konvergiert über Module auf **OVH-Über-Strenge**.
- **Zirkularitäts-Leitplanke:** Claude = Opus-GT-Modell → ein Claude-Tier-Sim misst die *Kaskaden-Reichweite* (erreicht Opus-Niveau), nicht eine unabhängige Validierung.
## 6. Offen (Reihenfolge)
1. **Claude-Tier-Sim (DSE + Cookie):** quantifiziert den verbleibenden **reinen** Judge-Fehler nach allen Katalog-Fixes — die letzte große unbekannte Variable. Erwartung: kleiner als roh, weil viel „Judge" sich als Katalog entpuppte.
2. **Impressum-Fix:** Rechtsform-Scope-Gate (#33) verdrahten + deterministischer Feld-Matcher + Re-Messung.
3. **Cookie Wave-2** (Cluster-E) + Produktions-Re-Route der 31 Banner-Controls (`control_classification`).
4. **Produktivschaltung** DSE + Cookie (zuletzt; verify-first DB-Write).
## 7. Artefakte
- DSE: `docs-src/development/dse_v1_validation.md`, `dse_criteria_changelog.json`/`dse_criteria_backup.json`.
- Cookie: `cookie_criteria_changelog.json`/`cookie_criteria_backup.json`/`cookie_best_practice.json` (Container `/tmp`), Cluster-Map.
- Impressum: `impressum_fp_by_cause.json` (SCOPE/JUDGE-Split).
- Gedächtnis: `project_engine_quality.md` (Detail je Modul). Werkzeuge: `cc_gt_opus_*`, `cc_engine_*`, `cc_*_candidates*` (alle macmini `/tmp`).
- **Alle Control-Änderungen nur auf macmini-dev**, versioniert, reversibel; Prod-Schaltung ausstehend.
@@ -0,0 +1,59 @@
# `verification_method` — die Prüfer-Routing-Achse
> **Status:** Architektur-Achse (2026-06-19), abgeleitet aus der 3-Modul-Kalibrierung (DSE / Cookie / Impressum).
> **Kernsatz:** *Nicht jede Compliance-Pflicht ist ein Textproblem.* `verification_method` sagt einem Control, **welcher Prüfer** zuständig ist — damit nicht alles am LLM hängt.
## 1. Warum diese Achse existiert
Die Kalibrierung von drei strukturell verschiedenen Dokumentklassen zeigte drei **verschiedene** dominante Fehlerursachen — und alle ließen sich auf die *Wahl des falschen Prüfers* zurückführen:
- **DSE** (Prosa): LLM-Urteil zu streng → Kriterien-Kalibrierung. Prüfer war richtig (LLM), Kriterien falsch.
- **Cookie** (Banner ≠ Richtlinie): Controls am falschen Artefakt geprüft → `artifact_type`-Re-Route.
- **Impressum** (Faktendokument): LLM verfehlt Felder, die *dastehen* (Adresse, HRB) → deterministischer Feld-Matcher schlägt den LLM. Und 5 Controls waren **gar nicht im Text beweisbar** (Erreichbarkeit/Verfügbarkeit) → gehören an Playwright, nicht an den Text-Check.
**Regel:** *Was im Text nicht beweisbar ist, gehört nicht in den Text-Check.* Sobald die Klassen sauber getrennt sind, sinken die False Positives fast automatisch (Beleg Impressum: SCOPE+JUDGE 171 Roh-FP → Text-Check-FP 0).
## 2. Die fünf Klassen
| `verification_method` | Prüfer | Leitfrage | Beispiel | Reifegrad |
|---|---|---|---|---|
| **CONTENT** | Embedding-Recall + LLM-Kaskade (OVH→Claude) | Was steht da? | DSE nennt Verarbeitungszwecke; Cookie-Richtlinie | DSE/Cookie kalibriert |
| **FIELD** | Regex / Parser (Feldmatrix) | Welche Felder existieren + sind valide? | HRB, USt-IdNr, Anschrift, E-Mail+Telefon | Impressum-Fakten ✓ (FP 0 %) |
| **PRESENTATION** | Playwright (Rendering-Sensor) | Ist es auffindbar / wahrnehmbar / erreichbar? | Impressum „leicht erkennbar", ständig verfügbar, Footer nicht verdeckt | Re-Route gemacht, Checker offen |
| **BEHAVIOR** | Playwright + API (Interaktion) | Manipuliert die UI die Entscheidung? | Reject = Accept, Cookies VOR Consent, Dark Pattern | Cookie-Banner-Matrix vorhanden |
| **PROCESS** | Audit / Nachweis | Gibt es einen internen Nachweis? | VVT, interne Richtlinie, Audit-Entscheidung | Org-Checkliste |
## 3. PRESENTATION ≠ BEHAVIOR
Beide nutzen Playwright, prüfen aber **verschiedene Rechtslogik** — getrennt halten:
- **PRESENTATION** = Auffindbarkeit / Sichtbarkeit / Zugänglichkeit. Beispiel: Impressum-Link erreichbar, nicht in 4px-Schrift, nicht hinter `display:none`, nicht dauerhaft vom Cookie-Layer verdeckt.
- **BEHAVIOR** = Entscheidungs-Manipulation / Dark-Pattern. Beispiel: „Ablehnen" versteckt, Vorauswahl gesetzt, Consent technisch ignoriert.
## 4. Playwright als Compliance-Sensor (nicht Crawler)
Playwright prüft, was **kein** LLM kann: Der LLM sieht `<a href="/impressum">` und urteilt „erfüllt"; der Sensor sieht, dass das Element verdeckt / unsichtbar / unerreichbar ist und urteilt „nicht erfüllt". Drei technische Prüfer langfristig:
- **Content-Checker** → LLM (CONTENT)
- **Structure-Checker** → Regex/Parser (FIELD)
- **Presentation-Checker** → Playwright (PRESENTATION + BEHAVIOR)
## 5. Schema-Status & Verortung
- `canonical_controls.verification_method` **existiert**, aber nur ~4 % befüllt und mit *anderer*, gröberer Taxonomie (`document` / `code_review` / `tool` / `hybrid` — generische Enterprise-Verifikation, nicht das Doc-Check-Routing).
- `doc_check_controls` hat **keine** `verification_method`-Spalte.
- → Die hier definierte Doc-Check-Routing-Achse ist **neu**, aber **ableitbar** aus den schon vorhandenen `control_classification`-Achsen (`artifact_type` / `obligation_type` / `check_intent`). **Kein** Schema-Eingriff nötig (DB ist eingefroren) — als abgeleitetes Tag in `control_classification` führen.
Heuristik für die Ableitung (Startpunkt, nicht final):
| Signal | → verification_method |
|---|---|
| `artifact_type = COOKIE_BANNER`, Interaktionspflicht | BEHAVIOR |
| Pflicht zu Erreichbarkeit / Sichtbarkeit / „ständig verfügbar" | PRESENTATION |
| Faktenfeld (Anschrift, Register, Kennung) | FIELD |
| `obligation_type` Prozess / Nachweis ohne Außenwirkung | PROCESS |
| sonst (inhaltliche Offenlegung in Prosa) | CONTENT |
## 6. Warum das über die 3 Module hinaus zählt
Für die nächsten Module (CRA, Maschinenverordnung, NIS2, TISAX, ISO 27001) ist diese Achse vermutlich fast so wichtig wie `artifact_type`: viele dieser Pflichten sind **PROCESS** oder **BEHAVIOR**, kein Textinhalt. Wer sie an den LLM-Text-Check hängt, erzeugt systematische False Positives. Das ist die eigentliche Erkenntnis der Kalibrierung: **nicht** dass DSE/Cookie/Impressum funktionieren, sondern dass klar wurde, *welcher Prüfer für welche Art von Pflicht zuständig ist*.
@@ -1,147 +0,0 @@
# Ground Truth: Conrady Gruppe
**URL:** https://conradygruppe.com
**Typ:** Mittelstand / B2B Industrie (CookieYes-CMP)
**Datum:** 2026-05-20
**Tester:** Benjamin (manuell verifiziert)
---
## Business Profile (erwartet)
| Feld | Erwarteter Wert |
|------|----------------|
| business_type | b2b |
| industry | manufacturing / services |
| has_online_shop | false |
| no_direct_sales | true |
---
## Dokumente
| Dokumenttyp | Vorhanden | URL / Hinweis |
|-------------|-----------|---------------|
| DSE | Ja | https://conradygruppe.com/datenschutz |
| Impressum | Ja | https://conradygruppe.com/impressum |
| **Cookie-Richtlinie** | **NEIN** | nicht erreichbar — separate Seite fehlt |
| AGB | (offen) | B2B, vermutlich individuell |
| Widerruf | In DSE | — |
| DSB-Kontakt | In DSE | E-Mail-Adresse benannt |
| Social Media DSE | (zu pruefen) | siehe SoMe-Findings |
---
## Erwartete Findings — Impressum (Art. 5 TMG)
| Check | Erwartet | Begruendung |
|-------|----------|-------------|
| Handelsregister/Registernummer | **FEHLT** | §5(1) Nr.4 TMG — Pflichtangabe |
| **USt-IdNr.** | **FEHLT** | §5(1) Nr.6 TMG — wenn vorhanden Pflicht. Steuernummer ist KEIN Ersatz |
| Verantwortlicher | OK | Name + Anschrift vorhanden |
| Vertretungsberechtigter | (zu pruefen) | bei juristischer Person Pflicht |
| Kontakt (E-Mail/Tel) | (zu pruefen) | §5(1) Nr.2 TMG |
---
## Cookie-Banner (CookieYes)
**3 Buttons im Banner:**
1. **"Speichern"** — funktional ein Reject mit aktuellen Einstellungen
2. **"Alle akzeptieren"**
3. **"Nur essenzielle Cookies akzeptieren"** — funktional der Ablehnen-Button
| Check | Erwartet | Anmerkung |
|-------|----------|-----------|
| Banner detected (CookieYes) | OK | Bot erkennt es als CookieYes |
| Ablehnen-Mechanismus vorhanden | OK (implicit via "Nur essenzielle") | aber: |
| Explizites "Ablehnen"-Label | **FEHLT** | "Nur essenzielle" + "Speichern" — kein "Ablehnen" |
| **"Speichern" als Button-Text fragwürdig** | **MEDIUM-Finding** | Speichert was? Mehrdeutig fuer Nutzer |
| Cookie-Richtlinie aus Banner verlinkt | **NEIN** | separate Seite fehlt |
| Re-Access (Floating-Icon o.ae.) | (zu pruefen) | CookieYes default hat Floating-Icon |
**Sprachlich-Fragwürdig:** Der primäre Action-Button heißt "Speichern" — semantisch unklar (speichert "essenziell"? speichert "alle"?). DSK-OH 2024 fordert eindeutige Beschriftung der Consent-Optionen.
---
## Cookie-Richtlinie (Sonderfall)
**Status:** **NICHT VORHANDEN** als separates Dokument.
→ HIGH-Finding: "Cookie-Richtlinie nicht auffindbar".
→ Cookie-Auflistung muss laut DSK-OH Telemedien 2024 pro Cookie enthalten: Name, Anbieter, Zweck, Speicherdauer, Drittlandtransfer.
---
## Datenschutzerklärung
**Widerruf:** In DSE benannt (Standard-Text "Widerruf jederzeit per E-Mail an…").
**DSB:** In DSE als E-Mail-Adresse benannt (kein separater Name/Bestellung).
| Check | Erwartet | Anmerkung |
|-------|----------|-----------|
| Verantwortlicher | OK | — |
| DSB | OK (E-Mail) | Name optional, E-Mail ausreichend nach Art. 13(1)(b) |
| Zwecke | (zu pruefen) | — |
| Rechtsgrundlage | (zu pruefen) | — |
| Empfaengerkategorien | **zu pruefen** | wer ist als Empfaenger genannt? Vergleich mit Cookie-Banner-Vendor-Liste |
| Speicherdauer | (zu pruefen) | — |
| Betroffenenrechte | (zu pruefen) | Art. 15-21 vollstaendig? |
---
## Social Media Verlinkung (zu pruefen)
| Plattform | Verlinkt? | DSGVO-konform (Shariff/2-Klick)? |
|-----------|-----------|-----------------------------------|
| LinkedIn | (zu pruefen) | — |
| Facebook | (zu pruefen) | — |
| Instagram | (zu pruefen) | — |
| X (Twitter) | (zu pruefen) | — |
| YouTube | (zu pruefen) | — |
**Pruefungspflicht:** SoMe-Buttons müssen DSGVO-konform eingebunden sein. Direkte iframes/Pixel zu Facebook etc. setzen vor Consent Tracking → Verstoss §25 TDDDG.
Lösungen: Shariff/2-Klick/Self-hosted-Icons.
---
## Konsistenz-Check (NEUE Pruefung — P33)
**3-Spalten-Vergleich:**
| Verarbeiter | in DSE | in Cookie-Richtlinie | im Cookie-Banner |
|-------------|--------|---------------------|------------------|
| TeleData GmbH | (zu pruefen) | n/a (Cookie-Richtlinie fehlt) | (zu pruefen) |
| CookieYes | (zu pruefen) | n/a | Ja (CMP-Anbieter) |
| ... | ... | ... | ... |
**Erwartung:** Inkonsistenzen wahrscheinlich, da Cookie-Richtlinie fehlt und DSE+Banner getrennt gepflegt werden.
---
## Score-Erwartung
| Bereich | Erwartet | Kommentar |
|---------|----------|-----------|
| DSE | ~80% | Standardpflichten OK, Drittland-Empfänger ggf. ungenau |
| Impressum | ~60% | Handelsregister + USt-IdNr. fehlen |
| Cookie-Richtlinie | 0% | nicht vorhanden |
| Banner-Quality | ~80% | implicit Reject OK, aber "Speichern"-Label problematisch + Cookie-Richtlinie nicht verlinkt |
| **Gesamt** | **~70-75%** | mittelmäßig, Mittelstand-Standard |
---
## Anlässe für neue Checks
1. **P33: 3-Spalten-Konsistenz-Check** (DSE vs Cookie-Richtlinie vs Banner-Vendors)
2. **P28b-Erweiterung: "Speichern" als problematisches Reject-Label** flaggen (mehrdeutig)
3. **P36: Social-Media-Einbindungs-Check** (Shariff/2-Klick/direkt?)
---
## Offene Fragen an User
- USt-IdNr. — hat Conrady Gruppe als juristische Person eine? (vermutlich ja als Gruppe mit Auslandsumsatz)
- Cookie-Richtlinie tatsächlich gar nicht vorhanden, oder nur schwer zu finden (z.B. tief im Datenschutz-Dokument)?
@@ -1,489 +0,0 @@
{
"site": "BMW AG",
"doc_type": "impressum",
"note": "GT=Haiku-Verdikt; v3=unsere deterministische Engine (Layer-0 Regex-Boost)",
"created": "2026-06-17T18:55:16.265861+00:00",
"haiku_pass": 24,
"v3_pass": 14,
"gate_dropped": 39,
"agreement_evaluated_pct": 92,
"controls": [
{
"control_id": "SEC-9172-A08",
"regulation": "DDG",
"article": "§ 33 Absatz mit Verweis auf Artikel 32 Absatz 2",
"title": "Aktualisierte Informationen zu Online-Schnittstellen unverzüglich zugänglich machen",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "TRD-658-A01",
"regulation": "DDG",
"article": "§ 33 Absatz 3",
"title": "Unternehmeridentität auf Plattform erkennbar machen",
"haiku_erfuellt": true,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9174-A03",
"regulation": "DDG",
"article": "§ 5 Absatz 1, Nr. 2 (b, c)",
"title": "Gesetzliche Berufsbezeichnung offenlegen",
"haiku_erfuellt": true,
"v3_passed": true,
"v3_status": "evaluated"
},
{
"control_id": "GOV-3881-A02",
"regulation": "MStV",
"article": "§ 18 Absatz 1",
"title": "Anschrift des Anbieters leicht erkennbar verfügbarmachen",
"haiku_erfuellt": true,
"v3_passed": true,
"v3_status": "evaluated"
},
{
"control_id": "SEC-9175-A04",
"regulation": "DDG",
"article": "§ 6 Absatz 1 Nr. 1-2",
"title": "Kommerzielle Kommunikationen deutlich kennzeichnen",
"haiku_erfuellt": true,
"v3_passed": true,
"v3_status": "evaluated"
},
{
"control_id": "AUTH-4120-A02",
"regulation": "DDG",
"article": "§ 33 Digitale-Dienste-Gesetz Bezug zu Artikel 11 Absatz 4",
"title": "Nutzerinformationen regelmäßig überprüfen",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9158-A09",
"regulation": "MStV",
"article": "§ 18 Absatz 2",
"title": "Zuständigkeitsbereiche mehrerer Verantwortlicher dokumentieren",
"haiku_erfuellt": true,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9158-A10",
"regulation": "MStV",
"article": "§ 18 Absatz 2",
"title": "Identität und Aufenthalt der Verantwortlichen überprüfen",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9174-A02",
"regulation": "DDG",
"article": "§ 5 Absatz 1, Nr. 2 (b, c)",
"title": "Informationen zu kommerziellen Angeboten leicht zugänglich bereitstellen",
"haiku_erfuellt": true,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9174-A04",
"regulation": "DDG",
"article": "§ 5 Absatz 1, Nr. 2 (b, c)",
"title": "Staat oder Region der Berufsbezeichnungs-Verleihung angeben",
"haiku_erfuellt": true,
"v3_passed": true,
"v3_status": "evaluated"
},
{
"control_id": "SEC-9174-A05",
"regulation": "DDG",
"article": "§ 5 Absatz 1, Nr. 2 (b, c)",
"title": "Bezeichnung geltender berufsrechtlicher Regelungen bereitstellen",
"haiku_erfuellt": true,
"v3_passed": true,
"v3_status": "evaluated"
},
{
"control_id": "SEC-9170-A04",
"regulation": "DDG",
"article": "§ 33 Absatz 1",
"title": "Kommerzieller Charakter in Nachrichten erkennbar machen",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9175-A01",
"regulation": "DDG",
"article": "§ 6 Absatz 1 Nr. 1-2",
"title": "Auftraggeber kommerzieller Kommunikation eindeutig identifizierbar machen",
"haiku_erfuellt": true,
"v3_passed": true,
"v3_status": "evaluated"
},
{
"control_id": "GOV-3881-A01",
"regulation": "MStV",
"article": "§ 18 Absatz 1",
"title": "Aktualität und Korrektheit von Anbieter-Kontaktdaten verifizieren",
"haiku_erfuellt": true,
"v3_passed": true,
"v3_status": "evaluated"
},
{
"control_id": "COMP-4123-A01",
"regulation": "MStV",
"article": "§ 18 Absatz 2",
"title": "Verantwortlichen für journalistisch-redaktionelle Angebote benennen",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "COMP-4123-A02",
"regulation": "MStV",
"article": "§ 18 Absatz 2",
"title": "Vollständigen Namen des Verantwortlichen aufführen",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9173-A03",
"regulation": "DDG",
"article": "§ 33 Digitale-Dienste-Gesetz Bezug zu Artikel 12 Absatz 6, Artikel 13 Absatz 4, Artikel 14 Absatz 3",
"title": "Angaben gemäß Artikel 13 Abs. 4 aktuell halten",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "GOV-3881-A07",
"regulation": "MStV",
"article": "§ 18 Absatz 1",
"title": "Impressum oder Kontaktseite auf Webseite oder App lokalisieren",
"haiku_erfuellt": true,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "COMP-4123-A04",
"regulation": "MStV",
"article": "§ 18 Absatz 2",
"title": "Verantwortliche zusätzlich zu DGA-Angaben benennen",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9174-A06",
"regulation": "DDG",
"article": "§ 5 Absatz 1, Nr. 2 (b, c)",
"title": "Kommerzielle Angebote eindeutig als solche kennzeichnen",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "GOV-3887-A03",
"regulation": "DDG",
"article": "§ 20 Absatz 1",
"title": "Fortbestand der Ansprechpartnerfunktion bei Fremdbearbeitung mitteilen",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9170-A01",
"regulation": "DDG",
"article": "§ 33 Absatz 1",
"title": "Absender kommerzieller Nachrichten eindeutig und unverschleiert offenlegen",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "LOG-2095-A03",
"regulation": "DDG",
"article": "§ 9 Abs. 1",
"title": "Identifikationskriterien nach § 2 DDG in Anbieterlisten dokumentieren",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9170-A05",
"regulation": "DDG",
"article": "§ 33 Absatz 1",
"title": "Versteckte Kommunikation von Absender oder kommerziellem Zweck verhindern",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9170-A08",
"regulation": "DDG",
"article": "§ 33 Absatz 1",
"title": "Erkennbarkeit des kommerziellen Charakters auf den ersten Blick prüfen",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "COMP-4123-A03",
"regulation": "MStV",
"article": "§ 18 Absatz 2",
"title": "Anschrift des Verantwortlichen angeben",
"haiku_erfuellt": true,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9175-A02",
"regulation": "DDG",
"article": "§ 6 Absatz 1 Nr. 1-2",
"title": "Kennzeichnung kommerzieller Kommunikation gut erkennbar anbringen",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9175-A03",
"regulation": "DDG",
"article": "§ 6 Absatz 1 Nr. 1-2",
"title": "Kennzeichnungsanforderungen auf alle kommerziellen Kommunikationen anwenden",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "GOV-3881-A03",
"regulation": "MStV",
"article": "§ 18 Absatz 1",
"title": "Name und Anschrift des Vertretungsberechtigten verfügbarmachen",
"haiku_erfuellt": true,
"v3_passed": true,
"v3_status": "evaluated"
},
{
"control_id": "GOV-3881-A04",
"regulation": "MStV",
"article": "§ 18 Absatz 1",
"title": "Anbieter-Kontaktdaten an prominenter Stelle positionieren",
"haiku_erfuellt": true,
"v3_passed": true,
"v3_status": "evaluated"
},
{
"control_id": "GOV-3881-A05",
"regulation": "MStV",
"article": "§ 18 Absatz 1",
"title": "Anbieter-Kontaktdaten auf allen relevanten Plattformen und Kanälen verfügbar machen",
"haiku_erfuellt": false,
"v3_passed": true,
"v3_status": "evaluated"
},
{
"control_id": "GOV-3881-A06",
"regulation": "MStV",
"article": "§ 18 Absatz 1",
"title": "Name des Anbieters leicht erkennbar und ständig verfügbar machen",
"haiku_erfuellt": true,
"v3_passed": true,
"v3_status": "evaluated"
},
{
"control_id": "GOV-3881-A08",
"regulation": "MStV",
"article": "§ 18 Absatz 1",
"title": "Deutliche Erkennbarkeit von Name und Anschrift des Anbieters verifizieren",
"haiku_erfuellt": true,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "GOV-3881-A09",
"regulation": "MStV",
"article": "§ 18 Absatz 1",
"title": "Name und Anschrift des Vertretungsberechtigten bei juristischen Personen überprüfen",
"haiku_erfuellt": true,
"v3_passed": true,
"v3_status": "evaluated"
},
{
"control_id": "GOV-3881-A10",
"regulation": "MStV",
"article": "§ 18 Absatz 1",
"title": "Auffindbarkeit der Kontaktdaten in maximal 2 Klicks testen",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9172-A02",
"regulation": "DDG",
"article": "§ 33 Absatz mit Verweis auf Artikel 32 Absatz 2",
"title": "Vorhandensein aller vorgeschriebenen Informationselemente kontrollieren",
"haiku_erfuellt": true,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9172-A03",
"regulation": "DDG",
"article": "§ 33 Absatz mit Verweis auf Artikel 32 Absatz 2",
"title": "Aktualität der Schnittstelleninformationen durch Vergleich mit technischen Dokumentationen überprüfen",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9172-A04",
"regulation": "DDG",
"article": "§ 33 Absatz mit Verweis auf Artikel 32 Absatz 2",
"title": "Zugangsbarkeit und Verständlichkeit der Schnittstelleninformationen prüfen",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9172-A05",
"regulation": "DDG",
"article": "§ 33 Absatz mit Verweis auf Artikel 32 Absatz 2",
"title": "Zeitliche Verzögerung zwischen Änderungen und Informationsaktualisierung kontrollieren",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "COMP-4123-A05",
"regulation": "MStV",
"article": "§ 18 Absatz 2",
"title": "Verantwortlicher im Impressum oder auf Kontaktseite benennen",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "COMP-4123-A06",
"regulation": "MStV",
"article": "§ 18 Absatz 2",
"title": "Name und Anschrift des benannten Verantwortlichen verifizieren",
"haiku_erfuellt": true,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "COMP-4123-A07",
"regulation": "MStV",
"article": "§ 18 Absatz 2",
"title": "Zusätzliche Angaben neben DGG-Informationen des Verantwortlichen überprüfen",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "COMP-4123-A08",
"regulation": "MStV",
"article": "§ 18 Absatz 2",
"title": "Auffindbarkeit und Aktualität der Verantwortlichen-Informationen verifizieren",
"haiku_erfuellt": true,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9174-A07",
"regulation": "DDG",
"article": "§ 5 Absatz 1, Nr. 2 (b, c)",
"title": "Zugangsweg zu berufsrechtlichen Regelungen angeben",
"haiku_erfuellt": true,
"v3_passed": true,
"v3_status": "evaluated"
},
{
"control_id": "SEC-9174-A08",
"regulation": "DDG",
"article": "§ 5 Absatz 1, Nr. 2 (b, c)",
"title": "Informationen leicht erkennbar gestalten",
"haiku_erfuellt": true,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9174-A09",
"regulation": "DDG",
"article": "§ 5 Absatz 1, Nr. 2 (b, c)",
"title": "Informationen unmittelbar erreichbar bereitstellen",
"haiku_erfuellt": true,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9174-A10",
"regulation": "DDG",
"article": "§ 5 Absatz 1, Nr. 2 (b, c)",
"title": "Informationen ständig verfügbar halten",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "AUTH-4120-A03",
"regulation": "DDG",
"article": "§ 33 Digitale-Dienste-Gesetz Bezug zu Artikel 11 Absatz 4",
"title": "Überprüfungen von Nutzerinformationen dokumentieren",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "AUTH-4120-A04",
"regulation": "DDG",
"article": "§ 33 Digitale-Dienste-Gesetz Bezug zu Artikel 11 Absatz 4",
"title": "Veraltete oder fehlerhafte Nutzerinformationen zeitnah aktualisieren",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "AUTH-4120-A05",
"regulation": "DDG",
"article": "§ 33 Digitale-Dienste-Gesetz Bezug zu Artikel 11 Absatz 4",
"title": "Aktualität von Nutzerinformationen nachweisbar gewährleisten",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "COMP-4124-A04",
"regulation": "DDG",
"article": "§ 25 Abs. 1",
"title": "Informationen vollständig, wahrheitsgemäß und verständlich bereitstellen",
"haiku_erfuellt": true,
"v3_passed": true,
"v3_status": "evaluated"
},
{
"control_id": "SEC-9172-A06",
"regulation": "DDG",
"article": "§ 33 Absatz mit Verweis auf Artikel 32 Absatz 2",
"title": "Informationen zu Online-Schnittstellen-Konzeption vollständig dokumentieren",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
},
{
"control_id": "SEC-9172-A07",
"regulation": "DDG",
"article": "§ 33 Absatz mit Verweis auf Artikel 32 Absatz 2",
"title": "Informationen zu Online-Schnittstellen in vorgeschriebener Weise präsentieren",
"haiku_erfuellt": false,
"v3_passed": null,
"v3_status": "gate_dropped"
}
]
}