Files
moneyfy/CHANGELOG.md
T
Jonas MenzelandClaude Opus 5 c110340628
CI / backend (push) Successful in 2m49s
Images bauen / build (frontend) (push) Successful in 3m12s
Images bauen / build (backend) (push) Successful in 3m22s
CI / frontend (push) Successful in 6m20s
feat: Kommando zum Setzen des Passworts
Die Erstanlage beim Start greift nur, solange die Benutzertabelle leer ist. Wer
.env.example zuerst unverändert übernimmt, bekommt einen Benutzer mit dem
Platzhalter; ein späteres Ändern von MONEYFY_ADMIN_PASSWORD bleibt danach
wirkungslos. Das Kommando setzt das Passwort direkt, legt den Benutzer bei
Bedarf an und beendet alle offenen Sitzungen.

docs/deployment.md nennt jetzt die drei Ursachen einer fehlgeschlagenen
Anmeldung in der Reihenfolge ihrer Häufigkeit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014e7t8UpmoVNMtWivY5LiSH
2026-09-09 23:40:42 +02:00

10 KiB
Raw Blame History

Changelog

Alle nennenswerten Änderungen an diesem Projekt werden hier dokumentiert.

Das Format orientiert sich an Keep a Changelog, die Versionierung folgt Semantic Versioning.

Unreleased

Hinzugefügt

  • python -m app.scripts.reset_password setzt das Passwort eines Benutzers oder legt ihn an. Nötig, weil die Erstanlage beim Start nur bei leerer Benutzertabelle greift und ein nachträglich geändertes MONEYFY_ADMIN_PASSWORD danach wirkungslos bleibt.

0.1.1 2026-09-09

Politur und ein Fehler, den erst die CI zutage gefördert hat.

Hinzugefügt

  • Demo-Seed mit einem realistischen deutschen Haushalt: drei Konten, zehn Firmen samt Logos, zwölf wiederkehrende Posten (Miete, Strom, Netflix, Spotify, jährliche Kfz-Versicherung, Handyvertrag mit Mindestlaufzeit, Kredit über 36 Raten, Gehalt), bestätigte Historie, Buchungen, Budgets und Sparziele. Alle Termine liegen relativ zum heutigen Monat. Aufruf über make seed-demo.
  • Tastaturkürzel: n neue Buchung, r neuer Posten, / Suche, ? Übersicht. Sie greifen nur, solange kein Eingabefeld den Fokus hat.
  • Fehlergrenze für unerwartete Renderfehler und eine eigene 404-Seite.

Geändert

  • Farbtoken beider Modi gegen die WCAG-Kontraste geprüft und nachgezogen: der Hilfstext lag im hellen Modus bei 2,56:1, Weiß auf dem Primärknopf bei 3,30:1. Jetzt erreicht jeder Text mindestens 4,5:1 und jedes Bedienelement 3:1.
  • Die Abo-Übersicht heißt „Laufende Kosten" sie enthält jede wiederkehrende Ausgabe, auch Miete und Sparplan, und nicht nur Abonnements.
  • build.yml weicht auf den automatischen GITEA_TOKEN aus, wenn das Secret REGISTRY_TOKEN fehlt, und schreibt bei einer gescheiterten Anmeldung die nötigen Schritte in die Job-Zusammenfassung.

Behoben

  • Die Testsuite hing an einer nicht eingecheckten lokalen .env: ohne sie galt COOKIE_SECURE=true, httpx verwarf die Secure-Cookies über http, und 106 Tests scheiterten mit 401. Aufgefallen ist das erst in der CI.

0.1.0 2026-09-09

Erste lauffähige Fassung: Planung, Auswertung und Benachrichtigung stehen, die Anwendung lässt sich per Compose betreiben.

Aus diesem Tag sind keine Images entstanden der Build scheiterte am noch nicht angelegten Registry-Secret. Verwende 0.1.1.

