feat: Phase 0 – Gerüst (FastAPI+SQLite, Multi-User-Login, React-App-Shell, Deploy)

Grundgerüst für Certain Finance:
- Backend: FastAPI + SQLAlchemy + SQLite, Alembic-Migrationen (Batch-Mode),
  argon2-Passwort-Hashing, server-seitige Sitzungen im Cookie, Erst-Admin,
  Benutzerverwaltung mit Temporär-Passwort, Einstellungen je Benutzer.
- Ein Prozess, ein Port: uvicorn liefert API (/api) und gebautes SPA aus,
  inkl. SPA-Deeplink-Fallback.
- Frontend: React 18 + Vite + JSX, Design-Tokens (Light/Dark), i18n DE/EN,
  Inline-SVG-Icons (keine Emojis), Login, Passwort-ändern, Dashboard-Platzhalter,
  Benutzer- und Einstellungsseiten.
- Deploy: nativer LXC-Installer + Update-Skript (systemd), env-Vorlage, Doku.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Guido
2026-08-19 18:27:42 +02:00
co-authored by Claude Opus 4.8
commit 2c795a57c8
59 changed files with 6419 additions and 0 deletions
+85
View File
@@ -0,0 +1,85 @@
{
"common": {
"save": "Speichern",
"cancel": "Abbrechen",
"delete": "Löschen",
"create": "Anlegen",
"edit": "Bearbeiten",
"loading": "Lädt…",
"logout": "Abmelden",
"admin": "Administrator",
"user": "Benutzer",
"close": "Schließen",
"retry": "Erneut versuchen",
"actions": "Aktionen"
},
"nav": {
"overview": "Übersicht",
"accounts": "Konten",
"categories": "Kategorien",
"transactions": "Buchungen",
"budget": "Budget",
"import": "Import",
"system": "System",
"users": "Benutzer",
"settings": "Einstellungen"
},
"login": {
"subtitle": "Bitte anmelden",
"username": "Benutzername",
"password": "Passwort",
"submit": "Anmelden",
"error": "Benutzername oder Passwort falsch",
"expired": "Deine Sitzung ist abgelaufen. Bitte erneut anmelden."
},
"changepw": {
"title": "Passwort ändern",
"forcedHint": "Bitte lege ein eigenes Passwort fest, bevor du fortfährst.",
"current": "Aktuelles Passwort",
"new": "Neues Passwort",
"repeat": "Neues Passwort wiederholen",
"submit": "Passwort speichern",
"mismatch": "Die neuen Passwörter stimmen nicht überein.",
"saved": "Passwort geändert."
},
"users": {
"title": "Benutzer",
"new": "Neuer Benutzer",
"username": "Benutzername",
"displayName": "Anzeigename",
"password": "Temporär-Passwort",
"passwordHint": "Der Benutzer wird beim ersten Login zum Ändern aufgefordert.",
"role": "Rolle",
"status": "Status",
"active": "Aktiv",
"inactive": "Deaktiviert",
"resetPassword": "Passwort zurücksetzen",
"deleteConfirm": "Diesen Benutzer wirklich löschen?",
"created": "Benutzer angelegt.",
"you": "(du)"
},
"settings": {
"title": "Einstellungen",
"baseCurrency": "Hauptwährung",
"baseCurrencyHint": "Währung für Budget-Summen und Dashboard-Gesamtwerte.",
"locale": "Sprache",
"theme": "Darstellung",
"themeSystem": "Automatisch (System)",
"themeLight": "Hell",
"themeDark": "Dunkel",
"budgetStartDay": "Budget-Monat beginnt am",
"budgetStartDayHint": "Tag, an dem dein Budget-Monat startet (z. B. 25.).",
"dateFormat": "Datumsformat",
"saved": "Gespeichert.",
"languageDe": "Deutsch",
"languageEn": "Englisch"
},
"dashboard": {
"title": "Übersicht",
"empty": "Noch keine Karten. Das Dashboard wird in einer späteren Phase ausgebaut."
},
"server": {
"unreachable": "Server nicht erreichbar.",
"sessionKept": "Deine Anmeldung ist noch gültig – sobald der Server wieder antwortet, geht es weiter."
}
}
+85
View File
@@ -0,0 +1,85 @@
{
"common": {
"save": "Save",
"cancel": "Cancel",
"delete": "Delete",
"create": "Create",
"edit": "Edit",
"loading": "Loading…",
"logout": "Log out",
"admin": "Administrator",
"user": "User",
"close": "Close",
"retry": "Try again",
"actions": "Actions"
},
"nav": {
"overview": "Overview",
"accounts": "Accounts",
"categories": "Categories",
"transactions": "Transactions",
"budget": "Budget",
"import": "Import",
"system": "System",
"users": "Users",
"settings": "Settings"
},
"login": {
"subtitle": "Please sign in",
"username": "Username",
"password": "Password",
"submit": "Sign in",
"error": "Wrong username or password",
"expired": "Your session has expired. Please sign in again."
},
"changepw": {
"title": "Change password",
"forcedHint": "Please set your own password before continuing.",
"current": "Current password",
"new": "New password",
"repeat": "Repeat new password",
"submit": "Save password",
"mismatch": "The new passwords do not match.",
"saved": "Password changed."
},
"users": {
"title": "Users",
"new": "New user",
"username": "Username",
"displayName": "Display name",
"password": "Temporary password",
"passwordHint": "The user will be asked to change it on first login.",
"role": "Role",
"status": "Status",
"active": "Active",
"inactive": "Disabled",
"resetPassword": "Reset password",
"deleteConfirm": "Really delete this user?",
"created": "User created.",
"you": "(you)"
},
"settings": {
"title": "Settings",
"baseCurrency": "Base currency",
"baseCurrencyHint": "Currency for budget totals and dashboard aggregates.",
"locale": "Language",
"theme": "Appearance",
"themeSystem": "Automatic (system)",
"themeLight": "Light",
"themeDark": "Dark",
"budgetStartDay": "Budget month starts on",
"budgetStartDayHint": "Day your budget month starts (e.g. the 25th).",
"dateFormat": "Date format",
"saved": "Saved.",
"languageDe": "German",
"languageEn": "English"
},
"dashboard": {
"title": "Overview",
"empty": "No cards yet. The dashboard will be built out in a later phase."
},
"server": {
"unreachable": "Server unreachable.",
"sessionKept": "Your session is still valid – once the server responds again, it will continue."
}
}