K24–K26 sind seit dem Webshop-Livegang (main) vergeben; der Mail-Lader sucht die Vorlage über den Dateianfang, doppelte Nummern hätten die falsche Mail geschickt. Das Feld ist noch nicht in der Produktion angelegt (zeiten-setup.mjs lief noch nicht), daher jetzt ein sprechender Name. Spec und Plan behalten die alten Nummern (Hinweis oben im Dokument). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
25 KiB
Öffnungszeiten live – Livegang-Notiz
Stand 05.10.2026, für Kenso. Grundlage: Spec Abschnitt 13.6, das Protokoll der Umsetzung (.superpowers/sdd/2026-10-04-oeffnungszeiten-live/progress.md, alle LIVEGANG-Hinweise und Rechtsrunde-Punkte) und die Gesamtprüfung (Task 37, Bericht task-37-report.md im selben Ordner). Nichts davon ist gepusht. Keine Rechtsberatung.
Stand der drei Branches
| Repo | Worktree / Branch | Stand | Basis und Abstand |
|---|---|---|---|
| Portal (+ Runner) | dev-zeiten, feature/oeffnungszeiten |
Inhalt von 90e8607 plus diese Notiz und die Fixrunde nach der Abschlussprüfung (ecf67d6 Server, aa9ee35 Skript und Editor, danach die Doku) |
enthält TP2 bis a629b25; TP2 steht inzwischen auf af63b69 (34 Commits weiter) |
| WOMS | ticket.webklar.com/dev-zeiten, feature/oeffnungszeiten |
919d96f (Fixrunde: Statustext der Einrichtung) auf 3d67aa8 |
auf WOMS-TP2 72eedeb; TP2 steht inzwischen auf 4c3f67e (5 Commits weiter) |
| Relaunch | webklar.com/dev-zeiten-station, feature/zeiten-station |
8f5d522 |
auf main 4139f31 (kein Abstand, Stand 05.10.) |
Letzte Prüfung vor der Fixrunde 05.10.2026, alles grün: Portal 4544/4545 (der eine Fehler war der bekannte wacklige previewDevRouter-Test, einzeln 12/12), Portal unter Node 20 (wie in Produktion) 4543/4543 ohne analyticsContract, Runner 177/177, UI-Prüfungen 31/31 + 8/8 + alle OK, WOMS 377/377 + vite build, Relaunch 349/349 + Build (Haupt-JS 128 084 Byte gz, Grenze 133 120).
Nach der Fixrunde (Abschlussprüfung, 05.10.2026), alles grün: Portal 4564/4564 (npm test), Runner 177/177, UI-Prüfungen Skript 34/34 und Portal 9/9, WOMS 378/378 + vite build. Der Node-20-Lauf (Schritt A.2) und die Relaunch-Prüfung (A.4) stehen für nach der TP2-Zusammenführung an, sie laufen ohnehin neu.
A. Reihenfolge am Livegang-Tag
- TP2 geht zuerst live (Portal und WOMS) nach seiner eigenen Reihenfolge (Kanzlei-Paket Abschnitt 7.6, mit
termine-setup.mjsundfeature-setup.mjs). Öffnungszeiten live baut auf TP2 auf und braucht dessen Schema (aboEndeMailAt,disabledReason,featureConsents). - Portal neu aufsetzen. In
dev-zeiten: das jetzt live gegangene TP2 einmal hineinführen, mitgit fetch origin && git merge origin/main. Nichtgit merge main: die lokale Refmainsteht noch auff1b43ca(vor TP2), das gäbe „Already up to date“, und der Push würde abgelehnt. Ist TP2 noch nicht inorigin/main:git merge feature/terminplaner-tp2. Es gibt einen Merge statt Rebase, damit die Commit-Nummern des Protokolls gültig bleiben. Eine Probe-Zusammenführung mit TP2af63b69(git merge-tree --write-tree) ergab im Portal drei Textkonflikte, die so zu lösen sind (bei der ersten Zusammenführung1d5a565überlappten 14 Dateien):server/routes/admin/funktionenAdmin.js: unser Zeiten-Zweig (zeitenAktivieren,zeitenAbschalten,ersatzTicketin der Antwort) und TP2s Textform-/K16-Warnung (warnung) bleiben beide; die Antwort trägt beides.server/services/retention.js: unserzeitenIds(Zeiten vor dem Abschalten des Kunden löschen) und TP2sconsentIds/featureFieldIdsbleiben beide. TP29a2a70b(„Fehlschlag hält den Kunden für den nächsten Lauf“) löst vermutlich die Retention-Hälfte von N9 (eine fehlgeschlageneloescheZeitenVonKundewird nicht wiederholt): bei der Konfliktlösung prüfen, obloescheZeitenVonKundebei jedem Lauf aufgerufen wird, und nicht vorher separat patchen.server/services/siteFeatures.js: Textkonflikt, beide Seiten behalten. TP2b974b3alegtdisable()unter die Sperrefeature-activate:<id>(Sperren sind nicht wiederbetretbar): nach der Zusammenführung prüfen, dass kein Halter vonfeature-activatedisable()aufruft (aboAbgleichundzeitenAbschaltenrufen es unterfeature-adminauf: erlaubte Reihenfolge). Danach alles erneut laufen lassen:nice npm test(nurpreviewDevRouterdarf wackeln, dann einzeln wiederholen),cd runner && nice npm test- Node 20:
docker run --rm --cpus 3 -v /home/webklar/apps/kundenbereich.webklar.com/dev-zeiten:/app:ro -w /app node:20 sh -c 'node --test --test-concurrency=3 $(ls test/*.test.js | grep -v analyticsContract)' - UI, je einzeln mit
niceund vorherfree -m:test/ui/zeiten-embed.ui.mjs,test/ui/zeiten-portal.ui.mjs,test/ui/funktionen.ui.mjs
- WOMS neu aufsetzen. In
ticket.webklar.com/dev-zeiten: die WOMS-Hauptlinie (test, mit TP2) hineinführen (git fetch origin && git merge origin/test). Erwarteter Konflikt (1 Datei):src/components/customer/CustomerFunktionen.jsx; dort bleiben unserersatzTicketund TP2sspeicherStatus/K16_WARNUNG(TP24c3f67eändert dieselbensave()-Zeilen sowie das Ende vonsrc/lib/funktionenView.jsund seinen Test, das Portal fügt dieselbe POST-Route umwarnungein).K16_WARNUNGnennt einen „AVV“, den Öffnungszeiten live nicht hat: nach der Zusammenführung prüfen und für die Zeiten anpassen. Danachnice npm testundnice npx vite build.node_modulesist dort im Git verfolgt und wurde vonnpm civerändert: nie stagen. - Relaunch prüfen.
git log --oneline 4139f31..mainim Relaunch-Repo; gibt es neue Commits,feature/zeiten-stationdarauf aufsetzen, dannnice npm test,nice npm run buildundgzip -9 -c dist/assets/index-*.js | wc -c(höchstens 133 120). - Schema anlegen, vor dem Portal-Deploy.
scripts/zeiten-setup.mjslegtoeffnungszeitenundzeitenErinnerungenan und ergänztportalFeaturesumunlockedBy,aboEndeAt,einbau,behaltenSessionId,einschaltMailAt. Seit der Fixrunde schreibtactivate()aboEndeAtundbehaltenSessionIdnur noch für Öffnungszeiten live (Parameterextra); News und Terminplaner brauchen die Felder nicht mehr und laufen auch vor dem Skript. Trotzdem erst das Schema, dann der Deploy: die Zeiten-Pfade schreiben die Felder. Das Skript braucht den neuen Code, also aus dem Worktree in einem Wegwerf-Container (keindocker compose run: der Container bekäme die Traefik-Labels des Portals). Die Env-Datei enthält Zugangsdaten: mitumask 077anlegen, nicht erst danachchmod. Erst--check(beim ersten Lauf Exit 1, erwartet: es fehlt ja noch alles), dann ohne, dann noch einmal--check(muss grün sein; die Index-Reihenfolge der Schema-Skripte hat am 30.09. schon einmal überrascht):(Der Aufruf ist so noch nie gegen die Produktion gelaufen; er folgt dem Muster der früheren Schema-Skripte. Das Skript ist idempotent,(umask 077; docker inspect webklar-kundenbereich-server -f '{{range .Config.Env}}{{println .}}{{end}}' > /root/zeiten-env.tmp) docker run --rm --env-file /root/zeiten-env.tmp --network webklar-network -v /home/webklar/apps/kundenbereich.webklar.com/dev-zeiten:/app:ro -w /app node:20-alpine node scripts/zeiten-setup.mjs --check docker run --rm --env-file /root/zeiten-env.tmp --network webklar-network -v /home/webklar/apps/kundenbereich.webklar.com/dev-zeiten:/app:ro -w /app node:20-alpine node scripts/zeiten-setup.mjs docker run --rm --env-file /root/zeiten-env.tmp --network webklar-network -v /home/webklar/apps/kundenbereich.webklar.com/dev-zeiten:/app:ro -w /app node:20-alpine node scripts/zeiten-setup.mjs --check rm /root/zeiten-env.tmp--checkschreibt nichts.) - Stripe prüfen.
node scripts/stripe-products.mjs --pruefen(gleicher Wegwerf-Container). Erwartet wird ein Preiswebklar_zeiten_einrichtung_3000(30 €, einmalig,tax_behaviorinclusive, Standard-Produktbild). Fehlt er:--anlegen; danach--pruefennochmal. - Einstellungen, vor dem Push. Zuerst Sicherungen:
cp /home/webklar/apps/docker-compose.yml /home/webklar/apps/docker-compose.yml.bak-2026-10-05-zeitenund(umask 077; cp /home/webklar/apps/.env /home/webklar/apps/.env.bak-2026-10-05-zeiten)(.enventhält Zugangsdaten). Dann in/home/webklar/apps/.env:ZEITEN_ENABLED=pilot,ZEITEN_PILOT_EMAILS=kenso.gri@gmail.com,ZEITEN_KEIN_NEUBAU=emmas-schatzkiste. In/home/webklar/apps/docker-compose.yml, Dienstkundenbereich-server, drei Zeilen nebenTERMINE_ENABLED:- ZEITEN_ENABLED=${ZEITEN_ENABLED:-off},- ZEITEN_PILOT_EMAILS=${ZEITEN_PILOT_EMAILS:-},- ZEITEN_KEIN_NEUBAU=${ZEITEN_KEIN_NEUBAU:-emmas-schatzkiste}. Prüfen mitdocker compose -f /home/webklar/apps/docker-compose.yml config -q(keine Ausgabe = gültig), dann übernehmen mitdocker compose -f /home/webklar/apps/docker-compose.yml up -d --no-deps kundenbereich-server. Ein bloßesdocker restartliest neue Umgebungswerte nicht. Das alles vor dem Push (Schritt 9): dann startet der Container mit dem alten Code und den neuen Werten (die kennt er nicht, harmlos), und der Neustart durchdeploy.shnach dem Push ist der einzige mit dem neuen Code (jeder Containerstart führtapk addundnpm installaus). - Runner: kein Image-Bau nötig. Der Runner ist
node:20-alpinemit eingehängtembuild/runner(das Protokoll sagt „Image neu bauen“, das stimmt für die echte Konfiguration nicht).deploy.shstartet ihn neu, nur wenn sichrunner/in der Deploy-Spanne ändert und die Warteschlange leer ist.ZEITEN_PUBLIC_BASEnicht setzen: die Vorgabehttps://project.webklar.com/embed/stimmt. Nach dem Push prüfen:docker inspect -f '{{.State.StartedAt}}' webklar-preview-runnermuss nach dem Push liegen (vorher 2026-10-02T16:17Z); sonst von Handdocker restart webklar-preview-runner(das Deploy-Log im Containerwebklar-kundenbereich-buildwird täglich um 00:00 rotiert und ist als Beleg unzuverlässig; „naechster Deploy versucht es erneut“ stimmt nicht, ohne Änderung anrunner/kommt kein Neustart). Ein alter Runner verwirft das neue Feldzeitenstillschweigend, der Einbau meldete dann „angestoßen“, setzt aber nichts ein. - Pushen, in dieser Reihenfolge (du pushst, ich nicht). Die Ziel-Ref steht immer dabei (
<lokaler Branch>:<Ziel>), damit nichts unter dem falschen Namen ankommt:- Portal samt Runner:
cd /home/webklar/apps/kundenbereich.webklar.com/dev-zeiten && git push origin feature/oeffnungszeiten:main. Der Portal-Webhook deployt jeden gepushten Branch (webhook-server.jssetztDEPLOY_BRANCHauspayload.ref,deploy.shmachtreset --hard origin/<branch>): den Feature-Branch nie unter seinem eigenen Namen pushen (git push origin feature/oeffnungszeiten), das würde ihn auf die Produktion bringen. - WOMS erst nach dem Portal, sonst antwortet das Portal auf die neuen Zeiten-Aktionen mit 404:
cd /home/webklar/apps/ticket.webklar.com/dev-zeiten && git push origin feature/oeffnungszeiten:test. Der WOMS-Webhook deployt nurtest(TICKET_DEPLOY_BRANCH, Vorgabetest; Pushes auf andere Branches ignoriert er);testalso nie vor dem Portal. Danachsetup-legal.mjs(legt die Rechtliches-Karteleistungsbeschreibung-zeitenan, Schlüssel ≤ 36 Zeichen): ungetestet gegen die Produktion, zuerstnode scripts/setup-legal.mjs --dry-runim WOMS-Worktree, dannAPPWRITE_API_KEY=… APPWRITE_ENDPOINT=… node scripts/setup-legal.mjs. Der Schlüssel (APPWRITE_API_KEY) ist nötig; der Standard-Endpoint des Skripts isthttps://appwrite.webklar.com/v1, das WOMS-Frontend nutzt in der Vorgabehttps://ticket.webklar.com/v1: den Endpoint vorher gegen den ausliefernden Container prüfen und ausdrücklich setzen. - Relaunch:
cd /home/webklar/apps/webklar.com/dev-zeiten-station && git push origin feature/zeiten-station:main. Die Station „Öffnungszeiten live“ steht dort aufbald: true(„Bald verfügbar“) und bleibt so bis Schritt C.
- Portal samt Runner:
- Live-Checks nach dem Deploy (Portal und WOMS sind da):
- Öffentliche Schnittstelle kennt einen unbekannten Schlüssel nicht:
curl -s https://project.webklar.com/api/public/zeiten/v1/aaaaaaaaaaaaaaaaantwortet{"aktiv":false}. - Skript:
curl -sI https://project.webklar.com/embed/zeiten.jsist 200, mitAccess-Control-Allow-OriginundCache-Control. - Leistungsbeschreibung:
curl -sI https://project.webklar.com/vertragsunterlagen/zeiten-leistungsbeschreibung.htmlist 200. - WOMS: Kunde → Reiter „Funktionen“ lädt ohne Fehler (auch für ein Projekt ohne Zeiten).
- Portal-Log:
docker logs --since 15m webklar-kundenbereich-server 2>&1 | grep -i "unknown attribute"bleibt leer (sonst fehlt ein Schema-Feld, Schritt 5). - Stripe: Webhook-Adresse und Ereignisliste im Dashboard sind unverändert (die Funktion nutzt dieselben Ereignisse wie News und Terminplaner; es kommt nichts Neues dazu).
- Rückweg, falls etwas hakt:
ZEITEN_ENABLED=offin.env, danndocker compose -f /home/webklar/apps/docker-compose.yml up -d --no-deps kundenbereich-server. Die Kachel verschwindet, die Schnittstelle antwortetaktiv: false, die Platzhalter zeigen ihr Ersatz-HTML, der Abo-Abgleich läuft weiter. Das Schema ist rein additiv (neue Collections und Felder), es gibt nichts zurückzubauen; ein Code-Rollback ist beioffnicht nötig.
- Öffentliche Schnittstelle kennt einen unbekannten Schlüssel nicht:
- Pilot-Probelauf (Abschnitt B), danach Rechtsrunde abschließen (Abschnitt D), dann Abschnitt C.
B. Probelauf mit ZEITEN_ENABLED=pilot auf test-website
Nur dein Konto sieht die Kachel. Beachte: Das Portal prüft nur „Leistungsbeschreibung vorhanden“, nicht „freigegeben“ (unterlagenBereit ist für Zeiten immer wahr). Der Pilot ist deshalb der einzige Schutz vor dem Entwurfstext, bis on kommt.
- Kachel im Funktionen-Tab sichtbar. Je nach Konto: „Einschalten“ (Wartungs-Abo aktiv) oder „30 € einmalig“. Den Bezahlweg nur mit echter 30-€-Zahlung testen (danach erstatten) oder weglassen; die Tests decken ihn ab.
- Einschalten: Ticket „Öffnungszeiten live einbauen“ in WOMS, Mail K27,
einbau=angestossen(Runner-Log) odermanuell. - Editor: Wochenplan mit Fenstern und Mitternacht, zweiter Plan, Bundesland und Feiertage, Urlaub (Hinweis-Vorschlag), Hinweis-Leiste, Kontakt-Leiste mit Telefon und Adresse, „Für Google kopieren“, Uhrzeit-Regler.
- Preview der
test-websitenach dem Neubau: im Quelltext<script data-wk-zeiten … data-site="…">; Hinweis-Leiste oben (schiebt den Header?), Kontakt-Leiste auf dem Handy, JSON-LD im Quelltext (kein Duplikat), Platzhalter mit Status, Tabelle und Badge; Ersatz-HTML aus WOMS („Ersatz-HTML kopieren“) in die Platzhalter. Dazu der Datenschutz-Absatz ausdocs/funktionen/website-datenschutz-absatz.md(Entwurf) auf der Test-Seite. - WOMS: Panel (Zeiten-Einstellungen
navSelektor, Leisten aus), „Aktivieren ohne Zahlung“ und „Abschalten“ am Testprojekt; Ticket schließen ⇒ nach spätestens 5 Minutenactiveund Mail K16; Abschalten ⇒ Ticket „Ersatz-Tabelle aktualisieren“ (nur wenn der Wochenplan vom Ersatz-HTML abweicht). - Mails K27 bis K30 ansehen (K28 über einen Feiertag in 1–7 Tagen, K29/K30 nur mit einem Abo-Ende; sonst über die Tests bewertet).
- Aufräumen: Funktion am Testprojekt abschalten, Ticket schließen. Das Abschalten durch das Team löscht nie Daten; die Testdaten löschst du von Hand in der Appwrite-Konsole (Datenbank des Portals): im Dokument der Funktion in
portalFeatures(featureKey=zeiten,projectId= das Testprojekt) die ID notieren; in der Collectionoeffnungszeitendas Dokument mit genau dieser ID löschen (es trägt die Eingaben, das Team-Feld und den Ersatz-Hash); inzeitenErinnerungenalle Dokumente mitfeatureId= dieser ID löschen (die Erinnerungs-Merker). Danach ist die Schnittstelle des Testprojekts nach spätestens 60 Sekunden (Zwischenspeicher) wieder leer. (Automatisch gelöscht wird nur beim Ende des Abos nach 30 Tagen und beim Löschen des Kundenkontos.)
C. Schalter on (letzter Schritt)
Erst wenn Abschnitt B ohne offene Fehler und Abschnitt D vollständig erledigt ist:
ZEITEN_ENABLED=onin.env,docker compose up -d kundenbereich-server.- Relaunch: in
src/components/home/Kundenportal.tsxden Eintragoeffnungszeitenaufbald: false(die Marke „Bald verfügbar“ verschwindet). Dabei den Test anpassen:relaunch-kundenportal.test.tsx(um Zeile 142 bis 156) pinnt genau zwei „Bald verfügbar“; nach dem Umschalten ist es eines weniger. Dann Tests und Build, du pushst. Das Handy-Bildphone-12-zeitenzeigt den Einleitungstext des Editors (und einen laufenden Urlaubs-Hinweis): nach der Textrunde neu aufnehmen, bevorbald: falselive geht. - Logs beobachten (
[zeiten],[zeiten-jobs]): Abo-Abgleich täglich, Feiertags-Erinnerung stündlich zwischen 08:00 und 20:00. - Zurück auf
off: Kachel verschwindet, die öffentliche Schnittstelle antwortetaktiv: false, die Platzhalter zeigen ihr Ersatz-HTML; der Abo-Abgleich läuft weiter.
D. Rechtsrunde und Texte (Voraussetzung für on)
Reihenfolge laut Spec Abschnitt 9: gemeinsame TP2-Bausteine, Leistungsbeschreibung, Datenschutz, Oberflächen- und Mailtexte, Fragen an die Kanzlei, Uploads, on.
- Gemeinsame TP2-Bausteine (Block F: Widerrufsbelehrung, AVV) zuerst.
- Leistungsbeschreibung
public/vertragsunterlagen/zeiten-leistungsbeschreibung.html: Entwurf („ENTWURF – vor Livegang Rechtsrunde“ im Kopf). Wortlaut-Punkte der Gesamtprüfung: Nr. 4 Abs. 2 „sobald das Wartungs-Abo aktiv ist“; Nr. 1 Abs. 1 (wann die Vereinbarung bei Team-Aktivierung entsteht, siehe ZQ11); Nr. 3 Abs. 2 „oder stehen sollen“ streichen; Nr. 3 Abs. 3 „bestätigt den Einbau als abgeschlossen“ und „Tag, der nicht geschlossen ist“; Nr. 8 Abs. 7 zweiter Satz unklar; „Behalten nach Abschaltung“. Danach Fassung festlegen (Registerleistungsbeschreibung.versionundconsent.versionhochzählen, Tests nachziehen). - Datenschutz Portal § 6d (
docs/rechtliches/zeiten-datenschutz-6d-entwurf.md) inpublic/datenschutz.htmleinbauen, mit dem Ankerid="zeiten", plus der Satz in § 6 (Öffnungszeiten im Kundenauftrag). Er muss live sein, bevor der Link der Leistungsbeschreibung funktioniert. Danachscripts/build-legal-pdfs.sh datenschutz(nichtall), Prüfsumme nachziehen,test/legalTexts.test.jsundtest/zeitenRecht.test.jsanpassen. Wortlaut-Punkte: „Ihre Eingaben“ gegen „der Kunde“, „keine Werbung“ gegen ZQ6. - Widerrufsbelehrung für das 30-€-Produkt freigeben. Die Bestellseite muss genau
featureHaken('zeiten').belehrung()vor dem Knopf zeigen (Ruling R32), sonst belegt der Nachweis einen Text, den der Kunde nie sah. - Wertersatz-Satz (§ 357a Abs. 2 BGB) im Beginn-Haken der bezahlten Bestellung, wie bei News und Terminplaner (ZQ3): im Code ergänzt (Fixrunde, Fassung
2026-10-05); der Wortlaut bleibt Entwurf bis zur Rechtsrunde, danach die Fassung auf den Tag der Freigabe setzen (Pins intest/zeitenRegister.test.js). - Widerruf-Seite: in der Fixrunde ergänzt (
public/widerrufen.html,server/routes/abo.jsmitORDERS,FEATURE_OF_ORDER,orderLabel); ein zahlender Verbraucher, der widerruft, wird jetzt den Öffnungszeiten zugeordnet. Nichts mehr zu tun, außer beim Livegang die Seite einmal zu öffnen. - Fragen an die Kanzlei:
docs/rechtliches/zeiten-kanzlei-fragen.md(ZQ1 bis ZQ12) ins Kanzlei-Paket des Terminplaners als Q27 ff. übernehmen (AVV Funktionen per Haken, Behalten-Haken, Wertersatz, Haftung ohne Abo, Ende mit dem Abo, Mails, Einstellung bei Unternehmern, Website-Absatz, Vertragsrahmen ohne Abo, Preisangaben in der Hinweis-Leiste, Aktivierung durch das Team ohne Zustimmung, Pflichtinformationen als Haken und in K15). - K02/K03: Entwurf für den Block
funktionenindocs/rechtliches/zeiten-k02-k03-entwurf.md. Nach der Freigabe die Vorlagen ändern und die Pins nachziehen (test/mailTemplates.test.js,test/publicForms.test.jsFUNKTIONEN_SATZ). - Website-Absatz
docs/funktionen/website-datenschutz-absatz.md(Varianten A/B, Baustein Route und WhatsApp nur wenn die Leiste die Knöpfe zeigt): freigeben; der Einbau auf einer Kundenseite erst, wenn er in deren Datenschutzerklärung steht. - K15 für bezahlte Öffnungszeiten trägt keine Vertragsunterlagen und keine Belehrung als Anhang (dauerhafter Datenträger): entscheiden, ob nötig (Frage ZQ12 zusammen mit dem Haken
information). - Mailtexte K27 bis K30 und die Texte im Editor in deiner Textrunde: K28 sagt „deine Zeiten gelten normal“, obwohl die Seite an gesetzlichen Feiertagen „geschlossen“ zeigt, wenn du nichts änderst; K27-Variante „wieder eingeschaltet“ (ohne „per Ticket“ / „von Hand“); T19-Text spricht von „Einrichtung“;
disabledMessageschreibt „du“ klein; eigene Texte des Editors (Preishinweis, Vorschau); Betreffzeile K29 nennt „Wartungs-Abo“ (so gewollt). - Uploads: die Fassungen (Leistungsbeschreibung, Datenschutzerklärung) in WOMS „Rechtliches“ hochladen (Karte
leistungsbeschreibung-zeiten).
E. Offene Code-Punkte (Checkliste für die letzte Fixrunde)
Mit ☐ markiert, was noch im Code offen ist; die Fixrunde des Controllers kann einzelne schließen (dann hier abhaken).
Vor on nötig
- N1 Wertersatz-Satz im Beginn-Haken
features.zeiten.consent(server/config.js), Fassung2026-10-05, Pins intest/zeitenRegister.test.js(Fixrundeecf67d6). Der Wortlaut bleibt Entwurf (ZQ3). - N2 „Öffnungszeiten live“ in
ORDERS,FEATURE_OF_ORDERund im Bestell-Label vonserver/routes/abo.js, im Radioknopf vonpublic/widerrufen.htmlund in den Pins (widerrufen_html_radio, neuer Testwiderruf_zeiten);public/legal-form.jsbraucht keine Änderung, es liestdata-text(Fixrundeecf67d6). - N3 Rechtstexte aus den Entwürfen übernehmen (Abschnitt D, Nr. 2 und 3) und den Entwurfskommentar der Leistungsbeschreibung entfernen.
- N4 Entscheidung zu Anhängen in K15 für Zeiten (D, Nr. 10); K02/K03-Block (D, Nr. 8).
Härtung (vor on empfohlen, für den Pilot nicht nötig)
- N5 Website-Skript: im JSON-LD
<als\u003cschreiben (jsonLdText, Test); Kopf-Elemente bekommen bei Scroll ≥ Leistenhöhe ihren eigenen Inline-topzurück (UI-Prüfungfester_header_versteckt_beim_scrollen); dazu späte Platzhalter (Einzelseiten-Apps) über einen entprellten MutationObserver (Fixrundeaa9ee35). - N6 Abo-Abgleich: K30 gilt als offen, solange
aboEndeMailAtvordisabledAtliegt (das Zurücksetzen nachdisable()entfällt); K30 geht erst nach dem Ersatz-Ticket raus, scheitert es, wiederholt der nächste Lauf beides (K30 so höchstens einmal);activatedAtwird bei der Löschung geleert (Fixrundeecf67d6). - N7 Team: Sperre
zeiten-ersatz:<docId>gegen zwei Ersatz-Tickets (paralleles Abschalten und Abgleich);PATCH …/zeiten/teamnur fürsetup/active/disabled(409 sonst);createFeatureTicketmitfallbackDetailsfür das lange Ersatz-Ticket. - N8 WOMS „Ticket nachlegen“ bei Abo- oder Team-Zeiten ohne
ticketId: das Portal geht überholeZeitenNach(Fixrundeecf67d6). Offen bleiben die Texte „keine Zahlung vermerkt“ (bei gekauften Zeiten ohne Zahlungsvermerk) und der 409 der Abnahme („noch keine Öffnungszeiten eingetragen“). - N9 Löschen: in
loescheFunktionerst die Merker, dann das Dokument; fehlgeschlagene Löschung inretention.jsbeim nächsten Lauf wiederholen. - N10
heileZeitenintry/finally, wennactivateClosedTicketswirft.
Qualität (kann nach on)
- N11 Zeitlogik:
wechselListeum Schwellen (Ende minus 24 h und minus 7 Tage) ergänzen (Texte wie „bis Sonntag Mitternacht“ bleiben sonst den ganzen Sonntag stehen); Mitternachts-Einträge nicht zusammenfassen („heute“ hinkt sonst bis zu 10 Minuten nach). - N12 Oberfläche: Portal-Knopf auf dem Desktop 40 px hoch (Ziel 44 px); Relaunch-Stationsliste kann bei 721–780 px Fensterhöhe überlaufen (Schwelle prüfen).
Weitere Punkte der Fixrunde nach der Abschlussprüfung (erledigt)
activate()schreibt die Zeiten-Felder nur noch überextra(Abo-Rückkehr und Team-Aktivierung der Zeiten): News und Terminplaner brechen auch vor dem Schema-Skript nicht mehr mit „Unknown attribute“.- Die Einschalten-Route (
/api/funktionen/zeiten/einschalten) nimmt nur{ zustimmung }, nicht die Altform{ consent: true }ohne Fassungsprüfung. - Die Team-Aktivierung behält
kaufundunlockedByPurchase, wenn das Dokument vorher gekauft war (die Widerrufs-Zuordnung bleibt richtig;einbaubleibt dabei stehen, weil für gekaufte Dokumente das Nachholen nicht neu baut). - WOMS: „Leisten live – Einbau läuft“ nur bei
einbau=angestossen, sonst „Einbau läuft (Team setzt die Skript-Zeile von Hand)“ (919d96f). - Editor: die Bestätigung klebt unter der Kopfleiste und bleibt nach dem Speichern eines unteren Abschnitts sichtbar; Website-Skript: Links mit Zugangsdaten werden verworfen, die Adresse der Schnittstelle bestimmt nur das eigene Script-Tag.
F. Bewusste Abweichungen und Hinweise
- Schema der neuen
portalFeatures-Felder liegt inscripts/zeiten-setup.mjs(nicht infeature-setup.mjs), weil dessen Tests genau drei Attribute festschreiben. - Das Angebot liefert
GET /api/funktionenalszeitenauf oberster Ebene pluszeitenStatusje Projekt (die Spec nenntzeitenAngebotje Projekt); die Kachel entscheidet nachinklusiveundgrund(Ruling R20). - Der Editor einer abgeschalteten Funktion (
disabled) ist nur lesbar (Spec Z13 sagt „nie gesperrt“); die Website zeigt dann ohnehin nichts mehr. - Der Block
funktionenin K02/K03 ist bewusst nur ein Entwurf (Rechtstext mit Pins). - Schalter aus (
off):GET /api/public/zeiten/v1/<siteKey>antwortetaktiv: false; die Jobs für Abo-Abgleich laufen unabhängig vom Schalter (ein beendetes Abo muss abschalten und löschen können). - Wie im Terminplaner-Livegang: den Code zu einer ruhigen Zeit deployen.