Naechste Session

Aktuelle Aufgaben und naechste Schritte

Session Aufgaben Aktuell Todo

Naechste Session

Datum: Naechste Session

Status: LIVE seit 01.02.2026 | Test-Modus deaktiviert | Workflow: DEV → STAGING → PRODUCTION

Letztes Update: 13.06.2026 (Login-Sicherheit & Passwort-Reset)

WICHTIG: Production = Master! Von Production wird auf DEV/STAGING deployed. Nur bei Fixes direkt auf Production deployen!


Session 13.06.2026 — Login-Sicherheit & Passwort-Reset

Direkt auf Production (Fix). MU-Plugin web/app/mu-plugins/webideas24-security.php (nicht im kurs-booking-Repo, vom Deploy-Script nicht erfasst → manuell deployt, Backups auf Server).

Erledigt

  • Login-Problem gelöst: Admin-Login (info@web-werkstatt.at) schlug trotz korrektem Passwort fehl. Ursache: IP-basierte Login-Sperre (5 Fehlversuche/15 Min) im MU-Plugin, kombiniert mit generischer Meldung, die jede Sperre als „Anmeldedaten ungültig" tarnte. Da IP-basiert → blockierte alle Konten von derselben IP (auch der Kunden-Test-Login). Jeder weitere Versuch verlängerte die Sperre. Gelöst: Sperren gelöscht (wp transient delete --all + wp cache flush), frisches Passwort gesetzt + am Hash verifiziert.
  • Patch 1 — ehrliche Meldung: Eine aktive Sperre zeigt jetzt „Zu viele Anmeldeversuche…" statt „Passwort falsch" vorzutäuschen.
  • Patch 2 — Passwort-Reset im WP-Backend deaktiviert: allow_password_reset=false + Redirect der Lost-Password-Seite + Link versteckt. Recovery nur per WP-CLI (dokumentiert in CLAUDE-NOTES.md). Kundenportal unberührt (eigene App). Erledigt damit auch den Punkt „hässliche Reset-Mail mit interner IP".
  • Wichtig gelernt: OPcache ist auf Production aktiv → Änderungen an MU-Plugins/PHP werden erst nach docker restart wp-islandpferde wirksam (CLI-opcache_reset reicht nicht).

Offene Aufgaben

Task Prio
Kundenportal-Reset prüfen & aufhübschen — Self-Service-Reset dort BEHALTEN, aber Flow + Mail prüfen und branden. Eigene App portal.islandpferde-melanieworbs.de, NICHT WordPress → separater Schritt. mittel

Session 28.05.2026 — Wartung, Versions-Audit & Sicherheits-Check

Keine Feature-Entwicklung, sondern Audit/Doku/Infrastruktur. Production unangetastet.

Erledigt

  • React-19-Frage geklaert: WP 7.x bringt React 19. ALLE Custom-Plugins (kurs-booking, SEO Elementor Sync, Webwerkstatt Optimization, WP Menu Manager, Kurs Admin Notifications) sind nicht betroffen — PHP + Vanilla/jQuery, kein React/Gutenberg. Live verifiziert.
  • composer.json: Mindest-PHP >=8.0>=8.4 (committet + gepusht, Deploy noch offen).
  • Live-Versionen verifiziert: Production = WordPress 6.9 + PHP 8.4.17 (lokaler Snapshot war veraltet auf 6.8.3).
  • WP Menu Manager Versions-Drift behoben: live lief 2.8.0, Repo nur 2.0.0 → lokale Quelle auf 2.8.0 gebracht (Backup vorhanden).
  • sevDesk geprueft: Q1-2026-Breaking-Changes (render/changeParameter/sendByWithRender) betreffen uns nicht (nutzen /render nur als Trigger, PDF via unveraendertes /getPdf).
  • Volles Production-Backup gezogen (DB + Files + Alt-Schema) nach backups/production_20260528_200228/.
  • Neue Doku im docs-Repo (kurs-booking-docs, alles gepusht): REACT-GUTENBERG-LEITFADEN.md, UPDATE-CHECKLISTE.md + viele Bestands-Dokus nachgezogen. docs-Repo war serverseitig weg → neu angelegt.
  • Global: neuer Skill security-compromise-check (~/.claude/skills) + taeglicher Cron (13:30). Compromise-Check ueber 5 Server + Workstation: keine IOCs.

Offene Aufgaben (Details: UPDATE-CHECKLISTE.md im docs-Repo)

Task Prio
PHP-Image 8.4.17 → 8.4.21 (Security) hoch
WordPress 6.9 → 7.0 (erst Staging testen!) mittel
composer.json-Anhebung DEV→Staging→Production deployen mittel
backup_pre_migration-Schema aus Live-DB droppen (Dump liegt vor) niedrig
MEC-Altsystem deinstallieren (deaktiviert, nicht fuers Design noetig) niedrig
Versions-Drift-Ursache klaeren (wie kam WP Menu Manager live auf 2.8.0?) mittel

Session 08.04.2026

Erledigt - Hotfix: OMGF Font-CORS-Errors (Altlast Subdomain-Umzug)

Problem: Browser-Konsole zeigte auf Production Cross-Origin Request blocked + NS_ERROR_UNEXPECTED fuer alle Google-Fonts aus dem OMGF-Plugin-Cache. Grund: Die OMGF-Stylesheets hatten //kurse.islandpferde-melanieworbs.de/wp-content/... als absolute URL hardcoded — Relikt aus der Zeit vor dem Domain-Umzug von kurse. auf die Bare-Domain. Der 301-Redirect zwischen Subdomains verliert die CORS-Header, Browser blockiert Font-Requests.

Fix: In-place sed-Replace in 5 OMGF-CSS-Dateien: kurse.islandpferde-melanieworbs.de/wp-content/islandpferde-melanieworbs.de/wp-content/. 76 Vorkommen ersetzt.

Betroffene Dateien (Production /var/www/html/web/app/uploads/omgf/): - dsvy-all-gfonts/dsvy-all-gfonts.css (26 Refs) - google-fonts-1/google-fonts-1.css (42 Refs) - omgf-stylesheet-100/omgf-stylesheet-100.css (6 Refs) - omgf-stylesheet-72/omgf-stylesheet-72.css (1 Ref) - rs-roboto/rs-roboto.css (1 Ref)

