# Architektur-Regeln – Mitai Jinkendo > **PFLICHTLEKTÜRE für Claude Code vor jeder Implementierung.** > Diese Regeln sind verbindlich und dürfen nicht ohne explizite > Genehmigung des Nutzers abgeändert werden. --- ## 1. Router-Architektur ### 1.1 Ein Modul = Ein Router Jedes fachliche Modul hat genau eine Router-Datei in `backend/routers/`. ``` backend/routers/ ├── auth.py # Authentifizierung ├── profiles.py # Nutzerprofile ├── weight.py # Gewichts-Tracking ├── sleep.py # Schlaf-Modul ├── training_types.py # Trainingstypen + HF └── ... # je neues Modul = neue Datei ``` **Regeln:** - Kein Endpoint darf außerhalb seines thematischen Routers definiert werden - Neue Module immer als neue Router-Datei anlegen, nie in bestehende einfügen - Router in `main.py` registrieren: `app.include_router(modul.router, prefix="/api")` - Router-Datei-Name = Modul-Name in `version.py` MODULE_VERSIONS ### 1.2 API-First Prinzip Jede Funktion ist zuerst als API-Endpoint implementiert – die UI nutzt ausschließlich diese Endpoints über `api.js`. Keine Business-Logik im Frontend. ```python # ✅ Richtig: Logik im Backend-Endpoint @router.get("/sleep/stats") def get_sleep_stats(session=Depends(require_auth)): # Berechnung hier return {"avg_duration": ..., "sleep_debt": ...} # ❌ Falsch: Berechnung im Frontend const sleepDebt = entries.reduce((sum, e) => sum + (goal - e.duration), 0) ``` ### 1.3 Einheitliche Fehlerbehandlung ```python # ✅ Immer dieses Format: raise HTTPException(status_code=404, detail="Eintrag nicht gefunden") # Response: {"detail": "Eintrag nicht gefunden"} # ❌ Nie eigene Formate: return {"error": "not found"} return {"message": "Fehler", "success": False} ``` --- ## 2. Versionskontrollsystem ### 2.1 Versionierungsschema **Semantic Versioning: `MAJOR.MINOR.PATCH`** | Typ | Wann | Beispiel | |-----|------|---------| | MAJOR | Breaking Change, DB-Migration inkompatibel | 9.0.0 → 10.0.0 | | MINOR | Neues Feature, neues Modul | 9.2.0 → 9.3.0 | | PATCH | Bugfix, kleine Änderung, Refactor | 9.3.0 → 9.3.1 | ### 2.2 Versions-Dateien **Backend: `backend/version.py`** ```python APP_VERSION = "9.3.0" BUILD_DATE = "2026-03-22" MODULE_VERSIONS = { "auth": "1.2.0", "profiles": "1.1.0", "weight": "1.0.3", "circumference": "1.0.1", "caliper": "1.0.1", "activity": "1.1.0", "nutrition": "1.0.2", "photos": "1.0.0", "insights": "1.3.0", "prompts": "1.1.0", "admin": "1.2.0", "stats": "1.0.1", "exportdata": "1.1.0", "importdata": "1.0.0", "membership": "2.1.0", } CHANGELOG = [ { "version": "9.3.0", "date": "2026-03-22", "changes": [ "Feature: Sleep Module (sleep_log, JSONB-Segmente)", "Feature: Vitalwerte-Seite in Navigation", "Feature: Trainingstypen-Kategorisierung", ] }, { "version": "9.2.1", "date": "2026-03-20", "changes": [ "Fix: Feature-Enforcement Rollback", "Fix: Erholungsstatus-Gewichtung korrigiert", ] }, ] ``` **Frontend: `frontend/src/version.js`** ```javascript export const APP_VERSION = "9.3.0" export const BUILD_DATE = "2026-03-22" export const PAGE_VERSIONS = { Dashboard: "1.3.0", LoginScreen: "1.1.0", WeightPage: "1.0.3", ActivityPage: "1.2.0", NutritionPage: "1.1.0", AnalysisPage: "1.3.0", SettingsPage: "1.4.0", AdminPanel: "1.2.0", SubscriptionPage: "1.0.0", // Neue Seiten hier eintragen } ``` ### 2.3 Versions-Endpoint **`GET /api/version`** – öffentlich (kein Auth erforderlich) ```json { "app_version": "9.3.0", "build_date": "2026-03-22", "backend_version": "9.3.0", "modules": { "auth": "1.2.0", "sleep": "1.0.0" }, "db_schema_version": "20260322", "environment": "production" } ``` Dieser Endpoint wird in `backend/routers/version.py` implementiert und liest direkt aus `version.py`. ### 2.4 Versions-Anzeige in der App **Settings-Seite – Versions-Panel:** ``` System-Versionen ───────────────────────────────────── App (gesamt) 9.3.0 Backend 9.3.0 ✓ erreichbar Frontend 9.3.0 ✓ geladen DB-Schema 20260322 Umgebung production ───────────────────────────────────── Module auth 1.2.0 sleep 1.0.0 membership 2.1.0 [alle Module...] ───────────────────────────────────── [Changelog] [Cache leeren] ``` Frontend ruft beim Laden der Settings-Seite `/api/version` ab und vergleicht mit der eigenen `APP_VERSION` aus `version.js`. Bei Abweichung: Warnung anzeigen. ### 2.5 Pflicht-Regel: Versions-Bump bei jedem Commit **Jede Code-Änderung erfordert:** 1. Versions-Bump in `backend/version.py` (APP_VERSION + betroffenes MODULE_VERSION) 2. Versions-Bump in `frontend/src/version.js` (APP_VERSION + betroffene PAGE_VERSION) 3. Changelog-Eintrag in `backend/version.py` CHANGELOG **Claude Code prüft das im `/deploy` Command automatisch.** Kein Commit ohne Versions-Bump – keine Ausnahme. ### 2.6 DB-Schema-Version Format: `YYYYMMDD` (Datum der letzten Migration) Gespeichert in `backend/version.py`: ```python DB_SCHEMA_VERSION = "20260322" ``` Bei jeder Schema-Änderung (ALTER TABLE, neue Tabelle) → DB_SCHEMA_VERSION aktualisieren. --- ## 3. Datenbankregeln ### 3.1 Pflichtfelder für neue Tabellen ```sql -- Jede neue Tabelle braucht: id SERIAL PRIMARY KEY, created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW() ``` ### 3.2 Source-Tracking bei Import-Daten Tabellen die Daten aus externen Quellen empfangen brauchen: ```sql source VARCHAR(50) DEFAULT 'manual' -- Werte: 'manual' | 'apple_health' | 'garmin' | 'withings' ``` Manuelle Einträge (`source = 'manual'`) haben IMMER Vorrang bei Reimport: ```sql -- Reimport überschreibt nur nicht-manuelle Einträge: INSERT INTO sleep_log (...) ON CONFLICT (profile_id, date) DO UPDATE SET ... WHERE sleep_log.source != 'manual' ``` ### 3.3 Profile-ID Isolation Jede Tabelle mit Nutzerdaten hat `profile_id` als Foreign Key. Kein Endpoint gibt Daten eines anderen Profils zurück. Profile-ID kommt IMMER aus der Session, nie aus Request-Parametern. ### 3.4 Boolean-Werte ```sql -- PostgreSQL Boolean (nicht SQLite 0/1): WHERE active = true ✓ WHERE active = 1 ✗ ``` --- ## 4. Frontend-Regeln ### 4.1 Alle API-Calls über api.js ```javascript // ✅ Richtig: import { api } from '../utils/api' const data = await api.listSleep() // ❌ Falsch: const r = await fetch('/api/sleep') ``` ### 4.2 Neue Seite = Eintrag in PAGE_VERSIONS Jede neue Seite in `frontend/src/version.js` registrieren. ### 4.3 CSS-Variablen statt Hardcoded-Farben ```javascript // ✅ Richtig: style={{color: 'var(--accent)'}} // ❌ Falsch: style={{color: '#1D9E75'}} ``` ### 4.4 Fehlerbehandlung in allen async Funktionen ```javascript try { const data = await api.meinEndpoint() setData(data) } catch(e) { setError(e.message) } finally { setLoading(false) } ``` --- ## 5. Git & Deployment-Regeln ### 5.1 Nie direkt auf main pushen Immer über Pull Request in Gitea: develop → main. develop Branch niemals löschen. ### 5.2 Commit-Message Format ``` feat: neues Feature oder Modul fix: Bugfix refactor: Umbau ohne Funktionsänderung docs: Dokumentation version: Versions-Bump ci: CI/CD Änderungen chore: Maintenance ``` ### 5.3 Versions-Bump im Commit ``` feat: Sleep Module v1.0.0 - sleep_log Tabelle mit JSONB-Segmenten - Import aus Apple Health CSV - Korrelationen Schlaf <-> Ruhepuls version: 9.3.0 (backend + frontend) module: sleep 1.0.0 ``` --- ## 6. Dokumentations-Regeln ### 6.1 Neue Module dokumentieren Bei jedem neuen Modul: 1. Fachliche Spec: `.claude/docs/functional/MODUL_NAME.md` 2. Technische Spec: `.claude/docs/technical/MODUL_NAME.md` 3. Nach Fertigstellung: `.claude/library/` aktualisieren ### 6.2 CLAUDE.md aktuell halten Nach größeren Änderungen CLAUDE.md Versions-Tabelle aktualisieren. ### 6.3 Lessons Learned dokumentieren Jeder Rollback oder schwerer Bug → Eintrag in `.claude/rules/LESSONS_LEARNED.md` --- ## Zusammenfassung: Checkliste vor jedem Commit ``` [ ] Versions-Bump in backend/version.py (APP_VERSION + MODULE) [ ] Versions-Bump in frontend/src/version.js (APP_VERSION + PAGE) [ ] Changelog-Eintrag in backend/version.py [ ] DB_SCHEMA_VERSION aktualisiert (wenn Schema geändert) [ ] Neues Modul in PAGE_VERSIONS / MODULE_VERSIONS eingetragen [ ] Auth auf alle neuen Endpoints (require_auth) [ ] Fehlerformat einheitlich (HTTPException mit detail) [ ] Neue Tabellen haben created_at + updated_at [ ] Import-Tabellen haben source-Feld [ ] api.js für alle Frontend API-Calls ```