Commit Graph
438 Commits
Author SHA1 Message Date
ClaudeandClaude Sonnet 5.5 d8e4d79891 Schema: Zustimmungsnachweis featureConsents im Skript feature-setup
scripts/feature-setup.mjs legt neben den portalFeatures-Attributen die Collection
featureConsents (nur Server-Key, ohne Rechte) mit 11 Attributen und den Indizes
idx_session und idx_project_feature an; --check meldet je fehlende Collection,
Attribut und Index eine Zeile "- <id>[.<key>] FEHLT", schreibt nichts und liefert
Exit-Code 1 bei Luecken. config.collections.featureConsents (Env
APPWRITE_COLLECTION_FEATURE_CONSENTS) und schemaKeys('featureConsents') in
test/support/schema.js ziehen mit. setup-abo-collections.mjs bleibt unveraendert.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 11:57:16 +00:00
ClaudeandClaude Sonnet 5.5 98fa03aad7 Stripe: Katalog Terminplaner-Einrichtung (149 €) und Checkout je Funktion aus dem Register
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 11:53:06 +00:00
ClaudeandClaude Sonnet 5.5 c584d220c8 Funktionen: Register config.features mit News- und Termine-Eintrag
config.features (news, termine) als reine Daten in config.js, config.ustHinweis,
config.funktionen als Alias mit Gettern auf features.news. Neu featureRegistry.js
(featureConfig, featureKeys, featureHaken mit Ueberschreib-Regel, oeffentlicheAnsicht);
FEATURE_KEYS, FEATURE_LABELS und DISABLED_MESSAGE in siteFeatures.js kommen aus dem
Register, Werte unveraendert.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 11:48:06 +00:00
ClaudeandClaude Sonnet 5.5 e2f50407a0 Terminplaner: Minutenjob in Verfall und Mailversand getrennt geschuetzt
fuehreAus nimmt { teil } und sperrt je job:teil; minutenJob startet Verfall
und Mailversand (Warteschlange plus Betriebspruefung) gemeinsam mit
Promise.all. Haengt ein Teil, laeuft der andere im naechsten Takt weiter
(verfallUebersprungen bzw. mailUebersprungen); uebersprungen gilt nur, wenn
beide Teile uebersprungen werden. Die Ueberlappungswarnung nennt den Teil,
das Fehlerlog behaelt minutenJob.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 11:41:00 +00:00
ClaudeandClaude Sonnet 5.5 aaed273b62 Funktionen: disable() idempotent, disabledReason, Schema-Skript feature-setup
disable() laeuft unter einer Sperre je Dokument und aendert ein schon
abgeschaltetes Dokument nicht mehr (disabledAt als Beginn der 30-Tage-Frist,
Grund und Notiz bleiben); nur Altbestand ohne disabledAt bekommt dieses Feld.
Neu: DISABLED_REASONS und der Parameter reason (Vorgabe team, unbekannt = 400),
disableCustomerFeatures reicht ihn durch, die Kundenloeschung nutzt
kunde_geloescht. activate() leert zusaetzlich disabledReason und aboEndeMailAt
und laesst zahlungMeldung unberuehrt.

