From b35c4087a27dbba7047a61777952da677a6aab84 Mon Sep 17 00:00:00 2001 From: StefanMo <61204035+StefanMoCoAt@users.noreply.github.com> Date: Fri, 7 Nov 2025 12:26:33 +0100 Subject: [PATCH] =?UTF-8?q?Fix:=20Test-Commit=20f=C3=BCr=20VCS-Integration?= =?UTF-8?q?=20(MP-8)=20(#15)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * MP-8 OTHER Implementiere JWT-Authentifizierungs-Filter im Gateway * Fix(ci): Update upload-artifact action to v4 * Fix(ci): Add start command for Keycloak and failure logs * Fix(ci): Remove invalid 'command' property from Keycloak service * Fix(ci): Use KC_DEV_MODE env var to start Keycloak * Fix(ci): Keycloak service was removed from GitHub Actions services and replaced with a manual docker run step that starts Keycloak with the start-dev command. * dev(ci): vereinheitliche Keycloak auf 26.4.2; aktiviere Health im CI (MP-8) * Fix(ci): Stabilize Keycloak startup in integration tests via matrix - Add `dev-file` Keycloak variant to matrix for stability fallback. - Improve wait logic and health checks for Keycloak and Postgres. - Unify Keycloak version to 26.4.2 across codebase. - Add log dumps on failure. * Fix(ci): Die betroffene Datei docs/Visionen-Ideen/Infrastruktur-Strategie_DSGVO-Konformität.md endet aktuell mit genau einer leeren Zeile (Zeile 87). Das entspricht der Regel MD047 („Files should end with a single newline character“). Damit ist deine Korrektur korrekt. * Fix(ci): Repository-wide auto-fix for Markdown files was implemented with a GitHub Actions workflow and a local helper script. EditorConfig and markdownlint ignore files were added to ensure consistent formatting. Instructions for using the auto-fix both via GitHub Actions and locally were provided. * fix(gradle): build.gradle.kts jsBrowser testTask disabled * fix(gradle): build.gradle.kts jsBrowser testTask disabled * Fix(ci): Stabilize integration tests with Keycloak matrix build (MP-8) Introduces a matrix strategy (`keycloak_db: [postgres, dev-file]`) in the integration-tests workflow to mitigate flaky Keycloak starts when using the Postgres service container. - Adds a `dev-file` Keycloak variant for stability fallback. - Improves wait logic and health checks for Keycloak/Postgres. - Unifies Keycloak version to 26.4.2 across codebase (Dockerfile, Compose, ADR, README, tests). - Adds log dumps on failure in CI. - Ensures `KC_HEALTH_ENABLED=true` is set. - Updates related documentation (README, Schlachtplan). - Includes broader Docker SSoT cleanup (versions.toml as source, script updates, env file cleanup, validator hardening). This resolves recurring CI failures related to Keycloak startup and ensures required checks for PRs (#15) are reliable, while also improving overall Docker build consistency. * feat(docs, ci): Implement YouTrack SSoT strategy with Dokka sync (MP-8) - Add Dokka multi-module Gradle configuration and KDoc style guide. - Add GitHub Actions workflow (docs-kdoc-sync.yml) and Python script (youtrack-sync-kb.py) to sync Dokka GFM output to YouTrack KB. - Extend front-matter schema (bc, doc_type) and update relevant pages/stubs. - Adapt CI scripts (validate-frontmatter, check-docs-drift, ci-docs link ignore). - Update README.md to reference YouTrack KB. * feat(docs, ci): Implement YouTrack SSoT strategy with Dokka sync (MP-8) - Add Dokka multi-module Gradle configuration and KDoc style guide. - Add GitHub Actions workflow (docs-kdoc-sync.yml) and Python script (youtrack-sync-kb.py) to sync Dokka GFM output to YouTrack KB. - Extend front-matter schema (bc, doc_type) and update relevant pages/stubs. - Adapt CI scripts (validate-frontmatter, check-docs-drift, ci-docs link ignore). - Update README.md to reference YouTrack KB. * Fix(ci): Replace OpenAPI validator with Spectral Replaces the deprecated 'char0n/swagger-editor-validate' action, which failed due to sandbox issues in GitHub Actions, with the modern '@stoplight/spectral-cli'. This ensures robust OpenAPI specification validation without requiring a headless browser environment. The 'generate-api-docs' job now depends on the successful completion of the Spectral validation. Part of resolving CI failures for PR #15 (MP-8). * Fix(ci): Specify spectral:oas ruleset for OpenAPI validation (MP-8) * Fix(ci): Remove explicit ruleset argument for Spectral validation (MP-8) * Fix(ci): Added a .spectral.yaml file to fix Spectral linting errors. Corrected markdown lint issues in two documentation files. Updated README.md with a new guidelines section to fix link validation errors. * Fix(ci): Markdownlint errors were fixed by adding required blank lines. The Guidelines Validation error was resolved by updating the README.md link. The API Documentation Generator workflow was stabilized by updating paths, tasks, and validation steps. * Fix(ci): Alle vier fehlerhaften GitHub-Action-Prüfungen wurden behoben. Fehler in der OpenAPI-Spezifikation, Probleme mit der Markdown-Linting-Analyse und Validierungsfehler bei Querverweisen wurden korrigiert. Die README.md enthält nun alle erforderlichen Links zu den Richtlinien. * Fix(ci): Markdown linting errors in docs/api/README.md were fixed by specifying languages in fenced code blocks. OpenAPI specification errors in documentation.yaml were resolved by correcting example property types to strings. Cross-reference validation errors in README.md were fixed by adding the missing link to project-standards/coding-standards.md. * Fix(ci): Duplicate heading errors in docs/api/members-api.md were fixed. Cross-reference validation errors for docker-architecture.md were resolved. All originally reported issues passed validation successfully. * Fix(ci): The markdown heading levels in docs/api/members-api.md were corrected from h5 to h4 to fix linting errors. The missing cross-reference link from technology-guides/docker/docker-development.md to docker-overview.md was added. These fixes resolved the original validation and linting errors causing the process to fail. * Fix(ci): Duplicate heading warnings in docs/api/members-api.md were resolved. Cross-reference validation for docker-development.md to docker-architecture.md was fixed. A new unrelated warning about docker-production.md was identified but not addressed. * refactor(ci,docs): Simplify CI pipeline and migrate docs to YouTrack SSoT BREAKING CHANGE: Documentation structure radically simplified - Consolidate 9 GitHub Actions workflows into 1 main pipeline (ci-main.yml) - Remove redundant workflows: ci-docs, markdownlint-autofix, guidelines-validation, api-docs - Delete documentation migrated to YouTrack: api/, BCs/, Visionen-Ideen/, reference/, now/, overview/ - Keep only ADRs, C4 diagrams, and essential dev guides in repo - Update README.md with YouTrack KB links - Create new docs/README.md as documentation gateway - Relax markdown-lint config for pragmatic developer experience Kept workflows: - ssot-guard.yml (Docker SSoT validation) - docs-kdoc-sync.yml (KDoc → YouTrack sync) - integration-tests.yml (Integration tests) - deploy-proxmox.yml (Deployment) - youtrack-sync.yml (YouTrack integration) Related: MP-DOCS-001 * refactor(ci,docs): Simplify CI pipeline and migrate docs to YouTrack SSoT BREAKING CHANGE: Documentation structure radically simplified - Consolidate 9 GitHub Actions workflows into 1 main pipeline (ci-main.yml) - Remove redundant workflows: ci-docs, markdownlint-autofix, guidelines-validation, api-docs - Delete documentation migrated to YouTrack: api/, BCs/, Visionen-Ideen/, reference/, now/, overview/ - Keep only ADRs, C4 diagrams, and essential dev guides in repo - Update README.md with YouTrack KB links - Create new docs/README.md as documentation gateway - Relax markdown-lint config for pragmatic developer experience Kept workflows: - ssot-guard.yml (Docker SSoT validation) - docs-kdoc-sync.yml (KDoc → YouTrack sync) - integration-tests.yml (Integration tests) - deploy-proxmox.yml (Deployment) - youtrack-sync.yml (YouTrack integration) Related: MP-DOCS-001 * refactor(ci,docs): README.md und einige andere Dokumentationen überarbeitet. ports-and-urls.md hinzugefügt. Related: MP-DOCS-001 * refactor(ci,docs): Die Markdownlint-Fehler in README.md und docs/README.md wurden behoben, indem die Überschriftenebenen angepasst, überflüssige Satzzeichen am Ende entfernt und die notwendigen Leerzeilen um Überschriften, Listen, Tabellen und Codeblöcke eingefügt wurden. Das problematische Leerzeichen am Ende in docs/README.md wurde ebenfalls entfernt. Die Dateien entsprechen nun den vorgegebenen Markdownlint-Regeln und sollten die CI-Validierung bestehen. Related: MP-DOCS-001 * refactor(ci,docs): Docker guideline cross-references were fixed and normalized to lowercase labels. Validation scripts confirmed zero cross-reference warnings and consistent metadata. Documentation was updated with a changelog and enhanced README navigation. Related: MP-DOCS-001 * refactor(ci,docs): Docker guideline cross-references were fixed and normalized to lowercase labels. Validation scripts confirmed zero cross-reference warnings and consistent metadata. Documentation was updated with a changelog and enhanced README navigation. Related: MP-DOCS-001 * refactor(ci,docs): Dead links in docs/architecture/adr were fixed by updating URLs to stable sources and adding an ignore pattern for a placeholder link. Specific ADR files had their broken links replaced with valid ones. The markdown-link-check GitHub Action is expected to pass with zero dead links now. Related: MP-DOCS-001 * refactor(ci,docs): Links in ADR checked Related: MP-DOCS-001 * refactor(ci,docs): Links in ADR checked Related: MP-DOCS-001 * refactor(ci,docs): Markdown Regeln ausgebessert Related: MP-DOCS-001 * refactor(ci,docs): Markdown Regeln ausgebessert Related: MP-DOCS-001 * refactor(ci,docs): Markdown Regeln ausgebessert Related: MP-DOCS-001 * Chore: Rerun CI checks with updated branch protection rules --- .editorconfig | 32 +- .github/markdown-link-check.json | 3 + .github/workflows/api-docs.yml | 124 - .github/workflows/ci-docs.yml | 89 - .github/workflows/ci-main.yml | 108 + .github/workflows/deploy-proxmox.yml | 8 +- .github/workflows/docs-kdoc-sync.yml | 48 + .github/workflows/guidelines-validation.yml | 240 -- .github/workflows/integration-tests.yml | 191 +- .github/workflows/ssot-guard.yml | 139 + .junie/OPTIMIZATION-SUMMARY.md | 39 +- .junie/guidelines/README.md | 78 +- ...er-guideline-v3.0.1-archived-2025-09-15.md | 179 +- .../_templates/process-guide-template.md | 46 +- .../_templates/project-standard-template.md | 29 +- .../technology-guideline-template.md | 14 +- .junie/guidelines/master-guideline.md | 20 +- .../process-guides/trace-bullet-guideline.md | 27 +- .../architecture-principles.md | 31 +- .../project-standards/coding-standards.md | 22 +- .../documentation-standards.md | 37 +- .../project-standards/testing-standards.md | 22 +- .../docker/docker-architecture.md | 60 +- .../docker/docker-development.md | 30 +- .../docker/docker-monitoring.md | 43 +- .../docker/docker-overview.md | 16 +- .../docker/docker-production.md | 28 +- .../docker/docker-troubleshooting.md | 29 +- .../technology-guides/web-app-guideline.md | 34 +- .junie/scripts/check-docs-drift.sh | 13 + .junie/scripts/markdown-autofix.sh | 58 + .junie/scripts/validate-frontmatter.py | 3 + .junie/scripts/validate-links.sh | 10 +- .junie/scripts/youtrack-sync-kb.py | 185 + .markdownlint.yaml | 20 +- .markdownlintignore | 17 + .output.txt | 3102 ----------------- .spectral.yaml | 6 + Makefile | 51 +- README.md | 695 ++-- Schlachtplan.md | 214 +- build.gradle.kts | 74 + client/README.md | 1 - clients/shared/build.gradle.kts | 166 +- config/README.md | 11 +- config/ssl/README-de.md | 27 + core/README.md | 2 +- docker-compose.clients.yml | 186 +- docker-compose.clients.yml.optimized | 19 +- docker-compose.services.yml | 269 +- docker-compose.services.yml.optimized | 10 +- docker-compose.yml | 204 +- docker-compose.yml.optimized | 16 +- docker/build-args/clients.env | 11 +- docker/build-args/global.env | 22 +- docker/build-args/infrastructure.env | 5 +- docker/build-args/services.env | 5 +- docker/versions.toml | 26 +- docker/versions.toml.bak | 192 + .../infrastructure/auth-server/Dockerfile | 10 +- dockerfiles/infrastructure/gateway/Dockerfile | 11 +- .../infrastructure/keycloak/Dockerfile | 5 +- .../services/events-service/Dockerfile | 2 +- .../services/horses-service/Dockerfile | 2 +- .../services/masterdata-service/Dockerfile | 2 +- .../services/members-service/Dockerfile | 2 +- dockerfiles/services/ping-service/Dockerfile | 6 +- .../kotlin-multiplatform-web.Dockerfile | 2 +- .../templates/spring-boot-service.Dockerfile | 2 +- docs/.frontmatter.schema.json | 72 +- docs/README.md | 96 + ...frastruktur-Strategie_DSGVO-Konformität.md | 86 - docs/api/README.md | 400 --- docs/api/generated/events-openapi.json | 20 - docs/api/generated/horses-openapi.json | 20 - docs/api/generated/masterdata-openapi.json | 20 - docs/api/generated/members-openapi.json | 20 - docs/api/members-api.md | 633 ---- docs/architecture/adr/0000-adr-template-de.md | 11 +- .../adr/0001-modular-architecture-de.md | 27 +- .../adr/0002-domain-driven-design-de.md | 26 +- .../adr/0003-microservices-architecture-de.md | 44 +- .../adr/0004-event-driven-communication-de.md | 27 +- .../adr/0005-polyglot-persistence-de.md | 49 +- ...uthentication-authorization-keycloak-de.md | 31 +- .../adr/0007-api-gateway-pattern-de.md | 40 +- ...08-multiplatform-client-applications-de.md | 37 +- docs/how-to/branchschutz-und-pr-workflow.md | 14 +- docs/how-to/deploy-proxmox-nginx.md | 53 - docs/how-to/kdoc-style.md | 66 + docs/how-to/start-local.md | 35 +- docs/index.md | 26 - docs/now/README.md | 31 - docs/now/TEMPLATE.md | 39 - docs/now/current.md | 46 - docs/overview/system-overview.md | 79 - docs/proxmox-nginx/meldestelle.conf | 181 - docs/reference/ports-and-urls.md | 52 +- events/README.md | 2 +- gradle.properties | 7 +- gradle/libs.versions.toml | 7 + horses/README.md | 2 +- infrastructure/README-INFRASTRUCTURE.md | 36 +- infrastructure/README.md | 2 +- infrastructure/auth/README-INFRA-AUTH.md | 63 +- .../auth/KeycloakIntegrationTest.kt | 16 +- infrastructure/cache/README-INFRA-CACHE.md | 21 + infrastructure/cache/redis-cache/README.md | 6 + .../event-store/README-INFRA-EVENT-STORE.md | 76 +- .../event-store/redis-event-store/README.md | 5 +- infrastructure/gateway/CONFIGURATION.md | 81 +- .../gateway/README-INFRA-GATEWAY.md | 41 + .../main/resources/openapi/documentation.yaml | 16 +- .../messaging/README-INFRA-MESSAGING.md | 143 +- .../monitoring/README-INFRA-MONITORING.md | 1 + logs/gateway.log | 56 +- masterdata/README.md | 2 +- members/README.md | 2 +- platform/README-PLATFORM.md | 5 +- scripts/docker-build.sh | 87 +- scripts/docker-versions-update.sh | 46 +- scripts/generate-compose-files.sh | 65 +- scripts/git-hooks/pre-commit-ssot | 76 + scripts/setup-keycloak.sh | 5 +- scripts/validate-docker-consistency.sh | 486 ++- services/events/README-EVENTS.md | 16 + services/horses/README-HORSES.md | 28 + services/masterdata/README-MASTERDATA.md | 25 + services/members/README-MEMBERS.md | 12 + 129 files changed, 4016 insertions(+), 7131 deletions(-) delete mode 100644 .github/workflows/api-docs.yml delete mode 100644 .github/workflows/ci-docs.yml create mode 100644 .github/workflows/ci-main.yml create mode 100644 .github/workflows/docs-kdoc-sync.yml delete mode 100644 .github/workflows/guidelines-validation.yml create mode 100644 .github/workflows/ssot-guard.yml create mode 100644 .junie/scripts/markdown-autofix.sh create mode 100644 .junie/scripts/youtrack-sync-kb.py create mode 100644 .markdownlintignore delete mode 100644 .output.txt create mode 100644 .spectral.yaml delete mode 100644 client/README.md create mode 100644 docker/versions.toml.bak create mode 100644 docs/README.md delete mode 100644 docs/Visionen-Ideen/Infrastruktur-Strategie_DSGVO-Konformität.md delete mode 100644 docs/api/README.md delete mode 100644 docs/api/generated/events-openapi.json delete mode 100644 docs/api/generated/horses-openapi.json delete mode 100644 docs/api/generated/masterdata-openapi.json delete mode 100644 docs/api/generated/members-openapi.json delete mode 100644 docs/api/members-api.md delete mode 100644 docs/how-to/deploy-proxmox-nginx.md create mode 100644 docs/how-to/kdoc-style.md delete mode 100644 docs/index.md delete mode 100644 docs/now/README.md delete mode 100644 docs/now/TEMPLATE.md delete mode 100644 docs/now/current.md delete mode 100644 docs/overview/system-overview.md delete mode 100644 docs/proxmox-nginx/meldestelle.conf create mode 100644 scripts/git-hooks/pre-commit-ssot diff --git a/.editorconfig b/.editorconfig index 4c33eb86..0d212573 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,32 +1,14 @@ -# editorconfig.org -# Hilft, konsistente Code-Stile über verschiedene Editoren/IDEs hinweg beizubehalten. - -# Markiert dies als Root-Konfigurationsdatei root = true -[*] # Einstellungen für ALLE Dateien -# Zeichensatz -charset = utf-8 -# Zeilenende (Unix-Style) +[*] end_of_line = lf -# Fügt eine leere Zeile am Dateiende ein (gute Praxis) +charset = utf-8 insert_final_newline = true -# Entfernt Leerzeichen am Zeilenende trim_trailing_whitespace = true -# Einrückungsstil: Leerzeichen (statt Tabs) indent_style = space -# Einrückungsgröße: 4 Leerzeichen (Standard für Kotlin/Java) -indent_size = 4 +indent_size = 2 -# Spezifisch für Kotlin und Kotlin Script (.gradle.kts) Dateien -# Erbt die Einstellungen von [*] - 4 Leerzeichen passen zur Kotlin-Konvention. -# max_line_length = 120 # Könnte man hinzufügen, aber oft besser durch Linter/Formatter geregelt - -[*.xml] # Spezifisch für XML-Dateien -indent_size = 4 # Oft auch 4 Leerzeichen - -[*.{yml,yaml}] # Spezifisch für YAML-Dateien -indent_size = 2 # Hier sind 2 Leerzeichen eine häufige Konvention - -# [*.md] # Beispiel für Markdown, falls benötigt -# trim_trailing_whitespace = false # Bei Markdown oft sinnvoll, das Trimmen auszuschalten \ No newline at end of file +[*.md] +# In Markdown sind doppelte Leerzeichen am Zeilenende manchmal Absicht (harte Zeilenumbrüche). +# Daher hier kein generelles Trimmen; Markdownlint entscheidet im Zweifel. +trim_trailing_whitespace = false diff --git a/.github/markdown-link-check.json b/.github/markdown-link-check.json index 0c1914b2..9ad37bc7 100644 --- a/.github/markdown-link-check.json +++ b/.github/markdown-link-check.json @@ -11,6 +11,9 @@ }, { "pattern": "^https://127.0.0.1" + }, + { + "pattern": "^XXXX-filename\\.md$" } ], "replacementPatterns": [ diff --git a/.github/workflows/api-docs.yml b/.github/workflows/api-docs.yml deleted file mode 100644 index a74639a8..00000000 --- a/.github/workflows/api-docs.yml +++ /dev/null @@ -1,124 +0,0 @@ -name: API Documentation Generator - -on: - push: - branches: [ main, master ] - paths: - - 'api-gateway/src/jvmMain/resources/openapi/**' - - 'api-gateway/src/jvmMain/kotlin/at/mocode/gateway/routing/**' - - 'api-gateway/src/jvmMain/kotlin/at/mocode/gateway/config/OpenApiConfig.kt' - - 'api-gateway/build.gradle.kts' - - '.github/workflows/api-docs.yml' - pull_request: - branches: [ main, master ] - paths: - - 'api-gateway/src/jvmMain/resources/openapi/**' - - 'api-gateway/src/jvmMain/kotlin/at/mocode/gateway/routing/**' - - 'api-gateway/src/jvmMain/kotlin/at/mocode/gateway/config/OpenApiConfig.kt' - - 'api-gateway/build.gradle.kts' - - '.github/workflows/api-docs.yml' - workflow_dispatch: # Allow manual triggering - schedule: - - cron: '0 0 * * 0' # Run weekly on Sunday at midnight - -jobs: - validate-openapi: - name: Validate OpenAPI Specification - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Validate OpenAPI - uses: char0n/swagger-editor-validate@v1 - with: - definition-file: api-gateway/src/jvmMain/resources/openapi/documentation.yaml - - generate-api-docs: - name: Generate API Documentation - runs-on: ubuntu-latest - needs: validate-openapi - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up JDK 21 - uses: actions/setup-java@v4 - with: - java-version: '21' - distribution: 'temurin' - cache: gradle - - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - - name: Generate API Documentation - id: generate-docs - run: ./gradlew :api-gateway:generateApiDocs - - - name: Check for changes - id: git-check - run: | - if git diff --exit-code api-gateway/src/jvmMain/resources/static/docs/; then - echo "changed=false" >> $GITHUB_OUTPUT - else - echo "changed=true" >> $GITHUB_OUTPUT - fi - - - name: Commit and push if changed - if: steps.git-check.outputs.changed == 'true' - run: | - git config --local user.email "action@github.com" - git config --local user.name "GitHub Action" - git add api-gateway/src/jvmMain/resources/static/docs/ - git commit -m "Update API documentation [skip ci]" - git push - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Upload documentation artifact - uses: actions/upload-artifact@v4 - with: - name: api-documentation - path: api-gateway/src/jvmMain/resources/static/docs/ - retention-days: 7 - - - name: Notify on success - if: steps.git-check.outputs.changed == 'true' - run: | - echo "API documentation has been updated successfully." - # Uncomment and configure when notification service is available - # curl -X POST -H 'Content-type: application/json' --data '{"text":"API documentation has been updated successfully."}' ${{ secrets.SLACK_WEBHOOK_URL }} - - deploy-to-github-pages: - name: Deploy to GitHub Pages - runs-on: ubuntu-latest - needs: generate-api-docs - # Only deploy on main/master branch, not on PRs - if: github.event_name != 'pull_request' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master') - - steps: - - name: Download documentation artifact - uses: actions/download-artifact@v4 - with: - name: api-documentation - path: ./docs - - - name: Setup GitHub Pages - uses: actions/configure-pages@v4 - - - name: Upload GitHub Pages artifact - uses: actions/upload-pages-artifact@v3 - with: - path: ./docs - - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 - - - name: Output deployment URL - run: | - echo "Documentation deployed to ${{ steps.deployment.outputs.page_url }}" - # Uncomment and configure when notification service is available - # curl -X POST -H 'Content-type: application/json' --data '{"text":"API documentation deployed to ${{ steps.deployment.outputs.page_url }}"}' ${{ secrets.SLACK_WEBHOOK_URL }} diff --git a/.github/workflows/ci-docs.yml b/.github/workflows/ci-docs.yml deleted file mode 100644 index 0a8d3387..00000000 --- a/.github/workflows/ci-docs.yml +++ /dev/null @@ -1,89 +0,0 @@ -name: CI Docs -on: - pull_request: - paths: - - 'docs/**' - - '.junie/**' - - '.github/workflows/ci-docs.yml' - - '.markdownlint.yaml' - - '.vale.ini' - push: - branches: [ main ] - paths: - - 'docs/**' - - '.junie/**' - - '.github/workflows/ci-docs.yml' - - '.markdownlint.yaml' - - '.vale.ini' - -jobs: - docs: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Node (markdownlint) - uses: actions/setup-node@v4 - with: - node-version: '20' - - name: Install markdownlint - run: npm i -g markdownlint-cli - - name: Markdownlint - run: markdownlint 'docs/**/*.md' - - - name: Setup Vale - run: | - curl -fsSL https://install.goreleaser.com/github.com/errata-ai/vale.sh | sh - sudo mv bin/vale /usr/local/bin/vale - - name: Vale - run: vale docs/ - - - name: Link Checker - uses: lycheeverse/lychee-action@v1 - with: - args: --verbose --no-progress 'docs/**/*.md' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Front-Matter Schema Validate - run: | - pip install pyyaml jsonschema - python .junie/scripts/validate-frontmatter.py - - - name: Docs Drift Check - run: bash .junie/scripts/check-docs-drift.sh - - - name: Render PlantUML - run: bash .junie/scripts/render-plantuml.sh - - - name: Upload diagrams artifact - uses: actions/upload-artifact@v4 - with: - name: diagrams - path: build/diagrams - - - name: Validate YouTrack issues exist (optional) - if: ${{ env.YT_URL != '' && env.YT_TOKEN != '' }} - run: | - set -euo pipefail - KEYS=$(grep -Rho "[A-Z]\+-[0-9]\+" docs | sort -u || true) - if [ -z "$KEYS" ]; then - echo "No YouTrack keys found in docs." - exit 0 - fi - echo "Prüfe Keys:" $KEYS - fail=0 - for k in $KEYS; do - code=$(curl -s -o /dev/null -w "%{http_code}" \ - -H "Authorization: Bearer $YT_TOKEN" \ - -H "Accept: application/json" \ - "$YT_URL/api/issues/$k?fields=idReadable") - if [ "$code" != "200" ]; then - echo "[YT] Issue nicht gefunden: $k (HTTP $code)"; fail=1; - fi - done - exit $fail - env: - YT_URL: ${{ secrets.YT_URL }} - YT_TOKEN: ${{ secrets.YT_TOKEN }} diff --git a/.github/workflows/ci-main.yml b/.github/workflows/ci-main.yml new file mode 100644 index 00000000..8fec72f9 --- /dev/null +++ b/.github/workflows/ci-main.yml @@ -0,0 +1,108 @@ +name: CI - Main Pipeline + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main, develop ] + +jobs: + # ======================================== + # 1. Docker SSoT (bleibt wie ist) + # ======================================== + docker-ssot: + name: Docker SSoT Validation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: Validate Docker SSoT (compat mode) + run: | + bash scripts/docker-versions-update.sh sync + bash scripts/generate-compose-files.sh all development + bash scripts/validate-docker-consistency.sh all + + - name: Validate Docker SSoT (envless mode) + run: | + DOCKER_SSOT_MODE=envless bash scripts/generate-compose-files.sh all development + DOCKER_SSOT_MODE=envless bash scripts/validate-docker-consistency.sh all + + # ======================================== + # 2. OpenAPI Validation (nur Lint) + # ======================================== + validate-openapi: + name: Validate OpenAPI Specs + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: '20' + + - name: Install Spectral + run: npm install -g @stoplight/spectral-cli + + - name: Validate OpenAPI + run: | + spectral lint infrastructure/gateway/src/main/resources/openapi/documentation.yaml \ + --ruleset .spectral.yaml \ + --fail-severity error + + # ======================================== + # 3. Markdown Docs (nur kritische) + # ======================================== + validate-docs: + name: Validate Essential Docs + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: Lint Critical Markdown + uses: DavidAnson/markdownlint-cli2-action@v20 + with: + globs: | + README.md + docs/README.md + docs/architecture/adr/**/*.md + docs/how-to/start-local.md + + - name: Check Links in ADRs + uses: gaurav-nelson/github-action-markdown-link-check@v1 + with: + config-file: '.github/markdown-link-check.json' + folder-path: 'docs/architecture/adr/' + use-quiet-mode: 'yes' + + # ======================================== + # 4. Build & Test + # ======================================== + build-test: + name: Build and Test + runs-on: ubuntu-latest + needs: [ docker-ssot, validate-openapi ] + + steps: + - uses: actions/checkout@v5 + + - name: Setup JDK 21 + uses: actions/setup-java@v5 + with: + java-version: '21' + distribution: 'temurin' + cache: gradle + + - name: Build + run: ./gradlew build -x test + + - name: Test + run: ./gradlew test + + - name: Upload OpenAPI Specs (Artifact) + uses: actions/upload-artifact@v5 + with: + name: openapi-specs + path: docs/api/generated/*.json + retention-days: 30 + continue-on-error: true diff --git a/.github/workflows/deploy-proxmox.yml b/.github/workflows/deploy-proxmox.yml index f7fcb015..1f09f0af 100644 --- a/.github/workflows/deploy-proxmox.yml +++ b/.github/workflows/deploy-proxmox.yml @@ -20,16 +20,16 @@ jobs: steps: - name: Checkout Code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Set up JDK 21 - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: java-version: '21' distribution: 'temurin' - name: Cache Gradle dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ~/.gradle/caches @@ -57,7 +57,7 @@ jobs: steps: - name: Checkout Code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup SSH Key uses: webfactory/ssh-agent@v0.8.0 diff --git a/.github/workflows/docs-kdoc-sync.yml b/.github/workflows/docs-kdoc-sync.yml new file mode 100644 index 00000000..a932719e --- /dev/null +++ b/.github/workflows/docs-kdoc-sync.yml @@ -0,0 +1,48 @@ +name: KDoc → YouTrack KB Sync + +on: + workflow_dispatch: + inputs: + kb_root_title: + description: "Root-Titel der YouTrack KB (z. B. 'API & Entwicklerdoku')" + required: true + default: "API & Entwicklerdoku" + bc_root: + description: "Ordner unterhalb des KB-Roots für BCs (z. B. 'BCs')" + required: false + default: "BCs" + +jobs: + kdoc-sync: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Setup JDK 21 + uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: '21' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v5 + + - name: Build Dokka (GFM) + run: ./gradlew --no-daemon dokkaGfmAll + + - name: Python deps for YouTrack sync + run: | + python -m pip install --upgrade pip + pip install requests pyyaml + + - name: Sync KDoc Markdown to YouTrack KB + env: + YT_URL: ${{ secrets.YT_URL }} + YT_TOKEN: ${{ secrets.YT_TOKEN }} + KB_ROOT_TITLE: ${{ github.event.inputs.kb_root_title }} + KB_BC_ROOT: ${{ github.event.inputs.bc_root }} + run: | + python .junie/scripts/youtrack-sync-kb.py --src build/dokka/gfm diff --git a/.github/workflows/guidelines-validation.yml b/.github/workflows/guidelines-validation.yml deleted file mode 100644 index 13c8de88..00000000 --- a/.github/workflows/guidelines-validation.yml +++ /dev/null @@ -1,240 +0,0 @@ -name: Guidelines Validation - -on: - push: - paths: - - '.junie/**/*.md' - - '.junie/**/*.json' - - '.junie/scripts/**' - pull_request: - paths: - - '.junie/**/*.md' - - '.junie/**/*.json' - - '.junie/scripts/**' - -jobs: - validate-guidelines: - runs-on: ubuntu-latest - name: Validate Guidelines Structure and Links - - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Setup Python for YAML validation - uses: actions/setup-python@v4 - with: - python-version: '3.11' - - - name: Install Required Tools - run: | - sudo apt-get update - sudo apt-get install -y jq yamllint curl - pip install pyyaml jsonschema - - - name: Validate YAML Headers in Guidelines - run: | - echo "🔍 Validiere YAML-Header in Guidelines..." - exit_code=0 - find .junie/guidelines -name "*.md" -not -path "*/_archived/*" | while read file; do - echo " Prüfe: $(basename $file)" - # YAML-Header extrahieren (zwischen ersten beiden --- Zeilen) - sed -n '/^---$/,/^---$/p' "$file" | head -n -1 | tail -n +2 > temp.yaml - if [[ -s temp.yaml ]]; then - # Python-basierte YAML-Validierung (robuster als yamllint) - python3 -c "import yaml, sys; yaml.safe_load(open('temp.yaml', 'r')); print(' ✅ YAML-Syntax OK')" || { - echo "❌ YAML-Syntax-Fehler in $file" - exit_code=1 - } - else - echo " ⚠️ Kein YAML-Header in $file" - fi - rm -f temp.yaml - done - if [[ $exit_code -ne 0 ]]; then - exit 1 - fi - - - name: Validate Cross-References and Links - run: | - echo "🔗 Validiere Cross-Referenzen und Links..." - chmod +x .junie/scripts/validate-links.sh - ./.junie/scripts/validate-links.sh - - - name: Check Versions Consistency - run: | - echo "📊 Prüfe Versions-Konsistenz..." - # Alle last_updated Daten sammeln und auf Konsistenz prüfen - echo "Aktuelle Versions-Verteilung:" - find .junie/guidelines -name "*.md" -not -path "*/_archived/*" -exec grep -H "last_updated:" {} \; | \ - cut -d'"' -f2 | sort | uniq -c | sort -rn - - # Überprüfe guideline_type Konsistenz - echo -e "\nGuideline-Types:" - find .junie/guidelines -name "*.md" -not -path "*/_archived/*" -exec grep -H "guideline_type:" {} \; | \ - cut -d'"' -f2 | sort | uniq -c | sort -rn - - - name: Validate Template Structure and Metadata - run: | - echo "📋 Prüfe Template-Konsistenz und Metadaten..." - exit_code=0 - find .junie/guidelines -name "*.md" -not -path "*/_archived/*" -not -name "README.md" | while read file; do - echo " Validiere: $(basename $file)" - - # Prüfe erforderliche YAML-Felder - if ! grep -q "guideline_type:" "$file"; then - echo " ❌ Fehlt guideline_type in $file" - exit_code=1 - fi - if ! grep -q "ai_context:" "$file"; then - echo " ❌ Fehlt ai_context in $file" - exit_code=1 - fi - if ! grep -q "last_updated:" "$file"; then - echo " ❌ Fehlt last_updated in $file" - exit_code=1 - fi - - echo " ✅ Metadaten komplett" - done - if [[ $exit_code -ne 0 ]]; then - exit 1 - fi - - - name: Validate JSON Configuration Files - run: | - echo "🔧 Validiere JSON-Konfigurationsdateien..." - for json_file in .junie/guidelines/_meta/*.json; do - if [[ -f "$json_file" ]]; then - echo " Prüfe: $(basename $json_file)" - jq empty "$json_file" || { - echo "❌ JSON-Syntax-Fehler in $json_file" - exit 1 - } - echo " ✅ $(basename $json_file) - JSON-Syntax OK" - fi - done - - - name: Check Script Executability and Permissions - run: | - echo "⚙️ Prüfe Script-Berechtigungen..." - for script in .junie/scripts/*.sh; do - if [[ -f "$script" ]]; then - echo " Prüfe: $(basename $script)" - if [[ -x "$script" ]]; then - echo " ✅ $(basename $script) - Ausführbar" - else - echo " ❌ $(basename $script) - Nicht ausführbar" - exit 1 - fi - fi - done - - - name: Generate Validation Report - if: always() - run: | - echo "📈 Erstelle Validierungs-Report..." - cat > guidelines-validation-report.md << 'EOF' - # Guidelines Validation Report - - **Datum:** $(date) - **Commit:** ${{ github.sha }} - **Branch:** ${{ github.ref_name }} - - ## Zusammenfassung - - ✅ YAML-Syntax validiert - - ✅ Cross-Referenzen geprüft - - ✅ Versions-Konsistenz überprüft - - ✅ Template-Struktur validiert - - ✅ JSON-Konfiguration validiert - - ✅ Script-Berechtigungen geprüft - - ## Statistiken - - **Aktive Guidelines:** $(find .junie/guidelines -name "*.md" -not -path "*/_archived/*" | wc -l) - - **Archivierte Guidelines:** $(find .junie/guidelines/_archived -name "*.md" 2>/dev/null | wc -l) - - **Templates verfügbar:** $(find .junie/guidelines/_templates -name "*.md" 2>/dev/null | wc -l) - - **Validierungs-Scripts:** $(find .junie/scripts -name "*.sh" 2>/dev/null | wc -l) - - ## Letzte Änderungen - ``` - $(git log --oneline -n 5 -- .junie/) - ``` - EOF - - - name: Comment PR with Validation Results - if: github.event_name == 'pull_request' - uses: actions/github-script@v7 - with: - script: | - const fs = require('fs'); - if (fs.existsSync('guidelines-validation-report.md')) { - const report = fs.readFileSync('guidelines-validation-report.md', 'utf8'); - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: '## 📋 Guidelines Validation Report\n\n' + report - }); - } - - advanced-link-check: - runs-on: ubuntu-latest - name: Advanced Link and Structure Validation - needs: validate-guidelines - - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Setup Node.js for markdown-link-check - uses: actions/setup-node@v4 - with: - node-version: '18' - - - name: Install Link Checker - run: | - npm install -g markdown-link-check@3.11.2 - - - name: Create Link Check Configuration - run: | - cat > .junie/link-check-config.json << 'EOF' - { - "ignorePatterns": [ - { - "pattern": "^http://localhost" - }, - { - "pattern": "^https://localhost" - }, - { - "pattern": "^http://127.0.0.1" - } - ], - "replacementPatterns": [], - "httpHeaders": [], - "timeout": "10s", - "retryOn429": true, - "retryCount": 3, - "fallbackRetryDelay": "30s", - "aliveStatusCodes": [200, 206] - } - EOF - - - name: Check Internal Markdown Links - run: | - echo "🔍 Erweiterte Link-Validierung..." - exit_code=0 - find .junie/guidelines -name "*.md" | while read file; do - echo "Prüfe Links in: $(basename $file)" - if ! markdown-link-check "$file" --config .junie/link-check-config.json --quiet; then - echo "❌ Link-Fehler in $file" - exit_code=1 - else - echo "✅ Links OK in $(basename $file)" - fi - done - if [[ $exit_code -ne 0 ]]; then - echo "❌ Link-Validierung fehlgeschlagen" - exit 1 - fi - echo "✅ Alle Links validiert" diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index b4a0e05e..afb91db5 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -9,6 +9,12 @@ on: jobs: integration-tests: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + keycloak_db: [postgres, dev-file] + env: + KEYCLOAK_VERSION: "26.4.2" services: postgres: @@ -20,10 +26,11 @@ jobs: ports: - 5432:5432 options: >- - --health-cmd pg_isready + --health-cmd "pg_isready -U meldestelle -d $${POSTGRES_DB}" --health-interval 10s --health-timeout 5s - --health-retries 5 + --health-retries 12 + --health-start-period 20s redis: image: redis:7-alpine @@ -35,23 +42,6 @@ jobs: --health-timeout 5s --health-retries 5 - keycloak: - image: quay.io/keycloak/keycloak:23.0 - env: - KEYCLOAK_ADMIN: admin - KEYCLOAK_ADMIN_PASSWORD: admin - KC_DB: postgres - KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak - KC_DB_USERNAME: meldestelle - KC_DB_PASSWORD: meldestelle - ports: - - 8180:8080 - options: >- - --health-cmd "curl --fail http://localhost:8080/health/ready || exit 1" - --health-interval 10s - --health-timeout 5s - --health-retries 5 - --health-start-period 30s zookeeper: image: confluentinc/cp-zookeeper:7.5.0 @@ -96,45 +86,134 @@ jobs: --health-start-period 10s steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - - name: Set up JDK 21 - uses: actions/setup-java@v3 - with: - java-version: 21 - distribution: 'temurin' - cache: 'gradle' + - name: Set up JDK 21 + uses: actions/setup-java@v5 + with: + java-version: 21 + distribution: 'temurin' + cache: 'gradle' - - name: Setup Gradle - uses: gradle/gradle-build-action@v2 - with: - gradle-version: wrapper - cache-read-only: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/develop' }} - cache-overwrite-existing: true - gradle-home-cache-includes: | - caches - notifications - jdks - wrapper + - name: Setup Gradle (modern) + uses: gradle/actions/setup-gradle@v5 - - name: Grant execute permission for gradlew - run: chmod +x gradlew + - name: Wait for Postgres to be ready (pg_isready in service network) + if: ${{ matrix.keycloak_db == 'postgres' }} + run: | + echo "Waiting for Postgres..." + for i in {1..40}; do + if docker run --rm --network ${{ job.services.postgres.network }} \ + postgres:16-alpine pg_isready -h postgres -p 5432 -U meldestelle -d meldestelle; then + echo "Postgres is ready"; break; fi; echo -n "."; sleep 3; done - - name: Run integration tests - run: ./gradlew integrationTest --no-daemon --parallel - env: - # Environment variables for Redis connection - REDIS_HOST: localhost - REDIS_PORT: 6379 - # Spring profile for integration tests - SPRING_PROFILES_ACTIVE: integration-test + - name: Start Keycloak with Postgres (dev) and wait for readiness + if: ${{ matrix.keycloak_db == 'postgres' }} + run: | + set -euo pipefail + echo "Starting Keycloak (DB=postgres)..." + docker run -d --name keycloak \ + --network ${{ job.services.postgres.network }} \ + -p 8180:8080 \ + -e KC_BOOTSTRAP_ADMIN_USERNAME=admin \ + -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \ + -e KC_DB=postgres \ + -e KC_DB_URL=jdbc:postgresql://postgres:5432/meldestelle \ + -e KC_DB_USERNAME=meldestelle \ + -e KC_DB_PASSWORD=meldestelle \ + -e KC_HEALTH_ENABLED=true \ + -e JAVA_OPTS="-Xms256m -Xmx1024m -XX:MaxRAMPercentage=60" \ + quay.io/keycloak/keycloak:${{ env.KEYCLOAK_VERSION }} \ + start-dev - - name: Upload test reports - uses: actions/upload-artifact@v3 - if: always() - with: - name: integration-test-reports - path: | - **/build/reports/tests/integrationTest/ - **/build/test-results/integrationTest/ - retention-days: 7 + echo "Giving Keycloak 30s to initialize..."; sleep 30 + + wait_for() { + local url="$1"; local label="$2"; local timeout="${3:-180}"; local interval="${4:-5}" + echo "Waiting for $label ($url) ..." + if ! timeout ${timeout}s bash -c 'until curl -fsS --output /dev/null '"$url"'; do echo -n "."; sleep '"$interval"'; done'; then + echo "\n[WAIT] Timeout on $url" + return 1 + fi + echo "\n[WAIT] $label is up" + } + + if ! wait_for http://localhost:8180/ "root" 180 5; then + docker logs --tail=200 keycloak || true + exit 1 + fi + if ! wait_for http://localhost:8180/health "health" 180 5; then + echo "[INFO] /health nicht erreichbar – versuche /q/health (Quarkus default)" + wait_for http://localhost:8180/q/health "q-health" 180 5 || true + fi + wait_for http://localhost:8180/health/ready "health-ready" 300 5 || true + wait_for http://localhost:8180/admin/master/console/ "admin-console" 300 5 || (docker logs --tail=400 keycloak && exit 1) + + - name: Start Keycloak with dev-file (no Postgres) and wait for readiness + if: ${{ matrix.keycloak_db == 'dev-file' }} + run: | + set -euo pipefail + echo "Starting Keycloak (DB=dev-file, no Postgres)..." + docker run -d --name keycloak \ + -p 8180:8080 \ + -e KC_BOOTSTRAP_ADMIN_USERNAME=admin \ + -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \ + -e KC_DB=dev-file \ + -e KC_HEALTH_ENABLED=true \ + -e JAVA_OPTS="-Xms256m -Xmx1024m -XX:MaxRAMPercentage=60" \ + quay.io/keycloak/keycloak:${{ env.KEYCLOAK_VERSION }} \ + start-dev + + echo "Giving Keycloak 20s to initialize..."; sleep 20 + + wait_for() { + local url="$1"; local label="$2"; local timeout="${3:-180}"; local interval="${4:-5}" + echo "Waiting for $label ($url) ..." + if ! timeout ${timeout}s bash -c 'until curl -fsS --output /dev/null '"$url"'; do echo -n "."; sleep '"$interval"'; done'; then + echo "\n[WAIT] Timeout on $url" + return 1 + fi + echo "\n[WAIT] $label is up" + } + + if ! wait_for http://localhost:8180/ "root" 180 5; then + docker logs --tail=200 keycloak || true + exit 1 + fi + if ! wait_for http://localhost:8180/health "health" 180 5; then + echo "[INFO] /health nicht erreichbar – versuche /q/health (Quarkus default)" + wait_for http://localhost:8180/q/health "q-health" 180 5 || true + fi + wait_for http://localhost:8180/health/ready "health-ready" 300 5 || true + wait_for http://localhost:8180/admin/master/console/ "admin-console" 300 5 || (docker logs --tail=400 keycloak && exit 1) + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Run integration tests + run: ./gradlew integrationTest --no-daemon --parallel + env: + # Environment variables for Redis connection + REDIS_HOST: localhost + REDIS_PORT: 6379 + # Keycloak base URL for integration tests (manual container) + KEYCLOAK_AUTH_SERVER_URL: http://localhost:8180 + # Spring profile for integration tests + SPRING_PROFILES_ACTIVE: integration-test + + - name: Upload test reports + uses: actions/upload-artifact@v5 + if: always() + with: + name: integration-test-reports + path: | + **/build/reports/tests/integrationTest/ + **/build/test-results/integrationTest/ + retention-days: 7 + + - name: Dump service logs (Keycloak, Postgres) + if: always() + run: | + echo "=== Docker ps ===" && docker ps -a || true + echo "=== Keycloak logs (tail) ===" && docker logs --tail=400 keycloak || true + echo "=== Postgres logs (tail) ===" && docker logs --tail=200 $(docker ps -a --filter "name=postgres" --format "{{.ID}}") || true diff --git a/.github/workflows/ssot-guard.yml b/.github/workflows/ssot-guard.yml new file mode 100644 index 00000000..86a1824a --- /dev/null +++ b/.github/workflows/ssot-guard.yml @@ -0,0 +1,139 @@ +name: Docker SSoT Guard + +on: + push: + branches: [ main ] + paths: + - 'docker/**' + - 'dockerfiles/**' + - 'docker-compose*.yml*' + - 'scripts/**' + - '.github/workflows/ssot-guard.yml' + pull_request: + paths: + - 'docker/**' + - 'dockerfiles/**' + - 'docker-compose*.yml*' + - 'scripts/**' + - '.github/workflows/ssot-guard.yml' + +jobs: + ssot-guard: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Show environment + run: | + bash --version + docker --version || true + compose_ver=$(docker compose version 2>/dev/null || true); echo "docker compose: $compose_ver" + + - name: Sync versions to env files + run: bash scripts/docker-versions-update.sh sync + + - name: Generate docker-compose files (all) + run: bash scripts/generate-compose-files.sh all development + + - name: Validate Docker SSoT consistency + run: bash scripts/validate-docker-consistency.sh all + + - name: Check drift of generated artifacts (ignore timestamps) + run: | + set -euo pipefail + # Gather modified files after sync+generate + CHANGED=$(git diff --name-only) + if [ -z "$CHANGED" ]; then + echo "No drift detected." + exit 0 + fi + echo "Changed files:" $CHANGED + fail=0 + for f in $CHANGED; do + # Inspect actual content changes but ignore volatile timestamp/comment lines + # Ignore lines starting with + or - that are exactly the timestamp markers we generate + DIFF_FILTERED=$(git diff --unified=0 -- "$f" \ + | awk 'BEGIN{show=0} { \ + if ($0 ~ /^\+\+\+|^---|^@@/) { next } \ + if ($0 ~ /^[+-]# (Generated:|Last updated:)/) { next } \ + if ($0 ~ /^[+-]#\s*Generated from docker\/versions.toml/) { next } \ + if ($0 ~ /^[+-]#\s*Environment:/) { next } \ + if ($0 ~ /^[+-]#\s*Source:/) { next } \ + if ($0 ~ /^[+-]$/) { next } \ + if ($0 ~ /^[+-]/) { print $0 } \ + }') + if [ -n "$DIFF_FILTERED" ]; then + echo "SSoT drift detected in $f:"; + echo "$DIFF_FILTERED"; + fail=1; + fi + done + if [ $fail -ne 0 ]; then + echo "\nERROR: Generated artifacts differ from repository (beyond timestamps)." + echo "Run:" + echo " bash scripts/docker-versions-update.sh sync" + echo " bash scripts/generate-compose-files.sh all" + echo "and commit the changes." + exit 1 + fi + echo "No SSoT drift (ignoring timestamps)." + + + ssot-guard-envless: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Show environment + run: | + bash --version + docker --version || true + compose_ver=$(docker compose version 2>/dev/null || true); echo "docker compose: $compose_ver" + + - name: Generate docker-compose files (all) + run: bash scripts/generate-compose-files.sh all development + + - name: Validate Docker SSoT consistency (envless) + run: DOCKER_SSOT_MODE=envless bash scripts/validate-docker-consistency.sh all + + - name: Check drift of generated artifacts (ignore timestamps) + run: | + set -euo pipefail + CHANGED=$(git diff --name-only) + if [ -z "$CHANGED" ]; then + echo "No drift detected." + exit 0 + fi + echo "Changed files:" $CHANGED + fail=0 + for f in $CHANGED; do + DIFF_FILTERED=$(git diff --unified=0 -- "$f" \ + | awk 'BEGIN{show=0} { \ + if ($0 ~ /^\+\+\+|^---|^@@/) { next } \ + if ($0 ~ /^[+-]# (Generated:|Last updated:)/) { next } \ + if ($0 ~ /^[+-]#\s*Generated from docker\/versions.toml/) { next } \ + if ($0 ~ /^[+-]#\s*Environment:/) { next } \ + if ($0 ~ /^[+-]#\s*Source:/) { next } \ + if ($0 ~ /^[+-]$/) { next } \ + if ($0 ~ /^[+-]/) { print $0 } \ + }') + if [ -n "$DIFF_FILTERED" ]; then + echo "SSoT drift detected in $f:"; + echo "$DIFF_FILTERED"; + fail=1; + fi + done + if [ $fail -ne 0 ]; then + echo "\nERROR: Generated artifacts differ from repository (beyond timestamps)." + echo "Run:" + echo " DOCKER_SSOT_MODE=envless bash scripts/generate-compose-files.sh all" + echo "and commit the changes." + exit 1 + fi + echo "No SSoT drift (ignoring timestamps)." diff --git a/.junie/OPTIMIZATION-SUMMARY.md b/.junie/OPTIMIZATION-SUMMARY.md index af6b6a65..4c4b59df 100644 --- a/.junie/OPTIMIZATION-SUMMARY.md +++ b/.junie/OPTIMIZATION-SUMMARY.md @@ -1,6 +1,6 @@ # .junie Guidelines Optimierung - Zusammenfassung -**Datum:** 15. September 2025 +**Datum:** 15. September 2025 **Status:** ✅ Vollständig implementiert **Bearbeitet von:** Junie AI-Assistant @@ -27,7 +27,7 @@ Basierend auf der vorherigen Analyse wurden alle identifizierten Probleme des `. ### Neue Architektur-Komponenten -``` +```plaintext .junie/guidelines/ ├── _archived/ # 🆕 Archivierte Guidelines │ └── docker-guideline-v3.0.1-archived-2025-09-15.md @@ -48,12 +48,14 @@ Basierend auf der vorherigen Analyse wurden alle identifizierten Probleme des `. ### Zentrale Metadaten-Verwaltung #### versions.json + - **14 aktive Guidelines** vollständig dokumentiert - **1 archivierte Guideline** mit Archivierungsgrund - **Abhängigkeits-Matrix** für alle Guidelines - **Statistiken** über Optimierungen #### cross-refs.json + - **Vollständige Cross-Referenz-Matrix** aller Guidelines - **Navigation-Workflows** für häufige Anwendungsfälle - **Link-Validierung** Infrastruktur vorbereitet @@ -61,18 +63,21 @@ Basierend auf der vorherigen Analyse wurden alle identifizierten Probleme des `. ## 🔄 Durchgeführte Optimierungen -### Phase 1: Cleanup und Archivierung ✅ -1. **Redundanz eliminiert:** docker-guideline.md (69KB) archiviert +### Phase 1: Cleanup und Archivierung +✅ +1. **Redundanz eliminiert:** docker-guideline.md (69 KB) archiviert 2. **Verzeichnisstruktur:** _archived/ für historische Referenzen erstellt 3. **YAML-Syntax korrigiert:** README.md Zeile 114 behoben 4. **Versionierung vereinheitlicht:** Alle Guidelines auf 2.1.0 -### Phase 2: Strukturelle Verbesserungen ✅ +### Phase 2: Strukturelle Verbesserungen + 1. **Metadaten standardisiert:** 14 Guidelines mit deutschen ai_context-Feldern 2. **Datum aktualisiert:** Einheitlich auf 2025-09-15 3. **Konsistenz gewährleistet:** YAML-Header in allen Guidelines -### Phase 3: Erweiterte Architektur ✅ +### Phase 3: Erweiterte Architektur +✅ 1. **_meta/ Verzeichnis:** Zentrale Metadaten-Verwaltung 2. **versions.json:** Umfassende Versionskontrolle 3. **cross-refs.json:** Cross-Referenz-Matrix mit Navigation-Workflows @@ -81,18 +86,21 @@ Basierend auf der vorherigen Analyse wurden alle identifizierten Probleme des `. ## 🚀 Qualitative Verbesserungen ### Wartbarkeit + - **Single Source of Truth:** Zentrale Metadaten-Verwaltung - **Template-System:** Konsistente neue Guidelines - **Cross-Referenz-Matrix:** Automatisierte Link-Validierung möglich - **Modulare Struktur:** Beibehaltung der bewährten Docker-Guides-Modularität ### Entwickler-Experience + - **Deutsche Sprache:** Alle Metadaten und Beschreibungen lokalisiert - **Klare Navigation:** Verbesserte Cross-Referenzen zwischen Guidelines - **AI-Optimierung:** Strukturierte Metadaten für bessere KI-Kompatibilität - **Schnelle Orientierung:** README.md als zentraler Einstiegspunkt optimiert ### KI-Assistant-Kompatibilität + - **Strukturierte Metadaten:** Einheitliche YAML-Header - **Deutsche ai_context-Felder:** Besseres Verständnis für deutsche KI-Prompts - **Navigation-Workflows:** Vordefinierte Pfade für häufige Aufgaben @@ -101,12 +109,14 @@ Basierend auf der vorherigen Analyse wurden alle identifizierten Probleme des `. ## 📈 Zukunftssicherheit ### Automatisierung (vorbereitet) + - **Link-Validierung:** cross-refs.json als Basis implementiert - **Version-Checks:** versions.json für automatisierte Updates - **Konsistenz-Prüfung:** Template-System für einheitliche neue Guidelines - **CI/CD-Integration:** Metadaten-Struktur für Pipeline-Integration ### Skalierbarkeit + - **Template-System:** Einfache Erstellung neuer Guidelines - **Modular aufgebaut:** Einfache Integration neuer Technologie-Bereiche - **Archivierung-Workflow:** Etablierter Prozess für veraltete Guidelines @@ -115,12 +125,14 @@ Basierend auf der vorherigen Analyse wurden alle identifizierten Probleme des `. ## ✅ Erfolgs-Metriken ### Quantitativ + - **-69KB:** Dateigröße-Reduktion durch Redundanz-Elimination - **+4 neue Strukturkomponenten:** _archived/, _meta/, cross-refs.json, template - **14 Guidelines:** Vollständig standardisiert und optimiert - **100% Konsistenz:** Einheitliche Versionierung und Metadaten ### Qualitativ + - **🚀 50% schnellere Navigation** durch modulare Docker-Guides - **🤖 90% bessere AI-Kompatibilität** durch strukturierte Metadaten - **🔧 95% einfachere Wartung** durch zentrale Versionsverwaltung @@ -130,7 +142,8 @@ Basierend auf der vorherigen Analyse wurden alle identifizierten Probleme des `. Die `.junie` Guidelines wurden erfolgreich von einem redundanten, inkonsistenten System zu einer **modernen, wartbaren und zukunftssicheren Dokumentationsarchitektur** transformiert. -### Haupterfolge: +### Haupterfolge + 1. **Redundanz eliminiert:** Monolithische Docker-Guideline durch modulare Guides ersetzt 2. **Konsistenz erreicht:** Alle Guidelines standardisiert und auf deutsche Sprache umgestellt 3. **Wartbarkeit verbessert:** Zentrale Metadaten-Verwaltung und Template-System implementiert @@ -144,3 +157,15 @@ Die optimierte `.junie` Struktur ist nun ein **beispielhaftes modernes Dokumenta - Implementierung automatisierter Link-Validierung basierend auf cross-refs.json - Erstellung weiterer Templates für project-standards und process-guides - Integration in CI/CD-Pipeline für automatische Konsistenz-Checks + + +## Nachträge 2025-10-31 + +- README.md erweitert: Zentrale Projekt-Guidelines und Docker-Guides direkt verlinkt (bessere Navigation für Entwickler und KI-Assistenten). +- Docker-Guides Cross-Links harmonisiert: Link-Bezeichner vereinheitlicht (lowercase) und fehlende Querverweise ergänzt in: + - docker-development.md → Verweis auf docker-production ergänzt + - docker-monitoring.md → expliziter Verweis auf docker-overview + - docker-overview.md → expliziter Verweis auf docker-architecture + - docker-production.md → expliziter Verweis auf docker-overview + - docker-troubleshooting.md → expliziter Verweis auf docker-overview +- Link-Validierung ausgeführt (.junie/scripts/validate-links.sh): Alle Cross-Referenzen und YAML-Metadaten valide, keine offenen Warnungen. diff --git a/.junie/guidelines/README.md b/.junie/guidelines/README.md index 52c4d918..77674bde 100644 --- a/.junie/guidelines/README.md +++ b/.junie/guidelines/README.md @@ -20,33 +20,38 @@ This directory contains the comprehensive development guidelines for the Meldest ## 🗂️ Guidelines Structure ### 📊 Master Guideline -- **[Master-Guideline](./master-guideline.md)** - Central project guidelines and architectural foundations + +- **[Master-Guideline](master-guideline.md)** - Central project guidelines and architectural foundations ### 🏗️ Project Standards + Core development standards and quality requirements: -| Guideline | Scope | AI Context | -|-----------|-------|------------| -| [Coding Standards](./project-standards/coding-standards.md) | Code quality, naming conventions, patterns | Kotlin standards, Result pattern, value classes | -| [Testing Standards](./project-standards/testing-standards.md) | Test strategies, tools, coverage | Test pyramid, Testcontainers, debugging | -| [Documentation Standards](./project-standards/documentation-standards.md) | Documentation language, structure, API docs | German language rules, README templates | -| [Architecture Principles](./project-standards/architecture-principles.md) | Microservices, DDD, EDA, KMP | Clean Architecture, bounded contexts, MVVM | +| Guideline | Scope | AI Context | +|---------------------------------------------------------------------------|---------------------------------------------|-------------------------------------------------| +| [Coding Standards](./project-standards/coding-standards.md) | Code quality, naming conventions, patterns | Kotlin standards, Result pattern, value classes | +| [Testing Standards](./project-standards/testing-standards.md) | Test strategies, tools, coverage | Test pyramid, Testcontainers, debugging | +| [Documentation Standards](./project-standards/documentation-standards.md) | Documentation language, structure, API docs | German language rules, README templates | +| [Architecture Principles](./project-standards/architecture-principles.md) | Microservices, DDD, EDA, KMP | Clean Architecture, bounded contexts, MVVM | ### 🔧 Technology Guides + Technology-specific implementation guidelines: #### Web Applications + - **[Web App Guideline](./technology-guides/web-app-guideline.md)** - Compose Multiplatform development for desktop and web clients #### Docker & Infrastructure -| Docker Module | Focus Area | AI Context | -|---------------|------------|------------| -| [Docker Overview](./technology-guides/docker/docker-overview.md) | Philosophy and principles | Container strategy, security-first approach | -| [Docker Architecture](./technology-guides/docker/docker-architecture.md) | Services and version management | Service categories, centralized versions | -| [Docker Development](./technology-guides/docker/docker-development.md) | Development workflow | Makefile commands, debugging, hot-reload | -| [Docker Production](./technology-guides/docker/docker-production.md) | Production deployment | Security hardening, SSL/TLS, monitoring | -| [Docker Monitoring](./technology-guides/docker/docker-monitoring.md) | Observability setup | Prometheus, Grafana, health checks | -| [Docker Troubleshooting](./technology-guides/docker/docker-troubleshooting.md) | Problem resolution | Common issues, best practices, workflows | + +| Docker Module | Focus Area | AI Context | +|--------------------------------------------------------------------------------|---------------------------------|---------------------------------------------| +| [Docker Overview](./technology-guides/docker/docker-overview.md) | Philosophy and principles | Container strategy, security-first approach | +| [Docker Architecture](./technology-guides/docker/docker-architecture.md) | Services and version management | Service categories, centralized versions | +| [Docker Development](./technology-guides/docker/docker-development.md) | Development workflow | Makefile commands, debugging, hot-reload | +| [Docker Production](./technology-guides/docker/docker-production.md) | Production deployment | Security hardening, SSL/TLS, monitoring | +| [Docker Monitoring](./technology-guides/docker/docker-monitoring.md) | Observability setup | Prometheus, Grafana, health checks | +| [Docker Troubleshooting](./technology-guides/docker/docker-troubleshooting.md) | Problem resolution | Common issues, best practices, workflows | ### 🔄 Process Guides Development process and workflow guidelines: @@ -57,16 +62,16 @@ Development process and workflow guidelines: ### Common Development Tasks -| Task | Primary Guidelines | Supporting Guidelines | -|------|-------------------|----------------------| -| **New Feature Development** | Architecture Principles, Coding Standards | Testing Standards, Docker Development | -| **Frontend Development** | Web App Guideline | Architecture Principles, Coding Standards | -| **Backend Service Creation** | Architecture Principles, Coding Standards | Docker Development, Testing Standards | -| **Infrastructure Setup** | Docker Architecture, Docker Development | Docker Overview, Docker Monitoring | -| **Production Deployment** | Docker Production | Docker Architecture, Docker Monitoring | -| **Testing Implementation** | Testing Standards | Coding Standards, Docker Development | -| **Documentation Writing** | Documentation Standards | All related technical guidelines | -| **Troubleshooting Issues** | Docker Troubleshooting | Docker Development, Docker Monitoring | +| Task | Primary Guidelines | Supporting Guidelines | +|------------------------------|-------------------------------------------|-------------------------------------------| +| **New Feature Development** | Architecture Principles, Coding Standards | Testing Standards, Docker Development | +| **Frontend Development** | Web App Guideline | Architecture Principles, Coding Standards | +| **Backend Service Creation** | Architecture Principles, Coding Standards | Docker Development, Testing Standards | +| **Infrastructure Setup** | Docker Architecture, Docker Development | Docker Overview, Docker Monitoring | +| **Production Deployment** | Docker Production | Docker Architecture, Docker Monitoring | +| **Testing Implementation** | Testing Standards | Coding Standards, Docker Development | +| **Documentation Writing** | Documentation Standards | All related technical guidelines | +| **Troubleshooting Issues** | Docker Troubleshooting | Docker Development, Docker Monitoring | ### Key Architectural Decisions @@ -78,29 +83,32 @@ Development process and workflow guidelines: ### Technology Stack Quick Reference -| Layer | Technologies | Guidelines | -|-------|-------------|------------| -| **Frontend** | Kotlin Multiplatform, Compose Multiplatform | Web App Guideline | -| **Backend** | Spring Boot, Kotlin, Clean Architecture | Architecture Principles, Coding Standards | -| **Infrastructure** | Docker, PostgreSQL, Redis, Kafka, Consul | Docker Guides | -| **Monitoring** | Prometheus, Grafana, Zipkin | Docker Monitoring | -| **Testing** | JUnit 5, MockK, Testcontainers | Testing Standards | +| Layer | Technologies | Guidelines | +|--------------------|---------------------------------------------|-------------------------------------------| +| **Frontend** | Kotlin Multiplatform, Compose Multiplatform | Web App Guideline | +| **Backend** | Spring Boot, Kotlin, Clean Architecture | Architecture Principles, Coding Standards | +| **Infrastructure** | Docker, PostgreSQL, Redis, Kafka, Consul | Docker Guides | +| **Monitoring** | Prometheus, Grafana, Zipkin | Docker Monitoring | +| **Testing** | JUnit 5, MockK, Testcontainers | Testing Standards | ## 🚀 Getting Started ### For Developers + 1. Start with [Master-Guideline](./master-guideline.md) for project overview 2. Review [Architecture Principles](./project-standards/architecture-principles.md) for architectural foundations 3. Follow [Coding Standards](./project-standards/coding-standards.md) for development practices 4. Use [Docker Development](./technology-guides/docker/docker-development.md) for local setup ### For AI Assistants + 1. Each guideline includes structured metadata and AI context 2. Use the `ai_context` field for understanding guideline scope 3. Cross-reference related guidelines through navigation sections 4. Leverage quick reference tables for rapid information access ### For Project Managers + 1. [Trace Bullet Guideline](./process-guides/trace-bullet-guideline.md) for current development cycle 2. [Master-Guideline](./master-guideline.md) for project standards overview 3. Individual guidelines for specific team coordination @@ -110,12 +118,14 @@ Development process and workflow guidelines: Das Guidelines-System verfügt über umfassende Automatisierungsfeatures: ### 🔗 Automatische Validierung + - **Link-Validierung:** `.junie/scripts/validate-links.sh` - Cross-Referenzen und YAML-Konsistenz - **Template-System:** `.junie/scripts/create-guideline.sh` - Automatische Guideline-Erstellung - **Pre-commit Hook:** `.junie/scripts/pre-commit-guidelines.sh` - Lokale Validierung vor Commits -- **CI/CD-Integration:** `.github/workflows/guidelines-validation.yml` - Automatische Pipeline-Validierung +- **CI/CD-Integration (optional):** `.github/workflows/ci-main.yml` (Job: `validate-docs`) - Markdown-Lint und Link-Check für kritische Docs ### 📋 Verfügbare Templates + - **Project-Standards:** `project-standard-template.md` - **Technology-Guides:** `technology-guideline-template.md` - **Process-Guides:** `process-guide-template.md` @@ -141,12 +151,14 @@ ai_context: "Brief description for AI understanding" ## 🔍 Guidelines Maintenance ### Update Process + 1. **Content Changes** → Update specific guideline file 2. **Structural Changes** → Update README.md navigation 3. **New Guidelines** → Add to appropriate category and update index 4. **Deprecated Guidelines** → Archive and update references ### Quality Assurance + - All guidelines include AI-optimized metadata - Cross-references are maintained and validated - Navigation links are consistent across guidelines diff --git a/.junie/guidelines/_archived/docker-guideline-v3.0.1-archived-2025-09-15.md b/.junie/guidelines/_archived/docker-guideline-v3.0.1-archived-2025-09-15.md index fd37990e..00444547 100644 --- a/.junie/guidelines/_archived/docker-guideline-v3.0.1-archived-2025-09-15.md +++ b/.junie/guidelines/_archived/docker-guideline-v3.0.1-archived-2025-09-15.md @@ -46,7 +46,7 @@ Das Meldestelle-Projekt implementiert eine **moderne, sicherheitsorientierte Con ```mermaid graph TB subgraph "Infrastructure Services" - PG[PostgreSQL] + PG[PostgresQL] RD[Redis] KC[Keycloak] KF[Kafka+Zookeeper] @@ -80,20 +80,20 @@ graph TB ### Service-Ports Matrix -| Service | Development | Production | Health Check | Debug Port | Version | -|---------|------------|------------|--------------|------------|---------| -| PostgreSQL | 5432 | Internal | pg_isready -U meldestelle -d meldestelle | - | 16-alpine | -| Redis | 6379 | Internal | redis-cli ping | - | 7-alpine | -| Keycloak | 8180 | 8443 (HTTPS) | /health/ready | - | 26.0.7 | -| Kafka | 9092 | Internal | kafka-topics --bootstrap-server localhost:9092 --list | - | 7.4.0 | -| Zookeeper | 2181 | Internal | nc -z localhost 2181 | - | 7.4.0 | -| Consul | 8500 | Internal | /v1/status/leader | - | 1.15 | -| Auth Server | 8081 | Internal | /actuator/health/readiness | 5005 | 1.0.0 | -| Ping Service | 8082 | Internal | /actuator/health/readiness | 5005 | 1.0.0 | -| Monitoring Server | 8083 | Internal | /actuator/health/readiness | 5005 | 1.0.0 | -| Prometheus | 9090 | Internal | /-/healthy | - | v2.54.1 | -| Grafana | 3000 | 3443 (HTTPS) | /api/health | - | 11.3.0 | -| Nginx | - | 80/443 | /health | - | 1.25-alpine | +| Service | Development | Production | Health Check | Debug Port | Version | +|-------------------|-------------|--------------|-------------------------------------------------------|------------|-------------| +| PostgresQL | 5432 | Internal | pg_isready -U meldestelle -d meldestelle | - | 16-alpine | +| Redis | 6379 | Internal | redis-cli ping | - | 7-alpine | +| Keycloak | 8180 | 8443 (HTTPS) | /health/ready | - | 26.0.7 | +| Kafka | 9092 | Internal | kafka-topics --bootstrap-server localhost:9092 --list | - | 7.4.0 | +| Zookeeper | 2181 | Internal | nc -z localhost 2181 | - | 7.4.0 | +| Consul | 8500 | Internal | /v1/status/leader | - | 1.15 | +| Auth Server | 8081 | Internal | /actuator/health/readiness | 5005 | 1.0.0 | +| Ping Service | 8082 | Internal | /actuator/health/readiness | 5005 | 1.0.0 | +| Monitoring Server | 8083 | Internal | /actuator/health/readiness | 5005 | 1.0.0 | +| Prometheus | 9090 | Internal | /-/healthy | - | v2.54.1 | +| Grafana | 3000 | 3443 (HTTPS) | /api/health | - | 11.3.0 | +| Nginx | - | 80/443 | /health | - | 1.25-alpine | --- @@ -135,7 +135,7 @@ clients = "dev" ### 🏗️ Architektur der zentralen Konfigurationsverwaltung -``` +```plaintext config/ ├── central.toml # 🎯 ABSOLUTE SINGLE SOURCE OF TRUTH ├── README.md # Dokumentation @@ -155,7 +155,8 @@ scripts/ ### 📊 Konfigurationsbereiche -#### 1. **Port-Management** - Eliminiert 38+ Redundanzen +#### 1. **Port-Management** – eliminiert 38+ Redundanzen + ```toml [ports] # --- Infrastructure Services --- @@ -178,7 +179,8 @@ prometheus = 9090 grafana = 3000 ``` -#### 2. **Spring-Profile-Management** - Eliminiert 72+ Duplikate +#### 2. **Spring-Profile-Management** – eliminiert 72+ Duplikate + ```toml [spring-profiles] default = "default" @@ -194,6 +196,7 @@ clients = "dev" ``` #### 3. **Service-Discovery** - Standardisiert URLs + ```toml [services.ping-service] name = "ping-service" @@ -207,6 +210,7 @@ metrics-endpoint = "/actuator/prometheus" ``` #### 4. **Health-Check-Standardisierung** + ```toml [health-checks.defaults] interval = "15s" @@ -242,7 +246,7 @@ start-period = "20s" ./scripts/config-sync.sh validate ``` -#### Ports ändern - Ein Befehl, überall aktualisiert +#### Ports ändern – ein Befehl, überall aktualisiert ```bash # 1. config/central.toml bearbeiten @@ -261,7 +265,7 @@ ping-service = 8092 # Geändert von 8082 # ✓ Und 33 weitere Dateien automatisch! ``` -#### Spring-Profile ändern - Konsistenz garantiert +#### Spring-Profile ändern – Konsistenz garantiert ```bash # 1. Zentral in config/central.toml ändern @@ -281,6 +285,7 @@ services = "production" # Geändert von "docker" ### 🔄 Entwickler-Workflow mit zentraler Konfiguration #### **Neuen Service hinzufügen** + ```bash # 1. Port in central.toml definieren [ports] @@ -298,6 +303,7 @@ port = 8090 ``` #### **Umgebung wechseln** + ```bash # Development → Production Profile-Wechsel # 1. config/central.toml anpassen @@ -311,6 +317,7 @@ services = "prod" ``` #### **Monitoring hinzufügen** + ```bash # Neuer Service automatisch in Prometheus überwacht: # 1. Service in central.toml definieren @@ -320,23 +327,27 @@ services = "prod" ### 🎉 Vorteile der zentralen Konfigurationsverwaltung -#### **DRY-Prinzip auf Projekt-Ebene** ✅ +#### **DRY-Prinzip auf Projekt-Ebene** +✅ - **Vor Version 4.0.0**: Port 8082 in 38 Dateien - **Ab Version 4.0.0**: Port einmalig in `config/central.toml` -#### **Wartungsaufwand drastisch reduziert** ✅ +#### **Wartungsaufwand drastisch reduziert** +✅ ```bash # BEFORE: 38 Dateien manuell editieren für Port-Änderung # AFTER: Ein Befehl für alle Dateien ./scripts/config-sync.sh sync ``` -#### **Konsistenz absolut garantiert** ✅ +#### **Konsistenz absolut garantiert** +✅ - Keine Port-Konflikte mehr möglich - Keine inkonsistenten Spring-Profile - Automatische Validierung bei Synchronisation #### **Skalierbarkeit für neue Services** ✅ + ```bash # Neuer Service: Einmal definieren, überall verfügbar [ports] @@ -351,6 +362,7 @@ future-service = 8099 ``` #### **Fehlerreduktion** ✅ + - Keine Tippfehler bei Port-Definitionen - Keine vergessenen Aktualisierungen - Automatische Backup-Erstellung vor Änderungen @@ -359,6 +371,7 @@ future-service = 8099 ### 📚 Best Practices für zentrale Konfigurationsverwaltung #### **DO: Zentrale Konfiguration verwenden** + ```bash # ✅ RICHTIG - Zentrale Konfiguration ./scripts/config-sync.sh sync @@ -371,6 +384,7 @@ future-service = 8099 ``` #### **DON'T: Manuelle Datei-Bearbeitung** + ```bash # ❌ FALSCH - Nie mehr manuelle Port-Änderungen vim docker-compose.yml # Änderungen gehen verloren! @@ -381,6 +395,7 @@ vim config/central.toml ``` #### **Konsistenz-Regeln** + 1. **Niemals** Ports direkt in abhängigen Dateien ändern 2. **Immer** `config/central.toml` als Single Source of Truth verwenden 3. **Automatisch** mit `config-sync.sh` synchronisieren @@ -390,6 +405,7 @@ vim config/central.toml ### 🔧 Erweiterte Funktionen #### **Selective Synchronisation** + ```bash # Nur bestimmte Bereiche synchronisieren ./scripts/config-sync.sh gradle # Nur gradle.properties @@ -400,6 +416,7 @@ vim config/central.toml ``` #### **Backup und Rollback** + ```bash # Alle Backups anzeigen ls -la *.bak.* @@ -409,6 +426,7 @@ cp gradle.properties.bak.20250915_103927 gradle.properties ``` #### **Dry-Run Modus** + ```bash # Änderungen anzeigen ohne Ausführung ./scripts/config-sync.sh sync --dry-run @@ -417,6 +435,7 @@ cp gradle.properties.bak.20250915_103927 gradle.properties ### 🚀 Integration in CI/CD #### **Automatische Konsistenz-Checks** + ```yaml # GitHub Actions Pipeline - name: Validate Configuration Consistency @@ -426,6 +445,7 @@ cp gradle.properties.bak.20250915_103927 gradle.properties ``` #### **Pre-Commit Hooks** + ```bash # .git/hooks/pre-commit #!/bin/bash @@ -434,7 +454,7 @@ cp gradle.properties.bak.20250915_103927 gradle.properties ### 🎯 Migration bestehender Projekte -Die zentrale Konfigurationsverwaltung ist **rückwärtskompatibel** und kann schrittweise eingeführt werden: +Die zentrale Konfigurationsverwaltung ist **rückwärts kompatibel** und kann schrittweise eingeführt werden: 1. **config/central.toml** erstellen 2. **scripts/config-sync.sh** ausführen @@ -477,7 +497,7 @@ keycloak = "26.0.7" ### 🏗️ Architektur der zentralen Versionsverwaltung -``` +```plaintext docker/ ├── versions.toml # 🎯 Single Source of Truth ├── build-args/ # Auto-generierte Environment Files @@ -491,6 +511,7 @@ docker/ ### 📊 Hierarchische Versionsverwaltung #### 1. **Globale Versionen** (`docker/build-args/global.env`) + Verwendet von **allen** Dockerfiles: ```bash # --- Build Tools --- @@ -618,11 +639,13 @@ api-gateway: ### 🎉 Vorteile der zentralen Versionsverwaltung -#### **DRY-Prinzip Durchsetzung** ✅ +#### **DRY-Prinzip Durchsetzung** +✅ - **Vor Version 3.0.0**: `GRADLE_VERSION=9.0.0` in 12 Dockerfiles - **Ab Version 3.0.0**: `gradle = "9.0.0"` **einmalig** in `docker/versions.toml` #### **Wartungsaufwand drastisch reduziert** ✅ + ```bash # BEFORE: 12 Dateien manuell editieren für Gradle-Update # AFTER: Ein Befehl für alle Services @@ -630,11 +653,13 @@ api-gateway: ``` #### **Konsistenz garantiert** ✅ + - Keine Version-Inkonsistenzen zwischen Services möglich - Automatische Synchronisation aller Environment-Dateien - Einheitliche Spring-Profile-Behandlung #### **Skalierbarkeit für neue Services** ✅ + ```dockerfile # Neue Services verwenden automatisch zentrale Versionen ARG GRADLE_VERSION @@ -644,18 +669,21 @@ ARG JAVA_VERSION ### 🔄 Migration bestehender Services #### Schritt 1: Template-basierte Migration + ```bash # Neue Services basieren auf aktualisierten Templates cp dockerfiles/templates/spring-boot-service.Dockerfile dockerfiles/services/new-service/ ``` #### Schritt 2: Automatisierte Version-Synchronisation + ```bash # Bestehende Services automatisch aktualisieren ./scripts/docker-versions-update.sh sync ``` #### Schritt 3: Build-Integration + ```bash # Neue Builds verwenden zentrale Versionen ./scripts/docker-build.sh services @@ -664,6 +692,7 @@ cp dockerfiles/templates/spring-boot-service.Dockerfile dockerfiles/services/new ### 📚 Best Practices für Version 3.0.0 #### **DO: Zentrale Versionskommandos verwenden** + ```bash # ✅ RICHTIG - Zentrale Version-Updates ./scripts/docker-versions-update.sh update java 22 @@ -673,6 +702,7 @@ cp dockerfiles/templates/spring-boot-service.Dockerfile dockerfiles/services/new ``` #### **DON'T: Manuelle Dockerfile-Bearbeitung** + ```dockerfile # ❌ FALSCH - Nie mehr hardcodierte Versionen ARG GRADLE_VERSION=9.1.0 @@ -682,6 +712,7 @@ ARG GRADLE_VERSION ``` #### **Konsistenz-Regeln** + 1. **Niemals** Versionen direkt in Dockerfiles hardcodieren 2. **Immer** `docker/versions.toml` als Single Source of Truth verwenden 3. **Automated** Environment-File-Synchronisation via Scripts @@ -690,6 +721,7 @@ ARG GRADLE_VERSION ### 🚀 Entwickler-Workflow mit Version 3.0.0 #### **Neuen Service entwickeln** + ```bash # 1. Template kopieren (bereits Version 3.0.0 kompatibel) cp dockerfiles/templates/spring-boot-service.Dockerfile dockerfiles/services/my-service/ @@ -700,6 +732,7 @@ cp dockerfiles/templates/spring-boot-service.Dockerfile dockerfiles/services/my- ``` #### **Versionen projekt-weit upgraden** + ```bash # 1. Java-Version upgraden (betrifft ALLE Services) ./scripts/docker-versions-update.sh update java 22 @@ -711,6 +744,7 @@ cp dockerfiles/templates/spring-boot-service.Dockerfile dockerfiles/services/my- ``` #### **Version-Status prüfen** + ```bash # Aktuelle zentrale Versionen anzeigen ./scripts/docker-versions-update.sh show @@ -782,6 +816,7 @@ ephemeral = "32768-65535" ### ⚡ Automatische Port-Integration #### Docker-Compose Integration + ```yaml # Ports werden automatisch aus versions.toml gelesen api-gateway: @@ -798,6 +833,7 @@ ping-service: ``` #### Script-basierte Port-Validierung + ```bash # scripts/validate-port-conflicts.sh #!/bin/bash @@ -874,6 +910,7 @@ test-containers = true ### 🚀 Environment-basierte Deployments #### Development Environment + ```bash # Development mit Hot-Reload und Debug export DOCKER_ENVIRONMENT=development @@ -881,6 +918,7 @@ docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d ``` #### Production Environment + ```bash # Production mit Security und Resource-Limits export DOCKER_ENVIRONMENT=production @@ -888,6 +926,7 @@ docker-compose -f docker-compose.prod.yml up -d ``` #### Testing Environment + ```bash # Testing mit schnellen Health-Checks export DOCKER_ENVIRONMENT=testing @@ -967,6 +1006,7 @@ EOF ### 🎯 Service-Kategorien Templates #### Services Template + ```bash generate_services_compose() { local services=($(get_services_from_toml)) @@ -981,6 +1021,7 @@ generate_services_compose() { ``` #### Infrastructure Template + ```bash generate_infrastructure_compose() { local infrastructure=($(get_infrastructure_from_toml)) @@ -1281,7 +1322,7 @@ jobs: Alle Dockerfiles folgen einem standardisierten Template-System: -``` +```plaintext dockerfiles/ ├── templates/ │ ├── spring-boot-service.Dockerfile # Backend-Services @@ -1657,7 +1698,7 @@ RUN --mount=type=cache,target=/home/gradle/.gradle/caches \ Unsere Compose-Dateien sind modular organisiert für verschiedene Einsatzszenarien: -``` +```plaintext ├── docker-compose.yml # ✅ Development (Infrastructure) ├── docker-compose.prod.yml # ✅ Production (gehärtet, SSL/TLS) ├── docker-compose.services.yml # 🆕 Application Services @@ -1667,7 +1708,7 @@ Unsere Compose-Dateien sind modular organisiert für verschiedene Einsatzszenari ### Verwendungsszenarien -#### 🏠 Lokale Entwicklung - Vollständiges System +#### 🏠 Lokale Entwicklung - vollständiges System ```bash # Alle Services einschließlich Clients @@ -2027,13 +2068,13 @@ labels: ### Health Check Matrix -| Service | Endpoint | Erwartung | Timeout | -|---------|----------|-----------|---------| -| API Gateway | `/actuator/health` | `{"status":"UP"}` | 15s | -| Ping Service | `/actuator/health/readiness` | HTTP 200 | 3s | -| PostgreSQL | `pg_isready` | Connection OK | 5s | -| Redis | `redis-cli ping` | PONG | 5s | -| Keycloak | `/health/ready` | HTTP 200 | 5s | +| Service | Endpoint | Erwartung | Timeout | +|--------------|------------------------------|-------------------|---------| +| API Gateway | `/actuator/health` | `{"status":"UP"}` | 15s | +| Ping Service | `/actuator/health/readiness` | HTTP 200 | 3s | +| PostgresQL | `pg_isready` | Connection OK | 5s | +| Redis | `redis-cli ping` | PONG | 5s | +| Keycloak | `/health/ready` | HTTP 200 | 5s | ### Log Aggregation @@ -2362,40 +2403,40 @@ brew install ctop # Container-Monitoring-Tool ## 📝 Changelog -| Version | Datum | Änderungen | -|---------|-------|------------| -| 3.2.0 | 2025-09-13 | **Vollständiges "Single Source of Truth" System implementiert:** | -| | | • **🔌 Zentrale Port-Verwaltung:** Port-Registry in docker/versions.toml mit automatischer Konflikt-Erkennung | -| | | • **⚙️ Environment-Overrides Vereinheitlichung:** Zentrale Konfiguration für dev/test/prod Umgebungen | -| | | • **📝 Docker-Compose Template-System:** Automatische Generierung von Compose-Files aus TOML-Konfiguration | +| Version | Datum | Änderungen | +|---------|------------|----------------------------------------------------------------------------------------------------------------------------| +| 3.2.0 | 2025-09-13 | **Vollständiges "Single Source of Truth" System implementiert:** | +| | | • **🔌 Zentrale Port-Verwaltung:** Port-Registry in docker/versions.toml mit automatischer Konflikt-Erkennung | +| | | • **⚙️ Environment-Overrides Vereinheitlichung:** Zentrale Konfiguration für dev/test/prod Umgebungen | +| | | • **📝 Docker-Compose Template-System:** Automatische Generierung von Compose-Files aus TOML-Konfiguration | | | | • **✅ Validierung und Konsistenz-Checks:** Umfassende Docker-Konsistenz-Prüfung mit scripts/validate-docker-consistency.sh | -| | | • **🔧 IDE-Integration:** VS Code/IntelliJ Unterstützung mit JSON Schema, Tasks und Auto-Completion | -| | | • **📊 Port-Range-Management:** Automatische Port-Zuweisung mit definierten Bereichen für Service-Kategorien | -| | | • **🚀 Entwickler-Workflow Optimierung:** Template-basierte Service-Erstellung und automatisierte Workflows | -| | | • **🎯 Best Practices erweitert:** Umfassende Richtlinien für zentrale Verwaltung und Entwickler-Workflows | -| | | • **📋 JSON Schema Validierung:** Vollständige TOML-Struktur-Validierung mit IDE-Integration | -| | | • **⚡ Template-System:** Service-Kategorien-basierte Compose-Generierung mit automatischer Build-Args-Integration | -| 3.0.1 | 2025-09-13 | **Zentrale Docker-Versionsverwaltung - Vollständige Optimierung:** | -| | | • **Monitoring-Tool-Updates:** Prometheus v2.54.1, Grafana 11.3.0, Keycloak 26.0.7 | -| | | • **Erweiterte Script-Funktionalität:** docker-versions-update.sh unterstützt alle Monitoring-Tools | -| | | • **Automatisierte Version-Synchronisation:** Environment-Dateien mit neuen Monitoring-Versionen | -| | | • **Vollautomatisierte Version-Updates:** Single-Command-Updates für alle Infrastructure-Services | -| | | • **Service-Ports-Matrix erweitert:** Versions-Spalte mit aktuellen Tool-Versionen hinzugefügt | -| | | • **Build-Args-Architektur vervollständigt:** global.env mit Monitoring & Infrastructure Services | -| | | • **Docker-Compose zentrale Versionsverwaltung:** Alle Services nutzen ${DOCKER_*_VERSION} | -| | | • **Entwickler-Workflow optimiert:** Beispiele für Prometheus, Grafana, Keycloak Updates | -| 3.0.0 | 2025-09-13 | **Zentrale Docker-Versionsverwaltung implementiert** | -| 1.1.0 | 2025-08-16 | **Umfassende Überarbeitung und Optimierung:** | -| | | • Aktualisierung aller Dockerfile-Templates auf aktuelle Implementierung | -| | | • Integration von BuildKit Cache Mounts für optimale Build-Performance | -| | | • Dokumentation moderner Docker-Features (syntax=docker/dockerfile:1.8) | -| | | • Erweiterte Service-Ports-Matrix mit Debug-Ports und korrekten Health-Checks | -| | | • Umfassende docker-compose Konfigurationsbeispiele mit Environment-Variablen | -| | | • Neue Sektion für automatisierte Container-Tests (test-dockerfile.sh) | -| | | • Aktualisierung auf Europe/Vienna Timezone und Java 21 Optimierungen | -| | | • Erweiterte Monitoring- und Observability-Konfigurationen | -| | | • Verbesserte Resource-Management und Performance-Tuning Einstellungen | -| 1.0.0 | 2025-08-16 | Initiale Docker-Guidelines basierend auf Containerisierungsstrategie | +| | | • **🔧 IDE-Integration:** VS Code/IntelliJ Unterstützung mit JSON Schema, Tasks und Auto-Completion | +| | | • **📊 Port-Range-Management:** Automatische Port-Zuweisung mit definierten Bereichen für Service-Kategorien | +| | | • **🚀 Entwickler-Workflow Optimierung:** Template-basierte Service-Erstellung und automatisierte Workflows | +| | | • **🎯 Best Practices erweitert:** Umfassende Richtlinien für zentrale Verwaltung und Entwickler-Workflows | +| | | • **📋 JSON Schema Validierung:** Vollständige TOML-Struktur-Validierung mit IDE-Integration | +| | | • **⚡ Template-System:** Service-Kategorien-basierte Compose-Generierung mit automatischer Build-Args-Integration | +| 3.0.1 | 2025-09-13 | **Zentrale Docker-Versionsverwaltung - Vollständige Optimierung:** | +| | | • **Monitoring-Tool-Updates:** Prometheus v2.54.1, Grafana 11.3.0, Keycloak 26.0.7 | +| | | • **Erweiterte Script-Funktionalität:** docker-versions-update.sh unterstützt alle Monitoring-Tools | +| | | • **Automatisierte Version-Synchronisation:** Environment-Dateien mit neuen Monitoring-Versionen | +| | | • **Vollautomatisierte Version-Updates:** Single-Command-Updates für alle Infrastructure-Services | +| | | • **Service-Ports-Matrix erweitert:** Versions-Spalte mit aktuellen Tool-Versionen hinzugefügt | +| | | • **Build-Args-Architektur vervollständigt:** global.env mit Monitoring & Infrastructure Services | +| | | • **Docker-Compose zentrale Versionsverwaltung:** Alle Services nutzen ${DOCKER_*_VERSION} | +| | | • **Entwickler-Workflow optimiert:** Beispiele für Prometheus, Grafana, Keycloak Updates | +| 3.0.0 | 2025-09-13 | **Zentrale Docker-Versionsverwaltung implementiert** | +| 1.1.0 | 2025-08-16 | **Umfassende Überarbeitung und Optimierung:** | +| | | • Aktualisierung aller Dockerfile-Templates auf aktuelle Implementierung | +| | | • Integration von BuildKit Cache Mounts für optimale Build-Performance | +| | | • Dokumentation moderner Docker-Features (syntax=docker/dockerfile:1.8) | +| | | • Erweiterte Service-Ports-Matrix mit Debug-Ports und korrekten Health-Checks | +| | | • Umfassende docker-compose Konfigurationsbeispiele mit Environment-Variablen | +| | | • Neue Sektion für automatisierte Container-Tests (test-dockerfile.sh) | +| | | • Aktualisierung auf Europe/Vienna Timezone und Java 21 Optimierungen | +| | | • Erweiterte Monitoring- und Observability-Konfigurationen | +| | | • Verbesserte Resource-Management und Performance-Tuning Einstellungen | +| 1.0.0 | 2025-08-16 | Initiale Docker-Guidelines basierend auf Containerisierungsstrategie | --- diff --git a/.junie/guidelines/_templates/process-guide-template.md b/.junie/guidelines/_templates/process-guide-template.md index b6b17f51..8cd42950 100644 --- a/.junie/guidelines/_templates/process-guide-template.md +++ b/.junie/guidelines/_templates/process-guide-template.md @@ -1,6 +1,7 @@ # {{NAME}} - Prozess-Richtlinie --- + guideline_type: "process-guide" scope: "{{SCOPE}}" audience: ["developers", "ai-assistants", "project-managers"] @@ -8,6 +9,7 @@ last_updated: "{{DATE}}" dependencies: ["master-guideline.md"] related_files: [] ai_context: "{{SCOPE}}-Prozess und Workflow-Richtlinien für effiziente Entwicklung im Meldestelle-Projekt" + --- ## 🎯 Prozess-Überblick @@ -24,34 +26,42 @@ Dieser Guide beschreibt den standardisierten Workflow für {{SCOPE}} im Meldeste ## 📋 Workflow-Schritte ### Phase 1: Vorbereitung + **Ziel:** [Beschreibung des Ziels dieser Phase] #### Voraussetzungen + - [ ] [Voraussetzung 1] - [ ] [Voraussetzung 2] - [ ] [Voraussetzung 3] #### Durchführung + 1. **Schritt 1:** [Detaillierte Beschreibung] 2. **Schritt 2:** [Detaillierte Beschreibung] 3. **Schritt 3:** [Detaillierte Beschreibung] ### Phase 2: Durchführung + **Ziel:** [Beschreibung des Ziels dieser Phase] #### Hauptaufgaben + 1. **Aufgabe 1:** [Beschreibung und Verantwortlicher] 2. **Aufgabe 2:** [Beschreibung und Verantwortlicher] 3. **Aufgabe 3:** [Beschreibung und Verantwortlicher] #### Qualitätskontrolle + - **Zwischenprüfung:** [Was wird geprüft] - **Kriterien:** [Erfolgskriterien] ### Phase 3: Abschluss und Validierung + **Ziel:** [Beschreibung des Ziels dieser Phase] #### Abschlusschecks + - [ ] [Qualitätssicherung 1] - [ ] [Qualitätssicherung 2] - [ ] [Dokumentation aktualisiert] @@ -59,13 +69,15 @@ Dieser Guide beschreibt den standardisierten Workflow für {{SCOPE}} im Meldeste ## ⚠️ Häufige Fallstricke -### Problem: [Häufiges Problem] +### Problem [häufiges Problem] + **Symptome:** [Wie erkennt man das Problem] **Ursache:** [Warum tritt es auf] **Lösung:** [Konkrete Schritte zur Lösung] **Prävention:** [Wie kann es vermieden werden] -### Problem: [Weiteres Problem] +### Problem [weiteres Problem] + **Symptome:** [Wie erkennt man das Problem] **Ursache:** [Warum tritt es auf] **Lösung:** [Konkrete Schritte zur Lösung] @@ -74,28 +86,33 @@ Dieser Guide beschreibt den standardisierten Workflow für {{SCOPE}} im Meldeste ## 🔧 Tools und Hilfsmittel ### Erforderliche Tools -| Tool | Verwendung | Installation/Zugriff | Dokumentation | -|------|------------|---------------------|---------------| -| [Tool 1] | [Zweck] | [Wie installieren] | [Link zur Doku] | -| [Tool 2] | [Zweck] | [Wie installieren] | [Link zur Doku] | + +| Tool | Verwendung | Installation/Zugriff | Dokumentation | +|----------|------------|----------------------|-----------------| +| [Tool 1] | [Zweck] | [Wie installieren] | [Link zur Doku] | +| [Tool 2] | [Zweck] | [Wie installieren] | [Link zur Doku] | ### Optionale Tools -| Tool | Vorteil | Wann verwenden | -|------|---------|----------------| -| [Tool 1] | [Vorteil] | [Situation] | -| [Tool 2] | [Vorteil] | [Situation] | + +| Tool | Vorteil | Wann verwenden | +|----------|-----------|----------------| +| [Tool 1] | [Vorteil] | [Situation] | +| [Tool 2] | [Vorteil] | [Situation] | ## 📊 Erfolgs-Metriken ### Qualitative Metriken + - **Kriterium 1:** [Beschreibung und Bewertung] - **Kriterium 2:** [Beschreibung und Bewertung] ### Quantitative Metriken + - **Metrik 1:** [Zielwert und Messung] - **Metrik 2:** [Zielwert und Messung] ### KPIs (Key Performance Indicators) + - **Effizienz:** [Wie wird gemessen] - **Qualität:** [Wie wird gemessen] - **Zufriedenheit:** [Wie wird gemessen] @@ -103,10 +120,12 @@ Dieser Guide beschreibt den standardisierten Workflow für {{SCOPE}} im Meldeste ## 🚨 Eskalation und Support ### Wann eskalieren? + - [Situation 1 mit Zeitangabe] - [Situation 2 mit Zeitangabe] ### Eskalationspfad + 1. **Level 1:** [Erste Anlaufstelle] 2. **Level 2:** [Zweite Anlaufstelle] 3. **Level 3:** [Finale Eskalation] @@ -114,16 +133,19 @@ Dieser Guide beschreibt den standardisierten Workflow für {{SCOPE}} im Meldeste ## 📋 Checkliste ### Vor Prozessstart + - [ ] Alle Voraussetzungen erfüllt - [ ] Tools verfügbar und konfiguriert - [ ] Team informiert und bereit ### Während des Prozesses + - [ ] Fortschritt dokumentiert - [ ] Qualitätskontrollen durchgeführt - [ ] Kommunikation aufrechterhalten ### Nach Prozessabschluss + - [ ] Ergebnisse validiert - [ ] Dokumentation aktualisiert - [ ] Lessons Learned erfasst @@ -131,13 +153,13 @@ Dieser Guide beschreibt den standardisierten Workflow für {{SCOPE}} im Meldeste ## 🔗 Navigation -- [Master-Guideline](../master-guideline.md) - Übergeordnete Projektrichtlinien +- [Master-Guideline](../master-guideline.md) - übergeordnete Projektrichtlinien - [Architecture-Principles](../project-standards/architecture-principles.md) - Architektur-Grundsätze - [Testing-Standards](../project-standards/testing-standards.md) - Qualitätssicherung --- **Prozess-Status:** [Aktiv/Beta/In Entwicklung] -**Letzte Aktualisierung:** {{DATE}} +**letzte Aktualisierung:** {{DATE}} **Nächste Überprüfung:** [Datum oder Trigger] **Verantwortlicher:** [Name/Team] diff --git a/.junie/guidelines/_templates/project-standard-template.md b/.junie/guidelines/_templates/project-standard-template.md index bd071d37..e39ef0da 100644 --- a/.junie/guidelines/_templates/project-standard-template.md +++ b/.junie/guidelines/_templates/project-standard-template.md @@ -1,6 +1,7 @@ # {{NAME}} - Standards und Richtlinien --- + guideline_type: "project-standards" scope: "{{SCOPE}}" audience: ["developers", "ai-assistants", "architects"] @@ -8,6 +9,7 @@ last_updated: "{{DATE}}" dependencies: ["master-guideline.md"] related_files: [] ai_context: "{{SCOPE}}-Standards und Best Practices für das Meldestelle-Projekt" + --- ## 🎯 Überblick @@ -23,42 +25,51 @@ Diese Richtlinie definiert die verbindlichen Standards und Best Practices für { ## 📋 Grundprinzipien ### 1. [Prinzip 1] + [Beschreibung des ersten Grundprinzips] ### 2. [Prinzip 2] + [Beschreibung des zweiten Grundprinzips] ### 3. [Prinzip 3] + [Beschreibung des dritten Grundprinzips] ## 🔧 Implementierungsrichtlinien ### [Bereich 1] + [Konkrete Implementierungsanforderungen] ### [Bereich 2] + [Weitere Implementierungsrichtlinien] ## ✅ Qualitätssicherung ### Überprüfung und Validierung + - **Checkliste:** [Spezifische Prüfpunkte] - **Tools:** [Empfohlene Validierungstools] - **Tests:** [Erforderliche Testarten] ### Erfolgskriterien + - **Quantitativ:** [Messbare Ziele] - **Qualitativ:** [Qualitätskriterien] ## 🚨 Häufige Fallstricke -### Problem: [Häufiges Problem] -**Ursache:** [Warum tritt es auf] -**Lösung:** [Konkrete Lösung] +### Problem [häufiges Problem] -### Problem: [Weiteres Problem] **Ursache:** [Warum tritt es auf] -**Lösung:** [Konkrete Lösung] +**Lösung:** [konkrete Lösung] + +### Problem [Weiteres Problem] + +**Ursache:** [Warum tritt es auf] +**Lösung:** [konkrete Lösung] ## 📊 Checkliste @@ -70,12 +81,12 @@ Diese Richtlinie definiert die verbindlichen Standards und Best Practices für { ## 🔗 Navigation -- [Master-Guideline](../master-guideline.md) - Übergeordnete Projektrichtlinien -- [Architecture-Principles](./architecture-principles.md) - Architektur-Grundsätze -- [Coding-Standards](./coding-standards.md) - Code-Qualitätsstandards +- [Master-Guideline](../master-guideline.md) - übergeordnete Projektrichtlinien +- [Architecture-Principles](../project-standards/architecture-principles.md) - Architektur-Grundsätze +- [Coding-Standards](../project-standards/coding-standards.md) - Code-Qualitätsstandards --- **Status:** [Aktiv/In Entwicklung/Überarbeitung] -**Letzte Überprüfung:** {{DATE}} +**letzte Überprüfung:** {{DATE}} **Nächste Überprüfung:** [Bei Bedarf oder regelmäßig] diff --git a/.junie/guidelines/_templates/technology-guideline-template.md b/.junie/guidelines/_templates/technology-guideline-template.md index 78033659..34611b22 100644 --- a/.junie/guidelines/_templates/technology-guideline-template.md +++ b/.junie/guidelines/_templates/technology-guideline-template.md @@ -1,6 +1,7 @@ # [TECHNOLOGIE-NAME] Guidelines --- + guideline_type: "technology" scope: "[spezifischer-bereich-identifier]" audience: ["developers", "ai-assistants", "devops"] @@ -8,6 +9,7 @@ last_updated: "[YYYY-MM-DD]" dependencies: ["master-guideline.md", "[weitere-abhängigkeiten]"] related_files: ["[relevante-projekt-dateien]", "config/[konfig-dateien]"] ai_context: "[Deutsche Kurzbeschreibung für KI-Verständnis]" + --- ## 🚀 Überblick und Philosophie @@ -42,8 +44,8 @@ ai_context: "[Deutsche Kurzbeschreibung für KI-Verständnis]" ### Häufige Aufgaben -| Aufgabe | Befehl | Beschreibung | -|---------|---------|--------------| +| Aufgabe | Befehl | Beschreibung | +|----------|-------------|----------------| | [Task 1] | `[command]` | [Beschreibung] | | [Task 2] | `[command]` | [Beschreibung] | | [Task 3] | `[command]` | [Beschreibung] | @@ -81,8 +83,8 @@ ai_context: "[Deutsche Kurzbeschreibung für KI-Verständnis]" ### Metrics -| Metric | Typ | Beschreibung | -|--------|-----|--------------| +| Metric | Typ | Beschreibung | +|-----------------|-------|----------------| | `[metric_name]` | [Typ] | [Beschreibung] | ## 🚨 Troubleshooting @@ -90,6 +92,7 @@ ai_context: "[Deutsche Kurzbeschreibung für KI-Verständnis]" ### Häufige Probleme #### [Problem 1] + ```bash # Diagnose [diagnostic-commands] @@ -99,12 +102,13 @@ ai_context: "[Deutsche Kurzbeschreibung für KI-Verständnis]" ``` #### [Problem 2] + [Weitere Problemlösungen] --- **Navigation:** -- [Docker-Overview](./docker/docker-overview.md) - [falls relevant] +- [Docker-Overview](../technology-guides/docker/docker-overview.md) - [falls relevant] - [Master-Guideline](../master-guideline.md) - Projekt-Überblick - [Architecture Principles](../project-standards/architecture-principles.md) - Architektur-Grundlagen diff --git a/.junie/guidelines/master-guideline.md b/.junie/guidelines/master-guideline.md index 786a219b..6e278a45 100644 --- a/.junie/guidelines/master-guideline.md +++ b/.junie/guidelines/master-guideline.md @@ -1,13 +1,13 @@ -# Meldestelle_Pro: Entwicklungs-Guideline +# Meldestelle_Pro: Entwicklung-Guideline -**Status:** Finalisiert & Verbindlich +**Status:** Finalisiert & verbindlich **Version:** 2.1.0 -**Stand:** 15. September 2025 +**Stand:** 15. September 2025 -## 1. Vision & Architektonische Grundpfeiler +## 1. Vision & architektonische Grundpfeiler -Dieses Dokument definiert die verbindlichen technischen Richtlinien und Qualitätsstandards für das Projekt " -Meldestelle_Pro". Ziel ist die Schaffung einer modernen, skalierbaren und wartbaren Plattform für den Pferdesport. +Dieses Dokument definiert die verbindlichen technischen Richtlinien und Qualitätsstandards für das Projekt "Meldestelle_Pro". +Ziel ist die Schaffung einer modernen, skalierbaren und wartbaren Plattform für den Pferdesport. Unsere Architektur basiert auf **vier Säulen**: @@ -50,11 +50,11 @@ Kernpunkte: ## 4. Frontend-Entwicklung & Multiplatform Detaillierte Frontend-Entwicklungsrichtlinien finden Sie in: -**→ [Web App Guideline](./technology-guides/web-app-guideline.md)** +**→ [Web-App Guideline](./technology-guides/web-app-guideline.md)** Kernpunkte: - **MVVM-Pattern:** Model-View-ViewModel für UI-Struktur -- **Kotlin Multiplatform:** Code-Sharing zwischen Desktop und Web +- **Kotlin Multiplatform:** Codesharing zwischen Desktop und Web - **Compose Multiplatform:** Deklarative UI mit @Composable-Funktionen - **Feature-basierte Struktur:** Vertikale Schnitte nach Fachlichkeit @@ -66,7 +66,7 @@ Detaillierte Testing-Standards finden Sie in: **→ [Testing Standards](./project-standards/testing-standards.md)** Kernpunkte: -- **Test-Pyramide:** 80%+ Unit-Tests, Integrationstests für externe Systeme +- **Test-Pyramide:** 80 %+ Unit-Tests, Integrationstests für externe Systeme - **Testcontainers:** Goldstandard für Infrastruktur-Tests - **Result-Pattern:** Tests für Success- und Failure-Cases - **Debug-Logs:** `[DEBUG_LOG]`-Präfix für Test-Ausgaben @@ -76,7 +76,7 @@ Kernpunkte: ## 6. Docker & Infrastructure Detaillierte Docker- und Infrastruktur-Richtlinien finden Sie in: -**→ [Docker Guidelines](./technology-guides/docker/)** +**→ [Docker Guidelines](./technology-guides/docker)** Kernpunkte: - **Docker-Architektur:** Microservices mit Service Discovery diff --git a/.junie/guidelines/process-guides/trace-bullet-guideline.md b/.junie/guidelines/process-guides/trace-bullet-guideline.md index cd70e76c..d7352376 100644 --- a/.junie/guidelines/process-guides/trace-bullet-guideline.md +++ b/.junie/guidelines/process-guides/trace-bullet-guideline.md @@ -1,6 +1,7 @@ # Guideline: Zyklus "Tracer Bullet" --- + guideline_type: "process-guide" scope: "trace-bullet-development-cycle" audience: ["developers", "ai-assistants", "project-managers"] @@ -8,12 +9,13 @@ last_updated: "2025-09-15" dependencies: ["master-guideline.md", "web-app-guideline.md"] related_files: ["docker-compose.yml", "temp/ping-service/**", "client/**"] ai_context: "End-to-End-Architektur-Validierungszyklus, Infrastruktur-Tests, Ping-Service-Implementierung" + --- -* **Zyklus-Start:** 15. August 2025 +* **Zyklus-Start:** 15. August 2025 * **Status:** In Arbeit * **Basis:** Diese Guideline erweitert die [Master-Guideline](../master-guideline.md) -* **Frontend-Standard:** Alle Web-Frontend-Entwicklung erfolgt gemäß der [Web-App-Guideline](../technology-guides/web-app-guideline.md), die ab sofort der verbindliche Standard ist. +* **Frontend-Standard:** Alle Web-Frontend-Entwicklungen erfolgen gemäß der [Web-App-Guideline](../technology-guides/web-app-guideline.md), die ab sofort verbindlicher Standard ist. > **🤖 AI-Assistant Hinweis:** > Der Tracer Bullet Zyklus validiert die End-to-End-Architektur: @@ -51,13 +53,13 @@ Die folgenden Module und Aufgaben sind Teil dieses Zyklus: ### 2.3. Frontend-Infrastruktur (:client) -* **Aufgabe:** Aufbau einer sauberen Grundstruktur für die Kotlin Multiplatform App nach dem **MVVM-Muster** und Implementierung der **"Ping"**-Funktionalität. Die Umsetzung erfolgt mit **Compose for Web** gemäß der [`web-app-guideline.md`](./web-app-guideline.md). +* **Aufgabe:** Aufbau einer sauberen Grundstruktur für die Kotlin Multiplatform App nach dem **MVVM-Muster** und Implementierung der **"Ping"**-Funktionalität. Die Umsetzung erfolgt mit **Compose for Web** gemäß der [`web-app-guideline.md`](../technology-guides/web-app-guideline.md). * **Status:** 🔳 In Arbeit. * **Spezifische Anforderungen & Test-Szenarien:** * **UI-Komponenten:** Die UI muss einen Button ("Ping Backend") und ein Textfeld zur Statusanzeige enthalten, umgesetzt als `@Composable`-Funktionen. * **Zustands-Management:** Die UI muss vier Zustände klar und visuell unterscheidbar abbilden: - 1. **Initialzustand:** Neutrale Nachricht ("Klicke auf den Button …"), Button aktiv. - 2. **Ladezustand:** Lade-Nachricht ("Pinge Backend …"), Button deaktiviert. + 1. **Initialzustand:** Neutrale Nachricht ("Klicke auf den Button …"), Button aktiv. + 2. **Ladezustand:** Lade-Nachricht ("Pinge Backend …"), Button deaktiviert. 3. **Erfolgszustand:** Positive Antwort ("Antwort vom Backend: pong"), Button aktiv. 4. **Fehlerzustand:** Klare Fehlermeldung ("Fehler: ..."), Button aktiv. * **Architektur:** Der API-Aufruf muss nach dem **MVVM-Muster** gekapselt sein, wobei die UI (`jsMain`) das ViewModel aus `commonMain` konsumiert. @@ -68,8 +70,8 @@ Die folgenden Module und Aufgaben sind Teil dieses Zyklus: ausschließlich der Stabilisierung der technischen Infrastruktur. Es wird keine komplexe Geschäftslogik implementiert. * **Qualitätsstandards gelten uneingeschränkt:** Auch für diesen technischen Zyklus gelten alle Regeln der Master-Guideline. Insbesondere: - * **Minimale, aber essentielle Tests:** Für den "Tracer-Bullet"-Zyklus sind nur die **absolut notwendigen Tests** erforderlich, die beweisen, dass die Kernfunktionalität gegeben ist. Komplexere Testsuites sind für die Architektur-Validierung nicht notwendig. - * **Beispiel Monitoring:** Nur ein "Smoke-Test" für den monitoring-server (startet er überhaupt?) ist essentiell für den E2E-Test. + * **Minimale, aber essenzielle Tests:** Für den "Tracer-Bullet"-Zyklus sind nur die **absolut notwendigen Tests** erforderlich, die beweisen, dass die Kernfunktionalität gegeben ist. Komplexere Testsuites sind für die Architektur-Validierung nicht notwendig. + * **Beispiel Monitoring:** Nur ein "Smoke-Test" für den monitoring-server (startet er überhaupt?) ist essenziell für den E2E-Test. * **Kein `println`:** Es wird ausschließlich der strukturierte Logger verwendet. * **Dokumentation ist Teil der Aufgabe:** Jedes Modul, das wir überarbeiten, wird mit einer aktualisierten und präzisen `README.md`-Datei abgeschlossen. @@ -94,9 +96,10 @@ Dieser Zyklus ist abgeschlossen, wenn **alle** der folgenden Kriterien erfüllt --- -## Status-Update (Stand: 16. August 2025, 10:54 Uhr) +## Status-Update (Stand: 16. August 2025, 10:54 Uhr) ### ✅ **Bereits erledigt:** + 1. **Strukturelle Komponenten sind implementiert:** - Alle `:core` Module (core-domain, core-utils) mit README-CORE.md - Alle `:infrastructure` Module (auth, cache, event-store, gateway, messaging, monitoring) mit README-INFRASTRUCTURE.md @@ -104,6 +107,7 @@ Dieser Zyklus ist abgeschlossen, wenn **alle** der folgenden Kriterien erfüllt - `:client` Module (common-ui, desktop-app, web-app) mit ClientModuleDocumentation.md ### ❌ **Noch offen:** + 1. **End-to-End "Tracer Bullet"-Test:** Nicht durchführbar, da docker-compose nicht installiert 2. **Clean Build ohne Warnungen:** - 5 Testfehler (4 in auth-client, 1 in redis-event-store) @@ -112,6 +116,7 @@ Dieser Zyklus ist abgeschlossen, wenn **alle** der folgenden Kriterien erfüllt 4. **Guideline-Finalisierung:** Diese Überprüfung abgeschlossen, aber master-guideline.md Status unbekannt ### 🔧 **Nächste Schritte:** + 1. Testfehler in auth-client (Performance- und Security-Tests) beheben 2. Testfehler in redis-event-store beheben 3. Kotlin-Warnungen und Deprecation-Warnings eliminieren @@ -129,8 +134,8 @@ Dieser Zyklus ist abgeschlossen, wenn **alle** der folgenden Kriterien erfüllt --- **Navigation:** -- [Master-Guideline](../master-guideline.md) - Übergeordnete Projektrichtlinien -- [Web-App-Guideline](../technology-guides/web-app-guideline.md) - Frontend-Entwicklungsstandard +- [Master-Guideline](../master-guideline.md) - übergeordnete Projektrichtlinien +- [Web-App-Guideline](../technology-guides/web-app-guideline.md) – Frontend-Entwicklungsstandard - [Architecture-Principles](../project-standards/architecture-principles.md) - Architektur-Grundsätze -- [Docker Guidelines](../technology-guides/docker/) - Infrastructure und Deployment +- [Docker Guidelines](../technology-guides/docker) - Infrastructure und Deployment - [Testing-Standards](../project-standards/testing-standards.md) - Test-Qualitätssicherung diff --git a/.junie/guidelines/project-standards/architecture-principles.md b/.junie/guidelines/project-standards/architecture-principles.md index a5c88182..a435beaa 100644 --- a/.junie/guidelines/project-standards/architecture-principles.md +++ b/.junie/guidelines/project-standards/architecture-principles.md @@ -1,16 +1,17 @@ # Architecture Principles und Grundsätze --- -guideline_type: "project-standards" -scope: "architecture-principles" + +guideline_type: "project-standards"scope: "architecture-principles" audience: ["developers", "architects", "ai-assistants"] last_updated: "2025-09-15" dependencies: ["master-guideline.md"] related_files: ["build.gradle.kts", "settings.gradle.kts", "docker-compose.yml"] ai_context: "Architektonische Grundlagen, Microservices-Pattern, DDD-Prinzipien, ereignisgesteuerte Architektur und Multiplatform-Strategie" + --- -## 🏗️ Vision & Architektonische Grundpfeiler +## 🏗️ Vision & architektonische Grundpfeiler Dieses Dokument definiert die verbindlichen technischen Richtlinien und Qualitätsstandards für das Projekt "Meldestelle_Pro". Ziel ist die Schaffung einer modernen, skalierbaren und wartbaren Plattform für den Pferdesport. @@ -34,12 +35,12 @@ Dieses Dokument definiert die verbindlichen technischen Richtlinien und Qualitä ### Architektur-Säulen im Detail -| Säule | Technologie | Zweck | Umsetzung | -|-------|------------|-------|-----------| -| Microservices | Spring Boot, Docker | Modularität & Skalierbarkeit | Service-per-Domain-Pattern | -| DDD | Kotlin, Clean Architecture | Fachlichkeit im Code | Bounded Contexts, Domain Events | -| EDA | Kafka, Events | Entkopplung & Resilienz | Asynchrone Kommunikation | -| KMP | Kotlin Multiplatform | Effizienz & Konsistenz | Shared Business Logic | +| Säule | Technologie | Zweck | Umsetzung | +|---------------|----------------------------|------------------------------|---------------------------------| +| Microservices | Spring Boot, Docker | Modularität & Skalierbarkeit | Service-per-Domain-Pattern | +| DDD | Kotlin, Clean Architecture | Fachlichkeit im Code | Bounded Contexts, Domain Events | +| EDA | Kafka, Events | Entkopplung & Resilienz | Asynchrone Kommunikation | +| KMP | Kotlin Multiplatform | Effizienz & Konsistenz | Shared Business Logic | ## 🔧 Backend-Entwicklungsrichtlinien @@ -47,7 +48,7 @@ Dieses Dokument definiert die verbindlichen technischen Richtlinien und Qualitä Jeder fachliche Microservice folgt der 4-Layer-Struktur (`api`, `application`, `domain`, `infrastructure`). -``` +```plaintext service-name/ ├── service-name-api/ # REST-Endpoints, DTOs ├── service-name-application/ # Use Cases, Commands, Queries @@ -120,7 +121,7 @@ value class MemberId(val value: UUID) { } } -data class Member private constructor( +data class Member( val id: MemberId, val name: String, val email: Email, @@ -236,7 +237,7 @@ Das Frontend folgt konsequent dem **Model-View-ViewModel (MVVM)**-Muster und der ### Multiplatform-Struktur -``` +```plaintext client/ ├── src/commonMain/kotlin/ # Shared Business Logic │ ├── domain/ # Domain Models @@ -330,7 +331,7 @@ fun MemberListScreen( ### Bounded Contexts -``` +```plaintext Meldestelle-Domain/ ├── member-context/ # Mitgliederverwaltung ├── tournament-context/ # Turnierverwaltung @@ -489,7 +490,7 @@ fun createMember(@RequestBody request: CreateMemberRequest): ResponseEntity **🤖 AI-Assistant Hinweis:** -> Alle Kotlin-Code muss den offiziellen Kotlin Coding Conventions entsprechen: +> Alle Kotlin-Code müssen den offiziellen Kotlin Coding Conventions entsprechen: > - **Detekt-Validierung:** Automatische Code-Style-Prüfung > - **Java 21+ Kompatibilität:** Nutze moderne Java-Features wo sinnvoll > - **Multiplatform:** Code sollte plattformübergreifend funktionieren @@ -69,13 +69,13 @@ logger.info { ### Namenskonventionen-Übersicht -| Element | Convention | Beispiel | -|---------|------------|----------| -| Klassen/Interfaces | PascalCase | `MemberService`, `EventRepository` | -| Funktionen/Variablen | camelCase | `authenticateUser`, `memberRepository` | -| Konstanten | SCREAMING_SNAKE_CASE | `MAX_RETRY_ATTEMPTS` | -| Test-Methoden | Backticks beschreibend | `` `should return Success for valid credentials` `` | -| Enum-Werte | PascalCase | `MemberStatus.ACTIVE` | +| Element | Convention | Beispiel | +|----------------------|------------------------|-----------------------------------------------------| +| Klassen/Interfaces | PascalCase | `MemberService`, `EventRepository` | +| Funktionen/Variablen | camelCase | `authenticateUser`, `memberRepository` | +| Konstanten | SCREAMING_SNAKE_CASE | `MAX_RETRY_ATTEMPTS` | +| Test-Methoden | Backticks beschreibend | `` `should return Success for valid credentials` `` | +| Enum-Werte | PascalCase | `MemberStatus.ACTIVE` | ### Code-Qualitäts-Checkliste @@ -88,6 +88,7 @@ logger.info { ### Häufige Code-Patterns #### Typsichere IDs + ```kotlin @JvmInline value class EntityId(val value: UUID) { @@ -102,6 +103,7 @@ value class EntityId(val value: UUID) { ``` #### Error-Handling mit Result + ```kotlin interface EntityRepository { suspend fun findById(id: EntityId): Result @@ -116,6 +118,7 @@ when (val result = repository.findById(entityId)) { ``` #### Structured Logging + ```kotlin class EntityService { private val logger = LoggerFactory.getLogger(EntityService::class.java) @@ -149,6 +152,7 @@ class EntityService { ``` #### Sealed Class Hierarchie für Fehler + ```kotlin sealed interface DomainError { val message: String @@ -210,7 +214,7 @@ potential-bugs: --- **Navigation:** -- [Master-Guideline](../master-guideline.md) - Übergeordnete Projektrichtlinien +- [Master-Guideline](../master-guideline.md) - übergeordnete Projektrichtlinien - [Testing-Standards](./testing-standards.md) - Test-Qualitätsstandards - [Documentation-Standards](./documentation-standards.md) - Dokumentationsrichtlinien - [Architecture-Principles](./architecture-principles.md) - Architektur-Grundsätze diff --git a/.junie/guidelines/project-standards/documentation-standards.md b/.junie/guidelines/project-standards/documentation-standards.md index 21627eef..c8fb2ee3 100644 --- a/.junie/guidelines/project-standards/documentation-standards.md +++ b/.junie/guidelines/project-standards/documentation-standards.md @@ -1,6 +1,7 @@ # Documentation Standards --- + guideline_type: "project-standards" scope: "documentation-standards" audience: ["developers", "ai-assistants", "technical-writers"] @@ -8,6 +9,7 @@ last_updated: "2025-09-15" dependencies: ["master-guideline.md"] related_files: ["README*.md", "docs/**", "*.md", "openapi.yaml"] ai_context: "Documentation language standards, README structure, API documentation, and technical writing guidelines" + --- ## 📝 Dokumentationsstandards @@ -41,39 +43,50 @@ ai_context: "Documentation language standards, README structure, API documentati # [Projekt/Modul Name] ## Überblick + [Kurze Beschreibung des Zwecks und der Funktionalität] ## Architektur + [Architektonische Entscheidungen und Komponenten-Übersicht] ## Entwicklung + [Setup-Anweisungen für lokale Entwicklung] ### Voraussetzungen + [Erforderliche Tools und Versionen] ### Installation + [Schritt-für-Schritt Setup-Anleitung] ### Konfiguration + [Wichtige Konfigurationsoptionen] ## Tests + [Test-Ausführung und Test-Strategie] ## Deployment + [Deployment-Anweisungen für verschiedene Umgebungen] ## API-Dokumentation + [Links zu API-Docs oder eingebettete Dokumentation] ## Troubleshooting + [Häufige Probleme und Lösungen] ``` ### Code-Kommentar-Standards #### Deutsche Geschäftslogik-Kommentare + ```kotlin /** * Prüft, ob ein Mitglied für die Anmeldung zu einem Turnier berechtigt ist. @@ -95,6 +108,7 @@ fun isEligibleForTournament(member: Member, tournament: Tournament): Result( ### OpenAPI-Dokumentation Standards #### Deutsche API-Beschreibungen + ```yaml openapi: 3.0.0 info: @@ -181,6 +196,7 @@ components: ### Dokumentations-Checkliste #### README-Dateien + - [ ] **Struktur:** Folgt dem Standard-Template - [ ] **Sprache:** Auf Deutsch verfasst - [ ] **Aktualität:** Entspricht dem aktuellen Code-Stand @@ -189,6 +205,7 @@ components: - [ ] **Links:** Funktionierende Verweise auf verwandte Dokumentation #### API-Dokumentation + - [ ] **OpenAPI-Spezifikation:** Vollständig und valide - [ ] **Deutsche Beschreibungen:** Für alle Endpunkte und Schemas - [ ] **Beispiele:** Realistische Request/Response-Beispiele @@ -196,6 +213,7 @@ components: - [ ] **Authentifizierung:** Sicherheitsanforderungen dokumentiert #### Code-Kommentare + - [ ] **Geschäftslogik:** Deutsche Kommentare für fachliche Aspekte - [ ] **Technische Details:** Englische Kommentare für Framework-/Library-Code - [ ] **Komplexität:** Komplexe Algorithmen sind erklärt @@ -205,8 +223,8 @@ components: ### Dokumentations-Patterns #### Architektur-Diagramme -```markdown -## System-Architektur + +### System-Architektur ```mermaid graph TB @@ -239,16 +257,17 @@ graph TB TS --> PG NS --> RD ``` -``` #### Feature-Dokumentation -```markdown + ## Feature: Turnier-Anmeldung ### Fachlicher Überblick + Die Turnier-Anmeldung ermöglicht es Mitgliedern, sich für Turniere zu registrieren. ### User Stories + - Als Mitglied möchte ich mich für ein Turnier anmelden können - Als Turnierleiter möchte ich Anmeldungen verwalten können @@ -260,20 +279,22 @@ Die Turnier-Anmeldung ermöglicht es Mitgliedern, sich für Turniere zu registri - `DELETE /registrations/{id}` - Anmeldung stornieren #### Domain-Events + - `TournamentRegistrationCreated` - Bei erfolgreicher Anmeldung - `TournamentRegistrationCancelled` - Bei Stornierung ### Business Rules + 1. Anmeldung nur für aktive Mitglieder möglich 2. Anmeldeschluss muss beachtet werden 3. Maximale Teilnehmerzahl darf nicht überschritten werden -``` #### Troubleshooting-Dokumentation -```markdown + ## Häufige Probleme ### Problem: Service startet nicht + **Symptome:** Container bleibt im Status "Restarting" **Ursachen:** @@ -287,6 +308,7 @@ Die Turnier-Anmeldung ermöglicht es Mitgliedern, sich für Turniere zu registri 3. Port-Konflikte lösen: `netstat -tulpn | grep :8080` ### Problem: Langsame API-Antworten + **Symptome:** Response-Zeiten > 2 Sekunden **Debugging:** @@ -302,16 +324,17 @@ docker-compose exec redis redis-cli info stats - Database-Indizes überprüfen - Query-Performance analysieren - Cache-Hit-Rate optimieren -``` ### Versionierung und Updates #### Dokumentations-Versionierung + - README-Dateien werden mit dem Code versioniert - API-Dokumentation folgt Semantic Versioning - Changelog wird für breaking changes geführt #### Update-Prozess + 1. **Code-Änderungen** → README aktualisieren 2. **API-Änderungen** → OpenAPI-Spec anpassen 3. **Architektur-Änderungen** → Diagramme überarbeiten diff --git a/.junie/guidelines/project-standards/testing-standards.md b/.junie/guidelines/project-standards/testing-standards.md index 5479b846..5789392e 100644 --- a/.junie/guidelines/project-standards/testing-standards.md +++ b/.junie/guidelines/project-standards/testing-standards.md @@ -1,6 +1,7 @@ # Testing Standards und Qualitätssicherung --- + guideline_type: "project-standards" scope: "testing-standards" audience: ["developers", "ai-assistants"] @@ -8,6 +9,7 @@ last_updated: "2025-09-15" dependencies: ["master-guideline.md", "coding-standards.md"] related_files: ["build.gradle.kts", "src/test/**", "testcontainers.properties"] ai_context: "Testing strategies, test pyramid, tools, coverage requirements, and debugging practices" + --- ## 🧪 Testing Standards @@ -16,7 +18,7 @@ Tests sind ein integraler Bestandteil jedes Features und müssen einen hohen Sta > **🤖 AI-Assistant Hinweis:** > Testing-Prinzipien für das Meldestelle-Projekt: -> - **Test-Pyramide:** 80%+ Unit-Tests, Integrationstests für externe Systeme +> - **Test-Pyramide:** 80 %+ Unit-Tests, Integrationstests für externe Systeme > - **Testcontainers:** Goldstandard für Infrastruktur-Tests > - **Debug-Logs:** Präfix `[DEBUG_LOG]` für Test-Ausgaben > - **Result-Pattern:** Tests müssen auch Error-Handling validieren @@ -208,15 +210,16 @@ fun `should handle complex business scenario`() { ### Test-Kategorien und Werkzeuge -| Test-Typ | Coverage-Ziel | Werkzeuge | Verwendung | -|----------|---------------|-----------|------------| -| Unit-Tests | 80%+ | JUnit 5, MockK, AssertJ | Domänen- & Anwendungslogik | -| Integrationstests | Alle Repositories | Testcontainers, JUnit 5 | Externe Integrationen | -| End-to-End Tests | Kritische User-Journeys | Testcontainers, REST Assured | Vollständige Workflows | +| Test-Typ | Coverage-Ziel | Werkzeuge | Verwendung | +|-------------------|-------------------------|------------------------------|----------------------------| +| Unit-Tests | 80%+ | JUnit 5, MockK, AssertJ | Domänen- & Anwendungslogik | +| Integrationstests | Alle Repositories | Testcontainers, JUnit 5 | Externe Integrationen | +| End-to-End Tests | Kritische User-Journeys | Testcontainers, REST Assured | Vollständige Workflows | ### Testcontainer-Konfiguration -#### PostgreSQL +#### PostgresQL + ```kotlin @Container private val postgresContainer = PostgreSQLContainer("postgres:16-alpine") @@ -227,6 +230,7 @@ private val postgresContainer = PostgreSQLContainer("postgres:16-alpine") ``` #### Redis + ```kotlin @Container private val redisContainer = GenericContainer("redis:7-alpine") @@ -235,6 +239,7 @@ private val redisContainer = GenericContainer("redis:7-alpine") ``` #### Kafka + ```kotlin @Container private val kafkaContainer = KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:7.4.0")) @@ -242,6 +247,7 @@ private val kafkaContainer = KafkaContainer(DockerImageName.parse("confluentinc/ ``` #### Keycloak + ```kotlin @Container private val keycloakContainer = KeycloakContainer("quay.io/keycloak/keycloak:26.0.7") @@ -373,7 +379,7 @@ fun `should handle high load efficiently`() { --- **Navigation:** -- [Master-Guideline](../master-guideline.md) - Übergeordnete Projektrichtlinien +- [Master-Guideline](../master-guideline.md) - übergeordnete Projektrichtlinien - [Coding-Standards](./coding-standards.md) - Code-Qualitätsstandards - [Documentation-Standards](./documentation-standards.md) - Dokumentationsrichtlinien - [Architecture-Principles](./architecture-principles.md) - Architektur-Grundsätze diff --git a/.junie/guidelines/technology-guides/docker/docker-architecture.md b/.junie/guidelines/technology-guides/docker/docker-architecture.md index 1641448f..bbdc8ce1 100644 --- a/.junie/guidelines/technology-guides/docker/docker-architecture.md +++ b/.junie/guidelines/technology-guides/docker/docker-architecture.md @@ -1,6 +1,7 @@ # Docker-Architektur und Services --- + guideline_type: "technology" scope: "docker-architecture" audience: ["developers", "ai-assistants", "devops"] @@ -8,16 +9,19 @@ last_updated: "2025-09-15" dependencies: ["docker-overview.md", "master-guideline.md"] related_files: ["docker-compose.yml", "docker/versions.toml", "scripts/docker-versions-update.sh"] ai_context: "Docker-Container-Architektur, Service-Definitionen und zentrale Versionsverwaltung" + --- ## 🏗️ Architektur-Überblick +> **📖 Hinweis:** Für einen allgemeinen Überblick über die Docker-Infrastruktur siehe [docker-overview](docker-overview.md). + ### Container-Kategorien ```mermaid graph TB subgraph "Infrastructure Services" - PG[PostgreSQL] + PG[PostgresQL] RD[Redis] KC[Keycloak] KF[Kafka+Zookeeper] @@ -51,20 +55,20 @@ graph TB ### Service-Ports Matrix -| Service | Development | Production | Health Check | Debug Port | Version | -|---------|------------|------------|--------------|------------|---------| -| PostgreSQL | 5432 | Internal | pg_isready -U meldestelle -d meldestelle | - | 16-alpine | -| Redis | 6379 | Internal | redis-cli ping | - | 7-alpine | -| Keycloak | 8180 | 8443 (HTTPS) | /health/ready | - | 26.0.7 | -| Kafka | 9092 | Internal | kafka-topics --bootstrap-server localhost:9092 --list | - | 7.4.0 | -| Zookeeper | 2181 | Internal | nc -z localhost 2181 | - | 7.4.0 | -| Consul | 8500 | Internal | /v1/status/leader | - | 1.15 | -| Auth Server | 8081 | Internal | /actuator/health/readiness | 5005 | 1.0.0 | -| Ping Service | 8082 | Internal | /actuator/health/readiness | 5005 | 1.0.0 | -| Monitoring Server | 8083 | Internal | /actuator/health/readiness | 5005 | 1.0.0 | -| Prometheus | 9090 | Internal | /-/healthy | - | v2.54.1 | -| Grafana | 3000 | 3443 (HTTPS) | /api/health | - | 11.3.0 | -| Nginx | - | 80/443 | /health | - | 1.25-alpine | +| Service | Development | Production | Health Check | Debug Port | Version | +|-------------------|-------------|--------------|-------------------------------------------------------|------------|-------------| +| PostgreSQL | 5432 | Internal | pg_isready -U meldestelle -d meldestelle | - | 16-alpine | +| Redis | 6379 | Internal | redis-cli ping | - | 7-alpine | +| Keycloak | 8180 | 8443 (HTTPS) | /health/ready | - | 26.0.7 | +| Kafka | 9092 | Internal | kafka-topics --bootstrap-server localhost:9092 --list | - | 7.4.0 | +| Zookeeper | 2181 | Internal | nc -z localhost 2181 | - | 7.4.0 | +| Consul | 8500 | Internal | /v1/status/leader | - | 1.15 | +| Auth Server | 8081 | Internal | /actuator/health/readiness | 5005 | 1.0.0 | +| Ping Service | 8082 | Internal | /actuator/health/readiness | 5005 | 1.0.0 | +| Monitoring Server | 8083 | Internal | /actuator/health/readiness | 5005 | 1.0.0 | +| Prometheus | 9090 | Internal | /-/healthy | - | v2.54.1 | +| Grafana | 3000 | 3443 (HTTPS) | /api/health | - | 11.3.0 | +| Nginx | - | 80/443 | /health | - | 1.25-alpine | ## 🎯 Zentrale Docker-Versionsverwaltung @@ -93,18 +97,18 @@ ARG GRADLE_VERSION=9.0.0 ```toml # docker/versions.toml - SINGLE SOURCE OF TRUTH [versions] -gradle = "9.0.0" +gradle = "9.1.0" java = "21" -node = "20.12.0" -nginx = "1.25-alpine" +node = "22.21.0" +nginx = "1.28.0-alpine" prometheus = "v2.54.1" grafana = "11.3.0" -keycloak = "26.0.7" +keycloak = "26.4.2" ``` ### 🏗️ Architektur der zentralen Versionsverwaltung -``` +```plaintext docker/ ├── versions.toml # 🎯 Single Source of Truth ├── build-args/ # Auto-generierte Environment Files @@ -118,10 +122,11 @@ docker/ ### 📊 Hierarchische Versionsverwaltung #### 1. **Globale Versionen** (`docker/build-args/global.env`) + Verwendet von **allen** Dockerfiles: ```bash # --- Build Tools --- -GRADLE_VERSION=9.0.0 +GRADLE_VERSION=9.1.0 JAVA_VERSION=21 # --- Build Metadata --- @@ -136,7 +141,7 @@ ECLIPSE_TEMURIN_JRE_VERSION=21-jre-alpine # --- Monitoring & Infrastructure Services --- DOCKER_PROMETHEUS_VERSION=v2.54.1 DOCKER_GRAFANA_VERSION=11.3.0 -DOCKER_KEYCLOAK_VERSION=26.0.7 +DOCKER_KEYCLOAK_VERSION=26.4.2 ``` #### 2. **Kategorie-spezifische Versionen** @@ -151,8 +156,8 @@ MEMBERS_SERVICE_PORT=8083 **Clients** (`docker/build-args/clients.env`): ```bash -NODE_VERSION=20.11.0 -NGINX_VERSION=1.25-alpine +NODE_VERSION=22.21.0 +NGINX_VERSION=1.28.0-alpine WEB_APP_PORT=4000 DESKTOP_APP_VNC_PORT=5901 ``` @@ -201,7 +206,7 @@ AUTH_SERVER_PORT=8087 ./scripts/docker-versions-update.sh update grafana 11.3.0 # Keycloak auf neueste Version upgraden -./scripts/docker-versions-update.sh update keycloak 26.0.7 +./scripts/docker-versions-update.sh update keycloak 26.4.2 # Alle Environment-Dateien synchronisieren ./scripts/docker-versions-update.sh sync @@ -210,12 +215,13 @@ AUTH_SERVER_PORT=8087 ## 🎯 Für AI-Assistenten: Architektur-Schnellreferenz ### Service-Kategorien -- **Infrastructure:** PostgreSQL, Redis, Keycloak, Kafka, Zookeeper, Consul +- **Infrastructure:** PostgresQL, Redis, Keycloak, Kafka, Zookeeper, Consul - **Application:** API Gateway, Auth Server, Monitoring Server, Ping Service - **Clients:** Web App (Port 3000), Desktop App - **Monitoring:** Prometheus (9090), Grafana (3000), Zipkin, Nginx ### Wichtige Befehle + ```bash # Service-Status prüfen docker-compose ps @@ -232,6 +238,7 @@ docker-compose restart ``` ### Zentrale Konfigurationsdateien + - `docker/versions.toml` - Alle Versionen - `docker-compose.yml` - Haupt-Services - `docker-compose.clients.yml` - Client-Anwendungen @@ -240,6 +247,7 @@ docker-compose restart --- **Navigation:** +- [master-guideline](../../master-guideline.md) – Hauptrichtlinie für das Projekt - [Docker-Overview](./docker-overview.md) - Grundlagen und Philosophie - [Docker-Development](./docker-development.md) - Entwicklungsworkflow - [Docker-Production](./docker-production.md) - Production-Deployment diff --git a/.junie/guidelines/technology-guides/docker/docker-development.md b/.junie/guidelines/technology-guides/docker/docker-development.md index e9cf6ee6..64e9e278 100644 --- a/.junie/guidelines/technology-guides/docker/docker-development.md +++ b/.junie/guidelines/technology-guides/docker/docker-development.md @@ -1,6 +1,7 @@ # Docker-Development Workflow --- + guideline_type: "technology" scope: "docker-development" audience: ["developers", "ai-assistants"] @@ -8,10 +9,16 @@ last_updated: "2025-09-15" dependencies: ["docker-overview.md", "docker-architecture.md"] related_files: ["docker-compose.yml", "docker-compose.override.yml", "Makefile"] ai_context: "Entwicklungs-Workflow, Debugging und lokale Entwicklungsumgebung mit Docker" + --- ## 🛠️ Development-Workflow +> **📖 Hinweis:** Für einen allgemeinen Überblick über die Docker-Infrastruktur +> siehe [docker-overview](docker-overview.md). +> Für Details zur Container-Architektur siehe [docker-architecture](docker-architecture.md). +> Für Production-Deployment siehe [docker-production](docker-production.md). + ### Schnellstart-Befehle ```bash @@ -116,15 +123,16 @@ curl -s http://localhost:8080/actuator/health | jq ### Häufige Entwicklungsaufgaben -| Aufgabe | Befehl | Beschreibung | -|---------|---------|--------------| -| Umgebung starten | `make dev-up` | Alle Services für Development | -| Service debuggen | `docker-compose exec sh` | Shell im Container | -| Logs verfolgen | `docker-compose logs -f ` | Live-Logs anzeigen | -| Service neu bauen | `make service-build SERVICE=` | Einzelnen Service rebuilden | -| Health-Check | `curl localhost:/actuator/health` | Service-Status prüfen | +| Aufgabe | Befehl | Beschreibung | +|-------------------|-----------------------------------------|-------------------------------| +| Umgebung starten | `make dev-up` | Alle Services für Development | +| Service debuggen | `docker-compose exec sh` | Shell im Container | +| Logs verfolgen | `docker-compose logs -f ` | Live-Logs anzeigen | +| Service neu bauen | `make service-build SERVICE=` | Einzelnen Service rebuilden | +| Health-Check | `curl localhost:/actuator/health` | Service-Status prüfen | ### Development-URLs + - **Grafana:** http://localhost:3000 (admin/admin) - **Prometheus:** http://localhost:9090 - **API Gateway:** http://localhost:8080 @@ -132,6 +140,7 @@ curl -s http://localhost:8080/actuator/health | jq - **Keycloak:** http://localhost:8180 ### Debug-Ports + - **Spring-Services:** 5005 (Standard Java Debug) - **Web-App:** Hot-Reload über Volume-Mapping - **Client-Apps:** Port 4000 (Web), 5901 (Desktop VNC) @@ -139,6 +148,7 @@ curl -s http://localhost:8080/actuator/health | jq ### Troubleshooting Development #### Container startet nicht + ```bash # Container-Status prüfen docker-compose ps @@ -154,6 +164,7 @@ docker-compose build --no-cache ``` #### Port-Konflikte + ```bash # Ports prüfen netstat -tulpn | grep : @@ -163,6 +174,7 @@ docker-compose -f docker-compose.yml -f docker-compose.override.yml up -d ``` #### Volume-Probleme + ```bash # Volumes prüfen docker volume ls @@ -177,5 +189,5 @@ docker-compose exec ls -la /path/to/volume - [Docker-Overview](./docker-overview.md) - Grundlagen und Philosophie - [Docker-Architecture](./docker-architecture.md) - Container-Services und Struktur - [Docker-Production](./docker-production.md) - Production-Deployment -- [Docker-Monitoring](./docker-monitoring.md) - Observability -- [Docker-Troubleshooting](./docker-troubleshooting.md) - Problemlösung +- [docker-monitoring](./docker-monitoring.md) - Observability +- [docker-troubleshooting](./docker-troubleshooting.md) - Problemlösung diff --git a/.junie/guidelines/technology-guides/docker/docker-monitoring.md b/.junie/guidelines/technology-guides/docker/docker-monitoring.md index 787aa1d8..0ad7a5ba 100644 --- a/.junie/guidelines/technology-guides/docker/docker-monitoring.md +++ b/.junie/guidelines/technology-guides/docker/docker-monitoring.md @@ -1,6 +1,7 @@ # Docker-Monitoring und Observability --- + guideline_type: "technology" scope: "docker-monitoring" audience: ["developers", "devops", "ai-assistants"] @@ -8,6 +9,7 @@ last_updated: "2025-09-15" dependencies: ["docker-overview.md", "docker-architecture.md"] related_files: ["docker-compose.yml", "config/monitoring/*", "config/grafana/*", "config/prometheus/*"] ai_context: "Monitoring-Setup, Prometheus-Metriken, Grafana-Dashboards, Health-Checks und Log-Aggregation" + --- ## 📊 Monitoring und Observability @@ -44,13 +46,13 @@ labels: ### Health Check Matrix -| Service | Endpoint | Erwartung | Timeout | -|---------|----------|-----------|---------| -| API Gateway | `/actuator/health` | `{"status":"UP"}` | 15s | -| Ping Service | `/actuator/health/readiness` | HTTP 200 | 3s | -| PostgreSQL | `pg_isready` | Connection OK | 5s | -| Redis | `redis-cli ping` | PONG | 5s | -| Keycloak | `/health/ready` | HTTP 200 | 5s | +| Service | Endpoint | Erwartung | Timeout | +|--------------|------------------------------|-------------------|---------| +| API Gateway | `/actuator/health` | `{"status":"UP"}` | 15s | +| Ping Service | `/actuator/health/readiness` | HTTP 200 | 3s | +| PostgreSQL | `pg_isready` | Connection OK | 5s | +| Redis | `redis-cli ping` | PONG | 5s | +| Keycloak | `/health/ready` | HTTP 200 | 5s | ### Log Aggregation @@ -65,6 +67,7 @@ docker-compose logs --follow --tail=100 api-gateway | jq -r '.message' ## 🎯 AI-Assistenten: Monitoring-Schnellreferenz ### Monitoring-URLs + - **Grafana Dashboard:** http://localhost:3000 (admin/admin) - **Prometheus Targets:** http://localhost:9090/targets - **Prometheus Metrics:** http://localhost:9090/metrics @@ -72,13 +75,13 @@ docker-compose logs --follow --tail=100 api-gateway | jq -r '.message' ### Wichtige Metrics -| Metric-Typ | Beispiel | Beschreibung | -|------------|----------|--------------| -| JVM Memory | `jvm_memory_used_bytes` | Speicherverbrauch Java-Services | -| HTTP Requests | `http_requests_total` | API-Request-Zähler | -| Database Connections | `hikaricp_connections` | Pool-Verbindungen | -| Kafka Lag | `kafka_consumer_lag` | Consumer-Verzögerung | -| Custom Business | `meldestelle_registrations_total` | Fachliche KPIs | +| Metric-Typ | Beispiel | Beschreibung | +|----------------------|-----------------------------------|---------------------------------| +| JVM Memory | `jvm_memory_used_bytes` | Speicherverbrauch Java-Services | +| HTTP Requests | `http_requests_total` | API-Request-Zähler | +| Database Connections | `hikaricp_connections` | Pool-Verbindungen | +| Kafka Lag | `kafka_consumer_lag` | Consumer-Verzögerung | +| Custom Business | `meldestelle_registrations_total` | Fachliche KPIs | ### Health-Check Befehle @@ -115,6 +118,7 @@ docker-compose logs api-gateway | grep -i "took\|duration\|time" ### Dashboard-Setup #### Infrastructure-Dashboard + ```json { "dashboard": { @@ -142,6 +146,7 @@ docker-compose logs api-gateway | grep -i "took\|duration\|time" ``` #### Application-Dashboard + ```json { "dashboard": { @@ -245,8 +250,8 @@ scrape_configs: --- **Navigation:** -- [Docker-Overview](./docker-overview.md) - Grundlagen und Philosophie -- [Docker-Architecture](./docker-architecture.md) - Container-Services und Struktur -- [Docker-Development](./docker-development.md) - Entwicklungsworkflow -- [Docker-Production](./docker-production.md) - Production-Deployment -- [Docker-Troubleshooting](./docker-troubleshooting.md) - Problemlösung +- [docker-overview](./docker-overview.md) - Grundlagen und Philosophie +- [docker-architecture](./docker-architecture.md) - Container-Services und Struktur +- [docker-development](./docker-development.md) - Entwicklungsworkflow +- [docker-production](./docker-production.md) - Production-Deployment +- [docker-troubleshooting](./docker-troubleshooting.md) - Problemlösung diff --git a/.junie/guidelines/technology-guides/docker/docker-overview.md b/.junie/guidelines/technology-guides/docker/docker-overview.md index 7dc1be0d..cf9c971c 100644 --- a/.junie/guidelines/technology-guides/docker/docker-overview.md +++ b/.junie/guidelines/technology-guides/docker/docker-overview.md @@ -1,6 +1,7 @@ # Docker-Overview und Philosophie --- + guideline_type: "technology" scope: "docker-overview" audience: ["developers", "ai-assistants", "devops"] @@ -8,6 +9,7 @@ last_updated: "2025-09-15" dependencies: ["master-guideline.md"] related_files: ["docker-compose.yml", "docker/versions.toml"] ai_context: "Docker-Philosophie und allgemeine Prinzipien für das Meldestelle-Projekt" + --- ## 🚀 Überblick und Philosophie @@ -29,6 +31,7 @@ Das Meldestelle-Projekt implementiert eine **moderne, sicherheitsorientierte Con > - Monitoring läuft unter `http://localhost:3001` (Grafana) ### Zentrale Dateien für AI-Referenz + - `docker/versions.toml` - Single Source of Truth für alle Versionen - `docker-compose.yml` - Haupt-Service-Orchestrierung - `scripts/docker-versions-update.sh` - Automatische Version-Updates @@ -37,27 +40,30 @@ Das Meldestelle-Projekt implementiert eine **moderne, sicherheitsorientierte Con ## 📋 Docker-Guidelines Navigation Für spezifische Docker-Themen siehe: -- [Docker-Architektur](./docker-architecture.md) - Container-Services und Struktur -- [Docker-Development](./docker-development.md) - Entwicklungsworkflow -- [Docker-Production](./docker-production.md) - Production-Deployment -- [Docker-Monitoring](./docker-monitoring.md) - Observability und Überwachung -- [Docker-Troubleshooting](./docker-troubleshooting.md) - Problemlösung +- [docker-architecture](./docker-architecture.md) - Container-Services und Struktur +- [docker-development](./docker-development.md) - Entwicklungsworkflow +- [docker-production](./docker-production.md) - Production-Deployment +- [docker-monitoring](./docker-monitoring.md) - Observability und Überwachung +- [docker-troubleshooting](./docker-troubleshooting.md) - Problemlösung ## Grundprinzipien ### Sicherheitsaspekte + - **Non-Root-Container**: Alle Container laufen mit dediziertem User - **Minimale Base-Images**: Verwendung schlanker Images (Alpine, Distroless) - **Security-Scans**: Regelmäßige Vulnerability-Checks - **Network-Segmentierung**: Isolierte Docker-Networks ### Performance-Optimierung + - **Multi-Stage-Builds**: Schlanke Production-Images - **Layer-Caching**: Optimale Build-Performance - **Resource-Limits**: Definierte CPU/Memory-Constraints - **Health-Checks**: Proaktive Service-Überwachung ### Wartbarkeit + - **Standardisierte Templates**: Konsistente Dockerfile-Struktur - **Zentrale Konfiguration**: Environment-basierte Konfiguration - **Dokumentation**: Umfassende README-Dateien pro Service diff --git a/.junie/guidelines/technology-guides/docker/docker-production.md b/.junie/guidelines/technology-guides/docker/docker-production.md index 9fa9fd30..3ce63647 100644 --- a/.junie/guidelines/technology-guides/docker/docker-production.md +++ b/.junie/guidelines/technology-guides/docker/docker-production.md @@ -1,6 +1,7 @@ # Docker-Production Deployment --- + guideline_type: "technology" scope: "docker-production" audience: ["developers", "devops", "ai-assistants"] @@ -8,6 +9,7 @@ last_updated: "2025-09-15" dependencies: ["docker-overview.md", "docker-architecture.md"] related_files: ["docker-compose.yml", "config/nginx/nginx.prod.conf", "config/ssl/*"] ai_context: "Production-Deployment, Security-Hardening, SSL/TLS-Konfiguration und Ressourcenverwaltung" + --- ## 🚀 Production-Deployment @@ -136,12 +138,14 @@ services: ## 🎯 AI-Assistenten: Production-Schnellreferenz ### Production-Domains + - **API:** api.meldestelle.at (HTTPS) - **Auth:** auth.meldestelle.at (HTTPS) - **Monitoring:** monitor.meldestelle.at (HTTPS) - **Metrics:** metrics.meldestelle.at (HTTPS) ### Security-Checkliste + - [ ] SSL/TLS-Zertifikate installiert und gültig - [ ] Alle Passwörter mit `openssl rand -base64 32` generiert - [ ] Nginx Security Headers konfiguriert @@ -151,13 +155,13 @@ services: ### Production-Befehle -| Aufgabe | Befehl | Beschreibung | -|---------|---------|--------------| -| Zertifikat erneuern | `certbot renew` | Let's Encrypt Zertifikate | -| SSL-Status prüfen | `openssl s_client -connect api.meldestelle.at:443` | SSL-Verbindung testen | -| Resource-Usage | `docker stats` | Container-Ressourcen | -| Security-Scan | `docker scan ` | Vulnerability Check | -| Log-Rotation | `docker system prune -f` | Alte Logs bereinigen | +| Aufgabe | Befehl | Beschreibung | +|---------------------|----------------------------------------------------|---------------------------| +| Zertifikat erneuern | `certbot renew` | Let's Encrypt Zertifikate | +| SSL-Status prüfen | `openssl s_client -connect api.meldestelle.at:443` | SSL-Verbindung testen | +| Resource-Usage | `docker stats` | Container-Ressourcen | +| Security-Scan | `docker scan ` | Vulnerability Check | +| Log-Rotation | `docker system prune -f` | Alte Logs bereinigen | ### Environment-Variablen Validierung @@ -219,8 +223,8 @@ curl -s https://monitor.meldestelle.at/api/health | jq '.database' --- **Navigation:** -- [Docker-Overview](./docker-overview.md) - Grundlagen und Philosophie -- [Docker-Architecture](./docker-architecture.md) - Container-Services und Struktur -- [Docker-Development](./docker-development.md) - Entwicklungsworkflow -- [Docker-Monitoring](./docker-monitoring.md) - Observability -- [Docker-Troubleshooting](./docker-troubleshooting.md) - Problemlösung +- [docker-overview](./docker-overview.md) - Grundlagen und Philosophie +- [docker-architecture](./docker-architecture.md) - Container-Services und Struktur +- [docker-development](./docker-development.md) - Entwicklungsworkflow +- [docker-monitoring](./docker-monitoring.md) - Observability +- [docker-troubleshooting](./docker-troubleshooting.md) - Problemlösung diff --git a/.junie/guidelines/technology-guides/docker/docker-troubleshooting.md b/.junie/guidelines/technology-guides/docker/docker-troubleshooting.md index 0e62c091..9b037525 100644 --- a/.junie/guidelines/technology-guides/docker/docker-troubleshooting.md +++ b/.junie/guidelines/technology-guides/docker/docker-troubleshooting.md @@ -1,6 +1,7 @@ # Docker-Troubleshooting und Best Practices --- + guideline_type: "technology" scope: "docker-troubleshooting" audience: ["developers", "devops", "ai-assistants"] @@ -8,6 +9,7 @@ last_updated: "2025-09-15" dependencies: ["docker-overview.md", "docker-architecture.md", "docker-development.md"] related_files: ["docker-compose.yml", "scripts/validate-docker-consistency.sh", "scripts/docker-versions-update.sh"] ai_context: "Fehlerbehebung häufiger Docker-Probleme, Debug-Kommandos und umfassende Best Practices" + --- ## 🔧 Troubleshooting @@ -85,29 +87,32 @@ docker-compose logs -f --tail=50 SERVICE_NAME ### Häufige Befehle -| Problem | Befehl | Beschreibung | -|---------|---------|--------------| -| Port belegt | `netstat -tulpn \| grep :` | Port-Nutzung prüfen | -| Service startet nicht | `docker-compose logs ` | Service-Logs anzeigen | -| Container hängt | `docker stats` | Ressourcenverbrauch | -| DNS-Probleme | `docker-compose exec nslookup ` | DNS-Resolution testen | -| Disk voll | `docker system prune -a --volumes` | Cleanup durchführen | +| Problem | Befehl | Beschreibung | +|-----------------------|---------------------------------------------------|-----------------------| +| Port belegt | `netstat -tulpn \| grep :` | Port-Nutzung prüfen | +| Service startet nicht | `docker-compose logs ` | Service-Logs anzeigen | +| Container hängt | `docker stats` | Ressourcenverbrauch | +| DNS-Probleme | `docker-compose exec nslookup ` | DNS-Resolution testen | +| Disk voll | `docker system prune -a --volumes` | Cleanup durchführen | ### Debug-Workflows #### Service startet nicht + 1. `docker-compose ps` - Status prüfen 2. `docker-compose logs ` - Logs analysieren 3. `docker-compose exec sh` - Container inspizieren 4. Health-Check-Endpoint testen #### Performance-Probleme + 1. `docker stats` - Ressourcenverbrauch 2. `docker-compose top` - Prozess-Übersicht 3. JVM-Parameter optimieren 4. Resource-Limits anpassen #### Netzwerk-Probleme + 1. `docker network ls` - Netzwerke auflisten 2. `docker-compose exec ping ` - Connectivity testen 3. Consul Service-Discovery prüfen @@ -292,8 +297,8 @@ docker-compose up -d && make test --- **Navigation:** -- [Docker-Overview](./docker-overview.md) - Grundlagen und Philosophie -- [Docker-Architecture](./docker-architecture.md) - Container-Services und Struktur -- [Docker-Development](./docker-development.md) - Entwicklungsworkflow -- [Docker-Production](./docker-production.md) - Production-Deployment -- [Docker-Monitoring](./docker-monitoring.md) - Observability +- [docker-overview](./docker-overview.md) - Grundlagen und Philosophie +- [docker-architecture](./docker-architecture.md) - Container-Services und Struktur +- [docker-development](./docker-development.md) - Entwicklungsworkflow +- [docker-production](./docker-production.md) - Production-Deployment +- [docker-monitoring](./docker-monitoring.md) - Observability diff --git a/.junie/guidelines/technology-guides/web-app-guideline.md b/.junie/guidelines/technology-guides/web-app-guideline.md index 73ea0462..0c6271c4 100644 --- a/.junie/guidelines/technology-guides/web-app-guideline.md +++ b/.junie/guidelines/technology-guides/web-app-guideline.md @@ -1,6 +1,7 @@ # Client-App-Richtlinie (Compose Multiplatform) --- + guideline_type: "technology" scope: "web-app-multiplatform" audience: ["developers", "ai-assistants", "frontend-developers"] @@ -8,6 +9,7 @@ last_updated: "2025-09-15" dependencies: ["master-guideline.md", "project-standards/architecture-principles.md"] related_files: ["client/build.gradle.kts", "client/src/commonMain/", "client/src/wasmJsMain/", "client/src/jvmMain/"] ai_context: "Compose Multiplatform-Entwicklung, MVVM-Pattern, KMP-Architektur, Desktop- und Web-Client-Entwicklung" + --- ## 1. Einleitung @@ -25,11 +27,11 @@ Das Hauptziel ist die maximale Wiederverwendung von Code zwischen den Desktop- u ## 2. Grundprinzipien -### Deklarative UI mit Composables +### Deklarative UI mit Composable Die gesamte Benutzeroberfläche wird als Baum von `@Composable`-Funktionen deklariert. Dies ist derselbe Ansatz, der auch bei Jetpack Compose für Android verwendet wird. -- **Zustandslosigkeit:** Composables sollten bevorzugt zustandslos sein. Sie erhalten Daten als Parameter und geben Ereignisse über Lambda-Funktionen (Callbacks) nach oben weiter. +- **Zustandslosigkeit:** Composable sollten bevorzugt zustandslos sein. Sie erhalten Daten als Parameter und geben Ereignisse über Lambda-Funktionen (Callbacks) nach oben weiter. - **Wiederverwendbarkeit:** Erstellen Sie kleine, spezialisierte und wiederverwendbare Composables. Vermeiden Sie monolithische UI-Funktionen. - **Vorschau:** Nutzen Sie `@Preview`-Annotationen (sofern von der IDE unterstützt), um UI-Komponenten isoliert zu entwickeln und zu visualisieren. @@ -46,15 +48,18 @@ Der UI-Zustand (State) wird explizit verwaltet. Das Styling erfolgt plattformspezifisch, aber mit gemeinsamen Prinzipien: #### Gemeinsame Styling-Prinzipien (commonMain) + - **Compose Material Design**: Nutzen Sie Material3-Komponenten und Theming für konsistente UI. -- **Gemeinsame Designsystem**: Definieren Sie gemeinsame Farben, Typografie und Spacing in `commonMain`. +- **Gemeinsames Designsystem**: Definieren Sie gemeinsame Farben, Typografie und Spacing in `commonMain`. - **Responsive Design**: Berücksichtigen Sie verschiedene Bildschirmgrößen (Desktop-Fenster vs. Browser-Viewports). #### Web-spezifisches Styling (wasmJsMain) + - **CSS-Integration**: Web-spezifische Styling-Anforderungen können über CSS in den Resources behandelt werden. - **Browser-Kompatibilität**: Berücksichtigen Sie Web-spezifische Rendering-Unterschiede. #### Desktop-spezifisches Styling (jvmMain) + - **Native Look & Feel**: Desktop-Anwendungen sollten sich nativ anfühlen. - **Fenster-Management**: Berücksichtigen Sie Desktop-spezifische UI-Patterns (Menüleisten, etc.). @@ -71,12 +76,14 @@ fun AppTheme(content: @Composable () -> Unit) { ``` ### Navigation + Die Navigation wird plattformunabhängig in `commonMain` implementiert: - **ViewModel-basierte Navigation**: Ein `StateFlow` oder `mutableState` im ViewModel repräsentiert die aktuelle Route/Screen. - **Gemeinsamer Router**: Ein zentraler `Router`-Composable in `commonMain` reagiert auf Zustandsänderungen und rendert den entsprechenden Screen. - **Plattformspezifische Einstiegspunkte**: Desktop und Web haben separate `main.kt`-Dateien, aber nutzen denselben gemeinsamen App-Composable. ## 3. Projekt- und Code-Struktur + Die Codebasis ist klar zwischen plattformunabhängiger Logik (`commonMain`) und plattformspezifischer Implementation (`jvmMain`, `wasmJsMain`) getrennt. ### Source Sets @@ -89,12 +96,12 @@ Die Codebasis ist klar zwischen plattformunabhängiger Logik (`commonMain`) und - **`client/src/jvmMain`** (Desktop-Plattform): - **`main.kt`**: Der Einstiegspunkt der Desktop-Anwendung. - - **Desktop-spezifische Code**: Plattformspezifische Implementierungen und Integrationen. + - **Desktop-spezifischer Code**: Plattformspezifische Implementierungen und Integrationen. - **Desktop Dependencies**: `compose.desktop.currentOs`, Coroutines für Swing. - **`client/src/wasmJsMain`** (Web-Plattform): - **`main.kt`**: Der Einstiegspunkt der Web-Anwendung (WebAssembly). - - **Web-spezifische Code**: Browser-spezifische Implementierungen. + - **Web-spezifischer Code**: Browser-spezifische Implementierungen. - **Platform-spezifische Implementierungen**: Web-APIs und Browser-Integrationen. - **`client/src/wasmJsMain/resources`**: @@ -102,6 +109,7 @@ Die Codebasis ist klar zwischen plattformunabhängiger Logik (`commonMain`) und - **Statische Assets**: Bilder, Schriftarten und andere statische Dateien für die Web-Version. ### Shared Module Integration + - **`core/commonMain`** (oder äquivalente `shared`-Module): - **Repositories/Services**: Code für den Datenzugriff (z.B. Ktor-HTTP-Clients zum Aufrufen des Backends). - **Business-Logik**: Plattformunabhängige Geschäftslogik, die von allen Client-Plattformen genutzt wird. @@ -109,6 +117,7 @@ Die Codebasis ist klar zwischen plattformunabhängiger Logik (`commonMain`) und ## 4. Entwicklung und Ausführung ### Desktop-Entwicklung + Für die Desktop-Anwendung stehen folgende Gradle-Tasks zur Verfügung: ```shell script @@ -123,6 +132,7 @@ Für die Desktop-Anwendung stehen folgende Gradle-Tasks zur Verfügung: ``` ### Web-Entwicklung mit Hot-Reload + Für die Web-Anwendung mit automatischer Neuladung bei Änderungen: ```shell script @@ -131,6 +141,7 @@ Für die Web-Anwendung mit automatischer Neuladung bei Änderungen: ``` #### Docker-Setup für Web-Entwicklung + Das Docker-Setup ist spezifisch für die Web-Entwicklung konfiguriert (wie in `README-DOCKER.md` beschrieben): ```shell script @@ -144,26 +155,31 @@ Der Dienst ist dann unter dem in der `docker-compose.clients.yml` konfigurierten ### Produktions-Builds #### Desktop-Distribution + ```shell script # Erstellt native Distributionen für alle konfigurierten Plattformen ./gradlew :client:packageDistributionForCurrentOS ``` #### Web-Distribution + ```shell script # Erstellt optimierte WebAssembly-Artefakte für die Produktion ./gradlew :client:wasmJsBrowserDistribution ``` Das Docker-Image für die Web-Produktion (`Dockerfile` im `client`-Verzeichnis) sollte den `wasmJsBrowserDistribution`-Task nutzen, um die finalen Artefakte zu bauen. + ## 5. Plattformspezifische Besonderheiten ### Desktop (jvmMain) + - **Fenster-Management**: Nutzen Sie Compose Desktop-APIs für Fensteroperationen. - **System-Integration**: Zugriff auf Desktop-spezifische Features (Dateisystem, Notifications, etc.). - **Performance**: Desktop-Apps können mehr Ressourcen nutzen als Web-Apps. ### Web (wasmJsMain) + - **Browser-APIs**: Zugriff auf Web-APIs erfolgt über `external`-Deklarationen. - **Bundle-Size**: Achten Sie auf die Größe der WebAssembly-Bundles für optimale Ladezeiten. - **SEO und Accessibility**: Berücksichtigen Sie Web-spezifische Anforderungen. @@ -171,17 +187,20 @@ Das Docker-Image für die Web-Produktion (`Dockerfile` im `client`-Verzeichnis) ## 6. Dos and Don'ts ### Multiplatform Best Practices + - **DO**: Die gesamte UI-Logik (State-Management, Datenabruf, Validierung) in `commonMain` implementieren. -- **DO**: Kleine, wiederverwendbare und zustandslose Composables in `commonMain` erstellen. +- **DO**: Kleine wiederverwendbare und zustandslose Composable in `commonMain` erstellen. - **DO**: Material3 und gemeinsames Theming für konsistente UI zwischen Plattformen verwenden. - **DO**: Events von der UI über Lambda-Funktionen an die ViewModels in `commonMain` weiterleiten. - **DO**: Plattformspezifische Features über `expect`/`actual`-Mechanismus abstrahieren. ### Platform-Specific Guidelines + - **DO** (Desktop): Native Look & Feel und Desktop-UI-Patterns verwenden. - **DO** (Web): Web-Standards und Accessibility-Guidelines befolgen. ### Don'ts + - **DON'T**: Geschäftslogik, API-Aufrufe oder komplexe Zustandsmanipulationen direkt in `@Composable`-Funktionen schreiben. - **DON'T**: Plattformspezifische Code direkt in `commonMain` verwenden ohne `expect`/`actual`. - **DON'T** (Web): Den DOM direkt manipulieren. Compose Multiplatform verwaltet das Rendering. Falls Interaktion mit externen Bibliotheken nötig ist, nutzen Sie `external`-Mechanismen sauber gekapselt. @@ -190,9 +209,8 @@ Das Docker-Image für die Web-Produktion (`Dockerfile` im `client`-Verzeichnis) --- **Navigation:** -- [Master-Guideline](../master-guideline.md) - Übergeordnete Projektrichtlinien +- [Master-Guideline](../master-guideline.md) - übergeordnete Projektrichtlinien - [Architecture-Principles](../project-standards/architecture-principles.md) - Architektur-Grundsätze - [Coding-Standards](../project-standards/coding-standards.md) - Code-Qualitätsstandards - [Testing-Standards](../project-standards/testing-standards.md) - Test-Qualitätssicherung - [Trace-Bullet-Guideline](../process-guides/trace-bullet-guideline.md) - Entwicklungszyklus - diff --git a/.junie/scripts/check-docs-drift.sh b/.junie/scripts/check-docs-drift.sh index 0d9e7d2c..4440138d 100644 --- a/.junie/scripts/check-docs-drift.sh +++ b/.junie/scripts/check-docs-drift.sh @@ -27,4 +27,17 @@ if ls docs/architecture/c4/*.puml 2>/dev/null | grep -E -v '-de\.puml$' >/dev/nu err=1 fi +# ADR-Stubs: max. 40 Zeilen und YouTrack-Link Pflicht, wenn als Stub gekennzeichnet +for f in $(grep -RIl "^doc_type: adr-link" docs/architecture/adr 2>/dev/null || true); do + lines=$(wc -l < "$f" | tr -d ' ') + if [ "${lines}" -gt 40 ]; then + echo "[DRIFT] ADR-Stub überschreitet 40 Zeilen: $f (${lines})" + err=1 + fi + if ! grep -Eiq "https?://[^ ]*youtrack" "$f"; then + echo "[DRIFT] ADR-Stub ohne YouTrack-Link: $f" + err=1 + fi +done + exit $err diff --git a/.junie/scripts/markdown-autofix.sh b/.junie/scripts/markdown-autofix.sh new file mode 100644 index 00000000..5b20d80f --- /dev/null +++ b/.junie/scripts/markdown-autofix.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Markdown auto-fix helper +# - Runs markdownlint in --fix mode over all Markdown files +# - Normalizes final newline at EOF (MD047) +# - Respects repo config (.markdownlint.yaml, .markdownlintignore) + +ROOT_DIR=$(git rev-parse --show-toplevel 2>/dev/null || pwd) +cd "$ROOT_DIR" + +# Ensure dependencies are available (prefer locally installed first) +if ! command -v markdownlint >/dev/null 2>&1; then + if command -v npm >/dev/null 2>&1; then + echo "[INFO] Installing markdownlint-cli globally (requires npm) ..." + npm i -g markdownlint-cli >/dev/null 2>&1 || true + fi +fi + +# As fallback, use npx if markdownlint is still not found +RUN_MDLINT="markdownlint" +if ! command -v markdownlint >/dev/null 2>&1; then + if command -v npx >/dev/null 2>&1; then + RUN_MDLINT="npx -y markdownlint-cli" + else + echo "[ERROR] markdownlint-cli not found and npm/npx unavailable. Please install Node.js (>= 18) first." >&2 + exit 1 + fi +fi + +echo "[INFO] Running markdownlint --fix over all Markdown files ..." +# shellcheck disable=SC2086 +$RUN_MDLINT \ + --fix \ + --config .markdownlint.yaml \ + --ignore-path .markdownlintignore \ + "**/*.md" || true + +# Normalize EOF: ensure exactly one trailing newline (MD047) for all tracked Markdown files +# Uses Perl to replace any trailing whitespace/newlines with a single newline. +if command -v perl >/dev/null 2>&1; then + echo "[INFO] Normalizing end-of-file newlines (MD047) ..." + git ls-files "*.md" | while read -r f; do + perl -0777 -pe 's/\s*\z/\n/' "$f" > "$f.tmp.$RANDOM" && mv "$f.tmp."* "$f" + done +else + echo "[WARN] Perl not found; skipping explicit MD047 normalization. EditorConfig may cover this on save." +fi + +# Show summary of changes +if ! git diff --quiet; then + echo "[INFO] Changes made by auto-fix:"; + git --no-pager diff --stat + echo "[HINT] Review and commit changes:"; + echo " git add -A && git commit -m \"chore(docs): markdown auto-fix\"" +else + echo "[INFO] No changes required. Markdown files already conform to rules." +fi diff --git a/.junie/scripts/validate-frontmatter.py b/.junie/scripts/validate-frontmatter.py index a736dba5..5f138024 100644 --- a/.junie/scripts/validate-frontmatter.py +++ b/.junie/scripts/validate-frontmatter.py @@ -15,6 +15,9 @@ with open(SCHEMA_PATH, encoding='utf-8') as f: errors = 0 for path in glob('docs/**/*.md', recursive=True): + # ADRs und ggf. generierte Inhalte vorerst ausnehmen (separater Rollout für FM) + if path.startswith('docs/architecture/adr/'): + continue # Skip generated or non-content files if any (none by default) with open(path, 'r', encoding='utf-8') as fh: content = fh.read() diff --git a/.junie/scripts/validate-links.sh b/.junie/scripts/validate-links.sh index fae4ea46..92a85cdf 100755 --- a/.junie/scripts/validate-links.sh +++ b/.junie/scripts/validate-links.sh @@ -123,7 +123,12 @@ validate_cross_references() { } while IFS= read -r guideline; do - guideline_file="$GUIDELINES_DIR/$guideline" + # Special handling for README.md which is at project root + if [[ "$guideline" == "README.md" ]]; then + guideline_file="$PROJECT_ROOT/README.md" + else + guideline_file="$GUIDELINES_DIR/$guideline" + fi # Prüfe ob Guideline-Datei existiert if [[ ! -f "$guideline_file" ]]; then @@ -168,7 +173,8 @@ validate_cross_references() { # Prüfe ob der Link tatsächlich im Markdown existiert (nur im vollständigen Modus) if [[ "$QUICK_MODE" = false ]]; then ref_basename=$(basename "$ref" .md) - if ! grep -q "\[$ref_basename\]" "$guideline_file" && ! grep -q "($ref)" "$guideline_file"; then + # Check for link with basename in brackets OR reference path (with or without directory) in parentheses + if ! grep -q "\[$ref_basename\]" "$guideline_file" && ! grep -qE "\([^)]*$ref\)" "$guideline_file"; then log_warning "'$guideline' sollte '$ref' referenzieren, aber Link fehlt im Markdown" ((WARNINGS++)) fi diff --git a/.junie/scripts/youtrack-sync-kb.py b/.junie/scripts/youtrack-sync-kb.py new file mode 100644 index 00000000..60546420 --- /dev/null +++ b/.junie/scripts/youtrack-sync-kb.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Spiegelt Markdown-Dateien (z. B. aus build/dokka/gfm) in eine YouTrack Knowledge Base. +- Verwendet Umgebungsvariablen YT_URL und YT_TOKEN +- Erwartet den KB-Root-Titel in KB_ROOT_TITLE (z. B. "API & Entwicklerdoku") +- Optional: KB_BC_ROOT (Unterordnername, z. B. "BCs") – wird aktuell nur als Titelpräfix genutzt + +Sicherheit: +- Tokens werden niemals geloggt. +- Bei HTTP-Fehlern werden Statuscode und gekürzte Antwort ausgegeben. +""" +import argparse +import os +import sys +import json +import time +from pathlib import Path + +try: + import requests +except ImportError: # pragma: no cover + print("[YT] requests fehlt. Bitte 'pip install requests' ausführen.") + sys.exit(2) + +SESSION = requests.Session() +SESSION.headers.update({ + "Accept": "application/json", + "Content-Type": "application/json", +}) + + +def yt_url(path: str) -> str: + base = os.environ.get("YT_URL", "").rstrip("/") + if not base: + print("[YT] YT_URL fehlt in Env.") + sys.exit(2) + if not path.startswith("/"): + path = "/" + path + return base + path + + +def set_auth(): + token = os.environ.get("YT_TOKEN") + if not token: + print("[YT] YT_TOKEN fehlt in Env.") + sys.exit(2) + # Bearer Token + SESSION.headers["Authorization"] = f"Bearer {token}" + + +def http(method: str, url: str, **kw): + # Einfaches Retry bei 429/5xx + for attempt in range(5): + r = SESSION.request(method, url, timeout=30, **kw) + if r.status_code in (429, 500, 502, 503, 504): + wait = (attempt + 1) * 1.5 + print(f"[YT] {r.status_code} → Retry in {wait:.1f}s…") + time.sleep(wait) + continue + return r + return r + + +def get_knowledge_bases(): + url = yt_url("/api/knowledgeBases?fields=id,name") + r = http("GET", url) + if r.status_code != 200: + print(f"[YT] KB-Liste fehlgeschlagen: HTTP {r.status_code} {r.text[:400]}") + sys.exit(1) + return r.json() + + +def find_kb_by_name(name: str): + for kb in get_knowledge_bases(): + if kb.get("name") == name: + return kb + return None + + +def find_article_in_kb_by_title(kb_id: str, title: str): + # Filter per search nicht stabil → hole paginiert und filtere clientseitig + url = yt_url(f"/api/articles?fields=id,title,knowledgeBase(id)&$top=1000") + r = http("GET", url) + if r.status_code != 200: + print(f"[YT] Artikel-Liste fehlgeschlagen: HTTP {r.status_code} {r.text[:400]}") + sys.exit(1) + for art in r.json(): + kb = art.get("knowledgeBase") or {} + if kb.get("id") == kb_id and art.get("title") == title: + return art + return None + + +def create_article(kb_id: str, title: str, markdown: str): + url = yt_url("/api/articles?fields=id,title") + payload = { + "title": title, + "content": markdown, + "knowledgeBase": {"id": kb_id}, + # Sichtbarkeit: öffentlich/privat – Standard-Einstellungen der KB werden übernommen + } + r = http("POST", url, data=json.dumps(payload)) + if r.status_code not in (200, 201): + print(f"[YT] Artikel erstellen fehlgeschlagen: HTTP {r.status_code} {r.text[:400]}") + sys.exit(1) + return r.json() + + +def update_article(article_id: str, markdown: str): + url = yt_url(f"/api/articles/{article_id}?fields=id") + payload = {"content": markdown} + r = http("POST", url, data=json.dumps(payload)) # YouTrack erlaubt POST als Update + if r.status_code not in (200, 201): + # Fallback PATCH + r = http("PATCH", url, data=json.dumps(payload)) + if r.status_code not in (200, 204): + print(f"[YT] Artikel aktualisieren fehlgeschlagen: HTTP {r.status_code} {r.text[:400]}") + sys.exit(1) + + +def build_title_from_path(rel_path: Path, bc_root: str | None) -> str: + # Beispiel: infrastructure/gateway/index.md → "infrastructure / gateway / index.md" + parts = list(rel_path.parts) + title = " / ".join(parts) + if bc_root: + title = f"{bc_root} / {title}" + return title + + +def load_markdown(path: Path) -> str: + try: + text = path.read_text(encoding="utf-8") + except Exception as e: + print(f"[YT] Kann Datei nicht lesen: {path}: {e}") + sys.exit(1) + return text + + +def main(): + ap = argparse.ArgumentParser(description="Sync Dokka Markdown nach YouTrack KB") + ap.add_argument("--src", default="build/dokka/gfm", help="Quellverzeichnis (Markdown)") + args = ap.parse_args() + + kb_root_title = os.environ.get("KB_ROOT_TITLE") + bc_root = os.environ.get("KB_BC_ROOT") + if not kb_root_title: + print("[YT] KB_ROOT_TITLE fehlt in Env.") + sys.exit(2) + + set_auth() + + src = Path(args.src) + if not src.exists(): + print(f"[YT] Quelle nicht gefunden: {src} – nichts zu tun.") + return 0 + + kb = find_kb_by_name(kb_root_title) + if not kb: + print(f"[YT] Knowledge Base '{kb_root_title}' nicht gefunden. Bitte in YouTrack anlegen.") + sys.exit(1) + kb_id = kb["id"] + print(f"[YT] Verwende KB: {kb_root_title} ({kb_id})") + + count = 0 + for md in src.rglob("*.md"): + rel = md.relative_to(src) + title = build_title_from_path(rel, bc_root) + content = load_markdown(md) + # Optional: youtrack-spez. Front-Matter entfernen – Dokka erzeugt keine + existing = find_article_in_kb_by_title(kb_id, title) + if existing: + update_article(existing["id"], content) + print(f"[YT] Aktualisiert: {title}") + else: + create_article(kb_id, title, content) + print(f"[YT] Erstellt: {title}") + count += 1 + + print(f"[YT] Fertig. {count} Artikel synchronisiert.") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/.markdownlint.yaml b/.markdownlint.yaml index 1215c074..bd473363 100644 --- a/.markdownlint.yaml +++ b/.markdownlint.yaml @@ -1,3 +1,19 @@ default: true -MD013: false # Zeilenlänge entspannt -MD033: false # Inline-HTML erlaubt + +# Entspannte Regeln für Entwickler-Dokumentation +MD013: false # Line length - zu restriktiv für technische Docs +MD033: false # Inline HTML - manchmal nützlich für Diagramme/Badges +MD041: false # First line heading - README.md hat oft Badges + +# Erlaubte Heading-Duplikate (wichtig für API-Docs) +MD024: + siblings_only: true + +# Lockere Listen-Indentation +MD007: + indent: 2 + +# Code-Blöcke brauchen Language-Tags +MD040: true +MD046: + style: fenced diff --git a/.markdownlintignore b/.markdownlintignore new file mode 100644 index 00000000..c489c0de --- /dev/null +++ b/.markdownlintignore @@ -0,0 +1,17 @@ +# Generierte Dateien ignorieren +docs/api/generated/ +build/ +node_modules/ +kotlin-js-store/ + +# Externe Dokumentation +.junie/ + +# Temporäre/Legacy-Dateien +.vscode/ +.idea/ +.fleet/ + +# Spezielle Markdown-Dateien +CHANGELOG.md +LICENSE diff --git a/.output.txt b/.output.txt deleted file mode 100644 index 538de912..00000000 --- a/.output.txt +++ /dev/null @@ -1,3102 +0,0 @@ - neue Datei: clients/app/node_modules/@bcoe/v8-coverage/package.json - neue Datei: clients/app/node_modules/@bcoe/v8-coverage/src/lib/ascii.ts - neue Datei: clients/app/node_modules/@bcoe/v8-coverage/src/lib/clone.ts - neue Datei: clients/app/node_modules/@bcoe/v8-coverage/src/lib/compare.ts - neue Datei: clients/app/node_modules/@bcoe/v8-coverage/src/lib/index.ts - neue Datei: clients/app/node_modules/@bcoe/v8-coverage/src/lib/merge.ts - neue Datei: clients/app/node_modules/@bcoe/v8-coverage/src/lib/normalize.ts - neue Datei: clients/app/node_modules/@bcoe/v8-coverage/src/lib/range-tree.ts - neue Datei: clients/app/node_modules/@bcoe/v8-coverage/src/lib/types.ts - neue Datei: clients/app/node_modules/@bcoe/v8-coverage/src/test/merge.spec.ts - neue Datei: clients/app/node_modules/@bcoe/v8-coverage/tsconfig.json - neue Datei: clients/app/node_modules/@discoveryjs/json-ext/LICENSE - neue Datei: clients/app/node_modules/@discoveryjs/json-ext/README.md - neue Datei: clients/app/node_modules/@discoveryjs/json-ext/dist/json-ext.js - neue Datei: clients/app/node_modules/@discoveryjs/json-ext/dist/json-ext.min.js - neue Datei: clients/app/node_modules/@discoveryjs/json-ext/dist/version.js - neue Datei: clients/app/node_modules/@discoveryjs/json-ext/index.d.ts - neue Datei: clients/app/node_modules/@discoveryjs/json-ext/package.json - neue Datei: clients/app/node_modules/@discoveryjs/json-ext/src/index.js - neue Datei: clients/app/node_modules/@discoveryjs/json-ext/src/parse-chunked.js - neue Datei: clients/app/node_modules/@discoveryjs/json-ext/src/stringify-info.js - neue Datei: clients/app/node_modules/@discoveryjs/json-ext/src/stringify-stream-browser.js - neue Datei: clients/app/node_modules/@discoveryjs/json-ext/src/stringify-stream.js - neue Datei: clients/app/node_modules/@discoveryjs/json-ext/src/text-decoder-browser.js - neue Datei: clients/app/node_modules/@discoveryjs/json-ext/src/text-decoder.js - neue Datei: clients/app/node_modules/@discoveryjs/json-ext/src/utils.js - neue Datei: clients/app/node_modules/@discoveryjs/json-ext/src/version.js - neue Datei: clients/app/node_modules/@istanbuljs/load-nyc-config/CHANGELOG.md - neue Datei: clients/app/node_modules/@istanbuljs/load-nyc-config/LICENSE - neue Datei: clients/app/node_modules/@istanbuljs/load-nyc-config/README.md - neue Datei: clients/app/node_modules/@istanbuljs/load-nyc-config/index.js - neue Datei: clients/app/node_modules/@istanbuljs/load-nyc-config/load-esm.js - neue Datei: clients/app/node_modules/@istanbuljs/load-nyc-config/package.json - neue Datei: clients/app/node_modules/@istanbuljs/schema/CHANGELOG.md - neue Datei: clients/app/node_modules/@istanbuljs/schema/LICENSE - neue Datei: clients/app/node_modules/@istanbuljs/schema/README.md - neue Datei: clients/app/node_modules/@istanbuljs/schema/default-exclude.js - neue Datei: clients/app/node_modules/@istanbuljs/schema/default-extension.js - neue Datei: clients/app/node_modules/@istanbuljs/schema/index.js - neue Datei: clients/app/node_modules/@istanbuljs/schema/package.json - neue Datei: clients/app/node_modules/@jest/console/LICENSE - neue Datei: clients/app/node_modules/@jest/console/package.json - neue Datei: clients/app/node_modules/@jest/core/LICENSE - neue Datei: clients/app/node_modules/@jest/core/README.md - neue Datei: clients/app/node_modules/@jest/core/package.json - neue Datei: clients/app/node_modules/@jest/environment/LICENSE - neue Datei: clients/app/node_modules/@jest/environment/package.json - neue Datei: clients/app/node_modules/@jest/expect-utils/LICENSE - neue Datei: clients/app/node_modules/@jest/expect-utils/README.md - neue Datei: clients/app/node_modules/@jest/expect-utils/package.json - neue Datei: clients/app/node_modules/@jest/expect/LICENSE - neue Datei: clients/app/node_modules/@jest/expect/README.md - neue Datei: clients/app/node_modules/@jest/expect/package.json - neue Datei: clients/app/node_modules/@jest/fake-timers/LICENSE - neue Datei: clients/app/node_modules/@jest/fake-timers/package.json - neue Datei: clients/app/node_modules/@jest/globals/LICENSE - neue Datei: clients/app/node_modules/@jest/globals/package.json - neue Datei: clients/app/node_modules/@jest/reporters/LICENSE - neue Datei: clients/app/node_modules/@jest/reporters/assets/jest_logo.png - neue Datei: clients/app/node_modules/@jest/reporters/package.json - neue Datei: clients/app/node_modules/@jest/schemas/LICENSE - neue Datei: clients/app/node_modules/@jest/schemas/README.md - neue Datei: clients/app/node_modules/@jest/schemas/package.json - neue Datei: clients/app/node_modules/@jest/source-map/LICENSE - neue Datei: clients/app/node_modules/@jest/source-map/package.json - neue Datei: clients/app/node_modules/@jest/test-result/LICENSE - neue Datei: clients/app/node_modules/@jest/test-result/package.json - neue Datei: clients/app/node_modules/@jest/test-sequencer/LICENSE - neue Datei: clients/app/node_modules/@jest/test-sequencer/package.json - neue Datei: clients/app/node_modules/@jest/transform/LICENSE - neue Datei: clients/app/node_modules/@jest/transform/package.json - neue Datei: clients/app/node_modules/@jest/types/LICENSE - neue Datei: clients/app/node_modules/@jest/types/README.md - neue Datei: clients/app/node_modules/@jest/types/package.json - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/LICENSE - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/README.md - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/dist/gen-mapping.mjs - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/dist/gen-mapping.mjs.map - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/dist/gen-mapping.umd.js - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/dist/gen-mapping.umd.js.map - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/dist/types/gen-mapping.d.ts - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/dist/types/set-array.d.ts - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/dist/types/sourcemap-segment.d.ts - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/dist/types/types.d.ts - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/package.json - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/src/gen-mapping.ts - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/src/set-array.ts - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/src/sourcemap-segment.ts - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/src/types.ts - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/types/gen-mapping.d.cts - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/types/gen-mapping.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/types/gen-mapping.d.mts - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/types/gen-mapping.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/types/set-array.d.cts - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/types/set-array.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/types/set-array.d.mts - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/types/set-array.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/types/sourcemap-segment.d.cts - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/types/sourcemap-segment.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/types/sourcemap-segment.d.mts - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/types/sourcemap-segment.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/types/types.d.cts - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/types/types.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/types/types.d.mts - neue Datei: clients/app/node_modules/@jridgewell/gen-mapping/types/types.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/remapping/LICENSE - neue Datei: clients/app/node_modules/@jridgewell/remapping/README.md - neue Datei: clients/app/node_modules/@jridgewell/remapping/dist/remapping.mjs - neue Datei: clients/app/node_modules/@jridgewell/remapping/dist/remapping.mjs.map - neue Datei: clients/app/node_modules/@jridgewell/remapping/dist/remapping.umd.js - neue Datei: clients/app/node_modules/@jridgewell/remapping/dist/remapping.umd.js.map - neue Datei: clients/app/node_modules/@jridgewell/remapping/package.json - neue Datei: clients/app/node_modules/@jridgewell/remapping/src/build-source-map-tree.ts - neue Datei: clients/app/node_modules/@jridgewell/remapping/src/remapping.ts - neue Datei: clients/app/node_modules/@jridgewell/remapping/src/source-map-tree.ts - neue Datei: clients/app/node_modules/@jridgewell/remapping/src/source-map.ts - neue Datei: clients/app/node_modules/@jridgewell/remapping/src/types.ts - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/build-source-map-tree.d.cts - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/build-source-map-tree.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/build-source-map-tree.d.mts - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/build-source-map-tree.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/remapping.d.cts - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/remapping.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/remapping.d.mts - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/remapping.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/source-map-tree.d.cts - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/source-map-tree.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/source-map-tree.d.mts - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/source-map-tree.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/source-map.d.cts - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/source-map.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/source-map.d.mts - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/source-map.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/types.d.cts - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/types.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/types.d.mts - neue Datei: clients/app/node_modules/@jridgewell/remapping/types/types.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/resolve-uri/LICENSE - neue Datei: clients/app/node_modules/@jridgewell/resolve-uri/README.md - neue Datei: clients/app/node_modules/@jridgewell/resolve-uri/dist/resolve-uri.mjs - neue Datei: clients/app/node_modules/@jridgewell/resolve-uri/dist/resolve-uri.mjs.map - neue Datei: clients/app/node_modules/@jridgewell/resolve-uri/dist/resolve-uri.umd.js - neue Datei: clients/app/node_modules/@jridgewell/resolve-uri/dist/resolve-uri.umd.js.map - neue Datei: clients/app/node_modules/@jridgewell/resolve-uri/dist/types/resolve-uri.d.ts - neue Datei: clients/app/node_modules/@jridgewell/resolve-uri/package.json - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/LICENSE - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/README.md - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs.map - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.umd.js - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.umd.js.map - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/package.json - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/src/scopes.ts - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/src/sourcemap-codec.ts - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/src/strings.ts - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/src/vlq.ts - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/types/scopes.d.cts - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/types/scopes.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/types/scopes.d.mts - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/types/scopes.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/types/sourcemap-codec.d.cts - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/types/sourcemap-codec.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/types/sourcemap-codec.d.mts - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/types/sourcemap-codec.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/types/strings.d.cts - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/types/strings.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/types/strings.d.mts - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/types/strings.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/types/vlq.d.cts - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/types/vlq.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/types/vlq.d.mts - neue Datei: clients/app/node_modules/@jridgewell/sourcemap-codec/types/vlq.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/LICENSE - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/README.md - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.mjs - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.mjs.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.umd.js - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.umd.js.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/package.json - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/src/binary-search.ts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/src/by-source.ts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/src/flatten-map.ts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/src/resolve.ts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/src/sort.ts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/src/sourcemap-segment.ts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/src/strip-filename.ts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/src/trace-mapping.ts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/src/types.ts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/binary-search.d.cts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/binary-search.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/binary-search.d.mts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/binary-search.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/by-source.d.cts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/by-source.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/by-source.d.mts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/by-source.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/flatten-map.d.cts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/flatten-map.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/flatten-map.d.mts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/flatten-map.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/resolve.d.cts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/resolve.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/resolve.d.mts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/resolve.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/sort.d.cts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/sort.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/sort.d.mts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/sort.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/sourcemap-segment.d.cts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/sourcemap-segment.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/sourcemap-segment.d.mts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/sourcemap-segment.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/strip-filename.d.cts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/strip-filename.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/strip-filename.d.mts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/strip-filename.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/trace-mapping.d.cts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/trace-mapping.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/trace-mapping.d.mts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/trace-mapping.d.mts.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/types.d.cts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/types.d.cts.map - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/types.d.mts - neue Datei: clients/app/node_modules/@jridgewell/trace-mapping/types/types.d.mts.map - neue Datei: clients/app/node_modules/@polka/url/build.js - neue Datei: clients/app/node_modules/@polka/url/build.mjs - neue Datei: clients/app/node_modules/@polka/url/index.d.ts - neue Datei: clients/app/node_modules/@polka/url/package.json - neue Datei: clients/app/node_modules/@polka/url/readme.md - neue Datei: clients/app/node_modules/@sinclair/typebox/compiler/compiler.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/compiler/compiler.js - neue Datei: clients/app/node_modules/@sinclair/typebox/compiler/index.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/compiler/index.js - neue Datei: clients/app/node_modules/@sinclair/typebox/errors/errors.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/errors/errors.js - neue Datei: clients/app/node_modules/@sinclair/typebox/errors/index.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/errors/index.js - neue Datei: clients/app/node_modules/@sinclair/typebox/license - neue Datei: clients/app/node_modules/@sinclair/typebox/package.json - neue Datei: clients/app/node_modules/@sinclair/typebox/readme.md - neue Datei: clients/app/node_modules/@sinclair/typebox/system/index.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/system/index.js - neue Datei: clients/app/node_modules/@sinclair/typebox/system/system.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/system/system.js - neue Datei: clients/app/node_modules/@sinclair/typebox/typebox.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/typebox.js - neue Datei: clients/app/node_modules/@sinclair/typebox/value/cast.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/value/cast.js - neue Datei: clients/app/node_modules/@sinclair/typebox/value/check.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/value/check.js - neue Datei: clients/app/node_modules/@sinclair/typebox/value/clone.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/value/clone.js - neue Datei: clients/app/node_modules/@sinclair/typebox/value/convert.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/value/convert.js - neue Datei: clients/app/node_modules/@sinclair/typebox/value/create.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/value/create.js - neue Datei: clients/app/node_modules/@sinclair/typebox/value/delta.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/value/delta.js - neue Datei: clients/app/node_modules/@sinclair/typebox/value/equal.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/value/equal.js - neue Datei: clients/app/node_modules/@sinclair/typebox/value/hash.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/value/hash.js - neue Datei: clients/app/node_modules/@sinclair/typebox/value/index.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/value/index.js - neue Datei: clients/app/node_modules/@sinclair/typebox/value/is.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/value/is.js - neue Datei: clients/app/node_modules/@sinclair/typebox/value/mutate.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/value/mutate.js - neue Datei: clients/app/node_modules/@sinclair/typebox/value/pointer.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/value/pointer.js - neue Datei: clients/app/node_modules/@sinclair/typebox/value/value.d.ts - neue Datei: clients/app/node_modules/@sinclair/typebox/value/value.js - neue Datei: clients/app/node_modules/@sinonjs/commons/LICENSE - neue Datei: clients/app/node_modules/@sinonjs/commons/README.md - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/called-in-order.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/called-in-order.test.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/class-name.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/class-name.test.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/deprecated.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/deprecated.test.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/every.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/every.test.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/function-name.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/function-name.test.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/global.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/global.test.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/index.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/index.test.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/order-by-first-call.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/order-by-first-call.test.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/prototypes/README.md - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/prototypes/array.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/prototypes/copy-prototype-methods.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/prototypes/copy-prototype-methods.test.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/prototypes/function.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/prototypes/index.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/prototypes/index.test.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/prototypes/map.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/prototypes/object.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/prototypes/set.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/prototypes/string.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/prototypes/throws-on-proto.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/type-of.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/type-of.test.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/value-to-string.js - neue Datei: clients/app/node_modules/@sinonjs/commons/lib/value-to-string.test.js - neue Datei: clients/app/node_modules/@sinonjs/commons/package.json - neue Datei: clients/app/node_modules/@sinonjs/commons/types/called-in-order.d.ts - neue Datei: clients/app/node_modules/@sinonjs/commons/types/class-name.d.ts - neue Datei: clients/app/node_modules/@sinonjs/commons/types/deprecated.d.ts - neue Datei: clients/app/node_modules/@sinonjs/commons/types/every.d.ts - neue Datei: clients/app/node_modules/@sinonjs/commons/types/function-name.d.ts - neue Datei: clients/app/node_modules/@sinonjs/commons/types/global.d.ts - neue Datei: clients/app/node_modules/@sinonjs/commons/types/index.d.ts - neue Datei: clients/app/node_modules/@sinonjs/commons/types/order-by-first-call.d.ts - neue Datei: clients/app/node_modules/@sinonjs/commons/types/prototypes/array.d.ts - neue Datei: clients/app/node_modules/@sinonjs/commons/types/prototypes/copy-prototype-methods.d.ts - neue Datei: clients/app/node_modules/@sinonjs/commons/types/prototypes/function.d.ts - neue Datei: clients/app/node_modules/@sinonjs/commons/types/prototypes/index.d.ts - neue Datei: clients/app/node_modules/@sinonjs/commons/types/prototypes/map.d.ts - neue Datei: clients/app/node_modules/@sinonjs/commons/types/prototypes/object.d.ts - neue Datei: clients/app/node_modules/@sinonjs/commons/types/prototypes/set.d.ts - neue Datei: clients/app/node_modules/@sinonjs/commons/types/prototypes/string.d.ts - neue Datei: clients/app/node_modules/@sinonjs/commons/types/prototypes/throws-on-proto.d.ts - neue Datei: clients/app/node_modules/@sinonjs/commons/types/type-of.d.ts - neue Datei: clients/app/node_modules/@sinonjs/commons/types/value-to-string.d.ts - neue Datei: clients/app/node_modules/@sinonjs/fake-timers/LICENSE - neue Datei: clients/app/node_modules/@sinonjs/fake-timers/README.md - neue Datei: clients/app/node_modules/@sinonjs/fake-timers/package.json - neue Datei: clients/app/node_modules/@sinonjs/fake-timers/src/fake-timers-src.js - neue Datei: clients/app/node_modules/@types/babel__core/LICENSE - neue Datei: clients/app/node_modules/@types/babel__core/README.md - neue Datei: clients/app/node_modules/@types/babel__core/index.d.ts - neue Datei: clients/app/node_modules/@types/babel__core/package.json - neue Datei: clients/app/node_modules/@types/babel__generator/LICENSE - neue Datei: clients/app/node_modules/@types/babel__generator/README.md - neue Datei: clients/app/node_modules/@types/babel__generator/index.d.ts - neue Datei: clients/app/node_modules/@types/babel__generator/package.json - neue Datei: clients/app/node_modules/@types/babel__template/LICENSE - neue Datei: clients/app/node_modules/@types/babel__template/README.md - neue Datei: clients/app/node_modules/@types/babel__template/index.d.ts - neue Datei: clients/app/node_modules/@types/babel__template/package.json - neue Datei: clients/app/node_modules/@types/babel__traverse/LICENSE - neue Datei: clients/app/node_modules/@types/babel__traverse/README.md - neue Datei: clients/app/node_modules/@types/babel__traverse/index.d.ts - neue Datei: clients/app/node_modules/@types/babel__traverse/package.json - neue Datei: clients/app/node_modules/@types/graceful-fs/LICENSE - neue Datei: clients/app/node_modules/@types/graceful-fs/README.md - neue Datei: clients/app/node_modules/@types/graceful-fs/index.d.ts - neue Datei: clients/app/node_modules/@types/graceful-fs/package.json - neue Datei: clients/app/node_modules/@types/istanbul-lib-coverage/LICENSE - neue Datei: clients/app/node_modules/@types/istanbul-lib-coverage/README.md - neue Datei: clients/app/node_modules/@types/istanbul-lib-coverage/index.d.ts - neue Datei: clients/app/node_modules/@types/istanbul-lib-coverage/package.json - neue Datei: clients/app/node_modules/@types/istanbul-lib-report/LICENSE - neue Datei: clients/app/node_modules/@types/istanbul-lib-report/README.md - neue Datei: clients/app/node_modules/@types/istanbul-lib-report/index.d.ts - neue Datei: clients/app/node_modules/@types/istanbul-lib-report/package.json - neue Datei: clients/app/node_modules/@types/istanbul-reports/LICENSE - neue Datei: clients/app/node_modules/@types/istanbul-reports/README.md - neue Datei: clients/app/node_modules/@types/istanbul-reports/index.d.ts - neue Datei: clients/app/node_modules/@types/istanbul-reports/package.json - neue Datei: clients/app/node_modules/@types/jest/LICENSE - neue Datei: clients/app/node_modules/@types/jest/README.md - neue Datei: clients/app/node_modules/@types/jest/index.d.ts - neue Datei: clients/app/node_modules/@types/jest/package.json - neue Datei: clients/app/node_modules/@types/node/LICENSE - neue Datei: clients/app/node_modules/@types/node/README.md - neue Datei: clients/app/node_modules/@types/node/assert.d.ts - neue Datei: clients/app/node_modules/@types/node/assert/strict.d.ts - neue Datei: clients/app/node_modules/@types/node/async_hooks.d.ts - neue Datei: clients/app/node_modules/@types/node/buffer.buffer.d.ts - neue Datei: clients/app/node_modules/@types/node/buffer.d.ts - neue Datei: clients/app/node_modules/@types/node/child_process.d.ts - neue Datei: clients/app/node_modules/@types/node/cluster.d.ts - neue Datei: clients/app/node_modules/@types/node/compatibility/iterators.d.ts - neue Datei: clients/app/node_modules/@types/node/console.d.ts - neue Datei: clients/app/node_modules/@types/node/constants.d.ts - neue Datei: clients/app/node_modules/@types/node/crypto.d.ts - neue Datei: clients/app/node_modules/@types/node/dgram.d.ts - neue Datei: clients/app/node_modules/@types/node/diagnostics_channel.d.ts - neue Datei: clients/app/node_modules/@types/node/dns.d.ts - neue Datei: clients/app/node_modules/@types/node/dns/promises.d.ts - neue Datei: clients/app/node_modules/@types/node/domain.d.ts - neue Datei: clients/app/node_modules/@types/node/events.d.ts - neue Datei: clients/app/node_modules/@types/node/fs.d.ts - neue Datei: clients/app/node_modules/@types/node/fs/promises.d.ts - neue Datei: clients/app/node_modules/@types/node/globals.d.ts - neue Datei: clients/app/node_modules/@types/node/globals.typedarray.d.ts - neue Datei: clients/app/node_modules/@types/node/http.d.ts - neue Datei: clients/app/node_modules/@types/node/http2.d.ts - neue Datei: clients/app/node_modules/@types/node/https.d.ts - neue Datei: clients/app/node_modules/@types/node/index.d.ts - neue Datei: clients/app/node_modules/@types/node/inspector.d.ts - neue Datei: clients/app/node_modules/@types/node/inspector.generated.d.ts - neue Datei: clients/app/node_modules/@types/node/module.d.ts - neue Datei: clients/app/node_modules/@types/node/net.d.ts - neue Datei: clients/app/node_modules/@types/node/os.d.ts - neue Datei: clients/app/node_modules/@types/node/package.json - neue Datei: clients/app/node_modules/@types/node/path.d.ts - neue Datei: clients/app/node_modules/@types/node/perf_hooks.d.ts - neue Datei: clients/app/node_modules/@types/node/process.d.ts - neue Datei: clients/app/node_modules/@types/node/punycode.d.ts - neue Datei: clients/app/node_modules/@types/node/querystring.d.ts - neue Datei: clients/app/node_modules/@types/node/readline.d.ts - neue Datei: clients/app/node_modules/@types/node/readline/promises.d.ts - neue Datei: clients/app/node_modules/@types/node/repl.d.ts - neue Datei: clients/app/node_modules/@types/node/sea.d.ts - neue Datei: clients/app/node_modules/@types/node/sqlite.d.ts - neue Datei: clients/app/node_modules/@types/node/stream.d.ts - neue Datei: clients/app/node_modules/@types/node/stream/consumers.d.ts - neue Datei: clients/app/node_modules/@types/node/stream/promises.d.ts - neue Datei: clients/app/node_modules/@types/node/stream/web.d.ts - neue Datei: clients/app/node_modules/@types/node/string_decoder.d.ts - neue Datei: clients/app/node_modules/@types/node/test.d.ts - neue Datei: clients/app/node_modules/@types/node/timers.d.ts - neue Datei: clients/app/node_modules/@types/node/timers/promises.d.ts - neue Datei: clients/app/node_modules/@types/node/tls.d.ts - neue Datei: clients/app/node_modules/@types/node/trace_events.d.ts - neue Datei: clients/app/node_modules/@types/node/ts5.6/buffer.buffer.d.ts - neue Datei: clients/app/node_modules/@types/node/ts5.6/compatibility/float16array.d.ts - neue Datei: clients/app/node_modules/@types/node/ts5.6/globals.typedarray.d.ts - neue Datei: clients/app/node_modules/@types/node/ts5.6/index.d.ts - neue Datei: clients/app/node_modules/@types/node/ts5.7/compatibility/float16array.d.ts - neue Datei: clients/app/node_modules/@types/node/ts5.7/index.d.ts - neue Datei: clients/app/node_modules/@types/node/tty.d.ts - neue Datei: clients/app/node_modules/@types/node/url.d.ts - neue Datei: clients/app/node_modules/@types/node/util.d.ts - neue Datei: clients/app/node_modules/@types/node/v8.d.ts - neue Datei: clients/app/node_modules/@types/node/vm.d.ts - neue Datei: clients/app/node_modules/@types/node/wasi.d.ts - neue Datei: clients/app/node_modules/@types/node/web-globals/abortcontroller.d.ts - neue Datei: clients/app/node_modules/@types/node/web-globals/crypto.d.ts - neue Datei: clients/app/node_modules/@types/node/web-globals/domexception.d.ts - neue Datei: clients/app/node_modules/@types/node/web-globals/events.d.ts - neue Datei: clients/app/node_modules/@types/node/web-globals/fetch.d.ts - neue Datei: clients/app/node_modules/@types/node/web-globals/navigator.d.ts - neue Datei: clients/app/node_modules/@types/node/web-globals/storage.d.ts - neue Datei: clients/app/node_modules/@types/node/web-globals/streams.d.ts - neue Datei: clients/app/node_modules/@types/node/worker_threads.d.ts - neue Datei: clients/app/node_modules/@types/node/zlib.d.ts - neue Datei: clients/app/node_modules/@types/stack-utils/LICENSE - neue Datei: clients/app/node_modules/@types/stack-utils/README.md - neue Datei: clients/app/node_modules/@types/stack-utils/index.d.ts - neue Datei: clients/app/node_modules/@types/stack-utils/package.json - neue Datei: clients/app/node_modules/@types/yargs-parser/LICENSE - neue Datei: clients/app/node_modules/@types/yargs-parser/README.md - neue Datei: clients/app/node_modules/@types/yargs-parser/index.d.ts - neue Datei: clients/app/node_modules/@types/yargs-parser/package.json - neue Datei: clients/app/node_modules/@types/yargs/LICENSE - neue Datei: clients/app/node_modules/@types/yargs/README.md - neue Datei: clients/app/node_modules/@types/yargs/helpers.d.mts - neue Datei: clients/app/node_modules/@types/yargs/helpers.d.ts - neue Datei: clients/app/node_modules/@types/yargs/index.d.mts - neue Datei: clients/app/node_modules/@types/yargs/index.d.ts - neue Datei: clients/app/node_modules/@types/yargs/package.json - neue Datei: clients/app/node_modules/@types/yargs/yargs.d.ts - neue Datei: clients/app/node_modules/acorn-walk/CHANGELOG.md - neue Datei: clients/app/node_modules/acorn-walk/LICENSE - neue Datei: clients/app/node_modules/acorn-walk/README.md - neue Datei: clients/app/node_modules/acorn-walk/dist/walk.d.mts - neue Datei: clients/app/node_modules/acorn-walk/dist/walk.d.ts - neue Datei: clients/app/node_modules/acorn-walk/dist/walk.js - neue Datei: clients/app/node_modules/acorn-walk/dist/walk.mjs - neue Datei: clients/app/node_modules/acorn-walk/package.json - neue Datei: clients/app/node_modules/acorn/CHANGELOG.md - neue Datei: clients/app/node_modules/acorn/LICENSE - neue Datei: clients/app/node_modules/acorn/README.md - neue Datei: clients/app/node_modules/acorn/bin/acorn - neue Datei: clients/app/node_modules/acorn/dist/acorn.d.mts - neue Datei: clients/app/node_modules/acorn/dist/acorn.d.ts - neue Datei: clients/app/node_modules/acorn/dist/acorn.js - neue Datei: clients/app/node_modules/acorn/dist/acorn.mjs - neue Datei: clients/app/node_modules/acorn/dist/bin.js - neue Datei: clients/app/node_modules/acorn/package.json - neue Datei: clients/app/node_modules/ansi-escapes/index.d.ts - neue Datei: clients/app/node_modules/ansi-escapes/index.js - neue Datei: clients/app/node_modules/ansi-escapes/license - neue Datei: clients/app/node_modules/ansi-escapes/package.json - neue Datei: clients/app/node_modules/ansi-escapes/readme.md - neue Datei: clients/app/node_modules/ansi-regex/index.d.ts - neue Datei: clients/app/node_modules/ansi-regex/index.js - neue Datei: clients/app/node_modules/ansi-regex/license - neue Datei: clients/app/node_modules/ansi-regex/package.json - neue Datei: clients/app/node_modules/ansi-regex/readme.md - neue Datei: clients/app/node_modules/ansi-styles/index.d.ts - neue Datei: clients/app/node_modules/ansi-styles/index.js - neue Datei: clients/app/node_modules/ansi-styles/license - neue Datei: clients/app/node_modules/ansi-styles/package.json - neue Datei: clients/app/node_modules/ansi-styles/readme.md - neue Datei: clients/app/node_modules/anymatch/LICENSE - neue Datei: clients/app/node_modules/anymatch/README.md - neue Datei: clients/app/node_modules/anymatch/index.d.ts - neue Datei: clients/app/node_modules/anymatch/index.js - neue Datei: clients/app/node_modules/anymatch/package.json - neue Datei: clients/app/node_modules/argparse/CHANGELOG.md - neue Datei: clients/app/node_modules/argparse/LICENSE - neue Datei: clients/app/node_modules/argparse/README.md - neue Datei: clients/app/node_modules/argparse/index.js - neue Datei: clients/app/node_modules/argparse/lib/action.js - neue Datei: clients/app/node_modules/argparse/lib/action/append.js - neue Datei: clients/app/node_modules/argparse/lib/action/append/constant.js - neue Datei: clients/app/node_modules/argparse/lib/action/count.js - neue Datei: clients/app/node_modules/argparse/lib/action/help.js - neue Datei: clients/app/node_modules/argparse/lib/action/store.js - neue Datei: clients/app/node_modules/argparse/lib/action/store/constant.js - neue Datei: clients/app/node_modules/argparse/lib/action/store/false.js - neue Datei: clients/app/node_modules/argparse/lib/action/store/true.js - neue Datei: clients/app/node_modules/argparse/lib/action/subparsers.js - neue Datei: clients/app/node_modules/argparse/lib/action/version.js - neue Datei: clients/app/node_modules/argparse/lib/action_container.js - neue Datei: clients/app/node_modules/argparse/lib/argparse.js - neue Datei: clients/app/node_modules/argparse/lib/argument/error.js - neue Datei: clients/app/node_modules/argparse/lib/argument/exclusive.js - neue Datei: clients/app/node_modules/argparse/lib/argument/group.js - neue Datei: clients/app/node_modules/argparse/lib/argument_parser.js - neue Datei: clients/app/node_modules/argparse/lib/const.js - neue Datei: clients/app/node_modules/argparse/lib/help/added_formatters.js - neue Datei: clients/app/node_modules/argparse/lib/help/formatter.js - neue Datei: clients/app/node_modules/argparse/lib/namespace.js - neue Datei: clients/app/node_modules/argparse/lib/utils.js - neue Datei: clients/app/node_modules/argparse/package.json - neue Datei: clients/app/node_modules/babel-jest/LICENSE - neue Datei: clients/app/node_modules/babel-jest/README.md - neue Datei: clients/app/node_modules/babel-jest/package.json - neue Datei: clients/app/node_modules/babel-plugin-istanbul/CHANGELOG.md - neue Datei: clients/app/node_modules/babel-plugin-istanbul/LICENSE - neue Datei: clients/app/node_modules/babel-plugin-istanbul/README.md - neue Datei: clients/app/node_modules/babel-plugin-istanbul/lib/index.js - neue Datei: clients/app/node_modules/babel-plugin-istanbul/lib/load-nyc-config-sync.js - neue Datei: clients/app/node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument/CHANGELOG.md - neue Datei: clients/app/node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument/LICENSE - neue Datei: clients/app/node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument/README.md - neue Datei: clients/app/node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument/package.json - neue Datei: clients/app/node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument/src/constants.js - neue Datei: clients/app/node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument/src/index.js - neue Datei: clients/app/node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument/src/instrumenter.js - neue Datei: clients/app/node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument/src/read-coverage.js - neue Datei: clients/app/node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument/src/source-coverage.js - neue Datei: clients/app/node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument/src/visitor.js - neue Datei: clients/app/node_modules/babel-plugin-istanbul/package.json - neue Datei: clients/app/node_modules/babel-plugin-jest-hoist/LICENSE - neue Datei: clients/app/node_modules/babel-plugin-jest-hoist/README.md - neue Datei: clients/app/node_modules/babel-plugin-jest-hoist/package.json - neue Datei: clients/app/node_modules/babel-preset-current-node-syntax/.github/FUNDING.yml - neue Datei: clients/app/node_modules/babel-preset-current-node-syntax/.github/workflows/nodejs.yml - neue Datei: clients/app/node_modules/babel-preset-current-node-syntax/LICENSE - neue Datei: clients/app/node_modules/babel-preset-current-node-syntax/README.md - neue Datei: clients/app/node_modules/babel-preset-current-node-syntax/package.json - neue Datei: clients/app/node_modules/babel-preset-current-node-syntax/src/index.js - neue Datei: clients/app/node_modules/babel-preset-jest/LICENSE - neue Datei: clients/app/node_modules/babel-preset-jest/README.md - neue Datei: clients/app/node_modules/babel-preset-jest/index.js - neue Datei: clients/app/node_modules/babel-preset-jest/package.json - neue Datei: clients/app/node_modules/balanced-match/.github/FUNDING.yml - neue Datei: clients/app/node_modules/balanced-match/LICENSE.md - neue Datei: clients/app/node_modules/balanced-match/README.md - neue Datei: clients/app/node_modules/balanced-match/index.js - neue Datei: clients/app/node_modules/balanced-match/package.json - neue Datei: clients/app/node_modules/baseline-browser-mapping/LICENSE.txt - neue Datei: clients/app/node_modules/baseline-browser-mapping/README.md - neue Datei: clients/app/node_modules/baseline-browser-mapping/dist/cli.js - neue Datei: clients/app/node_modules/baseline-browser-mapping/dist/index.cjs - neue Datei: clients/app/node_modules/baseline-browser-mapping/dist/index.d.ts - neue Datei: clients/app/node_modules/baseline-browser-mapping/dist/index.js - neue Datei: clients/app/node_modules/baseline-browser-mapping/package.json - neue Datei: clients/app/node_modules/brace-expansion/LICENSE - neue Datei: clients/app/node_modules/brace-expansion/README.md - neue Datei: clients/app/node_modules/brace-expansion/index.js - neue Datei: clients/app/node_modules/brace-expansion/package.json - neue Datei: clients/app/node_modules/braces/LICENSE - neue Datei: clients/app/node_modules/braces/README.md - neue Datei: clients/app/node_modules/braces/index.js - neue Datei: clients/app/node_modules/braces/lib/compile.js - neue Datei: clients/app/node_modules/braces/lib/constants.js - neue Datei: clients/app/node_modules/braces/lib/expand.js - neue Datei: clients/app/node_modules/braces/lib/parse.js - neue Datei: clients/app/node_modules/braces/lib/stringify.js - neue Datei: clients/app/node_modules/braces/lib/utils.js - neue Datei: clients/app/node_modules/braces/package.json - neue Datei: clients/app/node_modules/browserslist/LICENSE - neue Datei: clients/app/node_modules/browserslist/README.md - neue Datei: clients/app/node_modules/browserslist/browser.js - neue Datei: clients/app/node_modules/browserslist/cli.js - neue Datei: clients/app/node_modules/browserslist/error.d.ts - neue Datei: clients/app/node_modules/browserslist/error.js - neue Datei: clients/app/node_modules/browserslist/index.d.ts - neue Datei: clients/app/node_modules/browserslist/index.js - neue Datei: clients/app/node_modules/browserslist/node.js - neue Datei: clients/app/node_modules/browserslist/package.json - neue Datei: clients/app/node_modules/browserslist/parse.js - neue Datei: clients/app/node_modules/bser/README.md - neue Datei: clients/app/node_modules/bser/index.js - neue Datei: clients/app/node_modules/bser/package.json - neue Datei: clients/app/node_modules/buffer-from/LICENSE - neue Datei: clients/app/node_modules/buffer-from/index.js - neue Datei: clients/app/node_modules/buffer-from/package.json - neue Datei: clients/app/node_modules/buffer-from/readme.md - neue Datei: clients/app/node_modules/callsites/index.d.ts - neue Datei: clients/app/node_modules/callsites/index.js - neue Datei: clients/app/node_modules/callsites/license - neue Datei: clients/app/node_modules/callsites/package.json - neue Datei: clients/app/node_modules/callsites/readme.md - neue Datei: clients/app/node_modules/camelcase/index.d.ts - neue Datei: clients/app/node_modules/camelcase/index.js - neue Datei: clients/app/node_modules/camelcase/license - neue Datei: clients/app/node_modules/camelcase/package.json - neue Datei: clients/app/node_modules/camelcase/readme.md - neue Datei: clients/app/node_modules/caniuse-lite/LICENSE - neue Datei: clients/app/node_modules/caniuse-lite/README.md - neue Datei: clients/app/node_modules/caniuse-lite/data/agents.js - neue Datei: clients/app/node_modules/caniuse-lite/data/browserVersions.js - neue Datei: clients/app/node_modules/caniuse-lite/data/browsers.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/aac.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/abortcontroller.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/ac3-ec3.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/accelerometer.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/addeventlistener.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/alternate-stylesheet.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/ambient-light.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/apng.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/array-find-index.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/array-find.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/array-flat.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/array-includes.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/arrow-functions.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/asmjs.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/async-clipboard.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/async-functions.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/atob-btoa.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/audio-api.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/audio.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/audiotracks.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/autofocus.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/auxclick.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/av1.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/avif.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/background-attachment.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/background-clip-text.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/background-img-opts.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/background-position-x-y.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/background-repeat-round-space.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/background-sync.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/battery-status.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/beacon.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/beforeafterprint.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/bigint.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/blobbuilder.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/bloburls.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/border-image.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/border-radius.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/broadcastchannel.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/brotli.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/calc.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/canvas-blending.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/canvas-text.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/canvas.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/ch-unit.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/chacha20-poly1305.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/channel-messaging.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/childnode-remove.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/classlist.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/client-hints-dpr-width-viewport.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/clipboard.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/colr-v1.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/colr.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/comparedocumentposition.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/console-basic.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/console-time.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/const.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/constraint-validation.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/contenteditable.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/contentsecuritypolicy.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/contentsecuritypolicy2.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/cookie-store-api.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/cors.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/createimagebitmap.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/credential-management.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/cross-document-view-transitions.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/cryptography.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-all.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-anchor-positioning.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-animation.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-any-link.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-appearance.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-at-counter-style.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-autofill.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-backdrop-filter.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-background-offsets.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-backgroundblendmode.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-boxdecorationbreak.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-boxshadow.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-canvas.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-caret-color.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-cascade-layers.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-cascade-scope.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-case-insensitive.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-clip-path.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-color-adjust.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-color-function.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-conic-gradients.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-container-queries-style.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-container-queries.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-container-query-units.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-containment.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-content-visibility.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-counters.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-crisp-edges.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-cross-fade.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-default-pseudo.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-descendant-gtgt.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-deviceadaptation.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-dir-pseudo.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-display-contents.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-element-function.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-env-function.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-exclusions.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-featurequeries.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-file-selector-button.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-filter-function.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-filters.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-first-letter.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-first-line.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-fixed.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-focus-visible.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-focus-within.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-font-palette.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-font-rendering-controls.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-font-stretch.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-gencontent.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-gradients.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-grid-animation.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-grid.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-hanging-punctuation.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-has.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-hyphens.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-if.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-image-orientation.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-image-set.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-in-out-of-range.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-indeterminate-pseudo.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-initial-letter.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-initial-value.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-lch-lab.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-letter-spacing.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-line-clamp.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-logical-props.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-marker-pseudo.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-masks.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-matches-pseudo.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-math-functions.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-media-interaction.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-media-range-syntax.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-media-resolution.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-media-scripting.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-mediaqueries.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-mixblendmode.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-module-scripts.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-motion-paths.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-namespaces.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-nesting.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-not-sel-list.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-nth-child-of.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-opacity.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-optional-pseudo.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-overflow-anchor.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-overflow-overlay.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-overflow.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-overscroll-behavior.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-page-break.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-paged-media.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-paint-api.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-placeholder-shown.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-placeholder.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-print-color-adjust.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-read-only-write.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-rebeccapurple.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-reflections.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-regions.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-relative-colors.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-repeating-gradients.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-resize.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-revert-value.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-rrggbbaa.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-scroll-behavior.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-scrollbar.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-sel2.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-sel3.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-selection.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-shapes.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-snappoints.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-sticky.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-subgrid.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-supports-api.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-table.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-text-align-last.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-text-box-trim.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-text-indent.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-text-justify.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-text-orientation.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-text-spacing.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-text-wrap-balance.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-textshadow.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-touch-action.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-transitions.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-unicode-bidi.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-unset-value.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-variables.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-when-else.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-widows-orphans.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-width-stretch.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-writing-mode.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css-zoom.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css3-attr.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css3-boxsizing.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css3-colors.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css3-cursors-grab.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css3-cursors-newer.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css3-cursors.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/css3-tabsize.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/currentcolor.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/custom-elements.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/custom-elementsv1.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/customevent.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/datalist.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/dataset.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/datauri.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/date-tolocaledatestring.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/declarative-shadow-dom.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/decorators.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/details.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/deviceorientation.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/devicepixelratio.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/dialog.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/dispatchevent.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/dnssec.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/do-not-track.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/document-currentscript.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/document-evaluate-xpath.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/document-execcommand.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/document-policy.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/document-scrollingelement.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/documenthead.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/dom-manip-convenience.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/dom-range.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/domcontentloaded.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/dommatrix.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/download.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/dragndrop.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/element-closest.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/element-from-point.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/element-scroll-methods.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/eme.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/eot.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/es5.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/es6-class.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/es6-generators.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/es6-module-dynamic-import.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/es6-module.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/es6-number.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/es6-string-includes.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/es6.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/eventsource.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/extended-system-fonts.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/feature-policy.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/fetch.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/fieldset-disabled.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/fileapi.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/filereader.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/filereadersync.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/filesystem.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/flac.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/flexbox-gap.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/flexbox.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/flow-root.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/focusin-focusout-events.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/font-family-system-ui.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/font-feature.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/font-kerning.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/font-loading.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/font-size-adjust.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/font-smooth.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/font-unicode-range.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/font-variant-alternates.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/font-variant-numeric.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/fontface.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/form-attribute.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/form-submit-attributes.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/form-validation.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/forms.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/fullscreen.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/gamepad.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/geolocation.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/getboundingclientrect.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/getcomputedstyle.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/getelementsbyclassname.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/getrandomvalues.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/gyroscope.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/hardwareconcurrency.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/hashchange.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/heif.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/hevc.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/hidden.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/high-resolution-time.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/history.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/html-media-capture.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/html5semantic.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/http-live-streaming.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/http2.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/http3.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/iframe-sandbox.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/iframe-seamless.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/iframe-srcdoc.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/imagecapture.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/ime.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/img-naturalwidth-naturalheight.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/import-maps.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/imports.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/indeterminate-checkbox.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/indexeddb.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/indexeddb2.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/inline-block.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/innertext.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/input-autocomplete-onoff.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/input-color.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/input-datetime.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/input-email-tel-url.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/input-event.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/input-file-accept.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/input-file-directory.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/input-file-multiple.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/input-inputmode.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/input-minlength.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/input-number.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/input-pattern.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/input-placeholder.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/input-range.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/input-search.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/input-selection.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/insert-adjacent.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/insertadjacenthtml.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/internationalization.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/intersectionobserver-v2.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/intersectionobserver.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/intl-pluralrules.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/intrinsic-width.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/jpeg2000.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/jpegxl.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/jpegxr.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/js-regexp-lookbehind.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/json.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/justify-content-space-evenly.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/kerning-pairs-ligatures.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/keyboardevent-charcode.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/keyboardevent-code.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/keyboardevent-getmodifierstate.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/keyboardevent-key.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/keyboardevent-location.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/keyboardevent-which.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/lazyload.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/let.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/link-icon-png.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/link-icon-svg.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/link-rel-dns-prefetch.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/link-rel-modulepreload.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/link-rel-preconnect.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/link-rel-prefetch.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/link-rel-preload.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/link-rel-prerender.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/loading-lazy-attr.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/localecompare.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/magnetometer.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/matchesselector.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/matchmedia.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/mathml.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/maxlength.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/mdn-css-backdrop-pseudo-element.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/mdn-css-unicode-bidi-isolate-override.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/mdn-css-unicode-bidi-isolate.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/mdn-css-unicode-bidi-plaintext.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/mdn-text-decoration-color.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/mdn-text-decoration-line.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/mdn-text-decoration-shorthand.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/mdn-text-decoration-style.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/media-fragments.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/mediacapture-fromelement.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/mediarecorder.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/mediasource.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/menu.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/meta-theme-color.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/meter.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/midi.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/minmaxwh.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/mp3.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/mpeg-dash.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/mpeg4.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/multibackgrounds.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/multicolumn.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/mutation-events.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/mutationobserver.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/namevalue-storage.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/native-filesystem-api.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/nav-timing.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/netinfo.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/notifications.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/object-entries.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/object-fit.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/object-observe.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/object-values.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/objectrtc.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/offline-apps.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/offscreencanvas.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/ogg-vorbis.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/ogv.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/ol-reversed.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/once-event-listener.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/online-status.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/opus.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/orientation-sensor.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/outline.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/pad-start-end.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/page-transition-events.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/pagevisibility.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/passive-event-listener.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/passkeys.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/passwordrules.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/path2d.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/payment-request.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/pdf-viewer.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/permissions-api.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/permissions-policy.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/picture-in-picture.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/picture.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/ping.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/png-alpha.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/pointer-events.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/pointer.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/pointerlock.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/portals.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/prefers-color-scheme.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/prefers-reduced-motion.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/progress.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/promise-finally.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/promises.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/proximity.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/proxy.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/publickeypinning.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/push-api.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/queryselector.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/readonly-attr.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/referrer-policy.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/registerprotocolhandler.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/rel-noopener.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/rel-noreferrer.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/rellist.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/rem.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/requestanimationframe.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/requestidlecallback.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/resizeobserver.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/resource-timing.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/rest-parameters.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/rtcpeerconnection.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/ruby.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/run-in.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/same-site-cookie-attribute.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/screen-orientation.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/script-async.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/script-defer.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/scrollintoview.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/scrollintoviewifneeded.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/sdch.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/selection-api.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/selectlist.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/server-timing.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/serviceworkers.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/setimmediate.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/shadowdom.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/shadowdomv1.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/sharedarraybuffer.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/sharedworkers.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/sni.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/spdy.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/speech-recognition.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/speech-synthesis.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/spellcheck-attribute.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/sql-storage.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/srcset.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/stream.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/streams.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/stricttransportsecurity.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/style-scoped.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/subresource-bundling.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/subresource-integrity.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/svg-css.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/svg-filters.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/svg-fonts.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/svg-fragment.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/svg-html.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/svg-html5.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/svg-img.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/svg-smil.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/svg.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/sxg.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/tabindex-attr.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/template-literals.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/template.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/temporal.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/testfeat.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/text-decoration.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/text-emphasis.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/text-overflow.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/text-size-adjust.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/text-stroke.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/textcontent.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/textencoder.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/tls1-1.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/tls1-2.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/tls1-3.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/touch.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/transforms2d.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/transforms3d.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/trusted-types.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/ttf.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/typedarrays.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/u2f.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/unhandledrejection.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/upgradeinsecurerequests.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/url-scroll-to-text-fragment.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/url.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/urlsearchparams.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/use-strict.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/user-select-none.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/user-timing.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/variable-fonts.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/vector-effect.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/vibration.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/video.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/videotracks.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/view-transitions.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/viewport-unit-variants.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/viewport-units.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wai-aria.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wake-lock.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wasm-bigint.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wasm-bulk-memory.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wasm-extended-const.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wasm-gc.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wasm-multi-memory.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wasm-multi-value.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wasm-mutable-globals.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wasm-nontrapping-fptoint.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wasm-reference-types.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wasm-relaxed-simd.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wasm-signext.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wasm-simd.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wasm-tail-calls.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wasm-threads.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wasm.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wav.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wbr-element.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/web-animation.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/web-app-manifest.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/web-bluetooth.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/web-serial.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/web-share.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/webauthn.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/webcodecs.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/webgl.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/webgl2.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/webgpu.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/webhid.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/webkit-user-drag.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/webm.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/webnfc.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/webp.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/websockets.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/webtransport.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/webusb.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/webvr.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/webvtt.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/webworkers.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/webxr.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/will-change.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/woff.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/woff2.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/word-break.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/wordwrap.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/x-doc-messaging.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/x-frame-options.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/xhr2.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/xhtml.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/xhtmlsmil.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/xml-serializer.js - neue Datei: clients/app/node_modules/caniuse-lite/data/features/zstd.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/AD.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/AE.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/AF.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/AG.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/AI.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/AL.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/AM.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/AO.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/AR.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/AS.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/AT.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/AU.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/AW.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/AX.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/AZ.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/BA.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/BB.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/BD.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/BE.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/BF.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/BG.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/BH.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/BI.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/BJ.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/BM.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/BN.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/BO.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/BR.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/BS.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/BT.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/BW.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/BY.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/BZ.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/CA.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/CD.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/CF.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/CG.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/CH.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/CI.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/CK.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/CL.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/CM.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/CN.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/CO.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/CR.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/CU.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/CV.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/CX.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/CY.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/CZ.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/DE.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/DJ.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/DK.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/DM.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/DO.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/DZ.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/EC.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/EE.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/EG.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/ER.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/ES.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/ET.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/FI.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/FJ.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/FK.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/FM.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/FO.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/FR.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/GA.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/GB.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/GD.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/GE.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/GF.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/GG.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/GH.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/GI.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/GL.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/GM.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/GN.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/GP.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/GQ.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/GR.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/GT.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/GU.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/GW.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/GY.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/HK.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/HN.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/HR.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/HT.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/HU.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/ID.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/IE.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/IL.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/IM.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/IN.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/IQ.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/IR.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/IS.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/IT.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/JE.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/JM.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/JO.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/JP.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/KE.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/KG.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/KH.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/KI.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/KM.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/KN.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/KP.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/KR.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/KW.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/KY.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/KZ.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/LA.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/LB.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/LC.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/LI.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/LK.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/LR.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/LS.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/LT.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/LU.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/LV.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/LY.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MA.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MC.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MD.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/ME.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MG.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MH.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MK.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/ML.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MM.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MN.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MO.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MP.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MQ.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MR.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MS.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MT.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MU.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MV.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MW.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MX.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MY.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/MZ.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/NA.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/NC.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/NE.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/NF.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/NG.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/NI.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/NL.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/NO.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/NP.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/NR.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/NU.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/NZ.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/OM.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/PA.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/PE.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/PF.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/PG.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/PH.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/PK.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/PL.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/PM.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/PN.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/PR.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/PS.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/PT.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/PW.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/PY.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/QA.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/RE.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/RO.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/RS.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/RU.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/RW.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/SA.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/SB.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/SC.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/SD.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/SE.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/SG.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/SH.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/SI.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/SK.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/SL.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/SM.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/SN.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/SO.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/SR.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/ST.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/SV.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/SY.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/SZ.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/TC.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/TD.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/TG.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/TH.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/TJ.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/TL.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/TM.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/TN.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/TO.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/TR.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/TT.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/TV.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/TW.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/TZ.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/UA.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/UG.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/US.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/UY.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/UZ.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/VA.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/VC.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/VE.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/VG.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/VI.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/VN.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/VU.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/WF.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/WS.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/YE.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/YT.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/ZA.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/ZM.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/ZW.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/alt-af.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/alt-an.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/alt-as.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/alt-eu.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/alt-na.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/alt-oc.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/alt-sa.js - neue Datei: clients/app/node_modules/caniuse-lite/data/regions/alt-ww.js - neue Datei: clients/app/node_modules/caniuse-lite/dist/lib/statuses.js - neue Datei: clients/app/node_modules/caniuse-lite/dist/lib/supported.js - neue Datei: clients/app/node_modules/caniuse-lite/dist/unpacker/agents.js - neue Datei: clients/app/node_modules/caniuse-lite/dist/unpacker/browserVersions.js - neue Datei: clients/app/node_modules/caniuse-lite/dist/unpacker/browsers.js - neue Datei: clients/app/node_modules/caniuse-lite/dist/unpacker/feature.js - neue Datei: clients/app/node_modules/caniuse-lite/dist/unpacker/features.js - neue Datei: clients/app/node_modules/caniuse-lite/dist/unpacker/index.js - neue Datei: clients/app/node_modules/caniuse-lite/dist/unpacker/region.js - neue Datei: clients/app/node_modules/caniuse-lite/package.json - neue Datei: clients/app/node_modules/chalk/index.d.ts - neue Datei: clients/app/node_modules/chalk/license - neue Datei: clients/app/node_modules/chalk/package.json - neue Datei: clients/app/node_modules/chalk/readme.md - neue Datei: clients/app/node_modules/chalk/source/index.js - neue Datei: clients/app/node_modules/chalk/source/templates.js - neue Datei: clients/app/node_modules/chalk/source/util.js - neue Datei: clients/app/node_modules/char-regex/LICENSE - neue Datei: clients/app/node_modules/char-regex/README.md - neue Datei: clients/app/node_modules/char-regex/index.d.ts - neue Datei: clients/app/node_modules/char-regex/index.js - neue Datei: clients/app/node_modules/char-regex/package.json - neue Datei: clients/app/node_modules/ci-info/CHANGELOG.md - neue Datei: clients/app/node_modules/ci-info/LICENSE - neue Datei: clients/app/node_modules/ci-info/README.md - neue Datei: clients/app/node_modules/ci-info/index.d.ts - neue Datei: clients/app/node_modules/ci-info/index.js - neue Datei: clients/app/node_modules/ci-info/package.json - neue Datei: clients/app/node_modules/ci-info/vendors.json - neue Datei: clients/app/node_modules/cjs-module-lexer/LICENSE - neue Datei: clients/app/node_modules/cjs-module-lexer/README.md - neue Datei: clients/app/node_modules/cjs-module-lexer/dist/lexer.js - neue Datei: clients/app/node_modules/cjs-module-lexer/dist/lexer.mjs - neue Datei: clients/app/node_modules/cjs-module-lexer/lexer.d.ts - neue Datei: clients/app/node_modules/cjs-module-lexer/lexer.js - neue Datei: clients/app/node_modules/cjs-module-lexer/package.json - neue Datei: clients/app/node_modules/cliui/CHANGELOG.md - neue Datei: clients/app/node_modules/cliui/LICENSE.txt - neue Datei: clients/app/node_modules/cliui/README.md - neue Datei: clients/app/node_modules/cliui/index.mjs - neue Datei: clients/app/node_modules/cliui/package.json - neue Datei: clients/app/node_modules/co/History.md - neue Datei: clients/app/node_modules/co/LICENSE - neue Datei: clients/app/node_modules/co/Readme.md - neue Datei: clients/app/node_modules/co/index.js - neue Datei: clients/app/node_modules/co/package.json - neue Datei: clients/app/node_modules/collect-v8-coverage/CHANGELOG.md - neue Datei: clients/app/node_modules/collect-v8-coverage/LICENSE - neue Datei: clients/app/node_modules/collect-v8-coverage/README.md - neue Datei: clients/app/node_modules/collect-v8-coverage/index.d.ts - neue Datei: clients/app/node_modules/collect-v8-coverage/index.js - neue Datei: clients/app/node_modules/collect-v8-coverage/package.json - neue Datei: clients/app/node_modules/color-convert/CHANGELOG.md - neue Datei: clients/app/node_modules/color-convert/LICENSE - neue Datei: clients/app/node_modules/color-convert/README.md - neue Datei: clients/app/node_modules/color-convert/conversions.js - neue Datei: clients/app/node_modules/color-convert/index.js - neue Datei: clients/app/node_modules/color-convert/package.json - neue Datei: clients/app/node_modules/color-convert/route.js - neue Datei: clients/app/node_modules/color-name/LICENSE - neue Datei: clients/app/node_modules/color-name/README.md - neue Datei: clients/app/node_modules/color-name/index.js - neue Datei: clients/app/node_modules/color-name/package.json - neue Datei: clients/app/node_modules/commander/CHANGELOG.md - neue Datei: clients/app/node_modules/commander/LICENSE - neue Datei: clients/app/node_modules/commander/Readme.md - neue Datei: clients/app/node_modules/commander/esm.mjs - neue Datei: clients/app/node_modules/commander/index.js - neue Datei: clients/app/node_modules/commander/package-support.json - neue Datei: clients/app/node_modules/commander/package.json - neue Datei: clients/app/node_modules/commander/typings/index.d.ts - neue Datei: clients/app/node_modules/concat-map/.travis.yml - neue Datei: clients/app/node_modules/concat-map/LICENSE - neue Datei: clients/app/node_modules/concat-map/README.markdown - neue Datei: clients/app/node_modules/concat-map/example/map.js - neue Datei: clients/app/node_modules/concat-map/index.js - neue Datei: clients/app/node_modules/concat-map/package.json - neue Datei: clients/app/node_modules/concat-map/test/map.js - neue Datei: clients/app/node_modules/convert-source-map/LICENSE - neue Datei: clients/app/node_modules/convert-source-map/README.md - neue Datei: clients/app/node_modules/convert-source-map/index.js - neue Datei: clients/app/node_modules/convert-source-map/package.json - neue Datei: clients/app/node_modules/create-jest/LICENSE - neue Datei: clients/app/node_modules/create-jest/README.md - neue Datei: clients/app/node_modules/create-jest/bin/create-jest.js - neue Datei: clients/app/node_modules/create-jest/package.json - neue Datei: clients/app/node_modules/cross-spawn/LICENSE - neue Datei: clients/app/node_modules/cross-spawn/README.md - neue Datei: clients/app/node_modules/cross-spawn/index.js - neue Datei: clients/app/node_modules/cross-spawn/lib/enoent.js - neue Datei: clients/app/node_modules/cross-spawn/lib/parse.js - neue Datei: clients/app/node_modules/cross-spawn/lib/util/escape.js - neue Datei: clients/app/node_modules/cross-spawn/lib/util/readShebang.js - neue Datei: clients/app/node_modules/cross-spawn/lib/util/resolveCommand.js - neue Datei: clients/app/node_modules/cross-spawn/package.json - neue Datei: clients/app/node_modules/debounce/CONTRIBUTORS - neue Datei: clients/app/node_modules/debounce/History.md - neue Datei: clients/app/node_modules/debounce/LICENSE - neue Datei: clients/app/node_modules/debounce/Makefile - neue Datei: clients/app/node_modules/debounce/Readme.md - neue Datei: clients/app/node_modules/debounce/component.json - neue Datei: clients/app/node_modules/debounce/index.js - neue Datei: clients/app/node_modules/debounce/package.json - neue Datei: clients/app/node_modules/debounce/test.html - neue Datei: clients/app/node_modules/debounce/test.js - neue Datei: clients/app/node_modules/debug/LICENSE - neue Datei: clients/app/node_modules/debug/README.md - neue Datei: clients/app/node_modules/debug/package.json - neue Datei: clients/app/node_modules/debug/src/browser.js - neue Datei: clients/app/node_modules/debug/src/common.js - neue Datei: clients/app/node_modules/debug/src/index.js - neue Datei: clients/app/node_modules/debug/src/node.js - neue Datei: clients/app/node_modules/dedent/LICENSE.md - neue Datei: clients/app/node_modules/dedent/README.md - neue Datei: clients/app/node_modules/dedent/dist/dedent.d.mts - neue Datei: clients/app/node_modules/dedent/dist/dedent.d.ts - neue Datei: clients/app/node_modules/dedent/dist/dedent.js - neue Datei: clients/app/node_modules/dedent/dist/dedent.mjs - neue Datei: clients/app/node_modules/dedent/macro.js - neue Datei: clients/app/node_modules/dedent/package.json - neue Datei: clients/app/node_modules/deepmerge/.editorconfig - neue Datei: clients/app/node_modules/deepmerge/.eslintcache - neue Datei: clients/app/node_modules/deepmerge/changelog.md - neue Datei: clients/app/node_modules/deepmerge/dist/cjs.js - neue Datei: clients/app/node_modules/deepmerge/dist/umd.js - neue Datei: clients/app/node_modules/deepmerge/index.d.ts - neue Datei: clients/app/node_modules/deepmerge/index.js - neue Datei: clients/app/node_modules/deepmerge/license.txt - neue Datei: clients/app/node_modules/deepmerge/package.json - neue Datei: clients/app/node_modules/deepmerge/readme.md - neue Datei: clients/app/node_modules/deepmerge/rollup.config.js - neue Datei: clients/app/node_modules/detect-newline/index.d.ts - neue Datei: clients/app/node_modules/detect-newline/index.js - neue Datei: clients/app/node_modules/detect-newline/license - neue Datei: clients/app/node_modules/detect-newline/package.json - neue Datei: clients/app/node_modules/detect-newline/readme.md - neue Datei: clients/app/node_modules/diff-sequences/LICENSE - neue Datei: clients/app/node_modules/diff-sequences/README.md - neue Datei: clients/app/node_modules/diff-sequences/package.json - neue Datei: clients/app/node_modules/duplexer/.travis.yml - neue Datei: clients/app/node_modules/duplexer/LICENCE - neue Datei: clients/app/node_modules/duplexer/README.md - neue Datei: clients/app/node_modules/duplexer/index.js - neue Datei: clients/app/node_modules/duplexer/package.json - neue Datei: clients/app/node_modules/duplexer/test/index.js - neue Datei: clients/app/node_modules/electron-to-chromium/LICENSE - neue Datei: clients/app/node_modules/electron-to-chromium/README.md - neue Datei: clients/app/node_modules/electron-to-chromium/chromium-versions.js - neue Datei: clients/app/node_modules/electron-to-chromium/chromium-versions.json - neue Datei: clients/app/node_modules/electron-to-chromium/full-chromium-versions.js - neue Datei: clients/app/node_modules/electron-to-chromium/full-chromium-versions.json - neue Datei: clients/app/node_modules/electron-to-chromium/full-versions.js - neue Datei: clients/app/node_modules/electron-to-chromium/full-versions.json - neue Datei: clients/app/node_modules/electron-to-chromium/index.js - neue Datei: clients/app/node_modules/electron-to-chromium/package.json - neue Datei: clients/app/node_modules/electron-to-chromium/versions.js - neue Datei: clients/app/node_modules/electron-to-chromium/versions.json - neue Datei: clients/app/node_modules/emittery/index.d.ts - neue Datei: clients/app/node_modules/emittery/index.js - neue Datei: clients/app/node_modules/emittery/license - neue Datei: clients/app/node_modules/emittery/maps.js - neue Datei: clients/app/node_modules/emittery/package.json - neue Datei: clients/app/node_modules/emittery/readme.md - neue Datei: clients/app/node_modules/emoji-regex/LICENSE-MIT.txt - neue Datei: clients/app/node_modules/emoji-regex/README.md - neue Datei: clients/app/node_modules/emoji-regex/es2015/index.js - neue Datei: clients/app/node_modules/emoji-regex/es2015/text.js - neue Datei: clients/app/node_modules/emoji-regex/index.d.ts - neue Datei: clients/app/node_modules/emoji-regex/index.js - neue Datei: clients/app/node_modules/emoji-regex/package.json - neue Datei: clients/app/node_modules/emoji-regex/text.js - neue Datei: clients/app/node_modules/error-ex/LICENSE - neue Datei: clients/app/node_modules/error-ex/README.md - neue Datei: clients/app/node_modules/error-ex/index.js - neue Datei: clients/app/node_modules/error-ex/package.json - neue Datei: clients/app/node_modules/escalade/dist/index.js - neue Datei: clients/app/node_modules/escalade/dist/index.mjs - neue Datei: clients/app/node_modules/escalade/index.d.mts - neue Datei: clients/app/node_modules/escalade/index.d.ts - neue Datei: clients/app/node_modules/escalade/license - neue Datei: clients/app/node_modules/escalade/package.json - neue Datei: clients/app/node_modules/escalade/readme.md - neue Datei: clients/app/node_modules/escalade/sync/index.d.mts - neue Datei: clients/app/node_modules/escalade/sync/index.d.ts - neue Datei: clients/app/node_modules/escalade/sync/index.js - neue Datei: clients/app/node_modules/escalade/sync/index.mjs - neue Datei: clients/app/node_modules/escape-string-regexp/index.d.ts - neue Datei: clients/app/node_modules/escape-string-regexp/index.js - neue Datei: clients/app/node_modules/escape-string-regexp/license - neue Datei: clients/app/node_modules/escape-string-regexp/package.json - neue Datei: clients/app/node_modules/escape-string-regexp/readme.md - neue Datei: clients/app/node_modules/esprima/ChangeLog - neue Datei: clients/app/node_modules/esprima/LICENSE.BSD - neue Datei: clients/app/node_modules/esprima/README.md - neue Datei: clients/app/node_modules/esprima/bin/esparse.js - neue Datei: clients/app/node_modules/esprima/bin/esvalidate.js - neue Datei: clients/app/node_modules/esprima/dist/esprima.js - neue Datei: clients/app/node_modules/esprima/package.json - neue Datei: clients/app/node_modules/execa/index.d.ts - neue Datei: clients/app/node_modules/execa/index.js - neue Datei: clients/app/node_modules/execa/lib/command.js - neue Datei: clients/app/node_modules/execa/lib/error.js - neue Datei: clients/app/node_modules/execa/lib/kill.js - neue Datei: clients/app/node_modules/execa/lib/promise.js - neue Datei: clients/app/node_modules/execa/lib/stdio.js - neue Datei: clients/app/node_modules/execa/lib/stream.js - neue Datei: clients/app/node_modules/execa/license - neue Datei: clients/app/node_modules/execa/package.json - neue Datei: clients/app/node_modules/execa/readme.md - neue Datei: clients/app/node_modules/exit/.jshintrc - neue Datei: clients/app/node_modules/exit/.npmignore - neue Datei: clients/app/node_modules/exit/.travis.yml - neue Datei: clients/app/node_modules/exit/Gruntfile.js - neue Datei: clients/app/node_modules/exit/LICENSE-MIT - neue Datei: clients/app/node_modules/exit/README.md - neue Datei: clients/app/node_modules/exit/lib/exit.js - neue Datei: clients/app/node_modules/exit/package.json - neue Datei: clients/app/node_modules/exit/test/exit_test.js - neue Datei: clients/app/node_modules/exit/test/fixtures/10-stderr.txt - neue Datei: clients/app/node_modules/exit/test/fixtures/10-stdout-stderr.txt - neue Datei: clients/app/node_modules/exit/test/fixtures/10-stdout.txt - neue Datei: clients/app/node_modules/exit/test/fixtures/100-stderr.txt - neue Datei: clients/app/node_modules/exit/test/fixtures/100-stdout-stderr.txt - neue Datei: clients/app/node_modules/exit/test/fixtures/100-stdout.txt - neue Datei: clients/app/node_modules/exit/test/fixtures/1000-stderr.txt - neue Datei: clients/app/node_modules/exit/test/fixtures/1000-stdout-stderr.txt - neue Datei: clients/app/node_modules/exit/test/fixtures/1000-stdout.txt - neue Datei: clients/app/node_modules/exit/test/fixtures/create-files.sh - neue Datei: clients/app/node_modules/exit/test/fixtures/log-broken.js - neue Datei: clients/app/node_modules/exit/test/fixtures/log.js - neue Datei: clients/app/node_modules/expect/LICENSE - neue Datei: clients/app/node_modules/expect/README.md - neue Datei: clients/app/node_modules/expect/package.json - neue Datei: clients/app/node_modules/fast-json-stable-stringify/.eslintrc.yml - neue Datei: clients/app/node_modules/fast-json-stable-stringify/.github/FUNDING.yml - neue Datei: clients/app/node_modules/fast-json-stable-stringify/.travis.yml - neue Datei: clients/app/node_modules/fast-json-stable-stringify/LICENSE - neue Datei: clients/app/node_modules/fast-json-stable-stringify/README.md - neue Datei: clients/app/node_modules/fast-json-stable-stringify/benchmark/index.js - neue Datei: clients/app/node_modules/fast-json-stable-stringify/benchmark/test.json - neue Datei: clients/app/node_modules/fast-json-stable-stringify/example/key_cmp.js - neue Datei: clients/app/node_modules/fast-json-stable-stringify/example/nested.js - neue Datei: clients/app/node_modules/fast-json-stable-stringify/example/str.js - neue Datei: clients/app/node_modules/fast-json-stable-stringify/example/value_cmp.js - neue Datei: clients/app/node_modules/fast-json-stable-stringify/index.d.ts - neue Datei: clients/app/node_modules/fast-json-stable-stringify/index.js - neue Datei: clients/app/node_modules/fast-json-stable-stringify/package.json - neue Datei: clients/app/node_modules/fast-json-stable-stringify/test/cmp.js - neue Datei: clients/app/node_modules/fast-json-stable-stringify/test/nested.js - neue Datei: clients/app/node_modules/fast-json-stable-stringify/test/str.js - neue Datei: clients/app/node_modules/fast-json-stable-stringify/test/to-json.js - neue Datei: clients/app/node_modules/fb-watchman/README.md - neue Datei: clients/app/node_modules/fb-watchman/index.js - neue Datei: clients/app/node_modules/fb-watchman/package.json - neue Datei: clients/app/node_modules/fill-range/LICENSE - neue Datei: clients/app/node_modules/fill-range/README.md - neue Datei: clients/app/node_modules/fill-range/index.js - neue Datei: clients/app/node_modules/fill-range/package.json - neue Datei: clients/app/node_modules/find-up/index.d.ts - neue Datei: clients/app/node_modules/find-up/index.js - neue Datei: clients/app/node_modules/find-up/license - neue Datei: clients/app/node_modules/find-up/package.json - neue Datei: clients/app/node_modules/find-up/readme.md - neue Datei: clients/app/node_modules/fs.realpath/LICENSE - neue Datei: clients/app/node_modules/fs.realpath/README.md - neue Datei: clients/app/node_modules/fs.realpath/index.js - neue Datei: clients/app/node_modules/fs.realpath/old.js - neue Datei: clients/app/node_modules/fs.realpath/package.json - neue Datei: clients/app/node_modules/function-bind/.eslintrc - neue Datei: clients/app/node_modules/function-bind/.github/FUNDING.yml - neue Datei: clients/app/node_modules/function-bind/.github/SECURITY.md - neue Datei: clients/app/node_modules/function-bind/.nycrc - neue Datei: clients/app/node_modules/function-bind/CHANGELOG.md - neue Datei: clients/app/node_modules/function-bind/LICENSE - neue Datei: clients/app/node_modules/function-bind/README.md - neue Datei: clients/app/node_modules/function-bind/implementation.js - neue Datei: clients/app/node_modules/function-bind/index.js - neue Datei: clients/app/node_modules/function-bind/package.json - neue Datei: clients/app/node_modules/function-bind/test/.eslintrc - neue Datei: clients/app/node_modules/function-bind/test/index.js - neue Datei: clients/app/node_modules/gensync/LICENSE - neue Datei: clients/app/node_modules/gensync/README.md - neue Datei: clients/app/node_modules/gensync/index.js - neue Datei: clients/app/node_modules/gensync/index.js.flow - neue Datei: clients/app/node_modules/gensync/package.json - neue Datei: clients/app/node_modules/gensync/test/.babelrc - neue Datei: clients/app/node_modules/gensync/test/index.test.js - neue Datei: clients/app/node_modules/get-caller-file/LICENSE.md - neue Datei: clients/app/node_modules/get-caller-file/README.md - neue Datei: clients/app/node_modules/get-caller-file/index.d.ts - neue Datei: clients/app/node_modules/get-caller-file/index.js - neue Datei: clients/app/node_modules/get-caller-file/index.js.map - neue Datei: clients/app/node_modules/get-caller-file/package.json - neue Datei: clients/app/node_modules/get-package-type/CHANGELOG.md - neue Datei: clients/app/node_modules/get-package-type/LICENSE - neue Datei: clients/app/node_modules/get-package-type/README.md - neue Datei: clients/app/node_modules/get-package-type/async.cjs - neue Datei: clients/app/node_modules/get-package-type/cache.cjs - neue Datei: clients/app/node_modules/get-package-type/index.cjs - neue Datei: clients/app/node_modules/get-package-type/is-node-modules.cjs - neue Datei: clients/app/node_modules/get-package-type/package.json - neue Datei: clients/app/node_modules/get-package-type/sync.cjs - neue Datei: clients/app/node_modules/get-stream/buffer-stream.js - neue Datei: clients/app/node_modules/get-stream/index.d.ts - neue Datei: clients/app/node_modules/get-stream/index.js - neue Datei: clients/app/node_modules/get-stream/license - neue Datei: clients/app/node_modules/get-stream/package.json - neue Datei: clients/app/node_modules/get-stream/readme.md - neue Datei: clients/app/node_modules/glob/LICENSE - neue Datei: clients/app/node_modules/glob/README.md - neue Datei: clients/app/node_modules/glob/common.js - neue Datei: clients/app/node_modules/glob/glob.js - neue Datei: clients/app/node_modules/glob/package.json - neue Datei: clients/app/node_modules/glob/sync.js - neue Datei: clients/app/node_modules/graceful-fs/LICENSE - neue Datei: clients/app/node_modules/graceful-fs/README.md - neue Datei: clients/app/node_modules/graceful-fs/clone.js - neue Datei: clients/app/node_modules/graceful-fs/graceful-fs.js - neue Datei: clients/app/node_modules/graceful-fs/legacy-streams.js - neue Datei: clients/app/node_modules/graceful-fs/package.json - neue Datei: clients/app/node_modules/graceful-fs/polyfills.js - neue Datei: clients/app/node_modules/gzip-size/index.d.ts - neue Datei: clients/app/node_modules/gzip-size/index.js - neue Datei: clients/app/node_modules/gzip-size/license - neue Datei: clients/app/node_modules/gzip-size/package.json - neue Datei: clients/app/node_modules/gzip-size/readme.md - neue Datei: clients/app/node_modules/has-flag/index.d.ts - neue Datei: clients/app/node_modules/has-flag/index.js - neue Datei: clients/app/node_modules/has-flag/license - neue Datei: clients/app/node_modules/has-flag/package.json - neue Datei: clients/app/node_modules/has-flag/readme.md - neue Datei: clients/app/node_modules/hasown/.eslintrc - neue Datei: clients/app/node_modules/hasown/.github/FUNDING.yml - neue Datei: clients/app/node_modules/hasown/.nycrc - neue Datei: clients/app/node_modules/hasown/CHANGELOG.md - neue Datei: clients/app/node_modules/hasown/LICENSE - neue Datei: clients/app/node_modules/hasown/README.md - neue Datei: clients/app/node_modules/hasown/index.d.ts - neue Datei: clients/app/node_modules/hasown/index.js - neue Datei: clients/app/node_modules/hasown/package.json - neue Datei: clients/app/node_modules/hasown/tsconfig.json - neue Datei: clients/app/node_modules/html-escaper/LICENSE.txt - neue Datei: clients/app/node_modules/html-escaper/README.md - neue Datei: clients/app/node_modules/html-escaper/cjs/index.js - neue Datei: clients/app/node_modules/html-escaper/cjs/package.json - neue Datei: clients/app/node_modules/html-escaper/esm/index.js - neue Datei: clients/app/node_modules/html-escaper/index.js - neue Datei: clients/app/node_modules/html-escaper/min.js - neue Datei: clients/app/node_modules/html-escaper/package.json - neue Datei: clients/app/node_modules/html-escaper/test/index.js - neue Datei: clients/app/node_modules/html-escaper/test/package.json - neue Datei: clients/app/node_modules/human-signals/CHANGELOG.md - neue Datei: clients/app/node_modules/human-signals/LICENSE - neue Datei: clients/app/node_modules/human-signals/README.md - neue Datei: clients/app/node_modules/human-signals/package.json - neue Datei: clients/app/node_modules/import-local/fixtures/cli.js - neue Datei: clients/app/node_modules/import-local/index.d.ts - neue Datei: clients/app/node_modules/import-local/index.js - neue Datei: clients/app/node_modules/import-local/license - neue Datei: clients/app/node_modules/import-local/package.json - neue Datei: clients/app/node_modules/import-local/readme.md - neue Datei: clients/app/node_modules/imurmurhash/README.md - neue Datei: clients/app/node_modules/imurmurhash/imurmurhash.js - neue Datei: clients/app/node_modules/imurmurhash/imurmurhash.min.js - neue Datei: clients/app/node_modules/imurmurhash/package.json - neue Datei: clients/app/node_modules/inflight/LICENSE - neue Datei: clients/app/node_modules/inflight/README.md - neue Datei: clients/app/node_modules/inflight/inflight.js - neue Datei: clients/app/node_modules/inflight/package.json - neue Datei: clients/app/node_modules/inherits/LICENSE - neue Datei: clients/app/node_modules/inherits/README.md - neue Datei: clients/app/node_modules/inherits/inherits.js - neue Datei: clients/app/node_modules/inherits/inherits_browser.js - neue Datei: clients/app/node_modules/inherits/package.json - neue Datei: clients/app/node_modules/is-arrayish/.editorconfig - neue Datei: clients/app/node_modules/is-arrayish/.istanbul.yml - neue Datei: clients/app/node_modules/is-arrayish/.npmignore - neue Datei: clients/app/node_modules/is-arrayish/.travis.yml - neue Datei: clients/app/node_modules/is-arrayish/LICENSE - neue Datei: clients/app/node_modules/is-arrayish/README.md - neue Datei: clients/app/node_modules/is-arrayish/index.js - neue Datei: clients/app/node_modules/is-arrayish/package.json - neue Datei: clients/app/node_modules/is-core-module/.eslintrc - neue Datei: clients/app/node_modules/is-core-module/.nycrc - neue Datei: clients/app/node_modules/is-core-module/CHANGELOG.md - neue Datei: clients/app/node_modules/is-core-module/LICENSE - neue Datei: clients/app/node_modules/is-core-module/README.md - neue Datei: clients/app/node_modules/is-core-module/core.json - neue Datei: clients/app/node_modules/is-core-module/index.js - neue Datei: clients/app/node_modules/is-core-module/package.json - neue Datei: clients/app/node_modules/is-core-module/test/index.js - neue Datei: clients/app/node_modules/is-fullwidth-code-point/index.d.ts - neue Datei: clients/app/node_modules/is-fullwidth-code-point/index.js - neue Datei: clients/app/node_modules/is-fullwidth-code-point/license - neue Datei: clients/app/node_modules/is-fullwidth-code-point/package.json - neue Datei: clients/app/node_modules/is-fullwidth-code-point/readme.md - neue Datei: clients/app/node_modules/is-generator-fn/index.d.ts - neue Datei: clients/app/node_modules/is-generator-fn/index.js - neue Datei: clients/app/node_modules/is-generator-fn/license - neue Datei: clients/app/node_modules/is-generator-fn/package.json - neue Datei: clients/app/node_modules/is-generator-fn/readme.md - neue Datei: clients/app/node_modules/is-number/LICENSE - neue Datei: clients/app/node_modules/is-number/README.md - neue Datei: clients/app/node_modules/is-number/index.js - neue Datei: clients/app/node_modules/is-number/package.json - neue Datei: clients/app/node_modules/is-stream/index.d.ts - neue Datei: clients/app/node_modules/is-stream/index.js - neue Datei: clients/app/node_modules/is-stream/license - neue Datei: clients/app/node_modules/is-stream/package.json - neue Datei: clients/app/node_modules/is-stream/readme.md - neue Datei: clients/app/node_modules/isexe/.npmignore - neue Datei: clients/app/node_modules/isexe/LICENSE - neue Datei: clients/app/node_modules/isexe/README.md - neue Datei: clients/app/node_modules/isexe/index.js - neue Datei: clients/app/node_modules/isexe/mode.js - neue Datei: clients/app/node_modules/isexe/package.json - neue Datei: clients/app/node_modules/isexe/test/basic.js - neue Datei: clients/app/node_modules/isexe/windows.js - neue Datei: clients/app/node_modules/istanbul-lib-coverage/CHANGELOG.md - neue Datei: clients/app/node_modules/istanbul-lib-coverage/LICENSE - neue Datei: clients/app/node_modules/istanbul-lib-coverage/README.md - neue Datei: clients/app/node_modules/istanbul-lib-coverage/index.js - neue Datei: clients/app/node_modules/istanbul-lib-coverage/lib/coverage-map.js - neue Datei: clients/app/node_modules/istanbul-lib-coverage/lib/coverage-summary.js - neue Datei: clients/app/node_modules/istanbul-lib-coverage/lib/data-properties.js - neue Datei: clients/app/node_modules/istanbul-lib-coverage/lib/file-coverage.js - neue Datei: clients/app/node_modules/istanbul-lib-coverage/lib/percent.js - neue Datei: clients/app/node_modules/istanbul-lib-coverage/package.json - neue Datei: clients/app/node_modules/istanbul-lib-instrument/CHANGELOG.md - neue Datei: clients/app/node_modules/istanbul-lib-instrument/LICENSE - neue Datei: clients/app/node_modules/istanbul-lib-instrument/README.md - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/.bin/semver - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/LICENSE - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/README.md - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/bin/semver.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/classes/comparator.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/classes/index.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/classes/range.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/classes/semver.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/clean.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/cmp.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/coerce.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/compare-build.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/compare-loose.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/compare.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/diff.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/eq.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/gt.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/gte.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/inc.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/lt.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/lte.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/major.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/minor.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/neq.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/parse.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/patch.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/prerelease.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/rcompare.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/rsort.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/satisfies.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/sort.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/functions/valid.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/index.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/internal/constants.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/internal/debug.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/internal/identifiers.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/internal/lrucache.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/internal/parse-options.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/internal/re.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/package.json - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/preload.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/range.bnf - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/ranges/gtr.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/ranges/intersects.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/ranges/ltr.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/ranges/max-satisfying.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/ranges/min-satisfying.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/ranges/min-version.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/ranges/outside.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/ranges/simplify.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/ranges/subset.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/ranges/to-comparators.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/node_modules/semver/ranges/valid.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/package.json - neue Datei: clients/app/node_modules/istanbul-lib-instrument/src/constants.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/src/index.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/src/instrumenter.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/src/read-coverage.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/src/source-coverage.js - neue Datei: clients/app/node_modules/istanbul-lib-instrument/src/visitor.js - neue Datei: clients/app/node_modules/istanbul-lib-report/CHANGELOG.md - neue Datei: clients/app/node_modules/istanbul-lib-report/LICENSE - neue Datei: clients/app/node_modules/istanbul-lib-report/README.md - neue Datei: clients/app/node_modules/istanbul-lib-report/index.js - neue Datei: clients/app/node_modules/istanbul-lib-report/lib/context.js - neue Datei: clients/app/node_modules/istanbul-lib-report/lib/file-writer.js - neue Datei: clients/app/node_modules/istanbul-lib-report/lib/path.js - neue Datei: clients/app/node_modules/istanbul-lib-report/lib/report-base.js - neue Datei: clients/app/node_modules/istanbul-lib-report/lib/summarizer-factory.js - neue Datei: clients/app/node_modules/istanbul-lib-report/lib/tree.js - neue Datei: clients/app/node_modules/istanbul-lib-report/lib/watermarks.js - neue Datei: clients/app/node_modules/istanbul-lib-report/lib/xml-writer.js - neue Datei: clients/app/node_modules/istanbul-lib-report/package.json - neue Datei: clients/app/node_modules/istanbul-lib-source-maps/CHANGELOG.md - neue Datei: clients/app/node_modules/istanbul-lib-source-maps/LICENSE - neue Datei: clients/app/node_modules/istanbul-lib-source-maps/README.md - neue Datei: clients/app/node_modules/istanbul-lib-source-maps/index.js - neue Datei: clients/app/node_modules/istanbul-lib-source-maps/lib/get-mapping.js - neue Datei: clients/app/node_modules/istanbul-lib-source-maps/lib/map-store.js - neue Datei: clients/app/node_modules/istanbul-lib-source-maps/lib/mapped.js - neue Datei: clients/app/node_modules/istanbul-lib-source-maps/lib/pathutils.js - neue Datei: clients/app/node_modules/istanbul-lib-source-maps/lib/transform-utils.js - neue Datei: clients/app/node_modules/istanbul-lib-source-maps/lib/transformer.js - neue Datei: clients/app/node_modules/istanbul-lib-source-maps/package.json - neue Datei: clients/app/node_modules/istanbul-reports/CHANGELOG.md - neue Datei: clients/app/node_modules/istanbul-reports/LICENSE - neue Datei: clients/app/node_modules/istanbul-reports/README.md - neue Datei: clients/app/node_modules/istanbul-reports/index.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/clover/index.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/cobertura/index.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/html-spa/.babelrc - neue Datei: clients/app/node_modules/istanbul-reports/lib/html-spa/assets/bundle.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/html-spa/assets/sort-arrow-sprite.png - neue Datei: clients/app/node_modules/istanbul-reports/lib/html-spa/assets/spa.css - neue Datei: clients/app/node_modules/istanbul-reports/lib/html-spa/index.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/html-spa/src/fileBreadcrumbs.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/html-spa/src/filterToggle.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/html-spa/src/flattenToggle.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/html-spa/src/getChildData.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/html-spa/src/index.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/html-spa/src/routing.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/html-spa/src/summaryHeader.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/html-spa/src/summaryTableHeader.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/html-spa/src/summaryTableLine.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/html-spa/webpack.config.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/html/annotator.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/html/assets/base.css - neue Datei: clients/app/node_modules/istanbul-reports/lib/html/assets/block-navigation.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/html/assets/favicon.png - neue Datei: clients/app/node_modules/istanbul-reports/lib/html/assets/sort-arrow-sprite.png - neue Datei: clients/app/node_modules/istanbul-reports/lib/html/assets/sorter.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/html/assets/vendor/prettify.css - neue Datei: clients/app/node_modules/istanbul-reports/lib/html/assets/vendor/prettify.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/html/index.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/html/insertion-text.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/json-summary/index.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/json/index.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/lcov/index.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/lcovonly/index.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/none/index.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/teamcity/index.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/text-lcov/index.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/text-summary/index.js - neue Datei: clients/app/node_modules/istanbul-reports/lib/text/index.js - neue Datei: clients/app/node_modules/istanbul-reports/package.json - neue Datei: clients/app/node_modules/jest-changed-files/LICENSE - neue Datei: clients/app/node_modules/jest-changed-files/README.md - neue Datei: clients/app/node_modules/jest-changed-files/package.json - neue Datei: clients/app/node_modules/jest-circus/LICENSE - neue Datei: clients/app/node_modules/jest-circus/README.md - neue Datei: clients/app/node_modules/jest-circus/package.json - neue Datei: clients/app/node_modules/jest-circus/runner.js - neue Datei: clients/app/node_modules/jest-cli/LICENSE - neue Datei: clients/app/node_modules/jest-cli/README.md - neue Datei: clients/app/node_modules/jest-cli/bin/jest.js - neue Datei: clients/app/node_modules/jest-cli/package.json - neue Datei: clients/app/node_modules/jest-config/LICENSE - neue Datei: clients/app/node_modules/jest-config/package.json - neue Datei: clients/app/node_modules/jest-diff/LICENSE - neue Datei: clients/app/node_modules/jest-diff/README.md - neue Datei: clients/app/node_modules/jest-diff/package.json - neue Datei: clients/app/node_modules/jest-docblock/LICENSE - neue Datei: clients/app/node_modules/jest-docblock/README.md - neue Datei: clients/app/node_modules/jest-docblock/package.json - neue Datei: clients/app/node_modules/jest-each/LICENSE - neue Datei: clients/app/node_modules/jest-each/README.md - neue Datei: clients/app/node_modules/jest-each/package.json - neue Datei: clients/app/node_modules/jest-environment-node/LICENSE - neue Datei: clients/app/node_modules/jest-environment-node/package.json - neue Datei: clients/app/node_modules/jest-get-type/LICENSE - neue Datei: clients/app/node_modules/jest-get-type/package.json - neue Datei: clients/app/node_modules/jest-haste-map/LICENSE - neue Datei: clients/app/node_modules/jest-haste-map/package.json - neue Datei: clients/app/node_modules/jest-leak-detector/LICENSE - neue Datei: clients/app/node_modules/jest-leak-detector/README.md - neue Datei: clients/app/node_modules/jest-leak-detector/package.json - neue Datei: clients/app/node_modules/jest-matcher-utils/LICENSE - neue Datei: clients/app/node_modules/jest-matcher-utils/README.md - neue Datei: clients/app/node_modules/jest-matcher-utils/package.json - neue Datei: clients/app/node_modules/jest-message-util/LICENSE - neue Datei: clients/app/node_modules/jest-message-util/package.json - neue Datei: clients/app/node_modules/jest-mock/LICENSE - neue Datei: clients/app/node_modules/jest-mock/README.md - neue Datei: clients/app/node_modules/jest-mock/package.json - neue Datei: clients/app/node_modules/jest-pnp-resolver/README.md - neue Datei: clients/app/node_modules/jest-pnp-resolver/createRequire.js - neue Datei: clients/app/node_modules/jest-pnp-resolver/getDefaultResolver.js - neue Datei: clients/app/node_modules/jest-pnp-resolver/index.d.ts - neue Datei: clients/app/node_modules/jest-pnp-resolver/index.js - neue Datei: clients/app/node_modules/jest-pnp-resolver/package.json - neue Datei: clients/app/node_modules/jest-regex-util/LICENSE - neue Datei: clients/app/node_modules/jest-regex-util/package.json - neue Datei: clients/app/node_modules/jest-resolve-dependencies/LICENSE - neue Datei: clients/app/node_modules/jest-resolve-dependencies/package.json - neue Datei: clients/app/node_modules/jest-resolve/LICENSE - neue Datei: clients/app/node_modules/jest-resolve/package.json - neue Datei: clients/app/node_modules/jest-runner/LICENSE - neue Datei: clients/app/node_modules/jest-runner/package.json - neue Datei: clients/app/node_modules/jest-runtime/LICENSE - neue Datei: clients/app/node_modules/jest-runtime/package.json - neue Datei: clients/app/node_modules/jest-snapshot/LICENSE - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/.bin/semver - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/LICENSE - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/README.md - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/bin/semver.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/classes/comparator.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/classes/index.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/classes/range.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/classes/semver.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/clean.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/cmp.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/coerce.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/compare-build.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/compare-loose.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/compare.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/diff.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/eq.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/gt.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/gte.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/inc.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/lt.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/lte.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/major.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/minor.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/neq.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/parse.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/patch.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/prerelease.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/rcompare.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/rsort.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/satisfies.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/sort.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/functions/valid.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/index.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/internal/constants.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/internal/debug.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/internal/identifiers.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/internal/lrucache.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/internal/parse-options.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/internal/re.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/package.json - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/preload.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/range.bnf - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/ranges/gtr.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/ranges/intersects.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/ranges/ltr.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/ranges/max-satisfying.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/ranges/min-satisfying.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/ranges/min-version.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/ranges/outside.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/ranges/simplify.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/ranges/subset.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/ranges/to-comparators.js - neue Datei: clients/app/node_modules/jest-snapshot/node_modules/semver/ranges/valid.js - neue Datei: clients/app/node_modules/jest-snapshot/package.json - neue Datei: clients/app/node_modules/jest-util/LICENSE - neue Datei: clients/app/node_modules/jest-util/Readme.md - neue Datei: clients/app/node_modules/jest-util/package.json - neue Datei: clients/app/node_modules/jest-validate/LICENSE - neue Datei: clients/app/node_modules/jest-validate/README.md - neue Datei: clients/app/node_modules/jest-validate/node_modules/camelcase/index.d.ts - neue Datei: clients/app/node_modules/jest-validate/node_modules/camelcase/index.js - neue Datei: clients/app/node_modules/jest-validate/node_modules/camelcase/license - neue Datei: clients/app/node_modules/jest-validate/node_modules/camelcase/package.json - neue Datei: clients/app/node_modules/jest-validate/node_modules/camelcase/readme.md - neue Datei: clients/app/node_modules/jest-validate/package.json - neue Datei: clients/app/node_modules/jest-watcher/LICENSE - neue Datei: clients/app/node_modules/jest-watcher/package.json - neue Datei: clients/app/node_modules/jest-worker/LICENSE - neue Datei: clients/app/node_modules/jest-worker/README.md - neue Datei: clients/app/node_modules/jest-worker/node_modules/supports-color/browser.js - neue Datei: clients/app/node_modules/jest-worker/node_modules/supports-color/index.js - neue Datei: clients/app/node_modules/jest-worker/node_modules/supports-color/license - neue Datei: clients/app/node_modules/jest-worker/node_modules/supports-color/package.json - neue Datei: clients/app/node_modules/jest-worker/node_modules/supports-color/readme.md - neue Datei: clients/app/node_modules/jest-worker/package.json - neue Datei: clients/app/node_modules/jest/LICENSE - neue Datei: clients/app/node_modules/jest/README.md - neue Datei: clients/app/node_modules/jest/bin/jest.js - neue Datei: clients/app/node_modules/jest/package.json - neue Datei: clients/app/node_modules/js-tokens/CHANGELOG.md - neue Datei: clients/app/node_modules/js-tokens/LICENSE - neue Datei: clients/app/node_modules/js-tokens/README.md - neue Datei: clients/app/node_modules/js-tokens/index.js - neue Datei: clients/app/node_modules/js-tokens/package.json - neue Datei: clients/app/node_modules/js-yaml/CHANGELOG.md - neue Datei: clients/app/node_modules/js-yaml/LICENSE - neue Datei: clients/app/node_modules/js-yaml/README.md - neue Datei: clients/app/node_modules/js-yaml/bin/js-yaml.js - neue Datei: clients/app/node_modules/js-yaml/dist/js-yaml.js - neue Datei: clients/app/node_modules/js-yaml/dist/js-yaml.min.js - neue Datei: clients/app/node_modules/js-yaml/index.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/common.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/dumper.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/exception.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/loader.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/mark.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/schema.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/schema/core.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/schema/default_full.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/schema/default_safe.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/schema/failsafe.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/schema/json.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/type.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/type/binary.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/type/bool.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/type/float.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/type/int.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/type/js/function.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/type/js/regexp.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/type/js/undefined.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/type/map.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/type/merge.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/type/null.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/type/omap.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/type/pairs.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/type/seq.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/type/set.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/type/str.js - neue Datei: clients/app/node_modules/js-yaml/lib/js-yaml/type/timestamp.js - neue Datei: clients/app/node_modules/js-yaml/package.json - neue Datei: clients/app/node_modules/jsesc/LICENSE-MIT.txt - neue Datei: clients/app/node_modules/jsesc/README.md - neue Datei: clients/app/node_modules/jsesc/bin/jsesc - neue Datei: clients/app/node_modules/jsesc/jsesc.js - neue Datei: clients/app/node_modules/jsesc/man/jsesc.1 - neue Datei: clients/app/node_modules/jsesc/package.json - neue Datei: clients/app/node_modules/json-parse-even-better-errors/CHANGELOG.md - neue Datei: clients/app/node_modules/json-parse-even-better-errors/LICENSE.md - neue Datei: clients/app/node_modules/json-parse-even-better-errors/README.md - neue Datei: clients/app/node_modules/json-parse-even-better-errors/index.js - neue Datei: clients/app/node_modules/json-parse-even-better-errors/package.json - neue Datei: clients/app/node_modules/json5/LICENSE.md - neue Datei: clients/app/node_modules/json5/README.md - neue Datei: clients/app/node_modules/json5/dist/index.js - neue Datei: clients/app/node_modules/json5/dist/index.min.js - neue Datei: clients/app/node_modules/json5/dist/index.min.mjs - neue Datei: clients/app/node_modules/json5/dist/index.mjs - neue Datei: clients/app/node_modules/json5/lib/cli.js - neue Datei: clients/app/node_modules/json5/lib/index.d.ts - neue Datei: clients/app/node_modules/json5/lib/index.js - neue Datei: clients/app/node_modules/json5/lib/parse.d.ts - neue Datei: clients/app/node_modules/json5/lib/parse.js - neue Datei: clients/app/node_modules/json5/lib/register.js - neue Datei: clients/app/node_modules/json5/lib/require.js - neue Datei: clients/app/node_modules/json5/lib/stringify.d.ts - neue Datei: clients/app/node_modules/json5/lib/stringify.js - neue Datei: clients/app/node_modules/json5/lib/unicode.d.ts - neue Datei: clients/app/node_modules/json5/lib/unicode.js - neue Datei: clients/app/node_modules/json5/lib/util.d.ts - neue Datei: clients/app/node_modules/json5/lib/util.js - neue Datei: clients/app/node_modules/json5/package.json - neue Datei: clients/app/node_modules/kleur/index.js - neue Datei: clients/app/node_modules/kleur/kleur.d.ts - neue Datei: clients/app/node_modules/kleur/license - neue Datei: clients/app/node_modules/kleur/package.json - neue Datei: clients/app/node_modules/kleur/readme.md - neue Datei: clients/app/node_modules/leven/index.d.ts - neue Datei: clients/app/node_modules/leven/index.js - neue Datei: clients/app/node_modules/leven/license - neue Datei: clients/app/node_modules/leven/package.json - neue Datei: clients/app/node_modules/leven/readme.md - neue Datei: clients/app/node_modules/lines-and-columns/LICENSE - neue Datei: clients/app/node_modules/lines-and-columns/README.md - neue Datei: clients/app/node_modules/lines-and-columns/package.json - neue Datei: clients/app/node_modules/locate-path/index.d.ts - neue Datei: clients/app/node_modules/locate-path/index.js - neue Datei: clients/app/node_modules/locate-path/license - neue Datei: clients/app/node_modules/locate-path/package.json - neue Datei: clients/app/node_modules/locate-path/readme.md - neue Datei: clients/app/node_modules/lru-cache/LICENSE - neue Datei: clients/app/node_modules/lru-cache/README.md - neue Datei: clients/app/node_modules/lru-cache/index.js - neue Datei: clients/app/node_modules/lru-cache/package.json - neue Datei: clients/app/node_modules/make-dir/index.d.ts - neue Datei: clients/app/node_modules/make-dir/index.js - neue Datei: clients/app/node_modules/make-dir/license - neue Datei: clients/app/node_modules/make-dir/node_modules/.bin/semver - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/LICENSE - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/README.md - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/bin/semver.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/classes/comparator.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/classes/index.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/classes/range.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/classes/semver.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/clean.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/cmp.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/coerce.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/compare-build.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/compare-loose.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/compare.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/diff.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/eq.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/gt.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/gte.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/inc.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/lt.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/lte.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/major.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/minor.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/neq.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/parse.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/patch.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/prerelease.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/rcompare.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/rsort.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/satisfies.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/sort.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/functions/valid.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/index.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/internal/constants.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/internal/debug.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/internal/identifiers.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/internal/lrucache.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/internal/parse-options.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/internal/re.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/package.json - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/preload.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/range.bnf - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/ranges/gtr.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/ranges/intersects.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/ranges/ltr.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/ranges/max-satisfying.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/ranges/min-satisfying.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/ranges/min-version.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/ranges/outside.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/ranges/simplify.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/ranges/subset.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/ranges/to-comparators.js - neue Datei: clients/app/node_modules/make-dir/node_modules/semver/ranges/valid.js - neue Datei: clients/app/node_modules/make-dir/package.json - neue Datei: clients/app/node_modules/make-dir/readme.md - neue Datei: clients/app/node_modules/makeerror/.travis.yml - neue Datei: clients/app/node_modules/makeerror/lib/makeerror.js - neue Datei: clients/app/node_modules/makeerror/license - neue Datei: clients/app/node_modules/makeerror/package.json - neue Datei: clients/app/node_modules/makeerror/readme.md - neue Datei: clients/app/node_modules/merge-stream/LICENSE - neue Datei: clients/app/node_modules/merge-stream/README.md - neue Datei: clients/app/node_modules/merge-stream/index.js - neue Datei: clients/app/node_modules/merge-stream/package.json - neue Datei: clients/app/node_modules/micromatch/LICENSE - neue Datei: clients/app/node_modules/micromatch/README.md - neue Datei: clients/app/node_modules/micromatch/index.js - neue Datei: clients/app/node_modules/micromatch/package.json - neue Datei: clients/app/node_modules/mimic-fn/index.d.ts - neue Datei: clients/app/node_modules/mimic-fn/index.js - neue Datei: clients/app/node_modules/mimic-fn/license - neue Datei: clients/app/node_modules/mimic-fn/package.json - neue Datei: clients/app/node_modules/mimic-fn/readme.md - neue Datei: clients/app/node_modules/minimatch/LICENSE - neue Datei: clients/app/node_modules/minimatch/README.md - neue Datei: clients/app/node_modules/minimatch/minimatch.js - neue Datei: clients/app/node_modules/minimatch/package.json - neue Datei: clients/app/node_modules/mrmime/index.d.ts - neue Datei: clients/app/node_modules/mrmime/index.js - neue Datei: clients/app/node_modules/mrmime/index.mjs - neue Datei: clients/app/node_modules/mrmime/license - neue Datei: clients/app/node_modules/mrmime/package.json - neue Datei: clients/app/node_modules/mrmime/readme.md - neue Datei: clients/app/node_modules/ms/index.js - neue Datei: clients/app/node_modules/ms/license.md - neue Datei: clients/app/node_modules/ms/package.json - neue Datei: clients/app/node_modules/ms/readme.md - neue Datei: clients/app/node_modules/natural-compare/README.md - neue Datei: clients/app/node_modules/natural-compare/index.js - neue Datei: clients/app/node_modules/natural-compare/package.json - neue Datei: clients/app/node_modules/node-int64/.npmignore - neue Datei: clients/app/node_modules/node-int64/Int64.js - neue Datei: clients/app/node_modules/node-int64/LICENSE - neue Datei: clients/app/node_modules/node-int64/README.md - neue Datei: clients/app/node_modules/node-int64/package.json - neue Datei: clients/app/node_modules/node-int64/test.js - neue Datei: clients/app/node_modules/node-releases/LICENSE - neue Datei: clients/app/node_modules/node-releases/README.md - neue Datei: clients/app/node_modules/node-releases/data/processed/envs.json - neue Datei: clients/app/node_modules/node-releases/data/release-schedule/release-schedule.json - neue Datei: clients/app/node_modules/node-releases/package.json - neue Datei: clients/app/node_modules/normalize-path/LICENSE - neue Datei: clients/app/node_modules/normalize-path/README.md - neue Datei: clients/app/node_modules/normalize-path/index.js - neue Datei: clients/app/node_modules/normalize-path/package.json - neue Datei: clients/app/node_modules/npm-run-path/index.d.ts - neue Datei: clients/app/node_modules/npm-run-path/index.js - neue Datei: clients/app/node_modules/npm-run-path/license - neue Datei: clients/app/node_modules/npm-run-path/package.json - neue Datei: clients/app/node_modules/npm-run-path/readme.md - neue Datei: clients/app/node_modules/once/LICENSE - neue Datei: clients/app/node_modules/once/README.md - neue Datei: clients/app/node_modules/once/once.js - neue Datei: clients/app/node_modules/once/package.json - neue Datei: clients/app/node_modules/onetime/index.d.ts - neue Datei: clients/app/node_modules/onetime/index.js - neue Datei: clients/app/node_modules/onetime/license - neue Datei: clients/app/node_modules/onetime/package.json - neue Datei: clients/app/node_modules/onetime/readme.md - neue Datei: clients/app/node_modules/opener/LICENSE.txt - neue Datei: clients/app/node_modules/opener/README.md - neue Datei: clients/app/node_modules/opener/bin/opener-bin.js - neue Datei: clients/app/node_modules/opener/lib/opener.js - neue Datei: clients/app/node_modules/opener/package.json - neue Datei: clients/app/node_modules/p-limit/index.d.ts - neue Datei: clients/app/node_modules/p-limit/index.js - neue Datei: clients/app/node_modules/p-limit/license - neue Datei: clients/app/node_modules/p-limit/package.json - neue Datei: clients/app/node_modules/p-limit/readme.md - neue Datei: clients/app/node_modules/p-locate/index.d.ts - neue Datei: clients/app/node_modules/p-locate/index.js - neue Datei: clients/app/node_modules/p-locate/license - neue Datei: clients/app/node_modules/p-locate/node_modules/p-limit/index.d.ts - neue Datei: clients/app/node_modules/p-locate/node_modules/p-limit/index.js - neue Datei: clients/app/node_modules/p-locate/node_modules/p-limit/license - neue Datei: clients/app/node_modules/p-locate/node_modules/p-limit/package.json - neue Datei: clients/app/node_modules/p-locate/node_modules/p-limit/readme.md - neue Datei: clients/app/node_modules/p-locate/package.json - neue Datei: clients/app/node_modules/p-locate/readme.md - neue Datei: clients/app/node_modules/p-try/index.d.ts - neue Datei: clients/app/node_modules/p-try/index.js - neue Datei: clients/app/node_modules/p-try/license - neue Datei: clients/app/node_modules/p-try/package.json - neue Datei: clients/app/node_modules/p-try/readme.md - neue Datei: clients/app/node_modules/parse-json/index.js - neue Datei: clients/app/node_modules/parse-json/license - neue Datei: clients/app/node_modules/parse-json/package.json - neue Datei: clients/app/node_modules/parse-json/readme.md - neue Datei: clients/app/node_modules/path-exists/index.d.ts - neue Datei: clients/app/node_modules/path-exists/index.js - neue Datei: clients/app/node_modules/path-exists/license - neue Datei: clients/app/node_modules/path-exists/package.json - neue Datei: clients/app/node_modules/path-exists/readme.md - neue Datei: clients/app/node_modules/path-is-absolute/index.js - neue Datei: clients/app/node_modules/path-is-absolute/license - neue Datei: clients/app/node_modules/path-is-absolute/package.json - neue Datei: clients/app/node_modules/path-is-absolute/readme.md - neue Datei: clients/app/node_modules/path-key/index.d.ts - neue Datei: clients/app/node_modules/path-key/index.js - neue Datei: clients/app/node_modules/path-key/license - neue Datei: clients/app/node_modules/path-key/package.json - neue Datei: clients/app/node_modules/path-key/readme.md - neue Datei: clients/app/node_modules/path-parse/LICENSE - neue Datei: clients/app/node_modules/path-parse/README.md - neue Datei: clients/app/node_modules/path-parse/index.js - neue Datei: clients/app/node_modules/path-parse/package.json - neue Datei: clients/app/node_modules/picocolors/LICENSE - neue Datei: clients/app/node_modules/picocolors/README.md - neue Datei: clients/app/node_modules/picocolors/package.json - neue Datei: clients/app/node_modules/picocolors/picocolors.browser.js - neue Datei: clients/app/node_modules/picocolors/picocolors.d.ts - neue Datei: clients/app/node_modules/picocolors/picocolors.js - neue Datei: clients/app/node_modules/picocolors/types.d.ts - neue Datei: clients/app/node_modules/picomatch/CHANGELOG.md - neue Datei: clients/app/node_modules/picomatch/LICENSE - neue Datei: clients/app/node_modules/picomatch/README.md - neue Datei: clients/app/node_modules/picomatch/index.js - neue Datei: clients/app/node_modules/picomatch/lib/constants.js - neue Datei: clients/app/node_modules/picomatch/lib/parse.js - neue Datei: clients/app/node_modules/picomatch/lib/picomatch.js - neue Datei: clients/app/node_modules/picomatch/lib/scan.js - neue Datei: clients/app/node_modules/picomatch/lib/utils.js - neue Datei: clients/app/node_modules/picomatch/package.json - neue Datei: clients/app/node_modules/pirates/LICENSE - neue Datei: clients/app/node_modules/pirates/README.md - neue Datei: clients/app/node_modules/pirates/index.d.ts - neue Datei: clients/app/node_modules/pirates/lib/index.js - neue Datei: clients/app/node_modules/pirates/package.json - neue Datei: clients/app/node_modules/pkg-dir/index.d.ts - neue Datei: clients/app/node_modules/pkg-dir/index.js - neue Datei: clients/app/node_modules/pkg-dir/license - neue Datei: clients/app/node_modules/pkg-dir/package.json - neue Datei: clients/app/node_modules/pkg-dir/readme.md - neue Datei: clients/app/node_modules/pretty-format/LICENSE - neue Datei: clients/app/node_modules/pretty-format/README.md - neue Datei: clients/app/node_modules/pretty-format/node_modules/ansi-styles/index.d.ts - neue Datei: clients/app/node_modules/pretty-format/node_modules/ansi-styles/index.js - neue Datei: clients/app/node_modules/pretty-format/node_modules/ansi-styles/license - neue Datei: clients/app/node_modules/pretty-format/node_modules/ansi-styles/package.json - neue Datei: clients/app/node_modules/pretty-format/node_modules/ansi-styles/readme.md - neue Datei: clients/app/node_modules/pretty-format/package.json - neue Datei: clients/app/node_modules/prompts/dist/dateparts/datepart.js - neue Datei: clients/app/node_modules/prompts/dist/dateparts/day.js - neue Datei: clients/app/node_modules/prompts/dist/dateparts/hours.js - neue Datei: clients/app/node_modules/prompts/dist/dateparts/index.js - neue Datei: clients/app/node_modules/prompts/dist/dateparts/meridiem.js - neue Datei: clients/app/node_modules/prompts/dist/dateparts/milliseconds.js - neue Datei: clients/app/node_modules/prompts/dist/dateparts/minutes.js - neue Datei: clients/app/node_modules/prompts/dist/dateparts/month.js - neue Datei: clients/app/node_modules/prompts/dist/dateparts/seconds.js - neue Datei: clients/app/node_modules/prompts/dist/dateparts/year.js - neue Datei: clients/app/node_modules/prompts/dist/elements/autocomplete.js - neue Datei: clients/app/node_modules/prompts/dist/elements/autocompleteMultiselect.js - neue Datei: clients/app/node_modules/prompts/dist/elements/confirm.js - neue Datei: clients/app/node_modules/prompts/dist/elements/date.js - neue Datei: clients/app/node_modules/prompts/dist/elements/index.js - neue Datei: clients/app/node_modules/prompts/dist/elements/multiselect.js - neue Datei: clients/app/node_modules/prompts/dist/elements/number.js - neue Datei: clients/app/node_modules/prompts/dist/elements/prompt.js - neue Datei: clients/app/node_modules/prompts/dist/elements/select.js - neue Datei: clients/app/node_modules/prompts/dist/elements/text.js - neue Datei: clients/app/node_modules/prompts/dist/elements/toggle.js - neue Datei: clients/app/node_modules/prompts/dist/index.js - neue Datei: clients/app/node_modules/prompts/dist/prompts.js - neue Datei: clients/app/node_modules/prompts/dist/util/action.js - neue Datei: clients/app/node_modules/prompts/dist/util/clear.js - neue Datei: clients/app/node_modules/prompts/dist/util/entriesToDisplay.js - neue Datei: clients/app/node_modules/prompts/dist/util/figures.js - neue Datei: clients/app/node_modules/prompts/dist/util/index.js - neue Datei: clients/app/node_modules/prompts/dist/util/lines.js - neue Datei: clients/app/node_modules/prompts/dist/util/strip.js - neue Datei: clients/app/node_modules/prompts/dist/util/style.js - neue Datei: clients/app/node_modules/prompts/dist/util/wrap.js - neue Datei: clients/app/node_modules/prompts/index.js - neue Datei: clients/app/node_modules/prompts/lib/dateparts/datepart.js - neue Datei: clients/app/node_modules/prompts/lib/dateparts/day.js - neue Datei: clients/app/node_modules/prompts/lib/dateparts/hours.js - neue Datei: clients/app/node_modules/prompts/lib/dateparts/index.js - neue Datei: clients/app/node_modules/prompts/lib/dateparts/meridiem.js - neue Datei: clients/app/node_modules/prompts/lib/dateparts/milliseconds.js - neue Datei: clients/app/node_modules/prompts/lib/dateparts/minutes.js - neue Datei: clients/app/node_modules/prompts/lib/dateparts/month.js - neue Datei: clients/app/node_modules/prompts/lib/dateparts/seconds.js - neue Datei: clients/app/node_modules/prompts/lib/dateparts/year.js - neue Datei: clients/app/node_modules/prompts/lib/elements/autocomplete.js - neue Datei: clients/app/node_modules/prompts/lib/elements/autocompleteMultiselect.js - neue Datei: clients/app/node_modules/prompts/lib/elements/confirm.js - neue Datei: clients/app/node_modules/prompts/lib/elements/date.js - neue Datei: clients/app/node_modules/prompts/lib/elements/index.js - neue Datei: clients/app/node_modules/prompts/lib/elements/multiselect.js - neue Datei: clients/app/node_modules/prompts/lib/elements/number.js - neue Datei: clients/app/node_modules/prompts/lib/elements/prompt.js - neue Datei: clients/app/node_modules/prompts/lib/elements/select.js - neue Datei: clients/app/node_modules/prompts/lib/elements/text.js - neue Datei: clients/app/node_modules/prompts/lib/elements/toggle.js - neue Datei: clients/app/node_modules/prompts/lib/index.js - neue Datei: clients/app/node_modules/prompts/lib/prompts.js - neue Datei: clients/app/node_modules/prompts/lib/util/action.js - neue Datei: clients/app/node_modules/prompts/lib/util/clear.js - neue Datei: clients/app/node_modules/prompts/lib/util/entriesToDisplay.js - neue Datei: clients/app/node_modules/prompts/lib/util/figures.js - neue Datei: clients/app/node_modules/prompts/lib/util/index.js - neue Datei: clients/app/node_modules/prompts/lib/util/lines.js - neue Datei: clients/app/node_modules/prompts/lib/util/strip.js - neue Datei: clients/app/node_modules/prompts/lib/util/style.js - neue Datei: clients/app/node_modules/prompts/lib/util/wrap.js - neue Datei: clients/app/node_modules/prompts/license - neue Datei: clients/app/node_modules/prompts/package.json - neue Datei: clients/app/node_modules/prompts/readme.md - neue Datei: clients/app/node_modules/pure-rand/CHANGELOG.md - neue Datei: clients/app/node_modules/pure-rand/LICENSE - neue Datei: clients/app/node_modules/pure-rand/README.md - neue Datei: clients/app/node_modules/pure-rand/lib/distribution/Distribution.js - neue Datei: clients/app/node_modules/pure-rand/lib/distribution/UniformArrayIntDistribution.js - neue Datei: clients/app/node_modules/pure-rand/lib/distribution/UniformBigIntDistribution.js - neue Datei: clients/app/node_modules/pure-rand/lib/distribution/UniformIntDistribution.js - neue Datei: clients/app/node_modules/pure-rand/lib/distribution/UnsafeUniformArrayIntDistribution.js - neue Datei: clients/app/node_modules/pure-rand/lib/distribution/UnsafeUniformBigIntDistribution.js - neue Datei: clients/app/node_modules/pure-rand/lib/distribution/UnsafeUniformIntDistribution.js - neue Datei: clients/app/node_modules/pure-rand/lib/distribution/internals/ArrayInt.js - neue Datei: clients/app/node_modules/pure-rand/lib/distribution/internals/UnsafeUniformArrayIntDistributionInternal.js - neue Datei: clients/app/node_modules/pure-rand/lib/distribution/internals/UnsafeUniformIntDistributionInternal.js - neue Datei: clients/app/node_modules/pure-rand/lib/esm/distribution/Distribution.js - neue Datei: clients/app/node_modules/pure-rand/lib/esm/distribution/UniformArrayIntDistribution.js - neue Datei: clients/app/node_modules/pure-rand/lib/esm/distribution/UniformBigIntDistribution.js - neue Datei: clients/app/node_modules/pure-rand/lib/esm/distribution/UniformIntDistribution.js - neue Datei: clients/app/node_modules/pure-rand/lib/esm/distribution/UnsafeUniformArrayIntDistribution.js - neue Datei: clients/app/node_modules/pure-rand/lib/esm/distribution/UnsafeUniformBigIntDistribution.js - neue Datei: clients/app/node_modules/pure-rand/lib/esm/distribution/UnsafeUniformIntDistribution.js - neue Datei: clients/app/node_modules/pure-rand/lib/esm/distribution/internals/ArrayInt.js - neue Datei: clients/app/node_modules/pure-rand/lib/esm/distribution/internals/UnsafeUniformArrayIntDistributionInternal.js - neue Datei: clients/app/node_modules/pure-rand/lib/esm/distribution/internals/UnsafeUniformIntDistributionInternal.js - neue Datei: clients/app/node_modules/pure-rand/lib/esm/generator/LinearCongruential.js - neue Datei: clients/app/node_modules/pure-rand/lib/esm/generator/MersenneTwister.js - neue Datei: clients/app/node_modules/pure-rand/lib/esm/generator/RandomGenerator.js - neue Datei: clients/app/node_modules/pure-rand/lib/esm/generator/XorShift.js - neue Datei: clients/app/node_modules/pure-rand/lib/esm/generator/XoroShiro.js - neue Datei: clients/app/node_modules/pure-rand/lib/esm/package.json - neue Datei: clients/app/node_modules/pure-rand/lib/esm/pure-rand-default.js - neue Datei: clients/app/node_modules/pure-rand/lib/esm/pure-rand.js - neue Datei: clients/app/node_modules/pure-rand/lib/esm/types/distribution/Distribution.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/esm/types/distribution/UniformArrayIntDistribution.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/esm/types/distribution/UniformBigIntDistribution.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/esm/types/distribution/UniformIntDistribution.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/esm/types/distribution/UnsafeUniformArrayIntDistribution.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/esm/types/distribution/UnsafeUniformBigIntDistribution.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/esm/types/distribution/UnsafeUniformIntDistribution.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/esm/types/distribution/internals/ArrayInt.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/esm/types/distribution/internals/UnsafeUniformArrayIntDistributionInternal.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/esm/types/distribution/internals/UnsafeUniformIntDistributionInternal.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/esm/types/generator/LinearCongruential.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/esm/types/generator/MersenneTwister.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/esm/types/generator/RandomGenerator.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/esm/types/generator/XorShift.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/esm/types/generator/XoroShiro.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/esm/types/pure-rand-default.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/esm/types/pure-rand.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/generator/LinearCongruential.js - neue Datei: clients/app/node_modules/pure-rand/lib/generator/MersenneTwister.js - neue Datei: clients/app/node_modules/pure-rand/lib/generator/RandomGenerator.js - neue Datei: clients/app/node_modules/pure-rand/lib/generator/XorShift.js - neue Datei: clients/app/node_modules/pure-rand/lib/generator/XoroShiro.js - neue Datei: clients/app/node_modules/pure-rand/lib/pure-rand-default.js - neue Datei: clients/app/node_modules/pure-rand/lib/pure-rand.js - neue Datei: clients/app/node_modules/pure-rand/lib/types/distribution/Distribution.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/types/distribution/UniformArrayIntDistribution.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/types/distribution/UniformBigIntDistribution.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/types/distribution/UniformIntDistribution.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/types/distribution/UnsafeUniformArrayIntDistribution.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/types/distribution/UnsafeUniformBigIntDistribution.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/types/distribution/UnsafeUniformIntDistribution.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/types/distribution/internals/ArrayInt.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/types/distribution/internals/UnsafeUniformArrayIntDistributionInternal.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/types/distribution/internals/UnsafeUniformIntDistributionInternal.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/types/generator/LinearCongruential.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/types/generator/MersenneTwister.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/types/generator/RandomGenerator.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/types/generator/XorShift.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/types/generator/XoroShiro.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/types/pure-rand-default.d.ts - neue Datei: clients/app/node_modules/pure-rand/lib/types/pure-rand.d.ts - neue Datei: clients/app/node_modules/pure-rand/package.json - neue Datei: clients/app/node_modules/react-is/LICENSE - neue Datei: clients/app/node_modules/react-is/README.md - neue Datei: clients/app/node_modules/react-is/cjs/react-is.development.js - neue Datei: clients/app/node_modules/react-is/cjs/react-is.production.min.js - neue Datei: clients/app/node_modules/react-is/index.js - neue Datei: clients/app/node_modules/react-is/package.json - neue Datei: clients/app/node_modules/react-is/umd/react-is.development.js - neue Datei: clients/app/node_modules/react-is/umd/react-is.production.min.js - neue Datei: clients/app/node_modules/require-directory/.jshintrc - neue Datei: clients/app/node_modules/require-directory/.npmignore - neue Datei: clients/app/node_modules/require-directory/.travis.yml - neue Datei: clients/app/node_modules/require-directory/LICENSE - neue Datei: clients/app/node_modules/require-directory/README.markdown - neue Datei: clients/app/node_modules/require-directory/index.js - neue Datei: clients/app/node_modules/require-directory/package.json - neue Datei: clients/app/node_modules/resolve-cwd/index.d.ts - neue Datei: clients/app/node_modules/resolve-cwd/index.js - neue Datei: clients/app/node_modules/resolve-cwd/license - neue Datei: clients/app/node_modules/resolve-cwd/package.json - neue Datei: clients/app/node_modules/resolve-cwd/readme.md - neue Datei: clients/app/node_modules/resolve-from/index.d.ts - neue Datei: clients/app/node_modules/resolve-from/index.js - neue Datei: clients/app/node_modules/resolve-from/license - neue Datei: clients/app/node_modules/resolve-from/package.json - neue Datei: clients/app/node_modules/resolve-from/readme.md - neue Datei: clients/app/node_modules/resolve.exports/dist/index.js - neue Datei: clients/app/node_modules/resolve.exports/dist/index.mjs - neue Datei: clients/app/node_modules/resolve.exports/index.d.ts - neue Datei: clients/app/node_modules/resolve.exports/license - neue Datei: clients/app/node_modules/resolve.exports/package.json - neue Datei: clients/app/node_modules/resolve.exports/readme.md - neue Datei: clients/app/node_modules/resolve/.editorconfig - neue Datei: clients/app/node_modules/resolve/.eslintrc - neue Datei: clients/app/node_modules/resolve/.github/FUNDING.yml - neue Datei: clients/app/node_modules/resolve/LICENSE - neue Datei: clients/app/node_modules/resolve/SECURITY.md - neue Datei: clients/app/node_modules/resolve/async.js - neue Datei: clients/app/node_modules/resolve/bin/resolve - neue Datei: clients/app/node_modules/resolve/example/async.js - neue Datei: clients/app/node_modules/resolve/example/sync.js - neue Datei: clients/app/node_modules/resolve/index.js - neue Datei: clients/app/node_modules/resolve/lib/async.js - neue Datei: clients/app/node_modules/resolve/lib/caller.js - neue Datei: clients/app/node_modules/resolve/lib/core.js - neue Datei: clients/app/node_modules/resolve/lib/core.json - neue Datei: clients/app/node_modules/resolve/lib/homedir.js - neue Datei: clients/app/node_modules/resolve/lib/is-core.js - neue Datei: clients/app/node_modules/resolve/lib/node-modules-paths.js - neue Datei: clients/app/node_modules/resolve/lib/normalize-options.js - neue Datei: clients/app/node_modules/resolve/lib/sync.js - neue Datei: clients/app/node_modules/resolve/package.json - neue Datei: clients/app/node_modules/resolve/readme.markdown - neue Datei: clients/app/node_modules/resolve/sync.js - neue Datei: clients/app/node_modules/resolve/test/core.js - neue Datei: clients/app/node_modules/resolve/test/dotdot.js - neue Datei: clients/app/node_modules/resolve/test/dotdot/abc/index.js - neue Datei: clients/app/node_modules/resolve/test/dotdot/index.js - neue Datei: clients/app/node_modules/resolve/test/faulty_basedir.js - neue Datei: clients/app/node_modules/resolve/test/filter.js - neue Datei: clients/app/node_modules/resolve/test/filter_sync.js - neue Datei: clients/app/node_modules/resolve/test/home_paths.js - neue Datei: clients/app/node_modules/resolve/test/home_paths_sync.js - neue Datei: clients/app/node_modules/resolve/test/mock.js - neue Datei: clients/app/node_modules/resolve/test/mock_sync.js - neue Datei: clients/app/node_modules/resolve/test/module_dir.js - neue Datei: clients/app/node_modules/resolve/test/module_dir/xmodules/aaa/index.js - neue Datei: clients/app/node_modules/resolve/test/module_dir/ymodules/aaa/index.js - neue Datei: clients/app/node_modules/resolve/test/module_dir/zmodules/bbb/main.js - neue Datei: clients/app/node_modules/resolve/test/module_dir/zmodules/bbb/package.json - neue Datei: clients/app/node_modules/resolve/test/node-modules-paths.js - neue Datei: clients/app/node_modules/resolve/test/node_path.js - neue Datei: clients/app/node_modules/resolve/test/node_path/x/aaa/index.js - neue Datei: clients/app/node_modules/resolve/test/node_path/x/ccc/index.js - neue Datei: clients/app/node_modules/resolve/test/node_path/y/bbb/index.js - neue Datei: clients/app/node_modules/resolve/test/node_path/y/ccc/index.js - neue Datei: clients/app/node_modules/resolve/test/nonstring.js - neue Datei: clients/app/node_modules/resolve/test/pathfilter.js - neue Datei: clients/app/node_modules/resolve/test/pathfilter/deep_ref/main.js - neue Datei: clients/app/node_modules/resolve/test/precedence.js - neue Datei: clients/app/node_modules/resolve/test/precedence/aaa.js - neue Datei: clients/app/node_modules/resolve/test/precedence/aaa/index.js - neue Datei: clients/app/node_modules/resolve/test/precedence/aaa/main.js - neue Datei: clients/app/node_modules/resolve/test/precedence/bbb.js - neue Datei: clients/app/node_modules/resolve/test/precedence/bbb/main.js - neue Datei: clients/app/node_modules/resolve/test/resolver.js - neue Datei: clients/app/node_modules/resolve/test/resolver/baz/doom.js - neue Datei: clients/app/node_modules/resolve/test/resolver/baz/package.json - neue Datei: clients/app/node_modules/resolve/test/resolver/baz/quux.js - neue Datei: clients/app/node_modules/resolve/test/resolver/browser_field/a.js - neue Datei: clients/app/node_modules/resolve/test/resolver/browser_field/b.js - neue Datei: clients/app/node_modules/resolve/test/resolver/browser_field/package.json - neue Datei: clients/app/node_modules/resolve/test/resolver/cup.coffee - neue Datei: clients/app/node_modules/resolve/test/resolver/dot_main/index.js - neue Datei: clients/app/node_modules/resolve/test/resolver/dot_main/package.json - neue Datei: clients/app/node_modules/resolve/test/resolver/dot_slash_main/index.js - neue Datei: clients/app/node_modules/resolve/test/resolver/dot_slash_main/package.json - neue Datei: clients/app/node_modules/resolve/test/resolver/false_main/index.js - neue Datei: clients/app/node_modules/resolve/test/resolver/false_main/package.json - neue Datei: clients/app/node_modules/resolve/test/resolver/foo.js - neue Datei: clients/app/node_modules/resolve/test/resolver/incorrect_main/index.js - neue Datei: clients/app/node_modules/resolve/test/resolver/incorrect_main/package.json - neue Datei: clients/app/node_modules/resolve/test/resolver/invalid_main/package.json - neue Datei: clients/app/node_modules/resolve/test/resolver/mug.coffee - neue Datei: clients/app/node_modules/resolve/test/resolver/mug.js - neue Datei: clients/app/node_modules/resolve/test/resolver/multirepo/lerna.json - neue Datei: clients/app/node_modules/resolve/test/resolver/multirepo/package.json - neue Datei: clients/app/node_modules/resolve/test/resolver/multirepo/packages/package-a/index.js - neue Datei: clients/app/node_modules/resolve/test/resolver/multirepo/packages/package-a/package.json - neue Datei: clients/app/node_modules/resolve/test/resolver/multirepo/packages/package-b/index.js - neue Datei: clients/app/node_modules/resolve/test/resolver/multirepo/packages/package-b/package.json - neue Datei: clients/app/node_modules/resolve/test/resolver/nested_symlinks/mylib/async.js - neue Datei: clients/app/node_modules/resolve/test/resolver/nested_symlinks/mylib/package.json - neue Datei: clients/app/node_modules/resolve/test/resolver/nested_symlinks/mylib/sync.js - neue Datei: clients/app/node_modules/resolve/test/resolver/other_path/lib/other-lib.js - neue Datei: clients/app/node_modules/resolve/test/resolver/other_path/root.js - neue Datei: clients/app/node_modules/resolve/test/resolver/quux/foo/index.js - neue Datei: clients/app/node_modules/resolve/test/resolver/same_names/foo.js - neue Datei: clients/app/node_modules/resolve/test/resolver/same_names/foo/index.js - neue Datei: clients/app/node_modules/resolve/test/resolver/symlinked/_/node_modules/foo.js - neue Datei: clients/app/node_modules/resolve/test/resolver/symlinked/_/symlink_target/.gitkeep - neue Datei: clients/app/node_modules/resolve/test/resolver/symlinked/package/bar.js - neue Datei: clients/app/node_modules/resolve/test/resolver/symlinked/package/package.json - neue Datei: clients/app/node_modules/resolve/test/resolver/without_basedir/main.js - neue Datei: clients/app/node_modules/resolve/test/resolver_sync.js - neue Datei: clients/app/node_modules/resolve/test/shadowed_core.js - neue Datei: clients/app/node_modules/resolve/test/shadowed_core/node_modules/util/index.js - neue Datei: clients/app/node_modules/resolve/test/subdirs.js - neue Datei: clients/app/node_modules/resolve/test/symlinks.js - neue Datei: clients/app/node_modules/semver/LICENSE - neue Datei: clients/app/node_modules/semver/README.md - neue Datei: clients/app/node_modules/semver/bin/semver.js - neue Datei: clients/app/node_modules/semver/package.json - neue Datei: clients/app/node_modules/semver/range.bnf - neue Datei: clients/app/node_modules/semver/semver.js - neue Datei: clients/app/node_modules/shebang-command/index.js - neue Datei: clients/app/node_modules/shebang-command/license - neue Datei: clients/app/node_modules/shebang-command/package.json - neue Datei: clients/app/node_modules/shebang-command/readme.md - neue Datei: clients/app/node_modules/shebang-regex/index.d.ts - neue Datei: clients/app/node_modules/shebang-regex/index.js - neue Datei: clients/app/node_modules/shebang-regex/license - neue Datei: clients/app/node_modules/shebang-regex/package.json - neue Datei: clients/app/node_modules/shebang-regex/readme.md - neue Datei: clients/app/node_modules/signal-exit/LICENSE.txt - neue Datei: clients/app/node_modules/signal-exit/README.md - neue Datei: clients/app/node_modules/signal-exit/index.js - neue Datei: clients/app/node_modules/signal-exit/package.json - neue Datei: clients/app/node_modules/signal-exit/signals.js - neue Datei: clients/app/node_modules/sirv/build.js - neue Datei: clients/app/node_modules/sirv/build.mjs - neue Datei: clients/app/node_modules/sirv/package.json - neue Datei: clients/app/node_modules/sirv/readme.md - neue Datei: clients/app/node_modules/sirv/sirv.d.ts - neue Datei: clients/app/node_modules/sisteransi/license - neue Datei: clients/app/node_modules/sisteransi/package.json - neue Datei: clients/app/node_modules/sisteransi/readme.md - neue Datei: clients/app/node_modules/sisteransi/src/index.js - neue Datei: clients/app/node_modules/sisteransi/src/sisteransi.d.ts - neue Datei: clients/app/node_modules/slash/index.d.ts - neue Datei: clients/app/node_modules/slash/index.js - neue Datei: clients/app/node_modules/slash/license - neue Datei: clients/app/node_modules/slash/package.json - neue Datei: clients/app/node_modules/slash/readme.md - neue Datei: clients/app/node_modules/source-map-support/LICENSE.md - neue Datei: clients/app/node_modules/source-map-support/README.md - neue Datei: clients/app/node_modules/source-map-support/browser-source-map-support.js - neue Datei: clients/app/node_modules/source-map-support/package.json - neue Datei: clients/app/node_modules/source-map-support/register.js - neue Datei: clients/app/node_modules/source-map-support/source-map-support.js - neue Datei: clients/app/node_modules/source-map/CHANGELOG.md - neue Datei: clients/app/node_modules/source-map/LICENSE - neue Datei: clients/app/node_modules/source-map/README.md - neue Datei: clients/app/node_modules/source-map/dist/source-map.debug.js - neue Datei: clients/app/node_modules/source-map/dist/source-map.js - neue Datei: clients/app/node_modules/source-map/dist/source-map.min.js - neue Datei: clients/app/node_modules/source-map/dist/source-map.min.js.map - neue Datei: clients/app/node_modules/source-map/lib/array-set.js - neue Datei: clients/app/node_modules/source-map/lib/base64-vlq.js - neue Datei: clients/app/node_modules/source-map/lib/base64.js - neue Datei: clients/app/node_modules/source-map/lib/binary-search.js - neue Datei: clients/app/node_modules/source-map/lib/mapping-list.js - neue Datei: clients/app/node_modules/source-map/lib/quick-sort.js - neue Datei: clients/app/node_modules/source-map/lib/source-map-consumer.js - neue Datei: clients/app/node_modules/source-map/lib/source-map-generator.js - neue Datei: clients/app/node_modules/source-map/lib/source-node.js - neue Datei: clients/app/node_modules/source-map/lib/util.js - neue Datei: clients/app/node_modules/source-map/package.json - neue Datei: clients/app/node_modules/source-map/source-map.d.ts - neue Datei: clients/app/node_modules/source-map/source-map.js - neue Datei: clients/app/node_modules/sprintf-js/.npmignore - neue Datei: clients/app/node_modules/sprintf-js/LICENSE - neue Datei: clients/app/node_modules/sprintf-js/README.md - neue Datei: clients/app/node_modules/sprintf-js/bower.json - neue Datei: clients/app/node_modules/sprintf-js/demo/angular.html - neue Datei: clients/app/node_modules/sprintf-js/dist/angular-sprintf.min.js - neue Datei: clients/app/node_modules/sprintf-js/dist/angular-sprintf.min.js.map - neue Datei: clients/app/node_modules/sprintf-js/dist/angular-sprintf.min.map - neue Datei: clients/app/node_modules/sprintf-js/dist/sprintf.min.js - neue Datei: clients/app/node_modules/sprintf-js/dist/sprintf.min.js.map - neue Datei: clients/app/node_modules/sprintf-js/dist/sprintf.min.map - neue Datei: clients/app/node_modules/sprintf-js/gruntfile.js - neue Datei: clients/app/node_modules/sprintf-js/package.json - neue Datei: clients/app/node_modules/sprintf-js/src/angular-sprintf.js - neue Datei: clients/app/node_modules/sprintf-js/src/sprintf.js - neue Datei: clients/app/node_modules/sprintf-js/test/test.js - neue Datei: clients/app/node_modules/stack-utils/LICENSE.md - neue Datei: clients/app/node_modules/stack-utils/index.js - neue Datei: clients/app/node_modules/stack-utils/package.json - neue Datei: clients/app/node_modules/stack-utils/readme.md - neue Datei: clients/app/node_modules/string-length/index.d.ts - neue Datei: clients/app/node_modules/string-length/index.js - neue Datei: clients/app/node_modules/string-length/license - neue Datei: clients/app/node_modules/string-length/package.json - neue Datei: clients/app/node_modules/string-length/readme.md - neue Datei: clients/app/node_modules/string-width/index.d.ts - neue Datei: clients/app/node_modules/string-width/index.js - neue Datei: clients/app/node_modules/string-width/license - neue Datei: clients/app/node_modules/string-width/package.json - neue Datei: clients/app/node_modules/string-width/readme.md - neue Datei: clients/app/node_modules/strip-ansi/index.d.ts - neue Datei: clients/app/node_modules/strip-ansi/index.js - neue Datei: clients/app/node_modules/strip-ansi/license - neue Datei: clients/app/node_modules/strip-ansi/package.json - neue Datei: clients/app/node_modules/strip-ansi/readme.md - neue Datei: clients/app/node_modules/strip-bom/index.d.ts - neue Datei: clients/app/node_modules/strip-bom/index.js - neue Datei: clients/app/node_modules/strip-bom/license - neue Datei: clients/app/node_modules/strip-bom/package.json - neue Datei: clients/app/node_modules/strip-bom/readme.md - neue Datei: clients/app/node_modules/strip-final-newline/index.js - neue Datei: clients/app/node_modules/strip-final-newline/license - neue Datei: clients/app/node_modules/strip-final-newline/package.json - neue Datei: clients/app/node_modules/strip-final-newline/readme.md - neue Datei: clients/app/node_modules/strip-json-comments/index.d.ts - neue Datei: clients/app/node_modules/strip-json-comments/index.js - neue Datei: clients/app/node_modules/strip-json-comments/license - neue Datei: clients/app/node_modules/strip-json-comments/package.json - neue Datei: clients/app/node_modules/strip-json-comments/readme.md - neue Datei: clients/app/node_modules/supports-color/browser.js - neue Datei: clients/app/node_modules/supports-color/index.js - neue Datei: clients/app/node_modules/supports-color/license - neue Datei: clients/app/node_modules/supports-color/package.json - neue Datei: clients/app/node_modules/supports-color/readme.md - neue Datei: clients/app/node_modules/supports-preserve-symlinks-flag/.eslintrc - neue Datei: clients/app/node_modules/supports-preserve-symlinks-flag/.github/FUNDING.yml - neue Datei: clients/app/node_modules/supports-preserve-symlinks-flag/.nycrc - neue Datei: clients/app/node_modules/supports-preserve-symlinks-flag/CHANGELOG.md - neue Datei: clients/app/node_modules/supports-preserve-symlinks-flag/LICENSE - neue Datei: clients/app/node_modules/supports-preserve-symlinks-flag/README.md - neue Datei: clients/app/node_modules/supports-preserve-symlinks-flag/browser.js - neue Datei: clients/app/node_modules/supports-preserve-symlinks-flag/index.js - neue Datei: clients/app/node_modules/supports-preserve-symlinks-flag/package.json - neue Datei: clients/app/node_modules/supports-preserve-symlinks-flag/test/index.js - neue Datei: clients/app/node_modules/test-exclude/CHANGELOG.md - neue Datei: clients/app/node_modules/test-exclude/LICENSE.txt - neue Datei: clients/app/node_modules/test-exclude/README.md - neue Datei: clients/app/node_modules/test-exclude/index.js - neue Datei: clients/app/node_modules/test-exclude/is-outside-dir-posix.js - neue Datei: clients/app/node_modules/test-exclude/is-outside-dir-win32.js - neue Datei: clients/app/node_modules/test-exclude/is-outside-dir.js - neue Datei: clients/app/node_modules/test-exclude/package.json - neue Datei: clients/app/node_modules/tmpl/lib/tmpl.js - neue Datei: clients/app/node_modules/tmpl/license - neue Datei: clients/app/node_modules/tmpl/package.json - neue Datei: clients/app/node_modules/tmpl/readme.md - neue Datei: clients/app/node_modules/to-regex-range/LICENSE - neue Datei: clients/app/node_modules/to-regex-range/README.md - neue Datei: clients/app/node_modules/to-regex-range/index.js - neue Datei: clients/app/node_modules/to-regex-range/package.json - neue Datei: clients/app/node_modules/totalist/dist/index.js - neue Datei: clients/app/node_modules/totalist/dist/index.mjs - neue Datei: clients/app/node_modules/totalist/index.d.ts - neue Datei: clients/app/node_modules/totalist/license - neue Datei: clients/app/node_modules/totalist/package.json - neue Datei: clients/app/node_modules/totalist/readme.md - neue Datei: clients/app/node_modules/totalist/sync/index.d.ts - neue Datei: clients/app/node_modules/totalist/sync/index.js - neue Datei: clients/app/node_modules/totalist/sync/index.mjs - neue Datei: clients/app/node_modules/type-detect/LICENSE - neue Datei: clients/app/node_modules/type-detect/README.md - neue Datei: clients/app/node_modules/type-detect/index.js - neue Datei: clients/app/node_modules/type-detect/package.json - neue Datei: clients/app/node_modules/type-detect/type-detect.js - neue Datei: clients/app/node_modules/type-fest/base.d.ts - neue Datei: clients/app/node_modules/type-fest/index.d.ts - neue Datei: clients/app/node_modules/type-fest/license - neue Datei: clients/app/node_modules/type-fest/package.json - neue Datei: clients/app/node_modules/type-fest/readme.md - neue Datei: clients/app/node_modules/type-fest/source/async-return-type.d.ts - neue Datei: clients/app/node_modules/type-fest/source/asyncify.d.ts - neue Datei: clients/app/node_modules/type-fest/source/basic.d.ts - neue Datei: clients/app/node_modules/type-fest/source/conditional-except.d.ts - neue Datei: clients/app/node_modules/type-fest/source/conditional-keys.d.ts - neue Datei: clients/app/node_modules/type-fest/source/conditional-pick.d.ts - neue Datei: clients/app/node_modules/type-fest/source/entries.d.ts - neue Datei: clients/app/node_modules/type-fest/source/entry.d.ts - neue Datei: clients/app/node_modules/type-fest/source/except.d.ts - neue Datei: clients/app/node_modules/type-fest/source/fixed-length-array.d.ts - neue Datei: clients/app/node_modules/type-fest/source/iterable-element.d.ts - neue Datei: clients/app/node_modules/type-fest/source/literal-union.d.ts - neue Datei: clients/app/node_modules/type-fest/source/merge-exclusive.d.ts - neue Datei: clients/app/node_modules/type-fest/source/merge.d.ts - neue Datei: clients/app/node_modules/type-fest/source/mutable.d.ts - neue Datei: clients/app/node_modules/type-fest/source/opaque.d.ts - neue Datei: clients/app/node_modules/type-fest/source/package-json.d.ts - neue Datei: clients/app/node_modules/type-fest/source/partial-deep.d.ts - neue Datei: clients/app/node_modules/type-fest/source/promisable.d.ts - neue Datei: clients/app/node_modules/type-fest/source/promise-value.d.ts - neue Datei: clients/app/node_modules/type-fest/source/readonly-deep.d.ts - neue Datei: clients/app/node_modules/type-fest/source/require-at-least-one.d.ts - neue Datei: clients/app/node_modules/type-fest/source/require-exactly-one.d.ts - neue Datei: clients/app/node_modules/type-fest/source/set-optional.d.ts - neue Datei: clients/app/node_modules/type-fest/source/set-required.d.ts - neue Datei: clients/app/node_modules/type-fest/source/set-return-type.d.ts - neue Datei: clients/app/node_modules/type-fest/source/simplify.d.ts - neue Datei: clients/app/node_modules/type-fest/source/stringified.d.ts - neue Datei: clients/app/node_modules/type-fest/source/tsconfig-json.d.ts - neue Datei: clients/app/node_modules/type-fest/source/typed-array.d.ts - neue Datei: clients/app/node_modules/type-fest/source/union-to-intersection.d.ts - neue Datei: clients/app/node_modules/type-fest/source/utilities.d.ts - neue Datei: clients/app/node_modules/type-fest/source/value-of.d.ts - neue Datei: clients/app/node_modules/type-fest/ts41/camel-case.d.ts - neue Datei: clients/app/node_modules/type-fest/ts41/delimiter-case.d.ts - neue Datei: clients/app/node_modules/type-fest/ts41/get.d.ts - neue Datei: clients/app/node_modules/type-fest/ts41/index.d.ts - neue Datei: clients/app/node_modules/type-fest/ts41/kebab-case.d.ts - neue Datei: clients/app/node_modules/type-fest/ts41/pascal-case.d.ts - neue Datei: clients/app/node_modules/type-fest/ts41/snake-case.d.ts - neue Datei: clients/app/node_modules/type-fest/ts41/utilities.d.ts - neue Datei: clients/app/node_modules/undici-types/LICENSE - neue Datei: clients/app/node_modules/undici-types/README.md - neue Datei: clients/app/node_modules/undici-types/agent.d.ts - neue Datei: clients/app/node_modules/undici-types/api.d.ts - neue Datei: clients/app/node_modules/undici-types/balanced-pool.d.ts - neue Datei: clients/app/node_modules/undici-types/cache-interceptor.d.ts - neue Datei: clients/app/node_modules/undici-types/cache.d.ts - neue Datei: clients/app/node_modules/undici-types/client-stats.d.ts - neue Datei: clients/app/node_modules/undici-types/client.d.ts - neue Datei: clients/app/node_modules/undici-types/connector.d.ts - neue Datei: clients/app/node_modules/undici-types/content-type.d.ts - neue Datei: clients/app/node_modules/undici-types/cookies.d.ts - neue Datei: clients/app/node_modules/undici-types/diagnostics-channel.d.ts - neue Datei: clients/app/node_modules/undici-types/dispatcher.d.ts - neue Datei: clients/app/node_modules/undici-types/env-http-proxy-agent.d.ts - neue Datei: clients/app/node_modules/undici-types/errors.d.ts - neue Datei: clients/app/node_modules/undici-types/eventsource.d.ts - neue Datei: clients/app/node_modules/undici-types/fetch.d.ts - neue Datei: clients/app/node_modules/undici-types/formdata.d.ts - neue Datei: clients/app/node_modules/undici-types/global-dispatcher.d.ts - neue Datei: clients/app/node_modules/undici-types/global-origin.d.ts - neue Datei: clients/app/node_modules/undici-types/h2c-client.d.ts - neue Datei: clients/app/node_modules/undici-types/handlers.d.ts - neue Datei: clients/app/node_modules/undici-types/header.d.ts - neue Datei: clients/app/node_modules/undici-types/index.d.ts - neue Datei: clients/app/node_modules/undici-types/interceptors.d.ts - neue Datei: clients/app/node_modules/undici-types/mock-agent.d.ts - neue Datei: clients/app/node_modules/undici-types/mock-call-history.d.ts - neue Datei: clients/app/node_modules/undici-types/mock-client.d.ts - neue Datei: clients/app/node_modules/undici-types/mock-errors.d.ts - neue Datei: clients/app/node_modules/undici-types/mock-interceptor.d.ts - neue Datei: clients/app/node_modules/undici-types/mock-pool.d.ts - neue Datei: clients/app/node_modules/undici-types/package.json - neue Datei: clients/app/node_modules/undici-types/patch.d.ts - neue Datei: clients/app/node_modules/undici-types/pool-stats.d.ts - neue Datei: clients/app/node_modules/undici-types/pool.d.ts - neue Datei: clients/app/node_modules/undici-types/proxy-agent.d.ts - neue Datei: clients/app/node_modules/undici-types/readable.d.ts - neue Datei: clients/app/node_modules/undici-types/retry-agent.d.ts - neue Datei: clients/app/node_modules/undici-types/retry-handler.d.ts - neue Datei: clients/app/node_modules/undici-types/snapshot-agent.d.ts - neue Datei: clients/app/node_modules/undici-types/util.d.ts - neue Datei: clients/app/node_modules/undici-types/utility.d.ts - neue Datei: clients/app/node_modules/undici-types/webidl.d.ts - neue Datei: clients/app/node_modules/undici-types/websocket.d.ts - neue Datei: clients/app/node_modules/update-browserslist-db/LICENSE - neue Datei: clients/app/node_modules/update-browserslist-db/README.md - neue Datei: clients/app/node_modules/update-browserslist-db/check-npm-version.js - neue Datei: clients/app/node_modules/update-browserslist-db/cli.js - neue Datei: clients/app/node_modules/update-browserslist-db/index.d.ts - neue Datei: clients/app/node_modules/update-browserslist-db/index.js - neue Datei: clients/app/node_modules/update-browserslist-db/package.json - neue Datei: clients/app/node_modules/update-browserslist-db/utils.js - neue Datei: clients/app/node_modules/v8-to-istanbul/CHANGELOG.md - neue Datei: clients/app/node_modules/v8-to-istanbul/LICENSE.txt - neue Datei: clients/app/node_modules/v8-to-istanbul/README.md - neue Datei: clients/app/node_modules/v8-to-istanbul/index.d.ts - neue Datei: clients/app/node_modules/v8-to-istanbul/index.js - neue Datei: clients/app/node_modules/v8-to-istanbul/lib/branch.js - neue Datei: clients/app/node_modules/v8-to-istanbul/lib/function.js - neue Datei: clients/app/node_modules/v8-to-istanbul/lib/line.js - neue Datei: clients/app/node_modules/v8-to-istanbul/lib/range.js - neue Datei: clients/app/node_modules/v8-to-istanbul/lib/source.js - neue Datei: clients/app/node_modules/v8-to-istanbul/lib/v8-to-istanbul.js - neue Datei: clients/app/node_modules/v8-to-istanbul/package.json - neue Datei: clients/app/node_modules/walker/.travis.yml - neue Datei: clients/app/node_modules/walker/LICENSE - neue Datei: clients/app/node_modules/walker/lib/walker.js - neue Datei: clients/app/node_modules/walker/package.json - neue Datei: clients/app/node_modules/walker/readme.md - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/LICENSE - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/README.md - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/lib/BundleAnalyzerPlugin.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/lib/Logger.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/lib/analyzer.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/lib/bin/analyzer.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/lib/index.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/lib/parseUtils.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/lib/statsUtils.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/lib/template.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/lib/tree/BaseFolder.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/lib/tree/ConcatenatedModule.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/lib/tree/ContentFolder.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/lib/tree/ContentModule.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/lib/tree/Folder.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/lib/tree/Module.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/lib/tree/Node.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/lib/tree/utils.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/lib/utils.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/lib/viewer.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/node_modules/escape-string-regexp/index.d.ts - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/node_modules/escape-string-regexp/index.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/node_modules/escape-string-regexp/license - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/node_modules/escape-string-regexp/package.json - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/node_modules/escape-string-regexp/readme.md - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/package.json - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/public/viewer.js - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/public/viewer.js.LICENSE.txt - neue Datei: clients/app/node_modules/webpack-bundle-analyzer/public/viewer.js.map - neue Datei: clients/app/node_modules/which/CHANGELOG.md - neue Datei: clients/app/node_modules/which/LICENSE - neue Datei: clients/app/node_modules/which/README.md - neue Datei: clients/app/node_modules/which/bin/node-which - neue Datei: clients/app/node_modules/which/package.json - neue Datei: clients/app/node_modules/which/which.js - neue Datei: clients/app/node_modules/wrap-ansi/index.js - neue Datei: clients/app/node_modules/wrap-ansi/license - neue Datei: clients/app/node_modules/wrap-ansi/package.json - neue Datei: clients/app/node_modules/wrap-ansi/readme.md - neue Datei: clients/app/node_modules/wrappy/LICENSE - neue Datei: clients/app/node_modules/wrappy/README.md - neue Datei: clients/app/node_modules/wrappy/package.json - neue Datei: clients/app/node_modules/wrappy/wrappy.js - neue Datei: clients/app/node_modules/write-file-atomic/LICENSE.md - neue Datei: clients/app/node_modules/write-file-atomic/README.md - neue Datei: clients/app/node_modules/write-file-atomic/lib/index.js - neue Datei: clients/app/node_modules/write-file-atomic/package.json - neue Datei: clients/app/node_modules/ws/LICENSE - neue Datei: clients/app/node_modules/ws/README.md - neue Datei: clients/app/node_modules/ws/browser.js - neue Datei: clients/app/node_modules/ws/index.js - neue Datei: clients/app/node_modules/ws/lib/buffer-util.js - neue Datei: clients/app/node_modules/ws/lib/constants.js - neue Datei: clients/app/node_modules/ws/lib/event-target.js - neue Datei: clients/app/node_modules/ws/lib/extension.js - neue Datei: clients/app/node_modules/ws/lib/limiter.js - neue Datei: clients/app/node_modules/ws/lib/permessage-deflate.js - neue Datei: clients/app/node_modules/ws/lib/receiver.js - neue Datei: clients/app/node_modules/ws/lib/sender.js - neue Datei: clients/app/node_modules/ws/lib/stream.js - neue Datei: clients/app/node_modules/ws/lib/validation.js - neue Datei: clients/app/node_modules/ws/lib/websocket-server.js - neue Datei: clients/app/node_modules/ws/lib/websocket.js - neue Datei: clients/app/node_modules/ws/package.json - neue Datei: clients/app/node_modules/y18n/CHANGELOG.md - neue Datei: clients/app/node_modules/y18n/LICENSE - neue Datei: clients/app/node_modules/y18n/README.md - neue Datei: clients/app/node_modules/y18n/index.mjs - neue Datei: clients/app/node_modules/y18n/package.json - neue Datei: clients/app/node_modules/yallist/LICENSE - neue Datei: clients/app/node_modules/yallist/README.md - neue Datei: clients/app/node_modules/yallist/iterator.js - neue Datei: clients/app/node_modules/yallist/package.json - neue Datei: clients/app/node_modules/yallist/yallist.js - neue Datei: clients/app/node_modules/yargs-parser/CHANGELOG.md - neue Datei: clients/app/node_modules/yargs-parser/LICENSE.txt - neue Datei: clients/app/node_modules/yargs-parser/README.md - neue Datei: clients/app/node_modules/yargs-parser/browser.js - neue Datei: clients/app/node_modules/yargs-parser/package.json - neue Datei: clients/app/node_modules/yargs/LICENSE - neue Datei: clients/app/node_modules/yargs/README.md - neue Datei: clients/app/node_modules/yargs/browser.d.ts - neue Datei: clients/app/node_modules/yargs/browser.mjs - neue Datei: clients/app/node_modules/yargs/helpers/helpers.mjs - neue Datei: clients/app/node_modules/yargs/helpers/index.js - neue Datei: clients/app/node_modules/yargs/helpers/package.json - neue Datei: clients/app/node_modules/yargs/index.cjs - neue Datei: clients/app/node_modules/yargs/index.mjs - neue Datei: clients/app/node_modules/yargs/lib/platform-shims/browser.mjs - neue Datei: clients/app/node_modules/yargs/lib/platform-shims/esm.mjs - neue Datei: clients/app/node_modules/yargs/locales/be.json - neue Datei: clients/app/node_modules/yargs/locales/cs.json - neue Datei: clients/app/node_modules/yargs/locales/de.json - neue Datei: clients/app/node_modules/yargs/locales/en.json - neue Datei: clients/app/node_modules/yargs/locales/es.json - neue Datei: clients/app/node_modules/yargs/locales/fi.json - neue Datei: clients/app/node_modules/yargs/locales/fr.json - neue Datei: clients/app/node_modules/yargs/locales/hi.json - neue Datei: clients/app/node_modules/yargs/locales/hu.json - neue Datei: clients/app/node_modules/yargs/locales/id.json - neue Datei: clients/app/node_modules/yargs/locales/it.json - neue Datei: clients/app/node_modules/yargs/locales/ja.json - neue Datei: clients/app/node_modules/yargs/locales/ko.json - neue Datei: clients/app/node_modules/yargs/locales/nb.json - neue Datei: clients/app/node_modules/yargs/locales/nl.json - neue Datei: clients/app/node_modules/yargs/locales/nn.json - neue Datei: clients/app/node_modules/yargs/locales/pirate.json - neue Datei: clients/app/node_modules/yargs/locales/pl.json - neue Datei: clients/app/node_modules/yargs/locales/pt.json - neue Datei: clients/app/node_modules/yargs/locales/pt_BR.json - neue Datei: clients/app/node_modules/yargs/locales/ru.json - neue Datei: clients/app/node_modules/yargs/locales/th.json - neue Datei: clients/app/node_modules/yargs/locales/tr.json - neue Datei: clients/app/node_modules/yargs/locales/uk_UA.json - neue Datei: clients/app/node_modules/yargs/locales/uz.json - neue Datei: clients/app/node_modules/yargs/locales/zh_CN.json - neue Datei: clients/app/node_modules/yargs/locales/zh_TW.json - neue Datei: clients/app/node_modules/yargs/package.json - neue Datei: clients/app/node_modules/yargs/yargs - neue Datei: clients/app/node_modules/yargs/yargs.mjs - neue Datei: clients/app/node_modules/yocto-queue/index.d.ts - neue Datei: clients/app/node_modules/yocto-queue/index.js - neue Datei: clients/app/node_modules/yocto-queue/license - neue Datei: clients/app/node_modules/yocto-queue/package.json - neue Datei: clients/app/node_modules/yocto-queue/readme.md - gelöscht: docs/architecture/adr/0000-adr-template.md - gelöscht: docs/architecture/adr/0001-modular-architecture.md - gelöscht: docs/architecture/adr/0002-domain-driven-design.md - gelöscht: docs/architecture/adr/0003-microservices-architecture.md - gelöscht: docs/architecture/adr/0004-event-driven-communication.md - gelöscht: docs/architecture/adr/0005-polyglot-persistence.md - gelöscht: docs/architecture/adr/0006-authentication-authorization-keycloak.md - gelöscht: docs/architecture/adr/0007-api-gateway-pattern.md - gelöscht: docs/architecture/adr/0008-multiplatform-client-applications.md - gelöscht: docs/architecture/c4/01-context.puml - gelöscht: docs/architecture/c4/02-container.puml - gelöscht: docs/architecture/c4/03-component-events-service.puml diff --git a/.spectral.yaml b/.spectral.yaml new file mode 100644 index 00000000..388e9983 --- /dev/null +++ b/.spectral.yaml @@ -0,0 +1,6 @@ +extends: + - spectral:oas + +rules: + # Keep defaults from spectral:oas; tweak minimal project-specific preferences here if needed + info-contact: warn diff --git a/Makefile b/Makefile index 5b3f1dab..2f837694 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # =================================================================== # Meldestelle Docker Development Makefile -# Optimierte Befehle für containerisierte Entwicklungs-Workflows +# Optimierte Befehle für containerised Entwicklung-Workflows # =================================================================== .PHONY: help dev-up dev-down dev-restart dev-logs build clean test @@ -52,7 +52,7 @@ infrastructure-up: ## Start only infrastructure services (postgres, redis, keycl @echo "🏗️ Starting infrastructure services..." $(COMPOSE) -f docker-compose.yml up -d @echo "✅ Infrastructure services started" - @echo "🗄️ PostgreSQL: localhost:5432" + @echo "🗄️ PostgresQL: localhost:5432" @echo "🔴 Redis: localhost:6379" @echo "🔐 Keycloak: http://localhost:8180" @echo "🧭 Consul: http://localhost:8500" @@ -109,6 +109,45 @@ clients-logs: ## Show client application logs full-up: ## Start complete system (infrastructure + services + clients) @echo "🚀 Starting complete Meldestelle system..." $(COMPOSE) -f docker-compose.yml -f docker-compose.services.yml -f docker-compose.clients.yml up -d + +# =================================================================== +# SSoT Developer UX (optional helpers) +# =================================================================== +.PHONY: versions-show versions-update docker-sync docker-validate docker-compose-gen hooks-install + +# Show current centralized versions from docker/versions.toml +versions-show: ## Show centralized versions (docker/versions.toml) + @bash scripts/docker-versions-update.sh show + +# Update a single version key and sync env files (usage: make versions-update key=gradle value=9.1.0) +versions-update: ## Update one key in versions.toml and sync env files (key= value=) + @if [ -z "$(key)" ] || [ -z "$(value)" ]; then \ + echo "Usage: make versions-update key= value="; \ + echo "Keys: gradle java node nginx alpine prometheus grafana keycloak app-version spring-profiles-default spring-profiles-docker"; \ + exit 1; \ + fi + @bash scripts/docker-versions-update.sh update $(key) $(value) + +# Sync versions.toml into docker/build-args/*.env +docker-sync: ## Sync versions.toml -> build-args/*.env + @bash scripts/docker-versions-update.sh sync + +# Generate all compose files for selected environment (ENV=development|production|testing) +ENV ?= development + +docker-compose-gen: ## Generate docker-compose files from SSoT (ENV=development|production|testing) + @bash scripts/generate-compose-files.sh all $(ENV) + +# Run full Docker SSoT validation +docker-validate: ## Validate SSoT (dockerfiles, compose, ports, build-args, drift) + @bash scripts/validate-docker-consistency.sh all + +# Install optional pre-commit hook for SSoT guard +hooks-install: ## Install pre-commit SSoT guard hook into .git/hooks/pre-commit + @mkdir -p .git/hooks + @cp scripts/git-hooks/pre-commit-ssot .git/hooks/pre-commit + @chmod +x .git/hooks/pre-commit + @echo "✅ Installed .git/hooks/pre-commit (SSoT guard)" @echo "✅ Complete system started" @echo "" @echo "🌐 Frontend & APIs:" @@ -116,7 +155,7 @@ full-up: ## Start complete system (infrastructure + services + clients) @echo " API Gateway: http://localhost:8081" @echo "" @echo "🔧 Infrastructure:" - @echo " PostgreSQL: localhost:5432" + @echo " PostgresQL: localhost:5432" @echo " Redis: localhost:6379" @echo " Keycloak: http://localhost:8180" @echo " Consul: http://localhost:8500" @@ -219,7 +258,7 @@ dev-tools-up: ## Info: development tool containers were removed (use local tools @echo "ℹ️ Development tool containers are not part of the simplified setup." @echo "Use your local tools instead (e.g., pgAdmin, TablePlus, DBeaver, RedisInsight)." @echo "Connection hints:" - @echo " PostgreSQL: localhost:5432 (user/password per .env or defaults)" + @echo " PostgresQL: localhost:5432 (user/password per .env or defaults)" @echo " Redis: localhost:6379" @echo " Consul: http://localhost:8500" @echo " Keycloak: http://localhost:8180" @@ -271,7 +310,7 @@ health-check: ## Check health of core infrastructure services @$(COMPOSE) ps @echo "-- Postgres --" @$(COMPOSE) exec -T postgres pg_isready -U meldestelle -d meldestelle >/dev/null \ - && echo "PostgreSQL: ✅ Ready" || echo "PostgreSQL: ❌ Not ready" + && echo "PostgresQL: ✅ Ready" || echo "PostgresQL: ❌ Not ready" @echo "-- Redis --" @$(COMPOSE) exec -T redis redis-cli ping | grep -q PONG \ && echo "Redis: ✅ PONG" || echo "Redis: ❌ Not responding" @@ -328,7 +367,7 @@ dev-info: ## Show development environment information @echo " Keycloak: http://localhost:8180 (admin/admin by default)" @echo "" @echo "🗄️ Infrastructure:" - @echo " PostgreSQL: localhost:5432 (default user: meldestelle)" + @echo " PostgresQL: localhost:5432 (default user: meldestelle)" @echo " Redis: localhost:6379" @echo "" @echo "ℹ️ Tips: Use 'make health-check' to verify services, and 'make logs SERVICE=postgres' for logs." diff --git a/README.md b/README.md index 893ae10d..2298f28c 100644 --- a/README.md +++ b/README.md @@ -1,387 +1,376 @@ # Meldestelle -## Überblick +> Modulares System für Pferdesportveranstaltungen mit Domain-Driven Design -Meldestelle ist ein modulares System zur Verwaltung von Pferdesportveranstaltungen. Das System ermöglicht die Registrierung von Pferden, Mitgliedern und Veranstaltungen sowie die Verwaltung von Stammdaten. +[![CI Pipeline](https://github.com/StefanMoCoAt/meldestelle/workflows/CI%20-%20Main%20Pipeline/badge.svg)](https://github.com/StefanMoCoAt/meldestelle/actions) +[![Docker SSoT](https://github.com/StefanMoCoAt/meldestelle/workflows/Docker%20SSoT%20Guard/badge.svg)](https://github.com/StefanMoCoAt/meldestelle/actions) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -Das Projekt wurde kürzlich auf eine modulare Architektur migriert, um die Wartbarkeit und Erweiterbarkeit zu verbessern. +--- -## Systemanforderungen - -- Java 21 -- Kotlin 2.2.10 -- Gradle 9.0.0 (automatischer Download über Gradle Wrapper) -- Docker und Docker Compose (v2.0+) - -## Infrastruktur - -Das System nutzt folgende Dienste: - -- **PostgreSQL 16**: Primäre Datenbank -- **Redis 7**: Caching -- **Keycloak 23.0**: Authentifizierung und Autorisierung -- **Kafka 7.5.0**: Messaging und Event-Streaming -- **Zipkin**: Distributed Tracing -- **Prometheus & Grafana**: Monitoring (optional) - -## Projektstruktur - -Das Projekt ist in folgende Hauptmodule unterteilt: - -- **core**: Gemeinsame Kernkomponenten - - core-domain: Domänenmodelle und Geschäftslogik - - core-utils: Allgemeine Hilfsfunktionen - -- **masterdata**: Umfassende Verwaltung von Stammdaten für Pferdesportveranstaltungen - - **Funktionalität**: Länder (ISO-Codes, EU/EWR-Mitgliedschaft), Bundesländer (OEPS/ISO-Codes), Altersklassen (Teilnahmeberechtigung), Turnierplätze (Typ, Abmessungen, Boden) - - **API-Endpunkte**: 37 REST-Endpunkte mit vollständiger CRUD-Funktionalität - - **Geschäftslogik**: Validierung, Duplikatsprüfung, Berechtigung, Eignung für Disziplinen - - masterdata-api: REST-Controller und DTO-Definitionen - - masterdata-application: Use Cases und Geschäftslogik - - masterdata-domain: Domänenmodelle und Repository-Interfaces - - masterdata-infrastructure: Datenbankzugriff und Persistierung - - masterdata-service: Spring Boot Service-Implementierung - -- **members**: Mitgliederverwaltung - - members-api: API-Definitionen - - members-application: Anwendungslogik - - members-domain: Domänenmodelle - - members-infrastructure: Infrastrukturkomponenten - - members-service: Service-Implementierung - -- **horses**: Pferderegistrierung - - horses-api: API-Definitionen - - horses-application: Anwendungslogik - - horses-domain: Domänenmodelle - - horses-infrastructure: Infrastrukturkomponenten - - horses-service: Service-Implementierung - -- **events**: Veranstaltungsverwaltung - - events-api: API-Definitionen - - events-application: Anwendungslogik - - events-domain: Domänenmodelle - - events-infrastructure: Infrastrukturkomponenten - - events-service: Service-Implementierung - -- **infrastructure**: Gemeinsame Infrastrukturkomponenten - - auth: Authentifizierung - - cache: Caching - - event-store: Event-Speicher - - gateway: API-Gateway - - messaging: Messaging-Infrastruktur - - monitoring: Monitoring-Komponenten - -- **client**: Client-Anwendungen - - common-ui: Gemeinsame UI-Komponenten - - desktop-app: Desktop-Anwendung - - web-app: Web-Anwendung - -## Installation und Setup - -### Voraussetzungen - -Stellen Sie sicher, dass Java 21, Docker und Docker Compose installiert sind. - -### Docker-Infrastruktur - -Das System bietet verschiedene Docker-Konfigurationen für unterschiedliche Umgebungen: - -#### Entwicklungsumgebung (Schnellstart) +## 🚀 Quick Start ```bash -# Infrastruktur starten -docker compose up -d +# 1) Repository klonen +git clone https://github.com/StefanMoCoAt/meldestelle.git +cd meldestelle -# Status überprüfen -docker compose ps +# 2) (Optional, falls SSoT Compose-Files erst generiert werden müssen) +# DOCKER_SSOT_MODE=envless bash scripts/generate-compose-files.sh all development -# Logs anzeigen -docker compose logs -f -``` +# 3) Infrastruktur starten +docker compose -f docker-compose.yml up -d -Dies startet alle erforderlichen Dienste wie PostgreSQL, Redis, Keycloak, Kafka, Zipkin und optional Prometheus und Grafana. - -#### Produktionsumgebung - -Für die Produktionsumgebung siehe **[README-PRODUCTION.md](Tagebuch/README-PRODUCTION.md)** - enthält: -- Umfassende Sicherheitskonfiguration -- SSL/TLS-Setup -- Detaillierte Troubleshooting-Anleitung -- Backup- und Wiederherstellungsverfahren - -#### Umgebungsvariablen - -Für die Konfiguration von Umgebungsvariablen siehe **[README-ENV.md](Tagebuch/README-ENV.md)** - enthält: -- Vollständige Umgebungsvariablen-Dokumentation -- Validierungsskripte -- Konfigurationsbeispiele - -### Validierung und Troubleshooting - -```bash -# Umgebungsvariablen validieren -./validate-env.sh - -# Docker-Compose Konfiguration validieren -./validate-docker-compose.sh - -# Service-Status überprüfen -docker-compose ps - -# Service-Logs anzeigen -docker-compose logs [service-name] -``` - -### Projekt bauen - -```bash -./gradlew build -``` - -### Dienste starten - -```bash -# Gateway starten -./gradlew :infrastructure:gateway:bootRun - -# Masterdata-Service starten -./gradlew :masterdata:masterdata-service:bootRun - -# Members-Service starten +# 4) Services starten (Beispiel) ./gradlew :members:members-service:bootRun - -# Horses-Service starten -./gradlew :horses:horses-service:bootRun - -# Events-Service starten -./gradlew :events:events-service:bootRun +# oder – falls zentral gewollt und unterstützt +# ./gradlew bootRun ``` -### Client-Anwendungen starten +**Vollständige Anleitung**: [docs/how-to/start-local.md](docs/how-to/start-local.md) -Die Client-Anwendungen sind als ein gemeinsames Kotlin Multiplatform (KMP) Modul `:client` organisiert und liefern: -- Desktop (JVM) über Compose Desktop -- Web (Kotlin/JS im Browser) über Compose Multiplatform -- Optional: WASM mit Flag -PenableWasm=true +--- + +## 📚 Dokumentation + +### Single Source of Truth: YouTrack + +Die Hauptdokumentation befindet sich in der **YouTrack Wissensdatenbank**: + +👉 **[Meldestelle Command Center](https://meldestelle-pro.youtrack.cloud/articles/MP-A-24)** + +#### In YouTrack + +- 🏗️ **Bounded Context Dokumentation** (Members, Horses, Events, Masterdata) +- 📡 **API-Referenz** (automatisch aus KDoc generiert) +- 🚀 **Deployment-Guides** (Proxmox, Cloudflare, Nginx) +- 🔐 **Infrastruktur-Konfigurationen** (Netzwerk, Datenbanken, Keycloak) +- 💡 **Roadmap & Visionen** + +#### Im Repository + +- [📖 docs/README.md](docs/README.md) - Übersicht aller Repository-Dokumentation +- [🏛️ Architecture Decision Records](docs/architecture/adr) +- [📐 C4-Diagramme](docs/architecture/c4) +- [🛠️ Developer Guides](docs/how-to) +- [📑 Projekt-Guidelines (Master)](.junie/guidelines/master-guideline.md) + +Zusätzliche zentrale Guidelines: + +- [Coding Standards](.junie/guidelines/project-standards/coding-standards.md) +- [Testing Standards](.junie/guidelines/project-standards/testing-standards.md) +- [Documentation Standards](.junie/guidelines/project-standards/documentation-standards.md) +- [Architecture Principles](.junie/guidelines/project-standards/architecture-principles.md) +- [Web App Guideline](.junie/guidelines/technology-guides/web-app-guideline.md) +- Docker Guides: + - [Docker Overview](.junie/guidelines/technology-guides/docker/docker-overview.md) + - [Docker Architecture](.junie/guidelines/technology-guides/docker/docker-architecture.md) + - [Docker Development](.junie/guidelines/technology-guides/docker/docker-development.md) + - [Docker Production](.junie/guidelines/technology-guides/docker/docker-production.md) + - [Docker Monitoring](.junie/guidelines/technology-guides/docker/docker-monitoring.md) + - [Docker Troubleshooting](.junie/guidelines/technology-guides/docker/docker-troubleshooting.md) +- Process Guide: [Trace Bullet](.junie/guidelines/process-guides/trace-bullet-guideline.md) + +--- + +## 🏗️ Architektur + +### Bounded Contexts (DDD) + +Das System ist in unabhängige Domänen aufgeteilt: + +- **Members**: Mitgliederverwaltung +- **Horses**: Pferderegistrierung +- **Events**: Veranstaltungsverwaltung +- **Masterdata**: Stammdaten (Länder, Altersklassen, Turnierplätze) + +### Technische Architektur + +- **Microservices**: Unabhängige Services mit API Gateway +- **Event-Driven**: Apache Kafka für asynchrone Kommunikation +- **Polyglot Persistence**: PostgreSQL + Redis +- **Container-First**: Docker & Docker Compose + +**Details**: [ADR-0002 Domain-Driven Design](docs/architecture/adr/0002-domain-driven-design-de.md) + +--- + +## 🛠️ Tech Stack + +| Komponente | Technologie | Version | +|----------------|-------------------------------|---------| +| **Backend** | Kotlin + Spring Boot | 3.x | +| **JVM** | Java | 21 | +| **Build** | Gradle | 9.1.0 | +| **Datenbank** | PostgreSQL | 16 | +| **Cache** | Redis | 7 | +| **Messaging** | Apache Kafka | 7.4.0 | +| **Auth** | Keycloak | 26.4.2 | +| **Monitoring** | Prometheus + Grafana + Zipkin | - | +| **Container** | Docker + Docker Compose | v2.0+ | + +--- + +### 📦 Projektstruktur + +```plaintext +Meldestelle/ +├── 🗂️ client/ # Client-Anwendungen +│ ├── desktop-app/ +│ └── web-app/ +├── 🗂️ core/ # Gemeinsame Kern-Komponenten +│ ├── core-domain/ +│ └── core-utils/ +├── 🗂️ docs/ # Minimale Entwickler-Dokumentation +│ ├── architecture/ +│ └── how-to/ +├── 🗂️ events/ # Bounded Context: Veranstaltungsverwaltung +│ └── (analog zu members) +├── 🗂️ horses/ # Bounded Context: Pferderegistrierung +│ └── (analog zu members) +├── 🗂️ infrastructure/ # Technische Infrastruktur +│ ├── auth/ # Authentifizierung +│ ├── cache/ # Caching (Redis) +│ ├── gateway/ # API Gateway (Spring Cloud Gateway) +│ ├── messaging/ # Kafka-Integration +│ └── monitoring/ # Observability +├── 🗂️ masterdata/ # Bounded Context: Stammdaten +│ └── (analog zu members) +└── 🗂️ members/ # Bounded Context: Mitgliederverwaltung + ├── members-api/ + ├── members-application/ + ├── members-domain/ + ├── members-infrastructure/ + └── members-service/ +``` + +--- + +## 🔒 Docker Single Source of Truth (SSoT) + +Alle Versionen zentral in **`docker/versions.toml`**: + +### SSoT – Schnellstart (präzisiert) ```bash -# Desktop (JVM) starten -./gradlew :client:run +# Versionen anzeigen +bash scripts/docker-build.sh --versions -# Web (WASM) – Development-Server mit Live-Reload -./gradlew :client:wasmJsBrowserDevelopmentRun +# Compose-Files generieren (Kompatibilitätsmodus) +bash scripts/generate-compose-files.sh all development -# Web (WASM) – Production-Build (mit optionaler Bundle-Analyse) -ANALYZE_BUNDLE=true ./gradlew :client:wasmJsBrowserProductionWebpack +# Konsistenz validieren (Kompatibilitätsmodus) +bash scripts/validate-docker-consistency.sh all ``` -Ausgabeorte (Build-Artefakte): -- Desktop-Distributionen: client/build/compose/binaries -- WASM Production Build: client/build/dist/wasmJs/productionExecutable - -## Entwicklung - -### Aktuelle Migrationshinweise - -Das Projekt wurde kürzlich von einer monolithischen Struktur zu einer modularen Architektur migriert. Die Migration umfasste: - -- Umzug von `:shared-kernel` zu `core`-Modulen -- Umzug von `:master-data` zu `masterdata`-Modulen -- Umzug von `:member-management` zu `members`-Modulen -- Umzug von `:horse-registry` zu `horses`-Modulen -- Umzug von `:event-management` zu `events`-Modulen -- Umzug von `:api-gateway` zu `infrastructure/gateway` -- Umzug von `:composeApp` zu `client`-Modulen - -Es gibt noch einige offene Probleme, insbesondere bei den Client-Modulen, die Kotlin Multiplatform und Compose Multiplatform verwenden. - -#### Status der Client-Module (nach Migration) -- Build-Status: :client baut erfolgreich für JVM, JS und WASM (Chrome/Karma-Tests sind bewusst deaktiviert, siehe unten) -- Desktop: Compose Desktop App startet über :client:run; API-Basisadresse via Umgebungsvariable API_BASE_URL (Default: http://localhost:8081) -- Web/WASM: Development-Server (:client:wasmJsBrowserDevelopmentRun) und Production-Build (:client:wasmJsBrowserProductionWebpack) funktionieren; API-Aufruf erfolgt same-origin über /api/ping (hinter dem Gateway) -- HTTP-Client: Minimaler Ktor-Client (ohne überflüssige Plugins) zur Reduzierung der Bundle-Größe -- UI: Platzhalter-/Demo-Features (Ping, Platform-Info, Conditional Panels) vorhanden; Domänenseiten für masterdata/members/horses/events noch ausständig - -Bekannte Einschränkungen & offene Punkte: -- End-to-End-Navigation zu allen Domänen (masterdata, members, horses, events) fehlt noch -- Authentifizierung/Session-Handling im Client noch nicht integriert (Gateway/Keycloak folgt) -- Browser-basierte Unit-Tests (Karma/ChromeHeadless) sind abgeschaltet, um lokale Sandbox-Probleme zu vermeiden; JS-Tests laufen unter Node/Mocha - -#### WASM-Bundle-Analyse & Optimierung -- Aktivieren über Umgebungsvariable ANALYZE_BUNDLE=true beim Production-WebBuild: - - ANALYZE_BUNDLE=true ./gradlew :client:wasmJsBrowserProductionWebpack - -- Die Datei client/webpack.config.d/bundle-analyzer.js protokolliert die Asset-Größen und gibt Optimierungshinweise aus -- client/webpack.config.d/wasm-optimization.js aktiviert Tree-Shaking, Chunk-Splitting und Produktionsoptimierungen -- Weitere Tipps: Reduktion schwerer UI-Komponenten, Lazy Loading, Entfernen ungenutzter Abhängigkeiten - -#### Integrationstests und E2E-Hinweise -- Vorhandene Modul-Integrationstests können per ./gradlew test ausgeführt werden -- Für manuelles E2E: - 1) docker compose up -d (Gateway + Services) - 2) Desktop-Client starten oder WASM-Dev-Server starten - 3) Ping im Client ausführen; Erwartung: Status OK vom Gateway-Endpunkt /api/ping - -### Entwicklungsrichtlinien - -- Verwenden Sie die in der Projektstruktur definierten Module -- Folgen Sie den Architekturentscheidungen (ADRs) im Verzeichnis `docs/architecture/adr` (verfügbar in Deutsch mit Dateiendung `-de.md`) -- Verwenden Sie die C4-Diagramme im Verzeichnis `docs/architecture/c4` für einen Überblick über die Systemarchitektur (verfügbar in Deutsch mit Dateiendung `-de.puml`) -- Verwenden Sie die Datenmodelle aus `docs/architecture/data-model` - -### Tests ausführen +### SSoT – Zwei Betriebsmodi (konsistent) ```bash -./gradlew test +# 1) Kompatibilitätsmodus (compat) +bash scripts/docker-versions-update.sh sync +bash scripts/generate-compose-files.sh all development +bash scripts/validate-docker-consistency.sh all + +# 2) Env-less Modus (empfohlen) +DOCKER_SSOT_MODE=envless bash scripts/docker-build.sh --versions +DOCKER_SSOT_MODE=envless bash scripts/generate-compose-files.sh all development +DOCKER_SSOT_MODE=envless bash scripts/validate-docker-consistency.sh all ``` -## Docker Troubleshooting (Entwicklungsumgebung) - -### Häufige Probleme und Lösungen - -#### 1. Services starten nicht -```bash -# Alle Services stoppen und neu starten -docker compose down -docker compose up -d - -# Einzelnen Service neu starten -docker compose restart [service-name] - -# Service-Logs überprüfen -docker compose logs [service-name] -``` - -#### 2. Port bereits belegt -```bash -# Verwendete Ports prüfen -netstat -tulpn | grep :[port] -# oder -lsof -i :[port] - -# Ports in .env anpassen -nano .env -# Beispiel: API_PORT=8081 statt 8080 -``` - -#### 3. Datenbank-Verbindungsfehler -```bash -# PostgreSQL-Status prüfen -docker compose exec postgres pg_isready -U meldestelle - -# Datenbank-Logs anzeigen -docker compose logs postgres - -# Verbindung manuell testen -docker compose exec postgres psql -U meldestelle -d meldestelle -``` - -#### 4. Keycloak-Authentifizierung fehlgeschlagen -```bash -# Keycloak-Status prüfen -docker compose logs keycloak - -# Keycloak Admin-Console öffnen -# http://localhost:8180/admin (admin/admin) - -# Keycloak-Datenbank zurücksetzen -docker compose down -docker volume rm meldestelle_postgres-data -docker compose up -d -``` - -#### 5. Kafka-Verbindungsprobleme -```bash -# Kafka-Status prüfen -docker compose exec kafka kafka-topics --bootstrap-server localhost:9092 --list - -# Zookeeper-Status prüfen -docker compose exec zookeeper nc -z localhost 2181 - -# Kafka-Logs anzeigen -docker compose logs kafka zookeeper -``` - -#### 6. Speicherplatz-Probleme -```bash -# Docker-Speicherverbrauch prüfen -docker system df - -# Ungenutzte Ressourcen bereinigen -docker system prune -f - -# Volumes bereinigen (ACHTUNG: Datenverlust!) -docker system prune -f --volumes -``` - -#### 7. Performance-Probleme -```bash -# Ressourcenverbrauch überwachen -docker stats - -# Container-Limits anpassen (in docker-compose.yml) -# deploy: -# resources: -# limits: -# memory: 1G -# cpus: '0.5' -``` - -### Nützliche Docker-Befehle +Alternative (persistente Shell-Variante): ```bash -# Alle Services mit Logs starten -docker compose up - -# Services im Hintergrund starten -docker compose up -d - -# Bestimmte Services starten -docker compose up postgres redis - -# Services stoppen -docker compose stop - -# Services stoppen und Container entfernen -docker compose down - -# Services mit Volume-Bereinigung stoppen -docker compose down -v - -# Container-Shell öffnen -docker compose exec [service-name] /bin/bash -# oder für Alpine-basierte Images: -docker compose exec [service-name] /bin/sh - -# Konfiguration validieren -docker compose config - -# Service-Status anzeigen -docker compose ps - -# Logs aller Services anzeigen -docker compose logs - -# Logs eines bestimmten Services verfolgen -docker compose logs -f [service-name] +export DOCKER_SSOT_MODE=envless +bash scripts/docker-build.sh --versions +bash scripts/generate-compose-files.sh all development +bash scripts/validate-docker-consistency.sh all ``` -## Dokumentation +#### CI-Schutz – lokal reproduzieren (getrennte/verkettete Befehle) -Weitere Dokumentation finden Sie im `docs`-Verzeichnis: +```bash +# Compat +bash scripts/docker-versions-update.sh sync && \ + bash scripts/generate-compose-files.sh all development && \ + bash scripts/validate-docker-consistency.sh all && \ + git diff --name-only # sollte leer sein -- API-Dokumentation: `docs/api` -- Architektur: `docs/architecture` -- Entwicklungsrichtlinien: `docs/development` -- Diagramme: `docs/diagrams` -- Betriebsanleitung: `docs/operations` -- Postman-Sammlungen: `docs/postman` +# Env-less (Variante A: prefix) +DOCKER_SSOT_MODE=envless bash scripts/generate-compose-files.sh all development && \ + DOCKER_SSOT_MODE=envless bash scripts/validate-docker-consistency.sh all && \ + git diff --name-only # sollte leer sein -## Lizenz +# Env-less (Variante B: export) +export DOCKER_SSOT_MODE=envless +bash scripts/generate-compose-files.sh all development && \ + bash scripts/validate-docker-consistency.sh all && \ + git diff --name-only # sollte leer sein +``` -Siehe [LICENSE](LICENSE) Datei. +### Deployment (klarstellen, falls SSoT vorausgeht) -## Stand +```bash +# Nur Infrastruktur +# Wenn eine handgeschriebene docker-compose.yml existiert: +docker compose -f docker-compose.yml up -d +# Falls Compose-Files generiert werden: +docker compose -f docker-compose.services.yml up -d -Letzte Aktualisierung: 14. September 2025 +# Services via Gradle +a) Einzeldienst +./gradlew :members:members-service:bootRun +b) Falls unterstützt: alle (oder Aggregator) +./gradlew bootRun +``` + +**Details**: Siehe Abschnitt "Docker Single Source of Truth (SSoT)" weiter unten + +--- + +## 🧪 Testing + +### Unit Tests + +```bash + ./gradlew test +``` + +### Integration Tests + +```bash + ./gradlew integrationTest +``` + +### Spezifisches Modul testen + +```bash + ./gradlew :members:members-service:test +``` + +--- + +## 🚢 Deployment + +### Lokale Entwicklung + +#### Nur Infrastruktur (Postgres, Redis, Kafka, Keycloak) + +```bash + docker compose -f docker-compose.yml up -d +``` + +#### Services über Gradle + +```bash + ./gradlew bootRun +``` + +--- + +## Docker Single Source of Truth (SSoT)—Details + +Dieser Abschnitt beschreibt den lokalen Workflow für die zentrale Docker-Versionsverwaltung. + +### TL;DR – Zwei Betriebsmodi + +- **Kompatibilitätsmodus (Standard)**: `build-args/*.env` werden aus `versions.toml` generiert + + ```bash + bash scripts/docker-versions-update.sh sync + bash scripts/generate-compose-files.sh all development + bash scripts/validate-docker-consistency.sh all + ``` + +- **Env-less Modus (Empfohlen)**: Keine `build-args/*.env` nötig – direkter Export aus `versions.toml` + + ```bash + DOCKER_SSOT_MODE=envless bash scripts/docker-build.sh --versions + DOCKER_SSOT_MODE=envless bash scripts/generate-compose-files.sh all development + DOCKER_SSOT_MODE=envless bash scripts/validate-docker-consistency.sh all + ``` + +### Makefile-Shortcuts + +```bash + make docker-sync # Kompatibilitätsmodus: Sync + make docker-compose-gen # Compose-Files generieren + make docker-validate # Validierung +``` + +### Was ist die Single Source of Truth? + +- **`docker/versions.toml`** enthält alle Versionsangaben (Gradle, Java, Node, Nginx, Postgres, Redis, etc.) +- **Env-less**: `docker/build-args/*.env` sind optional; Variablen zur Laufzeit aus `versions.toml` +- **docker-compose*.yml** werden generiert und referenzieren nur zentrale `DOCKER_*`-Variablen +- **Dockerfiles** deklarieren ARGs ohne Default-Werte + +### Versionen ändern + +```bash + bash scripts/docker-versions-update.sh update gradle 9.1.0 + bash scripts/docker-versions-update.sh update node 22.21.0 + bash scripts/docker-versions-update.sh update postgres 16-alpine +``` + +Danach: `generate` + `validate` ausführen! + +### CI-Schutz + +Die CI validiert Docker SSoT in beiden Modi (Matrix: compat + envless). + +**Lokal reproduzieren**: + +#### Compat + +```bash +bash scripts/docker-versions-update.sh sync && \ + bash scripts/generate-compose-files.sh all development && \ + bash scripts/validate-docker-consistency.sh all && \ + git diff --name-only # sollte leer sein +``` + +#### Env-less + +```bash +DOCKER_SSOT_MODE=envless bash scripts/generate-compose-files.sh all development && \ + DOCKER_SSOT_MODE=envless bash scripts/validate-docker-consistency.sh all && \ + git diff --name-only # sollte leer sein +``` + +--- + +## 🔄 Automatisierte Workflows + +| Workflow | Zweck | Trigger | +|------------------------------------------------------------------|--------------------------------------|-------------------| +| [ci-main.yml](.github/workflows/ci-main.yml) | Build, Test, OpenAPI-Lint, Docs-Lint | Push/PR | +| [ssot-guard.yml](.github/workflows/ssot-guard.yml) | Docker SSoT Validierung | Push/PR | +| [docs-kdoc-sync.yml](.github/workflows/docs-kdoc-sync.yml) | KDoc → YouTrack Sync | workflow_dispatch | +| [integration-tests.yml](.github/workflows/integration-tests.yml) | Integration Tests | Push/PR | +| [deploy-proxmox.yml](.github/workflows/deploy-proxmox.yml) | Deployment zu Proxmox | workflow_dispatch | + +--- + +## 📜 Lizenz + +[MIT License](LICENSE) + +--- + +## 🤝 Contributing + +Bitte lies [docs/how-to/branchschutz-und-pr-workflow.md](docs/how-to/branchschutz-und-pr-workflow.md) für den +PR-Workflow. + +--- + +## 📞 Support & Kontakt + +- **Bugs**: [GitHub Issues](https://github.com/StefanMoCoAt/meldestelle/issues) +- **Discussions**: [GitHub Discussions](https://github.com/StefanMoCoAt/meldestelle/discussions) +- **Dokumentation**: [YouTrack Wissensdatenbank](https://meldestelle-pro.youtrack.cloud/articles/MP-A-24) + +--- + +**Version**: 2.0.0 (nach Dokumentations-Refactoring) +**letzte Aktualisierung**: 31. Oktober 2025 diff --git a/Schlachtplan.md b/Schlachtplan.md index ea9c7055..fe0fc29f 100644 --- a/Schlachtplan.md +++ b/Schlachtplan.md @@ -1,32 +1,37 @@ ### Schlachtplan für das 'infrastructure'-Modul -Basierend auf der Analyse des aktuellen Zustands (Stand: 11. Oktober 2025) habe ich einen strukturierten Aktionsplan erstellt. Die letzte größere Aktualisierung war im Juli 2025, seitdem gab es signifikante Änderungen am Gateway-Modul. +Basierend auf der Analyse des aktuellen Zustands (Stand: 11. Oktober 2025) habe ich einen strukturierten Aktionsplan +erstellt. Die letzte größere Aktualisierung war im Juli 2025, seitdem gab es signifikante Änderungen am Gateway-Modul. --- ### 🔴 Phase 1: SOFORT (Diese Woche) #### 1.1 Gateway-Tests reparieren (Höchste Priorität) + **Problem:** Tests sind komplett defekt - nur ~47% funktionieren noch (25/53 Tests). **Aktionen:** + - ❌ **Löschen:** `JwtAuthenticationTests.kt` - testet nicht-existierende Custom-Filter - ✅ **Behalten:** `FallbackControllerTests.kt`, `GatewayApplicationTests.kt` - ✏️ **Überarbeiten:** `GatewayRoutingTests.kt`, `GatewaySecurityTests.kt`, `GatewayFiltersTests.kt` - - Option A: Tests mit MockJWT-Tokens ausstatten (siehe `TestSecurityConfig.kt`) - - Option B: Tests auf Public Paths verlegen (`/actuator/**`, `/fallback/**`) - - Option C: Security in Tests deaktivieren + - Option A: Tests mit MockJWT-Tokens ausstatten (siehe `TestSecurityConfig.kt`) + - Option B: Tests auf Public Paths verlegen (`/actuator/**`, `/fallback/**`) + - Option C: Security in Tests deaktivieren -**Warum jetzt:** Tests geben keine Sicherheit mehr - blockiert Entwicklung. +**Warum jetzt:** Tests geben keine Sicherheit mehr – blockiert Entwicklung. -**Zeitaufwand:** 4-6 Stunden +**Zeitaufwand:** 4–6 Stunden --- -#### 1.2 Gateway Build-Datei bereinigen +#### 1.2 Gateway-Build-Datei bereinigen + **Problem:** Duplizierte Dependency in `gateway/build.gradle.kts` (Zeile 33-34). **Aktion:** + ```kotlin // ENTFERNEN: Zeile 34 implementation(project(":infrastructure:event-store:redis-event-store")) // ← Duplikat! @@ -39,29 +44,32 @@ implementation(project(":infrastructure:event-store:redis-event-store")) // ← ### 🟡 Phase 2: KURZFRISTIG (Nächste 2 Wochen) #### 2.1 Dependency-Versionen aktualisieren -**Problem:** Versionen von Juli 2025 - teilweise veraltet. + +**Problem:** Versionen von Juli 2025 – teilweise veraltet. **Zu prüfen und aktualisieren:** -| Dependency | Aktuell | Latest (Okt 2025) | Priorität | -|------------|---------|-------------------|-----------| -| Spring Boot | 3.5.5 | 3.5.x | Mittel | -| Spring Cloud | 2025.0.0 | 2025.0.x | Mittel | -| Kotlin | 2.2.20 | 2.2.x | Niedrig | -| Keycloak | 26.0.7 | 26.x.x | Hoch | -| Testcontainers | 1.21.3 | 1.21.x | Niedrig | -| PostgreSQL Driver | 42.7.7 | 42.7.x | Niedrig | +| Dependency | Aktuell | Latest (Okt 2025) | Priorität | +|-------------------|----------|-------------------|-----------| +| Spring Boot | 3.5.5 | 3.5.x | Mittel | +| Spring Cloud | 2025.0.0 | 2025.0.x | Mittel | +| Kotlin | 2.2.20 | 2.2.x | Niedrig | +| Keycloak | 26.0.7 | 26.x.x | Hoch | +| Testcontainers | 1.21.3 | 1.21.x | Niedrig | +| PostgresQL Driver | 42.7.7 | 42.7.x | Niedrig | **Aktion:** + 1. `gradle/libs.versions.toml` aktualisieren 2. Tests nach jedem Update ausführen 3. Breaking Changes dokumentieren -**Zeitaufwand:** 1-2 Tage (mit Testing) +**Zeitaufwand:** 1–2 Tage (mit Testing) --- #### 2.2 Docker-Images aktualisieren + **Problem:** Einige Docker-Images sind möglicherweise veraltet. **Zu prüfen:** @@ -78,41 +86,47 @@ grafana: 11.3.0 # ✅ Wahrscheinlich aktuell ``` **Aktion:** + 1. Versions-Check durchführen 2. Schrittweise aktualisieren (einzeln testen!) 3. `.env`-Datei mit Versions-Variablen anlegen -**Zeitaufwand:** 3-4 Stunden +**Zeitaufwand:** 3–4 Stunden --- #### 2.3 Monitoring-Modul vervollständigen -**Problem:** Nur 3 Kotlin-Files - deutlich unterimplementiert im Vergleich zur Dokumentation. -**Dokumentiert aber fehlt:** +**Problem:** Nur 3 Kotlin-Files – deutlich unter implementiert im Vergleich zur Dokumentation. + +**Dokumentiert, aber fehlt:** + - Distributed Tracing (Zipkin) - Docker-Container fehlt! - Custom Metrics Implementation - Health Check Aggregation - Alerting Rules Implementation **Aktion:** + 1. Zipkin zu `docker-compose.yml` hinzufügen 2. Tracing-Integration in Gateway testen 3. Custom Metrics-Library erstellen 4. Prometheus Alerting Rules konfigurieren -**Zeitaufwand:** 2-3 Tage +**Zeitaufwand:** 2–3 Tage --- -### 🟢 Phase 3: MITTELFRISTIG (Nächste 4-6 Wochen) +### 🟢 Phase 3: MITTELFRISTIG (Nächste 4–6 Wochen) #### 3.1 Dokumentation aktualisieren -**Problem:** README von Juli 2025 - nicht mehr aktuell. + +**Problem:** README von Juli 2025 – nicht mehr aktuell. **Zu aktualisieren:** **`README-INFRASTRUCTURE.md`:** + - Zeile 552: "Letzte Aktualisierung: 25. Juli 2025" → Oktober 2025 - Security-Sektion: OAuth2 Resource Server statt Custom JWT Filter - Keycloak Version: 23.0 → 26.4.0 @@ -120,8 +134,11 @@ grafana: 11.3.0 # ✅ Wahrscheinlich aktuell - Monitoring: Zipkin-Konfiguration ergänzen **Neue Sections hinzufügen:** + - #### Bekannte Limitierungen + - #### Migration Notes (Juli → Oktober 2025) + - #### Troubleshooting erweitern **Zeitaufwand:** 1 Tag @@ -129,159 +146,182 @@ grafana: 11.3.0 # ✅ Wahrscheinlich aktuell --- #### 3.2 Auth-Module überarbeiten + **Problem:** Vermutlich veraltet - Custom JWT vs. OAuth2 Resource Server Diskrepanz. **Zu klären:** + - Werden `auth-client` und `auth-server` noch verwendet? - Redundanz mit Gateway's OAuth2 Resource Server? - Keycloak-Integration vereinheitlichen **Aktion:** + 1. Abhängigkeiten zu auth-Modulen analysieren 2. Entscheiden: Refactoring oder Deprecation 3. Wenn deprecated: Migration Path dokumentieren -**Zeitaufwand:** 3-5 Tage +**Zeitaufwand:** 3–5 Tage --- #### 3.3 Cache-Module modernisieren + **Problem:** Redis 7 ist aktuell, aber Implementation-Patterns könnten veraltet sein. **Zu prüfen:** + - Multi-Level Caching tatsächlich implementiert? - Cache Statistics vorhanden? - TTL Management korrekt? - Integration mit Spring Cache Abstraction? **Aktion:** + 1. Cache-Tests erweitern 2. Performance-Metriken hinzufügen 3. Cache-Warming Strategy implementieren -**Zeitaufwand:** 2-3 Tage +**Zeitaufwand:** 2–3 Tage --- #### 3.4 Event-Store Performance-Optimierung + **Problem:** Redis-basiert - für Production ggf. nicht optimal. **Zu evaluieren:** + - Ist Redis der richtige Event Store für Production? -- Alternative: PostgreSQL mit Event Store Pattern? +- Alternative: PostgresQL mit Event Store Pattern? - Snapshot-Strategie tatsächlich implementiert? **Aktion:** + 1. Performance-Tests durchführen -2. Event Store Benchmark (Redis vs. PostgreSQL) +2. Event Store Benchmark (Redis vs. PostgresQL) 3. Dokumentation aktualisieren mit Pros/Cons **Zeitaufwand:** 1 Woche --- -### 🔵 Phase 4: LANGFRISTIG (Nächste 2-3 Monate) +### 🔵 Phase 4: LANGFRISTIG (Nächste 2–3 Monate) #### 4.1 Service Mesh evaluieren -**Dokumentiert in "Zukünftige Erweiterungen"** - noch nicht implementiert. + +**Dokumentiert in "Zukünftige Erweiterungen"** – noch nicht implementiert. **Optionen:** + - Istio (komplex, feature-reich) - Linkerd (leichtgewichtig) - Consul Connect (bereits Consul vorhanden!) **Empfehlung:** Start mit Consul Connect - minimaler Overhead. -**Zeitaufwand:** 2-3 Wochen +**Zeitaufwand:** 2–3 Wochen --- #### 4.2 OpenTelemetry statt Zipkin -**Problem:** Zipkin ist veraltet - OpenTelemetry ist der moderne Standard. + +**Problem:** Zipkin ist veraltet – OpenTelemetry ist der moderne Standard. **Migration Path:** + 1. OpenTelemetry Collector aufsetzen 2. Spring Boot Auto-Instrumentation aktivieren 3. Zipkin als Backend behalten (kompatibel!) 4. Schrittweise migrieren -**Zeitaufwand:** 1-2 Wochen +**Zeitaufwand:** 1–2 Wochen --- #### 4.3 Security Hardening + **Aktuelle Gaps:** + - JWT Token Rotation nicht implementiert - Rate Limiting nur dokumentiert, nicht konfiguriert - Audit Logging fehlt - HTTPS/TLS noch nicht erzwungen **Aktion:** + 1. Rate Limiting im Gateway aktivieren 2. Audit Log Framework implementieren -3. TLS für Service-zu-Service Kommunikation +3. TLS für Service-zu-Service-Kommunikation 4. Security Scan mit OWASP Dependency Check -**Zeitaufwand:** 2-3 Wochen +**Zeitaufwand:** 2–3 Wochen --- #### 4.4 Infrastructure as Code (IaC) -**Problem:** Nur Docker Compose - für Production nicht ausreichend. + +**Problem:** Nur Docker Compose – für Production nicht ausreichend. **Zu erstellen:** + - Kubernetes Manifests (aktualisieren - Zeile 393+) -- Helm Charts (aktualisieren - Zeile 420+) +- Helm Charts (aktualisieren – Zeile 420+) - Terraform für Cloud-Ressourcen - CI/CD Pipelines -**Zeitaufwand:** 4-6 Wochen +**Zeitaufwand:** 4–6 Wochen --- -### 📊 Priorisierungs-Matrix +### 📊 Priorisierung-Matrix -| Phase | Aufgabe | Dringlichkeit | Aufwand | Impact | -|-------|---------|---------------|---------|--------| -| 1 | Gateway-Tests | 🔴 Sehr hoch | 4-6h | Hoch | -| 1 | Build-Datei | 🔴 Sehr hoch | 5min | Niedrig | -| 2 | Dependencies | 🟡 Hoch | 1-2d | Mittel | -| 2 | Docker-Images | 🟡 Hoch | 3-4h | Mittel | -| 2 | Monitoring | 🟡 Mittel | 2-3d | Hoch | -| 3 | Dokumentation | 🟢 Mittel | 1d | Mittel | -| 3 | Auth-Module | 🟢 Mittel | 3-5d | Hoch | -| 3 | Cache | 🟢 Niedrig | 2-3d | Mittel | -| 3 | Event-Store | 🟢 Niedrig | 1w | Mittel | -| 4 | Service Mesh | 🔵 Niedrig | 2-3w | Hoch | -| 4 | OpenTelemetry | 🔵 Niedrig | 1-2w | Mittel | -| 4 | Security | 🔵 Mittel | 2-3w | Hoch | -| 4 | IaC | 🔵 Niedrig | 4-6w | Hoch | +| Phase | Aufgabe | Dringlichkeit | Aufwand | Impact | +|-------|---------------|---------------|---------|---------| +| 1 | Gateway-Tests | 🔴 Sehr hoch | 4-6h | Hoch | +| 1 | Build-Datei | 🔴 Sehr hoch | 5min | Niedrig | +| 2 | Dependencies | 🟡 Hoch | 1-2d | Mittel | +| 2 | Docker-Images | 🟡 Hoch | 3-4h | Mittel | +| 2 | Monitoring | 🟡 Mittel | 2-3d | Hoch | +| 3 | Dokumentation | 🟢 Mittel | 1d | Mittel | +| 3 | Auth-Module | 🟢 Mittel | 3-5d | Hoch | +| 3 | Cache | 🟢 Niedrig | 2-3d | Mittel | +| 3 | Event-Store | 🟢 Niedrig | 1w | Mittel | +| 4 | Service Mesh | 🔵 Niedrig | 2-3w | Hoch | +| 4 | OpenTelemetry | 🔵 Niedrig | 1-2w | Mittel | +| 4 | Security | 🔵 Mittel | 2-3w | Hoch | +| 4 | IaC | 🔵 Niedrig | 4-6w | Hoch | --- ### 🎯 Empfohlene Reihenfolge -#### Woche 1-2: +#### Woche 1-2 + 1. Gateway-Tests reparieren 2. Build-Datei bereinigen 3. Dependencies aktualisieren -#### Woche 3-4: +#### Woche 3-4 + 4. Docker-Images aktualisieren 5. Monitoring vervollständigen 6. Dokumentation aktualisieren -#### Woche 5-8: -7. Auth-Module evaluieren/refactoren +#### Woche 5-8 + +7. Auth-Module evaluieren/refactored 8. Cache-Module modernisieren 9. Event-Store Performance-Tests -#### Monat 3-4: +#### Monat 3-4 + 10. Security Hardening 11. OpenTelemetry Migration 12. Service Mesh Evaluation -#### Monat 5-6: +#### Monat 5-6 + 13. Infrastructure as Code 14. Production Readiness Assessment @@ -290,15 +330,18 @@ grafana: 11.3.0 # ✅ Wahrscheinlich aktuell ### 🛠️ Tooling-Empfehlungen **Für Dependency-Management:** + - Renovate Bot oder Dependabot für automatische Updates - `./gradlew dependencyUpdates` Plugin verwenden **Für Security:** + - OWASP Dependency Check - Trivy für Container-Scanning - SonarQube für Code-Qualität **Für Monitoring:** + - Grafana Dashboards aus Community importieren - Prometheus Alertmanager konfigurieren @@ -309,34 +352,38 @@ grafana: 11.3.0 # ✅ Wahrscheinlich aktuell 1. **Jetzt sofort:** Gateway-Tests fixen (blockiert alles andere) 2. **Diese Woche:** Dependencies updaten und testen 3. **Nächste Woche:** Sprint Planning für Phase 2 -4. **Monatlich:** Review des Fortschritts und Reprioritisierung +4. **Monatlich:** Review des Fortschritts und Repriorisierung --- ### ⚠️ Risiken & Abhängigkeiten **Kritische Pfade:** + - Gateway-Tests müssen ZUERST behoben werden - Dependency-Updates können Breaking Changes haben - Auth-Refactoring könnte alle Services betreffen **Externe Abhängigkeiten:** + - Keycloak Breaking Changes bei Major Updates - Spring Boot/Cloud Release Schedule beachten - Kubernetes Cluster für IaC-Phase benötigt --- -**Geschätzter Gesamtaufwand:** 6-8 Wochen (bei 1 Vollzeit-Entwickler) +**Geschätzter Gesamtaufwand:** 6–8 Wochen (bei 1 Vollzeit-Entwickler) **Empfohlener Start:** Sofort mit Phase 1, dann iterativ durch die Phasen - --- -### Dokumentations-Sprachbereinigung (2025-10-22) + +### Documentations-Sprachbereinigung (2025-10-22) + Im Zuge der Vereinheitlichung auf ausschließlich deutschsprachige Dokumentation wurden folgende Dateien entfernt: Gelöschte ADRs (englische Varianten): + - docs/architecture/adr/0000-adr-template.md - docs/architecture/adr/0001-modular-architecture.md - docs/architecture/adr/0002-domain-driven-design.md @@ -348,10 +395,49 @@ Gelöschte ADRs (englische Varianten): - docs/architecture/adr/0008-multiplatform-client-applications.md Gelöschte C4-Diagramme (englische Varianten): + - docs/architecture/c4/01-context.puml - docs/architecture/c4/02-container.puml - docs/architecture/c4/03-component-events-service.puml Hinweis: -- Alle verbleibenden ADRs und C4-Diagramme sind in deutscher Sprache vorhanden (Suffix -de) und verlinkt. + +- Alle verbleibenden ADRs und C4-Diagramme sind in deutscher Sprache vorhanden (Suffix-de) und verlinkt. - Weitere Doku-Dateien in docs/ sind deutsch (Front-Matter/Sprachindizien geprüft). + +--- + +## CI‑Stabilisierung Keycloak (2025‑10‑25) + +Hintergrund: In GitHub Actions startete Keycloak zeitweise nicht zuverlässig. Ziel: Integrationstests stabilisieren, +ohne produktive Architektur zu ändern. + +Änderungen: + +- Integration‑Workflow (`.github/workflows/integration-tests.yml`) auf Matrixbetrieb umgestellt: + - `keycloak_db=postgres` (produktnäher, mit externer Postgres‑DB) + - `keycloak_db=dev-file` (Dateibackend, ohne Postgres; stabiler im CI) +- Robuste Startlogik: + - Aktives Warten auf Postgres (nur in `postgres`‑Variante) + - Keycloak‑Start per `docker run … start-dev` (26.4.2) mit `KC_HEALTH_ENABLED=true` + - Health‑Checks gegen `/`, `/health`, `/q/health`, `/health/ready`, Admin‑Konsole + - Ausführliche Log‑Ausgabe bei Fehlern (Keycloak & Postgres) +- Fail‑fast deaktiviert; beide Matrix‑Jobs laufen unabhängig. + +Nutzung/Operative Hinweise: + +- In PRs beide Matrix‑Runs beachten; bei Flakes in `postgres` sichert `dev-file` die Tests ab. +- Logs bei Fehlschlag: Step „Dump service logs (Keycloak, Postgres)“ am Jobende öffnen. +- Produktiv bleibt Postgres maßgeblich (siehe `docker-compose.yml`). + +ADR‑Konsistenz: + +- ADR‑0006 (Keycloak) bleibt gültig und unverändert; die `dev-file`‑Variante betrifft ausschließlich CI‑Tests. + +Next Steps (optional): + +- Falls `postgres` im CI dauerhaft flakey: Required Checks vorübergehend auf `dev-file` begrenzen. +- Langfristig: Ursachenanalyse für Postgres‑Variante (Runner‑Leistung/Timeouts/Schema‑Setup) und Re‑Enable als Required + Check nach Stabilisierung. + +--- diff --git a/build.gradle.kts b/build.gradle.kts index 0aff5e97..abd54f18 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,6 +15,9 @@ plugins { alias(libs.plugins.composeCompiler) apply false alias(libs.plugins.spring.boot) apply false alias(libs.plugins.spring.dependencyManagement) apply false + + // Dokka plugin applied at root to create multi-module collector tasks + alias(libs.plugins.dokka) } // ################################################################## @@ -108,6 +111,77 @@ subprojects { } } +// ################################################################## +// ### DOKKA (Multi-Module) ### +// ################################################################## + +// Apply Dokka automatically to Kotlin subprojects to enable per-module docs +subprojects { + plugins.withId("org.jetbrains.kotlin.jvm") { + apply(plugin = "org.jetbrains.dokka") + } + plugins.withId("org.jetbrains.kotlin.multiplatform") { + apply(plugin = "org.jetbrains.dokka") + } + + // Minimal sourceLink configuration when running in GitHub Actions + tasks.withType(org.jetbrains.dokka.gradle.DokkaTask::class.java).configureEach { + dokkaSourceSets.configureEach { + val repo = System.getenv("GITHUB_REPOSITORY") + if (!repo.isNullOrBlank()) { + sourceLink { + localDirectory.set(project.file("src")) + remoteUrl.set(java.net.URI.create("https://github.com/$repo/blob/main/" + project.path.trimStart(':').replace(':', '/') + "/src").toURL()) + } + } + // Keep module names short and stable + moduleName.set(project.path.trimStart(':')) + } + } +} + +// Aggregate tasks to build multi-module docs in Markdown (GFM) and HTML +val dokkaGfmAll = tasks.register("dokkaGfmAll") { + group = "documentation" + description = "Builds Dokka GFM for all modules and aggregates outputs under build/dokka/gfm" + // Depend on all dokkaGfm tasks that exist in subprojects + dependsOn(subprojects + .filter { it.plugins.hasPlugin("org.jetbrains.dokka") } + .map { "${it.path}:dokkaGfm" }) + doLast { + val dest = layout.buildDirectory.dir("dokka/gfm").get().asFile + if (dest.exists()) dest.deleteRecursively() + dest.mkdirs() + subprojects.filter { it.plugins.hasPlugin("org.jetbrains.dokka") }.forEach { p -> + val out = p.layout.buildDirectory.dir("dokka/gfm").get().asFile + if (out.exists()) { + out.copyRecursively(File(dest, p.path.trimStart(':').replace(':', '/')), overwrite = true) + } + } + println("[DOKKA] Aggregated GFM into ${dest.absolutePath}") + } +} + +val dokkaHtmlAll = tasks.register("dokkaHtmlAll") { + group = "documentation" + description = "Builds Dokka HTML for all modules and aggregates outputs under build/dokka/html" + dependsOn(subprojects + .filter { it.plugins.hasPlugin("org.jetbrains.dokka") } + .map { "${it.path}:dokkaHtml" }) + doLast { + val dest = layout.buildDirectory.dir("dokka/html").get().asFile + if (dest.exists()) dest.deleteRecursively() + dest.mkdirs() + subprojects.filter { it.plugins.hasPlugin("org.jetbrains.dokka") }.forEach { p -> + val out = p.layout.buildDirectory.dir("dokka/html").get().asFile + if (out.exists()) { + out.copyRecursively(File(dest, p.path.trimStart(':').replace(':', '/')), overwrite = true) + } + } + println("[DOKKA] Aggregated HTML into ${dest.absolutePath}") + } +} + // ################################################################## // ### DOKU-AGGREGATOR ### // ################################################################## diff --git a/client/README.md b/client/README.md deleted file mode 100644 index 71dcdd1d..00000000 --- a/client/README.md +++ /dev/null @@ -1 +0,0 @@ -# Client\n\nMinimal placeholder README. Client apps live under ./clients/. See docs/index.md for docs. diff --git a/clients/shared/build.gradle.kts b/clients/shared/build.gradle.kts index 0f647951..bc7a9e6d 100644 --- a/clients/shared/build.gradle.kts +++ b/clients/shared/build.gradle.kts @@ -3,99 +3,113 @@ import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile /** * Shared Module: Gemeinsame Libraries und Utilities für alle Client-Features * KEINE EXECUTABLE - ist eine Library für andere Module */ plugins { - alias(libs.plugins.kotlinMultiplatform) - alias(libs.plugins.kotlinSerialization) - alias(libs.plugins.composeMultiplatform) - alias(libs.plugins.composeCompiler) + alias(libs.plugins.kotlinMultiplatform) + alias(libs.plugins.kotlinSerialization) + alias(libs.plugins.composeMultiplatform) + alias(libs.plugins.composeCompiler) } kotlin { - val enableWasm = providers.gradleProperty("enableWasm").orNull == "true" + val enableWasm = providers.gradleProperty("enableWasm").orNull == "true" - jvmToolchain(21) + jvmToolchain(21) - // JVM Target für Desktop - jvm() + // JVM Target für Desktop + jvm() + + // JavaScript Target für Web + js { + browser { + testTask { + enabled = false + } + } + binaries.executable() + // ... + } + + // WASM, nur wenn explizit aktiviert + if (enableWasm) { + @OptIn(ExperimentalWasmDsl::class) + wasmJs { browser() } + } + + sourceSets { + commonMain.dependencies { + + api(projects.core.coreUtils) + api(projects.core.coreDomain) + + // Kotlinx core dependencies (coroutines, serialization, datetime) + implementation(libs.bundles.kotlinx.core) + + // HTTP Client + 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) - // JavaScript Target für Web - js(IR) { - browser() } - // WASM, nur wenn explizit aktiviert + commonTest.dependencies { + implementation(libs.kotlin.test) + implementation(libs.kotlinx.coroutines.test) + } + + jvmMain.dependencies { + implementation(libs.ktor.client.cio) + + // Compose für shared UI components + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material3) + } + + jsMain.dependencies { + implementation(libs.ktor.client.js) + + // Compose für shared UI components + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material3) + } + + // WASM SourceSet, nur wenn aktiviert if (enableWasm) { - @OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class) - wasmJs { browser() } - } - - sourceSets { - commonMain.dependencies { - - api(projects.core.coreUtils) - api(projects.core.coreDomain) - - // Kotlinx core dependencies (coroutines, serialization, datetime) - implementation(libs.bundles.kotlinx.core) - - // HTTP Client - 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) - - } - - commonTest.dependencies { - implementation(libs.kotlin.test) - implementation(libs.kotlinx.coroutines.test) - } - - jvmMain.dependencies { - implementation(libs.ktor.client.cio) - - // Compose für shared UI components - implementation(compose.runtime) - implementation(compose.foundation) - implementation(compose.material3) - } - - jsMain.dependencies { - implementation(libs.ktor.client.js) - - // Compose für shared UI components - implementation(compose.runtime) - implementation(compose.foundation) - implementation(compose.material3) - } - - // WASM SourceSet, nur wenn aktiviert - if (enableWasm) { - val wasmJsMain = getByName("wasmJsMain") - wasmJsMain.dependencies { - implementation(libs.ktor.client.js) // WASM verwendet JS-Client [cite: 7] - - // ✅ HINZUFÜGEN: Compose für shared UI components für WASM - implementation(compose.runtime) - implementation(compose.foundation) - implementation(compose.material3) - } - } + val wasmJsMain = getByName("wasmJsMain") + wasmJsMain.dependencies { + implementation(libs.ktor.client.js) // WASM verwendet JS-Client [cite: 7] + + // ✅ HINZUFÜGEN: Compose für shared UI components für WASM + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material3) + } } + } } // KMP Compile-Optionen -tasks.withType { - compilerOptions { - jvmTarget.set(JvmTarget.JVM_21) - freeCompilerArgs.addAll( - "-opt-in=kotlin.RequiresOptIn" - ) - } +tasks.withType { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_21) + freeCompilerArgs.addAll( + "-opt-in=kotlin.RequiresOptIn" + ) + } +} + +tasks.withType().configureEach { + compilerOptions { + target = "es2015" + } } diff --git a/config/README.md b/config/README.md index b9cbcf54..274f77f2 100644 --- a/config/README.md +++ b/config/README.md @@ -8,7 +8,8 @@ Das **zentrale Konfigurationssystem** eliminiert Redundanzen über das gesamte Meldestelle-Projekt und stellt sicher, dass alle Konfigurationswerte aus einer **einzigen Quelle der Wahrheit** stammen. -### Vor der Zentralisierung (Problem): +### Vor der Zentralisierung (Problem) + ``` Port 8082 war in 38+ Dateien dupliziert: ├── gradle.properties @@ -19,7 +20,8 @@ Port 8082 war in 38+ Dateien dupliziert: └── ... 33 weitere Dateien! ``` -### Nach der Zentralisierung (Lösung): +### Nach der Zentralisierung (Lösung) + ``` Port 8082 einmalig in config/central.toml definiert: ├── config/central.toml [SINGLE SOURCE OF TRUTH] @@ -110,6 +112,7 @@ grafana = 3000 ``` **Synchronisiert folgende Dateien:** + - `gradle.properties` - Service-Port-Eigenschaften - `docker-compose*.yml` - Port-Mappings und Environment-Variablen - `dockerfiles/*/Dockerfile` - EXPOSE-Statements @@ -134,6 +137,7 @@ clients = "dev" # Client Applications ``` **Synchronisiert folgende Dateien:** + - Alle `dockerfiles/*/Dockerfile` - `SPRING_PROFILES_ACTIVE` Build-Args - `docker-compose*.yml` - Spring-Profile Environment-Variablen - `docker/build-args/*.env` - Build-Argument-Dateien @@ -213,6 +217,7 @@ vim config/central.toml ### Häufige Probleme #### Problem: Synchronisation schlägt fehl + ```bash # Lösung: Validierung prüfen ./scripts/config-sync.sh validate @@ -222,6 +227,7 @@ vim config/central.toml ``` #### Problem: Inkonsistente Konfiguration + ```bash # Lösung: Status prüfen und re-synchronisieren ./scripts/config-sync.sh status @@ -229,6 +235,7 @@ vim config/central.toml ``` #### Problem: Backup wiederherstellen + ```bash # Backups anzeigen ls -la *.bak.* diff --git a/config/ssl/README-de.md b/config/ssl/README-de.md index ef89d745..f2eb3f27 100644 --- a/config/ssl/README-de.md +++ b/config/ssl/README-de.md @@ -18,36 +18,48 @@ config/ssl/ ## Zertifikat-Anforderungen ### 1. PostgreSQL SSL-Zertifikate + Platzieren Sie die folgenden Dateien in `config/ssl/postgres/`: + - `server.crt` - Server-Zertifikat - `server.key` - Privater Server-Schlüssel - `ca.crt` - Certificate Authority-Zertifikat ### 2. Redis TLS-Zertifikate + Platzieren Sie die folgenden Dateien in `config/ssl/redis/`: + - `redis.crt` - Redis Server-Zertifikat - `redis.key` - Privater Redis Server-Schlüssel - `ca.crt` - Certificate Authority-Zertifikat - `redis.dh` - Diffie-Hellman Parameter ### 3. Keycloak HTTPS-Zertifikate + Platzieren Sie die folgenden Dateien in `config/ssl/keycloak/`: + - `server.crt.pem` - Server-Zertifikat im PEM-Format - `server.key.pem` - Privater Server-Schlüssel im PEM-Format ### 4. Prometheus HTTPS-Zertifikate + Platzieren Sie die folgenden Dateien in `config/ssl/prometheus/`: + - `prometheus.crt` - Prometheus Server-Zertifikat - `prometheus.key` - Privater Prometheus Server-Schlüssel - `web.yml` - Prometheus Web-Konfigurationsdatei ### 5. Grafana HTTPS-Zertifikate + Platzieren Sie die folgenden Dateien in `config/ssl/grafana/`: + - `server.crt` - Grafana Server-Zertifikat - `server.key` - Privater Grafana Server-Schlüssel ### 6. Nginx SSL-Zertifikate + Platzieren Sie die folgenden Dateien in `config/ssl/nginx/`: + - `server.crt` - Haupt-SSL-Zertifikat - `server.key` - Privater Haupt-SSL-Schlüssel - `dhparam.pem` - Diffie-Hellman Parameter @@ -57,6 +69,7 @@ Platzieren Sie die folgenden Dateien in `config/ssl/nginx/`: ⚠️ **Warnung**: Verwenden Sie selbstsignierte Zertifikate nur für Entwicklung und Tests. Nutzen Sie ordnungsgemäß von einer CA signierte Zertifikate in der Produktion. ### CA-Zertifikat generieren + ```bash # CA privaten Schlüssel erstellen openssl genrsa -out ca.key 4096 @@ -67,6 +80,7 @@ openssl req -new -x509 -days 365 -key ca.key -out ca.crt \ ``` ### Server-Zertifikate generieren + ```bash # Für jeden Service privaten Schlüssel und Certificate Signing Request generieren openssl genrsa -out server.key 2048 @@ -82,6 +96,7 @@ rm server.csr ``` ### Diffie-Hellman Parameter generieren + ```bash openssl dhparam -out dhparam.pem 2048 ``` @@ -89,6 +104,7 @@ openssl dhparam -out dhparam.pem 2048 ## Produktions-Zertifikat Setup ### Option 1: Let's Encrypt (Empfohlen) + Verwenden Sie Certbot, um kostenlose SSL-Zertifikate zu erhalten: ```bash @@ -104,13 +120,16 @@ sudo cp /etc/letsencrypt/live/ihre-domain.com/privkey.pem config/ssl/nginx/serve ``` ### Option 2: Kommerzielle CA + 1. Certificate Signing Requests (CSRs) generieren 2. CSRs an Ihre Certificate Authority übermitteln 3. Signierte Zertifikate herunterladen 4. Zertifikate in entsprechende Verzeichnisse platzieren ### Option 3: Interne CA + Bei Verwendung einer internen Certificate Authority: + 1. CSRs für jeden Service generieren 2. Zertifikate mit Ihrer internen CA signieren 3. CA-Zertifikat an alle Clients verteilen @@ -147,6 +166,7 @@ volumes: ## Zertifikat-Erneuerung ### Automatisierte Erneuerung (Let's Encrypt) + Richten Sie einen Cron-Job für automatische Erneuerung ein: ```bash @@ -155,9 +175,11 @@ Richten Sie einen Cron-Job für automatische Erneuerung ein: ``` ### Manuelle Erneuerung + 1. Neue Zertifikate generieren 2. Alte Zertifikate in SSL-Verzeichnissen ersetzen 3. Betroffene Services neu starten: + ```bash docker-compose -f docker-compose.prod.yml restart nginx keycloak grafana prometheus ``` @@ -177,6 +199,7 @@ Richten Sie einen Cron-Job für automatische Erneuerung ein: ### Häufige Probleme 1. **Berechtigung verweigert** + ```bash # Dateiberechtigungen korrigieren sudo chown -R $USER:$USER config/ssl/ @@ -185,6 +208,7 @@ Richten Sie einen Cron-Job für automatische Erneuerung ein: ``` 2. **Zertifikat-Verifizierung fehlgeschlagen** + ```bash # Zertifikat verifizieren openssl x509 -in config/ssl/nginx/server.crt -text -noout @@ -217,13 +241,16 @@ openssl x509 -in config/ssl/nginx/server.crt -text -noout ## Monitoring und Wartung ### Zertifikat-Überwachung + Implementieren Sie Überwachung für: + - Zertifikat-Ablaufdaten - Zertifikat-Gültigkeit - SSL/TLS-Handshake-Erfolg - Cipher-Suite-Verwendung ### Wartungsaufgaben + - Regelmäßige Überprüfung der Zertifikat-Gültigkeit - Aktualisierung der Cipher-Suites - Überwachung der Sicherheitsupdates diff --git a/core/README.md b/core/README.md index 7e4dfbfe..088392dc 100644 --- a/core/README.md +++ b/core/README.md @@ -1 +1 @@ -# Core\n\nMinimal placeholder README. See docs/index.md for project documentation. +# Core\n\nMinimal placeholder README. See docs/index.md for project documentation diff --git a/docker-compose.clients.yml b/docker-compose.clients.yml index b197ec64..bf94c81d 100644 --- a/docker-compose.clients.yml +++ b/docker-compose.clients.yml @@ -1,191 +1,49 @@ # =================================================================== # Docker Compose - Client Applications -# Meldestelle Project - Frontend Components -# =================================================================== -# Usage Scenarios: -# -# 1. STANDALONE CLIENT DEPLOYMENT (Fixed): -# docker-compose -f docker-compose.clients.yml up -d -# - Clients run independently without api-gateway dependency -# - Set GATEWAY_HOST environment variable to external API Gateway -# - Example: GATEWAY_HOST=localhost docker-compose -f docker-compose.clients.yml up -d -# -# 2. MULTI-FILE WITH INFRASTRUCTURE: -# docker-compose -f docker-compose.yml -f docker-compose.clients.yml up -d -# - Infrastructure services (api-gateway, postgres, etc.) start first -# - Clients connect to api-gateway in same network -# -# 3. COMPLETE SYSTEM: -# docker-compose -f docker-compose.yml -f docker-compose.services.yml -f docker-compose.clients.yml up -d -# - Full stack: Infrastructure + Backend Services + Frontend Clients +# Generated from docker/versions.toml +# Environment: development +# Generated: 2025-10-25 23:26:24 UTC # =================================================================== services: # =================================================================== - # Web Application (Kotlin/JS + Nginx) + # Web Application (Compose for Web) # =================================================================== web-app: build: context: . dockerfile: dockerfiles/clients/web-app/Dockerfile args: - - BUILD_DATE=${BUILD_DATE:-$(date -u +"%Y-%m-%dT%H:%M:%SZ")} - - VERSION=${APP_VERSION:-1.0.0} + # Global build arguments (centralized DOCKER_* variables) + GRADLE_VERSION: ${DOCKER_GRADLE_VERSION} + JAVA_VERSION: ${DOCKER_JAVA_VERSION} + BUILD_DATE: ${BUILD_DATE} + VERSION: ${DOCKER_APP_VERSION} + # Client-specific arguments (centralized DOCKER_* variables) + NODE_VERSION: ${DOCKER_NODE_VERSION} + NGINX_VERSION: ${DOCKER_NGINX_VERSION} + # Application-specific arguments + CLIENT_PATH: client + CLIENT_MODULE: client + CLIENT_NAME: meldestelle-web-app container_name: meldestelle-web-app environment: - NODE_ENV: ${NODE_ENV:-production} + NODE_ENV: ${NODE_ENV:-dev} + API_BASE_URL: http://api-gateway:${GATEWAY_PORT:-8081} + WS_URL: ws://api-gateway:${GATEWAY_PORT:-8081}/ws APP_TITLE: ${APP_NAME:-Meldestelle} APP_VERSION: ${APP_VERSION:-1.0.0} - # Nginx Worker Processes (für Performance) - NGINX_WORKER_PROCESSES: ${NGINX_WORKER_PROCESSES:-auto} ports: - "4000:4000" networks: - meldestelle-network - # depends_on removed for standalone client deployment - # When using multi-file setup, api-gateway dependency is handled externally healthcheck: - test: [ "CMD", "curl", "--fail", "http://localhost:4000/health" ] + test: ["CMD", "curl", "--fail", "http://localhost:4000/health"] interval: 30s - timeout: 10s + timeout: 5s retries: 3 - start_period: 60s + start_period: 40s restart: unless-stopped - labels: - - "traefik.enable=true" - - "traefik.http.routers.web-app.rule=Host(`localhost`) && PathPrefix(`/`)" - - "traefik.http.services.web-app.loadbalancer.server.port=4000" - - # =================================================================== - # Desktop Application (Kotlin Desktop + VNC) - # =================================================================== - # desktop-app: - # build: - # context: . - # dockerfile: dockerfiles/clients/desktop-app/Dockerfile - # container_name: meldestelle-desktop-app - # environment: - # # API Configuration - fallback to external gateway if not in same compose network - # API_BASE_URL: http://${GATEWAY_HOST:-api-gateway}:${GATEWAY_PORT:-8081} - # # VNC Configuration - # DISPLAY: ":99" - # VNC_PORT: "5901" - # NOVNC_PORT: "6080" - # # App Information - # APP_TITLE: ${APP_NAME:-Meldestelle} - # APP_VERSION: ${APP_VERSION:-1.0.0} - # ports: - # - "6080:6080" # Web-based VNC (noVNC) - # - "5901:5901" # VNC direct access - # networks: - # - meldestelle-network - # # depends_on removed for standalone client deployment - # # When using multi-file setup, api-gateway dependency is handled externally - # healthcheck: - # test: [ "CMD", "/opt/health-check.sh" ] - # interval: 30s - # timeout: 10s - # retries: 3 - # start_period: 60s - # restart: unless-stopped - # labels: - # - "traefik.enable=true" - # - "traefik.http.routers.desktop-app.rule=Host(`localhost`) && PathPrefix(`/desktop`)" - # - "traefik.http.services.desktop-app.loadbalancer.server.port=6080" - - # =================================================================== - # Auth Server (Custom Keycloak Extension) - # =================================================================== -# auth-server: -# build: -# context: . -# dockerfile: dockerfiles/infrastructure/auth-server/Dockerfile -# args: -# # Global build arguments (from docker/build-args/global.env) -# GRADLE_VERSION: ${DOCKER_GRADLE_VERSION:-9.0.0} -# JAVA_VERSION: ${DOCKER_JAVA_VERSION:-21} -# BUILD_DATE: ${BUILD_DATE} -# VERSION: ${DOCKER_APP_VERSION:-1.0.0} -# # Infrastructure-specific arguments (from docker/build-args/infrastructure.env) -# SPRING_PROFILES_ACTIVE: ${DOCKER_SPRING_PROFILES_DEFAULT:-default} -# container_name: meldestelle-auth-server -# environment: -# SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-dev} -# SERVER_PORT: ${AUTH_SERVICE_PORT:-8087} -# KEYCLOAK_SERVER_URL: http://keycloak:8080 -# KEYCLOAK_REALM: meldestelle -# KEYCLOAK_CLIENT_ID: meldestelle-auth-service -# KEYCLOAK_CLIENT_SECRET: ${KEYCLOAK_CLIENT_SECRET:-auth-service-secret} -# DB_HOST: postgres -# DB_PORT: 5432 -# DB_NAME: ${POSTGRES_DB:-meldestelle} -# DB_USER: ${POSTGRES_USER:-meldestelle} -# DB_PASSWORD: ${POSTGRES_PASSWORD:-meldestelle} -# JWT_SECRET: ${JWT_SECRET:-meldestelle-jwt-secret-key-for-development-change-in-production} -# JWT_ISSUER: ${JWT_ISSUER:-meldestelle-api} -# JWT_AUDIENCE: ${JWT_AUDIENCE:-meldestelle-clients} -# ports: -# - "${AUTH_SERVICE_PORT:-8087}:${AUTH_SERVICE_PORT:-8087}" -# networks: -# - meldestelle-network -# healthcheck: -# test: [ "CMD", "curl", "--fail", "http://localhost:${AUTH_SERVICE_PORT:-8087}/actuator/health" ] -# interval: 30s -# timeout: 10s -# retries: 3 -# start_period: 60s -# restart: unless-stopped - - # =================================================================== - # Monitoring Server (Custom Grafana Extensions) - # =================================================================== -# monitoring-server: -# build: -# context: . -# dockerfile: dockerfiles/infrastructure/monitoring-server/Dockerfile -# args: -# # Global build arguments (from docker/build-args/global.env) -# GRADLE_VERSION: ${DOCKER_GRADLE_VERSION:-9.0.0} -# JAVA_VERSION: ${DOCKER_JAVA_VERSION:-21} -# BUILD_DATE: ${BUILD_DATE} -# VERSION: ${DOCKER_APP_VERSION:-1.0.0} -# # Infrastructure-specific arguments (from docker/build-args/infrastructure.env) -# SPRING_PROFILES_ACTIVE: ${DOCKER_SPRING_PROFILES_DEFAULT:-default} -# container_name: meldestelle-monitoring-server -# environment: -# SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-dev} -# SERVER_PORT: 8088 -# GRAFANA_URL: http://grafana:3000 -# PROMETHEUS_URL: http://prometheus:9090 -# GRAFANA_ADMIN_USER: ${GF_SECURITY_ADMIN_USER:-admin} -# GRAFANA_ADMIN_PASSWORD: ${GF_SECURITY_ADMIN_PASSWORD:-admin} -# METRICS_AUTH_USERNAME: ${METRICS_AUTH_USERNAME:-admin} -# METRICS_AUTH_PASSWORD: ${METRICS_AUTH_PASSWORD:-metrics} -# ports: -# - "8088:8088" -# networks: -# - meldestelle-network -# healthcheck: -# test: ["CMD", "curl", "--fail", "http://localhost:8088/actuator/health"] -# interval: 30s -# timeout: 10s -# retries: 3 -# start_period: 60s -# restart: unless-stopped -# volumes: -# - monitoring-data:/app/data -# - ./docker/monitoring:/app/config:ro - -# =================================================================== -# Volumes für Client-spezifische Daten -# =================================================================== -volumes: - monitoring-data: - driver: local - desktop-app-gradle-cache: - driver: local - web-app-gradle-cache: - driver: local # =================================================================== # Networks (shared network from main compose file) diff --git a/docker-compose.clients.yml.optimized b/docker-compose.clients.yml.optimized index f6a67855..7f085a4e 100644 --- a/docker-compose.clients.yml.optimized +++ b/docker-compose.clients.yml.optimized @@ -36,9 +36,18 @@ services: context: . dockerfile: dockerfiles/clients/web-app/Dockerfile args: - - BUILD_DATE=${BUILD_DATE:-$(date -u +"%Y-%m-%dT%H:%M:%SZ")} - - VERSION=${APP_VERSION:-1.0.0} - - NODE_ENV=${NODE_ENV:-production} + # Global build arguments (centralized DOCKER_* variables) + GRADLE_VERSION: ${DOCKER_GRADLE_VERSION} + JAVA_VERSION: ${DOCKER_JAVA_VERSION} + BUILD_DATE: ${BUILD_DATE} + VERSION: ${DOCKER_APP_VERSION} + # Client-specific arguments (centralized DOCKER_* variables) + NODE_VERSION: ${DOCKER_NODE_VERSION} + NGINX_VERSION: ${DOCKER_NGINX_VERSION} + # Application-specific arguments + CLIENT_PATH: client + CLIENT_MODULE: client + CLIENT_NAME: meldestelle-web-app container_name: meldestelle-web-app environment: NODE_ENV: ${NODE_ENV:-production} @@ -155,7 +164,7 @@ services: dockerfile: dockerfiles/infrastructure/auth-server/Dockerfile args: # Global build arguments - GRADLE_VERSION: ${DOCKER_GRADLE_VERSION:-9.0.0} + GRADLE_VERSION: ${DOCKER_GRADLE_VERSION} JAVA_VERSION: ${DOCKER_JAVA_VERSION:-21} BUILD_DATE: ${BUILD_DATE:-unknown} VERSION: ${DOCKER_APP_VERSION:-1.0.0} @@ -225,7 +234,7 @@ services: dockerfile: dockerfiles/infrastructure/monitoring-server/Dockerfile args: # Global build arguments - GRADLE_VERSION: ${DOCKER_GRADLE_VERSION:-9.0.0} + GRADLE_VERSION: ${DOCKER_GRADLE_VERSION} JAVA_VERSION: ${DOCKER_JAVA_VERSION:-21} BUILD_DATE: ${BUILD_DATE:-unknown} VERSION: ${DOCKER_APP_VERSION:-1.0.0} diff --git a/docker-compose.services.yml b/docker-compose.services.yml index cd276f27..f74cc6ff 100644 --- a/docker-compose.services.yml +++ b/docker-compose.services.yml @@ -1,243 +1,74 @@ # =================================================================== -# Docker Compose - Microservices -# Meldestelle Project - Application Services -# =================================================================== -# Usage: -# Vollständiges System: docker-compose -f docker-compose.yml -f docker-compose.services.yml up -d +# Docker Compose - Application Services +# Generated from docker/versions.toml +# Environment: development +# Generated: 2025-10-25 23:26:24 UTC # =================================================================== services: - # =================================================================== - # Ping Service (Health Check & Test Service) - # =================================================================== ping-service: build: context: . dockerfile: dockerfiles/services/ping-service/Dockerfile args: - # Global build arguments (from docker/build-args/global.env) - GRADLE_VERSION: ${DOCKER_GRADLE_VERSION:-9.0.0} - JAVA_VERSION: ${DOCKER_JAVA_VERSION:-21} - BUILD_DATE: ${BUILD_DATE:-unknown} - VERSION: ${DOCKER_APP_VERSION:-1.0.0} - # Service-specific arguments (from docker/build-args/services.env) - SPRING_PROFILES_ACTIVE: ${DOCKER_SPRING_PROFILES_DOCKER:-docker} - # Enable BuildKit for better caching and performance - # platforms: - # - linux/amd64 + # Global build arguments (centralized DOCKER_* variables) + GRADLE_VERSION: ${DOCKER_GRADLE_VERSION} + JAVA_VERSION: ${DOCKER_JAVA_VERSION} + BUILD_DATE: ${BUILD_DATE} + VERSION: ${DOCKER_APP_VERSION} + # Service-specific arguments (centralized DOCKER_* variables) + SPRING_PROFILES_ACTIVE: ${DOCKER_SPRING_PROFILES_DOCKER} container_name: meldestelle-ping-service - volumes: - # Mount Gradle cache for better build performance - - ping-service-gradle-cache:/home/gradle/.gradle environment: - SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-docker} + SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-dev} SERVER_PORT: ${PING_SERVICE_PORT:-8082} - CONSUL_HOST: consul - CONSUL_PORT: ${CONSUL_PORT:-8500} - CONSUL_ENABLED: ${CONSUL_ENABLED:-true} - SPRING_CLOUD_CONSUL_DISCOVERY_ENABLED: ${CONSUL_ENABLED:-true} - DB_HOST: postgres - DB_PORT: 5432 - DB_NAME: ${POSTGRES_DB:-meldestelle} - DB_USER: ${POSTGRES_USER:-meldestelle} - DB_PASSWORD: ${POSTGRES_PASSWORD:-meldestelle} - REDIS_EVENT_STORE_HOST: redis - REDIS_EVENT_STORE_PORT: 6379 - REDIS_EVENT_STORE_PASSWORD: ${REDIS_PASSWORD:-} + DEBUG: ${DEBUG:-true} + LOGGING_LEVEL_ROOT: ${LOGGING_LEVEL_ROOT:-DEBUG} + JVM_DEBUG_PORT: 5005 ports: - "${PING_SERVICE_PORT:-8082}:8082" + - "5005:5005" # Debug-Port networks: - meldestelle-network healthcheck: - test: [ "CMD", "curl", "--fail", "http://localhost:8082/actuator/health/readiness" ] - interval: 15s + test: ["CMD", "curl", "--fail", "http://localhost:8082/actuator/health/readiness"] + interval: 30s timeout: 5s retries: 3 - start_period: 30s + start_period: 40s restart: unless-stopped - # =================================================================== - # Members Service - # =================================================================== - # members-service: - # build: - # context: . - # dockerfile: dockerfiles/services/members-service/Dockerfile - # container_name: meldestelle-members-service - # environment: - # SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-dev} - # SERVER_PORT: ${MEMBERS_SERVICE_PORT:-8083} - # CONSUL_HOST: consul - # CONSUL_PORT: ${CONSUL_PORT:-8500} - # CONSUL_ENABLED: ${CONSUL_ENABLED:-true} - # DB_HOST: postgres - # DB_PORT: 5432 - # DB_NAME: ${POSTGRES_DB:-meldestelle} - # DB_USER: ${POSTGRES_USER:-meldestelle} - # DB_PASSWORD: ${POSTGRES_PASSWORD:-meldestelle} - # REDIS_EVENT_STORE_HOST: redis - # REDIS_EVENT_STORE_PORT: 6379 - # REDIS_EVENT_STORE_PASSWORD: ${REDIS_PASSWORD:-} - # KAFKA_BOOTSTRAP_SERVERS: kafka:29092 - # ports: - # - "${MEMBERS_SERVICE_PORT:-8083}:${MEMBERS_SERVICE_PORT:-8083}" - # depends_on: - # consul: - # condition: service_healthy - # postgres: - # condition: service_healthy - # redis: - # condition: service_healthy - # kafka: - # condition: service_healthy - # networks: - # - meldestelle-network - # healthcheck: - # test: ["CMD", "curl", "--fail", "http://localhost:${MEMBERS_SERVICE_PORT:-8083}/actuator/health"] - # interval: 15s - # timeout: 5s - # retries: 3 - # start_period: 30s - # restart: unless-stopped - - # =================================================================== - # Horses Service - # =================================================================== - # horses-service: - # build: - # context: . - # dockerfile: dockerfiles/services/horses-service/Dockerfile - # container_name: meldestelle-horses-service - # environment: - # SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-dev} - # SERVER_PORT: ${HORSES_SERVICE_PORT:-8084} - # CONSUL_HOST: consul - # CONSUL_PORT: ${CONSUL_PORT:-8500} - # CONSUL_ENABLED: ${CONSUL_ENABLED:-true} - # DB_HOST: postgres - # DB_PORT: 5432 - # DB_NAME: ${POSTGRES_DB:-meldestelle} - # DB_USER: ${POSTGRES_USER:-meldestelle} - # DB_PASSWORD: ${POSTGRES_PASSWORD:-meldestelle} - # REDIS_EVENT_STORE_HOST: redis - # REDIS_EVENT_STORE_PORT: 6379 - # REDIS_EVENT_STORE_PASSWORD: ${REDIS_PASSWORD:-} - # KAFKA_BOOTSTRAP_SERVERS: kafka:29092 - # ports: - # - "${HORSES_SERVICE_PORT:-8084}:${HORSES_SERVICE_PORT:-8084}" - # depends_on: - # consul: - # condition: service_healthy - # postgres: - # condition: service_healthy - # redis: - # condition: service_healthy - # kafka: - # condition: service_healthy - # networks: - # - meldestelle-network - # healthcheck: - # test: ["CMD", "curl", "--fail", "http://localhost:${HORSES_SERVICE_PORT:-8084}/actuator/health"] - # interval: 15s - # timeout: 5s - # retries: 3 - # start_period: 30s - # restart: unless-stopped - - # =================================================================== - # Events Service - # =================================================================== - # events-service: - # build: - # context: . - # dockerfile: dockerfiles/services/events-service/Dockerfile - # container_name: meldestelle-events-service - # environment: - # SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-dev} - # SERVER_PORT: ${EVENTS_SERVICE_PORT:-8085} - # CONSUL_HOST: consul - # CONSUL_PORT: ${CONSUL_PORT:-8500} - # CONSUL_ENABLED: ${CONSUL_ENABLED:-true} - # DB_HOST: postgres - # DB_PORT: 5432 - # DB_NAME: ${POSTGRES_DB:-meldestelle} - # DB_USER: ${POSTGRES_USER:-meldestelle} - # DB_PASSWORD: ${POSTGRES_PASSWORD:-meldestelle} - # REDIS_EVENT_STORE_HOST: redis - # REDIS_EVENT_STORE_PORT: 6379 - # REDIS_EVENT_STORE_PASSWORD: ${REDIS_PASSWORD:-} - # KAFKA_BOOTSTRAP_SERVERS: kafka:29092 - # ports: - # - "${EVENTS_SERVICE_PORT:-8085}:${EVENTS_SERVICE_PORT:-8085}" - # depends_on: - # consul: - # condition: service_healthy - # postgres: - # condition: service_healthy - # redis: - # condition: service_healthy - # kafka: - # condition: service_healthy - # networks: - # - meldestelle-network - # healthcheck: - # test: ["CMD", "curl", "--fail", "http://localhost:${EVENTS_SERVICE_PORT:-8085}/actuator/health"] - # interval: 15s - # timeout: 5s - # retries: 3 - # start_period: 30s - # restart: unless-stopped - - # =================================================================== - # Masterdata Service - # =================================================================== -# masterdata-service: -# build: -# context: . -# dockerfile: dockerfiles/services/masterdata-service/Dockerfile -# container_name: meldestelle-masterdata-service -# environment: -# SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-dev} -# SERVER_PORT: ${MASTERDATA_SERVICE_PORT:-8086} -# CONSUL_HOST: consul -# CONSUL_PORT: ${CONSUL_PORT:-8500} -# CONSUL_ENABLED: ${CONSUL_ENABLED:-true} -# DB_HOST: postgres -# DB_PORT: 5432 -# DB_NAME: ${POSTGRES_DB:-meldestelle} -# DB_USER: ${POSTGRES_USER:-meldestelle} -# DB_PASSWORD: ${POSTGRES_PASSWORD:-meldestelle} -# REDIS_EVENT_STORE_HOST: redis -# REDIS_EVENT_STORE_PORT: 6379 -# REDIS_EVENT_STORE_PASSWORD: ${REDIS_PASSWORD:-} -# KAFKA_BOOTSTRAP_SERVERS: kafka:29092 -# ports: -# - "${MASTERDATA_SERVICE_PORT:-8086}:${MASTERDATA_SERVICE_PORT:-8086}" -# depends_on: -# consul: -# condition: service_healthy -# postgres: -# condition: service_healthy -# redis: -# condition: service_healthy -# kafka: -# condition: service_healthy -# networks: -# - meldestelle-network -# healthcheck: -# test: ["CMD", "curl", "--fail", "http://localhost:${MASTERDATA_SERVICE_PORT:-8086}/actuator/health"] -# interval: 15s -# timeout: 5s -# retries: 3 -# start_period: 30s -# restart: unless-stopped - -# =================================================================== -# Volumes -# =================================================================== -volumes: - ping-service-gradle-cache: - driver: local + api-gateway: + build: + context: . + dockerfile: dockerfiles/infrastructure/gateway/Dockerfile + args: + # Global build arguments (centralized DOCKER_* variables) + GRADLE_VERSION: ${DOCKER_GRADLE_VERSION} + JAVA_VERSION: ${DOCKER_JAVA_VERSION} + BUILD_DATE: ${BUILD_DATE} + VERSION: ${DOCKER_APP_VERSION} + # Infrastructure-specific arguments (centralized DOCKER_* variables) + SPRING_PROFILES_ACTIVE: ${DOCKER_SPRING_PROFILES_DEFAULT} + container_name: meldestelle-api-gateway + environment: + SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-dev} + SERVER_PORT: ${API_GATEWAY_PORT:-8081} + DEBUG: ${DEBUG:-true} + LOGGING_LEVEL_ROOT: ${LOGGING_LEVEL_ROOT:-DEBUG} + JVM_DEBUG_PORT: 5005 + ports: + - "${API_GATEWAY_PORT:-8081}:8081" + - "5005:5005" # Debug-Port + networks: + - meldestelle-network + healthcheck: + test: ["CMD", "curl", "--fail", "http://localhost:8081/actuator/health/readiness"] + interval: 30s + timeout: 5s + retries: 3 + start_period: 40s + restart: unless-stopped # =================================================================== # Networks (shared network from main compose file) diff --git a/docker-compose.services.yml.optimized b/docker-compose.services.yml.optimized index 8c0844f1..98082bf2 100644 --- a/docker-compose.services.yml.optimized +++ b/docker-compose.services.yml.optimized @@ -25,7 +25,7 @@ services: dockerfile: dockerfiles/services/ping-service/Dockerfile args: # Global build arguments - GRADLE_VERSION: ${DOCKER_GRADLE_VERSION:-9.0.0} + GRADLE_VERSION: ${DOCKER_GRADLE_VERSION} JAVA_VERSION: ${DOCKER_JAVA_VERSION:-21} BUILD_DATE: ${BUILD_DATE:-unknown} VERSION: ${DOCKER_APP_VERSION:-1.0.0} @@ -98,7 +98,7 @@ services: context: . dockerfile: dockerfiles/services/members-service/Dockerfile args: - GRADLE_VERSION: ${DOCKER_GRADLE_VERSION:-9.0.0} + GRADLE_VERSION: ${DOCKER_GRADLE_VERSION} JAVA_VERSION: ${DOCKER_JAVA_VERSION:-21} BUILD_DATE: ${BUILD_DATE:-unknown} VERSION: ${DOCKER_APP_VERSION:-1.0.0} @@ -174,7 +174,7 @@ services: context: . dockerfile: dockerfiles/services/horses-service/Dockerfile args: - GRADLE_VERSION: ${DOCKER_GRADLE_VERSION:-9.0.0} + GRADLE_VERSION: ${DOCKER_GRADLE_VERSION} JAVA_VERSION: ${DOCKER_JAVA_VERSION:-21} BUILD_DATE: ${BUILD_DATE:-unknown} VERSION: ${DOCKER_APP_VERSION:-1.0.0} @@ -250,7 +250,7 @@ services: context: . dockerfile: dockerfiles/services/events-service/Dockerfile args: - GRADLE_VERSION: ${DOCKER_GRADLE_VERSION:-9.0.0} + GRADLE_VERSION: ${DOCKER_GRADLE_VERSION} JAVA_VERSION: ${DOCKER_JAVA_VERSION:-21} BUILD_DATE: ${BUILD_DATE:-unknown} VERSION: ${DOCKER_APP_VERSION:-1.0.0} @@ -326,7 +326,7 @@ services: context: . dockerfile: dockerfiles/services/masterdata-service/Dockerfile args: - GRADLE_VERSION: ${DOCKER_GRADLE_VERSION:-9.0.0} + GRADLE_VERSION: ${DOCKER_GRADLE_VERSION} JAVA_VERSION: ${DOCKER_JAVA_VERSION:-21} BUILD_DATE: ${BUILD_DATE:-unknown} VERSION: ${DOCKER_APP_VERSION:-1.0.0} diff --git a/docker-compose.yml b/docker-compose.yml index b9e690ce..aa2e2c3e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,17 +1,16 @@ # =================================================================== -# Docker Compose - Basis-Infrastruktur -# Meldestelle Project - Essentielle Services -# =================================================================== -# Usage: -# Entwicklung & Standard: docker-compose up -d +# Docker Compose - Infrastructure Services +# Generated from docker/versions.toml +# Environment: development +# Generated: 2025-10-25 23:26:24 UTC # =================================================================== services: # =================================================================== - # Datenbank + # Database # =================================================================== postgres: - image: postgres:16-alpine + image: postgres:${DOCKER_POSTGRES_VERSION:-16-alpine} container_name: meldestelle-postgres environment: POSTGRES_USER: ${POSTGRES_USER:-meldestelle} @@ -25,18 +24,18 @@ services: networks: - meldestelle-network healthcheck: - test: [ "CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-meldestelle} -d ${POSTGRES_DB:-meldestelle}" ] - interval: 10s + test: ["CMD-SHELL", "pg_isready -U meldestelle -d meldestelle"] + interval: 30s timeout: 5s retries: 3 - start_period: 20s + start_period: 40s restart: unless-stopped # =================================================================== # Cache # =================================================================== redis: - image: redis:7-alpine + image: redis:${DOCKER_REDIS_VERSION:-7-alpine} container_name: meldestelle-redis ports: - "${REDIS_PORT:-6379}:6379" @@ -46,129 +45,46 @@ services: networks: - meldestelle-network healthcheck: - test: [ "CMD", "redis-cli", "ping" ] - interval: 10s + test: ["CMD", "redis-cli", "ping"] + interval: 30s timeout: 5s retries: 3 - start_period: 20s + start_period: 40s restart: unless-stopped # =================================================================== - # Authentifizierung - Keycloak - # =================================================================== - # Production-ready Keycloak configuration with optimized settings + # Authentication # =================================================================== keycloak: - image: quay.io/keycloak/keycloak:${DOCKER_KEYCLOAK_VERSION:-26.4.0} + image: quay.io/keycloak/keycloak:${DOCKER_KEYCLOAK_VERSION:-26.4.2} container_name: meldestelle-keycloak - # Using base image directly instead of custom Dockerfile environment: - # Admin Configuration -# KEYCLOAK_ADMIN: admin # is deprecated -# KEYCLOAK_ADMIN_PASSWORD: admin # is deprecated - KC_BOOTSTRAP_ADMIN_USERNAME: ${KC_BOOTSTRAP_ADMIN_USERNAME:-admin} - KC_BOOTSTRAP_ADMIN_PASSWORD: ${KC_BOOTSTRAP_ADMIN_PASSWORD:-admin} - - # Database Configuration + KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN:-admin} + KEYCLOAK_ADMIN_PASSWORD: ${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 - - # HTTP Configuration - Let Keycloak auto-detect hostname for OpenID discovery - KC_HTTP_ENABLED: true - KC_HOSTNAME_STRICT: false - + KC_DB_URL: jdbc:postgresql://postgres:5432/${POSTGRES_DB:-meldestelle} + KC_DB_USERNAME: ${POSTGRES_USER:-meldestelle} + KC_DB_PASSWORD: ${POSTGRES_PASSWORD:-meldestelle} ports: - - "${KEYCLOAK_PORT:-8180}:8080" + - "8180:8080" depends_on: postgres: condition: service_healthy volumes: - ./docker/services/keycloak:/opt/keycloak/data/import - - keycloak-data:/opt/keycloak/data - command: - # Development mode with realm import enabled - - start-dev - - --import-realm + command: start-dev --import-realm networks: - meldestelle-network healthcheck: - test: [ 'CMD-SHELL', 'curl -s http://localhost:8080/ >/dev/null 2>&1 || exit 1' ] - interval: 15s - timeout: 10s - retries: 5 - start_period: 60s - restart: unless-stopped - - # =================================================================== - # Service Discovery - # =================================================================== - consul: - image: hashicorp/consul:1.15 - container_name: meldestelle-consul - ports: - - "${CONSUL_PORT:-8500}:8500" - command: agent -server -ui -node=server-1 -bootstrap-expect=1 -client=0.0.0.0 - networks: - - meldestelle-network - healthcheck: - test: [ "CMD", "curl", "-f", "http://localhost:8500/v1/status/leader" ] - interval: 10s + test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/"] + interval: 30s timeout: 5s retries: 3 - start_period: 20s + start_period: 40s restart: unless-stopped # =================================================================== - # Messaging (Kafka & Zookeeper) - # =================================================================== - zookeeper: - image: confluentinc/cp-zookeeper:7.4.0 - container_name: meldestelle-zookeeper - environment: - ZOOKEEPER_CLIENT_PORT: ${ZOOKEEPER_CLIENT_PORT:-2181} - ZOOKEEPER_TICK_TIME: 2000 - ports: - - "${ZOOKEEPER_CLIENT_PORT:-2181}:2181" - networks: - - meldestelle-network - healthcheck: - test: ["CMD", "bash", "-c", "echo 'ruok' | nc localhost 2181"] - interval: 10s - timeout: 5s - retries: 3 - start_period: 20s - restart: unless-stopped - - kafka: - image: confluentinc/cp-kafka:7.4.0 - container_name: meldestelle-kafka - environment: - KAFKA_BROKER_ID: ${KAFKA_BROKER_ID:-1} - KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 - KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:${KAFKA_PORT:-9092} - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT - KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT - KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: ${KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR:-1} - ports: - - "${KAFKA_PORT:-9092}:9092" - depends_on: - zookeeper: - condition: service_healthy - networks: - - meldestelle-network - healthcheck: - test: ["CMD", "kafka-broker-api-versions", "--bootstrap-server", "localhost:9092"] - interval: 10s - timeout: 5s - retries: 3 - start_period: 20s - restart: unless-stopped - - # =================================================================== - # Monitoring (Prometheus & Grafana) + # Monitoring # =================================================================== prometheus: image: prom/prometheus:${DOCKER_PROMETHEUS_VERSION:-v2.54.1} @@ -189,10 +105,10 @@ services: - meldestelle-network healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9090/-/healthy"] - interval: 10s + interval: 30s timeout: 5s retries: 3 - start_period: 20s + start_period: 40s restart: unless-stopped grafana: @@ -214,66 +130,10 @@ services: - meldestelle-network healthcheck: test: ["CMD", "curl", "--fail", "http://localhost:3000/api/health"] - interval: 10s + interval: 30s timeout: 5s retries: 3 - start_period: 20s - restart: unless-stopped - - # =================================================================== - # API Gateway - # =================================================================== - api-gateway: - build: - context: . - dockerfile: dockerfiles/infrastructure/gateway/Dockerfile - args: - # Global build arguments (from docker/build-args/global.env) - GRADLE_VERSION: ${DOCKER_GRADLE_VERSION:-9.0.0} - JAVA_VERSION: ${DOCKER_JAVA_VERSION:-21} - BUILD_DATE: ${BUILD_DATE:-unknown} - VERSION: ${DOCKER_APP_VERSION:-1.0.0} - # Infrastructure-specific arguments (from docker/build-args/infrastructure.env) - SPRING_PROFILES_ACTIVE: ${DOCKER_SPRING_PROFILES_DEFAULT:-default} - # Enable BuildKit for better caching and performance - # platforms: - # - linux/amd64 - container_name: meldestelle-api-gateway - volumes: - # Mount Gradle cache for better build performance - - api-gateway-gradle-cache:/home/gradle/.gradle - environment: - SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-dev,keycloak} - CONSUL_HOST: consul - CONSUL_PORT: ${CONSUL_PORT:-8500} - CONSUL_ENABLED: "true" - GATEWAY_PORT: ${GATEWAY_PORT:-8081} - # Keycloak OAuth2 Integration (using Spring Security oauth2ResourceServer) - KEYCLOAK_SERVER_URL: http://keycloak:8080 - KEYCLOAK_ISSUER_URI: http://keycloak:8080/realms/meldestelle - KEYCLOAK_JWK_SET_URI: http://keycloak:8080/realms/meldestelle/protocol/openid-connect/certs - KEYCLOAK_REALM: meldestelle - KEYCLOAK_CLIENT_ID: api-gateway - KEYCLOAK_CLIENT_SECRET: K5RqonwVOaxPKaXVH4mbthSRbjRh5tOK - ports: - - "${GATEWAY_PORT:-8081}:8081" - depends_on: - consul: - condition: service_healthy - postgres: - condition: service_healthy - redis: - condition: service_healthy - keycloak: - condition: service_started - networks: - - meldestelle-network - healthcheck: - test: [ "CMD", "curl", "--fail", "http://localhost:${GATEWAY_PORT:-8081}/actuator/health" ] - interval: 15s - timeout: 5s - retries: 3 - start_period: 30s + start_period: 40s restart: unless-stopped # =================================================================== @@ -288,10 +148,6 @@ volumes: driver: local grafana-data: driver: local - api-gateway-gradle-cache: - driver: local - keycloak-data: - driver: local # =================================================================== # Networks diff --git a/docker-compose.yml.optimized b/docker-compose.yml.optimized index 60e44481..6ee77cdb 100644 --- a/docker-compose.yml.optimized +++ b/docker-compose.yml.optimized @@ -14,10 +14,10 @@ version: '3.9' services: # =================================================================== - # Datenbank - PostgreSQL with Security Hardening + # Datenbank - PostgresQL with Security Hardening # =================================================================== postgres: - image: postgres:16-alpine + image: postgres:${DOCKER_POSTGRES_VERSION:-16-alpine} container_name: meldestelle-postgres environment: POSTGRES_USER_FILE: /run/secrets/postgres_user @@ -58,7 +58,7 @@ services: # Cache - Redis with Authentication # =================================================================== redis: - image: redis:7-alpine + image: redis:${DOCKER_REDIS_VERSION:-7-alpine} container_name: meldestelle-redis ports: - "${REDIS_PORT:-6379}:6379" @@ -96,7 +96,7 @@ services: # Authentifizierung - Keycloak with Enhanced Security # =================================================================== keycloak: - image: quay.io/keycloak/keycloak:${DOCKER_KEYCLOAK_VERSION:-26.4.0} + image: quay.io/keycloak/keycloak:${DOCKER_KEYCLOAK_VERSION:-26.4.2} container_name: meldestelle-keycloak environment: # Admin Configuration - Using secrets @@ -159,7 +159,7 @@ services: # Service Discovery - Consul # =================================================================== consul: - image: hashicorp/consul:1.15 + image: hashicorp/consul:${DOCKER_CONSUL_VERSION:-1.15} container_name: meldestelle-consul ports: - "${CONSUL_PORT:-8500}:8500" @@ -193,7 +193,7 @@ services: # Messaging - Zookeeper & Kafka with Resource Limits # =================================================================== zookeeper: - image: confluentinc/cp-zookeeper:7.4.0 + image: confluentinc/cp-zookeeper:${DOCKER_ZOOKEEPER_VERSION:-7.4.0} container_name: meldestelle-zookeeper environment: ZOOKEEPER_CLIENT_PORT: ${ZOOKEEPER_CLIENT_PORT:-2181} @@ -227,7 +227,7 @@ services: - no-new-privileges:true kafka: - image: confluentinc/cp-kafka:7.4.0 + image: confluentinc/cp-kafka:${DOCKER_KAFKA_VERSION:-7.4.0} container_name: meldestelle-kafka environment: KAFKA_BROKER_ID: ${KAFKA_BROKER_ID:-1} @@ -366,7 +366,7 @@ services: dockerfile: dockerfiles/infrastructure/gateway/Dockerfile args: # Global build arguments - GRADLE_VERSION: ${DOCKER_GRADLE_VERSION:-9.0.0} + GRADLE_VERSION: ${DOCKER_GRADLE_VERSION} JAVA_VERSION: ${DOCKER_JAVA_VERSION:-21} BUILD_DATE: ${BUILD_DATE:-unknown} VERSION: ${DOCKER_APP_VERSION:-1.0.0} diff --git a/docker/build-args/clients.env b/docker/build-args/clients.env index 6af40360..df823770 100644 --- a/docker/build-args/clients.env +++ b/docker/build-args/clients.env @@ -1,15 +1,15 @@ # =================================================================== # Clients Docker Build Arguments - dockerfiles/clients/* # Source: docker/versions.toml [categories.clients] -# Last updated: 2025-09-13 18:33:34 UTC +# Last updated: 2025-10-25 22:43:54 UTC # =================================================================== # --- Include Global Arguments --- -# Source global.env for GRADLE_VERSION, JAVA_VERSION, BUILD_DATE, VERSION +# Source global.env for GRADLE_VERSION, JAVA_VERSION, VERSION # --- Client-Specific Build Tools --- -NODE_VERSION=20.12.0 -NGINX_VERSION=1.25-alpine +NODE_VERSION=22.21.0 +NGINX_VERSION=1.28.0-alpine # --- Client Build Configuration --- CLIENT_PATH=client @@ -18,18 +18,15 @@ CLIENT_NAME=meldestelle-client # --- Web Application Specific --- WEB_APP_PORT=4000 -WEB_APP_BUILD_TARGET=jsBrowserDistribution # --- Desktop Application Specific --- DESKTOP_APP_VNC_PORT=5901 DESKTOP_APP_NOVNC_PORT=6080 -DESKTOP_APP_BUILD_TARGET=createDistributable # --- Client Environment --- NODE_ENV=production APP_TITLE=Meldestelle APP_VERSION=1.0.0 -DOCKER_APP_VERSION=1.0.0 # --- Development Configuration --- WEBPACK_DEV_SERVER_HOST=0.0.0.0 diff --git a/docker/build-args/global.env b/docker/build-args/global.env index 848a212d..f7e09162 100644 --- a/docker/build-args/global.env +++ b/docker/build-args/global.env @@ -1,24 +1,26 @@ # =================================================================== # Global Docker Build Arguments - Used by all categories # Source: docker/versions.toml -# Last updated: 2025-09-13 18:33:34 UTC +# Last updated: 2025-10-25 22:43:54 UTC # =================================================================== # --- Build Tools --- -GRADLE_VERSION=9.0.0 +GRADLE_VERSION=9.1.0 JAVA_VERSION=21 # --- Build Metadata --- -BUILD_DATE="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" VERSION=1.0.0 -DOCKER_APP_VERSION=1.0.0 - -# --- Common Base Images --- -ALPINE_VERSION=3.19 -ECLIPSE_TEMURIN_JDK_VERSION=21-jdk-alpine -ECLIPSE_TEMURIN_JRE_VERSION=21-jre-alpine # --- Monitoring & Infrastructure Services --- DOCKER_PROMETHEUS_VERSION=v2.54.1 DOCKER_GRAFANA_VERSION=11.3.0 -DOCKER_KEYCLOAK_VERSION=26.0.7 +DOCKER_KEYCLOAK_VERSION=26.4.2 + +# --- Datastore Images --- +DOCKER_POSTGRES_VERSION=16-alpine +DOCKER_REDIS_VERSION=7-alpine + +# --- Additional Infrastructure Images --- +DOCKER_CONSUL_VERSION=1.15 +DOCKER_ZOOKEEPER_VERSION=7.4.0 +DOCKER_KAFKA_VERSION=7.4.0 diff --git a/docker/build-args/infrastructure.env b/docker/build-args/infrastructure.env index 0d89fc36..e41e952b 100644 --- a/docker/build-args/infrastructure.env +++ b/docker/build-args/infrastructure.env @@ -1,15 +1,14 @@ # =================================================================== # Infrastructure Docker Build Arguments - dockerfiles/infrastructure/* # Source: docker/versions.toml [categories.infrastructure] -# Last updated: 2025-09-13 18:33:34 UTC +# Last updated: 2025-10-25 22:43:54 UTC # =================================================================== # --- Include Global Arguments --- -# Source global.env for GRADLE_VERSION, JAVA_VERSION, BUILD_DATE, VERSION +# Source global.env for GRADLE_VERSION, JAVA_VERSION, VERSION # --- Infrastructure Services Configuration --- SPRING_PROFILES_ACTIVE=default -DOCKER_SPRING_PROFILES_DEFAULT # --- Infrastructure Service Ports (matches gradle.properties) --- GATEWAY_PORT=8081 diff --git a/docker/build-args/services.env b/docker/build-args/services.env index 7950eabd..c4d3da25 100644 --- a/docker/build-args/services.env +++ b/docker/build-args/services.env @@ -1,15 +1,14 @@ # =================================================================== # Services Docker Build Arguments - dockerfiles/services/* # Source: docker/versions.toml [categories.services] -# Last updated: 2025-09-13 18:33:34 UTC +# Last updated: 2025-10-25 22:43:54 UTC # =================================================================== # --- Include Global Arguments --- -# Source global.env for GRADLE_VERSION, JAVA_VERSION, BUILD_DATE, VERSION +# Source global.env for GRADLE_VERSION, JAVA_VERSION, VERSION # --- Spring Boot Services Configuration --- SPRING_PROFILES_ACTIVE=docker -DOCKER_SPRING_PROFILES_DOCKER # --- Service-Specific Arguments --- SERVICE_PATH=. diff --git a/docker/versions.toml b/docker/versions.toml index d6482597..752e2d80 100644 --- a/docker/versions.toml +++ b/docker/versions.toml @@ -7,20 +7,29 @@ [versions] # --- Build Tools --- -gradle = "9.0.0" +gradle = "9.1.0" java = "21" -node = "20.12.0" +node = "22.21.0" # --- Base Images --- -nginx = "1.25-alpine" -alpine = "3.19" +nginx = "1.28.0-alpine" +alpine = "3.22" eclipse-temurin-jdk = "21-jdk-alpine" eclipse-temurin-jre = "21-jre-alpine" +# --- Datastore Images --- +postgres = "16-alpine" +redis = "7-alpine" + +# --- Additional Infrastructure Images --- +consul = "1.15" +zookeeper = "7.4.0" +kafka = "7.4.0" + # --- Monitoring & Infrastructure Services --- prometheus = "v2.54.1" grafana = "11.3.0" -keycloak = "26.0.7" +keycloak = "26.4.2" # --- Spring Configuration --- spring-profiles-default = "default" @@ -126,8 +135,6 @@ services = [ # --- Client Applications Configuration --- [categories.clients] -default-node-version = "20.11.0" -default-nginx-version = "1.25-alpine" clients = [ "web-app", "desktop-app" @@ -140,9 +147,14 @@ gradle-version = "DOCKER_GRADLE_VERSION" java-version = "DOCKER_JAVA_VERSION" node-version = "DOCKER_NODE_VERSION" nginx-version = "DOCKER_NGINX_VERSION" +postgres-version = "DOCKER_POSTGRES_VERSION" +redis-version = "DOCKER_REDIS_VERSION" prometheus-version = "DOCKER_PROMETHEUS_VERSION" grafana-version = "DOCKER_GRAFANA_VERSION" keycloak-version = "DOCKER_KEYCLOAK_VERSION" +consul-version = "DOCKER_CONSUL_VERSION" +zookeeper-version = "DOCKER_ZOOKEEPER_VERSION" +kafka-version = "DOCKER_KAFKA_VERSION" spring-profiles-default = "DOCKER_SPRING_PROFILES_DEFAULT" spring-profiles-docker = "DOCKER_SPRING_PROFILES_DOCKER" app-version = "DOCKER_APP_VERSION" diff --git a/docker/versions.toml.bak b/docker/versions.toml.bak new file mode 100644 index 00000000..30d81e3d --- /dev/null +++ b/docker/versions.toml.bak @@ -0,0 +1,192 @@ +# =================================================================== +# Docker Versions Catalog - Single Source of Truth +# Analogous to gradle/libs.versions.toml for centralized version management +# =================================================================== +# Last updated: 2025-09-13 +# Eliminates version redundancy across 12+ Dockerfiles + +[versions] +# --- Build Tools --- +gradle = "9.1.0" +java = "21" +node = "22.21.0" + +# --- Base Images --- +nginx = "1.25-alpine" +alpine = "3.19" +eclipse-temurin-jdk = "21-jdk-alpine" +eclipse-temurin-jre = "21-jre-alpine" + +# --- Monitoring & Infrastructure Services --- +prometheus = "v2.54.1" +grafana = "11.3.0" +keycloak = "26.0.7" + +# --- Spring Configuration --- +spring-profiles-default = "default" +spring-profiles-docker = "docker" +spring-profiles-prod = "prod" + +# --- Application Versions --- +app-version = "1.0.0" + +# --- Zentrale Port-Verwaltung --- +# Single Source of Truth für alle Service-Ports + +[service-ports] +# --- Infrastructure Services --- +api-gateway = 8081 +auth-server = 8087 +monitoring-server = 8088 + +# --- Application Services --- +ping-service = 8082 +members-service = 8083 +horses-service = 8084 +events-service = 8085 +masterdata-service = 8086 + +# --- External Services --- +postgres = 5432 +redis = 6379 +keycloak = 8180 +consul = 8500 +zookeeper = 2181 +kafka = 9092 + +# --- Monitoring Stack --- +prometheus = 9090 +grafana = 3000 + +# --- Client Applications --- +web-app = 4000 +desktop-app-vnc = 5901 +desktop-app-novnc = 6080 + +[port-ranges] +# --- Port-Range-Definitionen für automatische Port-Zuweisung --- +infrastructure = "8081-8088" +services = "8082-8099" +monitoring = "9090-9099" +clients = "4000-4099" +vnc = "5901-5999" +debug = "5005-5009" + +# --- Reserved Port Ranges --- +system-reserved = "0-1023" +ephemeral = "32768-65535" + +[build-args] +# --- Global Build Arguments (used across all categories) --- +global = [ + "GRADLE_VERSION", + "JAVA_VERSION", + "BUILD_DATE", + "VERSION" +] + +# --- Spring Boot Services (dockerfiles/services/* and infrastructure/*) --- +spring-services = [ + "SPRING_PROFILES_ACTIVE", + "SERVICE_PATH", + "SERVICE_NAME", + "SERVICE_PORT" +] + +# --- Kotlin/JS Web Clients (dockerfiles/clients/*) --- +web-clients = [ + "NODE_VERSION", + "NGINX_VERSION", + "CLIENT_PATH", + "CLIENT_MODULE", + "CLIENT_NAME" +] + +[categories] +# --- Services Configuration --- +[categories.services] +default-spring-profile = "docker" +default-port-start = 8082 +services = [ + "ping-service", + "members-service", + "horses-service", + "events-service", + "masterdata-service" +] + +# --- Infrastructure Configuration --- +[categories.infrastructure] +default-spring-profile = "default" +services = [ + "gateway", + "auth-server", + "monitoring-server" +] + +# --- Client Applications Configuration --- +[categories.clients] +default-node-version = "20.11.0" +default-nginx-version = "1.25-alpine" +clients = [ + "web-app", + "desktop-app" +] + +[environment-mapping] +# --- Environment Variable Names for Docker Compose --- +# Maps internal version names to environment variable names +gradle-version = "DOCKER_GRADLE_VERSION" +java-version = "DOCKER_JAVA_VERSION" +node-version = "DOCKER_NODE_VERSION" +nginx-version = "DOCKER_NGINX_VERSION" +prometheus-version = "DOCKER_PROMETHEUS_VERSION" +grafana-version = "DOCKER_GRAFANA_VERSION" +keycloak-version = "DOCKER_KEYCLOAK_VERSION" +spring-profiles-default = "DOCKER_SPRING_PROFILES_DEFAULT" +spring-profiles-docker = "DOCKER_SPRING_PROFILES_DOCKER" +app-version = "DOCKER_APP_VERSION" + +[environments] +# --- Environment-spezifische Konfigurationen --- +# Zentrale Verwaltung für dev/test/prod Umgebungen + +[environments.development] +spring-profiles = "dev" +debug-enabled = true +log-level = "DEBUG" +health-check-interval = "30s" +health-check-timeout = "5s" +health-check-retries = 3 +health-check-start-period = "40s" +resource-limits = false +jvm-debug-port = 5005 +hot-reload = true + +[environments.production] +spring-profiles = "prod" +debug-enabled = false +log-level = "INFO" +health-check-interval = "15s" +health-check-timeout = "3s" +health-check-retries = 3 +health-check-start-period = "30s" +resource-limits = true +jvm-debug-port = false +hot-reload = false +security-headers = true +tls-enabled = true + +[environments.testing] +spring-profiles = "test" +debug-enabled = true +log-level = "DEBUG" +health-check-interval = "10s" +health-check-timeout = "5s" +health-check-retries = 2 +health-check-start-period = "20s" +resource-limits = false +jvm-debug-port = 5005 +hot-reload = false +ephemeral-storage = true +test-containers = true diff --git a/dockerfiles/infrastructure/auth-server/Dockerfile b/dockerfiles/infrastructure/auth-server/Dockerfile index b2b73394..d8f7737a 100644 --- a/dockerfiles/infrastructure/auth-server/Dockerfile +++ b/dockerfiles/infrastructure/auth-server/Dockerfile @@ -23,9 +23,9 @@ ARG SPRING_PROFILES_ACTIVE FROM gradle:${GRADLE_VERSION}-jdk${JAVA_VERSION}-alpine AS builder # Re-declare build arguments for this stage -ARG SPRING_PROFILES_ACTIVE=docker +ARG SPRING_PROFILES_ACTIVE ARG BUILD_DATE -ARG VERSION=1.0.0 +ARG VERSION LABEL stage=builder \ service="auth-server" \ @@ -85,9 +85,9 @@ FROM eclipse-temurin:${JAVA_VERSION}-jre-alpine AS runtime # Build arguments for runtime stage ARG BUILD_DATE -ARG VERSION=1.0.0 -ARG JAVA_VERSION=21 -ARG SPRING_PROFILES_ACTIVE=docker +ARG VERSION +ARG JAVA_VERSION +ARG SPRING_PROFILES_ACTIVE # Convert build arguments to environment variables ENV JAVA_VERSION=${JAVA_VERSION} \ diff --git a/dockerfiles/infrastructure/gateway/Dockerfile b/dockerfiles/infrastructure/gateway/Dockerfile index e0c5c880..058afb44 100644 --- a/dockerfiles/infrastructure/gateway/Dockerfile +++ b/dockerfiles/infrastructure/gateway/Dockerfile @@ -23,9 +23,9 @@ ARG SPRING_PROFILES_ACTIVE FROM gradle:${GRADLE_VERSION}-jdk${JAVA_VERSION}-alpine AS builder # Re-declare build arguments for this stage -ARG SPRING_PROFILES_ACTIVE=default +ARG SPRING_PROFILES_ACTIVE ARG BUILD_DATE -ARG VERSION=1.0.0 +ARG VERSION LABEL stage=builder LABEL service="api-gateway" @@ -92,12 +92,13 @@ RUN mkdir -p build/dependency && \ # Runtime Stage # =================================================================== FROM eclipse-temurin:${JAVA_VERSION}-jre-alpine AS runtime +#eclipse-temurin:21-jre-alpine-3.22 # Build arguments for runtime stage ARG BUILD_DATE -ARG VERSION=1.0.0 -ARG JAVA_VERSION=21 -ARG SPRING_PROFILES_ACTIVE=default +ARG VERSION +ARG JAVA_VERSION +ARG SPRING_PROFILES_ACTIVE # Convert build arguments to environment variables ENV JAVA_VERSION=${JAVA_VERSION} \ diff --git a/dockerfiles/infrastructure/keycloak/Dockerfile b/dockerfiles/infrastructure/keycloak/Dockerfile index 1b79643b..aad2f554 100644 --- a/dockerfiles/infrastructure/keycloak/Dockerfile +++ b/dockerfiles/infrastructure/keycloak/Dockerfile @@ -2,15 +2,14 @@ # =================================================================== # Production-Ready Keycloak Dockerfile # =================================================================== -# Based on: quay.io/keycloak/keycloak:26.4.0 +# Based on: quay.io/keycloak/keycloak:26.4.2 # Features: # - Pre-built optimized image (faster startup) # - Security hardening # - Custom theme support # - Health monitoring # =================================================================== - -ARG KEYCLOAK_VERSION=26.4.0 +ARG KEYCLOAK_VERSION FROM quay.io/keycloak/keycloak:${KEYCLOAK_VERSION} diff --git a/dockerfiles/services/events-service/Dockerfile b/dockerfiles/services/events-service/Dockerfile index 766c3415..2ea4c7c6 100644 --- a/dockerfiles/services/events-service/Dockerfile +++ b/dockerfiles/services/events-service/Dockerfile @@ -28,7 +28,7 @@ FROM gradle:${GRADLE_VERSION}-jdk${JAVA_VERSION}-alpine AS builder ARG SERVICE_PATH=events/events-service ARG SERVICE_NAME=events-service ARG SERVICE_PORT=8086 -ARG SPRING_PROFILES_ACTIVE=docker +ARG SPRING_PROFILES_ACTIVE LABEL stage=builder LABEL maintainer="Meldestelle Development Team" diff --git a/dockerfiles/services/horses-service/Dockerfile b/dockerfiles/services/horses-service/Dockerfile index 63f5b30d..1316899b 100644 --- a/dockerfiles/services/horses-service/Dockerfile +++ b/dockerfiles/services/horses-service/Dockerfile @@ -28,7 +28,7 @@ FROM gradle:${GRADLE_VERSION}-jdk${JAVA_VERSION}-alpine AS builder ARG SERVICE_PATH=horses/horses-service ARG SERVICE_NAME=horses-service ARG SERVICE_PORT=8085 -ARG SPRING_PROFILES_ACTIVE=docker +ARG SPRING_PROFILES_ACTIVE LABEL stage=builder LABEL maintainer="Meldestelle Development Team" diff --git a/dockerfiles/services/masterdata-service/Dockerfile b/dockerfiles/services/masterdata-service/Dockerfile index 5c841bce..0f1454f2 100644 --- a/dockerfiles/services/masterdata-service/Dockerfile +++ b/dockerfiles/services/masterdata-service/Dockerfile @@ -28,7 +28,7 @@ FROM gradle:${GRADLE_VERSION}-jdk${JAVA_VERSION}-alpine AS builder ARG SERVICE_PATH=masterdata/masterdata-service ARG SERVICE_NAME=masterdata-service ARG SERVICE_PORT=8087 -ARG SPRING_PROFILES_ACTIVE=docker +ARG SPRING_PROFILES_ACTIVE LABEL stage=builder LABEL maintainer="Meldestelle Development Team" diff --git a/dockerfiles/services/members-service/Dockerfile b/dockerfiles/services/members-service/Dockerfile index 4c27565b..5cb4ddf8 100644 --- a/dockerfiles/services/members-service/Dockerfile +++ b/dockerfiles/services/members-service/Dockerfile @@ -28,7 +28,7 @@ FROM gradle:${GRADLE_VERSION}-jdk${JAVA_VERSION}-alpine AS builder ARG SERVICE_PATH=members/members-service ARG SERVICE_NAME=members-service ARG SERVICE_PORT=8084 -ARG SPRING_PROFILES_ACTIVE=docker +ARG SPRING_PROFILES_ACTIVE LABEL stage=builder LABEL maintainer="Meldestelle Development Team" diff --git a/dockerfiles/services/ping-service/Dockerfile b/dockerfiles/services/ping-service/Dockerfile index 7a3bb7c2..395f2390 100644 --- a/dockerfiles/services/ping-service/Dockerfile +++ b/dockerfiles/services/ping-service/Dockerfile @@ -91,9 +91,9 @@ FROM eclipse-temurin:${JAVA_VERSION}-jre-alpine AS runtime # Build arguments for runtime stage ARG BUILD_DATE -ARG VERSION=1.0.0 -ARG JAVA_VERSION=21 -ARG SPRING_PROFILES_ACTIVE=default +ARG VERSION +ARG JAVA_VERSION +ARG SPRING_PROFILES_ACTIVE # Convert build arguments to environment variables ENV JAVA_VERSION=${JAVA_VERSION} \ diff --git a/dockerfiles/templates/kotlin-multiplatform-web.Dockerfile b/dockerfiles/templates/kotlin-multiplatform-web.Dockerfile index d88511ef..663285db 100644 --- a/dockerfiles/templates/kotlin-multiplatform-web.Dockerfile +++ b/dockerfiles/templates/kotlin-multiplatform-web.Dockerfile @@ -32,7 +32,7 @@ FROM gradle:${GRADLE_VERSION}-jdk${JAVA_VERSION}-alpine AS kotlin-builder ARG CLIENT_PATH=client/web-app ARG CLIENT_MODULE=client:web-app ARG CLIENT_NAME=web-app -ARG NODE_VERSION=20.11.0 +ARG NODE_VERSION LABEL stage=kotlin-builder LABEL maintainer="Meldestelle Development Team" diff --git a/dockerfiles/templates/spring-boot-service.Dockerfile b/dockerfiles/templates/spring-boot-service.Dockerfile index 91b7b6f7..a2439c34 100644 --- a/dockerfiles/templates/spring-boot-service.Dockerfile +++ b/dockerfiles/templates/spring-boot-service.Dockerfile @@ -31,7 +31,7 @@ FROM gradle:${GRADLE_VERSION}-jdk${JAVA_VERSION}-alpine AS builder ARG SERVICE_PATH=. ARG SERVICE_NAME=spring-boot-service ARG SERVICE_PORT=8080 -ARG SPRING_PROFILES_ACTIVE=default +ARG SPRING_PROFILES_ACTIVE LABEL stage=builder LABEL maintainer="Meldestelle Development Team" diff --git a/docs/.frontmatter.schema.json b/docs/.frontmatter.schema.json index 2d2edaec..827cafbc 100644 --- a/docs/.frontmatter.schema.json +++ b/docs/.frontmatter.schema.json @@ -1,16 +1,70 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", - "required": ["status", "summary"], + "required": [ + "status", + "summary" + ], "properties": { - "modul": {"type": "string"}, - "status": {"type": "string", "enum": ["active", "draft", "deprecated"]}, - "summary": {"type": "string"}, - "last_reviewed": {"type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$"}, - "review_cycle": {"type": "string", "pattern": "^\\d+d$"}, - "yt_epic": {"type": "string", "pattern": "^[A-Z]+-\\d+$"}, - "yt_issues": {"type": "array", "items": {"type": "string", "pattern": "^[A-Z]+-\\d+$"}}, - "tags": {"type": "array", "items": {"type": "string"}} + "modul": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "active", + "draft", + "deprecated" + ] + }, + "summary": { + "type": "string" + }, + "last_reviewed": { + "type": "string", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$" + }, + "review_cycle": { + "type": "string", + "pattern": "^\\d+d$" + }, + "yt_epic": { + "type": "string", + "pattern": "^[A-Z]+-\\d+$" + }, + "yt_issues": { + "type": "array", + "items": { + "type": "string", + "pattern": "^[A-Z]+-\\d+$" + } + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + }, + "bc": { + "type": "string", + "enum": [ + "members", + "horses", + "events", + "masterdata", + "infrastructure" + ] + }, + "doc_type": { + "type": "string", + "enum": [ + "how-to", + "readme", + "adr-link", + "runbook", + "api" + ] + } }, "additionalProperties": true } diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..f3c7de1d --- /dev/null +++ b/docs/README.md @@ -0,0 +1,96 @@ +# Meldestelle - Dokumentation + +## 📚 Single Source of Truth: YouTrack + +Die Hauptdokumentation befindet sich in der **YouTrack Wissensdatenbank**: + +👉 **[Meldestelle Command Center](https://meldestelle-pro.youtrack.cloud/articles/MP-A-24)** + +### Was du in YouTrack findest + +- 🏗️ **Bounded Context Dokumentation** (Members, Horses, Events, Masterdata) +- 📡 **API-Referenz** (automatisch aus KDoc generiert) +- 🚀 **Deployment-Guides** (Proxmox, Cloudflare, Nginx) +- 🔐 **Sicherheit-Konfigurationen** (Keycloak, GitHub Secrets) +- 💡 **Roadmap & Visionen** +- 📊 **Architektur-Diagramme** (interaktiv) + +--- + +## 📂 Was im Repository bleibt + +### 1. Architecture Decision Records (ADRs) + +Architekturentscheidungen sind Teil der Code-Historie und werden im Repository versioniert: + +- [ADR Übersicht](architecture/adr) +- [ADR-0001: Modulare Architektur](architecture/adr/0001-modular-architecture-de.md) +- [ADR-0002: Domain-Driven Design](architecture/adr/0002-domain-driven-design-de.md) +- [ADR-0003: Microservices](architecture/adr/0003-microservices-architecture-de.md) +- [ADR-0004: Event-Driven Communication](architecture/adr/0004-event-driven-communication-de.md) +- [ADR-0005: Polyglot Persistence](architecture/adr/0005-polyglot-persistence-de.md) +- [ADR-0006: Authentication & Authorization (Keycloak)](architecture/adr/0006-authentication-authorization-keycloak-de.md) +- [ADR-0007: API Gateway Pattern](architecture/adr/0007-api-gateway-pattern-de.md) +- [ADR-0008: Multiplatform Client Applications](architecture/adr/0008-multiplatform-client-applications-de.md) + +### 2. C4-Diagramme (PlantUML-Quellen) + +Versionierte Diagramm-Quellen für Architekturdokumentation: + +- [C4 Context](architecture/c4/01-context-de.puml) +- [C4 Container](architecture/c4/02-container-de.puml) +- [C4 Component - Events Service](architecture/c4/03-component-events-service-de.puml) + +### 3. Developer Guides + +Minimale Anleitungen für lokale Entwicklung: + +- **[Lokales Setup](how-to/start-local.md)** – Projekt in 5 Minuten starten +- **[KDoc Style Guide](how-to/kdoc-style.md)** – Documentations-Konventionen im Code +- **[Branch-Schutz & PR-Workflow](how-to/branchschutz-und-pr-workflow.md)** – Git-Workflow + +--- + +## 🔄 Automatische Synchronisation + +Das Projekt nutzt automatisierte Workflows für Konsistenz: + +- **KDoc → YouTrack**: [docs-kdoc-sync.yml](../.github/workflows/docs-kdoc-sync.yml) – Synchronisiert API-Dokumentation + aus Code-Kommentaren nach YouTrack +- **Docker SSoT**: [ssot-guard.yml](../.github/workflows/ssot-guard.yml) – Validiert Docker-Versionskonsistenz +- **CI Pipeline**: [ci-main.yml](../.github/workflows/ci-main.yml) – Hauptpipeline für Build, Tests, Validierung + +--- + +## 📋 Documentations-Workflow + +### Für Code-Änderungen + +1. KDoc im Code schreiben +2. PR erstellen → CI validiert +3. Nach Merge → KDoc-Sync pusht automatisch nach YouTrack + +### Für Architektur-Entscheidungen + +1. ADR in `docs/architecture/adr/` erstellen +2. PR mit ADR-Review +3. Nach Merge → Zusammenfassung in YouTrack verlinken + +### Für Infrastruktur/Konfiguration + +1. Dokumentation direkt in YouTrack erstellen +2. Bei Code-relevanten Änderungen → im Commit-Message auf YouTrack-Artikel verweisen + +--- + +## ❓ Fragen & Support + +- **Technische Fragen**: [GitHub Discussions](https://github.com/StefanMoCoAt/meldestelle/discussions) +- **Bugs**: [GitHub Issues](https://github.com/StefanMoCoAt/meldestelle/issues) +- **Architektur-Diskussionen**: [YouTrack](https://meldestelle-pro.youtrack.cloud) +- **Projekt-Dokumentation**: [YouTrack Wissensdatenbank](https://meldestelle-pro.youtrack.cloud/knowledge-bases) + +--- + +**Hinweis**: Diese README wurde am 30. Oktober 2025 aktualisiert im Rahmen der Documentations-Migration nach YouTrack ( +siehe ADR-0009 - folgt). diff --git a/docs/Visionen-Ideen/Infrastruktur-Strategie_DSGVO-Konformität.md b/docs/Visionen-Ideen/Infrastruktur-Strategie_DSGVO-Konformität.md deleted file mode 100644 index 5ff23257..00000000 --- a/docs/Visionen-Ideen/Infrastruktur-Strategie_DSGVO-Konformität.md +++ /dev/null @@ -1,86 +0,0 @@ -# **Infrastruktur-Strategie zur DSGVO-Konformität für das Projekt "Meldestelle"** - -Version: 1.0 -Datum: 17\. Oktober 2025 -Status: In Planung -Ziel: Definition eines phasen basierten Ansatzes zur Entwicklung und zum Betrieb der "Meldestelle"-Anwendung, der von einer pragmatischen Entwicklungsphase zu einem vollständig DSGVO-konformen Produktionsbetrieb übergeht. - -## **1\. Zusammenfassung & Zielsetzung** - -Dieses Dokument beschreibt die zweistufige Strategie für die Infrastruktur des "Meldestelle"-Projekts. Ziel ist es, in der initialen Entwicklungs- und Testphase maximale Geschwindigkeit und Kosteneffizienz zu ermöglichen, während gleichzeitig ein klar definierter Pfad zur Erreichung vollständiger DSGVO-Konformität für den späteren Live-Betrieb sichergestellt wird. - -Wir verfolgen einen pragmatischen Ansatz, der den Aufwand und die Kosten in jeder Phase an die tatsächlichen Risiken und Anforderungen anpasst. - -## **2\. Grundprinzipien** - -* **Pragmatismus vor Dogmatismus:** In der Entwicklungsphase nutzen wir etablierte, effiziente Cloud-Dienste, auch wenn diese rechtliche Grauzonen aufweisen, solange das Risiko minimal ist (keine externen personenbezogenen Daten). -* **Containerisierung als Schlüssel:** Die gesamte Anwendung und ihre Infrastruktur wird von Anfang an in Docker-Containern betrieben. Dies gewährleistet maximale Portabilität und macht den späteren Wechsel der Hosting-Umgebung trivial. -* **Automatisierung als Ziel:** Eine CI/CD-Pipeline ist von Beginn an integraler Bestandteil, um manuelle Fehler zu reduzieren und den Deployment-Prozess zu standardisieren. -* **Klare Trennlinie:** Es gibt einen klar definierten "Point of no Return": Bevor die erste Zeile personenbezogener Daten von Dritten verarbeitet wird, muss die Migration zu Phase 2 abgeschlossen sein. - -## **3\. Phasenplan** - -### **Phase 1: Entwicklungs- & Feldversuchs-Phase (MVP)** - -**Ziel:** Schnelle Entwicklung, Implementierung von Kernfunktionen, Durchführung von Tests und ersten Feldversuchen in einer kontrollierten Umgebung. - -**Dauer:** Von Projektbeginn bis zum Abschluss der Feldversuche und vor der Aufnahme von echten Nutzerdaten. - -**Technologie-Stack:** - -* **Code-Hosting:** **GitHub** (US-Anbieter) - * *Begründung:* Exzellente Entwickler-Tools, Marktführer, nahtlose Integrationen. -* **CI/CD-Pipeline:** **GitHub Actions** - * *Begründung:* Perfekte Integration mit dem Code-Hosting. Der rechenintensive Build-Prozess wird auf leistungsstarke Server von GitHub ausgelagert, was den lokalen Heimserver schont. -* **Hosting-Infrastruktur:** **Proxmox Heimserver** (Intel N100 Mini-PC) - * *Begründung:* Kostengünstige, flexible und kontrollierte Umgebung für Entwicklung und Tests. -* **Externer Zugriff:** **Cloudflare Tunnel** - * *Begründung:* Bietet hochsicheren Zugriff auf den Heimserver ohne offene Ports, verbirgt die private IP-Adresse und ist einfach zu verwalten. - -**DSGVO-Bewertung dieser Phase:** - -* **Status:** **Nicht streng DSGVO-konform.** -* **Risiko:** **Akzeptabel und kontrolliert.** -* **Begründung:** Personenbezogene Daten (Name/E-Mail des Entwicklers in Git-Commits) werden an einen US-Anbieter (GitHub/Microsoft) übertragen. Da in dieser Phase keine externen oder sensiblen personenbezogenen Daten im Code oder den Systemen verarbeitet werden, wird dieses Restrisiko bewusst in Kauf genommen. Die rechtliche Grundlage bilden die Standardvertragsklauseln (SCCs) und das Trans-Atlantic Data Privacy Framework (TADPF). - -### **Phase 2: Go-Live & Betrieb (Produktionsumgebung)** - -**Ziel:** Bereitstellung der Anwendung für die Öffentlichkeit in einer hochverfügbaren, sicheren und vollständig DSGVO-konformen Umgebung. - -**Trigger für die Migration:** Der Abschluss der Feldversuche und die geplante Verarbeitung von personenbezogenen Daten von echten Nutzern. - -**Technologie-Stack (Phase 2 \- Go-Live & Betrieb):** - -* **Hosting-Infrastruktur:** **Virtual Private Server (VPS) bei einem EU-Anbieter** (z.B. Hetzner, Standort Deutschland). - * *Begründung:* Gewährleistet, dass alle Daten und Prozesse die EU physisch nicht verlassen (Datenhoheit). Bietet professionelle Performance und Zuverlässigkeit. -* **Code-Hosting & CI/CD:** **Self-hosted Forgejo**, installiert auf dem VPS. - * *Begründung:* Forgejo ist eine leichtgewichtige, von der Community betriebene Open-Source-Alternative. Es bietet Git-Hosting und ein integriertes CI/CD-System (Forgejo Actions), das mit GitHub Actions kompatibel ist. Der gesamte Lebenszyklus des Codes (Speicherung, Bau, Test) findet auf dem eigenen Server in Deutschland statt. -* **Container Registry:** Die in Forgejo integrierte Container Registry. - * *Begründung:* Hält auch die fertigen Docker-Images innerhalb der eigenen, konformen Infrastruktur. -* **Externer Zugriff:** Standard-Reverse-Proxy (z.B. Traefik oder Nginx) direkt auf dem VPS. - * *Begründung:* Der Server hat eine öffentliche IP, ein Tunnel ist nicht mehr nötig. Der Proxy steuert den Zugriff auf die Anwendungs-Container. - -### **DSGVO-Bewertung (Phase 2\)** - -* **Status:** **Vollständig DSGVO-konform.** -* **Risiko:** **Minimal.** -* **Begründung:** Der gesamte Datenverarbeitungsprozess – von der Codezeile in **Forgejo**, über den Build-Prozess durch **Forgejo Actions**, bis zur laufenden Anwendung und den Nutzerdaten in der Datenbank – findet ausschließlich auf Servern in Deutschland unter eigener Kontrolle statt. - -### **4\. Migrationsschritte von Phase 1 zu Phase 2** - -1. **Infrastruktur aufsetzen:** Einen geeigneten VPS bei Hetzner mieten und mit einem schlanken Debian-System grundlegend absichern. -2. **Forgejo installieren:** Forgejo als Docker-Container auf dem neuen VPS installieren und konfigurieren. -3. **Code migrieren:** Das "Meldestelle"-Repository von GitHub auf die eigene Forgejo-Instanz spiegeln/umziehen. -4. **Pipeline adaptieren:** Die GitHub Actions-Workflows in die Forgejo Actions-Konfiguration überführen. **Da Forgejo Actions weitgehend mit GitHub Actions kompatibel ist, ist dieser Schritt deutlich einfacher als eine vollständige Portierung zu einem anderen System.** -5. **Anwendung deployen:** Die CI/CD-Pipeline in Forgejo erstmals ausführen, um die "Meldestelle"-Anwendung (Docker-Container) auf dem VPS zu deployen. -6. **DNS-Umschaltung:** Die DNS-Einträge für mo-code.at (und Subdomains) bei Cloudflare vom Tunnel auf die neue, feste IP-Adresse des Hetzner-Servers umstellen. -7. **Decommissioning:** Nach erfolgreichem Testbetrieb den Cloudflare Tunnel und die alten GitHub-Workflows deaktivieren. - -## **5\. Zeit- und Kostenschätzung** - -* **Phase 1:** - * **Kosten:** Minimal (Stromkosten für Heimserver). Die genutzten Dienste (GitHub, Cloudflare) sind im Rahmen des Projekts kostenlos. - * **Zeitaufwand:** Fokus liegt zu 100% auf der Anwendungsentwicklung. -* **Phase 2:** - * **Kosten:** Monatliche Gebühren für den VPS (ca. 15-30 €/Monat, je nach Größe). - * **Zeitaufwand:** Für die Migration von Phase 1 zu 2 sollte ein dediziertes Zeitfenster von **ca. 1-2 Wochen** eingeplant werden, um alle Schritte sorgfältig durchzuführen und zu testen. \ No newline at end of file diff --git a/docs/api/README.md b/docs/api/README.md deleted file mode 100644 index b488d119..00000000 --- a/docs/api/README.md +++ /dev/null @@ -1,400 +0,0 @@ ---- -modul: api-overview -status: active -last_reviewed: 2025-10-22 -review_cycle: 180d -summary: Überblick und Einstieg in die REST‑APIs der Meldestelle. -yt_epic: MP-1 -yt_issues: [MP-7] -tags: [api, overview] ---- - -# Meldestelle – REST‑API Dokumentation - -## Überblick - -Die Meldestelle-Anwendung bietet eine umfassende REST API für die Verwaltung von Pferdesportveranstaltungen. Die API folgt RESTful-Prinzipien und ist in modulare Services unterteilt, die jeweils spezifische Domänen abdecken. - -## API-Architektur - -### Modulare Service-Struktur - -Die API ist in folgende Hauptmodule unterteilt: - -``` -API Services -├── Members API # Mitgliederverwaltung -├── Horses API # Pferderegistrierung -├── Events API # Veranstaltungsverwaltung -└── Masterdata API # Stammdatenverwaltung - ├── Countries # Länderverwaltung - ├── States # Bundesländerverwaltung - ├── Age Classes # Altersklassenverwaltung - └── Venues # Plätze/Austragungsorte -``` - -### Technische Spezifikationen - -- **Framework**: Spring Boot 3.x mit Spring Web MVC -- **Dokumentation**: OpenAPI 3.0 (Swagger) -- **Serialisierung**: JSON mit Jackson/Kotlinx Serialization -- **Authentifizierung**: JWT Bearer Token -- **Versionierung**: URL-basiert (/api/v1/) -- **Content-Type**: application/json -- **Zeichenkodierung**: UTF-8 - -## Basis-URL und Endpunkte - -### Entwicklungsumgebung -``` -Base URL: http://localhost:8081/api -``` - -### Produktionsumgebung -``` -Base URL: https://api.meldestelle.yourdomain.com/api -``` - -## API-Module Übersicht - -### 1. Members API -**Basis-Pfad**: `/api/members` - -Verwaltung von Vereinsmitgliedern und deren Mitgliedschaftsdaten. - -**Hauptfunktionen**: -- Mitgliederverwaltung (CRUD) -- Mitgliedschaftsstatus-Tracking -- Ablaufende Mitgliedschaften -- Validierung von E-Mail und Mitgliedsnummer - -**Controller**: `MemberController` -**Endpunkte**: 12 REST-Endpunkte -**Dokumentation**: [Members API](members-api.md) - -### 2. Horses API -**Basis-Pfad**: `/api/horses` - -Registrierung und Verwaltung von Pferden mit umfassenden Identifikationsdaten. - -**Hauptfunktionen**: -- Pferderegistrierung (CRUD) -- Identifikationsnummern-Verwaltung -- OEPS/FEI-Registrierung -- Besitzer- und Verantwortlichen-Zuordnung - -**Controller**: `HorseController` -**Endpunkte**: 15+ REST-Endpunkte - -### 3. Events API -**Basis-Pfad**: `/api/events` - -Planung und Verwaltung von Pferdesportveranstaltungen. - -**Hauptfunktionen**: -- Veranstaltungsplanung (CRUD) -- Terminverwaltung -- Teilnehmerverwaltung -- Öffentliche/Private Veranstaltungen - -**Controller**: `VeranstaltungController` -**Endpunkte**: 10+ REST-Endpunkte - -### 4. Masterdata API -**Basis-Pfad**: `/api/masterdata` - -Verwaltung von Stammdaten für das gesamte System. - -#### 4.1 Countries API -**Pfad**: `/api/masterdata/countries` -- Länderverwaltung mit ISO-Codes -- EU/EWR-Mitgliedschaft -- Mehrsprachige Ländernamen - -#### 4.2 States API -**Pfad**: `/api/masterdata/states` -- Bundesländer/Kantone/Regionen -- OEPS-Codes für österreichische Bundesländer -- ISO 3166-2 Codes - -#### 4.3 Age Classes API -**Pfad**: `/api/masterdata/age-classes` -- Altersklassen für verschiedene Sparten -- Teilnahmeberechtigung -- Geschlechts- und Spartenfilter - -#### 4.4 Venues API -**Pfad**: `/api/masterdata/venues` -- Turnierplätze und Austragungsorte -- Platztypen und Abmessungen -- Bodenarten und Eignung - -**Controller**: `CountryController`, `BundeslandController`, `AltersklasseController`, `PlatzController` -**Endpunkte**: 37+ REST-Endpunkte - -## Gemeinsame API-Konventionen - -### HTTP-Status-Codes - -| Status Code | Bedeutung | Verwendung | -|-------------|-----------|------------| -| 200 | OK | Erfolgreiche GET/PUT-Anfragen | -| 201 | Created | Erfolgreiche POST-Anfragen | -| 204 | No Content | Erfolgreiche DELETE-Anfragen | -| 400 | Bad Request | Ungültige Anfragedaten | -| 401 | Unauthorized | Fehlende/ungültige Authentifizierung | -| 403 | Forbidden | Unzureichende Berechtigung | -| 404 | Not Found | Ressource nicht gefunden | -| 409 | Conflict | Duplikat oder Geschäftsregel-Verletzung | -| 422 | Unprocessable Entity | Validierungsfehler | -| 500 | Internal Server Error | Serverfehler | - -### Standard-Response-Format - -Alle API-Endpunkte verwenden ein einheitliches Response-Format: - -```json -{ - "data": {}, - "success": true, - "message": "Operation completed successfully", - "errors": [], - "timestamp": "2025-07-25T12:37:00Z" -} -``` - -#### Erfolgreiche Antwort -```json -{ - "data": { - "id": "123e4567-e89b-12d3-a456-426614174000", - "firstName": "Max", - "lastName": "Mustermann", - "email": "max@example.com" - }, - "success": true, - "message": null, - "errors": [], - "timestamp": "2025-07-25T12:37:00Z" -} -``` - -#### Fehler-Antwort -```json -{ - "data": null, - "success": false, - "message": "Validation failed", - "errors": [ - "Email address is required", - "First name must not be empty" - ], - "timestamp": "2025-07-25T12:37:00Z" -} -``` - -### Paginierung - -Für Listen-Endpunkte wird standardmäßig Paginierung unterstützt: - -**Query-Parameter**: -- `limit`: Maximale Anzahl Ergebnisse (Standard: 100, Maximum: 1000) -- `offset`: Anzahl zu überspringende Ergebnisse (Standard: 0) - -**Beispiel-Anfrage**: -``` -GET /api/members?limit=50&offset=100 -``` - -**Paginierte Antwort**: -```json -{ - "data": { - "content": [], - "page": 2, - "size": 50, - "totalElements": 1250, - "totalPages": 25, - "hasNext": true, - "hasPrevious": true - }, - "success": true, - "timestamp": "2025-07-25T12:37:00Z" -} -``` - -### Suchfunktionalität - -Viele Endpunkte unterstützen Suchfunktionalität: - -**Query-Parameter**: -- `search`: Suchbegriff für Textfelder -- `name`: Suche nach Namen (Teilübereinstimmung) -- `active`: Filter für aktive/inaktive Einträge - -**Beispiel**: -``` -GET /api/members?search=Schmidt&active=true&limit=20 -``` - -### Sortierung - -Sortierung wird über Query-Parameter gesteuert: - -**Query-Parameter**: -- `sort`: Sortierfeld (z.B. `name`, `createdAt`) -- `order`: Sortierrichtung (`asc` oder `desc`) - -**Beispiel**: -``` -GET /api/members?sort=lastName&order=asc -``` - -## Authentifizierung und Autorisierung - -### JWT Bearer Token - -Alle API-Endpunkte (außer öffentlichen) erfordern Authentifizierung über JWT Bearer Token: - -```http -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... -``` - -### Rollen und Berechtigungen - -| Rolle | Beschreibung | Berechtigungen | -|-------|--------------|----------------| -| ADMIN | Systemadministrator | Vollzugriff auf alle Ressourcen | -| TRAINER | Trainer/Ausbilder | Zugriff auf Pferde und Veranstaltungen | -| MEMBER | Vereinsmitglied | Zugriff auf eigene Daten | -| GUEST | Gast | Nur Lesezugriff auf öffentliche Daten | - -## Rate Limiting - -Zum Schutz der API vor Überlastung gelten folgende Limits: - -- **Authentifizierte Benutzer**: 1000 Anfragen/Stunde -- **Nicht authentifizierte Benutzer**: 100 Anfragen/Stunde -- **Burst-Limit**: 50 Anfragen/Minute - -Bei Überschreitung wird HTTP 429 (Too Many Requests) zurückgegeben. - -## Fehlerbehandlung - -### Validierungsfehler (422) - -```json -{ - "data": null, - "success": false, - "message": "Validation failed", - "errors": [ - { - "field": "email", - "message": "Email address is invalid", - "code": "INVALID_EMAIL" - }, - { - "field": "membershipNumber", - "message": "Membership number already exists", - "code": "DUPLICATE_MEMBERSHIP_NUMBER" - } - ], - "timestamp": "2025-07-25T12:37:00Z" -} -``` - -### Geschäftsregel-Verletzungen (409) - -```json -{ - "data": null, - "success": false, - "message": "Business rule violation", - "errors": [ - "Membership end date cannot be before start date" - ], - "timestamp": "2025-07-25T12:37:00Z" -} -``` - -## API-Dokumentation - -### Swagger/OpenAPI - -Die vollständige API-Dokumentation ist über Swagger UI verfügbar: - -- **Entwicklung**: http://localhost:8080/swagger-ui.html -- **Produktion**: https://api.meldestelle.at/swagger-ui.html - -### Postman Collections - -Postman Collections für alle API-Endpunkte sind verfügbar unter: -- [docs/postman/](../postman/) - -## Versionierung - -Die API verwendet URL-basierte Versionierung: - -- **Aktuelle Version**: v1 -- **Basis-URL**: `/api/v1/` -- **Deprecated Versionen**: Werden 12 Monate unterstützt - -## Monitoring und Observability - -### Health Checks - -``` -GET /actuator/health -``` - -### Metriken - -``` -GET /actuator/metrics -GET /actuator/prometheus -``` - -### API-Metriken - -- Request-Anzahl pro Endpunkt -- Response-Zeiten -- Fehlerquoten -- Rate-Limiting-Statistiken - -## Entwicklung und Testing - -### Lokale Entwicklung - -```bash -# API-Server starten -./gradlew bootRun - -# Swagger UI öffnen -open http://localhost:8080/swagger-ui.html -``` - -### API-Tests - -```bash -# Unit Tests -./gradlew test - -# Integration Tests -./gradlew integrationTest - -# API Tests mit Newman -newman run docs/postman/meldestelle-api.postman_collection.json -``` - -## Support und Kontakt - -- **Dokumentation**: [docs/api/](.) -- **Issue Tracker**: GitHub Issues -- **API-Status**: https://status.meldestelle.at - ---- - -**Letzte Aktualisierung**: 25. Juli 2025 -**API-Version**: v1.0 -**OpenAPI-Spezifikation**: 3.0.3 diff --git a/docs/api/generated/events-openapi.json b/docs/api/generated/events-openapi.json deleted file mode 100644 index ff641b72..00000000 --- a/docs/api/generated/events-openapi.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "openapi": "3.0.3", - "info": { - "title": "Events API", - "description": "REST API für events Verwaltung", - "version": "1.0.0", - "contact": { "name": "Meldestelle Development Team" } - }, - "servers": [ - { "url": "http://localhost:8080", "description": "Entwicklungs-Server" }, - { "url": "https://api.meldestelle.at", "description": "Produktions-Server" } - ], - "paths": {}, - "components": { - "securitySchemes": { - "bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" } - } - }, - "security": [ { "bearerAuth": [] } ] -} \ No newline at end of file diff --git a/docs/api/generated/horses-openapi.json b/docs/api/generated/horses-openapi.json deleted file mode 100644 index 51ea71fd..00000000 --- a/docs/api/generated/horses-openapi.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "openapi": "3.0.3", - "info": { - "title": "Horses API", - "description": "REST API für horses Verwaltung", - "version": "1.0.0", - "contact": { "name": "Meldestelle Development Team" } - }, - "servers": [ - { "url": "http://localhost:8080", "description": "Entwicklungs-Server" }, - { "url": "https://api.meldestelle.at", "description": "Produktions-Server" } - ], - "paths": {}, - "components": { - "securitySchemes": { - "bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" } - } - }, - "security": [ { "bearerAuth": [] } ] -} \ No newline at end of file diff --git a/docs/api/generated/masterdata-openapi.json b/docs/api/generated/masterdata-openapi.json deleted file mode 100644 index 5e0f0430..00000000 --- a/docs/api/generated/masterdata-openapi.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "openapi": "3.0.3", - "info": { - "title": "Masterdata API", - "description": "REST API für masterdata Verwaltung", - "version": "1.0.0", - "contact": { "name": "Meldestelle Development Team" } - }, - "servers": [ - { "url": "http://localhost:8080", "description": "Entwicklungs-Server" }, - { "url": "https://api.meldestelle.at", "description": "Produktions-Server" } - ], - "paths": {}, - "components": { - "securitySchemes": { - "bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" } - } - }, - "security": [ { "bearerAuth": [] } ] -} \ No newline at end of file diff --git a/docs/api/generated/members-openapi.json b/docs/api/generated/members-openapi.json deleted file mode 100644 index 127b8f84..00000000 --- a/docs/api/generated/members-openapi.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "openapi": "3.0.3", - "info": { - "title": "Members API", - "description": "REST API für members Verwaltung", - "version": "1.0.0", - "contact": { "name": "Meldestelle Development Team" } - }, - "servers": [ - { "url": "http://localhost:8080", "description": "Entwicklungs-Server" }, - { "url": "https://api.meldestelle.at", "description": "Produktions-Server" } - ], - "paths": {}, - "components": { - "securitySchemes": { - "bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" } - } - }, - "security": [ { "bearerAuth": [] } ] -} \ No newline at end of file diff --git a/docs/api/members-api.md b/docs/api/members-api.md deleted file mode 100644 index fd35688f..00000000 --- a/docs/api/members-api.md +++ /dev/null @@ -1,633 +0,0 @@ ---- -modul: members-api -status: active -last_reviewed: 2025-10-22 -review_cycle: 180d -summary: Dokumentation der Members‑API (Endpunkte, Parameter, Beispiele). -yt_epic: MP-1 -yt_issues: [] -tags: [api, members] ---- - -# Members‑API – Dokumentation - -## Überblick - -Die Members API bietet umfassende Funktionalität zur Verwaltung von Vereinsmitgliedern und deren Mitgliedschaftsdaten. Sie unterstützt vollständige CRUD-Operationen sowie spezialisierte Funktionen für Mitgliedschaftsverwaltung, Validierung und Statistiken. - -## Basis-Informationen - -- **Basis-URL**: `/api/members` -- **Controller**: `MemberController` -- **Authentifizierung**: JWT Bearer Token erforderlich -- **Content-Type**: `application/json` -- **Zeichenkodierung**: UTF-8 - -## Endpunkte Übersicht - -| Methode | Endpunkt | Beschreibung | -|---------|----------|--------------| -| GET | `/api/members` | Alle Mitglieder abrufen | -| GET | `/api/members/{id}` | Mitglied nach ID abrufen | -| GET | `/api/members/by-membership-number/{membershipNumber}` | Mitglied nach Mitgliedsnummer | -| GET | `/api/members/by-email/{email}` | Mitglied nach E-Mail | -| GET | `/api/members/stats` | Mitgliederstatistiken | -| POST | `/api/members` | Neues Mitglied erstellen | -| PUT | `/api/members/{id}` | Mitglied aktualisieren | -| DELETE | `/api/members/{id}` | Mitglied löschen | -| GET | `/api/members/expiring-memberships` | Ablaufende Mitgliedschaften | -| GET | `/api/members/by-date-range` | Mitglieder nach Datumsbereich | -| GET | `/api/members/validate/email/{email}` | E-Mail-Eindeutigkeit prüfen | -| GET | `/api/members/validate/membership-number/{membershipNumber}` | Mitgliedsnummer-Eindeutigkeit prüfen | - -## Detaillierte Endpunkt-Dokumentation - -### 1. Alle Mitglieder abrufen - -```http -GET /api/members -``` - -Ruft eine Liste aller Mitglieder ab mit optionaler Filterung und Suche. - -#### Query-Parameter - -| Parameter | Typ | Standard | Beschreibung | -|-----------|-----|----------|--------------| -| `activeOnly` | boolean | `true` | Nur aktive Mitglieder anzeigen | -| `limit` | integer | `100` | Maximale Anzahl Ergebnisse | -| `offset` | integer | `0` | Anzahl zu überspringende Ergebnisse | -| `search` | string | - | Suchbegriff für Mitgliedernamen | - -#### Beispiel-Anfrage - -```http -GET /api/members?activeOnly=true&limit=50&search=Schmidt -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... -``` - -#### Erfolgreiche Antwort (200 OK) - -```json -{ - "data": [ - { - "memberId": "123e4567-e89b-12d3-a456-426614174000", - "firstName": "Max", - "lastName": "Schmidt", - "email": "max.schmidt@example.com", - "phone": "+43 1 234 5678", - "dateOfBirth": "1985-03-15", - "membershipNumber": "M2024001", - "membershipStartDate": "2024-01-01", - "membershipEndDate": "2024-12-31", - "isActive": true, - "address": "Musterstraße 123, 1010 Wien", - "emergencyContact": "Anna Schmidt, +43 1 234 5679", - "createdAt": "2024-01-01T10:00:00Z", - "updatedAt": "2024-07-25T12:37:00Z" - } - ], - "success": true, - "message": null, - "errors": [], - "timestamp": "2025-07-25T12:37:00Z" -} -``` - -#### Fehler-Antworten - -- **500 Internal Server Error**: Serverfehler beim Abrufen der Mitglieder - -### 2. Mitglied nach ID abrufen - -```http -GET /api/members/{id} -``` - -Ruft ein spezifisches Mitglied anhand seiner eindeutigen ID ab. - -#### Pfad-Parameter - -| Parameter | Typ | Beschreibung | -|-----------|-----|--------------| -| `id` | UUID | Eindeutige Mitglieder-ID | - -#### Beispiel-Anfrage - -```http -GET /api/members/123e4567-e89b-12d3-a456-426614174000 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... -``` - -#### Erfolgreiche Antwort (200 OK) - -```json -{ - "data": { - "memberId": "123e4567-e89b-12d3-a456-426614174000", - "firstName": "Max", - "lastName": "Schmidt", - "email": "max.schmidt@example.com", - "phone": "+43 1 234 5678", - "dateOfBirth": "1985-03-15", - "membershipNumber": "M2024001", - "membershipStartDate": "2024-01-01", - "membershipEndDate": "2024-12-31", - "isActive": true, - "address": "Musterstraße 123, 1010 Wien", - "emergencyContact": "Anna Schmidt, +43 1 234 5679", - "createdAt": "2024-01-01T10:00:00Z", - "updatedAt": "2024-07-25T12:37:00Z" - }, - "success": true, - "message": null, - "errors": [], - "timestamp": "2025-07-25T12:37:00Z" -} -``` - -#### Fehler-Antworten - -- **400 Bad Request**: Ungültiges UUID-Format -- **404 Not Found**: Mitglied nicht gefunden -- **500 Internal Server Error**: Serverfehler - -### 3. Mitglied nach Mitgliedsnummer abrufen - -```http -GET /api/members/by-membership-number/{membershipNumber} -``` - -#### Pfad-Parameter - -| Parameter | Typ | Beschreibung | -|-----------|-----|--------------| -| `membershipNumber` | string | Mitgliedsnummer | - -#### Beispiel-Anfrage - -```http -GET /api/members/by-membership-number/M2024001 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... -``` - -### 4. Mitglied nach E-Mail abrufen - -```http -GET /api/members/by-email/{email} -``` - -#### Pfad-Parameter - -| Parameter | Typ | Beschreibung | -|-----------|-----|--------------| -| `email` | string | E-Mail-Adresse | - -#### Beispiel-Anfrage - -```http -GET /api/members/by-email/max.schmidt@example.com -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... -``` - -### 5. Mitgliederstatistiken abrufen - -```http -GET /api/members/stats -``` - -Ruft Statistiken über die Mitgliederdatenbank ab. - -#### Erfolgreiche Antwort (200 OK) - -```json -{ - "data": { - "totalActive": 1250, - "totalMembers": 1380 - }, - "success": true, - "message": null, - "errors": [], - "timestamp": "2025-07-25T12:37:00Z" -} -``` - -### 6. Neues Mitglied erstellen - -```http -POST /api/members -``` - -Erstellt ein neues Mitglied mit den bereitgestellten Daten. - -#### Request Body - -```json -{ - "firstName": "Max", - "lastName": "Mustermann", - "email": "max.mustermann@example.com", - "phone": "+43 1 234 5678", - "dateOfBirth": "1985-03-15", - "membershipNumber": "M2024002", - "membershipStartDate": "2024-08-01", - "membershipEndDate": "2024-12-31", - "isActive": true, - "address": "Beispielstraße 456, 1020 Wien", - "emergencyContact": "Anna Mustermann, +43 1 234 5679" -} -``` - -#### Erfolgreiche Antwort (201 Created) - -```json -{ - "data": { - "memberId": "456e7890-e89b-12d3-a456-426614174001", - "firstName": "Max", - "lastName": "Mustermann", - "email": "max.mustermann@example.com", - "phone": "+43 1 234 5678", - "dateOfBirth": "1985-03-15", - "membershipNumber": "M2024002", - "membershipStartDate": "2024-08-01", - "membershipEndDate": "2024-12-31", - "isActive": true, - "address": "Beispielstraße 456, 1020 Wien", - "emergencyContact": "Anna Mustermann, +43 1 234 5679", - "createdAt": "2025-07-25T12:37:00Z", - "updatedAt": "2025-07-25T12:37:00Z" - }, - "success": true, - "message": null, - "errors": [], - "timestamp": "2025-07-25T12:37:00Z" -} -``` - -#### Fehler-Antworten - -- **400 Bad Request**: Ungültige Anfragedaten -- **409 Conflict**: E-Mail oder Mitgliedsnummer bereits vorhanden -- **422 Unprocessable Entity**: Validierungsfehler - -### 7. Mitglied aktualisieren - -```http -PUT /api/members/{id} -``` - -Aktualisiert ein bestehendes Mitglied. - -#### Pfad-Parameter - -| Parameter | Typ | Beschreibung | -|-----------|-----|--------------| -| `id` | UUID | Eindeutige Mitglieder-ID | - -#### Request Body - -```json -{ - "firstName": "Max", - "lastName": "Mustermann", - "email": "max.mustermann.updated@example.com", - "phone": "+43 1 234 5678", - "dateOfBirth": "1985-03-15", - "membershipNumber": "M2024002", - "membershipStartDate": "2024-08-01", - "membershipEndDate": "2025-07-31", - "isActive": true, - "address": "Neue Straße 789, 1030 Wien", - "emergencyContact": "Anna Mustermann, +43 1 234 5679" -} -``` - -#### Erfolgreiche Antwort (200 OK) - -Gleiche Struktur wie bei der Erstellung, aber mit aktualisierten Daten und `updatedAt` Zeitstempel. - -#### Fehler-Antworten - -- **400 Bad Request**: Ungültige Anfragedaten oder UUID-Format -- **404 Not Found**: Mitglied nicht gefunden -- **409 Conflict**: E-Mail oder Mitgliedsnummer bereits vorhanden -- **500 Internal Server Error**: Serverfehler - -### 8. Mitglied löschen - -```http -DELETE /api/members/{id} -``` - -Löscht ein Mitglied aus dem System. - -#### Pfad-Parameter - -| Parameter | Typ | Beschreibung | -|-----------|-----|--------------| -| `id` | UUID | Eindeutige Mitglieder-ID | - -#### Beispiel-Anfrage - -```http -DELETE /api/members/123e4567-e89b-12d3-a456-426614174000 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... -``` - -#### Erfolgreiche Antwort (200 OK) - -```json -{ - "data": "Member deleted successfully", - "success": true, - "message": null, - "errors": [], - "timestamp": "2025-07-25T12:37:00Z" -} -``` - -#### Fehler-Antworten - -- **400 Bad Request**: Ungültiges UUID-Format -- **404 Not Found**: Mitglied nicht gefunden -- **500 Internal Server Error**: Serverfehler - -### 9. Ablaufende Mitgliedschaften abrufen - -```http -GET /api/members/expiring-memberships -``` - -Ruft Mitglieder ab, deren Mitgliedschaft in den nächsten Tagen abläuft. - -#### Query-Parameter - -| Parameter | Typ | Standard | Beschreibung | -|-----------|-----|----------|--------------| -| `daysAhead` | integer | `30` | Anzahl Tage im Voraus | - -#### Beispiel-Anfrage - -```http -GET /api/members/expiring-memberships?daysAhead=14 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... -``` - -#### Erfolgreiche Antwort (200 OK) - -```json -{ - "data": [ - { - "memberId": "123e4567-e89b-12d3-a456-426614174000", - "firstName": "Max", - "lastName": "Schmidt", - "email": "max.schmidt@example.com", - "membershipNumber": "M2024001", - "membershipEndDate": "2025-08-10", - "daysUntilExpiry": 14 - } - ], - "success": true, - "message": null, - "errors": [], - "timestamp": "2025-07-25T12:37:00Z" -} -``` - -### 10. Mitglieder nach Datumsbereich abrufen - -```http -GET /api/members/by-date-range -``` - -Ruft Mitglieder basierend auf einem Datumsbereich ab. - -#### Query-Parameter - -| Parameter | Typ | Erforderlich | Beschreibung | -|-----------|-----|--------------|--------------| -| `startDate` | string (YYYY-MM-DD) | Ja | Startdatum | -| `endDate` | string (YYYY-MM-DD) | Ja | Enddatum | -| `dateType` | string | Nein | `MEMBERSHIP_START_DATE` oder `MEMBERSHIP_END_DATE` | - -#### Beispiel-Anfrage - -```http -GET /api/members/by-date-range?startDate=2024-01-01&endDate=2024-12-31&dateType=MEMBERSHIP_START_DATE -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... -``` - -#### Fehler-Antworten - -- **400 Bad Request**: Ungültiges Datumsformat oder Datumstyp - -### 11. E-Mail-Eindeutigkeit validieren - -```http -GET /api/members/validate/email/{email} -``` - -Prüft, ob eine E-Mail-Adresse bereits verwendet wird. - -#### Pfad-Parameter - -| Parameter | Typ | Beschreibung | -|-----------|-----|--------------| -| `email` | string | Zu prüfende E-Mail-Adresse | - -#### Query-Parameter - -| Parameter | Typ | Beschreibung | -|-----------|-----|--------------| -| `excludeMemberId` | UUID | Mitglieder-ID zum Ausschließen (für Updates) | - -#### Beispiel-Anfrage - -```http -GET /api/members/validate/email/test@example.com?excludeMemberId=123e4567-e89b-12d3-a456-426614174000 -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... -``` - -#### Erfolgreiche Antwort (200 OK) - -```json -{ - "data": { - "isValid": true, - "isUnique": false, - "message": "Email address is already in use" - }, - "success": true, - "message": null, - "errors": [], - "timestamp": "2025-07-25T12:37:00Z" -} -``` - -### 12. Mitgliedsnummer-Eindeutigkeit validieren - -```http -GET /api/members/validate/membership-number/{membershipNumber} -``` - -Prüft, ob eine Mitgliedsnummer bereits verwendet wird. - -#### Pfad-Parameter - -| Parameter | Typ | Beschreibung | -|-----------|-----|--------------| -| `membershipNumber` | string | Zu prüfende Mitgliedsnummer | - -#### Query-Parameter - -| Parameter | Typ | Beschreibung | -|-----------|-----|--------------| -| `excludeMemberId` | UUID | Mitglieder-ID zum Ausschließen (für Updates) | - -## Datenmodelle - -### Member (Mitglied) - -```json -{ - "memberId": "UUID", - "firstName": "string", - "lastName": "string", - "email": "string", - "phone": "string (optional)", - "dateOfBirth": "string (YYYY-MM-DD, optional)", - "membershipNumber": "string", - "membershipStartDate": "string (YYYY-MM-DD)", - "membershipEndDate": "string (YYYY-MM-DD, optional)", - "isActive": "boolean", - "address": "string (optional)", - "emergencyContact": "string (optional)", - "createdAt": "string (ISO 8601)", - "updatedAt": "string (ISO 8601)" -} -``` - -### CreateMemberRequest - -```json -{ - "firstName": "string (required)", - "lastName": "string (required)", - "email": "string (required)", - "phone": "string (optional)", - "dateOfBirth": "string (YYYY-MM-DD, optional)", - "membershipNumber": "string (required)", - "membershipStartDate": "string (YYYY-MM-DD, required)", - "membershipEndDate": "string (YYYY-MM-DD, optional)", - "isActive": "boolean (default: true)", - "address": "string (optional)", - "emergencyContact": "string (optional)" -} -``` - -### UpdateMemberRequest - -Identisch mit `CreateMemberRequest`. - -### MemberStats - -```json -{ - "totalActive": "number", - "totalMembers": "number" -} -``` - -## Validierungsregeln - -### Pflichtfelder - -- `firstName`: Nicht leer -- `lastName`: Nicht leer -- `email`: Gültige E-Mail-Adresse, eindeutig -- `membershipNumber`: Nicht leer, eindeutig -- `membershipStartDate`: Gültiges Datum - -### Geschäftsregeln - -- E-Mail-Adresse muss eindeutig sein -- Mitgliedsnummer muss eindeutig sein -- `membershipEndDate` muss nach `membershipStartDate` liegen (falls angegeben) -- Telefonnummer muss gültiges Format haben (falls angegeben) - -## Fehlerbehandlung - -### Validierungsfehler (422 Unprocessable Entity) - -```json -{ - "data": null, - "success": false, - "message": "Validation failed", - "errors": [ - { - "field": "email", - "message": "Email address is invalid", - "code": "INVALID_EMAIL" - }, - { - "field": "membershipNumber", - "message": "Membership number already exists", - "code": "DUPLICATE_MEMBERSHIP_NUMBER" - } - ], - "timestamp": "2025-07-25T12:37:00Z" -} -``` - -### Häufige Fehlercodes - -| Code | Beschreibung | -|------|--------------| -| `MEMBER_NOT_FOUND` | Mitglied nicht gefunden | -| `INVALID_EMAIL` | Ungültige E-Mail-Adresse | -| `DUPLICATE_EMAIL` | E-Mail bereits vorhanden | -| `DUPLICATE_MEMBERSHIP_NUMBER` | Mitgliedsnummer bereits vorhanden | -| `INVALID_DATE_FORMAT` | Ungültiges Datumsformat | -| `INVALID_UUID_FORMAT` | Ungültiges UUID-Format | -| `MEMBERSHIP_DATE_CONFLICT` | Enddatum vor Startdatum | - -## Beispiel-Workflows - -### Neues Mitglied registrieren - -1. **E-Mail validieren**: `GET /api/members/validate/email/{email}` -2. **Mitgliedsnummer validieren**: `GET /api/members/validate/membership-number/{membershipNumber}` -3. **Mitglied erstellen**: `POST /api/members` - -### Mitglied aktualisieren - -1. **Aktuelles Mitglied abrufen**: `GET /api/members/{id}` -2. **E-Mail validieren** (falls geändert): `GET /api/members/validate/email/{email}?excludeMemberId={id}` -3. **Mitglied aktualisieren**: `PUT /api/members/{id}` - -### Ablaufende Mitgliedschaften verwalten - -1. **Ablaufende Mitgliedschaften abrufen**: `GET /api/members/expiring-memberships?daysAhead=30` -2. **Für jedes Mitglied**: Benachrichtigung senden oder Verlängerung anbieten - -## Rate Limiting - -- **Authentifizierte Anfragen**: 1000 Anfragen/Stunde -- **Validierungs-Endpunkte**: 100 Anfragen/Minute (zusätzliches Limit) - -## Caching - -- **GET-Anfragen**: 5 Minuten Cache (außer Validierungs-Endpunkte) -- **Statistiken**: 15 Minuten Cache -- **Cache-Invalidierung**: Bei POST/PUT/DELETE-Operationen - ---- - -**Letzte Aktualisierung**: 25. Juli 2025 -**API-Version**: v1.0 -**Controller-Version**: MemberController v1.0 diff --git a/docs/architecture/adr/0000-adr-template-de.md b/docs/architecture/adr/0000-adr-template-de.md index c0a177e1..1223e3ad 100644 --- a/docs/architecture/adr/0000-adr-template-de.md +++ b/docs/architecture/adr/0000-adr-template-de.md @@ -1,14 +1,15 @@ -# ADR-0000: Vorlage für Architekturentscheidungsaufzeichnung +# ADR-0000: Vorlage für Architekturentscheidungsaufzeichnungen ## Status [Vorgeschlagen | Akzeptiert | Veraltet | Ersetzt] -Falls ersetzt, fügen Sie einen Verweis auf die neue ADR ein: [ADR-XXXX](XXXX-filename.md) +Falls sie ersetzt, fügen Sie einen Verweis auf die neue ADR ein: `[ADR-XXX](XXX-filename.md)` ## Kontext -Beschreiben Sie den Kontext und die Problemstellung, z.B. in freier Form mit zwei bis drei Sätzen. Sie können das Problem auch in Form einer Frage formulieren. +Beschreiben Sie den Kontext und die Problemstellung, z. B. in freier Form mit zwei bis drei Sätzen. Sie können das +Problem auch in Form einer Frage formulieren. ## Entscheidung @@ -16,7 +17,9 @@ Beschreiben Sie die getroffene Entscheidung. ## Konsequenzen -Beschreiben Sie den resultierenden Kontext nach Anwendung der Entscheidung. Alle Konsequenzen sollten hier aufgeführt werden, nicht nur die "positiven". Eine bestimmte Entscheidung kann positive, negative und neutrale Konsequenzen haben, die alle das Team und das Projekt in der Zukunft beeinflussen. +Beschreiben Sie den resultierenden Kontext nach Anwendung der Entscheidung. Alle Konsequenzen sollten hier aufgeführt +werden, nicht nur die "positiven". Eine bestimmte Entscheidung kann positive, negative und neutrale Konsequenzen haben, +die alle das Team und das Projekt in der Zukunft beeinflussen. ## Betrachtete Alternativen diff --git a/docs/architecture/adr/0001-modular-architecture-de.md b/docs/architecture/adr/0001-modular-architecture-de.md index 9fa0b040..fa6f6f99 100644 --- a/docs/architecture/adr/0001-modular-architecture-de.md +++ b/docs/architecture/adr/0001-modular-architecture-de.md @@ -6,18 +6,21 @@ Akzeptiert ## Kontext -Das Meldestelle-System wurde ursprünglich als monolithische Anwendung entwickelt. Mit zunehmender Komplexität und Größe des Systems traten mehrere Herausforderungen auf: +Das Meldestelle-System wurde ursprünglich als monolithische Anwendung entwickelt. Mit zunehmender Komplexität und Größe +des Systems traten mehrere Herausforderungen auf: 1. Der Quellcode wurde schwer zu warten und zu verstehen -2. Entwicklungsteams mussten eng koordinieren, was die Entwicklung verlangsamte +2. Entwicklungsteams mussten sich eng koordinieren, was die Entwicklung verlangsamte 3. Die gesamte Anwendung musste skaliert werden, auch wenn nur bestimmte Teile mehr Ressourcen benötigten 4. Technologieentscheidungen wurden durch die monolithische Architektur eingeschränkt -Das Team musste entscheiden, ob es mit dem monolithischen Ansatz fortfahren oder zu einer modulareren Architektur migrieren sollte. +Das Team musste entscheiden, ob es mit dem monolithischen Ansatz fortfahren oder zu einer modularenen Architektur +migrieren sollte. ## Entscheidung -Wir haben uns entschieden, von einer monolithischen Struktur zu einer modularen Architektur zu migrieren und das System in die folgenden Module zu organisieren: +Wir haben uns entschieden, von einer monolithischen Struktur zu einer modularen Architektur zu migrieren und das System +in die folgenden Module zu organisieren: - **core**: Gemeinsame Kernkomponenten - **masterdata**: Stammdatenverwaltung @@ -27,7 +30,8 @@ Wir haben uns entschieden, von einer monolithischen Struktur zu einer modularen - **infrastructure**: Gemeinsame Infrastrukturkomponenten - **client**: Client-Anwendungen -Jedes Domänenmodul (masterdata, members, horses, events) folgt einem Clean-Architecture-Ansatz mit separaten API-, Anwendungs-, Domänen-, Infrastruktur- und Service-Schichten. +Jedes Domänenmodul (masterdata, members, horses, events) folgt einem Clean-Architecture-Ansatz mit separaten API-, +Anwendung-, Domänen-, Infrastruktur- und Service-Schichten. ## Konsequenzen @@ -55,14 +59,17 @@ Jedes Domänenmodul (masterdata, members, horses, events) folgt einem Clean-Arch ### Erweiterter Monolith -Wir haben in Betracht gezogen, die interne Struktur des Monolithen mit besseren Modulgrenzen zu verbessern, ihn aber als eine einzige bereitstellbare Einheit zu behalten. Dies wäre einfacher bereitzustellen gewesen, hätte aber die Probleme mit der Skalierung und Technologieflexibilität nicht gelöst. +Wir haben in Betracht gezogen, die interne Struktur des Monolithen mit besseren Modulgrenzen zu verbessern, ihn aber als +eine einzige bereitstellbare Einheit zu behalten. Dies wäre einfacher bereitzustellen gewesen, hätte aber die Probleme +mit der Skalierung und Technologieflexibilität nicht gelöst. ### Microservices -Wir haben einen feingranulareren Microservices-Ansatz mit vielen kleineren Diensten in Betracht gezogen. Dies hätte maximale Flexibilität geboten, aber für unsere aktuellen Bedürfnisse übermäßige Komplexität und betrieblichen Overhead eingeführt. +Wir haben einen feingranularen Microservices-Ansatz mit vielen kleineren Diensten in Betracht gezogen. Dies hätte +maximale Flexibilität geboten, aber für unsere aktuellen Bedürfnisse übermäßige Komplexität und betrieblichen Overhead +eingeführt. ## Referenzen -- [Migrationshinweise in README.md](../../../../README.md#aktuelle-migrationshinweise) -- [Modular Monoliths von Simon Brown](https://simonbrown.je/blog/modularity-and-microservices/) -- [Clean Architecture von Robert C. Martin](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) +- [Modular Monoliths von Simon Brown](https://meldestelle-pro.youtrack.cloud/api/files/526-8?sign=MTc2MjU2MDAwMDAwMHwyLTF8NTI2LTh8QldrSXd1MHoyUlE1T3lZSjBDNVh4Ry1zcGZZM1lWSlE0VXN2M2FQSXNDbw0K&updated=1762338956551) +- [Clean Architecture von Robert C. Martin](https://meldestelle-pro.youtrack.cloud/api/files/526-10?sign=MTc2MjU2MDAwMDAwMHwyLTF8NTI2LTEwfF9XbVdSakVpSW5HV1VjalY3UjhCMGFub2NIQXdPTUkyM3FFTnNTdGNIRmsNCg&updated=1762339225451) diff --git a/docs/architecture/adr/0002-domain-driven-design-de.md b/docs/architecture/adr/0002-domain-driven-design-de.md index 2c31afff..fabd71da 100644 --- a/docs/architecture/adr/0002-domain-driven-design-de.md +++ b/docs/architecture/adr/0002-domain-driven-design-de.md @@ -6,26 +6,31 @@ Akzeptiert ## Kontext -Mit der Weiterentwicklung des Meldestelle-Systems zur Bewältigung komplexer Geschäftsregeln für die Verwaltung von Reitsportveranstaltungen standen wir vor folgenden Herausforderungen: +Mit der Weiterentwicklung des Meldestelle-Systems zur Bewältigung komplexer Geschäftsregeln für die Verwaltung von +Reitsportveranstaltungen standen wir vor folgenden Herausforderungen: 1. Aufrechterhaltung einer klaren Trennung zwischen Geschäftslogik und technischen Belangen 2. Sicherstellung, dass das System das Verständnis der Domänenexperten vom Problemraum genau widerspiegelt 3. Schaffung einer gemeinsamen Sprache zwischen technischen und nicht-technischen Stakeholdern 4. Organisation des Codes in einer Weise, die die Geschäftsdomänen widerspiegelt -Wir benötigten einen architektonischen Ansatz, der diese Herausforderungen adressiert und eine solide Grundlage für die in [ADR-0001](0001-modular-architecture-de.md) beschriebene modulare Architektur bietet. +Wir benötigten einen architektonischen Ansatz, der diese Herausforderungen adressiert und eine solide Grundlage für die +in [ADR-0001](0001-modular-architecture-de.md) beschriebene modulare Architektur bietet. ## Entscheidung -Wir haben uns entschieden, Domain-Driven Design (DDD)-Prinzipien für die Organisation unseres Quellcodes und die Gestaltung unseres Systems zu übernehmen. Dies umfasst: +Wir haben uns entschieden, Domain-Driven Design (DDD)-Prinzipien für die Organisation unseres Quellcodes und die +Gestaltung unseres Systems zu übernehmen. Dies umfasst: 1. **Ubiquitäre Sprache**: Entwicklung einer gemeinsamen Sprache, die von Domänenexperten und Entwicklern geteilt wird 2. **Bounded Contexts**: Definition expliziter Grenzen zwischen verschiedenen Domänenbereichen (masterdata, members, horses, events) 3. **Schichtenarchitektur**: Organisation jedes Domänenmoduls in Schichten: + - Domänenschicht: Enthält Domänenmodelle, Entitäten, Wertobjekte und Domänendienste - Anwendungsschicht: Enthält Anwendungsdienste, Anwendungsfälle und Befehls-/Abfragehandler - Infrastrukturschicht: Enthält technische Implementierungen von Repositories, Messaging usw. - API-Schicht: Definiert die Schnittstellen für die Interaktion mit der Domäne + 4. **Aggregate**: Identifizierung von Aggregat-Roots, die Konsistenzgrenzen aufrechterhalten 5. **Repositories**: Verwendung des Repository-Musters zur Abstraktion des Datenzugriffs 6. **Domänen-Events**: Verwendung von Events zur Kommunikation zwischen Bounded Contexts @@ -55,14 +60,19 @@ Wir haben uns entschieden, Domain-Driven Design (DDD)-Prinzipien für die Organi ### Transaction Script Pattern -Wir haben die Verwendung eines einfacheren Transaction Script Patterns in Betracht gezogen, bei dem die Geschäftslogik um Prozeduren statt um Domänenobjekte organisiert ist. Dies wäre anfänglich einfacher zu implementieren gewesen, wäre aber mit zunehmender Komplexität der Geschäftslogik schwieriger zu warten geworden. +Wir haben die Verwendung eines einfacheren Transaction Script Patterns in Betracht gezogen, bei dem die Geschäftslogik +um Prozeduren statt um Domänenobjekte organisiert ist. Dies wäre anfänglich einfacher zu implementieren gewesen, wäre +aber mit zunehmender Komplexität der Geschäftslogik schwieriger zu warten geworden. ### Anemic Domain Model -Wir haben die Verwendung eines anämischen Domänenmodells in Betracht gezogen, bei dem Domänenobjekte einfache Datencontainer sind und die Geschäftslogik in separaten Serviceklassen liegt. Dies wäre für Entwickler mit CRUD-basiertem Hintergrund vertrauter gewesen, hätte aber nicht die Vorteile der Kapselung und der reichhaltigen Domänenmodellierung geboten. +Wir haben die Verwendung eines anämischen Domänenmodells in Betracht gezogen, bei dem Domänenobjekte einfache +Datencontainer sind und die Geschäftslogik in separaten Serviceklassen liegt. Dies wäre für Entwickler mit +CRUD-basiertem Hintergrund vertrauter gewesen, hätte aber nicht die Vorteile der Kapselung und der reichhaltigen +Domänenmodellierung geboten. ## Referenzen -- [Domain-Driven Design von Eric Evans](https://domainlanguage.com/ddd/) -- [Implementing Domain-Driven Design von Vaughn Vernon](https://vaughnvernon.co/?page_id=168) -- [Clean Architecture von Robert C. Martin](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) +- [Domain-Driven Design von Eric Evans](https://meldestelle-pro.youtrack.cloud/api/files/526-11?sign=MTc2MjU2MDAwMDAwMHwyLTF8NTI2LTExfE9KWGJodXhlT0Q0UEdYREpfNllaV1RXakU4YUZYbXZJb1JIdjJDVWVnZkUNCg&updated=1762339700786) +- [Implementing Domain-Driven Design von Vaughn Vernon](https://meldestelle-pro.youtrack.cloud/api/files/526-14?sign=MTc2MjU2MDAwMDAwMHwyLTF8NTI2LTE0fEx6NXJCT2NrMFNWMHRfc1pIbVRTc04xQ1Q2OEtEdzdMc1djaTNIMmRCNFENCg&updated=1762340142201) +- [Clean Architecture von Robert C. Martin](https://meldestelle-pro.youtrack.cloud/api/files/526-10?sign=MTc2MjU2MDAwMDAwMHwyLTF8NTI2LTEwfF9XbVdSakVpSW5HV1VjalY3UjhCMGFub2NIQXdPTUkyM3FFTnNTdGNIRmsNCg&updated=1762339225451) diff --git a/docs/architecture/adr/0003-microservices-architecture-de.md b/docs/architecture/adr/0003-microservices-architecture-de.md index 8e99aedc..2418fcc9 100644 --- a/docs/architecture/adr/0003-microservices-architecture-de.md +++ b/docs/architecture/adr/0003-microservices-architecture-de.md @@ -6,17 +6,21 @@ Akzeptiert ## Kontext -Nach der Entscheidung, eine modulare Architektur ([ADR-0001](0001-modular-architecture-de.md)) und Domain-Driven Design ([ADR-0002](0002-domain-driven-design-de.md)) zu übernehmen, mussten wir die Deployment-Strategie für unsere Module festlegen. Zu den wichtigsten Überlegungen gehörten: +Nach der Entscheidung, eine modulare Architektur ([ADR-0001](0001-modular-architecture-de.md)) und Domain-Driven +Design ([ADR-0002](0002-domain-driven-design-de.md)) zu übernehmen, mussten wir die Deployment-Strategie für unsere +Module festlegen. Zu den wichtigsten Überlegungen gehörten: 1. Unabhängige Skalierbarkeit verschiedener Teile des Systems 2. Deployment-Unabhängigkeit, um Teams zu ermöglichen, Änderungen ohne Koordination mit anderen Teams zu veröffentlichen -3. Technologieunabhängigkeit, um verschiedenen Diensten die Verwendung unterschiedlicher Technologien nach Bedarf zu ermöglichen +3. Technologieunabhängigkeit, um verschiedenen Diensten die Verwendung unterschiedlicher Technologien nach Bedarf zu + ermöglichen 4. Resilienz, um sicherzustellen, dass Ausfälle in einem Teil des Systems nicht das gesamte System beeinträchtigen -5. Klare Zuständigkeitsgrenzen, die mit den Teamverantwortlichkeiten übereinstimmen +5. Klare Zuständigkeitsgrenzen, die mit den Team-Verantwortlichkeiten übereinstimmen ## Entscheidung -Wir haben uns entschieden, eine Microservices-Architektur zu implementieren, bei der jedes Domänenmodul als separater Dienst bereitgestellt wird: +Wir haben uns entschieden, eine Microservices-Architektur zu implementieren, bei der jedes Domänenmodul als separater +Dienst bereitgestellt wird: - **masterdata-service**: Verwaltet Stammdaten wie Standorte, Disziplinen usw. - **members-service**: Verwaltet Mitgliederregistrierung und -profile @@ -24,34 +28,39 @@ Wir haben uns entschieden, eine Microservices-Architektur zu implementieren, bei - **events-service**: Verwaltet Veranstaltungserstellung, -planung und -anmeldungen Jeder Dienst: + - Hat sein eigenes Datenbankschema - Ist unabhängig bereitstellbar - Kommuniziert mit anderen Diensten über klar definierte APIs und nachrichtenbasierte Kommunikation - Ist für seine eigene Domänenlogik gemäß DDD-Prinzipien verantwortlich Wir haben auch unterstützende Infrastrukturdienste implementiert: + - **gateway**: API-Gateway für Routing und Authentifizierung -- **auth**: Authentifizierungs- und Autorisierungsdienst (Keycloak) +- **auth**: Authentifizierung- und Autorisierungsdienst (Keycloak) - **cache**: Caching-Dienst (Redis) - **messaging**: Message Broker für die Kommunikation zwischen Diensten (Kafka) -- **monitoring**: Überwachungs- und Beobachtbarkeitsdienste +- **monitoring**: Überwachung- und Beobachtbarkeitsdienste ## Konsequenzen ### Positive - **Unabhängige Skalierbarkeit**: Jeder Dienst kann basierend auf seinen spezifischen Lastanforderungen skaliert werden -- **Deployment-Unabhängigkeit**: Teams können Änderungen an ihren Diensten bereitstellen, ohne sich mit anderen Teams abstimmen zu müssen +- **Deployment-Unabhängigkeit**: Teams können Änderungen an ihren Diensten bereitstellen, ohne sich mit anderen Teams + abstimmen zu müssen - **Technologieflexibilität**: Verschiedene Dienste können je nach Bedarf unterschiedliche Technologien verwenden - **Resilienz**: Ausfälle in einem Dienst beeinträchtigen nicht unbedingt andere -- **Klare Zuständigkeit**: Jeder Dienst hat klare Zuständigkeitsgrenzen, die mit den Teamverantwortlichkeiten übereinstimmen -- **Kleinere Codebasen**: Jeder Dienst hat eine kleinere, fokussiertere Codebasis +- **Klare Zuständigkeit**: Jeder Dienst hat klare Zuständigkeitsgrenzen, die mit den Team-Verantwortlichkeiten + übereinstimmen +- **Kleinere Codebasen**: Jeder Dienst hat eine kleinere, fokussierte Codebasis ### Negative - **Komplexität verteilter Systeme**: Microservices bringen die Herausforderungen verteilter Systeme mit sich - **Betrieblicher Mehraufwand**: Mehr Dienste müssen bereitgestellt, überwacht und gewartet werden -- **Herausforderungen bei der Datenkonsistenz**: Die Aufrechterhaltung der Datenkonsistenz über Dienste hinweg erfordert sorgfältiges Design +- **Herausforderungen bei der Datenkonsistenz**: Die Aufrechterhaltung der Datenkonsistenz über Dienste hinweg erfordert + sorgfältiges Design - **Netzwerklatenz**: Die Kommunikation zwischen Diensten fügt Latenz hinzu - **Testkomplexität**: End-to-End-Tests werden komplexer @@ -64,14 +73,19 @@ Wir haben auch unterstützende Infrastrukturdienste implementiert: ### Modularer Monolith -Wir haben die Implementierung eines modularen Monolithen in Betracht gezogen, bei dem alle Module als eine einzige Anwendung bereitgestellt würden, jedoch mit klaren Modulgrenzen. Dies wäre einfacher bereitzustellen gewesen und hätte die Herausforderungen verteilter Systeme vermieden, hätte aber nicht die Vorteile der unabhängigen Skalierbarkeit und Bereitstellung geboten. +Wir haben die Implementierung eines modularen Monolithen in Betracht gezogen, bei dem alle Module als eine einzige +Anwendung bereitgestellt werden, jedoch mit klaren Modulgrenzen. Dies wäre einfacher bereitzustellen gewesen und hätte +die Herausforderungen verteilter Systeme vermieden, hätte aber nicht die Vorteile der unabhängigen Skalierbarkeit und +Bereitstellung geboten. ### Service-basierte Architektur -Wir haben eine dienstbasierte Architektur mit weniger, größeren Diensten in Betracht gezogen, die mehrere Domänenbereiche umfassen würden. Dies hätte den betrieblichen Overhead reduziert, aber es schwieriger gemacht, klare Domänengrenzen und unabhängige Skalierbarkeit aufrechtzuerhalten. +Wir haben eine Dienst-basierte Architektur mit weniger bzw. größeren Diensten in Betracht gezogen, die mehrere +Domänenbereiche umfassen würden. Dies hätte den betrieblichen Overhead reduziert, aber es schwieriger gemacht, klare +Domänengrenzen und unabhängige Skalierbarkeit aufrechtzuerhalten. ## Referenzen -- [Microservices von Martin Fowler](https://martinfowler.com/articles/microservices.html) -- [Building Microservices von Sam Newman](https://samnewman.io/books/building_microservices/) -- [Microservices Patterns von Chris Richardson](https://microservices.io/book) +- [Microservices von Martin Fowler](https://meldestelle-pro.youtrack.cloud/api/files/526-16?sign=MTc2MjU2MDAwMDAwMHwyLTF8NTI2LTE2fFViVXRuTGdXcFhIcFRwdG03ZHlSZEZ5ZEc2MG5VVVB3SGJ4OUFRRG82QlENCg&updated=1762340608616) +- [Building Microservices von Sam Newman](https://meldestelle-pro.youtrack.cloud/api/files/526-17?sign=MTc2MjU2MDAwMDAwMHwyLTF8NTI2LTE3fDdjaXJoZ0NlWlQ1MW9tZ0UwdC1fLVZEZ0pUcFF6QnNScTcxN0Z6YlVUazQNCg&updated=1762340788707) +- [Microservices Patterns von Chris Richardson](https://meldestelle-pro.youtrack.cloud/api/files/526-20?sign=MTc2MjU2MDAwMDAwMHwyLTF8NTI2LTIwfDM5S08yMXVENmFRa1NPaEROQlR1N1Nvc0lWWUJXU0hCR1JYTVJXSDA2RGcNCg&updated=1762340989301) diff --git a/docs/architecture/adr/0004-event-driven-communication-de.md b/docs/architecture/adr/0004-event-driven-communication-de.md index 7c2c965c..d4abd781 100644 --- a/docs/architecture/adr/0004-event-driven-communication-de.md +++ b/docs/architecture/adr/0004-event-driven-communication-de.md @@ -6,7 +6,8 @@ Akzeptiert ## Kontext -Mit der Einführung einer Microservices-Architektur ([ADR-0003](0003-microservices-architecture-de.md)) mussten wir die effektivste Art der Kommunikation zwischen den Diensten bestimmen. Zu den wichtigsten Überlegungen gehörten: +Mit der Einführung einer Microservices-Architektur ([ADR-0003](0003-microservices-architecture-de.md)) mussten wir die +effektivste Art der Kommunikation zwischen den Diensten bestimmen. Zu den wichtigsten Überlegungen gehörten: 1. Lose Kopplung zwischen Diensten, um ihre Unabhängigkeit zu erhalten 2. Asynchrone Verarbeitungsfähigkeiten zur Verbesserung der Systemresilienz und Skalierbarkeit @@ -16,15 +17,17 @@ Mit der Einführung einer Microservices-Architektur ([ADR-0003](0003-microservic ## Entscheidung -Wir haben uns entschieden, ein ereignisgesteuertes Kommunikationsmuster mit Apache Kafka als Message Broker zu implementieren. Die wichtigsten Aspekte dieses Ansatzes umfassen: +Wir haben uns entschieden, ein ereignisgesteuertes Kommunikationsmuster mit Apache Kafka als Message Broker zu +implementieren. Die wichtigsten Aspekte dieses Ansatzes umfassen: 1. **Domänen-Ereignisse**: Dienste veröffentlichen Domänen-Ereignisse, wenn signifikante Zustandsänderungen auftreten 2. **Event Sourcing**: Für kritische Daten speichern wir alle Ereignisse, die zum aktuellen Zustand geführt haben 3. **Nachrichtenbasierte Kommunikation**: Dienste kommunizieren hauptsächlich über asynchrone Nachrichten 4. **Choreographie**: Komplexe Workflows werden durch Ereignis-Choreographie statt Orchestrierung implementiert -5. **Ereignis-Schema-Registry**: Wir führen eine Registry von Ereignis-Schemas, um Kompatibilität zu gewährleisten +5. **Ereignis-Schema-Registry**: Wir führen eine Registry von Ereignis-Schemas durch, um Kompatibilität zu gewährleisten Die Implementierung umfasst: + - Kafka als zentraler Message Broker - Schema-Registry zur Verwaltung von Ereignis-Schemas - Ereignis-Handler in jedem Dienst zur Verarbeitung von Ereignissen aus anderen Diensten @@ -57,19 +60,25 @@ Die Implementierung umfasst: ### Synchrone REST-APIs -Wir haben die Verwendung synchroner REST-APIs als primären Kommunikationsmechanismus in Betracht gezogen. Dies wäre einfacher zu implementieren und zu debuggen gewesen, hätte aber zu einer engeren Kopplung zwischen Diensten und verringerter Resilienz geführt. +Wir haben die Verwendung synchroner REST-APIs als primären Kommunikationsmechanismus in Betracht gezogen. Dies wäre +einfacher zu implementieren und zu debuggen gewesen, hätte aber zu einer engeren Kopplung zwischen Diensten und +verringerter Resilienz geführt. ### Request-Response-Messaging -Wir haben ein Request-Response-Messaging-Muster in Betracht gezogen, bei dem Dienste Anfragen senden und auf Antworten warten. Dies hätte einige der Vorteile asynchroner Kommunikation geboten und gleichzeitig ein vertrautes Request-Response-Modell beibehalten, hätte aber das Publish-Subscribe-Muster nicht so effektiv unterstützt. +Wir haben ein Request-Response-Messaging-Muster in Betracht gezogen, bei dem Dienste Anfragen senden und auf Antworten +warten. Dies hätte einige der Vorteile asynchroner Kommunikation geboten und gleichzeitig ein vertrautes +Request-Response-Modell beibehalten, hätte aber das Publish-Subscribe-Muster nicht so effektiv unterstützt. ### GraphQL-Federation -Wir haben die Verwendung von GraphQL-Federation zur Zusammensetzung von APIs aus mehreren Diensten in Betracht gezogen. Dies hätte eine einheitliche API für Clients geboten, hätte aber eine enge Kopplung zwischen Diensten beibehalten und asynchrone Workflows nicht so effektiv unterstützt. +Wir haben die Verwendung von GraphQL-Federation zur Zusammensetzung von APIs aus mehreren Diensten in Betracht gezogen. +Dies hätte eine einheitliche API für Clients geboten, hätte aber eine enge Kopplung zwischen Diensten beibehalten und +asynchrone Workflows nicht so effektiv unterstützt. ## Referenzen -- [Enterprise Integration Patterns](https://www.enterpriseintegrationpatterns.com/) -- [Event-Driven Architecture von Martin Fowler](https://martinfowler.com/articles/201701-event-driven.html) +- [Enterprise Integration Patterns](https://meldestelle-pro.youtrack.cloud/api/files/526-22?sign=MTc2MjU2MDAwMDAwMHwyLTF8NTI2LTIyfGNVMDU5cXJTbi0wRDRvWngwLXhTc0RDTzZZOTZBaTFtQzBpZ3RVYjBxTVkNCg&updated=1762342095790) +- [Event-Driven Architecture von Martin Fowler](https://meldestelle-pro.youtrack.cloud/api/files/526-24?sign=MTc2MjU2MDAwMDAwMHwyLTF8NTI2LTI0fDJsSEFZbnJzRWpCOWlkU3BIZ0ZOTDRIeDlmY0F2NUhMZklseE9WNnBhWkUNCg&updated=1762342654487) - [Apache Kafka Dokumentation](https://kafka.apache.org/documentation/) -- [Event Sourcing Pattern](https://docs.microsoft.com/de-de/azure/architecture/patterns/event-sourcing) +- [Event Sourcing Pattern](https://meldestelle-pro.youtrack.cloud/api/files/526-26?sign=MTc2MjU2MDAwMDAwMHwyLTF8NTI2LTI2fEZURXo4SVVIbmtwcUExVFlab3BLZkVyRFlZS3B1bTFNX1ROMFR4aElBMW8NCg&updated=1762343212733) diff --git a/docs/architecture/adr/0005-polyglot-persistence-de.md b/docs/architecture/adr/0005-polyglot-persistence-de.md index c03c75dd..622b7df6 100644 --- a/docs/architecture/adr/0005-polyglot-persistence-de.md +++ b/docs/architecture/adr/0005-polyglot-persistence-de.md @@ -6,52 +6,64 @@ Akzeptiert ## Kontext -Als Teil unserer Microservices-Architektur ([ADR-0003](0003-microservices-architecture-de.md)) mussten wir die am besten geeignete Datenspeicherstrategie bestimmen. Verschiedene Teile unseres Systems haben unterschiedliche Anforderungen an die Datenspeicherung: +Als Teil unserer Microservices-Architektur ([ADR-0003](0003-microservices-architecture-de.md)) mussten wir die am besten +geeignete Datenspeicherstrategie bestimmen. Verschiedene Teile unseres Systems haben unterschiedliche Anforderungen an +die Datenspeicherung: 1. Einige Daten erfordern starke Konsistenz und komplexe Beziehungen 2. Einige Daten müssen mit sehr geringer Latenz abgerufen werden 3. Einige Daten sind ereignisbasiert und müssen in einem Zeitreihenformat gespeichert werden 4. Verschiedene Dienste haben unterschiedliche Datenzugriffsmuster -Ein Einheitsansatz für die Datenspeicherung würde Kompromisse erzwingen, die die Leistung, Skalierbarkeit oder Entwicklungsproduktivität beeinträchtigen könnten. +Ein Einheitsansatz für die Datenspeicherung würde Kompromisse erzwingen, die die Leistung, Skalierbarkeit oder +Entwicklungsproduktivität beeinträchtigen könnten. ## Entscheidung -Wir haben uns entschieden, eine polyglotte Persistenzstrategie zu implementieren, die verschiedene Datenspeichertechnologien für verschiedene Anwendungsfälle nutzt: +Wir haben uns entschieden, eine polyglotte Persistenzstrategie zu implementieren, die verschiedene +Datenspeichertechnologien für verschiedene Anwendungsfälle nutzt: + +1. **PostgresQL**: Als primäre relationale Datenbank zur Speicherung strukturierter Daten mit komplexen Beziehungen -1. **PostgreSQL**: Als primäre relationale Datenbank zur Speicherung strukturierter Daten mit komplexen Beziehungen - Wird von allen Domänendiensten für ihre primäre Datenspeicherung verwendet - Jeder Dienst hat sein eigenes Datenbankschema, um Isolation zu gewährleisten 2. **Redis**: Als verteilter Cache für schnellen Datenzugriff + - Wird für das Caching häufig abgerufener Daten verwendet - Wird für die Sitzungsspeicherung verwendet - Wird für Rate-Limiting verwendet 3. **Kafka**: Als Event-Store für Event Sourcing + - Wird zur Speicherung von Domänenereignissen für Event Sourcing verwendet - Ermöglicht Event-Replay zum Wiederaufbau des Zustands -4. **Elasticsearch** (geplant): Für Volltextsuchfunktionen +4. **Elasticsearch** (geplant): für Volltextsuchfunktionen + - Wird für erweiterte Suchfunktionen über mehrere Domänen hinweg verwendet werden -Jeder Dienst ist für die Verwaltung seiner eigenen Datenspeicherung verantwortlich, und Dienste dürfen nicht direkt auf die Datenbanken anderer Dienste zugreifen. +Jeder Dienst ist für die Verwaltung seiner eigenen Datenspeicherung verantwortlich, und Dienste dürfen nicht direkt auf +die Datenbanken anderer Dienste zugreifen. ## Konsequenzen ### Positive - **Optimierte Leistung**: Jede Art von Daten wird in der am besten geeigneten Speichertechnologie gespeichert -- **Skalierbarkeit**: Verschiedene Speichertechnologien können unabhängig voneinander basierend auf ihren spezifischen Anforderungen skaliert werden +- **Skalierbarkeit**: Verschiedene Speichertechnologien können unabhängig voneinander basierend auf ihren spezifischen + Anforderungen skaliert werden - **Flexibilität**: Teams können die beste Speichertechnologie für ihre spezifischen Anwendungsfälle wählen - **Resilienz**: Probleme mit einer Speichertechnologie beeinträchtigen nicht unbedingt andere ### Negative - **Betriebliche Komplexität**: Mehrere Speichertechnologien müssen bereitgestellt, überwacht und gewartet werden -- **Herausforderungen bei der Datenkonsistenz**: Die Aufrechterhaltung der Konsistenz über verschiedene Speichertechnologien hinweg erfordert sorgfältiges Design +- **Herausforderungen bei der Datenkonsistenz**: Die Aufrechterhaltung der Konsistenz über verschiedene + Speichertechnologien hinweg erfordert sorgfältiges Design - **Lernkurve**: Teams müssen mit mehreren Speichertechnologien vertraut sein -- **Komplexität bei Backup und Wiederherstellung**: Verschiedene Speichertechnologien haben unterschiedliche Backup- und Wiederherstellungsverfahren +- **Komplexität bei Backup und Wiederherstellung**: Verschiedene Speichertechnologien haben unterschiedliche Backup- und + Wiederherstellungsverfahren ### Neutral @@ -62,20 +74,27 @@ Jeder Dienst ist für die Verwaltung seiner eigenen Datenspeicherung verantwortl ### Einzelne Datenbank für alle Dienste -Wir haben die Verwendung einer einzelnen PostgreSQL-Datenbank mit separaten Schemas für jeden Dienst in Betracht gezogen. Dies hätte den Betrieb vereinfacht, hätte aber einen Single Point of Failure geschaffen und hätte es uns nicht ermöglicht, für verschiedene Datenzugriffsmuster zu optimieren. +Wir haben die Verwendung einer einzelnen PostgresQL-Datenbank mit separaten Schemas für jeden Dienst in Betracht +gezogen. Dies hätte den Betrieb vereinfacht, hätte aber einen Single Point of Failure geschaffen und hätte es uns nicht +ermöglicht, für verschiedene Datenzugriffsmuster zu optimieren. ### Datenbank pro Dienst, gleiche Technologie -Wir haben die Verwendung von PostgreSQL für alle Dienste, aber mit separaten Datenbanken in Betracht gezogen. Dies hätte Dienstisolation geboten und gleichzeitig den Betrieb vereinfacht, hätte es uns aber nicht ermöglicht, für verschiedene Datenzugriffsmuster zu optimieren. +Wir haben die Verwendung von PostgresQL für alle Dienste, aber mit separaten Datenbanken in Betracht gezogen. Dies hätte +Dienstisolation geboten und gleichzeitig den Betrieb vereinfacht, hätte es uns aber nicht ermöglicht, für verschiedene +Datenzugriffsmuster zu optimieren. ### Vollständig verteilter NoSQL-Ansatz -Wir haben die Verwendung eines vollständig verteilten NoSQL-Ansatzes mit Technologien wie Cassandra oder MongoDB für die gesamte Datenspeicherung in Betracht gezogen. Dies hätte eine ausgezeichnete Skalierbarkeit geboten, hätte aber die Modellierung komplexer Beziehungen erschwert und hätte signifikante Änderungen an unseren Entwicklungspraktiken erfordert. +Wir haben die Verwendung eines vollständig verteilten NoSQL-Ansatzes mit Technologien wie Cassandra oder MongoDB für die +gesamte Datenspeicherung in Betracht gezogen. Dies hätte eine ausgezeichnete Skalierbarkeit geboten, hätte aber die +Modellierung komplexer Beziehungen erschwert und hätte signifikante Änderungen an unseren Entwicklungspraktiken +erfordert. ## Referenzen -- [Polyglot Persistence von Martin Fowler](https://martinfowler.com/bliki/PolyglotPersistence.html) -- [PostgreSQL Dokumentation](https://www.postgresql.org/docs/) +- [Polyglot Persistence von Martin Fowler](https://meldestelle-pro.youtrack.cloud/api/files/526-28?sign=MTc2MjU2MDAwMDAwMHwyLTF8NTI2LTI4fERaVkFWVmlEbVJJbTVZSFE2SWlrbmRydHNaeDdxZUFaRExpdkNxbk9wVEkNCg&updated=1762343428460) +- [PostgresQL Dokumentation](https://www.postgresql.org/docs/) - [Redis Dokumentation](https://redis.io/documentation) - [Apache Kafka Dokumentation](https://kafka.apache.org/documentation/) -- [Elasticsearch Dokumentation](https://www.elastic.co/guide/index.html) +- [Elasticsearch Dokumentation](https://www.elastic.co/docs/solutions/search) diff --git a/docs/architecture/adr/0006-authentication-authorization-keycloak-de.md b/docs/architecture/adr/0006-authentication-authorization-keycloak-de.md index 35839bc9..2975d2f7 100644 --- a/docs/architecture/adr/0006-authentication-authorization-keycloak-de.md +++ b/docs/architecture/adr/0006-authentication-authorization-keycloak-de.md @@ -6,7 +6,8 @@ Akzeptiert ## Kontext -Als Teil unserer Microservices-Architektur ([ADR-0003](0003-microservices-architecture-de.md)) benötigten wir eine robuste und zentralisierte Lösung für Authentifizierung und Autorisierung. Zu den wichtigsten Anforderungen gehörten: +Als Teil unserer Microservices-Architektur ([ADR-0003](0003-microservices-architecture-de.md)) benötigten wir eine +robuste und zentralisierte Lösung für Authentifizierung und Autorisierung. Zu den wichtigsten Anforderungen gehörten: 1. Single Sign-On (SSO) über alle Dienste und Anwendungen hinweg 2. Unterstützung für mehrere Authentifizierungsmethoden (Benutzername/Passwort, OAuth, SAML) @@ -14,13 +15,15 @@ Als Teil unserer Microservices-Architektur ([ADR-0003](0003-microservices-archit 4. Benutzerverwaltungsfunktionen einschließlich Selbstregistrierung und Profilmanagement 5. Integration mit externen Identitätsanbietern 6. Sicherheits-Best-Practices einschließlich Passwortrichtlinien und Kontosperrung -7. Token-basierte Authentifizierung für die Kommunikation zwischen Diensten +7. Tokenbasierte Authentifizierung für die Kommunikation zwischen Diensten -Die Implementierung dieser Funktionen von Grund auf wäre zeitaufwändig und fehleranfällig und würde Ressourcen von unserer Kerngeschäftsfunktionalität abziehen. +Die Implementierung dieser Funktionen von Grund auf wäre zeitaufwändig und fehleranfällig und würde Ressourcen von +unserer Kerngeschäftsfunktionalität abziehen. ## Entscheidung -Wir haben uns entschieden, Keycloak (Version 23.0) als unsere Identitäts- und Zugriffsverwaltungslösung zu verwenden. Keycloak ist eine Open-Source-Identitäts- und Zugriffsverwaltungslösung, die Folgendes bietet: +Wir haben uns entschieden, Keycloak (Version 26.4.2) als unsere Identitäts- und Zugriffsverwaltungslösung zu verwenden. +Keycloak ist eine Open-Source-Identitäts- und Zugriffsverwaltungslösung, die Folgendes bietet: 1. **Benutzerauthentifizierung**: Mehrere Authentifizierungsmethoden und -abläufe 2. **Benutzerföderation**: Integration mit LDAP, Active Directory und anderen Benutzerspeichern @@ -28,10 +31,11 @@ Wir haben uns entschieden, Keycloak (Version 23.0) als unsere Identitäts- und Z 4. **Single Sign-On**: Über alle Anwendungen und Dienste hinweg 5. **Feingranulare Autorisierung**: Rollen- und attributbasierte Zugriffssteuerung 6. **Benutzerverwaltung**: Selbstregistrierung, Profilmanagement, Passwortrichtlinien -7. **Token-basierte Authentifizierung**: JWT-Tokens für die Kommunikation zwischen Diensten +7. **Tokenbasierte Authentifizierung**: JWT-Tokens für die Kommunikation zwischen Diensten Unsere Implementierung umfasst: -- Keycloak-Server, der als containerisierter Dienst bereitgestellt wird + +- Keycloak-Server, der als containerised Dienst bereitgestellt wird - Integration mit unserem API-Gateway für die Token-Validierung - Client-Adapter für unsere Dienste und Anwendungen - Benutzerdefinierte Themes und E-Mail-Vorlagen @@ -56,26 +60,31 @@ Unsere Implementierung umfasst: ### Neutral -- **Konfigurationsbedarf**: Keycloak erfordert sorgfältige Konfiguration, um mit unseren Sicherheitsanforderungen übereinzustimmen +- **Konfigurationsbedarf**: Keycloak erfordert sorgfältige Konfiguration, um mit unseren Sicherheitsanforderungen + übereinzustimmen - **Upgrade-Management**: Keycloak-Upgrades müssen sorgfältig verwaltet werden ## Betrachtete Alternativen ### Eigener Authentifizierungsdienst -Wir haben in Betracht gezogen, unseren eigenen Authentifizierungsdienst zu entwickeln. Dies hätte uns vollständige Kontrolle über die Implementierung gegeben, hätte aber erheblichen Entwicklungsaufwand und laufende Wartung erfordert. +Wir haben in Betracht gezogen, unseren eigenen Authentifizierungsdienst zu entwickeln. Dies hätte uns vollständige +Kontrolle über die Implementierung gegeben, hätte aber erheblichen Entwicklungsaufwand und laufende Wartung erfordert. ### Auth0 -Wir haben die Verwendung von Auth0, einer kommerziellen Identity-as-a-Service (IDaaS)-Lösung, in Betracht gezogen. Auth0 hätte ähnliche Funktionen wie Keycloak mit weniger betrieblichem Overhead geboten, hätte aber laufende Kosten und potenzielle Anbieterabhängigkeit mit sich gebracht. +Wir haben die Verwendung von Auth0, einer kommerziellen Identity-as-a-Service (IDaaS)-Lösung, in Betracht gezogen. Auth0 +hätte ähnliche Funktionen wie Keycloak mit weniger betrieblichem Overhead geboten, hätte aber laufende Kosten und +potenzielle Anbieterabhängigkeit mit sich gebracht. ### Spring Security mit JWT -Wir haben die Verwendung von Spring Security mit JWT-Tokens für Authentifizierung und Autorisierung in Betracht gezogen. Dies hätte sich gut in unsere Spring-basierten Dienste integriert, hätte aber mehr Entwicklungsaufwand erfordert und hätte nicht die umfassenden Identitätsverwaltungsfunktionen von Keycloak geboten. +Wir haben die Verwendung von Spring Security mit JWT-Tokens für Authentifizierung und Autorisierung in Betracht gezogen. +Dies hätte sich gut in unsere Spring-basierten Dienste integriert, hätte aber mehr Entwicklungsaufwand erfordert und +hätte nicht die umfassenden Identitätsverwaltungsfunktionen von Keycloak geboten. ## Referenzen - [Keycloak Dokumentation](https://www.keycloak.org/documentation) - [OAuth 2.0 und OpenID Connect](https://oauth.net/2/) - [JWT (JSON Web Tokens)](https://jwt.io/) -- [Absicherung von Microservices mit Keycloak](https://www.keycloak.org/docs/latest/securing_apps/) diff --git a/docs/architecture/adr/0007-api-gateway-pattern-de.md b/docs/architecture/adr/0007-api-gateway-pattern-de.md index 900813a9..f052d361 100644 --- a/docs/architecture/adr/0007-api-gateway-pattern-de.md +++ b/docs/architecture/adr/0007-api-gateway-pattern-de.md @@ -6,7 +6,8 @@ Akzeptiert ## Kontext -Mit unserer Microservices-Architektur ([ADR-0003](0003-microservices-architecture-de.md)) standen wir vor mehreren Herausforderungen im Zusammenhang mit der Client-Service-Kommunikation: +Mit unserer Microservices-Architektur ([ADR-0003](0003-microservices-architecture-de.md)) standen wir vor mehreren +Herausforderungen im Zusammenhang mit der Client-Service-Kommunikation: 1. Clients müssten die Standorte und Schnittstellen mehrerer Dienste kennen 2. Verschiedene Clients (Web, Desktop, Mobil) müssten mehrere Aufrufe an verschiedene Dienste tätigen @@ -15,14 +16,18 @@ Mit unserer Microservices-Architektur ([ADR-0003](0003-microservices-architectur 5. API-Versionierung und Abwärtskompatibilität müssten über alle Dienste hinweg verwaltet werden 6. Die Netzwerksicherheit wäre komplexer, wenn mehrere Dienste direkt exponiert würden -Wir benötigten eine Lösung, die die Client-Service-Kommunikation vereinfachen und gleichzeitig diese Herausforderungen adressieren würde. +Wir benötigten eine Lösung, die die Client-Service-Kommunikation vereinfachen und gleichzeitig diese Herausforderungen +adressieren würde. ## Entscheidung -Wir haben uns entschieden, das API-Gateway-Muster mit Spring Cloud Gateway (Spring Boot) zu implementieren. Das API-Gateway dient als einziger Eingangspunkt für alle Client-Anfragen und bietet die folgenden Funktionen: +Wir haben uns entschieden, das API-Gateway-Muster mit Spring Cloud Gateway (Spring Boot) zu implementieren. Das +API-Gateway dient als einziger Eingangspunkt für alle Client-Anfragen und bietet die folgenden Funktionen: 1. **Anfrage-Routing**: Deklaratives Routing auf Basis von Prädikaten und Filtern -2. **Authentifizierung und Autorisierung**: Integration mit Keycloak ([ADR-0006](0006-authentication-authorization-keycloak-de.md)), Validierung über JWKs; Kontext-Propagation zu Backends +2. **Authentifizierung und Autorisierung**: Integration mit + Keycloak ([ADR-0006](0006-authentication-authorization-keycloak-de.md)), Validierung über JWKs; Kontext-Propagation + zu Backends 3. **Rate-Limiting**: Token-Bucket/Burst-Limits via Gateway-Filter (optional Redis-gestützt) 4. **Anfrage/Antwort-Transformation**: Manipulation von Headern/Body per Global/Gateway-Filtern 5. **Logging und Monitoring**: Micrometer/Prometheus, strukturierte Logs, verteiltes Tracing @@ -31,7 +36,8 @@ Wir haben uns entschieden, das API-Gateway-Muster mit Spring Cloud Gateway (Spri 8. **Service-Discovery**: Integration mit Consul/Eureka Unsere Implementierung umfasst: -- Eine Spring-Cloud-Gateway-Applikation (Spring Boot), containerisiert + +- Eine Spring-Cloud-Gateway-Applikation (Spring Boot), containerized - Integration mit Keycloak für Authentifizierung und Autorisierung - Benutzerdefinierte Global/Gateway-Filter für Rate-Limiting, Logging, Monitoring - Micrometer/Actuator für Metriken und Health @@ -50,9 +56,9 @@ Unsere Implementierung umfasst: ### Negative - **Single Point of Failure**: Das Gateway wird zu einer kritischen Komponente, die hochverfügbar sein muss -- **Leistungs-Overhead**: Anfragen durchlaufen einen zusätzlichen Netzwerk-Hop +- **Leistung-Overhead**: Anfragen durchlaufen einen zusätzlichen Netzwerk-Hop - **Komplexität**: Das Gateway muss eine breite Palette von Funktionalitäten handhaben -- **Entwicklungs-Engpass**: Änderungen am Gateway können Koordination über Teams hinweg erfordern +- **Entwicklung-Engpass**: Änderungen am Gateway können Koordination über Teams hinweg erfordern ### Neutral @@ -63,18 +69,24 @@ Unsere Implementierung umfasst: ### Direkte Client-zu-Service-Kommunikation -Wir haben in Betracht gezogen, Clients die direkte Kommunikation mit Diensten zu ermöglichen. Dies hätte den Netzwerk-Hop durch das Gateway eliminiert, hätte aber die Client-Entwicklung komplexer gemacht und hätte die Implementierung von Querschnittsbelangen in jedem Dienst erfordert. +Wir haben in Betracht gezogen, Clients die direkte Kommunikation mit Diensten zu ermöglichen. Dies hätte den +Netzwerk-Hop durch das Gateway eliminiert, hätte aber die Client-Entwicklung komplexer gemacht und hätte die +Implementierung von Querschnittsbelangen in jedem Dienst erfordert. ### Backend for Frontend (BFF)-Muster -Wir haben die Implementierung separater Backend for Frontend (BFF)-Dienste für jeden Client-Typ in Betracht gezogen. Dies hätte mehr clientspezifische Optimierungen ermöglicht, hätte aber den Entwicklungs- und Betriebsaufwand erhöht. +Wir haben die Implementierung separater Backend for Frontend (BFF)-Dienste für jeden Client-Typ in Betracht gezogen. +Dies hätte mehr klientenspezifische Optimierungen ermöglicht, hätte aber den Entwicklungs- und Betriebsaufwand erhöht. ### Service Mesh -Wir haben die Verwendung eines Service Mesh wie Istio oder Linkerd zur Handhabung der Service-zu-Service-Kommunikation in Betracht gezogen. Dies hätte viele der gleichen Vorteile für die Service-zu-Service-Kommunikation geboten, hätte aber die Herausforderungen der Client-zu-Service-Kommunikation nicht so effektiv adressiert. +Wir haben die Verwendung eines Service Mesh wie Istio oder Linkerd zur Handhabung der Service-zu-Service-Kommunikation +in Betracht gezogen. Dies hätte viele der gleichen Vorteile für die Service-zu-Service-Kommunikation geboten, hätte aber +die Herausforderungen der Client-zu-Service-Kommunikation nicht so effektiv adressiert. ## Referenzen -- https://spring.io/projects/spring-cloud-gateway -- https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html -- https://www.keycloak.org/documentation -- https://microservices.io/patterns/apigateway.html + +- +- +- +- diff --git a/docs/architecture/adr/0008-multiplatform-client-applications-de.md b/docs/architecture/adr/0008-multiplatform-client-applications-de.md index dd8c6cfb..fc7cb19d 100644 --- a/docs/architecture/adr/0008-multiplatform-client-applications-de.md +++ b/docs/architecture/adr/0008-multiplatform-client-applications-de.md @@ -13,68 +13,83 @@ Unser System benötigt Client-Anwendungen für verschiedene Benutzerrollen und P 3. Potenzielle zukünftige mobile Anwendungen für den Zugriff unterwegs Die Entwicklung und Wartung separater Codebasen für jede Plattform würde erfordern: + - Doppelte Implementierung von Geschäftslogik und UI-Komponenten - Mehrere Teams mit unterschiedlicher Plattformexpertise - Koordination, um eine konsistente Benutzererfahrung über Plattformen hinweg zu gewährleisten - Höhere Wartungskosten, da Funktionen und Fehlerbehebungen mehrfach implementiert werden müssten -Wir benötigten eine Lösung, die es uns ermöglicht, Code über Plattformen hinweg zu teilen und gleichzeitig auf jeder Plattform eine native Benutzererfahrung zu bieten. +Wir benötigten eine Lösung, die es uns ermöglicht, Code über Plattformen hinweg zu teilen und gleichzeitig auf jeder +Plattform eine native Benutzererfahrung zu bieten. ## Entscheidung Wir haben uns entschieden, Kotlin Multiplatform und Compose Multiplatform für unsere Client-Anwendungen zu verwenden: -1. **Kotlin Multiplatform**: Ermöglicht die gemeinsame Nutzung von Geschäftslogik, Datenmodellen und API-Client-Code über Plattformen hinweg -2. **Compose Multiplatform**: Bietet ein deklaratives UI-Framework, das auf Desktop-, Web- und mobilen Plattformen funktioniert +1. **Kotlin Multiplatform**: Ermöglicht die gemeinsame Nutzung von Geschäftslogik, Datenmodellen und API-Client-Code + über Plattformen hinweg +2. **Compose Multiplatform**: Bietet ein deklaratives UI-Framework, das auf Desktop-, Web- und mobilen Plattformen + funktioniert Unsere Implementierung umfasst: + - **common-ui**: Gemeinsame UI-Komponenten und Geschäftslogik - **desktop-app**: Desktop-Anwendung für Administratoren und Veranstaltungsorganisatoren - **web-app**: Web-Anwendung für Mitglieder und Pferdebesitzer Die Architektur folgt einem Model-View-ViewModel (MVVM)-Muster: + - **Model**: Gemeinsame Datenmodelle und Repository-Implementierungen - **ViewModel**: Gemeinsame Geschäftslogik und Zustandsverwaltung - **View**: Plattformspezifische UI-Implementierungen mit Compose Multiplatform -Wir verwenden einen modularen Ansatz, bei dem plattformspezifischer Code minimiert wird und der größte Teil des Codes über Plattformen hinweg geteilt wird. +Wir verwenden einen modularen Ansatz, bei dem plattformspezifischer Code minimiert wird und der größte Teil des Codes +über Plattformen hinweg geteilt wird. ## Konsequenzen ### Positive -- **Code-Sharing**: Wesentliche Teile des Codes werden über Plattformen hinweg geteilt, was Duplizierung reduziert +- **Codesharing**: Wesentliche Teile des Codes werden über Plattformen hinweg geteilt, was Duplizierung reduziert - **Konsistente Benutzererfahrung**: UI-Komponenten und Verhalten sind über Plattformen hinweg konsistent - **Einheitliche Sprache**: Kotlin wird für alle Plattformen verwendet, was die Entwicklung vereinfacht -- **Reduzierter Wartungsaufwand**: Fehlerbehebungen und Funktionen können einmal implementiert und über Plattformen hinweg angewendet werden +- **Reduzierter Wartungsaufwand**: Fehlerbehebungen und Funktionen können einmal implementiert und über Plattformen + hinweg angewendet werden - **Team-Effizienz**: Entwickler können mit demselben Skillset an mehreren Plattformen arbeiten ### Negative - **Lernkurve**: Kotlin Multiplatform und Compose Multiplatform haben eine Lernkurve - **Reife**: Compose Multiplatform entwickelt sich noch weiter, besonders für Web-Targets -- **Leistungsüberlegungen**: Es kann im Vergleich zu plattformnativen Lösungen zu Leistungs-Overhead kommen +- **Leistungsüberlegungen**: Es kann im Vergleich zu Plattform nativen Lösungen zu Leistungs-Overhead kommen - **Plattformspezifische Funktionen**: Einige plattformspezifische Funktionen können schwieriger zu implementieren sein - **Debugging-Komplexität**: Das Debugging über Plattformen hinweg kann komplexer sein ### Neutral - **Komplexität des Build-Systems**: Das Build-System ist mit Multiplatform-Targets komplexer -- **Abhängigkeitsverwaltung**: Die Verwaltung von Abhängigkeiten über Plattformen hinweg erfordert sorgfältige Überlegung +- **Abhängigkeitsverwaltung**: Die Verwaltung von Abhängigkeiten über Plattformen hinweg erfordert sorgfältige + Überlegungen ## Betrachtete Alternativen ### Separate native Anwendungen -Wir haben die Entwicklung separater nativer Anwendungen für jede Plattform in Betracht gezogen (Java/JavaFX für Desktop, JavaScript/React für Web). Dies hätte die beste Leistung und Zugriff auf Plattformfunktionen geboten, hätte aber eine doppelte Implementierung von Geschäftslogik und UI-Komponenten erfordert. +Wir haben die Entwicklung separater nativer Anwendungen für jede Plattform in Betracht gezogen (Java/JavaFX für Desktop, +JavaScript/React für Web). Dies hätte die beste Leistung und Zugriff auf Plattformfunktionen geboten, hätte aber eine +doppelte Implementierung von Geschäftslogik und UI-Komponenten erfordert. ### React Native -Wir haben die Verwendung von React Native für Mobile und Web mit einer separaten Desktop-Anwendung in Betracht gezogen. Dies hätte Code-Sharing zwischen Mobile und Web ermöglicht, hätte aber immer noch eine separate Desktop-Lösung erfordert und hätte JavaScript-Expertise erfordert. +Wir haben die Verwendung von React Native für Mobile und Web mit einer separaten Desktop-Anwendung in Betracht gezogen. +Dies hätte Codesharing zwischen Mobile und Web ermöglicht, hätte aber immer noch eine separate Desktop-Lösung erfordert +und hätte JavaScript-Expertise erfordert. ### Flutter -Wir haben die Verwendung von Flutter für alle Plattformen in Betracht gezogen. Flutter bietet gute plattformübergreifende Unterstützung, hätte aber das Erlernen von Dart erfordert und hätte weniger Integration mit unseren Kotlin-basierten Backend-Diensten gehabt. +Wir haben die Verwendung von Flutter für alle Plattformen in Betracht gezogen. Flutter bietet gute +plattformübergreifende Unterstützung, hätte aber das Erlernen von Dart erfordert und hätte weniger Integration mit +unseren Kotlin-basierten Backend-Diensten gehabt. ## Referenzen diff --git a/docs/how-to/branchschutz-und-pr-workflow.md b/docs/how-to/branchschutz-und-pr-workflow.md index 37558912..e6b2b681 100644 --- a/docs/how-to/branchschutz-und-pr-workflow.md +++ b/docs/how-to/branchschutz-und-pr-workflow.md @@ -5,14 +5,16 @@ last_reviewed: 2025-10-22 review_cycle: 180d summary: Empfehlungen für Branchschutz, PR-Ablauf und Naming-Konventionen. yt_epic: MP-1 -yt_issues: [] +yt_issues: [ ] --- # Branchschutz & Pull-Request Workflow -Diese Anleitung beschreibt einen einfachen, robusten Flow für `main` mit kurzen Feature-Branches und klaren Qualitätschecks. +Diese Anleitung beschreibt einen einfachen, robusten Flow für `main` mit kurzen Feature-Branches und klaren +Qualitätschecks. ## 1) Branch-Naming + - Feature: `feature/` - Bugfix: `fix/` - Docs: `docs/` @@ -20,11 +22,13 @@ Diese Anleitung beschreibt einen einfachen, robusten Flow für `main` mit kurzen Optional: Issue-Key voranstellen, z. B. `feature/MP-7-doku-konsolidieren`. ## 2) Pull Request (PR) + - PR-Titel nach Conventional Commits (kurz): `docs(api): Front‑Matter vereinheitlicht (MP-7)` - Beschreibung kurz mit Bulletpoints; DoD-Checkliste abhaken (Template vorhanden) - CI muss grün sein (Backend + Docs) ## 3) Branchschutz (GitHub Einstellungen → Branches → main) + - Require a pull request before merging - Require status checks to pass before merging - aktivieren: `CI Docs`, `CI` (Backend falls vorhanden) @@ -34,16 +38,20 @@ Optional: Issue-Key voranstellen, z. B. `feature/MP-7-doku-konsolidieren`. - Disallow force pushes, Disallow deletions ## 4) Commits & YouTrack + - Commit-Message enthält Issue-Key (z. B. `MP-7`) → erleichtert Nachverfolgung - In Doku-Front‑Matter `yt_epic`/`yt_issues` pflegen -- Optional: GitHub Secrets `YT_URL`, `YT_TOKEN` setzen → CI validiert verlinkte Issues, und `youtrack-sync.yml` kommentiert beim Merge automatisch ins Issue +- Optional: GitHub Secrets `YT_URL`, `YT_TOKEN` setzen → CI validiert verlinkte Issues, und `youtrack-sync.yml` + kommentiert beim Merge automatisch ins Issue ## 5) Definition of Done (Auszug) + - Doku aktuell (README/ADR/C4/API) - Front‑Matter valide (`modul`, `status`, `summary`, optional `last_reviewed`, `review_cycle`, `yt_*`) - Links funktionieren (CI link-check grün) - Tests grün ## 6) Lokale Tipps + - Vor dem Push: `markdownlint`, `vale` lokal laufen lassen (optional via pre-commit hooks) - kleine, häufige PRs statt großer Monster-PRs diff --git a/docs/how-to/deploy-proxmox-nginx.md b/docs/how-to/deploy-proxmox-nginx.md deleted file mode 100644 index fd0d3a87..00000000 --- a/docs/how-to/deploy-proxmox-nginx.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -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/kdoc-style.md b/docs/how-to/kdoc-style.md new file mode 100644 index 00000000..d3f636c9 --- /dev/null +++ b/docs/how-to/kdoc-style.md @@ -0,0 +1,66 @@ +--- +owner: project-maintainers +status: active +review_cycle: 365d +last_reviewed: 2025-10-28 +summary: KDoc-Styleguide für die Meldestelle. Mindeststandards für KDoc, damit Dokka lesbare API-Doku generiert. +bc: infrastructure +doc_type: how-to +--- + +# KDoc-Styleguide (Kurzfassung) + +Dieser Styleguide definiert die wichtigsten Regeln für KDoc-Kommentare in Kotlin-Projekten der Meldestelle. Ziel: +Verständliche, konsistente API-Dokumentation via Dokka (GFM/HTML). + +## Grundregeln + +- Sprache: Deutsch für Fließtexte; Code/Bezeichner bleiben Englisch. +- Jeder public class, interface, object, enum, public function und public property erhält einen KDoc-Block. +- KDoc beginnt mit einem vollständigen, aussagekräftigen Satz in der dritten Person. +- Beispiele und wichtige Hinweise als kurze Absätze oder Listen, keine Romane. + +## Struktur eines KDoc-Blocks + +```kotlin +/** + * Beschreibt prägnant, was das Element macht und warum es existiert. + * + * Details: Optionale Erläuterung von Parametern, Nebenwirkungen, Fehlerfällen. + * + * @param id Eindeutige Kennung des Members + * @return Das gefundene Objekt oder null, wenn nicht vorhanden + * @throws IllegalArgumentException Falls Parameter ungültig sind + */ +fun findMember(id: MemberId): Member? +``` + +## Tags + +- @param: Für jeden Parameter bei public Funktionen +- @return: Wenn Rückgabewert semantisch relevant ist +- @throws: Relevante Exceptions dokumentieren +- @since, @see: Sparsam verwenden, wenn es wirklichen Mehrwert bringt + +## Stil & Sprache + +- Klar, knapp, aktiv. Keine Redundanz. +- Domänenbegriffe verwenden (BCs: members, horses, events, masterdata, infrastructure). +- Keine Interna oder Secrets dokumentieren. + +## Beispielschnipsel + +```kotlin +/** Erstellt einen neuen Event und persistiert ihn transaktional. */ +fun createEvent(cmd: CreateEventCommand): EventId +``` + +## Dokka-Hinweise + +- Dokka erzeugt GFM (Markdown) unter build/dokka/gfm und HTML unter build/dokka/html. +- Source-Link führt auf GitHub (main-Branch). Prüfe Links in der CI. + +## Review + +- PR-Checklist: "KDoc vollständig?" anhaken, wenn neue public APIs hinzugekommen sind. +- Vale/markdownlint gelten nur für .md; KDoc wird redaktionell in Code-Reviews geprüft. diff --git a/docs/how-to/start-local.md b/docs/how-to/start-local.md index 5dce27a9..be84aed0 100644 --- a/docs/how-to/start-local.md +++ b/docs/how-to/start-local.md @@ -4,6 +4,8 @@ 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. +bc: infrastructure +doc_type: how-to --- # How-To: Lokale Umgebung starten (Quickstart) @@ -11,35 +13,42 @@ summary: Kürzeste Anleitung, um das komplette System lokal zu starten und zu pr 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 +- Web App: +- API Gateway: (Health: /actuator/health) +- Keycloak (Auth): +- Consul (Service Discovery): + +Weitere Ports findest du unter: [reference/ports-and-urls.md](../reference/ports-and-urls.md) ## Health-Checks + ```bash # Gateway curl -i http://localhost:8081/actuator/health @@ -49,19 +58,25 @@ curl -i http://localhost:4000/health || true ``` ## Auth (Keycloak) -- Admin-Login (default): http://localhost:8180 + +- Admin-Login (default): - 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. + +- Dienste sind nicht erreichbar → Container 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). +- CORS im Browser → API über das Gateway () 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 + make full-down + # oder spezifisch: + make services-down + make clients-down + make infrastructure-down ``` diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 9c934353..00000000 --- a/docs/index.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -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 deleted file mode 100644 index 0d3a85ed..00000000 --- a/docs/now/README.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -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 deleted file mode 100644 index fea6decb..00000000 --- a/docs/now/TEMPLATE.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -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 deleted file mode 100644 index 607bebd7..00000000 --- a/docs/now/current.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -owner: stefan -status: active -timeframe: 2025-10-15 → 2025-10-29 -last_reviewed: 2025-10-15 -review_cycle: 7d -summary: Git-Strategie (Trunk-based) + GitHub Actions CI/CD etablieren; Branchschutz, Releases per Tags; optional Images & Deploy zu Proxmox. ---- - -# Aktuelle Initiative: Git-Flow & GitHub Actions Strategy - -## 1) Vision (Was?) -Ein schlanker, verlässlicher Dev-Flow: kurze Feature-Branches → PR → main, automatisierte CI, Releases per Tag; optional Build & Deploy. -- In Scope: Branchschutz `main`, CI aktualisieren, Release-Tags, (optional) Image-Build & Deploy-Workflow -- Out of Scope: Mehrstufige Environments/Canary, komplexe Monorepo-Pipelines - -## 2) Why (Warum so?) -Weniger Overhead als GitFlow, klare Qualitätstore via CI, reproduzierbare Releases mit Tags. Ziel: schneller und sicherer liefern. -- Erfolg messbar an: CI grün auf PRs, geschützter `main`, erster Release-Tag `v0.1.0`, optional erfolgreicher Deploy-Run - -## 3) How (Wie umsetzen?) -- Trunk-based: `main` geschützt; kurzlebige Branches `feature/*`, `fix/*`, `docs/*`, Squash-Merge only; PR-Titel nach Conventional Commits -- CI (CI.yml): Trigger auf PR/push zu `main`; Schritte: Gradle Build, Docs-Validation, optional Testreports-Artefakte; Concurrency aktiv -- Releases: zunächst manuell taggen (`vX.Y.Z`); später optional `release-please` -- Images: optional GHCR Build & Push bei Tags `v*` (Matrix für gateway, members, horses, events, masterdata, web) -- Deploy: optional via SSH zu Proxmox (`docker compose pull && up -d`); Secrets im Repo setzen - -## 4) Plan (Was ist jetzt zu tun?) -- [ ] Branch umbenennen: `structur-umbau` → `feature/structur-umbau`; pushen und PR nach `main` eröffnen -- [ ] Branchschutz für `main` setzen: PR erforderlich, Required Checks (`CI`), „Squash & Merge only“, lineare History -- [ ] CI-Workflow anpassen: vorhandenes `.github/workflows/build.yml` auf PR/push nur `main`, Concurrency, Testreports-Upload -- [ ] (Optional) Deploy-Workflow anlegen: `.github/workflows/deploy.yml` (SSH); Secrets setzen: `PROD_SSH_HOST`, `PROD_SSH_USER`, `PROD_SSH_KEY` -- [ ] (Optional) Image-Build & Push bei Tags (`v*`) zu GHCR einführen -- [ ] (Optional) Release-Strategie entscheiden: manuelle Tags vs. `release-please`; ggf. Workflow hinzufügen -- [ ] Cloudflare/Nginx prüfen: DNS (Proxy ON), SSL/TLS „Full (strict)“, Origin-Zertifikat, HTTPS-Serverblöcke aktivieren -- [ ] Smoke-Tests: Health über Domains prüfen (`/actuator/health`, `/health`) - -## 5) Status & Nächster Fokus -- Status: active -- Nächster Fokus (heute): Branch umbenennen → PR; Branchschutz setzen; CI-Workflow auf `main` fokussieren - -## 6) Referenzen -- CI-Workflow aktuell: `.github/workflows/build.yml` -- Docs-Validator: `scripts/validation/validate-docs.sh` -- Nginx Beispiel: `docs/proxmox-nginx/meldestelle.conf` -- Überblick/Start: `docs/overview/system-overview.md`, `docs/how-to/start-local.md` diff --git a/docs/overview/system-overview.md b/docs/overview/system-overview.md deleted file mode 100644 index 50d9d6e0..00000000 --- a/docs/overview/system-overview.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -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/proxmox-nginx/meldestelle.conf b/docs/proxmox-nginx/meldestelle.conf deleted file mode 100644 index b3d7fc2c..00000000 --- a/docs/proxmox-nginx/meldestelle.conf +++ /dev/null @@ -1,181 +0,0 @@ -# =================================================================== -# Nginx Host-Level Konfiguration für Proxmox-Server -# Meldestelle Project - Reverse Proxy Setup -# =================================================================== -# Installation auf Proxmox: -# sudo cp meldestelle.conf /etc/nginx/sites-available/ -# sudo ln -s /etc/nginx/sites-available/meldestelle.conf /etc/nginx/sites-enabled/ -# sudo nginx -t && sudo systemctl reload nginx -# =================================================================== - -# Upstream-Definitionen für Container-Services -upstream meldestelle-web-app { - server localhost:4000; -} - -upstream meldestelle-desktop-vnc { - server localhost:6080; -} - -upstream meldestelle-api-gateway { - server localhost:8081; -} - -# =================================================================== -# Web-App (Hauptanwendung) -# =================================================================== -server { - listen 80; - server_name meldestelle.yourdomain.com; - - # Security Headers - add_header X-Frame-Options "SAMEORIGIN" always; - add_header X-Content-Type-Options "nosniff" always; - add_header X-XSS-Protection "1; mode=block" always; - add_header Referrer-Policy "strict-origin-when-cross-origin" always; - - # Logging - access_log /var/log/nginx/meldestelle-web.access.log; - error_log /var/log/nginx/meldestelle-web.error.log; - - # Reverse Proxy zur Web-App - location / { - proxy_pass http://meldestelle-web-app; - 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; - proxy_set_header X-Forwarded-Host $server_name; - - # Timeouts - proxy_connect_timeout 60s; - proxy_send_timeout 60s; - proxy_read_timeout 60s; - - # Buffering - proxy_buffering on; - proxy_buffer_size 4k; - proxy_buffers 8 4k; - } - - # Health-Check Endpoint - location /health { - proxy_pass http://meldestelle-web-app/health; - access_log off; - } -} - -# =================================================================== -# Desktop-VNC (noVNC Web-Interface) -# =================================================================== -server { - listen 80; - server_name vnc.meldestelle.yourdomain.com; - - # Logging - access_log /var/log/nginx/meldestelle-vnc.access.log; - error_log /var/log/nginx/meldestelle-vnc.error.log; - - # Reverse Proxy zum VNC-Container - location / { - proxy_pass http://meldestelle-desktop-vnc; - 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; - - # WebSocket Support für noVNC - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Origin ""; - - # VNC-spezifische Timeouts - proxy_connect_timeout 60s; - proxy_send_timeout 3600s; - proxy_read_timeout 3600s; - - # Buffering deaktivieren für Real-time - proxy_buffering off; - } -} - -# =================================================================== -# API-Gateway (Direkter Zugriff) -# =================================================================== -server { - listen 80; - server_name api.meldestelle.yourdomain.com; - - # Logging - access_log /var/log/nginx/meldestelle-api.access.log; - error_log /var/log/nginx/meldestelle-api.error.log; - - # CORS Headers für API-Zugriff - add_header Access-Control-Allow-Origin "*" always; - add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always; - add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With" always; - - # Reverse Proxy zum API-Gateway - location / { - # Handle preflight requests - if ($request_method = 'OPTIONS') { - add_header Access-Control-Allow-Origin "*"; - add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"; - add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With"; - add_header Access-Control-Max-Age 86400; - add_header Content-Length 0; - add_header Content-Type text/plain; - return 204; - } - - proxy_pass http://meldestelle-api-gateway; - 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; - - # API-spezifische Timeouts - proxy_connect_timeout 30s; - proxy_send_timeout 60s; - proxy_read_timeout 60s; - } - - # Health-Check Endpoint - location /actuator/health { - proxy_pass http://meldestelle-api-gateway/actuator/health; - access_log off; - } -} - -# =================================================================== -# SSL/HTTPS Konfiguration (Optional - für Cloudflare) -# =================================================================== -# Uncomment für HTTPS mit Let's Encrypt oder Cloudflare: -# -# server { -# listen 443 ssl http2; -# server_name meldestelle.yourdomain.com; -# -# ssl_certificate /etc/ssl/certs/meldestelle.crt; -# ssl_certificate_key /etc/ssl/private/meldestelle.key; -# -# # SSL Configuration -# ssl_protocols TLSv1.2 TLSv1.3; -# ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512; -# ssl_prefer_server_ciphers off; -# ssl_session_cache shared:SSL:10m; -# -# # Rest der Web-App Konfiguration hier... -# } - -# =================================================================== -# HTTP -> HTTPS Redirect (Optional) -# =================================================================== -# Uncomment für automatische HTTPS-Weiterleitung: -# -# server { -# listen 80; -# server_name meldestelle.yourdomain.com vnc.meldestelle.yourdomain.com api.meldestelle.yourdomain.com; -# return 301 https://$server_name$request_uri; -# } diff --git a/docs/reference/ports-and-urls.md b/docs/reference/ports-and-urls.md index 7dbf7995..55e196e0 100644 --- a/docs/reference/ports-and-urls.md +++ b/docs/reference/ports-and-urls.md @@ -2,34 +2,44 @@ 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). +last_reviewed: 2025-10-31 +summary: "Übersicht der wichtigsten lokalen URLs und Ports. Quelle: docker/versions.toml" --- -# Referenz: Ports & URLs +# Referenz: Wichtige URLs und Ports (lokal) + +Quelle der Wahrheit für Ports: [docker/versions.toml](../../docker/versions.toml) → [service-ports] + +## Infrastruktur -## 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 +- PostgreSQL: 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. +## Services -## 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 +- 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 -Optional HTTPS: gleiche Hosts mit https://, sobald Zertifikate aktiv sind. +## Monitoring + +- Prometheus: http://localhost:9090 +- Grafana: http://localhost:3000 + +## Clients + +- Web App: http://localhost:4000 +- Desktop App (VNC): localhost:5901 +- Desktop App (noVNC): http://localhost:6080 + +## Hinweise + +- Die oben genannten Ports sind in `docker/versions.toml` unter `[service-ports]` zentral gepflegt und werden für Docker + Compose-Generierung und Validierung verwendet. +- Bei Port-Konflikten können die Werte in `docker/versions.toml` angepasst und anschließend die Compose-Dateien mit + `bash scripts/generate-compose-files.sh all development` neu generiert werden. diff --git a/events/README.md b/events/README.md index 97ac632e..fe671c3d 100644 --- a/events/README.md +++ b/events/README.md @@ -1 +1 @@ -# Events Module\n\nThis is a minimal placeholder README to satisfy documentation validation. See docs/index.md for project docs. +# Events Module\n\nThis is a minimal placeholder README to satisfy documentation validation. See docs/index.md for project docs diff --git a/gradle.properties b/gradle.properties index 2d4f68a2..76093ea4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -70,5 +70,10 @@ services.port.events=8085 # Development Environment Support dev.port.offset=0 # Set dev.port.offset=100 for second developer -# Set dev.port.offset=200 for third developer +# Set dev.port.offset=200 for the third developer enableWasm=false + + +# Dokka Gradle plugin V2 mode (with helpers for V1 compatibility) +# See https://kotl.in/dokka-gradle-migration +org.jetbrains.dokka.experimental.gradle.pluginMode=V2EnabledWithHelpers diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a94c40e2..9996b89e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -495,3 +495,10 @@ spring-boot = { id = "org.springframework.boot", version.ref = "springBoot" } spring-dependencyManagement = { id = "io.spring.dependency-management", version.ref = "springDependencyManagement" } foojayResolver = { id = "org.gradle.toolchains.foojay-resolver-convention", version.ref = "foojayResolver" } + +# Dokka plugin +# Version pinned to work with Kotlin 2.2.x +# See: https://github.com/Kotlin/dokka +# Note: dokka 2.0.0+ matches Kotlin 2.0+; verify compatibility if bumping Kotlin +# Using latest stable known compatible as of 2025-10 +dokka = { id = "org.jetbrains.dokka", version = "2.0.0" } diff --git a/horses/README.md b/horses/README.md index 71a3a27d..b2588a09 100644 --- a/horses/README.md +++ b/horses/README.md @@ -1 +1 @@ -# Horses Module\n\nThis is a minimal placeholder README to satisfy documentation validation. See docs/index.md for project docs. +# Horses Module\n\nThis is a minimal placeholder README to satisfy documentation validation. See docs/index.md for project docs diff --git a/infrastructure/README-INFRASTRUCTURE.md b/infrastructure/README-INFRASTRUCTURE.md index b1e4dd17..e446ce0e 100644 --- a/infrastructure/README-INFRASTRUCTURE.md +++ b/infrastructure/README-INFRASTRUCTURE.md @@ -38,6 +38,7 @@ infrastructure/ Zentrale Authentifizierungs- und Autorisierungskomponente basierend auf OAuth 2.0 und JWT. #### Features + - **JWT Token Management** - Erstellung, Validierung und Refresh von JWT-Tokens - **OAuth 2.0 Integration** - Unterstützung für OAuth 2.0 Flows - **Role-Based Access Control (RBAC)** - Rollenbasierte Zugriffskontrolle @@ -45,10 +46,12 @@ Zentrale Authentifizierungs- und Autorisierungskomponente basierend auf OAuth 2. - **Session Management** - Sichere Session-Verwaltung #### Komponenten + - **auth-client**: Client-seitige Authentifizierungslogik - **auth-server**: Server-seitige Authentifizierungsdienste #### Verwendung + ```kotlin // JWT Token validieren val tokenValidator = JwtTokenValidator() @@ -64,6 +67,7 @@ val user = authService.authenticate(credentials) Hochperformante Caching-Lösung für verbesserte Anwendungsleistung. #### Features + - **Redis Integration** - Redis als primärer Cache-Store - **Multi-Level Caching** - L1 (In-Memory) und L2 (Redis) Cache - **Cache Invalidation** - Intelligente Cache-Invalidierungsstrategien @@ -71,10 +75,12 @@ Hochperformante Caching-Lösung für verbesserte Anwendungsleistung. - **Cache Statistics** - Monitoring und Metriken #### Komponenten + - **cache-api**: Cache-Abstraktionen und Interfaces - **redis-cache**: Redis-basierte Cache-Implementierung #### Verwendung + ```kotlin // Cache-Service verwenden val cacheService = RedisCacheService() @@ -90,6 +96,7 @@ cacheService.invalidate("pattern:*") Event Sourcing Infrastruktur für Domain Events und CQRS-Pattern. #### Features + - **Event Sourcing** - Persistierung von Domain Events - **Event Replay** - Wiederherstellung von Aggregaten aus Events - **Snapshots** - Performance-Optimierung durch Snapshots @@ -97,10 +104,12 @@ Event Sourcing Infrastruktur für Domain Events und CQRS-Pattern. - **Stream Processing** - Event-Stream-Verarbeitung #### Komponenten + - **event-store-api**: Event Store Abstraktionen - **redis-event-store**: Redis-basierte Event Store Implementierung #### Verwendung + ```kotlin // Events speichern val eventStore = RedisEventStore() @@ -120,6 +129,7 @@ eventStore.subscribeToStream("member-events") { event -> Zentraler Eingangspoint für alle API-Anfragen mit Routing, Load Balancing und Sicherheit. #### Features + - **Request Routing** - Intelligentes Routing zu Microservices - **Load Balancing** - Lastverteilung zwischen Service-Instanzen - **Rate Limiting** - Schutz vor Überlastung @@ -129,6 +139,7 @@ Zentraler Eingangspoint für alle API-Anfragen mit Routing, Load Balancing und S - **Monitoring** - Request-Tracking und Metriken #### Konfiguration + ```yaml # gateway-config.yml routes: @@ -146,6 +157,7 @@ routes: Asynchrone Kommunikation zwischen Services über Message Queues. #### Features + - **Apache Kafka Integration** - Kafka als Message Broker - **Event-Driven Architecture** - Unterstützung für Event-driven Patterns - **Message Serialization** - JSON und Avro Serialisierung @@ -153,10 +165,12 @@ Asynchrone Kommunikation zwischen Services über Message Queues. - **Consumer Groups** - Skalierbare Message-Verarbeitung #### Komponenten + - **messaging-client**: Kafka-Client-Bibliothek - **messaging-config**: Messaging-Konfiguration #### Verwendung + ```kotlin // Message Producer val producer = KafkaMessageProducer() @@ -174,6 +188,7 @@ consumer.subscribe("member-events") { message -> Umfassende Monitoring- und Observability-Lösung. #### Features + - **Metrics Collection** - Sammlung von Anwendungsmetriken - **Distributed Tracing** - Zipkin-Integration für Request-Tracing - **Health Checks** - Service-Gesundheitsprüfungen @@ -181,10 +196,12 @@ Umfassende Monitoring- und Observability-Lösung. - **Dashboards** - Grafana-Integration für Visualisierung #### Komponenten + - **monitoring-client**: Client-seitige Monitoring-Bibliothek - **monitoring-server**: Monitoring-Server und Aggregation #### Metriken + ```kotlin // Custom Metrics val meterRegistry = PrometheusMeterRegistry() @@ -202,22 +219,27 @@ Timer.Sample.start(meterRegistry) ## Technologie-Stack ### Datenbanken und Speicher + - **Redis 7.0** - Caching und Event Store - **PostgreSQL 16** - Relationale Datenbank (über Domain-Module) ### Message Broker + - **Apache Kafka 7.5.0** - Event Streaming und Messaging ### Monitoring und Observability + - **Prometheus** - Metriken-Sammlung - **Grafana** - Dashboards und Visualisierung - **Zipkin** - Distributed Tracing ### Security -- **Keycloak 23.0** - Identity und Access Management + +- **Keycloak 26.4.2** - Identity und Access Management - **JWT** - Token-basierte Authentifizierung ### API Gateway + - **Spring Cloud Gateway** - API Gateway Implementierung - **Nginx** - Reverse Proxy und Load Balancer @@ -241,10 +263,10 @@ services: KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092 keycloak: - image: quay.io/keycloak/keycloak:23.0 + image: quay.io/keycloak/keycloak:26.4.2 environment: - KEYCLOAK_ADMIN: admin - KEYCLOAK_ADMIN_PASSWORD: admin + KC_BOOTSTRAP_ADMIN_USERNAME: admin + KC_BOOTSTRAP_ADMIN_PASSWORD: admin ports: - "8080:8080" ``` @@ -490,6 +512,7 @@ class InfrastructureIntegrationTest { ### Häufige Probleme #### Redis Connection Issues + ```bash # Redis Verbindung testen redis-cli -h localhost -p 6379 ping @@ -499,6 +522,7 @@ docker logs redis-container ``` #### Kafka Connection Issues + ```bash # Kafka Topics auflisten kafka-topics --bootstrap-server localhost:9092 --list @@ -508,6 +532,7 @@ kafka-consumer-groups --bootstrap-server localhost:9092 --describe --group melde ``` #### Gateway Routing Issues + ```bash # Gateway Health Check curl http://localhost:8080/actuator/health @@ -519,18 +544,21 @@ curl http://localhost:8080/actuator/gateway/routes ## Best Practices ### Caching + 1. **Cache Warming** - Wichtige Daten beim Start vorwärmen 2. **Cache Invalidation** - Konsistente Invalidierungsstrategien 3. **TTL Configuration** - Angemessene Time-To-Live Werte 4. **Cache Monitoring** - Hit/Miss Ratios überwachen ### Messaging + 1. **Idempotenz** - Message-Handler idempotent implementieren 2. **Error Handling** - Retry-Mechanismen und Dead Letter Queues 3. **Schema Evolution** - Backward-kompatible Schema-Änderungen 4. **Monitoring** - Message-Durchsatz und Latenz überwachen ### Security + 1. **Token Rotation** - Regelmäßige JWT-Token-Rotation 2. **HTTPS Only** - Ausschließlich verschlüsselte Verbindungen 3. **Rate Limiting** - Schutz vor Brute-Force-Angriffen diff --git a/infrastructure/README.md b/infrastructure/README.md index b4368904..c6b3cae5 100644 --- a/infrastructure/README.md +++ b/infrastructure/README.md @@ -1 +1 @@ -# Infrastructure\n\nMinimal placeholder README. For infrastructure details, start at docs/index.md and docs/overview/system-overview.md. +# Infrastructure\n\nMinimal placeholder README. For infrastructure details, start at docs/index.md and docs/overview/system-overview.md diff --git a/infrastructure/auth/README-INFRA-AUTH.md b/infrastructure/auth/README-INFRA-AUTH.md index ec8a1071..9b65e597 100644 --- a/infrastructure/auth/README-INFRA-AUTH.md +++ b/infrastructure/auth/README-INFRA-AUTH.md @@ -36,14 +36,15 @@ infrastructure/auth/ Dieses Modul ist eine **wiederverwendbare Bibliothek** und kein eigenständiger Service. Es enthält die gesamte Logik, die andere Microservices (wie `masterdata-service`, `members-service` etc.) benötigen, um ihre Endpunkte abzusichern. Aktueller Stand (09/2025): + - Enthält ein typensicheres Rollen- und Berechtigungsmodell: `RolleE`, `BerechtigungE` (kotlinx.serialization-annotiert für konsistente JSON-Serialisierung). - Definiert die Schnittstelle `AuthenticationService` mit suspend-Funktionen und Result-Typen zur Authentifizierung und Passwortänderung. Rückgabewerte sind versiegelt (sealed) und decken Success/Failure/Locked ab. Dadurch klare, explizite Fehlerfälle ohne Exceptions in Kontrollflüssen. - Stellt den `JwtService` bereit, der via Spring konfiguriert werden kann und in Services zur Token-Erzeugung/-Validierung genutzt wird. **Hauptaufgaben:** -* **JWT-Management:** Stellt einen `JwtService` zur Erstellung und Validierung von JSON Web Tokens bereit (Signatur, Claims, Ablaufzeiten). Neue, result-basierte APIs erleichtern das Fehler-Handling. -* **Modell-Definition:** Definiert die **Quelle der Wahrheit** für sicherheitsrelevante Konzepte wie `RolleE` und `BerechtigungE` als typsichere Kotlin-Enums. Dies stellt sicher, dass alle Services dieselbe "Sprache" für Berechtigungen sprechen. -* **Schnittstellen:** Bietet saubere Schnittstellen wie `AuthenticationService` an, die von der konkreten Implementierung (z.B. Keycloak) abstrahieren. Dadurch können Implementierungen im `auth-server` oder in Tests (Mocks/Fakes) ausgetauscht werden. +- **JWT-Management:** Stellt einen `JwtService` zur Erstellung und Validierung von JSON Web Tokens bereit (Signatur, Claims, Ablaufzeiten). Neue, result-basierte APIs erleichtern das Fehler-Handling. +- **Modell-Definition:** Definiert die **Quelle der Wahrheit** für sicherheitsrelevante Konzepte wie `RolleE` und `BerechtigungE` als typsichere Kotlin-Enums. Dies stellt sicher, dass alle Services dieselbe "Sprache" für Berechtigungen sprechen. +- **Schnittstellen:** Bietet saubere Schnittstellen wie `AuthenticationService` an, die von der konkreten Implementierung (z.B. Keycloak) abstrahieren. Dadurch können Implementierungen im `auth-server` oder in Tests (Mocks/Fakes) ausgetauscht werden. Einbindung: Jeder Microservice, der geschützte Endpunkte anbietet, bindet dieses Modul als Abhängigkeit ein. @@ -52,9 +53,9 @@ Einbindung: Jeder Microservice, der geschützte Endpunkte anbietet, bindet diese Dies ist ein **eigenständiger Spring Boot Microservice**, der als Brücke zwischen dem Meldestelle-System und Keycloak agiert. **Hauptaufgaben:** -* **Benutzer-API:** Stellt eine REST-API zur Verfügung, um Benutzer zu verwalten (z.B. Registrierung). Diese API kommuniziert im Hintergrund über den `keycloak-admin-client` mit Keycloak. -* **Token-Endpunkte:** Ist verantwortlich für das Ausstellen von Tokens nach einer erfolgreichen Authentifizierung. -* **Implementierung der `AuthenticationService`-Schnittstelle:** Enthält die konkrete Logik, die gegen Keycloak prüft, ob ein Benutzername und ein Passwort korrekt sind. +- **Benutzer-API:** Stellt eine REST-API zur Verfügung, um Benutzer zu verwalten (z.B. Registrierung). Diese API kommuniziert im Hintergrund über den `keycloak-admin-client` mit Keycloak. +- **Token-Endpunkte:** Ist verantwortlich für das Ausstellen von Tokens nach einer erfolgreichen Authentifizierung. +- **Implementierung der `AuthenticationService`-Schnittstelle:** Enthält die konkrete Logik, die gegen Keycloak prüft, ob ein Benutzername und ein Passwort korrekt sind. **Konfiguration (AuthServerConfiguration):** Der Service stellt einen konfigurierbaren `JwtService` per Spring-Bean bereit. Die dazugehörigen Properties werden über `auth.jwt.*` gesetzt: @@ -69,6 +70,7 @@ auth: ``` Kotlin-Konfiguration (vereinfacht): + ```kotlin @Configuration @EnableConfigurationProperties(JwtProperties::class) @@ -94,12 +96,12 @@ Hinweis: Standardwerte sind nur für lokale Entwicklung gedacht und müssen in P ## Zusammenspiel im System -1. Ein **Benutzer** meldet sich über eine Client-Anwendung am **`auth-server`** an. -2. Der **`auth-server`** validiert die Anmeldedaten gegen **Keycloak**. -3. Bei Erfolg erstellt der `auth-server` mit dem `JwtService` aus dem `auth-client` ein JWT, das die Berechtigungen des Benutzers enthält, und sendet es an den Client zurück. -4. Der **Client** sendet eine Anfrage an einen anderen Microservice (z.B. `members-service`) und fügt das JWT als Bearer-Token in den Header ein. -5. Der **`members-service`**, der ebenfalls den `auth-client` als Abhängigkeit hat, nutzt den `JwtService`, um das Token zu validieren und die Berechtigungen typsicher auszulesen. -6. Das **Gateway** kann vorgelagert JWT-basierte Authentifizierung durchführen. Aktuell existiert ein `JwtAuthenticationFilter`, der über `gateway.security.jwt.enabled=true` aktiviert wird. In der vorliegenden Codebasis nutzt dieser noch eine vereinfachte Validierung; die geplante Integration ist die Nutzung des `auth-client` zur vollständigen Validierung und Claim-Extraktion. +1. Ein **Benutzer** meldet sich über eine Client-Anwendung am **`auth-server`** an. +2. Der **`auth-server`** validiert die Anmeldedaten gegen **Keycloak**. +3. Bei Erfolg erstellt der `auth-server` mit dem `JwtService` aus dem `auth-client` ein JWT, das die Berechtigungen des Benutzers enthält, und sendet es an den Client zurück. +4. Der **Client** sendet eine Anfrage an einen anderen Microservice (z.B. `members-service`) und fügt das JWT als Bearer-Token in den Header ein. +5. Der **`members-service`**, der ebenfalls den `auth-client` als Abhängigkeit hat, nutzt den `JwtService`, um das Token zu validieren und die Berechtigungen typsicher auszulesen. +6. Das **Gateway** kann vorgelagert JWT-basierte Authentifizierung durchführen. Aktuell existiert ein `JwtAuthenticationFilter`, der über `gateway.security.jwt.enabled=true` aktiviert wird. In der vorliegenden Codebasis nutzt dieser noch eine vereinfachte Validierung; die geplante Integration ist die Nutzung des `auth-client` zur vollständigen Validierung und Claim-Extraktion. Diese Architektur entkoppelt die Fach-Services von der Komplexität der Identitätsverwaltung und schafft eine robuste, zentrale Sicherheitsinfrastruktur. @@ -108,6 +110,7 @@ Diese Architektur entkoppelt die Fach-Services von der Komplexität der Identit ### Technische Verbesserungen **Dependencies Updates:** + - Spring Boot: 3.2.5 → 3.3.2 (Security-Updates und Performance-Verbesserungen) - Spring Cloud: 2023.0.1 → 2023.0.3 (Bug-Fixes) - Spring Dependency Management: 1.1.5 → 1.1.6 (Kompatibilität) @@ -115,6 +118,7 @@ Diese Architektur entkoppelt die Fach-Services von der Komplexität der Identit - Keycloak: 23.0.0 → 25.0.2 (Wichtige Sicherheitsupdates) **Code Modernisierung:** + - **JWT Service**: Implementierung von Result-basierten APIs für besseres Error-Handling - **Structured Logging**: Integration von KotlinLogging für strukturierte Log-Ausgabe - **Exception Handling**: Spezifische JWT-Exception-Behandlung statt Catch-All-Blöcke @@ -122,12 +126,14 @@ Diese Architektur entkoppelt die Fach-Services von der Komplexität der Identit - **Backward Compatibility**: Deprecated Legacy-Methoden für sanfte Migration **Test-Verbesserungen:** + - Entfernung von `Thread.sleep()` für zuverlässigere Tests - Bessere Expired-Token-Tests mit eindeutigen Zeitstempel-Differenzen ### Token Claims und Struktur Empfohlene Claims im JWT (Beispiel): + - sub: Benutzer-ID (UUID) - pid: Personen-ID (UUID) - preferred_username: Loginname (derzeit intern als Claim "username" umgesetzt) @@ -143,6 +149,7 @@ Diese Claims werden vom `auth-client` gelesen und in typsichere Modelle abgebild ### API-Änderungen **Neue Result-basierte APIs:** + ```kotlin // Neu: Result-basierte APIs mit strukturiertem Error-Handling fun validateToken(token: String): Result @@ -160,6 +167,7 @@ fun getPermissions(token: String): List ### Auth-Client Modernisierung **Plugin-Erweiterungen:** + ```kotlin plugins { alias(libs.plugins.kotlin.jvm) @@ -171,12 +179,14 @@ plugins { ``` **Neue Dependencies:** + - **Kotlin Serialization**: Konsistente JSON-Verarbeitung mit anderen Modulen - **Type Safety**: Kompiletime-Validierung von JSON-Strukturen ### Auth-Server Production-Readiness **Production-Ready Dependencies:** + ```kotlin // API-Dokumentation mit OpenAPI/Swagger implementation(libs.springdoc.openapi.starter.webmvc.ui) @@ -189,6 +199,7 @@ implementation(libs.kotlinx.serialization.json) ``` **Neue Endpoints:** + - `/actuator/health` - Health Check - `/actuator/metrics` - Prometheus Metrics - `/actuator/info` - Application Info @@ -196,6 +207,7 @@ implementation(libs.kotlinx.serialization.json) - `/v3/api-docs` - OpenAPI JSON Schema **Monitoring Stack:** + - **Prometheus Metrics**: Via `micrometer-prometheus` - **Distributed Tracing**: Via `micrometer-tracing-bridge-brave` - **Zipkin Integration**: Für Request-Tracing @@ -208,29 +220,37 @@ Das Auth-Modul wurde von **kritisch untergetestet** auf **umfassend getestet** t ### Test-Statistiken **Vor der Implementierung:** + - JwtService: 5 Tests (Basis-Funktionalität) - Andere Module: 0 Tests ❌ **Nach der Implementierung:** + - **Gesamt: 80+ Tests** implementiert - **Erfolgsquote: 95%+** (nur umgebungsabhängige Performance-Tests variieren) ### Implementierte Test-Suiten #### 1. JwtServiceExtendedTest ✅ + **19 Tests** - Erweiterte JWT-Tests mit Result-APIs + - Result API Tests mit strukturiertem Error-Handling - Security Edge Cases und Token-Tampering - Legacy Compatibility für deprecated Methoden #### 2. AuthenticationServiceTest ✅ + **15 Tests** - Mock-Tests für Authentication Interface + - Authentication Scenarios (Success, Failure, Locked) - Password Management und Validation - Sealed Class Pattern Testing #### 3. SecurityTest ✅ + **15 Tests** - Sicherheitstests für JWT-Vulnerabilities + - Signature Tampering Protection - Timing Attack Resistance - Algorithm Confusion Prevention @@ -238,25 +258,32 @@ Das Auth-Modul wurde von **kritisch untergetestet** auf **umfassend getestet** t - Memory Safety Tests #### 4. AuthPerformanceTest ✅ + **13 Tests** - Performance-Tests (11+ bestanden) + - JWT Validation: < 20ms für komplexe Szenarien - Token Generation: < 5ms pro Token - Concurrent Throughput: > 10,000 validations/sec - Memory Stability: < 50MB bei 10,000 Operationen #### 5. ResultApiTest ✅ + **13 Tests** - Result-basierte API-Tests + - Result Success/Failure Cases - Functional Programming Patterns - Kotlin Standard Library Integration - Error Handling Consistency #### 6. Integration Tests ✅ + **29+ Tests** - Minimal Integration Tests + - AuthServerIntegrationTest: 15 Tests (minimale Spring-Konfiguration) - KeycloakIntegrationTest: 14 Tests (Container-only Testing, Docker-abhängig) **Integration Test Details:** + - KeycloakIntegrationTest nutzt Testcontainers mit Keycloak 25.0.2 - Tests sind mit @EnabledIf Docker-conditional ausgestattet - Automatische Keycloak-Container-Erkennung und -Konfiguration @@ -265,6 +292,7 @@ Das Auth-Modul wurde von **kritisch untergetestet** auf **umfassend getestet** t ### Performance-Validierung **Erfüllte Benchmarks:** + - ✅ JWT Validation: Durchschnitt < 1ms - ✅ Token Generation: Durchschnitt < 2ms - ✅ Concurrent Throughput: > 10,000 ops/sec @@ -272,6 +300,7 @@ Das Auth-Modul wurde von **kritisch untergetestet** auf **umfassend getestet** t - ✅ Consistent Performance: < 20% Degradation über Zeit **Debug-Ausgaben:** + ``` [DEBUG_LOG] Token generation: ~1.5ms average [DEBUG_LOG] Token validation: ~0.8ms average @@ -281,12 +310,14 @@ Das Auth-Modul wurde von **kritisch untergetestet** auf **umfassend getestet** t ### Sicherheitsvalidierung **CVE-Schutz implementiert:** + - JWT Algorithm Confusion (CVE-2018-0114) - JWT Signature Bypass Versuche - DoS via Long Tokens Prevention - Information Disclosure Prevention **Security Features getestet:** + - ✅ Token Tampering Protection (validiert in isolierten Tests 15.08.2025) - ✅ Timing Attack Resistance - ✅ Concurrent Access Safety @@ -294,6 +325,7 @@ Das Auth-Modul wurde von **kritisch untergetestet** auf **umfassend getestet** t - ✅ Injection Attack Prevention **Aktuelle Sicherheitsvalidierung (15. August 2025):** + - Alle 15 SecurityTest-Tests erfolgreich bestanden - JWT Signature Tampering Protection funktioniert korrekt - Keine Sicherheitslücken in der Token-Validierung festgestellt @@ -302,6 +334,7 @@ Das Auth-Modul wurde von **kritisch untergetestet** auf **umfassend getestet** t ## Dependencies-Übersicht ### Auth-Client Dependencies + ```kotlin; ├── platform-bom (Version Management) ├── platform-dependencies (Common Dependencies) @@ -314,6 +347,7 @@ Das Auth-Modul wurde von **kritisch untergetestet** auf **umfassend getestet** t ``` ### Auth-Server Dependencies + ```kotlin; ├── platform-bom (Version Management) ├── platform-dependencies (Common Dependencies) @@ -338,6 +372,7 @@ Diese README wurde am 03.09.2025 aktualisiert und spiegelt den aktuellen Stand d ## Production-Readiness Status ### ✅ Production-Ready Bereiche + - **JWT Service**: Vollständig getestet (40+ Tests) - **Result APIs**: Comprehensive Abdeckung (13 Tests) - **Security**: Alle kritischen Vulnerabilities getestet (15 Tests) @@ -347,24 +382,28 @@ Diese README wurde am 03.09.2025 aktualisiert und spiegelt den aktuellen Stand d - **API Documentation**: Automatische OpenAPI/Swagger-Docs ### ⚠️ Bereiche mit Notizen + - **Integration Tests**: Minimaler Ansatz implementiert (funktional) - **Performance Tests**: 2 Tests umgebungsabhängig (nicht kritisch) ## Qualitätsmerkmale ### Code Quality + - **Comprehensive Test Coverage**: Alle kritischen Pfade getestet - **Security-First Approach**: Sicherheit als Hauptfokus - **Modern Kotlin Features**: data object, Result APIs, strukturiertes Logging - **Backward Compatibility**: Sanfte Migration mit deprecated Methoden ### Maintainability + - **Strukturierte Test-Organisation**: Klare Kategorisierung - **Self-Documenting Code**: Aussagekräftige Namen und Kommentare - **Performance Baselines**: Monitoring-freundliche Metriken - **Zentrale Versionsverwaltung**: Via libs.versions.toml ### Development Experience + - **API Documentation**: Automatische Swagger/OpenAPI-Docs - **Type-Safe Configuration**: Plugin-Aliases und strukturierte Properties - **Debugging Support**: Strukturierte Logs mit Debug-Ausgaben diff --git a/infrastructure/auth/auth-server/src/test/kotlin/at/mocode/infrastructure/auth/KeycloakIntegrationTest.kt b/infrastructure/auth/auth-server/src/test/kotlin/at/mocode/infrastructure/auth/KeycloakIntegrationTest.kt index 33dc3891..18302c94 100644 --- a/infrastructure/auth/auth-server/src/test/kotlin/at/mocode/infrastructure/auth/KeycloakIntegrationTest.kt +++ b/infrastructure/auth/auth-server/src/test/kotlin/at/mocode/infrastructure/auth/KeycloakIntegrationTest.kt @@ -29,7 +29,7 @@ import java.time.Duration class KeycloakIntegrationTest { companion object { - private const val KEYCLOAK_VERSION = "26.4.0" + private const val KEYCLOAK_VERSION = "26.4.2" private const val KEYCLOAK_PORT = 8080 private const val KEYCLOAK_ADMIN_USER = "admin" private const val KEYCLOAK_ADMIN_PASSWORD = "admin" @@ -41,8 +41,8 @@ class KeycloakIntegrationTest { @JvmStatic val keycloakContainer: GenericContainer<*> = GenericContainer("quay.io/keycloak/keycloak:$KEYCLOAK_VERSION") .withExposedPorts(KEYCLOAK_PORT) - .withEnv("KEYCLOAK_ADMIN", KEYCLOAK_ADMIN_USER) - .withEnv("KEYCLOAK_ADMIN_PASSWORD", KEYCLOAK_ADMIN_PASSWORD) + .withEnv("KC_BOOTSTRAP_ADMIN_USERNAME", KEYCLOAK_ADMIN_USER) + .withEnv("KC_BOOTSTRAP_ADMIN_PASSWORD", KEYCLOAK_ADMIN_PASSWORD) .withCommand("start-dev") .waitingFor( Wait.forHttp("/admin/master/console/") @@ -197,15 +197,19 @@ class KeycloakIntegrationTest { // Verify container environment val envVars = keycloakContainer.envMap - assert(envVars["KEYCLOAK_ADMIN"] == KEYCLOAK_ADMIN_USER) { + // Support new KC_BOOTSTRAP_* variables (Keycloak 26+) with fallback to legacy KEYCLOAK_* names + val adminUser = envVars["KC_BOOTSTRAP_ADMIN_USERNAME"] ?: envVars["KEYCLOAK_ADMIN"] + val adminPass = envVars["KC_BOOTSTRAP_ADMIN_PASSWORD"] ?: envVars["KEYCLOAK_ADMIN_PASSWORD"] + + assert(adminUser == KEYCLOAK_ADMIN_USER) { "Admin user should be configured correctly" } - assert(envVars["KEYCLOAK_ADMIN_PASSWORD"] == KEYCLOAK_ADMIN_PASSWORD) { + assert(adminPass == KEYCLOAK_ADMIN_PASSWORD) { "Admin password should be configured correctly" } println("[DEBUG_LOG] Environment variables validated") - println("[DEBUG_LOG] Admin user: ${envVars["KEYCLOAK_ADMIN"]}") + println("[DEBUG_LOG] Admin user: $adminUser") println("[DEBUG_LOG] Environment count: ${envVars.size}") } diff --git a/infrastructure/cache/README-INFRA-CACHE.md b/infrastructure/cache/README-INFRA-CACHE.md index 482ae332..5f8fadab 100644 --- a/infrastructure/cache/README-INFRA-CACHE.md +++ b/infrastructure/cache/README-INFRA-CACHE.md @@ -3,13 +3,16 @@ Letzte Aktualisierung: 03. September 2025 ## Zweck und Aufgaben des Moduls + Das Infrastructure/Cache-Modul stellt eine einheitliche, technologie‑neutrale Cache‑Schnittstelle für alle Services bereit und liefert mit einer Redis‑basierten Adapter‑Implementierung die produktionsreife Ausführung. Ziele: + - Antwortzeiten reduzieren und Primärdatenbanken entlasten. - Einheitliche API für Lesen/Schreiben, Batch‑Operationen und TTLs. - Resilienz bei Redis‑Ausfällen durch lokalen Fallback. - Operative Transparenz durch einfache Metriken, Health‑Informationen und periodische Wartungsaufgaben. ## Architektur (Port‑Adapter) + - cache‑api: enthält die öffentlichen Verträge und Basistypen - DistributedCache: zentrale Port‑Schnittstelle für Cache‑Operationen - CacheEntry, CacheConfiguration, CacheSerializer @@ -19,7 +22,9 @@ Das Infrastructure/Cache-Modul stellt eine einheitliche, technologie‑neutrale - JacksonCacheSerializer: serialisiert Werte und CacheEntry per Jackson ## Öffentliche API (Auszug) + DistributedCache + - get(key, clazz)/set(key, value, ttl?) - delete(key), exists(key) - multiGet(keys, clazz), multiSet(map, ttl?) @@ -27,15 +32,18 @@ DistributedCache - synchronize(keys?), markDirty(key), getDirtyKeys(), clear() Idiomatic Kotlin Extensions + - cache.get(key) - cache.multiGet(keys) CacheConfiguration (DefaultCacheConfiguration vorhanden) + - defaultTtl?, localCacheMaxSize?, offlineModeEnabled, synchronizationInterval, offlineEntryMaxAge?, keyPrefix, compressionEnabled, compressionThreshold Hinweis: Die Kompression wird aktuell durch den Serializer bereitgestellt; Schwellwerte/Flags sind für zukünftiges Tuning vorgesehen. ## Implementierungsdetails (RedisDistributedCache) + - Lokaler Fallback: ConcurrentHashMap als lokaler Cache speichert CacheEntry inkl. expiresAt. Bei Redis‑Ausfall werden Schreibvorgänge lokal gehalten und als „dirty“ markiert. - Dirty‑Synchronisation: Sobald die Verbindung wieder ONLINE ist, werden geänderte Schlüssel zu Redis synchronisiert (synchronize()). - Key‑Prefixing: Alle externen Keys werden mittels keyPrefix gekapselt, um Mandanten/Services zu isolieren. @@ -49,13 +57,16 @@ Hinweis: Die Kompression wird aktuell durch den Serializer bereitgestellt; Schwe - Metriken‑Log: fixedDelayString = "${redis.metrics-log-interval:300000}" Wichtige Robustheitsdetails + - Alle Redis‑Operationen fangen RedisConnectionFailureException ab und schalten den ConnectionState auf DISCONNECTED. Beim nächsten erfolgreichen Zugriff wird CONNECTED gesetzt und eine Synchronisation der dirty keys ausgelöst. - multiSet setzt TTLs bei Bedarf per Pipeline nach (pExpire); einzelne set‑Operationen nutzen expire via Duration. ## Verwendung (Beispiele) + Einbinden: Projekte hängen gegen :infrastructure:cache:redis-cache und injizieren DistributedCache. Lesen/Schreiben mit TTL + ```kotlin val user = cache.get("user:42") if (user == null) { @@ -65,12 +76,14 @@ if (user == null) { ``` Batch‑Lesezugriff + ```kotlin val ids = listOf("user:1", "user:2", "user:3") val map = cache.multiGet(ids) ``` Bulk‑Schreiben + ```kotlin cache.multiSet(mapOf( "cfg:app" to appConfig, @@ -79,6 +92,7 @@ cache.multiSet(mapOf( ``` Verbindungsstatus überwachen + ```kotlin cache.registerConnectionListener(object : ConnectionStateListener { override fun onConnectionStateChanged(newState: ConnectionState, timestamp: Instant) { @@ -88,27 +102,34 @@ cache.registerConnectionListener(object : ConnectionStateListener { ``` ## Konfiguration + DefaultCacheConfiguration bietet sinnvolle Defaults. Relevante Properties (optional via Spring @Scheduled Platzhalter): + - redis.connection-check-interval: ms für Verbindungsprüfung (Default 10000) - redis.local-cache-cleanup-interval: ms für lokale Bereinigung (Default 60000) - redis.sync-interval: ms für Synchronisationsläufe (Default 300000) - redis.metrics-log-interval: ms für periodisches Metriken‑Logging (Default 300000) Hinweise + - keyPrefix sollte pro Service gesetzt werden (z. B. "masterdata"), um Kollisionen zu vermeiden. - localCacheMaxSize begrenzt die Größe des lokalen Fallback‑Caches. Bei null ist die Größe unbegrenzt. ## Betrieb & Monitoring + - Health‑Infos: getHealthStatus() liefert eine einfache Einschätzung basierend auf ConnectionState und Erfolgsrate der Operationen. - Metriken: getPerformanceMetrics() liefert einfache Kennzahlen (Operations, Success‑Rate, Größe lokaler Cache, Anzahl dirty Keys). Periodisches Logging per @Scheduled möglich. - Cache Warming: warmCache(keys, loader) und warmCacheBulk(map) helfen, Hot‑Keys/gefragte Konfigurationen beim Start vorzuwärmen. ## Grenzen & bekannte Punkte + - Kompression ist im Serializer implementiert; die konfigurierbaren Flags/Schwellenwerte sind derzeit nicht dynamisch an/aus‑geschaltet. - Offline‑Modus: Die Konfiguration offlineModeEnabled ist vorhanden; die Implementierung betreibt den lokalen Fallback standardmäßig bei Verbindungsproblemen. Eine harte Deaktivierung dieses Verhaltens ist aktuell nicht verdrahtet. ## Changelog (Kurz) + - 2025‑09‑03: Fehlerbehebungen für @Scheduled‑Platzhalter, korrektes Logging im Cache‑Warming, lokale Cache‑Größenbegrenzung (LRM‑Eviction) hinzugefügt. Dokumentation aktualisiert (diese Datei). ## Fazit + Das Cache‑Modul bietet eine klare, wiederverwendbare Cache‑Schnittstelle mit einer robusten Redis‑Implementierung. Es unterstützt TTLs, Batch‑Operationen, lokalen Fallback bei Ausfällen und liefert einfache, praxistaugliche Betriebsinformationen. Mit keyPrefix und lokalen Limits ist der Einsatz in Multi‑Service‑Umgebungen unkompliziert und stabil. diff --git a/infrastructure/cache/redis-cache/README.md b/infrastructure/cache/redis-cache/README.md index c0cce32f..e3aea97b 100644 --- a/infrastructure/cache/redis-cache/README.md +++ b/infrastructure/cache/redis-cache/README.md @@ -7,6 +7,7 @@ Dieses Modul stellt eine konkrete Implementierung der `cache-api` unter Verwendu ## Architektur Das Modul folgt dem Provider-Pattern: + - **cache-api**: Provider-agnostische Interfaces (`CacheService`, `DistributedCache`) - **redis-cache**: Redis-spezifische Implementierung @@ -90,7 +91,9 @@ redis: host: localhost port: 6379 database: 0 # Cache verwendet Database 0 +``` +```yaml # Redis Event Store Konfiguration redis: event-store: @@ -112,6 +115,7 @@ Die Module verwenden unterschiedliche Bean-Namen: ### Keine Konflikte ✅ Die Module sind so designed, dass sie **ohne Konflikte** gleichzeitig verwendet werden können: + - Separate ConnectionFactories mit `@Qualifier` - Separate Property-Prefixes (`redis` vs `redis.event-store`) - Unterschiedliche Database-Nummern @@ -120,6 +124,7 @@ Die Module verwenden unterschiedliche Bean-Namen: ## Serialisierung Das Modul verwendet Jackson für die Serialisierung: + - Automatische Kotlin-Modul Integration - Java 8 Date/Time Support - Custom Serializer können via `@Bean` überschrieben werden @@ -127,6 +132,7 @@ Das Modul verwendet Jackson für die Serialisierung: ## Health Checks Das Modul tracked automatisch den Redis-Verbindungsstatus: + - Connection State (CONNECTED, DISCONNECTED, CONNECTING) - Connection State Listeners für Benachrichtigungen - Automatische Reconnect-Versuche diff --git a/infrastructure/event-store/README-INFRA-EVENT-STORE.md b/infrastructure/event-store/README-INFRA-EVENT-STORE.md index e4335cbe..3d105fbc 100644 --- a/infrastructure/event-store/README-INFRA-EVENT-STORE.md +++ b/infrastructure/event-store/README-INFRA-EVENT-STORE.md @@ -67,36 +67,36 @@ Das Modul folgt streng dem **Port-Adapter-Muster** (Hexagonal Architecture), um ## Schlüsselfunktionen ### 🔒 Garantierte Konsistenz -- **Atomare Transaktionen**: Schreibvorgänge in aggregatspezifische Streams und den globalen "all-events"-Stream werden innerhalb einer **Redis-Transaktion (`MULTI`/`EXEC`)** ausgeführt -- **Optimistische Concurrency Control**: Verhindert Race Conditions durch `expectedVersion`-Prüfung mit `ConcurrencyException` bei Konflikten -- **Eventual Consistency**: Garantiert, dass alle Events sowohl in aggregatspezifischen als auch globalen Streams verfügbar sind +* **Atomare Transaktionen**: Schreibvorgänge in aggregatspezifische Streams und den globalen "all-events"-Stream werden innerhalb einer **Redis-Transaktion (`MULTI`/`EXEC`)** ausgeführt +* **Optimistische Concurrency Control**: Verhindert Race Conditions durch `expectedVersion`-Prüfung mit `ConcurrencyException` bei Konflikten +* **Eventual Consistency**: Garantiert, dass alle Events sowohl in aggregatspezifischen als auch globalen Streams verfügbar sind ### 🛡️ Resiliente Event-Verarbeitung -- **Redis Consumer Groups**: Skalierbare und ausfallsichere Event-Verarbeitung mit automatischer Last-Verteilung -- **Pending Message Recovery**: Robuste Logik zum "Claimen" von Nachrichten ausgefallener Consumer -- **Retry-Mechanismen**: Automatische Wiederholung bei temporären Fehlern -- **Graceful Degradation**: Kontinuierliche Funktion auch bei partiellen Ausfällen +* **Redis Consumer Groups**: Skalierbare und ausfallsichere Event-Verarbeitung mit automatischer Last-Verteilung +* **Pending Message Recovery**: Robuste Logik zum "Claimen" von Nachrichten ausgefallener Consumer +* **Retry-Mechanismen**: Automatische Wiederholung bei temporären Fehlern +* **Graceful Degradation**: Kontinuierliche Funktion auch bei partiellen Ausfällen ### 📊 Intelligente Serialisierung -- **Metadata Separation**: Event-Metadaten und Nutzlast werden getrennt gespeichert für effiziente Stream-Analyse -- **Type Registry**: Dynamische Event-Type-Registrierung für polymorphe Deserialisierung -- **JSON-basiert**: Verwendung von Jackson für robuste, schema-flexible Serialisierung +* **Metadata Separation**: Event-Metadaten und Nutzlast werden getrennt gespeichert für effiziente Stream-Analyse +* **Type Registry**: Dynamische Event-Type-Registrierung für polymorphe Deserialisierung +* **JSON-basiert**: Verwendung von Jackson für robuste, schema-flexible Serialisierung ### 🚀 Performance-Optimierung -- **Stream-basierte Speicherung**: Optimale Performance durch Redis Streams -- **Optimierte Batch-Operationen**: Alle Events einer Batch werden in einer einzigen Redis-Transaktion verarbeitet (bis zu 90% Performance-Verbesserung) -- **Intelligente Version-Cache**: Thread-sicherer Cache mit Hit/Miss-Tracking für Stream-Versionen -- **Connection Pooling**: Konfigurierbare Verbindungspools für optimale Resource-Nutzung -- **Asynchrone Verarbeitung**: Non-blocking Event-Processing +* **Stream-basierte Speicherung**: Optimale Performance durch Redis Streams +* **Optimierte Batch-Operationen**: Alle Events einer Batch werden in einer einzigen Redis-Transaktion verarbeitet (bis zu 90% Performance-Verbesserung) +* **Intelligente Version-Cache**: Thread-sicherer Cache mit Hit/Miss-Tracking für Stream-Versionen +* **Connection Pooling**: Konfigurierbare Verbindungspools für optimale Resource-Nutzung +* **Asynchrone Verarbeitung**: Non-blocking Event-Processing ### 📊 Enhanced Monitoring & Performance Tracking (NEW) -- **Real-time Metrics Collection**: Automatisches Tracking aller Event-Store-Operationen mit detaillierten Performance-Metriken -- **Comprehensive Operation Tracking**: Einzelne und Batch-Appends, Read-Operationen, Subscriptions mit Erfolgsraten -- **Cache Performance Monitoring**: Detaillierte Hit/Miss-Ratios für optimale Cache-Tuning -- **Concurrency Conflict Detection**: Spezifisches Tracking von Optimistic-Locking-Konflikten -- **Automated Performance Logging**: Periodische Performance-Reports alle 5 Minuten mit strukturierten Metriken -- **Event Throughput Analytics**: Tracking von Events/Sekunde für Capacity Planning -- **Error Rate Monitoring**: Detaillierte Fehlerklassifizierung und -tracking +* **Real-time Metrics Collection**: Automatisches Tracking aller Event-Store-Operationen mit detaillierten Performance-Metriken +* **Comprehensive Operation Tracking**: Einzelne und Batch-Appends, Read-Operationen, Subscriptions mit Erfolgsraten +* **Cache Performance Monitoring**: Detaillierte Hit/Miss-Ratios für optimale Cache-Tuning +* **Concurrency Conflict Detection**: Spezifisches Tracking von Optimistic-Locking-Konflikten +* **Automated Performance Logging**: Periodische Performance-Reports alle 5 Minuten mit strukturierten Metriken +* **Event Throughput Analytics**: Tracking von Events/Sekunde für Capacity Planning +* **Error Rate Monitoring**: Detaillierte Fehlerklassifizierung und -tracking ## Konfiguration @@ -449,19 +449,19 @@ fun `consumer should process events reliably`() { ### Test-Features -- **Testcontainers Integration**: Echte Redis-Instanz für Integrationstests -- **Deterministische Tests**: Manueller Polling-Trigger statt Thread.sleep -- **Saubere Test-Daten**: @Transient-Annotation für Event-Klassen -- **Umfassende Szenarien**: Configuration, Error Handling, Stream, Resilience Tests +* **Testcontainers Integration**: Echte Redis-Instanz für Integrationstests +* **Deterministische Tests**: Manueller Polling-Trigger statt Thread.sleep +* **Saubere Test-Daten**: @Transient-Annotation für Event-Klassen +* **Umfassende Szenarien**: Configuration, Error Handling, Stream, Resilience Tests ## Performance & Monitoring ### Performance-Charakteristiken -- **Durchsatz**: >10 000 Events/Sekunde bei optimaler Konfiguration -- **Latenz**: <10ms für Event-Appending, <50ms für Event-Reading -- **Skalierung**: Horizontal skalierbar durch Consumer Groups -- **Speicher**: Effiziente Stream-basierte Speicherung +* **Durchsatz**: >10 000 Events/Sekunde bei optimaler Konfiguration +* **Latenz**: <10ms für Event-Appending, <50ms für Event-Reading +* **Skalierung**: Horizontal skalierbar durch Consumer Groups +* **Speicher**: Effiziente Stream-basierte Speicherung ### Monitoring-Metriken @@ -514,6 +514,7 @@ class EventStoreHealthIndicator( ### Häufige Probleme #### 1. ConcurrencyException + ```kotlin // Problem: Race Condition bei parallel Schreibvorgängen // Lösung: Retry-Logic mit exponential backoff @@ -524,6 +525,7 @@ fun appendWithRetry(event: DomainEvent, streamId: UUID, expectedVersion: Long) { ``` #### 2. Consumer Lag + ```bash # Redis CLI - Check consumer group info XINFO GROUPS event-stream:aggregate-id @@ -536,6 +538,7 @@ XCLAIM event-stream:aggregate-id event-processors consumer-name 60000 message-id ``` #### 3. Speicher-Issues + ```yaml # Redis Memory Optimization redis: @@ -548,6 +551,7 @@ redis: ``` #### 4. Verbindungsprobleme + ```yaml # Connection troubleshooting redis: @@ -584,12 +588,12 @@ redis-cli INFO memory ### Deployment Checklist -- [ ] Redis Cluster verfügbar und erreichbar -- [ ] Konfiguration für Umgebung angepasst -- [ ] Consumer Groups erstellt (automatisch oder manuell) -- [ ] Monitoring und Alerting konfiguriert -- [ ] Health Checks implementiert -- [ ] Backup-Strategie definiert +* [ ] Redis Cluster verfügbar und erreichbar +* [ ] Konfiguration für Umgebung angepasst +* [ ] Consumer Groups erstellt (automatisch oder manuell) +* [ ] Monitoring und Alerting konfiguriert +* [ ] Health Checks implementiert +* [ ] Backup-Strategie definiert ### Migration zwischen Versionen diff --git a/infrastructure/event-store/redis-event-store/README.md b/infrastructure/event-store/redis-event-store/README.md index 19b5955e..ce517daa 100644 --- a/infrastructure/event-store/redis-event-store/README.md +++ b/infrastructure/event-store/redis-event-store/README.md @@ -7,6 +7,7 @@ Dieses Modul stellt eine konkrete Implementierung der `event-store-api` unter Ve ## Architektur Das Modul folgt dem Provider-Pattern: + - **event-store-api**: Provider-agnostische Interfaces (`EventStore`, `EventSerializer`) - **redis-event-store**: Redis Streams-spezifische Implementierung @@ -150,6 +151,7 @@ Die Module verwenden unterschiedliche Bean-Namen zur Vermeidung von Konflikten: ### Keine Konflikte ✅ Die Module sind so designed, dass sie **ohne Konflikte** gleichzeitig verwendet werden können: + - **Separate ConnectionFactories** mit `@Qualifier` Annotations - **Separate Property-Prefixes**: `redis` vs `redis.event-store` - **Unterschiedliche Database-Nummern**: 0 vs 1 @@ -219,6 +221,7 @@ val eventsFromVersion = eventStore.loadEvents( ## Serialisierung Das Modul verwendet Jackson für Event-Serialisierung: + - Automatische Kotlin-Modul Integration - Polymorphe Serialisierung für verschiedene Event-Typen - Custom Serializer können via `@Bean` überschrieben werden @@ -274,4 +277,4 @@ Wenn Sie Fehler wie "Multiple beans of type RedisConnectionFactory" erhalten: - Siehe auch: [cache-api README](../../cache/cache-api/README.md) - Siehe auch: [redis-cache README](../../cache/redis-cache/README.md) -- Redis Streams Dokumentation: https://redis.io/docs/data-types/streams/ +- Redis Streams Dokumentation: diff --git a/infrastructure/gateway/CONFIGURATION.md b/infrastructure/gateway/CONFIGURATION.md index 172e9f07..62373426 100644 --- a/infrastructure/gateway/CONFIGURATION.md +++ b/infrastructure/gateway/CONFIGURATION.md @@ -20,22 +20,26 @@ Dieses Dokument beschreibt alle zentralen Konfigurationseigenschaften für das A ## Server Configuration ### server.port + - **Typ**: Integer - **Default**: 8081 - **Environment Variable**: `GATEWAY_PORT` - **Beschreibung**: Port, auf dem das Gateway läuft ### server.netty.connection-timeout + - **Typ**: Duration - **Default**: 5s - **Beschreibung**: Timeout für initiale TCP-Verbindungen ### server.netty.idle-timeout + - **Typ**: Duration - **Default**: 15s - **Beschreibung**: Timeout für inaktive Verbindungen **Beispiel:** + ```yaml server: port: 8081 @@ -49,11 +53,13 @@ server: ## Spring Application ### spring.application.name + - **Typ**: String - **Default**: api-gateway - **Beschreibung**: Name der Anwendung, wird in Consul und Logs verwendet ### spring.profiles.active + - **Typ**: String - **Default**: dev - **Environment Variable**: `SPRING_PROFILES_ACTIVE` @@ -61,6 +67,7 @@ server: - **Mögliche Werte**: dev, test, staging, prod ### spring.security.user.name / password + - **Typ**: String - **Default**: admin / admin - **Environment Variables**: `GATEWAY_ADMIN_USER`, `GATEWAY_ADMIN_PASSWORD` @@ -68,6 +75,7 @@ server: - **⚠️ Wichtig**: In Produktion durch sichere Werte ersetzen! **Beispiel:** + ```yaml spring: application: @@ -85,51 +93,60 @@ spring: ## Consul Service Discovery ### spring.cloud.consul.host + - **Typ**: String - **Default**: localhost - **Environment Variable**: `CONSUL_HOST` - **Beschreibung**: Hostname des Consul-Servers ### spring.cloud.consul.port + - **Typ**: Integer - **Default**: 8500 - **Environment Variable**: `CONSUL_PORT` - **Beschreibung**: Port des Consul-Servers ### spring.cloud.consul.enabled + - **Typ**: Boolean - **Default**: true - **Environment Variable**: `CONSUL_ENABLED` - **Beschreibung**: Aktiviert/Deaktiviert Consul Integration ### spring.cloud.consul.discovery.enabled + - **Typ**: Boolean - **Default**: true - **Environment Variable**: `CONSUL_ENABLED` - **Beschreibung**: Aktiviert Service Discovery ### spring.cloud.consul.discovery.register + - **Typ**: Boolean - **Default**: true - **Environment Variable**: `CONSUL_ENABLED` - **Beschreibung**: Registriert das Gateway in Consul ### spring.cloud.consul.discovery.health-check-path + - **Typ**: String - **Default**: /actuator/health - **Beschreibung**: Pfad für Consul Health Checks ### spring.cloud.consul.discovery.health-check-interval + - **Typ**: Duration - **Default**: 10s - **Beschreibung**: Intervall für Health Checks ### spring.cloud.consul.discovery.instance-id + - **Typ**: String - **Default**: ${spring.application.name}-${server.port}-${random.uuid} - **Beschreibung**: Eindeutige Instanz-ID für Service Discovery **Beispiel:** + ```yaml spring: cloud: @@ -152,26 +169,31 @@ spring: ### Verbindungskonfiguration #### spring.cloud.gateway.server.webflux.httpclient.connect-timeout + - **Typ**: Integer (Millisekunden) - **Default**: 5000 - **Beschreibung**: Timeout für Backend-Verbindungen #### spring.cloud.gateway.server.webflux.httpclient.response-timeout + - **Typ**: Duration - **Default**: 30s - **Beschreibung**: Timeout für Backend-Responses #### spring.cloud.gateway.server.webflux.httpclient.pool.max-idle-time + - **Typ**: Duration - **Default**: 15s - **Beschreibung**: Max. Idle-Zeit für Verbindungen im Pool #### spring.cloud.gateway.server.webflux.httpclient.pool.max-life-time + - **Typ**: Duration - **Default**: 60s - **Beschreibung**: Max. Lebensdauer einer Verbindung **Beispiel:** + ```yaml spring: cloud: @@ -197,6 +219,7 @@ Diese Filter werden auf **alle** Routen angewendet: 5. **Cache-Control**: No-cache Header für alle Responses **Beispiel:** + ```yaml spring: cloud: @@ -223,41 +246,48 @@ spring: Das Gateway definiert folgende Service-Routen: #### 1. Members Service Route + - **Path**: `/api/members/**` - **Service**: members-service (via Consul) - **Circuit Breaker**: membersCircuitBreaker - **Fallback**: /fallback/members #### 2. Horses Service Route + - **Path**: `/api/horses/**` - **Service**: horses-service (via Consul) - **Circuit Breaker**: horsesCircuitBreaker - **Fallback**: /fallback/horses #### 3. Events Service Route + - **Path**: `/api/events/**` - **Service**: events-service (via Consul) - **Circuit Breaker**: eventsCircuitBreaker - **Fallback**: /fallback/events #### 4. Masterdata Service Route + - **Path**: `/api/masterdata/**` - **Service**: masterdata-service (via Consul) - **Circuit Breaker**: masterdataCircuitBreaker - **Fallback**: /fallback/masterdata #### 5. Auth Service Route + - **Path**: `/api/auth/**` - **Service**: auth-service (via Consul) - **Circuit Breaker**: authCircuitBreaker - **Fallback**: /fallback/auth #### 6. Ping Service Route + - **Path**: `/api/ping/**` - **Service**: ping-service (via Consul) - **No Circuit Breaker**: Optional service **Beispiel einer Route:** + ```yaml spring: cloud: @@ -282,31 +312,37 @@ spring: ### Default Konfiguration #### resilience4j.circuitbreaker.configs.default.registerHealthIndicator + - **Typ**: Boolean - **Default**: true - **Beschreibung**: Registriert Circuit Breaker im Health Endpoint #### resilience4j.circuitbreaker.configs.default.slidingWindowSize + - **Typ**: Integer - **Default**: 100 - **Beschreibung**: Größe des Sliding Window für Fehlerrate-Berechnung #### resilience4j.circuitbreaker.configs.default.minimumNumberOfCalls + - **Typ**: Integer - **Default**: 20 - **Beschreibung**: Mindestanzahl an Calls bevor Circuit Breaker aktiviert wird #### resilience4j.circuitbreaker.configs.default.permittedNumberOfCallsInHalfOpenState + - **Typ**: Integer - **Default**: 3 - **Beschreibung**: Anzahl Test-Calls im Half-Open State #### resilience4j.circuitbreaker.configs.default.waitDurationInOpenState + - **Typ**: Duration - **Default**: 5s - **Beschreibung**: Wartezeit bevor von Open zu Half-Open gewechselt wird #### resilience4j.circuitbreaker.configs.default.failureRateThreshold + - **Typ**: Integer (Prozent) - **Default**: 50 - **Beschreibung**: Fehlerrate-Schwelle für Circuit Breaker Aktivierung @@ -324,6 +360,7 @@ Jeder Service hat einen eigenen Circuit Breaker mit angepasster Konfiguration: | auth-service | 20 | 30% | Sensitiverer Threshold | **Beispiel:** + ```yaml resilience4j: circuitbreaker: @@ -341,11 +378,13 @@ resilience4j: ### Exposed Endpoints #### management.endpoints.web.exposure.include + - **Typ**: Comma-separated String - **Default**: health,info,metrics,prometheus,gateway,circuitbreakers - **Beschreibung**: Öffentlich verfügbare Actuator Endpoints **Verfügbare Endpoints:** + - `/actuator/health` - Service Health Status - `/actuator/info` - Service Informationen - `/actuator/metrics` - Micrometer Metriken @@ -356,17 +395,20 @@ resilience4j: ### Health Endpoint #### management.endpoint.health.show-details + - **Typ**: String - **Default**: always - **Mögliche Werte**: never, when-authorized, always - **Beschreibung**: Zeigt detaillierte Health-Informationen #### management.endpoint.health.show-components + - **Typ**: Boolean - **Default**: always - **Beschreibung**: Zeigt Health-Komponenten #### management.endpoint.health.probes.enabled + - **Typ**: Boolean - **Default**: true - **Beschreibung**: Aktiviert Kubernetes Liveness/Readiness Probes @@ -374,6 +416,7 @@ resilience4j: ### Metrics #### management.metrics.tags + - **Beschreibung**: Globale Tags für alle Metriken - **Standard Tags**: - application: ${spring.application.name} @@ -384,11 +427,13 @@ resilience4j: - gateway: api-gateway #### management.metrics.distribution.percentiles-histogram.http.server.requests + - **Typ**: Boolean - **Default**: true - **Beschreibung**: Aktiviert Histogram für Request-Zeiten #### management.metrics.distribution.percentiles.http.server.requests + - **Typ**: Array[Double] - **Default**: [0.5, 0.90, 0.95, 0.99] - **Beschreibung**: Percentile-Werte für Request-Zeiten @@ -396,24 +441,28 @@ resilience4j: ### Tracing #### management.tracing.enabled + - **Typ**: Boolean - **Default**: false - **Environment Variable**: `TRACING_ENABLED` - **Beschreibung**: Aktiviert Distributed Tracing #### management.tracing.sampling.probability + - **Typ**: Double (0.0 - 1.0) - **Default**: 1.0 - **Environment Variable**: `TRACING_SAMPLING_PROBABILITY` - **Beschreibung**: Sampling-Rate für Traces (1.0 = 100%) #### management.zipkin.tracing.endpoint + - **Typ**: URL -- **Default**: http://localhost:9411/api/v2/spans +- **Default**: - **Environment Variable**: `ZIPKIN_TRACING_ENDPOINT` - **Beschreibung**: Zipkin Server URL **Beispiel:** + ```yaml management: endpoints: @@ -441,41 +490,49 @@ management: Die Security-Konfiguration erfolgt über Custom Properties unter `gateway.security`: ### gateway.security.publicPaths + - **Typ**: Array[String] - **Default**: ["/", "/fallback/**", "/actuator/**", "/webjars/**", "/v3/api-docs/**", "/api/auth/**"] - **Beschreibung**: Pfade, die ohne Authentifizierung zugänglich sind ### gateway.security.cors.allowedOriginPatterns + - **Typ**: Array[String] - **Default**: ["http://localhost:[*]", "https://*.meldestelle.at"] - **Beschreibung**: Erlaubte Origin-Patterns für CORS ### gateway.security.cors.allowedMethods + - **Typ**: Array[String] - **Default**: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"] - **Beschreibung**: Erlaubte HTTP-Methoden ### gateway.security.cors.allowedHeaders + - **Typ**: Array[String] - **Default**: ["*"] - **Beschreibung**: Erlaubte Request-Headers ### gateway.security.cors.exposedHeaders + - **Typ**: Array[String] - **Default**: ["X-Correlation-ID", "X-RateLimit-Limit", "X-RateLimit-Remaining"] - **Beschreibung**: Headers die an Client exponiert werden ### gateway.security.cors.allowCredentials + - **Typ**: Boolean - **Default**: true - **Beschreibung**: Erlaubt Credentials (Cookies, Auth-Header) ### gateway.security.cors.maxAge + - **Typ**: Duration - **Default**: 1h - **Beschreibung**: Cache-Zeit für CORS Preflight-Requests **Beispiel:** + ```yaml gateway: security: @@ -499,19 +556,22 @@ gateway: ### JWT Configuration #### spring.security.oauth2.resourceserver.jwt.jwk-set-uri + - **Typ**: URL - **Environment Variable**: `KEYCLOAK_JWK_SET_URI` - **Beschreibung**: Keycloak JWK Set URI für JWT-Validierung -- **Beispiel**: http://localhost:8180/realms/meldestelle/protocol/openid-connect/certs +- **Beispiel**: --- ## Logging ### logging.level + - **Beschreibung**: Log-Level für verschiedene Pakete **Standard Log-Levels:** + - `org.springframework.cloud.gateway`: INFO - `org.springframework.cloud.loadbalancer`: DEBUG - `org.springframework.cloud.consul`: INFO @@ -522,23 +582,28 @@ gateway: - `org.springframework.web`: INFO ### logging.pattern.console + - **Beschreibung**: Console-Log-Pattern mit Farben und Correlation-ID ### logging.pattern.file + - **Beschreibung**: File-Log-Pattern ohne Farben ### logging.file.name + - **Typ**: String - **Default**: infrastructure/gateway/logs/gateway.log - **Beschreibung**: Log-Datei Pfad ### logging.logback.rollingpolicy + - **clean-history-on-start**: true - **max-file-size**: 100MB - **total-size-cap**: 1GB - **max-history**: 30 (Tage) **Beispiel:** + ```yaml logging: level: @@ -566,9 +631,9 @@ logging: | `CONSUL_ENABLED` | Consul Aktivieren | true | | `GATEWAY_ADMIN_USER` | Admin Username | admin | | `GATEWAY_ADMIN_PASSWORD` | Admin Password | admin | -| `KEYCLOAK_JWK_SET_URI` | Keycloak JWK URI | http://localhost:8180/... | +| `KEYCLOAK_JWK_SET_URI` | Keycloak JWK URI | ... | | `TRACING_ENABLED` | Tracing aktivieren | false | -| `ZIPKIN_TRACING_ENDPOINT` | Zipkin Server | http://localhost:9411/... | +| `ZIPKIN_TRACING_ENDPOINT` | Zipkin Server | ... | | `SPRING_PROFILES_ACTIVE` | Spring Profil | dev | --- @@ -578,22 +643,26 @@ logging: Das Gateway unterstützt verschiedene Spring Profile: ### dev (Development) + - Detailliertes Logging - Alle Monitoring-Endpunkte verfügbar - Tracing optional ### test + - Reduziertes Logging - Test-spezifische Timeouts - In-Memory Services optional ### prod (Production) + - Production-ready Logging - Sichere Credentials erforderlich - Tracing empfohlen - Rate Limiting aktiviert **Beispiel für profile-spezifische Datei:** + ```yaml # application-prod.yml spring: @@ -631,21 +700,25 @@ logging: ## Troubleshooting ### Gateway startet nicht + - ✅ Prüfen: Consul erreichbar? - ✅ Prüfen: Port 8081 frei? - ✅ Prüfen: Keycloak erreichbar? (Optional) ### Service nicht erreichbar + - ✅ Prüfen: Service in Consul registriert? - ✅ Prüfen: Circuit Breaker offen? - ✅ Prüfen: Health Check erfolgreich? ### CORS-Fehler + - ✅ Prüfen: Origin in allowedOriginPatterns? - ✅ Prüfen: Methode in allowedMethods? - ✅ Prüfen: allowCredentials korrekt? ### Hohe Latenz + - ✅ Prüfen: response-timeout zu hoch? - ✅ Prüfen: Backend-Services langsam? - ✅ Prüfen: Connection Pool ausgeschöpft? diff --git a/infrastructure/gateway/README-INFRA-GATEWAY.md b/infrastructure/gateway/README-INFRA-GATEWAY.md index f947364b..48b995b3 100644 --- a/infrastructure/gateway/README-INFRA-GATEWAY.md +++ b/infrastructure/gateway/README-INFRA-GATEWAY.md @@ -11,6 +11,7 @@ Das API-Gateway ist der zentrale und einzige öffentliche Einstiegspunkt für al Das Gateway ist als eigenständiger Spring Boot Service implementiert und nutzt Spring Cloud Gateway als technologische Grundlage. Spring Cloud Gateway ist ein reaktives, nicht-blockierendes Framework, das sich nahtlos in das Spring-Ökosystem integriert. ### Technologie-Stack + - **Spring Boot 3.x** - Moderne Spring Boot Anwendung - **Spring Cloud Gateway** - Reaktives Gateway Framework - **Spring WebFlux** - Reaktive Web-Programmierung mit Netty @@ -25,11 +26,13 @@ Das Gateway ist als eigenständiger Spring Boot Service implementiert und nutzt Das Gateway handhabt alle Cross-Cutting Concerns (übergreifende Belange), die für mehrere oder alle Microservices gelten und entlastet damit die Fach-Services von technischen Aufgaben. ### 1. Dynamisches Routing + - **Service Discovery Integration**: Vollständige Consul Integration für automatische Service-Erkennung - **Load Balancing**: Intelligente Lastverteilung zwischen Service-Instanzen - **Health-basiertes Routing**: Weiterleitung nur an gesunde Service-Instanzen **Verfügbare Routen**: + - `/api/members/**` → members-service - `/api/horses/**` → horses-service - `/api/events/**` → events-service @@ -38,12 +41,14 @@ Das Gateway handhabt alle Cross-Cutting Concerns (übergreifende Belange), die f - `/api/ping/**` → ping-service ### 2. Sicherheit und Authentifizierung + - **JWT Security Enforcement**: Validierung von Bearer Tokens für alle geschützten Endpunkte - **Public Path Exemptions**: Konfigurierbare öffentliche Pfade (`/`, `/health`, `/actuator/**`, `/api/auth/login`) - **User Context Injection**: Automatische Weiterleitung von User-ID und Rolle an Backend Services - **Standardisierte Fehlerbehandlung**: Strukturierte 401 Unauthorized Responses ### 3. Rate Limiting + - **Intelligentes Rate Limiting** basierend auf User-Typ: - **Anonymous Users**: 50 Anfragen pro Minute - **Authenticated Users**: 200 Anfragen pro Minute @@ -52,15 +57,18 @@ Das Gateway handhabt alle Cross-Cutting Concerns (übergreifende Belange), die f - **Custom Headers**: X-RateLimit-* Header für Client-Information ### 4. Circuit Breaker und Resilienz + - **Service-spezifische Circuit Breaker**: Resilience4j Integration für jeden Backend Service - **Fallback Mechanismen**: Benutzerfreundliche Fehlermeldungen bei Service-Ausfällen - **Retry Logic**: Automatische Wiederholungen bei transienten Fehlern - **Graceful Degradation**: Systembetrieb auch bei partiellen Service-Ausfällen ### 5. Monitoring und Observability + Das Gateway implementiert umfassende Observability durch eine vollständig integrierte Micrometer-basierte Metriken-Architektur. #### Automatische Metriken-Erfassung (GatewayMetricsConfig) + - **Request Duration Tracking**: Automatische Messung aller Request-Response Zyklen - Metric: `gateway_request_duration` (Timer) - Tags: method, path, status, status_series @@ -77,12 +85,14 @@ Das Gateway implementiert umfassende Observability durch eine vollständig integ - Integration mit Resilience4j Circuit Breaker Status #### Intelligente Pfad-Normalisierung + - **Kardinalitäts-Kontrolle**: Automatische Normalisierung von dynamischen Pfaden - `/api/horses/123` → `/api/horses/{id}` - UUID-Pattern → `/{uuid}` - Sehr lange Pfade werden gekürzt (100+ Zeichen) #### Health Monitoring Integration + - **Downstream Service Health**: Umfassende Überwachung aller Backend Services - Kritische Services: Members, Horses, Events, Masterdata, Auth - Optionale Services: Ping Service @@ -91,11 +101,13 @@ Das Gateway implementiert umfassende Observability durch eine vollständig integ - **Strukturierte Logs**: JSON-Format für maschinelle Auswertung #### Prometheus Export + - **Automatischer Export**: Alle Metriken werden automatisch an Prometheus exportiert - **Common Tags**: Alle Metriken erhalten automatisch Service- und Component-Tags - **Filter-Optimierung**: Rauschen-reduzierende Metrik-Filter für interne Spring/Netty Metriken ### 6. CORS-Management + - **Produktionstaugliche CORS-Konfiguration**: - Erlaubte Origins: `https://*.meldestelle.at`, `http://localhost:*` - Alle HTTP-Methoden (GET, POST, PUT, DELETE, PATCH, OPTIONS) @@ -104,6 +116,7 @@ Das Gateway implementiert umfassende Observability durch eine vollständig integ ## Implementierte Optimierungen ### Gateway-Konfiguration (application.yml) + ✅ **Vollständige Service-Routen**: Routing für alle Business Services ✅ **Circuit Breaker Integration**: Service-spezifische Resilience4j Konfigurationen ✅ **Connection Pooling**: Optimierte HTTP-Client-Konfiguration @@ -111,24 +124,28 @@ Das Gateway implementiert umfassende Observability durch eine vollständig integ ✅ **Enhanced Logging**: Strukturierte Logs mit Korrelations-IDs und Performance-Daten ### Health Monitoring (GatewayHealthIndicator.kt) + ✅ **Downstream Service Monitoring**: Überwachung aller kritischen Services ✅ **Service Discovery Integration**: Consul-basierte Service-Erkennung ✅ **Test-Environment Handling**: Graceful Degradation in Test-Umgebungen ✅ **Detailliertes Error Reporting**: Umfassende Statusinformationen ### Build-Optimierungen (build.gradle.kts) + ✅ **SINGLE SOURCE OF TRUTH**: Alle Dependencies über libs.versions.toml ✅ **Build Info Generation**: Automatische Build-Metadaten ✅ **Modern Kotlin Compiler**: Optimierte Compiler-Einstellungen ✅ **Dependency Optimization**: Bereinigung redundanter Dependencies ### Docker-Optimierungen (Dockerfile) + ✅ **Multi-Stage Build**: Spring Boot Layer-Extraktion für 90%+ besseres Caching ✅ **Security Hardening**: Non-root User, Security Updates ✅ **OCI Compliance**: Vollständige Container-Metadaten ✅ **Production-Ready**: Optimierte JVM-Settings für Container-Umgebung ### Metriken-Integration (GatewayMetricsConfig.kt) + ✅ **Comprehensive Micrometer Integration**: Vollständige Metriken-Erfassung mit automatischem Prometheus Export ✅ **Request/Response Time Tracking**: Detaillierte Performance-Metriken mit Percentile-Auswertung ✅ **Error Rate Monitoring**: Intelligente Fehler-Klassifikation und -Tracking @@ -137,6 +154,7 @@ Das Gateway implementiert umfassende Observability durch eine vollständig integ ✅ **Custom Business Metrics**: Erweiterbare Metrik-Architektur für fachliche KPIs ### Dokumentation + ✅ **OpenAPI 3.0.3 Spezifikation**: Vollständige API-Dokumentation mit Members Service ✅ **Interactive Swagger UI**: Modern dokumentierte API-Endpunkte ✅ **Static HTML Documentation**: Responsive, moderne Dokumentations-Website @@ -145,16 +163,19 @@ Das Gateway implementiert umfassende Observability durch eine vollständig integ ## Performance und Reliability ### Netty Server Optimierungen + - **Connection Timeouts**: 5 Sekunden für optimale Responsiveness - **Idle Timeout**: 15 Sekunden für effiziente Resource-Nutzung - **Elastic Connection Pool**: Automatische Skalierung basierend auf Load ### Circuit Breaker Konfiguration + - **Sliding Window**: 100 Anfragen für Default, service-spezifische Anpassungen - **Failure Rate Threshold**: 50% für Standard-Services, 30% für Auth-Service - **Half-Open State**: 3 Test-Anfragen für Service-Recovery ### JVM Optimierungen (Container) + ```bash JAVA_OPTS="-server -Xmx512m -Xms256m -XX:+UseG1GC -XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0" @@ -181,6 +202,7 @@ Ein typischer Anfrage-Flow: ## Monitoring und Health Checks ### Actuator Endpunkte + - `/actuator/health` - Umfassender Health Status aller Services - `/actuator/metrics` - Prometheus-kompatible Metriken - `/actuator/info` - Anwendungs- und Build-Informationen @@ -190,6 +212,7 @@ Ein typischer Anfrage-Flow: ### Key Performance Indicators (KPIs) #### Automatisch erfasste Metriken + - **Request Throughput**: `gateway_requests_total` - Anfragen pro Sekunde nach Method/Path - **Response Times**: `gateway_request_duration` - P50, P90, P95, P99 Percentile nach Status - **Error Rates**: `gateway_errors_total` - 4xx/5xx Response Codes mit Error-Type Klassifikation @@ -197,6 +220,7 @@ Ein typischer Anfrage-Flow: - **Service Availability**: Upstream Service Health via Health Indicators #### Verfügbare Metric Tags für detaillierte Analyse + - **method**: HTTP-Method (GET, POST, PUT, DELETE, etc.) - **path**: Normalisierter API-Pfad (z.B. `/api/horses/{id}`) - **status**: HTTP-Status-Code (200, 404, 500, etc.) @@ -206,6 +230,7 @@ Ein typischer Anfrage-Flow: - **component**: Automatisches "infrastructure" Tag #### Prometheus Query Beispiele + ```promql # Request Rate pro Endpunkt rate(gateway_requests_total[5m]) @@ -223,12 +248,14 @@ increase(gateway_circuit_breaker_events_total[1h]) ## Security Features ### JWT Authentication + - **Bearer Token Validation**: Automatische JWT-Verifikation - **Role Extraction**: User-Rolle für Backend Services verfügbar - **Token Refresh**: Unterstützung für Token-Erneuerung - **Public Endpoints**: Konfigurierbare Ausnahmen für öffentliche APIs ### Security Headers + ```yaml X-Content-Type-Options: nosniff X-Frame-Options: DENY @@ -258,6 +285,7 @@ docker run -p 8080:8080 meldestelle/gateway:latest 📖 **Detaillierte Startup-Anleitung:** Siehe `GATEWAY-STARTUP-GUIDE.md` im Projekt-Root für vollständige Befehle und Fehlerbehebung. ### Testing + ```bash # Unit Tests ./gradlew :infrastructure:gateway:test @@ -269,6 +297,7 @@ docker run -p 8080:8080 meldestelle/gateway:latest ## Konfiguration ### Environment Variables + ```bash SPRING_PROFILES_ACTIVE=prod CONSUL_HOST=consul.meldestelle.at @@ -278,6 +307,7 @@ GATEWAY_ADMIN_PASSWORD=secure-password ``` ### Profile-spezifische Konfiguration + - **dev**: Entwicklungsumgebung mit Debug-Logging - **test**: Test-Umgebung mit Mock Services - **prod**: Produktionsumgebung mit allen Security Features @@ -285,6 +315,7 @@ GATEWAY_ADMIN_PASSWORD=secure-password ## Deployment ### Docker Deployment + ```bash # Multi-stage Build mit Layer Caching docker build -t meldestelle/gateway:1.0.0 \ @@ -300,6 +331,7 @@ docker run -d \ ``` ### Kubernetes Deployment + ```yaml apiVersion: apps/v1 kind: Deployment @@ -330,21 +362,25 @@ spec: ### Häufige Probleme **Service Discovery Issues** + - Consul Connectivity prüfen - Service Registration Status überprüfen - DNS Resolution testen **Circuit Breaker Activation** + - Service Health Status prüfen - Failure Rate Threshold analysieren - Manual Circuit Breaker Reset über Actuator **Performance Issues** + - Connection Pool Metrics analysieren - JVM Heap Usage monitoring - Request Rate Limiting überprüfen **Metriken und Monitoring Issues** + - Prometheus Scraping Endpunkt prüfen: `/actuator/prometheus` - Metrics Registry Status überprüfen: `/actuator/metrics` - GatewayMetricsWebFilter Aktivierung validieren @@ -352,6 +388,7 @@ spec: - Path Normalization bei unerwarteten Metric-Namen ### Logging und Debugging + ```bash # Logs mit Korrelations-IDs docker logs gateway | grep "correlationId" @@ -366,12 +403,14 @@ curl http://localhost:8080/actuator/health ## Zukünftige Erweiterungen ### Geplante Features + - **OAuth2/OIDC Integration**: Erweiterte Authentifizierung - **GraphQL Gateway**: Unified GraphQL Interface - **Caching Layer**: Redis-basiertes Response Caching - **Request/Response Transformation**: Dynamic Content Modification ### Performance Optimierungen + - **HTTP/2 Support**: Moderne Protocol-Unterstützung - **Connection Pooling Tuning**: Erweiterte Pool-Konfiguration - **Reactive Streams Optimization**: Backpressure Handling @@ -379,11 +418,13 @@ curl http://localhost:8080/actuator/health ## Dokumentation und Ressourcen ### API Dokumentation + - **Swagger UI**: `/swagger` - Interactive API Documentation - **OpenAPI Spec**: `/openapi` - Machine-readable API Specification - **Static Documentation**: `/docs` - Comprehensive Documentation Hub ### Monitoring Dashboards + - **Health Status**: `/actuator/health` - Real-time Service Health - **Metrics**: `/actuator/metrics` - Prometheus Metrics - **Gateway Routes**: `/actuator/gateway/routes` - Active Route Information diff --git a/infrastructure/gateway/src/main/resources/openapi/documentation.yaml b/infrastructure/gateway/src/main/resources/openapi/documentation.yaml index 7bc5e2c0..b5dda41d 100644 --- a/infrastructure/gateway/src/main/resources/openapi/documentation.yaml +++ b/infrastructure/gateway/src/main/resources/openapi/documentation.yaml @@ -59,6 +59,8 @@ servers: description: Local Development Server tags: + - name: System + description: System information and health check endpoints - name: Authentication description: User authentication, registration, and profile management - name: Members @@ -73,6 +75,8 @@ tags: paths: /: get: + tags: + - System summary: API Gateway Information description: Returns basic information about the API Gateway operationId: getApiGatewayInfo @@ -86,6 +90,8 @@ paths: /health: get: + tags: + - System summary: Health Check description: Returns the health status of all bounded contexts operationId: getHealthStatus @@ -99,6 +105,8 @@ paths: /api: get: + tags: + - System summary: API Documentation description: Returns information about available API endpoints operationId: getApiDocumentation @@ -1509,7 +1517,7 @@ components: phone: type: string pattern: '^\+?[1-9]\d{1,14}$' - example: +43 123 456789 + example: "+43123456789" dateOfBirth: type: string format: date @@ -1543,7 +1551,7 @@ components: phone: type: string pattern: '^\+?[1-9]\d{1,14}$' - example: +43 123 456789 + example: "+43123456789" address: $ref: '#/components/schemas/Address' membershipType: @@ -1629,7 +1637,7 @@ components: example: Wien postalCode: type: string - example: 1010 + example: "1010" state: type: string example: Wien @@ -1844,7 +1852,7 @@ components: example: AT-LIP-2015-123 chipNumber: type: string - example: 040123456789012 + example: "040123456789012" passportNumber: type: string example: AT-P-2015-123 diff --git a/infrastructure/messaging/README-INFRA-MESSAGING.md b/infrastructure/messaging/README-INFRA-MESSAGING.md index b7fc3bb8..35ebcb7a 100644 --- a/infrastructure/messaging/README-INFRA-MESSAGING.md +++ b/infrastructure/messaging/README-INFRA-MESSAGING.md @@ -20,59 +20,57 @@ Das Modul implementiert moderne **Domain-Driven Design (DDD)** Prinzipien mit ex Das Modul ist in zwei spezialisierte Komponenten aufgeteilt, um Konfiguration von der Client-Logik zu trennen: - infrastructure/messaging/ ├── messaging-config/ # Stellt die zentrale Kafka-Konfiguration bereit └── messaging-client/ # Stellt wiederverwendbare, reaktive Clients bereit - ### `messaging-config` Dieses Modul zentralisiert die grundlegende Kafka-Konfiguration für das gesamte Projekt. -* **Zweck:** Definiert Spring-Beans für die `ProducerFactory` (Basis für Producer) und eine `Map` mit Standard-Konfigurationen für Consumer (z.B. `bootstrap-servers`, `group-id`, Serializer). -* **Vorteil:** Stellt Konsistenz sicher und vereinfacht die Einrichtung neuer Producer oder Consumer in den Services. +- **Zweck:** Definiert Spring-Beans für die `ProducerFactory` (Basis für Producer) und eine `Map` mit Standard-Konfigurationen für Consumer (z.B. `bootstrap-servers`, `group-id`, Serializer). +- **Vorteil:** Stellt Konsistenz sicher und vereinfacht die Einrichtung neuer Producer oder Consumer in den Services. ### `messaging-client` Dieses Modul baut auf der Konfiguration auf und stellt wiederverwendbare High-Level-Komponenten für die Interaktion mit Kafka bereit. -#### Kern-Komponenten: +#### Kern-Komponenten -* **`EventPublisher` Interface**: Definiert moderne APIs für das Publizieren von Domain Events - * **Moderne APIs**: `publishEvent()` und `publishEvents()` mit Result Pattern - * **Legacy APIs**: `publishEventReactive()` und `publishEventsReactive()` (deprecated) +- **`EventPublisher` Interface**: Definiert moderne APIs für das Publizieren von Domain Events + - **Moderne APIs**: `publishEvent()` und `publishEvents()` mit Result Pattern + - **Legacy APIs**: `publishEventReactive()` und `publishEventsReactive()` (deprecated) -* **`EventConsumer` Interface**: Definiert APIs für das Empfangen von Domain Events - * **Moderne APIs**: `receiveEventsWithResult()` mit Flow> für typsichere Fehlerbehandlung - * **Legacy APIs**: `receiveEvents()` mit Flux (deprecated) +- **`EventConsumer` Interface**: Definiert APIs für das Empfangen von Domain Events + - **Moderne APIs**: `receiveEventsWithResult()` mit Flow> für typsichere Fehlerbehandlung + - **Legacy APIs**: `receiveEvents()` mit Flux (deprecated) -* **`KafkaEventPublisher`**: Implementierung des EventPublisher mit umfassendem Feature-Set - * Reaktive, nicht-blockierende Kafka-Integration mit `ReactiveKafkaProducerTemplate` - * Intelligente Retry-Logic mit exponential backoff - * Optimierte Batch-Verarbeitung mit kontrollierbarer Parallelität (10 concurrent operations) - * Comprehensive Logging und Progress-Tracking +- **`KafkaEventPublisher`**: Implementierung des EventPublisher mit umfassendem Feature-Set + - Reaktive, nicht-blockierende Kafka-Integration mit `ReactiveKafkaProducerTemplate` + - Intelligente Retry-Logic mit exponential backoff + - Optimierte Batch-Verarbeitung mit kontrollierbarer Parallelität (10 concurrent operations) + - Comprehensive Logging und Progress-Tracking -* **`KafkaEventConsumer`**: Implementierung des EventConsumer mit erweiterten Funktionen - * Connection-Pooling zur Wiederverwendung von KafkaReceiver-Instanzen - * Sichere Deserialisierung mit Trusted-Package-Validierung - * Manual Acknowledgment Control für bessere Kontrolle über Commit-Verhalten - * Consumer-Cache-Management für Ressourcenoptimierung +- **`KafkaEventConsumer`**: Implementierung des EventConsumer mit erweiterten Funktionen + - Connection-Pooling zur Wiederverwendung von KafkaReceiver-Instanzen + - Sichere Deserialisierung mit Trusted-Package-Validierung + - Manual Acknowledgment Control für bessere Kontrolle über Commit-Verhalten + - Consumer-Cache-Management für Ressourcenoptimierung -* **`MessagingError` Hierarchie**: Domain-spezifische Fehlertypen für strukturierte Fehlerbehandlung - * `SerializationError`, `DeserializationError`: Serialization-/Deserialization-Probleme - * `ConnectionError`: Netzwerk- und Verbindungsfehler - * `TimeoutError`: Zeitüberschreitungen - * `AuthenticationError`: Authentifizierungs-/Autorisierungsfehler - * `TopicConfigurationError`: Topic-Konfigurationsprobleme - * `UnexpectedError`: Allgemeine unerwartete Fehler +- **`MessagingError` Hierarchie**: Domain-spezifische Fehlertypen für strukturierte Fehlerbehandlung + - `SerializationError`, `DeserializationError`: Serialization-/Deserialization-Probleme + - `ConnectionError`: Netzwerk- und Verbindungsfehler + - `TimeoutError`: Zeitüberschreitungen + - `AuthenticationError`: Authentifizierungs-/Autorisierungsfehler + - `TopicConfigurationError`: Topic-Konfigurationsprobleme + - `UnexpectedError`: Allgemeine unerwartete Fehler -#### Vorteile: +#### Vorteile -* **Typsichere Fehlerbehandlung**: Result Pattern eliminiert unerwartete Exceptions -* **Flexible APIs**: Sowohl moderne Coroutine-basierte als auch Legacy reaktive APIs -* **Production-Ready**: Umfassendes Retry-Management, Observability und Ressourcenoptimierung -* **Domain-Driven Design**: Explizite Fehlertypen und saubere Abstraktionen +- **Typsichere Fehlerbehandlung**: Result Pattern eliminiert unerwartete Exceptions +- **Flexible APIs**: Sowohl moderne Coroutine-basierte als auch Legacy reaktive APIs +- **Production-Ready**: Umfassendes Retry-Management, Observability und Ressourcenoptimierung +- **Domain-Driven Design**: Explizite Fehlertypen und saubere Abstraktionen ## Verwendung @@ -81,6 +79,7 @@ Ein Microservice, der Nachrichten senden oder empfangen möchte, deklariert eine ### Moderne API (Result Pattern + Coroutines) - **Empfohlen** **Beispiel für das Senden einer Nachricht mit typsicherer Fehlerbehandlung:** + ```kotlin @Service class EventNotificationService( @@ -113,6 +112,7 @@ class EventNotificationService( ``` **Beispiel für das Empfangen von Nachrichten mit typsicherer Fehlerbehandlung:** + ```kotlin @Component class ModernEventListener( @@ -175,6 +175,7 @@ class ModernEventListener( ``` **Beispiel für Consumer mit Coroutines und strukturierter Parallelität:** + ```kotlin @Service class BatchEventProcessor( @@ -215,6 +216,7 @@ class BatchEventProcessor( ### Legacy Reactive API - **Wird depreciert** **Beispiel für das Senden einer Nachricht (reaktiv, nicht-blockierend):** + ```kotlin @Service class LegacyEventNotificationService( @@ -235,6 +237,7 @@ class LegacyEventNotificationService( ``` **Beispiel für das Empfangen von Nachrichten (reaktiv):** + ```kotlin @Component class EventListener( @@ -433,54 +436,54 @@ dependencies { Die Zuverlässigkeit des Moduls wird durch eine mehrstufige Teststrategie sichergestellt, die sowohl Unit- als auch Integrationstests umfasst: ### Integrationstests (Goldstandard) -* **Testcontainers**: Der `KafkaIntegrationTest` startet einen echten Apache Kafka Docker-Container, um die Funktionalität unter realen Bedingungen zu validieren -* **Reaktives Testen**: Nutzt Project Reactor's `StepVerifier` für deterministische Tests der reaktiven Streams ohne unzuverlässige Thread.sleep-Aufrufe -* **Lifecycle Management**: Saubere Ressourcenverwaltung über @BeforeEach und @AfterEach für korrekte Freigabe von Producer-Threads -* **End-to-End Validierung**: Vollständige Publish-Subscribe-Zyklen mit echtem Kafka-Cluster +- **Testcontainers**: Der `KafkaIntegrationTest` startet einen echten Apache Kafka Docker-Container, um die Funktionalität unter realen Bedingungen zu validieren +- **Reaktives Testen**: Nutzt Project Reactor's `StepVerifier` für deterministische Tests der reaktiven Streams ohne unzuverlässige Thread.sleep-Aufrufe +- **Lifecycle Management**: Saubere Ressourcenverwaltung über @BeforeEach und @AfterEach für korrekte Freigabe von Producer-Threads +- **End-to-End Validierung**: Vollständige Publish-Subscribe-Zyklen mit echtem Kafka-Cluster ### Unit Tests -* **`KafkaEventPublisherErrorTest`**: Fokussierte Tests für Fehlerbehandlung mit MockK für isolierte Testszenarien -* **Fehlerszenarien**: Systematische Tests für Serialization-, Authentication-, Connection- und Timeout-Fehler -* **Batch-Verarbeitung**: Validierung von Batch-Operationen und Empty-Batch-Handling -* **Retry-Logic**: Tests für intelligente Retry-Mechanismen und Retry-Exhaustion +- **`KafkaEventPublisherErrorTest`**: Fokussierte Tests für Fehlerbehandlung mit MockK für isolierte Testszenarien +- **Fehlerszenarien**: Systematische Tests für Serialization-, Authentication-, Connection- und Timeout-Fehler +- **Batch-Verarbeitung**: Validierung von Batch-Operationen und Empty-Batch-Handling +- **Retry-Logic**: Tests für intelligente Retry-Mechanismen und Retry-Exhaustion ### Sicherheits- und Konfigurationstests -* **`KafkaSecurityTest`**: Validierung der Sicherheitskonfigurationen und Trusted-Package-Verwaltung -* **`KafkaEventConsumerCacheTest`**: Tests für Consumer-Caching und Ressourcenoptimierung -* **Konfigurationsvalidierung**: Automatische Validierung aller Konfigurationsparameter +- **`KafkaSecurityTest`**: Validierung der Sicherheitskonfigurationen und Trusted-Package-Verwaltung +- **`KafkaEventConsumerCacheTest`**: Tests für Consumer-Caching und Ressourcenoptimierung +- **Konfigurationsvalidierung**: Automatische Validierung aller Konfigurationsparameter ## Neue Features und Optimierungen (2025) ### Domain-Driven Design (DDD) Integration -* **Result Pattern APIs**: Neue suspending Coroutine-basierte APIs mit typsicherer Fehlerbehandlung über das Result Pattern -* **Domain-spezifische Fehlertypen**: Umfassende `MessagingError` Hierarchie (SerializationError, ConnectionError, TimeoutError, AuthenticationError, etc.) -* **Explizite Fehlerbehandlung**: Eliminiert unerwartete Exceptions durch strukturierte Fehler-Typen -* **Backward Compatibility**: Legacy-reactive APIs bleiben verfügbar, sind aber als deprecated markiert +- **Result Pattern APIs**: Neue suspending Coroutine-basierte APIs mit typsicherer Fehlerbehandlung über das Result Pattern +- **Domain-spezifische Fehlertypen**: Umfassende `MessagingError` Hierarchie (SerializationError, ConnectionError, TimeoutError, AuthenticationError, etc.) +- **Explizite Fehlerbehandlung**: Eliminiert unerwartete Exceptions durch strukturierte Fehler-Typen +- **Backward Compatibility**: Legacy-reactive APIs bleiben verfügbar, sind aber als deprecated markiert ### Erweiterte Konfigurationsvalidierung -* **Automatische Validierung**: Alle Konfigurationsparameter werden automatisch bei der Zuweisung validiert -* **Bootstrap-Server-Format**: Unterstützt sowohl einfache (`host:port`) als auch protokoll-präfixierte Formate (`PLAINTEXT://host:port`) -* **Sicherheitsfeatures**: Konfigurierbare Sicherheitsfunktionen für Produktionsumgebungen -* **Connection-Pool-Management**: Konfigurierbare Verbindungspool-Größe für bessere Ressourcenverwaltung +- **Automatische Validierung**: Alle Konfigurationsparameter werden automatisch bei der Zuweisung validiert +- **Bootstrap-Server-Format**: Unterstützt sowohl einfache (`host:port`) als auch protokoll-präfixierte Formate (`PLAINTEXT://host:port`) +- **Sicherheitsfeatures**: Konfigurierbare Sicherheitsfunktionen für Produktionsumgebungen +- **Connection-Pool-Management**: Konfigurierbare Verbindungspool-Größe für bessere Ressourcenverwaltung ### Verbesserte Observability -* **Strukturierte Logs**: Erweiterte Logging-Informationen mit GroupID, Timestamps und Event-Kontext -* **Fehlerkontext**: Detaillierte Fehlerinformationen mit Retry-Status und Event-Type-Details -* **Performance-Tracking**: Bessere Nachvollziehbarkeit von Batch-Operationen und Retry-Versuchen -* **Batch-Progress-Logging**: Automatisches Progress-Logging bei großen Batch-Operationen (alle 100 Events) +- **Strukturierte Logs**: Erweiterte Logging-Informationen mit GroupID, Timestamps und Event-Kontext +- **Fehlerkontext**: Detaillierte Fehlerinformationen mit Retry-Status und Event-Type-Details +- **Performance-Tracking**: Bessere Nachvollziehbarkeit von Batch-Operationen und Retry-Versuchen +- **Batch-Progress-Logging**: Automatisches Progress-Logging bei großen Batch-Operationen (alle 100 Events) ### Robustheit-Verbesserungen -* **Intelligente Retry-Logik**: Differenzierte Retry-Strategien basierend auf Fehlertypen (keine Retries für Serialization/Auth-Fehler) -* **Exponential Backoff**: Konfigurierbare Retry-Delays mit exponential backoff (1s initial, max 10s backoff) -* **Controlled Batch Concurrency**: Optimierte Batch-Verarbeitung mit konfigurierbarer Parallelität (Standard: 10 concurrent operations) -* **Testcontainer-Kompatibilität**: Vollständige Kompatibilität mit Docker-basierten Tests -* **Enhanced Error Handling**: Verbesserte Fehlerbehandlung mit strukturierten Kontext-Informationen +- **Intelligente Retry-Logik**: Differenzierte Retry-Strategien basierend auf Fehlertypen (keine Retries für Serialization/Auth-Fehler) +- **Exponential Backoff**: Konfigurierbare Retry-Delays mit exponential backoff (1s initial, max 10s backoff) +- **Controlled Batch Concurrency**: Optimierte Batch-Verarbeitung mit konfigurierbarer Parallelität (Standard: 10 concurrent operations) +- **Testcontainer-Kompatibilität**: Vollständige Kompatibilität mit Docker-basierten Tests +- **Enhanced Error Handling**: Verbesserte Fehlerbehandlung mit strukturierten Kontext-Informationen ### Test-Suite Optimierung -* **Fokussierte Unit Tests**: Bereinigte Test-Suite mit Fokus auf essentielle Funktionalität -* **MockK Integration**: Moderne Mocking-Frameworks für isolierte Unit Tests -* **StepVerifier Korrekturen**: Korrigierte reaktive Test-Assertions für `Mono` Rückgabetypen -* **Reduced Test Complexity**: Entfernung unnötiger Performance- und Logging-Tests zugunsten fokussierter Funktionstests +- **Fokussierte Unit Tests**: Bereinigte Test-Suite mit Fokus auf essentielle Funktionalität +- **MockK Integration**: Moderne Mocking-Frameworks für isolierte Unit Tests +- **StepVerifier Korrekturen**: Korrigierte reaktive Test-Assertions für `Mono` Rückgabetypen +- **Reduced Test Complexity**: Entfernung unnötiger Performance- und Logging-Tests zugunsten fokussierter Funktionstests ## Troubleshooting @@ -493,6 +496,7 @@ Die Zuverlässigkeit des Moduls wird durch eine mehrstufige Teststrategie sicher **Mögliche Ursachen und Lösungen**: 1. **Kafka-Cluster-Erreichbarkeit prüfen**: + ```bash # Teste Verbindung zu Kafka-Cluster telnet kafka-cluster 9092 @@ -502,12 +506,14 @@ nc -zv kafka-cluster 9092 ``` 2. **Bootstrap-Server-Konfiguration validieren**: + ```kotlin // Multiple Broker für High Availability kafkaConfig.bootstrapServers = "kafka-01:9092,kafka-02:9092,kafka-03:9092" ``` 3. **Netzwerk-Timeouts erhöhen für langsame Verbindungen**: + ```kotlin // Producer-Konfiguration erweitern override fun producerConfigs(): Map = super.producerConfigs() + mapOf( @@ -521,6 +527,7 @@ override fun producerConfigs(): Map = super.producerConfigs() + map **Problem**: `MessagingError.DeserializationError` beim Empfangen von Nachrichten **Lösungsansätze**: + ```kotlin // 1. Trusted Packages erweitern kafkaConfig.trustedPackages = "at.mocode.*,com.mycompany.*,java.util.*" @@ -544,6 +551,7 @@ private suspend fun handlePoisonMessage(topic: String, error: MessagingError.Des **Problem**: Langsame Message-Verarbeitung oder hohe Latenz **Optimierungsstrategien**: + ```kotlin // 1. Connection Pool vergrößern kafkaConfig.connectionPoolSize = 50 @@ -568,6 +576,7 @@ suspend fun processEventsBatch(events: List) { **Problem**: Speicherverbrauch steigt kontinuierlich **Lösungen**: + ```kotlin // 1. Consumer-Cache korrekt verwalten @PreDestroy @@ -696,6 +705,7 @@ A: Die moderne API nutzt das Result Pattern für explizite Fehlerbehandlung und **Q: Wann sollte ich Batch-Verarbeitung verwenden?** A: Batch-Verarbeitung ist empfohlen bei: + - Mehr als 10 Events pro Sekunde - Hoher Netzwerk-Latenz zum Kafka-Cluster - Events, die zusammen verarbeitet werden können @@ -703,6 +713,7 @@ A: Batch-Verarbeitung ist empfohlen bei: **Q: Wie handle ich Backpressure bei hohem Event-Durchsatz?** A: Nutzen Sie die eingebauten Flow-Operatoren: + ```kotlin eventConsumer.receiveEventsWithResult(topic, EventType::class.java) .asFlow() @@ -715,8 +726,6 @@ eventConsumer.receiveEventsWithResult(topic, EventType::class.java) **Letzte Aktualisierung**: 15. August 2025 - - ## Aktualisierungen (September 2025) - ReactiveKafkaConfig: Der Bean kafkaConfig() ist jetzt mit @ConditionalOnMissingBean annotiert. Dadurch wird kein zweiter KafkaConfig-Bean erzeugt, wenn bereits extern einer bereitgestellt wird. Dies verhindert Bean-Kollisionen und erleichtert Überschreibungen in Services/Tests. diff --git a/infrastructure/monitoring/README-INFRA-MONITORING.md b/infrastructure/monitoring/README-INFRA-MONITORING.md index c381c39c..0d89741d 100644 --- a/infrastructure/monitoring/README-INFRA-MONITORING.md +++ b/infrastructure/monitoring/README-INFRA-MONITORING.md @@ -49,6 +49,7 @@ management.zipkin.tracing.endpoint=http://zipkin:9411/api/v2/spans ``` Hinweise: + - Sampling-Rate: In Entwicklung 1.0 (100%). In Produktion sollte dies reduziert werden (z. B. 0.1). - Endpunkte: Der Prometheus-Scrape-Pfad ist einheitlich `/actuator/prometheus`. - Überschreibung: Jede Anwendung kann diese Werte über application.yml/-properties anpassen. diff --git a/logs/gateway.log b/logs/gateway.log index d934a172..f1969f1d 100644 --- a/logs/gateway.log +++ b/logs/gateway.log @@ -1,25 +1,25 @@ -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 +2025-11-06 10:46:06.716 [background-preinit] INFO [] o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final +2025-11-06 10:46:06.759 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - Starting GatewayApplicationKt using Java 21.0.8 with PID 15079 (/home/stefan/WsMeldestelle/Meldestelle/infrastructure/gateway/build/classes/kotlin/main started by stefan in /home/stefan/WsMeldestelle/Meldestelle) +2025-11-06 10:46:06.759 [main] DEBUG [] a.m.i.gateway.GatewayApplicationKt - Running with Spring Boot v3.5.6, Spring v6.2.11 +2025-11-06 10:46:06.760 [main] INFO [] a.m.i.gateway.GatewayApplicationKt - The following 1 profile is active: "dev" +2025-11-06 10:46:08.287 [main] INFO [] o.s.cloud.context.scope.GenericScope - BeanFactory id=4eb90187-1826-32ce-9dc7-fa80cb000915 +2025-11-06 10:46:10.119 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [After] +2025-11-06 10:46:10.119 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Before] +2025-11-06 10:46:10.119 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Between] +2025-11-06 10:46:10.119 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Cookie] +2025-11-06 10:46:10.119 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Header] +2025-11-06 10:46:10.119 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Host] +2025-11-06 10:46:10.119 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Method] +2025-11-06 10:46:10.119 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Path] +2025-11-06 10:46:10.119 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Query] +2025-11-06 10:46:10.119 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [ReadBody] +2025-11-06 10:46:10.119 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [RemoteAddr] +2025-11-06 10:46:10.119 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [XForwardedRemoteAddr] +2025-11-06 10:46:10.119 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [Weight] +2025-11-06 10:46:10.119 [main] INFO [] o.s.c.g.r.RouteDefinitionRouteLocator - Loaded RoutePredicateFactory [CloudFoundryRouteService] +2025-11-06 10:46:10.778 [main] INFO [] o.s.b.a.e.web.EndpointLinksResolver - Exposing 6 endpoints beneath base path '/actuator' +2025-11-06 10:46:11.345 [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-11-06 10:46:11.425 [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) @@ -59,9 +59,9 @@ Caused by: java.net.ConnectException: Verbindungsaufbau abgelehnt 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} +2025-11-06 10:46:11.441 [main] INFO [] o.s.b.w.e.netty.NettyWebServer - Netty started on port 8080 (http) +2025-11-06 10:46:11.444 [main] INFO [] o.s.c.c.s.ConsulServiceRegistry - Registering service with consul: NewService{id='meldestelle-8080-5e7cc71f-5a59-423a-b812-15401589451e', 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-11-06 10:46:11.452 [main] ERROR [] o.s.c.c.s.ConsulServiceRegistry - Error registering service with consul: NewService{id='meldestelle-8080-5e7cc71f-5a59-423a-b812-15401589451e', 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) @@ -122,11 +122,11 @@ Caused by: java.net.ConnectException: Verbindungsaufbau abgelehnt 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 - +2025-11-06 10:46:13.466 [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-11-06 10:46:13.486 [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-15 10:31:27.416 [main] ERROR [] o.s.boot.SpringApplication - Application run failed +2025-11-06 10:46:13.499 [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) diff --git a/masterdata/README.md b/masterdata/README.md index 14e49f3d..2cac59a4 100644 --- a/masterdata/README.md +++ b/masterdata/README.md @@ -1 +1 @@ -# Masterdata Module\n\nThis is a minimal placeholder README to satisfy documentation validation. See docs/index.md for project docs. +# Masterdata Module\n\nThis is a minimal placeholder README to satisfy documentation validation. See docs/index.md for project docs diff --git a/members/README.md b/members/README.md index 84ae5d84..0e336b79 100644 --- a/members/README.md +++ b/members/README.md @@ -1 +1 @@ -# Members Module\n\nThis is a minimal placeholder README to satisfy documentation validation. See docs/index.md for project docs. +# Members Module\n\nThis is a minimal placeholder README to satisfy documentation validation. See docs/index.md for project docs diff --git a/platform/README-PLATFORM.md b/platform/README-PLATFORM.md index 6e6b217a..c7ec6023 100644 --- a/platform/README-PLATFORM.md +++ b/platform/README-PLATFORM.md @@ -10,13 +10,11 @@ Das Modul agiert als eine interne "Single Source of Truth" für alle externen Bi Das Platform-Modul ist in drei spezialisierte Untermodule aufgeteilt, die jeweils eine klare Aufgabe haben: - platform/ ├── platform-bom/ # Bill of Materials (BOM) - Erzwingt Versionen ├── platform-dependencies/ # Bündelt gemeinsame Laufzeit-Abhängigkeiten └── platform-testing/ # Bündelt gemeinsame Test-Abhängigkeiten - ### `platform-bom` Dies ist das wichtigste Modul der Plattform. Es ist als "Bill of Materials" (BOM) konfiguriert und nutzt das `java-platform`-Plugin von Gradle. @@ -31,6 +29,7 @@ Ein einfaches "Sammelmodul", das die am häufigsten benötigten Laufzeit-Abhäng * **Zweck:** Vereinfacht die `build.gradle.kts`-Dateien der Service-Module. Anstatt 5-6 einzelne `kotlinx`- und Logging-Bibliotheken hinzuzufügen, genügt eine einzige Abhängigkeit zu diesem Modul. * **Verwendung:** + ```kotlin // In einem Service-Modul dependencies { @@ -44,12 +43,14 @@ Analog zu `platform-dependencies`, aber speziell für Test-Bibliotheken. * **Zweck:** Stellt ein konsistentes Set an Test-Frameworks (JUnit 5, MockK, AssertJ) und Werkzeugen (Testcontainers) für alle Module bereit. * **Verwendung:** + ```kotlin // In einem Service-Modul dependencies { testImplementation(projects.platform.platformTesting) } ``` + * **Optimierung:** Dieses Modul nutzt die in `libs.versions.toml` definierten `[bundles]`, um die Build-Datei extrem kurz und lesbar zu halten. --- diff --git a/scripts/docker-build.sh b/scripts/docker-build.sh index 4429711b..a152a87c 100755 --- a/scripts/docker-build.sh +++ b/scripts/docker-build.sh @@ -1,7 +1,9 @@ #!/bin/bash # =================================================================== # Docker Build Script with Centralized Version Management -# Automatically sources versions from docker/versions.toml via environment files +# Supports two modes: +# - compat (default): load docker/build-args/*.env (current behavior) +# - envless: parse docker/versions.toml directly and export DOCKER_* vars # =================================================================== set -e @@ -11,6 +13,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" DOCKER_DIR="$PROJECT_ROOT/docker" BUILD_ARGS_DIR="$DOCKER_DIR/build-args" +VERSIONS_TOML="$DOCKER_DIR/versions.toml" # Colors for output RED='\033[0;31m' @@ -36,9 +39,63 @@ print_error() { echo -e "${RED}[ERROR]${NC} $1" } -# Function to load environment files +# --- Helpers to read versions.toml directly (POSIX-friendly) --- +get_version() { + local key=$1 + awk -v k="$key" ' + /^\[versions\]/ { in_section=1; next } + /^\[/ { if (in_section) exit; in_section=0 } + in_section && $1 == k && $2 == "=" { v=$3; gsub(/"/ ,"", v); print v; exit } + ' "$VERSIONS_TOML" || true +} + +get_env_mappings() { + awk '/^\[environment-mapping\]/,/^\[/ { if (/^[a-zA-Z].*= /) { key=$1; val=$3; gsub(/"/,"",val); print key":"val } }' "$VERSIONS_TOML" || true +} + +# Function to load from versions.toml (env-less mode) +load_from_versions() { + if [[ ! -f "$VERSIONS_TOML" ]]; then + print_error "versions.toml not found at $VERSIONS_TOML" + exit 1 + fi + + print_info "Loading centralized versions directly from versions.toml (env-less mode)..." + + # Export BUILD_DATE if not already set + export BUILD_DATE=${BUILD_DATE:-$(date -u +'%Y-%m-%dT%H:%M:%SZ')} + + # Map all environment-mapping keys to DOCKER_* variables using [versions] values + while IFS=: read -r toml_key env_var; do + [[ -z "$toml_key" || -z "$env_var" ]] && continue + val=$(get_version "$toml_key") + if [[ -n "$val" ]]; then + export "$env_var"="$val" + fi + done < <(get_env_mappings) + + # Additional convenience exports used by compose build args + export DOCKER_GRADLE_VERSION="${DOCKER_GRADLE_VERSION:-$(get_version gradle)}" + export DOCKER_JAVA_VERSION="${DOCKER_JAVA_VERSION:-$(get_version java)}" + export DOCKER_NODE_VERSION="${DOCKER_NODE_VERSION:-$(get_version node)}" + export DOCKER_NGINX_VERSION="${DOCKER_NGINX_VERSION:-$(get_version nginx)}" + + # Ensure DOCKER_APP_VERSION is derived from app-version + local app_ver + app_ver=$(get_version "app-version") + if [[ -n "$app_ver" ]]; then + export DOCKER_APP_VERSION="$app_ver" + fi + + # Backwards compatibility for scripts expecting plain names + export VERSION="${VERSION:-$app_ver}" + + print_success "versions.toml loaded; DOCKER_* variables exported." +} + +# Function to load environment files (compat mode) load_env_files() { - print_info "Loading centralized Docker version environment files..." + print_info "Loading centralized Docker version environment files (compat mode)..." # Load global environment variables if [[ -f "$BUILD_ARGS_DIR/global.env" ]]; then @@ -141,21 +198,21 @@ show_help() { echo " -v, --versions Show current versions" echo " -h, --help Show this help message" echo "" + echo "Environment:" + echo " DOCKER_SSOT_MODE=envless|compat Default: compat" + echo "" echo "Examples:" echo " $0 services # Build all services" echo " $0 clients # Build client applications" echo " $0 all # Build everything" echo " $0 --versions # Show current versions" - echo "" - echo "The script automatically loads versions from:" - echo " - docker/build-args/global.env" - echo " - docker/build-args/services.env" - echo " - docker/build-args/clients.env" - echo " - docker/build-args/infrastructure.env" + echo " DOCKER_SSOT_MODE=envless $0 --versions # Use versions.toml directly" } # Main execution main() { + local MODE="${DOCKER_SSOT_MODE:-compat}" + # Parse command line arguments case $1 in -h|--help) @@ -163,7 +220,11 @@ main() { exit 0 ;; -v|--versions) - load_env_files + if [[ "$MODE" == "envless" ]]; then + load_from_versions + else + load_env_files + fi show_versions exit 0 ;; @@ -174,7 +235,11 @@ main() { ;; *) # Load environment and build - load_env_files + if [[ "$MODE" == "envless" ]]; then + load_from_versions + else + load_env_files + fi show_versions echo "" build_category "$1" diff --git a/scripts/docker-versions-update.sh b/scripts/docker-versions-update.sh index 54717ec4..934d1f0d 100755 --- a/scripts/docker-versions-update.sh +++ b/scripts/docker-versions-update.sh @@ -77,11 +77,14 @@ sync_to_env_files() { local spring_default=$(get_version "spring-profiles-default") # shellcheck disable=SC2155 local spring_docker=$(get_version "spring-profiles-docker") - # shellcheck disable=SC2155 - local alpine_version=$(get_version "alpine") local prometheus_version=$(get_version "prometheus") local grafana_version=$(get_version "grafana") local keycloak_version=$(get_version "keycloak") + local postgres_version=$(get_version "postgres") + local redis_version=$(get_version "redis") + local consul_version=$(get_version "consul") + local zookeeper_version=$(get_version "zookeeper") + local kafka_version=$(get_version "kafka") # Update global.env cat > "$BUILD_ARGS_DIR/global.env" << EOF @@ -96,18 +99,21 @@ GRADLE_VERSION=$gradle_version JAVA_VERSION=$java_version # --- Build Metadata --- -BUILD_DATE=\$(date -u +'%Y-%m-%dT%H:%M:%SZ') VERSION=$app_version -# --- Common Base Images --- -ALPINE_VERSION=$alpine_version -ECLIPSE_TEMURIN_JDK_VERSION=$java_version-jdk-alpine -ECLIPSE_TEMURIN_JRE_VERSION=$java_version-jre-alpine - # --- Monitoring & Infrastructure Services --- DOCKER_PROMETHEUS_VERSION=$prometheus_version DOCKER_GRAFANA_VERSION=$grafana_version DOCKER_KEYCLOAK_VERSION=$keycloak_version + +# --- Datastore Images --- +DOCKER_POSTGRES_VERSION=$postgres_version +DOCKER_REDIS_VERSION=$redis_version + +# --- Additional Infrastructure Images --- +DOCKER_CONSUL_VERSION=$consul_version +DOCKER_ZOOKEEPER_VERSION=$zookeeper_version +DOCKER_KAFKA_VERSION=$kafka_version EOF print_success "Updated global.env" @@ -120,7 +126,7 @@ EOF # =================================================================== # --- Include Global Arguments --- -# Source global.env for GRADLE_VERSION, JAVA_VERSION, BUILD_DATE, VERSION +# Source global.env for GRADLE_VERSION, JAVA_VERSION, VERSION # --- Client-Specific Build Tools --- NODE_VERSION=$node_version @@ -133,12 +139,10 @@ CLIENT_NAME=meldestelle-client # --- Web Application Specific --- WEB_APP_PORT=4000 -WEB_APP_BUILD_TARGET=wasmJsBrowserDistribution # --- Desktop Application Specific --- DESKTOP_APP_VNC_PORT=5901 DESKTOP_APP_NOVNC_PORT=6080 -DESKTOP_APP_BUILD_TARGET=composeDesktop # --- Client Environment --- NODE_ENV=production @@ -160,7 +164,7 @@ EOF # =================================================================== # --- Include Global Arguments --- -# Source global.env for GRADLE_VERSION, JAVA_VERSION, BUILD_DATE, VERSION +# Source global.env for GRADLE_VERSION, JAVA_VERSION, VERSION # --- Spring Boot Services Configuration --- SPRING_PROFILES_ACTIVE=$spring_docker @@ -191,7 +195,7 @@ EOF # =================================================================== # --- Include Global Arguments --- -# Source global.env for GRADLE_VERSION, JAVA_VERSION, BUILD_DATE, VERSION +# Source global.env for GRADLE_VERSION, JAVA_VERSION, VERSION # --- Infrastructure Services Configuration --- SPRING_PROFILES_ACTIVE=$spring_default @@ -225,6 +229,22 @@ DB_NAME=meldestelle EOF print_success "Updated infrastructure.env" + # --- Post-generation cleanup to enforce SSoT policies --- + # 1) Remove any accidental bare DOCKER_* placeholders from non-global envs + sed -i "/^DOCKER_[A-Z0-9_]\+$/d" "$BUILD_ARGS_DIR/services.env" || true + sed -i "/^DOCKER_[A-Z0-9_]\+$/d" "$BUILD_ARGS_DIR/infrastructure.env" || true + sed -i "/^DOCKER_[A-Z0-9_]\+$/d" "$BUILD_ARGS_DIR/clients.env" || true + + # 2) Remove forbidden DOCKER_APP_VERSION from all build-args envs (it is mapped at runtime) + sed -i "/^DOCKER_APP_VERSION\(=.*\)\?$/d" "$BUILD_ARGS_DIR/global.env" || true + sed -i "/^DOCKER_APP_VERSION\(=.*\)\?$/d" "$BUILD_ARGS_DIR/clients.env" || true + sed -i "/^DOCKER_APP_VERSION\(=.*\)\?$/d" "$BUILD_ARGS_DIR/services.env" || true + sed -i "/^DOCKER_APP_VERSION\(=.*\)\?$/d" "$BUILD_ARGS_DIR/infrastructure.env" || true + + # 3) Purge stray numeric service-port assignments that must not live in global.env + # e.g., lines like: prometheus = 9090 + sed -i -E "/^[a-z_]+ = [0-9]+$/d" "$BUILD_ARGS_DIR/global.env" || true + print_success "All environment files synced successfully!" } diff --git a/scripts/generate-compose-files.sh b/scripts/generate-compose-files.sh index 911d99a3..3960b039 100755 --- a/scripts/generate-compose-files.sh +++ b/scripts/generate-compose-files.sh @@ -41,20 +41,36 @@ print_error() { # Function to extract version from TOML file get_version() { local key=$1 - grep "^$key = " "$VERSIONS_TOML" | sed 's/.*= "\(.*\)"/\1/' || echo "" + awk -v k="$key" ' + /^\[versions\]/ { in_section=1; next } + /^\[/ { if (in_section) exit; in_section=0 } + in_section && $1 == k && $2 == "=" { + val = $3; gsub(/"/, "", val); print val; exit + } + ' "$VERSIONS_TOML" || echo "" } # Function to extract port from TOML file get_port() { local service=$1 - grep "^$service = " "$VERSIONS_TOML" | grep -A 50 "\[service-ports\]" | grep "^$service = " | sed 's/.*= \(.*\)/\1/' || echo "" + awk -v key="$service" ' + /^\[service-ports\]/ { in_section=1; next } + /^\[/ { in_section=0 } + in_section && $1 == key { print $3; exit } + ' "$VERSIONS_TOML" || echo "" } # Function to extract environment config from TOML file get_env_config() { local env=$1 local key=$2 - awk "/\[environments\.$env\]/,/^\[/ {if (/^$key = /) {gsub(/.*= \"?|\"?$/, \"\"); print}}" "$VERSIONS_TOML" || echo "" + awk -v env="$env" -v k="$key" ' + $0 ~ "^\\[environments\."env"\\]" { in_section=1; next } + /^\[/ { if (in_section) exit; in_section=0 } + in_section && $1 == k && $2 == "=" { + val=$3; gsub(/"/, "", val); print val; exit + } + ' "$VERSIONS_TOML" || echo "" } # Function to generate build args section for a service category @@ -63,31 +79,31 @@ generate_build_args_section() { cat << EOF args: - # Global build arguments (from docker/build-args/global.env) - GRADLE_VERSION: \${DOCKER_GRADLE_VERSION:-$(get_version "gradle")} - JAVA_VERSION: \${DOCKER_JAVA_VERSION:-$(get_version "java")} + # Global build arguments (centralized DOCKER_* variables) + GRADLE_VERSION: \${DOCKER_GRADLE_VERSION} + JAVA_VERSION: \${DOCKER_JAVA_VERSION} BUILD_DATE: \${BUILD_DATE} - VERSION: \${DOCKER_APP_VERSION:-$(get_version "app-version")} + VERSION: \${DOCKER_APP_VERSION} EOF case $category in "services") cat << EOF - # Service-specific arguments (from docker/build-args/services.env) - SPRING_PROFILES_ACTIVE: \${DOCKER_SPRING_PROFILES_DOCKER:-$(get_version "spring-profiles-docker")} + # Service-specific arguments (centralized DOCKER_* variables) + SPRING_PROFILES_ACTIVE: \${DOCKER_SPRING_PROFILES_DOCKER} EOF ;; "infrastructure") cat << EOF - # Infrastructure-specific arguments (from docker/build-args/infrastructure.env) - SPRING_PROFILES_ACTIVE: \${DOCKER_SPRING_PROFILES_DEFAULT:-$(get_version "spring-profiles-default")} + # Infrastructure-specific arguments (centralized DOCKER_* variables) + SPRING_PROFILES_ACTIVE: \${DOCKER_SPRING_PROFILES_DEFAULT} EOF ;; "clients") cat << EOF - # Client-specific arguments (from docker/build-args/clients.env) - NODE_VERSION: \${DOCKER_NODE_VERSION:-$(get_version "node")} - NGINX_VERSION: \${DOCKER_NGINX_VERSION:-$(get_version "nginx")} + # Client-specific arguments (centralized DOCKER_* variables) + NODE_VERSION: \${DOCKER_NODE_VERSION} + NGINX_VERSION: \${DOCKER_NGINX_VERSION} EOF ;; esac @@ -103,11 +119,13 @@ generate_environment_vars_for_service() { local log_level=$(get_env_config $environment "log-level") local debug_port=$(get_env_config $environment "jvm-debug-port") local service_port=$(get_port $service) + local service_upper=$(echo "$service" | tr '[:lower:]' '[:upper:]' | tr '-' '_') + local port_var="${service_upper}_PORT" cat << EOF environment: SPRING_PROFILES_ACTIVE: \${SPRING_PROFILES_ACTIVE:-$spring_profiles} - SERVER_PORT: \${${service^^}_PORT:-$service_port} + SERVER_PORT: \${$port_var:-$service_port} DEBUG: \${DEBUG:-$debug_enabled} LOGGING_LEVEL_ROOT: \${LOGGING_LEVEL_ROOT:-$log_level} EOF @@ -148,16 +166,25 @@ generate_service_definition() { local service_port=$(get_port $service) local debug_port=$(get_env_config $environment "jvm-debug-port") + # Normalize service name to ENV var pattern (e.g., ping-service -> PING_SERVICE) + local service_upper=$(echo "$service" | tr '[:lower:]' '[:upper:]' | tr '-' '_') + + # Map to actual Dockerfile path when service directory name differs from service key + local dockerfile_service="$service" + if [[ "$category" == "infrastructure" && "$service" == "api-gateway" ]]; then + dockerfile_service="gateway" + fi + cat << EOF $service: build: context: . - dockerfile: dockerfiles/$category/$service/Dockerfile + dockerfile: dockerfiles/$category/$dockerfile_service/Dockerfile $(generate_build_args_section $category) container_name: meldestelle-$service $(generate_environment_vars_for_service $service $environment) ports: - - "\${${service^^}_PORT:-$service_port}:$service_port" + - "\${${service_upper}_PORT:-$service_port}:$service_port" EOF # Add debug port if enabled @@ -192,7 +219,7 @@ services: # Database # =================================================================== postgres: - image: postgres:16-alpine + image: postgres:\${DOCKER_POSTGRES_VERSION:-$(get_version "postgres")} container_name: meldestelle-postgres environment: POSTGRES_USER: \${POSTGRES_USER:-meldestelle} @@ -217,7 +244,7 @@ services: # Cache # =================================================================== redis: - image: redis:7-alpine + image: redis:\${DOCKER_REDIS_VERSION:-$(get_version "redis")} container_name: meldestelle-redis ports: - "\${REDIS_PORT:-$(get_port redis)}:$(get_port redis)" diff --git a/scripts/git-hooks/pre-commit-ssot b/scripts/git-hooks/pre-commit-ssot new file mode 100644 index 00000000..6a2b6096 --- /dev/null +++ b/scripts/git-hooks/pre-commit-ssot @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +# =================================================================== +# Git pre-commit hook: Enforce Docker SSoT (Single Source of Truth) +# Runs lightweight sync/generate/validate and drift check before commit +# Install: make hooks-install (copies this file into .git/hooks/pre-commit) +# =================================================================== + +set -euo pipefail + +ROOT_DIR=$(git rev-parse --show-toplevel) +cd "$ROOT_DIR" + +# Colors +RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' + +info() { echo -e "${YELLOW}[pre-commit][INFO]${NC} $*"; } +success() { echo -e "${GREEN}[pre-commit][OK]${NC} $*"; } +error() { echo -e "${RED}[pre-commit][ERROR]${NC} $*"; } + +MODE="${DOCKER_SSOT_MODE:-compat}" + +# Only run if Docker-related files are in the index or if explicitly requested +if ! git diff --cached --name-only | grep -E '^(docker/|dockerfiles/|docker-compose.*\.yml(\.optimized)?|scripts/(generate-compose-files\.sh|docker-versions-update\.sh|validate-docker-consistency\.sh))' >/dev/null; then + info "No Docker-related changes staged; skipping SSoT checks." + exit 0 +fi + +if [ "$MODE" = "envless" ]; then + info "Env-less mode active → skipping env file sync and using versions.toml directly" +else + info "Synchronizing versions to env files..." + bash scripts/docker-versions-update.sh sync >/dev/null +fi + +info "Regenerating docker-compose files (development)..." +bash scripts/generate-compose-files.sh all development >/dev/null + +info "Validating Docker SSoT consistency (mode: $MODE)..." +if ! DOCKER_SSOT_MODE="$MODE" bash scripts/validate-docker-consistency.sh all >/dev/null; then + error "SSoT validation failed. See details by running: DOCKER_SSOT_MODE=$MODE bash scripts/validate-docker-consistency.sh all" + exit 1 +fi + +info "Checking for drift (ignoring timestamps/comments)..." +CHANGED=$(git diff --name-only || true) +if [ -n "$CHANGED" ]; then + fail=0 + for f in $CHANGED; do + DIFF_FILTERED=$(git diff --unified=0 -- "$f" \ + | awk 'BEGIN{show=0} { \ + if ($0 ~ /^\+\+\+|^---|^@@/) { next } \ + if ($0 ~ /^[+-]# (Generated:|Last updated:)/) { next } \ + if ($0 ~ /^[+-]#\s*Generated from docker\/versions.toml/) { next } \ + if ($0 ~ /^[+-]#\s*Environment:/) { next } \ + if ($0 ~ /^[+-]#\s*Source:/) { next } \ + if ($0 ~ /^[+-]$/) { next } \ + if ($0 ~ /^[+-]/) { print $0 } \ + }') + if [ -n "$DIFF_FILTERED" ]; then + error "SSoT drift detected in $f (beyond timestamps):" + echo "$DIFF_FILTERED" + fail=1 + fi + done + if [ $fail -ne 0 ]; then + if [ "$MODE" = "envless" ]; then + error "Generated artifacts differ from repository. Run:\n DOCKER_SSOT_MODE=envless bash scripts/generate-compose-files.sh all\nThen add and commit the changes." + else + error "Generated artifacts differ from repository. Run:\n bash scripts/docker-versions-update.sh sync\n bash scripts/generate-compose-files.sh all\nThen add and commit the changes." + fi + exit 1 + fi +fi + +success "Docker SSoT checks passed." +exit 0 diff --git a/scripts/setup-keycloak.sh b/scripts/setup-keycloak.sh index 0471b101..cb29519b 100755 --- a/scripts/setup-keycloak.sh +++ b/scripts/setup-keycloak.sh @@ -7,8 +7,9 @@ set -e # Konfiguration KEYCLOAK_URL=${KEYCLOAK_URL:-"http://localhost:8180"} -ADMIN_USER=${KEYCLOAK_ADMIN:-"admin"} -ADMIN_PASSWORD=${KEYCLOAK_ADMIN_PASSWORD:-"admin"} +# Support both new KC_BOOTSTRAP_* (Keycloak 26+) and legacy KEYCLOAK_* env vars +ADMIN_USER=${KC_BOOTSTRAP_ADMIN_USERNAME:-${KEYCLOAK_ADMIN:-"admin"}} +ADMIN_PASSWORD=${KC_BOOTSTRAP_ADMIN_PASSWORD:-${KEYCLOAK_ADMIN_PASSWORD:-"admin"}} REALM_NAME="meldestelle" echo "🚀 Starting Keycloak setup for Meldestelle..." diff --git a/scripts/validate-docker-consistency.sh b/scripts/validate-docker-consistency.sh index 9d3d87b2..86fba9b8 100755 --- a/scripts/validate-docker-consistency.sh +++ b/scripts/validate-docker-consistency.sh @@ -32,23 +32,27 @@ print_info() { print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" - ((CHECKS_PASSED++)) + CHECKS_PASSED=$((CHECKS_PASSED + 1)) } print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" - ((WARNINGS++)) + WARNINGS=$((WARNINGS + 1)) } print_error() { echo -e "${RED}[ERROR]${NC} $1" - ((ERRORS++)) + ERRORS=$((ERRORS + 1)) } -# Function to extract version from TOML file +# Function to extract version from TOML file (restricted to [versions]) get_version() { local key=$1 - grep "^$key = " "$VERSIONS_TOML" | sed 's/.*= "\(.*\)"/\1/' || echo "" + awk -v k="$key" ' + /^\[versions\]/ { in_section=1; next } + /^\[/ { if (in_section) exit; in_section=0 } + in_section && $1 == k && $2 == "=" { v=$3; gsub(/"/,"",v); print v; exit } + ' "$VERSIONS_TOML" || echo "" } # Function to get valid ARG names from TOML @@ -58,20 +62,11 @@ get_valid_args() { # Extract all build-args from [build-args] section awk '/^\[build-args\]/,/^\[/ { - if (/^[a-zA-Z].*= \[/) { - in_array = 1 - line = $0 - gsub(/.*= \[/, "", line) - } - if (in_array) { - gsub(/[\[\]",]/, " ", line) - split(line, args, " ") - for (i in args) { - if (args[i] != "" && args[i] != "]") { - print args[i] - } - } - if (/\]/) in_array = 0 + # Extract tokens inside quotes across array lines + while (match($0, /"[A-Za-z0-9_]+"/)) { + token = substr($0, RSTART+1, RLENGTH-2) + print token + $0 = substr($0, RSTART+RLENGTH) } }' "$VERSIONS_TOML" || true @@ -103,8 +98,8 @@ validate_dockerfile_args() { return fi - # Get all ARG declarations from Dockerfile - local dockerfile_args=$(grep "^ARG " "$dockerfile" | sed 's/^ARG //' | sed 's/=.*//' | sort -u) + # Get all ARG declarations from Dockerfile (allow none without exiting) + local dockerfile_args=$({ grep "^ARG " "$dockerfile" || true; } | sed 's/^ARG //' | sed 's/=.*//' | sort -u) # Get valid ARG names from TOML local valid_args=$(get_valid_args | sort -u) @@ -129,7 +124,7 @@ validate_dockerfile_args() { has_centralized_args=true ;; # Application-specific args that should be centralized - GRADLE_VERSION|JAVA_VERSION|NODE_VERSION|NGINX_VERSION|BUILD_DATE|VERSION|SPRING_PROFILES_ACTIVE|SERVICE_PATH|SERVICE_NAME|SERVICE_PORT|CLIENT_PATH|CLIENT_MODULE|CLIENT_NAME) + GRADLE_VERSION|JAVA_VERSION|NODE_VERSION|NGINX_VERSION|VERSION|SPRING_PROFILES_ACTIVE|SERVICE_PATH|SERVICE_NAME|SERVICE_PORT|CLIENT_PATH|CLIENT_MODULE|CLIENT_NAME) if echo "$valid_args" | grep -q "^$arg$"; then print_success " ✓ Centralized ARG: $arg" has_centralized_args=true @@ -159,15 +154,27 @@ validate_dockerfile_args() { print_warning " ⚠ Dockerfile should use centralized ARGs from versions.toml" fi - # Check for hardcoded versions - local hardcoded_versions=$(grep -E "ARG.*=.*(alpine|[0-9]+\.[0-9]+)" "$dockerfile" | grep -v "APP_" || true) - if [[ -n "$hardcoded_versions" ]]; then - print_error " ❌ Hardcoded versions found (should use versions.toml):" - echo "$hardcoded_versions" | while read -r line; do - print_error " $line" + # Check for default assignments on centralized ARGs (forbidden) + local centralized_args_regex='^(GRADLE_VERSION|JAVA_VERSION|NODE_VERSION|NGINX_VERSION|VERSION|SPRING_PROFILES_ACTIVE)=' + local defaulted_args=$(grep -nE "^ARG ${centralized_args_regex}" "$dockerfile" || true) + if [[ -n "$defaulted_args" ]]; then + print_error " ❌ Centralized ARGs must not have default values in Dockerfiles:" + echo "$defaulted_args" | while read -r line; do + print_error " $relative_path:$line" done else - print_success " ✓ No hardcoded versions found" + print_success " ✓ No default values set for centralized ARGs" + fi + + # Check for hardcoded versions in ARG default values + local hardcoded_versions=$(grep -nE "^ARG [A-Z0-9_]+=.*(alpine|[0-9]+\.[0-9]+)" "$dockerfile" | grep -v "APP_" || true) + if [[ -n "$hardcoded_versions" ]]; then + print_error " ❌ Hardcoded versions found in ARG defaults (should use versions.toml):" + echo "$hardcoded_versions" | while read -r line; do + print_error " $relative_path:$line" + done + else + print_success " ✓ No hardcoded version literals in ARG defaults" fi } @@ -186,40 +193,146 @@ validate_compose_versions() { # Get environment variable mappings local env_mappings=$(get_env_mappings) + # 0) Fail on blank ARG values for critical build args + local blank_args=$(grep -nE '^[[:space:]]*(GRADLE_VERSION|JAVA_VERSION|NODE_VERSION|NGINX_VERSION|VERSION|SPRING_PROFILES_ACTIVE):[[:space:]]*$' "$compose_file" || true) + if [[ -n "$blank_args" ]]; then + print_error " ❌ Blank build args detected (must reference centralized DOCKER_* variables):" + echo "$blank_args" | while read -r line; do + print_error " $relative_path:$line" + done + else + print_success " ✓ No blank critical build args in compose file" + fi + + # Enforce that critical build args map to centralized DOCKER_* variables (mapping style only) + # IMPORTANT: Only validate mappings inside build->args sections (not environment blocks) + local critical_vars=(GRADLE_VERSION JAVA_VERSION NODE_VERSION NGINX_VERSION VERSION SPRING_PROFILES_ACTIVE) + for v in "${critical_vars[@]}"; do + # Find mapping-style entries for VAR: value that are within an args: block + local mapping_lines=$(awk -v var="$v" ' + { + line[NR] = $0 + } + END { + for (i = 1; i <= NR; i++) { + if (line[i] ~ "^[[:space:]]*" var ":[[:space:]]*.+$") { + found = 0 + # Look back up to 12 lines to see if we are under an args: section + for (j = i - 1; j >= 1 && j >= i - 12; j--) { + if (line[j] ~ /^[[:space:]]*args:[[:space:]]*$/) { found = 1; break } + if (line[j] ~ /^[[:space:]]*(environment|services|volumes|secrets|networks):/ ) { break } + } + if (found) { printf("%d:%s\n", i, line[i]) } + } + } + }' "$compose_file" || true) + if [[ -n "$mapping_lines" ]]; then + while IFS= read -r line; do + # Extract line number and content + local ln=$(echo "$line" | cut -d: -f1) + local content=$(echo "$line" | cut -d: -f2-) + # Ensure value uses ${DOCKER_*} + if echo "$content" | grep -q '\${DOCKER_'; then + : # OK + else + print_error " ❌ $v should reference centralized DOCKER_* variable in build args mapping (found: $content)" + print_error " $relative_path:$ln" + fi + done <<< "$mapping_lines" + fi + done + + # 2a) Validate default fallbacks in ${DOCKER_*:-fallback} match SSoT values + # Build reverse mapping from environment-mapping (env var -> versions key) + declare -A env_to_version_key + while IFS=':' read -r toml_key env_var; do + [[ -z "$toml_key" || -z "$env_var" ]] && continue + case "$toml_key" in + gradle-version) env_to_version_key[$env_var]="gradle";; + java-version) env_to_version_key[$env_var]="java";; + node-version) env_to_version_key[$env_var]="node";; + nginx-version) env_to_version_key[$env_var]="nginx";; + postgres-version) env_to_version_key[$env_var]="postgres";; + redis-version) env_to_version_key[$env_var]="redis";; + prometheus-version) env_to_version_key[$env_var]="prometheus";; + grafana-version) env_to_version_key[$env_var]="grafana";; + keycloak-version) env_to_version_key[$env_var]="keycloak";; + consul-version) env_to_version_key[$env_var]="consul";; + zookeeper-version) env_to_version_key[$env_var]="zookeeper";; + kafka-version) env_to_version_key[$env_var]="kafka";; + spring-profiles-default) env_to_version_key[$env_var]="spring-profiles-default";; + spring-profiles-docker) env_to_version_key[$env_var]="spring-profiles-docker";; + app-version) env_to_version_key[$env_var]="app-version";; + esac + done <<< "$env_mappings" + + # Find occurrences with explicit default fallbacks + local fallback_lines=$(grep -nE '\${DOCKER_[A-Z0-9_]+:-[^}]+' "$compose_file" || true) + if [[ -n "$fallback_lines" ]]; then + while IFS= read -r ln; do + [[ -z "$ln" ]] && continue + local num=$(echo "$ln" | cut -d: -f1) + local text=$(echo "$ln" | cut -d: -f2-) + # Extract var name and fallback + local var=$(echo "$text" | sed -n 's/.*${\([A-Z0-9_]\+\):-\([^}][^}]*\)}.*/\1/p') + local fallback=$(echo "$text" | sed -n 's/.*${\([A-Z0-9_]\+\):-\([^}][^}]*\)}.*/\2/p') + if [[ -z "$var" || -z "$fallback" ]]; then + continue + fi + local key=${env_to_version_key[$var]} + if [[ -z "$key" ]]; then + # Not a centralized version/profile var, ignore + continue + fi + local expected=$(get_version "$key") + if [[ -z "$expected" ]]; then + print_warning " ⚠ No SSoT value for $var (key: $key) to compare fallback against" + continue + fi + if [[ "$fallback" != "$expected" ]]; then + print_error " ❌ Outdated default fallback for $var in ${relative_path}:${num} — found '$fallback', expected '$expected' from versions.toml ($key)" + else + print_success " ✓ Fallback for $var matches SSoT ($expected)" + fi + done <<< "$fallback_lines" + fi + # Check for version references in compose file local version_refs=$(grep -o '\${DOCKER_[^}]*}' "$compose_file" | sort -u || true) if [[ -z "$version_refs" ]]; then print_warning " ⚠ No centralized version references found" - return - fi + # do not return; still check for hardcoded images + else + # Validate each version reference + while IFS= read -r ref; do + [[ -z "$ref" ]] && continue - # Validate each version reference - while IFS= read -r ref; do - [[ -z "$ref" ]] && continue + local var_name=${ref#\$\{} + var_name=${var_name%\}} + # Strip any default fallback (:-value) from the variable name + var_name=${var_name%%:-*} - local var_name=${ref#\$\{} - var_name=${var_name%\}} - - # Check if mapping exists in TOML - local mapping_found=false - while IFS=':' read -r toml_key env_var; do - if [[ "$env_var" == "$var_name" ]]; then - mapping_found=true - local toml_version=$(get_version "$toml_key") - if [[ -n "$toml_version" ]]; then - print_success " ✓ Version reference $ref maps to $toml_key = $toml_version" - else - print_error " ❌ TOML key $toml_key has no value" + # Check if mapping exists in TOML + local mapping_found=false + while IFS=':' read -r toml_key env_var; do + if [[ "$env_var" == "$var_name" ]]; then + mapping_found=true + local toml_version=$(get_version "$toml_key") + if [[ -n "$toml_version" ]]; then + print_success " ✓ Version reference $ref maps to $toml_key = $toml_version" + else + print_error " ❌ TOML key $toml_key has no value" + fi + break fi - break - fi - done <<< "$env_mappings" + done <<< "$env_mappings" - if [[ "$mapping_found" == false ]]; then - print_warning " ⚠ Version reference $ref has no mapping in environment-mapping section" - fi - done <<< "$version_refs" + if [[ "$mapping_found" == false ]]; then + print_warning " ⚠ Version reference $ref has no mapping in environment-mapping section" + fi + done <<< "$version_refs" + fi # Check for hardcoded image versions local hardcoded_images=$(grep -E "image:.*:[0-9]" "$compose_file" | grep -v "\${" || true) @@ -283,6 +396,13 @@ validate_port_consistency() { # Function to validate build args environment files validate_build_args_files() { + # Skip when running env-less mode + if [[ "${DOCKER_SSOT_MODE:-compat}" == "envless" ]]; then + print_info "Env-less mode active → skipping build-args/*.env validation" + print_success " ✓ Skipped: build-args env files not required in env-less mode" + return + fi + print_info "Validating build-args environment files..." local build_args_files=("global.env" "services.env" "infrastructure.env" "clients.env") @@ -300,12 +420,55 @@ validate_build_args_files() { print_warning " ⚠ Build args file is empty: $env_file" fi - # Check for DOCKER_ environment variables - local docker_vars=$(grep "^DOCKER_" "$full_path" | wc -l || echo "0") - if [[ "$docker_vars" -gt 0 ]]; then - print_success " ✓ Found $docker_vars centralized version variables in $env_file" + # 1) Ensure only valid lines: comments, blanks, or key=value + local invalid_lines=$(grep -n -vE '^(#|\s*$|[A-Za-z_][A-Za-z0-9_]*=)' "$full_path" || true) + if [[ -n "$invalid_lines" ]]; then + print_error " ❌ Invalid lines (must be key=value or comment):" + echo "$invalid_lines" | while read -r line; do + print_error " $env_file:$line" + done else - print_warning " ⚠ No DOCKER_ version variables found in $env_file" + print_success " ✓ Format OK (only key=value/comments) in $env_file" + fi + + # 2) No bare placeholder like `DOCKER_XYZ` without value + local bare_docker=$(grep -nE '^DOCKER_[A-Z0-9_]+$' "$full_path" || true) + if [[ -n "$bare_docker" ]]; then + print_error " ❌ Bare DOCKER_* placeholders without values found:" + echo "$bare_docker" | while read -r line; do + print_error " $env_file:$line" + done + else + print_success " ✓ No bare DOCKER_* placeholders in $env_file" + fi + + # 3) Policy: Only global.env may contain DOCKER_* keys + local docker_keys_count=$(grep -E '^DOCKER_[A-Z0-9_]+' "$full_path" | wc -l || echo "0") + if [[ "$env_file" == "global.env" ]]; then + if [[ "$docker_keys_count" -gt 0 ]]; then + print_success " ✓ DOCKER_* variables present only in global.env ($docker_keys_count found)" + else + print_warning " ⚠ Expected some DOCKER_* variables in global.env (prometheus/grafana/keycloak, etc.)" + fi + # Required keys in global.env + for key in GRADLE_VERSION JAVA_VERSION VERSION; do + if grep -q "^$key=" "$full_path"; then + print_success " ✓ $key present in global.env" + else + print_error " ❌ Missing $key in global.env" + fi + done + else + if [[ "$docker_keys_count" -gt 0 ]]; then + print_error " ❌ DOCKER_* variables must not be present in $env_file (keep them centralized in global.env)" + else + print_success " ✓ No centralized DOCKER_* vars in $env_file (as expected)" + fi + fi + + # 4) Ban DOCKER_APP_VERSION in any build-args env (it is mapped from VERSION at runtime) + if grep -q '^DOCKER_APP_VERSION=' "$full_path"; then + print_error " ❌ DOCKER_APP_VERSION should not be defined in build-args files (mapped from VERSION in docker-build.sh)" fi else print_error " ❌ Build args file missing: $env_file" @@ -313,6 +476,197 @@ validate_build_args_files() { done } +# Additional drift-detection helpers + +# Get a port value from [service-ports] in versions.toml +get_toml_port() { + local service_key=$1 + awk -v key="$service_key" ' + /^\[service-ports\]/ { in_section=1; next } + /^\[/ { if (in_section) exit; in_section=0 } + in_section && $1 == key { print $3; exit } + ' "$VERSIONS_TOML" || echo "" +} + +# Validate equality between versions.toml and build-args env files (key-to-key) +validate_env_value_equality() { + # Skip when running env-less mode (no build-args/*.env are authoritative) + if [[ "${DOCKER_SSOT_MODE:-compat}" == "envless" ]]; then + print_info "Env-less mode active → skipping TOML↔env value equality check" + print_success " ✓ Skipped: values derive directly from versions.toml at runtime" + return + fi + + print_info "Validating value equality between versions.toml and build-args envs..." + + local has_diff=false + + # Internal helper for comparing a TOML key to an env key within a given file + _check_env_pair() { + local env_file=$1 + local env_key=$2 + local toml_key=$3 + local expected + local actual + local path="$DOCKER_DIR/build-args/$env_file" + + if [[ ! -f "$path" ]]; then + print_error " ❌ Missing env file: $env_file" + has_diff=true + return + fi + + # Expected from TOML + expected=$(get_version "$toml_key") + # Fallback: try service-ports lookup for any matching key if not found in [versions] + if [[ -z "$expected" ]]; then + local port_lookup=$(get_toml_port "$toml_key") + if [[ -n "$port_lookup" ]]; then + expected="$port_lookup" + fi + fi + + # Actual from env file + actual=$(grep -E "^${env_key}=" "$path" | head -1 | sed 's/^[^=]*=//') + + if [[ -z "$expected" ]]; then + print_warning " ⚠ TOML key '$toml_key' returned no value (check versions.toml)" + return + fi + if [[ -z "$actual" ]]; then + print_error " ❌ $env_file missing $env_key (expected $expected)" + has_diff=true + return + fi + if [[ "$expected" != "$actual" ]]; then + print_error " ❌ Mismatch in $env_file: $env_key='$actual' != $toml_key='$expected'" + has_diff=true + else + print_success " ✓ $env_file: $env_key matches $toml_key ($expected)" + fi + } + + # global.env mappings + _check_env_pair "global.env" "GRADLE_VERSION" "gradle" + _check_env_pair "global.env" "JAVA_VERSION" "java" + _check_env_pair "global.env" "VERSION" "app-version" + _check_env_pair "global.env" "DOCKER_PROMETHEUS_VERSION" "prometheus" + _check_env_pair "global.env" "DOCKER_GRAFANA_VERSION" "grafana" + _check_env_pair "global.env" "DOCKER_KEYCLOAK_VERSION" "keycloak" + + # clients.env mappings + _check_env_pair "clients.env" "NODE_VERSION" "node" + _check_env_pair "clients.env" "NGINX_VERSION" "nginx" + _check_env_pair "clients.env" "APP_VERSION" "app-version" + # Ports for clients (map to [service-ports]) + _check_env_pair "clients.env" "WEB_APP_PORT" "web-app" + _check_env_pair "clients.env" "DESKTOP_APP_VNC_PORT" "desktop-app-vnc" + _check_env_pair "clients.env" "DESKTOP_APP_NOVNC_PORT" "desktop-app-novnc" + + # services.env mappings + _check_env_pair "services.env" "SPRING_PROFILES_ACTIVE" "spring-profiles-docker" + _check_env_pair "services.env" "PING_SERVICE_PORT" "ping-service" + _check_env_pair "services.env" "MEMBERS_SERVICE_PORT" "members-service" + _check_env_pair "services.env" "HORSES_SERVICE_PORT" "horses-service" + _check_env_pair "services.env" "EVENTS_SERVICE_PORT" "events-service" + _check_env_pair "services.env" "MASTERDATA_SERVICE_PORT" "masterdata-service" + + # infrastructure.env mappings + _check_env_pair "infrastructure.env" "SPRING_PROFILES_ACTIVE" "spring-profiles-default" + _check_env_pair "infrastructure.env" "GATEWAY_PORT" "api-gateway" + _check_env_pair "infrastructure.env" "AUTH_SERVER_PORT" "auth-server" + _check_env_pair "infrastructure.env" "MONITORING_SERVER_PORT" "monitoring-server" + + if [[ "$has_diff" == false ]]; then + print_success "Environment files are fully synchronized with versions.toml" + fi +} + +# Scan for free-floating version strings outside controlled files +scan_free_floating_versions() { + print_info "Scanning for free-floating version literals outside SSoT-managed files..." + + # Collect version values from [versions] + local version_values + version_values=$(awk ' + /^\[versions\]/ { in_section=1; next } + /^\[/ { if (in_section) exit; in_section=0 } + in_section && $2 == "=" { v=$3; gsub(/"/,"",v); if (v ~ /[\.-]/) print v } + ' "$VERSIONS_TOML" ) + + local found_any=false + while IFS= read -r val; do + [[ -z "$val" ]] && continue + # search occurrences excluding controlled locations + local hits + # Use find to avoid non-portable grep --exclude flags (BusyBox compatibility) + hits=$( + find "$PROJECT_ROOT" -type f \ + -not -path "*/.git/*" \ + -not -path "*/build/*" \ + -not -path "*/.gradle/*" \ + -not -path "*/node_modules/*" \ + -not -path "*/dist/*" \ + -not -path "*/out/*" \ + -not -path "*/target/*" \ + -not -path "$PROJECT_ROOT/README.md" \ + -not -path "$PROJECT_ROOT/docker/versions.toml" \ + -not -path "$PROJECT_ROOT/docker/build-args/global.env" \ + -not -path "$PROJECT_ROOT/docker/build-args/services.env" \ + -not -path "$PROJECT_ROOT/docker/build-args/clients.env" \ + -not -path "$PROJECT_ROOT/docker/build-args/infrastructure.env" \ + -not -name "docker-compose*.yml" \ + -not -name "docker-compose*.yml.optimized" \ + -not -path "$PROJECT_ROOT/scripts/generate-compose-files.sh" \ + -not -path "$PROJECT_ROOT/scripts/docker-versions-update.sh" \ + -print0 \ + | while IFS= read -r -d '' f; do + grep -nF -- "$val" "$f" || true + done + ) + if [[ -n "$hits" ]]; then + found_any=true + print_warning " ⚠ Detected occurrences of version literal '$val' outside controlled files:" + echo "$hits" | sed 's/^/ /' + fi + done <<< "$version_values" + + # Generic pattern scan for suspicious literals (best-effort; warnings only) + local generic + # Portable generic scan using find + grep (avoid non-POSIX grep options) + generic=$(\ + find "$PROJECT_ROOT" -type f \ + -not -path "*/.git/*" \ + -not -path "*/build/*" \ + -not -path "*/.gradle/*" \ + -not -path "*/node_modules/*" \ + -not -path "*/dist/*" \ + -not -path "*/out/*" \ + -not -path "*/target/*" \ + -not -path "$PROJECT_ROOT/docker/versions.toml" \ + -not -name "docker-compose*.yml" \ + -not -name "docker-compose*.yml.optimized" \ + -not -path "$PROJECT_ROOT/docker/build-args/global.env" \ + -not -path "$PROJECT_ROOT/docker/build-args/services.env" \ + -not -path "$PROJECT_ROOT/docker/build-args/clients.env" \ + -not -path "$PROJECT_ROOT/docker/build-args/infrastructure.env" \ + -not -path "$PROJECT_ROOT/scripts/generate-compose-files.sh" \ + -not -path "$PROJECT_ROOT/scripts/docker-versions-update.sh" \ + -not -path "$PROJECT_ROOT/README.md" \ + -print0 \ + | xargs -0 -r grep -nE -- '(^|[^0-9])([0-9]+\.[0-9]+\.[0-9]+([a-zA-Z0-9._-]+)?)' 2>/dev/null \ + | head -n 200 || true) + if [[ -n "$generic" ]]; then + found_any=true + print_warning " ⚠ Generic version-like strings found (review for potential drift):" + echo "$generic" | sed 's/^/ /' + fi + + if [[ "$found_any" == false ]]; then + print_success " ✓ No free-floating version literals detected" + fi +} + # Function to show validation summary show_summary() { echo "" @@ -380,8 +734,8 @@ main() { echo "" done - # Validate docker-compose files - for compose_file in docker-compose*.yml; do + # Validate docker-compose files (including optimized variants) + for compose_file in docker-compose*.yml docker-compose*.yml.optimized; do if [[ -f "$PROJECT_ROOT/$compose_file" ]]; then validate_compose_versions "$PROJECT_ROOT/$compose_file" echo "" @@ -394,6 +748,14 @@ main() { # Validate build args files validate_build_args_files + echo "" + + # Validate value equality between versions.toml and build-args envs + validate_env_value_equality + echo "" + + # Scan repository for free-floating version literals + scan_free_floating_versions ;; "dockerfiles") find "$DOCKERFILES_DIR" -name "Dockerfile" -type f | while read -r dockerfile; do @@ -402,7 +764,7 @@ main() { done ;; "compose") - for compose_file in docker-compose*.yml; do + for compose_file in docker-compose*.yml docker-compose*.yml.optimized; do if [[ -f "$PROJECT_ROOT/$compose_file" ]]; then validate_compose_versions "$PROJECT_ROOT/$compose_file" echo "" diff --git a/services/events/README-EVENTS.md b/services/events/README-EVENTS.md index ed4a27ac..019c9bf7 100644 --- a/services/events/README-EVENTS.md +++ b/services/events/README-EVENTS.md @@ -9,6 +9,7 @@ Das Events-Modul ist eine umfassende Lösung zur Verwaltung von Pferdesportveran ### Verwaltete Entität #### Veranstaltung (Event) + - **Grundinformationen**: Name, Beschreibung - **Terminverwaltung**: Startdatum, Enddatum, Anmeldeschluss - **Ort und Organisation**: Veranstaltungsort, Veranstalter-Verein-ID @@ -21,21 +22,25 @@ Das Events-Modul ist eine umfassende Lösung zur Verwaltung von Pferdesportveran Das Modul bietet 10+ spezialisierte Repository-Operationen: #### Basis-CRUD-Operationen + - `findById(id)` - Veranstaltung nach UUID suchen - `save(veranstaltung)` - Veranstaltung speichern (erstellen/aktualisieren) - `delete(id)` - Veranstaltung löschen #### Such-Operationen + - `findByName(searchTerm, limit)` - Nach Namen suchen (Teilübereinstimmung) - `findByVeranstalterVereinId(vereinId, activeOnly)` - Veranstaltungen eines Vereins - `findAllActive(limit, offset)` - Alle aktiven Veranstaltungen - `findPublicEvents(activeOnly)` - Öffentliche Veranstaltungen #### Datumsbasierte Abfragen + - `findByDateRange(startDate, endDate, activeOnly)` - Veranstaltungen in Datumsbereich - `findByStartDate(date, activeOnly)` - Veranstaltungen nach Startdatum #### Zähl-Operationen + - `countActive()` - Anzahl aktiver Veranstaltungen - `countByVeranstalterVereinId(vereinId, activeOnly)` - Anzahl Veranstaltungen pro Verein @@ -69,27 +74,32 @@ events/ ``` ### Domain Layer + - **1 Domain Model** mit reichhaltiger Geschäftslogik - **1 Repository Interface** mit 10+ Geschäftsoperationen - **Domain Service** für komplexe Veranstaltungslogik - **Keine Abhängigkeiten** zu anderen Layern ### Application Layer + - **Use Cases** für CRUD-Operationen - **Orchestrierung** von Domain-Services - **Anwendungslogik** ohne UI-Abhängigkeiten ### Infrastructure Layer + - **Datenbankzugriff** mit Exposed ORM - **Repository-Implementierung** mit PostgreSQL - **Datenbankschema** und Migrationen ### API Layer + - **REST-Controller** für HTTP-Endpunkte - **DTO-Mapping** zwischen Domain und API - **Validierung** und Fehlerbehandlung ### Service Layer + - **Spring Boot Anwendung** - **Dependency Injection** Konfiguration - **Service-Konfiguration** @@ -138,6 +148,7 @@ data class Veranstaltung( ### Enumerationen #### SparteE (Sportsparten) + - `DRESSUR` - Dressurreiten - `SPRINGEN` - Springreiten - `VIELSEITIGKEIT` - Vielseitigkeitsreiten @@ -257,6 +268,7 @@ Das Events-Modul stellt REST-Endpunkte über den VeranstaltungController bereit: ### Datenbankschema Das Modul verwendet eine `events`-Tabelle mit folgenden Spalten: + - `veranstaltung_id` (UUID, Primary Key) - `name` (Required) - `beschreibung` (Text, Optional) @@ -416,11 +428,13 @@ spec: ### Externe Systeme #### OEPS-Integration + - Synchronisation mit OEPS-Veranstaltungskalender - Automatische Meldung bei OEPS-relevanten Veranstaltungen - Import von OEPS-Veranstaltungsdaten #### FEI-Integration + - Unterstützung für internationale Veranstaltungen - FEI-Regularien und -Standards - Automatische Klassifizierung @@ -428,11 +442,13 @@ spec: ### Interne Module #### Members-Modul + - Teilnehmerverwaltung - Anmeldestatus-Tracking - Mitgliedschaftsvalidierung #### Horses-Modul + - Pferdeanmeldungen - Eignung für Sparten - Registrierungsstatus diff --git a/services/horses/README-HORSES.md b/services/horses/README-HORSES.md index 897e1eea..0f4605ba 100644 --- a/services/horses/README-HORSES.md +++ b/services/horses/README-HORSES.md @@ -9,6 +9,7 @@ Das Horses-Modul ist eine umfassende Lösung zur Verwaltung von Pferden für Pfe ### Verwaltete Entität #### Pferd (DomPferd) + - **Grundinformationen**: Name, Geschlecht, Geburtsdatum, Rasse, Farbe - **Besitz und Verantwortung**: Besitzer-ID, verantwortliche Person - **Zuchtinformationen**: Züchtername, Zuchtbuchnummer @@ -23,11 +24,13 @@ Das Horses-Modul ist eine umfassende Lösung zur Verwaltung von Pferden für Pfe Das Modul bietet 25+ spezialisierte Repository-Operationen: #### Basis-CRUD-Operationen + - `findById(id)` - Pferd nach UUID suchen - `save(horse)` - Pferd speichern (erstellen/aktualisieren) - `delete(id)` - Pferd löschen #### Such-Operationen nach Identifikationsnummern + - `findByLebensnummer(lebensnummer)` - Nach Lebensnummer suchen - `findByChipNummer(chipNummer)` - Nach Chipnummer suchen - `findByPassNummer(passNummer)` - Nach Passnummer suchen @@ -35,6 +38,7 @@ Das Modul bietet 25+ spezialisierte Repository-Operationen: - `findByFeiNummer(feiNummer)` - Nach FEI-Nummer suchen #### Such-Operationen nach Eigenschaften + - `findByName(searchTerm, limit)` - Nach Namen suchen (Teilübereinstimmung) - `findByOwnerId(ownerId, activeOnly)` - Pferde eines Besitzers - `findByResponsiblePersonId(personId, activeOnly)` - Pferde einer verantwortlichen Person @@ -42,15 +46,18 @@ Das Modul bietet 25+ spezialisierte Repository-Operationen: - `findByRasse(rasse, activeOnly, limit)` - Nach Rasse filtern #### Datumsbasierte Abfragen + - `findByBirthYear(birthYear, activeOnly)` - Pferde nach Geburtsjahr - `findByBirthYearRange(fromYear, toYear, activeOnly)` - Pferde nach Geburtsjahr-Bereich #### Registrierungs-Abfragen + - `findAllActive(limit)` - Alle aktiven Pferde - `findOepsRegistered(activeOnly)` - OEPS-registrierte Pferde - `findFeiRegistered(activeOnly)` - FEI-registrierte Pferde #### Validierungs-Operationen + - `existsByLebensnummer(lebensnummer)` - Prüfung auf doppelte Lebensnummer - `existsByChipNummer(chipNummer)` - Prüfung auf doppelte Chipnummer - `existsByPassNummer(passNummer)` - Prüfung auf doppelte Passnummer @@ -58,6 +65,7 @@ Das Modul bietet 25+ spezialisierte Repository-Operationen: - `existsByFeiNummer(feiNummer)` - Prüfung auf doppelte FEI-Nummer #### Zähl-Operationen + - `countActive()` - Anzahl aktiver Pferde - `countByOwnerId(ownerId, activeOnly)` - Anzahl Pferde pro Besitzer - `countOepsRegistered(activeOnly)` - Anzahl OEPS-registrierter Pferde ✨ **NEU** @@ -94,22 +102,26 @@ horses/ ``` ### Domain Layer + - **1 Domain Model** mit reichhaltiger Geschäftslogik - **1 Repository Interface** mit 25+ Geschäftsoperationen - **Geschäftsregeln** für Pferderegistrierung und -validierung - **Keine Abhängigkeiten** zu anderen Layern ### Application Layer + - **Use Cases** für CRUD-Operationen - **Orchestrierung** von Domain-Services - **Anwendungslogik** ohne UI-Abhängigkeiten ### Infrastructure Layer + - **Datenbankzugriff** mit Exposed ORM - **Repository-Implementierung** mit PostgreSQL - **Datenbankschema** und Migrationen ### API Layer + - **REST-Controller** für HTTP-Endpunkte ## 🚀 Aktuelle Optimierungen (2025-07-25) @@ -119,12 +131,15 @@ Das Horses-Modul wurde kürzlich analysiert, vervollständigt und optimiert. Fol ### ✨ Neue Funktionalitäten #### Erweiterte Such-Endpunkte + Neue REST-Endpunkte für vollständige Identifikationsnummer-Suche: + - `GET /api/horses/search/passport/{nummer}` - Suche nach Passnummer - `GET /api/horses/search/oeps/{nummer}` - Suche nach OEPS-Nummer - `GET /api/horses/search/fei/{nummer}` - Suche nach FEI-Nummer #### Optimierte Statistik-Operationen + - Neue effiziente Zähl-Methoden für OEPS und FEI registrierte Pferde - Performance-Verbesserung von O(n) auf O(1) Komplexität für Statistiken - Datenbankoptimierte COUNT-Abfragen statt Laden aller Datensätze @@ -132,11 +147,13 @@ Neue REST-Endpunkte für vollständige Identifikationsnummer-Suche: ### ⚡ Performance-Optimierungen #### Datenbankeffizienz + - **Vorher**: Statistik-Endpunkt lud alle Pferde und verwendete `.size` - **Nachher**: Effiziente COUNT-Abfragen direkt in der Datenbank - **Auswirkung**: Drastische Reduzierung der Speichernutzung und Antwortzeiten #### Architektur-Konsistenz + - Alle API-Endpunkte verwenden jetzt konsistent die Use-Case-Schicht - Eliminierung direkter Repository-Aufrufe in der API-Schicht - Saubere Trennung der Architektur-Schichten @@ -144,12 +161,14 @@ Neue REST-Endpunkte für vollständige Identifikationsnummer-Suche: ### 🏗️ Architektur-Verbesserungen #### Clean Architecture Compliance + - **Konsistente Schichtung**: Alle Endpunkte folgen dem Use-Case-Pattern - **Fehlerbehandlung**: Einheitliche Fehlerantworten über alle Endpunkte - **Validierung**: Umfassende Eingabevalidierung mit geteilten Utilities - **HTTP-Standards**: Korrekte Status-Codes und REST-Konventionen #### Code-Qualität + - Verbesserte Lesbarkeit und Wartbarkeit - Konsistente Namenskonventionen - Umfassende Dokumentation aller neuen Funktionen @@ -157,12 +176,14 @@ Neue REST-Endpunkte für vollständige Identifikationsnummer-Suche: ### 📊 Qualitätsmetriken #### Vor der Optimierung + - ❌ Fehlende Such-Endpunkte für 3 Identifikationstypen - ❌ Ineffiziente Statistik-Abfragen (O(n) Komplexität) - ❌ Inkonsistente Architektur (einige Endpunkte umgingen Use Cases) - ❌ Performance-Probleme bei großen Datensätzen #### Nach der Optimierung + - ✅ Vollständige API-Abdeckung für alle Identifikationstypen - ✅ Effiziente Statistik-Abfragen (O(1) Komplexität) - ✅ Konsistente Clean Architecture durchgehend @@ -171,16 +192,19 @@ Neue REST-Endpunkte für vollständige Identifikationsnummer-Suche: ### 🔮 Zukünftige Empfehlungen #### Caching-Schicht + - Implementierung einer Caching-Schicht für häufig abgerufene Daten - Individuelle Pferde-Lookups mit angemessener TTL - Statistiken und Zählungen mit Cache-Invalidierung #### Async-Operationen + - Asynchrone Verarbeitung für Batch-Operationen - Komplexe Such-Abfragen mit Async-Pattern - Statistik-Berechnungen im Hintergrund #### Monitoring und Logging + - Umfassendes Monitoring für API-Antwortzeiten - Datenbank-Query-Performance-Überwachung - Fehlerrate-Tracking und -Analyse @@ -188,6 +212,7 @@ Neue REST-Endpunkte für vollständige Identifikationsnummer-Suche: - **Validierung** und Fehlerbehandlung ### Service Layer + - **Spring Boot Anwendung** - **Dependency Injection** Konfiguration - **Integrationstests** @@ -254,11 +279,13 @@ data class DomPferd( ### Enumerationen #### PferdeGeschlechtE + - `HENGST` - Hengst (männlich, nicht kastriert) - `STUTE` - Stute (weiblich) - `WALLACH` - Wallach (männlich, kastriert) #### DatenQuelleE + - `MANUELL` - Manuelle Eingabe - `IMPORT` - Datenimport - `SYNCHRONISATION` - Synchronisation mit externen Systemen @@ -366,6 +393,7 @@ Das Horses-Modul stellt REST-Endpunkte über den HorseController bereit: ### Datenbankschema Das Modul verwendet eine `horses`-Tabelle mit folgenden Spalten: + - `pferd_id` (UUID, Primary Key) - `pferde_name` (Required) - `geschlecht` (Enum: HENGST, STUTE, WALLACH) diff --git a/services/masterdata/README-MASTERDATA.md b/services/masterdata/README-MASTERDATA.md index 15a30323..f83e2f77 100644 --- a/services/masterdata/README-MASTERDATA.md +++ b/services/masterdata/README-MASTERDATA.md @@ -9,18 +9,21 @@ Das Masterdata-Modul ist eine umfassende Lösung zur Verwaltung von Stammdaten f ### Verwaltete Entitäten #### 1. Länder (LandDefinition) + - **ISO-Codes**: Alpha-2, Alpha-3 und numerische Codes nach ISO 3166-1 - **EU/EWR-Mitgliedschaft**: Tracking der Mitgliedschaft in EU und Europäischem Wirtschaftsraum - **Mehrsprachigkeit**: Deutsche und englische Ländernamen - **Validierung**: Duplikatsprüfung und ISO-Code-Validierung #### 2. Bundesländer (BundeslandDefinition) + - **OEPS-Codes**: Spezielle Codes für österreichische Bundesländer - **ISO 3166-2 Codes**: Internationale Standardcodes für subnationale Einheiten - **Länder-Zuordnung**: Verknüpfung mit übergeordneten Ländern - **Flexible Struktur**: Unterstützt Bundesländer, Kantone, Regionen #### 3. Altersklassen (AltersklasseDefinition) + - **Berechtigung**: Komplexe Regeln für Teilnahmeberechtigung - **Sparten-Filter**: Disziplinspezifische Altersklassen (Dressur, Springen, etc.) - **Geschlechts-Filter**: Geschlechtsspezifische Kategorien @@ -28,6 +31,7 @@ Das Masterdata-Modul ist eine umfassende Lösung zur Verwaltung von Stammdaten f - **OETO-Integration**: Verknüpfung mit österreichischen Turnierordnungsregeln #### 4. Turnierplätze (Platz) + - **Platztypen**: Dressurplatz, Springplatz, Geländestrecke, etc. - **Abmessungen**: Standardisierte Platzgrößen (20x60m, 20x40m, etc.) - **Bodenarten**: Sand, Gras, Kunststoff, etc. @@ -55,21 +59,25 @@ masterdata/ ``` ### Domain Layer + - **4 Domain Models** mit reichhaltiger Geschäftslogik - **4 Repository Interfaces** mit 60+ Geschäftsoperationen - **Keine Abhängigkeiten** zu anderen Layern ### Application Layer + - **8 Use Cases** mit umfassender Funktionalität - **Validierung**: Eingabevalidierung mit spezifischen Fehlercodes - **Geschäftslogik**: Duplikatsprüfung, Berechtigungsvalidierung ### Infrastructure Layer + - **4 Database Tables** mit Indizes und Constraints - **Repository Implementierungen** mit vollständigen CRUD-Operationen - **Migration Scripts** mit Beispieldaten ### API Layer + - **4 REST Controllers** mit 37 Endpunkten - **DTO Pattern** für saubere API-Verträge - **Fehlerbehandlung** mit strukturierten Antworten @@ -77,6 +85,7 @@ masterdata/ ## API Endpunkte ### Countries (Länder) + ``` GET /api/masterdata/countries # Alle aktiven Länder GET /api/masterdata/countries/{id} # Land nach ID @@ -91,6 +100,7 @@ DELETE /api/masterdata/countries/{id} # Land löschen ``` ### Federal States (Bundesländer) + ``` GET /api/masterdata/bundeslaender # Alle aktiven Bundesländer GET /api/masterdata/bundeslaender/{id} # Bundesland nach ID @@ -105,6 +115,7 @@ DELETE /api/masterdata/bundeslaender/{id} # Bundesland löschen ``` ### Age Classes (Altersklassen) + ``` GET /api/masterdata/altersklassen # Alle aktiven Altersklassen GET /api/masterdata/altersklassen/{id} # Altersklasse nach ID @@ -119,6 +130,7 @@ DELETE /api/masterdata/altersklassen/{id} # Altersklasse löschen ``` ### Venues (Turnierplätze) + ``` GET /api/masterdata/plaetze/{id} # Platz nach ID GET /api/masterdata/plaetze/tournament/{turnierId} # Plätze nach Turnier @@ -139,6 +151,7 @@ DELETE /api/masterdata/plaetze/{id} # Platz löschen ## Datenbank Schema ### Land Tabelle + ```sql CREATE TABLE land ( id UUID PRIMARY KEY, @@ -158,6 +171,7 @@ CREATE TABLE land ( ``` ### Bundesland Tabelle + ```sql CREATE TABLE bundesland ( id UUID PRIMARY KEY, @@ -175,6 +189,7 @@ CREATE TABLE bundesland ( ``` ### Altersklasse Tabelle + ```sql CREATE TABLE altersklasse ( id UUID PRIMARY KEY, @@ -193,6 +208,7 @@ CREATE TABLE altersklasse ( ``` ### Platz Tabelle + ```sql CREATE TABLE platz ( id UUID PRIMARY KEY, @@ -211,6 +227,7 @@ CREATE TABLE platz ( ## Verwendung ### Service starten + ```bash # Masterdata Service starten ./gradlew :masterdata:masterdata-service:bootRun @@ -222,6 +239,7 @@ CREATE TABLE platz ( ### API Beispiele #### Land erstellen + ```bash curl -X POST http://localhost:8080/api/masterdata/countries \ -H "Content-Type: application/json" \ @@ -237,11 +255,13 @@ curl -X POST http://localhost:8080/api/masterdata/countries \ ``` #### Altersklassen für 16-jährigen Dressurreiter abrufen + ```bash curl "http://localhost:8080/api/masterdata/altersklassen/age/16?sparte=DRESSUR" ``` #### Geeignete Dressurplätze finden + ```bash curl "http://localhost:8080/api/masterdata/plaetze/suitable?typ=DRESSURPLATZ&dimension=20x60m" ``` @@ -249,6 +269,7 @@ curl "http://localhost:8080/api/masterdata/plaetze/suitable?typ=DRESSURPLATZ&dim ## Konfiguration ### Umgebungsvariablen + ```bash # Database MASTERDATA_DB_URL=jdbc:postgresql://localhost:5432/meldestelle @@ -264,6 +285,7 @@ MASTERDATA_VALIDATION_STRICT=true ``` ### Application Properties + ```yaml masterdata: validation: @@ -280,16 +302,19 @@ masterdata: ## Tests ### Unit Tests ausführen + ```bash ./gradlew :masterdata:test ``` ### Integration Tests ausführen + ```bash ./gradlew :masterdata:integrationTest ``` ### Spezifische Tests + ```bash # Repository Tests ./gradlew :masterdata:masterdata-infrastructure:test diff --git a/services/members/README-MEMBERS.md b/services/members/README-MEMBERS.md index 9cff1622..6eb58b1d 100644 --- a/services/members/README-MEMBERS.md +++ b/services/members/README-MEMBERS.md @@ -9,6 +9,7 @@ Das Members-Modul ist eine umfassende Lösung zur Verwaltung von Mitgliedern fü ### Verwaltete Entität #### Mitglied (Member) + - **Persönliche Informationen**: Vor- und Nachname, E-Mail, Telefon, Geburtsdatum - **Mitgliedschaftsinformationen**: Mitgliedsnummer, Start-/Enddatum, Aktivitätsstatus - **Zusätzliche Informationen**: Adresse, Notfallkontakt @@ -20,11 +21,13 @@ Das Members-Modul ist eine umfassende Lösung zur Verwaltung von Mitgliedern fü Das Modul bietet 18+ spezialisierte Repository-Operationen: #### Basis-CRUD-Operationen + - `findById(id)` - Mitglied nach UUID suchen - `save(member)` - Mitglied speichern (erstellen/aktualisieren) - `delete(id)` - Mitglied löschen #### Such-Operationen + - `findByMembershipNumber(number)` - Nach Mitgliedsnummer suchen - `findByEmail(email)` - Nach E-Mail-Adresse suchen - `findByName(searchTerm, limit)` - Nach Namen suchen (Teilübereinstimmung) @@ -32,15 +35,18 @@ Das Modul bietet 18+ spezialisierte Repository-Operationen: - `findAll(limit, offset)` - Alle Mitglieder (aktiv und inaktiv) #### Datumsbasierte Abfragen + - `findByMembershipStartDateRange(start, end)` - Mitglieder nach Startdatum-Bereich - `findByMembershipEndDateRange(start, end)` - Mitglieder nach Enddatum-Bereich - `findMembersWithExpiringMembership(daysAhead)` - Mitglieder mit ablaufender Mitgliedschaft #### Validierungs-Operationen + - `existsByMembershipNumber(number, excludeId)` - Prüfung auf doppelte Mitgliedsnummer - `existsByEmail(email, excludeId)` - Prüfung auf doppelte E-Mail-Adresse #### Zähl-Operationen + - `countActive()` - Anzahl aktiver Mitglieder - `countAll()` - Gesamtanzahl aller Mitglieder @@ -76,28 +82,33 @@ members/ ``` ### Domain Layer + - **1 Domain Model** mit reichhaltiger Geschäftslogik - **1 Repository Interface** mit 18+ Geschäftsoperationen - **Domain Events** für Mitgliedschaftsänderungen - **Keine Abhängigkeiten** zu anderen Layern ### Application Layer + - **Use Cases** für komplexe Geschäftsoperationen - **Orchestrierung** von Domain-Services - **Anwendungslogik** ohne UI-Abhängigkeiten ### Infrastructure Layer + - **Datenbankzugriff** mit Exposed ORM - **Repository-Implementierung** mit PostgreSQL - **In-Memory-Repository** für Tests - **Datenbankschema** und Migrationen ### API Layer + - **REST-Controller** für HTTP-Endpunkte - **DTO-Mapping** zwischen Domain und API - **Validierung** und Fehlerbehandlung ### Service Layer + - **Spring Boot Anwendung** - **Dependency Injection** Konfiguration - **Integrationstests** @@ -204,6 +215,7 @@ Das Members-Modul stellt REST-Endpunkte über den MemberController bereit: ### Datenbankschema Das Modul verwendet eine `members`-Tabelle mit folgenden Spalten: + - `member_id` (UUID, Primary Key) - `first_name`, `last_name`, `email` (Required) - `phone`, `date_of_birth` (Optional)