Rechtsrunde Fassung 6 freigegeben (28.10.2026): Datum, Entwurfsmarken, R8b
Der Inhaber hat am 28.10.2026 alle Vorschläge R1 bis R18 angenommen (R10 = Option A) und zusätzlich R8b entschieden: Webshop und Buchungskalender kehren nach einem neuen Wartungs-Abo in der Frist automatisch zurück, wie der Server es schon tut. - Fassungen: Abo 2026-10-28-v6, Funktionsunterlagen 2026-10-28 (Seiten neu gebaut) - Entwurfsmarken und meta robots noindex entfernt, ENTWURF_V6 = false - WORTLAUT_STATUS = 'freigegeben' - Nr. 10 Abs. 5 Webshop/Buchungskalender ohne "auf Wunsch in Textform" (R8b) - Entscheidungsliste: Abschnitt "Freigabe"; Prüfpunkte D1 bis D8 auf die aktuelle Datenschutzerklärung (Fassung 22.10.2026, eine Zeile tiefer) umgestellt - Tests auf das neue Datum und den Status freigegeben gezogen Live ändert sich für Kunden nichts: die Seiten liegen unter /neu/ und gelten nur in der neuen Ansicht (Pilot). Umschalten (P10) folgt erst auf ausdrückliches "umschalten". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2873638b1c
commit
64f1a3b26b
36 files changed
+129
-131
No files matched your search
@@ -13,7 +13,7 @@ const { render, funktionen6Dokumente } = await import('../scripts/build-legal-ht
|
||||
|
||||
const ROOT = fileURLToPath(new URL('..', import.meta.url))
|
||||
const lies = (rel) => readFileSync(join(ROOT, rel), 'utf8')
|
||||
const ENTWURF = true
|
||||
const ENTWURF = false
|
||||
|
||||
const B = { // Bausteine; {N} = Nominativ, {G} = Genitiv der Partei (Kunde/Kunden, Händler/Händlers, Vermieter/Vermieters)
|
||||
geltung: 'Diese Leistungsbeschreibung gilt, wenn der {N} die Funktion im Kundenportal einschaltet und die dort angezeigte Zeile mit dem Klick auf „Einschalten“ bestätigt. Sie gilt für Funktionen, die ab ihrer Veröffentlichung eingeschaltet werden; hat der {N} die Funktion zuvor einzeln gekauft, gilt für sie weiter die Leistungsbeschreibung, unter der er sie gekauft hat.',
|
||||
@@ -49,7 +49,7 @@ const abschnitte = (md) => md.split(/^## /m).slice(1).map((s) => ({ kopf: s.spli
|
||||
test('Leistungsbeschreibungen v6: Fassungszeile, Bausteine, Pflichtsatz, Frist, keine Preise', () => {
|
||||
for (const key of LISTE) {
|
||||
const e = LB[key], md = lies(`docs/rechtliches/${e.slug}-v6.md`)
|
||||
assert.match(md.split('\n')[2], new RegExp(`^\\*\\*Fassung 2026-10-16\\*\\*${ENTWURF ? ' · Entwurf – Prüfung durch Kanzlei offen' : ''} · Zusatzbedingungen zum Wartungs-Abo$`), key)
|
||||
assert.match(md.split('\n')[2], new RegExp(`^\\*\\*Fassung 2026-10-28\\*\\*${ENTWURF ? ' · Entwurf – Prüfung durch Kanzlei offen' : ''} · Zusatzbedingungen zum Wartungs-Abo$`), key)
|
||||
assert.doesNotMatch(md, VERBOTEN, key)
|
||||
for (const t of ['geltung', 'voraussetzung', 'einrichtung', 'projekt', 'mehraufwand', key === 'zeiten' ? 'endeZeiten' : 'ende']) assert.ok(md.includes(bau(B[t], e.partei)), `${key}: Baustein ${t}`)
|
||||
if (key === 'zeiten') assert.doesNotMatch(md, /Karenz|Behalten|spätestens am folgenden Tag/, 'Zeiten: 30 Tage Weiterlauf wie das bestehende Modul, kein Behalten, nicht die Abschaltung am Folgetag')
|
||||
@@ -67,13 +67,13 @@ test('Terminplaner v6: Überschriften wie Fassung 5 (Nr. 5 heißt „Einrichtung
|
||||
})
|
||||
test('Seiten der Gruppe sind genau render(Markdown)', () => {
|
||||
for (const key of LISTE) {
|
||||
const d = funktionen6Dokumente().find((x) => x.html.includes(`/${LB[key].slug}-2026-10-16.html`))
|
||||
const d = funktionen6Dokumente().find((x) => x.html.includes(`/${LB[key].slug}-2026-10-28.html`))
|
||||
assert.equal(lies(d.html), render(lies(d.md), d.meta), `${d.html}: node scripts/build-legal-html.mjs funktionen6 --nur=${d.doc}`)
|
||||
}
|
||||
})
|
||||
test('Entwurfsseiten der Gruppe: Entwurfsmarke in der Quelle und meta robots noindex in der Seite (N45)', () => {
|
||||
for (const key of LISTE) {
|
||||
const d = funktionen6Dokumente().find((x) => x.html.includes(`/${LB[key].slug}-2026-10-16.html`))
|
||||
const d = funktionen6Dokumente().find((x) => x.html.includes(`/${LB[key].slug}-2026-10-28.html`))
|
||||
assert.equal(lies(d.md).includes('Entwurf – Prüfung durch Kanzlei offen'), ENTWURF, d.md)
|
||||
assert.equal(lies(d.html).includes('<meta name="robots" content="noindex">'), ENTWURF, d.html)
|
||||
}
|
||||
@@ -98,7 +98,7 @@ const BA = {
|
||||
}
|
||||
test('Website-Analyse v6 (Leistungsbeschreibung): in beiden Abos, Einrichtung kostenlos, Ende mit dem Abo, Zielgruppenregel bleibt', () => {
|
||||
const md = lies('docs/rechtliches/leistungsbeschreibung-website-analyse-v6.md')
|
||||
assert.match(md.split('\n')[2], /^\*\*Fassung 2026-10-16\*\* · (Entwurf – Prüfung durch Kanzlei offen · )?Zusatzbedingungen zum Hosting-Abo und zum Wartungs-Abo$/)
|
||||
assert.match(md.split('\n')[2], /^\*\*Fassung 2026-10-28\*\* · (Entwurf – Prüfung durch Kanzlei offen · )?Zusatzbedingungen zum Hosting-Abo und zum Wartungs-Abo$/)
|
||||
assert.doesNotMatch(md, /€|per Haken|[a-zäöüß,;:] Sie\b|Im Hosting-Abo ist die Website-Analyse nicht enthalten|Sie ist im Wartungs-Abo ohne Aufpreis|im Kundenportal bestellt/)
|
||||
assert.ok(md.includes(B.geltung.replaceAll('{N}', 'Kunde')))
|
||||
for (const t of Object.values(BA)) assert.ok(md.includes(t), t.slice(0, 40))
|
||||
@@ -114,16 +114,16 @@ const AVV = { // [alt, neu] je Datei; der Rest ab "## 1." ist sonst wortgleich
|
||||
['(Ausschalten oder Ende des Wartungs-Abos)', '(Ausschalten oder Ende des Abos, das sie enthält)'],
|
||||
['Das Wartungs-Abo bleibt davon unberührt.', 'Das Abo bleibt davon unberührt.']],
|
||||
}
|
||||
const KOPF_AVV = ENTWURF ? '**Fassung 2026-10-16** · Entwurf – Prüfung durch Kanzlei offen' : '**Fassung 2026-10-16**'
|
||||
const KOPF_AVV = ENTWURF ? '**Fassung 2026-10-28** · Entwurf – Prüfung durch Kanzlei offen' : '**Fassung 2026-10-28**'
|
||||
const AVV_FUNKTION = { termine: 'Terminplaner', shop: 'Webshop', unterkunft: 'Buchungskalender', analyse: 'Website-Analyse' }
|
||||
const avvVorbemerkung = (funktion, fassung) => `Der Kunde schließt diesen Vertrag, wenn er im Kundenportal die Funktion „${funktion}“ einschaltet und die dort angezeigte Zeile „Es gelten Leistungsbeschreibung und Auftragsverarbeitung (Fassung ${fassung})“ mit dem Klick auf „Einschalten“ bestätigt; diesem Vertrag und der Leistungsbeschreibung „${funktion}“ („Leistungsbeschreibung“) in der angezeigten Fassung stimmt er damit zu. Das Portal speichert den Wortlaut der angezeigten Zeile, die Fassungen, den Zeitpunkt, das Kundenkonto und die angemeldete Person. Anschließend sendet WEBklar dem Kunden eine E-Mail, die beide Texte in dieser Fassung als PDF enthält und auf sie verlinkt.`
|
||||
function pruefeAvv(key, slug) {
|
||||
const v5 = lies(`docs/rechtliches/${slug}.md`), v6 = lies(`docs/rechtliches/${slug}-v6.md`)
|
||||
assert.equal(v6.split('\n')[2], KOPF_AVV)
|
||||
assert.ok(v6.includes(`(1) ${avvVorbemerkung(AVV_FUNKTION[key], '2026-10-16')}`))
|
||||
assert.ok(v6.includes(`(1) ${avvVorbemerkung(AVV_FUNKTION[key], '2026-10-28')}`))
|
||||
assert.doesNotMatch(v6, /per Haken|Mit der Bestellung weist|Vertrag über den Betrieb der Website|keine Bestellung geworden/)
|
||||
let erwartet = v5.replace(/^\*\*Fassung \d{4}-\d{2}-\d{2}\*\*.*$/m, KOPF_AVV)
|
||||
erwartet = erwartet.replace(/^\(1\) Der Kunde schließt diesen Vertrag[^\n]*$/m, `(1) ${avvVorbemerkung(AVV_FUNKTION[key], '2026-10-16')}`)
|
||||
erwartet = erwartet.replace(/^\(1\) Der Kunde schließt diesen Vertrag[^\n]*$/m, `(1) ${avvVorbemerkung(AVV_FUNKTION[key], '2026-10-28')}`)
|
||||
for (const [alt, neu] of AVV[key]) { assert.ok(erwartet.includes(alt), `Bestand enthält: ${alt.slice(0, 40)}`); erwartet = erwartet.replaceAll(alt, neu) }
|
||||
assert.equal(v6, erwartet, `${slug}-v6.md = Bestandsfassung mit genau diesen Ersetzungen`)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user