feat!: Produktwechsel zu KI-Antragsprüfung — Phase 1 (Datenmodell, Regelwerk, Katalog)

Deklarix war eine Pre-Publish-Kennzeichnungsprüfung für Werbe-Content
(UWG/MStV). Dieser Scope wird komplett verworfen und durch eine
KI-Antragsprüfung ersetzt: Mitarbeitende beschreiben ein KI-Vorhaben,
das System leitet Datenklasse und KI-VO-Einstufung ab, gleicht sie
gegen einen Werkzeugkatalog ab und erzeugt einen Entscheidungsvorschlag
mit Herleitung — ein Mensch entscheidet, das System bereitet nur vor.

BREAKING CHANGE: Migration 0008 droppt alle werberechtsspezifischen
Tabellen (submission, finding, extraction, evidence_package,
participant, platform_connection, asset). account/app_user/session/
audit_log bleiben (Mandantentrennung, Login, Protokollierung sind
produktunabhängig) — app_user.role wechselt von
creator/agentur/marke/kanzlei/admin zu den fünf neuen Rollen
mitarbeiter/verantwortlicher/pruefer/admin/betreiber (vier
Mandanten-Rollen + eine plattformweite, siehe CLAUDE.md).

Entfernt: internal/extract, internal/dossier, internal/evidence,
internal/socialconnect, alte rules/*.yaml (UWG-Regeln), testdata/golden
— alles ausschließlich für das alte Produkt.

Neu, Phase 1 der Baureihenfolge ("Datenmodell, Regelwerk als YAML,
Katalogstruktur"):
- Store: abteilung (Stammdaten), werkzeug + werkzeug_sperre (der
  eigentliche Wert des Produkts — zentral gepflegter Katalog mit
  mandantenspezifischen Ergänzungen/Sperrungen, Pflichtfelder
  letzte_pruefung/quelle für jede Zusicherung), antrag (Fragebogen-
  Grundgerüst, Antworten als JSONB für den adaptiven Fragebogen aus
  Phase 2).
- internal/rules komplett neu: lädt und validiert drei YAML-
  Regelwerke (Datenklasse-Ableitung, KI-VO-Einstufung, Anforderungs-
  profil) aus rules/*.yaml — noch ohne Auswertungslogik gegen echte
  Fragebogen-Antworten (das ist Phase 3, bewusst erst nach dem
  Fragebogen aus Phase 2, der die exakten Fakten-Feldnamen festlegt).
  Offene fachliche Annahmen (Rangfolge der Datenklassen, Fragebogen-
  Lücke für die "verboten"-Varianten) explizit in rules/OPEN.md
  dokumentiert statt geraten.
- Web-Layer auf Minimalgerüst reduziert, das kompiliert und die neue
  Rollenwelt trägt: Firma-Registrierung (Ebene 1, erster Nutzer wird
  admin), Login/Logout, Plattform-Bereich (Ebene 5, nur betreiber:
  Dashboard, Accounts-Übersicht, Audit-Log) — Fragebogen (Ebene 2) und
  Fachebene (Ebene 3) folgen in den nächsten Phasen.
- CLAUDE.md komplett neu geschrieben: Produktbeschreibung, Fünf-Ebenen-
  Rollenmodell, Fragebogen-Spezifikation, Ableitungstabellen,
  Werkzeugkatalog, Bewertungslogik (geplant), Onboarding, offene
  Punkte (u. a. Postgres-RLS-Frage aus der Frontend-Spezifikation
  noch nicht entschieden, "Admin und Verantwortlicher gleichzeitig"
  beim Onboarding noch nicht datenmodelliert).

Volle Testsuite inkl. echter Postgres-Tests grün. End-to-End gegen
einen laufenden Server verifiziert: Firma-Registrierung legt Account +
admin-Nutzer an, Betreiber-Login leitet zu /betreiber, mandanten-
übergreifende Accounts-Liste sichtbar für betreiber, 404 für
mitarbeiter auf /betreiber, 303 zu /login ohne Sitzung.
This commit is contained in:
noroot
2026-08-28 21:39:04 +02:00
parent 6fd7831784
commit b4d4ee8d3c
96 changed files with 2348 additions and 7612 deletions

View File

@@ -1,62 +1,64 @@
# Offene Rechtsfragen
# Offene fachliche Fragen zum Regelwerk
Fragen, bei denen sich eine Regel nicht auf eine handgeprüfte,
eindeutig passende Fundstelle stützen lässt, ohne zu raten. Werden hier
notiert statt in einer Regel geraten beantwortet zu werden (siehe
CLAUDE.md, Arbeitsweise für Claude Code).
Diese Punkte wurden beim Anlegen der Regelwerk-YAML-Dateien (Phase 1)
bewusst nicht geraten, sondern hier notiert — vor Phase 3 (Ableitungen
und harte Filter) mit dem fachlich Verantwortlichen (z. B. der/dem
betrieblichen Datenschutzbeauftragten) klären.
## WK-004 — Fundstelle für "Kennzeichnung muss vor Kürzung sichtbar sein"
## 1. Rangfolge der Datenklassen
**Stand 2026-08-27, zweite Recherche:** Es gibt jetzt eine einschlägige
Entscheidung: **LG Köln, Urteil v. 12.05.2026** — Werbekennzeichnung muss
bereits im Vorschaubild/Grid erkennbar sein, wenn der kommerzielle Zweck
dort nicht auf den ersten Blick ersichtlich ist; eine erst in der
Caption oder erst im geöffneten Beitrag sichtbare Kennzeichnung kommt zu
spät. Das deckt sich direkt mit WK-004 und ist jetzt als Fundstelle in
der Regel hinterlegt. Zusätzlich bestätigt: OLG Celle hat ein bloßes
#ad" als unzureichend zurückgewiesen, das Kammergericht Berlin ebenso
#sponsoredby" — beides stützt die in WK-001/WK-004 empfohlene
Kennzeichnung mit „Werbung"/„Anzeige".
Die Spezifikation sagt "höchste zutreffende Stufe gewinnt", gibt aber
keine expliziten Rangzahlen vor. `rules/datenklasse.yaml` nimmt aktuell
diese Reihenfolge an (niedrigster zu höchstem Rang):
**Weiterhin offen:** Das LG-Köln-Urteil ist laut Quellenlage **noch
nicht rechtskräftig** (Stand der Recherche). Vor Kundeneinsatz prüfen,
ob es zwischenzeitlich in Berufung bestätigt oder aufgehoben wurde, und
ob es Aussagen zur reinen Caption-Kürzung (statt Vorschaubild) trifft —
das Urteil betont primär das Vorschaubild/Grid, WK-004 bewertet aktuell
die Caption-Kürzung. Beides hängt zusammen (wenn schon das Vorschaubild
fehlt, ist die Caption-Kürzung ohnehin nachrangig), sollte aber sauber
auseinandergehalten werden — evtl. braucht es eine eigene Regel für
"keine Kennzeichnung im Vorschaubild/ersten Frame", statt beides in
WK-004 zu vermischen.
1. `oeffentlich`
2. `intern`
3. `auftragsdaten`
4. `personenbezogen`
5. `berufsgeheimnis`
6. `besondere_kategorie`
## Ausnahme "kommerzieller Zweck ohnehin erkennbar" (BGH I ZR 90/20 u. a.)
Begründung der Annahme: DSGVO Art. 9 (besondere Kategorien) gilt
allgemein als striktester Datenschutz-Tatbestand, § 203 StGB
(Berufsgeheimnis) hat eigene strafrechtliche Relevanz — beide vor
"normalen" personenbezogenen Daten eingeordnet. `auftragsdaten` unter
`personenbezogen` einsortiert, weil vertragliche Geheimhaltung in der
Regel schwächer sanktioniert ist als DSGVO-Bußgelder. **Nicht
bestätigt.**
**Stand 2026-08-27, zweite Recherche — deutlich präzisiert:** Der BGH
unterscheidet zwei Fälle:
## 2. Anforderung `kein_training_auf_eingabe` und `auftragsdaten`
1. **Eigenwerbung** (Influencer bewirbt das eigene Unternehmen/die eigene
Marke): Bei kommerziell genutzten Accounts wissen Follower laut BGH
"aus den Umständen", dass es sich um Eigenwerbung handelt — hier kann
die Kennzeichnungspflicht entfallen. Als Kriterium diente u. a. die
Followerzahl (im konkreten Fall bei 600.000 bzw. 1,7 Mio. Followern
bejaht), aber der BGH hat **keine klare Grenze** gezogen. Das ist zu
vage für eine objektive, extrahierbare Bedingung — eine Regel, die
auf "Followerzahl > X" abstellt, würde eine Grenze erfinden, die es
so nicht gibt. Bleibt vorerst nicht automatisiert.
Die Spezifikation formuliert "aus intern, personenbezogen und höher" —
das lässt offen, ob `auftragsdaten` (zwischen `intern` und
`personenbezogen` einsortiert, siehe Punkt 1) eingeschlossen sein soll.
`rules/anforderungen.yaml` schließt `auftragsdaten` aktuell explizit
ein (Kundendaten sollten aus denselben Gründen wie Geschäftsgeheimnisse
nicht zum Training verwendet werden) — **Annahme, nicht bestätigt.**
2. **Fremdwerbung** (Influencer bewirbt Produkte/Marken Dritter): Hier
ist die neue, klar extrahierbare Erkenntnis: **Ein Link auf die
Website des Herstellers/der Marke begründet laut BGH regelmäßig einen
"werblichen Überschuss"** — die Kennzeichnungspflicht lebt dann
unabhängig davon auf, ob der Post sonst wie Eigenwerbung wirkt. Das
ist ein objektives Extraktionsfeld (Link vorhanden ja/nein, Linkziel
Hersteller/Marke ja/nein), kein Werturteil — passt zum Kernprinzip
und ist ein guter Kandidat für eine kommende Regel WK-002
("Verlinkung auf Fremdprodukt ohne Kennzeichnung"), sobald das
Extraktionsschema `verlinkungen`/`affiliate_link` echte Daten liefert.
## 3. Genaue Fragebogen-Fakten für "verboten" (KI-VO Art. 5)
**Ergebnis:** Die "ohnehin erkennbar"-Ausnahme bleibt bewusst
unautomatisiert (Kriterium zu vage, siehe oben) — WK-001/WK-004 lösen in
diesem seltenen Fall weiterhin ein potenzielles False Positive aus. Das
ist der sicherere Fehler in diese Richtung (lieber eine unnötige
Rückfrage an den Nutzer als eine übersehene Kennzeichnungspflicht).
Fragebogen-Abschnitt C stellt nur eine einzelne Frage (C3: "Erkennt
oder bewertet es Emotionen, Verhalten oder biometrische Merkmale?")
ohne Folgefragen, die zwischen den drei in der Bewertungslogik
genannten Auslösern für "verboten" unterscheiden:
- Emotionserkennung am Arbeitsplatz
- Social Scoring
- Biometrische Kategorisierung
`rules/kivo_einstufung.yaml` geht davon aus, dass Phase 2 (Fragebogen)
für C3 eine Folgefrage ergänzt, die zwischen diesen dreien (und "keins
davon") unterscheidet — analog zur bereits spezifizierten Folgefrage
bei C2. Die Feldnamen `c3_art` und dessen Werte
(`emotionserkennung_arbeitsplatz`, `social_scoring`,
`biometrische_kategorisierung`) sind Platzhalter, bis Phase 2 das
festlegt.
## 4. `loeschfrist_max_tage` — konkrete Fristen je Datenklasse
Die Spezifikation nennt `loeschfrist_max_tage` als Anforderung "aus
Datenklasse", ohne die konkreten Tageswerte pro Stufe zu nennen.
`rules/anforderungen.yaml` listet die Anforderung nur als grundsätzlich
anwendbar (welche Datenklassen sie überhaupt auslösen), ohne
Zahlenwerte — die eigentlichen Fristen (z. B. "personenbezogen: 90
Tage") müssen vor Phase 3 fachlich festgelegt werden.

View File

@@ -1,16 +0,0 @@
id: WK-001
version: 1
land: DE
titel: Keine Kennzeichnung trotz Gegenleistung
bedingung:
gegenleistung: [bezahlt, sachbezug]
kennzeichnung_vorhanden: false
schwere: hoch
fundstelle:
- "§ 5a Abs. 4 UWG"
- "§ 22 Abs. 1 MStV"
korrektur: >
Beitrag mit "Werbung" oder "Anzeige" kennzeichnen. Die bloße
plattform-eigene Kennzeichnung (z. B. Instagrams "Bezahlte
Partnerschaft") reicht laut Leitfaden der Medienanstalten nicht als
alleinige Kennzeichnung aus.

View File

@@ -1,17 +0,0 @@
id: WK-004
version: 1
land: DE
titel: Kennzeichnung nicht auf den ersten Blick erkennbar (Kürzung durch "mehr anzeigen")
bedingung:
gegenleistung: [bezahlt, sachbezug]
kennzeichnung_vorhanden: true
kennzeichnung_vor_kuerzung: false
schwere: hoch
fundstelle:
- "§ 5a Abs. 4 UWG"
- "Leitfaden der Medienanstalten: Werbekennzeichnung bei Online-Medien"
- "LG Köln, Urteil v. 12.05.2026 (noch nicht rechtskräftig) — Werbekennzeichnung muss bereits im Vorschaubild/Grid erkennbar sein, eine erst in der Caption versteckte Kennzeichnung kommt zu spät"
korrektur: >
Kennzeichnung ("Werbung" oder "Anzeige") an den Anfang der Caption
setzen, sodass sie sichtbar ist, bevor Instagram/TikTok den Text
hinter "mehr anzeigen" kürzt.

32
rules/anforderungen.yaml Normal file
View File

@@ -0,0 +1,32 @@
# Anforderungsprofil: aus Datenklasse und/oder KI-VO-Einstufung
# abgeleitete Menge von Anforderungen, die ein Werkzeug erfüllen muss.
#
# ACHTUNG: "kein_training_auf_eingabe aus intern, personenbezogen und
# höher" in der Produktspezifikation lässt offen, ob auftragsdaten
# (rang 3, zwischen intern und personenbezogen) eingeschlossen sein
# soll — hier bewusst explizit aufgeführt (siehe rules/OPEN.md), damit
# nichts über eine implizite Rangfolge erraten wird.
version: 1
anforderungen:
- id: avv_erforderlich
aus_datenklassen: [personenbezogen, besondere_kategorie, auftragsdaten]
beschreibung: "Auftragsverarbeitungsvertrag mit dem Werkzeug-Anbieter erforderlich"
- id: eu_verarbeitung
aus_datenklassen: [berufsgeheimnis, besondere_kategorie]
beschreibung: "Verarbeitung muss innerhalb der EU stattfinden"
- id: kein_training_auf_eingabe
aus_datenklassen: [intern, auftragsdaten, personenbezogen, berufsgeheimnis, besondere_kategorie]
beschreibung: "Eingaben dürfen nicht zum Training des Werkzeugs verwendet werden"
- id: loeschfrist_max_tage
aus_datenklassen: [oeffentlich, intern, auftragsdaten, personenbezogen, berufsgeheimnis, besondere_kategorie]
beschreibung: "maximale Aufbewahrungsdauer richtet sich nach der Datenklasse"
- id: menschliche_aufsicht
aus_einstufungen: [hochrisiko]
beschreibung: "ein Mensch muss das Ergebnis vor Wirksamkeit prüfen"
- id: kennzeichnungspflicht
aus_einstufungen: [transparenzpflicht]
beschreibung: "das Ergebnis muss als KI-generiert gekennzeichnet werden"
- id: dsfa_erforderlich
aus_datenklassen: [besondere_kategorie]
aus_einstufungen: [hochrisiko]
beschreibung: "Datenschutz-Folgenabschätzung erforderlich"

35
rules/datenklasse.yaml Normal file
View File

@@ -0,0 +1,35 @@
# Datenklasse-Ableitung aus Fragebogen-Abschnitt B. "Höchste zutreffende
# Stufe gewinnt" — rang entscheidet, welche Stufe gewinnt, wenn mehrere
# Auslöser gleichzeitig zutreffen. "Unsicher" zählt wie "Ja" (siehe
# Fragebogen-Spezifikation) — das wird in der Auswertung (Phase 3)
# umgesetzt, nicht hier.
#
# ACHTUNG: Die Rangfolge unten ist eine Annahme (nicht explizit in der
# Produktspezifikation vorgegeben), siehe rules/OPEN.md — vor Phase 3
# mit dem fachlich Verantwortlichen bestätigen.
version: 1
stufen:
- id: oeffentlich
rang: 1
ausloeser: [b7]
folge: "keine besonderen Anforderungen"
- id: intern
rang: 2
ausloeser: [b6]
folge: "Geschäftsgeheimnis-Schutz"
- id: auftragsdaten
rang: 3
ausloeser: [b5]
folge: "Weitergabe nur wenn Haupt-AVV es zulässt"
- id: personenbezogen
rang: 4
ausloeser: [b1, b4]
folge: "AVV, EU-Verarbeitung, Löschfrist"
- id: berufsgeheimnis
rang: 5
ausloeser: [b3]
folge: "§ 203 StGB — externe Verarbeitung nur mit Verpflichtung"
- id: besondere_kategorie
rang: 6
ausloeser: [b2]
folge: "zusätzlich DSFA prüfen, Art. 9 DSGVO"

View File

@@ -0,0 +1,30 @@
# KI-VO-Einstufung aus Fragebogen-Abschnitt C. Reihenfolge ist
# Prüfreihenfolge (erste zutreffende Stufe gewinnt) — "verboten" muss
# zuerst geprüft werden (K.-o.-Prüfung, siehe Bewertungslogik). Jede
# Variante ist eine UND-Verknüpfung von Fakten; mehrere Varianten pro
# Stufe sind ODER-verknüpft.
#
# ACHTUNG: c3_art (social_scoring / biometrische_kategorisierung /
# emotionserkennung_arbeitsplatz) und c2_folge sind Platzhalter-
# Feldnamen, bis Phase 2 (Fragebogen) die genauen Fakten-Schlüssel
# festlegt — siehe rules/OPEN.md.
version: 1
stufen:
- id: verboten
quelle: "Art. 5 KI-VO"
varianten:
- {c3: true, c3_art: emotionserkennung_arbeitsplatz}
- {c3: true, c3_art: social_scoring}
- {c3: true, c3_art: biometrische_kategorisierung}
- id: hochrisiko
varianten:
- {c2: true, c2_folge: beschaeftigung}
- {c2: true, c2_folge: kreditwuerdigkeit}
- {c2: true, c2_folge: leistungsbewilligung}
- {c2: true, c2_folge: bildung}
- {c2: true, c2_folge: gesundheit}
- id: transparenzpflicht
varianten:
- {c1: true, c5: false}
- id: minimal
varianten: []