mitai-jinkendo/.claude/docs/jinkendo-foundation/design-principles/DATA_LAYER_DESIGN_PRINCIPLES.md
Lars 532e17c4cd
All checks were successful
Deploy Development / deploy (push) Successful in 1m5s
Build Test / pytest-backend (push) Successful in 4s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 24s
feat: add Jinkendo Foundation design principles documentation
- Introduced a new section for the Jinkendo Foundation, detailing design principles for the product family.
- Updated README files to include references to the new design principles documentation.
- Enhanced the overall documentation structure to improve navigation and accessibility of design resources.
- Ensured consistency across documentation related to the Jinkendo Foundation and its principles.
2026-07-22 11:11:07 +02:00

18 KiB
Raw Blame History

Data Layer Designprinzipien (Extraktion)

Status: Analyse / Arbeitspapier
Stand: 2026-07-04
Geltungsbereich: Multi-Layer Data Architecture (Phase 0c, Issue #53) — keine Mitai-Gesamtarchitektur, keine konkrete Gesundheits-/Ernährungsfachlogik als Produktinhalt

Serie: Designprinzipien für Produktfamilie · Dokument 2 von n
Vorgänger: PROMPT_ENGINE_DESIGN_PRINCIPLES.md

Kernkomponenten:

Bereich Pfade
Metriken (Layer 1) backend/data_layer/*_metrics.py, scores.py, correlations.py
Utilities backend/data_layer/utils.py
Visualisierung (Layer 2b) *_chart_payloads.py, *_viz.py
KI-Formatierung (Layer 2a-Hilfe) prompt_output_compact.py
Persistenz-Orchestrierung activity_persistence_orchestrator.py, activity_session_metrics.py
Konsumenten routers/charts.py, placeholder_resolver.py, routers/exportdata.py
Leitfäden DATA_LAYER_EXTENSION_GUIDE.md, docs/issues/issue-53-phase-0c-multi-layer-architecture.md
Architektur-Regel Import-Grenze .claude/rules/ARCHITECTURE.md §8

Modul

Data Layer (Phase 0c Multi-Layer Architecture, Issue #53)

Zentrale Schicht für Datenabruf, Berechnung und strukturierte Aufbereitung — ohne UI-Formatierung, ohne Prompt-Texte, ohne Chart.js-spezifische Ausgabe in den Kern-Metrik-Modulen.


Fachliche Verantwortung

Der Data Layer ist die Single Source of Truth für alle abgeleiteten Messwerte und Metriken. Er übernimmt:

  1. Datenabruf — Lesen aus PostgreSQL (profile-scoped), optional mit Quality-Filter.
  2. Berechnung — Trends, Scores, Korrelationen, Aggregationen, Projektionen.
  3. Strukturierte Rückgabe — Dicts/Listen mit numerischen Werten, Datumsfeldern, Metadaten (confidence, data_points).
  4. Konsumenten-Bereitstellung — Charts (Layer 2b), KI-Platzhalter (Layer 2a via Resolver), Export, Router-Anreicherung.

Er übernimmt nicht:

  • CSV-Parsing und Feld-Mapping (Import-Schicht)
  • Prompt-Template-Auflösung (Prompt Engine)
  • React-Rendering oder Frontend-Berechnungen
  • Autorisierung / Feature-Limits (Auth-Schicht)

Schichtenmodell (Multi-Layer)

┌─────────────────────────────────────────────────────────┐
│  Layer 0: Persistenz (PostgreSQL)                        │
│  weight_log, nutrition_log, activity_log, sleep_log, …   │
└──────────────────────────┬──────────────────────────────┘
                           │
┌──────────────────────────▼──────────────────────────────┐
│  Layer 1: DATA LAYER (Metriken)                          │
│  Strukturierte Daten · confidence · data_points          │
│  KEINE formatierten Strings · KEINE Chart.js-Objekte     │
└──────────────┬───────────────────────┬──────────────────┘
               │                       │
               ▼                       ▼
┌──────────────────────────┐  ┌────────────────────────────┐
│  Layer 2a: KI / Prompts    │  │  Layer 2b: Visualisierung  │
│  placeholder_resolver      │  │  *_chart_payloads, *_viz   │
│  prompt_output_compact       │  │  routers/charts.py         │
└──────────────────────────┘  └────────────────────────────┘

Administrierte vs. code-definierte Konfiguration

Was Wo Administrierbar?
Berechnungslogik (Formeln, Fenster) data_layer/*.py Code + Review
Confidence-Schwellen data_layer/utils.py Code
Goal Mode / Focus Weights DB (profiles, user_focus_area_weights) Nutzer/Admin
Quality Filter (Profil) DB (profiles) Admin
Chart-Zeitfenster Query-Parameter an API Request
Referenzwerte (persönlich) DB + reference_values.py Nutzer
EAV Session Metrics DB (training_*_parameter) Admin

Bewusst nicht hardcodiert in Routern: Metrik-Berechnungen — Router delegieren an Data Layer.

Hardcodiert (Code): Domänen-Module, Confidence-Regeln, Schwellen pro Metrik-Typ, TDEE-Fallback-Logik, Chart-Payload-Struktur.

Trennung: Metriken · Chart-Payloads · KI-Formatierung · Persistenz

Schicht Module Verantwortung
Metriken body_metrics.py, nutrition_metrics.py, … Reine Berechnung, strukturierte Dicts
Chart-Payloads nutrition_chart_payloads.py, correlation_chart_payloads.py, … Chart.js-kompatible { labels, datasets, metadata } aus Layer-1-Daten
Viz-Bundles body_viz.py, fitness_viz.py, … Zusammengesetzte Dashboard-/History-Pakete für Frontend
KI-Kompaktierung prompt_output_compact.py Token-sparende Zahlen/JSON für Platzhalter
Interpretation *_interpretation.py, vital_signs_assessment.py Textliche Einordnung (WHO-Klassen etc.) — Grenze zu Layer 2a
Persistenz-Orchestrator activity_persistence_orchestrator.py Schreibpfade REST/CSV → DB + Nebenwirkungen (EAV, Eval)

Konsumenten (wer ruft den Data Layer auf?)

Konsument Muster
routers/charts.py Layer-1-Funktion + Chart-Payload-Builder
placeholder_resolver.py Layer-1 → Formatierung/JSON für {{placeholders}}
routers/exportdata.py enrich_sessions_with_metrics, serialize_dates
routers/activity.py, csv_import.py activity_persistence_orchestrator (Schreiben)
prompt_executor.execute_prompt_with_data ⚠️ teils Roh-SQL parallel zum Data Layer (Legacy)

Rollen

Der Data Layer hat keine eigene Admin-UI. Konfiguration erfolgt indirekt:

  • Admin: Training-Parameter, Attributprofile, Referenzwert-Typen, Quality-Filter
  • Nutzer: Profildaten, Referenzwerte, Focus-Area-Gewichte (beeinflussen Scores)
  • Entwickler: Neue Funktionen in data_layer/ nach Extension Guide

Designprinzipien

1. Single Source of Truth für Berechnungen

Prinzip Jede Metrik wird einmal in data_layer/ berechnet; Charts, KI und Export konsumieren dieselbe Funktion.
Begründung Verhindert divergierende Zahlen zwischen Dashboard, Analyse und KI-Ausgabe.
Quelle Issue #53 Executive Summary; nutrition_chart_payloads.py Kommentar „identisch zu GET /api/charts/energy-balance“
Tragfähigkeit hoch
Einschränkung Nicht alle Pfade migriert (insights._prepare_template_vars, execute_prompt_with_data Roh-SQL).

2. Layer 1 liefert strukturierte Daten, keine formatierten Strings

Prinzip Kern-Metrik-Funktionen geben Dicts mit float/int/date zurück — keine Strings mit Einheiten („86,1 kg“).
Begründung Formatierung ist konsumentenspezifisch (DE-Locale, Chart-Achsen, KI-Token).
Quelle data_layer/__init__.py Docstring: „NO FORMATTING. NO STRINGS WITH UNITS.“
Tragfähigkeit hoch
Einschränkung placeholder_resolver und *_interpretation Module formatieren teils direkt — Grenze Layer 1/2a nicht überall scharf.

3. Pflicht-Metadaten: confidence + data_points

Prinzip Jede Metrik-Funktion liefert mindestens confidence (high|medium|low|insufficient) und data_points.
Begründung UI/KI können Datenqualität kommunizieren; Debugging und Monitoring vereinfacht.
Quelle DATA_LAYER_EXTENSION_GUIDE.md § Pflicht-Felder; calculate_confidence() in utils.py
Tragfähigkeit hoch
Einschränkung Nicht runtime-validiert; Disziplin per Code-Review.

4. Confidence nach Metrik-Typ und Zeitfenster

Prinzip Schwellen unterscheiden general, correlation, trend und Fensterlänge (7d / 28d / 90d).
Begründung Korrelationen brauchen mehr Paare; Trends messen Abdeckung (% der Tage).
Quelle data_layer/utils.pycalculate_confidence()
Tragfähigkeit hoch
Einschränkung Schwellen global hardcodiert, nicht pro Metrik konfigurierbar.

5. Domänen-Module statt Monolith

Prinzip Ein Python-Modul pro fachlichem Bereich (body_metrics, nutrition_metrics, …), max. ~500 Zeilen, dann Split.
Begründung Wartbarkeit, klare Ownership, parallele Entwicklung.
Quelle DATA_LAYER_EXTENSION_GUIDE.md § Modul-Struktur
Tragfähigkeit hoch
Einschränkung Einige Module deutlich >500 Zeilen (Phase-0c-Wachstum).

6. Layer 2b: Chart-Payloads als Adapter

Prinzip Chart.js-Strukturen leben in dedizierten *_chart_payloads.py / *_viz.py, nicht in Metrik-Modulen.
Begründung Gleiche Metrik, verschiedene Visualisierungen; API-Endpoints bleiben dünn.
Quelle nutrition_chart_payloads.py; routers/charts.py Imports
Tragfähigkeit hoch
Einschränkung Teilweise noch SQL-Duplikation in Payload-Buildern neben Layer-1-Aufruf.

7. Layer 2a-Hilfe: KI-spezifische Kompaktierung getrennt

Prinzip Token-Reduktion für LLM-Kontext (compact_float_for_prompt, compact_json_payload_for_prompts) ist eigenes Modul, nicht in Metrik-Kern.
Begründung KI hat andere Anforderungen als Charts (Präzision vs. Token-Kosten).
Quelle prompt_output_compact.py; Tests in tests/test_prompt_output_compact.py
Tragfähigkeit hoch
Einschränkung Nur für KI-Pfad; Charts nutzen eigene Rundung.

8. Import-Grenze: Ingest vs. Interpretation

Prinzip CSV-Import macht Mapping + Typkonvertierung + Duplikatlogik — keine fachliche Auswertung beim Insert.
Begründung Semantik gehört in Layer 1+, sonst versteckte Business-Logik in Import-Adaptern.
Quelle ARCHITECTURE.md §8; Issue #53
Tragfähigkeit hoch
Einschränkung Legacy-Adapter (Apple-Schlaf-Aggregat, dedizierte Import-Endpoints) noch aktiv.

9. Persistenz-Orchestrator für Schreibpfade

Prinzip Alle Schreibwege eines Domänenobjekts (REST, CSV, Legacy) laufen durch einen Orchestrator mit Nebenwirkungen (EAV, Evaluation).
Begründung Konsistente Duplikat-Erkennung, Registry-Felder, keine divergierenden Insert-Logiken.
Quelle activity_persistence_orchestrator.py
Tragfähigkeit hoch
Einschränkung Bisher vor allem Aktivität; andere Domänen noch direkt in Routern.

10. Registry als Feld-Kanon (Activity)

Prinzip Erlaubte persistierbare Felder für CSV/REST leiten sich aus module_registry ab, nicht aus Router-Hardcoding.
Begründung Single Source of Truth für Import-Mappings und DB-Updates.
Quelle activity_data_canon.py, activity_persistence_orchestrator.py
Tragfähigkeit hoch
Einschränkung Nur Activity vollständig; andere Module noch klassische Spalten-CRUD.

11. EAV-Anreicherung als Read-Layer

Prinzip Session-Metriken (EAV) werden beim Lesen angereichert (enrich_sessions_with_metrics), nicht pro Consumer dupliziert.
Begründung Ein Merge-Kanon für Liste, Detail, Export, Platzhalter.
Quelle activity_session_metrics.py; ACTIVITY_SESSION_METRICS_EAV_AGENT_GUIDE.md
Tragfähigkeit hoch
Einschränkung Domänenspezifisch (Training); Muster übertragbar.

12. Scores als composable Layer

Prinzip Composite Scores (scores.py) kombinieren Domänen-Metriken mit nutzer-spezifischen Focus Weights — keine Score-Logik in Routern.
Begründung Goal-Mode-/Focus-abhängige Gewichtung zentral, für KI und Dashboard gleich.
Quelle data_layer/scores.py; Phase-0b-Fokus-System
Tragfähigkeit mittelhoch
Einschränkung Eng an Mitai-Zielsystem gekoppelt; Muster „gewichtete Composite Scores“ ist generisch.

13. API-First: Router delegieren, rechnen nicht

Prinzip routers/charts.py und ähnliche Endpoints rufen Data-Layer-Funktionen auf und mappen auf HTTP — keine Trend-Berechnung im Router.
Begründung Testbarkeit; Frontend ohne Business-Logik.
Quelle ARCHITECTURE.md §1.2 API-First
Tragfähigkeit hoch
Einschränkung charts.py ist groß (2246+ Zeilen) — viel Adapter-Code, aber Berechnung delegiert.

14. serialize_dates / safe_float als Querschnitt

Prinzip JSON/API-Serialisierung (Dates, Decimal) zentral in utils.py, nicht pro Modul neu erfunden.
Begründung PostgreSQL-Typen (DATE, DECIMAL) konsistent für API und Export.
Quelle data_layer/utils.py
Tragfähigkeit hoch
Einschränkung

15. Extension Guide als verbindlicher Entwicklungsvertrag

Prinzip Neue Metriken folgen Template (Retrieve → Confidence → Early Return → Calculate → Return) und werden in __init__.py exportiert.
Begründung Einheitliche Struktur für 97+ Funktionen und wachsende Codebase.
Quelle DATA_LAYER_EXTENSION_GUIDE.md
Tragfähigkeit hoch
Einschränkung Guide und Ist-Code divergieren teils (Modulgröße, goals.py noch nicht in __init__).

Nicht übernehmen

Muster, die sich nicht bewährt haben oder zu produktspezifisch sind:

  1. Berechnungslogik in placeholder_resolver.py — Phase-0b-Legacy; Resolver soll nur formatieren/aggregieren, nicht rechnen.

  2. Paralleler Roh-SQL-Kontext in prompt_executor.execute_prompt_with_data — lädt Modul-Rohdaten per SQL, obwohl Layer 1 existiert; zweite Wahrheit.

  3. Legacy Insights-Pfad (insights._prepare_template_vars) — eigene Variablen-Vorbereitung ohne Data Layer.

  4. Import mit fachlicher Interpretation — Apple-Schlaf-Aggregat und ähnliche Adapter verstecken Semantik im Ingest (Gitea #69).

  5. Monolithische Router mit Inline-Berechnung — vor Phase 0c; gelegentlich noch Reste in nicht migrierten Pfaden.

  6. Interpretation vermischt mit Layer 1*_interpretation.py liefert teils fertige Texte; für Familien-Architektur klar als Layer 2a/2b markieren oder auslagern.

  7. SQL-Duplikation in Chart-Payloads — manche Payload-Builder führen eigene Queries statt ausschließlich Layer-1-Ergebnisse zu visualisieren.

  8. Hardcodierte Confidence global — funktioniert, aber nicht pro Metrik/Domäne konfigurierbar; Skalierung in Multi-Tenant-Produktfamilie prüfen.

  9. Domänen-Module als Produktinhaltbody_metrics, TDEE, WHR etc. sind Mitai-spezifisch; Schichtenmodell übernehmen, Formeln nicht blind kopieren.

  10. Fehlende runtime-Validierung des Return-Schemasconfidence/data_points per Konvention, nicht per TypedDict/Pydantic erzwungen.

  11. Uneinheitliche Schreib-Orchestrierung — nur Activity hat persistence_orchestrator; andere Domänen noch fragmentiert.

  12. Riesige Einzeldateien — einige Metrik-Module >>500 Zeilen widersprechen eigenem Extension Guide.


Modul-Inventar (Ist-Stand)

backend/data_layer/
├── Kern-Metriken (Layer 1)
│   ├── body_metrics.py
│   ├── nutrition_metrics.py
│   ├── activity_metrics.py
│   ├── recovery_metrics.py
│   ├── health_metrics.py
│   ├── scores.py
│   └── correlations.py
├── Visualisierung (Layer 2b)
│   ├── *_chart_payloads.py (nutrition, recovery, correlation)
│   └── *_viz.py (body, nutrition, fitness, recovery, history_overview)
├── KI / Format (Layer 2a-Nähe)
│   ├── prompt_output_compact.py
│   └── *_interpretation.py
├── Persistenz / EAV
│   ├── activity_persistence_orchestrator.py
│   ├── activity_session_metrics.py
│   └── activity_data_canon.py
├── Querschnitt
│   ├── utils.py
│   ├── reference_values.py
│   └── nutrition_body_merge.py
└── __init__.py (Exports)

Konsumenten-Endpoints (Auswahl): 20+ Chart-Endpoints in routers/charts.py (E1E5, A1A8, R1R5, C1C4).


Verwandte Dokumentation


Geplante Folgedokumente (Serie)

# Modul Datei (geplant)
1 Prompt Engine PROMPT_ENGINE_DESIGN_PRINCIPLES.md
2 Data Layer dieses Dokument
3 Feature & Entitlement System FEATURE_ENTITLEMENT_DESIGN_PRINCIPLES.md
4 Registry-/Plugin-Muster REGISTRY_PLUGIN_DESIGN_PRINCIPLES.md
5 Auth & Session AUTH_SESSION_DESIGN_PRINCIPLES.md
6 Universal Import UNIVERSAL_IMPORT_DESIGN_PRINCIPLES.md
7 Dashboard Widgets DASHBOARD_WIDGETS_DESIGN_PRINCIPLES.md
8 Navigation / IA NAVIGATION_IA_DESIGN_PRINCIPLES.md
9 Migration & Deploy MIGRATION_DEPLOY_DESIGN_PRINCIPLES.md