Files
Speisekarte/CHANGELOG.md
T
florian.wildeandClaude Sonnet 5 358872d56c fix: BRANDING_DIR im app-Dienst setzen, sonst 500 beim Logo/Favicon-Upload
Ohne die Variable weicht lib/branding.ts auf ${cwd}/data/branding
(= /app/data/branding) aus statt das im Dockerfile vorbereitete und
gemountete /data/branding zu nutzen. /app gehört root, der App-Prozess
läuft aber als nicht-root – das Anlegen des Fallback-Verzeichnisses
schlägt mit EACCES fehl.

Version 1.6.3.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 15:10:46 +02:00

12 KiB
Raw Permalink Blame History

Changelog

Alle nennenswerten Änderungen an diesem Projekt werden hier dokumentiert. Format angelehnt an Keep a Changelog, Versionierung nach Semantic Versioning.

[1.6.3] – 2026-07-18

Behoben

  • docker-compose.yml: Der app-Dienst setzte BRANDING_DIR nicht, sodass lib/branding.ts beim Hochladen von Logo/Favicon auf den Fallback-Pfad ${cwd}/data/branding (= /app/data/branding) statt auf das im Dockerfile vorbereitete, gemountete Verzeichnis /data/branding auswich. /app gehört im Container root, der App-Prozess läuft aber als nicht-root-Nutzer nextjs – das Anlegen des Fallback-Verzeichnisses scheiterte mit EACCES, der Upload endete mit „Upload fehlgeschlagen: 500". Jetzt wird BRANDING_DIR=/data/branding explizit gesetzt, passend zum Volume-Mount und zum in Dockerfile per chown freigegebenen Verzeichnis.

[1.6.2] – 2026-07-18

Behoben

  • scripts/bootstrap-admin.mjs: Konnte ZUGANGSDATEN.md nicht geschrieben werden (z. B. EACCES, weil die per Bind-Mount eingebundene Host-Datei root gehört und der App-Container als nicht-root läuft), brach das Skript ab, nachdem der Admin-Benutzer bereits in der Datenbank angelegt war – das generierte Passwort war dann nirgends mehr zu finden. Schreibt jetzt bei einem Fehler stattdessen E-Mail/Passwort ins Log und beendet sich weiterhin erfolgreich.
  • DEPLOYMENT.md: Schritt 2 fehlte chmod 666 ZUGANGSDATEN.md (der eigentliche Auslöser des Bugs oben). Neue Fehlerbehebung-Einträge für ECONNREFUSED beim Start (harmlose Start-Reihenfolge, löst sich durch den automatischen Neustart von selbst) und für diesen EACCES-Fall inkl. Recovery-Anleitung für einen bereits verwaisten Admin-Account.

[1.6.1] – 2026-07-18

Geändert

  • PostgreSQL-Container ist nicht mehr über einen Host-Port erreichbar (docker-compose.yml: ports: 5433:5432 beim db-Dienst entfernt). App und Dev-Server erreichen die Datenbank weiterhin über das von Docker Compose automatisch angelegte interne Netzwerk (Hostname db) – reduziert die Angriffsfläche, ohne den Betrieb zu ändern. Debugging/Backup weiterhin über docker compose exec db psql/ pg_dump möglich.

Behoben

  • DEPLOYMENT.md: Fehlerbehebung-Abschnitt für password authentication failed for user "postgres" ergänzt (tritt auf, wenn docker compose up vor dem Setzen von LOCAL_PG_PASSWORD läuft oder ohne --env-file .env.local – PostgreSQL übernimmt das Passwort nur beim allerersten Start auf leerem Datenverzeichnis). .env.example warnt jetzt vor Sonderzeichen in LOCAL_PG_PASSWORD, die beim .env-Parsing zu stillen Fehlern führen können.

[1.6.0] – 2026-07-18

Hinzugefügt

  • RSS-Feed des Speiseplans (/feed.xml, ein Eintrag pro Tag mit den Gerichten je Essenszeit für die aktuelle und die nächste Woche) zum Abonnieren in einem Feedreader. Autodiscovery-Link im Seiten-<head> sowie sichtbares RSS-Icon im Kopfbereich der öffentlichen Speisekarte.
  • Kantinen-Bereich: „Vorschläge“-Navigationspunkt zeigt jetzt die Anzahl offener Rezeptvorschläge als Zahl im roten Kreis.
  • Neues DEPLOYMENT.md: Schritt-für-Schritt-Anleitung für die Inbetriebnahme auf einem neuen Server (Docker Compose, Konfiguration, Reverse-Proxy/HTTPS, Updates, Backup).

Geändert

  • Letzte Erwähnungen von Supabase in aktiven Doku-Texten und Code-Kommentaren entfernt/umformuliert (README, Migrationsschema, Passkey-Konfiguration, Branding-Ablage) – die App läuft seit v1.5 vollständig ohne Supabase, das sollte sich jetzt auch durchgängig in der Dokumentation widerspiegeln. Historische CHANGELOG-Einträge bleiben unverändert.
  • .env.example: LOCAL_PG_PASSWORD (von docker-compose.yml verwendet, um die Datenbank-Verbindung der App-Container zusammenzubauen) war bisher nirgends dokumentiert – beim Schreiben der Deployment-Anleitung aufgefallen und ergänzt.