Hinzugefügt

  • Projektgerüst mit getrennten Bereichen für Backend, Frontend, Dokumentation und CI.

  • FastAPI-Backend mit Konfiguration über pydantic-settings und einheitlichem Fehlerformat ({"detail": ..., "code": ...}).

  • Vollständiges Datenmodell als SQLAlchemy-2.0-Modelle: Konten, Kategorien, Firmen, Logo-Assets, Recurrences, Preishistorie, Occurrences, Buchungen, Budgets samt Vorlagen, Sparziele, Rücklagen, Benachrichtigungsregeln und -protokoll, Benutzer.

  • Alembic-Setup gegen die Async-Engine samt Erstmigration des kompletten Schemas; der Downgrade entfernt auch die nativen Enum-Typen, sodass Auf- und Abwärtsmigration beliebig oft wiederholbar sind.

  • Idempotenter Seed für den deutschen Standard-Kategoriebaum (35 Kategorien) und die Standard-Benachrichtigungsregeln.

  • Endpunkte GET /api/health und GET /api/version.

  • Testinfrastruktur mit pytest, httpx und transaktionsisolierten Fixtures.

  • .env.example, docker-compose.override.yml.example und Makefile für die lokale Entwicklung.

  • Recurrence-Engine (app/services/recurrence.py) mit vollständiger RFC-5545-Expansion: expand liefert nominale und tatsächliche Zahltage, expand_by_due_date filtert nach dem Zahltag für Kalender und Monatsberichte.

  • Wochenend- und Feiertagsverschiebung über den NRW-Kalender; das nominale Datum bleibt stabiler Schlüssel zur Zuordnung materialisierter Fälligkeiten.

  • Auflösung der Preishistorie je Fälligkeitsdatum, Overlays aus occurrence, Kappung der Serie durch until, Kündigung und Ratenzahl.

  • installments_remaining (Restraten und Restschuld), contract_term und notice_deadline (Mindestlaufzeit, automatische Verlängerung, Kündigungsfrist) sowie annual_burden und monthly_reserve für die Rücklagenbildung.

  • validate_rrule und next_dates als Grundlage für Eingabeprüfung und Vorschau.

  • Authentifizierung mit Argon2id, JWT in httpOnly-Cookies (Access 30 min, Refresh 14 Tage) und echter Token-Rotation über die Tabelle refresh_token; ein erneut eingelöstes Refresh-Token beendet alle Sitzungen.

  • AuthProvider-Protokoll mit lokalem Provider als Vorbereitung für OIDC.

  • Anlage des Administrators beim Erststart mit erzwungenem Passwortwechsel; bis dahin sind alle Fachrouten gesperrt.

  • CRUD für Konten, Kategorien, Firmen, wiederkehrende Posten, Preisversionen, Buchungen, Budgets, Budgetvorlagen und Sparziele.

  • Fälligkeiten-API mit Overlay-Logik: abrufen, bestätigen (auch mit abweichendem Betrag oder Datum), auslassen und zurücksetzen.

  • Kontosalden zum Stichtag aus Eröffnungssaldo, Buchungen und bestätigten Fälligkeiten, inklusive abweichender Konten je Fälligkeit.

  • Monatsübersicht mit Plan-Ist-Vergleich, Aufteilung in fixe und variable Kosten, Rücklagen und Vergleich zum Vormonat.

  • Vollständig annotiertes OpenAPI-Dokument unter /api/docs.

  • Logo-Service mit fünfstufiger Provider-Kette: lokal gevendorte simple-icons (3.459 Marken, rund 2 MB), logo.dev und Brandfetch bei gesetztem Schlüssel, Favicon-Fallback und generierter Buchstaben-Avatar als Garantie.

  • Logo-Cache im Dateisystem, benannt nach dem SHA-256 des Inhalts; Auslieferung ausschließlich über GET /api/logos/{id} mit immutable-Cache-Header und ETag-Unterstützung.

  • Ermittlung der Markenfarbe: bei SVG aus den fill-Attributen, bei Rastergrafiken per k-Means über 64×64 Pixel; dazu eine im HSL-Raum aufgehellte Variante, die gegen den dunklen Hintergrund mindestens 4,5:1 Kontrast erreicht.

  • Auswahldialog-Endpunkte: Kandidatensuche mit Vorauswahl, Übernahme eines Kandidaten, Upload (SVG/PNG/JPEG bis 1 MB) und Zurücksetzen.

  • Die Logosuche läuft nach dem Anlegen einer Firma im Hintergrund; der Aufruf antwortet sofort.

  • make vendor-icons erzeugt den simple-icons-Index neu.

  • Frontend auf React 18, TypeScript, Vite und TailwindCSS mit dunklem Standard- Theme, umschaltbar und im Browser gespeichert.

  • Anmeldung, erzwungener Passwortwechsel und Layout mit Seitenleiste.

  • TanStack-Query-Client mit zentralen Fehler-Toasts und stiller Token-Erneuerung bei abgelaufenem Access-Token.

  • Seiten für wiederkehrende Posten (inklusive Detail-Drawer mit Preishistorie, Ratenfortschritt und Vertragsfristen), Buchungen, Firmen und Einstellungen.

  • Geführter RRULE-Editor mit sechs Vorlagen, Expertenmodus, deutscher Klartextfassung und den nächsten fünf Terminen aus dem preview-Endpunkt.

  • Firmen als Kachelgrid mit Logo, Markenfarbe, Jahreskosten und Vertragszahl; Logo-Auswahldialog mit Vorauswahl, erneuter Suche über eine Domain und Upload.

  • Beträge durchgängig über Intl.NumberFormat('de-DE'); Eingaben akzeptieren deutsche wie englische Schreibweise.

  • Auswertungen: Monatsübersicht, 12-Monats-Forecast, Kategorienaufteilung mit Drilldown, Abo-Übersicht mit Jahreskosten, Jahresvergleich, Cashflow-Kalender, Budget-Ampel und Fortschritt der Sparziele.

  • Alle Berichte bauen auf einer gemeinsamen Bewegungsschicht auf, sodass Monatsübersicht, Forecast und Kalender nachweislich dieselben Zahlen zeigen.

  • Budgetübertrag über Monatsgrenzen und Budgets auf Oberkategorien, die deren Unterkategorien einschließen.

  • GET /api/reports/dashboard bündelt alles, was die Startseite braucht.

  • Export als CSV (Semikolon, Komma als Dezimaltrenner, UTF-8 mit BOM) und XLSX mit typisierten Beträgen und deutschem Zahlenformat für Buchungen, Posten und die Monatsauswertung.

  • Dashboard, Cashflow-Kalender, Budget-, Sparziel- und Auswertungsseite im Frontend; Diagramme mit Recharts.

  • Die Farbpalette der Diagramme wurde gegen die hellen und dunklen Flächen der Anwendung auf Kontrast und Farbfehlsichtigkeit geprüft. Grün/Rot schied als Serienpaar aus (bei Deuteranopie nicht unterscheidbar) und bleibt den Vorzeichen im Text vorbehalten.

  • Benachrichtigungen über SMTP (HTML-Mail mit eingebetteten Firmenlogos) und Apprise, gesteuert über Regeln je Anlass und Kanal.

  • Vier Anlässe: bald fällige Posten, Kündigungsfristen (30, 14 und 7 Tage vor dem Termin), überschrittene Budgets und anstehende Vertragsverlängerungen.

  • APScheduler-Job täglich um 07:00 Europe/Berlin, der zugleich abgelaufene Sitzungen aufräumt; verpasste Läufe werden einmal nachgeholt.

  • Duplikatsschutz über (rule_id, ref_type, ref_id, Zieltag). Maßgeblich ist der Zieltag des Ereignisses, nicht der Versandtag ein zweiter Lauf am selben oder am nächsten Tag erzeugt keine zweite Nachricht. Ein fehlgeschlagener Versand wird beim nächsten Lauf erneut versucht.

  • POST /api/notifications/test verschickt eine Testnachricht über beide Kanäle, POST /api/notifications/run führt einen Lauf sofort aus.

  • Benachrichtigungen sind in den Einstellungen pflegbar, samt Einrichtungsstand der Kanäle und Versandprotokoll.

  • Mehrstufige Dockerfiles für Backend und Frontend, beide mit einer Stufe für die Entwicklung und einer für den Betrieb; beide Images laufen unprivilegiert.

  • Entrypoint des Backends wartet auf die Datenbank, spielt die Migrationen ein und legt die Stammdaten nur beim leeren Kategoriebaum an.

  • docker-compose.yml mit Netz-Trennung (die Datenbank ist ausschließlich intern erreichbar), Healthchecks und benannten Volumes für Datenbank und Logo-Cache.

  • nginx liefert das Bundle aus und reicht /api weiter; index.html bleibt ungecacht, die gehashten Assets ein Jahr.

  • Gitea-Workflows ci.yml (Lint, Tests, Bundle-Bau) und build.yml (Images für linux/amd64 in die Gitea-Registry, ohne Deploy-Schritt).

  • docs/runner.md zur Einrichtung des act_runners samt Fehlersuche und docs/deployment.md zu NPMplus, Aktualisierung und Sicherung.

  • python -m app.scripts.seed --if-empty seedt nur bei leerem Kategoriebaum.

Geändert

  • SECRET_KEY muss mindestens 32 Zeichen lang sein (Vorgabe von HS256); in Produktion wird der Platzhalterwert beim Start abgelehnt.
  • Der Bildtyp eines Uploads wird ausschließlich am Inhalt bestimmt; die vom Aufrufer gemeldete Kopfzeile wird nicht mehr als Nachweis akzeptiert.