TP2 Abschlussprüfung: Rechtstexte (AVV, 6c, News-LB-Archiv, Livegang-Checkliste)

- AVV Vorbemerkung (2): K16 der Textform-Aktivierung trägt nur Leistungsbeschreibung und AVV als PDF
- AVV Nr. 9 Abs. 6, Anlage (Löschung), LB Nr. 8 Abs. 3 und Datenschutz 6c: das Einrichtungs-Ticket bleibt mit einer Kurzfassung der Einstellungen als Arbeitsnachweis (keine Daten von Gästen)
- AVV Nr. 8 Abs. 2: "Gastdaten löschen" löscht nur wartende E-Mails; fehlgeschlagene behalten Adresse und Inhalt bis Nr. 9 Abs. 4
- Datenschutz § 7: Frist für Bestellungen ohne Abo (drei Jahre nach Ablauf des Jahres der Bestellung)
- News-Leistungsbeschreibung vom 30.09.2026 unverändert archiviert (SHA-256-Pin), die geltende Datei verweist darauf
- Kanzlei-Paket: Zitate, Q4/Q9/Q23, Livegang-Checkliste (Abschnitt 7.6/7.7), K23-Hinweis
- build-legal-html: Rückwärtsschrägstrich in Navigationsadressen abgelehnt; TP1-Spezifikation E2 (ohne USt)
- HTML, PDFs und Prüfsummen neu erzeugt (Terminplaner-Unterlagen und Datenschutzerklärung)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-05 06:54:55 +00:00
1 parent 5f99f08a39
commit bea07e73b1
22 files changed
+299 -33

No files matched your search

