Files
certain/docs/ARCHITECTURE.md
GuidoandClaude Opus 4.8 2c795a57c8 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>
2026-08-19 18:27:42 +02:00

2.8 KiB
Raw Permalink Blame History

Architektur

Überblick

Ein einzelner Python-Prozess (uvicorn/FastAPI) liefert sowohl die JSON-API unter /api/* als auch das gebaute Frontend (web/dist, mit SPA-Fallback) auf einem Port aus. HTTPS terminiert extern der Nginx Proxy Manager; der Dienst lauscht nur auf 127.0.0.1:<APP_PORT>.

Browser ──HTTPS──> Nginx Proxy Manager ──HTTP──> 127.0.0.1:APP_PORT (uvicorn)
                                                   ├── /api/*  → FastAPI-Router
                                                   └── /*      → web/dist (SPA)

Verzeichnisse

backend/  app/ (config, database, security, deps, main, models, schemas, seed,
             migrate, routers/*, services/*), migrations/ (Alembic), requirements.txt
web/      src/ (main.jsx, App.jsx, brand.js, api.js, auth.jsx, settings.jsx,
             i18n.js, locales/, format.js, theme.js, styles.css, finance.css,
             components/, pages/), package.json, vite.config.js
deploy/   certain-finance.service, install.sh, update.sh, env.example
docs/     ARCHITECTURE.md, ROADMAP.md

Backend

  • Konfiguration (app/config.py): Umgebungsvariablen mit Präfix APP_. Standardwerte sind dev-freundlich; Produktivwerte kommen aus /etc/certain-finance/env.
  • Datenbank (app/database.py): SQLite mit WAL, foreign_keys=ON, Busy-Timeout.
  • Migrationen: Alembic (migrations/), render_as_batch=True (Pflicht für SQLite). Werden beim App-Start automatisch angewandt (app/migrate.py) – und vom Install-/ Update-Skript.
  • Auth (app/security.py, app/services/sessions.py, app/deps.py): argon2- Passwort-Hashing; server-seitige Sitzungen (im Cookie nur das Klartext-Token, in der DB nur dessen SHA-256-Hash). Erst-Admin beim ersten Start; weitere Nutzer legt der Admin mit Temporär-Passwort an (Änderung beim ersten Login erzwungen).
  • Isolation: Ab Phase 1 trägt jede fachliche Tabelle ein owner_id; jeder Nutzer sieht ausschließlich seine eigenen Daten.

Frontend

  • React 18 + Vite + reines JSX, Router mit Protected-Wrapper (Login immer nötig).
  • Design-Tokens in styles.css (aus der Vorlage übernommen), Ergänzungen in finance.css. Volle Hell/Dunkel-Unterstützung (prefers-color-scheme + data-theme).
  • i18n (react-i18next): Deutsch Standard, Englisch optional; Sprache aus der Benutzer-Einstellung locale.
  • Icons: ausschließlich Inline-SVG (components/Icon.jsx), niemals Emojis.
  • API-Client (api.js): alles über /api, immer credentials:"include" (Cookie-Sitzung), zentrales 401-Handling.

Namensgebung

Der Anzeigename „Certain Finance" steht nur in web/src/brand.js und backend/app/branding.py. Intern ist alles generisch (Paket app, Env-Präfix APP_). Der Betriebs-Slug certain-finance (systemd-Dienst, Pfade) steht in den Deploy-Skripten je einmal oben als Variable.