docs: log session outcomes and apply enhancements across multiple components
Desktop CI — Headless Tests & Build / Compose Desktop — Tests (headless) & Build (push) Has been cancelled
Build and Publish Docker Images / build-and-push (., backend/infrastructure/gateway/Dockerfile, api-gateway, api-gateway) (push) Has been cancelled
Build and Publish Docker Images / build-and-push (., backend/services/ping/Dockerfile, ping-service, ping-service) (push) Has been cancelled
Build and Publish Docker Images / build-and-push (., config/docker/caddy/web-app/Dockerfile, web-app, web-app) (push) Has been cancelled
Build and Publish Docker Images / build-and-push (., config/docker/keycloak/Dockerfile, keycloak, keycloak) (push) Has been cancelled

- **Docker Fixes:** Resolved failed builds for Gateway and Ping services by switching to `eclipse-temurin:21-jdk-alpine`, correcting Gradle configurations, and fixing cache mount paths.
- **ZNS-Import Consul Registration:** Enabled Consul service discovery by updating `application.yaml` and `build.gradle.kts`.
- **pgAdmin Provisioning:** Preconfigured the database server in `servers.json` and updated `dc-ops.yaml` for seamless setup.
- **Postman Documentation:** Added a detailed Postman test guide covering environment setup, endpoint groups, and recommended test sequences.

Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
This commit is contained in:
2026-04-03 14:24:42 +02:00
parent ed3d327c82
commit b9ec070993
16 changed files with 1685 additions and 22 deletions
+19 -12
View File
@@ -5,15 +5,16 @@
# =================================================================== # ===================================================================
# === CENTRALIZED BUILD ARGUMENTS === # === CENTRALIZED BUILD ARGUMENTS ===
ARG GRADLE_VERSION=9.3.1 # HINWEIS: gradle:X.Y-jdkZ-alpine Images existieren nicht für alle Gradle/JDK-Kombinationen.
ARG JAVA_VERSION=25 # Wir verwenden eclipse-temurin als Builder-Basis und das Projekt-eigene ./gradlew-Wrapper.
ARG JAVA_VERSION=21
ARG BUILD_DATE ARG BUILD_DATE
ARG VERSION ARG VERSION
# =================================================================== # ===================================================================
# Build Stage # Build Stage
# =================================================================== # ===================================================================
FROM gradle:${GRADLE_VERSION}-jdk${JAVA_VERSION}-alpine AS builder FROM eclipse-temurin:${JAVA_VERSION}-jdk-alpine AS builder
ARG VERSION ARG VERSION
ARG BUILD_DATE ARG BUILD_DATE
@@ -32,8 +33,7 @@ ENV GRADLE_OPTS="-Dorg.gradle.caching=true \
-Dorg.gradle.jvmargs=-Xmx2g \ -Dorg.gradle.jvmargs=-Xmx2g \
-XX:+UseParallelGC \ -XX:+UseParallelGC \
-XX:MaxMetaspaceSize=512m" -XX:MaxMetaspaceSize=512m"
ENV GRADLE_USER_HOME=/root/.gradle
ENV GRADLE_USER_HOME=/home/gradle/.gradle
# Copy gradle wrapper and configuration files # Copy gradle wrapper and configuration files
COPY gradlew gradlew.bat gradle.properties settings.gradle.kts ./ COPY gradlew gradlew.bat gradle.properties settings.gradle.kts ./
@@ -60,25 +60,32 @@ RUN mkdir -p \
frontend/core/network \ frontend/core/network \
frontend/core/local-db \ frontend/core/local-db \
frontend/core/sync \ frontend/core/sync \
frontend/features/ping-feature \
frontend/features/nennung-feature \
frontend/shared \ frontend/shared \
frontend/shells/meldestelle-portal \ frontend/shells/meldestelle-portal \
frontend/shells/meldestelle-desktop \ frontend/shells/meldestelle-desktop \
frontend/features/ping-feature \
frontend/features/nennung-feature \
frontend/features/zns-import-feature \ frontend/features/zns-import-feature \
frontend/features/billing-feature \
frontend/features/pferde-feature \
frontend/features/verein-feature \
frontend/features/veranstaltung-feature \
frontend/features/veranstalter-feature \
frontend/features/profile-feature \
frontend/features/reiter-feature \
frontend/features/turnier-feature \
docs docs
# Copy root build configuration # Copy root build configuration
COPY build.gradle.kts ./ COPY build.gradle.kts ./
# Download and cache dependencies # Download and cache dependencies
RUN --mount=type=cache,id=gradle-cache-gateway,target=/home/gradle/.gradle/caches \ RUN --mount=type=cache,id=gradle-cache-gateway,target=/root/.gradle/caches \
--mount=type=cache,id=gradle-wrapper-gateway,target=/home/gradle/.gradle/wrapper \ --mount=type=cache,id=gradle-wrapper-gateway,target=/root/.gradle/wrapper \
./gradlew :backend:infrastructure:gateway:dependencies --info ./gradlew :backend:infrastructure:gateway:dependencies --info
# Build the application # Build the application
RUN --mount=type=cache,id=gradle-cache-gateway,target=/home/gradle/.gradle/caches \ RUN --mount=type=cache,id=gradle-cache-gateway,target=/root/.gradle/caches \
--mount=type=cache,id=gradle-wrapper-gateway,target=/home/gradle/.gradle/wrapper \ --mount=type=cache,id=gradle-wrapper-gateway,target=/root/.gradle/wrapper \
./gradlew :backend:infrastructure:gateway:bootJar --info ./gradlew :backend:infrastructure:gateway:bootJar --info
# Extract JAR layers # Extract JAR layers
+17 -9
View File
@@ -5,15 +5,16 @@
# =================================================================== # ===================================================================
# === CENTRALIZED BUILD ARGUMENTS === # === CENTRALIZED BUILD ARGUMENTS ===
ARG GRADLE_VERSION=9.3.1 # HINWEIS: gradle:X.Y-jdkZ-alpine Images existieren nicht für alle Gradle/JDK-Kombinationen.
ARG JAVA_VERSION=25 # Wir verwenden eclipse-temurin als Builder-Basis und das Projekt-eigene ./gradlew-Wrapper.
ARG JAVA_VERSION=21
ARG BUILD_DATE ARG BUILD_DATE
ARG VERSION ARG VERSION
# =================================================================== # ===================================================================
# Build Stage # Build Stage
# =================================================================== # ===================================================================
FROM gradle:${GRADLE_VERSION}-jdk${JAVA_VERSION}-alpine AS builder FROM eclipse-temurin:${JAVA_VERSION}-jdk-alpine AS builder
ARG VERSION ARG VERSION
ARG BUILD_DATE ARG BUILD_DATE
@@ -33,7 +34,7 @@ ENV GRADLE_OPTS="-Dorg.gradle.caching=true \
-XX:+UseParallelGC \ -XX:+UseParallelGC \
-XX:MaxMetaspaceSize=512m" -XX:MaxMetaspaceSize=512m"
ENV GRADLE_USER_HOME=/home/gradle/.gradle ENV GRADLE_USER_HOME=/root/.gradle
# Copy gradle wrapper and configuration files # Copy gradle wrapper and configuration files
COPY gradlew gradlew.bat gradle.properties settings.gradle.kts ./ COPY gradlew gradlew.bat gradle.properties settings.gradle.kts ./
@@ -64,19 +65,26 @@ RUN mkdir -p \
frontend/shells/meldestelle-portal \ frontend/shells/meldestelle-portal \
frontend/shells/meldestelle-desktop \ frontend/shells/meldestelle-desktop \
frontend/features/zns-import-feature \ frontend/features/zns-import-feature \
frontend/features/veranstalter-feature \
frontend/features/veranstaltung-feature \
frontend/features/profile-feature \
frontend/features/reiter-feature \
frontend/features/pferde-feature \
frontend/features/verein-feature \
frontend/features/turnier-feature \
frontend/features/billing-feature \
docs docs
# Copy root build configuration # Copy root build configuration
COPY build.gradle.kts ./ COPY build.gradle.kts ./
# Download and cache dependencies # Download and cache dependencies
RUN --mount=type=cache,id=gradle-cache-ping,target=/home/gradle/.gradle/caches \ RUN --mount=type=cache,id=gradle-cache-ping,target=/root/.gradle/caches \
--mount=type=cache,id=gradle-wrapper-ping,target=/home/gradle/.gradle/wrapper \ --mount=type=cache,id=gradle-wrapper-ping,target=/root/.gradle/wrapper \
./gradlew :backend:services:ping:ping-service:dependencies --no-daemon --info ./gradlew :backend:services:ping:ping-service:dependencies --no-daemon --info
# Build the application # Build the application
RUN --mount=type=cache,id=gradle-cache-ping,target=/home/gradle/.gradle/caches \ RUN --mount=type=cache,id=gradle-cache-ping,target=/root/.gradle/caches \
--mount=type=cache,id=gradle-wrapper-ping,target=/home/gradle/.gradle/wrapper \ --mount=type=cache,id=gradle-wrapper-ping,target=/root/.gradle/wrapper \
./gradlew :backend:services:ping:ping-service:bootJar --no-daemon --info ./gradlew :backend:services:ping:ping-service:bootJar --no-daemon --info
# =================================================================== # ===================================================================
@@ -20,6 +20,7 @@ dependencies {
implementation(libs.spring.boot.starter.web) implementation(libs.spring.boot.starter.web)
implementation(libs.spring.boot.starter.validation) implementation(libs.spring.boot.starter.validation)
implementation(libs.spring.boot.starter.actuator) implementation(libs.spring.boot.starter.actuator)
implementation(libs.spring.cloud.starter.consul.discovery)
implementation(libs.exposed.core) implementation(libs.exposed.core)
implementation(libs.exposed.dao) implementation(libs.exposed.dao)
@@ -20,7 +20,17 @@ spring:
exclude: exclude:
- org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
cloud:
consul:
host: ${SPRING_CLOUD_CONSUL_HOST:localhost}
port: ${SPRING_CLOUD_CONSUL_PORT:8500}
enabled: ${CONSUL_ENABLED:true}
discovery:
enabled: ${CONSUL_ENABLED:true}
register: ${CONSUL_ENABLED:true}
health-check-path: /actuator/health
health-check-interval: 10s
instance-id: ${spring.application.name}-${server.port}-${random.uuid}
management: management:
endpoints: endpoints:
web: web:
+14
View File
@@ -0,0 +1,14 @@
{
"Servers": {
"1": {
"Name": "Meldestelle PostgreSQL",
"Group": "Meldestelle",
"Host": "postgres",
"Port": 5432,
"MaintenanceDB": "pg-meldestelle-db",
"Username": "pg-user",
"SSLMode": "prefer",
"Comment": "Haupt-Datenbank für die Meldestelle-Applikation"
}
}
}
+1
View File
@@ -35,6 +35,7 @@ services:
PGADMIN_DEFAULT_PASSWORD: "${PGADMIN_PASSWORD:-pgadmin}" PGADMIN_DEFAULT_PASSWORD: "${PGADMIN_PASSWORD:-pgadmin}"
volumes: volumes:
- "pgadmin-data:/var/lib/pgadmin" - "pgadmin-data:/var/lib/pgadmin"
- "./config/docker/pgadmin/servers.json:/pgadmin4/servers.json:ro"
healthcheck: healthcheck:
test: [ "CMD", "wget", "--spider", "-q", "http://localhost:80/" ] test: [ "CMD", "wget", "--spider", "-q", "http://localhost:80/" ]
interval: 30s interval: 30s
@@ -0,0 +1,56 @@
# 🏗️ [Lead Architect] — Zwischenbericht zur Besprechung vom 3. April 2026
> **Datum:** 3. April 2026, ca. 13:00 Uhr
> **Rolle:** Strategie, Architektur-Entscheidungen (ADRs), Domänen-Modell, Master-Roadmap
---
## ✅ Was wurde erreicht?
### Sprint A — vollständig abgeschlossen
- **ADR-0021 (Tenant-Resolution):** Die zentrale Architektur-Entscheidung wurde getroffen: **Eine Veranstaltung = eine
Datenbank**. Die Analyse zwischen Schema-per-Tenant und Tenant-ID ist abgeschlossen. Das ADR liegt in
`docs/01_Architecture/adr/0021-tenant-resolution-strategy-de.md`.
- **Domänen-Modell formal präzisiert:** Die Hierarchie `Veranstaltung → Turnier → Bewerb → Abteilung` ist
festgeschrieben. `TeilnehmerKonto` auf Veranstaltungsebene (Multi-Turnier), Veranstaltungs-Kassa mit
turnier-übergreifendem Saldo und die Abteilungs-Typen `SEPARATE_SIEGEREHRUNG` / `ORGANISATORISCH` sind modelliert.
### Sprint B — vollständig abgeschlossen
- **ADR-0022 (LAN-Sync-Protokoll):** Entscheidung für **Event-Sourcing Light mit Lamport-Uhren** (Option D) getroffen.
Optionen (Event-Sourcing, CRDT, Timestamp-Sync) wurden analysiert. ADR liegt in
`docs/01_Architecture/adr/0022-lan-sync-protocol-de.md`. Backend und Frontend wurden informiert — C-3 (LAN-Sync) bei
beiden freigegeben.
---
## 🔄 Was ist noch offen?
### Sprint C — nächste Woche (Priorität 2)
- **C-1 Synchronisations-Protokoll-Konzeption:** Offline-First-Konzept für Desktop ↔ Backend ausarbeiten,
Conflict-Resolution-Strategie definieren, Konzept-Dokument ablegen.
- **C-2 MASTER_ROADMAP aktualisieren:** Desktop-App-Fokus eintragen, Sprint A/B Ergebnisse als erledigt markieren,
Offline-Sync-Meilensteine eintragen, Phase-8-Fortschritt reflektieren.
---
## 🔗 Abhängigkeiten & Auswirkungen
| Meine Aufgabe | Blockiert wen |
|--------------------|--------------------------------------------------------------|
| ADR-0021 ✅ | 👷 Backend: Tenant-Isolation (abgeschlossen) |
| Domänen-Modell ✅ | 👷 Backend: Schema-Design; 🎨 Frontend: ViewModel-Design |
| ADR-0022 ✅ | 🎨 Frontend C-3, 👷 Backend C-3, 🐧 DevOps D-2 (freigegeben) |
| Sync-Konzept (C-1) | 🐧 DevOps: mDNS/WebSocket-Infrastruktur |
---
## 💬 Botschaft an die Runde
Die zwei wichtigsten Architektur-Fundamente sind gesetzt: **Tenant-Isolation** (ADR-0021) und **LAN-Sync-Protokoll** (
ADR-0022). Das Team kann auf diesen Entscheidungen aufbauen — Backend und Frontend haben ihre C-3-Aufgaben (
LAN-Sync-Implementierung) bereits in der Roadmap. Die nächste dringende Aufgabe ist das konkrete *
*Offline-First-Konzept (C-1)** und die Aktualisierung der **MASTER_ROADMAP (C-2)**, damit alle Teams einen aktuellen
Überblick haben.
@@ -0,0 +1,69 @@
# 👷 [Backend Developer] — Zwischenbericht zur Besprechung vom 3. April 2026
> **Datum:** 3. April 2026, ca. 13:00 Uhr
> **Rolle:** Spring Boot / Ktor, Kotlin, SQL, API-Design, Datenbankschema, Services
---
## ✅ Was wurde erreicht?
### Sprint A — weitgehend abgeschlossen
- **Datenbankschema (A-2):** Tabellen `veranstaltungen`, `turniere`, `bewerbe`, `abteilungen`, `teilnehmer_konten`,
`turnier_kassa` mit FK-Ketten implementiert. Flyway-Migrationen V1V3 laufen durch. `DomainHierarchyMigrationTest` ist
grün.
- **Tenant-Isolation (A-1):** ADR-0021 vollständig umgesetzt. `TenantWebFilter`, `TenantRegistry` (JDBC),
`JdbcTenantRegistry`, `TenantMigrationsRunner` und MDC-Logging implementiert. Flyway pro Tenant-Schema. Alle
Unit-Tests (`JdbcTenantRegistryTest`) grün. E2E-Isolationstest (`EntriesIsolationIntegrationTest`) wieder aktiv und
grün. Kritischer Bugfix: `springdoc` 3.0.0 → 2.8.9 (ClassNotFoundException behoben).
- **Validierungs-Grundlage (A-3 teilweise):** Entkoppelte Policy-Schnittstelle + Bewerb-Descriptor implementiert.
Konkrete ÖTO-Regeln/Limits als Policy-Implementierung umgesetzt.
### Sprint B (teilweise) — CRUD vollständig
- **CRUD-Endpunkte (B-1):** Alle Kern-Entitäten vollständig implementiert:
- `Veranstaltung`: GET, PUT
- `Turniere`: POST, GET, GET{id}, PUT, DELETE, PATCH /status
- `Bewerbe`, `Abteilungen`: vollständige CRUD-Endpunkte
- `Reiter`, `Pferde`, `Vereine`, `Funktionäre`: vollständige CRUD inkl. Filter-Parameter
- Konsistentes Error-Format (`problem+json`), Service-Guardrails für `PUBLISHED`-Lock
- **Regulation-as-Data (via Rulebook B-2):** `LizenzKlasseE`-Enum mit `R4` ergänzt, `RD4`-Fehler korrigiert. Flyway
V009: `license_height_matrix` + `horse_min_age_matrix` angelegt und befüllt. FEI Legacy→Numeric Resolver
implementiert (`/api/fei/resolve/{id}`).
---
## 🔄 Was ist noch offen?
### Sprint A — Restpunkt
- **A-3 Sonderregeln:** Einarbeitung der Rulebook-B-2-Spezifikation (wartet auf finale Übergabe).
### Sprint B — offen
- **B-1 Rest:** OpenAPI-Dokumentation (Springdoc) noch ausstehend. E2E-Tests für CRUD-Flows.
- **B-2 Kassa-Service:** `TeilnehmerKonto`-Service, `Zahlvorgang`-Service, Rechnungs-Generierung und Endpunkte noch
nicht implementiert.
- **B-3 ÖTO-Validierung serverseitig:** OEPS/FEI-Formate, Lizenzklassen, Altersklassen, CSN-C-NEU-Zwangsteilung — wartet
auf Rulebook-Spezifikation.
### Sprint C — geplant
- **C-1 Nennungs-Service**, **C-2 Stammdaten-Seeder**, **C-3 LAN-Sync-Endpunkte** (ADR-0022 ✅ freigegeben).
---
## 🔗 Abhängigkeiten
| Warte auf | Von wem | Betrifft |
|----------------------------|-------------|----------|
| Rulebook B-2 Spezifikation | 📜 Rulebook | A-3, B-3 |
---
## 💬 Botschaft an die Runde
Das Backend hat eine solide Grundlage: Tenant-Isolation läuft, alle CRUD-Endpunkte für Stammdaten sind fertig, das
Datenbankschema ist vollständig. Der nächste große Block ist der **Kassa-Service (B-2)** — der ist noch komplett offen.
Die **ÖTO-Validierung (B-3)** wartet auf die finale Rulebook-Übergabe. Sobald das Rulebook-Team B-2 abschließt, kann das
Backend sofort mit A-3 und B-3 starten.
@@ -0,0 +1,68 @@
# 🧹 [Curator] — Zwischenbericht zur Besprechung vom 3. April 2026
> **Datum:** 3. April 2026, ca. 13:00 Uhr
> **Rolle:** Dokumentation, Session-Logs, Ubiquitous Language, Ordnung in `docs/`
---
## ✅ Was wurde erreicht?
### Sprint A — vollständig abgeschlossen
- **A-1 `Ubiquitous_Language.md` aktualisiert** — nach Domänen-Modell-Präzisierung durch den Architect.
- **A-2 Event-First-Workflow dokumentiert** → `docs/02_Guides/Event-First-Workflow.md`
- **A-3 Navigation-V3 dokumentiert** → `docs/06_Frontend/Navigation_V3_Screen-Baum_und_Back-Stack.md`
- **A-4 Tenant-Konzept dokumentiert** →
`docs/01_Architecture/Reference/Tenant-Konzept_Eine-Veranstaltung-eine-Datenbank.md`
- **A-5 Session-Log Besprechung 02.04.2026** → `docs/99_Journal/2026-04-02_Meldestelle_Besprechung_Session-Log.md`
### Sprint B — weitgehend abgeschlossen
- **B-0 Rulebook-Session dokumentiert** → `docs/99_Journal/2026-04-03_Rulebook_B1_Validierung_Frontend.md`
- **B-1 Roadmaps vollständig gepflegt (03.04.2026):**
- Architect-Roadmap: Sprint B (ADR-0022) als ✅ abgeschlossen eingetragen
- Backend-Roadmap: C-3 LAN-Sync als freigegeben markiert
- Frontend-Roadmap: C-3 LAN-Sync als freigegeben markiert
- DevOps-Roadmap: vollständig und korrekt ✅
- UIUX-Roadmap: vollständig und korrekt ✅
- Rulebook-Roadmap: vollständig und korrekt ✅
- QA-Roadmap: Sprint-B-Header korrigiert (🔴 → 🟡 Teilweise offen) ✅
- Alle Roadmaps: abgeschlossene Aufgaben als `[x]` markiert ✅
- **Architect B-1 Session-Log erstellt** → `docs/99_Journal/2026-04-03_Architect_B1_LAN-Sync_ADR-0022.md`
---
## 🔄 Was ist noch offen?
### Sprint B — offen
- **B-2 `docs/05_Backend/` aktualisieren:** Datenbankschema (Tabellen V1V009), API-Endpunkte-Übersicht (Reiter, Pferde,
Vereine, Funktionäre), Tenant-Isolation beschreiben. Kassa-Endpunkte sobald Backend B-2 fertig.
- **B-3 `docs/06_Frontend/` aktualisieren:** ViewModel-Architektur-Muster verlinken, `VeranstalterViewModel` als
Referenz eintragen.
### Sprint C — geplant (nächste Woche)
- **C-1** `README.md` aktualisieren (Desktop-App-Fokus, Schnellstart, V1-Altlasten)
- **C-2** Setup-Guide erstellen (`docs/02_Guides/`)
- **C-3** Unterordner-Struktur in `docs/` prüfen und mit Architect abstimmen
- **C-4** V1-Code-Bereinigung koordinieren (gemeinsam mit Frontend + Backend)
- **C-5** Sprint-Reports archivieren in `docs/90_Reports/`
---
## 🔗 Abhängigkeiten
| Warte auf | Von wem | Betrifft |
|---------------------------|------------|--------------------------|
| Backend B-2 Kassa-Service | 👷 Backend | B-2 Kassa-Endpunkte-Doku |
---
## 💬 Botschaft an die Runde
Die Dokumentations-Basis ist solide: Session-Logs, Ubiquitous Language, alle Roadmaps und zentrale Architektur-Dokumente
sind aktuell. Die **Besprechungs-Berichte von heute** (dieses Dokument und alle Schwester-Berichte) wurden in
`docs/04_Agents/Besprechung_2026-04-03/Berichte/` abgelegt. Der dringendste offene Punkt ist **B-2** — die
Backend-Dokumentation (Datenbankschema + API-Übersicht) ist bereit zum Erstellen, da Backend B-1 abgeschlossen ist. Das
`README.md` ist veraltet und sollte bald auf Desktop-App-Fokus aktualisiert werden.
@@ -0,0 +1,69 @@
# 🐧 [DevOps Engineer] — Zwischenbericht zur Besprechung vom 3. April 2026
> **Datum:** 3. April 2026, ca. 13:00 Uhr
> **Rolle:** Docker, CI/CD, Gradle, Security, Desktop-Packaging, Infrastruktur
---
## ✅ Was wurde erreicht?
### Sprint A — vollständig abgeschlossen
- **Docker-Compose-Setup (A-1):** Alle Services in `docker-compose.yaml` / `dc-*.yaml` geprüft. Lokale
Entwicklungsumgebung startet mit einem einzigen Befehl. Healthchecks für alle Services definiert.
### Sprint B — vollständig abgeschlossen
- **CI/CD Pipeline für Compose Desktop Tests (B-1):** Gitea Actions Workflow `.gitea/workflows/desktop-tests.yml`
angelegt. Headless-Umgebung mit `xvfb-run` (1920×1080×24). Gradle-Task `:frontend:shells:meldestelle-desktop:jvmTest`
integriert. Build-Artefakte werden gespeichert.
- **Gradle-Build-Optimierungen (B-2):** Build-Cache, Parallele Builds, Headless-Flag aktiv. Gradle Wrapper auf Version
`9.4.0` aktualisiert.
### Sprint C — weitgehend abgeschlossen
- **Desktop-App Packaging (C-1):** `compose.desktop.nativeDistributions` vollständig konfiguriert für Linux (`.deb`),
Windows (`.msi`) und macOS (`.dmg`). App-Metadaten, eingebettetes JRE mit minimalem Footprint und JVM-Args für
gepackte App konfiguriert. Icon-Ressourcen-Verzeichnis mit `ICONS_PLACEHOLDER.md` angelegt.
- **Semantic Versioning (C-2):** Schema `MAJOR.MINOR.PATCH[-QUALIFIER]` definiert. Zentrale Versionsquelle
`version.properties` (aktuell `1.0.0-SNAPSHOT`). Root- und Desktop-`build.gradle.kts` lesen Version daraus.
Release-Workflow `.gitea/workflows/release.yml` mit Git-Tagging, Linux `.deb` und Windows `.msi` Build-Jobs angelegt.
`CHANGELOG.md` im Keep-a-Changelog-Format erstellt.
---
## 🔄 Was ist noch offen?
### Sprint C — Restpunkte
- **C-1 Offene Punkte:** Echte Icon-Dateien (`icon.png`, `icon.ico`, `icon.icns`) fehlen noch — wartet auf 🖌️ UI/UX.
Testinstallation auf Ziel-Betriebssystem steht noch aus.
- **C-3 Produktions-Deployment:** Reverse-Proxy (Nginx/Traefik), HTTPS-Zertifikat-Management, Backup-Strategie für
Produktionsdatenbanken.
### Sprint D — geplant (nächste Woche)
- **D-1 Multi-Tenant Datenbankinfrastruktur:** Pro-Tenant-Schema in Postgres absichern, Monitoring in Grafana,
Pro-Tenant-Backup-Strategie.
- **D-2 mDNS / LAN-Discovery Infrastruktur (ADR-0022 ✅):** Avahi-Dienst in Docker-Compose, WebSocket-Endpunkt in
Nginx/Traefik durchreichen.
> ⏸️ **Pangolin / externer Zugriff** — kein MVP-Blocker, zurückgestellt.
---
## 🔗 Abhängigkeiten
| Warte auf | Von wem | Betrifft |
|-----------------------------|-----------|---------------------|
| Icon-Dateien (PNG/ICO/ICNS) | 🖌️ UI/UX | C-1 Release-Build |
| QA: Test-Integration in CI | 🧐 QA C-4 | C-1 Packaging-Tests |
---
## 💬 Botschaft an die Runde
Die Infrastruktur läuft stabil: Docker-Compose, CI/CD-Pipeline und Gradle-Optimierungen sind fertig. Das *
*Desktop-Packaging ist vollständig konfiguriert** — wir können theoretisch schon `.deb`- und `.msi`-Installer bauen. Der
einzige Blocker für den ersten echten Release-Build sind die **App-Icons** vom UI/UX-Team. Sobald die Icons vorliegen,
kann der Release-Workflow sofort laufen.
@@ -0,0 +1,72 @@
# 🎨 [Frontend Expert] — Zwischenbericht zur Besprechung vom 3. April 2026
> **Datum:** 3. April 2026, ca. 13:00 Uhr
> **Rolle:** KMP, Compose Desktop, State-Management, Navigation, Backend-Anbindung
---
## ✅ Was wurde erreicht?
### Sprint A — vollständig abgeschlossen
- **ViewModel-Architektur (A-1):** MVVM mit UDF als verbindliches Muster festgelegt. `Intent`/`State`-Struktur mit
Sealed Classes definiert. `VeranstalterViewModel` als vollständige Referenz-Implementierung. Muster-Dokument in
`docs/06_Frontend/` abgelegt.
- **Abteilungs-Logik im Bewerb-Dialog (A-2):** CSN-C-NEU Automatik-Teilung mit 4 Abteilungen, AssistChip
„Pflicht-Teilung vorgeschlagen", Abteilungs-Typen `SEPARATE_SIEGEREHRUNG` / `ORGANISATORISCH` in der UI verankert.
### Sprint B (teilweise) — ViewModels & Navigation vollständig
- **ViewModels für alle V3-Screens (B-1):** `TurnierViewModel`, `BewerbViewModel`, `PferdProfilViewModel`,
`ReiterProfilViewModel`, `VereinsViewModel`, `FunktionaerViewModel`, `AbteilungViewModel` (Startliste, Ergebnisse) —
alle fertig.
- **Zusätzlich erledigt (02.04.2026):** Navigation V2 / Back-Stack-System, Profil-Cards mit Edit-Dialogen (Veranstalter,
Pferd, Reiter, Verein, Funktionär), Onboarding mit `rememberSaveable`, Veranstaltungs-Wizard mit Bestätigungs-Dialog,
Breadcrumbs und Zurück-Navigation korrigiert.
- **Backend-Anbindung (B-2 teilweise):** `HttpClient`-Factory zentral konfiguriert. `VeranstalterRepository`,
`BewerbRepository`, `AbteilungRepository`, `DefaultTurnierRepository` implementiert. DTOs + Mapper in commonMain. Koin
Feature-Modul `turnierFeatureModule` verdrahtet. Fehler-Mapping HTTP → Domain-Errors einheitlich.
- **Validierungs-Live-Feedback (B-3 teilweise):** `MsValidationWrapper` vorhanden. OEPS-Nummer- und
FEI-ID-Live-Validierung in `ReiterProfilViewModel` und `PferdProfilViewModel`. Lizenzklasse-Validierung im
ReiterProfilViewModel. `ReiterProfilEditDialog` und `PferdProfilEditDialog` vollständig mit `MsValidationWrapper`
ausgestattet.
---
## 🔄 Was ist noch offen?
### Sprint B — offen (höchste Priorität)
- **B-2 Rest:** `AuthApiClient`-Integration, `StoreV2` Feature-für-Feature ablösen, Akzeptanz-Tests (Mock Engine),
Dokumentation `Networking.md`.
- **B-3 Rest:** Lizenzklasse × Bewerbs-Klasse Warnung, Altersklasse Pferd × Bewerb Warnung — benötigen Bewerb-Kontext
und Rulebook-Spezifikation.
- **B-4 Kassa-Screen:** Gesamt-Saldo-Ansicht, turnier-übergreifender Zahlvorgang, Rechnungsvorschau — wartet auf Backend
B-2 und UI/UX-Wireframes.
### Sprint C — geplant
- **C-1** `StoreV2` vollständig ablösen
- **C-2** VeranstalterNeu: Vereinssuche & Daten-Übernahme
- **C-3** LAN-Sync-UI vorbereiten (ADR-0022 ✅ freigegeben)
- **C-4** Lint-Bereinigung & Code-Qualität
---
## 🔗 Abhängigkeiten
| Warte auf | Von wem | Betrifft |
|-------------------------------------|-------------------|-----------------------------------|
| Rulebook Validierungs-Spezifikation | 📜 Rulebook B-2 | B-3 Bewerb-Kontext-Validierung |
| Kassa-Service API | 👷 Backend B-2 | B-4 Kassa-Screen |
| Wireframes Bewerb-Dialog / Kassa | 🖌️ UI/UX B-2/B-3 | B-4 Implementierung (✅ vorhanden) |
---
## 💬 Botschaft an die Runde
Die Desktop-App hat eine vollständige ViewModel-Schicht und Navigation. Die Backend-Anbindung ist in vollem Gange —
Repositories für alle Kern-Entitäten sind angelegt. Der größte offene Punkt ist die **`StoreV2`-Ablösung** und die
Live-Validierung mit **Bewerb-Kontext** (B-3). Der **Kassa-Screen (B-4)** kann erst starten, wenn das Backend den
Kassa-Service liefert. Die UI/UX-Wireframes für Kassa und Bewerb-Dialog sind bereits vorhanden und warten auf
Implementierung.
@@ -0,0 +1,73 @@
# 🧐 [QA Specialist] — Zwischenbericht zur Besprechung vom 3. April 2026
> **Datum:** 3. April 2026, ca. 13:00 Uhr
> **Rolle:** Test-Strategie, Edge-Cases, Integrationstests, Regressionssicherung
---
## ✅ Was wurde erreicht?
### Sprint A — vollständig abgeschlossen
- **Test-Strategie für Desktop-App (A-1):** Testpyramide für Compose Desktop festgelegt (Unit / Integration / UI-Tests).
Tooling entschieden: `kotlin.test`, Compose UI Test, Mockk. Test-Konventionen dokumentiert (Namensschema,
Ordnerstruktur, Arrange-Act-Assert). `IdempotencyPluginTest` stabilisiert. `OetoValidatorsTest.kt` als Basis für
Grenzfall-Abdeckung etabliert.
### Sprint B (teilweise) — zwei Test-Suiten abgeschlossen
- **Onboarding-Wizard Edge-Cases (B-2) ✅ — 3. April 2026:**
- Leere Pflichtfelder → Speichern-Button bleibt deaktiviert
- Schnelles Doppelklick → kein doppelter Submit
- Abbrechen mitten im Wizard → kein inkonsistenter Zustand
- Zurück-Navigation: Gerätename und Sicherheitsschlüssel bleiben erhalten (`rememberSaveable`)
- **Fix:** `remember``rememberSaveable` in `OnboardingScreen.kt`
- **Neu:** `OnboardingValidator`-Objekt extrahiert für isolierte Unit-Tests
- **17 Tests, alle GRÜN** (`OnboardingValidatorTest.kt`)
- **Abteilungs-Logik (B-3) ✅ — 3. April 2026:**
- CSN-C-NEU ≤95cm / ≥100cm: Pflicht-Teilungen korrekt vorgeschlagen
- `ORGANISATORISCH`: Gesamtrangliste korrekt zusammengeführt
- `SEPARATE_SIEGEREHRUNG`: Abteilungen werden nicht zusammengeführt
- Caprilli-Regression abgesichert, Grenzfälle 90 cm und 110 cm abgedeckt
- **Fix:** CSN-C-NEU-Logik in `AbteilungsRegelService.kt` implementiert
- **Neu:** `ORGANISATORISCH` + `SEPARATE_SIEGEREHRUNG` in `AbteilungsTeilungsTypE` ergänzt
- **14 neue Tests, alle GRÜN** (`AbteilungsRegelServiceTest.kt`)
---
## 🔄 Was ist noch offen?
### Sprint B — offen
- **B-1 Navigation & Back-Stack:** Navigations-Flows, Back-Stack-Verhalten, SingleTop-Tabs, Logout-Verhalten — noch
nicht begonnen.
- **B-2 Restpunkt:** Ungültige OEPS-Nummer → Fehlermeldung sichtbar (abhängig von Frontend C-3).
- **B-4 ViewModel-Verhalten:** State-Initialisierung, Intent → State-Transitionen, Fehler-State bei Backend-Fehler,
Loading-State — noch nicht begonnen.
### Sprint C — geplant
- **C-1** Mandanten-Isolation (sicherheitskritisch; wartet auf Backend A-1 Rollout)
- **C-2** Kassa und Zahlvorgang (wartet auf Backend B-2)
- **C-3** ÖTO-Validierung (wartet auf Rulebook C-1 `AltersklasseRechner`)
- **C-4** Regressions-Test-Suite & CI-Integration (gemeinsam mit 🐧 DevOps)
---
## 🔗 Abhängigkeiten
| Warte auf | Von wem | Betrifft |
|----------------------------------|---------------|------------------------|
| Rulebook C-1 AltersklasseRechner | 📜 Rulebook | C-3 Validierungs-Tests |
| Backend B-2 Kassa-Service | 👷 Backend | C-2 Kassa-Tests |
| DevOps CI/CD Pipeline | 🐧 DevOps C-1 | C-4 CI-Integration |
---
## 💬 Botschaft an die Runde
Zwei wichtige Test-Suiten wurden heute fertiggestellt: **Onboarding (17 Tests)** und **Abteilungs-Logik (14 Tests)**
beide komplett grün, inklusive zweier produktiver Bugfixes im Produktivcode. Die Test-Basis steht. Der nächste kritische
Schritt ist die **Mandanten-Isolation (C-1)** — sicherheitskritisch und sofort anzugehen, sobald Backend A-1 vollständig
ausgerollt ist.
@@ -0,0 +1,68 @@
# 📜 [ÖTO/FEI Rulebook Expert] — Zwischenbericht zur Besprechung vom 3. April 2026
> **Datum:** 3. April 2026, ca. 13:00 Uhr
> **Rolle:** Regelwerks-Wächter, Validierungs-Spezialist, Compliance (ÖTO, FEI)
---
## ✅ Was wurde erreicht?
### Sprint A — vollständig abgeschlossen
- **Validierungs-Spezifikation v0.3 DRAFT (A-1):** Paragraphen-Pins ergänzt (Springen § 231, Dressur § 103, CCN §§ 3xx).
Einheitliche Label-Konventionen definiert (`ohne Lizenz`, `mit Lizenz`, `R2 und höher`; Keys: `LZF_ONLY`, `R1_PLUS`,
`R1_ONLY`, `R2_PLUS`). Optionale Jugend-/Jahrgangsteilungen als Regulation-as-Data modelliert. CVN (Voltigieren) und
CAN (Fahren) als Fallback-Regelung dokumentiert.
- **Abteilungs-Schwellenwerte:** Dokument abgelegt in
`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` abgelegt.
- **`OetoValidators` (KMP) implementiert:** `OetoValidatorsTest.kt` ist grün.
### Sprint B (teilweise) — Frontend-Begleitung abgeschlossen
- **B-1 Frontend-Validierung begleitet:** Spezifikation v0.3 DRAFT an 🎨 Frontend übergeben. Implementierung geprüft —
Live-Validierung entspricht den Anforderungen. Fehlermeldungs-Texte geprüft. Session-Log dokumentiert.
- **B-2 Regulation-as-Data an Backend übergeben:**
- `LizenzKlasseE`-Enum mit `R4` ergänzt, `RD4`-Fehler in V008 korrigiert.
- Flyway V009: `license_height_matrix` + `horse_min_age_matrix` angelegt und befüllt.
- B-2-Übergabe-Spezifikation: `docs/03_Domain/02_Reference/OETO_Regelwerk/B2-Backend-Uebergabe-Regulation-as-Data.md`.
- `Validierungsregeln.md` auf Version 0.4 angehoben (`LZF``LIZENZFREI` korrigiert).
- FEI Legacy→Numeric Resolver in Masterdata-SCS implementiert.
---
## 🔄 Was ist noch offen?
### Sprint B — offen
- **B-2 Rest:** Serverseitige Validierung prüfen. Backend-Endpunkte `/api/regulation/*` noch ausstehend (liegt bei
Backend). Abweichungen Backend ↔ Frontend dokumentieren. Lizenz×Bewerb-Tabellen von DRAFT auf STABLE anheben (
Fachfreigabe erforderlich).
### Sprint C — geplant
- **C-1 `AltersklasseRechner`:** Altersklassen-Berechnung Pferd (Jahrgang → Kategorie), Grenzfälle (Geburtsjahr,
Jahreswechsel, Stichtag), Unit-Tests.
- **C-2 Regelwerk-Enums vervollständigen:** Lizenzklassen-Übergänge, FEI-Kategorien-Mapping, Enums in `core:domain` als
SSoT.
- **C-3 Compliance-Dokumentation:** Series-Context (Cups, Serien, Meisterschaften) vorbereiten.
---
## 🔗 Abhängigkeiten & Auswirkungen
| Meine Aufgabe | Blockiert wen |
|-------------------------|---------------------------------------------------|
| B-2 Spec an Backend ✅ | 👷 Backend: A-3 Sonderregeln, B-3 ÖTO-Validierung |
| B-1 Spec an Frontend ✅ | 🎨 Frontend: B-3 Live-Validierung |
| C-1 AltersklasseRechner | 🧐 QA: C-3 Validierungs-Tests |
---
## 💬 Botschaft an die Runde
Die fachliche Grundlage für Validierung steht: `OetoValidators` ist implementiert, die Lizenz-/Altersmatrix liegt als
Regulation-as-Data im Backend. Der kritische offene Punkt ist die **Fachfreigabe für Lizenz×Bewerb-Tabellen** (DRAFT →
STABLE) — ohne diese können Backend und Frontend nicht auf stabiler Basis arbeiten. Der **`AltersklasseRechner` (C-1)**
muss vor der Backend-Implementierung spezifiziert sein, da die Grenzfall-Logik komplex ist.
@@ -0,0 +1,78 @@
# 🖌️ [UI/UX Designer] — Zwischenbericht zur Besprechung vom 3. April 2026
> **Datum:** 3. April 2026, ca. 13:00 Uhr
> **Rolle:** High-Density Design, Wireframes, Usability, Design-System, Empty States
---
## ✅ Was wurde erreicht?
### Sprint A — vollständig abgeschlossen
- **Design-Inventur (A-1):** Alle vorhandenen V3-Screens katalogisiert (Screenshots in `docs/06_Frontend/Screenshots/`).
Inkonsistenzen in Spacing, Typografie und Farbgebung identifiziert. Offene UX-Probleme und fehlende Empty States
dokumentiert. Issue-Liste für Sprint B vorbereitet.
### Sprint B — vollständig abgeschlossen (3. April 2026)
- **Editier-Formulare: Dialog vs. Fullscreen (B-1 ✅):**
- Entscheidungsgrundlage erarbeitet: Wann AlertDialog, wann Fullscreen-Edit?
- Wireframes für beide Varianten erstellt (Reiter-Edit, Pferd-Edit als Beispiele)
- Mapping aller bestehenden Edit-Screens auf AlertDialog / Side Sheet / Fullscreen dokumentiert
- Finale Entscheidung als **verbindliche Design-Richtlinie festgeschrieben** (Status: APPROVED)
- Ergebnis: `docs/06_Frontend/Guidelines/Editier-Formulare_Dialog-vs-Fullscreen_v1.md`
- **Bewerb anlegen mit Abteilungs-Logik (B-2 ✅):**
- Dialog-Flow: Bewerb-Grunddaten → Abteilungs-Vorschlag → Bestätigung
- CSN-C-NEU Pflicht-Teilung visuell dargestellt
- Abteilungs-Typ-Auswahl (`SEPARATE_SIEGEREHRUNG` vs. `ORGANISATORISCH`) verständlich gestaltet
- Ergebnis: `docs/06_Frontend/Wireframes/Bewerb_anlegen_Abteilungs-Logik_v1.md`
- **Veranstaltungs-Kassa (B-3 ✅):**
- Gesamt-Saldo-Ansicht: Teilnehmer mit offenen Beträgen aus mehreren Turnieren
- Zahlvorgang-Dialog: Eine Zahlung, Aufteilung auf Turniere sichtbar
- Rechnungsvorschau: Zwei separate Rechnungen je Turnier als Tab
- Ergebnis: `docs/06_Frontend/Wireframes/Kassa_Veranstaltung_v1.md`
- **Empty States für alle Listenansichten (B-4 ✅):**
- Liste aller 10 Screens mit möglichen leeren Zuständen (3 Typen) erstellt
- Icon-Konzept: Material Symbols Outlined (kein Custom-Illustration-Set für MVP)
- Texte (Titel, Beschreibung, CTA) für alle Screens und Typen definiert
- Composable-API `MsEmptyState` spezifiziert (Ablageort, Parameter, Verhalten, Beispiel)
- Ergebnis: `docs/06_Frontend/Guidelines/Empty-States_Spezifikation_v1.md` (Status: APPROVED)
---
## 🔄 Was ist noch offen?
### Sprint C — geplant (nächste Woche)
- **C-1 Wireframes in Compose umsetzen:** Edit-Dialog/Fullscreen (B-1), Bewerb-Anlegen-Dialog (B-2), Kassa-Screen (B-3),
`MsEmptyState`-Composable implementieren, Empty States in alle 10 Listenansichten integrieren, `PferdProfilEditDialog`
zu Fullscreen migrieren.
- **C-2 Design-System konsolidieren:** Farb-Palette in `MaterialTheme` / `Theme.kt`, Typografie-Skala, wiederverwendbare
Composables (Cards, Badges, Chips).
- **C-3 Abteilungs-Ansicht:** Wireframes für Startliste, Ergebnisliste und Ranglisten-Zusammenführung (
`ORGANISATORISCH`).
> ⏸️ **Web-App / PWA Design** — Nach Desktop-MVP; Anforderungen noch nicht definiert.
---
## 🔗 Abhängigkeiten & Auswirkungen
| Meine Aufgabe | Blockiert wen |
|------------------------|------------------------------------------------|
| B-1 Richtlinie ✅ | 🎨 Frontend C-1: Edit-Dialoge implementieren |
| B-4 Spezifikation ✅ | 🎨 Frontend C-1: `MsEmptyState` implementieren |
| B-2 / B-3 Wireframes ✅ | 🎨 Frontend C-1: Bewerb-Dialog, Kassa-Screen |
| Icons (PNG/ICO/ICNS) | 🐧 DevOps C-1: Release-Build (noch ausstehend) |
---
## 💬 Botschaft an die Runde
Sprint B ist vollständig abgeschlossen — alle vier Punkte (B-1 bis B-4) sind **APPROVED** und an das Frontend-Team
übergeben. Die Spezifikationen und Wireframes liegen vor. Das Frontend kann sofort mit **`MsEmptyState` (C-1)** und der
**`PferdProfilEditDialog`-Migration** beginnen. Die **App-Icons** (PNG/ICO/ICNS) sind der einzige ausstehende
Design-Deliverable für den DevOps-Release-Build — diese müssen priorisiert werden.
@@ -0,0 +1,960 @@
# 🧪 Postman Tests — Vollständige Dokumentation
> **Stand:** 3. April 2026
> **Erstellt von:** 👷 Backend Developer & 🧐 QA Specialist
> **Collection-Datei:**
`backend/infrastructure/gateway/src/main/resources/static/docs/postman/Meldestelle_API_Collection.json`
---
## Inhaltsverzeichnis
1. [Setup & Variablen](#1-setup--variablen)
2. [Smoke-Tests: System & Health](#2-smoke-tests-system--health)
3. [Ping Service](#3-ping-service)
4. [Authentication Context](#4-authentication-context)
5. [Master Data: Countries](#5-master-data-countries)
6. [Horse Registry (Pferde)](#6-horse-registry-pferde)
7. [ZNS Import Service](#7-zns-import-service)
8. [Empfohlene Test-Reihenfolge](#8-empfohlene-test-reihenfolge)
---
## 1. Setup & Variablen
### Collection importieren
1. Postman öffnen → **Import** → Datei auswählen:
```
backend/infrastructure/gateway/src/main/resources/static/docs/postman/Meldestelle_API_Collection.json
```
2. Collection `Meldestelle API Collection` erscheint im linken Panel.
### Environment-Variablen anlegen
In Postman ein **Environment** `Meldestelle Local` anlegen mit folgenden Variablen:
| Variable | Initial Value | Beschreibung |
|-------------|-------------------------|------------------------------------|
| `baseUrl` | `http://localhost:8081` | API-Gateway (Haupt-Einstiegspunkt) |
| `pingUrl` | `http://localhost:8082` | Ping-Service direkt (ohne Gateway) |
| `znsUrl` | `http://localhost:8095` | ZNS-Import-Service direkt |
| `authToken` | *(leer, wird befüllt)* | JWT-Token nach Login |
| `horseId` | *(leer, wird befüllt)* | ID eines angelegten Pferdes |
| `countryId` | *(leer, wird befüllt)* | ID eines angelegten Landes |
| `horseId1` | *(leer)* | Für Batch-Delete Tests |
| `horseId2` | *(leer)* | Für Batch-Delete Tests |
> ⚠️ **Wichtig:** Sicherstellen dass alle Services laufen bevor Tests gestartet werden (siehe Betriebsanleitung).
---
## 2. Smoke-Tests: System & Health
> **Zweck:** Schnell prüfen ob das API-Gateway und alle Services erreichbar sind. Immer zuerst ausführen!
---
### 2.1 API Gateway Info
| Feld | Wert |
|-------------|----------------|
| **Methode** | `GET` |
| **URL** | `{{baseUrl}}/` |
| **Auth** | Keine |
**Erwartete Antwort:** `200 OK`
```json
{
"service": "Meldestelle API Gateway",
"version": "...",
"status": "running"
}
```
**Wozu:** Bestätigt dass das Gateway läuft und auf Anfragen antwortet.
---
### 2.2 Health Check (Gateway)
| Feld | Wert |
|-------------|----------------------|
| **Methode** | `GET` |
| **URL** | `{{baseUrl}}/health` |
| **Auth** | Keine |
**Erwartete Antwort:** `200 OK`
```json
{
"status": "UP"
}
```
---
### 2.3 API Documentation
| Feld | Wert |
|-------------|-------------------|
| **Methode** | `GET` |
| **URL** | `{{baseUrl}}/api` |
| **Auth** | Keine |
**Erwartete Antwort:** `200 OK` — OpenAPI JSON-Dokumentation
---
### 2.4 Swagger UI
| Feld | Wert |
|-------------|-----------------------|
| **Methode** | `GET` |
| **URL** | `{{baseUrl}}/swagger` |
| **Auth** | Keine |
**Erwartete Antwort:** `200 OK` — Swagger HTML-Interface
**Tipp:** Im Browser öffnen für interaktive API-Erkundung.
---
## 3. Ping Service
> **Zweck:** Funktionsfähigkeit des Ping-Service testen, Circuit Breaker und Sync-Funktionen validieren.
> **Direkt-URL:** `{{pingUrl}}` = `http://localhost:8082`
> **Via Gateway:** `{{baseUrl}}` = `http://localhost:8081`
---
### 3.1 Simple Ping
| Feld | Wert |
|-------------|---------------------------|
| **Methode** | `GET` |
| **URL** | `{{pingUrl}}/ping/simple` |
| **Auth** | Keine |
**Erwartete Antwort:** `200 OK`
```json
{
"message": "pong",
"timestamp": "2026-04-03T14:00:00+02:00",
"service": "ping-service",
"status": "simple"
}
```
**Wozu:** Einfachster Smoke-Test — bestätigt dass der Service läuft und die DB erreichbar ist.
---
### 3.2 Simple Ping via Gateway
| Feld | Wert |
|-------------|---------------------------|
| **Methode** | `GET` |
| **URL** | `{{baseUrl}}/ping/simple` |
| **Auth** | Keine |
**Erwartete Antwort:** `200 OK` (identisch wie 3.1)
**Wozu:** Bestätigt dass das Gateway den Ping-Service korrekt routet (Service Discovery via Consul).
---
### 3.3 Enhanced Ping (mit Circuit Breaker)
| Feld | Wert |
|-----------------|-----------------------------|
| **Methode** | `GET` |
| **URL** | `{{pingUrl}}/ping/enhanced` |
| **Auth** | Keine |
| **Query-Param** | `simulate=false` (Standard) |
**Erwartete Antwort:** `200 OK`
```json
{
"message": "enhanced pong",
"timestamp": "...",
"service": "ping-service",
"status": "enhanced",
"circuitBreakerStatus": "CLOSED"
}
```
**Wozu:** Bestätigt dass Resilience4j Circuit Breaker korrekt konfiguriert ist.
---
### 3.4 Enhanced Ping — Fehler simulieren
| Feld | Wert |
|-------------|-------------------------------------------|
| **Methode** | `GET` |
| **URL** | `{{pingUrl}}/ping/enhanced?simulate=true` |
| **Auth** | Keine |
**Erwartete Antwort:** `200 OK` mit Fallback-Response (kein 500-Fehler!)
```json
{
"message": "fallback response",
"status": "fallback",
"circuitBreakerStatus": "OPEN",
"error": "..."
}
```
**Wozu:** Bestätigt dass der Circuit Breaker Fallback greift (60% simulierte Fehlerrate). Der Service antwortet trotz
Fehler mit einem sinnvollen Fallback.
**Mehrfach ausführen:** Nach ~5 Anfragen mit `simulate=true` öffnet der Circuit Breaker.
---
### 3.5 Public Ping (kein Auth erforderlich)
| Feld | Wert |
|-------------|---------------------------|
| **Methode** | `GET` |
| **URL** | `{{pingUrl}}/ping/public` |
| **Auth** | Keine |
**Erwartete Antwort:** `200 OK`
**Wozu:** Bestätigt dass der `/ping/public`-Endpunkt ohne JWT-Token erreichbar ist (Security-Konfiguration).
---
### 3.6 Secure Ping (Auth erforderlich)
| Feld | Wert |
|-------------|---------------------------------------|
| **Methode** | `GET` |
| **URL** | `{{pingUrl}}/ping/secure` |
| **Header** | `Authorization: Bearer {{authToken}}` |
**Mit gültigem Token:** `200 OK`
**Ohne Token:** `401 Unauthorized`
**Wozu:** Bestätigt dass JWT-Authentifizierung korrekt erzwungen wird.
---
### 3.7 Sync Pings (seit Timestamp)
| Feld | Wert |
|-----------------|-----------------------------------|
| **Methode** | `GET` |
| **URL** | `{{pingUrl}}/ping/sync` |
| **Auth** | Keine |
| **Query-Param** | `since=0` (alle Pings seit Epoch) |
**Erwartete Antwort:** `200 OK`
```json
[
{
"id": "...",
"message": "pong",
"timestamp": "...",
"lamportClock": 1
}
]
```
**Wozu:** Testet den LAN-Sync-Endpunkt (Lamport-Uhren, Event-Sourcing Light). `since` ist ein Unix-Timestamp in
Millisekunden.
---
### 3.8 Ping Service Health
| Feld | Wert |
|-------------|---------------------------|
| **Methode** | `GET` |
| **URL** | `{{pingUrl}}/ping/health` |
| **Auth** | Keine |
**Erwartete Antwort:** `200 OK`
```json
{
"status": "up",
"timestamp": "...",
"service": "ping-service",
"healthy": true
}
```
---
## 4. Authentication Context
> **Zweck:** Benutzer-Registrierung, Login und Profilverwaltung über Keycloak testen.
> **Reihenfolge:** Zuerst registrieren → dann einloggen → Token in `{{authToken}}` speichern.
---
### 4.1 User Registration
| Feld | Wert |
|-------------|----------------------------------|
| **Methode** | `POST` |
| **URL** | `{{baseUrl}}/auth/register` |
| **Header** | `Content-Type: application/json` |
**Request Body:**
```json
{
"email": "test@example.com",
"password": "SecurePassword123!",
"firstName": "Test",
"lastName": "User",
"phoneNumber": "+43123456789"
}
```
**Erwartete Antwort:** `201 Created`
```json
{
"userId": "uuid-...",
"email": "test@example.com",
"message": "Registrierung erfolgreich"
}
```
**Wozu:** Legt einen neuen Benutzer in Keycloak an.
---
### 4.2 User Login
| Feld | Wert |
|-------------|----------------------------------|
| **Methode** | `POST` |
| **URL** | `{{baseUrl}}/auth/login` |
| **Header** | `Content-Type: application/json` |
**Request Body:**
```json
{
"email": "test@example.com",
"password": "SecurePassword123!"
}
```
**Erwartete Antwort:** `200 OK`
```json
{
"accessToken": "eyJhbGci...",
"refreshToken": "...",
"expiresIn": 300
}
```
> **⚡ Tipp:** Postman-Test-Script einfügen um Token automatisch zu speichern:
> ```javascript
> var json = pm.response.json();
> pm.environment.set("authToken", json.accessToken);
> ```
---
### 4.3 Get User Profile
| Feld | Wert |
|-------------|---------------------------------------|
| **Methode** | `GET` |
| **URL** | `{{baseUrl}}/auth/profile` |
| **Header** | `Authorization: Bearer {{authToken}}` |
**Erwartete Antwort:** `200 OK`
```json
{
"userId": "...",
"email": "test@example.com",
"firstName": "Test",
"lastName": "User"
}
```
---
### 4.4 Update User Profile
| Feld | Wert |
|-------------|---------------------------------------|
| **Methode** | `PUT` |
| **URL** | `{{baseUrl}}/auth/profile` |
| **Header** | `Content-Type: application/json` |
| **Header** | `Authorization: Bearer {{authToken}}` |
**Request Body:**
```json
{
"firstName": "Updated",
"lastName": "User",
"phoneNumber": "+43987654321"
}
```
**Erwartete Antwort:** `200 OK` — aktualisierte Profildaten
---
### 4.5 Change Password
| Feld | Wert |
|-------------|---------------------------------------|
| **Methode** | `POST` |
| **URL** | `{{baseUrl}}/auth/change-password` |
| **Header** | `Content-Type: application/json` |
| **Header** | `Authorization: Bearer {{authToken}}` |
**Request Body:**
```json
{
"currentPassword": "SecurePassword123!",
"newPassword": "NewSecurePassword456!"
}
```
**Erwartete Antwort:** `200 OK`
**Fehlerfall (falsches Passwort):** `400 Bad Request`
---
## 5. Master Data: Countries
> **Zweck:** Länderstammdaten verwalten. Diese sind Voraussetzung für Pferde- und Reiter-Datensätze.
> **Basis-URL:** `{{baseUrl}}/api/masterdata/countries`
> **Hinweis:** GET-Endpunkte sind ohne Auth zugänglich; POST/PUT/DELETE benötigen `{{authToken}}`.
---
### 5.1 Get All Countries
| Feld | Wert |
|-------------|----------------------------------------|
| **Methode** | `GET` |
| **URL** | `{{baseUrl}}/api/masterdata/countries` |
| **Auth** | Keine |
**Erwartete Antwort:** `200 OK` — Array aller Länder (inkl. inaktive)
---
### 5.2 Get Active Countries
| Feld | Wert |
|-------------|-----------------------------------------------|
| **Methode** | `GET` |
| **URL** | `{{baseUrl}}/api/masterdata/countries/active` |
| **Auth** | Keine |
**Erwartete Antwort:** `200 OK` — Nur Länder mit `istAktiv: true`
**Wozu:** Für Dropdown-Listen in der Desktop-App (nur aktive Länder anzeigen).
---
### 5.3 Get Country by ID
| Feld | Wert |
|-------------|------------------------------------------------------|
| **Methode** | `GET` |
| **URL** | `{{baseUrl}}/api/masterdata/countries/{{countryId}}` |
| **Auth** | Keine |
**Erwartete Antwort:** `200 OK` — Einzelnes Land
**Fehlerfall:** `404 Not Found`
---
### 5.4 Get Country by ISO Code
| Feld | Wert |
|-------------|-----------------------------------------------|
| **Methode** | `GET` |
| **URL** | `{{baseUrl}}/api/masterdata/countries/iso/AT` |
| **Auth** | Keine |
**Erwartete Antwort:** `200 OK`
```json
{
"id": "...",
"isoAlpha2Code": "AT",
"nameDeutsch": "Österreich",
"istEuMitglied": true,
"istAktiv": true
}
```
**Wozu:** Österreich ist das primäre Land — dieser Test prüft ob die Stammdaten korrekt befüllt sind.
---
### 5.5 Create Country
| Feld | Wert |
|-------------|----------------------------------------|
| **Methode** | `POST` |
| **URL** | `{{baseUrl}}/api/masterdata/countries` |
| **Header** | `Content-Type: application/json` |
| **Header** | `Authorization: Bearer {{authToken}}` |
**Request Body:**
```json
{
"isoAlpha2Code": "TS",
"isoAlpha3Code": "TST",
"isoNumerischerCode": "999",
"nameDeutsch": "Testland",
"nameEnglisch": "Testland",
"istEuMitglied": false,
"istEwrMitglied": false,
"istAktiv": true,
"sortierReihenfolge": 999
}
```
**Erwartete Antwort:** `201 Created`
> **⚡ Tipp:** `countryId` aus der Antwort in Environment-Variable speichern:
> ```javascript
> var json = pm.response.json();
> pm.environment.set("countryId", json.id);
> ```
---
### 5.6 Update Country
| Feld | Wert |
|-------------|------------------------------------------------------|
| **Methode** | `PUT` |
| **URL** | `{{baseUrl}}/api/masterdata/countries/{{countryId}}` |
| **Header** | `Content-Type: application/json` |
| **Header** | `Authorization: Bearer {{authToken}}` |
**Request Body:**
```json
{
"isoAlpha2Code": "TS",
"isoAlpha3Code": "TST",
"isoNumerischerCode": "999",
"nameDeutsch": "Updated Testland",
"nameEnglisch": "Updated Testland",
"istEuMitglied": false,
"istEwrMitglied": false,
"istAktiv": true,
"sortierReihenfolge": 999
}
```
**Erwartete Antwort:** `200 OK`
---
### 5.7 Delete Country
| Feld | Wert |
|-------------|------------------------------------------------------|
| **Methode** | `DELETE` |
| **URL** | `{{baseUrl}}/api/masterdata/countries/{{countryId}}` |
| **Header** | `Authorization: Bearer {{authToken}}` |
**Erwartete Antwort:** `204 No Content`
**Fehlerfall (nicht gefunden):** `404 Not Found`
---
## 6. Horse Registry (Pferde)
> **Zweck:** Pferde-Stammdaten verwalten (CRUD).
> **⚠️ Hinweis Tabellen-Name:** In der Datenbank heißt die Tabelle `horse` (englisch), nicht `pferd`.
> **Basis-URL:** `{{baseUrl}}/api/horses`
---
### 6.1 Get All Horses
| Feld | Wert |
|-------------|---------------------------------------|
| **Methode** | `GET` |
| **URL** | `{{baseUrl}}/api/horses` |
| **Header** | `Authorization: Bearer {{authToken}}` |
**Erwartete Antwort:** `200 OK` — Array aller Pferde
**Nach ZNS-Import:** Hier erscheinen alle importierten Pferde.
---
### 6.2 Get Active Horses
| Feld | Wert |
|-------------|---------------------------------------|
| **Methode** | `GET` |
| **URL** | `{{baseUrl}}/api/horses/active` |
| **Header** | `Authorization: Bearer {{authToken}}` |
**Erwartete Antwort:** `200 OK` — Nur Pferde mit `istAktiv: true`
---
### 6.3 Get Horse by ID
| Feld | Wert |
|-------------|---------------------------------------|
| **Methode** | `GET` |
| **URL** | `{{baseUrl}}/api/horses/{{horseId}}` |
| **Header** | `Authorization: Bearer {{authToken}}` |
**Erwartete Antwort:** `200 OK`
```json
{
"id": "uuid-...",
"pferdeName": "Amadeus",
"geschlecht": "WALLACH",
"geburtsdatum": "2020-05-15",
"rasse": "Warmblut",
"farbe": "Braun",
"stockmass": 165,
"istAktiv": true
}
```
---
### 6.4 Search Horses by Name
| Feld | Wert |
|-------------|----------------------------------------------|
| **Methode** | `GET` |
| **URL** | `{{baseUrl}}/api/horses/search` |
| **Query** | `name=Test` (Suchbegriff), `limit=10` (max.) |
| **Header** | `Authorization: Bearer {{authToken}}` |
**Erwartete Antwort:** `200 OK` — gefilterte Pferde-Liste
**Wozu:** Echtzeit-Suche in der Desktop-App. Testen mit einem Namen aus dem ZNS-Import.
---
### 6.5 Get Horses by Owner
| Feld | Wert |
|-------------|--------------------------------------------|
| **Methode** | `GET` |
| **URL** | `{{baseUrl}}/api/horses/owner/{{ownerId}}` |
| **Header** | `Authorization: Bearer {{authToken}}` |
**Erwartete Antwort:** `200 OK` — alle Pferde eines bestimmten Besitzers
---
### 6.6 Create Horse
| Feld | Wert |
|-------------|---------------------------------------|
| **Methode** | `POST` |
| **URL** | `{{baseUrl}}/api/horses` |
| **Header** | `Content-Type: application/json` |
| **Header** | `Authorization: Bearer {{authToken}}` |
**Request Body:**
```json
{
"pferdeName": "Test Horse",
"geschlecht": "WALLACH",
"geburtsdatum": "2020-05-15",
"rasse": "Warmblut",
"farbe": "Braun",
"zuechterName": "Test Breeder",
"stockmass": 165,
"istAktiv": true,
"bemerkungen": "Test horse for API demonstration"
}
```
**Gültige Werte für `geschlecht`:** `WALLACH`, `STUTE`, `HENGST`
**Erwartete Antwort:** `201 Created`
> **⚡ Tipp:** `horseId` automatisch speichern:
> ```javascript
> var json = pm.response.json();
> pm.environment.set("horseId", json.id);
> ```
---
### 6.7 Update Horse
| Feld | Wert |
|-------------|---------------------------------------|
| **Methode** | `PUT` |
| **URL** | `{{baseUrl}}/api/horses/{{horseId}}` |
| **Header** | `Content-Type: application/json` |
| **Header** | `Authorization: Bearer {{authToken}}` |
**Request Body:**
```json
{
"pferdeName": "Updated Test Horse",
"geschlecht": "WALLACH",
"geburtsdatum": "2020-05-15",
"rasse": "Warmblut",
"farbe": "Dunkelbraun",
"zuechterName": "Updated Test Breeder",
"stockmass": 167,
"istAktiv": true,
"bemerkungen": "Updated test horse for API demonstration"
}
```
**Erwartete Antwort:** `200 OK`
---
### 6.8 Delete Horse
| Feld | Wert |
|-------------|---------------------------------------|
| **Methode** | `DELETE` |
| **URL** | `{{baseUrl}}/api/horses/{{horseId}}` |
| **Header** | `Authorization: Bearer {{authToken}}` |
**Erwartete Antwort:** `204 No Content`
---
### 6.9 Batch Delete Horses
| Feld | Wert |
|-------------|---------------------------------------|
| **Methode** | `DELETE` |
| **URL** | `{{baseUrl}}/api/horses/batch` |
| **Header** | `Content-Type: application/json` |
| **Header** | `Authorization: Bearer {{authToken}}` |
**Request Body:**
```json
{
"horseIds": ["{{horseId1}}", "{{horseId2}}"],
"forceDelete": false
}
```
**`forceDelete: false`** → Nur löschen wenn keine Abhängigkeiten vorhanden
**`forceDelete: true`** → Auch bei Abhängigkeiten löschen (⚠️ Vorsicht!)
**Erwartete Antwort:** `200 OK`
---
### 6.10 Get Horse Statistics
| Feld | Wert |
|-------------|---------------------------------------|
| **Methode** | `GET` |
| **URL** | `{{baseUrl}}/api/horses/stats` |
| **Header** | `Authorization: Bearer {{authToken}}` |
**Erwartete Antwort:** `200 OK`
```json
{
"total": 42,
"active": 38,
"inactive": 4,
"byGeschlecht": {
"WALLACH": 20,
"STUTE": 18,
"HENGST": 4
}
}
```
**Wozu:** Schnelle Übersicht über den Datenbestand nach dem ZNS-Import.
---
## 7. ZNS Import Service
> **Zweck:** ZNS-Daten (Reiter, Pferde, Vereine, Funktionäre) aus einer `.zip`/`.dat`-Datei importieren.
> **Direkt-URL:** `{{znsUrl}}` = `http://localhost:8095`
> **Basis-Pfad:** `/api/v1/import/zns`
---
### 7.1 ZNS Import starten
| Feld | Wert |
|--------------|------------------------------------------|
| **Methode** | `POST` |
| **URL** | `{{znsUrl}}/api/v1/import/zns` |
| **Body-Typ** | `form-data` |
| **Key** | `file` (Type: **File**) |
| **Value** | ZNS-Datei auswählen (`.zip` oder `.dat`) |
**Schritt-für-Schritt in Postman:**
1. Methode: `POST`
2. URL: `http://localhost:8095/api/v1/import/zns`
3. Tab **Body** → **form-data**
4. Key: `file` → Typ auf **File** umstellen (Dropdown neben dem Key-Feld)
5. Value: ZNS-Datei auswählen
6. **Send** klicken
**Erwartete Antwort:** `202 Accepted`
```json
{
"jobId": "abc-123-def-456",
"status": "STARTED",
"message": "Import gestartet",
"startedAt": "2026-04-03T14:00:00+02:00"
}
```
> **⚡ Tipp:** `jobId` automatisch speichern:
> ```javascript
> var json = pm.response.json();
> pm.environment.set("znsJobId", json.jobId);
> ```
---
### 7.2 ZNS Import-Status abfragen
| Feld | Wert |
|-------------|----------------------------------------------------|
| **Methode** | `GET` |
| **URL** | `{{znsUrl}}/api/v1/import/zns/{{znsJobId}}/status` |
| **Auth** | Keine |
**Antwort während Import:** `200 OK`
```json
{
"jobId": "abc-123-def-456",
"status": "IN_PROGRESS",
"processedRecords": 150,
"totalRecords": 500,
"progressPercent": 30,
"startedAt": "2026-04-03T14:00:00+02:00"
}
```
**Antwort nach Abschluss:** `200 OK`
```json
{
"jobId": "abc-123-def-456",
"status": "COMPLETED",
"processedRecords": 500,
"totalRecords": 500,
"progressPercent": 100,
"importedReiter": 200,
"importedPferde": 180,
"importedVereine": 30,
"importedFunktionaere": 90,
"startedAt": "2026-04-03T14:00:00+02:00",
"completedAt": "2026-04-03T14:01:30+02:00"
}
```
**Mögliche Status-Werte:**
| Status | Bedeutung |
|---------------|----------------------------------------|
| `STARTED` | Job wurde angenommen, noch nicht aktiv |
| `IN_PROGRESS` | Import läuft gerade |
| `COMPLETED` | Import erfolgreich abgeschlossen |
| `FAILED` | Import fehlgeschlagen (Fehlerdetails) |
**Wozu:** Status pollen bis `COMPLETED` — dann Daten in pgAdmin oder Desktop-App prüfen.
---
### 7.3 ZNS Import Health-Check
| Feld | Wert |
|-------------|------------------------------|
| **Methode** | `GET` |
| **URL** | `{{znsUrl}}/actuator/health` |
| **Auth** | Keine |
**Erwartete Antwort:** `200 OK`
```json
{
"status": "UP",
"components": {
"db": { "status": "UP" },
"diskSpace": { "status": "UP" }
}
}
```
**⚠️ Consul-Check:** Nach dem Neustart des ZNS-Service sollte er im Consul-UI unter http://localhost:8500 unter dem
Namen `zns-import-service` erscheinen.
---
## 8. Empfohlene Test-Reihenfolge
### Schnell-Smoke-Test (5 Minuten)
```
1. GET {{pingUrl}}/ping/simple → "pong" ✓
2. GET {{baseUrl}}/health → "UP" ✓
3. GET {{znsUrl}}/actuator/health → "UP" ✓
4. GET {{baseUrl}}/api/masterdata/countries/iso/AT → Österreich ✓
```
### Vollständiger Integrations-Test (heute, ZNS-Import)
```
1. GET {{pingUrl}}/ping/simple → Smoke-Test
2. GET {{pingUrl}}/ping/enhanced → Circuit Breaker CLOSED
3. GET {{pingUrl}}/ping/enhanced?simulate=true → Fallback greift
4. POST {{baseUrl}}/auth/login → Token speichern
5. GET {{baseUrl}}/api/masterdata/countries/iso/AT → Stammdaten vorhanden
6. GET {{baseUrl}}/api/horses → (leer vor Import)
7. GET {{znsUrl}}/actuator/health → ZNS bereit
8. POST {{znsUrl}}/api/v1/import/zns → ZNS-Datei hochladen → jobId speichern
9. GET {{znsUrl}}/api/v1/import/zns/{{znsJobId}}/status → Status pollen bis COMPLETED
10. GET {{baseUrl}}/api/horses → Pferde jetzt befüllt ✓
11. GET {{baseUrl}}/api/horses/stats → Statistiken prüfen
12. GET {{baseUrl}}/api/horses/search?name=... → Suche testen
```
---
## Anhang: Alle URLs auf einen Blick
| Service | URL | Verwendung |
|----------------|-----------------------|--------------------------|
| API-Gateway | http://localhost:8081 | Haupt-Einstiegspunkt |
| Ping (direkt) | http://localhost:8082 | Ping-Endpunkte direkt |
| ZNS-Import | http://localhost:8095 | Import-Endpunkte |
| Keycloak Admin | http://localhost:8180 | Auth-Verwaltung |
| Consul UI | http://localhost:8500 | Service-Discovery prüfen |
| Zipkin | http://localhost:9411 | Traces nachverfolgen |
| pgAdmin | http://localhost:8888 | DB-Inhalte prüfen |
| Mailpit | http://localhost:8025 | E-Mail-Mock |
@@ -0,0 +1,109 @@
# 🧹 Session-Log — 3. April 2026 (Nachmittag)
> **Uhrzeit:** ca. 14:0014:30 Uhr
> **Thema:** Docker-Fixes, ZNS-Consul-Registrierung, pgAdmin-Provisioning, Postman-Dokumentation
> **Erstellt von:** 🧹 Curator
---
## Was wurde gemacht?
### 1. 🐧 Dockerfiles korrigiert (Gateway + Ping)
**Problem:** `docker compose build api-gateway` und `docker compose build ping-service` schlugen fehl,
weil das Builder-Image `gradle:9.4.0-jdk25-alpine` (bzw. `9.3.1-jdk25`) auf Docker Hub nicht existiert.
**Fixes:**
- **Builder-Stage** auf `eclipse-temurin:21-jdk-alpine` umgestellt (verfügbar, LTS)
- **`./gradlew`-Wrapper** wird jetzt direkt verwendet statt dem Gradle-Docker-Image
- **`GRADLE_USER_HOME`** von `/home/gradle/.gradle` auf `/root/.gradle` korrigiert (kein `gradle`-User in temurin)
- **Cache-Mount-Paths** entsprechend angepasst
- **Ping-Dockerfile:** 8 fehlende Frontend-Dummy-Verzeichnisse ergänzt:
`veranstalter-feature`, `veranstaltung-feature`, `profile-feature`, `reiter-feature`,
`pferde-feature`, `verein-feature`, `turnier-feature`, `billing-feature`
**Geänderte Dateien:**
- `backend/infrastructure/gateway/Dockerfile`
- `backend/services/ping/Dockerfile`
---
### 2. 🔧 ZNS-Import-Service: Consul-Registrierung
**Problem:** ZNS-Service startete erfolgreich (Health-Check positiv), meldete sich aber nicht bei Consul an.
**Fixes:**
- `application.yaml`: `spring.cloud.consul`-Sektion ergänzt (Host, Port, Discovery, Health-Check-Interval)
- `build.gradle.kts`: `implementation(libs.spring.cloud.starter.consul.discovery)` hinzugefügt
**Geänderte Dateien:**
- `backend/services/zns-import/zns-import-service/src/main/resources/application.yaml`
- `backend/services/zns-import/zns-import-service/build.gradle.kts`
> **Nächster Schritt:** ZNS-Service neu starten → in Consul UI unter http://localhost:8500 prüfen ob
`zns-import-service` erscheint.
---
### 3. 🗄️ pgAdmin: Auto-Provisioning
**Problem:** pgAdmin war nach Login nicht konfiguriert — kein Server, keine Datenbank sichtbar.
**Fix:**
- `config/docker/pgadmin/servers.json` erstellt: Verbindung zu `postgres:5432` / `pg-meldestelle-db` vorkonfiguriert
- `dc-ops.yaml`: Volume-Mount `/pgadmin4/servers.json:ro` zum pgAdmin-Service hinzugefügt
**Geänderte/neue Dateien:**
- `config/docker/pgadmin/servers.json` *(neu)*
- `dc-ops.yaml`
> **Hinweis:** pgAdmin-Container neu starten damit die Konfiguration wirksam wird:
> `docker compose --profile tools up -d --force-recreate pgadmin`
> **Hinweis:** Die DB-Tabelle für Pferde heißt `horse` (englisch), nicht `pferd`.
---
### 4. 📋 Postman-Gesamt-Dokumentation
**Erstellt:** `docs/04_Agents/Besprechung_2026-04-03/Postman_Tests_Dokumentation.md` (930 Zeilen)
**Enthält:**
- Environment-Setup (Variablen-Tabelle)
- **8 Endpunkt-Gruppen** mit je Methode, URL, Headers, Request Body, erwarteter Antwort und Erklärung
- **25 Endpunkte** detailliert dokumentiert: System Info, Ping Service (8), Auth (5), Countries (7), Horses (10), ZNS
Import (3)
- Postman-Test-Scripts für automatisches Speichern von `authToken`, `horseId`, `countryId`, `znsJobId`
- Empfohlene Test-Reihenfolge: Schnell-Smoke-Test + Vollständiger ZNS-Integrations-Test
---
## Offene Punkte (nicht diese Session)
| Punkt | Wer | Prio |
|---------------------------------------------------------------------|------------|----------|
| ZNS-Service neu starten und Consul-Registrierung verifizieren | 👷 Owner | Sofort |
| pgAdmin neu starten und DB-Verbindung prüfen | 👷 Owner | Sofort |
| `docker compose build api-gateway ping-service` erneut testen | 🐧 DevOps | Heute |
| Tabellen-Name `horse` → Klären ob Umbenennung auf `pferd` gewünscht | 👷 Backend | Sprint B |
---
## Dateien dieser Session
```
backend/infrastructure/gateway/Dockerfile ← geändert
backend/services/ping/Dockerfile ← geändert
backend/services/zns-import/zns-import-service/build.gradle.kts ← geändert
backend/services/zns-import/zns-import-service/src/main/resources/application.yaml ← geändert
config/docker/pgadmin/servers.json ← neu
dc-ops.yaml ← geändert
docs/04_Agents/Besprechung_2026-04-03/Postman_Tests_Dokumentation.md ← neu
docs/04_Agents/Besprechung_2026-04-03/Session_Log_2026-04-03_Nachmittag.md ← neu (diese Datei)
```