Umsetzung des "Website Masterplan" (16 Seiten) unter /webdesign.
Zugangsschutz mit EIGENER Schranke (server/webdesign-gate.js) statt gate.js:
gate.js laesst seit dem oeffentlichen Start am 21.08.2026 jeden durch, weil
die Pruefung auf SITE_PUBLIC_LAUNCH_AT als allererste Zeile steht. Haette man
/webdesign dahintergehaengt, waere der ausdruecklich nicht-oeffentliche Bereich
inklusive Preisen und spaeteren Kundendaten ab der ersten Sekunde fuer jeden
lesbar gewesen. Eigenes Sitzungs-Cookie, bereich="webdesign" im Token, damit
ein gueltiges Universe-Cookie hier NICHT gilt. 37/37 Tests.
Sieben oeffentliche Seiten in fuenf Sprachen (de, de-CH mit echtem Dialekt, en,
fr, pt). Preise, Zeitrahmen, Paketnamen und die 30-%-Regel stehen an genau
EINER Stelle in wd-core.js -- der Masterplan verlangt "ueberall
widerspruchsfrei", und vier Kopien laufen bei der ersten Preisaenderung
auseinander.
Als App installierbar auf Handy und PC. Der Service Worker speichert bewusst
KEINE HTML-Seite zwischen: nach dem Abmelden wuerden sonst geschuetzte Seiten
weiter ausgeliefert, ohne dass der Server je gefragt wird. 18/18 Tests.
Handy-Abnahme ueber alle Seiten in fuenf Breiten (320-1440) und fuenf Sprachen:
40/40. Der Test fand 35 echte Fehler (Touch-Ziele unter 44px), behoben im
Designsystem statt einzeln pro Seite.
PayPal (Wunsch 22.08.2026 "sofort auf meinem paypal"): Orders API mit
intent=CAPTURE, also sofortiger Einzug statt blosser Reservierung. Gebuehr und
Nettobetrag getrennt gespeichert. Betraege durchgehend als Ganzzahl in Cent.
Gefaelschte Webhooks werden abgewiesen. Fail closed solange Zugangsdaten
fehlen. 28/28 Tests gegen einen nachgebauten PayPal-Server.
Datenbank: 15 Tabellen mit Praefix wd_, fachlich vollstaendig vom Universe
getrennt.
Co-Authored-By: Claude Opus 5 <[email protected]>
Diese Änderungen liefen bereits live auf dem Server, lagen dort aber
ausschließlich als nicht eingecheckte Arbeitskopie — bei jedem Deploy
(stash/pull/pop) und bei jedem Serverproblem wären sie verloren gewesen.
Deshalb hier unverändert in git übernommen, bevor darauf aufgebaut wird.
Enthalten (nicht von mir gebaut, nur gesichert):
- Supporter: eigener fester Zugangscode statt Einmalcode-Login
(Migration 0009, lib/crypto.js scrypt-Hash, routes/supporter.js,
abonnieren.html, supporter.html, i18n-abonnieren/-supporter)
- Stimmen: Profilbilder (Migration 0010, routes/testimonials.js)
- Event-Bild-Upload: voller Pfad statt relativem (routes/events.js)
- Neue/überarbeitete Hintergrundbilder für viele Seiten
- Teilen-Funktion (streamplan.js, i18n-index/-streamplan, main.css)
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Wunsch 21.08.2026: "überall wo Modis sind oder Scouts oder
Manager, oder Creator, will ich dass ich die easy über meine
Verwaltungsseite hinzufüge und die automatisch in der Website
hinzugefügt werden ... auch mit Fotos und TikTok Link."
Backend (server-internal, braucht Filipes manuellen Deploy):
- Neue Tabelle team_members (Migration 0007) für alle vier Kategorien
gemeinsam -- ergänzt, überschreibt NIE die von Hand gepflegten
Einträge in data-modis.js/data-scouts.js/data-creator.js.
- routes/team.js: öffentliches Lesen (nur aktive Mitglieder, optional
nach Kategorie gefiltert), TEAM_MANAGE-geschütztes Anlegen/Bearbeiten/
Löschen, Foto-Upload (gleiches Muster wie "Event des Jahres"),
automatische Übersetzung von Rolle/Bio/Zitat wie bei anderen
admin-gepflegten Texten. Slug global eindeutig (mit automatischer
Kollisionsauflösung), TikTok-Kurzname wird zu voller URL ergänzt.
27 Tests in isolierter Testumgebung geprüft (kein better-sqlite3
lokal kompilierbar).
Frontend:
- window.dogiTeamLaden() in main.js: holt admin-gepflegte Mitglieder
einer (oder aller) Kategorien und bringt sie in exakt dieselbe Form
wie die bestehenden data-*.js-Einträge.
- team-scouts.html/team-modis.html/creator.html hängen das Ergebnis
einfach an ihre bestehenden Arrays an und rendern erneut -- exakt
derselbe Look wie die schon bestehenden Profile (Foto/Avatar-Initiale,
Rolle, Zitat, TikTok-Button). creator.html hatte bisher ein "return"
bei leerem CREATORS-Array, wodurch admin-Creator NIE geladen worden
wären -- gefixt. team-modis.html berücksichtigt Rang/Rang-Bezeichnung
für die Pyramide.
- Neue Sektion "Weitere Manager" auf manager.html, komplett unsichtbar
bis der erste Manager angelegt wird (data-manager.js neu, wie
data-creator.js aktuell leer).
- profil.html sucht jetzt kategorieübergreifend auch in admin-gepflegten
Profilen, inkl. korrektem Theme/Zurück-Link auch für Manager.
Verwaltung: neue Sektion "Team verwalten" (TEAM_MANAGE-Berechtigung) --
ein Formular für alle vier Kategorien mit Foto-Sofort-Upload,
TikTok-Feld, Bio/Zitat, bedingten Rang-Feldern (nur Modi), Kategorie-
Filterleiste und Bearbeiten/Löschen pro Eintrag.
Beim Testen mit Playwright einen echten Syntaxfehler gefunden und
gefixt (ASCII-Anführungszeichen statt schließendem „" in einem
Statustext), der das GESAMTE Verwaltungs-Skript und damit die komplette
Seite lahmgelegt hätte.
Cache-Busting-Version auf 20260821j erhöht.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Nutzer-Wunsch 20.08.2026: "eine richtig geile kachel ... wo die leute mit
namen und tiktok namen mir eine nachricht schreiben können die ich in die
verwaltung kriege, und dann kann ich die ausgewählten über die
verwaltungsseite auf die website hinzufügen ... das wird mega persoenlich
zu den fans, bitte wirklich krass geil speziell."
- Neue, augenschonend gestaltete Einreich-Kachel auf stimmen.html: Name,
TikTok-Name (optional), Nachricht -- landet NIE automatisch oeffentlich,
sondern immer erst als Entwurf in der Verwaltung.
Warmer Babyblau/Rosé-Farbverlauf, wandernder Lichtschein, pulsierendes
Herz -- ersetzt die 3 ewigen "Hier steht bald..."-Platzhalterkarten.
- Neue Verwaltungs-Sektion "💬 Stimmen verwalten": Warteschlange (offene
zuerst), Freigeben/Ablehnen/Löschen pro Eintrag.
- Freigegebene Stimmen erscheinen automatisch in einer neuen, spezielleren
Zitat-Kartenoptik (großes Anführungszeichen, Name + TikTok-Chip) --
Abschnitt bleibt komplett unsichtbar, solange keine einzige freigegeben
wurde.
- Backend: neue Tabelle `testimonials` (Migration 0006), routes/
testimonials.js (oeffentliches Einreichen + Lesen freigegebener,
admin-Warteschlange + Status/Loeschen mit neuer TESTIMONIALS_MANAGE-
Berechtigung). 18 automatisierte Tests gegen eine Fake-DB bestanden.
- Alles per Playwright visuell durchgespielt: leerer Zustand, Einreichen
-> Erfolgsmeldung, freigegebene Stimmen-Anzeige, Verwaltungs-Warteschlange
mit allen Aktionen.
Backend-Teil (server-internal/, cloudflare-worker/migrations/) noch ohne
Deploy-Zugriff -- Dogi muss ihn manuell auf dogiintern ausrollen.
Co-Authored-By: Claude Opus 5 <[email protected]>
Naechste "Ausbaustufe" aus Dogfather_VanVan_Supporter_Abo.odt Abschnitt 20
(siehe Supporter-Abo-System.md), auf Nutzerwunsch "perfektioniere meine
Verwaltungsseite": Dogi/VanVan koennen in verwaltung.html eine Frage mit
2-6 Antwortoptionen auf Deutsch erstellen, automatische Uebersetzung beim
Speichern (gleiches Muster wie "Event des Jahres"). Jede aktive DogiCrew-
Person sieht die Abstimmung in ihrem Supporter-Bereich, stimmt genau einmal
ab (UNIQUE-Constraint in der DB, nicht nur Anwendungslogik), sieht danach
die Live-Ergebnisse. Admin-Seite zeigt Ergebnisbalken live, kann schliessen/
wiedereroeffnen/loeschen.
- Neue Migration 0005_supporter_polls.sql (supporter_polls,
supporter_poll_votes), neue Berechtigung POLLS_MANAGE.
- server-internal/routes/polls.js: 30 End-to-End-Tests gegen eine
Fake-DB bestanden (better-sqlite3 laesst sich lokal nicht kompilieren).
- verwaltung.html: neue "Abstimmungen"-Kiste im bestehenden
vw-overview-box-Stil (violett/pink Ergebnisbalken).
- supporter.html: neue "Aktuelle Abstimmung"-Karte im bestehenden
Gold-Look, Optionen -> Stimme -> Ergebnisbalken, alle 5 Sprachen.
Backend-Teil (server-internal/, cloudflare-worker/migrations/) noch ohne
Deploy-Zugriff -- Dogi muss ihn manuell auf dogiintern ausrollen.
Co-Authored-By: Claude Opus 5 <[email protected]>
Nutzer-Wunsch 20.08.2026: "will ich in der admin seite das selbst
gestalten können, mit bild und text und am besten auch einen link." Auf
Rueckfrage entschieden: Titel/Text nur auf Deutsch eingeben, die anderen
4 Sprachen werden beim Speichern automatisch uebersetzt (MyMemory, 0€,
kein API-Key) -- bewusste Ausnahme von der sonst geltenden "immer echte
Uebersetzung"-Regel, klar dokumentiert und im Admin-UI selbst als Hinweis
sichtbar. de-CH bekommt denselben deutschen Text (Dialekt ist keine von
Uebersetzungs-APIs unterstuetzte Zielsprache).
Backend (server-internal):
- routes/events.js: getEventsPublic (oeffentlich, keine Session),
saveEvent + uploadEventImage (beide hinter neuer EVENTS_MANAGE-
Berechtigung, Owner immer erlaubt). Speichert in der bereits
bestehenden app_settings-Tabelle (2 feste Slots) statt einer neuen
Tabelle -- es gibt nie mehr als genau 2 Events.
- lib/translate.js: MyMemory-Anbindung mit "fail closed auf Deutsch"
pro Sprache, falls der Dienst mal nicht antwortet.
- Bild-Upload per multer, zufaelliger Dateiname (crypto.randomUUID,
verhindert Path-Traversal ueber den Originalnamen komplett), 5 MB
Limit, nur jpeg/png/webp, Ablage unter /var/lib/dogfather-internal/
uploads/events (NICHT im Git-Ordner -- uebersteht Deploys), oeffentlich
ausgeliefert unter /uploads.
- Neue Berechtigung EVENTS_MANAGE im Katalog (Gruppe "Startseite").
Frontend:
- index.html: laedt /events-of-year beim Aufruf, ueberschreibt pro Slot
Datum/Titel/Text/Bild/Link NUR wenn dort tatsaechlich etwas gespeichert
ist -- bleibt der Abruf aus oder ist ein Slot leer, bleibt der bisherige
fest eingebaute Standardinhalt (dieselben zwei echten Events) stehen.
Kein Blocker, kein sichtbarer Fehler bei Ausfall.
- verwaltung.html: neue Sektion "🏆 Event des Jahres" (nur mit
EVENTS_MANAGE sichtbar), 2 Karten mit Bild-Upload+Vorschau, Datum,
Titel, Text, Link, eigenem Speichern-Knopf pro Event.
Ausfuehrlich getestet, weil server-internal wegen fehlender Visual-
Studio-Build-Tools auf dieser Windows-Maschine nicht lokal mit echtem
better-sqlite3 laufen kann: routes/events.js komplett isoliert gegen eine
Fake-DB getestet (11 Szenarien: oeffentlicher Abruf, fehlende Session,
Session ohne Recht, Owner, Rolle MIT EVENTS_MANAGE, alle Validierungen,
Bild-Upload inkl. falscher Dateityp, Abruf des hochgeladenen Bilds).
index.html per Playwright mit echtem Netzwerk-Mocking gegen zwei
Szenarien getestet (API nicht erreichbar -> Standardinhalt bleibt; API
liefert echte Daten -> nur der befuellte Slot wird ueberschrieben, der
leere bleibt Standard). Dabei einen echten CSS-Bug gefunden und behoben
(display:block auf .jahres-event-bild überschrieb die [hidden]-Regel des
Browsers, leeres Bild waere immer sichtbar gewesen). verwaltung.html per
Playwright mit gemocktem Login+API end-to-end getestet: Formular wird
korrekt vorbefuellt, Bild-Upload + Speichern senden die richtigen Daten.
WICHTIG: server-internal laeuft unter einem eigenen Systembenutzer
(dogiintern), auf den ich (claudian) bewusst KEINEN Zugriff habe -- diese
Aenderung kann ich anders als sonst nicht selbst bis auf den Server
bringen. Dogi muss den Deploy-Schritt fuer server-internal selbst
ausfuehren (git pull + npm install + Neustart des dogiintern-Dienstes).
Co-Authored-By: Claude Opus 5 <[email protected]>
- Login-Sperre war umgehbar: clientKey() vertraute dem Header CF-Connecting-IP.
Bei Cloudflare war das sicher (CF ueberschreibt ihn), auf dem eigenen Server nicht:
der Ursprungsserver ist auch direkt unter seiner IP erreichbar, dort konnte der
Header frei gesetzt und die 5-Versuche-Sperre komplett ausgehebelt werden
(nachgewiesen). Jetzt req.ip hinter trust proxy.
- Absturzsicherheit: Express 4 faengt Fehler aus async-Handlern nicht ab, eine
einzige fehlerhafte Anfrage konnte den ganzen Dienst beenden. wrap() um alle
Handler, zentraler Fehler-Handler, unhandledRejection/uncaughtException-Netz.
- Sicherheits-Header (X-Content-Type-Options, X-Frame-Options, Referrer-Policy,
Permissions-Policy, HSTS) wurden bisher nur ueber die Datei _headers gesetzt,
die auf dem eigenen Server wirkungslos ist. Jetzt im Express-Server.
- x-powered-by abgeschaltet.
- Datenschutzerklaerung/AGB: nannten Cloudflare als Hoster und eine Cloudflare-D1-
Datenbank. Jetzt korrekt netcup (Rechenzentrum Nuernberg) als Hoster, Cloudflare
als vorgeschaltetes CDN mit Drittlandhinweis.