scripts/feature-setup.mjs legt portalFeatures.disabledReason, aboEndeMailAt und
zahlungMeldung idempotent an (--check meldet Luecken mit Exit 1);
schemaKeys('portalFeatures') zieht die Schluessel mit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 11:33:17 +00:00
ClaudeandClaude Sonnet 5.5 39225594e5 Terminplaner: Status-Route fuer das Team
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 11:24:02 +00:00
ClaudeandClaude Sonnet 5.5 4601c5ef3b Terminplaner: Tagesjob-Meldung, Betriebe-Zaehlung und Bericht
meldeTagesjob meldet am Ende des Tagesjobs ueber den Melder aus A10a2 die Vorfaelle
tagesjob (Fehler oder Abbruch), deckel (Loeschdeckel an 3 Tagesjobs in Folge) und
betriebe (ab 20 aktiven Betrieben, D8) und merkt letzterTagesjob (nur Zaehlungen).
taeglicherJob liefert geloescht und aktiveBetriebe, tagesbericht haengt
"n aktive Betriebe" an.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 11:17:07 +00:00
ClaudeandClaude Sonnet 5.5 689a21f9ac Terminplaner: Betriebspruefung mit Abkuehlzeit fuer die Team-Mail
pruefeBetrieb (neu: termine/betrieb.js) prueft am Ende jedes Minutenjobs
Mailbudget (ab 70 %), Warteschlange (aeltester faelliger Eintrag > 10 Min
ueberfaellig, neu outbox.warteschlangeAlter) und Anmeldepause
(pausiertBis). Der gemeinsame Melder meldeVorfall schreibt je Schluessel
hoechstens stuendlich ein Warnlog und schickt die Team-Mail T20 beim
Beginn und danach fruehestens nach 6 Stunden; Lesefehler und Mailfehler
stehen nur im Log. T20 steht jetzt auch im Test der Team-Fusszeile.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 11:01:16 +00:00
ClaudeandClaude Sonnet 5.5 3a3319ec14 Terminplaner: Team-Mail-Vorlage T20 Betriebsmeldung
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 10:26:08 +00:00
ClaudeandClaude Sonnet 5.5 43b3caddde Terminplaner: veraltete G01 verworfen, Index bookingId
Eine G01, die erst nach holdMinutes + 1 Minute faellig wird, ist mit verfallenem Link
nutzlos: sie wird nicht mehr gesendet, sondern verworfen (kein Transportaufruf, kein
Budgetplatz, Felder geleert, kein Zustellfehler, raeumeAuf loescht sie nach 48 Stunden).
Neuer Index idx_booking auf termineOutbox fuer zustellFehler und verwerfeWartende;
verworfeneG01() zaehlt seit Prozessstart.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 10:21:25 +00:00
ClaudeandClaude Sonnet 5.5 36b94c3035 Terminplaner: Mail-Warteschlange begrenzt und nach Vorrang geordnet
verarbeite liest nicht mehr alle wartenden Eintraege, sondern je Klasse
(vorrang, normal, nachrangig) eine begrenzte Liste (config.termine.mailListe,
Standard 100) mit select und orderAsc(naechsterVersuch). Bei Pause oder
leerem Gesamtbudget endet der Lauf ohne Abfrage, bei erreichter Reserve
entfaellt die nachrangige Klasse. Funktionen mit ausgeschoepftem Kontingent
kommen in eine Ausschlussliste (hoechstens 90 Werte); hoechstens vier weitere
Runden je Klasse, damit keine Funktion hinter einer vollen verhungert.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 10:13:26 +00:00
ClaudeandClaude Sonnet 5.5 4d96565240 Terminplaner: Empfaenger-Kappe ueber Betriebe (G01, Freitext in G04/G06)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 10:03:39 +00:00
ClaudeandClaude Sonnet 5.5 c35711caad Terminplaner: Mailkontingent je Funktion, Vorrang-Reserve und kleinere Haltungsgrenze
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 09:54:11 +00:00
ClaudeandClaude Sonnet 5.5 978722023f Terminplaner: Zellen-Sweep seitenweise ueber idx_bis mit Deckel
raeumeVerwaisteZellen(now, { deckel = config.termine.zellenDeckel }) liest
Zellen mit bis < jetzt - 1 Tag in Seiten zu 100 ueber idx_bis (aelteste
zuerst, ohne Cursor neu gelesen), gruppiert je Ressourcensperre mit Map und
loescht unter der Sperre nur, was dort noch dieselbe Buchung hat und noch alt
ist. Die Buchungen werden nicht gelesen. Der Lauf endet am Deckel (5000,
gedeckelt wird im Tagesjob gezaehlt und im Log gewarnt), bei einer leeren
Seite oder einer Seite ohne Erfolg; der erste Fehler wird am Ende geworfen.
ungueltigeZellen prueft zuerst das Zeitfenster (auch fuer belegeZellen).
verwaisteZellen, alleZellen und ALLE_ZELLEN_MAX entfallen.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 09:44:47 +00:00
ClaudeandClaude Sonnet 5.5 d040a55f89 Terminplaner: CSV-Export seitenweise gestreamt
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 09:32:14 +00:00
ClaudeandClaude Sonnet 5.5 a1732613c9 Terminplaner: Loeschung abgeschalteter Funktionen seitenweise, Rest an Folgetagen
loescheAbgeschaltete liest je abgeschalteter Funktion (disabledAt vor 30 Tagen) Seiten zu 100
(neu buchungen.ersteBuchungen: nur $id, limit, nie Gastfelder) und loescht sie ueber arbeiteSeiten
samt Zellen, bis die Seite leer ist. Die Funktion wird nach jedem Lesen einer Seite und alle 50
Buchungen frisch geprueft (nochAbgeschaltet); wird sie wieder eingeschaltet, endet die Loeschung
fuer sie sofort. Deckel config.termine.loeschDeckel je Funktion: am Deckel bleibt die Funktion
disabled mit altem disabledAt, eine Warnung ohne Kennungen steht im Log, der naechste Tag macht
weiter, die uebrigen Funktionen kommen im selben Lauf dran. Die Einstellung (termineConfig) wird
nur nach leerer Seite ohne Fehler und mit letzter Pruefung unter termine-cfg:<id> geloescht.
loescheAbgeschalteteFunktionen liefert { funktionen, buchungen, gedeckelt }; taeglicherJob traegt
gedeckelt.abgeschaltet getrennt vom Loeschzaehler ein (Tagesbericht: Loeschlaeufe am Deckel).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 09:24:33 +00:00
ClaudeandClaude Sonnet 5.5 9b4305e5de Terminplaner: Aufbewahrungs-Loeschung je Funktion mit Deckel, Sicherheitsnetz und Bericht
erledigt/nichterschienen werden jetzt je Funktion (portalFeatures termine, active|disabled)
nach deren aufbewahrungTage seitenweise geloescht; beide Status teilen sich den Deckel
loeschDeckel der Funktion, alle Schritte eines Laufs zusammen loeschDeckelGesamt (neu,
Standard 20000). Ein Sicherheitsnetz loescht erledigt/nichterschienen ohne Funktionsfilter
nach 365 Tagen (Buchungen ohne Funktionsdokument, unlesbare Einstellung). Der Tagesbericht
nennt "Loeschlaeufe am Deckel: n, Rest folgt an den nächsten Tagen" nur bei gedeckelt > 0.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 09:09:48 +00:00
ClaudeandClaude Sonnet 5.5 5c95dfc322 Terminplaner: Aufbewahrungs-Loeschung seitenweise (Grundlagen, verfallen/abgesagt/abgelehnt)
loeschKandidaten liest eine Seite (Standard 100, aelteste Bezugszeit zuerst, optional je Funktion)
ohne Gastfelder; die Frist steht in der Abfrage. arbeiteSeiten (Seite lesen, bearbeiten, neu lesen)
endet bei leerer Seite, am Deckel (config.termine.loeschDeckel, 2000 je Status und Lauf, Rest an den
Folgetagen, gezaehlt als gedeckelt) oder bei einer Seite ohne Fortschritt. verfallen, abgesagt und
abgelehnt laufen darueber, unter der Buchungssperre werden Status und Bezugszeit frisch geprueft.
taeglicherJob liefert gedeckelt getrennt vom Loeschzaehler. Neue Indizes idx_status_ends und
idx_status_updated auf termineBookings (scripts/termine-setup.mjs legt sie an).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 08:55:32 +00:00
ClaudeandClaude Sonnet 5.5 2dd9c0dec7 Appwrite-Abfragen: select, notEqual, countDocuments und Nachbau dazu
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 08:38:21 +00:00
ClaudeandClaude Sonnet 5.5 8c1055e8a0 Kundenansicht: Terminplaner-POSTs nur noch ueber eine explizite Liste
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 08:34:29 +00:00
ClaudeandClaude Opus 5.5 a72380cc8b Terminplaner TP2 Verkauf: Umsetzungsplan (Bloecke A, B, E, C, D, F und Livegang-Checkliste G)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 20:04:49 +00:00
ClaudeandClaude Opus 5.5 6ed0e3bcaf Terminplaner TP2 Verkauf: Design mit den Entscheidungen D1–D8 des Inhabers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 18:17:11 +00:00
ClaudeandClaude Opus 5.5 3a0b0089dd Terminplaner: eigener Betreff fuer die Ablehnung einer Anfrage (G04)
Eingang (G03) und Ablehnung (G04) hatten denselben Betreff "Ihre Terminanfrage bei {betrieb}".
G04 heisst jetzt "Ihre/Deine Terminanfrage bei {betrieb} – leider abgelehnt".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 17:40:52 +00:00
ClaudeandClaude Opus 5.5 5077dd5a20 Mitarbeiter-Zugang: --ohne-buckets (Server-Key ohne buckets-Scope, Buckets dann in der Konsole)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 11:10:09 +00:00
ClaudeandClaude Opus 5.5 10b393687c Mitarbeiter-Zugang: Review-Punkte (fail closed, Kunden-Konto bleibt, Probelauf robuster)
- removeEmployeeEntry: nur 404 heisst "kein Konto", jeder andere Fehler bricht ab
- Mitarbeiter loeschen (Admin-Panel): Konto ohne Mitarbeiter-Label (Kunde mit
  altem employees-Eintrag) bleibt bestehen, nur der Eintrag geht
