feat: Werkzeugkatalog nennt tatsächliche Verarbeitungsländer statt EU/USA/gemischt-Eimer, plus DPF-Feld
Die USA sind DSGVO-rechtlich bereits ein Drittland wie jedes andere - der alte verarbeitungsort-Wertebereich (EU/USA/gemischt/on-prem) verschleierte das. Ersetzt durch verarbeitungslaender TEXT[] mit echter Weltländerliste im Formular (Mehrfachauswahl, kein JS nötig). Der harte Filter eu_verarbeitung verlangt jetzt, dass ALLE genannten Länder EU/EWR sind. Neues Feld dpf_zertifiziert macht die EU-US Data Privacy Framework-Zertifizierung strukturiert statt nur Fließtext. Öffnet nebenbei den Weg für Katalogeinträge außerhalb EU/USA (z. B. DeepSeek), die vorher am alten Wertebereich scheiterten. Zusätzlich Typografie-Nachbesserung nach Nutzer-Feedback: Formular- Abschnittsüberschriften (<legend>) saßen zu dicht am Kartenrand, weil <legend> das Padding des umschließenden <fieldset> ignoriert - jetzt mit eigenem Padding und größerer Schrift, h2/h3 einheitlich gesetzt.
This commit is contained in:
@@ -186,11 +186,47 @@ func containsString(list []string, v string) bool {
|
||||
// statt store.Werkzeug direkt zu verwenden: internal/rules bleibt so
|
||||
// unabhängig von internal/store und für sich allein testbar.
|
||||
type WerkzeugEigenschaften struct {
|
||||
AVVVerfuegbar bool
|
||||
Verarbeitungsort string
|
||||
TrainingOptOut bool
|
||||
TrainingStandard bool
|
||||
AufbewahrungTage int
|
||||
AVVVerfuegbar bool
|
||||
// Verarbeitungslaender nennt die tatsächlichen Länder statt eines
|
||||
// groben "EU"/"USA"-Eimers (siehe CLAUDE.md, Werkzeugkatalog) — die
|
||||
// eu_verarbeitung-Anforderung gilt nur als erfüllt, wenn ALLE
|
||||
// genannten Länder EU/EWR-Mitgliedstaaten sind.
|
||||
Verarbeitungslaender []string
|
||||
TrainingOptOut bool
|
||||
TrainingStandard bool
|
||||
AufbewahrungTage int
|
||||
}
|
||||
|
||||
// euEwrLaender sind die Staaten, für die eine Verarbeitung nicht als
|
||||
// Drittlandtransfer gilt (Art. 44 ff. DSGVO) — die 27 EU-Mitgliedstaaten
|
||||
// plus die drei über den EWR-Vertrag gleichgestellten Staaten. Die USA
|
||||
// gehören bewusst NICHT dazu — sie sind ein Drittland wie jedes andere,
|
||||
// unabhängig vom EU-US Data Privacy Framework (das mildert die
|
||||
// Transfer-Grundlage, macht die USA aber nicht zum EU/EWR-Gebiet).
|
||||
var euEwrLaender = map[string]bool{
|
||||
"Belgien": true, "Bulgarien": true, "Dänemark": true, "Deutschland": true,
|
||||
"Estland": true, "Finnland": true, "Frankreich": true, "Griechenland": true,
|
||||
"Irland": true, "Italien": true, "Kroatien": true, "Lettland": true,
|
||||
"Litauen": true, "Luxemburg": true, "Malta": true, "Niederlande": true,
|
||||
"Österreich": true, "Polen": true, "Portugal": true, "Rumänien": true,
|
||||
"Schweden": true, "Slowakei": true, "Slowenien": true, "Spanien": true,
|
||||
"Tschechien": true, "Ungarn": true, "Zypern": true,
|
||||
"Island": true, "Liechtenstein": true, "Norwegen": true,
|
||||
}
|
||||
|
||||
// alleLaenderInEUEWR prüft, ob jedes genannte Land EU/EWR ist. Eine
|
||||
// leere Liste (kein Land benannt) gilt als NICHT erfüllt — "wissen wir
|
||||
// nicht" darf nie stillschweigend als "ist okay" durchgehen.
|
||||
func alleLaenderInEUEWR(laender []string) bool {
|
||||
if len(laender) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, l := range laender {
|
||||
if !euEwrLaender[l] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ErfuelltAnforderung prüft, ob ein Werkzeug eine einzelne Anforderung
|
||||
@@ -206,7 +242,7 @@ func ErfuelltAnforderung(anforderungID string, w WerkzeugEigenschaften) bool {
|
||||
case "avv_erforderlich":
|
||||
return w.AVVVerfuegbar
|
||||
case "eu_verarbeitung":
|
||||
return w.Verarbeitungsort == "EU"
|
||||
return alleLaenderInEUEWR(w.Verarbeitungslaender)
|
||||
case "kein_training_auf_eingabe":
|
||||
return w.TrainingStandard
|
||||
default:
|
||||
|
||||
@@ -158,6 +158,21 @@ func TestErfuelltAnforderungAVV(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestErfuelltAnforderungEUVerarbeitung(t *testing.T) {
|
||||
if !rules.ErfuelltAnforderung("eu_verarbeitung", rules.WerkzeugEigenschaften{Verarbeitungslaender: []string{"Irland"}}) {
|
||||
t.Error("erwartet: erfuellt bei einem einzelnen EU/EWR-Land")
|
||||
}
|
||||
if rules.ErfuelltAnforderung("eu_verarbeitung", rules.WerkzeugEigenschaften{Verarbeitungslaender: []string{"USA"}}) {
|
||||
t.Error("erwartet: nicht erfuellt bei USA - die USA sind ein Drittland wie jedes andere")
|
||||
}
|
||||
if rules.ErfuelltAnforderung("eu_verarbeitung", rules.WerkzeugEigenschaften{Verarbeitungslaender: []string{"Irland", "USA"}}) {
|
||||
t.Error("erwartet: nicht erfuellt, sobald auch nur ein Land nicht EU/EWR ist")
|
||||
}
|
||||
if rules.ErfuelltAnforderung("eu_verarbeitung", rules.WerkzeugEigenschaften{}) {
|
||||
t.Error("erwartet: nicht erfuellt ohne benanntes Land - 'wissen wir nicht' darf nicht als 'ist okay' durchgehen")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErfuelltAnforderungUnbekannteAnforderungIstUnkritisch(t *testing.T) {
|
||||
if !rules.ErfuelltAnforderung("menschliche_aufsicht", rules.WerkzeugEigenschaften{}) {
|
||||
t.Error("Prozess-Anforderungen duerfen ein Werkzeug nicht hart aussortieren")
|
||||
@@ -166,8 +181,8 @@ func TestErfuelltAnforderungUnbekannteAnforderungIstUnkritisch(t *testing.T) {
|
||||
|
||||
func TestFilterWerkzeugeSortsOutMissingAVV(t *testing.T) {
|
||||
kandidaten := []rules.WerkzeugKandidat{
|
||||
{ID: "mit-avv", Eigenschaften: rules.WerkzeugEigenschaften{AVVVerfuegbar: true, Verarbeitungsort: "EU", TrainingStandard: true}},
|
||||
{ID: "ohne-avv", Eigenschaften: rules.WerkzeugEigenschaften{AVVVerfuegbar: false, Verarbeitungsort: "EU", TrainingStandard: true}},
|
||||
{ID: "mit-avv", Eigenschaften: rules.WerkzeugEigenschaften{AVVVerfuegbar: true, Verarbeitungslaender: []string{"Deutschland"}, TrainingStandard: true}},
|
||||
{ID: "ohne-avv", Eigenschaften: rules.WerkzeugEigenschaften{AVVVerfuegbar: false, Verarbeitungslaender: []string{"Deutschland"}, TrainingStandard: true}},
|
||||
}
|
||||
zulaessig, ausgeschlossen := rules.FilterWerkzeuge(kandidaten, []string{"avv_erforderlich"})
|
||||
if len(zulaessig) != 1 || zulaessig[0] != "mit-avv" {
|
||||
|
||||
Reference in New Issue
Block a user