Compare commits
4 Commits
8b294d947d
...
9bee2f233e
| Author | SHA1 | Date | |
|---|---|---|---|
| 9bee2f233e | |||
| c317147ca4 | |||
| 15222b5453 | |||
| 6f15ada447 |
@@ -0,0 +1,44 @@
|
|||||||
|
name: Feature Build — Windows MSI
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "feature/*" ] # Reagiert auf alle Feature-Branches
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
package-windows:
|
||||||
|
name: 📦 Windows .msi Packaging
|
||||||
|
# Nur ausführen, wenn Desktop-CI explizit aktiviert ist
|
||||||
|
if: ${{ vars.DESKTOP_CI_ENABLED == 'true' }}
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup JDK 21 (Temurin)
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: '21'
|
||||||
|
|
||||||
|
- name: Gradle cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.gradle/caches
|
||||||
|
~/.gradle/wrapper
|
||||||
|
.gradle
|
||||||
|
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'gradle.properties') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-gradle-
|
||||||
|
|
||||||
|
- name: Windows .msi bauen
|
||||||
|
env:
|
||||||
|
_JAVA_OPTIONS: -Djava.awt.headless=true
|
||||||
|
run: |
|
||||||
|
./gradlew :frontend:shells:meldestelle-desktop:packageMsi --stacktrace --no-daemon
|
||||||
|
|
||||||
|
- name: .msi Artefakt hochladen
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: meldestelle-windows-feature-build
|
||||||
|
path: frontend/shells/meldestelle-desktop/build/compose/binaries/main/msi/*.msi
|
||||||
|
if-no-files-found: warn
|
||||||
@@ -3,7 +3,7 @@ name: "${PROJECT_NAME:-meldestelle}"
|
|||||||
include:
|
include:
|
||||||
- dc-infra.yaml
|
- dc-infra.yaml
|
||||||
- dc-backend.yaml
|
- dc-backend.yaml
|
||||||
- dc-gui.yaml
|
#- dc-gui.yaml
|
||||||
- dc-ops.yaml
|
- dc-ops.yaml
|
||||||
|
|
||||||
# Globale Definitionen, falls nötig (meistens reichen die in den Teil-Dateien,
|
# Globale Definitionen, falls nötig (meistens reichen die in den Teil-Dateien,
|
||||||
|
|||||||
@@ -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
|
Status: April 2026
|
||||||
|
|
||||||
## ✅ Abgeschlossene Migrationen (Feature-Module)
|
## ✅ Abgeschlossene Migrationen (Feature-Module)
|
||||||
|
|
||||||
- `billing-feature`: `at.mocode.frontend.features.billing` (KMP)
|
- `billing-feature`: `at.mocode.frontend.features.billing` (KMP)
|
||||||
- `verein-feature`: `at.mocode.frontend.features.verein` (KMP)
|
- `verein-feature`: `at.mocode.frontend.features.verein` (KMP)
|
||||||
- `nennung-feature`: `at.mocode.frontend.features.nennung` (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)
|
- `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)
|
## 🚧 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.
|
1. **Onboarding**: `OnboardingScreen.kt` -> Design-System Integration erfolgt, KMP-Modul folgt.
|
||||||
|
|
||||||
## 🧹 Architektur-Cleanup
|
## 🧹 Architektur-Cleanup
|
||||||
|
|
||||||
- [ ] `at.mocode.desktop.v2.StoreV2` entfernen, sobald alle Screens auf ViewModels und API-Repositories umgestellt sind.
|
- [ ] `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`.
|
- [ ] `at.mocode.desktop.v2.TurnierStoreV2` konsolidieren mit dem `turnier-feature`.
|
||||||
- [ ] Paketnamen vereinheitlichen: `at.mocode.ping.feature` -> `at.mocode.frontend.features.ping`.
|
- [ ] 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.
|
- [ ] `DesktopMainLayout.kt`: Die `when`-Zweige für `v2` Screens aufräumen, sobald die Module bereit sind.
|
||||||
|
|
||||||
## ✅ Abgeschlossen am 11.04.2026
|
## ✅ Abgeschlossen am 11.04.2026
|
||||||
|
|
||||||
- Migration `pferde-feature`, `reiter-feature`, `funktionaer-feature`, `veranstalter-feature`.
|
- Migration `pferde-feature`, `reiter-feature`, `funktionaer-feature`, `veranstalter-feature`.
|
||||||
- Integration in `DesktopMainLayout` und `AppScreen`.
|
- Integration in `DesktopMainLayout` und `AppScreen`.
|
||||||
- Bereinigung der Repository-Pakete.
|
- Bereinigung der Repository-Pakete.
|
||||||
@@ -9,7 +9,9 @@ last_update: 2026-04-03
|
|||||||
|
|
||||||
## Ziel und Rahmen
|
## 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.
|
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.
|
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.
|
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.
|
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.
|
5. Deterministische Konfliktauflösung: Lamport-Uhren + Regel-Matrix; keine Abhängigkeit von Systemuhren.
|
||||||
|
|
||||||
## Topologie & Rollen
|
## Topologie & Rollen
|
||||||
|
|
||||||
- Backend (Zentrale Plattform):
|
- 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).
|
- Aggregations-/Archiv-Quelle nach Veranstaltungsende (finale Ergebnisse, Abrechnungen).
|
||||||
- Desktop (Meldestelle-Zentrale):
|
- 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.
|
- Master während der Veranstaltung für: Nennungen (operativ), Startreihenfolgen, Startlisten-Status,
|
||||||
- Hält lokales `SyncEvent`-Log + Snapshots (vgl. ADR-0022) und synchronisiert mit Backend, sobald Konnektivität besteht.
|
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
|
## Datenkategorien & Mastership
|
||||||
|
|
||||||
| Kategorie | Master | Desktop Rechte | Backend Rechte |
|
| Kategorie | Master | Desktop Rechte | Backend Rechte |
|
||||||
|--------------------------|----------------|--------------------------------|-----------------------------------|
|
|---------------------------|-----------------|----------------------------------------------|----------------------------------|
|
||||||
| Stammdaten (Actor) | Backend | Lesen, lokal „provisional“ anlegen (Temp-ID) | Vollzugriff, ID-Zuteilung, Merge |
|
| Stammdaten (Actor) | Backend | Lesen, lokal „provisional“ anlegen (Temp-ID) | Vollzugriff, ID-Zuteilung, Merge |
|
||||||
| Veranstaltungs-Stammdaten| Backend | Lesen | Vollzugriff |
|
| Veranstaltungs-Stammdaten | Backend | Lesen | Vollzugriff |
|
||||||
| Nennungen operativ | Desktop | Vollzugriff | Lesen, Import nach Sync |
|
| Nennungen operativ | Desktop | Vollzugriff | Lesen, Import nach Sync |
|
||||||
| Startreihenfolge/Status | Desktop | Vollzugriff | Lesen, Import nach Sync |
|
| Startreihenfolge/Status | Desktop | Vollzugriff | Lesen, Import nach Sync |
|
||||||
| Bewertungen/Ergebnisse | Desktop/Richter| Vollzugriff (Eventzeitraum) | Lesen, Publikation/Archiv |
|
| Bewertungen/Ergebnisse | Desktop/Richter | Vollzugriff (Eventzeitraum) | Lesen, Publikation/Archiv |
|
||||||
| Kassa/Finanzen vor Ort | Desktop | Vollzugriff | Lesen, Abgleich Summen |
|
| 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`)
|
## Änderungsmodell (Wiederverwendung `SyncEvent`)
|
||||||
|
|
||||||
@@ -71,11 +79,13 @@ data class SyncEvent(
|
|||||||
## Lamport-Uhren & Vector-Clock (Optional)
|
## Lamport-Uhren & Vector-Clock (Optional)
|
||||||
|
|
||||||
- Primär: Lamport-Uhren wie ADR-0022. Gleichstand → lexikografisch größere `originNodeId` gewinnt (Determinismus).
|
- 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)
|
## 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`):
|
Empfohlene Endpunkte (pro `eventId`):
|
||||||
|
|
||||||
@@ -94,42 +104,55 @@ Idempotenz: Jeder `SyncEvent` wird durch `(eventId, originNodeId, sequenceNumber
|
|||||||
## Konfliktauflösung
|
## Konfliktauflösung
|
||||||
|
|
||||||
1) Strukturkonflikte (gleiches Aggregat, konkurrierende Events):
|
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):
|
- Beide Master (Sonderfälle, z. B. Ergebnisse während parallelem Backend-Fix):
|
||||||
- Lamport höher gewinnt.
|
- Lamport höher gewinnt.
|
||||||
- Gleichstand → `originNodeId`-Tiebreaker.
|
- 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):
|
2) Identitätskonflikte (provisionale Stammdaten):
|
||||||
|
|
||||||
- Desktop darf temporäre Einträge (Temp-ID `tmp-...`) erzeugen.
|
- 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.
|
- 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:
|
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
|
## 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.
|
- Snapshot-Intervall: standardmäßig 100 Events pro `(aggregateType, scope)` (wie ADR-0022), für WAN-Sync zusätzlich
|
||||||
- Recovery: Desktop kann mit leerem Log starten → `snapshot/request` → Full-State + `snapshotSeq` → weitere Deltas über `pull`.
|
Full-State-Snapshot pro Veranstaltung vor Event-Abschluss.
|
||||||
- USB-Fallback (Notbetrieb): Export/Import von `sync_events` und `sync_snapshots` als verschlüsselte Archive (`.msync`). Offene Spezifikation; separater PoC.
|
- 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
|
## Sicherheit
|
||||||
|
|
||||||
- Mandantentrennung: Jeder Request trägt `X-Event-Id` (ADR-0021). Backend validiert gegen `control.tenants`.
|
- 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.
|
- Integrität: `checksum` pro Event wird serverseitig geprüft; Mismatch → Reject.
|
||||||
- Rechte: Backend erzwingt Mastership-Regeln serverseitig; Verstöße → `PENDING_REVIEW` + Audit-Log.
|
- Rechte: Backend erzwingt Mastership-Regeln serverseitig; Verstöße → `PENDING_REVIEW` + Audit-Log.
|
||||||
|
|
||||||
## Fehlerfälle & Resilienz
|
## 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.
|
- 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`.
|
- Duplikate: Idempotenz-Keys verhindern Doppelverarbeitung. ACK enthält höchste verarbeitete `sequenceNumber`.
|
||||||
|
|
||||||
## Observability
|
## 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`.
|
- Logs: pro Event `tenant`, `originNodeId`, `seq`, `aggType`, `eventType`, `result`.
|
||||||
- UI: Status-Anzeige (Verbunden, Getrennt, Ausstehend X), Konflikt-Review-Queue.
|
- UI: Status-Anzeige (Verbunden, Getrennt, Ausstehend X), Konflikt-Review-Queue.
|
||||||
|
|
||||||
@@ -5,72 +5,96 @@
|
|||||||
> **Kontext:** Phase 9 — Zeitplan & Protokollierung
|
> **Kontext:** Phase 9 — Zeitplan & Protokollierung
|
||||||
|
|
||||||
## 1. Vision & Zielsetzung
|
## 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)
|
## 2. Fachliche Anforderungen (Use Cases)
|
||||||
|
|
||||||
### UC-1: Verschieben eines Bewerbs/einer Abteilung
|
### UC-1: Verschieben eines Bewerbs/einer Abteilung
|
||||||
|
|
||||||
- Ein Benutzer zieht einen Bewerb oder eine Abteilung auf eine neue Startzeit oder einen anderen Austragungsplatz.
|
- Ein Benutzer zieht einen Bewerb oder eine Abteilung auf eine neue Startzeit oder einen anderen Austragungsplatz.
|
||||||
- **System-Reaktion:**
|
- **System-Reaktion:**
|
||||||
- Neuberechnung der Endzeit basierend auf `reitdauerMinuten * starterAnzahl + besichtigungMinuten + umbauMinuten`.
|
- Neuberechnung der Endzeit basierend auf `reitdauerMinuten * starterAnzahl + besichtigungMinuten + umbauMinuten`.
|
||||||
- Prüfung auf Überschneidungen am selben Austragungsplatz.
|
- Prüfung auf Überschneidungen am selben Austragungsplatz.
|
||||||
- Warnung bei Konflikten (z.B. Richter-Doppelbelegung).
|
- Warnung bei Konflikten (z.B. Richter-Doppelbelegung).
|
||||||
|
|
||||||
### UC-2: Dynamische Zeitplan-Anpassung („Anschließend“)
|
### UC-2: Dynamische Zeitplan-Anpassung („Anschließend“)
|
||||||
|
|
||||||
- Bewerbe können als `ANSCHLIESSEND` markiert werden (`beginnZeitTyp`).
|
- 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
|
### UC-3: Drag & Drop in der Startliste
|
||||||
|
|
||||||
- Innerhalb einer Startliste können Teilnehmer per Drag & Drop umsortiert werden.
|
- 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)
|
### UC-4: Protokollierung (Audit Log)
|
||||||
|
|
||||||
- Jede manuelle Änderung am Zeitplan oder der Startlisten-Reihenfolge muss protokolliert werden.
|
- 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. Datenmodell-Erweiterungen & Logik
|
||||||
|
|
||||||
### 3.1 Erweiterung `Bewerb` & `Abteilung`
|
### 3.1 Erweiterung `Bewerb` & `Abteilung`
|
||||||
|
|
||||||
Das bestehende Modell in `entries-domain` deckt bereits viele Felder ab. Für die Optimierung präzisieren wir:
|
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.
|
- **`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.
|
- **`BesichtigungsBlock` (NEU):** Eigenständiges Objekt für Parcoursbesichtigungen.
|
||||||
- Kann mit mehreren Bewerben/Abteilungen verknüpft werden (Cross-Competition Inspection).
|
- 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).
|
- 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).
|
- Validierung: Mindestens 5 Min. Puffer vor dem ersten Start (ÖTO §43).
|
||||||
|
|
||||||
### 3.2 Zeitberechnungs-Algorithmus (Präzisierung)
|
### 3.2 Zeitberechnungs-Algorithmus (Präzisierung)
|
||||||
|
|
||||||
Die Logik in `StartlistenService.berechneStartzeiten` wird erweitert:
|
Die Logik in `StartlistenService.berechneStartzeiten` wird erweitert:
|
||||||
|
|
||||||
1. **Basis:** `Startzeit` der Abteilung.
|
1. **Basis:** `Startzeit` der Abteilung.
|
||||||
2. **Vorlauf:** `besichtigungMinuten`.
|
2. **Vorlauf:** `besichtigungMinuten`.
|
||||||
3. **Starter-Loop:**
|
3. **Starter-Loop:**
|
||||||
- `individuelleStartzeit = aktuelleZeit`.
|
- `individuelleStartzeit = aktuelleZeit`.
|
||||||
- `aktuelleZeit += bewerb.reitdauerMinuten`.
|
- `aktuelleZeit += bewerb.reitdauerMinuten`.
|
||||||
- *Neu:* Berücksichtigung von festen Pausen nach X Startern (z.B. 10 Min. Pause alle 20 Starter).
|
- *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.
|
4. **Nachlauf:** `umbauMinuten` am Ende der Abteilung/des Bewerbs.
|
||||||
|
|
||||||
### 3.3 Drag & Drop Logik (Frontend & Backend)
|
### 3.3 Drag & Drop Logik (Frontend & Backend)
|
||||||
- **Frontend (Compose Desktop):**
|
|
||||||
- Implementierung eines `DraggableBewerbItem`.
|
- **Frontend (Compose Desktop):**
|
||||||
- Visuelle Darstellung von Konflikten (Rote Markierung bei Überlappung).
|
- Implementierung eines `DraggableBewerbItem`.
|
||||||
|
- Visuelle Darstellung von Konflikten (Rote Markierung bei Überlappung).
|
||||||
- **Backend (API):**
|
- **Backend (API):**
|
||||||
- Neuer Endpunkt `PATCH /bewerbe/{id}/zeitplan` für schnelle Updates.
|
- Neuer Endpunkt `PATCH /bewerbe/{id}/zeitplan` für schnelle Updates.
|
||||||
- Validierung der neuen Zeiten gegen den `austragungsplatzId` und `richterEinsaetze`.
|
- Validierung der neuen Zeiten gegen den `austragungsplatzId` und `richterEinsaetze`.
|
||||||
|
|
||||||
## 4. Konflikt-Management
|
## 4. Konflikt-Management
|
||||||
|
|
||||||
Das System arbeitet nach dem Prinzip **„Warnen statt Blockieren“** (ADR-0016):
|
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).
|
- **Harte Fehler:** Nur bei technischer Unmöglichkeit (z.B. Datum in der Vergangenheit bei Live-Betrieb).
|
||||||
- **Warnungen:**
|
- **Warnungen:**
|
||||||
- Überlappung auf dem Platz.
|
- Überlappung auf dem Platz.
|
||||||
- Richter hat gleichzeitig Einsatz in anderem Bewerb.
|
- Richter hat gleichzeitig Einsatz in anderem Bewerb.
|
||||||
- Zeitunterschreitung für Reiter (Reiter startet in zwei kurz aufeinanderfolgenden Bewerben).
|
- Zeitunterschreitung für Reiter (Reiter startet in zwei kurz aufeinanderfolgenden Bewerben).
|
||||||
|
|
||||||
## 5. Synchronisation (Offline-First)
|
## 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.
|
Änderungen am Zeitplan erzeugen `SyncEvents` (gemäß ADR-0022).
|
||||||
- **Echtzeit-Update:** Über WebSockets werden Zeitplan-Änderungen sofort an alle verbundenen Clients (z.B. Anzeige-Monitor, Richter-Tablet) gepusht.
|
|
||||||
|
- **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
|
## 6. Nächste Schritte
|
||||||
|
|
||||||
1. **Backend:** ✅ Implementiert (BewerbService, API, Zeitberechnungs-Pausen).
|
1. **Backend:** ✅ Implementiert (BewerbService, API, Zeitberechnungs-Pausen).
|
||||||
2. **Frontend:** Prototyping der Kalender-Ansicht mit Compose Desktop.
|
2. **Frontend:** Prototyping der Kalender-Ansicht mit Compose Desktop.
|
||||||
3. **QA:** Test-Szenarien für komplexe Verschiebungen (Kettenreaktionen bei „Anschließend“).
|
3. **QA:** Test-Szenarien für komplexe Verschiebungen (Kettenreaktionen bei „Anschließend“).
|
||||||
@@ -5,42 +5,63 @@
|
|||||||
> **Kontext:** Zeitplan-Optimierung & Praxis-Szenarien
|
> **Kontext:** Zeitplan-Optimierung & Praxis-Szenarien
|
||||||
|
|
||||||
## 1. Parcoursbesichtigung zu Pferd
|
## 1. Parcoursbesichtigung zu Pferd
|
||||||
|
|
||||||
Die Aussage des Users wurde geprüft und bestätigt.
|
Die Aussage des Users wurde geprüft und bestätigt.
|
||||||
|
|
||||||
### 1.1 Regelwerks-Referenz (ÖTO 2026)
|
### 1.1 Regelwerks-Referenz (ÖTO 2026)
|
||||||
|
|
||||||
Gemäß **ÖTO Teil B, § 43 (Abweichungen)** gilt:
|
Gemäß **ÖTO Teil B, § 43 (Abweichungen)** gilt:
|
||||||
|
|
||||||
- **Normalfall:** Parcoursbesichtigung erfolgt zu Fuß.
|
- **Normalfall:** Parcoursbesichtigung erfolgt zu Fuß.
|
||||||
- **Springpferde- & Jungpferdeprüfungen (bis 110 cm):** Eine Besichtigung **zu Pferd im Schritt** kann von der Richtergruppe erlaubt werden.
|
- **Springpferde- & Jungpferdeprüfungen (bis 110 cm):** Eine Besichtigung **zu Pferd im Schritt** kann von der
|
||||||
- **Zweck:** Junge, unerfahrene Pferde sollen stressfrei an optische Reize (Fangständer, Farben, Unterbauten) herangeführt werden.
|
Richtergruppe erlaubt werden.
|
||||||
|
- **Zweck:** Junge, unerfahrene Pferde sollen stressfrei an optische Reize (Fangständer, Farben, Unterbauten)
|
||||||
|
herangeführt werden.
|
||||||
|
|
||||||
### 1.2 Organisatorische Implikationen
|
### 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)
|
## 2. Zusammengelegte Besichtigungen (Cross-Competition Inspection)
|
||||||
|
|
||||||
In der Praxis üblich, wenn der Parcours für aufeinanderfolgende Bewerbe identisch bleibt.
|
In der Praxis üblich, wenn der Parcours für aufeinanderfolgende Bewerbe identisch bleibt.
|
||||||
|
|
||||||
### 2.1 Szenario
|
### 2.1 Szenario
|
||||||
|
|
||||||
- **Bewerb A:** Springpferdeprüfung 105cm (Besichtigung zu Pferd erlaubt).
|
- **Bewerb A:** Springpferdeprüfung 105cm (Besichtigung zu Pferd erlaubt).
|
||||||
- **Bewerb B:** Standardspringprüfung 105cm (Besichtigung zu Fuß).
|
- **Bewerb B:** Standardspringprüfung 105cm (Besichtigung zu Fuß).
|
||||||
- **Lösung:** Eine gemeinsame Besichtigungszeit vor Bewerb A.
|
- **Lösung:** Eine gemeinsame Besichtigungszeit vor Bewerb A.
|
||||||
|
|
||||||
### 2.2 Regelwerks-Konformität
|
### 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. Anforderungen für die Software (Zeitplan-Modul)
|
||||||
|
|
||||||
### 3.1 Datenmodell
|
### 3.1 Datenmodell
|
||||||
|
|
||||||
- `Abteilung` oder `Bewerb` benötigt ein Flag `besichtigungZuPferdErlaubt` (Boolean).
|
- `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
|
### 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
|
## 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*
|
*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
|
||||||
@@ -150,26 +150,26 @@ Code-Stand.*
|
|||||||
|
|
||||||
## 5. Wichtige Referenzen
|
## 5. Wichtige Referenzen
|
||||||
|
|
||||||
| Dokument | Pfad |
|
| Dokument | Pfad |
|
||||||
|---------------------------|----------------------------------------------------------------------------------------------|
|
|-------------------------------|----------------------------------------------------------------------------------------------|
|
||||||
| Ubiquitous Language | `docs/03_Domain/01_Glossary/Ubiquitous_Language.md` |
|
| Ubiquitous Language | `docs/03_Domain/01_Glossary/Ubiquitous_Language.md` |
|
||||||
| Abteilungs-Schwellenwerte | `docs/03_Domain/02_Reference/OETO_Regelwerk/Abteilungs-Trennungs-Schwellenwerte.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` |
|
| 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` |
|
| Session Log (DDD) | `docs/99_Journal/2026-03-24_Session_Log_DDD_Ubiquitous_Language.md` |
|
||||||
| Infrastruktur | `docs/07_Infrastructure/Zora_System_Architektur.md` |
|
| Infrastruktur | `docs/07_Infrastructure/Zora_System_Architektur.md` |
|
||||||
| Deployment Guide | `docs/07_Infrastructure/Guides/Setup_Git_Deployment_Zora.md` |
|
| Deployment Guide | `docs/07_Infrastructure/Guides/Setup_Git_Deployment_Zora.md` |
|
||||||
| Backup Guide | `docs/07_Infrastructure/Guides/Setup_Backup_Zora.md` |
|
| Backup Guide | `docs/07_Infrastructure/Guides/Setup_Backup_Zora.md` |
|
||||||
| CI/CD | `.gitea/workflows/docker-publish.yaml` |
|
| CI/CD | `.gitea/workflows/docker-publish.yaml` |
|
||||||
| Agent Playbooks | `docs/04_Agents/Playbooks/` |
|
| Agent Playbooks | `docs/04_Agents/Playbooks/` |
|
||||||
| ADR-Verzeichnis | `docs/01_Architecture/adr/` |
|
| ADR-Verzeichnis | `docs/01_Architecture/adr/` |
|
||||||
| ADR-0025: Plan-USB | `docs/01_Architecture/adr/0025-plan-usb-offline-integritaet.md` |
|
| 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-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` |
|
| ADR-0027: Discovery | `docs/01_Architecture/adr/0027-netzwerk-discovery-interface-binding.md` |
|
||||||
| Docker-Fix: dc-gui.yaml | `dc-gui.yaml` |
|
| Docker-Fix: dc-gui.yaml | `dc-gui.yaml` |
|
||||||
| ZNS-Importer Roadmap | `docs/01_Architecture/Roadmap_ZNS_Importer.md` |
|
| ZNS-Importer Roadmap | `docs/01_Architecture/Roadmaps/Roadmap_ZNS_Importer.md` |
|
||||||
| Masterdata Roadmap | `backend/services/masterdata/docs/ROADMAP.md` |
|
| Masterdata Roadmap | `backend/services/masterdata/docs/ROADMAP.md` |
|
||||||
| Masterdata Changelog | `backend/services/masterdata/docs/CHANGELOG.md` |
|
| Masterdata Changelog | `backend/services/masterdata/docs/CHANGELOG.md` |
|
||||||
| Masterdata Operations | `backend/services/masterdata/docs/runbooks/masterdata-ops.md` |
|
| Masterdata Operations | `backend/services/masterdata/docs/runbooks/masterdata-ops.md` |
|
||||||
| Zeitplan-Optimierung | `docs/01_Architecture/konzept-zeitplan-optimierung-de.md` |
|
| Zeitplan-Optimierung | `docs/01_Architecture/Concepts/konzept-zeitplan-optimierung-de.md` |
|
||||||
| Parcoursbesichtigung-Rulebook | `docs/01_Architecture/rulebook-check-parcoursbesichtigung-de.md` |
|
| Parcoursbesichtigung-Rulebook | `docs/01_Architecture/Concepts/rulebook-check-parcoursbesichtigung-de.md` |
|
||||||
| Status-Automat-Nennungen | `docs/01_Architecture/status-automat-nennungen-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
|
## 🏗️ [Lead Architect] | 14. April 2026
|
||||||
|
|
||||||
Dieses Dokument beschreibt die Umsetzung der Online-Nennung für das Turnier in Neumarkt (24. 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) ✅
|
### Phase 1: E-Mail-Infrastruktur (Vorbereitung) ✅
|
||||||
|
|
||||||
* [x] Definition des Adress-Schemas: `meldestelle-[Turnier-Nr]@mo-code.at`.
|
* [x] Definition des Adress-Schemas: `meldestelle-[Turnier-Nr]@mo-code.at`.
|
||||||
* [x] Konfiguration der World4You SMTP/IMAP Zugangsdaten.
|
* [x] Konfiguration der World4You SMTP/IMAP Zugangsdaten.
|
||||||
* [x] Mailpit Integration für lokale Tests (bereits in `dc-ops.yaml`).
|
* [x] Mailpit Integration für lokale Tests (bereits in `dc-ops.yaml`).
|
||||||
|
|
||||||
### Phase 2: Das Web-Formular (WasmJS Frontend) ✅
|
### Phase 2: Das Web-Formular (WasmJS Frontend) ✅
|
||||||
|
|
||||||
* [x] **Basis-UI:** Erstellung des Formulars gemäß Spezifikation (Reiter, Pferd, Lizenz, Bewerbe).
|
* [x] **Basis-UI:** Erstellung des Formulars gemäß Spezifikation (Reiter, Pferd, Lizenz, Bewerbe).
|
||||||
* [x] **Validierung:** Implementierung der Pflichtfeld-Prüfung (Buttonsperre bis alles ok).
|
* [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] **Mail-Versand:** Integration des API-Calls an das Backend (`mail-service`), um die Nennung zu speichern.
|
||||||
* [x] **DSGVO:** Checkbox und Hinweistext eingebaut.
|
* [x] **DSGVO:** Checkbox und Hinweistext eingebaut.
|
||||||
|
|
||||||
### Phase 3: Mail-Service (Backend-Verarbeitung) 🏗️
|
### Phase 3: Mail-Service (Backend-Verarbeitung) 🏗️
|
||||||
|
|
||||||
* [x] **Endpoint:** POST-Endpunkt für direkte Nennungen aus dem Web-Formular implementiert.
|
* [x] **Endpoint:** POST-Endpunkt für direkte Nennungen aus dem Web-Formular implementiert.
|
||||||
* [ ] **Polling:** Implementierung des IMAP-Pollers (imap.world4you.com).
|
* [ ] **Polling:** Implementierung des IMAP-Pollers (imap.world4you.com).
|
||||||
* [ ] **Parsing:** Extraktion der Turnier-Nummer aus dem `To`-Header und Mapping auf das Datenbank-Schema (Tenant).
|
* [ ] **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.
|
* [x] **Persistence:** Speichern der eingegangenen "Nennungs-Mails" in einer temporären Tabelle.
|
||||||
|
|
||||||
### Phase 4: Desktop-Zentrale Integration ✅
|
### Phase 4: Desktop-Zentrale Integration ✅
|
||||||
|
|
||||||
* [x] **UI-Tab:** Neuer Reiter "Online-Eingang" in der Turnierverwaltung (`TurnierDetailScreen`).
|
* [x] **UI-Tab:** Neuer Reiter "Online-Eingang" in der Turnierverwaltung (`TurnierDetailScreen`).
|
||||||
* [x] **Vorschau:** Anzeige der eingegangenen Nennungen mit Details (`OnlineNennungEingangTabContent`).
|
* [x] **Vorschau:** Anzeige der eingegangenen Nennungen mit Details (`OnlineNennungEingangTabContent`).
|
||||||
* [x] **Übernahme:** "Übernehmen"-Button, der Reiter/Pferd in die Nennung vorausfüllt (`NennungViewModel`).
|
* [x] **Übernahme:** "Übernehmen"-Button, der Reiter/Pferd in die Nennung vorausfüllt (`NennungViewModel`).
|
||||||
* [ ] **Abschluss:** Manueller "Bestätigen"-Button zum Versenden der finalen Bestätigungsmail.
|
* [ ] **Abschluss:** Manueller "Bestätigen"-Button zum Versenden der finalen Bestätigungsmail.
|
||||||
|
|
||||||
### Phase 5: End-to-End Test & Deployment 🚀 (Deadline: 21.04.2026)
|
### Phase 5: End-to-End Test & Deployment 🚀 (Deadline: 21.04.2026)
|
||||||
|
|
||||||
* [ ] Test-Nennung über Web-Formular (Mailpit).
|
* [ ] Test-Nennung über Web-Formular (Mailpit).
|
||||||
* [ ] Verifikation der Schema-Zuordnung im Backend.
|
* [ ] Verifikation der Schema-Zuordnung im Backend.
|
||||||
* [ ] Live-Test mit `online-nennen@mo-code.at`.
|
* [ ] 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
|
### Meilensteine
|
||||||
|
|
||||||
1. **16.04.:** Web-Formular ist funktionsfähig (Senden möglich).
|
1. **16.04.:** Web-Formular ist funktionsfähig (Senden möglich).
|
||||||
2. **18.04.:** Mail-Service verarbeitet Mails und sendet Auto-Antworten.
|
2. **18.04.:** Mail-Service verarbeitet Mails und sendet Auto-Antworten.
|
||||||
3. **20.04.:** Desktop-UI zur Übernahme ist fertig.
|
3. **20.04.:** Desktop-UI zur Übernahme ist fertig.
|
||||||
@@ -10,7 +10,9 @@ last_update: 2026-03-25
|
|||||||
10. **🏗️ [Lead Architect]** | 5. April 2026
|
10. **🏗️ [Lead Architect]** | 5. April 2026
|
||||||
|
|
||||||
**Kontext:**
|
**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
|
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
|
Stammdaten (Reiter, Pferde, Vereine, Funktionäre). Diese Daten werden vom ÖPS (Österreichischer Pferdesportverband) in
|
||||||
Form einer `ZNS.zip` bereitgestellt.
|
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`).
|
* ZIP-Entpackung in-memory implementiert (`ZnsImportService`).
|
||||||
* [x] **Legacy-Parser (CP850 Fixed-Width):**
|
* [x] **Legacy-Parser (CP850 Fixed-Width):**
|
||||||
* `ZnsLegacyParsers` in `core:zns-parser` (KMP-Modul) implementiert.
|
* `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)
|
### 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
|
status: ACTIVE
|
||||||
owner: Lead Architect
|
owner: Lead Architect
|
||||||
---
|
---
|
||||||
|
|
||||||
# Architektur: Das Platform-Modul
|
# Architektur: Das Platform-Modul
|
||||||
|
|
||||||
## Überblick
|
## Ü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.
|
Das Modul agiert als eine interne "Single Source of Truth" für alle externen Bibliotheken.
|
||||||
|
|
||||||
@@ -24,19 +28,23 @@ platform/
|
|||||||
|
|
||||||
### `platform-bom`
|
### `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).
|
* **Zweck:** Definiert eine umfassende Liste von Abhängigkeiten und deren exakten, geprüften Versionen. Es importiert
|
||||||
* **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.
|
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.
|
* **Vorteil:** Absolute Versionskontrolle über das gesamte Projekt.
|
||||||
|
|
||||||
### `platform-dependencies`
|
### `platform-dependencies`
|
||||||
|
|
||||||
Ein einfaches "Sammelmodul", das die am häufigsten benötigten Laufzeit-Abhängigkeiten bündelt.
|
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:**
|
* **Verwendung:**
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
// In einem Service-Modul
|
// In einem Service-Modul
|
||||||
dependencies {
|
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.
|
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:**
|
* **Verwendung:**
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
// In einem Service-Modul
|
// In einem Service-Modul
|
||||||
dependencies {
|
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) Fokus-Themen und Deliverables (heute Nacht)
|
||||||
|
|
||||||
1. Reporting & Output (Vorbereitung)
|
1. Reporting & Output (Vorbereitung)
|
||||||
- [Owner] Vorlagen sammeln/übermitteln: Startlisten, Ergebnislisten (PDF/Scan/Excel)
|
|
||||||
- [Owner] Spring-Protokolle: Inhalte/Felder definieren (Fehler, Zeit, Stechen)
|
- [Owner] Vorlagen sammeln/übermitteln: Startlisten, Ergebnislisten (PDF/Scan/Excel)
|
||||||
- [Owner] Dressur-Protokolle: Vorlage für personalisierten Ausdruck (Kopfzeile Reiter/Pferd)
|
- [Owner] Spring-Protokolle: Inhalte/Felder definieren (Fehler, Zeit, Stechen)
|
||||||
- [Arch/BE] Technik-Entscheidung PDF: KMP-Library vs. Server-Side Rendering (ADR-Entwurf)
|
- [Owner] Dressur-Protokolle: Vorlage für personalisierten Ausdruck (Kopfzeile Reiter/Pferd)
|
||||||
- [FE] UI-Draft „Druckvorschau“ in V2-Screens: Platzhalter mit Beispiel-Daten
|
- [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)
|
2. Events/Turniere (Backend-Readiness für Neumarkt)
|
||||||
- [BE] DB-Migrationen finalisieren: `turniere`, `ausschreibungen` (Flyway)
|
|
||||||
- [BE] Seed-Datensatz „Veranstaltung Neumarkt 2026“ (+ 1–2 Turniere)
|
- [BE] DB-Migrationen finalisieren: `turniere`, `ausschreibungen` (Flyway)
|
||||||
- [BE] Repositories prüfen und Test-Cases anlegen (Roundtrip CRUD)
|
- [BE] Seed-Datensatz „Veranstaltung Neumarkt 2026“ (+ 1–2 Turniere)
|
||||||
|
- [BE] Repositories prüfen und Test-Cases anlegen (Roundtrip CRUD)
|
||||||
|
|
||||||
3. Identity & Profil (Verifikation)
|
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)
|
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,20 +1,33 @@
|
|||||||
# ADR-0027: Netzwerk-Discovery & Interface-Binding
|
# ADR-0027: Netzwerk-Discovery & Interface-Binding
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
In Prüfung (Wartet auf PoC)
|
|
||||||
|
Akzeptiert & Implementiert (05.05.2026)
|
||||||
|
|
||||||
## Kontext
|
## Kontext
|
||||||
Desktop-Rechner auf Turnieren sind oft mit mehreren Netzwerken gleichzeitig verbunden (z.B. LAN für das Turnier-Netzwerk, WLAN für Internet-Hotspot). Automatische Discovery-Dienste (JmDNS) wählen ohne explizite Konfiguration oft das falsche Interface, wodurch sich Clients und Master nicht finden.
|
|
||||||
|
Desktop-Rechner auf Turnieren sind oft mit mehreren Netzwerken gleichzeitig verbunden (z.B. LAN für das
|
||||||
|
Turnier-Netzwerk, WLAN für Internet-Hotspot). Automatische Discovery-Dienste (mDNS) wählen ohne explizite Konfiguration
|
||||||
|
oft ein Interface, das für die anderen Teilnehmer nicht erreichbar ist (Bridging-Probleme zwischen LAN und WLAN). Zudem
|
||||||
|
blockieren einige Router Multicast-Pakete zwischen WLAN und LAN-Segmenten.
|
||||||
|
|
||||||
## Entscheidung
|
## Entscheidung
|
||||||
Wir führen ein explizites Netzwerk-Management für die Initialisierung ein.
|
|
||||||
|
|
||||||
1. **Interface-Selektion:** Der Benutzer muss bei der technischen Initialisierung explizit wählen, über welches Netzwerk-Interface (IP-Adresse/Adapter) die App kommunizieren soll. Die UI zeigt hierfür benutzerfreundliche Namen (WLAN, Ethernet) an.
|
Wir führen ein robustes, mehrstufiges Netzwerk-Management für die Initialisierung ein:
|
||||||
2. **Geführte Discovery:** Sobald ein Interface gewählt ist, startet ein "Radar-Modus". Dieser scannt aktiv via JmDNS nach vorhandenen Master-Geräten.
|
|
||||||
3. **Adaptive Rolle:** Findet die Discovery einen Master, wird dem Benutzer die Rolle "Client" vorgeschlagen. Die UI bleibt jedoch flexibel für manuelle Rollenwechsel.
|
1. **Multi-Interface Broadcast:** Der Master registriert seinen Dienst proaktiv auf **allen** verfügbaren
|
||||||
4. **Fokus-Management:** Nach Auswahl der Rolle wird der Fokus automatisch in das erste relevante Eingabefeld (Gerätename) gesetzt, um einen reibungslosen Workflow zu ermöglichen.
|
Netzwerk-Interfaces (IPv4). Dies erhöht die Chance massiv, dass Clients in verschiedenen Segmenten (WLAN/LAN) den
|
||||||
|
Master finden.
|
||||||
|
2. **Interface-Selektion:** Der Benutzer kann weiterhin ein bevorzugtes Interface wählen. Die Master-Info-Card zeigt die
|
||||||
|
Erreichbarkeit transparent an.
|
||||||
|
3. **Manueller IP-Fallback:** Wenn mDNS fehlschlägt, kann die IP des Masters manuell eingegeben werden. Dies ist der "
|
||||||
|
Ultima-Ratio"-Weg für restriktive Netzwerke.
|
||||||
|
4. **Konnektivitäts-Check (Chat & Self-Test):** Nach dem Handshake wird ein Modal geöffnet, das einen automatischen
|
||||||
|
Ping-Pong Test durchführt und einen Test-Chat bietet. Dies verifiziert die reale Datenübertragung (Serialisierung,
|
||||||
|
WebSockets) noch vor Abschluss des Setups.
|
||||||
|
|
||||||
## Konsequenzen
|
## Konsequenzen
|
||||||
- Verhindert "Geistersuchen" im falschen Netzwerk.
|
|
||||||
- Erhöht die Benutzerfreundlichkeit durch automatische Vorschläge.
|
- Deutlich höhere Stabilität in heterogenen Netzwerkumgebungen.
|
||||||
- Erfordert Zugriff auf System-Netzwerk-APIs in der Desktop-Shell.
|
- Transparenteres Feedback für den Anwender bei Verbindungsproblemen.
|
||||||
|
- Der Chat dient als "Connectivity-Proof" für das Support-Personal vor Ort.
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
# CSN-C NEU / CSNP-C NEU NEUMARKT/M.
|
# CSN-C NEU / CSNP-C NEU NEUMARKT/M.
|
||||||
|
|
||||||
**Turnier-Nr.: 26128** | **Datum: 25. April 2026**
|
**Turnier-Nr.: 26128** | **Datum: 25. April 2026**
|
||||||
|
|
||||||
## Allgemeine Informationen
|
## Allgemeine Informationen
|
||||||
|
|
||||||
* **Veranstalter:** Union Reit- u. Fahrverein Neumarkt/M. (6-009)
|
* **Veranstalter:** Union Reit- u. Fahrverein Neumarkt/M. (6-009)
|
||||||
* **Ort:** Reitanlage Stroblmair, 4212 Neumarkt
|
* **Ort:** Reitanlage Stroblmair, 4212 Neumarkt
|
||||||
* **Kontakt:** Ursula Stroblmair, Brandstetterweg 2, 4212 Neumarkt
|
* **Kontakt:** Ursula Stroblmair, Brandstetterweg 2, 4212 Neumarkt
|
||||||
* **Tel.:** 0664 1832381
|
* **Tel.:** 0664 1832381
|
||||||
* **E-Mail:** reit-stall@gmx.at
|
* **E-Mail:** reit-stall@gmx.at
|
||||||
* **Nennungsschluss:** 24.04.2026, 19:00 Uhr
|
* **Nennungsschluss:** 24.04.2026, 19:00 Uhr
|
||||||
* **Online-Nennung:** Ab Mittwoch, 22.04.
|
* **Online-Nennung:** Ab Mittwoch, 22.04.
|
||||||
auf [www.ihremeldestelle.at](http://www.ihremeldestelle.at)
|
auf [www.ihremeldestelle.at](http://www.ihremeldestelle.at)
|
||||||
@@ -17,17 +17,17 @@
|
|||||||
## Technische Details
|
## Technische Details
|
||||||
|
|
||||||
* **Austragungsplatz:** 45 x 65 m (Sand/Vlies)
|
* **Austragungsplatz:** 45 x 65 m (Sand/Vlies)
|
||||||
* **Vorbereitungsplatz:** 20 x 40 m Halle (Sand/Vlies)
|
* **Vorbereitungsplatz:** 20 x 40 m Halle (Sand/Vlies)
|
||||||
* **Warmreiten:** Draußen (20 x 60 m Sand/Vlies) möglich
|
* **Warmreiten:** Draußen (20 x 60 m Sand/Vlies) möglich
|
||||||
* **Boxen:** Keine Einstallung möglich
|
* **Boxen:** Keine Einstallung möglich
|
||||||
|
|
||||||
## Funktionäre
|
## Funktionäre
|
||||||
|
|
||||||
* **Turnierleiter:** Ursula Stroblmair
|
* **Turnierleiter:** Ursula Stroblmair
|
||||||
* **Turnierbeauftragter:** Rudi Kreupl
|
* **Turnierbeauftragter:** Rudi Kreupl
|
||||||
* **Richter:** Rudi Kreupl, Helmut Riedler
|
* **Richter:** Rudi Kreupl, Helmut Riedler
|
||||||
* **Parcoursbauchef:** Kurt Reitetschlägerr
|
* **Parcoursbauchef:** Kurt Reitetschlägerr
|
||||||
* **Tierarzt:** Dr. Sabine Ötschmaier
|
* **Tierarzt:** Dr. Sabine Ötschmaier
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -36,8 +36,8 @@
|
|||||||
* **Kosten:** Startgeld € 15,- pro Bewerb. Kein Nenngeld, kein Sporteuro.
|
* **Kosten:** Startgeld € 15,- pro Bewerb. Kein Nenngeld, kein Sporteuro.
|
||||||
* **Teilnahmebedingungen:**
|
* **Teilnahmebedingungen:**
|
||||||
* Für Springprüfungen bis 95 cm: Mitgliedschaft OEPS-Verein und Reiterpass erforderlich.
|
* Für Springprüfungen bis 95 cm: Mitgliedschaft OEPS-Verein und Reiterpass erforderlich.
|
||||||
* Pferde bis 90 cm müssen **nicht** beim OEPS registriert sein.
|
* Pferde bis 90 cm müssen **nicht** beim OEPS registriert sein.
|
||||||
* Pferdepass mit gültigem Impfschutz (§ 11 OTO) ist vorzulegen.
|
* Pferdepass mit gültigem Impfschutz (§ 11 OTO) ist vorzulegen.
|
||||||
* Haftpflichtversicherung für jedes Pferd ist Pflicht.
|
* Haftpflichtversicherung für jedes Pferd ist Pflicht.
|
||||||
* **Startregelung:**
|
* **Startregelung:**
|
||||||
* Ein Pferd darf maximal 3x pro Tag starten.
|
* Ein Pferd darf maximal 3x pro Tag starten.
|
||||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 325 KiB After Width: | Height: | Size: 325 KiB |
|
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 109 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
@@ -11,6 +11,7 @@ Dieser Ordner ist archiviert. Historische Betriebs-/Infra-Screenshots wurden nac
|
|||||||
`docs/80_Assets/exports/ops/archive/` verschoben.
|
`docs/80_Assets/exports/ops/archive/` verschoben.
|
||||||
|
|
||||||
Neue Screens bitte gemäß Docs-as-Code in folgenden Bereichen ablegen:
|
Neue Screens bitte gemäß Docs-as-Code in folgenden Bereichen ablegen:
|
||||||
|
|
||||||
- UI-/Produkt-Screens: `docs/80_Assets/frontend/screens/<Modul>/...`
|
- UI-/Produkt-Screens: `docs/80_Assets/frontend/screens/<Modul>/...`
|
||||||
- Figma-Exports: `docs/80_Assets/frontend/figma/<vision>/<bereich>/...`
|
- Figma-Exports: `docs/80_Assets/frontend/figma/<vision>/<bereich>/...`
|
||||||
- Ops-/Infra-Exports: `docs/80_Assets/exports/ops/<topic>/...`
|
- Ops-/Infra-Exports: `docs/80_Assets/exports/ops/<topic>/...`
|
||||||
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 175 KiB After Width: | Height: | Size: 175 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 173 KiB After Width: | Height: | Size: 173 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
@@ -1,60 +0,0 @@
|
|||||||
---
|
|
||||||
type: Report
|
|
||||||
status: ACTIVE
|
|
||||||
owner: Backend Developer
|
|
||||||
last_update: 2026-02-01
|
|
||||||
---
|
|
||||||
|
|
||||||
# Abschlussbericht: Backend Hardening & Infrastructure (Ping-Service)
|
|
||||||
|
|
||||||
## 1. Management Summary
|
|
||||||
Der **Ping-Service** wurde erfolgreich als technischer Blueprint ("Tracer Bullet") gehärtet. Er erfüllt nun alle Anforderungen der **Phase 1 (Backend Hardening)** der Q1 Roadmap.
|
|
||||||
Die Infrastruktur wurde modernisiert (Valkey 9.0), und die Testabdeckung wurde durch echte Integrationstests (Testcontainers) auf ein Enterprise-Niveau gehoben.
|
|
||||||
|
|
||||||
Der Service ist **Production Ready** und dient ab sofort als Vorlage für alle fachlichen Microservices.
|
|
||||||
|
|
||||||
## 2. Durchgeführte Maßnahmen
|
|
||||||
|
|
||||||
### 🛡️ Security & Resilience
|
|
||||||
* **OAuth2 Resource Server:** Implementiert und konfiguriert (`GlobalSecurityConfig`). Tokens vom Keycloak werden validiert.
|
|
||||||
* **RBAC:** Endpunkte wie `/ping/secure` sind durch Rollen geschützt (`@PreAuthorize`).
|
|
||||||
* **CircuitBreaker:** Resilience4j sichert DB-Zugriffe ab (`@CircuitBreaker`). Fallback-Methoden ("Degraded Mode") sind aktiv.
|
|
||||||
|
|
||||||
### 🏗️ Infrastructure Upgrade
|
|
||||||
* **Valkey Migration:** Erfolgreiche Migration von Redis (proprietär) auf **Valkey 9.0** (Open Source) in `docker-compose` und Environment-Configs.
|
|
||||||
* Images: `valkey/valkey:9.0`
|
|
||||||
* Kompatibilität: Vollständig gegeben (Drop-In Replacement).
|
|
||||||
|
|
||||||
### 🧪 Quality Assurance (Testing)
|
|
||||||
* **Integrationstests:** Implementierung von `PingRepositoryTest` mit **Testcontainers** (Postgres).
|
|
||||||
* Prüft Flyway-Migrationen (`V1`, `V2`).
|
|
||||||
* Prüft JPA-Mapping und UUIDv7-Persistenz gegen eine echte Datenbank.
|
|
||||||
* **Test-Isolierung:** Lösung komplexer Spring-Kontext-Probleme (`BeanDefinitionOverrideException`) durch:
|
|
||||||
* Einführung einer isolierten `TestPersistenceConfig` für Repository-Tests.
|
|
||||||
* Nutzung von `@TestConfiguration` in Controller-Tests.
|
|
||||||
* Entfernung des hinderlichen `@Profile("!test")` im `PingRepositoryAdapter`.
|
|
||||||
|
|
||||||
### 📊 Observability
|
|
||||||
* **Actuator:** Health, Info, Metrics und Prometheus-Endpunkte sind exponiert.
|
|
||||||
* **Tracing:** Zipkin-Integration vorbereitet via `monitoring-client`.
|
|
||||||
|
|
||||||
## 3. Technische Details & Learnings
|
|
||||||
|
|
||||||
### Problem: Spring Context Pollution
|
|
||||||
Während der Implementierung der Integrationstests kam es zu Konflikten zwischen den Bean-Definitionen verschiedener Tests (`BeanDefinitionOverrideException`).
|
|
||||||
**Lösung:**
|
|
||||||
Strikte Trennung der Kontexte. `PingRepositoryTest` lädt nun **nicht** mehr die gesamte `PingServiceApplication`, sondern nur eine minimale `TestPersistenceConfig`, die gezielt nur das Persistence-Layer scannt. Dies beschleunigt die Tests und verhindert Seiteneffekte durch Controller oder Security-Configs.
|
|
||||||
|
|
||||||
### Problem: Profile-Exclusion
|
|
||||||
Der `PingRepositoryAdapter` war mit `@Profile("!test")` annotiert. Dies verhinderte, dass Integrationstests (die im `test`-Profil laufen) den echten Adapter nutzen konnten.
|
|
||||||
**Lösung:**
|
|
||||||
Annotation entfernt. In Unit-Tests wird der Adapter ohnehin durch Mocks ersetzt, daher ist die Exclusion unnötig und schädlich für Integrationstests.
|
|
||||||
|
|
||||||
## 4. Nächste Schritte (Handover an Frontend)
|
|
||||||
Der Backend-Stack ist stabil. Der Frontend-Expert kann nun die Integration (Phase 2) abschließen:
|
|
||||||
1. Login gegen Keycloak.
|
|
||||||
2. Aufruf von `/ping/secure` mit Bearer-Token.
|
|
||||||
3. Test des Delta-Syncs (`/ping/sync`).
|
|
||||||
|
|
||||||
---
|
|
||||||
*Gez. Senior Backend Developer*
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
---
|
|
||||||
type: Report
|
|
||||||
status: ACTIVE
|
|
||||||
owner: Frontend Expert
|
|
||||||
title: Frontend Cleanup & Architecture Status Report
|
|
||||||
date: 2026-02-01
|
|
||||||
author: Frontend Expert & Curator
|
|
||||||
tags: [frontend, architecture, cleanup, kmp, compose]
|
|
||||||
---
|
|
||||||
|
|
||||||
# 🧹 Frontend Cleanup & Architecture Status Report
|
|
||||||
|
|
||||||
## 1. Executive Summary
|
|
||||||
Dieses Dokument fasst die umfangreichen Aufräum- und Refactoring-Arbeiten am Frontend ("Meldestelle Portal") zusammen. Ziel war es, technischen Ballast ("Dead Code") zu entfernen, die Architektur zu vereinheitlichen (MVVM + Clean Architecture) und die Kompilierbarkeit über alle Plattformen (JVM/Desktop & JS/Web) sicherzustellen.
|
|
||||||
|
|
||||||
**Ergebnis:** Der Build ist erfolgreich (`BUILD SUCCESSFUL`). Das Frontend ist nun schlank, wartbar und bereit für die Feature-Entwicklung.
|
|
||||||
|
|
||||||
## 2. Durchgeführte Maßnahmen
|
|
||||||
|
|
||||||
### 2.1. Entfernung von "Dead Code"
|
|
||||||
* **`frontend/shared` gelöscht:** Dieses Modul enthielt einen kompletten, ungenutzten Redux-Stack (`AppStore`, `AppAction`, etc.), der im Widerspruch zur genutzten MVVM-Architektur stand.
|
|
||||||
* **Legacy-Komponenten entfernt:** Veraltete UI-Komponenten (z.B. `NotificationCard.kt`) und doppelte Navigations-Konzepte wurden bereinigt.
|
|
||||||
|
|
||||||
### 2.2. Architektur-Konsolidierung
|
|
||||||
* **MVVM als Standard:** Die Anwendung folgt nun strikt dem MVVM-Muster mit Kotlin Coroutines (`StateFlow`) und Koin für Dependency Injection.
|
|
||||||
* **Clean Architecture:** Das `ping-feature` dient als Referenz-Implementierung mit klarer Trennung von `Presentation`, `Domain` und `Data` Layer.
|
|
||||||
* **Navigation:** Zentralisierung der Navigation auf `AppScreen` (Sealed Class) im Core-Modul.
|
|
||||||
|
|
||||||
### 2.3. Build & Plattform-Support
|
|
||||||
* **Koin-Initialisierung:** Korrektur der Koin-Start-Logik für JVM (`startKoin` statt `initKoin`) und JS (`startKoin` im `main.kt`).
|
|
||||||
* **Gradle-Konfiguration:** Bereinigung der `build.gradle.kts` Dateien und Entfernung von Abhängigkeiten zu gelöschten Modulen.
|
|
||||||
* **Web-Support:** Sicherstellung, dass die Web-Version (Kotlin/JS) fehlerfrei baut und die Datenbank (SQLDelight Wasm) korrekt initialisiert.
|
|
||||||
|
|
||||||
## 3. Modul-Status (Ist-Zustand)
|
|
||||||
|
|
||||||
| Modul | Status | Beschreibung |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| **`core/navigation`** | ✅ Grün | Zentrale Routen (`AppScreen`, `Routes`), DeepLink-Handling. Sauber. |
|
|
||||||
| **`core/design-system`** | ✅ Grün | UI-Komponenten (`AppTheme`, `Buttons`, `Inputs`). Modern (Material 3). |
|
|
||||||
| **`core/auth`** | ✅ Grün | Login-Logik, Token-Manager, API-Client. Funktional. |
|
|
||||||
| **`core/network`** | ✅ Grün | Zentraler `HttpClient` mit Auth-Interceptor. |
|
|
||||||
| **`core/sync`** | ✅ Grün | Generischer `SyncManager` für Offline-First. |
|
|
||||||
| **`core/local-db`** | ✅ Grün | SQLDelight Setup für JVM & Web. |
|
|
||||||
| **`features/ping`** | ✅ Grün | **Blueprint-Feature**. Zeigt Best Practices (Sync, UI, DI). |
|
|
||||||
| **`shells/portal`** | ✅ Grün | Einstiegspunkt (`MainApp`). Verbindet alle Module. |
|
|
||||||
|
|
||||||
## 4. Offene Punkte & Nächste Schritte
|
|
||||||
|
|
||||||
Obwohl der technische Zustand nun exzellent ist, gibt es logische nächste Schritte für die Produktentwicklung:
|
|
||||||
|
|
||||||
1. **Feature-Rollout:** Implementierung des `members-feature` (Mitglieder) basierend auf dem `ping-feature` Blueprint.
|
|
||||||
2. **Testing:** Etablierung von Unit-Tests für die Core-Logik (Auth, Sync) und UI-Tests für kritische Flows.
|
|
||||||
3. **Backend-Alignment:** Sicherstellung, dass die Backend-Services (Registry) die erwarteten Sync-Endpunkte bereitstellen.
|
|
||||||
|
|
||||||
## 5. Fazit
|
|
||||||
Das Frontend-Fundament ist stabil. Die "technischen Schulden" aus der Experimentierphase (Redux vs. MVVM) sind getilgt. Das Team kann sich nun voll auf die Implementierung der fachlichen Anforderungen konzentrieren.
|
|
||||||
|
|
||||||
---
|
|
||||||
*Gez. Frontend Expert & Curator*
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
---
|
|
||||||
type: Report
|
|
||||||
status: ACTIVE
|
|
||||||
owner: Curator
|
|
||||||
date: 2026-02-01
|
|
||||||
author: Curator
|
|
||||||
---
|
|
||||||
|
|
||||||
# Report: Fix Sync Type Mismatch (String vs Long)
|
|
||||||
|
|
||||||
## 1. Problembeschreibung
|
|
||||||
Es wurde eine kritische Inkonsistenz im Delta-Sync-Mechanismus zwischen Frontend und Backend festgestellt.
|
|
||||||
* **Frontend:** Der generische `SyncManager` nutzte einen String-Cursor (UUIDv7), was zu einem Typ-Fehler führte.
|
|
||||||
* **Backend:** Der `PingController` erwartete strikt einen `Long` (Timestamp) für den Parameter `lastSyncTimestamp`.
|
|
||||||
|
|
||||||
## 2. Durchgeführte Maßnahmen
|
|
||||||
### 2.1 Backend (`ping-service`)
|
|
||||||
* **Parameter-Umbenennung:** Der Parameter im `PingController` wurde von `lastSyncTimestamp` zu `since` umbenannt, um der Konvention des Frontend-SyncManagers zu entsprechen.
|
|
||||||
* **Tests:** Unit- und Integrationstests (`PingControllerTest`) wurden aktualisiert.
|
|
||||||
|
|
||||||
### 2.2 Frontend (`meldestelle-portal`)
|
|
||||||
* **Repository-Anpassung:** `PingEventRepositoryImpl` holt nun explizit den `last_modified` Timestamp aus der Datenbank (via neuer SQL-Query `selectLatestPingEventTimestamp`).
|
|
||||||
* **Typ-Konvertierung:** Der Timestamp wird als String an den `SyncManager` übergeben, der ihn als URL-Parameter anhängt. Spring Boot konvertiert diesen String automatisch zurück in einen `Long`.
|
|
||||||
|
|
||||||
### 2.3 Contracts (`ping-api`)
|
|
||||||
* Das Interface `PingApi` wurde aktualisiert: `syncPings(since: Long)`.
|
|
||||||
|
|
||||||
## 3. Ergebnis
|
|
||||||
* Die Typ-Sicherheit ist hergestellt.
|
|
||||||
* Tests im Backend laufen erfolgreich durch.
|
|
||||||
* Der Sync-Mechanismus ist nun robust und bereit für den produktiven Einsatz.
|
|
||||||
|
|
||||||
## 4. Status
|
|
||||||
✅ **RESOLVED**
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
---
|
|
||||||
type: Report
|
|
||||||
status: ARCHIVED
|
|
||||||
author: Senior Backend Developer
|
|
||||||
date: 2026-01-17
|
|
||||||
context: Phase 3 - Sync Implementation
|
|
||||||
---
|
|
||||||
|
|
||||||
# Backend Status Report: Phase 3 (Sync) abgeschlossen
|
|
||||||
|
|
||||||
**ARCHIVED:** This report reflects a past state. Please refer to `2026-01-23_Weekend_Status_Report.md` for the current status.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. Zusammenfassung
|
|
||||||
Die Phase 3 der "Operation Tracer Bullet" wurde erfolgreich abgeschlossen. Der `PingService` wurde um Delta-Sync-Funktionalität erweitert, um Offline-First-Clients effizient zu unterstützen.
|
|
||||||
|
|
||||||
**Wichtigste Errungenschaften:**
|
|
||||||
* **Delta-Sync API:** Implementierung von `/ping/sync` basierend auf Zeitstempeln.
|
|
||||||
* **Contract-Update:** Synchronisierung der API-Definitionen zwischen Backend und Frontend (`:contracts:ping-api`).
|
|
||||||
* **Testing:** Vollständige Testabdeckung für die neuen Sync-Endpunkte.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. Technische Details
|
|
||||||
|
|
||||||
### A. Sync-Strategie
|
|
||||||
* **Mechanismus:** Zeitstempel-basierter Delta-Sync.
|
|
||||||
* **API:** `GET /ping/sync?lastSyncTimestamp={epochMillis}`
|
|
||||||
* **Response:** Liste von `PingEvent` (ID, Message, LastModified).
|
|
||||||
* **Vorteil:** Clients laden nur geänderte Daten, was Bandbreite spart und Offline-Fähigkeit unterstützt.
|
|
||||||
|
|
||||||
### B. Implementierung
|
|
||||||
* **Domain:** Erweiterung des `PingUseCase` um `getPingsSince(timestamp: Long)`.
|
|
||||||
* **Persistence:** Effiziente JPA-Query `findByCreatedAtAfter` auf dem `timestamp`-Index.
|
|
||||||
* **Security:** Der Sync-Endpunkt ist aktuell `public` (analog zu anderen Ping-Endpunkten), kann aber bei Bedarf geschützt werden.
|
|
||||||
|
|
||||||
### C. Frontend-Kompatibilität
|
|
||||||
* Die Frontend-Clients (`PingApiClient`, `PingApiKoinClient`) wurden aktualisiert, um den neuen Endpunkt zu unterstützen.
|
|
||||||
* Test-Doubles im Frontend wurden angepasst, um die Build-Integrität zu wahren.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. Offene Punkte & Nächste Schritte
|
|
||||||
|
|
||||||
* **Frontend Integration:** Der Frontend-Expert muss nun die Logik implementieren, um den `lastSyncTimestamp` lokal zu speichern und den Sync-Prozess zu steuern.
|
|
||||||
* **Konfliktlösung:** Aktuell ist der Sync unidirektional (Server -> Client). Für bidirektionalen Sync (Client -> Server) müssen noch Strategien (z.B. "Last Write Wins") definiert werden.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. Fazit
|
|
||||||
Das Backend ist bereit für Offline-First-Szenarien. Die Delta-Sync-Schnittstelle ist performant und einfach zu konsumieren.
|
|
||||||
@@ -6,10 +6,10 @@ date: 2026-01-31
|
|||||||
tags: [e2e, smoke, docker, migration, ktor-3.4.0, exposed-1.0.0]
|
tags: [e2e, smoke, docker, migration, ktor-3.4.0, exposed-1.0.0]
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
# E2E Smoke – Migration Exposed 1.0.0 & Ktor 3.4.0
|
# E2E Smoke – Migration Exposed 1.0.0 & Ktor 3.4.0
|
||||||
|
|
||||||
## Einrichtung
|
## Einrichtung
|
||||||
|
|
||||||
- Compose: docker compose --profile all up --build -d
|
- Compose: docker compose --profile all up --build -d
|
||||||
- Services (Auszug):
|
- Services (Auszug):
|
||||||
- api-gateway (8080/actuator, 8080/api via Proxy)
|
- api-gateway (8080/actuator, 8080/api via Proxy)
|
||||||
@@ -20,17 +20,22 @@ tags: [e2e, smoke, docker, migration, ktor-3.4.0, exposed-1.0.0]
|
|||||||
- Versionen (Platform/Catalog): ktor=3.4.0, exposed=1.0.0
|
- Versionen (Platform/Catalog): ktor=3.4.0, exposed=1.0.0
|
||||||
|
|
||||||
## Checks & Ergebnisse
|
## Checks & Ergebnisse
|
||||||
|
|
||||||
- Gateway Health: 200 OK (readiness/live, Prometheus)
|
- Gateway Health: 200 OK (readiness/live, Prometheus)
|
||||||
- Ping-Service Health/Prometheus: 200 OK stabil
|
- Ping-Service Health/Prometheus: 200 OK stabil
|
||||||
- Web-App Health: 200 OK (Fallback-Assets aktiv, Favicon bereitgestellt)
|
- Web-App Health: 200 OK (Fallback-Assets aktiv, Favicon bereitgestellt)
|
||||||
- Desktop-App: Xvfb/XFCE/x11vnc/noVNC aktiv, Zugriff via http://localhost:6080/
|
- Desktop-App: Xvfb/XFCE/x11vnc/noVNC aktiv, Zugriff via http://localhost:6080/
|
||||||
|
|
||||||
## Beobachtbarkeit
|
## Beobachtbarkeit
|
||||||
|
|
||||||
- Prometheus-Metriken erreichbar (Gateway/Ping)
|
- Prometheus-Metriken erreichbar (Gateway/Ping)
|
||||||
- Logs ohne kritische Fehler im Happy Path
|
- Logs ohne kritische Fehler im Happy Path
|
||||||
|
|
||||||
## Probleme & Hinweise
|
## Probleme & Hinweise
|
||||||
- Frontend KMP/JS-Build schlägt in Builder aktuell fehl (fehlende JS-Implementierungen in Auth/Ping-Data). Nginx liefert Fallback-Assets aus; Favicon hinzugefügt, um 404 zu vermeiden.
|
|
||||||
|
- Frontend KMP/JS-Build schlägt in Builder aktuell fehl (fehlende JS-Implementierungen in Auth/Ping-Data). Nginx liefert
|
||||||
|
Fallback-Assets aus; Favicon hinzugefügt, um 404 zu vermeiden.
|
||||||
|
|
||||||
## Entscheidung
|
## Entscheidung
|
||||||
|
|
||||||
- Empfehlung: Go für Phase 4 (FE „web“-Target Migration & Build-Fix; Dokumente finalisieren)
|
- Empfehlung: Go für Phase 4 (FE „web“-Target Migration & Build-Fix; Dokumente finalisieren)
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
---
|
||||||
|
type: Report
|
||||||
|
status: ACTIVE
|
||||||
|
owner: Backend Developer
|
||||||
|
last_update: 2026-02-01
|
||||||
|
---
|
||||||
|
|
||||||
|
# Abschlussbericht: Backend Hardening & Infrastructure (Ping-Service)
|
||||||
|
|
||||||
|
## 1. Management Summary
|
||||||
|
|
||||||
|
Der **Ping-Service** wurde erfolgreich als technischer Blueprint ("Tracer Bullet") gehärtet. Er erfüllt nun alle
|
||||||
|
Anforderungen der **Phase 1 (Backend Hardening)** der Q1 Roadmap.
|
||||||
|
Die Infrastruktur wurde modernisiert (Valkey 9.0), und die Testabdeckung wurde durch echte Integrationstests (
|
||||||
|
Testcontainers) auf ein Enterprise-Niveau gehoben.
|
||||||
|
|
||||||
|
Der Service ist **Production Ready** und dient ab sofort als Vorlage für alle fachlichen Microservices.
|
||||||
|
|
||||||
|
## 2. Durchgeführte Maßnahmen
|
||||||
|
|
||||||
|
### 🛡️ Security & Resilience
|
||||||
|
|
||||||
|
* **OAuth2 Resource Server:** Implementiert und konfiguriert (`GlobalSecurityConfig`). Tokens vom Keycloak werden
|
||||||
|
validiert.
|
||||||
|
* **RBAC:** Endpunkte wie `/ping/secure` sind durch Rollen geschützt (`@PreAuthorize`).
|
||||||
|
* **CircuitBreaker:** Resilience4j sichert DB-Zugriffe ab (`@CircuitBreaker`). Fallback-Methoden ("Degraded Mode") sind
|
||||||
|
aktiv.
|
||||||
|
|
||||||
|
### 🏗️ Infrastructure Upgrade
|
||||||
|
|
||||||
|
* **Valkey Migration:** Erfolgreiche Migration von Redis (proprietär) auf **Valkey 9.0** (Open Source) in
|
||||||
|
`docker-compose` und Environment-Configs.
|
||||||
|
* Images: `valkey/valkey:9.0`
|
||||||
|
* Kompatibilität: Vollständig gegeben (Drop-In Replacement).
|
||||||
|
|
||||||
|
### 🧪 Quality Assurance (Testing)
|
||||||
|
|
||||||
|
* **Integrationstests:** Implementierung von `PingRepositoryTest` mit **Testcontainers** (Postgres).
|
||||||
|
* Prüft Flyway-Migrationen (`V1`, `V2`).
|
||||||
|
* Prüft JPA-Mapping und UUIDv7-Persistenz gegen eine echte Datenbank.
|
||||||
|
* **Test-Isolierung:** Lösung komplexer Spring-Kontext-Probleme (`BeanDefinitionOverrideException`) durch:
|
||||||
|
* Einführung einer isolierten `TestPersistenceConfig` für Repository-Tests.
|
||||||
|
* Nutzung von `@TestConfiguration` in Controller-Tests.
|
||||||
|
* Entfernung des hinderlichen `@Profile("!test")` im `PingRepositoryAdapter`.
|
||||||
|
|
||||||
|
### 📊 Observability
|
||||||
|
|
||||||
|
* **Actuator:** Health, Info, Metrics und Prometheus-Endpunkte sind exponiert.
|
||||||
|
* **Tracing:** Zipkin-Integration vorbereitet via `monitoring-client`.
|
||||||
|
|
||||||
|
## 3. Technische Details & Learnings
|
||||||
|
|
||||||
|
### Problem: Spring Context Pollution
|
||||||
|
|
||||||
|
Während der Implementierung der Integrationstests kam es zu Konflikten zwischen den Bean-Definitionen verschiedener
|
||||||
|
Tests (`BeanDefinitionOverrideException`).
|
||||||
|
**Lösung:**
|
||||||
|
Strikte Trennung der Kontexte. `PingRepositoryTest` lädt nun **nicht** mehr die gesamte `PingServiceApplication`,
|
||||||
|
sondern nur eine minimale `TestPersistenceConfig`, die gezielt nur das Persistence-Layer scannt. Dies beschleunigt die
|
||||||
|
Tests und verhindert Seiteneffekte durch Controller oder Security-Configs.
|
||||||
|
|
||||||
|
### Problem: Profile-Exclusion
|
||||||
|
|
||||||
|
Der `PingRepositoryAdapter` war mit `@Profile("!test")` annotiert. Dies verhinderte, dass Integrationstests (die im
|
||||||
|
`test`-Profil laufen) den echten Adapter nutzen konnten.
|
||||||
|
**Lösung:**
|
||||||
|
Annotation entfernt. In Unit-Tests wird der Adapter ohnehin durch Mocks ersetzt, daher ist die Exclusion unnötig und
|
||||||
|
schädlich für Integrationstests.
|
||||||
|
|
||||||
|
## 4. Nächste Schritte (Handover an Frontend)
|
||||||
|
|
||||||
|
Der Backend-Stack ist stabil. Der Frontend-Expert kann nun die Integration (Phase 2) abschließen:
|
||||||
|
|
||||||
|
1. Login gegen Keycloak.
|
||||||
|
2. Aufruf von `/ping/secure` mit Bearer-Token.
|
||||||
|
3. Test des Delta-Syncs (`/ping/sync`).
|
||||||
|
|
||||||
|
---
|
||||||
|
*Gez. Senior Backend Developer*
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
---
|
||||||
|
type: Report
|
||||||
|
status: ACTIVE
|
||||||
|
owner: Frontend Expert
|
||||||
|
title: Frontend Cleanup & Architecture Status Report
|
||||||
|
date: 2026-02-01
|
||||||
|
author: Frontend Expert & Curator
|
||||||
|
tags: [frontend, architecture, cleanup, kmp, compose]
|
||||||
|
---
|
||||||
|
|
||||||
|
# 🧹 Frontend Cleanup & Architecture Status Report
|
||||||
|
|
||||||
|
## 1. Executive Summary
|
||||||
|
|
||||||
|
Dieses Dokument fasst die umfangreichen Aufräum- und Refactoring-Arbeiten am Frontend ("Meldestelle Portal") zusammen.
|
||||||
|
Ziel war es, technischen Ballast ("Dead Code") zu entfernen, die Architektur zu vereinheitlichen (MVVM + Clean
|
||||||
|
Architecture) und die Kompilierbarkeit über alle Plattformen (JVM/Desktop & JS/Web) sicherzustellen.
|
||||||
|
|
||||||
|
**Ergebnis:** Der Build ist erfolgreich (`BUILD SUCCESSFUL`). Das Frontend ist nun schlank, wartbar und bereit für die
|
||||||
|
Feature-Entwicklung.
|
||||||
|
|
||||||
|
## 2. Durchgeführte Maßnahmen
|
||||||
|
|
||||||
|
### 2.1. Entfernung von "Dead Code"
|
||||||
|
|
||||||
|
* **`frontend/shared` gelöscht:** Dieses Modul enthielt einen kompletten, ungenutzten Redux-Stack (`AppStore`,
|
||||||
|
`AppAction`, etc.), der im Widerspruch zur genutzten MVVM-Architektur stand.
|
||||||
|
* **Legacy-Komponenten entfernt:** Veraltete UI-Komponenten (z.B. `NotificationCard.kt`) und doppelte
|
||||||
|
Navigations-Konzepte wurden bereinigt.
|
||||||
|
|
||||||
|
### 2.2. Architektur-Konsolidierung
|
||||||
|
|
||||||
|
* **MVVM als Standard:** Die Anwendung folgt nun strikt dem MVVM-Muster mit Kotlin Coroutines (`StateFlow`) und Koin für
|
||||||
|
Dependency Injection.
|
||||||
|
* **Clean Architecture:** Das `ping-feature` dient als Referenz-Implementierung mit klarer Trennung von `Presentation`,
|
||||||
|
`Domain` und `Data` Layer.
|
||||||
|
* **Navigation:** Zentralisierung der Navigation auf `AppScreen` (Sealed Class) im Core-Modul.
|
||||||
|
|
||||||
|
### 2.3. Build & Plattform-Support
|
||||||
|
|
||||||
|
* **Koin-Initialisierung:** Korrektur der Koin-Start-Logik für JVM (`startKoin` statt `initKoin`) und JS (`startKoin` im
|
||||||
|
`main.kt`).
|
||||||
|
* **Gradle-Konfiguration:** Bereinigung der `build.gradle.kts` Dateien und Entfernung von Abhängigkeiten zu gelöschten
|
||||||
|
Modulen.
|
||||||
|
* **Web-Support:** Sicherstellung, dass die Web-Version (Kotlin/JS) fehlerfrei baut und die Datenbank (SQLDelight Wasm)
|
||||||
|
korrekt initialisiert.
|
||||||
|
|
||||||
|
## 3. Modul-Status (Ist-Zustand)
|
||||||
|
|
||||||
|
| Modul | Status | Beschreibung |
|
||||||
|
|:-------------------------|:-------|:-----------------------------------------------------------------------|
|
||||||
|
| **`core/navigation`** | ✅ Grün | Zentrale Routen (`AppScreen`, `Routes`), DeepLink-Handling. Sauber. |
|
||||||
|
| **`core/design-system`** | ✅ Grün | UI-Komponenten (`AppTheme`, `Buttons`, `Inputs`). Modern (Material 3). |
|
||||||
|
| **`core/auth`** | ✅ Grün | Login-Logik, Token-Manager, API-Client. Funktional. |
|
||||||
|
| **`core/network`** | ✅ Grün | Zentraler `HttpClient` mit Auth-Interceptor. |
|
||||||
|
| **`core/sync`** | ✅ Grün | Generischer `SyncManager` für Offline-First. |
|
||||||
|
| **`core/local-db`** | ✅ Grün | SQLDelight Setup für JVM & Web. |
|
||||||
|
| **`features/ping`** | ✅ Grün | **Blueprint-Feature**. Zeigt Best Practices (Sync, UI, DI). |
|
||||||
|
| **`shells/portal`** | ✅ Grün | Einstiegspunkt (`MainApp`). Verbindet alle Module. |
|
||||||
|
|
||||||
|
## 4. Offene Punkte & Nächste Schritte
|
||||||
|
|
||||||
|
Obwohl der technische Zustand nun exzellent ist, gibt es logische nächste Schritte für die Produktentwicklung:
|
||||||
|
|
||||||
|
1. **Feature-Rollout:** Implementierung des `members-feature` (Mitglieder) basierend auf dem `ping-feature` Blueprint.
|
||||||
|
2. **Testing:** Etablierung von Unit-Tests für die Core-Logik (Auth, Sync) und UI-Tests für kritische Flows.
|
||||||
|
3. **Backend-Alignment:** Sicherstellung, dass die Backend-Services (Registry) die erwarteten Sync-Endpunkte
|
||||||
|
bereitstellen.
|
||||||
|
|
||||||
|
## 5. Fazit
|
||||||
|
|
||||||
|
Das Frontend-Fundament ist stabil. Die "technischen Schulden" aus der Experimentierphase (Redux vs. MVVM) sind getilgt.
|
||||||
|
Das Team kann sich nun voll auf die Implementierung der fachlichen Anforderungen konzentrieren.
|
||||||
|
|
||||||
|
---
|
||||||
|
*Gez. Frontend Expert & Curator*
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
type: Report
|
||||||
|
status: ACTIVE
|
||||||
|
owner: Curator
|
||||||
|
date: 2026-02-01
|
||||||
|
author: Curator
|
||||||
|
---
|
||||||
|
|
||||||
|
# Report: Fix Sync Type Mismatch (String vs Long)
|
||||||
|
|
||||||
|
## 1. Problembeschreibung
|
||||||
|
|
||||||
|
Es wurde eine kritische Inkonsistenz im Delta-Sync-Mechanismus zwischen Frontend und Backend festgestellt.
|
||||||
|
|
||||||
|
* **Frontend:** Der generische `SyncManager` nutzte einen String-Cursor (UUIDv7), was zu einem Typ-Fehler führte.
|
||||||
|
* **Backend:** Der `PingController` erwartete strikt einen `Long` (Timestamp) für den Parameter `lastSyncTimestamp`.
|
||||||
|
|
||||||
|
## 2. Durchgeführte Maßnahmen
|
||||||
|
|
||||||
|
### 2.1 Backend (`ping-service`)
|
||||||
|
|
||||||
|
* **Parameter-Umbenennung:** Der Parameter im `PingController` wurde von `lastSyncTimestamp` zu `since` umbenannt, um
|
||||||
|
der Konvention des Frontend-SyncManagers zu entsprechen.
|
||||||
|
* **Tests:** Unit- und Integrationstests (`PingControllerTest`) wurden aktualisiert.
|
||||||
|
|
||||||
|
### 2.2 Frontend (`meldestelle-portal`)
|
||||||
|
|
||||||
|
* **Repository-Anpassung:** `PingEventRepositoryImpl` holt nun explizit den `last_modified` Timestamp aus der
|
||||||
|
Datenbank (via neuer SQL-Query `selectLatestPingEventTimestamp`).
|
||||||
|
* **Typ-Konvertierung:** Der Timestamp wird als String an den `SyncManager` übergeben, der ihn als URL-Parameter
|
||||||
|
anhängt. Spring Boot konvertiert diesen String automatisch zurück in einen `Long`.
|
||||||
|
|
||||||
|
### 2.3 Contracts (`ping-api`)
|
||||||
|
|
||||||
|
* Das Interface `PingApi` wurde aktualisiert: `syncPings(since: Long)`.
|
||||||
|
|
||||||
|
## 3. Ergebnis
|
||||||
|
|
||||||
|
* Die Typ-Sicherheit ist hergestellt.
|
||||||
|
* Tests im Backend laufen erfolgreich durch.
|
||||||
|
* Der Sync-Mechanismus ist nun robust und bereit für den produktiven Einsatz.
|
||||||
|
|
||||||
|
## 4. Status
|
||||||
|
|
||||||
|
✅ **RESOLVED**
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
---
|
||||||
|
type: Report
|
||||||
|
status: ARCHIVED
|
||||||
|
author: Senior Backend Developer
|
||||||
|
date: 2026-01-17
|
||||||
|
context: Phase 3 - Sync Implementation
|
||||||
|
---
|
||||||
|
|
||||||
|
# Backend Status Report: Phase 3 (Sync) abgeschlossen
|
||||||
|
|
||||||
|
**ARCHIVED:** This report reflects a past state. Please refer to `2026-01-23_Weekend_Status_Report.md` for the current
|
||||||
|
status.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Zusammenfassung
|
||||||
|
|
||||||
|
Die Phase 3 der "Operation Tracer Bullet" wurde erfolgreich abgeschlossen. Der `PingService` wurde um
|
||||||
|
Delta-Sync-Funktionalität erweitert, um Offline-First-Clients effizient zu unterstützen.
|
||||||
|
|
||||||
|
**Wichtigste Errungenschaften:**
|
||||||
|
|
||||||
|
* **Delta-Sync API:** Implementierung von `/ping/sync` basierend auf Zeitstempeln.
|
||||||
|
* **Contract-Update:** Synchronisierung der API-Definitionen zwischen Backend und Frontend (`:contracts:ping-api`).
|
||||||
|
* **Testing:** Vollständige Testabdeckung für die neuen Sync-Endpunkte.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Technische Details
|
||||||
|
|
||||||
|
### A. Sync-Strategie
|
||||||
|
|
||||||
|
* **Mechanismus:** Zeitstempel-basierter Delta-Sync.
|
||||||
|
* **API:** `GET /ping/sync?lastSyncTimestamp={epochMillis}`
|
||||||
|
* **Response:** Liste von `PingEvent` (ID, Message, LastModified).
|
||||||
|
* **Vorteil:** Clients laden nur geänderte Daten, was Bandbreite spart und Offline-Fähigkeit unterstützt.
|
||||||
|
|
||||||
|
### B. Implementierung
|
||||||
|
|
||||||
|
* **Domain:** Erweiterung des `PingUseCase` um `getPingsSince(timestamp: Long)`.
|
||||||
|
* **Persistence:** Effiziente JPA-Query `findByCreatedAtAfter` auf dem `timestamp`-Index.
|
||||||
|
* **Security:** Der Sync-Endpunkt ist aktuell `public` (analog zu anderen Ping-Endpunkten), kann aber bei Bedarf
|
||||||
|
geschützt werden.
|
||||||
|
|
||||||
|
### C. Frontend-Kompatibilität
|
||||||
|
|
||||||
|
* Die Frontend-Clients (`PingApiClient`, `PingApiKoinClient`) wurden aktualisiert, um den neuen Endpunkt zu
|
||||||
|
unterstützen.
|
||||||
|
* Test-Doubles im Frontend wurden angepasst, um die Build-Integrität zu wahren.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Offene Punkte & Nächste Schritte
|
||||||
|
|
||||||
|
* **Frontend Integration:** Der Frontend-Expert muss nun die Logik implementieren, um den `lastSyncTimestamp` lokal zu
|
||||||
|
speichern und den Sync-Prozess zu steuern.
|
||||||
|
* **Konfliktlösung:** Aktuell ist der Sync unidirektional (Server -> Client). Für bidirektionalen Sync (Client ->
|
||||||
|
Server) müssen noch Strategien (z.B. "Last Write Wins") definiert werden.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Fazit
|
||||||
|
|
||||||
|
Das Backend ist bereit für Offline-First-Szenarien. Die Delta-Sync-Schnittstelle ist performant und einfach zu
|
||||||
|
konsumieren.
|
||||||
@@ -8,13 +8,15 @@ context: Phase 1-3 (Backend Ready)
|
|||||||
|
|
||||||
# Infrastructure Status Report: "Tracer Bullet" Readiness
|
# Infrastructure Status Report: "Tracer Bullet" Readiness
|
||||||
|
|
||||||
**ARCHIVED:** This report reflects a past state. Please refer to `2026-01-23_Weekend_Status_Report.md` for the current status.
|
**ARCHIVED:** This report reflects a past state. Please refer to `2026-01-23_Weekend_Status_Report.md` for the current
|
||||||
|
status.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Datum:** 20. Jänner 2026
|
**Datum:** 20. Jänner 2026
|
||||||
**Autor:** DevOps & Infrastructure Engineer (Updated by Backend Developer)
|
**Autor:** DevOps & Infrastructure Engineer (Updated by Backend Developer)
|
||||||
**Ziel:** Bestätigung der Einsatzbereitschaft der lokalen Entwicklungsumgebung für Phase 1 (Backend Hardening) und Phase 3 (Sync).
|
**Ziel:** Bestätigung der Einsatzbereitschaft der lokalen Entwicklungsumgebung für Phase 1 (Backend Hardening) und Phase
|
||||||
|
3 (Sync).
|
||||||
|
|
||||||
## 1. Executive Summary
|
## 1. Executive Summary
|
||||||
|
|
||||||
@@ -36,23 +38,27 @@ Die Integrationstests des `ping-service` gegen die Docker-Umgebung waren erfolgr
|
|||||||
## 3. Durchgeführte Maßnahmen (DevOps)
|
## 3. Durchgeführte Maßnahmen (DevOps)
|
||||||
|
|
||||||
### 3.1. Keycloak Stabilisierung
|
### 3.1. Keycloak Stabilisierung
|
||||||
* Umstellung auf offizielles Image `quay.io/keycloak/keycloak:26.4` (start-dev).
|
|
||||||
* Realm-Import via `--import-realm` erfolgreich.
|
* Umstellung auf offizielles Image `quay.io/keycloak/keycloak:26.4` (start-dev).
|
||||||
|
* Realm-Import via `--import-realm` erfolgreich.
|
||||||
|
|
||||||
### 3.2. Datenbank Initialisierung
|
### 3.2. Datenbank Initialisierung
|
||||||
* Init-Skripte gehärtet.
|
|
||||||
* Sauberer State durch Reset garantiert.
|
* Init-Skripte gehärtet.
|
||||||
|
* Sauberer State durch Reset garantiert.
|
||||||
|
|
||||||
### 3.3. Konfigurations-Bereinigung
|
### 3.3. Konfigurations-Bereinigung
|
||||||
* `base-application.yaml` bereinigt und Flyway aktiviert.
|
|
||||||
|
* `base-application.yaml` bereinigt und Flyway aktiviert.
|
||||||
|
|
||||||
## 4. Backend Feedback (Phase 1 & 3 Abschluss)
|
## 4. Backend Feedback (Phase 1 & 3 Abschluss)
|
||||||
|
|
||||||
Der **Senior Backend Developer** bestätigt:
|
Der **Senior Backend Developer** bestätigt:
|
||||||
|
|
||||||
1. **Connectivity:** Der `ping-service` verbindet sich erfolgreich mit Postgres, Keycloak und Consul.
|
1. **Connectivity:** Der `ping-service` verbindet sich erfolgreich mit Postgres, Keycloak und Consul.
|
||||||
2. **Security:** Die Token-Validierung (Issuer: `http://keycloak:8080/...`) funktioniert im Docker-Netzwerk einwandfrei.
|
2. **Security:** Die Token-Validierung (Issuer: `http://keycloak:8080/...`) funktioniert im Docker-Netzwerk einwandfrei.
|
||||||
3. **Sync:** Die Performance der DB für den Delta-Sync (`/ping/sync`) ist auch bei lokalen Tests sehr gut (Index-Nutzung bestätigt).
|
3. **Sync:** Die Performance der DB für den Delta-Sync (`/ping/sync`) ist auch bei lokalen Tests sehr gut (Index-Nutzung
|
||||||
|
bestätigt).
|
||||||
|
|
||||||
**Status:** Der `ping-service` ist vollständig implementiert (inkl. Hardening & Sync) und bereit für das Frontend.
|
**Status:** Der `ping-service` ist vollständig implementiert (inkl. Hardening & Sync) und bereit für das Frontend.
|
||||||
|
|
||||||
@@ -8,7 +8,8 @@ tags: [backend, ping-service, task]
|
|||||||
|
|
||||||
# Arbeitsauftrag: Implementierung des `ping-service` (Tracer Bullet)
|
# Arbeitsauftrag: Implementierung des `ping-service` (Tracer Bullet)
|
||||||
|
|
||||||
**ARCHIVED:** This is the original task description. The implementation has evolved. Please refer to `docs/05_Backend/Services/PingService_Reference.md`.
|
**ARCHIVED:** This is the original task description. The implementation has evolved. Please refer to
|
||||||
|
`docs/05_Backend/Services/PingService_Reference.md`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -58,6 +59,7 @@ JVM-spezifischen Abhängigkeiten** enthalten, um die KMP-Kompatibilität für da
|
|||||||
```text
|
```text
|
||||||
PingResponse.kt
|
PingResponse.kt
|
||||||
```
|
```
|
||||||
|
|
||||||
```text
|
```text
|
||||||
package de.meldestelle.api.ping
|
package de.meldestelle.api.ping
|
||||||
|
|
||||||
@@ -71,12 +73,13 @@ JVM-spezifischen Abhängigkeiten** enthalten, um die KMP-Kompatibilität für da
|
|||||||
```
|
```
|
||||||
|
|
||||||
3. Service-Implementierung in :ping-service
|
3. Service-Implementierung in :ping-service
|
||||||
|
|
||||||
Implementiere die Spring Boot Anwendung.
|
Implementiere die Spring Boot Anwendung.
|
||||||
|
|
||||||
- **`PingController.kt`:**
|
- **`PingController.kt`:**
|
||||||
- **`GET /api/ping`:** Ein öffentlicher Endpunkt, der eine `PingResponse("Pong", "anonymous")` zurückgibt.
|
- **`GET /api/ping`:** Ein öffentlicher Endpunkt, der eine `PingResponse("Pong", "anonymous")` zurückgibt.
|
||||||
- **`GET /api/ping/secure`:** Ein durch Spring Security geschützter Endpunkt. Er soll den `preferred_username` aus dem `Jwt` Principal extrahieren und in der `PingResponse` zurückgeben.
|
- **`GET /api/ping/secure`:** Ein durch Spring Security geschützter Endpunkt. Er soll den `preferred_username` aus dem
|
||||||
|
`Jwt` Principal extrahieren und in der `PingResponse` zurückgeben.
|
||||||
|
|
||||||
Hier ist ein Implementierungsvorschlag für den Controller:
|
Hier ist ein Implementierungsvorschlag für den Controller:
|
||||||
|
|
||||||
@@ -108,7 +111,7 @@ Erstelle die `application.yml` für den Service. Sie muss die Anwendung für uns
|
|||||||
- **Service Discovery:** Registrierung bei Consul.
|
- **Service Discovery:** Registrierung bei Consul.
|
||||||
- **Security:** Konfiguration als Resource Server, der JWTs vom `issuer-uri` unseres Keycloak-Containers validiert.
|
- **Security:** Konfiguration als Resource Server, der JWTs vom `issuer-uri` unseres Keycloak-Containers validiert.
|
||||||
- **Observability:** Actuator-Endpunkte (`health`, `info`, `prometheus`) freigeben und Tracing aktivieren.
|
- **Observability:** Actuator-Endpunkte (`health`, `info`, `prometheus`) freigeben und Tracing aktivieren.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# in backend/services/ping/ping-service/src/main/resources/application.yml
|
# in backend/services/ping/ping-service/src/main/resources/application.yml
|
||||||
|
|
||||||
@@ -150,7 +153,7 @@ Erstelle die `application.yml` für den Service. Sie muss die Anwendung für uns
|
|||||||
pattern:
|
pattern:
|
||||||
level: "%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]"
|
level: "%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]"
|
||||||
```
|
```
|
||||||
|
|
||||||
5. **Build-Konfiguration(`build.gradle.kts`)
|
5. **Build-Konfiguration(`build.gradle.kts`)
|
||||||
|
|
||||||
Achte auf die korrekte und saubere Definition der Abhängigkeiten.
|
Achte auf die korrekte und saubere Definition der Abhängigkeiten.
|
||||||
@@ -172,7 +175,7 @@ Achte auf die korrekte und saubere Definition der Abhängigkeiten.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- `ping-service/build.gradle.kts`
|
- `ping-service/build.gradle.kts`
|
||||||
```text
|
```text
|
||||||
plugins {
|
plugins {
|
||||||
@@ -202,14 +205,17 @@ Achte auf die korrekte und saubere Definition der Abhängigkeiten.
|
|||||||
testImplementation(libs.bundles.test.spring)
|
testImplementation(libs.bundles.test.spring)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Definition of Done:
|
## Definition of Done:
|
||||||
|
|
||||||
Der Auftrag gilt als erledigt, wenn:
|
Der Auftrag gilt als erledigt, wenn:
|
||||||
|
|
||||||
1. Die Anwendung erfolgreich startet und sich im Consul UI als `UP` registriert.
|
1. Die Anwendung erfolgreich startet und sich im Consul UI als `UP` registriert.
|
||||||
2. Ein `GET`-Request auf `http//localhost:8081/api/ping` (über das Gateway) den Status `200 OK` und die `{"message":"Pong", "principal":"anonymous"}` zurückgibt.
|
2. Ein `GET`-Request auf `http//localhost:8081/api/ping` (über das Gateway) den Status `200 OK` und die
|
||||||
|
`{"message":"Pong", "principal":"anonymous"}` zurückgibt.
|
||||||
3. Ein `GET`-Request auf `http//localhost:8081/api/ping/secure` ohne Token den Status `401 Unauthorized` zurückgibt.
|
3. Ein `GET`-Request auf `http//localhost:8081/api/ping/secure` ohne Token den Status `401 Unauthorized` zurückgibt.
|
||||||
4. Ein `GET`-Request auf `http//localhost:8081/api/ping/secure` mit einem gültigen Keycloak-Token deb Status `200 OK` und eine Antwort mit dem korrekten Benutzernamen zurückgibt.
|
4. Ein `GET`-Request auf `http//localhost:8081/api/ping/secure` mit einem gültigen Keycloak-Token deb Status `200 OK`
|
||||||
|
und eine Antwort mit dem korrekten Benutzernamen zurückgibt.
|
||||||
5. Die Requests in der Zipkin UI als Trace sichtbar sind.
|
5. Die Requests in der Zipkin UI als Trace sichtbar sind.
|
||||||
|
|
||||||
Bei Fragen zur Konfiguration oder zur Architektur stehe ich dir zur Verfügung.
|
Bei Fragen zur Konfiguration oder zur Architektur stehe ich dir zur Verfügung.
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
# Session Log: Behebung Flyway Migrations-Fehler im Ping-Service
|
|
||||||
**Datum:** 2026-04-03
|
|
||||||
**Agent:** Backend Developer / Curator
|
|
||||||
|
|
||||||
## Problembeschreibung
|
|
||||||
Der `ping-service` ließ sich via Docker nicht starten und warf eine `FlywayMigrateException` mit der Ursache `ERROR: relation "ping" does not exist`.
|
|
||||||
Die Log-Analyse zeigte, dass die Datenbankmigration `V2__seed_data.sql` fehlgeschlagen ist, weil die vorausgehende Migration `V1__init_ping.sql` (in der die Tabelle `ping` erstellt wird) offensichtlich nicht ausgeführt wurde.
|
|
||||||
|
|
||||||
## Ursachenanalyse
|
|
||||||
Die `application.yaml` des `ping-service` enthielt die Konfiguration `baseline-on-migrate: true`. Wenn mehrere Services (z. B. `masterdata-service`, `ping-service` etc.) dieselbe PostgreSQL-Datenbank (`pg-meldestelle-db`) und standardmäßig das Schema `public` nutzen, teilen sie sich ohne weitere Konfiguration die gleiche Flyway-Historientabelle (`flyway_schema_history`).
|
|
||||||
|
|
||||||
Wenn ein anderer Service bereits Migrationen ausgeführt oder die Datenbank initialisiert hatte, setzte Flyway für den `ping-service` eine Baseline mit Version `1`. Infolgedessen ignorierte Flyway die Datei `V1__init_ping.sql` und versuchte direkt, `V2__seed_data.sql` auszuführen. Dies führte zum Scheitern der Migration, da die notwendige Struktur aus `V1` fehlte.
|
|
||||||
|
|
||||||
## Lösung
|
|
||||||
1. **Isolierung der Flyway-Historientabelle:** In der `application.yaml` des `ping-service` wurde die Property `spring.flyway.table: flyway_schema_history_ping` hinzugefügt. Dadurch verwaltet der `ping-service` seinen eigenen Migrationsstatus unabhängig von anderen Services in der gleichen Datenbank.
|
|
||||||
2. **Anpassung der Baseline-Version:** Es wurde explizit `spring.flyway.baseline-version: "0"` konfiguriert, um sicherzustellen, dass V1-Skripte stets als Teil der Historie betrachtet werden, selbst falls Flyway in einer nicht leeren Datenbank ansetzt.
|
|
||||||
|
|
||||||
## Geänderte Dateien
|
|
||||||
* `/mocode/Meldestelle/backend/services/ping/ping-service/src/main/resources/application.yaml`
|
|
||||||
* `/mocode/Meldestelle/docs/05_Backend/Services/PingService_Reference.md` (Dokumentation aktualisiert)
|
|
||||||
|
|
||||||
## Nächste Schritte
|
|
||||||
* Die Infrastruktur sollte nun stabil hochfahren. (Ggf. Ping Service im Docker Stack neustarten).
|
|
||||||
* Diese Best Practice (spezifische `flyway.table` pro Service) sollte zukünftig auch bei anderen Microservices angewandt werden, die sich dasselbe DB-Schema teilen, um Konflikte zu vermeiden.
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
---
|
|
||||||
type: Journal
|
|
||||||
status: ACTIVE
|
|
||||||
owner: Curator
|
|
||||||
last_update: 2026-04-10
|
|
||||||
---
|
|
||||||
# Journal Entry: 2026-04-10 - Billing Service Setup & ZNS Importer Hardening
|
|
||||||
|
|
||||||
## 👷 [Backend Developer] / 🏗️ [Lead Architect] / 🧹 [Curator]
|
|
||||||
|
|
||||||
### Zusammenfassung der Session
|
|
||||||
In dieser Session wurde das Fundament für den Kassa-Service (`billing-context`) gelegt und die Robustheit des ZNS-Importers durch zusätzliche Integrationstests für Funktionäre gesteigert.
|
|
||||||
|
|
||||||
### Wichtigste Ergebnisse
|
|
||||||
1. **Billing Service Initialisierung & API:**
|
|
||||||
* `billing-service` Modul erstellt, konfiguriert und mit `core-domain` (Serialisierung) verknüpft.
|
|
||||||
* Exposed-Tabellendefinitionen (v1) für `TeilnehmerKonto` und `Buchung` implementiert.
|
|
||||||
* `BillingController` mit REST-Endpunkten für Konten, Buchungen und Historie erstellt.
|
|
||||||
* `TeilnehmerKontoService` um API-Methoden (`getKontoById`, `getKonto`, `getBuchungsHistorie`, `buche`) erweitert.
|
|
||||||
* Integrationstests (`TeilnehmerKontoServiceTest`) erfolgreich mit H2-In-Memory-DB durchgeführt.
|
|
||||||
* **OpenAPI-Dokumentation:** `documentation.yaml` für `billing-service` erstellt und CRUD-Endpunkte für Konten und Buchungen dokumentiert.
|
|
||||||
2. **Entries-Integration (Neu):**
|
|
||||||
* Automatische Buchung von Nenngeld und Nachnenngebühren bei Einreichung einer Nennung implementiert.
|
|
||||||
* Erweiterung der `Bewerb`-Entität um Finanzfelder (`nenngeld_cent`, `nachnenngebuehr_cent`).
|
|
||||||
* Neue Flyway-Migration `V8__add_bewerb_financial_fields.sql` im `entries-service` hinzugefügt.
|
|
||||||
* `NennungUseCases` nutzt nun den `TeilnehmerKontoService` zur automatischen Belastung der Teilnehmerkonten (negativer Saldo).
|
|
||||||
* `EntriesServiceApplication` scannt nun auch `at.mocode.billing` Pakete für die Cross-Context Integration.
|
|
||||||
3. **ZNS-Importer Hardening:**
|
|
||||||
* Erweiterung von `ZnsImportServiceTest` um Tests für mehrfache Qualifikationen und die Update-Strategie (Delete+Insert) bei Funktionären (`RICHT01.dat`).
|
|
||||||
* Alle 11 Integrationstests sind erfolgreich durchgelaufen.
|
|
||||||
4. **Kompilations-Fixes (Billing):**
|
|
||||||
* `billing-service` auf korrekte Exposed DSL Syntax (`selectAll().where { ... }`) umgestellt.
|
|
||||||
* Explizite `transaction { ... }` Blöcke in `TeilnehmerKontoService` eingeführt.
|
|
||||||
* Typ-Konsistenz für `Instant` (kotlin.time) in `billing-domain` zur Übereinstimmung mit `core-domain` hergestellt.
|
|
||||||
|
|
||||||
### Betroffene Dateien
|
|
||||||
- `backend/services/billing/` (Neuer SCS-Kontext)
|
|
||||||
- `backend/infrastructure/zns-importer/src/test/kotlin/at/mocode/zns/importer/ZnsImportServiceTest.kt`
|
|
||||||
|
|
||||||
### Nächste Schritte
|
|
||||||
- [x] Integration des Billing-Services in den `entries-context` (automatische Buchung bei Nennung).
|
|
||||||
- [x] Fix von Kompilationsfehlern und Test-Regressionen (H2/Exposed Kompatibilität).
|
|
||||||
- UI-Anbindung im Frontend für Kontenübersicht und manuelle Buchungen.
|
|
||||||
- Erweiterung der Abrechnungs-Logik (z.B. Rechnungserstellung als PDF).
|
|
||||||
|
|
||||||
### Technische Details & Fixes
|
|
||||||
- **Exposed / H2:** `TIMESTAMPTZ` in Flyway-Migrationen auf `TIMESTAMP WITH TIME ZONE` umgestellt, um H2-Kompatibilität in Integrationstests zu gewährleisten.
|
|
||||||
- **Multi-Tenancy:** `ExposedTenantTransactions` unterstützt nun sowohl PostgreSQL (`SET search_path`) als auch H2 (`SET SCHEMA`).
|
|
||||||
- **Billing Config:** `BillingDatabaseConfiguration` ist nun robust gegen fehlende JDBC-URLs (wichtig für modularisierte Tests).
|
|
||||||
|
|
||||||
---
|
|
||||||
*Co-authored-by: Junie <junie@jetbrains.com>*
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
---
|
|
||||||
type: Journal
|
|
||||||
status: ACTIVE
|
|
||||||
owner: DevOps Engineer
|
|
||||||
last_update: 2026-04-14
|
|
||||||
---
|
|
||||||
|
|
||||||
# Session Log: Fix Kotlin Wasm JS Compilation OOM
|
|
||||||
|
|
||||||
## Problem
|
|
||||||
Die Kompilierung des Moduls `:frontend:features:billing-feature` für `wasmJs` schlug mit einem `java.lang.OutOfMemoryError: GC overhead limit exceeded` fehl.
|
|
||||||
|
|
||||||
Ursache war die Verwendung von `material-icons-extended` in Kombination mit den bisherigen JVM-Speichereinstellungen (6GB). Da `material-icons-extended` tausende generierte Icon-Dateien enthält, stößt der Kotlin/Wasm-Compiler bei der IR-Lowering-Phase an seine Grenzen.
|
|
||||||
|
|
||||||
## Lösung
|
|
||||||
1. **Speichererhöhung:** Die JVM-Heap-Einstellungen in `gradle.properties` wurden von 6GB auf 8GB erhöht.
|
|
||||||
- `kotlin.daemon.jvmargs` wurde auf `-Xmx8g` gesetzt.
|
|
||||||
- `org.gradle.jvmargs` wurde auf `-Xmx8g` gesetzt, wobei die Optionen für den Kotlin-Daemon (`-Dkotlin.daemon.jvm.options`) auf `-Xmx6g` erhöht wurden.
|
|
||||||
2. **Verifizierung:** Die Kompilierung von `:frontend:features:billing-feature:compileProductionLibraryKotlinWasmJs` wurde nach einem Daemon-Restart erfolgreich durchgeführt.
|
|
||||||
|
|
||||||
## Betroffene Dateien
|
|
||||||
- `gradle.properties`: Erhöhung der Speicherlimits.
|
|
||||||
- `frontend/features/billing-feature/build.gradle.kts`: (Kurzzeitig getestet ohne `materialIconsExtended`, aber wieder aktiviert, da Icons daraus benötigt werden).
|
|
||||||
|
|
||||||
## Handover
|
|
||||||
- Zukünftig sollte bei weiteren OOM-Problemen im Wasm-Bereich geprüft werden, ob `material-icons-extended` durch eine selektive Icon-Einbindung (z.B. als Ressourcen) ersetzt werden kann, um den Compiler zu entlasten.
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
---
|
|
||||||
type: Journal
|
|
||||||
status: ACTIVE
|
|
||||||
owner: DevOps Engineer
|
|
||||||
last_update: 2026-04-14
|
|
||||||
---
|
|
||||||
|
|
||||||
# Session Log: Finalize and Enable Entries Isolation Integration Test
|
|
||||||
|
|
||||||
## Problem
|
|
||||||
Der Test `EntriesIsolationIntegrationTest` im Modul `:backend:services:entries:entries-service` war deaktiviert (`@Disabled`). Er hatte Probleme mit der Daten-Isolierung zwischen verschiedenen Tenants, wenn Exposed mit mehreren Schemas und PostgreSQL-Containern verwendet wurde.
|
|
||||||
|
|
||||||
Zusätzlich gab es IDE-Warnungen bezüglich nicht auflösbarer Symbole in SQL-Strings, redundantem `runBlocking` und ungenutzten Variablen.
|
|
||||||
|
|
||||||
## Lösung
|
|
||||||
1. **Test-Bereinigung:**
|
|
||||||
- Entfernung der `@Disabled` Annotation.
|
|
||||||
- Behebung der `runBlocking` Redundanz durch Verwendung von `runBlocking` auf Test-Methoden-Ebene.
|
|
||||||
- Entfernung ungenutzter Variablen (`saved`).
|
|
||||||
- Bereitstellung einer `@TestConfiguration` mit einem Mock `JwtDecoder`, um ApplicationContext-Ladefehler durch Security-Abhängigkeiten zu vermeiden.
|
|
||||||
|
|
||||||
2. **Schema-Isolierung fixiert:**
|
|
||||||
- Umstellung der Tabellen-Erstellung im `setup` auf JDBC, um zu verhindern, dass Exposed's `Table`-Singletons frühzeitig an ein falsches Schema gebunden werden.
|
|
||||||
- Sicherstellung, dass `tenantTransaction` den `search_path` in PostgreSQL korrekt setzt.
|
|
||||||
- Explizite Verwendung von `SET search_path` innerhalb der Transaktionen im Isolationstest, um Leaks zu vermeiden.
|
|
||||||
- Verifizierung der Isolation: Schreibzugriffe in `event_a` landen nun nachweislich nicht mehr in `event_b`.
|
|
||||||
|
|
||||||
3. **Verifizierung & Cleanup:**
|
|
||||||
- Alle 10 Tests im Modul (inkl. der neu aktivierten Isolation-Tests) laufen erfolgreich durch.
|
|
||||||
- IDE-Warnungen in `EntriesIsolationIntegrationTest` und `JdbcTenantRegistryTest` wurden durch `@Suppress("SqlResolve")`, Verwendung von String-Konstanten/Interpolation (`$CONTROL_SCHEMA`) und Entfernung ungenutzter Code-Fragmente (`nennungRepository`, `random()`, `registerDataSource`) behoben.
|
|
||||||
- Typos wie "testdb" -> "test_db" und "Produktions" -> "Production" wurden korrigiert.
|
|
||||||
- Behebung von IDE-Warnungen in `NennungBillingIntegrationTest`, `BewerbeZeitplanIntegrationTest` und `DomainHierarchyMigrationTest` durch Entfernung ungenutzter Variablen (`result`), Ersetzen von Umlauten in Funktionsnamen/Strings durch ASCII-Zeichen und Verwendung von Konstanten für Schema-Namen (`TEST_SCHEMA`).
|
|
||||||
- Fehlende Spring-Konfigurations-Metadaten für `multitenancy.*` wurden in `additional-spring-configuration-metadata.json` ergänzt.
|
|
||||||
|
|
||||||
## Betroffene Dateien
|
|
||||||
- `backend/services/entries/entries-service/src/test/kotlin/at/mocode/entries/service/tenant/EntriesIsolationIntegrationTest.kt`: Reaktiviert und repariert.
|
|
||||||
- `backend/services/entries/entries-service/src/test/kotlin/at/mocode/entries/service/tenant/JdbcTenantRegistryTest.kt`: Bereinigt und optimiert.
|
|
||||||
- `backend/services/entries/entries-service/src/main/resources/META-INF/additional-spring-configuration-metadata.json`: Metadaten ergänzt.
|
|
||||||
|
|
||||||
## Handover
|
|
||||||
- Der `EntriesIsolationIntegrationTest` dient nun als Referenz für Multi-Tenancy Tests mit echten PostgreSQL-Containern. Bei weiteren Tests dieser Art sollte auf das Exposed-Schema-Caching geachtet werden.
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
---
|
|
||||||
type: Journal
|
|
||||||
status: ACTIVE
|
|
||||||
owner: DevOps Engineer
|
|
||||||
last_update: 2026-04-14
|
|
||||||
---
|
|
||||||
|
|
||||||
# Session Log: Fix Entries Service Integration Tests (EOFException / PostgreSQL Connection)
|
|
||||||
|
|
||||||
## Problem
|
|
||||||
Die Integrationstests im Modul `:backend:services:entries:entries-service` (`BewerbeZeitplanIntegrationTest`, `NennungBillingIntegrationTest`) schlugen mit einer `FlywaySqlUnableToConnectToDbException` (verursacht durch `PSQLException: EOFException`) fehl.
|
|
||||||
|
|
||||||
Ursache war das Fehlen einer `application-test.yaml`. Dadurch wurden die Standardwerte aus `application.yaml` geladen, welche eine aktive PostgreSQL-Instanz auf `localhost:5432` sowie Consul und Flyway-Migrationen erwarteten. In der CI/Test-Umgebung ohne diese Infrastruktur führte der Verbindungsversuch zum Abbruch.
|
|
||||||
|
|
||||||
## Lösung
|
|
||||||
1. **Test-Konfiguration erstellt:** Eine neue Datei `backend/services/entries/entries-service/src/test/resources/application-test.yaml` wurde angelegt.
|
|
||||||
- Umstellung auf H2 In-Memory Datenbank (`jdbc:h2:mem:entries-test`).
|
|
||||||
- Deaktivierung von Flyway (`spring.flyway.enabled=false`), da die Tests Tabellen manuell via Exposed `SchemaUtils` anlegen.
|
|
||||||
- Deaktivierung von Consul Discovery (`spring.cloud.consul.enabled=false`).
|
|
||||||
- Umstellung der Multitenancy-Registry auf `inmem`.
|
|
||||||
2. **Verifizierung:** Die Tests im Modul wurden mit `./gradlew :backend:services:entries:entries-service:test` erfolgreich durchgeführt (5 Tests bestanden, 1 übersprungen/disabled).
|
|
||||||
|
|
||||||
## Betroffene Dateien
|
|
||||||
- `backend/services/entries/entries-service/src/test/resources/application-test.yaml`: Neue Konfiguration für das `test` Profil.
|
|
||||||
|
|
||||||
## Handover
|
|
||||||
- Die `EntriesIsolationIntegrationTest` bleibt weiterhin `@Disabled`, da sie Testcontainers benötigt und laut Quellcode-Kommentar noch weitere Fixes für die Exposed-Metadaten-Isolierung erfordert.
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
---
|
|
||||||
type: Journal
|
|
||||||
status: COMPLETED
|
|
||||||
agent: 🏗️ Lead Architect & 🧐 QA Specialist
|
|
||||||
date: 2026-04-18
|
|
||||||
---
|
|
||||||
|
|
||||||
# 📜 Session-Abschluss: Stabilisierung & Security-Fix Ping-Service (Update)
|
|
||||||
|
|
||||||
## 🎯 Zusammenfassung
|
|
||||||
|
|
||||||
In dieser Session wurde die fehlerhafte Authentifizierung des **Ping-Service (ConnectivityCheck)** bei Zugriffen via Postman und externen Clients behoben. Die Hauptursache war ein **Issuer-Mismatch** im JWT-Token zwischen der internen Docker-Infrastruktur (`keycloak:8080`) und der externen Sicht des Clients (`localhost:8180`).
|
|
||||||
|
|
||||||
## ✅ Erreichte Meilensteine
|
|
||||||
|
|
||||||
### 1. Diagnose & Ursachenanalyse
|
|
||||||
- **Issuer-Mismatch:** Spring Security validiert standardmäßig den `iss` Claim. Da Keycloak im Docker-Netzwerk einen anderen Hostnamen hat als für den externen Client, schlug die Validierung fehl (401 Unauthorized), obwohl der Token an sich gültig war.
|
|
||||||
- **Autorisierungs-Lücke:** Der Ping-Service (Resource Server) und das Gateway lehnten Token ab, deren Issuer nicht exakt der konfigurierten `issuer-uri` entsprach.
|
|
||||||
|
|
||||||
### 2. Flexibilisierung der Security-Validierung
|
|
||||||
- **Custom JWT Decoder (Gateway):** Implementierung eines `ResilienceReactiveJwtDecoder`, der die Issuer-Validierung überspringt, aber weiterhin Signatur und Zeitstempel prüft. Dies ermöglicht den nahtlosen Wechsel zwischen Docker-internen und externen Aufrufen.
|
|
||||||
- **Custom JWT Decoder (Ping-Service):** Analog wurde in der `GlobalSecurityConfig` ein `JwtDecoder` konfiguriert, der auf die strikte Issuer-Prüfung verzichtet.
|
|
||||||
|
|
||||||
### 3. Security Hardening & Konsistenz
|
|
||||||
- **CORS-Fix:** Die `allowedHeaders` im Gateway wurden auf `*` gesetzt, um Inkompatibilitäten mit Postman-Headern zu vermeiden.
|
|
||||||
- **Endpunkt-Konsistenz:** Die Postman-Tests für `secure`, `sync` (authentifiziert) und `enhanced` (authentifiziert) sind nun wieder erfolgreich, da das Gateway und der Service den Token korrekt akzeptieren.
|
|
||||||
|
|
||||||
## 🛠️ Technische Änderungen
|
|
||||||
|
|
||||||
- `backend/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/security/SecurityConfig.kt`: Neuer `ResilienceReactiveJwtDecoder` mit deaktiviertem Issuer-Check.
|
|
||||||
- `backend/infrastructure/security/src/main/kotlin/at/mocode/infrastructure/security/GlobalSecurityConfig.kt`: Explizite `JwtDecoder` Bean zur Umgehung des Issuer-Mismatches hinzugefügt.
|
|
||||||
- `backend/infrastructure/gateway/src/main/resources/static/docs/postman/Meldestelle_API_Collection.json`: Refactoring und Erweiterung der Connectivity-Tests.
|
|
||||||
|
|
||||||
## 🚀 Status-Report
|
|
||||||
|
|
||||||
Alle Connectivity-Endpunkte (Simple, Health, Public, Sync, Secure, Enhanced) sind nun sowohl öffentlich als auch authentifiziert (je nach Anforderung) erreichbar. Die Infrastruktur ist robuster gegenüber Umgebungsunterschieden (Local vs. Docker) geworden.
|
|
||||||
|
|
||||||
**Status:** Authentifizierung stabilisiert und Issuer-Mismatch behoben. 🟢
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
# Journal: 19. April 2026 - Backend Stabilität & Desktop UX-Refinement
|
|
||||||
|
|
||||||
## 🏗️ Backend: Infrastruktur & Mail-Service
|
|
||||||
|
|
||||||
* **Mail-Service:** Konflikt beim Request-Mapping behoben. Der redundante `NennungController` wurde entfernt und seine Funktionalität (Status-Update, Erstellung) in den zentralen `MailController` integriert.
|
|
||||||
* **Health-Checks:** `spring-boot-starter-actuator` zum `entries-service` hinzugefügt, um die 404-Fehler in der Consul-Überwachung zu eliminieren.
|
|
||||||
* **Mail-Features:** Neuer Endpunkt `POST /send-reply` im `MailController` implementiert, um Bestätigungs-Mails an Nenner mit dynamischer Absenderadresse (Turnier-spezifisch) zu senden.
|
|
||||||
|
|
||||||
## 💻 Desktop-App: Navigation & UI
|
|
||||||
|
|
||||||
* **Veranstaltungs-Konfiguration:** White-Screen Fix durch Korrektur der Navigation im `DesktopMainLayout.kt`. Es wird nun korrekt auf den `VeranstaltungKonfigScreen` aus dem Feature-Modul verwiesen.
|
|
||||||
* **Device-Setup:** UX-Verbesserung durch Entfernung blockierender `onKeyEvent` Handler. Die Navigation zwischen Feldern mittels **Tab** und **Enter** funktioniert nun reibungslos über den Standard-Fokus-Flow.
|
|
||||||
* **Design-System:**
|
|
||||||
* Suchfeld-Höhe in `MsFilterBar.kt` auf `44.dp` erhöht, um abgeschnittenen Text bei kleinen Schriftarten zu verhindern.
|
|
||||||
* `MsMasterDetailLayout` im Vereins-Bereich um einen **Preview-Bereich** (Card-Ansicht) erweitert.
|
|
||||||
|
|
||||||
## 🚀 Neue Features
|
|
||||||
|
|
||||||
### Nennungs-Eingang
|
|
||||||
* **Antwort-Funktion:** Ein neuer Button "Antwort & Übernahme" im Detail-Dialog ermöglicht das direkte Versenden einer Bestätigungs-Mail an den Nenner.
|
|
||||||
* **Sortierung:** Die Liste wird nun standardmäßig mit neuen Nennungen (`NEU`) zuerst sortiert.
|
|
||||||
|
|
||||||
### Vereins-Verwaltung
|
|
||||||
* **Card-Preview:** Der obere Teil des Detail-Bereichs zeigt nun eine visuelle Vorschau des Vereins (Name, Status, Ort).
|
|
||||||
* **Logo-Support:** Das Domain-Modell und der Editor wurden um ein `logoUrl` Feld erweitert, um Vereinslogos (z.B. für nicht registrierte Vereine) zu hinterlegen.
|
|
||||||
|
|
||||||
## 🧹 Curator Hinweis
|
|
||||||
Alle gemeldeten Start-Fehler im Backend wurden behoben. Die Desktop-App ist nun voll navigierbar und bietet verbesserte Effizienz für die Meldestellen-Mitarbeiter.
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# 📓 Journal-Eintrag: Billing-Feature Blueprint Migration
|
|
||||||
|
|
||||||
## 🏗️ [Lead Architect] | 🎨 [Frontend Expert] | 🧹 [Curator]
|
|
||||||
**Datum:** 2026-04-19
|
|
||||||
**Status:** ✅ Abgeschlossen
|
|
||||||
|
|
||||||
### 🎯 Ziel
|
|
||||||
Migration des `billing-feature` Moduls auf den neuen **Module Structure Blueprint** (Klasse B: `UI_COMPONENT`) unter Verwendung von `device-initialization` als Referenz.
|
|
||||||
|
|
||||||
### 🛠️ Durchgeführte Änderungen
|
|
||||||
|
|
||||||
1. **Gradle Konfiguration (`build.gradle.kts`):**
|
|
||||||
* `group` von `at.mocode.clients` auf `at.mocode.frontend.features` geändert (Alignment mit neuem Namensraum).
|
|
||||||
* `wasmJsMain` Source-Set explizit mit `kotlin.stdlib.wasm.js` Dependency konfiguriert.
|
|
||||||
* Struktur der Source-Sets an die Referenz angepasst.
|
|
||||||
|
|
||||||
2. **Strukturelle Anpassungen:**
|
|
||||||
* Verzeichnisse `src/jvmMain/kotlin/at/mocode/frontend/features/billing/` und `src/wasmJsMain/kotlin/at/mocode/frontend/features/billing/` erstellt, um die Blueprint "Consistency Rule" zu erfüllen.
|
|
||||||
* Die Paketstruktur in `commonMain` war bereits konsistent (`at.mocode.frontend.features.billing`).
|
|
||||||
|
|
||||||
3. **Verifizierung:**
|
|
||||||
* `./gradlew :frontend:features:billing-feature:assemble` wurde erfolgreich ausgeführt.
|
|
||||||
* Sowohl JVM- als auch WasmJS-Targets kompilieren fehlerfrei.
|
|
||||||
|
|
||||||
### 🚩 Nächste Schritte
|
|
||||||
* Fortführung der Feature-Migration mit dem nächsten Modul in der Liste (z.B. `pferde-feature` oder `profile-feature`).
|
|
||||||
* Sicherstellen, dass alle Referenzen auf das `billing-feature` (z.B. im `turnier-feature`) weiterhin funktionieren (ggf. Gradle-Projektpfade prüfen, falls diese sich ändern würden, was hier nicht der Fall war, da nur die `group` ID in Gradle geändert wurde, nicht der Pfad).
|
|
||||||
|
|
||||||
---
|
|
||||||
*Dokumentiert durch den Curator.*
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
# 📓 Journal-Eintrag: Core-Domain Blueprint Migration
|
|
||||||
|
|
||||||
## 🏗️ [Lead Architect] | 👷 [Backend Developer] | 🧹 [Curator]
|
|
||||||
**Datum:** 2026-04-19
|
|
||||||
**Status:** ✅ Abgeschlossen
|
|
||||||
|
|
||||||
### 🎯 Ziel
|
|
||||||
Migration des `frontend/core/domain` Moduls auf den neuen **Module Structure Blueprint** (Klasse B: `UI_COMPONENT`, da Plattform-spezifische `PlatformType` Implementierungen vorhanden sind).
|
|
||||||
|
|
||||||
### 🛠️ Durchgeführte Änderungen
|
|
||||||
|
|
||||||
1. **Gradle Konfiguration (`build.gradle.kts`):**
|
|
||||||
* `group` auf `at.mocode.frontend.core` gesetzt (Konsistenz mit `auth` & `design-system`).
|
|
||||||
* `version` auf `1.0.0` gesetzt.
|
|
||||||
* `wasmJsMain` Source-Set explizit mit `kotlin.stdlib.wasm.js` Dependency konfiguriert, um die KMP-Web-Infrastruktur zu vervollständigen.
|
|
||||||
|
|
||||||
2. **Strukturelle Analyse:**
|
|
||||||
* Die Paketstruktur `at.mocode.frontend.core.domain` war bereits vorbildlich und konsistent über alle Source-Sets (`commonMain`, `jvmMain`, `wasmJsMain`) hinweg.
|
|
||||||
* `PlatformType` nutzt das `expect/actual` Pattern korrekt.
|
|
||||||
|
|
||||||
3. **Verifizierung:**
|
|
||||||
* `./gradlew :frontend:core:domain:assemble` wurde erfolgreich ausgeführt.
|
|
||||||
|
|
||||||
### 🚩 Nächste Schritte
|
|
||||||
* Migration der weiteren Core-Module (`network`, `sync`, `localDb`).
|
|
||||||
* Anpassung der Feature-Module (Batch 1: Source-Set Topologie).
|
|
||||||
|
|
||||||
---
|
|
||||||
*Dokumentiert durch den Curator.*
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# 📓 Journal-Eintrag: Core-LocalDb Blueprint Migration
|
|
||||||
|
|
||||||
## 🏗️ [Lead Architect] | 👷 [Backend Developer] | 🧹 [Curator]
|
|
||||||
**Datum:** 2026-04-19
|
|
||||||
**Status:** ✅ Abgeschlossen
|
|
||||||
|
|
||||||
### 🎯 Ziel
|
|
||||||
Migration des `frontend/core/local-db` Moduls auf den neuen **Module Structure Blueprint** (Klasse B: `UI_COMPONENT`, da es KMP-spezifische Treiber-Implementierungen für JVM und WasmJS enthält).
|
|
||||||
|
|
||||||
### 🛠️ Durchgeführte Änderungen
|
|
||||||
|
|
||||||
1. **Gradle Konfiguration (`build.gradle.kts`):**
|
|
||||||
* `group` auf `at.mocode.frontend.core` gesetzt (Konsistenz mit anderen Core-Modulen).
|
|
||||||
* `version` auf `1.0.0` gesetzt.
|
|
||||||
* SqlDelight Konfiguration und Source-Sets waren bereits korrekt für Multiplatform (JVM & WasmJS) vorbereitet.
|
|
||||||
|
|
||||||
2. **Strukturelle Analyse:**
|
|
||||||
* Die Paketstruktur `at.mocode.frontend.core.localdb` ist konsistent über alle Source-Sets hinweg.
|
|
||||||
* `DatabaseDriverFactory` nutzt das `expect/actual` Pattern korrekt.
|
|
||||||
* `src/wasmJsMain` ist vorhanden und enthält die notwendige `sqlite.worker.js` und Web-Treiber Implementierung.
|
|
||||||
|
|
||||||
3. **Verifizierung:**
|
|
||||||
* `./gradlew :frontend:core:local-db:assemble` wurde erfolgreich ausgeführt.
|
|
||||||
|
|
||||||
### 🚩 Nächste Schritte
|
|
||||||
* Migration der verbleibenden Core-Module (`network`, `sync`).
|
|
||||||
* Batch-Update der Feature-Module (Source-Set Struktur & Group-IDs).
|
|
||||||
|
|
||||||
---
|
|
||||||
*Dokumentiert durch den Curator.*
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# 📓 Journal-Eintrag: Core-Navigation Blueprint Migration
|
|
||||||
|
|
||||||
## 🏗️ [Lead Architect] | 🎨 [Frontend Expert] | 🧹 [Curator]
|
|
||||||
**Datum:** 2026-04-19
|
|
||||||
**Status:** ✅ Abgeschlossen
|
|
||||||
|
|
||||||
### 🎯 Ziel
|
|
||||||
Migration des `frontend/core/navigation` Moduls auf den neuen **Module Structure Blueprint** (Klasse B: `UI_COMPONENT`, da es die Navigationslogik für die UI-Shells bereitstellt).
|
|
||||||
|
|
||||||
### 🛠️ Durchgeführte Änderungen
|
|
||||||
|
|
||||||
1. **Gradle Konfiguration (`build.gradle.kts`):**
|
|
||||||
* `group` auf `at.mocode.frontend.core` gesetzt (Konsistenz mit anderen Core-Modulen).
|
|
||||||
* `version` auf `1.0.0` gesetzt.
|
|
||||||
* `jvmMain` und `wasmJsMain` Source-Sets konfiguriert.
|
|
||||||
* `kotlin.stdlib.wasm.js` als Dependency für WasmJS hinzugefügt.
|
|
||||||
|
|
||||||
2. **Strukturelle Anpassungen:**
|
|
||||||
* Verzeichnisse `src/jvmMain/kotlin/at/mocode/frontend/core/navigation/` und `src/wasmJsMain/kotlin/at/mocode/frontend/core/navigation/` erstellt, um die Blueprint "Consistency Rule" zu erfüllen.
|
|
||||||
* Die Paketstruktur war bereits vorbildlich konsistent.
|
|
||||||
|
|
||||||
3. **Verifizierung:**
|
|
||||||
* `./gradlew :frontend:core:navigation:assemble` wurde erfolgreich ausgeführt.
|
|
||||||
|
|
||||||
### 🚩 Nächste Schritte
|
|
||||||
* Migration der verbleibenden Core-Module (`network`, `sync`).
|
|
||||||
* Batch-Anpassung der Group-IDs in den Feature-Modulen (`at.mocode.frontend.features`).
|
|
||||||
|
|
||||||
---
|
|
||||||
*Dokumentiert durch den Curator.*
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# 📓 Journal-Eintrag: Core-Network Blueprint Migration
|
|
||||||
|
|
||||||
## 🏗️ [Lead Architect] | 👷 [Backend Developer] | 🧹 [Curator]
|
|
||||||
**Datum:** 2026-04-19
|
|
||||||
**Status:** ✅ Abgeschlossen
|
|
||||||
|
|
||||||
### 🎯 Ziel
|
|
||||||
Migration des `frontend/core/network` Moduls auf den neuen **Module Structure Blueprint** (Klasse B: `UI_COMPONENT`).
|
|
||||||
|
|
||||||
### 🛠️ Durchgeführte Änderungen
|
|
||||||
|
|
||||||
1. **Gradle Konfiguration (`build.gradle.kts`):**
|
|
||||||
* `group` auf `at.mocode.frontend.core` gesetzt (Konsistenz mit anderen Core-Modulen).
|
|
||||||
* `version` auf `1.0.0` gesetzt.
|
|
||||||
* Die bestehende Multiplatform-Konfiguration (KMP) wurde als bereits blueprint-konform verifiziert.
|
|
||||||
|
|
||||||
2. **Strukturelle Analyse:**
|
|
||||||
* Die Paketstruktur `at.mocode.frontend.core.network` ist bereits konsistent über alle Source-Sets (`commonMain`, `jvmMain`, `wasmJsMain`) hinweg.
|
|
||||||
* Plattform-spezifische Implementierungen (z.B. `PlatformConfig`, `JmDnsDiscoveryService`) sind korrekt in den jeweiligen Source-Sets platziert.
|
|
||||||
* WasmJS-Unterstützung ist strukturell und in Gradle bereits vorbereitet.
|
|
||||||
|
|
||||||
3. **Verifizierung:**
|
|
||||||
* `./gradlew :frontend:core:network:assemble` wurde erfolgreich ausgeführt.
|
|
||||||
|
|
||||||
### 🚩 Nächste Schritte
|
|
||||||
* Migration des letzten verbleibenden Core-Moduls (`sync`).
|
|
||||||
* Anschließend Batch-Anpassung der Feature-Module (Topologie & Group-IDs).
|
|
||||||
|
|
||||||
---
|
|
||||||
*Dokumentiert durch den Curator.*
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# 📓 Journal-Eintrag: Core-Sync Blueprint Migration
|
|
||||||
|
|
||||||
## 🏗️ [Lead Architect] | 👷 [Backend Developer] | 🧹 [Curator]
|
|
||||||
**Datum:** 2026-04-19
|
|
||||||
**Status:** ✅ Abgeschlossen
|
|
||||||
|
|
||||||
### 🎯 Ziel
|
|
||||||
Migration des `frontend/core/sync` Moduls auf den neuen **Module Structure Blueprint** (Klasse B: `UI_COMPONENT`, da es KMP-spezifische Sync-Strategien unterstützen soll).
|
|
||||||
|
|
||||||
### 🛠️ Durchgeführte Änderungen
|
|
||||||
|
|
||||||
1. **Gradle Konfiguration (`build.gradle.kts`):**
|
|
||||||
* `group` auf `at.mocode.frontend.core` gesetzt (Konsistenz mit anderen Core-Modulen).
|
|
||||||
* `version` auf `1.0.0` gesetzt.
|
|
||||||
* `jvmMain` und `wasmJsMain` Source-Sets konfiguriert.
|
|
||||||
* `kotlin.stdlib.wasm.js` als Dependency für WasmJS hinzugefügt.
|
|
||||||
|
|
||||||
2. **Strukturelle Anpassungen:**
|
|
||||||
* Verzeichnisse `src/jvmMain/kotlin/at/mocode/frontend/core/sync/` und `src/wasmJsMain/kotlin/at/mocode/frontend/core/sync/` erstellt, um die Blueprint "Consistency Rule" zu erfüllen.
|
|
||||||
* Die Paketstruktur war bereits vorbildlich konsistent (`at.mocode.frontend.core.sync`).
|
|
||||||
|
|
||||||
3. **Verifizierung:**
|
|
||||||
* `./gradlew :frontend:core:sync:assemble` wurde erfolgreich ausgeführt.
|
|
||||||
|
|
||||||
### 🚩 Nächste Schritte
|
|
||||||
* Die Migration der Core-Module (`frontend/core/*`) ist hiermit weitgehend abgeschlossen.
|
|
||||||
* Nächster großer Block: Batch-Anpassung der Feature-Module (`frontend/features/*`) bezüglich Topologie (WasmJS-Ordner) und Group-IDs (`at.mocode.frontend.features`).
|
|
||||||
|
|
||||||
---
|
|
||||||
*Dokumentiert durch den Curator.*
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# 📓 Journal-Eintrag: Design-System Blueprint Migration
|
|
||||||
|
|
||||||
## 🏗️ [Lead Architect] | 🎨 [Frontend Expert] | 🧹 [Curator]
|
|
||||||
**Datum:** 2026-04-19
|
|
||||||
**Status:** ✅ Abgeschlossen
|
|
||||||
|
|
||||||
### 🎯 Ziel
|
|
||||||
Migration des `design-system` Moduls auf den neuen **Module Structure Blueprint** (Klasse B: `UI_COMPONENT`).
|
|
||||||
|
|
||||||
### 🛠️ Durchgeführte Änderungen
|
|
||||||
|
|
||||||
1. **Gradle Konfiguration (`build.gradle.kts`):**
|
|
||||||
* `group` auf `at.mocode.frontend.core` gesetzt (Konsistenz mit `auth` Referenz).
|
|
||||||
* `wasmJsMain` Source-Set explizit mit `kotlin.stdlib.wasm.js` Dependency konfiguriert.
|
|
||||||
* Version auf `1.0.0` fixiert.
|
|
||||||
|
|
||||||
2. **Strukturelle Anpassungen:**
|
|
||||||
* Verzeichnis `src/wasmJsMain/kotlin/at/mocode/frontend/core/designsystem/` erstellt, um die Blueprint "Consistency Rule" zu erfüllen.
|
|
||||||
* Paket-Migration in `jvmMain`:
|
|
||||||
* `at.mocode.wui.preview` -> `at.mocode.frontend.core.designsystem.preview`
|
|
||||||
* `Multipreview.kt` verschoben und Package-Deklaration aktualisiert.
|
|
||||||
* Damit ist die Paketstruktur nun konsistent über alle Source-Sets hinweg.
|
|
||||||
|
|
||||||
3. **Verifizierung:**
|
|
||||||
* `./gradlew :frontend:core:design-system:assemble` wurde erfolgreich ausgeführt.
|
|
||||||
* Alle Ziel-Plattformen (JVM & WasmJS) kompilieren fehlerfrei.
|
|
||||||
|
|
||||||
### 🚩 Nächste Schritte
|
|
||||||
* Fortsetzung der Migration mit den nächsten Core-Modulen (z.B. `network`, `domain`) oder den Feature-Modulen.
|
|
||||||
* Batch-Anpassung der Group-IDs in den Feature-Modulen.
|
|
||||||
|
|
||||||
---
|
|
||||||
*Dokumentiert durch den Curator.*
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# Journal: Finalisierung der Frontend-Blueprint-Migration
|
|
||||||
|
|
||||||
**Datum:** 19. April 2026
|
|
||||||
**Status:** Abgeschlossen
|
|
||||||
**Agent:** 🏗️ [Lead Architect] | 🧹 [Curator]
|
|
||||||
|
|
||||||
## 🎯 Zielsetzung
|
|
||||||
Nach der großflächigen Migration der Core- und Feature-Module wurden im letzten Schritt verbleibende strukturelle Inkonsistenzen in den Modulen `ping-feature` und `turnier-feature` bereinigt. Ziel war die vollständige Einhaltung des **Module Structure Blueprint** (Klasse B).
|
|
||||||
|
|
||||||
## 🛠️ Durchgeführte Änderungen
|
|
||||||
|
|
||||||
### 1. Paket-Synchronisierung (`ping-feature`)
|
|
||||||
* Das veraltete Paket `at.mocode.ping.feature` wurde konsistent in `at.mocode.frontend.features.ping` umbenannt.
|
|
||||||
* Dies betraf die Source-Sets `commonMain`, `jvmMain` und `commonTest`.
|
|
||||||
* Die physische Verzeichnisstruktur wurde von `at/mocode/ping/feature/` nach `at/mocode/frontend/features/ping/` verschoben.
|
|
||||||
|
|
||||||
### 2. Paket-Synchronisierung (`turnier-feature`)
|
|
||||||
* Das veraltete Paket `at.mocode.turnier.feature` wurde konsistent in `at.mocode.frontend.features.turnier` umbenannt.
|
|
||||||
* Betroffen waren alle Ebenen (`commonMain`, `jvmMain`, `wasmJsMain`) inklusive Unterpakete für `data`, `domain` und `presentation`.
|
|
||||||
* Die physische Verzeichnisstruktur wurde analog zum Standard angepasst.
|
|
||||||
|
|
||||||
### 3. Shell-Integration
|
|
||||||
* Die Importe in `frontend/shells/meldestelle-desktop` wurden an die neuen Paketnamen angepasst, um die Lauffähigkeit der Desktop-App sicherzustellen.
|
|
||||||
* Die `meldestelle-web` Shell wurde ebenfalls verifiziert.
|
|
||||||
|
|
||||||
## ✅ Verifizierung
|
|
||||||
* `./gradlew :frontend:features:ping-feature:assemble`: **ERFOLGREICH**
|
|
||||||
* `./gradlew :frontend:features:turnier-feature:assemble`: **ERFOLGREICH**
|
|
||||||
* `./gradlew :frontend:shells:meldestelle-desktop:assemble`: **ERFOLGREICH**
|
|
||||||
* `./gradlew :frontend:shells:meldestelle-web:assemble`: **ERFOLGREICH**
|
|
||||||
|
|
||||||
## 🧹 Fazit
|
|
||||||
Mit diesem Schritt ist die strukturelle Bereinigung des Frontends abgeschlossen. Alle Module (Core, Features, Shells) folgen nun einem einheitlichen Namens- und Struktur-Schema. Die "Consistency Rule" des Blueprints ist somit im gesamten Frontend-Projekt erfüllt.
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
# Journal: Fehlerbehebung PingSyncIntegrationTest nach Blueprint-Migration
|
|
||||||
|
|
||||||
**Datum:** 19. April 2026
|
|
||||||
**Status:** Abgeschlossen
|
|
||||||
**Agent:** 🧐 [QA Specialist] | 🏗️ [Lead Architect]
|
|
||||||
|
|
||||||
## 🎯 Problemstellung
|
|
||||||
Nach der großflächigen Umbenennung der Pakete und der Migration der Feature-Module auf den neuen Blueprint traten Kompilierfehler im Modul `ping-feature` auf, speziell im `PingSyncIntegrationTest.kt`.
|
|
||||||
|
|
||||||
### Fehlermeldungen:
|
|
||||||
* `Unresolved reference 'FakePingEventRepository'`: Die Mock-Klasse für den Test fehlte.
|
|
||||||
* `Unresolved reference 'it'`: Typ-Inferenz-Fehler aufgrund der fehlenden Repository-Klasse.
|
|
||||||
|
|
||||||
## 🛠️ Durchgeführte Änderungen
|
|
||||||
|
|
||||||
### 1. Wiederherstellung der Test-Infrastruktur
|
|
||||||
* Die Klasse `FakePingEventRepository` wurde im Verzeichnis `frontend/features/ping-feature/src/commonTest/kotlin/at/mocode/frontend/features/ping/integration/` neu erstellt.
|
|
||||||
* Sie implementiert das `SyncableRepository<PingEvent>` Interface und ermöglicht die Verifizierung der synchronisierten Daten im Integrationstest.
|
|
||||||
|
|
||||||
### 2. Korrektur des Integrationstests
|
|
||||||
* In `PingSyncIntegrationTest.kt` wurden die fehlenden Importe (insbesondere `at.mocode.ping.api.PingEvent`) hinzugefügt.
|
|
||||||
* Die Lambda-Ausdrücke in den Assertions wurden verifiziert; durch die Anwesenheit der `FakePingEventRepository` Klasse funktioniert die Typ-Inferenz von Kotlin nun wieder korrekt, und die Referenzen auf `it.id` und `it.message` werden aufgelöst.
|
|
||||||
|
|
||||||
## ✅ Verifizierung
|
|
||||||
* `./gradlew :frontend:features:ping-feature:compileTestKotlinJvm`: **ERFOLGREICH**
|
|
||||||
* `./gradlew :frontend:features:ping-feature:jvmTest`: **ERFOLGREICH** (Alle Tests bestanden)
|
|
||||||
|
|
||||||
## 🧹 Fazit
|
|
||||||
Die Test-Suite für das `ping-feature` ist nun wieder vollständig und blueprint-konform. Die Entkopplung durch das `SyncableRepository` wurde im Test erfolgreich durch das Fake-Repository validiert.
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
# Journal: Behebung von 500er Fehlern im Ping-Service & Security-Fixes
|
|
||||||
|
|
||||||
**Datum:** 19. April 2026
|
|
||||||
**Status:** Abgeschlossen
|
|
||||||
**Agent:** 🏗️ [Lead Architect] | 🧐 [QA Specialist] | 🧹 [Curator]
|
|
||||||
|
|
||||||
## 🎯 Zielsetzung
|
|
||||||
Nach der gestrigen Umstrukturierung traten beim `ping-service` HTTP 500 Fehler bei autorisierten API-Aufrufen auf. Ziel war die Identifikation der Ursachen (Security, Parameter-Mapping, Resilience) und deren Behebung sowie die Aktualisierung der Testsuite.
|
|
||||||
|
|
||||||
## 🛠️ Durchgeführte Änderungen
|
|
||||||
|
|
||||||
### 1. Security-Mapping & Rollen-Korrektur
|
|
||||||
* Im `PingController` wurden die `@PreAuthorize`-Annotationen korrigiert. Da der `KeycloakRoleConverter` das Präfix `ROLE_` hartkodiert hinzufügt und die Rollen in Großbuchstaben umwandelt, wurden die Prüfungen von `MELD_USER` auf `ROLE_MELD_USER` (bzw. `ROLE_MELD_ADMIN`) angepasst.
|
|
||||||
* Der Import der `AccessDeniedException` im `PingExceptionHandler` wurde auf die korrekte Spring Security Klasse fixiert, um 403-Fehler sauber zu fangen und nicht in 500er zu verwandeln.
|
|
||||||
|
|
||||||
### 2. API-Konsistenz & Parameter-Mapping
|
|
||||||
* Der Query-Parameter für `/api/ping/sync` wurde explizit auf `lastSyncTimestamp` gemappt, um mit dem Postman-Aufruf und den Anforderungen des Frontends konsistent zu sein.
|
|
||||||
|
|
||||||
### 3. Resilience4j & Coroutines
|
|
||||||
* Die Bibliothek `resilience4j-kotlin` wurde in die `libs.versions.toml` aufgenommen und im `ping-service` eingebunden. Dies stellt sicher, dass der `@CircuitBreaker` korrekt mit Kotlin `suspend` Funktionen zusammenarbeitet und Exceptions nicht unkontrolliert durchschlagen.
|
|
||||||
|
|
||||||
### 4. Test-Aktualisierung
|
|
||||||
* `PingControllerTest.kt` wurde angepasst, um den neuen Parameter-Namen `lastSyncTimestamp` zu verwenden.
|
|
||||||
* Alle 5 Tests im `PingControllerTest` verlaufen nun erfolgreich.
|
|
||||||
|
|
||||||
## ✅ Verifizierung
|
|
||||||
* `./gradlew :backend:services:ping:ping-service:test`: **ERFOLGREICH** (5/5 Tests passed)
|
|
||||||
* Manueller Check der Parameter-Namen gegen Postman-Anforderungen: **ERFOLGREICH**
|
|
||||||
* Verifizierung des Rollen-Mappings im `KeycloakRoleConverter` gegen Controller-Annotationen: **KONSISTENT**
|
|
||||||
|
|
||||||
## 🧹 Fazit
|
|
||||||
Die "letzte Meile" der Service-Kommunikation ist nun stabil. Durch das verbesserte Exception-Handling und die korrekte Resilience-Integration liefert der Service nun aussagekräftige HTTP-Statuscodes statt generischer 500er Fehler.
|
|
||||||
|
|
||||||
### Nachtrag 20:30
|
|
||||||
* **Networking-Fix:** `GlobalSecurityConfig` angepasst, um `jwk-set-uri` primär aus Spring-Properties oder Environment-Variables zu lesen. Default auf `localhost:8180` für IDE-Betrieb korrigiert, um `UnknownHostException: keycloak` zu vermeiden.
|
|
||||||
* **Exception-Handling:** `PingExceptionHandler` um generischen `Exception`-Handler erweitert, um auch Security-Initialisierungsfehler (wie JWT-Decoder-Probleme) sauber abzufangen und zu loggen.
|
|
||||||
|
|
||||||
### Nachtrag 21:25
|
|
||||||
* **Re-Fix Circuit Breaker Fallback:** Nachdem ein fehlerhafter Zwischenversuch (möglicherweise durch einen anderen Agenten) die `suspend`-Markierung wieder eingeführt hatte, wurde diese nun final entfernt. Die Signatur `fallbackPing(simulate: Boolean, ex: Throwable)` ohne `suspend` ist die einzig stabile Variante für Resilience4j in Kombination mit Spring Boot 3 AOP-Proxies und Kotlin Coroutines. Tests bestätigen die strukturelle Korrektheit.
|
|
||||||
|
|
||||||
### Nachtrag 21:45
|
|
||||||
* **Stochastic Simulation:** Die Zufallskomponente (`Random.nextDouble() < 0.6`) wurde in der `enhancedPing`-Methode wieder eingeführt.
|
|
||||||
* **Logik:** Wenn `simulate=true` übergeben wird, tritt der Fehler nun nur noch in ca. 60% der Fälle auf, was ein realistisches "intermittierendes" Fehlerszenario für den Circuit Breaker Test darstellt. In den restlichen 40% wird die Anfrage trotz Simulationsmodus erfolgreich verarbeitet.
|
|
||||||
* **Logging:** Zusätzliches Log-Statement für den "Lucky Pass" Fall hinzugefügt, um die Simulationstransparenz in der Konsole zu wahren.
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
# 🧹 [Curator] Journal: Session-Abschluss 19. April 2026
|
|
||||||
|
|
||||||
## 📋 Zusammenfassung der Session
|
|
||||||
Die heutige Session stand im Zeichen der **Code-Hygiene** und der **funktionalen Härtung** der Kernbereiche (Veranstaltung, Nennung, ZNS-Sync). Durch radikale Modularisierung konnte die Wartbarkeit massiv erhöht werden, während gleichzeitig kritische UX-Mängel behoben wurden.
|
|
||||||
|
|
||||||
## ✅ Erledigte Aufgaben
|
|
||||||
|
|
||||||
### 1. Radikale Modularisierung (Clean Code)
|
|
||||||
* **Veranstaltung-Context:** Die `VeranstaltungScreens.kt` (ca. 2000 Zeilen) wurde in eine saubere Paketstruktur unter `at.mocode.desktop.screens.veranstaltung` aufgeteilt.
|
|
||||||
* `VeranstaltungVerwaltung.kt` (Liste/Haupt-Screen)
|
|
||||||
* `wizards/` (Turnier- & Veranstalter-Wizards)
|
|
||||||
* `details/` (Profil & Konfig)
|
|
||||||
* `components/` (Wiederverwendbare UI-Atome)
|
|
||||||
* **Nennung-Context:** Die `NennungsMaske.kt` wurde analog dazu modularisiert und unter `at.mocode.frontend.features.nennung.presentation` neu strukturiert.
|
|
||||||
* `NennungManagementScreen.kt` (Integrations-Screen)
|
|
||||||
* `tabs/` (Nennungs-Tabellen, Verkauf/Buchung)
|
|
||||||
* `online/` (Online-Nennung/Mail-Import)
|
|
||||||
|
|
||||||
### 2. ZNS-Import & Masterdata-Sync
|
|
||||||
* **Stabilität:** Das `ZnsImportViewModel` wurde um detailliertes Terminal-Logging und robustes Error-Handling erweitert.
|
|
||||||
* **Persistenz:** Einführung des `MasterdataRepository`-Patterns. Die Desktop-Shell persistiert nun synchronisierte Reiter, Pferde, Vereine und Funktionäre direkt in den reaktiven `Store`.
|
|
||||||
* **UX:** Implementierung von Scrolling-Support (Scrollbars) in allen Stammdaten-Listen.
|
|
||||||
|
|
||||||
### 3. UX & Tastatur-Navigation
|
|
||||||
* **Fokus-Kette:** In der `DeviceInitialization` wurden die Blockaden bei TAB und ENTER in Schritt 2 vollständig behoben.
|
|
||||||
* **Logging:** Konsolen-Logs für die Initialisierung und den Sync-Prozess sind nun auch in der lokalen Umgebung via Gradle-Run sichtbar.
|
|
||||||
|
|
||||||
## 🛠️ Technische Details (ADR-0024 Plug-and-Play)
|
|
||||||
* **Navigation:** Alle Referenzen in `DesktopMainLayout.kt` wurden auf die neuen Modul-Pfade aktualisiert.
|
|
||||||
* **Build:** `./gradlew :frontend:shells:meldestelle-desktop:compileKotlinJvm` läuft fehlerfrei durch.
|
|
||||||
|
|
||||||
## 🚀 Ausblick für die nächste Session
|
|
||||||
1. **Sync-Validierung:** Testlauf des initialen Masterdata-Syncs unter Realbedingungen (Backend-Anbindung).
|
|
||||||
2. **Bewerb-Verwaltung:** Vertiefung der Modularisierung für die Bewerb-Konfiguration innerhalb der Turnier-Details.
|
|
||||||
3. **Druck-Engine:** Erste Prototypen für ÖTO-konforme Starterlisten (PDF/Export).
|
|
||||||
|
|
||||||
**Status:** Projekt ist in einem stabilen und sauberen Zustand.
|
|
||||||
**Signatur:** 🧹 [Curator] - 19. April 2026, 00:52 Uhr
|
|
||||||