- Mitarbeiter bearbeiten gibt nie automatisch das Label (der Eintrag kann von
  einem Kunden stammen); nur Neuanlage bekommt "mitarbeiter"
- --rechte: --offen-lassen <ids>, unlesbare Listen als Fehler statt Abbruch
  (--anwenden verweigert dann), --sicherung <datei> + docker-cp-Hinweis,
  Bucket-Einstellung transformations wird mitgeschickt
- getEmployeeByEmail entfernt (unbenutzt)
- Tests: write/users-unverified, zweiter Lauf idempotent, >100 Dokumente,
  Loeschen mit Kunden- und Mitarbeiter-Konto

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 11:00:48 +00:00
ClaudeandClaude Opus 5.5 2659385205 Mitarbeiter nur noch per Label: Kunden-Konten bekommen keinen Team-Zugang
Kunden haben Konten im selben Appwrite-Projekt wie das Ticketsystem. Bisher
galt als Mitarbeiter, wer einen employees-Eintrag hatte - den legte das
Ticketsystem beim Login jedes Kontos automatisch an, und jedes angemeldete
Konto konnte ihn auch selbst anlegen. Damit kam ein Kunde ueber /api/team an
Chats, Kundenansicht, Angebote und Finanzen.

- staffLabels.js: Mitarbeiter = Label "mitarbeiter" oder "admin" (setzt nur
  der Server-Key)
