chore: entferne veraltete Architekturdokumente

Signed-off-by: StefanMoCoAt <stefan.mo.co@gmail.com>
This commit is contained in:
2026-05-05 21:22:46 +02:00
parent 6f15ada447
commit 15222b5453
258 changed files with 3388 additions and 6533 deletions
@@ -1,71 +0,0 @@
---
type: Reference
status: ACTIVE
owner: Lead Architect
last_update: 2026-03-15
---
# Frontend-Architektur & Modularisierungsstrategie
**Status:** ENTWURF
**Zuletzt aktualisiert:** 2026-01-19
**Kontext:** Migration zu Clean Architecture & Feature-Modulen
---
## 1. Übersicht
Die Frontend-Architektur von **Meldestelle** basiert auf **Kotlin Multiplatform (KMP)** mit **Compose Multiplatform** für die Benutzeroberfläche. Wir folgen einem strikten **Clean Architecture**-Ansatz, um Testbarkeit, Skalierbarkeit und Trennung der Zuständigkeiten sicherzustellen.
## 2. Modulstruktur
Das Projekt ist in folgende Schichten unterteilt:
### 2.1 Core-Module (`frontend/core`)
Wiederverwendbare Komponenten, die unabhängig von spezifischen Geschäftsfunktionen sind.
* `core-network`: Zentrale HTTP-Client-Konfiguration (Auth, Logging, ContentNegotiation).
* `core-sync`: Generische Synchronisierungslogik (`SyncManager`, `SyncableRepository`).
* `core-ui`: Gemeinsame UI-Komponenten und Design-System.
### 2.2 Feature-Module (`frontend/features`)
Jede Geschäftsdomäne (z.B. `ping`, `auth`, `events`) liegt in ihrem eigenen Modul.
Ein Feature-Modul MUSS die **Clean Architecture** Paketstruktur einhalten:
* `at.mocode.{feature}.feature.domain`
* **Entitäten:** Reine Datenklassen.
* **Interfaces:** Repository-Interfaces, Service-Interfaces.
* **Use Cases:** Geschäftslogik (optional, für komplexe Logik).
* `at.mocode.{feature}.feature.data`
* **Implementierungen:** Repository-Implementierungen, API-Clients.
* **DTOs:** Data Transfer Objects (wenn von Domain-Entitäten abweichend).
* `at.mocode.{feature}.feature.presentation`
* **ViewModels:** Zustandsverwaltung.
* **Screens:** Composable-Funktionen.
* `at.mocode.{feature}.feature.di`
* **Koin-Modul:** Konfiguration der Dependency Injection.
### 2.3 Shells (`frontend/shells`)
Anwendungs-Einstiegspunkte, die alles zusammenführen.
* `meldestelle-portal`: Die Haupt-Web-/Desktop-Anwendung.
## 3. Migrationsstrategie (Übergangsphase)
Wir migrieren aktuell von einer monolithischen `clients`-Paketstruktur zu modularen Feature-Modulen.
**Regeln für die Migration:**
1. **Neue Features:** Müssen direkt in `frontend/features/{name}` unter Verwendung der Clean Architecture-Struktur implementiert werden.
2. **Bestehende Features:** Werden schrittweise migriert.
3. **Koexistenz:** Während des Übergangs ist Legacy-Code in `clients/` erlaubt, aber als veraltet markiert.
4. **Dependency Injection:** Legacy-Code muss die neuen Koin-Module verwenden, sofern verfügbar.
5. **Keine Ghost-Klassen:** Klassen nicht duplizieren. Wenn eine Klasse in ein Feature-Modul verschoben wird, muss die alte in `clients/` gelöscht werden.
## 4. Wichtige Entscheidungen (ADRs)
### ADR-001: Entkopplung der Sync-Logik
* **Entscheidung:** ViewModels dürfen nicht direkt vom `SyncManager` abhängen.
* **Begründung:** Um einfacheres Testen zu ermöglichen und die Komplexität des generischen Sync-Mechanismus zu verbergen.
* **Umsetzung:** Ein Domain-Service-Interface (z.B. `PingSyncService`) einführen, das den `SyncManager`-Aufruf kapselt.
### ADR-002: Feature-Modul-Isolation
* **Entscheidung:** Feature-Module sollten nach Möglichkeit nicht direkt voneinander abhängen.
* **Kommunikation:** Gemeinsame Core-Module oder lose Kopplung über Interfaces/Events verwenden, wenn modulübergreifende Kommunikation nötig ist.
---
**Freigegeben von:** Lead Architect
@@ -1,51 +0,0 @@
---
type: Reference
status: ACTIVE
owner: Lead Architect
---
# Open-Source-Konformität & Lizenz-Checkliste
Dieses Dokument dient der Überwachung und Sicherstellung der Open-Source-Konformität des Projekts **Meldestelle**. Es wird vom Lead Architect gepflegt.
## Status der Kern-Komponenten (Stand: Januar 2026)
| Komponente | Lizenz | Status | Risiko | Maßnahme / Kommentar |
| :--- | :--- | :--- | :--- | :--- |
| **Kotlin / JVM** | Apache 2.0 / GPLv2+CE | ✅ OK | Sehr gering | Standard-Stack. |
| **Spring Boot / Cloud** | Apache 2.0 | ✅ OK | Sehr gering | |
| **PostgreSQL** | PostgreSQL (BSD-like) | ✅ OK | Sehr gering | |
| **Redis** | **RSALv2 / SSPL** | ⚠️ KRITISCH | Hoch | **Umstieg auf Valkey (BSD) geplant.** |
| **Consul** | **BSL 1.1** | ⚠️ BEOBACHTEN | Mittel | Lizenzänderung durch HashiCorp. Für interne Nutzung aktuell unkritisch. |
| **Keycloak** | Apache 2.0 | ✅ OK | Gering | |
| **SQLDelight** | Apache 2.0 | ✅ OK | Sehr gering | |
| **Redisson** | Apache 2.0 (Core) | ✅ OK | Gering | Sicherstellen, dass keine PRO-Features genutzt werden. |
---
## Checkliste für neue Abhängigkeiten
Bevor eine neue Bibliothek oder Infrastruktur-Komponente hinzugefügt wird, muss sie folgende Kriterien erfüllen:
1. **Lizenz-Typ:**
* Bevorzugt: Apache 2.0, MIT, BSD (3-Clause).
* Akzeptabel: MPL 2.0.
* Einzelfallprüfung: LGPL (nur als dynamische Bibliothek).
* **Verboten:** AGPL, SSPL, RSAL, BSL (sofern nicht explizit vom Architect freigegeben).
2. **Community & Governance:**
* Wird das Projekt von einer neutralen Foundation (Apache, CNCF, Linux Foundation) verwaltet?
* Gibt es eine "Single Vendor" Abhängigkeit (Risiko einer plötzlichen Lizenzänderung)?
3. **Transitive Abhängigkeiten:**
* Bringt die Bibliothek "versteckte" Copyleft-Lizenzen mit? (Check via Gradle License Plugin).
---
## TODOs & Strategische Entscheidungen
- [ ] **Migration Redis -> Valkey:** Umstellung der Docker-Images und Test der Kompatibilität.
- [ ] **Consul Review:** Jährliche Prüfung der BSL-Auswirkungen auf unser Deployment-Modell.
- [ ] **Automatisierung:** Integration eines License-Check-Plugins in den CI-Build (z.B. `com.github.jk1.dependency-license-report`).
---
*Dieses Dokument ist Teil der "Docs-as-Code" Strategie und muss bei jeder Änderung am Tech-Stack aktualisiert werden.*
@@ -0,0 +1,54 @@
---
type: Reference
status: ACTIVE
owner: Lead Architect
---
# Open-Source-Konformität & Lizenz-Checkliste
Dieses Dokument dient der Überwachung und Sicherstellung der Open-Source-Konformität des Projekts **Meldestelle**. Es
wird vom Lead Architect gepflegt.
## Status der Kern-Komponenten (Stand: Januar 2026)
| Komponente | Lizenz | Status | Risiko | Maßnahme / Kommentar |
|:------------------------|:----------------------|:--------------|:------------|:------------------------------------------------------------------------|
| **Kotlin / JVM** | Apache 2.0 / GPLv2+CE | ✅ OK | Sehr gering | Standard-Stack. |
| **Spring Boot / Cloud** | Apache 2.0 | ✅ OK | Sehr gering | |
| **PostgreSQL** | PostgreSQL (BSD-like) | ✅ OK | Sehr gering | |
| **Redis** | **RSALv2 / SSPL** | ⚠️ KRITISCH | Hoch | **Umstieg auf Valkey (BSD) geplant.** |
| **Consul** | **BSL 1.1** | ⚠️ BEOBACHTEN | Mittel | Lizenzänderung durch HashiCorp. Für interne Nutzung aktuell unkritisch. |
| **Keycloak** | Apache 2.0 | ✅ OK | Gering | |
| **SQLDelight** | Apache 2.0 | ✅ OK | Sehr gering | |
| **Redisson** | Apache 2.0 (Core) | ✅ OK | Gering | Sicherstellen, dass keine PRO-Features genutzt werden. |
---
## Checkliste für neue Abhängigkeiten
Bevor eine neue Bibliothek oder Infrastruktur-Komponente hinzugefügt wird, muss sie folgende Kriterien erfüllen:
1. **Lizenz-Typ:**
* Bevorzugt: Apache 2.0, MIT, BSD (3-Clause).
* Akzeptabel: MPL 2.0.
* Einzelfallprüfung: LGPL (nur als dynamische Bibliothek).
* **Verboten:** AGPL, SSPL, RSAL, BSL (sofern nicht explizit vom Architect freigegeben).
2. **Community & Governance:**
* Wird das Projekt von einer neutralen Foundation (Apache, CNCF, Linux Foundation) verwaltet?
* Gibt es eine "Single Vendor" Abhängigkeit (Risiko einer plötzlichen Lizenzänderung)?
3. **Transitive Abhängigkeiten:**
* Bringt die Bibliothek "versteckte" Copyleft-Lizenzen mit? (Check via Gradle License Plugin).
---
## TODOs & Strategische Entscheidungen
- [ ] **Migration Redis -> Valkey:** Umstellung der Docker-Images und Test der Kompatibilität.
- [ ] **Consul Review:** Jährliche Prüfung der BSL-Auswirkungen auf unser Deployment-Modell.
- [ ] **Automatisierung:** Integration eines License-Check-Plugins in den CI-Build (z.B.
`com.github.jk1.dependency-license-report`).
---
*Dieses Dokument ist Teil der "Docs-as-Code" Strategie und muss bei jeder Änderung am Tech-Stack aktualisiert werden.*
@@ -3,6 +3,7 @@
Status: April 2026
## ✅ Abgeschlossene Migrationen (Feature-Module)
- `billing-feature`: `at.mocode.frontend.features.billing` (KMP)
- `verein-feature`: `at.mocode.frontend.features.verein` (KMP)
- `nennung-feature`: `at.mocode.frontend.features.nennung` (KMP)
@@ -13,11 +14,14 @@ Status: April 2026
- `ping-feature`: `at.mocode.ping.feature` (muss noch auf `at.mocode.frontend.features.ping` vereinheitlicht werden)
## 🚧 Ausstehende Migrationen (von `at.mocode.desktop.v2` zu Features)
Die folgenden Komponenten in `meldestelle-desktop/src/jvmMain/kotlin/at/mocode/desktop/v2/` basieren noch auf `StoreV2` (In-Memory Mock) und sollten in KMP-Module überführt werden:
Die folgenden Komponenten in `meldestelle-desktop/src/jvmMain/kotlin/at/mocode/desktop/v2/` basieren noch auf
`StoreV2` (In-Memory Mock) und sollten in KMP-Module überführt werden:
1. **Onboarding**: `OnboardingScreen.kt` -> Design-System Integration erfolgt, KMP-Modul folgt.
## 🧹 Architektur-Cleanup
- [ ] `at.mocode.desktop.v2.StoreV2` entfernen, sobald alle Screens auf ViewModels und API-Repositories umgestellt sind.
- [ ] `at.mocode.desktop.v2.TurnierStoreV2` konsolidieren mit dem `turnier-feature`.
- [ ] Paketnamen vereinheitlichen: `at.mocode.ping.feature` -> `at.mocode.frontend.features.ping`.
@@ -26,6 +30,7 @@ Die folgenden Komponenten in `meldestelle-desktop/src/jvmMain/kotlin/at/mocode/d
- [ ] `DesktopMainLayout.kt`: Die `when`-Zweige für `v2` Screens aufräumen, sobald die Module bereit sind.
## ✅ Abgeschlossen am 11.04.2026
- Migration `pferde-feature`, `reiter-feature`, `funktionaer-feature`, `veranstalter-feature`.
- Integration in `DesktopMainLayout` und `AppScreen`.
- Bereinigung der Repository-Pakete.
@@ -9,7 +9,9 @@ last_update: 2026-04-03
## Ziel und Rahmen
Dieses Dokument definiert das Synchronisations-Konzept zwischen der Compose Desktop App (Meldestelle-Zentrale) und dem Backend in einem Offline-First Szenario. Es baut auf ADR-0021 (Tenant-Isolation) und ADR-0022 (LAN-Sync mit Lamport-Uhren) auf und erweitert sie um die WAN/Backend-Synchronisation.
Dieses Dokument definiert das Synchronisations-Konzept zwischen der Compose Desktop App (Meldestelle-Zentrale) und dem
Backend in einem Offline-First Szenario. Es baut auf ADR-0021 (Tenant-Isolation) und ADR-0022 (LAN-Sync mit
Lamport-Uhren) auf und erweitert sie um die WAN/Backend-Synchronisation.
Nicht-Ziele: Cloud-Realtime für Endnutzer, kollaboratives Editieren außerhalb des Veranstaltungsbetriebs.
@@ -18,32 +20,38 @@ Nicht-Ziele: Cloud-Realtime für Endnutzer, kollaboratives Editieren außerhalb
1. Offline-First: Die Desktop-App ist voll funktionsfähig ohne Netzwerk; Synchronisation erfolgt opportunistisch.
2. Event-isoliert: Pro Veranstaltung eigener Datenraum (gemäß ADR-0021). Keine Vermischung von Events.
3. Einheitliches Änderungsmodell: Wiederverwendung des `SyncEvent`-Logs (ADR-0022) für Desktop↔Backend.
4. Domänen-Mastership: Klare Schreibhoheiten reduzieren Konflikte, fachliche Regeln haben Vorrang vor rein technischen Timestamps.
4. Domänen-Mastership: Klare Schreibhoheiten reduzieren Konflikte, fachliche Regeln haben Vorrang vor rein technischen
Timestamps.
5. Deterministische Konfliktauflösung: Lamport-Uhren + Regel-Matrix; keine Abhängigkeit von Systemuhren.
## Topologie & Rollen
- Backend (Zentrale Plattform):
- Master für: Stammdaten (Reiter, Pferde, Vereine, Funktionäre), Identität/Rollen, Gebührenkataloge, globale Referenzen.
- Master für: Stammdaten (Reiter, Pferde, Vereine, Funktionäre), Identität/Rollen, Gebührenkataloge, globale
Referenzen.
- Aggregations-/Archiv-Quelle nach Veranstaltungsende (finale Ergebnisse, Abrechnungen).
- Desktop (Meldestelle-Zentrale):
- Master während der Veranstaltung für: Nennungen (operativ), Startreihenfolgen, Startlisten-Status, Ergebnisse/Protokolle (falls Richter nicht direkt am Backend), Kassa-Operationen vor Ort.
- Hält lokales `SyncEvent`-Log + Snapshots (vgl. ADR-0022) und synchronisiert mit Backend, sobald Konnektivität besteht.
- Master während der Veranstaltung für: Nennungen (operativ), Startreihenfolgen, Startlisten-Status,
Ergebnisse/Protokolle (falls Richter nicht direkt am Backend), Kassa-Operationen vor Ort.
- Hält lokales `SyncEvent`-Log + Snapshots (vgl. ADR-0022) und synchronisiert mit Backend, sobald Konnektivität
besteht.
Hinweis Mehrfach-Desktops: Genau eine „Zentrale“ pro Veranstaltung besitzt Schreibhoheit (Konfig-Flag `isEventAuthority=true`). Weitere Geräte sind Replikate/Clients.
Hinweis Mehrfach-Desktops: Genau eine „Zentrale“ pro Veranstaltung besitzt Schreibhoheit (Konfig-Flag
`isEventAuthority=true`). Weitere Geräte sind Replikate/Clients.
## Datenkategorien & Mastership
| Kategorie | Master | Desktop Rechte | Backend Rechte |
|--------------------------|----------------|--------------------------------|-----------------------------------|
| Stammdaten (Actor) | Backend | Lesen, lokal „provisional“ anlegen (Temp-ID) | Vollzugriff, ID-Zuteilung, Merge |
| Veranstaltungs-Stammdaten| Backend | Lesen | Vollzugriff |
| Nennungen operativ | Desktop | Vollzugriff | Lesen, Import nach Sync |
| Startreihenfolge/Status | Desktop | Vollzugriff | Lesen, Import nach Sync |
| Bewertungen/Ergebnisse | Desktop/Richter| Vollzugriff (Eventzeitraum) | Lesen, Publikation/Archiv |
| Kassa/Finanzen vor Ort | Desktop | Vollzugriff | Lesen, Abgleich Summen |
| Kategorie | Master | Desktop Rechte | Backend Rechte |
|---------------------------|-----------------|----------------------------------------------|----------------------------------|
| Stammdaten (Actor) | Backend | Lesen, lokal „provisional“ anlegen (Temp-ID) | Vollzugriff, ID-Zuteilung, Merge |
| Veranstaltungs-Stammdaten | Backend | Lesen | Vollzugriff |
| Nennungen operativ | Desktop | Vollzugriff | Lesen, Import nach Sync |
| Startreihenfolge/Status | Desktop | Vollzugriff | Lesen, Import nach Sync |
| Bewertungen/Ergebnisse | Desktop/Richter | Vollzugriff (Eventzeitraum) | Lesen, Publikation/Archiv |
| Kassa/Finanzen vor Ort | Desktop | Vollzugriff | Lesen, Abgleich Summen |
Konflikte über Kategoriegrenzen werden durch Mastership-Regeln verhindert; verbleibende Konflikte werden per Regel-Matrix gelöst.
Konflikte über Kategoriegrenzen werden durch Mastership-Regeln verhindert; verbleibende Konflikte werden per
Regel-Matrix gelöst.
## Änderungsmodell (Wiederverwendung `SyncEvent`)
@@ -71,11 +79,13 @@ data class SyncEvent(
## Lamport-Uhren & Vector-Clock (Optional)
- Primär: Lamport-Uhren wie ADR-0022. Gleichstand → lexikografisch größere `originNodeId` gewinnt (Determinismus).
- Optional für feingranulare Erkennung: Per-Aggregat Vector-Clock (`Map<nodeId, lamport>`) zur Diagnose; Entscheidungsgrundlage bleibt Lamport + Fachregeln.
- Optional für feingranulare Erkennung: Per-Aggregat Vector-Clock (`Map<nodeId, lamport>`) zur Diagnose;
Entscheidungsgrundlage bleibt Lamport + Fachregeln.
## Sync-Protokoll Desktop ↔ Backend (HTTPS)
Transport: HTTPS (HTTP/2), JSON oder Protobuf, idempotente Endpunkte. Auth: mTLS zwischen Desktop und Backend ODER OAuth2 Client Credentials + Signatur der Batch-Payload.
Transport: HTTPS (HTTP/2), JSON oder Protobuf, idempotente Endpunkte. Auth: mTLS zwischen Desktop und Backend ODER
OAuth2 Client Credentials + Signatur der Batch-Payload.
Empfohlene Endpunkte (pro `eventId`):
@@ -94,42 +104,55 @@ Idempotenz: Jeder `SyncEvent` wird durch `(eventId, originNodeId, sequenceNumber
## Konfliktauflösung
1) Strukturkonflikte (gleiches Aggregat, konkurrierende Events):
- Wenn eine Seite nicht Master ist → Event wird angenommen, aber als `PENDING_REVIEW` markiert; fachliche Entscheidung erforderlich (Backend-UI oder Desktop-Review-Queue).
- Wenn eine Seite nicht Master ist → Event wird angenommen, aber als `PENDING_REVIEW` markiert; fachliche Entscheidung
erforderlich (Backend-UI oder Desktop-Review-Queue).
- Beide Master (Sonderfälle, z. B. Ergebnisse während parallelem Backend-Fix):
- Lamport höher gewinnt.
- Gleichstand → `originNodeId`-Tiebreaker.
- Zusätzlich fachliche Heuristik optional: „Korrektur-Events“ (z. B. `ErgebnisKorrigiert`) schlagen normale `ErgebnisErfasst` bei gleichem Lamport.
- Zusätzlich fachliche Heuristik optional: „Korrektur-Events“ (z. B. `ErgebnisKorrigiert`) schlagen normale
`ErgebnisErfasst` bei gleichem Lamport.
2) Identitätskonflikte (provisionale Stammdaten):
- Desktop darf temporäre Einträge (Temp-ID `tmp-...`) erzeugen.
- Beim Push führt Backend `Upsert+Merge` aus, weist finale IDs zu und liefert `IdMapping { tmpId -> finalId }` zurück.
- Desktop ersetzt Referenzen transaktional und emittiert ein lokales `IdRemapped`-Event (kein Re-Upload nötig, außer für Diagnose).
- Desktop ersetzt Referenzen transaktional und emittiert ein lokales `IdRemapped`-Event (kein Re-Upload nötig, außer für
Diagnose).
3) Reihenfolge-/Kausalitätskonflikte:
- Bei fehlenden Vorgänger-Events antwortet Backend mit `rejected: [id]` und `requiredSinceSeq`. Desktop zieht Delta (`pull`) und wiederholt den `push`.
- Bei fehlenden Vorgänger-Events antwortet Backend mit `rejected: [id]` und `requiredSinceSeq`. Desktop zieht Delta (
`pull`) und wiederholt den `push`.
## Snapshots & Recovery
- Snapshot-Intervall: standardmäßig 100 Events pro `(aggregateType, scope)` (wie ADR-0022), für WAN-Sync zusätzlich Full-State-Snapshot pro Veranstaltung vor Event-Abschluss.
- Recovery: Desktop kann mit leerem Log starten → `snapshot/request` Full-State + `snapshotSeq` → weitere Deltas über `pull`.
- USB-Fallback (Notbetrieb): Export/Import von `sync_events` und `sync_snapshots` als verschlüsselte Archive (`.msync`). Offene Spezifikation; separater PoC.
- Snapshot-Intervall: standardmäßig 100 Events pro `(aggregateType, scope)` (wie ADR-0022), für WAN-Sync zusätzlich
Full-State-Snapshot pro Veranstaltung vor Event-Abschluss.
- Recovery: Desktop kann mit leerem Log starten → `snapshot/request` → Full-State + `snapshotSeq` → weitere Deltas über
`pull`.
- USB-Fallback (Notbetrieb): Export/Import von `sync_events` und `sync_snapshots` als verschlüsselte Archive (`.msync`).
Offene Spezifikation; separater PoC.
## Sicherheit
- Mandantentrennung: Jeder Request trägt `X-Event-Id` (ADR-0021). Backend validiert gegen `control.tenants`.
- Transport: `https` + mTLS (bevorzugt) oder `https` + OAuth2 Client Credentials. Payload-Signatur (HMAC-SHA256) empfohlen.
- Transport: `https` + mTLS (bevorzugt) oder `https` + OAuth2 Client Credentials. Payload-Signatur (HMAC-SHA256)
empfohlen.
- Integrität: `checksum` pro Event wird serverseitig geprüft; Mismatch → Reject.
- Rechte: Backend erzwingt Mastership-Regeln serverseitig; Verstöße → `PENDING_REVIEW` + Audit-Log.
## Fehlerfälle & Resilienz
- Netzwerkfehler: Exponentielles Backoff (bis 5 min), Offline-Queue unbegrenzt (bounded by disk quota), Telemetrie im UI.
- Netzwerkfehler: Exponentielles Backoff (bis 5 min), Offline-Queue unbegrenzt (bounded by disk quota), Telemetrie im
UI.
- Schema-Divergenz: `minSupportedSchema` aus `hello`; Desktop migriert vor weiterem Sync oder schaltet in Read-Only.
- Duplikate: Idempotenz-Keys verhindern Doppelverarbeitung. ACK enthält höchste verarbeitete `sequenceNumber`.
## Observability
- Metriken: `sync_push_events_total`, `sync_pull_events_total`, `sync_rejected_total`, `sync_latency_ms` (p50/p95), `offline_duration_s`.
- Metriken: `sync_push_events_total`, `sync_pull_events_total`, `sync_rejected_total`, `sync_latency_ms` (p50/p95),
`offline_duration_s`.
- Logs: pro Event `tenant`, `originNodeId`, `seq`, `aggType`, `eventType`, `result`.
- UI: Status-Anzeige (Verbunden, Getrennt, Ausstehend X), Konflikt-Review-Queue.
@@ -5,72 +5,96 @@
> **Kontext:** Phase 9 — Zeitplan & Protokollierung
## 1. Vision & Zielsetzung
Die Zeitplan-Optimierung ist das zentrale Werkzeug für die Meldestelle, um den Turnierablauf dynamisch an die Gegebenheiten vor Ort anzupassen. Ziel ist eine intuitive, visuelle Oberfläche (Kalender-Ansicht), in der Bewerbe und Abteilungen per Drag & Drop verschoben werden können, wobei das System automatisch Auswirkungen auf Folge-Bewerbe berechnet und vor Konflikten warnt.
Die Zeitplan-Optimierung ist das zentrale Werkzeug für die Meldestelle, um den Turnierablauf dynamisch an die
Gegebenheiten vor Ort anzupassen. Ziel ist eine intuitive, visuelle Oberfläche (Kalender-Ansicht), in der Bewerbe und
Abteilungen per Drag & Drop verschoben werden können, wobei das System automatisch Auswirkungen auf Folge-Bewerbe
berechnet und vor Konflikten warnt.
## 2. Fachliche Anforderungen (Use Cases)
### UC-1: Verschieben eines Bewerbs/einer Abteilung
- Ein Benutzer zieht einen Bewerb oder eine Abteilung auf eine neue Startzeit oder einen anderen Austragungsplatz.
- **System-Reaktion:**
- Neuberechnung der Endzeit basierend auf `reitdauerMinuten * starterAnzahl + besichtigungMinuten + umbauMinuten`.
- Prüfung auf Überschneidungen am selben Austragungsplatz.
- Warnung bei Konflikten (z.B. Richter-Doppelbelegung).
- **System-Reaktion:**
- Neuberechnung der Endzeit basierend auf `reitdauerMinuten * starterAnzahl + besichtigungMinuten + umbauMinuten`.
- Prüfung auf Überschneidungen am selben Austragungsplatz.
- Warnung bei Konflikten (z.B. Richter-Doppelbelegung).
### UC-2: Dynamische Zeitplan-Anpassung („Anschließend“)
- Bewerbe können als `ANSCHLIESSEND` markiert werden (`beginnZeitTyp`).
- **System-Reaktion:** Wenn der vorangehende Bewerb verschoben wird oder länger dauert, verschiebt sich der anschließende Bewerb automatisch mit.
- **System-Reaktion:** Wenn der vorangehende Bewerb verschoben wird oder länger dauert, verschiebt sich der
anschließende Bewerb automatisch mit.
### UC-3: Drag & Drop in der Startliste
- Innerhalb einer Startliste können Teilnehmer per Drag & Drop umsortiert werden.
- **System-Reaktion:** Automatische Aktualisierung der Kopfnummern (Startnummern) und Neuberechnung der individuellen Startzeiten.
- **System-Reaktion:** Automatische Aktualisierung der Kopfnummern (Startnummern) und Neuberechnung der individuellen
Startzeiten.
### UC-4: Protokollierung (Audit Log)
- Jede manuelle Änderung am Zeitplan oder der Startlisten-Reihenfolge muss protokolliert werden.
- **Grund:** Nachvollziehbarkeit bei Einsprüchen und Synchronisation zwischen verschiedenen Arbeitsplätzen (Meldestelle ↔ Richterturm).
- **Grund:** Nachvollziehbarkeit bei Einsprüchen und Synchronisation zwischen verschiedenen Arbeitsplätzen (
Meldestelle ↔ Richterturm).
## 3. Datenmodell-Erweiterungen & Logik
### 3.1 Erweiterung `Bewerb` & `Abteilung`
Das bestehende Modell in `entries-domain` deckt bereits viele Felder ab. Für die Optimierung präzisieren wir:
- **`Umbauzeit`:** Zeit zwischen zwei Abteilungen oder Bewerben.
- **`Pausen`:** Geplante Unterbrechungen (z.B. Mittagspause, Platzpflege) werden als spezielle „Blocker-Events“ im Zeitplan geführt.
- **`Pausen`:** Geplante Unterbrechungen (z.B. Mittagspause, Platzpflege) werden als spezielle „Blocker-Events“ im
Zeitplan geführt.
- **`BesichtigungsBlock` (NEU):** Eigenständiges Objekt für Parcoursbesichtigungen.
- Kann mit mehreren Bewerben/Abteilungen verknüpft werden (Cross-Competition Inspection).
- Unterstützt Typen: `ZU_FUSS` (Standard) und `ZU_PFERD` (Spezialfall für Springpferde bis 110cm gemäß ÖTO).
- Validierung: Mindestens 5 Min. Puffer vor dem ersten Start (ÖTO §43).
- Kann mit mehreren Bewerben/Abteilungen verknüpft werden (Cross-Competition Inspection).
- Unterstützt Typen: `ZU_FUSS` (Standard) und `ZU_PFERD` (Spezialfall für Springpferde bis 110cm gemäß ÖTO).
- Validierung: Mindestens 5 Min. Puffer vor dem ersten Start (ÖTO §43).
### 3.2 Zeitberechnungs-Algorithmus (Präzisierung)
Die Logik in `StartlistenService.berechneStartzeiten` wird erweitert:
1. **Basis:** `Startzeit` der Abteilung.
2. **Vorlauf:** `besichtigungMinuten`.
3. **Starter-Loop:**
- `individuelleStartzeit = aktuelleZeit`.
- `aktuelleZeit += bewerb.reitdauerMinuten`.
- *Neu:* Berücksichtigung von festen Pausen nach X Startern (z.B. 10 Min. Pause alle 20 Starter).
3. **Starter-Loop:**
- `individuelleStartzeit = aktuelleZeit`.
- `aktuelleZeit += bewerb.reitdauerMinuten`.
- *Neu:* Berücksichtigung von festen Pausen nach X Startern (z.B. 10 Min. Pause alle 20 Starter).
4. **Nachlauf:** `umbauMinuten` am Ende der Abteilung/des Bewerbs.
### 3.3 Drag & Drop Logik (Frontend & Backend)
- **Frontend (Compose Desktop):**
- Implementierung eines `DraggableBewerbItem`.
- Visuelle Darstellung von Konflikten (Rote Markierung bei Überlappung).
- **Frontend (Compose Desktop):**
- Implementierung eines `DraggableBewerbItem`.
- Visuelle Darstellung von Konflikten (Rote Markierung bei Überlappung).
- **Backend (API):**
- Neuer Endpunkt `PATCH /bewerbe/{id}/zeitplan` für schnelle Updates.
- Validierung der neuen Zeiten gegen den `austragungsplatzId` und `richterEinsaetze`.
- Neuer Endpunkt `PATCH /bewerbe/{id}/zeitplan` für schnelle Updates.
- Validierung der neuen Zeiten gegen den `austragungsplatzId` und `richterEinsaetze`.
## 4. Konflikt-Management
Das System arbeitet nach dem Prinzip **„Warnen statt Blockieren“** (ADR-0016):
- **Harte Fehler:** Nur bei technischer Unmöglichkeit (z.B. Datum in der Vergangenheit bei Live-Betrieb).
- **Warnungen:**
- Überlappung auf dem Platz.
- Richter hat gleichzeitig Einsatz in anderem Bewerb.
- Zeitunterschreitung für Reiter (Reiter startet in zwei kurz aufeinanderfolgenden Bewerben).
- **Warnungen:**
- Überlappung auf dem Platz.
- Richter hat gleichzeitig Einsatz in anderem Bewerb.
- Zeitunterschreitung für Reiter (Reiter startet in zwei kurz aufeinanderfolgenden Bewerben).
## 5. Synchronisation (Offline-First)
Änderungen am Zeitplan erzeugen `SyncEvents` (gemäß ADR-0022).
- **Lamport-Uhren:** Stellen sicher, dass bei gleichzeitigen Änderungen an zwei Laptops die zeitlich spätere Änderung (oder die mit höherer Priorität) gewinnt.
- **Echtzeit-Update:** Über WebSockets werden Zeitplan-Änderungen sofort an alle verbundenen Clients (z.B. Anzeige-Monitor, Richter-Tablet) gepusht.
Änderungen am Zeitplan erzeugen `SyncEvents` (gemäß ADR-0022).
- **Lamport-Uhren:** Stellen sicher, dass bei gleichzeitigen Änderungen an zwei Laptops die zeitlich spätere Änderung (
oder die mit höherer Priorität) gewinnt.
- **Echtzeit-Update:** Über WebSockets werden Zeitplan-Änderungen sofort an alle verbundenen Clients (z.B.
Anzeige-Monitor, Richter-Tablet) gepusht.
## 6. Nächste Schritte
1. **Backend:** ✅ Implementiert (BewerbService, API, Zeitberechnungs-Pausen).
2. **Frontend:** Prototyping der Kalender-Ansicht mit Compose Desktop.
3. **QA:** Test-Szenarien für komplexe Verschiebungen (Kettenreaktionen bei „Anschließend“).
@@ -5,42 +5,63 @@
> **Kontext:** Zeitplan-Optimierung & Praxis-Szenarien
## 1. Parcoursbesichtigung zu Pferd
Die Aussage des Users wurde geprüft und bestätigt.
### 1.1 Regelwerks-Referenz (ÖTO 2026)
Gemäß **ÖTO Teil B, § 43 (Abweichungen)** gilt:
- **Normalfall:** Parcoursbesichtigung erfolgt zu Fuß.
- **Springpferde- & Jungpferdeprüfungen (bis 110 cm):** Eine Besichtigung **zu Pferd im Schritt** kann von der Richtergruppe erlaubt werden.
- **Zweck:** Junge, unerfahrene Pferde sollen stressfrei an optische Reize (Fangständer, Farben, Unterbauten) herangeführt werden.
- **Springpferde- & Jungpferdeprüfungen (bis 110 cm):** Eine Besichtigung **zu Pferd im Schritt** kann von der
Richtergruppe erlaubt werden.
- **Zweck:** Junge, unerfahrene Pferde sollen stressfrei an optische Reize (Fangständer, Farben, Unterbauten)
herangeführt werden.
### 1.2 Organisatorische Implikationen
- **Dauer:** Die Besichtigung zu Pferd benötigt oft etwas mehr Zeit für die Koordination am Einlass (15-20 Min. sind praxisnah).
- **Sicherheit:** Da Pferde im Parcours sind, während andere Reiter eventuell noch draußen warten, muss der Zeitplan einen Puffer von mindestens **5 Minuten** zwischen Ende Besichtigung und erstem Start vorsehen (ÖTO Vorschrift).
- **Dauer:** Die Besichtigung zu Pferd benötigt oft etwas mehr Zeit für die Koordination am Einlass (15-20 Min. sind
praxisnah).
- **Sicherheit:** Da Pferde im Parcours sind, während andere Reiter eventuell noch draußen warten, muss der Zeitplan
einen Puffer von mindestens **5 Minuten** zwischen Ende Besichtigung und erstem Start vorsehen (ÖTO Vorschrift).
## 2. Zusammengelegte Besichtigungen (Cross-Competition Inspection)
In der Praxis üblich, wenn der Parcours für aufeinanderfolgende Bewerbe identisch bleibt.
### 2.1 Szenario
- **Bewerb A:** Springpferdeprüfung 105cm (Besichtigung zu Pferd erlaubt).
- **Bewerb B:** Standardspringprüfung 105cm (Besichtigung zu Fuß).
- **Lösung:** Eine gemeinsame Besichtigungszeit vor Bewerb A.
### 2.2 Regelwerks-Konformität
- Es gibt kein Verbot für gemeinsame Besichtigungen, solange die Teilnehmer beider Bewerbe die Möglichkeit haben, den Parcours regelkonform zu besichtigen.
- **Wichtig:** Wenn Bewerb B erst 2 Stunden später startet, muss für Teilnehmer von Bewerb B theoretisch eine zweite Besichtigungsmöglichkeit (oder ein "Refresh") angeboten werden, falls der Parcours zwischenzeitlich verändert wurde. Wenn er identisch bleibt, reicht die einmalige Bekanntgabe.
- Es gibt kein Verbot für gemeinsame Besichtigungen, solange die Teilnehmer beider Bewerbe die Möglichkeit haben, den
Parcours regelkonform zu besichtigen.
- **Wichtig:** Wenn Bewerb B erst 2 Stunden später startet, muss für Teilnehmer von Bewerb B theoretisch eine zweite
Besichtigungsmöglichkeit (oder ein "Refresh") angeboten werden, falls der Parcours zwischenzeitlich verändert wurde.
Wenn er identisch bleibt, reicht die einmalige Bekanntgabe.
## 3. Anforderungen für die Software (Zeitplan-Modul)
### 3.1 Datenmodell
- `Abteilung` oder `Bewerb` benötigt ein Flag `besichtigungZuPferdErlaubt` (Boolean).
- `BesichtigungsBlock` als eigenständiges Entitätsobjekt im Zeitplan, das mit **mehreren** Bewerben/Abteilungen verknüpft werden kann.
- `BesichtigungsBlock` als eigenständiges Entitätsobjekt im Zeitplan, das mit **mehreren** Bewerben/Abteilungen
verknüpft werden kann.
### 3.2 Validierung & Warnungen
- **Warnung:** Wenn ein Besichtigungsblock mit "zu Pferd" markiert ist, aber ein verbundener Bewerb (z.B. L-Springen) dies laut ÖTO normalerweise nicht vorsieht (Diskretionsspielraum der Richter).
- **Puffer-Check:** Automatische Prüfung, ob zwischen `Ende Besichtigung` und `Start Erster Reiter` mindestens 5 Minuten liegen.
- **Warnung:** Wenn ein Besichtigungsblock mit "zu Pferd" markiert ist, aber ein verbundener Bewerb (z.B. L-Springen)
dies laut ÖTO normalerweise nicht vorsieht (Diskretionsspielraum der Richter).
- **Puffer-Check:** Automatische Prüfung, ob zwischen `Ende Besichtigung` und `Start Erster Reiter` mindestens 5 Minuten
liegen.
## 4. Fazit für Architect & Entwickler
Die "Besichtigung zu Pferd" ist ein valider Spezialfall für Springpferdeprüfungen. Die Software muss erlauben, Besichtigungszeiten flexibel vor einen oder mehrere Bewerbe zu lagern und den Typ (Fuß/Pferd) zu kennzeichnen.
Die "Besichtigung zu Pferd" ist ein valider Spezialfall für Springpferdeprüfungen. Die Software muss erlauben,
Besichtigungszeiten flexibel vor einen oder mehrere Bewerbe zu lagern und den Typ (Fuß/Pferd) zu kennzeichnen.
---
*Geprüft durch den 📜 ÖTO/FEI Rulebook Expert am 11.04.2026*
@@ -0,0 +1,62 @@
# 🤖 Konzept: Status-Automat für Nennungen & Zeitplan-Synchronisation
Dieses Dokument spezifiziert die Logik des Status-Automaten für Nennungen (Sprint C-1) und dessen Auswirkungen auf den
dynamischen Zeitplan.
## 1. Status-Definitionen (NennStatusE)
Basierend auf `core-domain/Enums.kt`:
| Status | Bedeutung | Auswirkung auf Zeitplan |
|:-------------------|:--------------------------------------------------|:--------------------------------------------------------|
| `EINGEGANGEN` | Nennung wurde erstellt (Initialzustand) | Belegt Zeitslot (basierend auf `reitdauerMinuten`) |
| `BESTAETIGT` | Meldestelle hat Nennung geprüft | Belegt Zeitslot |
| `NACHNENNUNG` | Nennung nach Nennschluss | Belegt Zeitslot (ggf. am Ende der Liste) |
| `TRANSFERIERT` | Nennung wurde auf anderes Paar übertragen | **Inaktiv** (Original-Eintrag wird durch neuen ersetzt) |
| `ZURUECKGEZOGEN` | Reiter hat abgemeldet (vor Startlistenerstellung) | **Inaktiv** (Slot wird frei) |
| `GESTARTET` | Paar ist in die Prüfung eingeritten | Startzeitpunkt fixiert, Folgestarts ggf. anpassen |
| `NICHT_ANGETRETEN` | Paar ist zum Startzeitpunkt nicht erschienen | **Zeitslot verfällt** oder Folgestarts rücken nach |
## 2. Status-Übergänge & Validierung
### 2.1 Gültige Übergänge (Beispiele)
- `EINGEGANGEN` -> `BESTAETIGT` (Normalfall)
- `EINGEGANGEN` -> `ZURUECKGEZOGEN` (Abmeldung)
- `BESTAETIGT` -> `TRANSFERIERT` (Reitertausch)
- `BESTAETIGT` -> `GESTARTET` (Während des Turniers)
### 2.2 Side-Effects (Side-Effect-Engine)
Wenn sich der Status einer Nennung ändert, müssen folgende Systeme informiert werden:
1. **Billing-Service:** Bei `ZURUECKGEZOGEN` ggf. Stornogebühren prüfen. Bei `TRANSFERIERT` Guthaben übertragen.
2. **Startlisten-Service:** Bei `ZURUECKGEZOGEN` nach Veröffentlichung der Startliste -> Eintrag als
`istGestrichen = true` markieren.
3. **Zeitplan-Optimierung:** Bei `NICHT_ANGETRETEN` -> Alle folgenden Startzeiten rücken um `reitdauerMinuten` nach
vorne (sofern im Kalender-Modus "Dynamisch" aktiv ist).
## 3. Dynamische Zeitplan-Anpassung (C-1 Extension)
Der `StartlistenService` muss eine Methode `aktualisiereZeitplanNachStatusAenderung` erhalten:
- **Szenario A (Nicht angetreten):** Wenn Nennung X `NICHT_ANGETRETEN` wird, rücken alle folgenden Nennungen in der
Abteilung nach vorne.
- **Szenario B (Verspätung):** Wenn Nennung X `GESTARTET` wird, aber 2 Minuten später als geplant, verschieben sich alle
Folgetermine um +2 Minuten (Kettenreaktion).
### Puffer-Regel (ÖTO-Konformität)
- Eine dynamische Verschiebung nach *vorne* darf nie dazu führen, dass ein Reiter vor seiner ursprünglich kommunizierten
Startzeit (oder einem definierten Puffer-Zeitraum von z.B. 15 Minuten) starten muss, ohne dass dies explizit bestätigt
wurde.
## 4. Implementierungs-Leitfaden für Backend (C-1)
1. Erweiterung von `NennungUseCases.statusAendern` um Aufrufe der Side-Effect-Handler.
2. Implementierung des `NennungStatusListener` in `entries-service`.
3. Anbindung an den `StartlistenService` zur Zeitre-Kalkulation.
---
**Status:** Entwurf (Lead Architect)
**Datum:** 11. April 2026
+23 -23
View File
@@ -150,26 +150,26 @@ Code-Stand.*
## 5. Wichtige Referenzen
| Dokument | Pfad |
|---------------------------|----------------------------------------------------------------------------------------------|
| Ubiquitous Language | `docs/03_Domain/01_Glossary/Ubiquitous_Language.md` |
| Abteilungs-Schwellenwerte | `docs/03_Domain/02_Reference/OETO_Regelwerk/Abteilungs-Trennungs-Schwellenwerte.md` |
| Warn-Logik-Spezifikation | `docs/03_Domain/02_Reference/OETO_Regelwerk/Warn-Logik-Spezifikation-competition-context.md` |
| Session Log (DDD) | `docs/99_Journal/2026-03-24_Session_Log_DDD_Ubiquitous_Language.md` |
| Infrastruktur | `docs/07_Infrastructure/Zora_System_Architektur.md` |
| Deployment Guide | `docs/07_Infrastructure/Guides/Setup_Git_Deployment_Zora.md` |
| Backup Guide | `docs/07_Infrastructure/Guides/Setup_Backup_Zora.md` |
| CI/CD | `.gitea/workflows/docker-publish.yaml` |
| Agent Playbooks | `docs/04_Agents/Playbooks/` |
| ADR-Verzeichnis | `docs/01_Architecture/adr/` |
| ADR-0025: Plan-USB | `docs/01_Architecture/adr/0025-plan-usb-offline-integritaet.md` |
| ADR-0026: Lizenzierung | `docs/01_Architecture/adr/0026-offline-lizenzierung-pay-per-event.md` |
| ADR-0027: Discovery | `docs/01_Architecture/adr/0027-netzwerk-discovery-interface-binding.md` |
| Docker-Fix: dc-gui.yaml | `dc-gui.yaml` |
| ZNS-Importer Roadmap | `docs/01_Architecture/Roadmap_ZNS_Importer.md` |
| Masterdata Roadmap | `backend/services/masterdata/docs/ROADMAP.md` |
| Masterdata Changelog | `backend/services/masterdata/docs/CHANGELOG.md` |
| Masterdata Operations | `backend/services/masterdata/docs/runbooks/masterdata-ops.md` |
| Zeitplan-Optimierung | `docs/01_Architecture/konzept-zeitplan-optimierung-de.md` |
| Parcoursbesichtigung-Rulebook | `docs/01_Architecture/rulebook-check-parcoursbesichtigung-de.md` |
| Status-Automat-Nennungen | `docs/01_Architecture/status-automat-nennungen-de.md` |
| Dokument | Pfad |
|-------------------------------|----------------------------------------------------------------------------------------------|
| Ubiquitous Language | `docs/03_Domain/01_Glossary/Ubiquitous_Language.md` |
| Abteilungs-Schwellenwerte | `docs/03_Domain/02_Reference/OETO_Regelwerk/Abteilungs-Trennungs-Schwellenwerte.md` |
| Warn-Logik-Spezifikation | `docs/03_Domain/02_Reference/OETO_Regelwerk/Warn-Logik-Spezifikation-competition-context.md` |
| Session Log (DDD) | `docs/99_Journal/2026-03-24_Session_Log_DDD_Ubiquitous_Language.md` |
| Infrastruktur | `docs/07_Infrastructure/Zora_System_Architektur.md` |
| Deployment Guide | `docs/07_Infrastructure/Guides/Setup_Git_Deployment_Zora.md` |
| Backup Guide | `docs/07_Infrastructure/Guides/Setup_Backup_Zora.md` |
| CI/CD | `.gitea/workflows/docker-publish.yaml` |
| Agent Playbooks | `docs/04_Agents/Playbooks/` |
| ADR-Verzeichnis | `docs/01_Architecture/adr/` |
| ADR-0025: Plan-USB | `docs/01_Architecture/adr/0025-plan-usb-offline-integritaet.md` |
| ADR-0026: Lizenzierung | `docs/01_Architecture/adr/0026-offline-lizenzierung-pay-per-event.md` |
| ADR-0027: Discovery | `docs/01_Architecture/adr/0027-netzwerk-discovery-interface-binding.md` |
| Docker-Fix: dc-gui.yaml | `dc-gui.yaml` |
| ZNS-Importer Roadmap | `docs/01_Architecture/Roadmaps/Roadmap_ZNS_Importer.md` |
| Masterdata Roadmap | `backend/services/masterdata/docs/ROADMAP.md` |
| Masterdata Changelog | `backend/services/masterdata/docs/CHANGELOG.md` |
| Masterdata Operations | `backend/services/masterdata/docs/runbooks/masterdata-ops.md` |
| Zeitplan-Optimierung | `docs/01_Architecture/Concepts/konzept-zeitplan-optimierung-de.md` |
| Parcoursbesichtigung-Rulebook | `docs/01_Architecture/Concepts/rulebook-check-parcoursbesichtigung-de.md` |
| Status-Automat-Nennungen | `docs/01_Architecture/Concepts/status-automat-nennungen-de.md` |
@@ -1,358 +0,0 @@
---
type: Reference
status: ACTIVE
owner: Lead Architect
date: 2026-03-07
---
# Meldestelle — Tech-Stack Zusammenfassung
> **Zweck:** Vollständige Referenz des eingesetzten Tech-Stacks im Projekt "Meldestelle".
> Dient als Basis für Recherchen zu Self-Hosted AI (Codegenerierung, RAG, Agenten).
> **Stand:** 07. März 2026
---
## 1. Überblick
Das Projekt "Meldestelle" ist eine **Kotlin-first, Cloud-native Microservices-Plattform** für die Verwaltung von Reitsport-Meldungen (FEI / ÖTO). Es kombiniert ein **Kotlin Multiplatform (KMP) Frontend** mit einem **Spring Boot Microservices Backend** auf einer vollständig self-hosted Infrastruktur.
```
┌─────────────────────────────────────────────────────────────────┐
│ Frontend (KMP) │ Backend (Spring Boot / Kotlin JVM) │
│ Kotlin 2.3 / Compose │ Java 25 / Spring Boot 3.5.9 │
│ JS + WASM (geplant) │ Microservices + API-Gateway │
├─────────────────────────────────────────────────────────────────┤
│ Infrastruktur (Self-Hosted auf Zora / Proxmox) │
│ Keycloak · Consul · Valkey · PostgreSQL · Zipkin │
│ Prometheus · Grafana · Caddy · Pangolin-Tunnel │
└─────────────────────────────────────────────────────────────────┘
```
---
## 2. Sprachen & Laufzeiten
| Komponente | Sprache / Runtime | Version |
|:------------------|:-------------------------|:------------|
| Backend | Kotlin (JVM) | 2.3.0 |
| Frontend | Kotlin (KMP / JS) | 2.3.0 |
| JVM | Java (Eclipse Temurin) | 25 (EA) |
| Build | Gradle (Kotlin DSL) | 9.3.1 |
| Plattform | ARM64 (AArch64) | Linux |
---
## 3. Frontend — Kotlin Multiplatform (KMP)
### 3.1 Core-Framework
| Bibliothek | Version | Zweck |
|:------------------------------|:----------|:-----------------------------------|
| Kotlin Multiplatform | 2.3.0 | Cross-Platform-Basis (JS + WASM) |
| Compose Multiplatform | 1.10.0 | UI-Framework (Deklarativ) |
| Compose Hot Reload | 1.0.0 | Live-Reload im Dev-Modus |
| Koin (DI) | 4.1.1 | Dependency Injection |
| Koin Compose | 4.1.1 | DI-Integration für Compose |
| Ktor Client | 3.4.0 | HTTP-Client (Multiplatform) |
| Kotlin Serialization | 2.3.0 | JSON-Serialisierung |
### 3.2 Persistenz (Offline-First)
| Bibliothek | Version | Zweck |
|:------------------------------|:----------|:-----------------------------------|
| SQLDelight | 2.2.1 | Cross-Platform SQL-Datenbank |
| SQLite (WASM) | 3.51.1 | SQLite für Browser/WASM |
| SQLite (Native) | 2.6.2 | SQLite für JVM/Desktop |
### 3.3 Build-Targets
| Target | Status | Anmerkung |
|:--------------|:------------|:-----------------------------------|
| KotlinJS | ✅ Aktiv | Primäres Build-Target |
| WASM | ⏳ Geplant | Warten auf Alpha-Version |
| Desktop (JVM) | ⚙️ Möglich | uiDesktop 1.7.0 vorhanden |
### 3.4 Modul-Struktur
```
frontend/
├── core/
│ ├── core-network/ # Ktor HTTP-Client, Auth-Interceptor
│ ├── core-ui/ # Design-System, Tokens, Komponenten
│ ├── core-domain/ # Shared Domain-Models
│ └── core-data/ # Repository-Interfaces
├── features/
│ ├── ping-feature/ # ✅ Blueprint: MVVM + Repository + DI + Tests
│ └── members-feature/ # ⏳ Auskommentiert (nächste Phase)
└── shells/
└── meldestelle-portal/ # Web-App Shell (Caddy-served)
```
---
## 4. Backend — Spring Boot Microservices
### 4.1 Core-Framework
| Bibliothek | Version | Zweck |
|:------------------------------|:----------|:-----------------------------------|
| Spring Boot | 3.5.9 | Microservices-Framework |
| Spring Cloud | 2025.0.1 | Service Discovery, Config |
| Spring Security (OAuth2) | (Boot) | JWT-Validierung, Resource Server |
| Spring Data JPA | (Boot) | ORM-Layer |
| Spring Data Valkey | 0.2.0 | Cache-Integration (Valkey/Redis) |
| Spring WebFlux | (Boot) | Reaktive API (Gateway) |
| Kotlin Coroutines | 2.3.0 | Async/Non-blocking |
### 4.2 Persistenz
| Bibliothek | Version | Zweck |
|:------------------------------|:----------|:-----------------------------------|
| PostgreSQL Driver | 42.7.8 | JDBC-Treiber |
| Exposed (JetBrains) | 1.0.0 | Kotlin-native SQL DSL |
| Flyway | 11.19.1 | Datenbank-Migrationen |
| HikariCP | 7.0.2 | Connection Pool |
> **Strategie (ADR-001):** Hybrid — JPA für einfache CRUD-Entities, Exposed für komplexe Queries und Domain-Logik.
### 4.3 Caching & Messaging
| Bibliothek | Version | Zweck |
|:------------------------------|:----------|:-----------------------------------|
| Lettuce | 6.6.0 | Valkey/Redis-Client (reaktiv) |
| Redisson | 4.0.0 | Distributed Locks, Pub/Sub |
| Caffeine | 3.2.3 | In-Memory Cache (L1) |
| Reactor Kafka | 1.3.23 | Kafka-Client (Phase 3 / Outbox) |
### 4.4 Observability & Tracing
| Bibliothek | Version | Zweck |
|:------------------------------|:----------|:-----------------------------------|
| Micrometer | 1.16.1 | Metriken (Prometheus-Export) |
| Micrometer Tracing | 1.6.1 | Distributed Tracing |
| Zipkin Reporter | 3.5.1 | Trace-Export zu Zipkin |
| Logback | 1.5.25 | Logging |
### 4.5 Security
| Bibliothek | Version | Zweck |
|:------------------------------|:----------|:-----------------------------------|
| Keycloak Admin Client | 26.0.7 | Keycloak-API-Integration |
| Spring Security OAuth2 | (Boot) | JWT Resource Server |
| Jackson (Kotlin) | 3.0.3 | JSON-Serialisierung |
### 4.6 API & Dokumentation
| Bibliothek | Version | Zweck |
|:------------------------------|:----------|:-----------------------------------|
| Springdoc OpenAPI | 3.0.0 | Swagger / OpenAPI 3.1 |
| Jakarta Annotation | 3.0.0 | Jakarta EE Annotations |
### 4.7 Modul-Struktur
```
backend/
├── infrastructure/
│ ├── gateway/ # ✅ API-Gateway (Spring Cloud Gateway)
│ ├── security/ # ✅ Zentrales OAuth2/JWT-Modul (DRY)
│ ├── cache/
│ │ ├── cache-api/ # Interface-Abstraktion
│ │ └── valkey-impl/ # Valkey-Implementierung
│ ├── event-store/
│ │ ├── event-store-api/ # Interface-Abstraktion
│ │ └── valkey-impl/ # Valkey-Implementierung
│ ├── persistence/ # Hybrid JPA + Exposed
│ └── messaging/ # Kafka (Phase 3 / Outbox-Pattern)
└── services/
├── ping/ # ✅ Deployed — Test/Blueprint-Service
├── entries/ # ⚙️ Registriert, noch nicht deployed
├── events/ # 👻 Ghost Service (nicht registriert)
├── horses/ # 👻 Ghost Service (nicht registriert)
├── masterdata/ # 👻 Ghost Service (nicht registriert)
├── registry/ # 👻 Ghost Service (nicht registriert)
├── results/ # 👻 Ghost Service (nicht registriert)
└── scheduling/ # 👻 Ghost Service (nicht registriert)
```
---
## 5. Infrastruktur-Services (Docker)
### 5.1 Laufende Services
| Service | Image / Version | Port(s) | Zweck |
|:---------------|:--------------------------|:--------------|:-----------------------------|
| PostgreSQL | postgres:16-alpine | 5432 | Primäre Datenbank |
| Keycloak | keycloak:26.4 (custom) | 8180, 9000 | IAM / OAuth2 / OIDC |
| Valkey | valkey:8-alpine | 6379 | Cache + Event-Store |
| Consul | consul:1.21 | 8500, 8600 | Service Discovery + Config |
| Zipkin | openzipkin/zipkin:3.5 | 9411 | Distributed Tracing |
| Prometheus | prom/prometheus:v3.4 | 9090 | Metriken-Sammlung |
| Grafana | grafana/grafana:11.6 | 3000 | Dashboards / Visualisierung |
| Caddy | caddy:2.10-alpine | 4000 | Web-App Serving (Frontend) |
| API-Gateway | (custom Spring Boot) | 8081 | Zentraler Eintrittspunkt |
| Ping-Service | (custom Spring Boot) | 8082 | Test/Blueprint-Service |
### 5.2 CI/CD & DevOps
| Tool | Version / Details | Zweck |
|:----------------|:--------------------------|:-----------------------------|
| Gitea | Self-Hosted (CT 101) | Git-Repository + Registry |
| Gitea Actions | (Runner VM 102) | CI/CD-Pipeline |
| Docker Buildx | ARM64 (linux/arm64) | Multi-Arch Image Build |
| Pangolin | Self-Hosted Tunnel | Reverse Proxy / Extern-Zugang|
### 5.3 Netzwerk & Routing
| Subdomain | Intern (Zora) | Zweck |
|:-----------------------|:--------------------|:-------------------------|
| `git.mo-code.at` | `10.0.0.22:3000` | Gitea |
| `api.mo-code.at` | `10.0.0.50:8081` | API-Gateway |
| `auth.mo-code.at` | `10.0.0.50:8180` | Keycloak |
| `app.mo-code.at` | `10.0.0.50:4000` | Web-App |
| `photos.mo-code.at` | `10.0.0.24:2283` | Immich (Fotos) |
---
## 6. Code-Qualität & Build-Tools
| Tool | Version | Zweck |
|:------------------|:----------|:-----------------------------------|
| Detekt | 1.23.6 | Kotlin Static Analysis |
| ktlint | 12.1.1 | Kotlin Code Formatter |
| ArchUnit | 1.4.1 | Architektur-Tests (Layer-Regeln) |
| Dokka | 2.1.0 | API-Dokumentation (KDoc) |
| Ben-Manes Versions| 0.51.0 | Dependency-Update-Check |
| KSP | 2.3.4 | Kotlin Symbol Processing |
### Build-Konfiguration
```properties
# gradle.properties
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.workers.max=8
org.gradle.configuration-cache=false # wegen JS-Test Serialisierungsproblem
org.gradle.dependency.verification=strict
```
---
## 7. Test-Stack
| Bibliothek | Version | Zweck |
|:------------------------------|:----------|:-----------------------------------|
| JUnit Jupiter | 5.11.3 | Unit-Tests |
| JUnit Platform | 1.11.3 | Test-Runner |
| MockK | 1.14.7 | Kotlin Mocking |
| AssertJ | 3.27.7 | Fluent Assertions |
| Testcontainers | 2.0.3 | Integration-Tests (Docker) |
| Testcontainers Keycloak | 4.0.1 | Keycloak-Integration-Tests |
| Testcontainers PostgreSQL | 1.21.4 | DB-Integration-Tests |
| Testcontainers Kafka | 1.21.4 | Kafka-Integration-Tests |
| ArchUnit | 1.4.1 | Architektur-Compliance-Tests |
---
## 8. Architektur-Prinzipien (ADRs)
| ADR | Entscheidung | Status |
|:------|:--------------------------------------------------|:---------|
| 0001 | Modulare Architektur (DDD, Clean Architecture) | ✅ Aktiv |
| 0003 | Microservices-Architektur | ✅ Aktiv |
| 0004 | Event-Driven Communication (Kafka Phase 3) | ✅ Aktiv |
| 001 | Backend-Infrastruktur: Hybrid JPA+Exposed, Valkey | ✅ Aktiv |
| 0013 | Tech-Stack-Stabilisierung 2026 (Versionen) | ✅ Aktiv |
**Kern-Prinzipien:**
- **Offline-First:** SQLDelight als Cross-Platform-DB, Sync-Mechanismus
- **Docs-as-Code:** `/docs` als Single Source of Truth
- **DRY-Infrastruktur:** Shared Security/Cache/EventStore-Module
- **ARM64-Native:** Alle Images für `linux/arm64` gebaut
---
## 9. Relevanz für Self-Hosted AI
### 9.1 Welche AI-Aufgaben entstehen im Projekt?
| Aufgabe | Häufigkeit | Komplexität |
|:---------------------------------|:-----------|:------------|
| Kotlin/Spring Boot Code-Completion| Täglich | Mittel |
| Compose Multiplatform UI-Code | Täglich | Mittel |
| SQL / Exposed DSL Queries | Häufig | Mittel |
| Gradle Kotlin DSL Build-Skripte | Gelegentlich| Niedrig |
| Docker / YAML Konfigurationen | Gelegentlich| Niedrig |
| Architektur-Entscheidungen (ADR) | Selten | Hoch |
| Fachlogik FEI/ÖTO Regelwerk | Selten | Sehr hoch |
### 9.2 Anforderungen an das AI-Modell
```
MUSS:
✅ Kotlin (JVM + Multiplatform) — sehr gute Unterstützung
✅ Spring Boot / Spring Cloud — sehr gute Unterstützung
✅ Compose Multiplatform — gute Unterstützung (neuere Modelle)
✅ SQL / PostgreSQL — sehr gute Unterstützung
✅ Docker / YAML — sehr gute Unterstützung
✅ Deutsch (Fachsprache Reitsport) — für RAG-Dokumente
NICE-TO-HAVE:
⭐ Gradle Kotlin DSL
⭐ Keycloak / OAuth2 / OIDC
⭐ Microservices-Architektur-Patterns
```
### 9.3 Empfohlene Modelle für diesen Stack
| Modell | Größe | Stärke | RAM-Bedarf |
|:------------------------|:-------|:------------------------------------|:-----------|
| `qwen2.5-coder:14b` | 14B | Code (Kotlin, Java, SQL) — Top | ~10 GB |
| `deepseek-coder-v2:16b` | 16B | Code-Completion, Refactoring | ~12 GB |
| `llama3.1:8b` | 8B | Allgemein + Deutsch, schnell | ~6 GB |
| `qwen2.5:32b` | 32B | Architektur, Planung, Fachlogik | ~22 GB |
| `codellama:13b` | 13B | Code-Completion (IntelliJ-Plugin) | ~9 GB |
> **Empfehlung für Zora (64 GB RAM):**
> - **Primär:** `qwen2.5-coder:14b` — bester Kotlin/Spring-Support
> - **Sekundär:** `qwen2.5:32b` — für Architektur und Fachlogik
> - **IntelliJ-Integration:** `codellama:13b` oder `qwen2.5-coder:14b`
### 9.4 RAG-Dokumente (Priorität)
Folgende Projekt-Dokumente sind besonders wertvoll als RAG-Kontext:
```
Hohe Priorität:
├── docs/01_Architecture/MASTER_ROADMAP_2026_Q1.md
├── docs/01_Architecture/adr/ (alle ADRs)
├── docs/04_Agents/Playbooks/ (Agenten-Rollen)
├── gradle/libs.versions.toml (Versions-SSoT)
└── docs/07_Infrastructure/ (Infrastruktur-Referenz)
Mittlere Priorität:
├── docs/05_Backend/ (Backend-Guides)
├── docs/06_Frontend/ (Frontend-Guides)
└── docs/03_Domain/ (Fachlogik-Konzepte)
```
---
## 10. Zusammenfassung
```
TECH-STACK KOMPLEXITÄT
──────────────────────────────────────────────────────
Sprachen: Kotlin (JVM + KMP/JS)
Build: Gradle 9.3.1 + Kotlin DSL + libs.versions.toml
Frontend: Compose Multiplatform 1.10 + SQLDelight 2.2 + Koin 4.1
Backend: Spring Boot 3.5.9 + Spring Cloud 2025.0.1
Persistenz: PostgreSQL 16 + Exposed 1.0 + Flyway 11 + HikariCP 7
Cache: Valkey 8 + Lettuce 6.6 + Caffeine 3.2
Security: Keycloak 26.4 + Spring Security OAuth2 + JWT
Observability: Micrometer 1.16 + Zipkin 3.5 + Prometheus + Grafana 11.6
Service Mesh: Consul 1.21 + Spring Cloud Gateway
Messaging: Kafka (Phase 3) + Reactor Kafka 1.3
CI/CD: Gitea Actions + Docker Buildx (ARM64)
Hosting: Proxmox VE 8.4 + Docker Compose + Pangolin-Tunnel
```
@@ -3,22 +3,26 @@
## 🏗️ [Lead Architect] | 14. April 2026
Dieses Dokument beschreibt die Umsetzung der Online-Nennung für das Turnier in Neumarkt (24. April 2026).
Ziel ist ein schlankes Web-Formular, das strukturierte E-Mails an den `Mail-Service` sendet, welcher diese verarbeitet und in der Desktop-Zentrale zur manuellen Übernahme bereitstellt.
Ziel ist ein schlankes Web-Formular, das strukturierte E-Mails an den `Mail-Service` sendet, welcher diese verarbeitet
und in der Desktop-Zentrale zur manuellen Übernahme bereitstellt.
---
### Phase 1: E-Mail-Infrastruktur (Vorbereitung) ✅
* [x] Definition des Adress-Schemas: `meldestelle-[Turnier-Nr]@mo-code.at`.
* [x] Konfiguration der World4You SMTP/IMAP Zugangsdaten.
* [x] Mailpit Integration für lokale Tests (bereits in `dc-ops.yaml`).
### Phase 2: Das Web-Formular (WasmJS Frontend) ✅
* [x] **Basis-UI:** Erstellung des Formulars gemäß Spezifikation (Reiter, Pferd, Lizenz, Bewerbe).
* [x] **Validierung:** Implementierung der Pflichtfeld-Prüfung (Buttonsperre bis alles ok).
* [x] **Mail-Versand:** Integration des API-Calls an das Backend (`mail-service`), um die Nennung zu speichern.
* [x] **DSGVO:** Checkbox und Hinweistext eingebaut.
### Phase 3: Mail-Service (Backend-Verarbeitung) 🏗️
* [x] **Endpoint:** POST-Endpunkt für direkte Nennungen aus dem Web-Formular implementiert.
* [ ] **Polling:** Implementierung des IMAP-Pollers (imap.world4you.com).
* [ ] **Parsing:** Extraktion der Turnier-Nummer aus dem `To`-Header und Mapping auf das Datenbank-Schema (Tenant).
@@ -26,12 +30,14 @@ Ziel ist ein schlankes Web-Formular, das strukturierte E-Mails an den `Mail-Serv
* [x] **Persistence:** Speichern der eingegangenen "Nennungs-Mails" in einer temporären Tabelle.
### Phase 4: Desktop-Zentrale Integration ✅
* [x] **UI-Tab:** Neuer Reiter "Online-Eingang" in der Turnierverwaltung (`TurnierDetailScreen`).
* [x] **Vorschau:** Anzeige der eingegangenen Nennungen mit Details (`OnlineNennungEingangTabContent`).
* [x] **Übernahme:** "Übernehmen"-Button, der Reiter/Pferd in die Nennung vorausfüllt (`NennungViewModel`).
* [ ] **Abschluss:** Manueller "Bestätigen"-Button zum Versenden der finalen Bestätigungsmail.
### Phase 5: End-to-End Test & Deployment 🚀 (Deadline: 21.04.2026)
* [ ] Test-Nennung über Web-Formular (Mailpit).
* [ ] Verifikation der Schema-Zuordnung im Backend.
* [ ] Live-Test mit `online-nennen@mo-code.at`.
@@ -40,6 +46,7 @@ Ziel ist ein schlankes Web-Formular, das strukturierte E-Mails an den `Mail-Serv
---
### Meilensteine
1. **16.04.:** Web-Formular ist funktionsfähig (Senden möglich).
2. **18.04.:** Mail-Service verarbeitet Mails und sendet Auto-Antworten.
3. **20.04.:** Desktop-UI zur Übernahme ist fertig.
@@ -10,7 +10,9 @@ last_update: 2026-03-25
10. **🏗️ [Lead Architect]** | 5. April 2026
**Kontext:**
Der ZNS-Importer wurde für die Verarbeitung der Datei `RICHT01.dat` optimiert. Es wurde klargestellt, dass Richter (SatzID 'X') und Parcoursbauer (SatzID 'Y') gemeinsam in dieser Datei geliefert werden. Eine separate `PARCO01.dat` existiert nicht.
Der ZNS-Importer wurde für die Verarbeitung der Datei `RICHT01.dat` optimiert. Es wurde klargestellt, dass Richter (
SatzID 'X') und Parcoursbauer (SatzID 'Y') gemeinsam in dieser Datei geliefert werden. Eine separate `PARCO01.dat`
existiert nicht.
Um den `registration-context` und `actor-context` unter realistischen Bedingungen testen zu können, benötigen wir echte
Stammdaten (Reiter, Pferde, Vereine, Funktionäre). Diese Daten werden vom ÖPS (Österreichischer Pferdesportverband) in
Form einer `ZNS.zip` bereitgestellt.
@@ -51,7 +53,8 @@ gesteuert wird und die Daten persistent im Backend (`actor-context`) ablegt.
* ZIP-Entpackung in-memory implementiert (`ZnsImportService`).
* [x] **Legacy-Parser (CP850 Fixed-Width):**
* `ZnsLegacyParsers` in `core:zns-parser` (KMP-Modul) implementiert.
* Alle 4 Dateitypen (VEREIN01, LIZENZ01, PFERDE01, RICHT01) bytegenau gemappt. RICHT01 verarbeitet Richter ('X') und Parcoursbauer ('Y'). ✅
* Alle 4 Dateitypen (VEREIN01, LIZENZ01, PFERDE01, RICHT01) bytegenau gemappt. RICHT01 verarbeitet Richter ('X') und
Parcoursbauer ('Y'). ✅
### Phase 2: Domain-Mapping & Persistenz (👷 Backend Developer)
@@ -0,0 +1,89 @@
---
type: Reference
status: ACTIVE
owner: Lead Architect
last_update: 2026-03-15
---
# Frontend-Architektur & Modularisierungsstrategie
**Status:** ENTWURF
**Zuletzt aktualisiert:** 2026-01-19
**Kontext:** Migration zu Clean Architecture & Feature-Modulen
---
## 1. Übersicht
Die Frontend-Architektur von **Meldestelle** basiert auf **Kotlin Multiplatform (KMP)** mit **Compose Multiplatform**
für die Benutzeroberfläche. Wir folgen einem strikten **Clean Architecture**-Ansatz, um Testbarkeit, Skalierbarkeit und
Trennung der Zuständigkeiten sicherzustellen.
## 2. Modulstruktur
Das Projekt ist in folgende Schichten unterteilt:
### 2.1 Core-Module (`frontend/core`)
Wiederverwendbare Komponenten, die unabhängig von spezifischen Geschäftsfunktionen sind.
* `core-network`: Zentrale HTTP-Client-Konfiguration (Auth, Logging, ContentNegotiation).
* `core-sync`: Generische Synchronisierungslogik (`SyncManager`, `SyncableRepository`).
* `core-ui`: Gemeinsame UI-Komponenten und Design-System.
### 2.2 Feature-Module (`frontend/features`)
Jede Geschäftsdomäne (z.B. `ping`, `auth`, `events`) liegt in ihrem eigenen Modul.
Ein Feature-Modul MUSS die **Clean Architecture** Paketstruktur einhalten:
* `at.mocode.{feature}.feature.domain`
* **Entitäten:** Reine Datenklassen.
* **Interfaces:** Repository-Interfaces, Service-Interfaces.
* **Use Cases:** Geschäftslogik (optional, für komplexe Logik).
* `at.mocode.{feature}.feature.data`
* **Implementierungen:** Repository-Implementierungen, API-Clients.
* **DTOs:** Data Transfer Objects (wenn von Domain-Entitäten abweichend).
* `at.mocode.{feature}.feature.presentation`
* **ViewModels:** Zustandsverwaltung.
* **Screens:** Composable-Funktionen.
* `at.mocode.{feature}.feature.di`
* **Koin-Modul:** Konfiguration der Dependency Injection.
### 2.3 Shells (`frontend/shells`)
Anwendungs-Einstiegspunkte, die alles zusammenführen.
* `meldestelle-portal`: Die Haupt-Web-/Desktop-Anwendung.
## 3. Migrationsstrategie (Übergangsphase)
Wir migrieren aktuell von einer monolithischen `clients`-Paketstruktur zu modularen Feature-Modulen.
**Regeln für die Migration:**
1. **Neue Features:** Müssen direkt in `frontend/features/{name}` unter Verwendung der Clean Architecture-Struktur
implementiert werden.
2. **Bestehende Features:** Werden schrittweise migriert.
3. **Koexistenz:** Während des Übergangs ist Legacy-Code in `clients/` erlaubt, aber als veraltet markiert.
4. **Dependency Injection:** Legacy-Code muss die neuen Koin-Module verwenden, sofern verfügbar.
5. **Keine Ghost-Klassen:** Klassen nicht duplizieren. Wenn eine Klasse in ein Feature-Modul verschoben wird, muss die
alte in `clients/` gelöscht werden.
## 4. Wichtige Entscheidungen (ADRs)
### ADR-001: Entkopplung der Sync-Logik
* **Entscheidung:** ViewModels dürfen nicht direkt vom `SyncManager` abhängen.
* **Begründung:** Um einfacheres Testen zu ermöglichen und die Komplexität des generischen Sync-Mechanismus zu
verbergen.
* **Umsetzung:** Ein Domain-Service-Interface (z.B. `PingSyncService`) einführen, das den `SyncManager`-Aufruf kapselt.
### ADR-002: Feature-Modul-Isolation
* **Entscheidung:** Feature-Module sollten nach Möglichkeit nicht direkt voneinander abhängen.
* **Kommunikation:** Gemeinsame Core-Module oder lose Kopplung über Interfaces/Events verwenden, wenn modulübergreifende
Kommunikation nötig ist.
---
**Freigegeben von:** Lead Architect
@@ -3,11 +3,15 @@ type: Reference
status: ACTIVE
owner: Lead Architect
---
# Architektur: Das Platform-Modul
## Überblick
Das **Platform-Modul** ist das Rückgrat der Build-Infrastruktur des Meldestelle-Projekts. Seine alleinige Aufgabe ist die zentrale Verwaltung und Bereitstellung von Abhängigkeiten und deren Versionen. Dies stellt sicher, dass alle Module im gesamten Projekt dieselben Bibliotheksversionen verwenden, was Inkonsistenzen ("JAR Hell") verhindert und die Wartbarkeit drastisch verbessert.
Das **Platform-Modul** ist das Rückgrat der Build-Infrastruktur des Meldestelle-Projekts. Seine alleinige Aufgabe ist
die zentrale Verwaltung und Bereitstellung von Abhängigkeiten und deren Versionen. Dies stellt sicher, dass alle Module
im gesamten Projekt dieselben Bibliotheksversionen verwenden, was Inkonsistenzen ("JAR Hell") verhindert und die
Wartbarkeit drastisch verbessert.
Das Modul agiert als eine interne "Single Source of Truth" für alle externen Bibliotheken.
@@ -24,19 +28,23 @@ platform/
### `platform-bom`
Dies ist das wichtigste Modul der Plattform. Es ist als "Bill of Materials" (BOM) konfiguriert und nutzt das `java-platform`-Plugin von Gradle.
Dies ist das wichtigste Modul der Plattform. Es ist als "Bill of Materials" (BOM) konfiguriert und nutzt das
`java-platform`-Plugin von Gradle.
* **Zweck:** Definiert eine umfassende Liste von Abhängigkeiten und deren exakten, geprüften Versionen. Es importiert auch andere wichtige BOMs (z.B. von Spring Boot und Kotlin).
* **Funktionsweise:** Andere Module importieren diese BOM mit `platform(projects.platform.platformBom)`. Gradle sorgt dann dafür, dass alle transitiven und deklarierten Abhängigkeiten den in der BOM festgelegten Versionen entsprechen.
* **Zweck:** Definiert eine umfassende Liste von Abhängigkeiten und deren exakten, geprüften Versionen. Es importiert
auch andere wichtige BOMs (z.B. von Spring Boot und Kotlin).
* **Funktionsweise:** Andere Module importieren diese BOM mit `platform(projects.platform.platformBom)`. Gradle sorgt
dann dafür, dass alle transitiven und deklarierten Abhängigkeiten den in der BOM festgelegten Versionen entsprechen.
* **Vorteil:** Absolute Versionskontrolle über das gesamte Projekt.
### `platform-dependencies`
Ein einfaches "Sammelmodul", das die am häufigsten benötigten Laufzeit-Abhängigkeiten bündelt.
* **Zweck:** Vereinfacht die `build.gradle.kts`-Dateien der Service-Module. Anstatt 5-6 einzelne `kotlinx`- und Logging-Bibliotheken hinzuzufügen, genügt eine einzige Abhängigkeit zu diesem Modul.
* **Zweck:** Vereinfacht die `build.gradle.kts`-Dateien der Service-Module. Anstatt 5-6 einzelne `kotlinx`- und
Logging-Bibliotheken hinzuzufügen, genügt eine einzige Abhängigkeit zu diesem Modul.
* **Verwendung:**
```kotlin
// In einem Service-Modul
dependencies {
@@ -48,9 +56,10 @@ Ein einfaches "Sammelmodul", das die am häufigsten benötigten Laufzeit-Abhäng
Analog zu `platform-dependencies`, aber speziell für Test-Bibliotheken.
* **Zweck:** Stellt ein konsistentes Set an Test-Frameworks (JUnit 5, MockK, AssertJ) und Werkzeugen (Testcontainers) für alle Module bereit.
* **Zweck:** Stellt ein konsistentes Set an Test-Frameworks (JUnit 5, MockK, AssertJ) und Werkzeugen (Testcontainers)
für alle Module bereit.
* **Verwendung:**
```kotlin
// In einem Service-Modul
dependencies {
@@ -58,4 +67,5 @@ Analog zu `platform-dependencies`, aber speziell für Test-Bibliotheken.
}
```
* **Optimierung:** Dieses Modul nutzt die in `libs.versions.toml` definierten `[bundles]`, um die Build-Datei extrem kurz und lesbar zu halten.
* **Optimierung:** Dieses Modul nutzt die in `libs.versions.toml` definierten `[bundles]`, um die Build-Datei extrem
kurz und lesbar zu halten.
@@ -0,0 +1,362 @@
---
type: Reference
status: ACTIVE
owner: Lead Architect
date: 2026-03-07
---
# Meldestelle — Tech-Stack Zusammenfassung
> **Zweck:** Vollständige Referenz des eingesetzten Tech-Stacks im Projekt "Meldestelle".
> Dient als Basis für Recherchen zu Self-Hosted AI (Codegenerierung, RAG, Agenten).
> **Stand:** 07. März 2026
---
## 1. Überblick
Das Projekt "Meldestelle" ist eine **Kotlin-first, Cloud-native Microservices-Plattform** für die Verwaltung von
Reitsport-Meldungen (FEI / ÖTO). Es kombiniert ein **Kotlin Multiplatform (KMP) Frontend** mit einem **Spring Boot
Microservices Backend** auf einer vollständig self-hosted Infrastruktur.
```
┌─────────────────────────────────────────────────────────────────┐
│ Frontend (KMP) │ Backend (Spring Boot / Kotlin JVM) │
│ Kotlin 2.3 / Compose │ Java 25 / Spring Boot 3.5.9 │
│ JS + WASM (geplant) │ Microservices + API-Gateway │
├─────────────────────────────────────────────────────────────────┤
│ Infrastruktur (Self-Hosted auf Zora / Proxmox) │
│ Keycloak · Consul · Valkey · PostgreSQL · Zipkin │
│ Prometheus · Grafana · Caddy · Pangolin-Tunnel │
└─────────────────────────────────────────────────────────────────┘
```
---
## 2. Sprachen & Laufzeiten
| Komponente | Sprache / Runtime | Version |
|:-----------|:-----------------------|:--------|
| Backend | Kotlin (JVM) | 2.3.0 |
| Frontend | Kotlin (KMP / JS) | 2.3.0 |
| JVM | Java (Eclipse Temurin) | 25 (EA) |
| Build | Gradle (Kotlin DSL) | 9.3.1 |
| Plattform | ARM64 (AArch64) | Linux |
---
## 3. Frontend — Kotlin Multiplatform (KMP)
### 3.1 Core-Framework
| Bibliothek | Version | Zweck |
|:----------------------|:--------|:---------------------------------|
| Kotlin Multiplatform | 2.3.0 | Cross-Platform-Basis (JS + WASM) |
| Compose Multiplatform | 1.10.0 | UI-Framework (Deklarativ) |
| Compose Hot Reload | 1.0.0 | Live-Reload im Dev-Modus |
| Koin (DI) | 4.1.1 | Dependency Injection |
| Koin Compose | 4.1.1 | DI-Integration für Compose |
| Ktor Client | 3.4.0 | HTTP-Client (Multiplatform) |
| Kotlin Serialization | 2.3.0 | JSON-Serialisierung |
### 3.2 Persistenz (Offline-First)
| Bibliothek | Version | Zweck |
|:----------------|:--------|:-----------------------------|
| SQLDelight | 2.2.1 | Cross-Platform SQL-Datenbank |
| SQLite (WASM) | 3.51.1 | SQLite für Browser/WASM |
| SQLite (Native) | 2.6.2 | SQLite für JVM/Desktop |
### 3.3 Build-Targets
| Target | Status | Anmerkung |
|:--------------|:-----------|:--------------------------|
| KotlinJS | ✅ Aktiv | Primäres Build-Target |
| WASM | ⏳ Geplant | Warten auf Alpha-Version |
| Desktop (JVM) | ⚙️ Möglich | uiDesktop 1.7.0 vorhanden |
### 3.4 Modul-Struktur
```
frontend/
├── core/
│ ├── core-network/ # Ktor HTTP-Client, Auth-Interceptor
│ ├── core-ui/ # Design-System, Tokens, Komponenten
│ ├── core-domain/ # Shared Domain-Models
│ └── core-data/ # Repository-Interfaces
├── features/
│ ├── ping-feature/ # ✅ Blueprint: MVVM + Repository + DI + Tests
│ └── members-feature/ # ⏳ Auskommentiert (nächste Phase)
└── shells/
└── meldestelle-portal/ # Web-App Shell (Caddy-served)
```
---
## 4. Backend — Spring Boot Microservices
### 4.1 Core-Framework
| Bibliothek | Version | Zweck |
|:-------------------------|:---------|:---------------------------------|
| Spring Boot | 3.5.9 | Microservices-Framework |
| Spring Cloud | 2025.0.1 | Service Discovery, Config |
| Spring Security (OAuth2) | (Boot) | JWT-Validierung, Resource Server |
| Spring Data JPA | (Boot) | ORM-Layer |
| Spring Data Valkey | 0.2.0 | Cache-Integration (Valkey/Redis) |
| Spring WebFlux | (Boot) | Reaktive API (Gateway) |
| Kotlin Coroutines | 2.3.0 | Async/Non-blocking |
### 4.2 Persistenz
| Bibliothek | Version | Zweck |
|:--------------------|:--------|:----------------------|
| PostgreSQL Driver | 42.7.8 | JDBC-Treiber |
| Exposed (JetBrains) | 1.0.0 | Kotlin-native SQL DSL |
| Flyway | 11.19.1 | Datenbank-Migrationen |
| HikariCP | 7.0.2 | Connection Pool |
> **Strategie (ADR-001):** Hybrid — JPA für einfache CRUD-Entities, Exposed für komplexe Queries und Domain-Logik.
### 4.3 Caching & Messaging
| Bibliothek | Version | Zweck |
|:--------------|:--------|:--------------------------------|
| Lettuce | 6.6.0 | Valkey/Redis-Client (reaktiv) |
| Redisson | 4.0.0 | Distributed Locks, Pub/Sub |
| Caffeine | 3.2.3 | In-Memory Cache (L1) |
| Reactor Kafka | 1.3.23 | Kafka-Client (Phase 3 / Outbox) |
### 4.4 Observability & Tracing
| Bibliothek | Version | Zweck |
|:-------------------|:--------|:-----------------------------|
| Micrometer | 1.16.1 | Metriken (Prometheus-Export) |
| Micrometer Tracing | 1.6.1 | Distributed Tracing |
| Zipkin Reporter | 3.5.1 | Trace-Export zu Zipkin |
| Logback | 1.5.25 | Logging |
### 4.5 Security
| Bibliothek | Version | Zweck |
|:-----------------------|:--------|:-------------------------|
| Keycloak Admin Client | 26.0.7 | Keycloak-API-Integration |
| Spring Security OAuth2 | (Boot) | JWT Resource Server |
| Jackson (Kotlin) | 3.0.3 | JSON-Serialisierung |
### 4.6 API & Dokumentation
| Bibliothek | Version | Zweck |
|:-------------------|:--------|:-----------------------|
| Springdoc OpenAPI | 3.0.0 | Swagger / OpenAPI 3.1 |
| Jakarta Annotation | 3.0.0 | Jakarta EE Annotations |
### 4.7 Modul-Struktur
```
backend/
├── infrastructure/
│ ├── gateway/ # ✅ API-Gateway (Spring Cloud Gateway)
│ ├── security/ # ✅ Zentrales OAuth2/JWT-Modul (DRY)
│ ├── cache/
│ │ ├── cache-api/ # Interface-Abstraktion
│ │ └── valkey-impl/ # Valkey-Implementierung
│ ├── event-store/
│ │ ├── event-store-api/ # Interface-Abstraktion
│ │ └── valkey-impl/ # Valkey-Implementierung
│ ├── persistence/ # Hybrid JPA + Exposed
│ └── messaging/ # Kafka (Phase 3 / Outbox-Pattern)
└── services/
├── ping/ # ✅ Deployed — Test/Blueprint-Service
├── entries/ # ⚙️ Registriert, noch nicht deployed
├── events/ # 👻 Ghost Service (nicht registriert)
├── horses/ # 👻 Ghost Service (nicht registriert)
├── masterdata/ # 👻 Ghost Service (nicht registriert)
├── registry/ # 👻 Ghost Service (nicht registriert)
├── results/ # 👻 Ghost Service (nicht registriert)
└── scheduling/ # 👻 Ghost Service (nicht registriert)
```
---
## 5. Infrastruktur-Services (Docker)
### 5.1 Laufende Services
| Service | Image / Version | Port(s) | Zweck |
|:-------------|:-----------------------|:-----------|:----------------------------|
| PostgreSQL | postgres:16-alpine | 5432 | Primäre Datenbank |
| Keycloak | keycloak:26.4 (custom) | 8180, 9000 | IAM / OAuth2 / OIDC |
| Valkey | valkey:8-alpine | 6379 | Cache + Event-Store |
| Consul | consul:1.21 | 8500, 8600 | Service Discovery + Config |
| Zipkin | openzipkin/zipkin:3.5 | 9411 | Distributed Tracing |
| Prometheus | prom/prometheus:v3.4 | 9090 | Metriken-Sammlung |
| Grafana | grafana/grafana:11.6 | 3000 | Dashboards / Visualisierung |
| Caddy | caddy:2.10-alpine | 4000 | Web-App Serving (Frontend) |
| API-Gateway | (custom Spring Boot) | 8081 | Zentraler Eintrittspunkt |
| Ping-Service | (custom Spring Boot) | 8082 | Test/Blueprint-Service |
### 5.2 CI/CD & DevOps
| Tool | Version / Details | Zweck |
|:--------------|:---------------------|:------------------------------|
| Gitea | Self-Hosted (CT 101) | Git-Repository + Registry |
| Gitea Actions | (Runner VM 102) | CI/CD-Pipeline |
| Docker Buildx | ARM64 (linux/arm64) | Multi-Arch Image Build |
| Pangolin | Self-Hosted Tunnel | Reverse Proxy / Extern-Zugang |
### 5.3 Netzwerk & Routing
| Subdomain | Intern (Zora) | Zweck |
|:--------------------|:-----------------|:---------------|
| `git.mo-code.at` | `10.0.0.22:3000` | Gitea |
| `api.mo-code.at` | `10.0.0.50:8081` | API-Gateway |
| `auth.mo-code.at` | `10.0.0.50:8180` | Keycloak |
| `app.mo-code.at` | `10.0.0.50:4000` | Web-App |
| `photos.mo-code.at` | `10.0.0.24:2283` | Immich (Fotos) |
---
## 6. Code-Qualität & Build-Tools
| Tool | Version | Zweck |
|:-------------------|:--------|:---------------------------------|
| Detekt | 1.23.6 | Kotlin Static Analysis |
| ktlint | 12.1.1 | Kotlin Code Formatter |
| ArchUnit | 1.4.1 | Architektur-Tests (Layer-Regeln) |
| Dokka | 2.1.0 | API-Dokumentation (KDoc) |
| Ben-Manes Versions | 0.51.0 | Dependency-Update-Check |
| KSP | 2.3.4 | Kotlin Symbol Processing |
### Build-Konfiguration
```properties
# gradle.properties
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.workers.max=8
org.gradle.configuration-cache=false # wegen JS-Test Serialisierungsproblem
org.gradle.dependency.verification=strict
```
---
## 7. Test-Stack
| Bibliothek | Version | Zweck |
|:--------------------------|:--------|:-----------------------------|
| JUnit Jupiter | 5.11.3 | Unit-Tests |
| JUnit Platform | 1.11.3 | Test-Runner |
| MockK | 1.14.7 | Kotlin Mocking |
| AssertJ | 3.27.7 | Fluent Assertions |
| Testcontainers | 2.0.3 | Integration-Tests (Docker) |
| Testcontainers Keycloak | 4.0.1 | Keycloak-Integration-Tests |
| Testcontainers PostgreSQL | 1.21.4 | DB-Integration-Tests |
| Testcontainers Kafka | 1.21.4 | Kafka-Integration-Tests |
| ArchUnit | 1.4.1 | Architektur-Compliance-Tests |
---
## 8. Architektur-Prinzipien (ADRs)
| ADR | Entscheidung | Status |
|:-----|:--------------------------------------------------|:--------|
| 0001 | Modulare Architektur (DDD, Clean Architecture) | ✅ Aktiv |
| 0003 | Microservices-Architektur | ✅ Aktiv |
| 0004 | Event-Driven Communication (Kafka Phase 3) | ✅ Aktiv |
| 001 | Backend-Infrastruktur: Hybrid JPA+Exposed, Valkey | ✅ Aktiv |
| 0013 | Tech-Stack-Stabilisierung 2026 (Versionen) | ✅ Aktiv |
**Kern-Prinzipien:**
- **Offline-First:** SQLDelight als Cross-Platform-DB, Sync-Mechanismus
- **Docs-as-Code:** `/docs` als Single Source of Truth
- **DRY-Infrastruktur:** Shared Security/Cache/EventStore-Module
- **ARM64-Native:** Alle Images für `linux/arm64` gebaut
---
## 9. Relevanz für Self-Hosted AI
### 9.1 Welche AI-Aufgaben entstehen im Projekt?
| Aufgabe | Häufigkeit | Komplexität |
|:-----------------------------------|:-------------|:------------|
| Kotlin/Spring Boot Code-Completion | Täglich | Mittel |
| Compose Multiplatform UI-Code | Täglich | Mittel |
| SQL / Exposed DSL Queries | Häufig | Mittel |
| Gradle Kotlin DSL Build-Skripte | Gelegentlich | Niedrig |
| Docker / YAML Konfigurationen | Gelegentlich | Niedrig |
| Architektur-Entscheidungen (ADR) | Selten | Hoch |
| Fachlogik FEI/ÖTO Regelwerk | Selten | Sehr hoch |
### 9.2 Anforderungen an das AI-Modell
```
MUSS:
✅ Kotlin (JVM + Multiplatform) — sehr gute Unterstützung
✅ Spring Boot / Spring Cloud — sehr gute Unterstützung
✅ Compose Multiplatform — gute Unterstützung (neuere Modelle)
✅ SQL / PostgreSQL — sehr gute Unterstützung
✅ Docker / YAML — sehr gute Unterstützung
✅ Deutsch (Fachsprache Reitsport) — für RAG-Dokumente
NICE-TO-HAVE:
⭐ Gradle Kotlin DSL
⭐ Keycloak / OAuth2 / OIDC
⭐ Microservices-Architektur-Patterns
```
### 9.3 Empfohlene Modelle für diesen Stack
| Modell | Größe | Stärke | RAM-Bedarf |
|:------------------------|:------|:----------------------------------|:-----------|
| `qwen2.5-coder:14b` | 14B | Code (Kotlin, Java, SQL) — Top | ~10 GB |
| `deepseek-coder-v2:16b` | 16B | Code-Completion, Refactoring | ~12 GB |
| `llama3.1:8b` | 8B | Allgemein + Deutsch, schnell | ~6 GB |
| `qwen2.5:32b` | 32B | Architektur, Planung, Fachlogik | ~22 GB |
| `codellama:13b` | 13B | Code-Completion (IntelliJ-Plugin) | ~9 GB |
> **Empfehlung für Zora (64 GB RAM):**
> - **Primär:** `qwen2.5-coder:14b` — bester Kotlin/Spring-Support
> - **Sekundär:** `qwen2.5:32b` — für Architektur und Fachlogik
> - **IntelliJ-Integration:** `codellama:13b` oder `qwen2.5-coder:14b`
### 9.4 RAG-Dokumente (Priorität)
Folgende Projekt-Dokumente sind besonders wertvoll als RAG-Kontext:
```
Hohe Priorität:
├── docs/01_Architecture/MASTER_ROADMAP_2026_Q1.md
├── docs/01_Architecture/adr/ (alle ADRs)
├── docs/04_Agents/Playbooks/ (Agenten-Rollen)
├── gradle/libs.versions.toml (Versions-SSoT)
└── docs/07_Infrastructure/ (Infrastruktur-Referenz)
Mittlere Priorität:
├── docs/05_Backend/ (Backend-Guides)
├── docs/06_Frontend/ (Frontend-Guides)
└── docs/03_Domain/ (Fachlogik-Konzepte)
```
---
## 10. Zusammenfassung
```
TECH-STACK KOMPLEXITÄT
──────────────────────────────────────────────────────
Sprachen: Kotlin (JVM + KMP/JS)
Build: Gradle 9.3.1 + Kotlin DSL + libs.versions.toml
Frontend: Compose Multiplatform 1.10 + SQLDelight 2.2 + Koin 4.1
Backend: Spring Boot 3.5.9 + Spring Cloud 2025.0.1
Persistenz: PostgreSQL 16 + Exposed 1.0 + Flyway 11 + HikariCP 7
Cache: Valkey 8 + Lettuce 6.6 + Caffeine 3.2
Security: Keycloak 26.4 + Spring Security OAuth2 + JWT
Observability: Micrometer 1.16 + Zipkin 3.5 + Prometheus + Grafana 11.6
Service Mesh: Consul 1.21 + Spring Cloud Gateway
Messaging: Kafka (Phase 3) + Reactor Kafka 1.3
CI/CD: Gitea Actions + Docker Buildx (ARM64)
Hosting: Proxmox VE 8.4 + Docker Compose + Pangolin-Tunnel
```
@@ -10,23 +10,27 @@ Cups/Serien.
## 1) Fokus-Themen und Deliverables (heute Nacht)
1. Reporting & Output (Vorbereitung)
- [Owner] Vorlagen sammeln/übermitteln: Startlisten, Ergebnislisten (PDF/Scan/Excel)
- [Owner] Spring-Protokolle: Inhalte/Felder definieren (Fehler, Zeit, Stechen)
- [Owner] Dressur-Protokolle: Vorlage für personalisierten Ausdruck (Kopfzeile Reiter/Pferd)
- [Arch/BE] Technik-Entscheidung PDF: KMP-Library vs. Server-Side Rendering (ADR-Entwurf)
- [FE] UI-Draft „Druckvorschau“ in V2-Screens: Platzhalter mit Beispiel-Daten
- [Owner] Vorlagen sammeln/übermitteln: Startlisten, Ergebnislisten (PDF/Scan/Excel)
- [Owner] Spring-Protokolle: Inhalte/Felder definieren (Fehler, Zeit, Stechen)
- [Owner] Dressur-Protokolle: Vorlage für personalisierten Ausdruck (Kopfzeile Reiter/Pferd)
- [Arch/BE] Technik-Entscheidung PDF: KMP-Library vs. Server-Side Rendering (ADR-Entwurf)
- [FE] UI-Draft „Druckvorschau“ in V2-Screens: Platzhalter mit Beispiel-Daten
2. Events/Turniere (Backend-Readiness für Neumarkt)
- [BE] DB-Migrationen finalisieren: `turniere`, `ausschreibungen` (Flyway)
- [BE] Seed-Datensatz „Veranstaltung Neumarkt 2026“ (+ 12 Turniere)
- [BE] Repositories prüfen und Test-Cases anlegen (Roundtrip CRUD)
- [BE] DB-Migrationen finalisieren: `turniere`, `ausschreibungen` (Flyway)
- [BE] Seed-Datensatz „Veranstaltung Neumarkt 2026“ (+ 12 Turniere)
- [BE] Repositories prüfen und Test-Cases anlegen (Roundtrip CRUD)
3. Identity & Profil (Verifikation)
- [QA] E2E-Check „ZNS-Link“: Login → Profile → Satznummer verknüpfen → Refresh
- [FE] Validation/UX-Polish im `profile-feature`
- [QA] E2E-Check „ZNS-Link“: Login → Profile → Satznummer verknüpfen → Refresh
- [FE] Validation/UX-Polish im `profile-feature`
4. Live-Ergebnisse Vision (Input sammeln)
- [Owner] Skizze/Mock für mobile Web-Ansicht (Zuschauer): Bewerb → Abteilungen → Live-Board
- [Owner] Skizze/Mock für mobile Web-Ansicht (Zuschauer): Bewerb → Abteilungen → Live-Board
---
@@ -1,51 +0,0 @@
# 🤖 Konzept: Status-Automat für Nennungen & Zeitplan-Synchronisation
Dieses Dokument spezifiziert die Logik des Status-Automaten für Nennungen (Sprint C-1) und dessen Auswirkungen auf den dynamischen Zeitplan.
## 1. Status-Definitionen (NennStatusE)
Basierend auf `core-domain/Enums.kt`:
| Status | Bedeutung | Auswirkung auf Zeitplan |
| :--- | :--- | :--- |
| `EINGEGANGEN` | Nennung wurde erstellt (Initialzustand) | Belegt Zeitslot (basierend auf `reitdauerMinuten`) |
| `BESTAETIGT` | Meldestelle hat Nennung geprüft | Belegt Zeitslot |
| `NACHNENNUNG` | Nennung nach Nennschluss | Belegt Zeitslot (ggf. am Ende der Liste) |
| `TRANSFERIERT` | Nennung wurde auf anderes Paar übertragen | **Inaktiv** (Original-Eintrag wird durch neuen ersetzt) |
| `ZURUECKGEZOGEN`| Reiter hat abgemeldet (vor Startlistenerstellung) | **Inaktiv** (Slot wird frei) |
| `GESTARTET` | Paar ist in die Prüfung eingeritten | Startzeitpunkt fixiert, Folgestarts ggf. anpassen |
| `NICHT_ANGETRETEN`| Paar ist zum Startzeitpunkt nicht erschienen | **Zeitslot verfällt** oder Folgestarts rücken nach |
## 2. Status-Übergänge & Validierung
### 2.1 Gültige Übergänge (Beispiele)
- `EINGEGANGEN` -> `BESTAETIGT` (Normalfall)
- `EINGEGANGEN` -> `ZURUECKGEZOGEN` (Abmeldung)
- `BESTAETIGT` -> `TRANSFERIERT` (Reitertausch)
- `BESTAETIGT` -> `GESTARTET` (Während des Turniers)
### 2.2 Side-Effects (Side-Effect-Engine)
Wenn sich der Status einer Nennung ändert, müssen folgende Systeme informiert werden:
1. **Billing-Service:** Bei `ZURUECKGEZOGEN` ggf. Stornogebühren prüfen. Bei `TRANSFERIERT` Guthaben übertragen.
2. **Startlisten-Service:** Bei `ZURUECKGEZOGEN` nach Veröffentlichung der Startliste -> Eintrag als `istGestrichen = true` markieren.
3. **Zeitplan-Optimierung:** Bei `NICHT_ANGETRETEN` -> Alle folgenden Startzeiten rücken um `reitdauerMinuten` nach vorne (sofern im Kalender-Modus "Dynamisch" aktiv ist).
## 3. Dynamische Zeitplan-Anpassung (C-1 Extension)
Der `StartlistenService` muss eine Methode `aktualisiereZeitplanNachStatusAenderung` erhalten:
- **Szenario A (Nicht angetreten):** Wenn Nennung X `NICHT_ANGETRETEN` wird, rücken alle folgenden Nennungen in der Abteilung nach vorne.
- **Szenario B (Verspätung):** Wenn Nennung X `GESTARTET` wird, aber 2 Minuten später als geplant, verschieben sich alle Folgetermine um +2 Minuten (Kettenreaktion).
### Puffer-Regel (ÖTO-Konformität)
- Eine dynamische Verschiebung nach *vorne* darf nie dazu führen, dass ein Reiter vor seiner ursprünglich kommunizierten Startzeit (oder einem definierten Puffer-Zeitraum von z.B. 15 Minuten) starten muss, ohne dass dies explizit bestätigt wurde.
## 4. Implementierungs-Leitfaden für Backend (C-1)
1. Erweiterung von `NennungUseCases.statusAendern` um Aufrufe der Side-Effect-Handler.
2. Implementierung des `NennungStatusListener` in `entries-service`.
3. Anbindung an den `StartlistenService` zur Zeitre-Kalkulation.
---
**Status:** Entwurf (Lead Architect)
**Datum:** 11. April 2026