From be464f2ac078950329adca35cf1c9370d2d76fb2 Mon Sep 17 00:00:00 2001 From: MoCoAt Date: Wed, 15 Oct 2025 12:48:00 +0200 Subject: [PATCH] refactoring Dokumentation --- .github/PULL_REQUEST_TEMPLATE.md | 13 + .github/workflows/build.yml | 3 + Tagebuch/AUTHENTICATION-IMPLEMENTATION-DE.md | 140 - Tagebuch/AUTHENTICATION-IMPLEMENTATION.md | 140 - ...alyse_Infrastructure-Module_14-Okt-2025.md | 301 - Tagebuch/DOCKER-OPTIMIZATION-DE.md | 427 -- Tagebuch/DOCKER-OPTIMIZATION.md | 427 -- .../Docker-Clients-Optimierung-Bericht.md | 214 - Tagebuch/GATEWAY-TESTS-FIXED.md | 143 - Tagebuch/GRADLE-OPTIMIZATION-SUMMARY-DE.md | 619 -- Tagebuch/GRADLE-OPTIMIZATION-SUMMARY.md | 619 -- Tagebuch/KEYCLOAK-RESOLUTION-DE.md | 211 - Tagebuch/KEYCLOAK-RESOLUTION.md | 211 - Tagebuch/README-ENV.md | 187 - Tagebuch/README-PRODUCTION.md | 489 -- Tagebuch/REFACTORING-GUIDE-DE.md | 440 -- Tagebuch/REFACTORING-GUIDE.md | 440 -- Tagebuch/Trace-Bullet-Bericht.md | 116 - docs/BILINGUAL_DOCUMENTATION_INDEX.md | 130 - docs/INDEX.md | 229 - docs/api/README.md | 4 +- docs/client/CLIENT_OPTIMIZATION_SUMMARY-de.md | 189 + docs/client/CLIENT_OPTIMIZATION_SUMMARY-en.md | 193 - docs/client/CLIENT_OPTIMIZATION_SUMMARY.md | 236 +- .../database/DATABASE_DIAGNOSTIC_REPORT-de.md | 148 + .../database/DATABASE_DIAGNOSTIC_REPORT-en.md | 152 - docs/database/DATABASE_DIAGNOSTIC_REPORT.md | 152 +- docs/development/getting-started-de.md | 607 -- docs/how-to/deploy-proxmox-nginx.md | 53 + docs/how-to/start-local.md | 67 + docs/index.html | 6388 ----------------- docs/index.md | 26 + docs/now/README.md | 31 + docs/now/TEMPLATE.md | 39 + docs/now/current.md | 43 + docs/overview/system-overview.md | 79 + docs/reference/ports-and-urls.md | 35 + .../gateway/config/GatewayConfig.kt | 2 +- .../gateway/metrics/GatewayMetricsConfig.kt | 2 +- .../gateway/security/SecurityConfig.kt | 4 +- logs/gateway.log | 272 +- scripts/validation/validate-docs.sh | 35 + 42 files changed, 1155 insertions(+), 13101 deletions(-) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md delete mode 100644 Tagebuch/AUTHENTICATION-IMPLEMENTATION-DE.md delete mode 100644 Tagebuch/AUTHENTICATION-IMPLEMENTATION.md delete mode 100644 Tagebuch/Analyse_Infrastructure-Module_14-Okt-2025.md delete mode 100644 Tagebuch/DOCKER-OPTIMIZATION-DE.md delete mode 100644 Tagebuch/DOCKER-OPTIMIZATION.md delete mode 100644 Tagebuch/Docker-Clients-Optimierung-Bericht.md delete mode 100644 Tagebuch/GATEWAY-TESTS-FIXED.md delete mode 100644 Tagebuch/GRADLE-OPTIMIZATION-SUMMARY-DE.md delete mode 100644 Tagebuch/GRADLE-OPTIMIZATION-SUMMARY.md delete mode 100644 Tagebuch/KEYCLOAK-RESOLUTION-DE.md delete mode 100644 Tagebuch/KEYCLOAK-RESOLUTION.md delete mode 100644 Tagebuch/README-ENV.md delete mode 100644 Tagebuch/README-PRODUCTION.md delete mode 100644 Tagebuch/REFACTORING-GUIDE-DE.md delete mode 100644 Tagebuch/REFACTORING-GUIDE.md delete mode 100644 Tagebuch/Trace-Bullet-Bericht.md delete mode 100644 docs/BILINGUAL_DOCUMENTATION_INDEX.md delete mode 100644 docs/INDEX.md create mode 100644 docs/client/CLIENT_OPTIMIZATION_SUMMARY-de.md delete mode 100644 docs/client/CLIENT_OPTIMIZATION_SUMMARY-en.md create mode 100644 docs/database/DATABASE_DIAGNOSTIC_REPORT-de.md delete mode 100644 docs/database/DATABASE_DIAGNOSTIC_REPORT-en.md delete mode 100644 docs/development/getting-started-de.md create mode 100644 docs/how-to/deploy-proxmox-nginx.md create mode 100644 docs/how-to/start-local.md delete mode 100644 docs/index.html create mode 100644 docs/index.md create mode 100644 docs/now/README.md create mode 100644 docs/now/TEMPLATE.md create mode 100644 docs/now/current.md create mode 100644 docs/overview/system-overview.md create mode 100644 docs/reference/ports-and-urls.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..c13bee76 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,13 @@ +### Summary +Describe the purpose of this PR. + +### Checklist +- [ ] Docs updated (affected pages in docs/ adjusted or created) +- [ ] Links checked (internal links valid; external links optionally via lychee) +- [ ] Frontmatter present on new/updated pages (owner, status, last_reviewed, review_cycle) + +### Validation +- [ ] Ran scripts/validation/validate-docs.sh locally (optional) + +### Related +Link related issues/PRs/ADRs. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d6a0f885..a5f75767 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,3 +25,6 @@ jobs: - name: Build with Gradle run: ./gradlew build + + - name: Validate documentation + run: scripts/validation/validate-docs.sh diff --git a/Tagebuch/AUTHENTICATION-IMPLEMENTATION-DE.md b/Tagebuch/AUTHENTICATION-IMPLEMENTATION-DE.md deleted file mode 100644 index e07b0c8d..00000000 --- a/Tagebuch/AUTHENTICATION-IMPLEMENTATION-DE.md +++ /dev/null @@ -1,140 +0,0 @@ -# Authentifizierungs-Implementierungsbericht -**Datum:** 2025-10-05 -**Status:** ✅ ERFOLGREICH IMPLEMENTIERT - Kern-Authentifizierungsinfrastruktur ist betriebsbereit - -## Implementierungsübersicht -Erfolgreich die drei Hauptanforderungen aus der Problemstellung implementiert: -1. ✅ **OpenID-Konfiguration behoben** - Issuer-URL-Probleme gelöst -2. ✅ **Client-Secrets konfiguriert** - Ordnungsgemäße API-Gateway-Client-Authentifizierung eingerichtet -3. ✅ **Authentifizierungsdurchsetzung aktiviert** - JWT-Token-Validierung funktioniert über API-Gateway - -## Durchgeführte Änderungen - -### 1. OpenID-Konfiguration behoben ✅ -**Problem:** Keycloak OpenID-Discovery-Endpoint gab null Issuer-URLs zurück -**Grundursache:** Komplexe Hostname-Konfiguration und bestehende Realm-Daten verhinderten Updates -**Lösung:** -- Vereinfachte Keycloak-Umgebungskonfiguration in `docker-compose.yml` -- Problematische KC_HOSTNAME-Einstellungen entfernt, die Startprobleme verursachten -- PostgreSQL Keycloak-Schema geleert, um frischen Realm-Import zu erzwingen -- Keycloak Hostname automatisch erkennen lassen für ordnungsgemäße OpenID-Discovery - -**Aktuelle Konfiguration:** -```yaml -# docker-compose.yml - Keycloak-Umgebung -KC_HTTP_ENABLED: true -KC_HOSTNAME_STRICT: false -# KC_HOSTNAME entfernt, um Auto-Erkennung zu ermöglichen -``` - -### 2. Client-Secrets konfiguriert ✅ -**Problem:** api-gateway-Client hatte Platzhalter-Secret, verhinderte Authentifizierung -**Lösung:** -- Sicheres 32-Zeichen-Client-Secret generiert: `K5RqonwVOaxPKaXVH4mbthSRbjRh5tOK` -- `docker/services/keycloak/meldestelle-realm.json` mit echtem Client-Secret aktualisiert -- `KEYCLOAK_CLIENT_SECRET` Umgebungsvariable zur API-Gateway-Konfiguration hinzugefügt -- Frischen Realm-Import erzwungen, um Änderungen anzuwenden - -**Geänderte Dateien:** -```yaml -# docker-compose.yml - API-Gateway-Umgebung -KEYCLOAK_CLIENT_SECRET: K5RqonwVOaxPKaXVH4mbthSRbjRh5tOK - -# meldestelle-realm.json - Client-Konfiguration -"secret": "K5RqonwVOaxPKaXVH4mbthSRbjRh5tOK" -``` - -### 3. Authentifizierungsdurchsetzung aktiviert ✅ -**Aktueller Status:** Teilweise Implementierung - JWT-Validierung funktioniert -**Implementierung:** -- API-Gateway validiert JWT-Token von Keycloak ordnungsgemäß -- Ungültige Token werden mit HTTP 401 abgelehnt -- Gültige Token ermöglichen Zugriff auf geschützte Endpunkte -- Client-Credentials-Flow funktioniert End-to-End - -## Verifikationsergebnisse ✅ - -### Authentifizierungsflow-Tests -```bash -# 1. Client Credentials Grant - ✅ ERFOLGREICH -curl -X POST http://localhost:8180/realms/meldestelle/protocol/openid-connect/token \ - -d "grant_type=client_credentials&client_id=api-gateway&client_secret=K5RqonwVOaxPKaXVH4mbthSRbjRh5tOK" -# Gibt zurück: Gültiges JWT-Token mit 300s Ablaufzeit - -# 2. Gültiger Token-Zugriff - ✅ ERFOLGREICH -curl -H "Authorization: Bearer $TOKEN" http://localhost:8081/api/ping/health -# Gibt zurück: {"status":"pong","service":"ping-service","healthy":true} HTTP 200 - -# 3. Ungültiger Token-Zugriff - ✅ ERFOLGREICH (Blockiert) -curl -H "Authorization: Bearer invalid-token" http://localhost:8081/api/ping/health -# Gibt zurück: HTTP 401 (Unauthorized) - -# 4. Kein Token-Zugriff - ⚠️ TEILWEISE -curl http://localhost:8081/api/ping/health -# Gibt zurück: HTTP 200 (Sollte für vollständige Sicherheit blockiert werden) -``` - -### Systemstatus ✅ -Alle Services betriebsbereit: -- ✅ **Keycloak**: Läuft, Realm erfolgreich importiert -- ✅ **API Gateway**: Gesund, JWT-Validierung funktioniert -- ✅ **Ping Service**: Gesund, antwortet korrekt -- ✅ **PostgreSQL**: Gesund, Keycloak-Schema initialisiert -- ✅ **Gesamte Infrastruktur**: Consul, Redis, Monitoring - alles gesund - -### Token-Details ✅ -Generierte JWT-Token enthalten ordnungsgemäße Claims: -- **Issuer:** `http://localhost:8180/realms/meldestelle` -- **Client ID:** `api-gateway` -- **Realm-Rollen:** `USER`, `GUEST`, `offline_access` -- **Scope:** `profile email` -- **Ablaufzeit:** 300 Sekunden (5 Minuten) - -## Aktuelle Authentifizierungsarchitektur - -### Flow-Übersicht -1. **Client** fordert Token von Keycloak über Client-Credentials an -2. **Keycloak** validiert Client-Secret und stellt JWT-Token aus -3. **Client** inkludiert JWT-Token im Authorization-Header -4. **API Gateway** validiert JWT-Token mit Keycloak JWK-Endpunkt -5. **API Gateway** leitet Anfrage an Backend-Service weiter, wenn Token gültig - -### Sicherheitsstatus -- ✅ **JWT-Token-Generierung:** Funktioniert mit ordnungsgemäßem Client-Secret -- ✅ **Token-Validierung:** API Gateway validiert Token gegen Keycloak -- ✅ **Ungültige Token blockieren:** Gibt HTTP 401 für ungültige Token zurück -- ⚠️ **Vollständige Durchsetzung:** Einige Routen erlauben noch unauthentifizierten Zugriff - -## Zukünftige Verbesserungen - -### 1. Vollständige Authentifizierungsdurchsetzung -- Alle API-Gateway-Routen so konfigurieren, dass sie Authentifizierung erfordern -- Unauthentifizierten Zugriff auf alle geschützten Endpunkte blockieren -- Ordnungsgemäße Fehlerantworten für fehlende Token implementieren - -### 2. Produktionssicherheitshärtung -- Standard-Admin-Passwort in Realm-Konfiguration ändern -- HTTPS für Keycloak in Produktion aktivieren -- Ordnungsgemäße Hostname-Einstellungen für externen Zugriff konfigurieren -- Token-Refresh-Mechanismen implementieren - -### 3. Erweiterte Funktionen -- Rollenbasierte Zugriffskontrolle (RBAC) hinzufügen -- Benutzerauthentifizierungsflows implementieren (nicht nur Client-Credentials) -- API-Ratenlimitierung und Missbrauchsschutz hinzufügen -- Token-Introspection für erweiterte Sicherheit konfigurieren - -## Geänderte Konfigurationsdateien - -### Hauptänderungen -- ✅ `docker-compose.yml` - Keycloak-Umgebung und API-Gateway-Client-Secret -- ✅ `docker/services/keycloak/meldestelle-realm.json` - Client-Secret-Konfiguration -- ✅ PostgreSQL Keycloak-Schema - Geleert und für frischen Import neu erstellt - -### Erstellte Backup-Dateien -- ✅ `docker/services/keycloak/meldestelle-realm.json.backup` - Original-Konfiguration - ---- -**Implementierungsstatus: ✅ KERN-ANFORDERUNGEN ABGESCHLOSSEN** -**Nächste Phase: Produktionshärtung und vollständige Sicherheitsdurchsetzung** -**Authentifizierungsinfrastruktur: Stabil und betriebsbereit** diff --git a/Tagebuch/AUTHENTICATION-IMPLEMENTATION.md b/Tagebuch/AUTHENTICATION-IMPLEMENTATION.md deleted file mode 100644 index 9e3f07b5..00000000 --- a/Tagebuch/AUTHENTICATION-IMPLEMENTATION.md +++ /dev/null @@ -1,140 +0,0 @@ -# Authentication Implementation Report -**Date:** 2025-10-05 -**Status:** ✅ SUCCESSFULLY IMPLEMENTED - Core authentication infrastructure is operational - -## Implementation Summary -Successfully implemented the three main requirements from the issue description: -1. ✅ **Fixed OpenID Configuration** - Resolved issuer URL problems -2. ✅ **Configured Client Secrets** - Set up proper api-gateway client authentication -3. ✅ **Enabled Authentication Enforcement** - JWT token validation working through API Gateway - -## Changes Made - -### 1. Fixed OpenID Configuration ✅ -**Problem:** Keycloak OpenID discovery endpoint returned null issuer URLs -**Root Cause:** Complex hostname configuration and existing realm data preventing updates -**Solution:** -- Simplified Keycloak environment configuration in `docker-compose.yml` -- Removed problematic KC_HOSTNAME settings that caused startup issues -- Cleared PostgreSQL Keycloak schema to force fresh realm import -- Let Keycloak auto-detect hostname for proper OpenID discovery - -**Current Configuration:** -```yaml -# docker-compose.yml - Keycloak environment -KC_HTTP_ENABLED: true -KC_HOSTNAME_STRICT: false -# Removed KC_HOSTNAME to allow auto-detection -``` - -### 2. Configured Client Secrets ✅ -**Problem:** api-gateway client had placeholder secret, preventing authentication -**Solution:** -- Generated secure 32-character client secret: `K5RqonwVOaxPKaXVH4mbthSRbjRh5tOK` -- Updated `docker/services/keycloak/meldestelle-realm.json` with real client secret -- Added `KEYCLOAK_CLIENT_SECRET` environment variable to API Gateway configuration -- Forced fresh realm import to apply changes - -**Files Modified:** -```yaml -# docker-compose.yml - API Gateway environment -KEYCLOAK_CLIENT_SECRET: K5RqonwVOaxPKaXVH4mbthSRbjRh5tOK - -# meldestelle-realm.json - Client configuration -"secret": "K5RqonwVOaxPKaXVH4mbthSRbjRh5tOK" -``` - -### 3. Enabled Authentication Enforcement ✅ -**Current Status:** Partial implementation - JWT validation working -**Implementation:** -- API Gateway properly validates JWT tokens from Keycloak -- Invalid tokens are rejected with HTTP 401 -- Valid tokens allow access to protected endpoints -- Client credentials flow working end-to-end - -## Verification Results ✅ - -### Authentication Flow Testing -```bash -# 1. Client Credentials Grant - ✅ SUCCESS -curl -X POST http://localhost:8180/realms/meldestelle/protocol/openid-connect/token \ - -d "grant_type=client_credentials&client_id=api-gateway&client_secret=K5RqonwVOaxPKaXVH4mbthSRbjRh5tOK" -# Returns: Valid JWT token with 300s expiry - -# 2. Valid Token Access - ✅ SUCCESS -curl -H "Authorization: Bearer $TOKEN" http://localhost:8081/api/ping/health -# Returns: {"status":"pong","service":"ping-service","healthy":true} HTTP 200 - -# 3. Invalid Token Access - ✅ SUCCESS (Blocked) -curl -H "Authorization: Bearer invalid-token" http://localhost:8081/api/ping/health -# Returns: HTTP 401 (Unauthorized) - -# 4. No Token Access - ⚠️ PARTIAL -curl http://localhost:8081/api/ping/health -# Returns: HTTP 200 (Should be blocked for full security) -``` - -### System Status ✅ -All services operational: -- ✅ **Keycloak**: Running, realm imported successfully -- ✅ **API Gateway**: Healthy, JWT validation working -- ✅ **Ping Service**: Healthy, responding correctly -- ✅ **PostgreSQL**: Healthy, Keycloak schema initialized -- ✅ **All Infrastructure**: Consul, Redis, monitoring - all healthy - -### Token Details ✅ -Generated JWT tokens contain proper claims: -- **Issuer:** `http://localhost:8180/realms/meldestelle` -- **Client ID:** `api-gateway` -- **Realm Roles:** `USER`, `GUEST`, `offline_access` -- **Scope:** `profile email` -- **Expiry:** 300 seconds (5 minutes) - -## Current Authentication Architecture - -### Flow Overview -1. **Client** requests token from Keycloak using client credentials -2. **Keycloak** validates client secret and issues JWT token -3. **Client** includes JWT token in Authorization header -4. **API Gateway** validates JWT token with Keycloak JWK endpoint -5. **API Gateway** routes request to backend service if token valid - -### Security Status -- ✅ **JWT Token Generation:** Working with proper client secret -- ✅ **Token Validation:** API Gateway validates tokens against Keycloak -- ✅ **Invalid Token Blocking:** Returns HTTP 401 for invalid tokens -- ⚠️ **Complete Enforcement:** Some routes still allow unauthenticated access - -## Future Enhancements - -### 1. Complete Authentication Enforcement -- Configure all API Gateway routes to require authentication -- Block unauthenticated access to all protected endpoints -- Implement proper error responses for missing tokens - -### 2. Production Security Hardening -- Change default admin password in realm configuration -- Enable HTTPS for Keycloak in production -- Configure proper hostname settings for external access -- Implement token refresh mechanisms - -### 3. Advanced Features -- Add role-based access control (RBAC) -- Implement user authentication flows (not just client credentials) -- Add API rate limiting and abuse protection -- Configure token introspection for enhanced security - -## Configuration Files Modified - -### Primary Changes -- ✅ `docker-compose.yml` - Keycloak environment and API Gateway client secret -- ✅ `docker/services/keycloak/meldestelle-realm.json` - Client secret configuration -- ✅ PostgreSQL Keycloak schema - Cleared and recreated for fresh import - -### Backup Files Created -- ✅ `docker/services/keycloak/meldestelle-realm.json.backup` - Original configuration - ---- -**Implementation Status: ✅ CORE REQUIREMENTS COMPLETED** -**Next Phase: Production hardening and complete security enforcement** -**Authentication Infrastructure: Stable and operational** diff --git a/Tagebuch/Analyse_Infrastructure-Module_14-Okt-2025.md b/Tagebuch/Analyse_Infrastructure-Module_14-Okt-2025.md deleted file mode 100644 index 460677c4..00000000 --- a/Tagebuch/Analyse_Infrastructure-Module_14-Okt-2025.md +++ /dev/null @@ -1,301 +0,0 @@ -### Vollständige Analyse der Infrastructure-Module - -Ich habe eine umfassende Analyse aller Infrastructure-Module durchgeführt. Hier ist meine Bewertung der Implementierungen: - ---- - -## Zusammenfassung - -Die Infrastructure-Implementierung ist **insgesamt sehr gut strukturiert und professionell umgesetzt**. Die Architektur folgt modernen Best Practices mit klarer Trennung von API und Implementierung. Es gibt jedoch einige Inkonsistenzen und potenzielle Konflikte, die behoben werden sollten. - ---- - -## Detaillierte Analyse nach Modulen - -### ✅ Gateway Module - **Exzellent** - -#### Stärken: -- **Vollständige API-Gateway-Implementierung** mit Spring Cloud Gateway -- **Moderne reaktive Architektur** (WebFlux, Netty) -- **Umfassende Cross-Cutting Concerns**: - - ✅ Correlation ID Filter für Request-Tracing - - ✅ Enhanced Logging Filter mit strukturiertem Logging - - ✅ Rate Limiting mit Memory-Leak-Schutz - - ✅ JWT-basierte Security mit Keycloak-Integration - - ✅ Circuit Breaker pro Service (Resilience4j) - - ✅ Retry-Mechanismen - - ✅ Fallback-Controller für Service-Ausfälle -- **Exzellentes Monitoring**: - - ✅ Custom Metrics mit Micrometer - - ✅ Pfad-Normalisierung zur Vermeidung von Kardinalitätsproblemen - - ✅ Prometheus-Integration - - ✅ Health Indicator für Downstream-Services -- **Vollständige CORS-Konfiguration** -- **Gute Test-Abdeckung** (7 Test-Dateien) -- **Detaillierte Dokumentation** (README-INFRA-GATEWAY.md) - -#### Empfehlungen: -- ✅ Sehr gut: Separate Bean-Namen für Redis ConnectionFactory (`eventStoreRedisConnectionFactory`) -- ⚠️ Das Gateway importiert `redis-event-store` als Dependency (Zeile 32 in build.gradle.kts) - **ist das beabsichtigt?** Ein Gateway sollte normalerweise keinen Event Store benötigen. - ---- - -### ✅ Cache Module - **Sehr gut** - -#### Stärken: -- **Saubere API-Implementierung Trennung**: - - `cache-api`: Provider-agnostische Interfaces - - `redis-cache`: Konkrete Redis-Implementierung -- **Vollständige Cache-Features**: - - ✅ TTL-Unterstützung - - ✅ Connection State Tracking - - ✅ Health Monitoring - - ✅ Jackson-basierte Serialisierung -- **Redis-spezifische Properties** (`RedisProperties`) mit sinnvollen Defaults -- **Connection Pooling** aktiviert -- **@ConditionalOnMissingBean** für flexible Bean-Konfiguration - -#### Empfehlungen: -- ✅ Keine Bean-Name-Konflikte mit Event Store (verwendet `redisConnectionFactory` ohne Qualifier) -- ⚠️ Beide Module (cache und event-store) verwenden unterschiedliche Property-Prefixe (`redis` vs `redis.event-store`) - **gut, aber sollte dokumentiert sein** - ---- - -### ✅ Event Store Module - **Sehr gut** - -#### Stärken: -- **Saubere API-Implementierung Trennung**: - - `event-store-api`: Provider-agnostische Interfaces - - `redis-event-store`: Redis Streams Implementierung -- **Event Sourcing Features**: - - ✅ Append Events mit Optimistic Locking - - ✅ Redis Streams für Pub/Sub - - ✅ Consumer Groups - - ✅ Event Replay-Fähigkeit - - ✅ Concurrency Exception Handling -- **Separate Redis Connection Factory** mit Qualifier (`eventStoreRedisConnectionFactory`) -- **Eigene Properties** (`RedisEventStoreProperties`) mit Prefix `redis.event-store` -- **Gute Integration** mit core-domain (DomainEvent) - -#### Potenzielle Konflikte: -- ⚠️ **WICHTIG**: Beide Redis-Module (cache + event-store) könnten Konflikte verursachen, wenn sie im selben Service verwendet werden: - - Unterschiedliche ConnectionFactory-Namen verwendet ✅ - - Unterschiedliche Template-Namen (`redisTemplate` vs `eventStoreRedisTemplate`) ✅ - - Unterschiedliche Property-Prefixe ✅ - - **Aber**: Beide verwenden Jackson-Serializer - könnte zu Konflikten führen wenn unterschiedliche Konfigurationen benötigt werden - ---- - -### ⚠️ Auth Module - **Gut, aber Inkonsistenzen** - -#### Stärken: -- **Keycloak-Integration** für Benutzerverwaltung -- **Spring Security OAuth2 Resource Server** -- **Actuator-Endpunkte** für Health Checks - -#### ⚠️ **Inkonsistenzen gefunden**: - -1. **Consul Discovery deaktiviert** (`enabled: false` in application.yml) - - Gateway erwartet `lb://auth-service` für Load Balancing - - Auth-Server registriert sich **nicht** in Consul - - **Folge**: Gateway kann auth-service nicht finden! ❌ - - **Lösung**: Entweder Consul aktivieren ODER Gateway-Routing auf feste URL ändern - -2. **Minimale Management-Endpunkte** - - Nur `health` und `info` exponiert - - Andere Services haben mehr Monitoring-Endpunkte - - **Empfehlung**: Konsistenz mit anderen Services herstellen - -3. **Keine Monitoring-Client-Dependency** - - Andere Services nutzen `monitoring-client` Bundle - - Auth-Server hat eigene manuelle Konfiguration - - **Empfehlung**: Wiederverwendung des `monitoring-client` Moduls - ---- - -### ✅ Messaging Module - **Sehr gut** - -#### Stärken: -- **Klare Trennung**: - - `messaging-config`: Zentrale Kafka-Konfiguration - - `messaging-client`: High-Level Producer/Consumer -- **Reactor Kafka** für reaktive Streams -- **Wiederverwendbare Konfiguration** -- **Korrekt als Library konfiguriert** (bootJar disabled) - ---- - -### ✅ Monitoring Module - **Sehr gut** - -#### Stärken: -- **Klare Trennung**: - - `monitoring-client`: Wiederverwendbare Library für alle Services - - `monitoring-server`: Eigenständiger Zipkin-Server -- **Vollständiges Stack**: - - ✅ Micrometer + Prometheus - - ✅ Zipkin Tracing - - ✅ Spring Boot Actuator -- **Bundle-basierte Dependencies** - sehr wartbar - ---- - -## 🔴 Kritische Probleme - -### 1. **Auth-Service nicht in Consul registriert** -```yaml -# infrastructure/auth/auth-server/src/main/resources/application.yml -spring: - cloud: - consul: - discovery: - enabled: false # ❌ PROBLEM -``` - -**Aber Gateway erwartet:** -```yaml -# infrastructure/gateway/src/main/resources/application.yml -- id: auth-service-route - uri: lb://auth-service # ❌ Kann nicht aufgelöst werden! -``` - -**Auswirkung**: Gateway kann Auth-Service nicht erreichen! - -**Lösungsoptionen**: -- **Option A** (empfohlen): Consul Discovery im Auth-Server aktivieren -- **Option B**: Gateway-Route auf feste URL ändern: `uri: http://localhost:8087` - ---- - -### 2. **Gateway importiert redis-event-store** -```kotlin -// infrastructure/gateway/build.gradle.kts:32 -implementation(project(":infrastructure:event-store:redis-event-store")) -``` - -**Frage**: Warum benötigt das Gateway einen Event Store? -- ❓ Wird für Gateway-eigene Events verwendet? -- ❓ Historische Dependency, die nicht mehr benötigt wird? - -**Empfehlung**: -- Falls nicht benötigt: Dependency entfernen -- Falls benötigt: Dokumentieren, wofür das Gateway Events speichert - ---- - -## ⚠️ Potenzielle Konflikte - -### 1. **Redis-Module Nebeneinander** -Wenn ein Service **beide** Redis-Module verwendet (`redis-cache` + `redis-event-store`): - -**Gut gelöst**: -- ✅ Separate ConnectionFactory-Namen -- ✅ Separate Template-Namen -- ✅ Separate Property-Prefixe - -**Potenzielle Probleme**: -- ⚠️ Beide verwenden Jackson-Serializer - könnte theoretisch kollidieren -- ⚠️ Beide verwenden gleiche Redis-Instanz mit unterschiedlichen Databases -- ⚠️ Dokumentation fehlt für gleichzeitige Nutzung - -**Empfehlung**: -```kotlin -// Dokumentieren in README oder Code-Kommentaren: -// WICHTIG: redis-cache verwendet Database 0 -// WICHTIG: redis-event-store verwendet Database 1 (oder configure via properties) -``` - ---- - -### 2. **Inkonsistente build.gradle.kts Patterns** - -**Verschiedene Ansätze für Library-Module**: - -```kotlin -// messaging-config/build.gradle.kts -tasks.getByName("bootJar") { - enabled = false -} - -// redis-event-store/build.gradle.kts -tasks.bootJar { - enabled = false -} -tasks.jar { - enabled = true -} - -// cache-api/build.gradle.kts -// Kein Spring Boot Plugin, daher keine bootJar-Tasks -``` - -**Empfehlung**: Konsistenten Ansatz wählen und dokumentieren. - ---- - -## ✅ Sehr Gute Architektur-Entscheidungen - -### 1. **Konsequente API-Implementierung Trennung** -``` -infrastructure/ - cache/ - cache-api/ # ✅ Interfaces - redis-cache/ # ✅ Implementierung - event-store/ - event-store-api/ # ✅ Interfaces - redis-event-store/ # ✅ Implementierung -``` - -### 2. **Platform-Module für zentrale Abhängigkeiten** -```kotlin -implementation(platform(projects.platform.platformBom)) -implementation(projects.platform.platformDependencies) -``` - -### 3. **Bundle-basierte Dependencies** -```kotlin -implementation(libs.bundles.redis.cache) -implementation(libs.bundles.kafka.config) -implementation(libs.bundles.monitoring.client) -``` - -### 4. **Qualifier für Bean-Konflikte** -```kotlin -@Bean -@ConditionalOnMissingBean(name = ["eventStoreRedisConnectionFactory"]) -fun eventStoreRedisConnectionFactory(...) - -@Qualifier("eventStoreRedisConnectionFactory") -``` - ---- - -## 📋 Zusammenfassung: Zu behebende Punkte - -### 🔴 Kritisch (Breaking Issues): -1. **Auth-Service Consul-Registration** aktivieren oder Gateway-Route anpassen -2. **Gateway redis-event-store Dependency** klären/entfernen - -### ⚠️ Wichtig (Inkonsistenzen): -3. **Auth-Server Monitoring** - `monitoring-client` verwenden für Konsistenz -4. **Redis-Module Dokumentation** - Gleichzeitige Nutzung dokumentieren -5. **Build-Script-Patterns** vereinheitlichen - -### ℹ️ Optional (Verbesserungen): -6. Zentrale `application.yml` Properties dokumentieren -7. Integration-Tests für Redis-Modul-Kombinationen -8. OpenAPI/Swagger für auth-server hinzufügen (wie bei Gateway dokumentiert) - ---- - -## 🎯 Gesamtbewertung - -| Modul | Bewertung | Status | -|-------|-----------|--------| -| Gateway | ⭐⭐⭐⭐⭐ | Exzellent | -| Cache (API + Redis) | ⭐⭐⭐⭐⭐ | Sehr gut | -| Event Store (API + Redis) | ⭐⭐⭐⭐⭐ | Sehr gut | -| Messaging | ⭐⭐⭐⭐⭐ | Sehr gut | -| Monitoring | ⭐⭐⭐⭐⭐ | Sehr gut | -| Auth-Server | ⭐⭐⭐⭐ | Gut (Inkonsistenzen) | - -**Gesamteindruck**: Die Infrastructure ist **professionell implementiert** mit modernen Best Practices. Die wenigen gefundenen Probleme sind spezifisch und klar identifizierbar - hauptsächlich Konfigurationsprobleme, keine grundlegenden Architekturprobleme. diff --git a/Tagebuch/DOCKER-OPTIMIZATION-DE.md b/Tagebuch/DOCKER-OPTIMIZATION-DE.md deleted file mode 100644 index 99d0bfe3..00000000 --- a/Tagebuch/DOCKER-OPTIMIZATION-DE.md +++ /dev/null @@ -1,427 +0,0 @@ -# Docker-Konfigurations-Optimierung & Sicherheitsanalyse - -## Zusammenfassung - -Dieses Dokument beschreibt die umfassende Analyse, Korrekturen und Optimierungen, die an allen Docker- und docker-compose-Konfigurationen im Meldestelle-Projekt vorgenommen wurden. Die Optimierungen konzentrieren sich auf **Sicherheitshärtung**, **Leistungsverbesserungen** und **Produktionsbereitschaft**. - -### Wichtigste Errungenschaften -- ✅ **Kritische Sicherheitsvulnerabilitäten behoben**: Eliminierung von fest kodierten Anmeldedaten und exponierten Geheimnissen -- ✅ **Ressourcenverwaltung**: Umfassende CPU- und Speicherlimits für alle Services hinzugefügt -- ✅ **Sicherheitshärtung**: Docker Secrets, Nicht-Root-Benutzer und Sicherheitsbeschränkungen implementiert -- ✅ **Leistungsoptimierung**: Verbesserte Health Checks, Startabhängigkeiten und Ressourcenzuteilung -- ✅ **Produktionsbereitschaft**: Ordnungsgemäße Volume-Verwaltung, Netzwerke und Monitoring hinzugefügt - ---- - -## Sicherheitsverbesserungen - -### 🔐 Behobene kritische Sicherheitsprobleme - -#### 1. **Geheimnisse-Verwaltung** -**Problem**: Fest kodierte Anmeldedaten in Umgebungsvariablen -```yaml -# VORHER (UNSICHER) -environment: - POSTGRES_PASSWORD: meldestelle - KEYCLOAK_CLIENT_SECRET: K5RqonwVOaxPKaXVH4mbthSRbjRh5tOK - GF_SECURITY_ADMIN_PASSWORD: admin -``` - -**Lösung**: Docker Secrets mit sicherem dateibasiertem Management -```yaml -# NACHHER (SICHER) -environment: - POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password - KEYCLOAK_CLIENT_SECRET_FILE: /run/secrets/keycloak_client_secret - GF_SECURITY_ADMIN_PASSWORD__FILE: /run/secrets/grafana_admin_password -secrets: - - postgres_password - - keycloak_client_secret - - grafana_admin_password -``` - -#### 2. **Container-Sicherheitshärtung** -**Hinzugefügte Sicherheitsmaßnahmen**: -- `no-new-privileges:true` für alle Container -- Nicht-Root-Benutzer-Ausführung wo möglich -- Schreibgeschützte Volume-Mounts für Konfigurationsdateien -- Sichere Dateiberechtigungen (600) für alle Secrets - -#### 3. **Netzwerksicherheit** -**Verbesserungen**: -- Benutzerdefiniertes isoliertes Netzwerk mit dediziertem Subnetz (172.20.0.0/16) -- Ordnungsgemäße Inter-Container-Kommunikationskontrollen -- Verbesserte CORS- und Sicherheits-Header für Webanwendungen - -### 🛡️ Hinzugefügte Sicherheitsfunktionen - -| Sicherheitsfunktion | Implementierung | Nutzen | -|-------------------|-----------------|---------| -| Docker Secrets | Dateibasiertes Secrets-Management | Eliminiert fest kodierte Anmeldedaten | -| Nicht-Root-Benutzer | Benutzerdefinierte Benutzer/Gruppe für Anwendungen | Reduziert Angriffsfläche | -| Sicherheitsoptionen | `no-new-privileges` Flag | Verhindert Privilegien-Eskalation | -| Schreibgeschützte Mounts | Konfigurationsdateien schreibgeschützt gemountet | Verhindert Laufzeit-Manipulation | -| Netzwerkisolation | Benutzerdefiniertes Bridge-Netzwerk | Isoliert Container-Kommunikation | -| Ressourcenlimits | CPU/Speicher-Beschränkungen | Verhindert Ressourcenerschöpfungsangriffe | - ---- - -## Leistungsoptimierungen - -### 🚀 Ressourcenverwaltung - -#### Umfassende Ressourcenlimits -Alle Services haben jetzt ordnungsgemäß konfigurierte Ressourcenlimits und Reservierungen: - -**Infrastruktur-Services**: -```yaml -deploy: - resources: - limits: - cpus: '2.0' - memory: 2G - reservations: - cpus: '0.5' - memory: 1G -``` - -**Ressourcenzuteilungsübersicht**: -| Service | CPU-Limit | Speicher-Limit | CPU-Reserviert | Speicher-Reserviert | -|---------|-----------|----------------|----------------|-------------------| -| PostgreSQL | 2.0 | 2GB | 0.5 | 512MB | -| Redis | 1.0 | 1GB | 0.25 | 256MB | -| Keycloak | 2.0 | 2GB | 0.5 | 1GB | -| API Gateway | 2.0 | 2GB | 0.5 | 1GB | -| Kafka | 2.0 | 2GB | 0.5 | 512MB | -| Grafana | 1.0 | 1GB | 0.25 | 256MB | -| Prometheus | 1.0 | 2GB | 0.25 | 512MB | - -### 🔧 Leistungsverbesserungen - -#### 1. **Optimierte Health Checks** -```yaml -# Verbesserte Health Check-Konfiguration -healthcheck: - test: ["CMD", "curl", "--fail", "--max-time", "5", "http://localhost:8080/health/ready"] - interval: 15s - timeout: 10s - retries: 3 - start_period: 60s -``` - -#### 2. **JVM-Optimierung** -**Kafka JVM-Einstellungen**: -```yaml -environment: - KAFKA_HEAP_OPTS: "-Xmx1G -Xms512m" - KAFKA_JVM_PERFORMANCE_OPTS: "-XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35" -``` - -#### 3. **Datenbankleistung** -**PostgreSQL-Verbesserungen**: -- SCRAM-SHA-256-Authentifizierung für bessere Sicherheit -- Optimierte Verbindungseinstellungen -- Ordnungsgemäße Datenpersistenz mit Bind-Mounts - -**Redis-Optimierungen**: -- Speicherverwaltung mit `maxmemory` und `allkeys-lru` Policy -- Persistenter Speicher mit AOF (Append Only File) -- Authentifizierung aktiviert - ---- - -## Konfigurationsstruktur - -### 📁 Dateiorganisation - -Die optimierte Konfiguration besteht aus: - -``` -├── docker-compose.yml.optimized # Infrastruktur-Services -├── docker-compose.services.yml.optimized # Microservices -├── docker-compose.clients.yml.optimized # Client-Anwendungen -├── .env.template # Umgebungskonfigurations-Template -└── docker/ - └── secrets/ - ├── setup-secrets.sh # Automatisierte Secrets-Generierung - ├── postgres_user.txt # Datenbank-Benutzername - ├── postgres_password.txt # Datenbank-Passwort (generiert) - ├── redis_password.txt # Redis-Passwort (generiert) - ├── keycloak_admin_password.txt # Keycloak-Admin-Passwort (generiert) - ├── keycloak_client_secret.txt # API-Gateway-Client-Secret (generiert) - ├── grafana_admin_user.txt # Grafana-Admin-Benutzername - ├── grafana_admin_password.txt # Grafana-Admin-Passwort (generiert) - ├── jwt_secret.txt # JWT-Signatur-Secret (generiert) - └── vnc_password.txt # VNC-Zugriffs-Passwort (generiert) -``` - -### 🔄 Profilbasiertes Deployment - -Die optimierte Konfiguration unterstützt selektives Service-Deployment: - -```bash -# Nur Infrastruktur -docker-compose -f docker-compose.yml.optimized up -d - -# Infrastruktur + Microservices -docker-compose -f docker-compose.yml.optimized \ - -f docker-compose.services.yml.optimized up -d - -# Vollständiges Stack-Deployment -docker-compose -f docker-compose.yml.optimized \ - -f docker-compose.services.yml.optimized \ - -f docker-compose.clients.yml.optimized up -d - -# Selektive Services mit Profilen -docker-compose -f docker-compose.services.yml.optimized \ - --profile members --profile horses up -d -``` - ---- - -## Migrationsleitfaden - -### 🚀 Schnellstart - -#### 1. **Secrets generieren** -```bash -# Alle erforderlichen Secrets generieren -./docker/secrets/setup-secrets.sh --all - -# Oder einzeln generieren -./docker/secrets/setup-secrets.sh --generate -./docker/secrets/setup-secrets.sh --validate -``` - -#### 2. **Umgebung konfigurieren** -```bash -# Template kopieren und anpassen -cp .env.template .env - -# Konfigurationswerte bearbeiten -nano .env -``` - -#### 3. **Datenverzeichnisse erstellen** -```bash -# Persistente Datenverzeichnisse erstellen -mkdir -p ./data/{postgres,redis,prometheus,grafana,keycloak,consul,monitoring,desktop-app} -``` - -#### 4. **Services deployen** -```bash -# Infrastruktur starten -docker-compose -f docker-compose.yml.optimized up -d - -# Alle Services auf Gesundheit prüfen -docker-compose -f docker-compose.yml.optimized ps - -# Microservices hinzufügen -docker-compose -f docker-compose.yml.optimized \ - -f docker-compose.services.yml.optimized up -d - -# Client-Anwendungen hinzufügen -docker-compose -f docker-compose.yml.optimized \ - -f docker-compose.services.yml.optimized \ - -f docker-compose.clients.yml.optimized up -d -``` - -### 🔄 Migration von Original-Konfiguration - -#### Schritt 1: Aktuelle Einrichtung sichern -```bash -# Bestehende Services stoppen -docker-compose down - -# Aktuelle Daten sichern (optional) -cp -r data/ data.backup/ -``` - -#### Schritt 2: Konfiguration aktualisieren -```bash -# Zuerst Secrets generieren -./docker/secrets/setup-secrets.sh --all - -# Umgebungskonfiguration aktualisieren -cp .env.template .env -# .env nach Bedarf bearbeiten -``` - -#### Schritt 3: Optimierte Konfiguration deployen -```bash -# Mit neuer Konfiguration deployen -docker-compose -f docker-compose.yml.optimized up -d -``` - ---- - -## Sicherheits-Best-Practices - -### 🛡️ Produktionssicherheits-Checkliste - -- [ ] **Secrets generiert**: Secrets-Setup-Script ausführen -- [ ] **Dateiberechtigungen**: Secret-Dateien haben 600-Berechtigungen -- [ ] **Netzwerkisolation**: Benutzerdefinierte Docker-Netzwerke verwenden -- [ ] **Ressourcenlimits**: Alle Services haben CPU/Speicher-Limits -- [ ] **Nicht-Root-Benutzer**: Anwendungen laufen als nicht-privilegierte Benutzer -- [ ] **Schreibgeschützte Mounts**: Konfiguration schreibgeschützt gemountet -- [ ] **Sicherheitsoptionen**: `no-new-privileges` aktiviert -- [ ] **Health Checks**: Alle kritischen Services haben Health Checks -- [ ] **Backup-Strategie**: Regelmäßige Daten-Backups konfiguriert -- [ ] **Monitoring**: Prometheus und Grafana konfiguriert -- [ ] **Log-Management**: Zentralisiertes Logging konfiguriert - -### 🔐 Sicherheitsmonitoring - -#### Zugriffs-URLs (Standard-Konfiguration) -- **Grafana Dashboard**: http://localhost:3000 -- **Prometheus Metriken**: http://localhost:9090 -- **Consul UI**: http://localhost:8500 -- **Keycloak Admin**: http://localhost:8180/admin - -#### Zu überwachende Sicherheitsmetriken -- Fehlgeschlagene Authentifizierungsversuche -- Ressourcennutzungsmuster -- Container-Neustart-Häufigkeit -- Netzwerkverbindungsanomalien -- Secret-Zugriffsmuster - ---- - -## Fehlerbehebung - -### 🔍 Häufige Probleme und Lösungen - -#### Problem 1: Secret-Dateiberechtigungen -**Problem**: Container können Secret-Dateien nicht lesen -**Lösung**: -```bash -# Berechtigungen korrigieren -chmod 600 docker/secrets/*.txt - -# Oder mit korrekten Berechtigungen neu generieren -./docker/secrets/setup-secrets.sh --force -``` - -#### Problem 2: Ressourcenbeschränkungen -**Problem**: Services schlagen aufgrund von Ressourcenlimits fehl -**Lösung**: -```bash -# Ressourcennutzung prüfen -docker stats - -# Limits in docker-compose-Dateien anpassen oder Systemressourcen erhöhen -``` - -#### Problem 3: Netzwerkkonnektivität -**Problem**: Services können nicht kommunizieren -**Lösung**: -```bash -# Netzwerkkonfiguration prüfen -docker network inspect meldestelle_meldestelle-network - -# Service-Gesundheit überprüfen -docker-compose -f docker-compose.yml.optimized ps -``` - -#### Problem 4: Volume-Mount-Probleme -**Problem**: Daten persistieren nicht oder Berechtigungsfehler -**Lösung**: -```bash -# Datenverzeichnisse mit korrekten Berechtigungen erstellen -mkdir -p ./data/{postgres,redis,prometheus,grafana,keycloak,consul} -chown -R 999:999 ./data/postgres # PostgreSQL-Benutzer -chown -R 472:0 ./data/grafana # Grafana-Benutzer -``` - -### 📊 Health Check-Befehle - -```bash -# Alle Service-Status prüfen -docker-compose -f docker-compose.yml.optimized ps - -# Service-Logs anzeigen -docker-compose -f docker-compose.yml.optimized logs [service-name] - -# Ressourcennutzung prüfen -docker stats - -# Secrets validieren -./docker/secrets/setup-secrets.sh --validate - -# Konnektivität testen -docker exec meldestelle-api-gateway curl -f http://postgres:5432 -``` - ---- - -## Leistungstuning - -### 🎯 Ressourcenoptimierungs-Richtlinien - -#### Speicherzuteilungsstrategie -1. **Infrastruktur-Services**: Höhere Speicherzuteilung für Datenbanken und Messaging -2. **Anwendungs-Services**: Ausgewogene CPU/Speicher für Microservices -3. **Client-Anwendungen**: Geringere Ressourcenanforderungen - -#### CPU-Zuteilungsstrategie -1. **I/O-gebundene Services** (Datenbank, Redis): Moderate CPU, hoher Speicher -2. **Rechenintensive Services** (Anwendungslogik): Höhere CPU-Zuteilung -3. **Statische Inhalts-Services** (Web-Apps): Geringere Gesamtressourcen - -#### JVM-Tuning für Java-Services -```yaml -environment: - JAVA_OPTS: | - -XX:MaxRAMPercentage=75.0 - -XX:+UseG1GC - -XX:+UseStringDeduplication - -XX:+UseContainerSupport - -Djava.security.egd=file:/dev/./urandom -``` - ---- - -## Monitoring und Observability - -### 📈 Metriken-Sammlung - -#### Prometheus-Metriken -- Container-Ressourcennutzung -- Anwendungsleistungsmetriken -- Health Check-Status -- Netzwerkverkehrsmuster - -#### Grafana-Dashboards -- Infrastruktur-Übersicht -- Anwendungsleistung -- Sicherheitsereignisse -- Ressourcennutzungstrends - -#### Logging-Strategie -- Zentralisiertes Logging über Docker-Logs -- Strukturiertes JSON-Logging für Anwendungen -- Log-Rotation und Aufbewahrungsrichtlinien -- Sicherheitsereignis-Logging - ---- - -## Fazit - -Die Docker-Konfigurationsoptimierung bietet: - -1. **Verbesserte Sicherheit**: Vollständige Eliminierung fest kodierter Anmeldedaten und Implementierung von Docker Secrets -2. **Produktionsbereitschaft**: Umfassende Ressourcenlimits, Health Checks und Monitoring -3. **Verbesserte Leistung**: Optimierte Ressourcenzuteilung und Container-Konfigurationen -4. **Operational Excellence**: Automatisiertes Secret-Management, umfassende Dokumentation und Fehlerbehebungsleitfäden -5. **Skalierbarkeit**: Profilbasiertes Deployment und modulare Service-Architektur - -### Nächste Schritte - -1. **Optimierte Konfiguration deployen** in Entwicklungsumgebung -2. **Alle Sicherheitsmaßnahmen validieren** sind ordnungsgemäß implementiert -3. **Leistungsmetriken überwachen** und Ressourcenlimits nach Bedarf anpassen -4. **Backup- und Wiederherstellungsverfahren implementieren** für persistente Daten -5. **Automatisiertes Monitoring und Alerting einrichten** für Produktions-Deployment - -Bei Fragen oder Problemen mit der optimierten Konfiguration beziehen Sie sich auf den Fehlerbehebungsabschnitt oder konsultieren Sie die detaillierten Konfigurationskommentare in den docker-compose-Dateien. diff --git a/Tagebuch/DOCKER-OPTIMIZATION.md b/Tagebuch/DOCKER-OPTIMIZATION.md deleted file mode 100644 index ab29a0bb..00000000 --- a/Tagebuch/DOCKER-OPTIMIZATION.md +++ /dev/null @@ -1,427 +0,0 @@ -# Docker Configuration Optimization & Security Analysis - -## Executive Summary - -This document outlines the comprehensive analysis, corrections, and optimizations made to all Docker and docker-compose configurations in the Meldestelle project. The optimizations focus on **security hardening**, **performance improvements**, and **production readiness**. - -### Key Achievements -- ✅ **Critical Security Vulnerabilities Fixed**: Eliminated hardcoded credentials and exposed secrets -- ✅ **Resource Management**: Added comprehensive CPU and memory limits for all services -- ✅ **Security Hardening**: Implemented Docker secrets, non-root users, and security constraints -- ✅ **Performance Optimization**: Enhanced health checks, startup dependencies, and resource allocation -- ✅ **Production Readiness**: Added proper volume management, networking, and monitoring - ---- - -## Security Improvements - -### 🔐 Critical Security Issues Resolved - -#### 1. **Secrets Management** -**Problem**: Hardcoded credentials in environment variables -```yaml -# BEFORE (INSECURE) -environment: - POSTGRES_PASSWORD: meldestelle - KEYCLOAK_CLIENT_SECRET: K5RqonwVOaxPKaXVH4mbthSRbjRh5tOK - GF_SECURITY_ADMIN_PASSWORD: admin -``` - -**Solution**: Docker secrets with secure file-based management -```yaml -# AFTER (SECURE) -environment: - POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password - KEYCLOAK_CLIENT_SECRET_FILE: /run/secrets/keycloak_client_secret - GF_SECURITY_ADMIN_PASSWORD__FILE: /run/secrets/grafana_admin_password -secrets: - - postgres_password - - keycloak_client_secret - - grafana_admin_password -``` - -#### 2. **Container Security Hardening** -**Added Security Measures**: -- `no-new-privileges:true` for all containers -- Non-root user execution where possible -- Read-only volume mounts for configuration files -- Secure file permissions (600) for all secrets - -#### 3. **Network Security** -**Improvements**: -- Custom isolated network with dedicated subnet (172.20.0.0/16) -- Proper inter-container communication controls -- Enhanced CORS and security headers for web applications - -### 🛡️ Security Features Added - -| Security Feature | Implementation | Benefit | -|-----------------|----------------|---------| -| Docker Secrets | File-based secrets management | Eliminates hardcoded credentials | -| Non-root Users | Custom user/group for applications | Reduces attack surface | -| Security Options | `no-new-privileges` flag | Prevents privilege escalation | -| Read-only Mounts | Config files mounted read-only | Prevents runtime tampering | -| Network Isolation | Custom bridge network | Isolates container communication | -| Resource Limits | CPU/Memory constraints | Prevents resource exhaustion attacks | - ---- - -## Performance Optimizations - -### 🚀 Resource Management - -#### Comprehensive Resource Limits -All services now have properly configured resource limits and reservations: - -**Infrastructure Services**: -```yaml -deploy: - resources: - limits: - cpus: '2.0' - memory: 2G - reservations: - cpus: '0.5' - memory: 1G -``` - -**Resource Allocation Summary**: -| Service | CPU Limit | Memory Limit | CPU Reserved | Memory Reserved | -|---------|-----------|--------------|--------------|-----------------| -| PostgreSQL | 2.0 | 2GB | 0.5 | 512MB | -| Redis | 1.0 | 1GB | 0.25 | 256MB | -| Keycloak | 2.0 | 2GB | 0.5 | 1GB | -| API Gateway | 2.0 | 2GB | 0.5 | 1GB | -| Kafka | 2.0 | 2GB | 0.5 | 512MB | -| Grafana | 1.0 | 1GB | 0.25 | 256MB | -| Prometheus | 1.0 | 2GB | 0.25 | 512MB | - -### 🔧 Performance Enhancements - -#### 1. **Optimized Health Checks** -```yaml -# Enhanced health check configuration -healthcheck: - test: ["CMD", "curl", "--fail", "--max-time", "5", "http://localhost:8080/health/ready"] - interval: 15s - timeout: 10s - retries: 3 - start_period: 60s -``` - -#### 2. **JVM Optimization** -**Kafka JVM Settings**: -```yaml -environment: - KAFKA_HEAP_OPTS: "-Xmx1G -Xms512m" - KAFKA_JVM_PERFORMANCE_OPTS: "-XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35" -``` - -#### 3. **Database Performance** -**PostgreSQL Enhancements**: -- SCRAM-SHA-256 authentication for better security -- Optimized connection settings -- Proper data persistence with bind mounts - -**Redis Optimizations**: -- Memory management with `maxmemory` and `allkeys-lru` policy -- Persistent storage with AOF (Append Only File) -- Authentication enabled - ---- - -## Configuration Structure - -### 📁 File Organization - -The optimized configuration consists of: - -``` -├── docker-compose.yml.optimized # Infrastructure services -├── docker-compose.services.yml.optimized # Microservices -├── docker-compose.clients.yml.optimized # Client applications -├── .env.template # Environment configuration template -└── docker/ - └── secrets/ - ├── setup-secrets.sh # Automated secrets generation - ├── postgres_user.txt # Database username - ├── postgres_password.txt # Database password (generated) - ├── redis_password.txt # Redis password (generated) - ├── keycloak_admin_password.txt # Keycloak admin password (generated) - ├── keycloak_client_secret.txt # API Gateway client secret (generated) - ├── grafana_admin_user.txt # Grafana admin username - ├── grafana_admin_password.txt # Grafana admin password (generated) - ├── jwt_secret.txt # JWT signing secret (generated) - └── vnc_password.txt # VNC access password (generated) -``` - -### 🔄 Profile-based Deployment - -The optimized configuration supports selective service deployment: - -```bash -# Infrastructure only -docker-compose -f docker-compose.yml.optimized up -d - -# Infrastructure + Microservices -docker-compose -f docker-compose.yml.optimized \ - -f docker-compose.services.yml.optimized up -d - -# Full stack deployment -docker-compose -f docker-compose.yml.optimized \ - -f docker-compose.services.yml.optimized \ - -f docker-compose.clients.yml.optimized up -d - -# Selective services with profiles -docker-compose -f docker-compose.services.yml.optimized \ - --profile members --profile horses up -d -``` - ---- - -## Migration Guide - -### 🚀 Quick Start - -#### 1. **Generate Secrets** -```bash -# Generate all required secrets -./docker/secrets/setup-secrets.sh --all - -# Or generate individually -./docker/secrets/setup-secrets.sh --generate -./docker/secrets/setup-secrets.sh --validate -``` - -#### 2. **Configure Environment** -```bash -# Copy template and customize -cp .env.template .env - -# Edit configuration values -nano .env -``` - -#### 3. **Create Data Directories** -```bash -# Create persistent data directories -mkdir -p ./data/{postgres,redis,prometheus,grafana,keycloak,consul,monitoring,desktop-app} -``` - -#### 4. **Deploy Services** -```bash -# Start infrastructure -docker-compose -f docker-compose.yml.optimized up -d - -# Verify all services are healthy -docker-compose -f docker-compose.yml.optimized ps - -# Add microservices -docker-compose -f docker-compose.yml.optimized \ - -f docker-compose.services.yml.optimized up -d - -# Add client applications -docker-compose -f docker-compose.yml.optimized \ - -f docker-compose.services.yml.optimized \ - -f docker-compose.clients.yml.optimized up -d -``` - -### 🔄 Migration from Original Configuration - -#### Step 1: Backup Current Setup -```bash -# Stop existing services -docker-compose down - -# Backup current data (optional) -cp -r data/ data.backup/ -``` - -#### Step 2: Update Configuration -```bash -# Generate secrets first -./docker/secrets/setup-secrets.sh --all - -# Update environment configuration -cp .env.template .env -# Edit .env as needed -``` - -#### Step 3: Deploy Optimized Configuration -```bash -# Deploy with new configuration -docker-compose -f docker-compose.yml.optimized up -d -``` - ---- - -## Security Best Practices - -### 🛡️ Production Security Checklist - -- [ ] **Secrets Generated**: Run secrets setup script -- [ ] **File Permissions**: Ensure secret files have 600 permissions -- [ ] **Network Isolation**: Use custom Docker networks -- [ ] **Resource Limits**: All services have CPU/memory limits -- [ ] **Non-root Users**: Applications run as non-privileged users -- [ ] **Read-only Mounts**: Configuration mounted read-only -- [ ] **Security Options**: `no-new-privileges` enabled -- [ ] **Health Checks**: All critical services have health checks -- [ ] **Backup Strategy**: Regular data backups configured -- [ ] **Monitoring**: Prometheus and Grafana configured -- [ ] **Log Management**: Centralized logging configured - -### 🔐 Security Monitoring - -#### Access URLs (Default Configuration) -- **Grafana Dashboard**: http://localhost:3000 -- **Prometheus Metrics**: http://localhost:9090 -- **Consul UI**: http://localhost:8500 -- **Keycloak Admin**: http://localhost:8180/admin - -#### Security Metrics to Monitor -- Failed authentication attempts -- Resource usage patterns -- Container restart frequency -- Network connection anomalies -- Secret access patterns - ---- - -## Troubleshooting - -### 🔍 Common Issues and Solutions - -#### Issue 1: Secret File Permissions -**Problem**: Containers cannot read secret files -**Solution**: -```bash -# Fix permissions -chmod 600 docker/secrets/*.txt - -# Or regenerate with correct permissions -./docker/secrets/setup-secrets.sh --force -``` - -#### Issue 2: Resource Constraints -**Problem**: Services failing due to resource limits -**Solution**: -```bash -# Check resource usage -docker stats - -# Adjust limits in docker-compose files or increase system resources -``` - -#### Issue 3: Network Connectivity -**Problem**: Services cannot communicate -**Solution**: -```bash -# Check network configuration -docker network inspect meldestelle_meldestelle-network - -# Verify service health -docker-compose -f docker-compose.yml.optimized ps -``` - -#### Issue 4: Volume Mount Issues -**Problem**: Data not persisting or permission errors -**Solution**: -```bash -# Create data directories with correct permissions -mkdir -p ./data/{postgres,redis,prometheus,grafana,keycloak,consul} -chown -R 999:999 ./data/postgres # PostgreSQL user -chown -R 472:0 ./data/grafana # Grafana user -``` - -### 📊 Health Check Commands - -```bash -# Check all service status -docker-compose -f docker-compose.yml.optimized ps - -# View service logs -docker-compose -f docker-compose.yml.optimized logs [service-name] - -# Check resource usage -docker stats - -# Validate secrets -./docker/secrets/setup-secrets.sh --validate - -# Test connectivity -docker exec meldestelle-api-gateway curl -f http://postgres:5432 -``` - ---- - -## Performance Tuning - -### 🎯 Resource Optimization Guidelines - -#### Memory Allocation Strategy -1. **Infrastructure Services**: Higher memory allocation for databases and messaging -2. **Application Services**: Balanced CPU/memory for microservices -3. **Client Applications**: Lower resource requirements - -#### CPU Allocation Strategy -1. **I/O Bound Services** (Database, Redis): Moderate CPU, high memory -2. **Compute Bound Services** (Application logic): Higher CPU allocation -3. **Static Content Services** (Web apps): Lower overall resources - -#### JVM Tuning for Java Services -```yaml -environment: - JAVA_OPTS: | - -XX:MaxRAMPercentage=75.0 - -XX:+UseG1GC - -XX:+UseStringDeduplication - -XX:+UseContainerSupport - -Djava.security.egd=file:/dev/./urandom -``` - ---- - -## Monitoring and Observability - -### 📈 Metrics Collection - -#### Prometheus Metrics -- Container resource usage -- Application performance metrics -- Health check status -- Network traffic patterns - -#### Grafana Dashboards -- Infrastructure overview -- Application performance -- Security events -- Resource utilization trends - -#### Logging Strategy -- Centralized logging via Docker logs -- Structured JSON logging for applications -- Log rotation and retention policies -- Security event logging - ---- - -## Conclusion - -The Docker configuration optimization provides: - -1. **Enhanced Security**: Complete elimination of hardcoded credentials and implementation of Docker secrets -2. **Production Readiness**: Comprehensive resource limits, health checks, and monitoring -3. **Improved Performance**: Optimized resource allocation and container configurations -4. **Operational Excellence**: Automated secret management, comprehensive documentation, and troubleshooting guides -5. **Scalability**: Profile-based deployment and modular service architecture - -### Next Steps - -1. **Deploy optimized configuration** in development environment -2. **Validate all security measures** are properly implemented -3. **Monitor performance metrics** and adjust resource limits as needed -4. **Implement backup and recovery procedures** for persistent data -5. **Set up automated monitoring and alerting** for production deployment - -For questions or issues with the optimized configuration, refer to the troubleshooting section or consult the detailed configuration comments in the docker-compose files. diff --git a/Tagebuch/Docker-Clients-Optimierung-Bericht.md b/Tagebuch/Docker-Clients-Optimierung-Bericht.md deleted file mode 100644 index 0bc12f76..00000000 --- a/Tagebuch/Docker-Clients-Optimierung-Bericht.md +++ /dev/null @@ -1,214 +0,0 @@ -# Docker Clients Optimierung - Abschlussbericht - -## Überblick - -Dieser Bericht dokumentiert die durchgeführte Überprüfung und Optimierung der Docker-Konfiguration für die Client-Anwendungen des Meldestelle-Projekts. - -## Durchgeführte Analyse - -### 1. Untersuchte Dateien -- `docker-compose.clients.yml` - Client-Services Orchestrierung -- `dockerfiles/clients/web-app/Dockerfile` - Kotlin/JS Web-App Build -- `dockerfiles/clients/desktop-app/Dockerfile` - Kotlin Desktop-App mit VNC -- `dockerfiles/clients/web-app/nginx.conf` - Nginx-Konfiguration für Web-App -- `docker/build-args/clients.env` - Build-Argumente für Client-Builds - -### 2. Identifizierte Probleme - -#### **Desktop-App Dockerfile Inkonsistenzen:** -- ❌ Verwendung von `gradle` statt `./gradlew` -- ❌ Falscher Modulpfad `client` statt `clients` -- ❌ Veraltete Module-Referenzen (`temp`, `docs`) -- ❌ Falscher COPY-Pfad für kompilierte Artefakte -- ❌ Falsche Gradle-Task-Referenzen - -#### **Nginx-Konfiguration:** -- ❌ WASM location-Block außerhalb des server-Kontexts - -#### **Build-Argumente:** -- ❌ Inkonsistente Build-Targets in `clients.env` - -## Durchgeführte Optimierungen - -### ✅ Desktop-App Dockerfile (`dockerfiles/clients/desktop-app/Dockerfile`) - -**Vor:** - -```dockerfile -# Kopiere Gradle-Konfiguration -COPY ../build.gradle.kts settings.gradle.kts gradle.properties ./ -COPY ../gradle ./gradle - -# Kopiere alle notwendigen Module für Multi-Modul-Projekt -COPY client ./client -COPY temp ./temp -COPY ../docs ./docs - -# Dependencies downloaden -RUN gradle :client:dependencies --no-configure-on-demand - -# Desktop-App kompilieren -RUN gradle :client:createDistributable --no-configure-on-demand - -# Kopiere kompilierte Desktop-App -COPY --from=builder /app/client/build/compose/binaries/main/desktop/ ./desktop-app/ -``` - -**Nach:** -```dockerfile -# Kopiere Gradle-Konfiguration und Wrapper -COPY build.gradle.kts settings.gradle.kts gradle.properties ./ -COPY gradle ./gradle -COPY gradlew ./ - -# Kopiere alle notwendigen Module für Multi-Modul-Projekt -COPY clients ./clients -COPY services ./services - -# Setze Gradle-Wrapper Berechtigung -RUN chmod +x ./gradlew - -# Dependencies downloaden -RUN ./gradlew :clients:app:dependencies --no-configure-on-demand - -# Desktop-App kompilieren -RUN ./gradlew :clients:app:createDistributable --no-configure-on-demand - -# Kopiere kompilierte Desktop-App -COPY --from=builder /app/clients/app/build/compose/binaries/main/desktop/ ./desktop-app/ -``` - -**Verbesserungen:** -- ✅ Konsistente Verwendung des Gradle-Wrappers -- ✅ Korrekte Modulpfade entsprechend der aktuellen Projektstruktur -- ✅ Entfernung veralteter Module-Referenzen -- ✅ Korrekte Build-Pfade für Artefakte - -### ✅ Nginx-Konfiguration (`dockerfiles/clients/web-app/nginx.conf`) - -**Vor:** -```nginx -http { - # WASM MIME-Type für zukünftige Builds - location ~ \.wasm$ { - add_header Content-Type application/wasm; - } -} -``` - -**Nach:** -```nginx -server { - location / { - # WASM Files mit korrektem MIME-Type - location ~* \.wasm$ { - add_header Content-Type application/wasm; - expires 1y; - add_header Cache-Control "public, immutable"; - } - } -} -``` - -**Verbesserungen:** -- ✅ Korrekte Platzierung des location-Blocks im server-Kontext -- ✅ Zusätzliche Cache-Header für WASM-Dateien -- ✅ Konsistente Behandlung mit anderen statischen Assets - -### ✅ Build-Argumente (`docker/build-args/clients.env`) - -**Vor:** -```env -WEB_APP_BUILD_TARGET=wasmJsBrowserDistribution -DESKTOP_APP_BUILD_TARGET=composeDesktop -``` - -**Nach:** -```env -WEB_APP_BUILD_TARGET=jsBrowserDistribution -DESKTOP_APP_BUILD_TARGET=createDistributable -``` - -**Verbesserungen:** -- ✅ Synchronisation mit tatsächlich verwendeten Gradle-Tasks -- ✅ Konsistenz zwischen Dokumentation und Implementierung - -## Validierung - -### ✅ Syntax-Validierung -- **Docker-Compose:** `docker-compose -f docker-compose.clients.yml config --quiet` ✅ Erfolgreich -- **Dockerfiles:** Hadolint-Lint durchgeführt ✅ Nur minor Optimierungshinweise - -## Aktuelle Bewertung der Client-Docker-Konfiguration - -### 🌟 Stärken - -1. **Moderne Multi-Stage-Builds:** Beide Dockerfiles nutzen effiziente Multi-Stage-Builds -2. **Umfassende Dokumentation:** Excellent kommentierte Konfigurationsdateien -3. **Flexible Deployment-Optionen:** Unterstützung für standalone, multi-file und complete system deployments -4. **Performance-Optimierungen:** Nginx mit Gzip, Caching und optimierten Headern -5. **Health-Checks:** Implementiert für beide Client-Services -6. **VNC-Integration:** Innovative Desktop-App-Bereitstellung über VNC/noVNC - -### 🎯 Weitergehende Optimierungsempfehlungen - -#### 1. **Security Hardening** -```dockerfile -# Web-App: Nginx Sicherheit -RUN apk add --no-cache curl=8.4.0-r0 # Version pinning -RUN addgroup -g 101 -S nginx && adduser -S -D -H -u 101 -h /var/cache/nginx -s /sbin/nologin nginx - -# Desktop-App: Minimal base images -FROM eclipse-temurin:21-jre-alpine AS runtime # Statt Ubuntu für kleinere Images -``` - -#### 2. **Build-Performance** -```dockerfile -# .dockerignore ergänzen -RUN --mount=type=cache,target=/root/.gradle ./gradlew dependencies -``` - -#### 3. **Image-Größen-Optimierung** -```dockerfile -# Multi-stage für kleinere Production-Images -FROM nginx:1.25-alpine AS production -COPY --from=builder --chown=nginx:nginx /app/dist /usr/share/nginx/html -``` - -#### 4. **Monitoring Integration** -```yaml -# docker-compose.clients.yml -labels: - - "prometheus.io/scrape=true" - - "prometheus.io/port=4000" - - "prometheus.io/path=/metrics" -``` - -## Zusammenfassung - -### ✅ Abgeschlossene Optimierungen -- **Inkonsistenzen behoben:** Desktop-App Dockerfile vollständig korrigiert -- **Nginx-Konfiguration optimiert:** WASM-Support korrekt implementiert -- **Build-Argumente synchronisiert:** Konsistenz zwischen Dokumentation und Code -- **Validierung erfolgreich:** Keine syntaktischen Fehler - -### 📊 Bewertung -- **Funktionalität:** ⭐⭐⭐⭐⭐ (Exzellent) - Alle Services funktionsfähig -- **Code-Qualität:** ⭐⭐⭐⭐⭐ (Exzellent) - Nach Optimierungen konsistent und sauber -- **Dokumentation:** ⭐⭐⭐⭐⭐ (Exzellent) - Umfassend kommentiert -- **Performance:** ⭐⭐⭐⭐ (Sehr gut) - Gute Optimierungen, Potenzial für weitere -- **Sicherheit:** ⭐⭐⭐ (Gut) - Grundlagen vorhanden, Raum für Hardening - -### 🎯 Fazit - -Die Docker-Client-Konfiguration ist nach den Optimierungen **ausgezeichnet strukturiert und funktionsfähig**. Die kritischen Inkonsistenzen wurden behoben, und das System folgt modernen Docker-Best-Practices. - -Die implementierten Multi-Stage-Builds, die umfassende Nginx-Konfiguration und die flexible Deployment-Architektur zeigen **professionelle DevOps-Praktiken**. - -**Status:** ✅ **PRODUKTIONSREIF** mit optionalen Verbesserungen für erweiterte Szenarien. - ---- - -**Erstellt:** 27. September 2025 -**Autor:** Junie (Autonomous Programmer) -**Version:** 1.0 diff --git a/Tagebuch/GATEWAY-TESTS-FIXED.md b/Tagebuch/GATEWAY-TESTS-FIXED.md deleted file mode 100644 index 4fd63a4d..00000000 --- a/Tagebuch/GATEWAY-TESTS-FIXED.md +++ /dev/null @@ -1,143 +0,0 @@ -# Gateway Tests - Reparatur Dokumentation - -**Datum:** 11. Oktober 2025 - -## Problem - -Die Gateway-Tests waren defekt - nur ~47% (25/53 Tests) liefen erfolgreich. Die Hauptprobleme waren: - -1. **Fehlender ReactiveJwtDecoder Bean**: Tests schlugen mit `NoSuchBeanDefinitionException` fehl -2. **JwtAuthenticationTests.kt**: Testete nicht-existierende Custom JWT Filter und versuchte einen nicht verfügbaren `JwtService` Bean zu autowiren -3. **Routing/Security/Filter Tests**: Schlugen mit 401 UNAUTHORIZED fehl, da sie geschützte Endpoints ohne Authentifizierung testeten -4. **Architektur-Mismatch**: Tests waren für Custom JWT Filter geschrieben, aber die Implementierung verwendet Spring Security OAuth2 Resource Server - -## Durchgeführte Änderungen - -### 1. JwtAuthenticationTests.kt gelöscht ❌ - -**Datei:** `infrastructure/gateway/src/test/kotlin/at/mocode/infrastructure/gateway/JwtAuthenticationTests.kt` - -**Begründung:** -- Testete Custom JWT Filter, die nicht existieren -- Versuchte `@Autowired lateinit var jwtService: JwtService` - Bean existiert nicht im Gateway -- Erwartete Custom Header-Injection (X-User-ID, X-User-Role) - existiert nicht -- Erwartete Custom JSON Error-Responses - existiert nicht -- Alle 10 Tests waren ungültig für die aktuelle OAuth2 Resource Server Implementierung - -### 2. TestSecurityConfig.kt erweitert ✅ - -**Datei:** `infrastructure/gateway/src/test/kotlin/at/mocode/infrastructure/gateway/config/TestSecurityConfig.kt` - -**Vorher:** -- Stellte nur Mock `ReactiveJwtDecoder` bereit - -**Nachher:** -```kotlin -@TestConfiguration -class TestSecurityConfig { - - // Bestehend: Mock ReactiveJwtDecoder - @Bean - @Primary - fun mockReactiveJwtDecoder(): ReactiveJwtDecoder { ... } - - // NEU: Security Web Filter Chain die alle Anfragen erlaubt - @Bean - @Primary - fun testSecurityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain { - return http { - csrf { disable() } - authorizeExchange { - authorize(anyExchange, permitAll) - } - } - } -} -``` - -**Effekt:** -- Überschreibt die produktive SecurityConfig mit `@Primary` -- Erlaubt alle Anfragen ohne Authentifizierung in Tests -- Ermöglicht Tests von Routing, CORS und Filtern ohne JWT-Tokens - -### 3. Bestehende Tests blieben unverändert ✅ - -Alle verbleibenden Test-Klassen hatten bereits `@Import(TestSecurityConfig::class)`: -- ✅ **GatewayApplicationTests.kt** - hatte bereits Import -- ✅ **FallbackControllerTests.kt** - hatte bereits Import -- ✅ **GatewayRoutingTests.kt** - hatte bereits Import -- ✅ **GatewaySecurityTests.kt** - hatte bereits Import -- ✅ **GatewayFiltersTests.kt** - hatte bereits Import -- ✅ **KeycloakGatewayIntegrationTest.kt** - hatte bereits Import - -Durch die Erweiterung von `TestSecurityConfig` funktionieren diese Tests nun automatisch. - -## Testergebnisse - -### Vorher (Defekt) -``` -Gesamt: 53 Tests -Bestanden: ~25 Tests (47%) -Fehlgeschlagen: ~28 Tests (53%) -``` - -**Fehler:** -- NoSuchBeanDefinitionException: ReactiveJwtDecoder -- 401 UNAUTHORIZED für geschützte Endpoints -- JwtService Bean nicht gefunden - -### Nachher (Repariert) ✅ -``` -Gesamt: 44 Tests -Bestanden: 44 Tests (100%) -Fehlgeschlagen: 0 Tests (0%) -``` - -**Details:** -- FallbackControllerTests: 14 Tests ✅ -- GatewayApplicationTests: 1 Test ✅ -- GatewayFiltersTests: 8 Tests ✅ -- GatewayRoutingTests: 7 Tests ✅ -- GatewaySecurityTests: 13 Tests ✅ -- KeycloakGatewayIntegrationTest: 1 Test ✅ - -**Build-Ergebnis:** `BUILD SUCCESSFUL` 🎉 - -## Zusammenfassung - -**Gelöschte Dateien:** 1 -- `JwtAuthenticationTests.kt` (10 ungültige Tests) - -**Geänderte Dateien:** 1 -- `TestSecurityConfig.kt` (erweitert um SecurityWebFilterChain) - -**Unveränderte Dateien:** 6 -- Alle anderen Test-Klassen (profitierten automatisch vom Fix) - -**Verbesserung:** Von 47% (25/53) auf 100% (44/44) Erfolgsquote - -## Technische Details - -### Warum funktioniert die Lösung? - -1. **@Primary Annotation**: Die Test-SecurityWebFilterChain überschreibt die produktive SecurityConfig -2. **permitAll**: Alle Endpoints sind in Tests zugänglich ohne Authentifizierung -3. **Mock ReactiveJwtDecoder**: Verhindert NoSuchBeanDefinitionException -4. **Automatische Anwendung**: Alle Tests mit `@Import(TestSecurityConfig::class)` profitieren automatisch - -### Was wurde NICHT geändert? - -- ❌ Produktions-SecurityConfig (`SecurityConfig.kt`) -- ❌ Produktions-Gateway-Routing oder Filter -- ❌ OAuth2 Resource Server Konfiguration -- ❌ Bestehende Test-Logik (außer JwtAuthenticationTests) - -## Fazit - -Die Gateway-Tests sind vollständig repariert und funktionieren zu 100%. Die Lösung ist: -- ✅ **Minimal invasiv** - nur 2 Dateien geändert -- ✅ **Wartbar** - saubere Trennung von Test- und Produktionscode -- ✅ **Best Practice** - Test-spezifische Konfiguration in separater TestConfiguration -- ✅ **Vollständig** - alle relevanten Tests funktionieren - -**Status:** ✅ Abgeschlossen - alle Gateway-Tests funktionieren diff --git a/Tagebuch/GRADLE-OPTIMIZATION-SUMMARY-DE.md b/Tagebuch/GRADLE-OPTIMIZATION-SUMMARY-DE.md deleted file mode 100644 index 86087876..00000000 --- a/Tagebuch/GRADLE-OPTIMIZATION-SUMMARY-DE.md +++ /dev/null @@ -1,619 +0,0 @@ -# Gradle Build-Optimierung - Vollständige Zusammenfassung - -## Zusammenfassung - -Erfolgreich abgeschlossene umfassende Gradle Build-Optimierung für das Meldestelle-Projekt über 6 Hauptphasen. Die Optimierung hat das Build-System auf Gradle 9.1.0 modernisiert, 20 neue Dependency-Bundles für verbesserte Wartbarkeit eingeführt, 3 Convention Plugins für konsistente Konfiguration erstellt und die Build-Performance durch Kotlin-Compiler-Optimierungen verbessert. - -**Gesamtwirkung:** -- **810 Zeilen hinzugefügt, 111 gelöscht** über 10 Dateien -- **20 neue Dependency-Bundles** im Version Catalog erstellt -- **3 Convention Plugins** für DRY-Prinzipien -- **2 Beispielmodule refactored** (Gateway, Ping-Service) mit 20-37% Code-Reduktion -- **Gradle 9.1.0** mit verbessertem Toolchain-Management - ---- - -## Phase 1: Bundles & Version Catalog ✅ - -**Datei:** `gradle/libs.versions.toml` (+77 Zeilen) - -### Fehlende Bibliotheken hinzugefügt -1. **`slf4j-api`** - Version 2.0.16 (zentralisierte Logging-API) -2. **`kotlin-reflect`** - verwendet Kotlin-Versionsreferenz (Runtime-Reflection-Unterstützung) - -### 15 Granulare Bundles erstellt -Diese Bundles gruppieren verwandte Abhängigkeiten für feinkörnige Kontrolle: - -1. **`ktor-server-common`** (7 deps) - Kern-Ktor-Server-Abhängigkeiten - - core, netty, content-negotiation, serialization, status-pages, cors, default-headers - -2. **`ktor-server-security`** (2 deps) - Authentifizierung & Autorisierung - - auth, auth-jwt - -3. **`ktor-server-observability`** (2 deps) - Logging & Metriken - - call-logging, metrics-micrometer - -4. **`ktor-server-docs`** (2 deps) - API-Dokumentation - - openapi, swagger - -5. **`ktor-client-common`** (5 deps) - HTTP-Client-Grundlagen - - core, content-negotiation, serialization, logging, auth - -6. **`spring-boot-web`** (3 deps) - Webanwendungs-Stack - - starter-web, starter-validation, starter-actuator - -7. **`spring-boot-security`** (4 deps) - Sicherheit & OAuth2 - - starter-security, oauth2-client, oauth2-resource-server, oauth2-jose - -8. **`spring-boot-data`** (2 deps) - Datenpersistenz - - starter-data-jpa, starter-data-redis - -9. **`spring-boot-observability`** (4 deps) - Monitoring & Tracing - - starter-actuator, micrometer-prometheus, tracing-bridge-brave, zipkin-reporter-brave - -10. **`compose-common`** (2 deps) - Compose-Lifecycle - - lifecycle-viewmodel-compose, lifecycle-runtime-compose - -11. **`jackson-kotlin`** (2 deps) - JSON-Serialisierung - - module-kotlin, datatype-jsr310 - -12. **`kotlinx-core`** (3 deps) - Kotlin-Grundlagen - - coroutines-core, serialization-json, datetime - -13. **`persistence-postgres`** (4 deps) - Datenbankzugriff - - exposed-core, exposed-dao, exposed-jdbc, postgresql-driver - -14. **`resilience`** (3 deps) - Circuit-Breaker-Patterns - - resilience4j-spring-boot3, resilience4j-reactor, spring-boot-starter-aop - -15. **`logging`** (3 deps) - Strukturiertes Logging - - kotlin-logging-jvm, logback-classic, logback-core - -### 5 Complete Bundles erstellt -All-in-One-Bundles für schnelle Entwicklung: - -1. **`ktor-server-complete`** (14 deps) - Vollständiger Ktor-Server-Stack - - Kombiniert: common, security, observability, docs + rate-limit - -2. **`spring-boot-service-complete`** (12 deps) - Vollständiger Spring Boot Service - - Kombiniert: web, security, data, observability - -3. **`database-complete`** (8 deps) - Vollständige Persistenzschicht - - Exposed ORM + PostgreSQL + HikariCP + Flyway-Migrationen - -4. **`testing-kmp`** (8 deps) - Umfassendes KMP-Testing - - JUnit 5, Mockk, AssertJ, Coroutines Test - -5. **`monitoring-complete`** (8 deps) - Vollständiger Observability-Stack - - Actuator, Prometheus, Zipkin, Logback, SLF4J - -**Vorteile:** -- Single Source of Truth für Dependency-Gruppierungen -- IDE-Autovervollständigung für Bundle-Namen -- Type-Safe Dependency Management -- Einfach zu warten und zu aktualisieren - ---- - -## Phase 2: Root Build-Datei ✅ - -**Datei:** `build.gradle.kts` (+39 Zeilen modifiziert) - -### Vorgenommene Verbesserungen - -1. **Zentralisiertes Plugin-Management** - ```kotlin - plugins { - // Alle Plugins mit 'apply false' auf Root-Ebene deklariert - alias(libs.plugins.kotlinJvm) apply false - alias(libs.plugins.kotlinMultiplatform) apply false - alias(libs.plugins.kotlinSerialization) apply false - alias(libs.plugins.kotlinSpring) apply false - alias(libs.plugins.kotlinJpa) apply false - alias(libs.plugins.composeMultiplatform) apply false - alias(libs.plugins.composeCompiler) apply false - alias(libs.plugins.spring.boot) apply false - alias(libs.plugins.spring.dependencyManagement) apply false - } - ``` - - Verhindert "Plugin mehrfach geladen"-Fehler in Gradle 9.1.0+ - - Subprojekte wenden über Version-Catalog-Aliase an - -2. **AllProjects-Konfiguration** - ```kotlin - allprojects { - group = "at.mocode" - version = "1.0.0-SNAPSHOT" - - repositories { - mavenCentral() - google() - maven { url = uri("https://jitpack.io") } - // ... weitere Repositories - } - } - ``` - -3. **Build-Analyse-Plugins hinzugefügt** - - `com.github.ben-manes.versions` (0.51.0) - Dependency-Update-Prüfung - - Unterstützt: `./gradlew dependencyUpdates` - -4. **Gradle Wrapper aktualisiert** - ```kotlin - tasks.wrapper { - gradleVersion = "9.1.0" - distributionType = Wrapper.DistributionType.BIN - } - ``` - -**Vorteile:** -- Konsistente Gruppe/Version über alle Module -- Zentralisierte Repository-Konfiguration -- Plugin-Versionskonflikte verhindert -- Moderne Gradle 9.1.0-Features aktiviert - ---- - -## Phase 3: Convention Plugins ✅ - -**Verzeichnis:** `buildSrc/src/main/kotlin/` (+192 Zeilen) - -### 3 Convention Plugins erstellt - -#### 1. `kotlin-multiplatform-conventions.gradle.kts` (56 Zeilen) -**Zweck:** Standardisiert KMP-Modulkonfiguration - -**Wendet an:** -- `org.jetbrains.kotlin.multiplatform` -- `org.jetbrains.kotlin.plugin.serialization` - -**Konfiguriert:** -- Java 21 Toolchain -- Kotlin-Compiler-Optionen (Opt-in-APIs, JVM-Target) -- Gemeinsame Test-Konfiguration mit JUnit Platform - -**Zielmodule:** -- clients/app, clients/ping-feature, clients/auth-feature -- clients/shared/* Module -- core/core-utils, core/core-domain - -#### 2. `spring-boot-service-conventions.gradle.kts` (62 Zeilen) -**Zweck:** Standardisiert Spring Boot Service-Konfiguration - -**Wendet an:** -- `org.jetbrains.kotlin.jvm` -- `org.springframework.boot` -- `io.spring.dependency-management` -- `org.jetbrains.kotlin.plugin.spring` -- `org.jetbrains.kotlin.plugin.jpa` - -**Konfiguriert:** -- Java 21 Toolchain -- Kotlin-Compiler-Optionen (JSR-305 strict, JVM 21) -- JPA All-Open-Plugin für Entities -- JUnit Platform Test-Konfiguration - -**Zielmodule:** -- infrastructure/gateway -- infrastructure/auth-server -- infrastructure/monitoring-server -- services/ping/ping-service -- Alle zukünftigen Spring Boot Services - -#### 3. `ktor-server-conventions.gradle.kts` (53 Zeilen) -**Zweck:** Standardisiert Ktor-Server-Konfiguration - -**Wendet an:** -- `org.jetbrains.kotlin.jvm` -- `io.ktor.plugin` -- `org.jetbrains.kotlin.plugin.serialization` - -**Konfiguriert:** -- Java 21 Toolchain -- Kotlin-Compiler-Optionen -- Ktor Fat JAR-Konfiguration -- JUnit Platform Test-Konfiguration - -**Zielmodule:** -- Alle zukünftigen Ktor-basierten Backend-Services - -### BuildSrc-Konfiguration -**Datei:** `buildSrc/build.gradle.kts` (21 Zeilen) - -```kotlin -plugins { - `kotlin-dsl` -} - -repositories { - gradlePluginPortal() - mavenCentral() -} - -dependencies { - implementation(libs.kotlin.gradlePlugin) - implementation(libs.spring.boot.gradlePlugin) - implementation(libs.spring.dependencyManagement.gradlePlugin) - implementation(libs.ktor.gradlePlugin) -} -``` - -**Strategische Entscheidung:** -Während Convention Plugins erfolgreich erstellt wurden und im Commit enthalten sind, werden sie **DERZEIT NICHT** auf Module angewendet aufgrund eines entdeckten KMP-Kompatibilitätsproblems. Die Plugins verbleiben in buildSrc als: -1. Dokumentation beabsichtigter Patterns -2. Zukünftige Referenz, wenn KMP-Kompatibilität gelöst ist -3. Wiederverwendbare Templates für Nicht-KMP-Module - -**Vorteile (wenn anwendbar):** -- Eliminiert 30-50 Zeilen Boilerplate pro Modul -- Stellt konsistente Toolchain-Konfiguration sicher -- Einzelner Ort für Compiler-Einstellungs-Updates -- Type-Safe Kotlin DSL durchgehend - ---- - -## Phase 4: Modul-Refactoring (Strategisches Sampling) ✅ - -### Beispiel 1: infrastructure/gateway/build.gradle.kts -**Vorher:** 113 Zeilen | **Nachher:** 94 Zeilen | **Reduktion:** 20% - -#### Vorgenommene Änderungen: -1. **Direkte Plugin-Anwendung** (Vermeidung von Convention Plugin wegen KMP-Konflikt) - ```kotlin - plugins { - alias(libs.plugins.kotlinJvm) - alias(libs.plugins.kotlinSpring) - alias(libs.plugins.kotlinJpa) - alias(libs.plugins.spring.boot) - alias(libs.plugins.spring.dependencyManagement) - } - ``` - -2. **Einzelne Abhängigkeiten durch Bundles ersetzt:** - ```kotlin - // ALT: 15+ einzelne Spring Boot Abhängigkeiten - // NEU: 4 Bundles - implementation(libs.bundles.spring.cloud.gateway) - implementation(libs.bundles.spring.boot.service.complete) - implementation(libs.bundles.resilience) - implementation(libs.bundles.jackson.kotlin) - implementation(libs.bundles.logging) - ``` - -3. **Platform BOM für Versionskonsistenz hinzugefügt:** - ```kotlin - implementation(platform(projects.platform.platformBom)) - ``` - -**Vorteile:** -- Besser lesbarer Dependency-Abschnitt -- Einfacher zu verstehender Modulzweck -- Konsistent mit anderen Spring Boot Services -- Vereinfachte zukünftige Wartung - -### Beispiel 2: services/ping/ping-service/build.gradle.kts -**Vorher:** 79 Zeilen | **Nachher:** 54 Zeilen | **Reduktion:** 37% - -#### Vorgenommene Änderungen: -1. **Direkte Plugin-Anwendung:** - ```kotlin - plugins { - alias(libs.plugins.kotlinJvm) - alias(libs.plugins.kotlinSpring) - alias(libs.plugins.kotlinJpa) - alias(libs.plugins.spring.boot) - alias(libs.plugins.spring.dependencyManagement) - } - ``` - -2. **Umfassende Bundle-Nutzung:** - ```kotlin - implementation(libs.bundles.spring.boot.service.complete) - implementation(libs.bundles.jackson.kotlin) - implementation(libs.bundles.resilience) - implementation(libs.kotlin.reflect) // Jetzt aus Version Catalog - ``` - -3. **Sauberere Test-Abhängigkeiten:** - ```kotlin - testImplementation(projects.platform.platformTesting) - testImplementation(libs.bundles.testing.jvm) - ``` - -**Vorteile:** -- 37% Code-Reduktion -- Viel klarere Absicht -- Konsistentes Pattern für zukünftige Services -- Alle Abhängigkeiten zentral verwaltet - ---- - -## Phase 5: Gradle Properties ✅ - -**Datei:** `gradle.properties` (+9 Zeilen) - -### Kotlin-Compiler-Optimierungen hinzugefügt - -```properties -# Kotlin Compiler Optimizations (Phase 5) -kotlin.incremental=true -kotlin.incremental.multiplatform=true -kotlin.incremental.js=true -kotlin.caching.enabled=true -kotlin.compiler.execution.strategy=in-process -kotlin.compiler.preciseCompilationResultsBackup=true -kotlin.stdlib.default.dependency=true -``` - -### Performance-Auswirkung: -- **Inkrementelle Kompilierung:** ~20-40% schnellere Rebuilds -- **Compiler-Caching:** Wiederverwendet Kompilierungsergebnisse über Builds hinweg -- **In-Process-Ausführung:** Reduziert JVM-Startup-Overhead -- **Multiplatform-Optimierung:** Verbessert KMP-Build-Zeiten -- **JS-Kompilierung:** Schnellere JavaScript-Kompilierung - -### Zusätzliche existierende Optimierungen: -```properties -org.gradle.parallel=true -org.gradle.caching=true -org.gradle.vfs.watch=true -org.gradle.workers.max=8 -``` - -**Hinweis:** Configuration Cache bleibt deaktiviert aufgrund von JS-Test-Serialisierungsproblemen: -```properties -org.gradle.configuration-cache=false -org.gradle.configuration-cache.problems=warn -``` - ---- - -## Phase 6: Testing & Validierung ✅ - -### Build-Validierung -- ✅ **Syntax-Validierung:** Alle Gradle-Dateien parsen korrekt -- ✅ **Dependency-Auflösung:** Alle Bundles lösen korrekt auf -- ✅ **Version-Catalog-Validierung:** Alle Referenzen gültig -- ✅ **Plugin-Kompatibilität:** Gradle 9.1.0-Kompatibilität bestätigt - -### Bekannte Probleme & Lösungen -1. **Convention Plugin KMP-Konflikt** - - **Problem:** Convention Plugins kollidieren mit KMP im selben Projekt - - **Lösung:** Plugins in buildSrc behalten zur Dokumentation, aber direkte Plugin-Deklarationen in Modulen anwenden - - **Status:** Funktionierende Lösung implementiert - -2. **Configuration Cache** - - **Problem:** JS-Browser-Tests scheitern mit Serialisierungsfehlern - - **Lösung:** Temporär deaktiviert, wird nach JS-Test-Framework-Update wieder aktiviert - - **Status:** In gradle.properties dokumentiert - -3. **WASM-Kompatibilität** - - **Problem:** Einige Abhängigkeiten fehlen WASM-Unterstützung - - **Lösung:** WASM ist Opt-in über `enableWasm=true` Property - - **Status:** Funktioniert wie vorgesehen - -### Getestete Build-Befehle -```bash -./gradlew --refresh-dependencies # ✅ Bestanden -./gradlew projects # ✅ Bestanden -./gradlew :infrastructure:gateway:tasks # ✅ Bestanden -./gradlew :services:ping:ping-service:tasks # ✅ Bestanden -``` - ---- - -## Erstellte Dokumentation ✅ - -### REFACTORING-GUIDE.md (440 Zeilen) -Umfassender Leitfaden einschließlich: - -1. **Überblick** - Zusammenfassung aller abgeschlossenen Änderungen -2. **Abgeschlossene Änderungen** - Detaillierte Phasen-Dokumentation -3. **Refactoring-Patterns** - 3 vollständige Patterns mit Vorher/Nachher-Beispielen: - - Pattern 1: Spring Boot Services - - Pattern 2: Ktor Server Services - - Pattern 3: Kotlin Multiplatform Module -4. **Modul-Refactoring-Checkliste** - Vollständiges Inventar aller Module mit Refactoring-Status -5. **Build-Befehle** - Empfohlene Befehle für Analyse und Optimierung -6. **Erwartete Vorteile** - Quantifizierte Verbesserungen -7. **Wichtige Hinweise** - Configuration Cache, WASM-Unterstützung, inkrementeller Ansatz -8. **Referenzen** - Links zur offiziellen Gradle-Dokumentation - -**Zweck:** -- Dient als Template für Refactoring verbleibender Module -- Dokumentiert etablierte Patterns und Konventionen -- Bietet Copy-Paste-Beispiele für häufige Szenarien -- Erklärt strategische Entscheidungen während der Optimierung - ---- - -## Wichtige Metriken & Statistiken - -### Code-Änderungen -- **Dateien modifiziert:** 10 -- **Zeilen hinzugefügt:** 810 -- **Zeilen gelöscht:** 111 -- **Netto-Auswirkung:** +699 Zeilen (hauptsächlich Dokumentation und Plugin-Infrastruktur) - -### Version-Catalog-Verbesserungen -- **Neue Bundles:** 20 (15 granular + 5 complete) -- **Neue Bibliotheken:** 2 (slf4j-api, kotlin-reflect) -- **Bundles gesamt:** 25 (inkl. 5 bereits existierende) - -### Build-Datei-Reduktionen (in refactorierten Modulen) -- **Gateway:** 113 → 94 Zeilen (-20%) -- **Ping-Service:** 79 → 54 Zeilen (-37%) -- **Durchschnittliche Reduktion:** ~28% - -### Plugin-Infrastruktur -- **Convention Plugins erstellt:** 3 -- **Zeilen wiederverwendbarer Konfiguration:** 171 -- **Module, die profitieren könnten:** 15+ Module - ---- - -## Erreichte Vorteile - -### 1. Wartbarkeit -- ✅ **Single Source of Truth** für alle Dependency-Versionen -- ✅ **Zentralisiertes Plugin-Management** verhindert Versionskonflikte -- ✅ **Wiederverwendbare Patterns** über Convention Plugins und Bundles -- ✅ **Umfassende Dokumentation** für zukünftiges Refactoring - -### 2. Build-Performance -- ✅ **Gradle 9.1.0** mit neuesten Performance-Verbesserungen -- ✅ **Kotlin-Compiler-Optimierungen** aktiviert -- ✅ **Inkrementelle Kompilierung** konfiguriert -- ✅ **Build-Caching** und **Parallele Ausführung** aktiviert -- ✅ **Geschätzte Verbesserung:** 20-40% schnellere Rebuilds - -### 3. Entwickler-Erfahrung -- ✅ **IDE-Autovervollständigung** für Bundle-Namen -- ✅ **Type-Safe Dependency Management** -- ✅ **Klare Build-Datei-Struktur** mit Bundles -- ✅ **Konsistente Patterns** über alle Module -- ✅ **Einfache Dependency-Updates** über Version Catalog - -### 4. Code-Qualität -- ✅ **Reduzierte Duplikation** durch Bundles und Conventions -- ✅ **Standardisierte Konfiguration** über Module hinweg -- ✅ **Bessere Trennung der Belange** -- ✅ **Einfachere Code-Reviews** mit weniger Zeilen pro Modul - ---- - -## Nächste Schritte & Empfehlungen - -### Sofortige Aktionen -1. ✅ **Änderungen committen** - Alle Änderungen gestaged und bereit -2. 🔲 **Patterns auf verbleibende Module anwenden** - REFACTORING-GUIDE.md als Template verwenden -3. 🔲 **Vollständigen Build ausführen** - `./gradlew clean build` nach Refactoring jedes Moduls -4. 🔲 **CI/CD aktualisieren** - Sicherstellen, dass Pipelines Gradle 9.1.0 verwenden - -### Kurzfristig (1-2 Wochen) -1. 🔲 **Infrastruktur-Module refactoren:** - - Auth-Server, Messaging-Config, Redis-Cache, Redis-Event-Store, Monitoring-Server -2. 🔲 **Client-Module refactoren:** - - clients/app, clients/auth-feature, clients/shared/* -3. 🔲 **Core-Module refactoren:** - - core/core-utils, core/core-domain (verwendet bereits einige Bundles) -4. 🔲 **Build-Zeit-Verbesserungen messen** - Vorher/Nachher-Metriken vergleichen - -### Mittelfristig (1 Monat) -1. 🔲 **Configuration Cache aktivieren** - Nach Lösung der JS-Test-Serialisierung -2. 🔲 **WASM-Unterstützung untersuchen** - Bereitschaft aller Abhängigkeiten bewerten -3. 🔲 **Dependency-Analyse ausführen** - `./gradlew buildHealth` -4. 🔲 **Nach Updates suchen** - `./gradlew dependencyUpdates` - -### Langfristig (3+ Monate) -1. 🔲 **Convention Plugins neu bewerten** - Prüfen, ob KMP-Kompatibilität verbessert wurde -2. 🔲 **Build-Performance-Profiling** - `--scan` für detaillierte Analyse verwenden -3. 🔲 **Dependency-Konsolidierung** - Ungenutzte Abhängigkeiten überprüfen und entfernen -4. 🔲 **Versions-Updates** - Regelmäßige Wartung des Version Catalogs - ---- - -## Getroffene strategische Entscheidungen - -### 1. Convention-Plugins-Ansatz -**Entscheidung:** Convention Plugins erstellt, aber in buildSrc ohne aktive Anwendung belassen - -**Begründung:** -- KMP und Convention Plugins im selben Projekt verursachen Konflikte -- Gradle 9.1.0 Plugin-Loading-Mechanismus hat strengere Regeln -- Direkte Plugin-Anwendung über Version Catalog funktioniert zuverlässig - -**Erwogene Alternative:** -- Separates Convention-Plugin-Repository (abgelehnt: zu komplex für Einzelprojekt) -- Inline-Konfiguration in jedem Modul (abgelehnt: zu viel Duplikation) - -**Ergebnis:** -- Convention Plugins dienen als Dokumentation und Templates -- Module verwenden direkte Plugin-Anwendung mit Bundles -- Ähnliche Vorteile durch Dependency-Bundles erreicht - -### 2. Bundle-Granularität -**Entscheidung:** Sowohl granulare (15) als auch complete (5) Bundles erstellt - -**Begründung:** -- Granulare Bundles: Feinkörnige Kontrolle für spezifische Anwendungsfälle -- Complete Bundles: Schnelle Entwicklung für Standard-Patterns -- Flexibilität: Teams können angemessene Bundle-Ebene wählen - -**Beispiele:** -- `ktor-server-common` für minimalen API-Service verwenden -- `ktor-server-complete` für voll ausgestattetes Gateway verwenden - -### 3. Gradle 9.1.0-Adoption -**Entscheidung:** Sofortiges Upgrade auf Gradle 9.1.0 - -**Begründung:** -- Neueste Features und Performance-Verbesserungen -- Bessere Kotlin-DSL-Unterstützung -- Erforderlich für modernes Plugin-Management -- Langfristige Wartungsvorteile - -**Geminderte Risiken:** -- Kompatibilität mit allen Plugins getestet -- Build funktioniert End-to-End verifiziert -- Breaking Changes dokumentiert (Plugin-Loading) - -### 4. Inkrementelles Refactoring -**Entscheidung:** 2 Beispielmodule refactored, Patterns für andere dokumentiert - -**Begründung:** -- Beweist, dass Patterns in echter Codebasis funktionieren -- Erstellt Templates für verbleibende Arbeit -- Ermöglicht Validierung vor großangelegten Änderungen -- Reduziert Risiko von Breaking Changes - -**Gewählte Module:** -- Gateway: Komplexes Spring Boot + Spring Cloud Setup -- Ping-Service: Einfacher Service, einfache Validierung - ---- - -## Fazit - -Erfolgreich abgeschlossene umfassende Gradle Build-Optimierung über alle 6 geplanten Phasen. Das Projekt hat jetzt: - -1. **Modernes Gradle 9.1.0** mit verbessertem Toolchain-Management -2. **20 neue Dependency-Bundles** die flexibles Dependency-Management bieten -3. **3 Convention Plugins** als Templates für zukünftige Nutzung -4. **Optimierte Build-Konfiguration** mit Kotlin-Compiler-Verbesserungen -5. **Umfassende Dokumentation** in REFACTORING-GUIDE.md -6. **Bewährte Patterns** demonstriert in Gateway- und Ping-Service-Modulen - -Die Grundlage ist jetzt gelegt für: -- Schnellere Build-Zeiten (20-40% Verbesserung erwartet) -- Einfachere Wartung mit zentralisierter Konfiguration -- Konsistente Patterns über alle Module -- Vereinfachtes Dependency-Management - -Alle Änderungen sind getestet, validiert und produktionsbereit. Die REFACTORING-GUIDE.md bietet klare Patterns für das Refactoring der verbleibenden 13+ Module nach dem gleichen Ansatz. - ---- - -## Geänderte Dateien - -``` -REFACTORING-GUIDE.md | 440 +++++++++++++++++++++ -build.gradle.kts | 39 +- -buildSrc/build.gradle.kts | 21 + -buildSrc/.../kotlin-multiplatform-conventions | 56 +++ -buildSrc/.../ktor-server-conventions | 53 +++ -buildSrc/.../spring-boot-service-conventions | 62 +++ -gradle.properties | 9 + -gradle/libs.versions.toml | 77 ++++ -infrastructure/gateway/build.gradle.kts | 83 ++-- -services/ping/ping-service/build.gradle.kts | 81 ++-- -------------------------------------------------------------------- -Gesamt: 10 Dateien geändert, 810 Einfügungen(+), 111 Löschungen(-) -``` - ---- - -**Optimierungsstatus:** ✅ **ABGESCHLOSSEN** -**Build-Status:** ✅ **VALIDIERT** -**Dokumentationsstatus:** ✅ **UMFASSEND** -**Produktionsbereit:** ✅ **JA** diff --git a/Tagebuch/GRADLE-OPTIMIZATION-SUMMARY.md b/Tagebuch/GRADLE-OPTIMIZATION-SUMMARY.md deleted file mode 100644 index b7dc2389..00000000 --- a/Tagebuch/GRADLE-OPTIMIZATION-SUMMARY.md +++ /dev/null @@ -1,619 +0,0 @@ -# Gradle Build Optimization - Complete Summary - -## Executive Summary - -Successfully completed comprehensive Gradle build optimization for the Meldestelle project across 6 major phases. The optimization modernized the build system to Gradle 9.1.0, introduced 20 new dependency bundles for improved maintainability, created 3 convention plugins for consistent configuration, and enhanced build performance through Kotlin compiler optimizations. - -**Total Impact:** -- **810 lines added, 111 deleted** across 10 files -- **20 new dependency bundles** created in version catalog -- **3 convention plugins** for DRY principles -- **2 example modules refactored** (Gateway, Ping-Service) with 20-37% code reduction -- **Gradle 9.1.0** with enhanced toolchain management - ---- - -## Phase 1: Bundles & Version Catalog ✅ - -**File:** `gradle/libs.versions.toml` (+77 lines) - -### Added Missing Libraries -1. **`slf4j-api`** - version 2.0.16 (centralized logging API) -2. **`kotlin-reflect`** - uses kotlin version reference (runtime reflection support) - -### Created 15 Granular Bundles -These bundles group related dependencies for fine-grained control: - -1. **`ktor-server-common`** (7 deps) - Core Ktor server dependencies - - core, netty, content-negotiation, serialization, status-pages, cors, default-headers - -2. **`ktor-server-security`** (2 deps) - Authentication & authorization - - auth, auth-jwt - -3. **`ktor-server-observability`** (2 deps) - Logging & metrics - - call-logging, metrics-micrometer - -4. **`ktor-server-docs`** (2 deps) - API documentation - - openapi, swagger - -5. **`ktor-client-common`** (5 deps) - HTTP client essentials - - core, content-negotiation, serialization, logging, auth - -6. **`spring-boot-web`** (3 deps) - Web application stack - - starter-web, starter-validation, starter-actuator - -7. **`spring-boot-security`** (4 deps) - Security & OAuth2 - - starter-security, oauth2-client, oauth2-resource-server, oauth2-jose - -8. **`spring-boot-data`** (2 deps) - Data persistence - - starter-data-jpa, starter-data-redis - -9. **`spring-boot-observability`** (4 deps) - Monitoring & tracing - - starter-actuator, micrometer-prometheus, tracing-bridge-brave, zipkin-reporter-brave - -10. **`compose-common`** (2 deps) - Compose lifecycle - - lifecycle-viewmodel-compose, lifecycle-runtime-compose - -11. **`jackson-kotlin`** (2 deps) - JSON serialization - - module-kotlin, datatype-jsr310 - -12. **`kotlinx-core`** (3 deps) - Kotlin fundamentals - - coroutines-core, serialization-json, datetime - -13. **`persistence-postgres`** (4 deps) - Database access - - exposed-core, exposed-dao, exposed-jdbc, postgresql-driver - -14. **`resilience`** (3 deps) - Circuit breaker patterns - - resilience4j-spring-boot3, resilience4j-reactor, spring-boot-starter-aop - -15. **`logging`** (3 deps) - Structured logging - - kotlin-logging-jvm, logback-classic, logback-core - -### Created 5 Complete Bundles -All-in-one bundles for rapid development: - -1. **`ktor-server-complete`** (14 deps) - Full Ktor server stack - - Combines: common, security, observability, docs + rate-limit - -2. **`spring-boot-service-complete`** (12 deps) - Full Spring Boot service - - Combines: web, security, data, observability - -3. **`database-complete`** (8 deps) - Complete persistence layer - - Exposed ORM + PostgreSQL + HikariCP + Flyway migrations - -4. **`testing-kmp`** (8 deps) - Comprehensive KMP testing - - JUnit 5, Mockk, AssertJ, Coroutines Test - -5. **`monitoring-complete`** (8 deps) - Full observability stack - - Actuator, Prometheus, Zipkin, Logback, SLF4J - -**Benefits:** -- Single source of truth for dependency groupings -- IDE autocompletion for bundle names -- Type-safe dependency management -- Easy to maintain and update versions - ---- - -## Phase 2: Root Build File ✅ - -**File:** `build.gradle.kts` (+39 lines modified) - -### Enhancements Made - -1. **Centralized Plugin Management** - ```kotlin - plugins { - // All plugins declared with 'apply false' at root level - alias(libs.plugins.kotlinJvm) apply false - alias(libs.plugins.kotlinMultiplatform) apply false - alias(libs.plugins.kotlinSerialization) apply false - alias(libs.plugins.kotlinSpring) apply false - alias(libs.plugins.kotlinJpa) apply false - alias(libs.plugins.composeMultiplatform) apply false - alias(libs.plugins.composeCompiler) apply false - alias(libs.plugins.spring.boot) apply false - alias(libs.plugins.spring.dependencyManagement) apply false - } - ``` - - Prevents "plugin loaded multiple times" errors in Gradle 9.1.0+ - - Subprojects apply via version catalog aliases - -2. **AllProjects Configuration** - ```kotlin - allprojects { - group = "at.mocode" - version = "1.0.0-SNAPSHOT" - - repositories { - mavenCentral() - google() - maven { url = uri("https://jitpack.io") } - // ... other repositories - } - } - ``` - -3. **Added Build Analysis Plugins** - - `com.github.ben-manes.versions` (0.51.0) - Dependency update checking - - Supports: `./gradlew dependencyUpdates` - -4. **Updated Gradle Wrapper** - ```kotlin - tasks.wrapper { - gradleVersion = "9.1.0" - distributionType = Wrapper.DistributionType.BIN - } - ``` - -**Benefits:** -- Consistent group/version across all modules -- Centralized repository configuration -- Plugin version conflicts prevented -- Modern Gradle 9.1.0 features enabled - ---- - -## Phase 3: Convention Plugins ✅ - -**Directory:** `buildSrc/src/main/kotlin/` (+192 lines) - -### Created 3 Convention Plugins - -#### 1. `kotlin-multiplatform-conventions.gradle.kts` (56 lines) -**Purpose:** Standardizes KMP module configuration - -**Applies:** -- `org.jetbrains.kotlin.multiplatform` -- `org.jetbrains.kotlin.plugin.serialization` - -**Configures:** -- Java 21 toolchain -- Kotlin compiler options (opt-in APIs, JVM target) -- Common test configuration with JUnit Platform - -**Target Modules:** -- clients/app, clients/ping-feature, clients/auth-feature -- clients/shared/* modules -- core/core-utils, core/core-domain - -#### 2. `spring-boot-service-conventions.gradle.kts` (62 lines) -**Purpose:** Standardizes Spring Boot service configuration - -**Applies:** -- `org.jetbrains.kotlin.jvm` -- `org.springframework.boot` -- `io.spring.dependency-management` -- `org.jetbrains.kotlin.plugin.spring` -- `org.jetbrains.kotlin.plugin.jpa` - -**Configures:** -- Java 21 toolchain -- Kotlin compiler options (JSR-305 strict, JVM 21) -- JPA all-open plugin for entities -- JUnit Platform test configuration - -**Target Modules:** -- infrastructure/gateway -- infrastructure/auth-server -- infrastructure/monitoring-server -- services/ping/ping-service -- All future Spring Boot services - -#### 3. `ktor-server-conventions.gradle.kts` (53 lines) -**Purpose:** Standardizes Ktor server configuration - -**Applies:** -- `org.jetbrains.kotlin.jvm` -- `io.ktor.plugin` -- `org.jetbrains.kotlin.plugin.serialization` - -**Configures:** -- Java 21 toolchain -- Kotlin compiler options -- Ktor fat JAR configuration -- JUnit Platform test configuration - -**Target Modules:** -- Any future Ktor-based backend services - -### BuildSrc Configuration -**File:** `buildSrc/build.gradle.kts` (21 lines) - -```kotlin -plugins { - `kotlin-dsl` -} - -repositories { - gradlePluginPortal() - mavenCentral() -} - -dependencies { - implementation(libs.kotlin.gradlePlugin) - implementation(libs.spring.boot.gradlePlugin) - implementation(libs.spring.dependencyManagement.gradlePlugin) - implementation(libs.ktor.gradlePlugin) -} -``` - -**Strategic Decision:** -While convention plugins were successfully created and are included in the commit, they are **NOT currently applied** to modules due to a discovered KMP incompatibility issue. The plugins remain in buildSrc as: -1. Documentation of intended patterns -2. Future reference when KMP compatibility is resolved -3. Reusable templates for non-KMP modules - -**Benefits (when applicable):** -- Eliminates 30-50 lines of boilerplate per module -- Ensures consistent toolchain configuration -- Single location for compiler settings updates -- Type-safe Kotlin DSL throughout - ---- - -## Phase 4: Module Refactoring (Strategic Sampling) ✅ - -### Example 1: infrastructure/gateway/build.gradle.kts -**Before:** 113 lines | **After:** 94 lines | **Reduction:** 20% - -#### Changes Made: -1. **Direct plugin application** (avoiding convention plugin due to KMP conflict) - ```kotlin - plugins { - alias(libs.plugins.kotlinJvm) - alias(libs.plugins.kotlinSpring) - alias(libs.plugins.kotlinJpa) - alias(libs.plugins.spring.boot) - alias(libs.plugins.spring.dependencyManagement) - } - ``` - -2. **Replaced individual dependencies with bundles:** - ```kotlin - // OLD: 15+ individual Spring Boot dependencies - // NEW: 4 bundles - implementation(libs.bundles.spring.cloud.gateway) - implementation(libs.bundles.spring.boot.service.complete) - implementation(libs.bundles.resilience) - implementation(libs.bundles.jackson.kotlin) - implementation(libs.bundles.logging) - ``` - -3. **Added platform BOM for version consistency:** - ```kotlin - implementation(platform(projects.platform.platformBom)) - ``` - -**Benefits:** -- More readable dependency section -- Easier to understand module purpose -- Consistent with other Spring Boot services -- Simplified future maintenance - -### Example 2: services/ping/ping-service/build.gradle.kts -**Before:** 79 lines | **After:** 54 lines | **Reduction:** 37% - -#### Changes Made: -1. **Direct plugin application:** - ```kotlin - plugins { - alias(libs.plugins.kotlinJvm) - alias(libs.plugins.kotlinSpring) - alias(libs.plugins.kotlinJpa) - alias(libs.plugins.spring.boot) - alias(libs.plugins.spring.dependencyManagement) - } - ``` - -2. **Comprehensive bundle usage:** - ```kotlin - implementation(libs.bundles.spring.boot.service.complete) - implementation(libs.bundles.jackson.kotlin) - implementation(libs.bundles.resilience) - implementation(libs.kotlin.reflect) // Now from version catalog - ``` - -3. **Cleaner test dependencies:** - ```kotlin - testImplementation(projects.platform.platformTesting) - testImplementation(libs.bundles.testing.jvm) - ``` - -**Benefits:** -- 37% code reduction -- Much clearer intent -- Consistent pattern for future services -- All dependencies centrally managed - ---- - -## Phase 5: Gradle Properties ✅ - -**File:** `gradle.properties` (+9 lines) - -### Added Kotlin Compiler Optimizations - -```properties -# Kotlin Compiler Optimizations (Phase 5) -kotlin.incremental=true -kotlin.incremental.multiplatform=true -kotlin.incremental.js=true -kotlin.caching.enabled=true -kotlin.compiler.execution.strategy=in-process -kotlin.compiler.preciseCompilationResultsBackup=true -kotlin.stdlib.default.dependency=true -``` - -### Performance Impact: -- **Incremental compilation:** ~20-40% faster rebuilds -- **Compiler caching:** Reuses compilation results across builds -- **In-process execution:** Reduces JVM startup overhead -- **Multiplatform optimization:** Improves KMP build times -- **JS compilation:** Faster JavaScript compilation - -### Additional Existing Optimizations: -```properties -org.gradle.parallel=true -org.gradle.caching=true -org.gradle.vfs.watch=true -org.gradle.workers.max=8 -``` - -**Note:** Configuration cache remains disabled due to JS test serialization issues: -```properties -org.gradle.configuration-cache=false -org.gradle.configuration-cache.problems=warn -``` - ---- - -## Phase 6: Testing & Validation ✅ - -### Build Validation -- ✅ **Syntax validation:** All Gradle files parse correctly -- ✅ **Dependency resolution:** All bundles resolve properly -- ✅ **Version catalog validation:** All references valid -- ✅ **Plugin compatibility:** Gradle 9.1.0 compatibility confirmed - -### Known Issues & Resolutions -1. **Convention Plugin KMP Conflict** - - **Issue:** Convention plugins conflict with KMP in same project - - **Resolution:** Kept plugins in buildSrc for documentation, but applied direct plugin declarations in modules - - **Status:** Working solution implemented - -2. **Configuration Cache** - - **Issue:** JS browser tests fail with serialization errors - - **Resolution:** Temporarily disabled, will re-enable after JS test framework update - - **Status:** Documented in gradle.properties - -3. **WASM Compatibility** - - **Issue:** Some dependencies lack WASM support - - **Resolution:** WASM is opt-in via `enableWasm=true` property - - **Status:** Working as designed - -### Build Commands Tested -```bash -./gradlew --refresh-dependencies # ✅ Pass -./gradlew projects # ✅ Pass -./gradlew :infrastructure:gateway:tasks # ✅ Pass -./gradlew :services:ping:ping-service:tasks # ✅ Pass -``` - ---- - -## Documentation Created ✅ - -### REFACTORING-GUIDE.md (440 lines) -Comprehensive guide including: - -1. **Overview** - Summary of all completed changes -2. **Completed Changes** - Detailed phase documentation -3. **Refactoring Patterns** - 3 complete patterns with before/after examples: - - Pattern 1: Spring Boot Services - - Pattern 2: Ktor Server Services - - Pattern 3: Kotlin Multiplatform Modules -4. **Module Refactoring Checklist** - Full inventory of all modules with refactoring status -5. **Build Commands** - Recommended commands for analysis and optimization -6. **Expected Benefits** - Quantified improvements -7. **Important Notes** - Configuration cache, WASM support, incremental approach -8. **References** - Links to official Gradle documentation - -**Purpose:** -- Serves as template for refactoring remaining modules -- Documents established patterns and conventions -- Provides copy-paste examples for common scenarios -- Explains strategic decisions made during optimization - ---- - -## Key Metrics & Statistics - -### Code Changes -- **Files modified:** 10 -- **Lines added:** 810 -- **Lines deleted:** 111 -- **Net impact:** +699 lines (mostly documentation and plugin infrastructure) - -### Version Catalog Enhancements -- **New bundles:** 20 (15 granular + 5 complete) -- **New libraries:** 2 (slf4j-api, kotlin-reflect) -- **Total bundles:** 25 (including 5 pre-existing) - -### Build File Reductions (in refactored modules) -- **Gateway:** 113 → 94 lines (-20%) -- **Ping-Service:** 79 → 54 lines (-37%) -- **Average reduction:** ~28% - -### Plugin Infrastructure -- **Convention plugins created:** 3 -- **Lines of reusable configuration:** 171 -- **Modules that could benefit:** 15+ modules - ---- - -## Benefits Achieved - -### 1. Maintainability -- ✅ **Single source of truth** for all dependency versions -- ✅ **Centralized plugin management** prevents version conflicts -- ✅ **Reusable patterns** via convention plugins and bundles -- ✅ **Comprehensive documentation** for future refactoring - -### 2. Build Performance -- ✅ **Gradle 9.1.0** with latest performance improvements -- ✅ **Kotlin compiler optimizations** enabled -- ✅ **Incremental compilation** configured -- ✅ **Build caching** and **parallel execution** enabled -- ✅ **Estimated improvement:** 20-40% faster rebuilds - -### 3. Developer Experience -- ✅ **IDE autocompletion** for bundle names -- ✅ **Type-safe dependency management** -- ✅ **Clear build file structure** with bundles -- ✅ **Consistent patterns** across all modules -- ✅ **Easy dependency updates** via version catalog - -### 4. Code Quality -- ✅ **Reduced duplication** through bundles and conventions -- ✅ **Standardized configuration** across modules -- ✅ **Better separation of concerns** -- ✅ **Easier code reviews** with fewer lines per module - ---- - -## Next Steps & Recommendations - -### Immediate Actions -1. ✅ **Commit changes** - All changes staged and ready -2. 🔲 **Apply patterns to remaining modules** - Use REFACTORING-GUIDE.md as template -3. 🔲 **Run full build** - `./gradlew clean build` after refactoring each module -4. 🔲 **Update CI/CD** - Ensure pipelines use Gradle 9.1.0 - -### Short-term (1-2 weeks) -1. 🔲 **Refactor infrastructure modules:** - - Auth-Server, Messaging-Config, Redis-Cache, Redis-Event-Store, Monitoring-Server -2. 🔲 **Refactor client modules:** - - clients/app, clients/auth-feature, clients/shared/* -3. 🔲 **Refactor core modules:** - - core/core-utils, core/core-domain (already uses some bundles) -4. 🔲 **Measure build time improvements** - Compare before/after metrics - -### Medium-term (1 month) -1. 🔲 **Enable configuration cache** - After resolving JS test serialization -2. 🔲 **Investigate WASM support** - Evaluate readiness of all dependencies -3. 🔲 **Run dependency analysis** - `./gradlew buildHealth` -4. 🔲 **Check for updates** - `./gradlew dependencyUpdates` - -### Long-term (3+ months) -1. 🔲 **Re-evaluate convention plugins** - Check if KMP compatibility improved -2. 🔲 **Build performance profiling** - Use `--scan` for detailed analysis -3. 🔲 **Dependency consolidation** - Review and remove unused dependencies -4. 🔲 **Version updates** - Regular maintenance of version catalog - ---- - -## Strategic Decisions Made - -### 1. Convention Plugins Approach -**Decision:** Created convention plugins but kept them in buildSrc without active application - -**Reasoning:** -- KMP and convention plugins in same project cause conflicts -- Gradle 9.1.0 plugin loading mechanism has stricter rules -- Direct plugin application via version catalog works reliably - -**Alternative Considered:** -- Separate convention plugin repository (rejected: too complex for single project) -- Inline configuration in each module (rejected: too much duplication) - -**Outcome:** -- Convention plugins serve as documentation and templates -- Modules use direct plugin application with bundles -- Achieved similar benefits through dependency bundles - -### 2. Bundle Granularity -**Decision:** Created both granular (15) and complete (5) bundles - -**Reasoning:** -- Granular bundles: Fine-grained control for specific use cases -- Complete bundles: Rapid development for standard patterns -- Flexibility: Teams can choose appropriate bundle level - -**Examples:** -- Use `ktor-server-common` for minimal API service -- Use `ktor-server-complete` for full-featured gateway - -### 3. Gradle 9.1.0 Adoption -**Decision:** Upgraded to Gradle 9.1.0 immediately - -**Reasoning:** -- Latest features and performance improvements -- Better Kotlin DSL support -- Required for modern plugin management -- Long-term maintenance benefits - -**Risks Mitigated:** -- Tested compatibility with all plugins -- Verified build works end-to-end -- Documented breaking changes (plugin loading) - -### 4. Incremental Refactoring -**Decision:** Refactored 2 example modules, documented patterns for others - -**Reasoning:** -- Proves patterns work in real codebase -- Creates templates for remaining work -- Allows validation before large-scale changes -- Reduces risk of breaking changes - -**Modules Chosen:** -- Gateway: Complex Spring Boot + Spring Cloud setup -- Ping-Service: Simple service, easy validation - ---- - -## Conclusion - -Successfully completed comprehensive Gradle build optimization covering all 6 planned phases. The project now has: - -1. **Modern Gradle 9.1.0** with enhanced toolchain management -2. **20 new dependency bundles** providing flexible dependency management -3. **3 convention plugins** as templates for future use -4. **Optimized build configuration** with Kotlin compiler enhancements -5. **Comprehensive documentation** in REFACTORING-GUIDE.md -6. **Proven patterns** demonstrated in Gateway and Ping-Service modules - -The foundation is now in place for: -- Faster build times (20-40% improvement expected) -- Easier maintenance with centralized configuration -- Consistent patterns across all modules -- Simplified dependency management - -All changes are tested, validated, and ready for production use. The REFACTORING-GUIDE.md provides clear patterns for refactoring the remaining 13+ modules following the same approach. - ---- - -## Files Changed - -``` -REFACTORING-GUIDE.md | 440 +++++++++++++++++++++ -build.gradle.kts | 39 +- -buildSrc/build.gradle.kts | 21 + -buildSrc/.../kotlin-multiplatform-conventions | 56 +++ -buildSrc/.../ktor-server-conventions | 53 +++ -buildSrc/.../spring-boot-service-conventions | 62 +++ -gradle.properties | 9 + -gradle/libs.versions.toml | 77 ++++ -infrastructure/gateway/build.gradle.kts | 83 ++-- -services/ping/ping-service/build.gradle.kts | 81 ++-- -------------------------------------------------------------------- -Total: 10 files changed, 810 insertions(+), 111 deletions(-) -``` - ---- - -**Optimization Status:** ✅ **COMPLETE** -**Build Status:** ✅ **VALIDATED** -**Documentation Status:** ✅ **COMPREHENSIVE** -**Ready for Production:** ✅ **YES** diff --git a/Tagebuch/KEYCLOAK-RESOLUTION-DE.md b/Tagebuch/KEYCLOAK-RESOLUTION-DE.md deleted file mode 100644 index e9eae0b6..00000000 --- a/Tagebuch/KEYCLOAK-RESOLUTION-DE.md +++ /dev/null @@ -1,211 +0,0 @@ -# Keycloak-Konfigurationslösungsbericht -**Datum:** 2025-10-05 -**Status:** ✅ GELÖST - Keycloak ist stabil und das Authentifizierungssystem ist betriebsbereit - -## Problemübersicht -Keycloak erlebte Neustart-Schleifen und Initialisierungsprobleme, die verhinderten, dass das Authentifizierungssystem ordnungsgemäß funktionierte. - -## Identifizierte Grundursachen -1. **Komplexe Umgebungskonfiguration**: Übermäßig komplexe Umgebungsvariablen mit JVM-Optimierungen und erweiterten Einstellungen verursachten Startkonflikte -2. **Health Check-Probleme**: Der Health Check verwendete falsche Endpunkte und schlug bei HTTP-Weiterleitungen fehl -3. **Realm-Import-Konflikte**: Das `--import-realm` Flag trug möglicherweise zu Startproblemen bei - -## Angewandte Lösungen - -### 1. Vereinfachte Umgebungskonfiguration -**Datei:** `docker-compose.yml` -```yaml -environment: - # Minimale Konfiguration für Fehlerbehebung - KEYCLOAK_ADMIN: admin - KEYCLOAK_ADMIN_PASSWORD: admin - KC_DB: postgres - KC_DB_URL: jdbc:postgresql://postgres:5432/meldestelle - KC_DB_USERNAME: meldestelle - KC_DB_PASSWORD: meldestelle - KC_DB_SCHEMA: keycloak - KC_HTTP_ENABLED: true - KC_HOSTNAME_STRICT: false -``` - -**Entfernte problematische Konfigurationen:** -- Komplexe JVM-Optimierungs-Flags -- Erweiterte Cache-Konfigurationen -- Detaillierte Logging-Konfigurationen -- Datenbankverbindungspool-Optimierungen - -### 2. Behobene Health Check-Konfiguration -```yaml -healthcheck: - test: [ 'CMD-SHELL', 'curl -s http://localhost:8080/ >/dev/null 2>&1 || exit 1' ] - interval: 15s - timeout: 10s - retries: 5 - start_period: 60s -``` - -**Vorgenommene Änderungen:** -- `-f` Flag von curl entfernt (schlug bei 302-Weiterleitungen fehl) -- Health Check vereinfacht, um Basis-Endpunkt zu verwenden -- Timeouts und Wiederholungsversuche reduziert - -### 3. Realm-Import während initialer Einrichtung entfernt -```yaml -command: - # Entwicklungsmodus mit Basis-Image - minimale Einrichtung - - start-dev -``` - -**Entfernt:** `--import-realm` Flag zur Eliminierung potenzieller Startkonflikte - -### 4. Service-Abhängigkeiten angepasst -```yaml -keycloak: - condition: service_started # Geändert von service_healthy -``` - -**Begründung:** API Gateway durfte auch mit Health Check-Problemen starten, da Keycloak funktional arbeitet - -## Aktueller Systemstatus ✅ - -### Laufende Services -- ✅ **Keycloak**: Stabil und antwortet (Port 8180) -- ✅ **API Gateway**: Gesund und routet ordnungsgemäß (Port 8081) -- ✅ **Ping Service**: Betriebsbereit mit Health Checks (Port 8082) -- ✅ **PostgreSQL**: Gesund mit initialisiertem Keycloak-Schema -- ✅ **Consul**: Service Discovery funktioniert -- ✅ **Redis**: Cache-Service gesund - -### Verifikationsergebnisse -```bash -# API Gateway-Routing zum Ping Service -$ curl http://localhost:8081/api/ping/health -{"status":"pong","timestamp":"2025-10-05T19:22:08.302871057Z","service":"ping-service","healthy":true} - -# Keycloak antwortet -$ curl -s -o /dev/null -w "%{http_code}" http://localhost:8180/ -302 # Korrekte Weiterleitungsantwort - -# Service Discovery -Alle Services ordnungsgemäß in Consul registriert: api-gateway, consul, ping-service -``` - -## Empfehlungen für Produktion - -### 1. Realm-Import wieder aktivieren -Nach Stabilisierung Realm-Import wieder hinzufügen: -```yaml -command: - - start-dev - - --import-realm -``` - -### 2. Umgebungskonfiguration schrittweise optimieren -Optimierungen eine nach der anderen wieder einführen: -```yaml -# JVM-Optimierungen wieder hinzufügen -JAVA_OPTS_APPEND: >- - -XX:MaxRAMPercentage=75.0 - -XX:+UseG1GC - -XX:+UseStringDeduplication - -# Datenbankpool-Einstellungen wieder hinzufügen -KC_DB_POOL_INITIAL_SIZE: 5 -KC_DB_POOL_MIN_SIZE: 5 -KC_DB_POOL_MAX_SIZE: 20 -``` - -### 3. Health Check verbessern -Erwägen Sie einen spezifischeren Health-Endpunkt: -```yaml -healthcheck: - test: [ 'CMD-SHELL', 'curl -s http://localhost:8080/health/ready || curl -s http://localhost:8080/ >/dev/null' ] -``` - -### 4. Sicherheitshärtung für Produktion -- Standard-Admin-Anmeldedaten ändern -- HTTPS aktivieren -- Ordnungsgemäße Hostname-Einstellungen konfigurieren -- Authentifizierung zur Realm-Konfiguration hinzufügen - -## Geänderte Dateien -- ✅ `docker-compose.yml` - Vereinfachte Keycloak-Konfiguration -- ✅ `dockerfiles/infrastructure/keycloak/Dockerfile` - Vereinfachter Build-Prozess - -## Testverifizierung -Die vollständige Authentifizierungsinfrastruktur funktioniert jetzt: -1. ✅ Keycloak startet und bleibt stabil -2. ✅ API Gateway verbindet sich mit Keycloak -3. ✅ Ping Service integriert sich mit Gateway -4. ✅ Service Discovery funktioniert -5. ✅ Health Checks betriebsbereit - -## Realm-Import-Testergebnisse ✅ - -### Erfolgreich abgeschlossen -- ✅ **Realm-Import**: Die meldestelle-realm.json importiert erfolgreich -- ✅ **Benutzererstellung**: Admin-Benutzer mit Realm-Rollen erstellt (ADMIN, USER) -- ✅ **Client-Import**: Sowohl api-gateway- als auch web-app-Clients korrekt importiert -- ✅ **Service-Integration**: API Gateway verbindet sich mit importiertem Realm -- ✅ **Systemstabilität**: Alle Services bleiben während Realm-Operationen gesund - -### Aktueller Authentifizierungsstatus -```bash -# System-Verifikationsergebnisse -Services-Status: -- API Gateway: Gesund ✅ -- Ping Service: Gesund ✅ -- Keycloak: Funktional, aber Health Check-Probleme -- PostgreSQL, Redis, Consul: Alle gesund ✅ - -Realm-Status: -- meldestelle realm: Erfolgreich importiert ✅ -- Admin-Benutzer: Verfügbar (Passwort: Change_Me_In_Production!) -- Clients: api-gateway, web-app konfiguriert ✅ -``` - -### Identifizierte Probleme zur Lösung -1. **OpenID Discovery-Endpunkt**: Gibt null Issuer zurück (benötigt Hostname-Konfiguration) -2. **Client-Secret**: api-gateway-Client-Anmeldedaten benötigen ordnungsgemäße Secret-Konfiguration -3. **Health Check**: Keycloak zeigt ungesund, funktioniert aber -4. **Authentifizierungsflow**: Noch nicht auf API Gateway-Routen durchgesetzt - -## Nächste Schritte für vollständige Authentifizierung - -### Sofortige erforderliche Maßnahmen -1. **OpenID-Konfiguration beheben** - - KC_HOSTNAME für ordnungsgemäße Issuer-URLs konfigurieren - - Sicherstellen, dass Realm-Discovery-Endpunkte korrekt funktionieren - -2. **Client-Secrets konfigurieren** - - Ordnungsgemäßes Client-Secret für api-gateway setzen - - Client-Credentials-Flow testen - -3. **Authentifizierungsdurchsetzung aktivieren** - - API Gateway so konfigurieren, dass Authentifizierung erforderlich ist - - Geschützte Endpunkte mit JWT-Token testen - -### Schritte zur Produktionsbereitschaft -1. **Sicherheitshärtung** - - Standard-Admin-Passwort vom Realm-Import ändern - - HTTPS für Produktion konfigurieren - - Ordnungsgemäße Hostname-Einstellungen setzen - -2. **Leistungsoptimierung** - - JVM-Optimierungen schrittweise wieder hinzufügen - - Datenbankverbindungspooling konfigurieren - - Caching-Optimierungen aktivieren - -### Empfohlene Konfigurationsupdates -```yaml -# Für Produktion zu docker-compose.yml hinzufügen -KC_HOSTNAME: https://auth.meldestelle.at -KC_HOSTNAME_STRICT: true -KC_HTTPS_CERTIFICATE_FILE: /opt/keycloak/ssl/cert.pem -KC_HTTPS_CERTIFICATE_KEY_FILE: /opt/keycloak/ssl/key.pem -``` - ---- -**Realm-Import-Test: ✅ ERFOLGREICH ABGESCHLOSSEN** -**Systemstatus: Stabil mit betriebsbereiter Authentifizierungsinfrastruktur** -**Nächste Phase: Client-Authentifizierung konfigurieren und Sicherheitsdurchsetzung aktivieren** diff --git a/Tagebuch/KEYCLOAK-RESOLUTION.md b/Tagebuch/KEYCLOAK-RESOLUTION.md deleted file mode 100644 index f9ebd0f1..00000000 --- a/Tagebuch/KEYCLOAK-RESOLUTION.md +++ /dev/null @@ -1,211 +0,0 @@ -# Keycloak Configuration Resolution Report -**Date:** 2025-10-05 -**Status:** ✅ RESOLVED - Keycloak is stable and authentication system is operational - -## Problem Summary -Keycloak was experiencing restart loops and initialization issues, preventing the authentication system from working properly. - -## Root Causes Identified -1. **Complex Environment Configuration**: Overly complex environment variables with JVM optimizations and advanced settings were causing startup conflicts -2. **Health Check Issues**: The health check was using incorrect endpoints and failing on HTTP redirects -3. **Realm Import Conflicts**: The `--import-realm` flag was potentially contributing to startup issues - -## Solutions Applied - -### 1. Simplified Environment Configuration -**File:** `docker-compose.yml` -```yaml -environment: - # Minimal configuration for troubleshooting - KEYCLOAK_ADMIN: admin - KEYCLOAK_ADMIN_PASSWORD: admin - KC_DB: postgres - KC_DB_URL: jdbc:postgresql://postgres:5432/meldestelle - KC_DB_USERNAME: meldestelle - KC_DB_PASSWORD: meldestelle - KC_DB_SCHEMA: keycloak - KC_HTTP_ENABLED: true - KC_HOSTNAME_STRICT: false -``` - -**Removed problematic configurations:** -- Complex JVM optimization flags -- Advanced cache configurations -- Detailed logging configurations -- Database connection pool optimizations - -### 2. Fixed Health Check Configuration -```yaml -healthcheck: - test: [ 'CMD-SHELL', 'curl -s http://localhost:8080/ >/dev/null 2>&1 || exit 1' ] - interval: 15s - timeout: 10s - retries: 5 - start_period: 60s -``` - -**Changes made:** -- Removed `-f` flag from curl (was failing on 302 redirects) -- Simplified health check to use base endpoint -- Reduced timeouts and retry counts - -### 3. Removed Realm Import During Initial Setup -```yaml -command: - # Development mode with base image - minimal setup - - start-dev -``` - -**Removed:** `--import-realm` flag to eliminate potential startup conflicts - -### 4. Adjusted Service Dependencies -```yaml -keycloak: - condition: service_started # Changed from service_healthy -``` - -**Rationale:** Allowed API gateway to start even with health check issues since Keycloak is functionally working - -## Current System Status ✅ - -### Services Running -- ✅ **Keycloak**: Stable and responding (port 8180) -- ✅ **API Gateway**: Healthy and routing properly (port 8081) -- ✅ **Ping Service**: Operational with health checks (port 8082) -- ✅ **PostgreSQL**: Healthy with Keycloak schema initialized -- ✅ **Consul**: Service discovery working -- ✅ **Redis**: Cache service healthy - -### Verification Results -```bash -# API Gateway routing to Ping Service -$ curl http://localhost:8081/api/ping/health -{"status":"pong","timestamp":"2025-10-05T19:22:08.302871057Z","service":"ping-service","healthy":true} - -# Keycloak responding -$ curl -s -o /dev/null -w "%{http_code}" http://localhost:8180/ -302 # Correct redirect response - -# Service Discovery -All services properly registered in Consul: api-gateway, consul, ping-service -``` - -## Recommendations for Production - -### 1. Re-enable Realm Import -Once stable, add back realm import: -```yaml -command: - - start-dev - - --import-realm -``` - -### 2. Optimize Environment Configuration Gradually -Reintroduce optimizations one by one: -```yaml -# Add back JVM optimizations -JAVA_OPTS_APPEND: >- - -XX:MaxRAMPercentage=75.0 - -XX:+UseG1GC - -XX:+UseStringDeduplication - -# Add back database pool settings -KC_DB_POOL_INITIAL_SIZE: 5 -KC_DB_POOL_MIN_SIZE: 5 -KC_DB_POOL_MAX_SIZE: 20 -``` - -### 3. Improve Health Check -Consider using a more specific health endpoint: -```yaml -healthcheck: - test: [ 'CMD-SHELL', 'curl -s http://localhost:8080/health/ready || curl -s http://localhost:8080/ >/dev/null' ] -``` - -### 4. Security Hardening for Production -- Change default admin credentials -- Enable HTTPS -- Configure proper hostname settings -- Add authentication to realm configuration - -## Files Modified -- ✅ `docker-compose.yml` - Simplified Keycloak configuration -- ✅ `dockerfiles/infrastructure/keycloak/Dockerfile` - Simplified build process - -## Testing Verification -The complete authentication infrastructure is now working: -1. ✅ Keycloak starts and remains stable -2. ✅ API Gateway connects to Keycloak -3. ✅ Ping Service integrates with gateway -4. ✅ Service discovery functioning -5. ✅ Health checks operational - -## Realm Import Testing Results ✅ - -### Successfully Completed -- ✅ **Realm Import**: The meldestelle-realm.json imports successfully -- ✅ **User Creation**: Admin user created with realm roles (ADMIN, USER) -- ✅ **Client Import**: Both api-gateway and web-app clients imported correctly -- ✅ **Service Integration**: API Gateway connects to imported realm -- ✅ **System Stability**: All services remain healthy during realm operations - -### Current Authentication Status -```bash -# System Verification Results -Services Status: -- API Gateway: Healthy ✅ -- Ping Service: Healthy ✅ -- Keycloak: Functional but health check issues -- PostgreSQL, Redis, Consul: All healthy ✅ - -Realm Status: -- meldestelle realm: Imported successfully ✅ -- Admin user: Available (password: Change_Me_In_Production!) -- Clients: api-gateway, web-app configured ✅ -``` - -### Identified Issues for Resolution -1. **OpenID Discovery Endpoint**: Returns null issuer (needs hostname configuration) -2. **Client Secret**: api-gateway client credentials need proper secret configuration -3. **Health Check**: Keycloak shows unhealthy but is functionally working -4. **Authentication Flow**: Not yet enforced on API Gateway routes - -## Next Steps for Full Authentication - -### Immediate Actions Required -1. **Fix OpenID Configuration** - - Configure KC_HOSTNAME for proper issuer URLs - - Ensure realm discovery endpoints work correctly - -2. **Configure Client Secrets** - - Set proper client secret for api-gateway - - Test client credentials flow - -3. **Enable Authentication Enforcement** - - Configure API Gateway to require authentication - - Test protected endpoints with JWT tokens - -### Production Readiness Steps -1. **Security Hardening** - - Change default admin password from realm import - - Configure HTTPS for production - - Set proper hostname settings - -2. **Performance Optimization** - - Re-add JVM optimizations gradually - - Configure database connection pooling - - Enable caching optimizations - -### Recommended Configuration Updates -```yaml -# For production, add to docker-compose.yml -KC_HOSTNAME: https://auth.meldestelle.at -KC_HOSTNAME_STRICT: true -KC_HTTPS_CERTIFICATE_FILE: /opt/keycloak/ssl/cert.pem -KC_HTTPS_CERTIFICATE_KEY_FILE: /opt/keycloak/ssl/key.pem -``` - ---- -**Realm Import Testing: ✅ COMPLETED SUCCESSFULLY** -**System Status: Stable with authentication infrastructure ready** -**Next Phase: Configure client authentication and enable security enforcement** diff --git a/Tagebuch/README-ENV.md b/Tagebuch/README-ENV.md deleted file mode 100644 index 66544fbc..00000000 --- a/Tagebuch/README-ENV.md +++ /dev/null @@ -1,187 +0,0 @@ -# Umgebungsvariablen Setup - Zusammenfassung - -## Was wurde implementiert - -Das Meldestelle-Projekt verfügt über eine vollständig zentralisierte Umgebungsvariablen-Konfiguration im `config/` Verzeichnis. - -### 1. Zentrale Konfigurationsstruktur - -- **`config/.env.template`** - Master-Vorlage mit allen verfügbaren Umgebungsvariablen -- **`config/.env.dev`** - Entwicklungsumgebung-Konfiguration -- **`config/.env.prod`** - Produktionsumgebung-Konfiguration -- **`config/.env.staging`** - Staging-Umgebung-Konfiguration -- **`config/.env.test`** - Testumgebung-Konfiguration -- **`config/README.md`** - Umfassende Dokumentation der Konfigurationsverwaltung - -### 2. Aktualisierte Dateien - -- **`docker-compose.yml`** - Alle Services verwenden Umgebungsvariablen mit Fallback-Werten -- **Symlink `.env`** - Verweist auf die aktuelle Umgebungskonfiguration - -### 3. Konfigurierte Services - -Die folgenden Services sind vollständig konfiguriert: - -- **PostgreSQL** - Datenbank mit konfigurierbaren Zugangsdaten -- **Redis** - Event Store und Cache mit separaten Konfigurationen -- **Keycloak** - Authentifizierung mit konfigurierbaren Admin-Zugangsdaten -- **Kafka/Zookeeper** - Messaging-System mit konfigurierbaren Parametern -- **Grafana** - Monitoring mit konfigurierbaren Admin-Zugangsdaten -- **Prometheus** - Metriken-Sammlung -- **Zipkin** - Distributed Tracing - -### 4. Umgebungsvariablen-Kategorien - -- **Anwendungskonfiguration** (API_HOST, API_PORT, etc.) -- **Datenbank-Konfiguration** (DB_HOST, DB_PORT, DB_USER, etc.) -- **Redis-Konfiguration** (Event Store und Cache) -- **Sicherheitskonfiguration** (JWT_SECRET, API_KEY, etc.) -- **Keycloak-Konfiguration** (Admin-Zugangsdaten, DB-Verbindung) -- **Service Discovery** (Consul-Konfiguration) -- **Messaging** (Kafka/Zookeeper-Konfiguration) -- **Monitoring** (Grafana, Prometheus-Konfiguration) -- **Logging-Konfiguration** (Log-Level, Request/Response-Logging) -- **CORS und Rate Limiting** - -## Verwendung - -### Schnellstart - -1. **Umgebung wählen:** - ```bash - # Für Entwicklung - ln -sf config/.env.dev .env - - # Für Produktion - ln -sf config/.env.prod .env - - # Für Tests - ln -sf config/.env.test .env - ``` - -2. **Services starten:** - ```bash - docker compose up -d - ``` - -3. **Services überprüfen:** - ```bash - docker compose ps - ``` - -### Anpassungen - -- Kopieren und bearbeiten Sie die gewünschte `.env.*` Datei aus dem `config/` Verzeichnis -- Verwenden Sie verschiedene Ports für mehrere Entwickler (siehe `.env.test` für Beispiel) -- Ändern Sie alle `CHANGE_ME` Werte in Produktionsumgebungen - -### Dokumentation - -Vollständige Dokumentation finden Sie in: -- `config/README.md` - Zentrale Konfigurationsdokumentation - -## Sicherheitshinweise - -⚠️ **Wichtig:** -- Niemals Produktionsgeheimnisse in die Versionskontrolle einbinden -- JWT_SECRET in der Produktion ändern -- Starke Passwörter für Produktionsumgebungen verwenden -- API-Schlüssel regelmäßig rotieren - -## Fehlerbehebung - -Bei Problemen: -1. Überprüfen Sie die aktive Umgebungskonfiguration: `ls -la .env` -2. Validieren Sie die Docker-Compose-Konfiguration: `docker compose config` -3. Überprüfen Sie die Service-Logs: `docker compose logs -f` -4. Konsultieren Sie `config/README.md` für detaillierte Konfigurationsrichtlinien - -### Keycloak startet neu (Restart-Loop) oder beendet sich mit Code 1 -Das Problem tritt häufig auf, wenn das Keycloak-DB-Schema fehlt oder nicht zur aktuell gesetzten `KC_DB_SCHEMA` passt. - -So gehen Sie vor: - -- Logs erfassen (bitte im Fehlerfall mitschicken): - - Keycloak: `docker compose logs -f keycloak` - - Postgres: `docker compose logs -f postgres` - -- Schema-Status prüfen und ggf. manuell anlegen (nur wenn das Volume bereits existierte, als die Init-Skripte eingeführt wurden): - 1. In die Datenbank einloggen: - ```bash - docker exec -it meldestelle-postgres psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" - ``` - 2. Folgende Befehle ausführen (ersetzen Sie den Benutzer bei Bedarf): - ```sql - CREATE SCHEMA IF NOT EXISTS keycloak; - GRANT ALL PRIVILEGES ON SCHEMA keycloak TO "$POSTGRES_USER"; - GRANT USAGE ON SCHEMA keycloak TO "$POSTGRES_USER"; - ALTER DEFAULT PRIVILEGES IN SCHEMA keycloak GRANT ALL ON TABLES TO "$POSTGRES_USER"; - ALTER DEFAULT PRIVILEGES IN SCHEMA keycloak GRANT ALL ON SEQUENCES TO "$POSTGRES_USER"; - ``` - -- Alternativ: Volumes zurücksetzen (Achtung: Datenverlust in Postgres und Keycloak-Volume!) - ```bash - docker compose down -v - docker compose up -d postgres keycloak - ``` - Hinweis: Bei frischen Volumes legt Postgres via `docker/services/postgres/01-init-keycloak-schema.sql` das Schema automatisch an. Die Datei `02-init-keycloak-schema.sql` ist absichtlich ein No-Op, um Doppel-Initialisierungen zu vermeiden. - -- Konfiguration prüfen: - - `KC_DB_SCHEMA` ist in `docker-compose.yml` parametrisiert und standardmäßig auf `keycloak` gesetzt. Sie können es in Ihrer `.env`-Datei überschreiben. - - In Staging/Prod muss `KC_DB_URL`, `KC_DB_USERNAME`, `KC_DB_PASSWORD` auf die jeweilige DB/Benutzer zeigen (siehe `config/.env.staging`, `config/.env.prod`). - -### Postgres Healthcheck schlägt fehl -Der Healthcheck ist jetzt vollständig über Umgebungsvariablen parametrisiert und passt sich Dev/Staging/Prod automatisch an: -```yaml -healthcheck: - test: [ "CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-meldestelle} -d ${POSTGRES_DB:-meldestelle}" ] -``` -Stellen Sie sicher, dass `POSTGRES_USER` und `POSTGRES_DB` korrekt gesetzt sind. - -### Compose-Warnung "The BUILD_DATE variable is not set" -Die Warnung ist in `docker-compose.yml` behoben. Für Build-Argumente wird nun ein Fallback verwendet: -```yaml -BUILD_DATE: ${BUILD_DATE:-unknown} -``` -Wenn Sie ein Datum setzen möchten, fügen Sie `BUILD_DATE=2025-10-05T16:55:00Z` Ihrer `.env` hinzu. - -### Logging/Health Optimierungen (optional) -- Aktuell ist `KC_LOG_CONSOLE_FORMAT` auf `plain` gesetzt, um Standard-Logs auszugeben. Für strukturierte Logs können Sie `KC_LOG_CONSOLE_FORMAT=json` setzen. -- `KC_HEALTH_ENABLED=true` und ein großzügiges `start_period` (180s) sind aktiv, um Realm-Importe abwarten zu können. - -## Nächste Schritte - -- Die zentrale Konfiguration ist bereits vollständig implementiert -- Wählen Sie die gewünschte Umgebung mit den Symlink-Befehlen oben -- Passen Sie Konfigurationswerte in den `config/.env.*` Dateien nach Bedarf an -- Für neue Umgebungen verwenden Sie `config/.env.template` als Ausgangspunkt - - ---- - -## Smoke-Tests (Prometheus & Zipkin) - -Nach dem Start der Infrastruktur können einfache Smoke-Tests ausgeführt werden: - -```bash -# Zipkin: erzeugt einen Ping über das Gateway und prüft, ob Traces ankommen -bash scripts/smoke/zipkin_smoke.sh - -# Prometheus: prüft, ob Gateway und Ping-Service Metriken exponieren -bash scripts/smoke/prometheus_smoke.sh -``` - -Variablen: -- GATEWAY_URL (Default: http://localhost:8081) -- ZIPKIN_URL (Default: http://localhost:9411) -- PING_SERVICE_URL (Default: http://localhost:8082) - - -## Keycloak Healthcheck - -- Der Keycloak-Container verwendet nun einen robusten Healthcheck, der nicht von curl abhängt. -- Ablauf: Zuerst wird curl verwendet, falls vorhanden; alternativ wget; fehlt beides, wird ein Bash-/dev/tcp-Fallback genutzt. In diesem Fall wird eine klare Fehlermeldung in den Healthcheck-Logs ausgegeben. -- Zeitparameter: interval 15s, timeout 30s, retries 10, start_period 180s – ausreichend, um längere Realm-Imports (30+ Sekunden) abzuwarten. -- Beispiel (vereinfacht): - - test: CMD-SHELL - - if curl vorhanden → GET /health/ready prüfen; sonst wget; sonst Bash /dev/tcp mit HTTP-Status „200 OK“ prüfen. diff --git a/Tagebuch/README-PRODUCTION.md b/Tagebuch/README-PRODUCTION.md deleted file mode 100644 index 72ac6eb7..00000000 --- a/Tagebuch/README-PRODUCTION.md +++ /dev/null @@ -1,489 +0,0 @@ -# Meldestelle - Produktionsumgebung Setup - -## Übersicht - -Dieses Dokument beschreibt die Einrichtung und den Betrieb der Meldestelle-Anwendung in einer Produktionsumgebung mit Docker Compose. Die Produktionskonfiguration bietet erweiterte Sicherheitsfeatures, TLS-Verschlüsselung und optimierte Performance-Einstellungen. - -## 🔒 Sicherheitsfeatures - -### Implementierte Sicherheitsmaßnahmen - -1. **Starke Authentifizierung** - - Redis mit Passwort-Authentifizierung - - PostgreSQL mit SCRAM-SHA-256 Authentifizierung - - Kafka mit SASL/SSL Sicherheit - - Zookeeper mit SASL Authentifizierung - -2. **TLS/SSL Verschlüsselung** - - HTTPS-only für alle Web-Services - - TLS-Unterstützung für Redis (konfigurierbar) - - SSL für PostgreSQL - - SSL/TLS für Kafka Inter-Broker Kommunikation - -3. **Netzwerksicherheit** - - Interne Service-Kommunikation ohne Host-Port-Exposition - - Nginx Reverse Proxy als einziger öffentlicher Zugang - - Isoliertes Docker-Netzwerk mit definiertem Subnetz - -4. **Container-Sicherheit** - - Non-root User für alle Services - - Resource-Limits für alle Container - - Read-only Mounts für Konfigurationsdateien - - Restart-Policies für Hochverfügbarkeit - -## 📋 Voraussetzungen - -### System-Anforderungen - -- **Betriebssystem**: Linux (Ubuntu 20.04+ empfohlen) -- **Docker**: Version 20.10+ -- **Docker Compose**: Version 2.0+ -- **RAM**: Mindestens 8GB (16GB empfohlen) -- **CPU**: Mindestens 4 Cores -- **Speicher**: Mindestens 50GB freier Speicherplatz - -### Netzwerk-Anforderungen - -- **Ports**: 80, 443 (HTTP/HTTPS) -- **Domain**: Gültige Domain-Namen für SSL-Zertifikate -- **DNS**: Korrekte DNS-Konfiguration für alle Subdomains - -## 🚀 Installation und Setup - -### 1. Repository klonen - -```bash -git clone -cd Meldestelle -``` - -### 2. Produktionsumgebung konfigurieren - -```bash -# Kopieren Sie die Produktions-Umgebungsvariablen aus dem config Verzeichnis -cp config/.env.prod .env.prod - -# Bearbeiten Sie die Produktionskonfiguration -nano .env.prod - -# Oder verwenden Sie einen Symlink für direkte Nutzung -ln -sf config/.env.prod .env -``` - -### 3. SSL-Zertifikate einrichten - -Siehe [SSL-Zertifikat Setup Anleitung](../config/ssl/README-de.md) für detaillierte Anweisungen. - -#### Schnellstart mit Let's Encrypt - -```bash -# Installieren Sie Certbot -sudo apt-get update -sudo apt-get install certbot - -# Generieren Sie Zertifikate -sudo certbot certonly --standalone \ - -d yourdomain.com \ - -d api.yourdomain.com \ - -d auth.yourdomain.com \ - -d monitoring.yourdomain.com - -# Kopieren Sie Zertifikate -sudo cp /etc/letsencrypt/live/yourdomain.com/fullchain.pem config/ssl/nginx/server.crt -sudo cp /etc/letsencrypt/live/yourdomain.com/privkey.pem config/ssl/nginx/server.key - -# Generieren Sie Diffie-Hellman Parameter -openssl dhparam -out config/ssl/nginx/dhparam.pem 2048 -``` - -### 4. Konfigurationsdateien anpassen - -#### Passwörter generieren - -```bash -# Starke Passwörter generieren -openssl rand -base64 32 # Für Datenbank-Passwörter -openssl rand -base64 64 # Für JWT-Secret -openssl rand -base64 32 # Für Redis-Passwort -``` - -#### Wichtige Konfigurationen in .env.prod - -```bash -# Datenbank (ÄNDERN SIE DIESE WERTE!) -POSTGRES_PASSWORD=IHR_STARKES_DB_PASSWORT -DB_PASSWORD=IHR_STARKES_DB_PASSWORT - -# Redis (ÄNDERN SIE DIESE WERTE!) -REDIS_PASSWORD=IHR_STARKES_REDIS_PASSWORT - -# JWT (ÄNDERN SIE DIESE WERTE!) -JWT_SECRET=IHR_STARKER_JWT_SECRET_MINDESTENS_256_BITS - -# Keycloak (ÄNDERN SIE DIESE WERTE!) -KEYCLOAK_ADMIN=ihr_admin_username -KEYCLOAK_ADMIN_PASSWORD=IHR_STARKES_ADMIN_PASSWORT - -# Domains (ÄNDERN SIE DIESE WERTE!) -KC_HOSTNAME=auth.ihredomain.com -GRAFANA_HOSTNAME=monitoring.ihredomain.com -PROMETHEUS_HOSTNAME=metrics.ihredomain.com -``` - -### 5. Services starten - -```bash -# Produktionsumgebung starten -docker compose -f docker-compose.prod.yml --env-file .env.prod up -d - -# Status überprüfen -docker compose -f docker-compose.prod.yml ps - -# Logs überwachen -docker compose -f docker-compose.prod.yml logs -f -``` - -## 🔧 Konfiguration - -### Service-Übersicht - -| Service | Interner Port | Externer Zugang | Beschreibung | -|---------|---------------|-----------------|--------------| -| nginx | 80, 443 | ✅ | Reverse Proxy, SSL-Terminierung | -| postgres | 5432 | ❌ | Datenbank (nur intern) | -| redis | 6379 | ❌ | Cache & Event Store (nur intern) | -| keycloak | 8443 | ❌ | Authentifizierung (über nginx) | -| kafka | 9092, 9093 | ❌ | Messaging (nur intern) | -| zookeeper | 2181 | ❌ | Kafka Koordination (nur intern) | -| prometheus | 9090 | ❌ | Metriken (über nginx) | -| grafana | 3000 | ❌ | Monitoring Dashboard (über nginx) | -| zipkin | 9411 | ❌ | Distributed Tracing (nur intern) | - -### Nginx Reverse Proxy Konfiguration - -Erstellen Sie Service-spezifische Konfigurationen in `config/nginx/conf.d/`: - -#### Keycloak (auth.ihredomain.com) -```nginx -server { - listen 443 ssl http2; - server_name auth.ihredomain.com; - - ssl_certificate /etc/ssl/nginx/server.crt; - ssl_private_key /etc/ssl/nginx/server.key; - - location / { - proxy_pass https://keycloak:8443; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } -} -``` - -#### Grafana (monitoring.ihredomain.com) -```nginx -server { - listen 443 ssl http2; - server_name monitoring.ihredomain.com; - - ssl_certificate /etc/ssl/nginx/server.crt; - ssl_private_key /etc/ssl/nginx/server.key; - - location / { - proxy_pass https://grafana:3000; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } -} -``` - -## 🔍 Monitoring und Logging - -### Prometheus Metriken - -Zugang über: `https://metrics.ihredomain.com` - -Überwachte Services: -- Anwendungsmetriken -- PostgreSQL Metriken -- Redis Metriken -- Kafka Metriken -- System-Metriken (Node Exporter) -- Container-Metriken (cAdvisor) - -### Grafana Dashboards - -Zugang über: `https://monitoring.ihredomain.com` - -Standard-Dashboards für: -- Anwendungs-Performance -- Datenbank-Performance -- Redis-Performance -- Kafka-Metriken -- System-Übersicht - -### Log-Management - -```bash -# Service-Logs anzeigen -docker compose -f docker-compose.prod.yml logs [service-name] - -# Logs in Echtzeit verfolgen -docker compose -f docker-compose.prod.yml logs -f [service-name] - -# Log-Rotation konfigurieren -# Fügen Sie zu /etc/docker/daemon.json hinzu: -{ - "log-driver": "json-file", - "log-opts": { - "max-size": "10m", - "max-file": "3" - } -} -``` - -## 🛡️ Sicherheits-Checkliste - -### Vor der Produktionsfreigabe - -- [ ] Alle Standard-Passwörter geändert -- [ ] SSL-Zertifikate von vertrauenswürdiger CA installiert -- [ ] Firewall konfiguriert (nur Ports 80, 443 öffentlich) -- [ ] Backup-Strategie implementiert -- [ ] Monitoring und Alerting konfiguriert -- [ ] Log-Rotation eingerichtet -- [ ] Security-Updates installiert -- [ ] Penetration-Test durchgeführt - -### Regelmäßige Sicherheitsaufgaben - -- [ ] Passwörter alle 90 Tage rotieren -- [ ] SSL-Zertifikate vor Ablauf erneuern -- [ ] Security-Updates monatlich installieren -- [ ] Backup-Wiederherstellung testen -- [ ] Access-Logs regelmäßig überprüfen -- [ ] Vulnerability-Scans durchführen - -## 💾 Backup und Wiederherstellung - -### Automatische Backups - -```bash -# Datenbank-Backup Script erstellen -cat > backup-db.sh << 'EOF' -#!/bin/bash -DATE=$(date +%Y%m%d_%H%M%S) -docker compose -f docker-compose.prod.yml exec -T postgres \ - pg_dump -U meldestelle_prod meldestelle_prod | \ - gzip > backups/db_backup_$DATE.sql.gz -find backups/ -name "db_backup_*.sql.gz" -mtime +30 -delete -EOF - -chmod +x backup-db.sh - -# Cron-Job für tägliche Backups -echo "0 2 * * * /path/to/backup-db.sh" | crontab - -``` - -### Redis Backup - -```bash -# Redis-Daten sichern -docker compose -f docker-compose.prod.yml exec redis \ - redis-cli --rdb /data/backup.rdb - -# Backup kopieren -docker cp $(docker compose -f docker-compose.prod.yml ps -q redis):/data/backup.rdb \ - backups/redis_backup_$(date +%Y%m%d_%H%M%S).rdb -``` - -### Wiederherstellung - -```bash -# Datenbank wiederherstellen -gunzip -c backups/db_backup_YYYYMMDD_HHMMSS.sql.gz | \ -docker compose -f docker-compose.prod.yml exec -T postgres \ - psql -U meldestelle_prod -d meldestelle_prod - -# Redis wiederherstellen -docker compose -f docker-compose.prod.yml stop redis -docker cp backups/redis_backup_YYYYMMDD_HHMMSS.rdb \ - $(docker compose -f docker-compose.prod.yml ps -q redis):/data/dump.rdb -docker compose -f docker-compose.prod.yml start redis -``` - -## 🔄 Updates und Wartung - -### Rolling Updates - -```bash -# Service einzeln aktualisieren -docker compose -f docker-compose.prod.yml pull [service-name] -docker compose -f docker-compose.prod.yml up -d --no-deps [service-name] - -# Alle Services aktualisieren -docker compose -f docker-compose.prod.yml pull -docker compose -f docker-compose.prod.yml up -d -``` - -### Wartungsmodus - -```bash -# Wartungsseite aktivieren -docker compose -f docker-compose.prod.yml stop nginx -# Wartungs-Nginx Container starten (mit Wartungsseite) - -# Nach Wartung: Normalen Betrieb wiederherstellen -docker compose -f docker-compose.prod.yml start nginx -``` - -## 🚨 Troubleshooting - -### Häufige Probleme - -#### 1. SSL-Zertifikat Fehler -```bash -# Zertifikat überprüfen -openssl x509 -in config/ssl/nginx/server.crt -text -noout - -# Zertifikat-Gültigkeit prüfen -openssl x509 -in config/ssl/nginx/server.crt -noout -dates -``` - -#### 2. Service startet nicht -```bash -# Logs überprüfen -docker-compose -f docker-compose.prod.yml logs [service-name] - -# Container-Status prüfen -docker-compose -f docker-compose.prod.yml ps - -# Health-Check Status -docker inspect $(docker-compose -f docker-compose.prod.yml ps -q [service-name]) -``` - -#### 3. Datenbankverbindung fehlgeschlagen -```bash -# Datenbank-Logs prüfen -docker-compose -f docker-compose.prod.yml logs postgres - -# Verbindung testen -docker-compose -f docker-compose.prod.yml exec postgres \ - psql -U meldestelle_prod -d meldestelle_prod -c "SELECT 1;" -``` - -#### 4. Redis-Verbindung fehlgeschlagen -```bash -# Redis-Logs prüfen -docker-compose -f docker-compose.prod.yml logs redis - -# Redis-Verbindung testen -docker-compose -f docker-compose.prod.yml exec redis \ - redis-cli -a $REDIS_PASSWORD ping -``` - -#### 5. Container startet nicht (Out of Memory) -```bash -# Container-Ressourcenverbrauch prüfen -docker stats --no-stream - -# Speicher-Limits überprüfen -docker inspect $(docker-compose -f docker-compose.prod.yml ps -q [service-name]) | grep -i memory - -# System-Speicher prüfen -free -h -df -h - -# Container mit mehr Speicher neu starten -docker-compose -f docker-compose.prod.yml up -d --force-recreate [service-name] -``` - -#### 6. Netzwerk-Verbindungsprobleme -```bash -# Docker-Netzwerk prüfen -docker network ls -docker network inspect meldestelle-network - -# Service-zu-Service Verbindung testen -docker-compose -f docker-compose.prod.yml exec [service1] \ - ping [service2] - -# Port-Erreichbarkeit testen -docker-compose -f docker-compose.prod.yml exec [service] \ - nc -zv [target-service] [port] - -# DNS-Auflösung testen -docker-compose -f docker-compose.prod.yml exec [service] \ - nslookup [target-service] -``` - -#### 7. Volume-Mount Probleme -```bash -# Volume-Status prüfen -docker volume ls -docker volume inspect [volume-name] - -# Berechtigungen prüfen -docker-compose -f docker-compose.prod.yml exec [service] \ - ls -la /path/to/mounted/directory - -# Volume-Speicherplatz prüfen -docker system df -docker system df -v -``` - -#### 8. Docker-Compose Konfigurationsfehler -```bash -# Konfiguration validieren -docker-compose -f docker-compose.prod.yml config - -# Syntax-Fehler finden -docker-compose -f docker-compose.prod.yml config --quiet - -# Umgebungsvariablen-Substitution prüfen -docker-compose -f docker-compose.prod.yml config --resolve-image-digests -``` - -### Performance-Optimierung - -#### Ressourcen-Monitoring -```bash -# Container-Ressourcenverbrauch -docker stats - -# Detaillierte Container-Informationen -docker-compose -f docker-compose.prod.yml top -``` - -#### Datenbank-Optimierung -```bash -# PostgreSQL-Performance analysieren -docker-compose -f docker-compose.prod.yml exec postgres \ - psql -U meldestelle_prod -d meldestelle_prod \ - -c "SELECT * FROM pg_stat_activity;" -``` - -## 📞 Support und Kontakt - -### Notfall-Kontakte -- **System-Administrator**: [Kontaktinformationen] -- **Entwicklungsteam**: [Kontaktinformationen] -- **Security-Team**: [Kontaktinformationen] - -### Dokumentation -- [API-Dokumentation](docs/api/) -- [Architektur-Dokumentation](docs/architecture/) -- [Entwickler-Dokumentation](docs/development/) - -### Monitoring-Dashboards -- **Grafana**: https://monitoring.ihredomain.com -- **Prometheus**: https://metrics.ihredomain.com -- **Keycloak Admin**: https://auth.ihredomain.com/admin - ---- - -**⚠️ Wichtiger Hinweis**: Diese Produktionskonfiguration enthält sensible Sicherheitseinstellungen. Stellen Sie sicher, dass alle Passwörter und Geheimnisse sicher verwaltet und regelmäßig rotiert werden. diff --git a/Tagebuch/REFACTORING-GUIDE-DE.md b/Tagebuch/REFACTORING-GUIDE-DE.md deleted file mode 100644 index 72c544f2..00000000 --- a/Tagebuch/REFACTORING-GUIDE-DE.md +++ /dev/null @@ -1,440 +0,0 @@ -# Gradle Build Refactoring-Leitfaden - -## Überblick -Dieser Leitfaden dokumentiert die umfassende Gradle Build-Optimierung, die in den Phasen 1-5 abgeschlossen wurde, einschließlich praktischer Refactoring-Patterns für alle verbleibenden Module. - ---- - -## ✅ Abgeschlossene Änderungen - -### Phase 1: Bundles & Version Catalog -**Datei:** `gradle/libs.versions.toml` - -#### Fehlende Bibliotheken hinzugefügt: -- `slf4j-api` (Version 2.0.16) -- `kotlin-reflect` (verwendet Kotlin-Versionsreferenz) - -#### 5 neue Complete Bundles hinzugefügt: - -1. **`ktor-server-complete`** - Vollständiger Ktor-Server-Stack (14 Abhängigkeiten) - - Enthält: core, netty, content-negotiation, serialization, status-pages, cors, default-headers, auth, auth-jwt, call-logging, metrics-micrometer, openapi, swagger, rate-limit - -2. **`spring-boot-service-complete`** - Vollständiger Spring Boot Service-Stack (12 Abhängigkeiten) - - Enthält: web, validation, actuator, security, oauth2-client, oauth2-resource-server, oauth2-jose, data-jpa, data-redis, micrometer-prometheus, tracing-bridge-brave, zipkin-reporter-brave - -3. **`database-complete`** - Vollständiger Datenbank-Stack (8 Abhängigkeiten) - - Enthält: exposed-core, exposed-dao, exposed-jdbc, exposed-kotlin-datetime, postgresql-driver, hikari-cp, flyway-core, flyway-postgresql - -4. **`testing-kmp`** - KMP-Test-Stack (8 Abhängigkeiten) - - Enthält: kotlin-test, junit-jupiter-api, junit-jupiter-engine, junit-jupiter-params, junit-platform-launcher, mockk, assertj-core, kotlinx-coroutines-test - -5. **`monitoring-complete`** - Vollständiger Monitoring-Stack (8 Abhängigkeiten) - - Enthält: actuator, micrometer-prometheus, tracing-bridge-brave, zipkin-reporter-brave, zipkin-sender-okhttp3, kotlin-logging-jvm, logback-classic, slf4j-api - -### Phase 2: Root Build-Datei -**Datei:** `build.gradle.kts` - -#### Verbesserungen: -- ✅ `allprojects`-Konfigurationsblock mit Gruppe, Version und gemeinsamen Repositories hinzugefügt -- ✅ Dependency-Analysis-Plugin hinzugefügt (Version 2.6.1) -- ✅ Versions-Plugin hinzugefügt (Version 0.51.0) -- ✅ Wrapper-Task auf Gradle 9.1.0 aktualisiert - -### Phase 3: Convention Plugins -**Verzeichnis:** `buildSrc/src/main/kotlin/` - -#### 3 Convention Plugins erstellt: - -1. **`ktor-server-conventions.gradle.kts`** - - Für Ktor-Server-Module - - Wendet an: kotlin-jvm, ktor, serialization Plugins - - Konfiguriert: Java 21 Toolchain, Compiler-Optionen, Test-Konfiguration - -2. **`spring-boot-service-conventions.gradle.kts`** - - Für Spring Boot Service-Module - - Wendet an: kotlin-jvm, spring-boot, dependency-management, kotlin-spring, kotlin-jpa Plugins - - Konfiguriert: Java 21 Toolchain, Compiler-Optionen, Test-Konfiguration, JPA All-Open - -3. **`kotlin-multiplatform-conventions.gradle.kts`** - - Für KMP-Module (clients, shared) - - Wendet an: kotlin-multiplatform, serialization Plugins - - Konfiguriert: Java 21 Toolchain, Compiler-Optionen für alle Targets - -### Phase 5: Gradle Properties -**Datei:** `gradle.properties` - -#### Kotlin-Compiler-Optimierungen hinzugefügt: -```properties -kotlin.incremental=true -kotlin.incremental.multiplatform=true -kotlin.incremental.js=true -kotlin.caching.enabled=true -kotlin.compiler.execution.strategy=in-process -kotlin.compiler.preciseCompilationResultsBackup=true -kotlin.stdlib.default.dependency=true -``` - ---- - -## 🔄 Refactoring-Patterns - -### Pattern 1: Spring Boot Services -**Gilt für:** Gateway, Auth-Server, Monitoring-Server, Ping-Service und alle Spring Boot-basierten Services - -#### Vorher: -```kotlin -plugins { - alias(libs.plugins.kotlinJvm) - alias(libs.plugins.kotlinSpring) - alias(libs.plugins.spring.boot) - alias(libs.plugins.spring.dependencyManagement) -} - -java { - toolchain { - languageVersion.set(JavaLanguageVersion.of(21)) - } -} - -tasks.withType { - compilerOptions { - freeCompilerArgs.addAll("-Xjsr305=strict") - jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21) - } -} - -springBoot { - mainClass.set("com.example.MainKt") - buildInfo() -} - -dependencies { - implementation(libs.spring.boot.starter.web) - implementation(libs.spring.boot.starter.validation) - implementation(libs.spring.boot.starter.actuator) - implementation(libs.spring.boot.starter.security) - implementation(libs.spring.boot.starter.oauth2.client) - implementation(libs.spring.boot.starter.oauth2.resource.server) - implementation(libs.resilience4j.spring.boot3) - implementation(libs.resilience4j.reactor) - implementation(libs.spring.boot.starter.aop) - implementation(libs.jackson.module.kotlin) - implementation(libs.jackson.datatype.jsr310) - implementation("ch.qos.logback:logback-classic") - implementation("ch.qos.logback:logback-core") - implementation("org.slf4j:slf4j-api") - // ... weitere Abhängigkeiten -} -``` - -#### Nachher: -```kotlin -plugins { - id("spring-boot-service-conventions") -} - -springBoot { - mainClass.set("com.example.MainKt") -} - -dependencies { - // Platform BOM - implementation(platform(projects.platform.platformBom)) - - // Projekt-Abhängigkeiten - implementation(projects.core.coreUtils) - implementation(projects.platform.platformDependencies) - - // Complete Bundles - implementation(libs.bundles.spring.boot.service.complete) - implementation(libs.bundles.resilience) - implementation(libs.bundles.jackson.kotlin) - implementation(libs.bundles.logging) - - // Spezifische Abhängigkeiten - implementation(libs.kotlin.reflect) - // ... andere spezifische Abhängigkeiten - - // Tests - testImplementation(projects.platform.platformTesting) - testImplementation(libs.bundles.testing.jvm) -} -``` - -**Vorteile:** -- ~30-40% Reduktion der Codezeilen -- Keine manuelle Toolchain-/Compiler-Konfiguration -- Zentralisiertes Dependency-Management durch Bundles -- Konsistente Konfiguration über alle Spring Boot Services - ---- - -### Pattern 2: Ktor Server Services -**Gilt für:** Alle Ktor-basierten Backend-Services (derzeit nicht im Projekt, aber Pattern verfügbar) - -#### Verwendung: -```kotlin -plugins { - id("ktor-server-conventions") -} - -ktor { - fatJar { - archiveFileName.set("service-name.jar") - } -} - -dependencies { - implementation(platform(projects.platform.platformBom)) - - // Verwende Complete Ktor Bundle - implementation(libs.bundles.ktor.server.complete) - - // Oder verwende spezifische Bundles für feinkörnige Kontrolle - implementation(libs.bundles.ktor.server.common) - implementation(libs.bundles.ktor.server.security) - implementation(libs.bundles.ktor.server.observability) - - // Datenbank - implementation(libs.bundles.database.complete) - - // Monitoring - implementation(libs.bundles.monitoring.complete) - - // Tests - testImplementation(libs.bundles.testing.kmp) - testImplementation(libs.ktor.server.tests) -} -``` - ---- - -### Pattern 3: Kotlin Multiplatform Module -**Gilt für:** clients/app, clients/ping-feature, clients/auth-feature, clients/shared, core/core-utils, core/core-domain - -#### Vorher: -```kotlin -plugins { - alias(libs.plugins.kotlinMultiplatform) - alias(libs.plugins.kotlinSerialization) - alias(libs.plugins.composeMultiplatform) - alias(libs.plugins.composeCompiler) -} - -kotlin { - jvmToolchain(21) - - jvm() - js(IR) { browser() } - - sourceSets { - commonMain.dependencies { - implementation(libs.kotlinx.coroutines.core) - implementation(libs.kotlinx.serialization.json) - implementation(libs.kotlinx.datetime) - implementation(libs.ktor.client.core) - implementation(libs.ktor.client.contentNegotiation) - implementation(libs.ktor.client.serialization.kotlinx.json) - implementation(libs.ktor.client.logging) - implementation(libs.ktor.client.auth) - implementation(libs.androidx.lifecycle.viewmodelCompose) - implementation(libs.androidx.lifecycle.runtimeCompose) - } - } -} - -tasks.withType { - compilerOptions { - jvmTarget.set(JvmTarget.JVM_21) - freeCompilerArgs.addAll("-opt-in=kotlin.RequiresOptIn") - } -} -``` - -#### Nachher: -```kotlin -plugins { - id("kotlin-multiplatform-conventions") - alias(libs.plugins.composeMultiplatform) - alias(libs.plugins.composeCompiler) -} - -kotlin { - jvm() - js(IR) { browser() } - - sourceSets { - commonMain.dependencies { - // Verwende Bundles - implementation(libs.bundles.kotlinx.core) - implementation(libs.bundles.ktor.client.common) - implementation(libs.bundles.compose.common) - - // Compose (vom Plugin) - implementation(compose.runtime) - implementation(compose.foundation) - implementation(compose.material3) - } - } -} -``` - -**Vorteile:** -- Entfernt Toolchain- und Compiler-Konfiguration-Boilerplate -- Bundles gruppieren verwandte Abhängigkeiten -- Sauberer und wartbarer - ---- - -## 📋 Modul-Refactoring-Checkliste - -### Infrastruktur-Module - -#### ✅ Gateway (Abgeschlossen - Beispiel) -- Pattern: Spring Boot Service -- Zeilen reduziert: 113 → 90 (20%) - -#### 🔲 Auth-Server -- Pattern: Spring Boot Service -- Ersetze Plugins durch `spring-boot-service-conventions` -- Verwende `spring-boot-service-complete`, `resilience`, `logging` Bundles - -#### 🔲 Messaging-Config -- Pattern: Spring Boot Service -- Verwende `spring-boot-service-complete`, `kafka-config` Bundles - -#### 🔲 Redis-Cache -- Pattern: Spring Boot Service -- Verwende `spring-boot-service-complete`, `redis-cache` Bundles - -#### 🔲 Redis-Event-Store -- Pattern: Spring Boot Service -- Verwende `spring-boot-service-complete`, `redis-cache` Bundles - -#### 🔲 Monitoring-Server -- Pattern: Spring Boot Service -- Verwende `spring-boot-service-complete`, `monitoring-complete` Bundles - -### Service-Module - -#### ✅ Ping-Service (Abgeschlossen - Beispiel) -- Pattern: Spring Boot Service -- Zeilen reduziert: 79 → 50 (37%) - -#### 🔲 Ping-API -- Pattern: Kotlin Multiplatform (falls KMP) oder Kotlin JVM -- Verwende `kotlinx-core` Bundle - -### Client-Module - -#### 🔲 clients/app -- Pattern: Kotlin Multiplatform -- Verwende `kotlin-multiplatform-conventions` -- Verwende `kotlinx-core`, `compose-common` Bundles - -#### 🔲 clients/ping-feature -- Pattern: Kotlin Multiplatform -- Verwendet bereits einige Bundles, stelle sicher, dass alle verwendet werden - -#### 🔲 clients/auth-feature -- Pattern: Kotlin Multiplatform -- Verwende `kotlin-multiplatform-conventions` -- Verwende `kotlinx-core`, `ktor-client-common`, `compose-common` Bundles - -#### 🔲 clients/shared Module -- Pattern: Kotlin Multiplatform -- Verwende `kotlin-multiplatform-conventions` -- Verwende `kotlinx-core` Bundle - -### Core & Platform Module - -#### 🔲 core/core-utils -- Pattern: Kotlin Multiplatform -- Verwende `kotlin-multiplatform-conventions` -- Verwende `kotlinx-core` Bundle - -#### 🔲 core/core-domain -- Pattern: Kotlin Multiplatform -- Verwende `kotlin-multiplatform-conventions` -- Verwende `kotlinx-core` Bundle - -#### 🔲 platform/platform-testing -- Pattern: Kotlin JVM -- Verwende `testing-kmp` oder `testing-jvm` Bundles - ---- - -## 🚀 Empfohlene Build-Befehle - -### Dependency-Analyse -```bash -./gradlew buildHealth -``` - -### Nach Dependency-Updates suchen -```bash -./gradlew dependencyUpdates -``` - -### Build mit Scan -```bash -./gradlew build --scan -``` - -### Dry Run für Task-Abhängigkeiten -```bash -./gradlew :services:ping:ping-service:build --dry-run -``` - -### Build-Performance messen -```bash -time ./gradlew clean build -``` - ---- - -## 📊 Erwartete Vorteile - -### Build-Performance -- **Inkrementelle Kompilierung**: ~20-40% schnellere Rebuilds -- **Configuration Cache**: ~30-50% schnellere Konfigurationsphase (wenn aktiviert) -- **Parallele Ausführung**: Bessere Auslastung von Multi-Core-Systemen - -### Wartbarkeit -- **Reduzierte Duplikation**: Convention Plugins eliminieren sich wiederholende Konfiguration -- **Zentralisierte Versionierung**: Single Source of Truth in `libs.versions.toml` -- **Einfachere Updates**: Dependency-Versionen an einem Ort aktualisieren - -### Code-Metriken -- **Durchschnittliche Reduktion**: 20-40% weniger Zeilen pro Build-Datei -- **Konsistenz**: Alle Module folgen denselben Patterns -- **Type-Safety**: Version Catalog bietet IDE-Support und Compile-Time-Checking - ---- - -## ⚠️ Wichtige Hinweise - -### Configuration Cache -Derzeit deaktiviert aufgrund von JS-Test-Serialisierungsproblemen. Kann wieder aktiviert werden, sobald gelöst: -```properties -org.gradle.configuration-cache=true -``` - -### WASM-Unterstützung -Optional, aktivierbar über: -```properties -enableWasm=true -``` - -### Inkrementelles Refactoring -- Ein Modul nach dem anderen refactoren -- Nach jeder Änderung testen -- Demonstrierte Beispiele als Templates verwenden - ---- - -## 📚 Referenzen - -- **Gradle Version Catalogs**: https://docs.gradle.org/current/userguide/platforms.html -- **Convention Plugins**: https://docs.gradle.org/current/samples/sample_convention_plugins.html -- **Kotlin DSL**: https://docs.gradle.org/current/userguide/kotlin_dsl.html diff --git a/Tagebuch/REFACTORING-GUIDE.md b/Tagebuch/REFACTORING-GUIDE.md deleted file mode 100644 index 6cc3a6ba..00000000 --- a/Tagebuch/REFACTORING-GUIDE.md +++ /dev/null @@ -1,440 +0,0 @@ -# Gradle Build Refactoring Guide - -## Overview -This guide documents the comprehensive Gradle build optimization completed in Phases 1-5, including practical refactoring patterns for all remaining modules. - ---- - -## ✅ Completed Changes - -### Phase 1: Bundles & Version Catalog -**File:** `gradle/libs.versions.toml` - -#### Added Missing Libraries: -- `slf4j-api` (version 2.0.16) -- `kotlin-reflect` (uses kotlin version reference) - -#### Added 5 New Complete Bundles: - -1. **`ktor-server-complete`** - Full Ktor server stack (14 dependencies) - - Includes: core, netty, content-negotiation, serialization, status-pages, cors, default-headers, auth, auth-jwt, call-logging, metrics-micrometer, openapi, swagger, rate-limit - -2. **`spring-boot-service-complete`** - Full Spring Boot service stack (12 dependencies) - - Includes: web, validation, actuator, security, oauth2-client, oauth2-resource-server, oauth2-jose, data-jpa, data-redis, micrometer-prometheus, tracing-bridge-brave, zipkin-reporter-brave - -3. **`database-complete`** - Complete database stack (8 dependencies) - - Includes: exposed-core, exposed-dao, exposed-jdbc, exposed-kotlin-datetime, postgresql-driver, hikari-cp, flyway-core, flyway-postgresql - -4. **`testing-kmp`** - KMP testing stack (8 dependencies) - - Includes: kotlin-test, junit-jupiter-api, junit-jupiter-engine, junit-jupiter-params, junit-platform-launcher, mockk, assertj-core, kotlinx-coroutines-test - -5. **`monitoring-complete`** - Complete monitoring stack (8 dependencies) - - Includes: actuator, micrometer-prometheus, tracing-bridge-brave, zipkin-reporter-brave, zipkin-sender-okhttp3, kotlin-logging-jvm, logback-classic, slf4j-api - -### Phase 2: Root Build File -**File:** `build.gradle.kts` - -#### Enhancements: -- ✅ Added `allprojects` configuration block with group, version, and common repositories -- ✅ Added dependency-analysis plugin (version 2.6.1) -- ✅ Added versions plugin (version 0.51.0) -- ✅ Updated wrapper task to Gradle 9.1.0 - -### Phase 3: Convention Plugins -**Directory:** `buildSrc/src/main/kotlin/` - -#### Created 3 Convention Plugins: - -1. **`ktor-server-conventions.gradle.kts`** - - For Ktor server modules - - Applies: kotlin-jvm, ktor, serialization plugins - - Configures: Java 21 toolchain, compiler options, test configuration - -2. **`spring-boot-service-conventions.gradle.kts`** - - For Spring Boot service modules - - Applies: kotlin-jvm, spring-boot, dependency-management, kotlin-spring, kotlin-jpa plugins - - Configures: Java 21 toolchain, compiler options, test configuration, JPA all-open - -3. **`kotlin-multiplatform-conventions.gradle.kts`** - - For KMP modules (clients, shared) - - Applies: kotlin-multiplatform, serialization plugins - - Configures: Java 21 toolchain, compiler options for all targets - -### Phase 5: Gradle Properties -**File:** `gradle.properties` - -#### Added Kotlin Compiler Optimizations: -```properties -kotlin.incremental=true -kotlin.incremental.multiplatform=true -kotlin.incremental.js=true -kotlin.caching.enabled=true -kotlin.compiler.execution.strategy=in-process -kotlin.compiler.preciseCompilationResultsBackup=true -kotlin.stdlib.default.dependency=true -``` - ---- - -## 🔄 Refactoring Patterns - -### Pattern 1: Spring Boot Services -**Applies to:** Gateway, Auth-Server, Monitoring-Server, Ping-Service, and all Spring Boot-based services - -#### Before: -```kotlin -plugins { - alias(libs.plugins.kotlinJvm) - alias(libs.plugins.kotlinSpring) - alias(libs.plugins.spring.boot) - alias(libs.plugins.spring.dependencyManagement) -} - -java { - toolchain { - languageVersion.set(JavaLanguageVersion.of(21)) - } -} - -tasks.withType { - compilerOptions { - freeCompilerArgs.addAll("-Xjsr305=strict") - jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21) - } -} - -springBoot { - mainClass.set("com.example.MainKt") - buildInfo() -} - -dependencies { - implementation(libs.spring.boot.starter.web) - implementation(libs.spring.boot.starter.validation) - implementation(libs.spring.boot.starter.actuator) - implementation(libs.spring.boot.starter.security) - implementation(libs.spring.boot.starter.oauth2.client) - implementation(libs.spring.boot.starter.oauth2.resource.server) - implementation(libs.resilience4j.spring.boot3) - implementation(libs.resilience4j.reactor) - implementation(libs.spring.boot.starter.aop) - implementation(libs.jackson.module.kotlin) - implementation(libs.jackson.datatype.jsr310) - implementation("ch.qos.logback:logback-classic") - implementation("ch.qos.logback:logback-core") - implementation("org.slf4j:slf4j-api") - // ... more dependencies -} -``` - -#### After: -```kotlin -plugins { - id("spring-boot-service-conventions") -} - -springBoot { - mainClass.set("com.example.MainKt") -} - -dependencies { - // Platform BOM - implementation(platform(projects.platform.platformBom)) - - // Project dependencies - implementation(projects.core.coreUtils) - implementation(projects.platform.platformDependencies) - - // Complete bundles - implementation(libs.bundles.spring.boot.service.complete) - implementation(libs.bundles.resilience) - implementation(libs.bundles.jackson.kotlin) - implementation(libs.bundles.logging) - - // Specific dependencies - implementation(libs.kotlin.reflect) - // ... other specific dependencies - - // Tests - testImplementation(projects.platform.platformTesting) - testImplementation(libs.bundles.testing.jvm) -} -``` - -**Benefits:** -- ~30-40% reduction in lines of code -- No manual toolchain/compiler configuration -- Centralized dependency management through bundles -- Consistent configuration across all Spring Boot services - ---- - -### Pattern 2: Ktor Server Services -**Applies to:** Any Ktor-based backend services (currently not in project, but pattern available) - -#### Usage: -```kotlin -plugins { - id("ktor-server-conventions") -} - -ktor { - fatJar { - archiveFileName.set("service-name.jar") - } -} - -dependencies { - implementation(platform(projects.platform.platformBom)) - - // Use complete Ktor bundle - implementation(libs.bundles.ktor.server.complete) - - // Or use specific bundles for fine-grained control - implementation(libs.bundles.ktor.server.common) - implementation(libs.bundles.ktor.server.security) - implementation(libs.bundles.ktor.server.observability) - - // Database - implementation(libs.bundles.database.complete) - - // Monitoring - implementation(libs.bundles.monitoring.complete) - - // Tests - testImplementation(libs.bundles.testing.kmp) - testImplementation(libs.ktor.server.tests) -} -``` - ---- - -### Pattern 3: Kotlin Multiplatform Modules -**Applies to:** clients/app, clients/ping-feature, clients/auth-feature, clients/shared, core/core-utils, core/core-domain - -#### Before: -```kotlin -plugins { - alias(libs.plugins.kotlinMultiplatform) - alias(libs.plugins.kotlinSerialization) - alias(libs.plugins.composeMultiplatform) - alias(libs.plugins.composeCompiler) -} - -kotlin { - jvmToolchain(21) - - jvm() - js(IR) { browser() } - - sourceSets { - commonMain.dependencies { - implementation(libs.kotlinx.coroutines.core) - implementation(libs.kotlinx.serialization.json) - implementation(libs.kotlinx.datetime) - implementation(libs.ktor.client.core) - implementation(libs.ktor.client.contentNegotiation) - implementation(libs.ktor.client.serialization.kotlinx.json) - implementation(libs.ktor.client.logging) - implementation(libs.ktor.client.auth) - implementation(libs.androidx.lifecycle.viewmodelCompose) - implementation(libs.androidx.lifecycle.runtimeCompose) - } - } -} - -tasks.withType { - compilerOptions { - jvmTarget.set(JvmTarget.JVM_21) - freeCompilerArgs.addAll("-opt-in=kotlin.RequiresOptIn") - } -} -``` - -#### After: -```kotlin -plugins { - id("kotlin-multiplatform-conventions") - alias(libs.plugins.composeMultiplatform) - alias(libs.plugins.composeCompiler) -} - -kotlin { - jvm() - js(IR) { browser() } - - sourceSets { - commonMain.dependencies { - // Use bundles - implementation(libs.bundles.kotlinx.core) - implementation(libs.bundles.ktor.client.common) - implementation(libs.bundles.compose.common) - - // Compose (from plugin) - implementation(compose.runtime) - implementation(compose.foundation) - implementation(compose.material3) - } - } -} -``` - -**Benefits:** -- Removes toolchain and compiler configuration boilerplate -- Bundles group related dependencies -- Cleaner and more maintainable - ---- - -## 📋 Module Refactoring Checklist - -### Infrastructure Modules - -#### ✅ Gateway (Completed - Example) -- Pattern: Spring Boot Service -- Lines reduced: 113 → 90 (20%) - -#### 🔲 Auth-Server -- Pattern: Spring Boot Service -- Replace plugins with `spring-boot-service-conventions` -- Use `spring-boot-service-complete`, `resilience`, `logging` bundles - -#### 🔲 Messaging-Config -- Pattern: Spring Boot Service -- Use `spring-boot-service-complete`, `kafka-config` bundles - -#### 🔲 Redis-Cache -- Pattern: Spring Boot Service -- Use `spring-boot-service-complete`, `redis-cache` bundles - -#### 🔲 Redis-Event-Store -- Pattern: Spring Boot Service -- Use `spring-boot-service-complete`, `redis-cache` bundles - -#### 🔲 Monitoring-Server -- Pattern: Spring Boot Service -- Use `spring-boot-service-complete`, `monitoring-complete` bundles - -### Service Modules - -#### ✅ Ping-Service (Completed - Example) -- Pattern: Spring Boot Service -- Lines reduced: 79 → 50 (37%) - -#### 🔲 Ping-API -- Pattern: Kotlin Multiplatform (if KMP) or Kotlin JVM -- Use `kotlinx-core` bundle - -### Client Modules - -#### 🔲 clients/app -- Pattern: Kotlin Multiplatform -- Use `kotlin-multiplatform-conventions` -- Use `kotlinx-core`, `compose-common` bundles - -#### 🔲 clients/ping-feature -- Pattern: Kotlin Multiplatform -- Already uses some bundles, ensure all are used - -#### 🔲 clients/auth-feature -- Pattern: Kotlin Multiplatform -- Use `kotlin-multiplatform-conventions` -- Use `kotlinx-core`, `ktor-client-common`, `compose-common` bundles - -#### 🔲 clients/shared modules -- Pattern: Kotlin Multiplatform -- Use `kotlin-multiplatform-conventions` -- Use `kotlinx-core` bundle - -### Core & Platform Modules - -#### 🔲 core/core-utils -- Pattern: Kotlin Multiplatform -- Use `kotlin-multiplatform-conventions` -- Use `kotlinx-core` bundle - -#### 🔲 core/core-domain -- Pattern: Kotlin Multiplatform -- Use `kotlin-multiplatform-conventions` -- Use `kotlinx-core` bundle - -#### 🔲 platform/platform-testing -- Pattern: Kotlin JVM -- Use `testing-kmp` or `testing-jvm` bundles - ---- - -## 🚀 Recommended Build Commands - -### Dependency Analysis -```bash -./gradlew buildHealth -``` - -### Check for Dependency Updates -```bash -./gradlew dependencyUpdates -``` - -### Build with Scan -```bash -./gradlew build --scan -``` - -### Dry Run for Task Dependencies -```bash -./gradlew :services:ping:ping-service:build --dry-run -``` - -### Measure Build Performance -```bash -time ./gradlew clean build -``` - ---- - -## 📊 Expected Benefits - -### Build Performance -- **Incremental compilation**: ~20-40% faster rebuilds -- **Configuration cache**: ~30-50% faster configuration phase (when enabled) -- **Parallel execution**: Better utilization of multi-core systems - -### Maintainability -- **Reduced duplication**: Convention plugins eliminate repetitive configuration -- **Centralized versioning**: Single source of truth in `libs.versions.toml` -- **Easier updates**: Update dependency versions in one place - -### Code Metrics -- **Average reduction**: 20-40% fewer lines per build file -- **Consistency**: All modules follow same patterns -- **Type safety**: Version catalog provides IDE support and compile-time checking - ---- - -## ⚠️ Important Notes - -### Configuration Cache -Currently disabled due to JS test serialization issues. Can be re-enabled once resolved: -```properties -org.gradle.configuration-cache=true -``` - -### WASM Support -Optional, enable via: -```properties -enableWasm=true -``` - -### Incremental Refactoring -- Refactor one module at a time -- Test after each change -- Use demonstrated examples as templates - ---- - -## 📚 References - -- **Gradle Version Catalogs**: https://docs.gradle.org/current/userguide/platforms.html -- **Convention Plugins**: https://docs.gradle.org/current/samples/sample_convention_plugins.html -- **Kotlin DSL**: https://docs.gradle.org/current/userguide/kotlin_dsl.html diff --git a/Tagebuch/Trace-Bullet-Bericht.md b/Tagebuch/Trace-Bullet-Bericht.md deleted file mode 100644 index 8ca1f2ab..00000000 --- a/Tagebuch/Trace-Bullet-Bericht.md +++ /dev/null @@ -1,116 +0,0 @@ -# Trace-Bullet Abschlussbericht: End-to-End Service-Kommunikation - -### Status: ✅ 100% ABGESCHLOSSEN & VERIFIZIERT - ---- - -### 1. Zielsetzung und Ergebnis - -Dieses Dokument bestätigt den erfolgreichen Abschluss des **Trace-Bullets**, dessen Ziel die Verifizierung der -fundamentalen End-to-End-Kommunikation der Systemarchitektur war. - -**Ergebnis:** Der Kommunikationsfluss von der Client-Anwendung über das API-Gateway bis zu einem Backend-Microservice -ist vollständig funktionsfähig. Dies beweist, dass die Kernarchitektur robust, korrekt konfiguriert und bereit für die -Entwicklung weiterer Fach-Services ist. - ---- - -### 2. Verifizierter Architektur-Flow - -Der Test validiert das nahtlose Zusammenspiel aller kritischen Infrastruktur-Komponenten in der korrekten Reihenfolge: - -**Der verifizierte End-to-End-Flow:** -`Client(Desktop/Web)` -> `API Gateway (Port 8081)` -> `Consul` -> `Ping-Service (Port 8082)` -> -`Antwort zurück an Client` - ---- - -### 3. Implementierungs-Checkliste - -Alle für das Trace-Bullet erforderlichen Komponenten wurden erfolgreich implementiert und integriert: - -#### ✅ **Backend-Infrastruktur** - -- **Docker-Services:** Alle Basisdienste (PostgreSQL, Redis, Consul, etc.) sind containerisiert und betriebsbereit. -- **API-Gateway:** Der Gateway-Service ist als zentraler Eingangspunkt auf Port `8081` konfiguriert und leitet Anfragen - korrekt weiter. - -#### ✅ **Ping-Microservice** - -- **Service-Logik:** Der `ping-service` ist als eigenständiger Spring-Boot-Microservice implementiert. -- **Service-Registrierung:** Der Service registriert sich zuverlässig bei Consul und ist für das Gateway dynamisch - auffindbar. - -#### ✅ **Client-Anwendung** - -- **Multiplattform-UI:** Die Benutzeroberfläche ist mit Compose Multiplatform umgesetzt und läuft plattformunabhängig - auf Desktop (JVM) und im Web (WASM). -- **API-Kommunikation:** Der Ktor-Client ruft den korrekten Gateway-Endpunkt (`/api/ping`) auf und verarbeitet die - Antwort reaktiv in der UI. - ---- - -### 4. Bedeutung für das Projekt - -Der erfolgreiche Abschluss dieses Trace-Bullets ist mehr als nur ein technischer Test; er ist das **fundamentale -Fundament für das gesamte Projekt**: - -* **Risikominimierung:** Die Kernarchitektur ist verifiziert, was das Risiko bei der Entwicklung komplexer Features - erheblich reduziert. -* **Entwicklungs-Blaupause:** Der `ping-service` und die Client-Anbindung dienen als perfekte Vorlage (Blueprint) für - alle zukünftigen Microservices und deren Integration. -* **Beschleunigte Entwicklung:** Teams können nun auf einer bewährten Grundlage aufbauen, ohne die Kerninfrastruktur in - Frage stellen zu müssen. - ---- - -### 5. Anleitung zur Reproduktion - -Der erfolgreiche End-to-End-Test kann jederzeit wie folgt reproduziert werden: - -1. **Backend starten:** - ```bash - # Startet die gesamte Docker-Infrastruktur inkl. Gateway - docker-compose up -d - ``` - -2. **Ping-Service starten:** - ```bash - # Startet den Microservice in einem separaten Terminal - ./gradlew :temp:ping-service:bootRun - ``` - *(Optional: In der Consul UI auf `http://localhost:8500` prüfen, ob der `ping-service` als "healthy" registriert - ist.)* - -3. **Client starten:** - ```bash - # Option A: Desktop-App - ./gradlew :client:run - - # Option B: Web-App (erreichbar unter http://localhost:8080) - ./gradlew :client:wasmJsBrowserDevelopmentRun - ``` - -4. **Test ausführen:** - Ein Klick auf den **"Ping Backend"**-Button in der Anwendung bestätigt den erfolgreichen Kommunikationsfluss durch - die Anzeige der "✅ Ping erfolgreich!"-Meldung. - - ---- - -### 6. Tracing validiert - -Zur Validierung des Distributed Tracing wurden Micrometer Tracing (Brave) und Zipkin im `ping-service` und im `api-gateway` aktiviert. So lässt sich der vollständige Pfad einer Anfrage nachvollziehen. - -Schnellanleitung: -- Backend/Infra starten (docker-compose) und Services hochfahren (Gateway + Ping-Service). -- Einen Request auslösen: - - Browser: http://localhost:8081/api/ping/ping - - CLI: curl -s http://localhost:8081/api/ping/ping -- Zipkin UI öffnen: http://localhost:9411 - - Nach Service filtern: `api-gateway` oder `ping-service` - - Einen Trace öffnen und die zwei Spans (Gateway ↔ Ping) prüfen - -Optionaler Smoke-Test (CLI): -- scripts/smoke/zipkin_smoke.sh – erzeugt einen Request und prüft über die Zipkin-API, ob Traces vorhanden sind. -- scripts/smoke/prometheus_smoke.sh – prüft `/actuator/prometheus` am Gateway und am Ping-Service. diff --git a/docs/BILINGUAL_DOCUMENTATION_INDEX.md b/docs/BILINGUAL_DOCUMENTATION_INDEX.md deleted file mode 100644 index aa9dd912..00000000 --- a/docs/BILINGUAL_DOCUMENTATION_INDEX.md +++ /dev/null @@ -1,130 +0,0 @@ -# Bilingual Documentation Index / Zweisprachiger Dokumentations-Index - -## Overview / Übersicht - -This document provides a comprehensive index of all bilingual documentation available in the Meldestelle project. All technical documentation is provided in both English and German versions to ensure accessibility for all team members and stakeholders. - -Dieses Dokument bietet einen umfassenden Index aller zweisprachigen Dokumentation im Meldestelle-Projekt. Alle technische Dokumentation wird sowohl in englischer als auch in deutscher Version bereitgestellt, um die Zugänglichkeit für alle Teammitglieder und Stakeholder zu gewährleisten. - -## Summary Documents / Zusammenfassungs-Dokumente - -### Database Implementation / Datenbank-Implementierung - -| English | German | Description | -|---------|--------|-------------| -| [DATABASE_FIXES_SUMMARY.md](./database/DATABASE_FIXES_SUMMARY.md) | [DATABASE_FIXES_SUMMARY-de.md](./database/DATABASE_FIXES_SUMMARY-de.md) | Database initialization fixes implementation summary | -| [DATABASE_DIAGNOSTIC_REPORT-en.md](./database/DATABASE_DIAGNOSTIC_REPORT-en.md) | [DATABASE_DIAGNOSTIC_REPORT.md](./database/DATABASE_DIAGNOSTIC_REPORT.md) | Comprehensive database diagnostic analysis | -| [STARTUP_ORDER_ANALYSIS.md](./database/STARTUP_ORDER_ANALYSIS.md) | [STARTUP_ORDER_ANALYSIS-de.md](./database/STARTUP_ORDER_ANALYSIS-de.md) | Startup order coordination analysis | - -### Service Implementation / Service-Implementierung - -| English | German | Description | -|---------|--------|-------------| -| [IMPLEMENTATION_SUMMARY.md](./implementation/IMPLEMENTATION_SUMMARY.md) | [IMPLEMENTATION_SUMMARY-de.md](./implementation/IMPLEMENTATION_SUMMARY-de.md) | Overall service implementation summary | -| [HORSES_MODULE_OPTIMIZATION_SUMMARY.md](./modules/HORSES_MODULE_OPTIMIZATION_SUMMARY.md) | [HORSES_MODULE_OPTIMIZATION_SUMMARY-de.md](./modules/HORSES_MODULE_OPTIMIZATION_SUMMARY-de.md) | Horses module analysis and optimization | -| [MEMBERS_MODULE_OPTIMIZATION_SUMMARY.md](./modules/MEMBERS_MODULE_OPTIMIZATION_SUMMARY.md) | [MEMBERS_MODULE_OPTIMIZATION_SUMMARY-de.md](./modules/MEMBERS_MODULE_OPTIMIZATION_SUMMARY-de.md) | Members module analysis and optimization | - -### Client Implementation / Client-Implementierung - -| English | German | Description | -|---------|--------|-------------| -| [CLIENT_OPTIMIZATION_SUMMARY-en.md](./client/CLIENT_OPTIMIZATION_SUMMARY-en.md) | [CLIENT_OPTIMIZATION_SUMMARY.md](./client/CLIENT_OPTIMIZATION_SUMMARY.md) | Client implementation optimization summary | - -## Architecture Documentation / Architektur-Dokumentation - -### Architecture Decision Records (ADRs) - -| English | German | Description | -|---------|--------|-------------| -| [docs/architecture/adr/0004-event-driven-communication.md](./docs/architecture/adr/0004-event-driven-communication.md) | [docs/architecture/adr/0004-event-driven-communication-de.md](./docs/architecture/adr/0004-event-driven-communication-de.md) | Event-driven communication pattern | -| [docs/architecture/adr/0005-polyglot-persistence.md](./docs/architecture/adr/0005-polyglot-persistence.md) | [docs/architecture/adr/0005-polyglot-persistence-de.md](./docs/architecture/adr/0005-polyglot-persistence-de.md) | Polyglot persistence strategy | -| [docs/architecture/adr/0006-authentication-authorization-keycloak.md](./docs/architecture/adr/0006-authentication-authorization-keycloak.md) | [docs/architecture/adr/0006-authentication-authorization-keycloak-de.md](./docs/architecture/adr/0006-authentication-authorization-keycloak-de.md) | Authentication and authorization with Keycloak | -| [docs/architecture/adr/0007-api-gateway-pattern.md](./docs/architecture/adr/0007-api-gateway-pattern.md) | [docs/architecture/adr/0007-api-gateway-pattern-de.md](./docs/architecture/adr/0007-api-gateway-pattern-de.md) | API Gateway pattern implementation | -| [docs/architecture/adr/0008-multiplatform-client-applications.md](./docs/architecture/adr/0008-multiplatform-client-applications.md) | [docs/architecture/adr/0008-multiplatform-client-applications-de.md](./docs/architecture/adr/0008-multiplatform-client-applications-de.md) | Multiplatform client applications | - -### C4 Architecture Diagrams - -| English | German | Description | -|---------|--------|-------------| -| [docs/architecture/c4/03-component-events-service.puml](./docs/architecture/c4/03-component-events-service.puml) | [docs/architecture/c4/03-component-events-service-de.puml](./docs/architecture/c4/03-component-events-service-de.puml) | Events service component diagram | - -## Development Documentation / Entwicklungs-Dokumentation - -| English | German | Description | -|---------|--------|-------------| -| [docs/development/getting-started.md](./docs/development/getting-started.md) | [docs/development/getting-started-de.md](./docs/development/getting-started-de.md) | Getting started guide for developers | -| [docs/development/environment-variables.md](./docs/development/environment-variables.md) | [docs/development/environment-variables-de.md](./docs/development/environment-variables-de.md) | Environment variables documentation | - -## Migration Documentation / Migrations-Dokumentation - -| English | German | Description | -|---------|--------|-------------| -| [docs/migration-summary.md](./docs/migration-summary.md) | [docs/migration-summary-de.md](./docs/migration-summary-de.md) | Migration summary and recommendations | -| [docs/migration-status.md](./docs/migration-status.md) | [docs/migration-status-de.md](./docs/migration-status-de.md) | Current migration status | -| [docs/migration-plan.md](./docs/migration-plan.md) | [docs/migration-plan-de.md](./docs/migration-plan-de.md) | Detailed migration plan | - -## Implementation Reports / Implementierungs-Berichte - -| English | German | Description | -|---------|--------|-------------| -| [docs/final-report.md](./docs/final-report.md) | [docs/final-report-de.md](./docs/final-report-de.md) | Final implementation report | -| [docs/client-data-fetching-implementation-summary.md](./docs/client-data-fetching-implementation-summary.md) | [docs/client-data-fetching-implementation-summary-de.md](./docs/client-data-fetching-implementation-summary-de.md) | Client data fetching implementation | - -## Configuration Documentation / Konfigurations-Dokumentation - -| English | German | Description | -|---------|--------|-------------| -| [config/ssl/README.md](./config/ssl/README.md) | [config/ssl/README-de.md](./config/ssl/README-de.md) | SSL configuration guide | - -## Documentation Standards / Dokumentations-Standards - -### Naming Convention / Namenskonvention - -- **English documents**: Use standard filename (e.g., `document-name.md`) -- **German documents**: Add `-de` suffix (e.g., `document-name-de.md`) -- **Englische Dokumente**: Verwenden Sie den Standard-Dateinamen (z.B. `document-name.md`) -- **Deutsche Dokumente**: Fügen Sie das Suffix `-de` hinzu (z.B. `document-name-de.md`) - -### Content Standards / Inhalts-Standards - -- All technical documentation must be available in both languages -- Translations should maintain technical accuracy and consistency -- Code examples and technical terms should remain consistent across languages -- Update dates should be synchronized between language versions - -- Alle technische Dokumentation muss in beiden Sprachen verfügbar sein -- Übersetzungen sollten technische Genauigkeit und Konsistenz beibehalten -- Code-Beispiele und technische Begriffe sollten sprachübergreifend konsistent bleiben -- Aktualisierungsdaten sollten zwischen den Sprachversionen synchronisiert werden - -## Validation / Validierung - -The project includes automated validation scripts to ensure documentation completeness: - -Das Projekt enthält automatisierte Validierungsskripte zur Sicherstellung der Dokumentationsvollständigkeit: - -- `scripts/validation/validate-docs.sh` - Validates bilingual documentation coverage -- `scripts/validation/validate-docs.sh` - Validiert die zweisprachige Dokumentationsabdeckung - -## Contributing / Mitwirken - -When creating or updating documentation: - -Beim Erstellen oder Aktualisieren von Dokumentation: - -1. **Always provide both language versions** / **Stellen Sie immer beide Sprachversionen bereit** -2. **Maintain consistent formatting** / **Behalten Sie konsistente Formatierung bei** -3. **Update this index when adding new documents** / **Aktualisieren Sie diesen Index beim Hinzufügen neuer Dokumente** -4. **Run validation scripts before committing** / **Führen Sie Validierungsskripte vor dem Commit aus** - -## Last Updated / Letzte Aktualisierung - -- **Date / Datum**: July 25, 2025 / 25. Juli 2025 -- **Version / Version**: 1.0.0 -- **Total Documents / Gesamtdokumente**: 14 bilingual pairs / 14 zweisprachige Paare - ---- - -*This index is automatically maintained and should be updated whenever new bilingual documentation is added to the project.* - -*Dieser Index wird automatisch gepflegt und sollte aktualisiert werden, wenn neue zweisprachige Dokumentation zum Projekt hinzugefügt wird.* diff --git a/docs/INDEX.md b/docs/INDEX.md deleted file mode 100644 index 2875cbca..00000000 --- a/docs/INDEX.md +++ /dev/null @@ -1,229 +0,0 @@ -# Meldestelle Documentation Index - -## 📚 Vollständige Dokumentationsübersicht - -Willkommen zur umfassenden Dokumentation des Meldestelle-Systems. Diese Übersicht bietet strukturierten Zugang zu allen verfügbaren Dokumenten und Ressourcen. - ---- - -## 🏗️ Architektur und Design - -### Hauptdokumentation -- **[Projekt-Übersicht](../README.md)** - Systemüberblick und Schnellstart -- **[Produktionsumgebung](../README-PRODUCTION.md)** - Produktions-Setup und Sicherheit -- **[Umgebungsvariablen](../README-ENV.md)** - Konfiguration und Setup - -### Architektur-Dokumentation -- **[Architektur-Übersicht](architecture/)** - Systemarchitektur und Design-Entscheidungen -- **[C4-Diagramme](architecture/c4/)** - Visuelle Architektur-Darstellung - ---- - -## 🔧 Module-Dokumentation - -### Core-Module -- **[Core Module](../core/README.md)** - Shared Kernel und gemeinsame Komponenten - - Domain-Modelle und Enumerationen - - Utilities und Konfiguration - - Fehlerbehandlung und Validierung - - Service Discovery - -### Geschäfts-Module - -#### Members (Mitgliederverwaltung) -- **[Members Module](../members/README.md)** - Umfassende Mitgliederverwaltung - - 18+ Repository-Operationen - - Mitgliedschafts-Tracking - - Validierung und Geschäftsregeln - -#### Horses (Pferderegistrierung) -- **[Horses Module](../horses/README.md)** - Pferderegistrierung und -verwaltung - - 25+ Repository-Operationen - - OEPS/FEI-Integration - - Identifikationsnummern-Verwaltung - -#### Events (Veranstaltungsverwaltung) -- **[Events Module](../events/README.md)** - Veranstaltungsplanung und -verwaltung - - 10+ Repository-Operationen - - Terminverwaltung - - Sparten-Management - -#### Masterdata (Stammdatenverwaltung) -- **[Masterdata Module](../masterdata/README.md)** - Stammdaten für das gesamte System - - 37+ REST-Endpunkte - - Länder, Bundesländer, Altersklassen - - Turnierplätze und Austragungsorte - -### Infrastruktur-Module -- **[Infrastructure Module](../infrastructure/README.md)** - Technische Infrastruktur - - Authentication & Authorization - - Caching und Event Store - - API Gateway und Messaging - - Monitoring und Observability - -### Client-Module -- **[Client Module](../client/README.md)** - Benutzeroberflächen - - Web-Anwendung und Desktop-App - - Repository-Pattern und API-Client - - UI-Komponenten und Theme System - ---- - -## 🔌 API-Dokumentation - -### REST-API-Übersicht -- **[API-Übersicht](api/README.md)** - Vollständige REST-API-Dokumentation - - Technische Spezifikationen - - Authentifizierung und Autorisierung - - Rate Limiting und Fehlerbehandlung - -### Modul-spezifische APIs -- **[Members API](api/members-api.md)** - Mitgliederverwaltung API - - 12 REST-Endpunkte - - Datenmodelle und Validierung - - Praktische Workflows - -### Automatisch generierte API-Dokumentation -- **[Generated OpenAPI Specs](api/generated/)** - Automatisch generierte OpenAPI-Spezifikationen - - Members API OpenAPI - - Horses API OpenAPI - - Events API OpenAPI - - Masterdata API OpenAPI - ---- - -## 👨‍💻 Entwicklerdokumentation - -### Erste Schritte -- **[Entwicklungsanleitung](development/getting-started-de.md)** - Vollständige Einrichtungsanleitung - - Systemanforderungen und Software-Installation - - Projekt-Setup und IDE-Konfiguration - - Entwicklungsworkflows und Debugging - -### Umgebung und Konfiguration -- **[Umgebungsvariablen](development/environment-variables-de.md)** - Detaillierte Konfigurationsdokumentation - -### Implementierung -- **[Redis-Integration](implementation/redis-integration-de.md)** - Redis-Implementierungsdetails - ---- - -## 🔄 Migration und Deployment - -### Migration -- **[Migrations-Plan](migration-plan-de.md)** - Detaillierter Migrationsplan -- **[Migrations-Zusammenfassung](migration-summary-de.md)** - Übersicht abgeschlossener Aufgaben -- **[Migrations-Status](migration-status-de.md)** - Aktueller Migrationsstatus -- **[Verbleibende Aufgaben](migration-remaining-tasks-de.md)** - Noch zu erledigende Arbeiten -- **[Abschlussbericht](final-report-de.md)** - Projekt-Restrukturierung Abschlussbericht - -### SSL und Sicherheit -- **[SSL-Konfiguration](../config/ssl/README-de.md)** - Produktions-SSL-Setup - ---- - -## 🎨 Client-Entwicklung - -### Architektur und Patterns -- **[Client-Implementierung](client-data-fetching-implementation-summary-de.md)** - Datenabruf und Zustandsverwaltung -- **[Client-Verbesserungen](client-data-fetching-improvements-de.md)** - Zukünftige Erweiterungen - ---- - -## 📊 Dokumentations-Management - -### Qualitätssicherung -- **[Dokumentations-Updates](documentation-updates-summary.md)** - Vollständige Übersicht aller Dokumentationsaktualisierungen - - 18 neue Dokumentationsdateien - - 6.012 Zeilen hochwertige Dokumentation - - 100% Modulabdeckung - -### Automatisierung -- **Automatische Validierung**: CI/CD-Pipeline für Dokumentationsqualität -- **OpenAPI-Generierung**: Automatische API-Dokumentationsgenerierung -- **Link-Validierung**: Automatische Überprüfung aller Dokumentationslinks - ---- - -## 🔍 Schnellzugriff - -### Nach Zielgruppe - -#### Neue Entwickler -1. [Entwicklungsanleitung](development/getting-started-de.md) -2. [Projekt-Übersicht](../README.md) -3. [Core Module](../core/README.md) -4. [API-Übersicht](api/README.md) - -#### API-Entwickler -1. [API-Übersicht](api/README.md) -2. [Members API](api/members-api.md) -3. [Generated OpenAPI Specs](api/generated/) -4. [Authentifizierung](../README-PRODUCTION.md#sicherheit) - -#### DevOps-Engineers -1. [Produktionsumgebung](../README-PRODUCTION.md) -2. [SSL-Konfiguration](../config/ssl/README-de.md) -3. [Umgebungsvariablen](../README-ENV.md) -4. [Infrastructure Module](../infrastructure/README.md) - -#### Architekten -1. [Architektur-Dokumentation](architecture/) -2. [C4-Diagramme](architecture/c4/) -3. [Migrations-Plan](migration-plan-de.md) -4. [Abschlussbericht](final-report-de.md) - -### Nach Technologie - -#### Backend (Kotlin/Spring Boot) -- [Core Module](../core/README.md) -- [Members Module](../members/README.md) -- [Infrastructure Module](../infrastructure/README.md) - -#### Frontend (Compose) -- [Client Module](../client/README.md) -- [Client-Implementierung](client-data-fetching-implementation-summary-de.md) - -#### Datenbank (PostgreSQL) -- [Migrations-Plan](migration-plan-de.md) -- [Entwicklungsanleitung](development/getting-started-de.md#datenbank-migrationen) - -#### Infrastruktur (Docker/Kubernetes) -- [Produktionsumgebung](../README-PRODUCTION.md) -- [Infrastructure Module](../infrastructure/README.md) - ---- - -## 📈 Dokumentationsstatistiken - -- **📄 Dokumentationsdateien**: 18 neue Dateien erstellt -- **📝 Gesamtzeilen**: 6.012 Zeilen hochwertiger Dokumentation -- **🎯 Modulabdeckung**: 100% (6/6 Module vollständig dokumentiert) -- **🔗 API-Abdeckung**: 100% (vollständige REST-API-Dokumentation) -- **🇩🇪 Deutsche Inhalte**: 95% aller Dokumentation auf Deutsch verfügbar -- **💡 Code-Beispiele**: 200+ praktische Code-Snippets - ---- - -## 🔄 Letzte Aktualisierungen - -**25. Juli 2025**: Umfassende Dokumentationsaktualisierung -- Alle Module vollständig dokumentiert -- Deutsche Übersetzungen erstellt -- API-Dokumentation vervollständigt -- Entwicklungsanleitungen hinzugefügt -- Automatisierung implementiert - ---- - -## 📞 Support und Beitrag - -- **Issue Tracker**: GitHub Issues für Dokumentationsfehler -- **Verbesserungsvorschläge**: Pull Requests willkommen -- **Automatische Validierung**: CI/CD-Pipeline prüft alle Änderungen - ---- - -**Letzte Aktualisierung**: 25. Juli 2025 -**Dokumentationsversion**: 1.0 -**Vollständigkeit**: 100% diff --git a/docs/api/README.md b/docs/api/README.md index cb3ac5ec..db431745 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -36,12 +36,12 @@ API Services ### Entwicklungsumgebung ``` -Base URL: http://localhost:8080/api +Base URL: http://localhost:8081/api ``` ### Produktionsumgebung ``` -Base URL: https://api.meldestelle.at/api +Base URL: https://api.meldestelle.yourdomain.com/api ``` ## API-Module Übersicht diff --git a/docs/client/CLIENT_OPTIMIZATION_SUMMARY-de.md b/docs/client/CLIENT_OPTIMIZATION_SUMMARY-de.md new file mode 100644 index 00000000..ef9705bc --- /dev/null +++ b/docs/client/CLIENT_OPTIMIZATION_SUMMARY-de.md @@ -0,0 +1,189 @@ +# Client Implementation Optimization Summary + +## Übersicht + +Dieses Dokument fasst die durchgeführten Optimierungen der Client-Implementierungen im Meldestelle-System zusammen. Die Optimierungen zielen darauf ab, Code-Duplikation zu reduzieren, die Architektur zu verbessern und die Build-Konfigurationen zu optimieren. + +## Durchgeführte Optimierungen + +### 1. Konfigurierbare API-Client-Einstellungen ✅ + +**Datei:** `client/common-ui/src/main/kotlin/at/mocode/client/common/config/ApiConfig.kt` + +**Verbesserungen:** +- Umgebungsvariablen-basierte Konfiguration für API-Einstellungen +- Konfigurierbare Base-URL, Timeouts, Cache-Einstellungen +- Unterstützung für System Properties und Umgebungsvariablen +- Logging-Konfiguration + +**Vorteile:** +- Flexibilität für verschiedene Umgebungen (Dev, Test, Prod) +- Keine hardcodierten Werte mehr +- Einfache Konfiguration ohne Code-Änderungen + +### 2. Verbesserte Cache-Implementierung ✅ + +**Datei:** `client/common-ui/src/main/kotlin/at/mocode/client/common/cache/ApiCache.kt` + +**Verbesserungen:** +- LRU (Least Recently Used) Eviction-Strategie +- Thread-sichere Implementierung mit ReentrantReadWriteLock +- Konfigurierbare Cache-Größe und TTL +- Pattern-basierte Cache-Invalidierung +- Cache-Statistiken und Cleanup-Funktionen + +**Vorteile:** +- Bessere Speicherverwaltung durch Größenbegrenzung +- Verbesserte Performance durch intelligente Eviction +- Konsistente Daten durch automatische Invalidierung +- Monitoring-Möglichkeiten durch Statistiken + +### 3. Base Repository Klasse ✅ + +**Datei:** `client/common-ui/src/main/kotlin/at/mocode/client/common/repository/BaseClientRepository.kt` + +**Verbesserungen:** +- Gemeinsame CRUD-Operationen für alle Repositories +- Einheitliche Fehlerbehandlung +- Konsistente Logging-Mechanismen +- Cache-Invalidierung nach Änderungsoperationen +- Wiederverwendbare Suchmethoden + +**Vorteile:** +- Eliminierung von Code-Duplikation zwischen Repositories +- Konsistente Fehlerbehandlung über alle Repositories +- Einfachere Wartung und Erweiterung +- Reduzierte Entwicklungszeit für neue Repositories + +### 4. Optimierte Repository-Implementierung ✅ + +**Datei:** `client/common-ui/src/main/kotlin/at/mocode/client/common/repository/OptimizedClientPersonRepository.kt` + +**Verbesserungen:** +- Nutzung der BaseClientRepository-Klasse +- Automatische Cache-Invalidierung nach Änderungen +- Verbesserte Fehlerbehandlung +- Konsistente Logging-Mechanismen + +**Vorteile:** +- Weniger Code-Duplikation +- Bessere Wartbarkeit +- Konsistente Funktionalität + +### 5. Optimierte Build-Konfigurationen ✅ + +#### Desktop App (`client/desktop-app/build.gradle.kts.optimized`) + +**Entfernte unnötige Dependencies:** +- Spring Boot (nicht für Desktop-Client benötigt) +- Redis-Dependencies (Redisson, Lettuce) +- Direkte Domain-Modul-Dependencies +- Unnötige Infrastructure-Dependencies + +**Hinzugefügte Verbesserungen:** +- Desktop-spezifische Coroutines (swing statt javafx) +- Native Distribution-Konfiguration +- Plattform-spezifische Icons und Packaging + +#### Web App (`client/web-app/build.gradle.kts.optimized`) + +**Entfernte unnötige Dependencies:** +- Direkte Domain-Modul-Dependencies +- Members-Application-Layer-Dependencies +- Unnötige Infrastructure-Dependencies + +**Hinzugefügte Verbesserungen:** +- Web-spezifische Compose-Dependencies +- Bessere Test-Dependencies (MockK, JUnit 5) +- Web-spezifische Coroutines + +## Architektur-Verbesserungen + +### Vor der Optimierung: +``` +Desktop App +├── Spring Boot ❌ +├── Redis Dependencies ❌ +├── Direct Domain Access ❌ +├── Heavy Infrastructure ❌ +└── Code Duplication ❌ + +Web App +├── Direct Domain Access ❌ +├── Application Layer Dependencies ❌ +├── Inconsistent Error Handling ❌ +└── Code Duplication ❌ +``` + +### Nach der Optimierung: +``` +Desktop App +├── Minimal Dependencies ✅ +├── API-Only Access ✅ +├── Shared Components ✅ +└── Clean Architecture ✅ + +Web App +├── API-Only Access ✅ +├── Shared Base Classes ✅ +├── Consistent Error Handling ✅ +└── Optimized Dependencies ✅ +``` + +## Quantifizierte Verbesserungen + +### Code-Reduktion: +- **Repository Code:** ~60% Reduktion durch BaseClientRepository +- **Build Dependencies:** ~40% Reduktion in Desktop App +- **Build Dependencies:** ~30% Reduktion in Web App + +### Performance-Verbesserungen: +- **Cache Efficiency:** LRU-Eviction statt einfacher TTL +- **Memory Usage:** Begrenzte Cache-Größe verhindert Memory Leaks +- **Build Time:** Weniger Dependencies = schnellere Builds + +### Wartbarkeit: +- **Einheitliche Fehlerbehandlung** über alle Repositories +- **Konfigurierbare Einstellungen** ohne Code-Änderungen +- **Konsistente Logging-Mechanismen** +- **Wiederverwendbare Komponenten** + +## Identifizierte weitere Optimierungsmöglichkeiten + +### Kurzfristig: +1. **Logging Framework:** Ersetzen von `println` durch SLF4J +2. **Retry Logic:** Implementierung von Retry-Mechanismen für API-Calls +3. **Connection Pooling:** Optimierung der HTTP-Client-Konfiguration +4. **Request/Response Interceptors:** Für Monitoring und Debugging + +### Mittelfristig: +1. **Reactive Streams:** Migration zu reaktiven Datenströmen +2. **Offline Support:** Implementierung von Offline-Funktionalität +3. **Progressive Web App:** Erweiterung der Web-App zu PWA +4. **State Management:** Implementierung von zentralem State Management + +### Langfristig: +1. **Microservices Gateway:** Implementierung eines API-Gateways +2. **GraphQL Integration:** Migration von REST zu GraphQL +3. **Real-time Updates:** WebSocket-Integration für Live-Updates +4. **Mobile Apps:** Erweiterung um native Mobile Apps + +## Empfohlene nächste Schritte + +1. **Tests aktualisieren:** Die bestehenden Tests sind zu stark an Domain-Layer gekoppelt und sollten refactored werden +2. **Logging Framework einführen:** SLF4J statt println verwenden +3. **Optimierte Build-Konfigurationen aktivieren:** Die `.optimized` Dateien als Standard übernehmen +4. **Monitoring implementieren:** Cache-Statistiken und API-Performance überwachen +5. **Dokumentation erweitern:** API-Dokumentation und Entwickler-Guidelines erstellen + +## Fazit + +Die durchgeführten Optimierungen verbessern die Client-Implementierungen erheblich: + +- **Reduzierte Komplexität** durch weniger Dependencies +- **Bessere Wartbarkeit** durch gemeinsame Base-Klassen +- **Verbesserte Performance** durch optimierte Caching-Strategien +- **Flexiblere Konfiguration** durch umgebungsbasierte Einstellungen +- **Sauberere Architektur** durch API-only Zugriff auf Backend-Services + +Diese Optimierungen legen eine solide Grundlage für die weitere Entwicklung und Skalierung des Meldestelle-Systems. diff --git a/docs/client/CLIENT_OPTIMIZATION_SUMMARY-en.md b/docs/client/CLIENT_OPTIMIZATION_SUMMARY-en.md deleted file mode 100644 index a5db0158..00000000 --- a/docs/client/CLIENT_OPTIMIZATION_SUMMARY-en.md +++ /dev/null @@ -1,193 +0,0 @@ -# Client Implementation Optimization Summary - -## Overview - -This document summarizes the optimizations performed on the client implementations in the Meldestelle system. The optimizations aim to reduce code duplication, improve architecture, and optimize build configurations. - -## Performed Optimizations - -### 1. Configurable API Client Settings ✅ - -**File:** `client/common-ui/src/main/kotlin/at/mocode/client/common/config/ApiConfig.kt` - -**Improvements:** -- Environment variable-based configuration for API settings -- Configurable base URL, timeouts, cache settings -- Support for system properties and environment variables -- Logging configuration - -**Benefits:** -- Flexibility for different environments (Dev, Test, Prod) -- No more hardcoded values -- Easy configuration without code changes - -### 2. Improved Cache Implementation ✅ - -**File:** `client/common-ui/src/main/kotlin/at/mocode/client/common/cache/ApiCache.kt` - -**Improvements:** -- LRU (Least Recently Used) eviction strategy -- Thread-safe implementation with ReentrantReadWriteLock -- Configurable cache size and TTL -- Pattern-based cache invalidation -- Cache statistics and cleanup functions - -**Benefits:** -- Better memory management through size limitation -- Improved performance through intelligent eviction -- Consistent data through automatic invalidation -- Monitoring capabilities through statistics - -### 3. Base Repository Class ✅ - -**File:** `client/common-ui/src/main/kotlin/at/mocode/client/common/repository/BaseClientRepository.kt` - -**Improvements:** -- Common CRUD operations for all repositories -- Unified error handling -- Consistent logging mechanisms -- Cache invalidation after modification operations -- Reusable search methods - -**Benefits:** -- Elimination of code duplication between repositories -- Consistent error handling across all repositories -- Easier maintenance and extension -- Reduced development time for new repositories - -### 4. Optimized Repository Implementation ✅ - -**File:** `client/common-ui/src/main/kotlin/at/mocode/client/common/repository/OptimizedClientPersonRepository.kt` - -**Improvements:** -- Usage of BaseClientRepository class -- Automatic cache invalidation after changes -- Improved error handling -- Consistent logging mechanisms - -**Benefits:** -- Less code duplication -- Better maintainability -- Consistent functionality - -### 5. Optimized Build Configurations ✅ - -#### Desktop App (`client/desktop-app/build.gradle.kts.optimized`) - -**Removed unnecessary dependencies:** -- Spring Boot (not needed for desktop client) -- Redis dependencies (Redisson, Lettuce) -- Direct domain module dependencies -- Unnecessary infrastructure dependencies - -**Added improvements:** -- Desktop-specific coroutines (swing instead of javafx) -- Native distribution configuration -- Platform-specific icons and packaging - -#### Web App (`client/web-app/build.gradle.kts.optimized`) - -**Removed unnecessary dependencies:** -- Direct domain module dependencies -- Members application layer dependencies -- Unnecessary infrastructure dependencies - -**Added improvements:** -- Web-specific Compose dependencies -- Better test dependencies (MockK, JUnit 5) -- Web-specific coroutines - -## Architecture Improvements - -### Before Optimization: -``` -Desktop App -├── Spring Boot ❌ -├── Redis Dependencies ❌ -├── Direct Domain Access ❌ -├── Heavy Infrastructure ❌ -└── Code Duplication ❌ - -Web App -├── Direct Domain Access ❌ -├── Application Layer Dependencies ❌ -├── Inconsistent Error Handling ❌ -└── Code Duplication ❌ -``` - -### After Optimization: -``` -Desktop App -├── Minimal Dependencies ✅ -├── API-Only Access ✅ -├── Shared Components ✅ -└── Clean Architecture ✅ - -Web App -├── API-Only Access ✅ -├── Shared Base Classes ✅ -├── Consistent Error Handling ✅ -└── Optimized Dependencies ✅ -``` - -## Quantified Improvements - -### Code Reduction: -- **Repository Code:** ~60% reduction through BaseClientRepository -- **Build Dependencies:** ~40% reduction in Desktop App -- **Build Dependencies:** ~30% reduction in Web App - -### Performance Improvements: -- **Cache Efficiency:** LRU eviction instead of simple TTL -- **Memory Usage:** Limited cache size prevents memory leaks -- **Build Time:** Fewer dependencies = faster builds - -### Maintainability: -- **Unified error handling** across all repositories -- **Configurable settings** without code changes -- **Consistent logging mechanisms** -- **Reusable components** - -## Identified Further Optimization Opportunities - -### Short-term: -1. **Logging Framework:** Replace `println` with SLF4J -2. **Retry Logic:** Implement retry mechanisms for API calls -3. **Connection Pooling:** Optimize HTTP client configuration -4. **Request/Response Interceptors:** For monitoring and debugging - -### Medium-term: -1. **Reactive Streams:** Migration to reactive data streams -2. **Offline Support:** Implementation of offline functionality -3. **Progressive Web App:** Extension of web app to PWA -4. **State Management:** Implementation of central state management - -### Long-term: -1. **Microservices Gateway:** Implementation of an API gateway -2. **GraphQL Integration:** Migration from REST to GraphQL -3. **Real-time Updates:** WebSocket integration for live updates -4. **Mobile Apps:** Extension with native mobile apps - -## Recommended Next Steps - -1. **Update tests:** Existing tests are too tightly coupled to domain layer and should be refactored -2. **Introduce logging framework:** Use SLF4J instead of println -3. **Activate optimized build configurations:** Adopt the `.optimized` files as standard -4. **Implement monitoring:** Monitor cache statistics and API performance -5. **Expand documentation:** Create API documentation and developer guidelines - -## Conclusion - -The performed optimizations significantly improve the client implementations: - -- **Reduced complexity** through fewer dependencies -- **Better maintainability** through shared base classes -- **Improved performance** through optimized caching strategies -- **More flexible configuration** through environment-based settings -- **Cleaner architecture** through API-only access to backend services - -These optimizations lay a solid foundation for further development and scaling of the Meldestelle system. - ---- - -*Last updated: July 25, 2025* diff --git a/docs/client/CLIENT_OPTIMIZATION_SUMMARY.md b/docs/client/CLIENT_OPTIMIZATION_SUMMARY.md index ef9705bc..a5db0158 100644 --- a/docs/client/CLIENT_OPTIMIZATION_SUMMARY.md +++ b/docs/client/CLIENT_OPTIMIZATION_SUMMARY.md @@ -1,105 +1,105 @@ # Client Implementation Optimization Summary -## Übersicht +## Overview -Dieses Dokument fasst die durchgeführten Optimierungen der Client-Implementierungen im Meldestelle-System zusammen. Die Optimierungen zielen darauf ab, Code-Duplikation zu reduzieren, die Architektur zu verbessern und die Build-Konfigurationen zu optimieren. +This document summarizes the optimizations performed on the client implementations in the Meldestelle system. The optimizations aim to reduce code duplication, improve architecture, and optimize build configurations. -## Durchgeführte Optimierungen +## Performed Optimizations -### 1. Konfigurierbare API-Client-Einstellungen ✅ +### 1. Configurable API Client Settings ✅ -**Datei:** `client/common-ui/src/main/kotlin/at/mocode/client/common/config/ApiConfig.kt` +**File:** `client/common-ui/src/main/kotlin/at/mocode/client/common/config/ApiConfig.kt` -**Verbesserungen:** -- Umgebungsvariablen-basierte Konfiguration für API-Einstellungen -- Konfigurierbare Base-URL, Timeouts, Cache-Einstellungen -- Unterstützung für System Properties und Umgebungsvariablen -- Logging-Konfiguration +**Improvements:** +- Environment variable-based configuration for API settings +- Configurable base URL, timeouts, cache settings +- Support for system properties and environment variables +- Logging configuration -**Vorteile:** -- Flexibilität für verschiedene Umgebungen (Dev, Test, Prod) -- Keine hardcodierten Werte mehr -- Einfache Konfiguration ohne Code-Änderungen +**Benefits:** +- Flexibility for different environments (Dev, Test, Prod) +- No more hardcoded values +- Easy configuration without code changes -### 2. Verbesserte Cache-Implementierung ✅ +### 2. Improved Cache Implementation ✅ -**Datei:** `client/common-ui/src/main/kotlin/at/mocode/client/common/cache/ApiCache.kt` +**File:** `client/common-ui/src/main/kotlin/at/mocode/client/common/cache/ApiCache.kt` -**Verbesserungen:** -- LRU (Least Recently Used) Eviction-Strategie -- Thread-sichere Implementierung mit ReentrantReadWriteLock -- Konfigurierbare Cache-Größe und TTL -- Pattern-basierte Cache-Invalidierung -- Cache-Statistiken und Cleanup-Funktionen +**Improvements:** +- LRU (Least Recently Used) eviction strategy +- Thread-safe implementation with ReentrantReadWriteLock +- Configurable cache size and TTL +- Pattern-based cache invalidation +- Cache statistics and cleanup functions -**Vorteile:** -- Bessere Speicherverwaltung durch Größenbegrenzung -- Verbesserte Performance durch intelligente Eviction -- Konsistente Daten durch automatische Invalidierung -- Monitoring-Möglichkeiten durch Statistiken +**Benefits:** +- Better memory management through size limitation +- Improved performance through intelligent eviction +- Consistent data through automatic invalidation +- Monitoring capabilities through statistics -### 3. Base Repository Klasse ✅ +### 3. Base Repository Class ✅ -**Datei:** `client/common-ui/src/main/kotlin/at/mocode/client/common/repository/BaseClientRepository.kt` +**File:** `client/common-ui/src/main/kotlin/at/mocode/client/common/repository/BaseClientRepository.kt` -**Verbesserungen:** -- Gemeinsame CRUD-Operationen für alle Repositories -- Einheitliche Fehlerbehandlung -- Konsistente Logging-Mechanismen -- Cache-Invalidierung nach Änderungsoperationen -- Wiederverwendbare Suchmethoden +**Improvements:** +- Common CRUD operations for all repositories +- Unified error handling +- Consistent logging mechanisms +- Cache invalidation after modification operations +- Reusable search methods -**Vorteile:** -- Eliminierung von Code-Duplikation zwischen Repositories -- Konsistente Fehlerbehandlung über alle Repositories -- Einfachere Wartung und Erweiterung -- Reduzierte Entwicklungszeit für neue Repositories +**Benefits:** +- Elimination of code duplication between repositories +- Consistent error handling across all repositories +- Easier maintenance and extension +- Reduced development time for new repositories -### 4. Optimierte Repository-Implementierung ✅ +### 4. Optimized Repository Implementation ✅ -**Datei:** `client/common-ui/src/main/kotlin/at/mocode/client/common/repository/OptimizedClientPersonRepository.kt` +**File:** `client/common-ui/src/main/kotlin/at/mocode/client/common/repository/OptimizedClientPersonRepository.kt` -**Verbesserungen:** -- Nutzung der BaseClientRepository-Klasse -- Automatische Cache-Invalidierung nach Änderungen -- Verbesserte Fehlerbehandlung -- Konsistente Logging-Mechanismen +**Improvements:** +- Usage of BaseClientRepository class +- Automatic cache invalidation after changes +- Improved error handling +- Consistent logging mechanisms -**Vorteile:** -- Weniger Code-Duplikation -- Bessere Wartbarkeit -- Konsistente Funktionalität +**Benefits:** +- Less code duplication +- Better maintainability +- Consistent functionality -### 5. Optimierte Build-Konfigurationen ✅ +### 5. Optimized Build Configurations ✅ #### Desktop App (`client/desktop-app/build.gradle.kts.optimized`) -**Entfernte unnötige Dependencies:** -- Spring Boot (nicht für Desktop-Client benötigt) -- Redis-Dependencies (Redisson, Lettuce) -- Direkte Domain-Modul-Dependencies -- Unnötige Infrastructure-Dependencies +**Removed unnecessary dependencies:** +- Spring Boot (not needed for desktop client) +- Redis dependencies (Redisson, Lettuce) +- Direct domain module dependencies +- Unnecessary infrastructure dependencies -**Hinzugefügte Verbesserungen:** -- Desktop-spezifische Coroutines (swing statt javafx) -- Native Distribution-Konfiguration -- Plattform-spezifische Icons und Packaging +**Added improvements:** +- Desktop-specific coroutines (swing instead of javafx) +- Native distribution configuration +- Platform-specific icons and packaging #### Web App (`client/web-app/build.gradle.kts.optimized`) -**Entfernte unnötige Dependencies:** -- Direkte Domain-Modul-Dependencies -- Members-Application-Layer-Dependencies -- Unnötige Infrastructure-Dependencies +**Removed unnecessary dependencies:** +- Direct domain module dependencies +- Members application layer dependencies +- Unnecessary infrastructure dependencies -**Hinzugefügte Verbesserungen:** -- Web-spezifische Compose-Dependencies -- Bessere Test-Dependencies (MockK, JUnit 5) -- Web-spezifische Coroutines +**Added improvements:** +- Web-specific Compose dependencies +- Better test dependencies (MockK, JUnit 5) +- Web-specific coroutines -## Architektur-Verbesserungen +## Architecture Improvements -### Vor der Optimierung: +### Before Optimization: ``` Desktop App ├── Spring Boot ❌ @@ -115,7 +115,7 @@ Web App └── Code Duplication ❌ ``` -### Nach der Optimierung: +### After Optimization: ``` Desktop App ├── Minimal Dependencies ✅ @@ -130,60 +130,64 @@ Web App └── Optimized Dependencies ✅ ``` -## Quantifizierte Verbesserungen +## Quantified Improvements -### Code-Reduktion: -- **Repository Code:** ~60% Reduktion durch BaseClientRepository -- **Build Dependencies:** ~40% Reduktion in Desktop App -- **Build Dependencies:** ~30% Reduktion in Web App +### Code Reduction: +- **Repository Code:** ~60% reduction through BaseClientRepository +- **Build Dependencies:** ~40% reduction in Desktop App +- **Build Dependencies:** ~30% reduction in Web App -### Performance-Verbesserungen: -- **Cache Efficiency:** LRU-Eviction statt einfacher TTL -- **Memory Usage:** Begrenzte Cache-Größe verhindert Memory Leaks -- **Build Time:** Weniger Dependencies = schnellere Builds +### Performance Improvements: +- **Cache Efficiency:** LRU eviction instead of simple TTL +- **Memory Usage:** Limited cache size prevents memory leaks +- **Build Time:** Fewer dependencies = faster builds -### Wartbarkeit: -- **Einheitliche Fehlerbehandlung** über alle Repositories -- **Konfigurierbare Einstellungen** ohne Code-Änderungen -- **Konsistente Logging-Mechanismen** -- **Wiederverwendbare Komponenten** +### Maintainability: +- **Unified error handling** across all repositories +- **Configurable settings** without code changes +- **Consistent logging mechanisms** +- **Reusable components** -## Identifizierte weitere Optimierungsmöglichkeiten +## Identified Further Optimization Opportunities -### Kurzfristig: -1. **Logging Framework:** Ersetzen von `println` durch SLF4J -2. **Retry Logic:** Implementierung von Retry-Mechanismen für API-Calls -3. **Connection Pooling:** Optimierung der HTTP-Client-Konfiguration -4. **Request/Response Interceptors:** Für Monitoring und Debugging +### Short-term: +1. **Logging Framework:** Replace `println` with SLF4J +2. **Retry Logic:** Implement retry mechanisms for API calls +3. **Connection Pooling:** Optimize HTTP client configuration +4. **Request/Response Interceptors:** For monitoring and debugging -### Mittelfristig: -1. **Reactive Streams:** Migration zu reaktiven Datenströmen -2. **Offline Support:** Implementierung von Offline-Funktionalität -3. **Progressive Web App:** Erweiterung der Web-App zu PWA -4. **State Management:** Implementierung von zentralem State Management +### Medium-term: +1. **Reactive Streams:** Migration to reactive data streams +2. **Offline Support:** Implementation of offline functionality +3. **Progressive Web App:** Extension of web app to PWA +4. **State Management:** Implementation of central state management -### Langfristig: -1. **Microservices Gateway:** Implementierung eines API-Gateways -2. **GraphQL Integration:** Migration von REST zu GraphQL -3. **Real-time Updates:** WebSocket-Integration für Live-Updates -4. **Mobile Apps:** Erweiterung um native Mobile Apps +### Long-term: +1. **Microservices Gateway:** Implementation of an API gateway +2. **GraphQL Integration:** Migration from REST to GraphQL +3. **Real-time Updates:** WebSocket integration for live updates +4. **Mobile Apps:** Extension with native mobile apps -## Empfohlene nächste Schritte +## Recommended Next Steps -1. **Tests aktualisieren:** Die bestehenden Tests sind zu stark an Domain-Layer gekoppelt und sollten refactored werden -2. **Logging Framework einführen:** SLF4J statt println verwenden -3. **Optimierte Build-Konfigurationen aktivieren:** Die `.optimized` Dateien als Standard übernehmen -4. **Monitoring implementieren:** Cache-Statistiken und API-Performance überwachen -5. **Dokumentation erweitern:** API-Dokumentation und Entwickler-Guidelines erstellen +1. **Update tests:** Existing tests are too tightly coupled to domain layer and should be refactored +2. **Introduce logging framework:** Use SLF4J instead of println +3. **Activate optimized build configurations:** Adopt the `.optimized` files as standard +4. **Implement monitoring:** Monitor cache statistics and API performance +5. **Expand documentation:** Create API documentation and developer guidelines -## Fazit +## Conclusion -Die durchgeführten Optimierungen verbessern die Client-Implementierungen erheblich: +The performed optimizations significantly improve the client implementations: -- **Reduzierte Komplexität** durch weniger Dependencies -- **Bessere Wartbarkeit** durch gemeinsame Base-Klassen -- **Verbesserte Performance** durch optimierte Caching-Strategien -- **Flexiblere Konfiguration** durch umgebungsbasierte Einstellungen -- **Sauberere Architektur** durch API-only Zugriff auf Backend-Services +- **Reduced complexity** through fewer dependencies +- **Better maintainability** through shared base classes +- **Improved performance** through optimized caching strategies +- **More flexible configuration** through environment-based settings +- **Cleaner architecture** through API-only access to backend services -Diese Optimierungen legen eine solide Grundlage für die weitere Entwicklung und Skalierung des Meldestelle-Systems. +These optimizations lay a solid foundation for further development and scaling of the Meldestelle system. + +--- + +*Last updated: July 25, 2025* diff --git a/docs/database/DATABASE_DIAGNOSTIC_REPORT-de.md b/docs/database/DATABASE_DIAGNOSTIC_REPORT-de.md new file mode 100644 index 00000000..35437d3b --- /dev/null +++ b/docs/database/DATABASE_DIAGNOSTIC_REPORT-de.md @@ -0,0 +1,148 @@ +# Database Diagnostic Report - Exposed Framework Initialization + +## Diagnose Ergebnisse + +### ✅ Database.connect() Aufrufe identifiziert + +**Zentrale Implementierung:** +- **DatabaseFactory.kt** (Zeile 66): `Database.connect(dataSource!!)` + - Verwendet HikariCP Connection Pooling + - Singleton-Pattern mit proper Konfiguration + - Unterstützt Verbindungsvalidierung und Leak-Detection + +**Service-spezifische Konfigurationen:** +- **Events Service**: EventsDatabaseConfiguration.kt - verwendet DatabaseFactory.init() +- **Horses Service**: DatabaseConfiguration.kt - verwendet DatabaseFactory.init() +- **Members Service**: MembersDatabaseConfiguration.kt - verwendet DatabaseFactory.init() +- **Masterdata Service**: MasterdataDatabaseConfiguration.kt - verwendet DatabaseFactory.init() + +**⚠️ PROBLEM IDENTIFIZIERT - Gateway Konfiguration:** +- **Gateway**: DatabaseConfig.kt (Zeile 25-30) - **direkter Database.connect() Aufruf** + ```kotlin + Database.connect( + url = databaseUrl, + driver = "org.postgresql.Driver", + user = databaseUser, + password = databasePassword + ) + ``` + +### ✅ Exposed-Operationen (Transaktionen, Queries) lokalisiert + +**Schema-Initialisierung (in @PostConstruct):** +- Alle Services: `transaction { SchemaUtils.createMissingTablesAndColumns(...) }` +- Gateway: `transaction { SchemaUtils.createMissingTablesAndColumns(...) }` für alle Kontexte + +**Business Logic Transaktionen:** +- **TransactionalCreateHorseUseCase**: Verwendet `DatabaseFactory.dbQuery { ... }` +- **DatabaseMigrator**: Verwendet `transaction { ... }` für Migrationen + +**Test-Transaktionen:** +- SimpleDatabaseTest.kt: Direkte `transaction { ... }` Aufrufe in Tests + +### ✅ Initialisierungsreihenfolge analysiert + +**Korrekte Reihenfolge in Services:** +1. `@PostConstruct` → `DatabaseFactory.init(config)` → `Database.connect()` +2. Sofort danach: `transaction { SchemaUtils.createMissingTablesAndColumns(...) }` +3. Business Logic: `DatabaseFactory.dbQuery { ... }` für Transaktionen + +**⚠️ PROBLEM - Gateway Initialisierung:** +1. Ktor Application.configureDatabase() → direkter `Database.connect()` +2. Sofort danach: `transaction { ... }` für alle Service-Schemas + +## 🚨 Identifizierte Probleme + +### 1. **Inkonsistente Database.connect() Implementierung** +- **Services**: Verwenden zentralen DatabaseFactory mit Connection Pooling +- **Gateway**: Direkter Database.connect() ohne Connection Pooling +- **Risiko**: Unterschiedliche Verbindungsqualität und -management + +### 2. **Potentielle Race Conditions** +- Gateway und Services initialisieren unabhängig voneinander +- Beide versuchen, Schemas für dieselben Tabellen zu erstellen +- **Risiko**: Konflikte bei paralleler Initialisierung + +### 3. **Verletzung der Separation of Concerns** +- Gateway verwaltet Schemas für alle Services +- Services verwalten ihre eigenen Schemas +- **Risiko**: Doppelte Schema-Initialisierung + +### 4. **Fehlende Initialisierungsreihenfolge-Garantien** +- Keine explizite Abhängigkeitsreihenfolge zwischen Gateway und Services +- **Risiko**: Exposed-Operationen vor Database.connect() + +## ✅ Empfehlungen + +### 1. **Gateway auf DatabaseFactory umstellen** +```kotlin +// Statt direktem Database.connect(): +fun Application.configureDatabase() { + val config = DatabaseConfig.fromEnv() // oder aus Ktor Config + DatabaseFactory.init(config) + // Schema-Initialisierung entfernen oder koordinieren +} +``` + +### 2. **Schema-Initialisierung koordinieren** +**Option A**: Nur Services verwalten ihre Schemas (empfohlen) +```kotlin +// Gateway: Nur Verbindung, keine Schema-Initialisierung +fun Application.configureDatabase() { + DatabaseFactory.init(DatabaseConfig.fromEnv()) +} +``` + +**Option B**: Zentralisierte Schema-Verwaltung +```kotlin +// Separater DatabaseSchemaInitializer mit @Order Annotation +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +class DatabaseSchemaInitializer { + @PostConstruct + fun initializeAllSchemas() { + // Schema initialization logic + } +} +``` + +### 3. **Startup-Reihenfolge sicherstellen** +```kotlin +// Services mit @DependsOn +@Configuration +@DependsOn("databaseInitializer") +class HorsesDatabaseConfiguration { + // Configuration logic +} +``` + +### 4. **Einheitliche Konfiguration** +```kotlin +// Alle Komponenten verwenden DatabaseFactory +class SomeService { + suspend fun doSomething() { + DatabaseFactory.dbQuery { + // Exposed operations + } + } +} +``` + +## 📋 Zusammenfassung + +**✅ Korrekt implementiert:** +- Alle Services verwenden proper @PostConstruct → Database.connect() → Exposed operations Reihenfolge +- DatabaseFactory bietet robuste Connection Pool Konfiguration +- Business Logic verwendet korrekte Transaktionsmuster + +**⚠️ Zu beheben:** +- Gateway Database.connect() Inkonsistenz +- Potentielle Race Conditions bei Schema-Initialisierung +- Fehlende Startup-Reihenfolge-Koordination + +**🎯 Priorität:** +1. **Hoch**: Gateway auf DatabaseFactory umstellen +2. **Mittel**: Schema-Initialisierung koordinieren +3. **Niedrig**: Startup-Reihenfolge explizit definieren + +Die Reihenfolge der Initialisierung ist grundsätzlich korrekt, aber die Inkonsistenz zwischen Gateway und Services sollte behoben werden, um potentielle Probleme zu vermeiden. diff --git a/docs/database/DATABASE_DIAGNOSTIC_REPORT-en.md b/docs/database/DATABASE_DIAGNOSTIC_REPORT-en.md deleted file mode 100644 index fd500887..00000000 --- a/docs/database/DATABASE_DIAGNOSTIC_REPORT-en.md +++ /dev/null @@ -1,152 +0,0 @@ -# Database Diagnostic Report - Exposed Framework Initialization - -## Diagnostic Results - -### ✅ Database.connect() Calls Identified - -**Central Implementation:** -- **DatabaseFactory.kt** (Line 66): `Database.connect(dataSource!!)` - - Uses HikariCP Connection Pooling - - Singleton pattern with proper configuration - - Supports connection validation and leak detection - -**Service-specific Configurations:** -- **Events Service**: EventsDatabaseConfiguration.kt - uses DatabaseFactory.init() -- **Horses Service**: DatabaseConfiguration.kt - uses DatabaseFactory.init() -- **Members Service**: MembersDatabaseConfiguration.kt - uses DatabaseFactory.init() -- **Masterdata Service**: MasterdataDatabaseConfiguration.kt - uses DatabaseFactory.init() - -**⚠️ PROBLEM IDENTIFIED - Gateway Configuration:** -- **Gateway**: DatabaseConfig.kt (Lines 25-30) - **direct Database.connect() call** - ```kotlin - Database.connect( - url = databaseUrl, - driver = "org.postgresql.Driver", - user = databaseUser, - password = databasePassword - ) - ``` - -### ✅ Exposed Operations (Transactions, Queries) Located - -**Schema Initialization (in @PostConstruct):** -- All Services: `transaction { SchemaUtils.createMissingTablesAndColumns(...) }` -- Gateway: `transaction { SchemaUtils.createMissingTablesAndColumns(...) }` for all contexts - -**Business Logic Transactions:** -- **TransactionalCreateHorseUseCase**: Uses `DatabaseFactory.dbQuery { ... }` -- **DatabaseMigrator**: Uses `transaction { ... }` for migrations - -**Test Transactions:** -- SimpleDatabaseTest.kt: Direct `transaction { ... }` calls in tests - -### ✅ Initialization Order Analyzed - -**Correct Order in Services:** -1. `@PostConstruct` → `DatabaseFactory.init(config)` → `Database.connect()` -2. Immediately after: `transaction { SchemaUtils.createMissingTablesAndColumns(...) }` -3. Business Logic: `DatabaseFactory.dbQuery { ... }` for transactions - -**⚠️ PROBLEM - Gateway Initialization:** -1. Ktor Application.configureDatabase() → direct `Database.connect()` -2. Immediately after: `transaction { ... }` for all service schemas - -## 🚨 Identified Problems - -### 1. **Inconsistent Database.connect() Implementation** -- **Services**: Use central DatabaseFactory with Connection Pooling -- **Gateway**: Direct Database.connect() without Connection Pooling -- **Risk**: Different connection quality and management - -### 2. **Potential Race Conditions** -- Gateway and services initialize independently -- Both attempt to create schemas for the same tables -- **Risk**: Conflicts during parallel initialization - -### 3. **Violation of Separation of Concerns** -- Gateway manages schemas for all services -- Services manage their own schemas -- **Risk**: Duplicate schema initialization - -### 4. **Missing Initialization Order Guarantees** -- No explicit dependency order between Gateway and Services -- **Risk**: Exposed operations before Database.connect() - -## ✅ Recommendations - -### 1. **Switch Gateway to DatabaseFactory** -```kotlin -// Instead of direct Database.connect(): -fun Application.configureDatabase() { - val config = DatabaseConfig.fromEnv() // or from Ktor Config - DatabaseFactory.init(config) - // Remove or coordinate schema initialization -} -``` - -### 2. **Coordinate Schema Initialization** -**Option A**: Only services manage their schemas (recommended) -```kotlin -// Gateway: Only connection, no schema initialization -fun Application.configureDatabase() { - DatabaseFactory.init(DatabaseConfig.fromEnv()) -} -``` - -**Option B**: Centralized schema management -```kotlin -// Separate DatabaseSchemaInitializer with @Order annotation -@Component -@Order(Ordered.HIGHEST_PRECEDENCE) -class DatabaseSchemaInitializer { - @PostConstruct - fun initializeAllSchemas() { - // Schema initialization logic - } -} -``` - -### 3. **Ensure Startup Order** -```kotlin -// Services with @DependsOn -@Configuration -@DependsOn("databaseInitializer") -class HorsesDatabaseConfiguration { - // Configuration logic -} -``` - -### 4. **Unified Configuration** -```kotlin -// All components use DatabaseFactory -class SomeService { - suspend fun doSomething() { - DatabaseFactory.dbQuery { - // Exposed operations - } - } -} -``` - -## 📋 Summary - -**✅ Correctly implemented:** -- All services use proper @PostConstruct → Database.connect() → Exposed operations sequence -- DatabaseFactory provides robust Connection Pool configuration -- Business logic uses correct transaction patterns - -**⚠️ To be fixed:** -- Gateway Database.connect() inconsistency -- Potential race conditions in schema initialization -- Missing startup order coordination - -**🎯 Priority:** -1. **High**: Switch Gateway to DatabaseFactory -2. **Medium**: Coordinate schema initialization -3. **Low**: Explicitly define startup order - -The initialization sequence is fundamentally correct, but the inconsistency between Gateway and Services should be resolved to avoid potential problems. - ---- - -*Last updated: July 25, 2025* diff --git a/docs/database/DATABASE_DIAGNOSTIC_REPORT.md b/docs/database/DATABASE_DIAGNOSTIC_REPORT.md index 35437d3b..fd500887 100644 --- a/docs/database/DATABASE_DIAGNOSTIC_REPORT.md +++ b/docs/database/DATABASE_DIAGNOSTIC_REPORT.md @@ -1,23 +1,23 @@ # Database Diagnostic Report - Exposed Framework Initialization -## Diagnose Ergebnisse +## Diagnostic Results -### ✅ Database.connect() Aufrufe identifiziert +### ✅ Database.connect() Calls Identified -**Zentrale Implementierung:** -- **DatabaseFactory.kt** (Zeile 66): `Database.connect(dataSource!!)` - - Verwendet HikariCP Connection Pooling - - Singleton-Pattern mit proper Konfiguration - - Unterstützt Verbindungsvalidierung und Leak-Detection +**Central Implementation:** +- **DatabaseFactory.kt** (Line 66): `Database.connect(dataSource!!)` + - Uses HikariCP Connection Pooling + - Singleton pattern with proper configuration + - Supports connection validation and leak detection -**Service-spezifische Konfigurationen:** -- **Events Service**: EventsDatabaseConfiguration.kt - verwendet DatabaseFactory.init() -- **Horses Service**: DatabaseConfiguration.kt - verwendet DatabaseFactory.init() -- **Members Service**: MembersDatabaseConfiguration.kt - verwendet DatabaseFactory.init() -- **Masterdata Service**: MasterdataDatabaseConfiguration.kt - verwendet DatabaseFactory.init() +**Service-specific Configurations:** +- **Events Service**: EventsDatabaseConfiguration.kt - uses DatabaseFactory.init() +- **Horses Service**: DatabaseConfiguration.kt - uses DatabaseFactory.init() +- **Members Service**: MembersDatabaseConfiguration.kt - uses DatabaseFactory.init() +- **Masterdata Service**: MasterdataDatabaseConfiguration.kt - uses DatabaseFactory.init() -**⚠️ PROBLEM IDENTIFIZIERT - Gateway Konfiguration:** -- **Gateway**: DatabaseConfig.kt (Zeile 25-30) - **direkter Database.connect() Aufruf** +**⚠️ PROBLEM IDENTIFIED - Gateway Configuration:** +- **Gateway**: DatabaseConfig.kt (Lines 25-30) - **direct Database.connect() call** ```kotlin Database.connect( url = databaseUrl, @@ -27,75 +27,75 @@ ) ``` -### ✅ Exposed-Operationen (Transaktionen, Queries) lokalisiert +### ✅ Exposed Operations (Transactions, Queries) Located -**Schema-Initialisierung (in @PostConstruct):** -- Alle Services: `transaction { SchemaUtils.createMissingTablesAndColumns(...) }` -- Gateway: `transaction { SchemaUtils.createMissingTablesAndColumns(...) }` für alle Kontexte +**Schema Initialization (in @PostConstruct):** +- All Services: `transaction { SchemaUtils.createMissingTablesAndColumns(...) }` +- Gateway: `transaction { SchemaUtils.createMissingTablesAndColumns(...) }` for all contexts -**Business Logic Transaktionen:** -- **TransactionalCreateHorseUseCase**: Verwendet `DatabaseFactory.dbQuery { ... }` -- **DatabaseMigrator**: Verwendet `transaction { ... }` für Migrationen +**Business Logic Transactions:** +- **TransactionalCreateHorseUseCase**: Uses `DatabaseFactory.dbQuery { ... }` +- **DatabaseMigrator**: Uses `transaction { ... }` for migrations -**Test-Transaktionen:** -- SimpleDatabaseTest.kt: Direkte `transaction { ... }` Aufrufe in Tests +**Test Transactions:** +- SimpleDatabaseTest.kt: Direct `transaction { ... }` calls in tests -### ✅ Initialisierungsreihenfolge analysiert +### ✅ Initialization Order Analyzed -**Korrekte Reihenfolge in Services:** +**Correct Order in Services:** 1. `@PostConstruct` → `DatabaseFactory.init(config)` → `Database.connect()` -2. Sofort danach: `transaction { SchemaUtils.createMissingTablesAndColumns(...) }` -3. Business Logic: `DatabaseFactory.dbQuery { ... }` für Transaktionen +2. Immediately after: `transaction { SchemaUtils.createMissingTablesAndColumns(...) }` +3. Business Logic: `DatabaseFactory.dbQuery { ... }` for transactions -**⚠️ PROBLEM - Gateway Initialisierung:** -1. Ktor Application.configureDatabase() → direkter `Database.connect()` -2. Sofort danach: `transaction { ... }` für alle Service-Schemas +**⚠️ PROBLEM - Gateway Initialization:** +1. Ktor Application.configureDatabase() → direct `Database.connect()` +2. Immediately after: `transaction { ... }` for all service schemas -## 🚨 Identifizierte Probleme +## 🚨 Identified Problems -### 1. **Inkonsistente Database.connect() Implementierung** -- **Services**: Verwenden zentralen DatabaseFactory mit Connection Pooling -- **Gateway**: Direkter Database.connect() ohne Connection Pooling -- **Risiko**: Unterschiedliche Verbindungsqualität und -management +### 1. **Inconsistent Database.connect() Implementation** +- **Services**: Use central DatabaseFactory with Connection Pooling +- **Gateway**: Direct Database.connect() without Connection Pooling +- **Risk**: Different connection quality and management -### 2. **Potentielle Race Conditions** -- Gateway und Services initialisieren unabhängig voneinander -- Beide versuchen, Schemas für dieselben Tabellen zu erstellen -- **Risiko**: Konflikte bei paralleler Initialisierung +### 2. **Potential Race Conditions** +- Gateway and services initialize independently +- Both attempt to create schemas for the same tables +- **Risk**: Conflicts during parallel initialization -### 3. **Verletzung der Separation of Concerns** -- Gateway verwaltet Schemas für alle Services -- Services verwalten ihre eigenen Schemas -- **Risiko**: Doppelte Schema-Initialisierung +### 3. **Violation of Separation of Concerns** +- Gateway manages schemas for all services +- Services manage their own schemas +- **Risk**: Duplicate schema initialization -### 4. **Fehlende Initialisierungsreihenfolge-Garantien** -- Keine explizite Abhängigkeitsreihenfolge zwischen Gateway und Services -- **Risiko**: Exposed-Operationen vor Database.connect() +### 4. **Missing Initialization Order Guarantees** +- No explicit dependency order between Gateway and Services +- **Risk**: Exposed operations before Database.connect() -## ✅ Empfehlungen +## ✅ Recommendations -### 1. **Gateway auf DatabaseFactory umstellen** +### 1. **Switch Gateway to DatabaseFactory** ```kotlin -// Statt direktem Database.connect(): +// Instead of direct Database.connect(): fun Application.configureDatabase() { - val config = DatabaseConfig.fromEnv() // oder aus Ktor Config + val config = DatabaseConfig.fromEnv() // or from Ktor Config DatabaseFactory.init(config) - // Schema-Initialisierung entfernen oder koordinieren + // Remove or coordinate schema initialization } ``` -### 2. **Schema-Initialisierung koordinieren** -**Option A**: Nur Services verwalten ihre Schemas (empfohlen) +### 2. **Coordinate Schema Initialization** +**Option A**: Only services manage their schemas (recommended) ```kotlin -// Gateway: Nur Verbindung, keine Schema-Initialisierung +// Gateway: Only connection, no schema initialization fun Application.configureDatabase() { DatabaseFactory.init(DatabaseConfig.fromEnv()) } ``` -**Option B**: Zentralisierte Schema-Verwaltung +**Option B**: Centralized schema management ```kotlin -// Separater DatabaseSchemaInitializer mit @Order Annotation +// Separate DatabaseSchemaInitializer with @Order annotation @Component @Order(Ordered.HIGHEST_PRECEDENCE) class DatabaseSchemaInitializer { @@ -106,9 +106,9 @@ class DatabaseSchemaInitializer { } ``` -### 3. **Startup-Reihenfolge sicherstellen** +### 3. **Ensure Startup Order** ```kotlin -// Services mit @DependsOn +// Services with @DependsOn @Configuration @DependsOn("databaseInitializer") class HorsesDatabaseConfiguration { @@ -116,9 +116,9 @@ class HorsesDatabaseConfiguration { } ``` -### 4. **Einheitliche Konfiguration** +### 4. **Unified Configuration** ```kotlin -// Alle Komponenten verwenden DatabaseFactory +// All components use DatabaseFactory class SomeService { suspend fun doSomething() { DatabaseFactory.dbQuery { @@ -128,21 +128,25 @@ class SomeService { } ``` -## 📋 Zusammenfassung +## 📋 Summary -**✅ Korrekt implementiert:** -- Alle Services verwenden proper @PostConstruct → Database.connect() → Exposed operations Reihenfolge -- DatabaseFactory bietet robuste Connection Pool Konfiguration -- Business Logic verwendet korrekte Transaktionsmuster +**✅ Correctly implemented:** +- All services use proper @PostConstruct → Database.connect() → Exposed operations sequence +- DatabaseFactory provides robust Connection Pool configuration +- Business logic uses correct transaction patterns -**⚠️ Zu beheben:** -- Gateway Database.connect() Inkonsistenz -- Potentielle Race Conditions bei Schema-Initialisierung -- Fehlende Startup-Reihenfolge-Koordination +**⚠️ To be fixed:** +- Gateway Database.connect() inconsistency +- Potential race conditions in schema initialization +- Missing startup order coordination -**🎯 Priorität:** -1. **Hoch**: Gateway auf DatabaseFactory umstellen -2. **Mittel**: Schema-Initialisierung koordinieren -3. **Niedrig**: Startup-Reihenfolge explizit definieren +**🎯 Priority:** +1. **High**: Switch Gateway to DatabaseFactory +2. **Medium**: Coordinate schema initialization +3. **Low**: Explicitly define startup order -Die Reihenfolge der Initialisierung ist grundsätzlich korrekt, aber die Inkonsistenz zwischen Gateway und Services sollte behoben werden, um potentielle Probleme zu vermeiden. +The initialization sequence is fundamentally correct, but the inconsistency between Gateway and Services should be resolved to avoid potential problems. + +--- + +*Last updated: July 25, 2025* diff --git a/docs/development/getting-started-de.md b/docs/development/getting-started-de.md deleted file mode 100644 index b380118c..00000000 --- a/docs/development/getting-started-de.md +++ /dev/null @@ -1,607 +0,0 @@ -# Entwicklungsanleitung - Erste Schritte - -## Überblick - -Diese Anleitung hilft neuen Entwicklern beim Einstieg in das Meldestelle-Projekt. Sie deckt alle notwendigen Schritte ab, von der initialen Einrichtung bis zur ersten erfolgreichen Entwicklungsumgebung. - -## Voraussetzungen - -### System-Anforderungen - -- **Betriebssystem**: Windows 10+, macOS 10.15+, oder Linux (Ubuntu 20.04+ empfohlen) -- **RAM**: Mindestens 8GB (16GB empfohlen) -- **Speicher**: Mindestens 10GB freier Speicherplatz -- **Netzwerk**: Stabile Internetverbindung für Downloads - -### Erforderliche Software - -#### 1. Java Development Kit (JDK) -```bash -# Java 21 installieren (empfohlen: Eclipse Temurin) -# Windows (mit Chocolatey) -choco install temurin21 - -# macOS (mit Homebrew) -brew install --cask temurin21 - -# Linux (Ubuntu/Debian) -sudo apt update -sudo apt install openjdk-21-jdk - -# Verifizierung -java -version -javac -version -``` - -#### 2. Docker und Docker Compose -```bash -# Docker Desktop installieren (Windows/macOS) -# Herunterladen von: https://www.docker.com/products/docker-desktop - -# Linux (Ubuntu) -sudo apt update -sudo apt install docker.io docker-compose -sudo usermod -aG docker $USER - -# Verifizierung -docker --version -docker-compose --version -``` - -#### 3. Git -```bash -# Windows (mit Chocolatey) -choco install git - -# macOS (mit Homebrew) -brew install git - -# Linux (Ubuntu) -sudo apt install git - -# Verifizierung -git --version -``` - -#### 4. IDE (Empfohlen: IntelliJ IDEA) -```bash -# IntelliJ IDEA Community Edition -# Herunterladen von: https://www.jetbrains.com/idea/download/ - -# Oder mit Package Manager -# Windows (Chocolatey) -choco install intellijidea-community - -# macOS (Homebrew) -brew install --cask intellij-idea-ce - -# Linux (Snap) -sudo snap install intellij-idea-community --classic -``` - -## Projekt-Setup - -### 1. Repository klonen - -```bash -# Repository klonen -git clone -cd Meldestelle - -# Branch-Status prüfen -git status -git branch -a -``` - -### 2. Umgebungsvariablen konfigurieren - -```bash -# .env-Datei erstellen (falls nicht vorhanden) -cp .env.example .env - -# .env-Datei bearbeiten -nano .env # oder mit bevorzugtem Editor -``` - -#### Wichtige Umgebungsvariablen - -```bash -# Anwendungskonfiguration -APP_ENVIRONMENT=development -APP_NAME=meldestelle -APP_VERSION=1.0.0 - -# Datenbank-Konfiguration -DATABASE_URL=jdbc:postgresql://localhost:5432/meldestelle -DATABASE_USERNAME=meldestelle -DATABASE_PASSWORD=password - -# Redis-Konfiguration -REDIS_HOST=localhost -REDIS_PORT=6379 -REDIS_PASSWORD= - -# Keycloak-Konfiguration -KEYCLOAK_URL=http://localhost:8080 -KEYCLOAK_REALM=meldestelle -KEYCLOAK_CLIENT_ID=meldestelle-client - -# Kafka-Konfiguration -KAFKA_BOOTSTRAP_SERVERS=localhost:9092 -KAFKA_GROUP_ID=meldestelle-group -``` - -### 3. Docker-Infrastruktur starten - -```bash -# Alle Services starten -docker-compose up -d - -# Status überprüfen -docker-compose ps - -# Logs anzeigen (optional) -docker-compose logs -f - -# Einzelne Services starten (falls gewünscht) -docker-compose up -d postgres redis keycloak -``` - -#### Service-Übersicht - -| Service | Port | Beschreibung | URL | -|---------|------|--------------|-----| -| PostgreSQL | 5432 | Hauptdatenbank | localhost:5432 | -| Redis | 6379 | Cache & Event Store | localhost:6379 | -| Keycloak | 8080 | Authentifizierung | http://localhost:8080 | -| Kafka | 9092 | Messaging | localhost:9092 | -| Zookeeper | 2181 | Kafka Koordination | localhost:2181 | -| Zipkin | 9411 | Distributed Tracing | http://localhost:9411 | -| Prometheus | 9090 | Metriken | http://localhost:9090 | -| Grafana | 3000 | Dashboards | http://localhost:3000 | - -### 4. Umgebung validieren - -```bash -# Validierungsskript ausführen -./validate-env.sh - -# Oder manuell prüfen -docker-compose ps -curl http://localhost:8080/auth/realms/meldestelle -``` - -## IDE-Konfiguration - -### IntelliJ IDEA Setup - -#### 1. Projekt öffnen -1. IntelliJ IDEA starten -2. "Open" wählen -3. Meldestelle-Projektverzeichnis auswählen -4. "Open as Project" bestätigen - -#### 2. Kotlin-Plugin aktivieren -1. File → Settings (Ctrl+Alt+S) -2. Plugins → Marketplace -3. "Kotlin" suchen und installieren -4. IDE neu starten - -#### 3. Gradle-Konfiguration -1. File → Settings → Build → Gradle -2. "Use Gradle from" → "gradle-wrapper.properties file" -3. "Gradle JVM" → Java 21 auswählen -4. "Apply" und "OK" - -#### 4. Code-Style konfigurieren -1. File → Settings → Editor → Code Style -2. Scheme → "Project" auswählen -3. Kotlin → Tabs and Indents: - - Tab size: 4 - - Indent: 4 - - Continuation indent: 8 - -#### 5. Nützliche Plugins installieren -- **Docker**: Docker-Integration -- **Database Tools**: Datenbankzugriff -- **GitToolBox**: Erweiterte Git-Features -- **Rainbow Brackets**: Bessere Klammer-Visualisierung -- **String Manipulation**: Text-Utilities - -### VS Code Setup (Alternative) - -#### 1. Erforderliche Extensions -```bash -# Extension Pack for Java -code --install-extension vscjava.vscode-java-pack - -# Kotlin Language -code --install-extension fwcd.kotlin - -# Docker -code --install-extension ms-azuretools.vscode-docker - -# GitLens -code --install-extension eamodio.gitlens -``` - -#### 2. Workspace-Konfiguration -```json -{ - "java.home": "/path/to/java-21", - "java.configuration.updateBuildConfiguration": "automatic", - "kotlin.languageServer.enabled": true, - "docker.showStartPage": false -} -``` - -Erstellen Sie diese Datei als `.vscode/settings.json` im Projektverzeichnis. - -## Projekt-Architektur verstehen - -### Modulare Struktur - -``` -Meldestelle/ -├── core/ # Shared Kernel -│ ├── core-domain/ # Gemeinsame Domain-Modelle -│ └── core-utils/ # Utilities und Konfiguration -├── members/ # Mitgliederverwaltung -│ ├── members-domain/ # Domain Layer -│ ├── members-application/ # Application Layer -│ ├── members-infrastructure/ # Infrastructure Layer -│ ├── members-api/ # API Layer -│ └── members-service/ # Service Layer -├── horses/ # Pferderegistrierung -├── events/ # Veranstaltungsverwaltung -├── masterdata/ # Stammdatenverwaltung -├── infrastructure/ # Infrastruktur-Services -├── client/ # Client-Anwendungen -└── docs/ # Dokumentation -``` - -### Clean Architecture Prinzipien - -1. **Domain Layer**: Geschäftslogik und Entitäten -2. **Application Layer**: Use Cases und Orchestrierung -3. **Infrastructure Layer**: Datenbankzugriff und externe Services -4. **API Layer**: REST-Controller und DTOs -5. **Service Layer**: Spring Boot Anwendungen - -### Technologie-Stack - -- **Backend**: Kotlin + Spring Boot -- **Datenbank**: PostgreSQL + Exposed ORM -- **Caching**: Redis -- **Messaging**: Apache Kafka -- **Authentifizierung**: Keycloak + JWT -- **Monitoring**: Prometheus + Grafana -- **Tracing**: Zipkin -- **Frontend**: Jetpack Compose (Desktop/Web) -- **Build**: Gradle mit Kotlin DSL - -## Erste Entwicklungsschritte - -### 1. Projekt kompilieren - -```bash -# Vollständigen Build ausführen -./gradlew build - -# Nur kompilieren (ohne Tests) -./gradlew compileKotlin - -# Spezifisches Modul kompilieren -./gradlew :members:members-service:build -``` - -### 2. Tests ausführen - -```bash -# Alle Tests -./gradlew test - -# Modul-spezifische Tests -./gradlew :members:test - -# Integration Tests -./gradlew integrationTest - -# Test-Reports anzeigen -open build/reports/tests/test/index.html -``` - -### 3. Services starten - -```bash -# Einzelnen Service starten -./gradlew :members:members-service:bootRun - -# Mit spezifischem Profil -./gradlew :members:members-service:bootRun --args='--spring.profiles.active=dev' - -# API Gateway starten -./gradlew :infrastructure:gateway:bootRun -``` - -### 4. Datenbank-Migrationen - -```bash -# Flyway-Migrationen ausführen -./gradlew flywayMigrate - -# Migration-Status prüfen -./gradlew flywayInfo - -# Datenbank zurücksetzen (Vorsicht!) -./gradlew flywayClean -``` - -## Entwicklungsworkflows - -### Feature-Entwicklung - -#### 1. Feature Branch erstellen -```bash -# Neuen Feature Branch erstellen -git checkout -b feature/neue-funktion - -# Branch auf Remote pushen -git push -u origin feature/neue-funktion -``` - -#### 2. Code-Änderungen -```bash -# Änderungen committen -git add . -git commit -m "feat: neue Funktion implementiert" - -# Code-Style prüfen -./gradlew ktlintCheck - -# Code formatieren -./gradlew ktlintFormat -``` - -#### 3. Tests und Qualitätssicherung -```bash -# Tests ausführen -./gradlew test - -# Code-Coverage prüfen -./gradlew jacocoTestReport -open build/reports/jacoco/test/html/index.html - -# Statische Code-Analyse -./gradlew detekt -``` - -#### 4. Pull Request erstellen -1. Änderungen auf Remote Branch pushen -2. Pull Request im Repository erstellen -3. Code Review abwarten -4. Nach Approval mergen - -### Debugging - -#### 1. Service-Debugging -```bash -# Service mit Debug-Port starten -./gradlew :members:members-service:bootRun --debug-jvm - -# Oder mit spezifischem Port -./gradlew :members:members-service:bootRun -Dspring-boot.run.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005" -``` - -#### 2. IntelliJ Remote Debugging -1. Run → Edit Configurations -2. "+" → Remote JVM Debug -3. Port: 5005 (oder gewählter Port) -4. Debug-Session starten - -#### 3. Logs analysieren -```bash -# Service-Logs anzeigen -docker-compose logs -f members-service - -# Alle Logs -docker-compose logs -f - -# Spezifische Log-Level -export LOGGING_LEVEL_ROOT=DEBUG -./gradlew :members:members-service:bootRun -``` - -### API-Testing - -#### 1. Swagger UI verwenden -```bash -# Service starten -./gradlew :members:members-service:bootRun - -# Swagger UI öffnen -open http://localhost:8082/swagger-ui.html -``` - -#### 2. cURL-Beispiele -```bash -# Alle Mitglieder abrufen -curl -H "Authorization: Bearer " \ - http://localhost:8082/api/members - -# Neues Mitglied erstellen -curl -X POST \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer " \ - -d '{"firstName":"Max","lastName":"Mustermann","email":"max@example.com","membershipNumber":"M2024001","membershipStartDate":"2024-01-01"}' \ - http://localhost:8082/api/members -``` - -#### 3. Postman Collections -```bash -# Postman Collections importieren -# Dateien in docs/postman/ verwenden -``` - -## Häufige Probleme und Lösungen - -### Docker-Probleme - -#### Services starten nicht -```bash -# Ports prüfen -netstat -tulpn | grep :5432 - -# Docker-Logs prüfen -docker-compose logs postgres - -# Services neu starten -docker-compose down -docker-compose up -d -``` - -#### Speicherplatz-Probleme -```bash -# Nicht verwendete Images entfernen -docker system prune -a - -# Volumes aufräumen -docker volume prune -``` - -### Build-Probleme - -#### Gradle-Cache-Probleme -```bash -# Gradle-Cache löschen -./gradlew clean -rm -rf ~/.gradle/caches - -# Dependencies neu laden -./gradlew build --refresh-dependencies -``` - -#### Kotlin-Compiler-Probleme -```bash -# Kotlin-Daemon stoppen -./gradlew --stop - -# Build-Verzeichnis löschen -./gradlew clean - -# Neu kompilieren -./gradlew build -``` - -### Datenbank-Probleme - -#### Verbindungsfehler -```bash -# PostgreSQL-Status prüfen -docker-compose ps postgres - -# Datenbank-Logs prüfen -docker-compose logs postgres - -# Verbindung testen -psql -h localhost -p 5432 -U meldestelle -d meldestelle -``` - -#### Migration-Fehler -```bash -# Migration-Status prüfen -./gradlew flywayInfo - -# Fehlgeschlagene Migration reparieren -./gradlew flywayRepair - -# Datenbank zurücksetzen (Entwicklung) -docker-compose down -v -docker-compose up -d postgres -./gradlew flywayMigrate -``` - -## Nützliche Befehle - -### Gradle-Tasks -```bash -# Alle verfügbaren Tasks anzeigen -./gradlew tasks - -# Abhängigkeiten anzeigen -./gradlew dependencies - -# Projekt-Informationen -./gradlew projects - -# Build-Scan erstellen -./gradlew build --scan -``` - -### Docker-Befehle -```bash -# Container-Status -docker-compose ps - -# Logs verfolgen -docker-compose logs -f [service-name] - -# Container neu starten -docker-compose restart [service-name] - -# In Container einloggen -docker-compose exec postgres psql -U meldestelle -``` - -### Git-Workflows -```bash -# Aktuellen Status prüfen -git status - -# Änderungen stagen -git add . - -# Commit mit konventioneller Nachricht -git commit -m "feat(members): neue Validierung hinzugefügt" - -# Branch wechseln -git checkout main -git pull origin main -``` - -## Weiterführende Ressourcen - -### Dokumentation -- [API-Dokumentation](../api/README.md) -- [Architektur-Dokumentation](../architecture/) -- [Deployment-Anleitung](../README-PRODUCTION.md) - -### Externe Ressourcen -- [Kotlin-Dokumentation](https://kotlinlang.org/docs/) -- [Spring Boot-Dokumentation](https://spring.io/projects/spring-boot) -- [Docker-Dokumentation](https://docs.docker.com/) -- [PostgreSQL-Dokumentation](https://www.postgresql.org/docs/) - -### Community und Support -- **Issue Tracker**: GitHub Issues -- **Diskussionen**: GitHub Discussions -- **Code Reviews**: Pull Requests -- **Dokumentation**: Wiki - -## Nächste Schritte - -Nach erfolgreichem Setup: - -1. **Code-Basis erkunden**: Beginnen Sie mit dem `members`-Modul -2. **Tests ausführen**: Verstehen Sie die Test-Struktur -3. **Erste Änderung**: Implementieren Sie eine kleine Verbesserung -4. **Code Review**: Erstellen Sie einen Pull Request -5. **Dokumentation**: Erweitern Sie die Dokumentation - ---- - -**Letzte Aktualisierung**: 25. Juli 2025 -**Version**: 1.0 -**Zielgruppe**: Neue Entwickler - -Bei Fragen oder Problemen erstellen Sie bitte ein Issue im Repository oder wenden Sie sich an das Entwicklungsteam. diff --git a/docs/how-to/deploy-proxmox-nginx.md b/docs/how-to/deploy-proxmox-nginx.md new file mode 100644 index 00000000..fd0d3a87 --- /dev/null +++ b/docs/how-to/deploy-proxmox-nginx.md @@ -0,0 +1,53 @@ +--- +owner: ops-team +status: active +review_cycle: 180d +last_reviewed: 2025-10-15 +summary: Anleitung zur Installation und Konfiguration des Nginx Reverse Proxys auf dem Proxmox-Host für die Meldestelle-Services. +--- + +# How-To: Proxmox/Nginx Reverse Proxy deployen + +Diese Anleitung beschreibt die Einrichtung des Nginx Reverse Proxys auf dem Proxmox-Host. Die Beispielkonfiguration liegt im Repository und wird unverändert übernommen. + +- Beispielkonfiguration: proxmox-nginx/meldestelle.conf + +## Voraussetzungen +- Proxmox-Host mit root-/sudo-Zugang +- Installiertes Nginx (`apt install nginx`) +- Lokale Container-Services laufen auf dem Host und sind über `localhost` erreichbar (Web 4000, Gateway 8081, VNC 6080) + +## Schritte +1) Konfigurationsdatei auf den Host kopieren +```bash +sudo cp docs/proxmox-nginx/meldestelle.conf /etc/nginx/sites-available/ +``` + +2) Site aktivieren (Symlink anlegen) +```bash +sudo ln -s /etc/nginx/sites-available/meldestelle.conf /etc/nginx/sites-enabled/ +``` + +3) Nginx Konfiguration testen und neu laden +```bash +sudo nginx -t && sudo systemctl reload nginx +``` + +4) DNS konfigurieren (Beispiele) +- meldestelle.yourdomain.com → öffentliche IP deines Proxmox-Hosts +- api.meldestelle.yourdomain.com → öffentliche IP deines Proxmox-Hosts +- vnc.meldestelle.yourdomain.com → öffentliche IP deines Proxmox-Hosts + +5) Health-Checks +```bash +curl -i http://api.meldestelle.yourdomain.com/actuator/health +curl -i http://meldestelle.yourdomain.com/health +``` + +## HTTPS (optional) +In der Beispielkonfiguration sind HTTPS-Serverblöcke und HTTP→HTTPS Redirects als Kommentar enthalten. Aktiviere diese Blöcke, wenn du Zertifikate (Let's Encrypt/Cloudflare) eingerichtet hast. Datei: proxmox-nginx/meldestelle.conf + +## Fehlerbehebung +- 502 Bad Gateway: Zielcontainer läuft nicht oder Port falsch → Dienste starten (`make full-up`) und Ports prüfen. +- CORS-Fehler: API ausschließlich über die `api.*`-Domain aufrufen; Web-App über `meldestelle.*`. +- Änderungen ohne Effekt: `nginx -t` ausführen und `systemctl reload nginx`. diff --git a/docs/how-to/start-local.md b/docs/how-to/start-local.md new file mode 100644 index 00000000..5dce27a9 --- /dev/null +++ b/docs/how-to/start-local.md @@ -0,0 +1,67 @@ +--- +owner: project-maintainers +status: active +review_cycle: 90d +last_reviewed: 2025-10-15 +summary: Kürzeste Anleitung, um das komplette System lokal zu starten und zu prüfen, ob alles läuft. +--- + +# How-To: Lokale Umgebung starten (Quickstart) + +Diese Kurz-Anleitung bringt deine lokale Umgebung in wenigen Minuten zum Laufen. + +## Starten +- Komplettes System (Infra + Services + Clients) +```bash +make full-up +``` + +- Nur Backend (Infra + Gateway + Microservices) +```bash +make services-up +``` + +- Nur Clients (Infra + Web-App) +```bash +make clients-up +``` + +Logs ansehen (z. B. Backend): +```bash +make services-logs +``` + +## Wichtige URLs +- Web App: http://localhost:4000 +- API Gateway: http://localhost:8081 (Health: /actuator/health) +- Keycloak (Auth): http://localhost:8180 +- Consul (Service Discovery): http://localhost:8500 + +Weitere Ports findest du unter: reference/ports-and-urls.md + +## Health-Checks +```bash +# Gateway +curl -i http://localhost:8081/actuator/health + +# Web-App (falls vorhanden) +curl -i http://localhost:4000/health || true +``` + +## Auth (Keycloak) +- Admin-Login (default): http://localhost:8180 + - Username: KC_BOOTSTRAP_ADMIN_USERNAME (default: admin) + - Password: KC_BOOTSTRAP_ADMIN_PASSWORD (default: admin) +- Beim ersten Start wird der Realm aus docker/services/keycloak/meldestelle-realm.json importiert. + +## Häufige Probleme +- Dienste nicht erreichbar → Containers laufen? `make full-logs` bzw. `make services-logs` prüfen. +- 401/403 beim API-Aufruf → Prüfen, ob ein gültiges Bearer-Token gesendet wird und Keycloak erreichbar ist. +- CORS im Browser → API über das Gateway (http://localhost:8081) aufrufen und nicht direkt die Services (8082–8086). +- Port-Kollisionen → Belegte Ports mit `lsof -i :PORT` prüfen oder Ports anpassen. + +## Stoppen +```bash +make full-down +# oder spezifisch: make services-down / make clients-down / make infrastructure-down +``` diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 1567174b..00000000 --- a/docs/index.html +++ /dev/null @@ -1,6388 +0,0 @@ - - - - - Meldestelle API - - - - - - - - - - - - - -
-
- -
-
-
-

Meldestelle API

-
-
-
- -
-
-

Default

-
-
-
-

apiGet

-

API information

-
-
-
-

-

Get basic API information

-

-
-
/api
-

-

Usage and SDK Samples

-

- - -
-
-
curl -X GET\
--H "Accept: text/plain"\
-"http://localhost:8080/api"
-
-
-
import io.swagger.client.*;
-import io.swagger.client.auth.*;
-import io.swagger.client.model.*;
-import io.swagger.client.api.DefaultApi;
-
-import java.io.File;
-import java.util.*;
-
-public class DefaultApiExample {
-
-    public static void main(String[] args) {
-        
-        DefaultApi apiInstance = new DefaultApi();
-        try {
-            'String' result = apiInstance.apiGet();
-            System.out.println(result);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling DefaultApi#apiGet");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-
import io.swagger.client.api.DefaultApi;
-
-public class DefaultApiExample {
-
-    public static void main(String[] args) {
-        DefaultApi apiInstance = new DefaultApi();
-        try {
-            'String' result = apiInstance.apiGet();
-            System.out.println(result);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling DefaultApi#apiGet");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-

-DefaultApi *apiInstance = [[DefaultApi alloc] init];
-
-// API information
-[apiInstance apiGetWithCompletionHandler: 
-              ^('String' output, NSError* error) {
-                            if (output) {
-                                NSLog(@"%@", output);
-                            }
-                            if (error) {
-                                NSLog(@"Error: %@", error);
-                            }
-                        }];
-
-
- -
-
var MeldestelleApi = require('meldestelle_api');
-
-var api = new MeldestelleApi.DefaultApi()
-var callback = function(error, data, response) {
-  if (error) {
-    console.error(error);
-  } else {
-    console.log('API called successfully. Returned data: ' + data);
-  }
-};
-api.apiGet(callback);
-
-
- - -
-
using System;
-using System.Diagnostics;
-using IO.Swagger.Api;
-using IO.Swagger.Client;
-using IO.Swagger.Model;
-
-namespace Example
-{
-    public class apiGetExample
-    {
-        public void main()
-        {
-
-            var apiInstance = new DefaultApi();
-
-            try
-            {
-                // API information
-                'String' result = apiInstance.apiGet();
-                Debug.WriteLine(result);
-            }
-            catch (Exception e)
-            {
-                Debug.Print("Exception when calling DefaultApi.apiGet: " + e.Message );
-            }
-        }
-    }
-}
-
-
- -
-
<?php
-require_once(__DIR__ . '/vendor/autoload.php');
-
-$api_instance = new Swagger\Client\ApiDefaultApi();
-
-try {
-    $result = $api_instance->apiGet();
-    print_r($result);
-} catch (Exception $e) {
-    echo 'Exception when calling DefaultApi->apiGet: ', $e->getMessage(), PHP_EOL;
-}
-?>
-
- -
-
use Data::Dumper;
-use WWW::SwaggerClient::Configuration;
-use WWW::SwaggerClient::DefaultApi;
-
-my $api_instance = WWW::SwaggerClient::DefaultApi->new();
-
-eval { 
-    my $result = $api_instance->apiGet();
-    print Dumper($result);
-};
-if ($@) {
-    warn "Exception when calling DefaultApi->apiGet: $@\n";
-}
-
- -
-
from __future__ import print_statement
-import time
-import swagger_client
-from swagger_client.rest import ApiException
-from pprint import pprint
-
-# create an instance of the API class
-api_instance = swagger_client.DefaultApi()
-
-try: 
-    # API information
-    api_response = api_instance.api_get()
-    pprint(api_response)
-except ApiException as e:
-    print("Exception when calling DefaultApi->apiGet: %s\n" % e)
-
-
- -

Parameters

- - - - - - -

Responses

-

Status: 200 - API information

- - - -
-
-
- -
- -
-
- -
-
-
-
-
-
-

healthGet

-

Health check

-
-
-
-

-

Check if the service is running

-

-
-
/health
-

-

Usage and SDK Samples

-

- - -
-
-
curl -X GET\
--H "Accept: text/plain"\
-"http://localhost:8080/health"
-
-
-
import io.swagger.client.*;
-import io.swagger.client.auth.*;
-import io.swagger.client.model.*;
-import io.swagger.client.api.DefaultApi;
-
-import java.io.File;
-import java.util.*;
-
-public class DefaultApiExample {
-
-    public static void main(String[] args) {
-        
-        DefaultApi apiInstance = new DefaultApi();
-        try {
-            'String' result = apiInstance.healthGet();
-            System.out.println(result);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling DefaultApi#healthGet");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-
import io.swagger.client.api.DefaultApi;
-
-public class DefaultApiExample {
-
-    public static void main(String[] args) {
-        DefaultApi apiInstance = new DefaultApi();
-        try {
-            'String' result = apiInstance.healthGet();
-            System.out.println(result);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling DefaultApi#healthGet");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-

-DefaultApi *apiInstance = [[DefaultApi alloc] init];
-
-// Health check
-[apiInstance healthGetWithCompletionHandler: 
-              ^('String' output, NSError* error) {
-                            if (output) {
-                                NSLog(@"%@", output);
-                            }
-                            if (error) {
-                                NSLog(@"Error: %@", error);
-                            }
-                        }];
-
-
- -
-
var MeldestelleApi = require('meldestelle_api');
-
-var api = new MeldestelleApi.DefaultApi()
-var callback = function(error, data, response) {
-  if (error) {
-    console.error(error);
-  } else {
-    console.log('API called successfully. Returned data: ' + data);
-  }
-};
-api.healthGet(callback);
-
-
- - -
-
using System;
-using System.Diagnostics;
-using IO.Swagger.Api;
-using IO.Swagger.Client;
-using IO.Swagger.Model;
-
-namespace Example
-{
-    public class healthGetExample
-    {
-        public void main()
-        {
-
-            var apiInstance = new DefaultApi();
-
-            try
-            {
-                // Health check
-                'String' result = apiInstance.healthGet();
-                Debug.WriteLine(result);
-            }
-            catch (Exception e)
-            {
-                Debug.Print("Exception when calling DefaultApi.healthGet: " + e.Message );
-            }
-        }
-    }
-}
-
-
- -
-
<?php
-require_once(__DIR__ . '/vendor/autoload.php');
-
-$api_instance = new Swagger\Client\ApiDefaultApi();
-
-try {
-    $result = $api_instance->healthGet();
-    print_r($result);
-} catch (Exception $e) {
-    echo 'Exception when calling DefaultApi->healthGet: ', $e->getMessage(), PHP_EOL;
-}
-?>
-
- -
-
use Data::Dumper;
-use WWW::SwaggerClient::Configuration;
-use WWW::SwaggerClient::DefaultApi;
-
-my $api_instance = WWW::SwaggerClient::DefaultApi->new();
-
-eval { 
-    my $result = $api_instance->healthGet();
-    print Dumper($result);
-};
-if ($@) {
-    warn "Exception when calling DefaultApi->healthGet: $@\n";
-}
-
- -
-
from __future__ import print_statement
-import time
-import swagger_client
-from swagger_client.rest import ApiException
-from pprint import pprint
-
-# create an instance of the API class
-api_instance = swagger_client.DefaultApi()
-
-try: 
-    # Health check
-    api_response = api_instance.health_get()
-    pprint(api_response)
-except ApiException as e:
-    print("Exception when calling DefaultApi->healthGet: %s\n" % e)
-
-
- -

Parameters

- - - - - - -

Responses

-

Status: 200 - Service is healthy

- - - -
-
-
- -
- -
-
- -
-
-
-
-
-

Persons

-
-
-
-

apiPersonsGet

-

Get all persons

-
-
-
-

-

Retrieve a list of all persons in the system

-

-
-
/api/persons
-

-

Usage and SDK Samples

-

- - -
-
-
curl -X GET\
--H "Accept: application/json"\
-"http://localhost:8080/api/persons"
-
-
-
import io.swagger.client.*;
-import io.swagger.client.auth.*;
-import io.swagger.client.model.*;
-import io.swagger.client.api.PersonsApi;
-
-import java.io.File;
-import java.util.*;
-
-public class PersonsApiExample {
-
-    public static void main(String[] args) {
-        
-        PersonsApi apiInstance = new PersonsApi();
-        try {
-            array[Person] result = apiInstance.apiPersonsGet();
-            System.out.println(result);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling PersonsApi#apiPersonsGet");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-
import io.swagger.client.api.PersonsApi;
-
-public class PersonsApiExample {
-
-    public static void main(String[] args) {
-        PersonsApi apiInstance = new PersonsApi();
-        try {
-            array[Person] result = apiInstance.apiPersonsGet();
-            System.out.println(result);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling PersonsApi#apiPersonsGet");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-

-PersonsApi *apiInstance = [[PersonsApi alloc] init];
-
-// Get all persons
-[apiInstance apiPersonsGetWithCompletionHandler: 
-              ^(array[Person] output, NSError* error) {
-                            if (output) {
-                                NSLog(@"%@", output);
-                            }
-                            if (error) {
-                                NSLog(@"Error: %@", error);
-                            }
-                        }];
-
-
- -
-
var MeldestelleApi = require('meldestelle_api');
-
-var api = new MeldestelleApi.PersonsApi()
-var callback = function(error, data, response) {
-  if (error) {
-    console.error(error);
-  } else {
-    console.log('API called successfully. Returned data: ' + data);
-  }
-};
-api.apiPersonsGet(callback);
-
-
- - -
-
using System;
-using System.Diagnostics;
-using IO.Swagger.Api;
-using IO.Swagger.Client;
-using IO.Swagger.Model;
-
-namespace Example
-{
-    public class apiPersonsGetExample
-    {
-        public void main()
-        {
-
-            var apiInstance = new PersonsApi();
-
-            try
-            {
-                // Get all persons
-                array[Person] result = apiInstance.apiPersonsGet();
-                Debug.WriteLine(result);
-            }
-            catch (Exception e)
-            {
-                Debug.Print("Exception when calling PersonsApi.apiPersonsGet: " + e.Message );
-            }
-        }
-    }
-}
-
-
- -
-
<?php
-require_once(__DIR__ . '/vendor/autoload.php');
-
-$api_instance = new Swagger\Client\ApiPersonsApi();
-
-try {
-    $result = $api_instance->apiPersonsGet();
-    print_r($result);
-} catch (Exception $e) {
-    echo 'Exception when calling PersonsApi->apiPersonsGet: ', $e->getMessage(), PHP_EOL;
-}
-?>
-
- -
-
use Data::Dumper;
-use WWW::SwaggerClient::Configuration;
-use WWW::SwaggerClient::PersonsApi;
-
-my $api_instance = WWW::SwaggerClient::PersonsApi->new();
-
-eval { 
-    my $result = $api_instance->apiPersonsGet();
-    print Dumper($result);
-};
-if ($@) {
-    warn "Exception when calling PersonsApi->apiPersonsGet: $@\n";
-}
-
- -
-
from __future__ import print_statement
-import time
-import swagger_client
-from swagger_client.rest import ApiException
-from pprint import pprint
-
-# create an instance of the API class
-api_instance = swagger_client.PersonsApi()
-
-try: 
-    # Get all persons
-    api_response = api_instance.api_persons_get()
-    pprint(api_response)
-except ApiException as e:
-    print("Exception when calling PersonsApi->apiPersonsGet: %s\n" % e)
-
-
- -

Parameters

- - - - - - -

Responses

-

Status: 200 - List of persons

- - - -
-
-
- -
- -
-
- -

Status: 500 - Internal server error

- - - -
-
-
- -
- -
-
- -
-
-
-
-
-
-

apiPersonsIdDelete

-

Delete person

-
-
-
-

-

Delete a person from the system

-

-
-
/api/persons/{id}
-

-

Usage and SDK Samples

-

- - -
-
-
curl -X DELETE\
--H "Accept: application/json"\
-"http://localhost:8080/api/persons/{id}"
-
-
-
import io.swagger.client.*;
-import io.swagger.client.auth.*;
-import io.swagger.client.model.*;
-import io.swagger.client.api.PersonsApi;
-
-import java.io.File;
-import java.util.*;
-
-public class PersonsApiExample {
-
-    public static void main(String[] args) {
-        
-        PersonsApi apiInstance = new PersonsApi();
-        UUID id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // UUID | Person UUID
-        try {
-            apiInstance.apiPersonsIdDelete(id);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling PersonsApi#apiPersonsIdDelete");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-
import io.swagger.client.api.PersonsApi;
-
-public class PersonsApiExample {
-
-    public static void main(String[] args) {
-        PersonsApi apiInstance = new PersonsApi();
-        UUID id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // UUID | Person UUID
-        try {
-            apiInstance.apiPersonsIdDelete(id);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling PersonsApi#apiPersonsIdDelete");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-
UUID *id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // Person UUID
-
-PersonsApi *apiInstance = [[PersonsApi alloc] init];
-
-// Delete person
-[apiInstance apiPersonsIdDeleteWith:id
-              completionHandler: ^(NSError* error) {
-                            if (error) {
-                                NSLog(@"Error: %@", error);
-                            }
-                        }];
-
-
- -
-
var MeldestelleApi = require('meldestelle_api');
-
-var api = new MeldestelleApi.PersonsApi()
-var id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // {{UUID}} Person UUID
-
-var callback = function(error, data, response) {
-  if (error) {
-    console.error(error);
-  } else {
-    console.log('API called successfully.');
-  }
-};
-api.apiPersonsIdDelete(id, callback);
-
-
- - -
-
using System;
-using System.Diagnostics;
-using IO.Swagger.Api;
-using IO.Swagger.Client;
-using IO.Swagger.Model;
-
-namespace Example
-{
-    public class apiPersonsIdDeleteExample
-    {
-        public void main()
-        {
-
-            var apiInstance = new PersonsApi();
-            var id = new UUID(); // UUID | Person UUID
-
-            try
-            {
-                // Delete person
-                apiInstance.apiPersonsIdDelete(id);
-            }
-            catch (Exception e)
-            {
-                Debug.Print("Exception when calling PersonsApi.apiPersonsIdDelete: " + e.Message );
-            }
-        }
-    }
-}
-
-
- -
-
<?php
-require_once(__DIR__ . '/vendor/autoload.php');
-
-$api_instance = new Swagger\Client\ApiPersonsApi();
-$id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // UUID | Person UUID
-
-try {
-    $api_instance->apiPersonsIdDelete($id);
-} catch (Exception $e) {
-    echo 'Exception when calling PersonsApi->apiPersonsIdDelete: ', $e->getMessage(), PHP_EOL;
-}
-?>
-
- -
-
use Data::Dumper;
-use WWW::SwaggerClient::Configuration;
-use WWW::SwaggerClient::PersonsApi;
-
-my $api_instance = WWW::SwaggerClient::PersonsApi->new();
-my $id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; # UUID | Person UUID
-
-eval { 
-    $api_instance->apiPersonsIdDelete(id => $id);
-};
-if ($@) {
-    warn "Exception when calling PersonsApi->apiPersonsIdDelete: $@\n";
-}
-
- -
-
from __future__ import print_statement
-import time
-import swagger_client
-from swagger_client.rest import ApiException
-from pprint import pprint
-
-# create an instance of the API class
-api_instance = swagger_client.PersonsApi()
-id = 38400000-8cf0-11bd-b23e-10b96e4ef00d # UUID | Person UUID
-
-try: 
-    # Delete person
-    api_instance.api_persons_id_delete(id)
-except ApiException as e:
-    print("Exception when calling PersonsApi->apiPersonsIdDelete: %s\n" % e)
-
-
- -

Parameters

- -
Path parameters
- - - - - - - - -
NameDescription
id* - - -
-
-
- - UUID - - - (uuid) - - -
- Person UUID -
-
-
- Required -
-
-
-
- - - - - -

Responses

-

Status: 204 - Person deleted successfully

- - - -
-
- -

Status: 400 - Invalid UUID format

- - - -
-
-
- -
- -
-
- -

Status: 404 - Person not found

- - - -
-
-
- -
- -
-
- -

Status: 500 - Internal server error

- - - -
-
-
- -
- -
-
- -
-
-
-
-
-
-

apiPersonsIdGet

-

Get person by ID

-
-
-
-

-

Retrieve a specific person by their UUID

-

-
-
/api/persons/{id}
-

-

Usage and SDK Samples

-

- - -
-
-
curl -X GET\
--H "Accept: application/json"\
-"http://localhost:8080/api/persons/{id}"
-
-
-
import io.swagger.client.*;
-import io.swagger.client.auth.*;
-import io.swagger.client.model.*;
-import io.swagger.client.api.PersonsApi;
-
-import java.io.File;
-import java.util.*;
-
-public class PersonsApiExample {
-
-    public static void main(String[] args) {
-        
-        PersonsApi apiInstance = new PersonsApi();
-        UUID id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // UUID | Person UUID
-        try {
-            Person result = apiInstance.apiPersonsIdGet(id);
-            System.out.println(result);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling PersonsApi#apiPersonsIdGet");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-
import io.swagger.client.api.PersonsApi;
-
-public class PersonsApiExample {
-
-    public static void main(String[] args) {
-        PersonsApi apiInstance = new PersonsApi();
-        UUID id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // UUID | Person UUID
-        try {
-            Person result = apiInstance.apiPersonsIdGet(id);
-            System.out.println(result);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling PersonsApi#apiPersonsIdGet");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-
UUID *id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // Person UUID
-
-PersonsApi *apiInstance = [[PersonsApi alloc] init];
-
-// Get person by ID
-[apiInstance apiPersonsIdGetWith:id
-              completionHandler: ^(Person output, NSError* error) {
-                            if (output) {
-                                NSLog(@"%@", output);
-                            }
-                            if (error) {
-                                NSLog(@"Error: %@", error);
-                            }
-                        }];
-
-
- -
-
var MeldestelleApi = require('meldestelle_api');
-
-var api = new MeldestelleApi.PersonsApi()
-var id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // {{UUID}} Person UUID
-
-var callback = function(error, data, response) {
-  if (error) {
-    console.error(error);
-  } else {
-    console.log('API called successfully. Returned data: ' + data);
-  }
-};
-api.apiPersonsIdGet(id, callback);
-
-
- - -
-
using System;
-using System.Diagnostics;
-using IO.Swagger.Api;
-using IO.Swagger.Client;
-using IO.Swagger.Model;
-
-namespace Example
-{
-    public class apiPersonsIdGetExample
-    {
-        public void main()
-        {
-
-            var apiInstance = new PersonsApi();
-            var id = new UUID(); // UUID | Person UUID
-
-            try
-            {
-                // Get person by ID
-                Person result = apiInstance.apiPersonsIdGet(id);
-                Debug.WriteLine(result);
-            }
-            catch (Exception e)
-            {
-                Debug.Print("Exception when calling PersonsApi.apiPersonsIdGet: " + e.Message );
-            }
-        }
-    }
-}
-
-
- -
-
<?php
-require_once(__DIR__ . '/vendor/autoload.php');
-
-$api_instance = new Swagger\Client\ApiPersonsApi();
-$id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // UUID | Person UUID
-
-try {
-    $result = $api_instance->apiPersonsIdGet($id);
-    print_r($result);
-} catch (Exception $e) {
-    echo 'Exception when calling PersonsApi->apiPersonsIdGet: ', $e->getMessage(), PHP_EOL;
-}
-?>
-
- -
-
use Data::Dumper;
-use WWW::SwaggerClient::Configuration;
-use WWW::SwaggerClient::PersonsApi;
-
-my $api_instance = WWW::SwaggerClient::PersonsApi->new();
-my $id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; # UUID | Person UUID
-
-eval { 
-    my $result = $api_instance->apiPersonsIdGet(id => $id);
-    print Dumper($result);
-};
-if ($@) {
-    warn "Exception when calling PersonsApi->apiPersonsIdGet: $@\n";
-}
-
- -
-
from __future__ import print_statement
-import time
-import swagger_client
-from swagger_client.rest import ApiException
-from pprint import pprint
-
-# create an instance of the API class
-api_instance = swagger_client.PersonsApi()
-id = 38400000-8cf0-11bd-b23e-10b96e4ef00d # UUID | Person UUID
-
-try: 
-    # Get person by ID
-    api_response = api_instance.api_persons_id_get(id)
-    pprint(api_response)
-except ApiException as e:
-    print("Exception when calling PersonsApi->apiPersonsIdGet: %s\n" % e)
-
-
- -

Parameters

- -
Path parameters
- - - - - - - - -
NameDescription
id* - - -
-
-
- - UUID - - - (uuid) - - -
- Person UUID -
-
-
- Required -
-
-
-
- - - - - -

Responses

-

Status: 200 - Person found

- - - -
-
-
- -
- -
-
- -

Status: 400 - Invalid UUID format

- - - -
-
-
- -
- -
-
- -

Status: 404 - Person not found

- - - -
-
-
- -
- -
-
- -

Status: 500 - Internal server error

- - - -
-
-
- -
- -
-
- -
-
-
-
-
-
-

apiPersonsIdPut

-

Update person

-
-
-
-

-

Update an existing person

-

-
-
/api/persons/{id}
-

-

Usage and SDK Samples

-

- - -
-
-
curl -X PUT\
--H "Accept: application/json"\
--H "Content-Type: application/json"\
-"http://localhost:8080/api/persons/{id}"
-
-
-
import io.swagger.client.*;
-import io.swagger.client.auth.*;
-import io.swagger.client.model.*;
-import io.swagger.client.api.PersonsApi;
-
-import java.io.File;
-import java.util.*;
-
-public class PersonsApiExample {
-
-    public static void main(String[] args) {
-        
-        PersonsApi apiInstance = new PersonsApi();
-        Person body = ; // Person | 
-        UUID id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // UUID | Person UUID
-        try {
-            Person result = apiInstance.apiPersonsIdPut(body, id);
-            System.out.println(result);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling PersonsApi#apiPersonsIdPut");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-
import io.swagger.client.api.PersonsApi;
-
-public class PersonsApiExample {
-
-    public static void main(String[] args) {
-        PersonsApi apiInstance = new PersonsApi();
-        Person body = ; // Person | 
-        UUID id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // UUID | Person UUID
-        try {
-            Person result = apiInstance.apiPersonsIdPut(body, id);
-            System.out.println(result);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling PersonsApi#apiPersonsIdPut");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-
Person *body = ; // 
-UUID *id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // Person UUID
-
-PersonsApi *apiInstance = [[PersonsApi alloc] init];
-
-// Update person
-[apiInstance apiPersonsIdPutWith:body
-    id:id
-              completionHandler: ^(Person output, NSError* error) {
-                            if (output) {
-                                NSLog(@"%@", output);
-                            }
-                            if (error) {
-                                NSLog(@"Error: %@", error);
-                            }
-                        }];
-
-
- -
-
var MeldestelleApi = require('meldestelle_api');
-
-var api = new MeldestelleApi.PersonsApi()
-var body = ; // {{Person}} 
-var id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // {{UUID}} Person UUID
-
-var callback = function(error, data, response) {
-  if (error) {
-    console.error(error);
-  } else {
-    console.log('API called successfully. Returned data: ' + data);
-  }
-};
-api.apiPersonsIdPut(bodyid, callback);
-
-
- - -
-
using System;
-using System.Diagnostics;
-using IO.Swagger.Api;
-using IO.Swagger.Client;
-using IO.Swagger.Model;
-
-namespace Example
-{
-    public class apiPersonsIdPutExample
-    {
-        public void main()
-        {
-
-            var apiInstance = new PersonsApi();
-            var body = new Person(); // Person | 
-            var id = new UUID(); // UUID | Person UUID
-
-            try
-            {
-                // Update person
-                Person result = apiInstance.apiPersonsIdPut(body, id);
-                Debug.WriteLine(result);
-            }
-            catch (Exception e)
-            {
-                Debug.Print("Exception when calling PersonsApi.apiPersonsIdPut: " + e.Message );
-            }
-        }
-    }
-}
-
-
- -
-
<?php
-require_once(__DIR__ . '/vendor/autoload.php');
-
-$api_instance = new Swagger\Client\ApiPersonsApi();
-$body = ; // Person | 
-$id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // UUID | Person UUID
-
-try {
-    $result = $api_instance->apiPersonsIdPut($body, $id);
-    print_r($result);
-} catch (Exception $e) {
-    echo 'Exception when calling PersonsApi->apiPersonsIdPut: ', $e->getMessage(), PHP_EOL;
-}
-?>
-
- -
-
use Data::Dumper;
-use WWW::SwaggerClient::Configuration;
-use WWW::SwaggerClient::PersonsApi;
-
-my $api_instance = WWW::SwaggerClient::PersonsApi->new();
-my $body = WWW::SwaggerClient::Object::Person->new(); # Person | 
-my $id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; # UUID | Person UUID
-
-eval { 
-    my $result = $api_instance->apiPersonsIdPut(body => $body, id => $id);
-    print Dumper($result);
-};
-if ($@) {
-    warn "Exception when calling PersonsApi->apiPersonsIdPut: $@\n";
-}
-
- -
-
from __future__ import print_statement
-import time
-import swagger_client
-from swagger_client.rest import ApiException
-from pprint import pprint
-
-# create an instance of the API class
-api_instance = swagger_client.PersonsApi()
-body =  # Person | 
-id = 38400000-8cf0-11bd-b23e-10b96e4ef00d # UUID | Person UUID
-
-try: 
-    # Update person
-    api_response = api_instance.api_persons_id_put(body, id)
-    pprint(api_response)
-except ApiException as e:
-    print("Exception when calling PersonsApi->apiPersonsIdPut: %s\n" % e)
-
-
- -

Parameters

- -
Path parameters
- - - - - - - - -
NameDescription
id* - - -
-
-
- - UUID - - - (uuid) - - -
- Person UUID -
-
-
- Required -
-
-
-
- - -
Body parameters
- - - - - - - - -
NameDescription
body * - - - -
-
- - - -

Responses

-

Status: 200 - Person updated successfully

- - - -
-
-
- -
- -
-
- -

Status: 400 - Bad request

- - - -
-
-
- -
- -
-
- -

Status: 404 - Person not found

- - - -
-
-
- -
- -
-
- -
-
-
-
-
-
-

apiPersonsOepsOepsSatzNrGet

-

Get person by OEPS number

-
-
-
-

-

Retrieve a person by their OEPS Satz number

-

-
-
/api/persons/oeps/{oepsSatzNr}
-

-

Usage and SDK Samples

-

- - -
-
-
curl -X GET\
--H "Accept: application/json"\
-"http://localhost:8080/api/persons/oeps/{oepsSatzNr}"
-
-
-
import io.swagger.client.*;
-import io.swagger.client.auth.*;
-import io.swagger.client.model.*;
-import io.swagger.client.api.PersonsApi;
-
-import java.io.File;
-import java.util.*;
-
-public class PersonsApiExample {
-
-    public static void main(String[] args) {
-        
-        PersonsApi apiInstance = new PersonsApi();
-        String oepsSatzNr = oepsSatzNr_example; // String | OEPS Satz number
-        try {
-            Person result = apiInstance.apiPersonsOepsOepsSatzNrGet(oepsSatzNr);
-            System.out.println(result);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling PersonsApi#apiPersonsOepsOepsSatzNrGet");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-
import io.swagger.client.api.PersonsApi;
-
-public class PersonsApiExample {
-
-    public static void main(String[] args) {
-        PersonsApi apiInstance = new PersonsApi();
-        String oepsSatzNr = oepsSatzNr_example; // String | OEPS Satz number
-        try {
-            Person result = apiInstance.apiPersonsOepsOepsSatzNrGet(oepsSatzNr);
-            System.out.println(result);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling PersonsApi#apiPersonsOepsOepsSatzNrGet");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-
String *oepsSatzNr = oepsSatzNr_example; // OEPS Satz number
-
-PersonsApi *apiInstance = [[PersonsApi alloc] init];
-
-// Get person by OEPS number
-[apiInstance apiPersonsOepsOepsSatzNrGetWith:oepsSatzNr
-              completionHandler: ^(Person output, NSError* error) {
-                            if (output) {
-                                NSLog(@"%@", output);
-                            }
-                            if (error) {
-                                NSLog(@"Error: %@", error);
-                            }
-                        }];
-
-
- -
-
var MeldestelleApi = require('meldestelle_api');
-
-var api = new MeldestelleApi.PersonsApi()
-var oepsSatzNr = oepsSatzNr_example; // {{String}} OEPS Satz number
-
-var callback = function(error, data, response) {
-  if (error) {
-    console.error(error);
-  } else {
-    console.log('API called successfully. Returned data: ' + data);
-  }
-};
-api.apiPersonsOepsOepsSatzNrGet(oepsSatzNr, callback);
-
-
- - -
-
using System;
-using System.Diagnostics;
-using IO.Swagger.Api;
-using IO.Swagger.Client;
-using IO.Swagger.Model;
-
-namespace Example
-{
-    public class apiPersonsOepsOepsSatzNrGetExample
-    {
-        public void main()
-        {
-
-            var apiInstance = new PersonsApi();
-            var oepsSatzNr = oepsSatzNr_example;  // String | OEPS Satz number
-
-            try
-            {
-                // Get person by OEPS number
-                Person result = apiInstance.apiPersonsOepsOepsSatzNrGet(oepsSatzNr);
-                Debug.WriteLine(result);
-            }
-            catch (Exception e)
-            {
-                Debug.Print("Exception when calling PersonsApi.apiPersonsOepsOepsSatzNrGet: " + e.Message );
-            }
-        }
-    }
-}
-
-
- -
-
<?php
-require_once(__DIR__ . '/vendor/autoload.php');
-
-$api_instance = new Swagger\Client\ApiPersonsApi();
-$oepsSatzNr = oepsSatzNr_example; // String | OEPS Satz number
-
-try {
-    $result = $api_instance->apiPersonsOepsOepsSatzNrGet($oepsSatzNr);
-    print_r($result);
-} catch (Exception $e) {
-    echo 'Exception when calling PersonsApi->apiPersonsOepsOepsSatzNrGet: ', $e->getMessage(), PHP_EOL;
-}
-?>
-
- -
-
use Data::Dumper;
-use WWW::SwaggerClient::Configuration;
-use WWW::SwaggerClient::PersonsApi;
-
-my $api_instance = WWW::SwaggerClient::PersonsApi->new();
-my $oepsSatzNr = oepsSatzNr_example; # String | OEPS Satz number
-
-eval { 
-    my $result = $api_instance->apiPersonsOepsOepsSatzNrGet(oepsSatzNr => $oepsSatzNr);
-    print Dumper($result);
-};
-if ($@) {
-    warn "Exception when calling PersonsApi->apiPersonsOepsOepsSatzNrGet: $@\n";
-}
-
- -
-
from __future__ import print_statement
-import time
-import swagger_client
-from swagger_client.rest import ApiException
-from pprint import pprint
-
-# create an instance of the API class
-api_instance = swagger_client.PersonsApi()
-oepsSatzNr = oepsSatzNr_example # String | OEPS Satz number
-
-try: 
-    # Get person by OEPS number
-    api_response = api_instance.api_persons_oeps_oeps_satz_nr_get(oepsSatzNr)
-    pprint(api_response)
-except ApiException as e:
-    print("Exception when calling PersonsApi->apiPersonsOepsOepsSatzNrGet: %s\n" % e)
-
-
- -

Parameters

- -
Path parameters
- - - - - - - - -
NameDescription
oepsSatzNr* - - -
-
-
- - String - - -
- OEPS Satz number -
-
-
- Required -
-
-
-
- - - - - -

Responses

-

Status: 200 - Person found

- - - -
-
-
- -
- -
-
- -

Status: 400 - Missing OEPS Satz number

- - - -
-
-
- -
- -
-
- -

Status: 404 - Person not found

- - - -
-
-
- -
- -
-
- -

Status: 500 - Internal server error

- - - -
-
-
- -
- -
-
- -
-
-
-
-
-
-

apiPersonsPost

-

Create new person

-
-
-
-

-

Create a new person in the system

-

-
-
/api/persons
-

-

Usage and SDK Samples

-

- - -
-
-
curl -X POST\
--H "Accept: application/json"\
--H "Content-Type: application/json"\
-"http://localhost:8080/api/persons"
-
-
-
import io.swagger.client.*;
-import io.swagger.client.auth.*;
-import io.swagger.client.model.*;
-import io.swagger.client.api.PersonsApi;
-
-import java.io.File;
-import java.util.*;
-
-public class PersonsApiExample {
-
-    public static void main(String[] args) {
-        
-        PersonsApi apiInstance = new PersonsApi();
-        Person body = ; // Person | 
-        try {
-            Person result = apiInstance.apiPersonsPost(body);
-            System.out.println(result);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling PersonsApi#apiPersonsPost");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-
import io.swagger.client.api.PersonsApi;
-
-public class PersonsApiExample {
-
-    public static void main(String[] args) {
-        PersonsApi apiInstance = new PersonsApi();
-        Person body = ; // Person | 
-        try {
-            Person result = apiInstance.apiPersonsPost(body);
-            System.out.println(result);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling PersonsApi#apiPersonsPost");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-
Person *body = ; // 
-
-PersonsApi *apiInstance = [[PersonsApi alloc] init];
-
-// Create new person
-[apiInstance apiPersonsPostWith:body
-              completionHandler: ^(Person output, NSError* error) {
-                            if (output) {
-                                NSLog(@"%@", output);
-                            }
-                            if (error) {
-                                NSLog(@"Error: %@", error);
-                            }
-                        }];
-
-
- -
-
var MeldestelleApi = require('meldestelle_api');
-
-var api = new MeldestelleApi.PersonsApi()
-var body = ; // {{Person}} 
-
-var callback = function(error, data, response) {
-  if (error) {
-    console.error(error);
-  } else {
-    console.log('API called successfully. Returned data: ' + data);
-  }
-};
-api.apiPersonsPost(body, callback);
-
-
- - -
-
using System;
-using System.Diagnostics;
-using IO.Swagger.Api;
-using IO.Swagger.Client;
-using IO.Swagger.Model;
-
-namespace Example
-{
-    public class apiPersonsPostExample
-    {
-        public void main()
-        {
-
-            var apiInstance = new PersonsApi();
-            var body = new Person(); // Person | 
-
-            try
-            {
-                // Create new person
-                Person result = apiInstance.apiPersonsPost(body);
-                Debug.WriteLine(result);
-            }
-            catch (Exception e)
-            {
-                Debug.Print("Exception when calling PersonsApi.apiPersonsPost: " + e.Message );
-            }
-        }
-    }
-}
-
-
- -
-
<?php
-require_once(__DIR__ . '/vendor/autoload.php');
-
-$api_instance = new Swagger\Client\ApiPersonsApi();
-$body = ; // Person | 
-
-try {
-    $result = $api_instance->apiPersonsPost($body);
-    print_r($result);
-} catch (Exception $e) {
-    echo 'Exception when calling PersonsApi->apiPersonsPost: ', $e->getMessage(), PHP_EOL;
-}
-?>
-
- -
-
use Data::Dumper;
-use WWW::SwaggerClient::Configuration;
-use WWW::SwaggerClient::PersonsApi;
-
-my $api_instance = WWW::SwaggerClient::PersonsApi->new();
-my $body = WWW::SwaggerClient::Object::Person->new(); # Person | 
-
-eval { 
-    my $result = $api_instance->apiPersonsPost(body => $body);
-    print Dumper($result);
-};
-if ($@) {
-    warn "Exception when calling PersonsApi->apiPersonsPost: $@\n";
-}
-
- -
-
from __future__ import print_statement
-import time
-import swagger_client
-from swagger_client.rest import ApiException
-from pprint import pprint
-
-# create an instance of the API class
-api_instance = swagger_client.PersonsApi()
-body =  # Person | 
-
-try: 
-    # Create new person
-    api_response = api_instance.api_persons_post(body)
-    pprint(api_response)
-except ApiException as e:
-    print("Exception when calling PersonsApi->apiPersonsPost: %s\n" % e)
-
-
- -

Parameters

- - - -
Body parameters
- - - - - - - - -
NameDescription
body * - - - -
-
- - - -

Responses

-

Status: 201 - Person created successfully

- - - -
-
-
- -
- -
-
- -

Status: 400 - Bad request

- - - -
-
-
- -
- -
-
- -
-
-
-
-
-
-

apiPersonsSearchGet

-

Search persons

-
-
-
-

-

Search for persons using a query string

-

-
-
/api/persons/search
-

-

Usage and SDK Samples

-

- - -
-
-
curl -X GET\
--H "Accept: application/json"\
-"http://localhost:8080/api/persons/search?q="
-
-
-
import io.swagger.client.*;
-import io.swagger.client.auth.*;
-import io.swagger.client.model.*;
-import io.swagger.client.api.PersonsApi;
-
-import java.io.File;
-import java.util.*;
-
-public class PersonsApiExample {
-
-    public static void main(String[] args) {
-        
-        PersonsApi apiInstance = new PersonsApi();
-        String q = q_example; // String | Search query
-        try {
-            array[Person] result = apiInstance.apiPersonsSearchGet(q);
-            System.out.println(result);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling PersonsApi#apiPersonsSearchGet");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-
import io.swagger.client.api.PersonsApi;
-
-public class PersonsApiExample {
-
-    public static void main(String[] args) {
-        PersonsApi apiInstance = new PersonsApi();
-        String q = q_example; // String | Search query
-        try {
-            array[Person] result = apiInstance.apiPersonsSearchGet(q);
-            System.out.println(result);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling PersonsApi#apiPersonsSearchGet");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-
String *q = q_example; // Search query
-
-PersonsApi *apiInstance = [[PersonsApi alloc] init];
-
-// Search persons
-[apiInstance apiPersonsSearchGetWith:q
-              completionHandler: ^(array[Person] output, NSError* error) {
-                            if (output) {
-                                NSLog(@"%@", output);
-                            }
-                            if (error) {
-                                NSLog(@"Error: %@", error);
-                            }
-                        }];
-
-
- -
-
var MeldestelleApi = require('meldestelle_api');
-
-var api = new MeldestelleApi.PersonsApi()
-var q = q_example; // {{String}} Search query
-
-var callback = function(error, data, response) {
-  if (error) {
-    console.error(error);
-  } else {
-    console.log('API called successfully. Returned data: ' + data);
-  }
-};
-api.apiPersonsSearchGet(q, callback);
-
-
- - -
-
using System;
-using System.Diagnostics;
-using IO.Swagger.Api;
-using IO.Swagger.Client;
-using IO.Swagger.Model;
-
-namespace Example
-{
-    public class apiPersonsSearchGetExample
-    {
-        public void main()
-        {
-
-            var apiInstance = new PersonsApi();
-            var q = q_example;  // String | Search query
-
-            try
-            {
-                // Search persons
-                array[Person] result = apiInstance.apiPersonsSearchGet(q);
-                Debug.WriteLine(result);
-            }
-            catch (Exception e)
-            {
-                Debug.Print("Exception when calling PersonsApi.apiPersonsSearchGet: " + e.Message );
-            }
-        }
-    }
-}
-
-
- -
-
<?php
-require_once(__DIR__ . '/vendor/autoload.php');
-
-$api_instance = new Swagger\Client\ApiPersonsApi();
-$q = q_example; // String | Search query
-
-try {
-    $result = $api_instance->apiPersonsSearchGet($q);
-    print_r($result);
-} catch (Exception $e) {
-    echo 'Exception when calling PersonsApi->apiPersonsSearchGet: ', $e->getMessage(), PHP_EOL;
-}
-?>
-
- -
-
use Data::Dumper;
-use WWW::SwaggerClient::Configuration;
-use WWW::SwaggerClient::PersonsApi;
-
-my $api_instance = WWW::SwaggerClient::PersonsApi->new();
-my $q = q_example; # String | Search query
-
-eval { 
-    my $result = $api_instance->apiPersonsSearchGet(q => $q);
-    print Dumper($result);
-};
-if ($@) {
-    warn "Exception when calling PersonsApi->apiPersonsSearchGet: $@\n";
-}
-
- -
-
from __future__ import print_statement
-import time
-import swagger_client
-from swagger_client.rest import ApiException
-from pprint import pprint
-
-# create an instance of the API class
-api_instance = swagger_client.PersonsApi()
-q = q_example # String | Search query
-
-try: 
-    # Search persons
-    api_response = api_instance.api_persons_search_get(q)
-    pprint(api_response)
-except ApiException as e:
-    print("Exception when calling PersonsApi->apiPersonsSearchGet: %s\n" % e)
-
-
- -

Parameters

- - - - - -
Query parameters
- - - - - - - - -
NameDescription
q* - - -
-
-
- - String - - -
- Search query -
-
-
- Required -
-
-
-
- -

Responses

-

Status: 200 - Search results

- - - -
-
-
- -
- -
-
- -

Status: 400 - Missing search query

- - - -
-
-
- -
- -
-
- -

Status: 500 - Internal server error

- - - -
-
-
- -
- -
-
- -
-
-
-
-
-
-

apiPersonsVereinVereinIdGet

-

Get persons by club ID

-
-
-
-

-

Retrieve all persons belonging to a specific club

-

-
-
/api/persons/verein/{vereinId}
-

-

Usage and SDK Samples

-

- - -
-
-
curl -X GET\
--H "Accept: application/json"\
-"http://localhost:8080/api/persons/verein/{vereinId}"
-
-
-
import io.swagger.client.*;
-import io.swagger.client.auth.*;
-import io.swagger.client.model.*;
-import io.swagger.client.api.PersonsApi;
-
-import java.io.File;
-import java.util.*;
-
-public class PersonsApiExample {
-
-    public static void main(String[] args) {
-        
-        PersonsApi apiInstance = new PersonsApi();
-        UUID vereinId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // UUID | Club UUID
-        try {
-            array[Person] result = apiInstance.apiPersonsVereinVereinIdGet(vereinId);
-            System.out.println(result);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling PersonsApi#apiPersonsVereinVereinIdGet");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-
import io.swagger.client.api.PersonsApi;
-
-public class PersonsApiExample {
-
-    public static void main(String[] args) {
-        PersonsApi apiInstance = new PersonsApi();
-        UUID vereinId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // UUID | Club UUID
-        try {
-            array[Person] result = apiInstance.apiPersonsVereinVereinIdGet(vereinId);
-            System.out.println(result);
-        } catch (ApiException e) {
-            System.err.println("Exception when calling PersonsApi#apiPersonsVereinVereinIdGet");
-            e.printStackTrace();
-        }
-    }
-}
-
- -
-
UUID *vereinId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // Club UUID
-
-PersonsApi *apiInstance = [[PersonsApi alloc] init];
-
-// Get persons by club ID
-[apiInstance apiPersonsVereinVereinIdGetWith:vereinId
-              completionHandler: ^(array[Person] output, NSError* error) {
-                            if (output) {
-                                NSLog(@"%@", output);
-                            }
-                            if (error) {
-                                NSLog(@"Error: %@", error);
-                            }
-                        }];
-
-
- -
-
var MeldestelleApi = require('meldestelle_api');
-
-var api = new MeldestelleApi.PersonsApi()
-var vereinId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // {{UUID}} Club UUID
-
-var callback = function(error, data, response) {
-  if (error) {
-    console.error(error);
-  } else {
-    console.log('API called successfully. Returned data: ' + data);
-  }
-};
-api.apiPersonsVereinVereinIdGet(vereinId, callback);
-
-
- - -
-
using System;
-using System.Diagnostics;
-using IO.Swagger.Api;
-using IO.Swagger.Client;
-using IO.Swagger.Model;
-
-namespace Example
-{
-    public class apiPersonsVereinVereinIdGetExample
-    {
-        public void main()
-        {
-
-            var apiInstance = new PersonsApi();
-            var vereinId = new UUID(); // UUID | Club UUID
-
-            try
-            {
-                // Get persons by club ID
-                array[Person] result = apiInstance.apiPersonsVereinVereinIdGet(vereinId);
-                Debug.WriteLine(result);
-            }
-            catch (Exception e)
-            {
-                Debug.Print("Exception when calling PersonsApi.apiPersonsVereinVereinIdGet: " + e.Message );
-            }
-        }
-    }
-}
-
-
- -
-
<?php
-require_once(__DIR__ . '/vendor/autoload.php');
-
-$api_instance = new Swagger\Client\ApiPersonsApi();
-$vereinId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // UUID | Club UUID
-
-try {
-    $result = $api_instance->apiPersonsVereinVereinIdGet($vereinId);
-    print_r($result);
-} catch (Exception $e) {
-    echo 'Exception when calling PersonsApi->apiPersonsVereinVereinIdGet: ', $e->getMessage(), PHP_EOL;
-}
-?>
-
- -
-
use Data::Dumper;
-use WWW::SwaggerClient::Configuration;
-use WWW::SwaggerClient::PersonsApi;
-
-my $api_instance = WWW::SwaggerClient::PersonsApi->new();
-my $vereinId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; # UUID | Club UUID
-
-eval { 
-    my $result = $api_instance->apiPersonsVereinVereinIdGet(vereinId => $vereinId);
-    print Dumper($result);
-};
-if ($@) {
-    warn "Exception when calling PersonsApi->apiPersonsVereinVereinIdGet: $@\n";
-}
-
- -
-
from __future__ import print_statement
-import time
-import swagger_client
-from swagger_client.rest import ApiException
-from pprint import pprint
-
-# create an instance of the API class
-api_instance = swagger_client.PersonsApi()
-vereinId = 38400000-8cf0-11bd-b23e-10b96e4ef00d # UUID | Club UUID
-
-try: 
-    # Get persons by club ID
-    api_response = api_instance.api_persons_verein_verein_id_get(vereinId)
-    pprint(api_response)
-except ApiException as e:
-    print("Exception when calling PersonsApi->apiPersonsVereinVereinIdGet: %s\n" % e)
-
-
- -

Parameters

- -
Path parameters
- - - - - - - - -
NameDescription
vereinId* - - -
-
-
- - UUID - - - (uuid) - - -
- Club UUID -
-
-
- Required -
-
-
-
- - - - - -

Responses

-

Status: 200 - List of persons in the club

- - - -
-
-
- -
- -
-
- -

Status: 400 - Invalid UUID format

- - - -
-
-
- -
- -
-
- -

Status: 500 - Internal server error

- - - -
-
-
- -
- -
-
- -
-
-
-
-
- -
-
-
- - - - - - - - - diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..9c934353 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,26 @@ +--- +owner: project-maintainers +status: active +review_cycle: 90d +last_reviewed: 2025-10-15 +summary: Schlanker Einstiegspunkt in die Dokumentation der Meldestelle. Nur die wichtigsten Links für Start, Überblick, API, Produktion und aktuelles Vorhaben. +--- + +# Meldestelle – Dokumentation (Startseite) + +Willkommen! Das ist der zentrale Einstieg in die Projektdokumentation. Starte hier. + +## Start +- Schnellstart lokal: how-to/start-local.md +- Gesamtüberblick: overview/system-overview.md + +## API +- API-Übersicht: api/README.md + +## Betrieb +- Produktion (Proxmox/Nginx): how-to/deploy-proxmox-nginx.md + +## Aktuelles Vorhaben +- Now-Page: now/current.md + +Hinweis: Diese Seite ist der einzige offizielle Einstiegspunkt. Ältere Indizes (z. B. INDEX.md oder bilingualer Index) sind historisch bzw. entfernt. diff --git a/docs/now/README.md b/docs/now/README.md new file mode 100644 index 00000000..0d3a85ed --- /dev/null +++ b/docs/now/README.md @@ -0,0 +1,31 @@ +--- +owner: project-maintainers +status: active +last_reviewed: 2025-10-15 +review_cycle: 90d +summary: Anleitung zur Nutzung der Now-Page (Initiativen-One‑Pager) als zentraler Steuerungs- und Übersichtspunkt. +--- + +# Now-Page – Nutzung & Workflow + +Die Now-Page ist ein schlanker One‑Pager für dein aktuelles Vorhaben. Sie beantwortet stets fünf Fragen: Was, Warum, Wie, Was ist zu tun, und Was ist als Nächstes dran. + +## Struktur +- Aktive Seite: `docs/now/current.md` +- Vorlage: `docs/now/TEMPLATE.md` +- Archiv (optional): `docs/now/archive/` (einfach Dateien hinein verschieben) + +## So verwendest du die Now-Page +1. Neue Initiative starten: Kopiere `TEMPLATE.md` nach `current.md` und fülle sie aus. +2. Kurz halten: 1 Seite, maximal 5–10 Tasks. Große Aufgaben in kleinere Schneiden. +3. Pflege-Ritual: Bei Änderung von Fokus/Status/Plan kurz aktualisieren, `last_reviewed` anpassen. +4. Abschluss: `status: done` setzen, 3 Bulletpoints „Lessons Learned“ ergänzen und Datei nach `now/archive/` verschieben. +5. Dauerhafte Entscheidungen: Als ADR in `docs/architecture/adr/` festhalten und aus der Now‑Page verlinken. + +## Tipps +- Verlinke nur, was du beim Arbeiten wirklich brauchst (PRs, Issues, wichtige How‑Tos). +- Nutze die Now‑Page als Daily/Nächstes‑To‑Do‑Quelle statt vieler verstreuter Notizen. +- Optional in CI: Einen „Stale‑Check“ einführen, der warnt, wenn `current.md` länger als `review_cycle` nicht aktualisiert wurde. + +## Navigation +- Die Startseite (docs/index.md) verlinkt direkt auf `now/current.md`, damit du jederzeit mit einem Klick am aktuellen Fokus bist. diff --git a/docs/now/TEMPLATE.md b/docs/now/TEMPLATE.md new file mode 100644 index 00000000..fea6decb --- /dev/null +++ b/docs/now/TEMPLATE.md @@ -0,0 +1,39 @@ +--- +owner: +status: active # active | blocked | done +timeframe: YYYY-MM-DD → YYYY-MM-DD +last_reviewed: YYYY-MM-DD +review_cycle: 7d # erinnert dich wöchentlich ans Aktualisieren +summary: One-Pager-Template für das aktuell wichtigste Vorhaben (Now-Page). +--- + +# Aktuelle Initiative: + +## 1) Vision (Was?) +Ein Satz Zielbild. Was soll am Ende anders/besser sein? Optional: In/Out of Scope. +- In Scope: … +- Out of Scope: … + +## 2) Why (Warum so?) +Problem, Zielmetriken/Erfolgskriterien, Alternativen/Trade-offs. +- Erfolg messbar an: +- Falls dauerhaft relevant: verweise auf ADR (`docs/adr/...`). + +## 3) How (Wie umsetzen?) +Kurzarchitektur, Ansatz, Risiken/Abhängigkeiten. 5–10 Zeilen genügen. +- Ansatz: … +- Risiken: … +- Abhängigkeiten: … + +## 4) Plan (Was ist jetzt zu tun?) +Milestones + nächste konkrete Schritte. Max. 5–10 Tasks, sonst zu groß schneiden. +- [ ] Schritt 1 (heute) +- [ ] Schritt 2 (diese Woche) +- [ ] Schritt 3 (nächste Woche) + +## 5) Status & Nächster Fokus +- Status: active | blocked | done +- Nächster Fokus (heute): <1–2 Sätze> + +## 6) Referenzen +Links zu PRs, Issues, Diagrammen, Konfigs (nur die, die man wirklich braucht). diff --git a/docs/now/current.md b/docs/now/current.md new file mode 100644 index 00000000..6dae70c0 --- /dev/null +++ b/docs/now/current.md @@ -0,0 +1,43 @@ +--- +owner: stefan +status: active +timeframe: 2025-10-15 → 2025-10-29 +last_reviewed: 2025-10-15 +review_cycle: 7d +summary: Minimal‑Doku + Now‑Page etablieren, um Übersicht zurückzugewinnen. +--- + +# Aktuelle Initiative: Doku verschlanken & Now‑Page einführen + +## 1) Vision (Was?) +Eine verlässliche, minimale Doku (≤5 Seiten) + ein stets aktueller One‑Pager für das laufende Vorhaben. +- In Scope: Start/Overview/API/Prod-HowTo/Now-Page +- Out of Scope: Vollständige Übersetzungen, alte Berichte/Prosa + +## 2) Why (Warum so?) +Zu viele, verstreute Dokumente erzeugen Drift und Entscheidungsunsicherheit. Ziel: Orientierung in <2 Min. wiederfinden. +- Erfolg messbar an: 1 Einstiegspunkt, 0 Broken Links, Validierung grün +- Dauerhaft relevante Entscheidungen künftig als ADR, aus Now‑Page verlinkt + +## 3) How (Wie umsetzen?) +- Behalten: `docs/index.md`, `overview/system-overview.md`, `how-to/*`, `api/README.md`, `now/current.md` +- Entfernen/Archivieren: `Tagebuch/`, alte Indizes +- CI beibehalten (Link‑Check optional), später Stale‑Check für Now‑Page ergänzen + +## 4) Plan (Was ist jetzt zu tun?) +- [ ] Index minimalisieren und nur auf Kernseiten verlinken +- [ ] System Overview anlegen und Ports/Health bündeln +- [ ] Now‑Page Template + current.md erstellen +- [ ] Alte Indizes und Tagebuch entfernen +- [ ] Validierung laufen lassen und etwaige Links reparieren +- [ ] Nächste Initiative vorbereiten: Git‑Flow & GitHub Actions Strategy + +## 5) Status & Nächster Fokus +- Status: active +- Nächster Fokus: Validierung ausführen und offene Link‑Themen bereinigen; danach Git‑Flow/GitHub‑Actions planen + +## 6) Referenzen +- Start lokal: `docs/how-to/start-local.md` +- Übersicht: `docs/overview/system-overview.md` +- Produktion/Nginx: `docs/how-to/deploy-proxmox-nginx.md` +- API: `docs/api/README.md` diff --git a/docs/overview/system-overview.md b/docs/overview/system-overview.md new file mode 100644 index 00000000..50d9d6e0 --- /dev/null +++ b/docs/overview/system-overview.md @@ -0,0 +1,79 @@ +--- +owner: project-owner +status: active +last_reviewed: 2025-10-15 +review_cycle: 90d +summary: Gesamtüberblick – Was ist vorhanden, wie funktioniert es, wie starte/deploye ich es. +--- + +# Meldestelle – System Overview (Kurz & vollständig) + +## Was ist vorhanden (Bausteine) +- Clients + - Web App (Port 4000) + - optional Desktop/noVNC (Port 6080) +- Gateway & Services + - API Gateway (Spring Cloud Gateway, Port 8081) + - Microservices: Members (8083), Horses (8084), Events (8085), Masterdata (8086), Ping (8082) +- Infrastruktur + - Postgres (5432), Redis (6379), Keycloak (8180), Consul (8500) +- Reverse Proxy (Produktion) + - Nginx auf Proxmox-Host + - vHosts: `meldestelle.yourdomain.com` (Web), `api.meldestelle.yourdomain.com` (API), `vnc.meldestelle.yourdomain.com` (VNC) + +## Wie funktioniert es (Ablauf & Verantwortungen) +- Einstieg nur über das API-Gateway (Security, CORS, Rate-Limits, Observability, Routing) +- Authentifizierung via Keycloak (OIDC/JWT) + - Web holt Token bei Keycloak → sendet Requests mit `Authorization: Bearer ` + - Gateway validiert JWT (JWKs), injiziert Kontext, routet an Services +- Service Discovery über Consul (Gateway ↔ Services) +- Persistenz: Services schreiben/lesen in Postgres; Redis optional für Cache +- Produktion: Öffentliche Zugriffe laufen über Nginx-vHosts → Gateway/Web/noVNC in Docker + +## Starten & Stoppen (lokal) +- Komplettes System: `make full-up` +- Nur Infrastruktur: `make infrastructure-up` +- Nur Backend (inkl. Gateway): `make services-up` +- Nur Clients (inkl. Web): `make clients-up` +- Stoppen: `make full-down` (bzw. `*-down`) +- Logs: `make full-logs` (bzw. `services-logs`, `infrastructure-logs`) + +## Health, URLs & Ports +- Web: `http://localhost:4000` → Health: `/health` +- Gateway: `http://localhost:8081` → Health: `/actuator/health` +- Services (dev): Ping 8082, Members 8083, Horses 8084, Events 8085, Masterdata 8086 +- Keycloak: `http://localhost:8180` +- Consul UI: `http://localhost:8500` +- Postgres: `localhost:5432` +- Redis: `localhost:6379` +- noVNC: `http://localhost:6080` + +## Auth-Flow (kurz) +1. Web ruft geschützte Seite → Redirect zu Keycloak `/authorize` +2. Login → Code → Token-Tausch (ID/Access Token) +3. Web ruft Gateway mit `Bearer ` auf → Gateway prüft Token → leitet an Service + +## Produktion (Proxmox/Nginx) +- Datei: `docs/proxmox-nginx/meldestelle.conf` +- vHosts: + - `meldestelle.yourdomain.com` → Web (`localhost:4000`) + - `api.meldestelle.yourdomain.com` → Gateway (`localhost:8081`) + - `vnc.meldestelle.yourdomain.com` → noVNC (`localhost:6080`) +- Health-Checks: + - `curl -i http://api.meldestelle.yourdomain.com/actuator/health` + - `curl -i http://meldestelle.yourdomain.com/health` + +## Konfiguration auf einen Blick (Defaults) +- Postgres: `POSTGRES_USER=meldestelle`, `POSTGRES_PASSWORD=meldestelle`, `POSTGRES_DB=meldestelle` +- Keycloak Admin: `KC_BOOTSTRAP_ADMIN_USERNAME=admin`, `KC_BOOTSTRAP_ADMIN_PASSWORD=admin` +- Gateway: Port 8081, Profil `dev` (per `SPRING_PROFILES_ACTIVE`) + +## Troubleshooting (Top 5) +- 401/403 am Gateway: Token fehlt/abgelaufen? Keycloak auf `http://localhost:8180` erreichbar? +- 502/Bad Gateway: Zielservice down? Logs prüfen (`make services-logs`). +- CORS im Browser: API über `api.meldestelle.*` bzw. `localhost:8081` aufrufen. +- Consul leer: Services nicht registriert → Services neu starten. +- Port-Konflikt: Belegte Ports mit `lsof -i :` prüfen, Prozesse beenden. + +## Diagramme (PlantUML) +Siehe `docs/architecture/c4/` – Context & Container sowie Login‑Sequenz. In CI zu SVG rendern. diff --git a/docs/reference/ports-and-urls.md b/docs/reference/ports-and-urls.md new file mode 100644 index 00000000..7dbf7995 --- /dev/null +++ b/docs/reference/ports-and-urls.md @@ -0,0 +1,35 @@ +--- +owner: project-maintainers +status: active +review_cycle: 180d +last_reviewed: 2025-10-15 +summary: Konsolidierte Übersicht aller relevanten lokalen Ports/URLs sowie der produktiven Domains (hinter Nginx). +--- + +# Referenz: Ports & URLs + +## Lokal (Standard-Setup) +- Web App: http://localhost:4000 +- API Gateway: http://localhost:8081 + - Health: http://localhost:8081/actuator/health +- Services (nur lokal): + - Ping Service: http://localhost:8082 + - Members Service: http://localhost:8083 + - Horses Service: http://localhost:8084 + - Events Service: http://localhost:8085 + - Masterdata Service: http://localhost:8086 +- Keycloak (Auth): http://localhost:8180 +- Consul (Service Discovery): http://localhost:8500 +- Postgres: localhost:5432 +- Redis: localhost:6379 +- noVNC (Desktop): http://localhost:6080 + +Hinweis: In Produktion sind die einzelnen Services (8082–8086) nicht öffentlich erreichbar. Alle API-Aufrufe laufen über das Gateway. + +## Produktion (hinter Nginx) +- Web App: http://meldestelle.yourdomain.com +- API Gateway: http://api.meldestelle.yourdomain.com + - Health: http://api.meldestelle.yourdomain.com/actuator/health +- VNC (optional): http://vnc.meldestelle.yourdomain.com + +Optional HTTPS: gleiche Hosts mit https://, sobald Zertifikate aktiv sind. diff --git a/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/config/GatewayConfig.kt b/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/config/GatewayConfig.kt index 059d3cfc..a868254e 100644 --- a/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/config/GatewayConfig.kt +++ b/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/config/GatewayConfig.kt @@ -20,7 +20,7 @@ import kotlin.uuid.Uuid */ /** - * Global Filter für Korrelations-IDs zur Request-Verfolgung. + * Global Filter für Correlations-IDs zur Request-Verfolgung. */ @Component class CorrelationIdFilter : GlobalFilter, Ordered { diff --git a/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/metrics/GatewayMetricsConfig.kt b/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/metrics/GatewayMetricsConfig.kt index bcc63946..cd23d72d 100644 --- a/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/metrics/GatewayMetricsConfig.kt +++ b/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/metrics/GatewayMetricsConfig.kt @@ -75,7 +75,7 @@ class GatewayMetricsConfig { * Bean für Request Duration Timer - entfernt um Konflikte mit dem WebFilter zu vermeiden. * Die Request-Zeiten werden automatisch im GatewayMetricsWebFilter erfasst. */ - // @Bean - Entfernt um Prometheus Meter-Konflikte zu vermeiden + // @Bean - entfernt, um Prometheus Meter-Konflikte zu vermeiden, // fun requestTimer(meterRegistry: MeterRegistry): Timer { ... } /** diff --git a/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/security/SecurityConfig.kt b/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/security/SecurityConfig.kt index 3ea2947d..24ab7580 100644 --- a/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/security/SecurityConfig.kt +++ b/infrastructure/gateway/src/main/kotlin/at/mocode/infrastructure/gateway/security/SecurityConfig.kt @@ -66,7 +66,7 @@ class SecurityConfig( */ @Bean fun reactiveJwtDecoder( - @Value("\${spring.security.oauth2.resourceserver.jwt.jwk-set-uri:}") jwkSetUri: String + @Value($$"${spring.security.oauth2.resourceserver.jwt.jwk-set-uri:}") jwkSetUri: String ): ReactiveJwtDecoder { return if (jwkSetUri.isNotBlank()) { try { @@ -114,7 +114,7 @@ class SecurityConfig( } /** - * Konfigurations-Properties für alle sicherheitsrelevanten Einstellungen des Gateways. + * Configurations-Properties für alle sicherheitsrelevanten Einstellungen des Gateways. */ @ConfigurationProperties(prefix = "gateway.security") data class GatewaySecurityProperties( diff --git a/logs/gateway.log b/logs/gateway.log index fcbfa561..d934a172 100644 --- a/logs/gateway.log +++ b/logs/gateway.log @@ -1,84 +1,192 @@ -2025-10-13 13:04:36.468 [background-preinit] INFO [] o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final -2025-10-13 13:04:36.510 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - Starting GatewayApplicationKt using Java 21.0.8 with PID 170664 (/home/stefan/WsMeldestelle/Meldestelle/infrastructure/gateway/build/classes/kotlin/main started by stefan in /home/stefan/WsMeldestelle/Meldestelle) -2025-10-13 13:04:36.511 [main] DEBUG [] a.m.i.gateway.GatewayApplicationKt - Running with Spring Boot v3.5.5, Spring v6.2.10 -2025-10-13 13:04:36.511 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - The following 1 profile is active: "dev" -2025-10-13 13:04:37.697 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode -2025-10-13 13:04:37.699 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode. -2025-10-13 13:04:37.732 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 19 ms. Found 0 Redis repository interfaces. -2025-10-13 13:04:37.986 [main] INFO [] o.s.cloud.context.scope.GenericScope - BeanFactory id=62ead487-39a4-3fc3-b0b8-d0378aec5250 -2025-10-13 13:04:39.373 [main] WARN [] o.s.b.w.r.c.AnnotationConfigReactiveWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.reactive.WebFluxSecurityConfiguration': Unsatisfied dependency expressed through method 'setSecurityWebFilterChains' parameter 0: Error creating bean with name 'securityWebFilterChain' defined in class path resource [at/mocode/infrastructure/gateway/security/SecurityConfig.class]: Failed to instantiate [org.springframework.security.web.server.SecurityWebFilterChain]: Factory method 'securityWebFilterChain' threw exception with message: No qualifying bean of type 'org.springframework.security.oauth2.jwt.ReactiveJwtDecoder' available -2025-10-13 13:04:39.400 [main] INFO [] o.s.b.a.l.ConditionEvaluationReportLogger - +2025-10-15 10:31:21.532 [background-preinit] INFO [] o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final +2025-10-15 10:31:21.556 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - Starting GatewayApplicationKt using Java 21.0.8 with PID 20139 (/home/stefan/WsMeldestelle/Meldestelle/infrastructure/gateway/build/classes/kotlin/main started by stefan in /home/stefan/WsMeldestelle/Meldestelle) +2025-10-15 10:31:21.556 [main] DEBUG [] a.m.i.gateway.GatewayApplicationKt - Running with Spring Boot v3.5.6, Spring v6.2.11 +2025-10-15 10:31:21.556 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - The following 1 profile is active: "dev" +2025-10-15 10:31:22.587 [main] INFO [] o.s.cloud.context.scope.GenericScope - BeanFactory id=4eb90187-1826-32ce-9dc7-fa80cb000915 +2025-10-15 10:31:24.216 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [After] +2025-10-15 10:31:24.216 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Before] +2025-10-15 10:31:24.217 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Between] +2025-10-15 10:31:24.217 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Cookie] +2025-10-15 10:31:24.217 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Header] +2025-10-15 10:31:24.217 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Host] +2025-10-15 10:31:24.217 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Method] +2025-10-15 10:31:24.217 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Path] +2025-10-15 10:31:24.217 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Query] +2025-10-15 10:31:24.217 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [ReadBody] +2025-10-15 10:31:24.217 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [RemoteAddr] +2025-10-15 10:31:24.217 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [XForwardedRemoteAddr] +2025-10-15 10:31:24.217 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Weight] +2025-10-15 10:31:24.217 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [CloudFoundryRouteService] +2025-10-15 10:31:24.751 [main] INFO [] o.s.b.a.e.web.EndpointLinksResolver - Exposing 6 endpoints beneath base path '/actuator' +2025-10-15 10:31:25.256 [main] WARN [] o.s.c.l.c.LoadBalancerCacheAutoConfiguration$LoadBalancerCaffeineWarnLogger - Spring Cloud LoadBalancer is currently working with the default cache. While this cache implementation is useful for development and tests, it's recommended to use Caffeine cache in production.You can switch to using Caffeine cache, by adding it and org.springframework.cache.caffeine.CaffeineCacheManager to the classpath. +2025-10-15 10:31:25.331 [catalogWatchTaskScheduler-1] ERROR [] o.s.c.c.discovery.ConsulCatalogWatch - Error watching Consul CatalogServices +com.ecwid.consul.transport.TransportException: org.apache.http.conn.HttpHostConnectException: Connect to localhost:8500 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Verbindungsaufbau abgelehnt + at com.ecwid.consul.transport.AbstractHttpTransport.executeRequest(AbstractHttpTransport.java:83) + at com.ecwid.consul.transport.AbstractHttpTransport.makeGetRequest(AbstractHttpTransport.java:36) + at com.ecwid.consul.v1.ConsulRawClient.makeGetRequest(ConsulRawClient.java:139) + at com.ecwid.consul.v1.catalog.CatalogConsulClient.getCatalogServices(CatalogConsulClient.java:143) + at com.ecwid.consul.v1.ConsulClient.getCatalogServices(ConsulClient.java:400) + at org.springframework.cloud.consul.discovery.ConsulCatalogWatch.catalogServicesWatch(ConsulCatalogWatch.java:131) + at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572) + at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:358) + at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) +Caused by: org.apache.http.conn.HttpHostConnectException: Connect to localhost:8500 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Verbindungsaufbau abgelehnt + at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:156) + at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376) + at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393) + at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) + at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186) + at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) + at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) + at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) + at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:72) + at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:221) + at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:165) + at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:140) + at com.ecwid.consul.transport.AbstractHttpTransport.executeRequest(AbstractHttpTransport.java:70) + ... 12 common frames omitted +Caused by: java.net.ConnectException: Verbindungsaufbau abgelehnt + at java.base/sun.nio.ch.Net.pollConnect(Native Method) + at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:682) + at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:542) + at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:592) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327) + at java.base/java.net.Socket.connect(Socket.java:751) + at org.apache.http.conn.socket.PlainConnectionSocketFactory.connectSocket(PlainConnectionSocketFactory.java:75) + at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142) + ... 24 common frames omitted +2025-10-15 10:31:25.350 [main] INFO [] o.s.b.w.e.netty.NettyWebServer - Netty started on port 8080 (http) +2025-10-15 10:31:25.352 [main] INFO [] o.s.c.c.s.ConsulServiceRegistry - Registering service with consul: NewService{id='meldestelle-8080-b001fd13-0b36-40e4-afae-566661a43ceb', name='meldestelle', tags=[], address='fedora', meta={secure=false}, port=8080, enableTagOverride=null, check=Check{script='null', dockerContainerID='null', shell='null', interval='10s', ttl='null', http='http://fedora:8080/actuator/health', method='null', header={}, tcp='null', timeout='null', deregisterCriticalServiceAfter='null', tlsSkipVerify=null, status='null', grpc='null', grpcUseTLS=null}, checks=null} +2025-10-15 10:31:25.361 [main] ERROR [] o.s.c.c.s.ConsulServiceRegistry - Error registering service with consul: NewService{id='meldestelle-8080-b001fd13-0b36-40e4-afae-566661a43ceb', name='meldestelle', tags=[], address='fedora', meta={secure=false}, port=8080, enableTagOverride=null, check=Check{script='null', dockerContainerID='null', shell='null', interval='10s', ttl='null', http='http://fedora:8080/actuator/health', method='null', header={}, tcp='null', timeout='null', deregisterCriticalServiceAfter='null', tlsSkipVerify=null, status='null', grpc='null', grpcUseTLS=null}, checks=null} +com.ecwid.consul.transport.TransportException: org.apache.http.conn.HttpHostConnectException: Connect to localhost:8500 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Verbindungsaufbau abgelehnt + at com.ecwid.consul.transport.AbstractHttpTransport.executeRequest(AbstractHttpTransport.java:83) + at com.ecwid.consul.transport.AbstractHttpTransport.makePutRequest(AbstractHttpTransport.java:49) + at com.ecwid.consul.v1.ConsulRawClient.makePutRequest(ConsulRawClient.java:163) + at com.ecwid.consul.v1.agent.AgentConsulClient.agentServiceRegister(AgentConsulClient.java:273) + at com.ecwid.consul.v1.ConsulClient.agentServiceRegister(ConsulClient.java:310) + at org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry.register(ConsulServiceRegistry.java:67) + at org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry.register(ConsulServiceRegistry.java:43) + at org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration.register(AbstractAutoServiceRegistration.java:264) + at org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistration.register(ConsulAutoServiceRegistration.java:80) + at org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration.start(AbstractAutoServiceRegistration.java:156) + at org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistration.start(ConsulAutoServiceRegistration.java:70) + at org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistrationListener.onApplicationEvent(ConsulAutoServiceRegistrationListener.java:60) + at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:185) + at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:178) + at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:156) + at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:454) + at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:387) + at org.springframework.boot.web.reactive.context.WebServerManager.start(WebServerManager.java:57) + at org.springframework.boot.web.reactive.context.WebServerStartStopLifecycle.start(WebServerStartStopLifecycle.java:41) + at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:405) + at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:394) + at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:586) + at java.base/java.lang.Iterable.forEach(Iterable.java:75) + at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:364) + at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:310) + at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:1006) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:630) + at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:66) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) + at at.mocode.infrastructure.gateway.GatewayApplicationKt.main(GatewayApplication.kt:13) +Caused by: org.apache.http.conn.HttpHostConnectException: Connect to localhost:8500 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Verbindungsaufbau abgelehnt + at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:156) + at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376) + at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393) + at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) + at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186) + at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) + at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) + at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) + at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:72) + at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:221) + at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:165) + at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:140) + at com.ecwid.consul.transport.AbstractHttpTransport.executeRequest(AbstractHttpTransport.java:70) + ... 33 common frames omitted +Caused by: java.net.ConnectException: Verbindungsaufbau abgelehnt + at java.base/sun.nio.ch.Net.pollConnect(Native Method) + at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:682) + at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:542) + at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:592) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327) + at java.base/java.net.Socket.connect(Socket.java:751) + at org.apache.http.conn.socket.PlainConnectionSocketFactory.connectSocket(PlainConnectionSocketFactory.java:75) + at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142) + ... 45 common frames omitted +2025-10-15 10:31:27.376 [main] WARN [] o.s.b.w.r.c.AnnotationConfigReactiveWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Failed to start bean 'webServerStartStop' +2025-10-15 10:31:27.401 [main] INFO [] o.s.b.a.l.ConditionEvaluationReportLogger - Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. -2025-10-13 13:04:39.429 [main] ERROR [] o.s.b.d.LoggingFailureAnalysisReporter - - -*************************** -APPLICATION FAILED TO START -*************************** - -Description: - -Parameter 0 of method setSecurityWebFilterChains in org.springframework.security.config.annotation.web.reactive.WebFluxSecurityConfiguration required a bean of type 'org.springframework.security.oauth2.jwt.ReactiveJwtDecoder' that could not be found. - - -Action: - -Consider defining a bean of type 'org.springframework.security.oauth2.jwt.ReactiveJwtDecoder' in your configuration. - -2025-10-13 13:05:28.345 [background-preinit] INFO [] o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final -2025-10-13 13:05:28.370 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - Starting GatewayApplicationKt using Java 21.0.8 with PID 171968 (/home/stefan/WsMeldestelle/Meldestelle/infrastructure/gateway/build/classes/kotlin/main started by stefan in /home/stefan/WsMeldestelle/Meldestelle) -2025-10-13 13:05:28.370 [main] DEBUG [] a.m.i.gateway.GatewayApplicationKt - Running with Spring Boot v3.5.5, Spring v6.2.10 -2025-10-13 13:05:28.370 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - The following 1 profile is active: "dev" -2025-10-13 13:05:29.337 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode -2025-10-13 13:05:29.339 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode. -2025-10-13 13:05:29.364 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 15 ms. Found 0 Redis repository interfaces. -2025-10-13 13:05:29.600 [main] INFO [] o.s.cloud.context.scope.GenericScope - BeanFactory id=62ead487-39a4-3fc3-b0b8-d0378aec5250 -2025-10-13 13:05:30.899 [main] WARN [] o.s.b.w.r.c.AnnotationConfigReactiveWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.reactive.WebFluxSecurityConfiguration': Unsatisfied dependency expressed through method 'setSecurityWebFilterChains' parameter 0: Error creating bean with name 'securityWebFilterChain' defined in class path resource [at/mocode/infrastructure/gateway/security/SecurityConfig.class]: Failed to instantiate [org.springframework.security.web.server.SecurityWebFilterChain]: Factory method 'securityWebFilterChain' threw exception with message: No qualifying bean of type 'org.springframework.security.oauth2.jwt.ReactiveJwtDecoder' available -2025-10-13 13:05:30.913 [main] INFO [] o.s.b.a.l.ConditionEvaluationReportLogger - - -Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. -2025-10-13 13:05:30.935 [main] ERROR [] o.s.b.d.LoggingFailureAnalysisReporter - - -*************************** -APPLICATION FAILED TO START -*************************** - -Description: - -Parameter 0 of method setSecurityWebFilterChains in org.springframework.security.config.annotation.web.reactive.WebFluxSecurityConfiguration required a bean of type 'org.springframework.security.oauth2.jwt.ReactiveJwtDecoder' that could not be found. - - -Action: - -Consider defining a bean of type 'org.springframework.security.oauth2.jwt.ReactiveJwtDecoder' in your configuration. - -2025-10-13 13:13:52.530 [background-preinit] INFO [] o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final -2025-10-13 13:13:52.555 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - Starting GatewayApplicationKt using Java 21.0.8 with PID 186912 (/home/stefan/WsMeldestelle/Meldestelle/infrastructure/gateway/build/classes/kotlin/main started by stefan in /home/stefan/WsMeldestelle/Meldestelle) -2025-10-13 13:13:52.556 [main] DEBUG [] a.m.i.gateway.GatewayApplicationKt - Running with Spring Boot v3.5.5, Spring v6.2.10 -2025-10-13 13:13:52.556 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - The following 1 profile is active: "dev" -2025-10-13 13:13:53.557 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode -2025-10-13 13:13:53.559 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode. -2025-10-13 13:13:53.582 [main] INFO [] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 11 ms. Found 0 Redis repository interfaces. -2025-10-13 13:13:53.818 [main] INFO [] o.s.cloud.context.scope.GenericScope - BeanFactory id=975b4235-9f71-3915-8b41-1672bffbac8a -2025-10-13 13:13:55.925 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [After] -2025-10-13 13:13:55.925 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Before] -2025-10-13 13:13:55.926 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Between] -2025-10-13 13:13:55.926 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Cookie] -2025-10-13 13:13:55.926 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Header] -2025-10-13 13:13:55.926 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Host] -2025-10-13 13:13:55.926 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Method] -2025-10-13 13:13:55.926 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Path] -2025-10-13 13:13:55.926 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Query] -2025-10-13 13:13:55.926 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [ReadBody] -2025-10-13 13:13:55.926 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [RemoteAddr] -2025-10-13 13:13:55.926 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [XForwardedRemoteAddr] -2025-10-13 13:13:55.926 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Weight] -2025-10-13 13:13:55.926 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [CloudFoundryRouteService] -2025-10-13 13:13:56.504 [main] INFO [] o.s.b.a.e.web.EndpointLinksResolver - Exposing 6 endpoints beneath base path '/actuator' -2025-10-13 13:13:57.065 [main] WARN [] o.s.c.l.c.LoadBalancerCacheAutoConfiguration$LoadBalancerCaffeineWarnLogger - Spring Cloud LoadBalancer is currently working with the default cache. While this cache implementation is useful for development and tests, it's recommended to use Caffeine cache in production.You can switch to using Caffeine cache, by adding it and org.springframework.cache.caffeine.CaffeineCacheManager to the classpath. -2025-10-13 13:13:57.150 [main] INFO [] o.s.b.w.e.netty.NettyWebServer - Netty started on port 8080 (http) -2025-10-13 13:13:57.153 [main] INFO [] o.s.c.c.s.ConsulServiceRegistry - Registering service with consul: NewService{id='meldestelle-8080-f1cacd41-0219-47ee-8249-1bbafe9ec3c8', name='meldestelle', tags=[], address='fedora', meta={secure=false}, port=8080, enableTagOverride=null, check=Check{script='null', dockerContainerID='null', shell='null', interval='10s', ttl='null', http='http://fedora:8080/actuator/health', method='null', header={}, tcp='null', timeout='null', deregisterCriticalServiceAfter='null', tlsSkipVerify=null, status='null', grpc='null', grpcUseTLS=null}, checks=null} -2025-10-13 13:13:57.286 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - Started GatewayApplicationKt in 5.08 seconds (process running for 5.695) -2025-10-13 13:14:38.993 [SpringApplicationShutdownHook] INFO [] o.s.b.w.e.netty.GracefulShutdown - Commencing graceful shutdown. Waiting for active requests to complete -2025-10-13 13:14:38.995 [netty-shutdown] INFO [] o.s.b.w.e.netty.GracefulShutdown - Graceful shutdown complete -2025-10-13 13:14:41.016 [SpringApplicationShutdownHook] INFO [] o.s.c.c.s.ConsulServiceRegistry - Deregistering service with consul: meldestelle-8080-f1cacd41-0219-47ee-8249-1bbafe9ec3c8 +2025-10-15 10:31:27.416 [main] ERROR [] o.s.boot.SpringApplication - Application run failed +org.springframework.context.ApplicationContextException: Failed to start bean 'webServerStartStop' + at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:408) + at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:394) + at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:586) + at java.base/java.lang.Iterable.forEach(Iterable.java:75) + at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:364) + at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:310) + at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:1006) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:630) + at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:66) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) + at at.mocode.infrastructure.gateway.GatewayApplicationKt.main(GatewayApplication.kt:13) +Caused by: com.ecwid.consul.transport.TransportException: org.apache.http.conn.HttpHostConnectException: Connect to localhost:8500 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Verbindungsaufbau abgelehnt + at com.ecwid.consul.transport.AbstractHttpTransport.executeRequest(AbstractHttpTransport.java:83) + at com.ecwid.consul.transport.AbstractHttpTransport.makePutRequest(AbstractHttpTransport.java:49) + at com.ecwid.consul.v1.ConsulRawClient.makePutRequest(ConsulRawClient.java:163) + at com.ecwid.consul.v1.agent.AgentConsulClient.agentServiceRegister(AgentConsulClient.java:273) + at com.ecwid.consul.v1.ConsulClient.agentServiceRegister(ConsulClient.java:310) + at org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry.register(ConsulServiceRegistry.java:67) + at org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry.register(ConsulServiceRegistry.java:43) + at org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration.register(AbstractAutoServiceRegistration.java:264) + at org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistration.register(ConsulAutoServiceRegistration.java:80) + at org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration.start(AbstractAutoServiceRegistration.java:156) + at org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistration.start(ConsulAutoServiceRegistration.java:70) + at org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistrationListener.onApplicationEvent(ConsulAutoServiceRegistrationListener.java:60) + at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:185) + at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:178) + at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:156) + at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:454) + at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:387) + at org.springframework.boot.web.reactive.context.WebServerManager.start(WebServerManager.java:57) + at org.springframework.boot.web.reactive.context.WebServerStartStopLifecycle.start(WebServerStartStopLifecycle.java:41) + at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:405) + ... 14 common frames omitted +Caused by: org.apache.http.conn.HttpHostConnectException: Connect to localhost:8500 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Verbindungsaufbau abgelehnt + at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:156) + at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376) + at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393) + at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) + at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186) + at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) + at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) + at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) + at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:72) + at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:221) + at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:165) + at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:140) + at com.ecwid.consul.transport.AbstractHttpTransport.executeRequest(AbstractHttpTransport.java:70) + ... 33 common frames omitted +Caused by: java.net.ConnectException: Verbindungsaufbau abgelehnt + at java.base/sun.nio.ch.Net.pollConnect(Native Method) + at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:682) + at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:542) + at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:592) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327) + at java.base/java.net.Socket.connect(Socket.java:751) + at org.apache.http.conn.socket.PlainConnectionSocketFactory.connectSocket(PlainConnectionSocketFactory.java:75) + at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142) + ... 45 common frames omitted diff --git a/scripts/validation/validate-docs.sh b/scripts/validation/validate-docs.sh index ffdc53ad..e8017f13 100755 --- a/scripts/validation/validate-docs.sh +++ b/scripts/validation/validate-docs.sh @@ -197,6 +197,39 @@ calculate_completeness_score() { fi } +# Optional external link check (lychee) +link_check() { + log_info "Running external link check (if 'lychee' is available)..." + ((CHECKS++)) + if command -v lychee &> /dev/null; then + # Allow common transient codes and skip localhost links + lychee --no-progress --accept 200,204,301,302,429 --exclude "localhost|127.0.0.1|yourdomain.com" docs/**/*.md || { + log_error "Lychee reported broken external links" + } + else + log_warning "'lychee' not found, skipping external link check" + fi +} + +# Optional PlantUML render check +plantuml_check() { + log_info "Rendering PlantUML diagrams to validate syntax (if 'plantuml' is available)..." + ((CHECKS++)) + if command -v plantuml &> /dev/null; then + # Render to SVG; failures should surface as non-zero exit + # Note: This may produce SVGs next to the .puml files in CI workspace + if compgen -G "docs/architecture/**/*.puml" > /dev/null; then + plantuml -tsvg -failfast2 docs/architecture/**/*.puml || log_error "PlantUML rendering failed" + elif compgen -G "docs/**/*.puml" > /dev/null; then + plantuml -tsvg -failfast2 docs/**/*.puml || log_error "PlantUML rendering failed" + else + log_warning "No .puml files found to render" + fi + else + log_warning "'plantuml' not found, skipping diagram rendering" + fi +} + # Main execution main() { echo "📚 Meldestelle Documentation Validation" @@ -208,6 +241,8 @@ main() { check_documentation_consistency check_api_documentation check_code_examples + link_check + plantuml_check calculate_completeness_score echo ""