Backup: backups/production/2026-04-08_omgf-hostname-fix/omgf-css-backup.tar.gz

Verifikation: Font-Request yantramanav-normal-latin-700.woff2 liefert jetzt HTTP 200 + access-control-allow-origin: * + content-type: font/woff2. Keine CORS-Errors mehr.

Kein Code-Fix noetig — nur Cache-Files. DEV/STAGING wurden nicht angefasst, sollten aber in einer zukuenftigen Session geprueft werden, ob dort aehnliche Altlasten existieren.

Erledigt - Sprint 100.5b: HTML im Form-Editor Label fuer agreement-Felder (Issue #119)

Problem: Das %s-Page-Title-Replacement im Form-Editor koppelte den Link-Text starr an den Page-Title. Bei zusammengesetzten deutschen Begriffen fuehrte das zu Grammatik-Fallen (Mellys Punkt 4 aus Mail vom 08.04.2026):

  • Page-Title: Allgemeine Geschaeftsbedingungen (Nominativ Singular)
  • Label: Ich erkenne die %s an. (Akkusativ Plural mit Artikel → Adjektiv-Endung -en)
  • Frontend: "Ich erkenne die Allgemeine Geschaeftsbedingungen an."
  • Korrekt: "Ich erkenne die Allgemeinen Geschaeftsbedingungen an."

Recherche: Alle grossen Form-Plugins (WPForms, Gravity Forms, Formidable, Fluent Forms, WS Form) erlauben HTML im Label. Kein Plugin koppelt den Link-Text starr an einen Page-Title. Das %s-Replacement im kurs-booking war eine Sonderloesung mit unvermeidlichem Grammatik-Problem.

Loesung: sanitize_custom_fields() in class-settings.php:505 umgestellt auf typabhaengige Sanitization. Agreement-Felder nutzen jetzt wp_kses mit Whitelist <a>, <em>, <strong>, <br>. Alle anderen Feldtypen behalten sanitize_text_field. Template booking-form.php entsprechend erweitert fuer Whitelist-Paritaet.

Backward-compatible: Bestehende Felder mit %s-Platzhalter funktionieren unveraendert weiter — str_replace('%s', $link_html, ...) im Template bleibt erhalten.

Task Beschreibung
Code-Fix class-settings.php Typabhaengige Label-Sanitization, Whitelist a/em/strong/br fuer agreement-Felder
Template-Fix booking-form.php wp_kses Whitelist erweitert (vorher nur <a>) fuer Paritaet mit Sanitization
DEV-Tests (5 Cases) A: HTML-Link erhalten ✅ / B: %s backward-compat ✅ / C: verschachteltes <a><strong> ✅ / D: <script> gestrippt ✅ / E: text-Feld <a> gestrippt ✅
DEV-Frontend-Test Field #34 live umgestellt, Buchungsformular zeigt korrektes Label mit Link
Production-Backup backups/production/2026-04-08_pre-sprint-100-5b/ (class-settings.php + booking-form.php)
Deployed DEV → STAGING → PRODUCTION, HTTP 200, keine PHP-Errors
Field #35 migriert (Prod) Ich erkenne die %s an.Ich erkenne die <a href="https://islandpferde-melanieworbs.de/agbs/" target="_blank" rel="noopener">Allgemeinen Geschaeftsbedingungen</a> an.
Bonus-Fix Field #34 (Prod) Datenschutz-Checkbox hatte den bekannten Bug Datenschutz</a>erklaerung (Link nur um "Datenschutz"). Migriert auf komplettes Wort <a>Datenschutzerklaerung</a> mit korrektem Permalink
Frontend-Verifikation Prod Buchungsseite /kurs/individualtraining-spezial-am-oedhof/ zeigt beide Labels korrekt verlinkt
Gitea Issue #119 erstellt mit Labels feature + kundenanfrage

Geaenderte Dateien: - includes/class-settings.php (typabhaengige Label-Sanitization, +22/-1 Zeilen) - templates/booking-form.php (wp_kses Whitelist-Paritaet, +4/-0 Zeilen)

Gitea Issue: #119

Erledigt - Sprint 100.5a: sevDesk Rechnungsfelder UStG-konform (Issue #118)

Problem: Mellys Anfrage 3a+3b+3c — sevDesk-Rechnungen waren nicht UStG-konform und nicht Best-Practice:

  1. Leistungszeitraum bei mehrtaegigen Kursen unvollstaendig (nur deliveryDate, kein deliveryDateUntil) → Verstoss gegen §14 Abs. 4 UStG (DE) / §11 UStG (AT)
  2. Betreff war Kurstitel statt Rechnungsnummer → nicht Best Practice (lexoffice/FastBill/Debitoor/sevDesk-Defaults setzen alle "Rechnung Nr. ..." als Header)
  3. Kopftext-Datumszeile zeigte nur Startdatum statt Datumsbereich

Loesung: Drei neue zentrale Helper in class-sevdesk.php + Anpassung aller drei Code-Pfade (Vollrechnung + Anzahlung + Restrechnung):

Helper Zweck
format_kurs_date_range() Compact-Format "10. - 12.05.2026" bei gleichem Monat, voll bei Monatsuebergang, einzel bei 1-Tages-Kurs
build_delivery_date_range() Liefert deliveryDate + deliveryDateUntil mit echten Kursterminen. Frueherer Sprint-43 +1-day-Workaround entfernt — sevDesk akzeptiert zukuenftige deliveryDate bei invoiceType=AR
build_invoice_header() Setzt "Rechnung Nr. {nummer}" mit Fallback. Nutzt existierende get_next_invoice_number() zur Vorab-Reservierung — kein zweistufiger PUT-Flow noetig, kein GoBD-Risiko
Task Beschreibung
API-Recherche via context7 sevDesk-API-Doku zu deliveryDateUntil, header, getNextInvoiceNumber. Bestaetigt: deliveryDateUntil ist offizielles API-Feld, invoiceNumber darf bei saveInvoice mitgegeben werden
Code-Fix class-sevdesk.php 3 neue Public-Helper, create_invoice_for_booking() mit Nummer-Reservierung + Header + delivery-range, build_head_text() ueber zentralen Datums-Helper
Code-Fix class-sevdesk-partial-invoice.php create_deposit_invoice() + create_rest_invoice() mit Nummer-Reservierung + Header + delivery-range, build_deposit_head_text() + build_rest_head_text() ueber zentralen Datums-Helper. Dead code get_delivery_date_for_invoice() entfernt
DEV-Setup: 3 Test-Kurse angelegt Kurs 5741 (10.-12.05, gleicher Monat → compact), 5742 (29.05-02.06, Uebergang → voll), 5743 (15.05, eintaegig → kein Range). Marker _sprint_100_5a_test=1
DEV-sevDesk auf Test-Account umgestellt Mellys Production-Token war faelschlich auf DEV konfiguriert (sevClient 1170381). Auf Joseph's separates Test-Konto umgestellt (sevClient 1168006 / info@webwerkstatt365.at). Credentials in /mnt/projects/dokumentenaustausch/API-KEYS-CREDENTIALS.md gesichert. Draft-Mode auf DEV aktiviert als zusaetzlicher Schutz
DEV infra: WP_DEBUG_DISPLAY off docker-compose.dev.yaml + WORDPRESS_CONFIG_EXTRA gepatcht (define('WP_DEBUG_DISPLAY', false); define('WP_DEBUG_LOG', true);). Vorher: PHP-Deprecations im Browser blockierten Header → Plugin-Updates nicht moeglich. Nun: Deprecations in /wp-content/debug.log
End-to-End Test (DEV) 9/9 Checks gruen: Vollrechnung + Anzahlung + Restrechnung mit echten sevDesk-API-Calls, Verifikation aller drei Felder (header, deliveryDate+Until, headText)
Bug-Fix Sprint-43 Workaround Iteration nach erstem Test entdeckt: Wir haben den Sprint-43 +1-day-Workaround mitgeschleppt → Leistungszeitraum zeigte "morgen bis Kursende" statt echte Kurstermine. Workaround entfernt, sevDesk-API akzeptiert jetzt zukuenftige deliveryDate problemlos
DRY-Refactoring Datumsbereich-Logik aus 3 Stellen in einen zentralen format_kurs_date_range() Helper extrahiert
Deployed DEV → STAGING → PRODUCTION (in dieser Reihenfolge), PHP-Lint + HTTP-Smoketest + Docker-Logs auf allen 3 sauber
Gitea Issue #118 erstellt mit Labels bug + kundenanfrage + prio-hoch, via Commit 8b83c3c geschlossen

Geaenderte Dateien: - includes/class-sevdesk.php (+161 Zeilen, 3 neue Helper, geaendertes create_invoice_for_booking + build_head_text) - includes/class-sevdesk-partial-invoice.php (-/+124 Zeilen, geaenderte create_deposit_invoice + create_rest_invoice + build_deposit_head_text + build_rest_head_text, dead code entfernt)

Git Commit: 8b83c3c Gitea Issue: #118 (geschlossen)

Backup vor Production-Deploy: /mnt/projects/proj_wordpress_webnus/backups/production/2026-04-08_pre-sprint-100-5a/ - class-sevdesk.php.production-state (115 KB) — Production-Stand vor Sprint 100.5a - class-sevdesk-partial-invoice.php.production-state (60 KB) — dito

Beobachtungen waehrend Test: - Joseph's Test-sevDesk-Konto vergibt AR-Nummern ohne Praefix (1006, 1007, ...). Mellys Production vergibt RE-2026-04-XXXX. Format ist konto-spezifisch — unser Code ist format-agnostisch und uebernimmt was die API zurueckgibt - Im Test-Konto wurde das Leistungszeitraum-Feld der ersten Test-Drafts (Run 1, Run 2 vor Bug-Fix) ISO-formatiert angezeigt; bei spaeter erstellten Drafts korrekt DE. Vermutlich sevDesk-internes UI-State-Caching pro Invoice. Production wird nur frische Rechnungen erzeugen → DE-Format - 6 Test-Drafts mit +1 day Bug + 9 weitere Test-Drafts in Joseph's sevDesk hinterblieben — koennen manuell geloescht werden, harmlos im Test-Konto

Erledigt - Punkt 2b aus Melly-Mail: Bankdaten bei Fremdbuchung (Issue #116)

Problem: Bei Buchungen fuer Kurse mit Abrechnungstyp Fremdbuchung (UI-Label "Fremdbuchung (extern)") erschienen Mellys Bankdaten trotzdem in der Buchungsbestaetigungs-E-Mail. Kundinnen haben daraufhin faelschlicherweise an Melly statt an den externen Veranstalter ueberwiesen.

Root Cause: Das Kurs-Meta abrechnung kennt drei Werte: eigen, partner, extern. UI-Label "Fremdbuchung (extern)" speichert als partner. Die sevDesk-Logik prueft korrekt auf beide (in_array($abrechnung, ['extern','partner'])), aber class-email.php:218 prueft nur auf 'extern' === $abrechnung → Bankdaten-Section wurde bei partner eingeblendet.

Task Beschreibung
Diagnose Production 8 Kurse mit nicht-eigen Abrechnung gefunden: 6x partner (5399, 5398, 5396, 5394, 5389, 5384), 2x extern (5391, 5382). Nur partner-Kurse betroffen.
Code-Fix class-email.php:218 'extern' === $abrechnungin_array($abrechnung, ['extern','partner'], true). Konsistent mit class-sevdesk.php:1453 und class-sevdesk-partial-invoice.php.
Logik-Verifikation Via php -r auf STAGING getestet: eigen → FALSE (Bankdaten), extern/partner → TRUE (keine Bankdaten).
Deployed DEV + STAGING + PRODUCTION, File-Check auf allen 3, keine Errors in Logs.
Gitea Issue #116 erstellt mit Labels bug + prio-hoch + kundenanfrage, via Commit 763d1c2 geschlossen.

Geaenderte Dateien: includes/class-email.php Git Commit: 763d1c2 Gitea Issue: #116 (geschlossen)

Erledigt - Punkt 2 aus Melly-Mail: Drei-Rechnungen-Bug

Problem: Bei Buchungen mit weniger als 21 Tagen Vorlauf hat das Plugin faelschlicherweise 3 Rechnungen in sevDesk erstellt (Gesamt + Anzahlung + Rest) statt nur einer Gesamtrechnung. Gemeldet am Beispiel BK-2026-0251 (Ulrike Corradi, 16 Tage Vorlauf).

Root Cause: Die 21-Tage-Regel aus Sprint 36 war nur in class-sevdesk.php:3062 eingebaut. Spaetere Sprints 49 und 58 fuegten zwei weitere Code-Pfade in class-reminder-engine.php hinzu, die die Regel nicht respektierten:

  1. on_booking_confirmed() - erstellte unbedingt Anzahlungsrechnung
  2. maybe_create_immediate_rest_invoice() - erstellte Restrechnung sofort bei T<=payment_days
  3. catch_missed_rest_invoices() - Safety-Net Cron (Sprint 58) schloss die Restrechnung nach

Zusaetzlich: cancel_all_invoices() in class-sevdesk-storno.php hatte eine Entweder-Oder-Annahme, die bei drei gesetzten Meta-Keys die Gesamtrechnung nicht mehr storniert haette.

Task Beschreibung
Gitea-Recherche Bug-Historie Issues #12 (Sprint 36), #50 (Sprint 58), #48, #96 analysiert. Sprint 36 hat die 21-Tage-Regel nur in class-sevdesk.php eingebaut. Spaetere Sprints haben parallele Code-Pfade erzeugt ohne die Regel mitzunehmen.
Production-Backup vor Fixes wordpress_kurse.sql.gz (18 MB) + wp_files.tar.gz (1.6 GB, ohne /backups, /cache, /upgrade) lokal in backups/production/2026-04-08_1603/
Code-Fix 1: Zentrale 21-Tage-Regel Neue Methode Kurs_Booking_SevDesk::is_deposit_invoice_mode( int $kurs_id ): bool in class-sevdesk.php. Einzige Quelle der Wahrheit fuer die Regel.
Code-Fix 2: class-reminder-engine.php 3 Code-Pfade abgesichert: on_booking_confirmed(), maybe_create_immediate_rest_invoice(), catch_missed_rest_invoices(). Alle pruefen jetzt is_deposit_invoice_mode() + early-return wenn _sevdesk_invoice_id bereits gesetzt (Defense-in-Depth).
Code-Fix 3: class-sevdesk-storno.php cancel_all_invoices() storniert die Gesamtrechnung jetzt unabhaengig von deposit/rest Meta-Keys. Verhindert dass Altlasten-Buchungen mit allen drei Meta-Keys bei einem Storno die Gesamtrechnung verlieren.
Diagnose Ulrike + Sophie verifiziert READ-ONLY DB-Query: Ulrike Corradi (16 Tage Vorlauf) hat alle 3 sevdesk-Meta-Keys → Bug bestaetigt. Sophie Schuldlos (67 Tage Vorlauf) korrekt mit Anzahlung + Rest.
Report betroffener Altlasten-Buchungen 4 Buchungen mit allen drei Meta-Keys in Production-DB gefunden: Ulrike Corradi (5886), Laura Lorenz (5885), Bettina Gehmacher (5884), Barbara Ecker-Streule (5953). Alle auf Kurs 5393 "Individualtraining Spezial am Oedhof".
DB-Cleanup Runde 1 22 sevDesk-Meta-Keys (deposit/rest invoice_id/number/amount) fuer die 4 Altlasten-Buchungen geloescht. Rollback-Export: geloeschte-meta-keys.sql.
DB-Cleanup Runde 2 4 weitere Legacy-Keys bei Barbara (5953) geloescht: _sevdesk_invoice_number_rest, _sevdesk_invoice_status_rest, _sevdesk_positions_120940868/873. Sprint-77-Format. Rollback-Export: geloeschte-meta-keys-barbara.sql.
Reminder entwaffnet (KRITISCH!) 4 Payment-Reminder (IDs 34, 40, 41, 42) in gbbM2_kurs_reminders auf Status canceled gesetzt. Ohne das haette get_dunning_candidates() die Kundinnen beim naechsten Mahnlauf als saeumig erkannt und Mahnungen fuer nicht mehr existierende Rest-Rechnungen erzeugt. Rollback-Export: geaenderte-reminder.sql.
Verifikation Plaetze Kurs 5393: max 12 Teilnehmer, 10 belegt (9 Buchungen) - unveraendert. Alle 4 Buchungen weiterhin Status confirmed.
Antwort an Melly Ausfuehrliche Mail verschickt mit Erklaerung dass es ein Code-Bug war (keine Einstellung), was gefixt wurde, und dass die 4 Altlasten technisch bereinigt wurden.

Geaenderte Dateien: - includes/class-sevdesk.php - neue is_deposit_invoice_mode() Methode - includes/class-reminder-engine.php - 3 Code-Pfade abgesichert - includes/class-sevdesk-storno.php - cancel_all_invoices() fix

Deployed auf: DEV + STAGING + PRODUCTION (alle 3, in der Reihenfolge, keine Errors in den Logs)

Backup-Ordner: /mnt/projects/proj_wordpress_webnus/backups/production/2026-04-08_1603/ - wordpress_kurse.sql.gz (18 MB) - DB-Dump vor allen Aenderungen - wordpress_kurse_pre_delete_1640.sql.gz (18 MB) - DB-Dump direkt vor DB-Cleanup - wp_files.tar.gz (1.6 GB) - WordPress Files - diagnose-corradi-fix.md - Dokumentation - geloeschte-meta-keys.sql - Rollback Runde 1 (22 INSERTs) - geloeschte-meta-keys-barbara.sql - Rollback Runde 2 (4 INSERTs) - geaenderte-reminder.sql - Rollback Reminder-Update (4 INSERTs)

Noch offen aus Mellys Mail

Punkt Thema Typ Status
~~2b~~ ~~Bankdaten bei Typ-2 (extern) Buchungen~~ Code-Fix ERLEDIGT 08.04.2026 (Issue #116, Commit 763d1c2)
~~3a+3b+3c~~ ~~sevDesk Rechnungsfelder (Leistungszeitraum, Betreff, Kopftext)~~ Code-Fix + Compliance ERLEDIGT 08.04.2026 (Sprint 100.5a, Issue #118, Commit 8b83c3c)
~~4~~ ~~Tippfehler "Allgemeine Geschaeftsbedingungen" → "Allgemeinen"~~ Code-Fix + Migration ERLEDIGT 08.04.2026 (Sprint 100.5b, Issue #119). HTML im Form-Editor Label erlaubt, Field #35 auf "Allgemeinen" umgestellt. Bonus-Fix Datenschutz-Checkbox Field #34 inklusive
~~5~~ ~~Kundenportal: globale oder pro-Kunden Einstellungen?~~ Antwort-Frage ERLEDIGT (in Melly-Mail 08.04.2026 erklaert: ist global, class-settings-tab-portal.php:60-105)

Hinweis fuer naechste Session

  • PRIO 1: Sprint 100 weiter - Tasks: 100.1 (Install-Routine), 100.2 (Uninstall.php), 100.3 (Konfig-Migration), 100.4 (Dependency-Check)
  • Sprint 100.5c (OFFEN, P3 Tech-Debt): Rodiar-Demo-Assets Migration. Browser-Konsole zeigt NS_BINDING_ABORTED fuer 8 Bilder auf rodiar-demo.pbminfotech.com. Umfang: 74 eindeutige URLs in 23 published pages + 19 elementor_library + 27 custom post types. Assets auf dem PBM-Server bereits 404 — Asset-Rescue nicht trivial. Voller Plan: sprint-100-5c-rodiar-demo-assets-migration.md. Vor Sprint-Start Ruecksprache mit Melly wegen Asset-Ersatz-Strategie (Wayback vs. Replacement-Icons) und Dead-Link-Strategie
  • Melly informieren dass (a) die naechste echte Buchung die neuen Rechnungsfelder zeigt + (b) Punkt 4 (Tippfehler AGB) und Bonus-Fix Datenschutz-Checkbox auf Production live sind — sie soll beides bestaetigen
  • DEV-Test-Artefakte aufraeumen: 15 Test-Buchungen (IDs 5744-5759) + 3 Test-Kurse (5741-5743) + ~17 Test-Drafts in Joseph's Test-sevDesk koennen geloescht werden. Marker: _sprint_100_5a_test=1 in DB
  • Backup 2026-04-08_pre-sprint-100-5a kann nach 7 Tagen Live-Beobachtung geloescht werden wenn keine Probleme auftreten
  • Backup 2026-04-08_pre-sprint-100-5b (class-settings.php + booking-form.php) kann nach 7 Tagen Live-Beobachtung geloescht werden wenn keine Probleme auftreten
  • Bekannter Save-Handler-Bug DEV (offen, prio-niedrig): UI-Save in sevDesk > Verbindung persistierte den api_token nicht. Workaround: via PHP update_option() Direkt-Update. Vermutete Ursache: Sub-Tab-Mismatch beim Hidden-Field oder Browser-Password-Autofill. Sollte separat als Gitea-Issue angelegt werden
  • Gitea Issue #117 (UX: abrechnung-Labels) ist Refactoring-Kandidat fuer Sprint 100
  • Backup aus 2026-04-08_1603 (Drei-Rechnungen-Bug-Fix) kann geloescht werden — DB ist seit Stunden stabil

Session 20.03.2026

Erledigt

Task Beschreibung
Restrechnung Bug gefixt (Issue #115) Erste Restrechnung im System (BK-2026-0249, Bettina Gehmacher) schlug fehl. sevDesk lehnte invoiceType = 'RE' ab wenn deliveryDate > invoiceDate (Kurs in der Zukunft). Fix: invoiceType auf AR geaendert wie bei Anzahlungsrechnung. War ein Programmierfehler von Anfang an, nie aufgefallen da es die allererste Restrechnung war.
Restrechnung manuell erstellt RE-2026-03-1043 (140 EUR) fuer BK-2026-0249 erstellt und per E-Mail an Kundin gesendet.
CPU-Alert untersucht Grafana meldete >80% CPU um 10:50 UTC. Nicht mit Rechnungs-Bug verwandt - Gitea verursacht hohe CPU-Last (32% zum Zeitpunkt der Pruefung).

Geaenderte Dateien: includes/class-sevdesk-partial-invoice.php (Zeile 369: TYPE_INVOICE -> TYPE_PARTIAL) Git Commit: 8197692 Gitea Issue: #115 (geschlossen) Deployed auf: Production (direkt, kritischer Bugfix)

Hinweis fuer naechste Session

  • Gitea CPU-Last beobachten - 32% CPU, moeglicherweise Indexierung/GC
  • Alte Container aufraumen (paperless, paperless-redis, backup_gui) - Services auf SaaS-Server umgezogen, Uptime-Kuma Monitors anpassen
  • Sprint 100 Phase 1 starten: uninstall.php erstellen
  • WordPress Update 6.9 → 6.9.1 noch offen
  • E-Mail-Versand WordPress (All-Inkl Support) noch offen

Session 04.03.2026

Erledigt

Task Beschreibung
Wettbewerbsanalyse Marktanalyse erstellt: Amelia, Bookly, BookingPress, Booknetic, edoobox verglichen. Ergebnis: Nische "sevDesk + GoBD + Kurslogik" ist einzigartig am Markt. Kein Konkurrent bietet native sevDesk-Integration. Dokument: docs/kurs-booking/entwicklung/WETTBEWERBSANALYSE.md
Sprint 100 geplant 55h-Roadmap fuer Plugin-Neutralisierung & Verkaufsfaehigkeit. 4 Phasen: Neutralisierung (12h), Core-Stabilisierung (15h), Nischen-Onboarding (18h), Release & Test (10h). 19 Tasks priorisiert (P1-P4). Sprint-Plan: docs/kurs-booking/entwicklung/sprints/sprint-100-neutralisierung-verkaufsfaehigkeit.md
Plugin-Analyse (Phase 1) Ist-Zustand analysiert: Kein uninstall.php, 7 Custom Tables, ~150 Options ohne Cleanup, Audit-Log nicht im Activation Hook, keine Credential-Validierung bei Modul-Load, Versions-Header Mismatch.

Hinweis fuer naechste Session

  • Sprint 100 Phase 1 starten: uninstall.php erstellen (hoechste Prioritaet)
  • Activation Hook erweitern: Audit-Log Tabelle + Versions-Fix
  • Dependency-Check: Graceful Warnings bei fehlenden API-Keys
  • WordPress Update 6.9 → 6.9.1 noch offen (geplant fuer Sonntag)
  • E-Mail-Versand WordPress (All-Inkl Support) noch offen

Sprint 100 Quick-Referenz

Phase Stunden Fokus
Phase 1: Neutralisierung 12h Install/Uninstall, DB-Saeberung, Dependencies
Phase 2: Core-Stabilisierung 15h Dashboard, Formular, Demo-Content, E-Mail
Phase 3: Nischen-Onboarding 18h sevDesk-Wizard, GoBD-Doku, Marketing
Phase 4: Release & Test 10h Tests, Packaging, Beta

Sprint-Plan: sprint-100-neutralisierung-verkaufsfaehigkeit.md


Session 06.02.2026

Erledigt

Task Beschreibung
Safety-Net Fix: MEC-Importe Kritischer Bug im Reminder-Engine Safety-Net behoben. catch_missed_rest_invoices() versuchte Restrechnungen fuer 18 MEC-importierte Buchungen zu erstellen, die keine Anzahlung hatten. SQL: LEFT JOIN → INNER JOIN fuer _buchung_deposit_amount + Bedingung deposit > 0. Zusaetzlicher PHP-Check als zweite Sicherheitsebene. Fehler-Emails an Admin sofort gestoppt.
MEC-Buchungen markiert 18 MEC-importierte Buchungen (MEC-1813 bis MEC-1838) in Production-DB mit _buchung_source=mec_import und _sevdesk_error="MEC-Import: Abrechnung erfolgte ueber das alte Buchungssystem" markiert.
System bereinigt kurs_booking_last_error (alter API-Fehler) und _sevdesk_error auf geloeschter Test-Buchung #5534 entfernt.
Komplett-Analyse auf MEC-Risiken Alle 16 Dateien mit MEC-Referenzen geprueft. Keine weiteren Schwachstellen gefunden - alle anderen Code-Pfade haben saubere Fallbacks.
sevDesk Rechnungs-Audit 5 aktuelle Rechnungen geprueft. Nur RE-1010 (Johanna Heinzel, 90 EUR Anzahlung) von unserem Plugin. 4 manuell erstellte Rechnungen identifiziert (Melanie 0 EUR, Fiona 3.540 EUR, Carmen 2x). Email an Kundin gesendet.

Geaenderte Dateien: includes/class-reminder-engine.php Git Commit: b89e4a3 Deployed auf: Production (direkt, kritischer Bugfix)

Hinweis fuer naechste Session

  • WordPress Update 6.9 → 6.9.1 durchfuehren! (Minor/Patch, Bugfixes + Sicherheit)
  • DEV/Staging: Update per WP-Admin
  • Production (Bedrock): composer require roots/wordpress:6.9.1 im Container
  • Workflow: DEV testen → Staging testen → Production updaten
  • composer.json danach ins Git committen (islandpferde-infrastructure)
  • Antwort von Melanie abwarten bzgl. manueller sevDesk-Rechnungen (0 EUR, 3.540 EUR, Carmen Hansel)
  • Falls Melly die E-Mail-Vorlagen im Admin manuell angepasst hat, muss sie unter sevDesk > Rechnungs-Texte auf "Auf Standard zurücksetzen" klicken
  • E-Mail-Versand WordPress (All-Inkl Support) noch offen
  • Resend-Button AJAX noch nicht final getestet

Session 05.02.2026

Erledigt

Task Beschreibung
sevDesk Rechnungs-E-Mail: Umlaute + Tabellen Kundenanfrage MW: "ueberweisen"→"überweisen", "fuer"→"für" in PDF-Kopf/Fusstext-Defaults und E-Mail-Betreff-Defaults (6 Stellen). HTML-Tabellen aus allen 3 sevDesk-E-Mail-Templates (deposit, rest, full) durch schlichten Fliesstext ersetzt. monospace-Schrift bei IBAN entfernt.
Production DB geprueft Gespeicherte Werte kurs_booking_sevdesk_foot_text und _head_text haben bereits korrektes "ü". Das "Ueberweisen" im PDF war eine alte, bereits festgeschriebene Rechnung (nicht mehr aenderbar, GoBD).
Backup erstellt Plugin (9,7 MB) + DB (17 MB) → /mnt/projects/proj_wordpress_webnus/backups/2026-02-05/
Kurs Admin Notifications Plugin Eigenstaendiges Plugin fuer Admin-E-Mail-Benachrichtigungen. 21 Dateien, ~3000 Zeilen. Deployed auf DEV, Staging und Production. Plugin aktiviert, Test-Mail erfolgreich. Empfaenger: info@web-werkstatt.at. 8 Echtzeit-Events aktiviert (Buchungen, Stornos, Fehler). Tagesbericht taeglich um 08:00.
KAN Bugfix: Hidden Fields General-Tab hat beim Speichern Echtzeit-Events und Tagesbericht-Settings ueberschrieben. Hidden Fields ergaenzt, um cross-tab Settings zu preserven.

Geaenderte Dateien: includes/class-sevdesk-settings.php Git Commits (kurs-booking): 7ebea13, 71d3c2f Git Commits (kurs-admin-notifications): 3e0628b (Initial v1.0.0), fc09246 (Hidden Fields Bugfix) Gitea Repo: https://git.webideas24.com/webideas24/kurs-admin-notifications Deployed auf: DEV + Staging + Production (alle 3)


Session 04.02.2026 (Nacht)

Erledigt

Task Beschreibung
sevDesk E-Mail Template wrap_in_template() in class-email.php: Rechnungs-E-Mails (sevDesk) nutzen jetzt das gleiche Teal-Header-Design wie Buchungsbestaetigungen. body_only-Parameter fuer sevDesk API (kein DOCTYPE). HTML-Kommentare entfernt (sevDesk rendert sie als Text).
Invoice Detail Fixes Brutto/Netto-Inkonsistenz behoben (sumGross statt sumNet), Kundenadresse im Kopf, Spaltenbreiten angepasst (120px), JS showNotice Fix (DOMException)
Erweiterte Buchungssuche Suche nach Kursname, Kundenname, E-Mail, Telefon, Buchungsnummer via pre_get_posts + Sub-Query SQL
Resend Button JS Fix showNotice mit :scope > h1 und heading.after() Fallback
Vollstaendiges Server-Backup 20 GB Backup aller Volumes, Datenbanken, Configs nach /mnt/projects/dokumentenaustausch/backup-2026-02-04/
Deploy auf DEV + STAGING 227 Dateien auf beide Umgebungen deployed

Geaenderte Dateien: class-email.php, class-sevdesk.php, class-invoice-resend.php, class-invoice-detail.php, admin-invoice-detail.css, class-buchung.php Git Commit: 05c714d (gepusht auf Gitea)

Offene Punkte

Punkt Status
E-Mail-Versand WordPress (All-Inkl Support) All-Inkl sagt: WordPress sendet nicht, kein SPF-Problem. SMTP-Plugin pruefen.
Resend-Button AJAX testen Rate-Limiting verhinderte Tests, noch nicht final getestet

Session 04.02.2026 (Abend)

Erledigt

Task Beschreibung
Buchungs-Integrity-Check (Cron) Neuer taeglicher Cron-Job kurs_booking_integrity_check. Prueft ob bestaetigte Buchungen (laut Audit-Log + Custom Table) noch als WordPress-Posts existieren. Haette den Sophie-Fall sofort erkannt. Bei Befunden: Admin-Alert (Glocke) + Debug-Warning + Audit-Log-Eintrag. Deployed auf DEV, STAGING und PRODUCTION.
Buchungs-Log im System-Tab Neues Feature zur Anzeige von Buchungs-Logs im System-Tab
Cleanup in Papierkorb Buchungs-Cleanup verschiebt jetzt in Papierkorb statt hart zu loeschen
sevDesk Adress-Repair Werkzeug Neues Tool zur Reparatur fehlerhafter sevDesk-Adressen
Buchungs-Templates verbessert Adresse in Custom-E-Mail-Templates + kurs_edit_url zentral

Neue Dateien: includes/class-integrity-check.php (~150 Zeilen) Geaenderte Dateien: kurs-booking.php (init + deactivate), includes/class-admin-alerts.php (neuer TYPE_INTEGRITY_ISSUE)

Neuer Cron-Hook

Hook Intervall Pruefung
kurs_booking_integrity_check taeglich Audit-Log Orphans (90 Tage) + Custom Table Orphans

Session 04.02.2026

Erledigt

Task Beschreibung
Sprint 87 geplant Sprint-Plan erstellt: sevDesk Settings Konsolidierung & Monolith-Aufloesung. Umsetzung auf spaeter verschoben.
Sophie Schuldlos Buchung wiederhergestellt Buchung durch Container-Crash am 02.02 verloren. Neue Buchung Post #5837 mit BK-2026-0234 erstellt, sevDesk-Rechnung RE-2026-02-1004 (#116118899) verknuepft, Custom Table (gbbM2_kurs_buchungen) synchronisiert. Kurs #5393 Individualtraining Spezial am Oedhof (10.-12.04.2026), 330 EUR (90 EUR Anzahlung).
sevDesk-WP Abgleich Alle 4 aktiven WP-Buchungen stimmen mit sevDesk ueberein. 6 verwaiste sevDesk-Rechnungen identifiziert (Sophie's RE-2026-02-1004 jetzt verknuepft, Rest: alte Test/Storno-Eintraege + 1 unbekannte RE-2026-02-1008 fuer 3.380 EUR).

Neue Dateien: docs/kurs-booking/entwicklung/sprints/sprint-87-sevdesk-settings-konsolidierung.md Geaenderte Dateien: SPRINT-UEBERSICHT.md, kundenfeedback.md

Offene Punkte (Sophie-Buchung)

Punkt Status
sevDesk-Rechnung RE-2026-02-1004 enthaelt noch "BK-2026-0226" im Kopftext Optional: Header in sevDesk aktualisieren
Verwaiste RE-2026-02-1008 (Contact#124294584, 3.380 EUR) Klaerung mit Roman/Melly noetig

Session 02.02.2026 (Abend)

Erledigt

Feature Beschreibung Commit
Buchungen Export Modul Neue Admin-Seite unter Veranstaltungen > Buchungen Export. CSV/Excel Export aller Buchungen, sevDesk Sammelrechnungen (Einzelschritt, Draft-Pflicht), Buchungs-PDFs als ZIP, Rechnungs-PDFs als ZIP. Vollstaendig gekapselt - nur 2 bestehende Dateien minimal geaendert. 2f13c2e

Neue Dateien: includes/class-booking-export.php (787 Zeilen) Geaenderte Dateien: kurs-booking.php (init-Aufruf), includes/class-admin.php (Menue-Reihenfolge)

Getestet auf DEV: CSV Export OK, Excel Export OK, sevDesk Draft-Schutz OK Deployed auf Production: 02.02.2026


Session 02.02.2026

Erledigt

Feature Beschreibung Commit
Spam-Logging persistent log_form_submission() nutzt jetzt Kurs_Booking_Debug::warning('spam') statt error_log(). Logs landen in kurs-booking-debug.log (5MB-Rotation) statt Docker stderr (verloren bei Restart) 982794b
Honeypot False-Positive Fix Kundin Susanne Eder wurde 10+ Mal als Spam blockiert (Chrome Autofill fuellte Honeypot-Felder aus). Feldnamen kryptisiert, autocomplete="one-time-code", CSS extern, Version 2.15.2 a0994db
Splide.js Slider "Aehnliche Kurse" auf Kurs-Detailseiten als Carousel b2039c9
Auto-Cleanup unbestaetigter Buchungen Pending-Buchungen nach 24h automatisch loeschen c85d26d
Sync-Bug bei Buchungsbestaetigung Custom Table wurde nicht aktualisiert bei DOI-Bestaetigung 76d3eb5
Auto-Sync bei ALLEN Status-Aenderungen updated_post_meta Hook fuer _buchung_status afe00ab
Sprint 86: Best-Practice-Haertung Re-Entrancy-Guard, Doppel-Sync entfernt, System-Cron 0f43a93

Sprint 86 Details

  • Re-Entrancy-Guard: Static Flag in sync_to_database() verhindert Mehrfach-Aufrufe
  • Doppel-Sync entfernt: confirm() rief sync redundant auf (Hook erledigt das bereits)
  • System-Cron: */5 * * * * auf Hetzner, DISABLE_WP_CRON=true in Bedrock .env
  • Alle 8 Cron-Hooks profitieren (Reminders, Archive, Audit-Log-Cleanup, etc.)

Betroffene Dateien: - includes/class-buchung.php - Guard + Doppel-Sync entfernt - Hetzner Crontab, Container .env, docker-compose.yaml, entrypoint.d/10-create-env.sh

Gitea Issue: #108 (geschlossen)

Production Health-Check (02.02.2026, 17:22 UTC)

Pruefpunkt Status
Alle Container healthy
WordPress erreichbar HTTP 200
Debug-Log Keine Fehler
PHP Error-Log Keine Fehler
System-Cron Eintrag */5 * * * * aktiv
DISABLE_WP_CRON true (Konstante gesetzt)
Cron manuell ausfuehrbar Exit 0
7 Cron-Hooks registriert Alle mit korrekten Intervallen

Registrierte Cron-Hooks: - kurs_booking_cleanup_pending (alle 15 Min) - kurs_booking_process_reminders (stuendlich) - kurs_booking_auto_archive (taeglich) - kurs_booking_auto_archive_kurse (taeglich) - kurs_booking_audit_log_cleanup (taeglich) - kurs_booking_cleanup_temp_uploads (taeglich) - kurs_booking_generate_reminders (taeglich)


WICHTIG: Workflow-Aenderung ab 01.02.2026

Production ist LIVE! Neuer Workflow:

DEV → STAGING → PRODUCTION
  • Entwicklung IMMER auf DEV (/dev)
  • Testen auf STAGING (/staging)
  • Deploy auf PRODUCTION nur nach erfolgreichem Staging-Test (/deploy)
  • Production NUR zum Logs lesen (/production)

Go-Live Session (01.02.2026)

Was wurde gemacht

  1. Test-Modus auf Production deaktiviert (war 1, jetzt aus)
  2. sevDesk Entwurfs-Modus war bereits AUS - Rechnungen werden finalisiert (Status 200)
  3. Turnstile Test-Modus bleibt vorerst AN (nicht ausreichend getestet)
  4. Workflow-Dokumentation aktualisiert (CLAUDE.md: DEV → STAGING → PROD)
  5. Alte Backups auf Server geloescht (~94 GB befreit, von 46% auf 24% Disk)
  6. Kurs-Anzahlungen geprueft: 17 aktive Kurse haben Anzahlung (90 EUR fix), 35 alte Kurse ohne Anzahlung sind alle in der Vergangenheit → kein Handlungsbedarf
  7. E-Mail an Kundin vorbereitet (System ist live, Buchungen moeglich)

Production-Status nach Go-Live

Pruefpunkt Status
Test-Modus AUS
sevDesk Entwurfs-Modus AUS
Rechnungen finalisiert JA (Status 200 + Nummer)
Test-Buchungen 0 (sauber)
Echte Buchungen 19
Turnstile Test-Modus AN (Sandbox-Key, noch nicht getestet)
Disk-Auslastung 24% (318 GB frei)

Offene Gitea Issues

Details und Akzeptanzkriterien: https://git.webideas24.com/webideas24/kurs-booking/issues

# Titel Labels Prio
#109 GoBD-konforme Buchungsarchivierung feature, security -
#111 Stornorechnungen ueber Original-Rechnung verknuepfen feature hoch
#112 CSV/Excel Export Spaltenreihenfolge verbessern refactoring -
#113 Cloudflare Turnstile mit echten Keys aktivieren feature, security niedrig
#114 Lehrvideo-Detailseite implementieren feature niedrig
#102 Video Verkauf - E-Commerce Funktion feature niedrig

Git Commits (01.02.2026 - 32 Commits)

1bb8449 Docs: Go-Live 01.02.2026 - Test-Modus deaktiviert, Workflow DEV→STAGING→PROD
2173db3 Docs: Session 01.02.2026 abgeschlossen - Sprint 85 komplett
9b60600 Docs: Mahnungen/Stornos/Gutschriften geprueft - kein Fix noetig
7bbd41f Fix: Positions-Vorlage text (Beschreibung) konsistent in allen Rechnungstypen
bd95a3c Fix: E-Mail-Templates mit HTML-Tags bekommen keine extra <br> mehr
545ee39 Fix: Video-Kurs Entwurf-Banner als fixed-position via admin_footer
308d2a9 Feature: Video-Kurs Enddatum-Validierung + Reaktivierungs-Buttons
61dcc14 Feature: Sprint 85 - Tab-Verschiebungen, Gruppenfarben, Save-Fix
692a373 Feature: E-Mail-Vorlagen logisch gruppiert mit Farbkennzeichnung
14c2b60 Feature: Video-Zugang Vorlage als bearbeitbares DB-Template
59792e9 Feature: Online/Zoom Buchungsbestaetigung als eigene E-Mail-Vorlage
1b3a0dd Feature: Video-Buchungsbestaetigung als eigene E-Mail-Vorlage
db699f3 Feature: E-Mail-Vorlage pro Dienstleistung zuweisbar
+ 19 weitere Fixes und Style-Commits

Backup (01.02.2026)

Lokal: /mnt/projects/proj_wordpress_webnus/backups/2026-02-01/

Datei Groesse Inhalt
db-backup-2026-02-01.sql.gz 17 MB WordPress DB (wordpress_kurse)
plugin-backup-2026-02-01.tar.gz 9,7 MB kurs-booking Plugin
volumes/vol-plugins-2026-02-01.tar.gz 72 MB Alle Plugins
volumes/vol-themes-2026-02-01.tar.gz 40 MB Themes
volumes/vol-uploads-2026-02-01.tar.gz 1,4 GB Medien/Uploads
volumes/vol-languages-2026-02-01.tar.gz 1,2 MB Sprachdateien
volumes/vol-mu-plugins-2026-02-01.tar.gz 9,3 KB Must-Use Plugins

Server-Backups bis 31.01.2026 geloescht (~94 GB befreit)


Ressource URL
Test-Booking Tool http://144.76.167.158:5056/
WordPress Admin https://islandpferde-melanieworbs.de/wp/wp-admin/
Staging Admin https://staging.islandpferde-melanieworbs.de/wp-admin/
DEV Admin https://dev-kurse.webideas24.com/wp-admin/
Kundenportal https://portal.islandpferde-melanieworbs.de
Gitea Plugin https://git.webideas24.com/webideas24/kurs-booking

Server-Zugang

ssh hetzner-dev

Sudo-Passwort: N64u4>B*mzC9E?(h


Verwandte Themen