docs: massive restructuring of documentation, development guides and agent playbooks

This commit is contained in:
2026-06-15 12:54:38 +02:00
parent e4988b4397
commit ce63303b2c
686 changed files with 45423 additions and 319 deletions
@@ -0,0 +1,63 @@
---
type: Reference
status: ACTIVE
owner: Backend Developer
last_update: 2026-04-03
---
# API-Übersicht Stammdaten
Abdeckung: Backend Sprint B1 (abgeschlossen). Konsolidierte Endpunkte für Reiter, Pferde, Vereine und Funktionäre. Implementiert mit Ktor; DTOs und Validierung in den jeweiligen Services.
Hinweis Tenant/Headers: Stammdaten sind global bzw. nicht tenantspezifisch. Für domainspezifische Vorgänge (Entries, Kassa) gilt ADR0021/`X-Event-Id`.
## Reiter (`/reiter`)
- GET `/reiter` — Liste (optional Filter: `lizenzKlasse`, `vereinId`; Pagination: `limit`, `offset`)
- GET `/reiter/search?q=...` — Suche nach Name oder Satznummer
- GET `/reiter/{id}` — Einzelabruf
- GET `/reiter/satznummer/{nr}` — Lookup per Satznummer
- POST `/reiter` — Anlegen
- PUT `/reiter/{id}` — Aktualisieren (partiell)
- DELETE `/reiter/{id}` — Löschen
Quelle: `backend/services/masterdata/masterdata-api/.../ReiterController.kt`
## Pferde (`/horse`)
- GET `/horse` — Liste (optional Filter: `jahrgang`, `besitzerId`; Pagination: `limit`, `offset`)
- GET `/horse/search?q=...` — Suche nach Name/Nummern
- GET `/horse/{id}` — Einzelabruf
- POST `/horse` — Anlegen
- PUT `/horse/{id}` — Aktualisieren (partiell)
- DELETE `/horse/{id}` — Löschen
Quelle: `backend/services/masterdata/masterdata-api/.../HorseController.kt`
## Vereine (`/verein`)
- GET `/verein` — Liste (optional Filter: `verband`/Bundesland; Pagination: `limit`, `offset`)
- GET `/verein/search?q=...` — Suche nach Name/Kurzname
- GET `/verein/{id}` — Einzelabruf
- POST `/verein` — Anlegen
- PUT `/verein/{id}` — Aktualisieren (partiell)
- DELETE `/verein/{id}` — Löschen
Quelle: `backend/services/masterdata/masterdata-api/.../VereinController.kt`
## Funktionäre (`/funktionaer`)
- GET `/funktionaer` — Liste (optional Filter: `rolle`; Pagination: `limit`, `offset`)
- GET `/funktionaer/search?q=...` — Suche nach Name
- GET `/funktionaer/{id}` — Einzelabruf
- POST `/funktionaer` — Anlegen
- PUT `/funktionaer/{id}` — Aktualisieren (partiell)
- DELETE `/funktionaer/{id}` — Löschen
Quelle: `backend/services/masterdata/masterdata-api/.../FunktionaerController.kt`
## Standards
- Auth: Standard-Bearer optional je nach Deploymentprofil (siehe Service-Konfig)
- Content-Type: `application/json; charset=utf-8`
- Fehlerfälle: 400 (Validierung), 404 (nicht gefunden)
@@ -0,0 +1,37 @@
---
type: Reference
status: DRAFT
owner: Backend Developer
last_update: 2026-04-03
---
# Kassa-API (Entwurf)
Abhängigkeit: Backend Sprint B2 (Kassa-Service) — laut CuratorRoadmap noch offen. Dieses Dokument reserviert die Endpunkte und beschreibt die Erwartungen. Die Implementierungsdetails werden ergänzt, sobald der Service fertiggestellt ist.
Mandantenkontext: Erfordert `X-Event-Id` (ADR0021). Alle KassaOperationen sind tenantlokal.
## Endpunkte (geplant)
- GET `/kassa/saldo` — Liefert den aktuellen Saldo der Veranstaltung und optional pro Turnier.
- Query: `turnierId` (optional, UUID)
- Response: `{ saldoCents: long, currency: "EUR", scope: "veranstaltung"|"turnier", turnierId?: UUID }`
- GET `/zahlvorgaenge` — Listet KassaBuchungen/Zahlvorgänge (paginiert, filterbar).
- Query: `turnierId?`, `teilnehmerId?`, `typ?` (EINZAHLUNG|AUSZAHLUNG|KORREKTUR), `limit`, `offset`
- Response: Liste von Transaktionen mit Betrag, Zeit, Verweis (Teilnehmer/Turnier), Notiz
- POST `/zahlvorgaenge` — Erstellt einen neuen Zahlungsvorgang (Ein-/Auszahlung/Korrektur).
- Body: `{ typ, betragCents, currency, referenz: { teilnehmerId?|turnierId? }, notiz? }`
- Wirkung: Aktualisiert `teilnehmer_konten` bzw. `turnier_kassa` atomar.
## Validierung & Regeln (voraussichtlich)
- Atomare Konsistenz: Transaktion + SaldoUpdate innerhalb einer DBTransaktion.
- Negativsaldo optional durch FeatureFlag blockierbar.
- AuditTrail pro Vorgang (who/when), IdempotenzKey optional.
## Implementierungsstand
- Datenstrukturen `teilnehmer_konten` und `turnier_kassa` sind per Flyway angelegt (siehe [Datenbankschema](../Schema/Database_Schema_V1-V009.md)).
- Endpunkte folgen nach Abschluss Backend B2. Dieses Dokument wird dann auf `status: ACTIVE` gesetzt.
@@ -0,0 +1,59 @@
---
type: Guide
status: DRAFT
owner: Backend Developer
date: 2026-02-02
last_update: 2026-03-15
---
# Database Best Practices & Exposed 1.0.0
Dieser Guide beschreibt den korrekten Umgang mit der Datenbank-Schicht in unseren Backend-Services, basierend auf JetBrains Exposed 1.0.0.
## 1. Architektur-Prinzipien
* **Trennung:** Datenbank-Zugriffe gehören ausschließlich in die `infrastructure/persistence` Schicht. Services nutzen Repositories (Interfaces), keine direkten Exposed-Aufrufe.
* **Transaktionen:** Jede geschäftliche Operation sollte in einer Transaktion laufen. Nutze dafür die Helper aus `DatabaseUtils.kt`.
## 2. Nutzung von `DatabaseUtils`
Wir haben zentrale Wrapper für Transaktionen, um Fehlerbehandlung und Logging zu vereinheitlichen.
### 2.1 Transaktionen starten
Nutze immer `transactionResult` (oder die Aliase `readTransaction` / `writeTransaction`), um Exposed-Code auszuführen.
```kotlin
fun findUser(id: UUID): Result<User> = readTransaction {
// 'this' ist hier eine JdbcTransaction
UserTable.select { UserTable.id eq id }
.map { /* row -> User(...) */ }
.singleOrNull()
}
```
**Wichtig:** Der Lambda-Receiver ist `JdbcTransaction`. Das ermöglicht Zugriff auf Low-Level JDBC Funktionen, falls nötig.
### 2.2 Low-Level SQL (`exec`, `executeUpdate`)
Vermeide rohes SQL, wo immer möglich. Wenn es sein muss (z.B. für Performance-Optimierungen oder spezielle Postgres-Features), beachte folgende Regeln für Exposed 1.0.0:
* **`exec`:** Nutze immer `explicitStatementType`.
```kotlin
this.exec("SELECT 1", explicitStatementType = StatementType.SELECT) { rs -> /* handle ResultSet */ }
```
* **`executeUpdate`:** Nutze die Helper-Methode `DatabaseUtils.executeUpdate`, da sie sich um das korrekte Schließen von Statements kümmert (Exposed `PreparedStatementApi` ist nicht `AutoCloseable`).
## 3. Exposed 1.0.0 Besonderheiten
* **UUIDs:** Nutze `Table.javaUUID()` für `java.util.UUID` Spalten. `Table.uuid()` ist für `kotlin.uuid.Uuid` reserviert.
* **JSONB:** Bei SQLite wird JSON automatisch gewrappt. Prüfe `castToJsonFormat` Flag.
## 4. Fehlerbehandlung
`DatabaseUtils` fängt `SQLException` ab und mappt sie auf unsere Domain-Fehler (`ErrorDto`):
* Duplicate Key -> `ErrorCodes.DUPLICATE_ENTRY`
* Foreign Key -> `ErrorCodes.FOREIGN_KEY_VIOLATION`
* Timeout -> `ErrorCodes.DATABASE_TIMEOUT`
Wirf keine rohen Exceptions aus Repositories.
@@ -0,0 +1,18 @@
---
type: Guide
status: REDIRECT
owner: Curator
tags: [testing, postman, backend, api]
last_update: 2026-04-03
---
# 🧪 Testanleitung: PingService & Gateway mit Postman (Weiterleitung)
Diese Seite wurde in ein zentrales Runbook für Betriebsanleitungen überführt.
Bitte nutze ab sofort das konsolidierte Runbook:
- Runbook: APITests mit Postman
`docs/07_Infrastructure/runbooks/POSTMAN_API_Tests_Runbook.md`
Hinweis: Dieser Eintrag bleibt als Verweis bestehen, damit bestehende Links nicht brechen.
@@ -0,0 +1,28 @@
---
type: Reference
status: ACTIVE
owner: Lead Architect
last_update: 2026-04-03
---
# Tenant-Isolation & MultiTenant (Kurzfassung)
Vollständige Entscheidung: [ADR0021: TenantResolutionStrategie (SchemaperTenant)](../01_Architecture/adr/0021-tenant-resolution-strategy-de.md).
## Kernaussagen
- Eine Veranstaltung = ein Tenant = ein Datenbankschema (SchemaperTenant).
- Requests tragen `X-Event-Id`; Backend validiert gegen `control.tenants` und schaltet das Schema je Request.
- Flyway führt Migrationen je TenantSchema aus (eigene `flyway_schema_history`).
- Stammdaten (Reiter/Pferde/Vereine/Funktionäre) sind global und nicht tenantspezifisch; Entries/Kassa sind tenantlokal.
## Umsetzung (Kurz)
- WebLayer: `TenantWebFilter` (Spring) bzw. Plugin (Ktor) liest `X-Event-Id` und legt `TenantContext` ab.
- Persistence: SCHEMAMultitenancy (`SET search_path`) oder Hibernate`MultiTenantConnectionProvider`.
- Registry: `control.tenants(event_id, schema_name, status, db_url?, version, created_at)`.
## Betroffene Bereiche
- Datenmodell tenantlokal: `veranstaltungen`, `turniere`, `bewerbe`, `abteilungen`, `teilnehmer_konten`, `turnier_kassa` (siehe [Datenbankschema](./Schema/Database_Schema_V1-V009.md)).
- Services: Der EntriesService arbeitet mandantenfähig; andere Services bleiben SingleTenant/global (vgl. BackendRoadmap).
+25
View File
@@ -0,0 +1,25 @@
---
type: Reference
status: ACTIVE
owner: Backend Developer
last_update: 2026-03-15
---
# Backend Dokumentation
Dieses Verzeichnis enthält die spezifische Dokumentation für alle Backend-Komponenten, einschließlich der Microservices und der Infrastruktur-Module wie dem API-Gateway.
## Struktur
* `Services/`: Enthält pro Service eine dedizierte Markdown-Datei, die dessen Zweck, API, Datenmodell und Konfiguration beschreibt.
* `API/`: Querliegende API-Referenzen und Übersichten (Stammdaten, Kassa, usw.).
* `Schema/`: Datenbankschemata und Migrationsübersichten (Flyway).
* `Integration/`: Dokumentation zur Interaktion zwischen den Services (z.B. Event-Flows).
## Wichtige Einstiegspunkte
* **[Ping-Service](./Services/PingService_Reference.md):** Dient als technischer Blueprint und einfachstes Beispiel für einen Service.
* **[API-Gateway](../07_Infrastructure/api-gateway.md):** Beschreibung des zentralen Einstiegspunkts für alle externen Anfragen.
* **[Stammdaten-APIs (Reiter, Pferde, Vereine, Funktionäre)](./API/API_Uebersicht_Stammdaten.md):** Konsolidierte Endpunkt-Übersicht (Backend B1 abgeschlossen).
* **[Datenbankschema V1V009](./Schema/Database_Schema_V1-V009.md):** Tabellen und Constraints (veranstaltungen, turniere, bewerbe, abteilungen, teilnehmer_konten, turnier_kassa).
* **[Kassa-API](./API/Kassa_API.md):** Platzhalter für Saldo/Transaktionen; wird ergänzt, sobald Backend B2 Kassa fertig ist.
* **[Tenant-Isolation & MultiTenant kurz](./Multi_Tenant_Kurz.md):** Zusammenfassung gem. ADR0021.
@@ -0,0 +1,130 @@
---
type: Reference
status: ACTIVE
owner: Backend Developer
last_update: 2026-04-03
---
# Datenbankschema V1V009 (TenantSchema)
Quelle: FlywayMigrationen im EntriesService (`backend/services/entries/entries-service/src/main/resources/db/tenant/`), insbesondere `V2__domain_hierarchy.sql`.
Hinweis zur Architektur: Je Veranstaltung (Tenant) existiert ein eigenes Datenbankschema (ADR0021). Alle untenstehenden Tabellen werden pro TenantSchema angelegt und sind somit mandantengetrennt.
## Tabellenübersicht
- `veranstaltungen` — Eine Veranstaltung (Singleton im TenantSchema)
- `turniere` — Turniere einer Veranstaltung (1:N zu `veranstaltungen`)
- `bewerbe` — Bewerbe/Prüfungen eines Turniers (1:N zu `turniere`)
- `abteilungen` — Abteilungen/Heats eines Bewerbs (1:N zu `bewerbe`)
- `teilnehmer_konten` — Aggregierte Salden eines Teilnehmers über alle Turniere der Veranstaltung
- `turnier_kassa` — KassaSaldo pro Turnier
## Detaillierte Definitionen (aus V2__domain_hierarchy.sql)
### veranstaltungen
Primärschlüssel: `id (UUID)`
Spalten:
- `id UUID PRIMARY KEY`
- `created_at TIMESTAMPTZ NOT NULL`
- `updated_at TIMESTAMPTZ NOT NULL`
### turniere
Primärschlüssel: `id (UUID)`
Fremdschlüssel: `veranstaltung_id → veranstaltungen(id) ON DELETE CASCADE`
Spalten:
- `id UUID PRIMARY KEY`
- `veranstaltung_id UUID NOT NULL`
- `oeps_turniernummer VARCHAR(50) NOT NULL`
- `created_at TIMESTAMPTZ NOT NULL`
- `updated_at TIMESTAMPTZ NOT NULL`
Indizes/Constraints:
- `UNIQUE (oeps_turniernummer)``uq_turniere_oeps_nr`
- `INDEX (veranstaltung_id)``idx_turniere_veranstaltung_id`
### bewerbe
Primärschlüssel: `id (UUID)`
Fremdschlüssel: `turnier_id → turniere(id) ON DELETE CASCADE`
Spalten:
- `id UUID PRIMARY KEY`
- `turnier_id UUID NOT NULL`
- `klasse VARCHAR(50) NOT NULL`
- `hoehe_cm INTEGER NULL`
- `bezeichnung TEXT NOT NULL`
- `created_at TIMESTAMPTZ NOT NULL`
- `updated_at TIMESTAMPTZ NOT NULL`
Indizes:
- `INDEX (turnier_id)``idx_bewerbe_turnier_id`
- `INDEX (klasse)``idx_bewerbe_klasse`
### abteilungen
Primärschlüssel: `id (UUID)`
Fremdschlüssel: `bewerb_id → bewerbe(id) ON DELETE CASCADE`
Spalten:
- `id UUID PRIMARY KEY`
- `bewerb_id UUID NOT NULL`
- `nr INTEGER NOT NULL`
- `bezeichnung TEXT NOT NULL`
- `typ VARCHAR(32) NOT NULL` (Werte: `SEPARATE_SIEGEREHRUNG`, `ORGANISATORISCH`)
- `created_at TIMESTAMPTZ NOT NULL`
- `updated_at TIMESTAMPTZ NOT NULL`
Constraints/Indizes:
- `CHECK (typ IN ('SEPARATE_SIEGEREHRUNG','ORGANISATORISCH'))``chk_abteilungen_typ`
- `UNIQUE (bewerb_id, nr)``uq_abteilungen_bewerb_nr`
- `INDEX (bewerb_id)``idx_abteilungen_bewerb_id`
- `INDEX (typ)``idx_abteilungen_typ`
### teilnehmer_konten
Primärschlüssel: `id (UUID)`
Fremdschlüssel: `veranstaltung_id → veranstaltungen(id) ON DELETE CASCADE`
Spalten:
- `id UUID PRIMARY KEY`
- `veranstaltung_id UUID NOT NULL`
- `teilnehmer_id UUID NOT NULL`
- `saldo_cents BIGINT NOT NULL DEFAULT 0`
- `currency CHAR(3) NOT NULL DEFAULT 'EUR'`
- `created_at TIMESTAMPTZ NOT NULL`
- `updated_at TIMESTAMPTZ NOT NULL`
Indizes/Constraints:
- `UNIQUE (veranstaltung_id, teilnehmer_id)``uq_tkonten_veranstaltung_teilnehmer`
- `INDEX (veranstaltung_id)``idx_tkonten_veranstaltung_id`
- `INDEX (teilnehmer_id)``idx_tkonten_teilnehmer_id`
### turnier_kassa
Primärschlüssel: `id (UUID)`
Fremdschlüssel: `turnier_id → turniere(id) ON DELETE CASCADE`
Spalten:
- `id UUID PRIMARY KEY`
- `turnier_id UUID NOT NULL`
- `saldo_cents BIGINT NOT NULL DEFAULT 0`
- `currency CHAR(3) NOT NULL DEFAULT 'EUR'`
- `created_at TIMESTAMPTZ NOT NULL`
- `updated_at TIMESTAMPTZ NOT NULL`
Indizes/Constraints:
- `UNIQUE (turnier_id)``uq_turnier_kassa_turnier`
- `INDEX (turnier_id)``idx_turnier_kassa_turnier_id`
## Versionierung / Flyway
- Die oben dokumentierten Tabellen sind in `V2__domain_hierarchy.sql` definiert.
- Weitere Migrationen V1V009 betreffen Bootstrap/Erweiterungen; diese Seite wird fortlaufend ergänzt, sobald neue fachrelevante Strukturen hinzukommen.
## Beziehungen (Kurz)
`veranstaltungen (1) ──< (N) turniere (1) ──< (N) bewerbe (1) ──< (N) abteilungen`
Separat aggregierend:
- `teilnehmer_konten` auf Veranstaltungsebene (pro Teilnehmer genau ein Konto)
- `turnier_kassa` auf Turnierebene (pro Turnier genau ein KassaEintrag)
@@ -0,0 +1,121 @@
---
type: Reference
status: ACTIVE
owner: Backend Developer
tags: [backend, service, reference, ping]
last_update: 2026-04-03
---
# 🎯 Ping Service Reference
Der `ping-service` ist der **"Tracer Bullet"** (Leuchtspurgeschoss) der Meldestelle-Architektur. Er ist kein Wegwerf-Prototyp, sondern die **Referenzimplementierung** für alle zukünftigen Microservices.
## 1. Mission & Verantwortung
* **Technischer Durchstich:** Beweist, dass die Kette *Frontend -> Gateway -> Service -> DB* funktioniert.
* **Blueprint:** Definiert Standards für Architektur (DDD/Hexagonal), Testing, Security und Build-Prozesse.
* **Infrastruktur-Validierung:** Testet die Integration mit Consul, Keycloak, Postgres, Redis und Zipkin.
* **Offline-First Lab:** Hier wird die Delta-Sync-Logik (`/sync`) entwickelt und validiert, bevor sie in fachliche Services einzieht.
---
## 2. Technologie-Stack
* **Framework:** Spring Boot 3.5.x (Spring MVC, Tomcat).
* **Sprache:** Kotlin 2.x (Coroutines für asynchrone Abläufe).
* **Datenbank:** PostgreSQL (via Spring Data JPA).
* **Migration:** Flyway (mit service-spezifischer Historientabelle `flyway_schema_history_ping`).
* **Security:** OAuth2 Resource Server (JWT via Keycloak).
* **Resilience:** Resilience4j (Circuit Breaker).
* **API Contract:** KMP-Modul `:contracts:ping-api` (Shared Code mit Frontend).
---
## 3. Architektur (Hexagonal)
Der Service folgt strikt der **Ports & Adapters** (Hexagonal) Architektur:
1. **Domain (`at.mocode.ping.domain`):**
* Der Kern. Enthält Entities (`Ping`) und Business-Regeln.
* Frei von Frameworks (kein Spring, kein JPA).
* Definiert Interfaces für Ports (`PingRepository`).
2. **Application (`at.mocode.ping.application`):**
* Orchestriert die Use Cases (`PingUseCase`).
* Steuert Transaktionen (`@Transactional`).
* Verbindet Domain und Infrastructure.
3. **Infrastructure (`at.mocode.ping.infrastructure`):**
* **Web:** `PingController` (REST API).
* **Persistence:** `PingRepositoryAdapter` (JPA Implementierung).
* **Security:** Global Config für JWT-Validierung.
---
## 4. API Endpunkte
| Methode | Pfad | Auth | Beschreibung |
| :--- | :--- | :--- | :--- |
| `GET` | `/ping/simple` | 🔓 Public | Erstellt einen Ping in der DB. Testet Schreibzugriff. |
| `GET` | `/ping/enhanced` | 🔓 Public | Testet Circuit Breaker. Parameter `simulate=true` löst Fehler aus. |
| `GET` | `/ping/health` | 🔓 Public | Gibt Status "UP" zurück. |
| `GET` | `/ping/public` | 🔓 Public | Expliziter Public-Test. |
| `GET` | `/ping/secure` | 🔒 **Secure** | Erfordert Token mit Rolle `MELD_USER`. Testet Auth-Flow. |
| `GET` | `/ping/sync` | 🔒 **Secure** | **Delta-Sync**. Liefert Änderungen seit `lastSyncTimestamp`. |
---
## 5. Getting Started
### A. Voraussetzungen
* Java 25 (oder kompatibel).
* Docker & Docker Compose (für Infrastruktur).
### B. Infrastruktur starten
Bevor der Service laufen kann, braucht er Datenbank und Keycloak.
```bash
# Im Root-Verzeichnis
docker compose --profile infra up -d
```
### C. Starten via Gradle (Lokal)
Ideal für Entwicklung und Debugging.
```bash
# Startet den Service im Profil "local"
./gradlew :backend:services:ping:ping-service:bootRun
```
* **URL:** `http://localhost:8082` (Direktzugriff)
* **Debug Port:** 5006
### D. Starten via Docker (Integration)
Testet den Service im Container-Verbund (hinter dem Gateway).
```bash
# Baut das Image und startet es zusammen mit dem Gateway
docker compose --profile backend up -d --build
```
* **URL (via Gateway):** `http://localhost:8081/api/ping/...`
---
## 6. Konfiguration
Die Konfiguration erfolgt primär über `application.yml` und Environment-Variables (12-Factor App).
| Variable | Default (Docker) | Beschreibung |
| :--- | :--- | :--- |
| `SERVER_PORT` | `8082` | Port des Services. |
| `POSTGRES_DB_URL` | `jdbc:postgresql://postgres:5432/...` | JDBC URL. |
| `SSEC_ISSUER_URI` | `http://keycloak:8080/...` | URL des Identity Providers (für Token-Check). |
| `CONSUL_HOST` | `consul` | Host für Service Discovery. |
### Profile
* `local`: Für lokale Entwicklung (nutzt `localhost` Adressen).
* `docker`: Für Betrieb im Docker-Netzwerk (nutzt Service-Namen wie `postgres`).
* `test`: Für Unit/Integration-Tests (nutzt H2 oder Testcontainers).
---
## 7. Testing
* **Unit Tests:** `./gradlew :backend:services:ping:ping-service:test`
* **Manuelle Tests:** Siehe [Testing with Postman](../Guides/Testing_with_Postman.md).
@@ -0,0 +1,80 @@
---
type: Task
status: ARCHIVED
owner: Senior Backend Developer
created: 2026-01-15
completed: 2026-01-16
priority: HIGH
context: Operation Tracer Bullet (Phase 1)
---
# Arbeitsanweisung: Infrastructure Hardening & Security Implementation
**Ziel:** Finalisierung der Backend-Infrastruktur-Module und Härtung des `ping-service` gemäß [ADR 001](../../01_Architecture/adr/001-backend-infrastructure-decisions.md).
---
## 1. Kontext & Architektur-Entscheidungen
Wir befinden uns in **Phase 1** ("Tracer Bullet"). Das Ziel ist ein stabiler, sicherer Durchstich vom Frontend bis zur Datenbank.
Die Architektur wurde wie folgt geschärft (siehe ADR 001):
* **Persistence:** Hybrid-Ansatz (JPA für Writes/Entities, Exposed für komplexe Reads).
* **Security:** Zentralisiertes Modul (`backend/infrastructure/security`).
* **Messaging:** Kafka ist für Phase 1 **out of scope**. Fokus auf REST.
* **Migration:** Flyway Skripte liegen direkt im Service (`db/migration`).
---
## 2. Deine Aufgaben (Checkliste)
### A. Security Module (`backend/infrastructure/security`)
Dieses Modul wurde neu angelegt. Fülle es mit Leben.
* [x] **Security Configuration:**
* Erstelle eine `SecurityConfig`-Klasse, die `SecurityFilterChain` konfiguriert.
* Implementiere OAuth2 Resource Server Support (JWT Validierung).
* Definiere globale CORS-Regeln (Frontend darf zugreifen).
* [x] **Role Converter:**
* Implementiere einen `KeycloakRoleConverter`, der die Rollen aus dem JWT (Realm/Resource Access) in Spring Security `GrantedAuthority` mapping.
* **Wichtig:** Achte auf Kompatibilität. Das Gateway nutzt WebFlux (Reactive), die Services nutzen WebMVC (Servlet). Falls nötig, trenne die Konfigurationen oder nutze `ConditionalOnWebApplication`.
### B. Persistence Layer (`backend/infrastructure/persistence`)
Das Modul ist bereits konfiguriert.
* [x] **Verwendung im Service:**
* Stelle sicher, dass der `ping-service` dieses Modul nutzt.
* Implementiere `PingEntity` als JPA Entity.
* Nutze `JpaRepository` für Standard-CRUD-Operationen.
### C. Ping Service Hardening (`backend/services/ping/ping-service`)
Mache den Service "Production Ready."
* [x] **Flyway:**
* Erstelle `src/main/resources/db/migration/V1__init_ping.sql`.
* Definiere das Schema für die `ping` Tabelle.
* [x] **API Implementation:**
* Implementiere `/ping/public` (offen) und `/ping/secure` (benötigt Auth).
* Nutze `@PreAuthorize("hasRole('MELD_USER')")` o.ä. zum Testen der Rollen.
* [x] **Resilience:**
* Konfiguriere Resilience4j (CircuitBreaker) für die DB-Verbindung (via `application.yml`).
### D. Gateway Integration (`backend/infrastructure/gateway`)
* [x] **Routing:**
* Prüfe die `application.yml` im Gateway.
* Stelle sicher, dass Routen zum `ping-service` korrekt konfiguriert sind (via Service Discovery "ping-service").
---
## 3. Definition of Done
1. Das Projekt kompiliert fehlerfrei (`./gradlew build`).
2. `docker compose up` startet Gateway, Ping-Service, Keycloak und Postgres ohne Fehler.
3. Ein Request auf `http://localhost:8080/ping/public` (via Gateway) liefert 200 OK.
4. Ein Request auf `http://localhost:8080/ping/secure` ohne Token liefert 401 Unauthorized.
5. Die Datenbank-Tabelle `ping` wurde durch Flyway automatisch erstellt.
---
**Referenzen:**
* [ADR 001: Backend Infrastructure Decisions](../../01_Architecture/adr/001-backend-infrastructure-decisions.md)
* [Master Roadmap Q1 2026](../../01_Architecture/_archive/2026-03-15_MASTER_ROADMAP_2026_Q1.md)