+38 -1
View File
@@ -625,7 +625,10 @@ test('avv_inhalt: Abschluss, Zwecke ohne Eigennutz, Datenarten, Weisungen, Daten
assert.ok(vorbemerkung.includes('Das Portal speichert die Fassung, den Zeitpunkt, das Kundenkonto und die angemeldete Person.'))
assert.ok(vorbemerkung.includes('Anschließend sendet WEBklar dem Kunden eine E-Mail, die beide Texte und die Widerrufsbelehrung in dieser Fassung als PDF enthält'))
assert.ok(vorbemerkung.includes('Ein Mitarbeiter von WEBklar darf die Funktion nur einschalten, wenn der Kunde vorher in Textform'))
assert.ok(vorbemerkung.includes('Der Kunde erhält die E-Mail nach Absatz 1 anschließend.'))
// T1: In der Textform-Aktivierung trägt K16 nur Leistungsbeschreibung und AVV als PDF (ohne Widerrufsbelehrung, ohne Links): der Text verspricht nicht die E-Mail nach Absatz 1
assert.ok(vorbemerkung.includes('Der Kunde erhält anschließend eine E-Mail mit diesen beiden Texten als PDF.'))
assert.ok(!vorbemerkung.includes('E-Mail nach Absatz 1 anschließend'), 'der Satz verwies auf die Mail mit Belehrung und Links')
assert.match(lies('server/routes/admin/funktionenAdmin.js'), /featureLegalAttachments\('termine', \{ ohne: \['widerruf'\] \}\)/, 'K16 der Textform-Aktivierung: nur Leistungsbeschreibung und AVV')
assert.ok(vorbemerkung.includes('Für den Terminplaner geht er Anlage 1 vor'))
assert.ok(vorbemerkung.includes('Anlage 1 der Abo-Bedingungen'))
@@ -673,6 +676,37 @@ test('avv_inhalt: Abschluss, Zwecke ohne Eigennutz, Datenarten, Weisungen, Daten
assert.ok(nr12.includes('Im Übrigen gilt § 16 der Abo-Bedingungen.'))
})
test('avv_ausnahmen_loeschung: Einrichtungs-Ticket bleibt (Nr. 9 Abs. 6, Anlage, LB Nr. 8 Abs. 3); fehlgeschlagene E-Mails behalten Adresse und Inhalt bis Nr. 9 Abs. 4 (Nr. 8 Abs. 2)', () => {
// T2: das Einrichtungs-Ticket (workorders.details = Kurzfassung der Einstellungen, ticketDetails.js) wird beim Löschlauf nicht angefasst
const ticket = 'Eine Ausnahme ist das Einrichtungs-Ticket, in dem WEBklar die Einrichtung als Arbeitsnachweis festhält: Es bleibt mit einer Kurzfassung der Einstellungen bestehen'
const nr9 = avvNr(9)
const abs6 = nr9.slice(nr9.indexOf('(6) '), nr9.indexOf('(7) '))
assert.ok(abs6.includes(ticket))
assert.ok(abs6.includes('(zum Beispiel Betriebsangaben, Namen der Leistungen, die ersten acht Namen der Personen oder Plätze und die Wünsche des Kunden zum Einbau) und enthält keine Daten von Gästen; dafür gilt die Datenschutzerklärung von WEBklar (Abschnitt 6).'))
// Reihenfolge: erst die Löschung nach 30 Tagen, dann die Ausnahme, dann der Export; „Bis dahin“ hätte sich auf die Datenschutzerklärung beziehen lassen
assert.ok(abs6.indexOf('30 Tage danach.') < abs6.indexOf(ticket) && abs6.indexOf(ticket) < abs6.indexOf('Bis zur Löschung kann der Kunde die Termine'))
assert.ok(!abs6.includes('Bis dahin'))
assert.ok(tomZeilen()['Löschung'].includes('das Einrichtungs-Ticket bleibt als Arbeitsnachweis mit einer Kurzfassung der Einstellungen bestehen und enthält keine Daten von Gästen (Nummer 9 Abs. 6)'))
assert.ok(norm(abschnitt(LB, 8).text).includes('Eine Ausnahme ist das Einrichtungs-Ticket, in dem WEBklar die Einrichtung als Arbeitsnachweis festhält: Es bleibt mit einer Kurzfassung der Einstellungen bestehen und enthält keine Daten von Gästen (Nummer 9 Abs. 6 des AVV Terminplaner).'))
// die Zahl „acht“ ist die der Kurzfassung (einbauanleitung.js KURZ_NAMEN); die Kurzfassung hat keinen Zugriff auf Buchungen (ticketDetails.js liest nur den Stand der Einstellungen)
assert.match(lies('server/services/termine/einbauanleitung.js'), /const KURZ_NAMEN = 8\b/)
assert.doesNotMatch(lies('server/services/termine/ticketDetails.js'), /termineBookings|buchungen\.js|gastName|gastEmail/)
// Datenschutzerklärung Abschnitt 6 nennt die Arbeitsnachweise und die Aufbewahrung bis zur Verjährung
const ds = norm(lies('public/datenschutz.html').replace(/<[^>]+>/g, ' '))
assert.ok(ds.includes('unsere Arbeitsnachweise') && ds.includes('bis zum Ablauf der Verjährungsfrist (in der Regel drei Jahre)'))
// T3: „Gastdaten löschen“ löscht nur Einträge im Status wartet (verwerfeWartende); Einträge im Status fehler behalten Adresse und Inhalt bis 48 Stunden nach dem Fehlschlag
const nr8 = avvNr(8)
assert.ok(nr8.includes('Dabei löscht WEBklar die E-Mails zu dieser Buchung, die noch auf den Versand warten, und die Links des Gastes werden ungültig.'))
assert.ok(nr8.includes('E-Mails, deren Versand endgültig fehlgeschlagen ist, behalten Empfängeradresse und Inhalt, bis WEBklar sie nach Nummer 9 Abs. 4 löscht (48 Stunden nach dem Fehlschlag).'))
assert.ok(!nr8.includes('Noch nicht versandte E-Mails zu dieser Buchung löscht WEBklar dabei'), 'der alte Satz versprach mehr, als verwerfeWartende löscht')
const verwerfe = /export async function verwerfeWartende[\s\S]*?\n\}\n/.exec(OUTBOX)?.[0]
assert.ok(verwerfe, 'verwerfeWartende')
assert.ok(verwerfe.includes("Query.equal('status', 'wartet')") && !verwerfe.includes("'fehler'"), 'verwerfeWartende löscht nur den Status wartet')
assert.match(OUTBOX, /const FEHLER_BEHALTEN_MS = 48 \* STUNDE_MS/)
assert.ok(avvNr(9).includes('löscht WEBklar mit Empfängeradresse und Inhalt 48 Stunden nach dem endgültigen Fehlschlag'))
})
/**
* Fundstellen der Anlage TOM: jede Zeile der Tabelle nennt hier, wo im Code, in den Tests oder in den Abo-Bedingungen ihre
* Aussage gesichert ist. { datei, hat } = die Datei enthält das Muster; { datei, nicht } = die Datei enthält es nicht.
@@ -730,6 +764,9 @@ const TOM_FUNDSTELLEN = {
{ datei: 'server/services/termine/entwuerfe.js', hat: /const funktion = await holeOderNull\(config\.collections\.portalFeatures, id\)/ },
// die Warteschlange löscht die gelisteten Einträge ohne erneutes Lesen (nur Buchungen, abgeschaltete Funktionen und Entwürfe lesen frisch)
{ datei: 'server/services/termine/outbox.js', hat: /await deleteDocument\(col\(\), eintrag\.\$id\)/ },
// das Einrichtungs-Ticket (Kurzfassung der Einstellungen, ohne Daten von Gästen) bleibt als Arbeitsnachweis
{ datei: 'server/services/termine/ticketDetails.js', hat: /const \{ kurz \} = einbauanleitung\(/ },
{ datei: 'server/services/termine/einbauanleitung.js', hat: /const KURZ_NAMEN = 8 / },
],
'Protokolle': [
{ datei: 'test/termineJobs.test.js', hat: /kein Gastname und keine Gastadresse im Log/ },