[1.5.0] – 2026-07-18

Hinzugefügt

  • Wochenplan: „Mahlzeit hinzufügen" bietet jetzt ein Suchfeld mit gefilterter Trefferliste statt einer langen Dropdown-Liste zum Durchscrollen.
  • db/seed-demo.sql (npm run db:seed-demo): spielt für lokale Entwicklung/Demos den ursprünglichen Beispieldatensatz ein (Essenszeiten, Allergene, Zusatzstoffe, Testgerichte, zwei Beispielwochen) – kein Teil der automatischen Migrationen, frische Deployments starten weiterhin leer.

Geändert

  • Supabase vollständig entfernt – die App läuft jetzt komplett selbst gehostet, einzige externe Abhängigkeit bleibt optional DeepL.
    • Datenbank: selbst gehostetes PostgreSQL statt Supabase-Cloud-Postgres. Schema in db/migrations/*.sql, wird beim Start automatisch und idempotent angewendet (db/migrate.mjs).
    • Anmeldung: eigene Session-Verwaltung (opake, in der DB gespeicherte Tokens, httpOnly/sameSite=lax-Cookie) statt Supabase Auth. Passwörter werden mit Node-eigenem crypto.scrypt gehasht (keine neue Abhängigkeit).
    • Passkeys: @simplewebauthn ersetzt Supabase's bisher experimentelles WebAuthn-API. Die RP-Domain wird direkt aus APP_URL abgeleitet – kein externer Konfigurationsschritt mehr nötig.
    • Logo/Favicon: lokale Dateiablage (Docker-Volume) statt Supabase-Storage-Bucket, ausgeliefert über /branding/[filename].
    • Autorisierung (öffentlich lesbar / Kantinen-Team schreibt / nur Admin für Einstellungen & Benutzer) läuft jetzt in den API-Routen statt über Postgres-Row-Level-Security.
    • E-Mail-Änderung im eigenen Konto läuft direkt nach Passwort-Bestätigung statt über eine Supabase-Bestätigungsmail (kein SMTP-Server vorhanden).
  • Datenbank startet beim allerersten Deployment leer; beim ersten Start wird automatisch genau ein Admin-Benutzer mit zufällig generiertem Passwort angelegt, die Zugangsdaten landen in ZUGANGSDATEN.md.

Behoben

  • „Mindestens 1 Passkey nötig, um die Passwort-Anmeldung zu deaktivieren" wurde bisher nur clientseitig geprüft; ein manuell gebauter Request hätte die Passwort-Anmeldung auch ohne Passkey deaktivieren können. Jetzt zusätzlich serverseitig erzwungen.
  • Logo-/Favicon-Upload akzeptierte anhand des vom Browser gemeldeten Dateityps auch SVG-Dateien. Da diese (anders als beim vorherigen Supabase-Storage-Bucket auf fremder Domain) jetzt auf der eigenen Origin ausgeliefert werden, hätte eine SVG mit eingebettetem <script> bei direktem Aufruf der Datei-URL im Browser eines anderen angemeldeten Admins ausgeführt werden können. Upload akzeptiert jetzt nur noch eine Whitelist an Rasterformaten (png/jpg/webp/gif/ico); vor dem Merge im Rahmen der Sicherheitsprüfung gefunden und behoben.

Hinweis für bestehende Docker-Installationen

Das Docker-Volume pgdata diente bisher nur als Lese-Kopie/Backup und wird mit v1.5 zur primären Datenbank. Es enthält noch das alte Supabase-Mirror-Schema und muss vor dem Upgrade entfernt werden (docker compose down -v, danach docker compose up -d --build), damit die neuen Migrationen auf einer leeren Datenbank laufen.

[1.4.0] – 2026-07-18

Hinzugefügt

  • Essenszeiten (Brotzeit/Mittagessen/…) vollständig verwaltbar: anlegen, umbenennen (inkl. EN/PL), Uhrzeit ändern, löschen und per Pfeil-Buttons neu anordnen – neue Seite „Essenszeiten" im Kantinen-Bereich. Löschen entfernt zugewiesene Gerichte automatisch aus allen Wochenplänen.

Geändert

  • „Automatisch übersetzen"-Button bei Gerichten/Allergenen/Zusatzstoffen ist nur noch sichtbar, wenn DEEPL_API_KEY gesetzt ist, statt erst nach Klick auf die fehlende Konfiguration hinzuweisen.

Behoben

  • Sprachumschalter (DE/EN/PL) erschien auf der öffentlichen Speisekarte in der mobilen Ansicht doppelt.

[1.3.0] – 2026-07-18

Hinzugefügt

  • Mehrsprachigkeit für die komplette Anwendung (Deutsch, Englisch, Polnisch): Sprachumschalter (Cookie-basiert, kein Neuladen der Seite nötig), sämtliche Oberflächentexte übersetzt
  • Gerichte, Bereiche, Allergene und Zusatzstoffe zusätzlich mit englischem/polnischem Namen; öffentliche Speisekarte zeigt je nach gewählter Sprache automatisch den passenden Namen (Fallback: Deutsch, falls keine Übersetzung hinterlegt ist)
  • Automatische Übersetzung per DeepL: Button „Automatisch übersetzen“ beim Anlegen/Bearbeiten von Gerichten, Allergenen und Zusatzstoffen; Ergebnis bleibt danach manuell korrigierbar. Aktivierung über die neue Docker-Variable DEEPL_API_KEY – ohne Key bleibt der Button inaktiv, die Felder lassen sich weiterhin von Hand ausfüllen
  • Rezeptvorschläge im öffentlichen Bereich: nicht angemeldete Besucher können über „Rezept vorschlagen“ ein fehlendes Gericht vorschlagen (Name + optionale Beschreibung), inkl. Dublettenprüfung gegen bestehende Gerichte und einfachem Honeypot-Spamschutz
  • Neue Seite „Vorschläge“ im Kantinen-Bereich: eingereichte Vorschläge sichten, als Gericht übernehmen oder ablehnen

Behoben

  • Passwort-wiederholen-Feld beim Bearbeiten eines Benutzers erschien erst, nachdem im ersten Passwortfeld schon getippt wurde – wirkte wie ein einzelnes Pflichtfeld
  • Anmelden-Button überlappte auf Mobilgeräten mit breiten Logos (Banner-Format) das Logo, da er absolut in der oberen Ecke positioniert war

[1.2.0] – 2026-07-18

Hinzugefügt

  • „Heute"-Button in der Wochennavigation (öffentliche Speisekarte und Wochenplan-Editor)
  • Mobile Ansicht der öffentlichen Speisekarte: umschaltbar zwischen Tag (Standard) und Woche, unabhängig von der Desktop-Tabelle
  • Allergene und Zusatzstoffe wieder pro Gericht auswählbar (Chip-Auswahl im Formular) und als kleine Kürzel neben dem Gerichtnamen sichtbar – in Speisekarte, mobiler Ansicht und Wochenplan-Editor
  • Passwort-Wiederholung beim Anlegen neuer Benutzer und beim optionalen Passwort-Reset
  • Passwort-Anmeldung pro Konto deaktivierbar (nur wenn mindestens ein Passkey registriert ist), Durchsetzung im Login-Flow
  • SITE_TITLE-Umgebungsvariable für Browser-Tab-Titel und Überschrift ohne Logo
  • Austauschbares Favicon über den Admin-Design-Bereich

Geändert

  • Gemeinsame Navigation für Kantinen- und Admin-Bereich statt zwei getrennter Menüs
  • Live-Suche bei den Gerichten
  • Mehrfachauswahl zum Batch-Löschen von Gerichten
  • App erreichbar auf 0.0.0.0 statt nur localhost (Docker und nativer Betrieb)
  • Projekt umbenannt von „Speisekarte“ zu „canteen-menu“ (Docker-, npm- und Supabase-Namen; deutsche In-App-Texte unverändert)
  • Öffentliche URL über APP_URL konfigurierbar (CSRF-Origin-Check hinter Reverse-Proxy, Passkey-Domain)

Behoben

  • Next.js band app/favicon.ico zusätzlich zu einem dynamisch gesetzten Favicon ein – Favicon wird jetzt immer explizit gesetzt
  • Weiterleitungen (Logout, Zugriffsschutz) übernahmen nach der 0.0.0.0-Bindung fälschlich die Server-Adresse statt des aufgerufenen Hosts

[1.1.0] – 2026-07-17

Hinzugefügt

  • Versionsnummer im Fußbereich jeder Seite

[1.0.0] – 2026-07-17

Erste vollständige Version.

Hinzugefügt

  • Öffentliche Speisekarte ohne Login: Wochenansicht Mo–Fr mit den Bereichen Brotzeit, Mittagessen, Mittagessen vegetarisch und Suppe; Wochen-Navigation; Logo zentriert; Allergene & Zusatzstoffe unterhalb der Karte
  • Anmeldung mit E-Mail/Passwort oder Passkey
  • Kantinen-Bereich: Gerichte anlegen/bearbeiten/löschen, Wochenplan pflegen, globale Allergen-/Zusatzstofflisten verwalten
  • Admin-Bereich: Benutzerverwaltung, Farbgebung, Logo-Upload
  • Eigenes Konto verwalten: Name, E-Mail, Passwort, Passkeys
  • Row-Level-Security, HTTP-Security-Header, CSRF-Origin-Check
  • Docker-Setup (App-Image, lokale PostgreSQL-Kopie, Dev-Profil ohne lokales Node.js)
  • Lokale PostgreSQL-Kopie mit Sync-Skript