Datenschutz (Entwurf): Übermittlung an UptimeRobot, Bestellungen im Portal, Formulare, Tests

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Fable 5.1 committed 2026-09-27 20:37:06 +00:00
1 parent a2c1f0d81c
commit 6f7daf757f
3 files changed
+52 -18

No files matched your search

+47 -15
View File
@@ -203,30 +203,62 @@ test('Alle internen Links und Querverweise treffen', () => {
// --- Datenschutzerklärung (Plan 2, Task 2) ---
test('Datenschutz: Abos, UptimeRobot, Stand wie termsVersion', () => {
const ds = strip(read('public/datenschutz.html'))
const DS = 'public/datenschutz.html'
// Ein Satz ab seinem Anfang bis zum nächsten Satzende (in den geprüften Sätzen kommt kein "Art. 6" o. ä. vor)
const sentence = (s, start) => between(s, start, '. ') + '.'
test('Datenschutz: Abos, produktneutral, Stand wie termsVersion', () => {
const ds = strip(read(DS))
for (const s of ['Abos und Zahlung über Stripe', 'UptimeRobot s. r. o.', 'Obchodná 507/2', '811 06 Bratislava',
'Standardvertragsklauseln', 'im Rahmen unserer Abos']) assert.ok(ds.includes(s), s)
// Produktneutral: keine Formulierung mehr, die nur das Wartungs-Abo meint, wo beide Abos gemeint sind
// Produktneutral; keine Zusage einer Ereignisansicht (Plan 2 baut keine); UptimeRobot ist kein Unterauftragsverarbeiter
for (const s of ['insbesondere das Wartungs-Abo', 'Schließen Sie das Wartungs-Abo', 'im Rahmen des Wartungs-Abos',
'für das Wartungs-Abo über Stripe']) assert.ok(!ds.includes(s), `noch da: ${s}`)
// Abschnitt 3 und 12: Überwachung der Erreichbarkeit durch UptimeRobot, Drittland auf Grundlage von SCC
const hosting = between(ds, '3. Hosting', '4. Cookies')
for (const s of ['UptimeRobot s. r. o., Obchodná 507/2, 811 06 Bratislava (Slowakei)', 'Art. 46 Abs. 2 lit. c DSGVO',
'Auftragsverarbeitung', 'Nutzungsbedingungen']) assert.ok(hosting.includes(s), `Abschnitt 3: ${s}`)
assert.ok(between(ds, '12. Empfänger im Überblick', '13. Ihre Rechte').includes('UptimeRobot'))
// Abschnitt 7: Nachweisdaten auch bei Wechsel und Zusatzspeicher, Aufbewahrung wie bisher
const abos = between(ds, '7. Abos und Zahlung über Stripe', '8. E-Mail')
for (const s of ['Wechsel', 'Zusatzspeicher', 'Kündigung', 'Widerruf', 'Version der Vertragsbedingungen',
'drei Jahre nach Vertragsende']) assert.ok(abos.includes(s), `Abschnitt 7: ${s}`)
// Stand der Erklärung = Datum aus termsVersion (JJJJ-MM-TT-v4); das Freigabedatum kommt erst beim Livegang (Task 20)
const [, y, mo, d] = /^(\d{4})-(\d{2})-(\d{2})-v4$/.exec(config.abo.termsVersion)
'für das Wartungs-Abo über Stripe', 'Sie sehen diese Ereignisse', 'Unterauftragsverarbeiter']) assert.ok(!ds.includes(s), `noch da: ${s}`)
// Stand = Datum aus termsVersion (JJJJ-MM-TT-v4). Die Kopplung gilt bis zum Livegang: Task 20 trägt in beiden das
// Freigabedatum ein. Danach darf sie gelockert werden, sobald die Erklärung unabhängig von den Bedingungen geändert wird.
const m = /^(\d{4})-(\d{2})-(\d{2})-v4$/.exec(config.abo.termsVersion)
assert.ok(m, `termsVersion nicht im Format JJJJ-MM-TT-v4: ${config.abo.termsVersion}`)
const [, y, mo, d] = m
const stand = /Stand (\d{2}\.\d{2}\.\d{4})/.exec(ds)
assert.ok(stand, 'Stand fehlt')
assert.equal(stand[1], `${d}.${mo}.${y}`)
assert.ok(read('scripts/build-legal-pdfs.sh').includes('pdf public/datenschutz.html docs/WEBklar-Datenschutzerklaerung.pdf'))
})
test('Datenschutz Abschnitt 3 und 12: UptimeRobot, Drittland USA, SCC im AVV mit Kopie', () => {
const ds = strip(read(DS))
// Nur die UptimeRobot-Absätze (nach dem Hetzner-Absatz), damit "Auftragsverarbeitung" wirklich UptimeRobot meint
const robot = between(ds, 'Ob unsere Websites', '4. Cookies')
for (const s of ['UptimeRobot s. r. o., Obchodná 507/2, 811 06 Bratislava (Slowakei)', 'Adressen (URLs)', 'Daten der Besucher',
'Auftragsverarbeitung', 'außerhalb der EU', 'insbesondere in den USA', 'Standardvertragsklauseln', 'Art. 46 Abs. 2 lit. c DSGVO',
'uptimerobot.com/dpa', 'Kopie', 'lit. b', 'lit. f', 'entfernen wir']) assert.ok(robot.includes(s), `UptimeRobot: ${s}`)
const empfaenger = between(ds, '12. Empfänger im Überblick', '13. Ihre Rechte')
assert.ok(empfaenger.includes('UptimeRobot s. r. o.'))
assert.ok(empfaenger.includes('(insbesondere USA)'))
})
test('Datenschutz Abschnitt 7: Nachweisdaten je Bestellung, Vertragsereignisse, Kündigungs- und Widerrufsseite', () => {
const abos = between(strip(read(DS)), '7. Abos und Zahlung über Stripe', '8. E-Mail')
// Nachweisdaten (mit IP und Browser) für Abschluss, Wechsel und Zusatzspeicher-Bestellung, im Portal und bei Stripe
const nachweis = between(abos, 'Um Ihre Bestellungen nachweisen', 'Außerdem')
for (const s of ['Version der Vertragsbedingungen', 'gegebenenfalls Ihre Angaben zum Leistungsbeginn', 'IP-Adresse', 'Browserkennung',
'bei Stripe', 'Abschluss eines Abos', 'Wechsel', 'Zusatzspeicher']) assert.ok(nachweis.includes(s), `Nachweis: ${s}`)
// Ereignis-Satz nennt Kündigung und Widerruf als Ereignisse (eine "Kündigungsbestätigung" genügt nicht)
const ereignisse = sentence(abos, 'Außerdem halten wir')
for (const re of [/[ :,]Abschluss[ ,.]/, /[ :,]Wechsel[ ,.]/, /[ :,]Zusatzspeicher[ ,.]/, /[ :,]Verringerungen[ ,.]/,
/[ :,]Kündigung[ ,.]/, /[ :,]Widerruf[ ,.]/]) assert.match(ereignisse, re)
// Verringerung, Kündigung, Widerruf: nur Zeitpunkt und Status (Task 8 speichert beim Minus keine IP/Browserkennung)
assert.ok(abos.includes('nur Zeitpunkt und Status, keine IP-Adresse und Browserkennung'))
assert.ok(abos.includes('Den Stand Ihrer Bestellungen, etwa laufende Widerrufsfristen und die Einrichtung von Zusatzspeicher, sehen Sie im Kundenportal unter „Verträge“.'))
assert.ok(abos.includes('Aufgabenliste, um Änderungen am Zusatzspeicher umzusetzen'))
assert.ok(sentence(abos, 'Diese Angaben löschen wir').includes('drei Jahre nach Vertragsende'))
// Öffentliche Kündigungs- und Widerrufsseite (§§ 312k, 356a BGB): Daten, Zweck, Rechtsgrundlage, IP nur zur Begrenzung
const formulare = between(abos, 'kuendigen.html', 'Abschnitt 9')
for (const s of ['widerrufen.html', 'ohne Anmeldung', 'Namen', 'E-Mail-Adresse', 'Kundennummer', 'Eingang', 'Bestätigung', 'Team',
'Art. 6 Abs. 1 lit. c DSGVO', '§§ 312k, 356a BGB', 'lit. b', 'IP-Adresse', 'Arbeitsspeicher', 'zehn',
'drei Jahre nach Vertragsende']) assert.ok(formulare.includes(s), `Formulare: ${s}`)
})
// --- Übernahmegutschrift, Prüftexte, Leitfaden (Plan 2, Task 3) ---
test('Übernahmegutschrift und Leitfaden: produktneutral', () => {