Next reicht Route-Handlern einen Proxy um NextRequest. undici 7 (Node 24)
prueft private Felder (#state), die ein Proxy nicht besitzt; new Request(request)
warf "Cannot read private member #state" und jede /api/auth-Anfrage endete
lokal mit 500. Produktion (Node 22, undici 6) war nicht betroffen.
withClientIp baut die Anfrage jetzt aus URL, Methode, Headern und Body neu.
Regressionstest mit einem Proxy wie in Next.
- CF-Connecting-IP gilt nur noch als oeffentliche Unicast-Adresse
(nicht 0/8, 10/8, 100.64/10, 127/8, 169.254/16, 172.16/12,
192.168/16, 240/4, Broadcast, ::, ::1, fc00::/7, fe80::/10,
::ffff:privat); sonst gilt die Gegenstelle.
- X-Real-IP ohne X-Forwarded-For nur noch ausserhalb von Produktion;
in Produktion ergibt das "unknown".
- Neuer Helfer headersWithClientIp, von withClientIp und der
Admin-Session-Pruefung genutzt: ein vom Client gesendeter
x-artista-client-ip-Wert wird nie geglaubt.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Bisher setzte jeder SMTP-5xx die Mail sofort auf FAILED, auch Anmelde-
und Richtlinienfehler (EAUTH, EMESSAGE, 552). Ein kaputtes SMTP-Secret
haette alle Buchungs- und Zahlungsmails verworfen, ohne Rueckweg
(dedupeKey verhindert erneutes Einreihen).
Endgueltig ist jetzt nur EENVELOPE mit 550, 551, 553, 556 oder 5xx mit
Status 5.1.x. Alles andere bleibt PENDING und wird bis
MAX_EMAIL_ATTEMPTS wiederholt.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
consumeRateLimit bekommt IPv6-Adressen als /64-Praefix (rateLimitSubject):
ein Anschluss hat meist ein ganzes /64 und koennte sonst durch Adresswechsel
jedes Limit umgehen. better-auth bekommt weiter die einzelne Adresse und
normalisiert sie selbst auf /64 (ipv6Subnet, Standard 64).
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Traefik vertraut seit 2026-10-12 den weitergeleiteten Headern aus
Cloudflare-Netzen. Wer eine eigene Cloudflare-Zone auf den Server zeigen
laesst, konnte damit X-Real-IP und den ersten X-Forwarded-For-Eintrag
faelschen und die Rate-Limits (Buchung, Kontakt, Login, 2FA) umgehen.
- clientIp: Gegenstelle ist der letzte X-Forwarded-For-Eintrag (von Traefik
angehaengt); CF-Connecting-IP nur, wenn sie eine Cloudflare-Edge ist.
- better-auth liest nur noch x-artista-client-ip, den der Auth-Endpunkt
per withClientIp setzt (ein mitgeschickter Wert wird ersetzt).
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Eine Mail an eine Adresse ohne Mailserver (SMTP 556, nullMX) wurde bis zu
8-mal erneut versendet und liess jeden Worker-Lauf mit Exit-Code 1 enden;
das SMTP-Fehlerlog enthielt dabei die Empfaengeradresse.
- SMTP-Antworten 5xx markieren die Mail sofort als FAILED, 4xx und
Verbindungsfehler bleiben wiederholbar.
- Adressen werden aus Log und lastError entfernt.
- Worker-CronJob: backoffLimit 0 (kein zweiter Pod je Fehlschlag) und
ttlSecondsAfterFinished 1 Tag, damit Fehler-Pods nicht stehen bleiben.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Gleiche Prüfung wie bei der Buchung: mindestens 6 Zeichen, nur Ziffern, Leerzeichen und + ( ) / -.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Vor dem 01.11.2026 gilt dann der Early-Bird-Preis. Fehlt eine Freigabe, bleibt die Vorschau.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Neuer Abschnitt nach den Fragen, im Menü als Erstgespräch. Anfrage geht als E-Mail an die Veranstalter-Adresse (Admin) bzw. ADMIN_NOTIFY_EMAIL, sofort zugestellt, sonst über den Worker wiederholt. Gleicher Schutz wie die Buchung: nur JSON von der eigenen Seite, Rate Limit (5/h je IP), Prüfung auf dem Server, Honeypot gegen Bots, doppeltes Absenden ergibt eine Mail. Keine automatische Mail an die angegebene Adresse (sonst Missbrauch für Spam an Dritte).
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Befunde aus dem Sicherheits-Review des vorherigen Commits:
- Gerät eine Buchung in "Prüfung nötig" (Rückbuchung, Doppelzahlung ...),
wird der Stripe-Plan beendet und offene Rechnungen storniert. Nach
Bestätigung legt der Worker einen neuen Plan für die offenen Raten an.
Vorher zog Stripe auch bei Buchungen in Prüfung weiter ein.
- Vor dem Anlegen wird bei Stripe nach einem laufenden Plan der Buchung
gesucht; der Idempotenzschlüssel enthält Generation und Start. Verhindert
einen zweiten Plan nach verlorener ID und die Rückgabe des alten,
beendeten Plans nach einer Prüfung.
- Start bei bereits verstrichener Fälligkeit deterministisch am nächsten
9-Uhr-Termin, letzte Rate bleibt am Stichtag.
- Rückbuchungs-Event meldet die betroffene Buchung zurück.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
- ReviewsSection (Server Component) mit Durchschnitt, zugaenglichen
Sternen, Initialen statt Profilbildern, relativer Zeit, Links zur
Rezension und zum Maps-Eintrag sowie Hinweis "Rezensionen von Google"
- lange Texte optisch gekuerzt, "Weiterlesen" mit aria-expanded
- ohne Daten ausgeblendet; in Entwicklung/Staging ein Einrichtungshinweis
- Laden parallel zu loadPublicPage, Fehler blenden nur den Abschnitt aus
- Links aus der API-Antwort nur zu HTTPS-Google-Hosts (safeGoogleUrl)
- Linkstile und Browser-Oberflaechen (Scrollbar, Caret, Unterstreichung)
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>