- Team-Eingang (requireStaffJwt) und Portal-Login-Sperre nur noch per Label;
  kein Abgleich ueber employees-Eintrag oder Mail mehr
- Portal-Login: Konto-Abruf gestoert -> 503 fuer alle (fail closed)
- Mitarbeiter anlegen/bearbeiten setzt das Label "mitarbeiter"
- scripts/mitarbeiter-zugang.mjs: --status (markiert employees-Eintraege von
  Kunden), --label, --eintrag-loeschen (nur Eintrag, nie das Konto), --rechte
  (Probelauf, --anwenden mit Sicherung, --zurueck): any/guests/users ->
  label:mitarbeiter + label:admin in Collections, Buckets und bei Dokument-/
  Datei-Sicherheit auch einzelnen Dokumenten und Dateien

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 10:54:09 +00:00
ClaudeandClaude Opus 5.5 be7f9b1aa3 Terminplaner: Test an zweiten absoluten Import von funktionen.js (/geraete.js) angepasst
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 08:18:21 +00:00
ClaudeandClaude Opus 5.5 5bd8ee8457 Terminplaner: Abschluss – kein "null" in abgeschalteten Einstellungen, Kommentar zu disabledAt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 08:17:44 +00:00
ClaudeandClaude Sonnet 5.5 f134ed0032 Terminplaner: Abschluss – Spezifikation und Rechtshinweise an den Stand des Codes angeglichen
- Spezifikation: Abweichungen aus den Abschlussreviews nachgezogen (kontakt_url, kein ETag und formMinSekunden,
  Token-Endpunkte unter /termin/*, Zellen bis blockEndsAt, Outbox-Fristen, Reihenfolge Buchung vor Zellen,
  Widerrufsfrist nach §§ 187/188/193 BGB, Abwesenheit schlägt Sonderöffnung, Kunden-API vollständig,
  Impressum-Adresse) sowie R53 (Wartezeit vor dem Absenden), R54 (Widerruf als Knopf, im Knopfmodus
  dauerhaft) und R55 (Widerruf bei jeder Verbraucher-Buchung, auch Anfragen).
- Neuer Abschnitt "Betrieb und Livegang – Hinweise" in 14 (SESSION_SECRET nie rotieren, Modus off stoppt die
  Löschjobs, Zellbereinigung vor TP2 begrenzen, Warteschlange listet jede Minute alles Fällige).
- Plan: Impressum-Link auf https://webklar.com/impressum.
- Rechtshinweise: "offen 1" durch R14 erledigt, Haken für vorzeitigen Beginn nach R29/R31, Widerrufshinweis
  nach R55 und G02; offene Punkte zu Abo-Ende und Knopfmodus in den Datenschutz-Entwürfen.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:44 +00:00
ClaudeandClaude Sonnet 5.5 794a63c0d7 Terminplaner: Abschluss – Client (Formular-Token, Widerruf prominent, Telefonlink, Einbau-Code, G02)
- R53: Das Widget wartet vor jedem Absenden, bis das Formular-Token formMinSekunden plus 0,5 s alt
  ist ("Einen Moment …", Knopf gesperrt); gilt nach dem Neuladen der Konfiguration und beim Wiederholen
  nach "neu_laden". Kein stilles Erfolgs-201 ohne Buchung mehr.
- R54: "Vertrag widerrufen" im Fuß ist ein zweiter Knopf (44 px). Im Knopfmodus lädt das Widget die
  Konfiguration beim Laden der Seite (ein Abruf) und zeigt bei Widerrufsrecht dauerhaft einen zweiten
  Knopf "Vertrag widerrufen" neben dem Buchungsknopf, der den Dialog beim Widerrufsformular öffnet.
- Telefonlink im Widget und auf der Gästeseite: Text mit Buchstaben oder Mehrfachangaben wird nie zum
  tel:-Link, "(0)" hinter der Landesvorwahl entfällt.
- Portal, Einstellungen: Kasten "Einbau auf deiner Website" mit Einbau-Code und Kopierknopf; Hinweistexte
  zum Widerruf passen zu R55 (auch Anfragen).
- G02: Widerrufssatz nennt, dass der Knopf bis zum Beginn des Termins gilt und danach das Formular auf der
  Website oder die E-Mail an den Betrieb.
- Einbau-Anleitung angepasst (siteKey und Code im Portal, Knopfmodus, Checkliste); Tests und Playwright.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:44 +00:00
ClaudeandClaude Sonnet 5.5 bd65c9dc58 Terminplaner: Abschluss – Server (Widerruf auch bei Anfragen, Gastdaten löschen vollständig, formMinSekunden)
- R55: Widerrufsbelehrung, Anschrift-Pflicht und Knopf "Vertrag widerrufen" gelten für jede
  Verbraucher-Buchung mit sichtbarer Leistung, auch Anfragen (zeigtWiderruf); der Nachweis
  hält die Belehrung auch bei Anfragen fest. Damit bleibt die Annahme einer Anfrage nie mehr
  still ohne G02.
- "Gastdaten löschen" leert auch absageGrund und löscht noch nicht versandte Mails der Buchung
  (neu: verwerfeWartende in der Warteschlange).
- R53: GET /:siteKey/config nennt formMinSekunden.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:44 +00:00
ClaudeandClaude Sonnet 5.5 4be886a4de Terminplaner: Portal-Ansicht – Fokus und aria-busy
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:44 +00:00
ClaudeandClaude Sonnet 5.5 3ad056f261 Terminplaner: Portal-Ansicht Einstellungen – Nachbesserungen
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:44 +00:00
ClaudeandClaude Sonnet 5.5 0b75b31009 Terminplaner: Portal-Ansicht Leistungen, Team, Einstellungen
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:44 +00:00
ClaudeandClaude Sonnet 5.5 650919b022 Terminplaner: Portal-Ansicht – Nachbesserungen (2/2)
- Annehmen mit Rueckfrage in der Seite (schliesst den Vertrag, schickt G02)
- Offene Anfragen: alle bis Ende des Buchungszeitraums (Fenster zu je 62 Tagen,
  hoechstens 6 Aufrufe), passend zur Zahl auf Kachel und Banner
- Meldung ins Bild geholt, Fehler mit Fokus; einzige Live-Region
- Netzwerkfehler auf Deutsch; Antwort einer frueheren Website erscheint nie
  unter der neuen (Zaehler je Aufruf); Datumssprung nur mit echtem Tag
- Ende um Mitternacht als 24:00, Statusfilter nach Eintragen auf Alle,
  abgeschaltet ohne Einstellung mit Export-Link, dunkles Datumsfeld
- Playwright: Zeitzone New York/Berlin, ferne Anfragen, Projektwechsel,
  Meldung im Bild, Datumssprung, abgeschaltet ohne Einstellung

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:44 +00:00
ClaudeandClaude Sonnet 5.5 9c07f6a8c5 Terminplaner: Portal-Ansicht – Nachbesserungen (1/2: Module getrennt)
public/termine.js in Huelle und Module zerlegt, Verhalten unveraendert (R48):
termine-dom.js (Helfer ohne Zustand), termine-tab-termine.js (Liste, Kopf, Zeilen),
termine-aktionen.js (Aktionen mit Rueckfrage), termine-formulare.js (Uhrzeiten,
Termin eintragen, Zeit sperren). Reiter bekommen Zustand und aktuell() nur ueber
ctx; die Huelle haengt sie ueber die Registry REITER ein. Statiktest prueft alle
public/termine*.js.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:44 +00:00
ClaudeandClaude Sonnet 5.5 43e4826ae3 Terminplaner: Portal-Ansicht, Kachel, Termine
Kachel in Funktionen (Kommt bald / Aus / Aktiv mit Anfragen-Zahl / Abgeschaltet),
Ansicht #termine als Unterseite von Funktionen: Projektauswahl, Vorlagenauswahl
beim ersten Oeffnen, Reiter-Geruest (Platzhalter fuer Leistungen, Team & Plaetze,
Einstellungen) und der Reiter Termine mit Tag/Woche/Monat, Filtern, Aktionen mit
Rueckfragen in der Seite, Termin eintragen und Zeit sperren.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:44 +00:00
ClaudeandClaude Sonnet 5.5 70940e02c8 Terminplaner: Gaesteseiten – Nachbesserungen
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:44 +00:00
ClaudeandClaude Sonnet 5.5 734e397e73 Terminplaner: Gaesteseiten Bestaetigen, Verwalten, Widerrufen
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:44 +00:00
ClaudeandClaude Sonnet 5.5 781eccb2d6 Terminplaner: Einbau-Skript – veraltetes Angebot
Fehler an leistung/ressource (beim Absenden und bei Tage/Zeiten) laden zuerst die Konfiguration
neu (ladeNeu): gilt die Auswahl nicht mehr, beginnt die Strecke von vorn mit Hinweis; sonst
steht die Meldung des Servers. Knopfmodus: Aufbaufehler zeigt den Ausweichtext statt "Wird
geladen".

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:44 +00:00
ClaudeandClaude Sonnet 5.5 4465ac7b94 Terminplaner: Einbau-Skript – Nachbesserungen
429 ohne Schleife (Meldung und Erneut-versuchen-Knopf, Formulare bleiben stehen), Schriftfarbe
auf der Betriebsfarbe mit mindestens 4,5 : 1, AGB-Link aus der oeffentlichen Konfiguration
(betrieb.agbUrl), Haken starten bei geaenderter Auswahl ohne Haken, Fehler ohne Feld nicht
verschluckt, Konfiguration fail closed, ladeNeu fuer Neuladen und neu_laden, Tastatur und
Fokus (Modifikatoren, Monatspfeile, Belehrungstext), Aufraeumen. UI-Testserver: Timer,
offene Verbindungen, Hinweis auf sessionCookie.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:44 +00:00
ClaudeandClaude Sonnet 5.5 5fef7e47f0 Terminplaner: Einbau-Skript, Demo und Einbauanleitung
public/embed/termine.js: Buchungs-Widget fuer Kundenwebsites (inline und Knopf mit dialog,
Monatsraster nach APG, Haken-Texte und Knopf aus der Konfiguration, Honigtopf kontakt_url,
Widerrufsfunktion, Konfiguration nach 100 min neu, Ausweichtext bei Fehlern). Rechnet nie mit
Datum oder Zeitzone des Browsers. Dazu Demo-Seite, Einbauanleitung fuer Mitarbeiter, statischer
Test und Playwright-Skript mit wiederverwendbarem UI-Testserver (test/ui/termineTestServer.mjs).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:43 +00:00
ClaudeandClaude Sonnet 5.5 bb45d35ec7 Terminplaner: Kunden-Schnittstelle – Nachbesserungen
- GET /zeiten?ohne=<Buchung>: Leistung, Dauer und Person der Buchung wie beim
  Verschieben (verschiebeZeiten exportiert), unbekannte/fremde/Sperre 404 (R42)
- Schreib-Begrenzung als gemeinsamer Baustein (writeLimiter.js) fuer News und
  Terminplaner statt kopierter Funktion (R43)
- Unlesbares Einstellungs-JSON: Kontext traegt die echte Version, Speichern
  ueberschreibt den Schaden statt dauerhaft 409
- U+FEFF als Escape statt als rohes Zeichen
- Tests: Mandantentrennung mit echtem zweitem Kunden, R42, Limiter, kaputtes JSON

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:43 +00:00
ClaudeandClaude Sonnet 5.5 e3e198fb1a Terminplaner: Kunden-Schnittstelle
/api/termine: Einstellungen (Vorlage, PATCH mit Version, Feed-Link), Buchungen
(Liste, Zeiten, von Hand, Sperre, Aktionen), CSV-Export, Protokoll der
Kundenansicht. Pflichtangaben fuer Gaeste (Telefon immer, Anschrift bei
Widerrufsbelehrung) in normalisiereEinstellung, Entwurf aus Vorlagen,
kontextPerSiteKey ohne Pflichtangaben nicht buchbar; speichereEinstellung
nimmt eine Funktion unter der Sperre.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:43 +00:00
ClaudeandClaude Sonnet 5.5 9e8fd33713 Funktionen: Terminplaner als zweite Funktion (Team-Route, Kundenansicht)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:43 +00:00
ClaudeandClaude Sonnet 5.5 ae1886c030 Terminplaner: Zaehler je IP getrennt und Abgelaufene zuerst, Notantwort beim Schreiben, Pruefung aller Antworten auf interne IDs
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:43 +00:00
ClaudeandClaude Sonnet 5.5 2b0c05b8e9 Terminplaner: oeffentliche Schnittstelle v1 mit Missbrauchsschutz
Router /api/public/termine/v1 (config, tage, zeiten, buchungen, widerruf, Token-Seiten /termin/*, Kalender-Abo) mit
eigenem 16-KB-Parser und Fehlermiddleware, CORS nach Herkunft, Honeypot und Formular-Token, Grenzen je IP (IPv6 je /64),
siteKey und Adresse in limits.js, Mindestantwortzeit (TERMINE_MIN_ANTWORT_MS) und 10-Sekunden-Cache fuer tage/zeiten.
Vor dem globalen express.json eingehaengt; /api/public/ ist vom Kundenansicht-Waechter ausgenommen.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:43 +00:00
ClaudeandClaude Sonnet 5.5 43ac05aa06 Terminplaner: Jobs lesen abgeschaltete Funktionen vor dem Löschen neu, Tagesbericht im Log
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:43 +00:00
ClaudeandClaude Sonnet 5.5 485ff3bc15 Terminplaner: Hintergrund-Jobs
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 08:17:43 +00:00
ClaudeandClaude Opus 5.5 efe17551c2 Spec/Plan: Zustimmung vorzeitiger Beginn und Widerrufsfrist nach §§ 187/188/193 BGB (Rulings R29, R31)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 08:17:43 +00:00