Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1690da3fab | |||
| cb6e0103e7 | |||
| 98d0bf0c7b | |||
| 0a90b57c2a | |||
| 0ab62a2752 | |||
| 6070709bf2 | |||
| 763c2a9157 | |||
| 4f715d10bb | |||
| 0b830eb675 | |||
| 4c37ecb952 | |||
| c25ef17a4a | |||
| e5e3b4cfec | |||
| 7d064853e5 | |||
| 387180c12c | |||
| 49393d3eac | |||
| e389fe9bce | |||
| 1a4753cd73 | |||
| ece3f8bf78 | |||
| 8d176ce955 | |||
| 280db663c7 | |||
| 74ef6424b7 | |||
| 3959168695 | |||
| 04a435df1d | |||
| 3aaf5cc59c | |||
| a2d94bbc7e | |||
| 95a130c72e | |||
| 223bf77776 | |||
| 99cbfeef11 | |||
| ed1cb507cf | |||
| f4fab93a6c | |||
| 9b9f60a071 | |||
| d219176609 | |||
| 7411038b3b | |||
| 77ee608094 | |||
| 9bee2f233e | |||
| c317147ca4 | |||
| 15222b5453 | |||
| 6f15ada447 | |||
| 8b294d947d | |||
| 66c8838379 | |||
| 022ffccccd | |||
| 8ab6ab1c2a | |||
| 46d993e47f | |||
| 62f9472695 | |||
| b94984043c | |||
| fd78404d72 | |||
| 884ccc0db5 | |||
| 8ecc9fbe52 | |||
| d0edfa2538 | |||
| e1bf4d8454 | |||
| 5a08361f83 | |||
| 5d6d9efd27 |
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
|
||||
# shellcheck disable=SC1091
|
||||
source "$SCRIPT_DIR/lib/common.sh"
|
||||
|
||||
REPO_ROOT="$(resolve_repo_root)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
# check-docs-drift.sh
|
||||
# Zweck: sehr schlanke Drift-Checks gegen die neue Doku-Struktur.
|
||||
# - Kein Guidelines-System mehr.
|
||||
# - Single Source of Truth: `docs/`
|
||||
|
||||
err=0
|
||||
|
||||
has() { grep -q "$2" "$1" || { echo "[DRIFT] '$2' fehlt in $1"; err=1; }; }
|
||||
miss() { grep -q "$2" "$1" && { echo "[DRIFT] Veralteter Begriff '$2' in $1"; err=1; }; }
|
||||
|
||||
# Harte Altlast-Pfade dürfen nicht mehr vorkommen
|
||||
if git grep -n "docs/00_Domain/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/00_Domain/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
if git grep -n "docs/adr/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/adr/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
if git grep -n "docs/c4/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/c4/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
if git grep -n "docs/how-to/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/how-to/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
if git grep -n "docs/reference/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/reference/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
|
||||
# Quelle der Wahrheit: Gateway-Technologie (sollte in Architektur/ADRs/C4 konsistent sein)
|
||||
has docs/01_Architecture/ARCHITECTURE.md "Spring Cloud Gateway"
|
||||
has docs/01_Architecture/adr/0007-api-gateway-pattern-de.md "Spring Cloud Gateway"
|
||||
miss docs/01_Architecture/adr/0007-api-gateway-pattern-de.md "Ktor"
|
||||
has docs/01_Architecture/c4/02-container-de.puml "Spring Cloud Gateway"
|
||||
miss docs/01_Architecture/c4/02-container-de.puml "Ktor"
|
||||
|
||||
exit $err
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Common helpers for AI guardrail scripts
|
||||
|
||||
# Robustly resolve the repository root directory.
|
||||
# Strategy: prefer Git; fallback to marker search upwards; last resort: current dir.
|
||||
resolve_repo_root() {
|
||||
local start
|
||||
start="${1:-$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)}"
|
||||
if command -v git >/dev/null 2>&1; then
|
||||
if git -C "$start" rev-parse --show-toplevel >/dev/null 2>&1; then
|
||||
git -C "$start" rev-parse --show-toplevel
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
local dir
|
||||
dir="$(cd "$start" && pwd)"
|
||||
while [ "$dir" != "/" ]; do
|
||||
if [ -f "$dir/gradlew" ] || [ -f "$dir/settings.gradle.kts" ] || [ -d "$dir/.git" ]; then
|
||||
echo "$dir"
|
||||
return 0
|
||||
fi
|
||||
dir="$(dirname "$dir")"
|
||||
done
|
||||
pwd
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
|
||||
# shellcheck disable=SC1091
|
||||
source "$SCRIPT_DIR/lib/common.sh"
|
||||
|
||||
REPO_ROOT="$(resolve_repo_root)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
mkdir -p build/diagrams
|
||||
shopt -s nullglob
|
||||
for f in docs/architecture/c4/*.puml; do
|
||||
docker run --rm -v "$PWD":/data plantuml/plantuml -tsvg "/data/$f" -o "/data/build/diagrams"
|
||||
echo "Rendered build/diagrams/$(basename "${f%.puml}").svg"
|
||||
done
|
||||
@@ -0,0 +1,127 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
|
||||
# shellcheck disable=SC1091
|
||||
source "$SCRIPT_DIR/lib/common.sh"
|
||||
|
||||
REPO_ROOT="$(resolve_repo_root)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
QUICK_MODE=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--quick)
|
||||
QUICK_MODE=true
|
||||
shift
|
||||
;;
|
||||
--help|-h)
|
||||
cat << 'EOF'
|
||||
Docs Link-Validierung
|
||||
|
||||
USAGE:
|
||||
./.ai/scripts/validate-links.sh [--quick]
|
||||
|
||||
BESCHREIBUNG:
|
||||
Prüft Markdown-Links in `docs/**/*.md` auf gebrochene relative Pfade.
|
||||
Ignoriert externe Links (http/https/mailto) sowie reine Anchors (#...).
|
||||
|
||||
OPTIONEN:
|
||||
--quick Führt nur eine Teilmenge der Prüfungen durch (aktuell nicht implementiert).
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "[ERROR] Unbekannter Parameter: $1" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
python3 - <<'PY'
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from urllib.parse import unquote
|
||||
|
||||
root = Path.cwd()
|
||||
docs_dir = root / "docs"
|
||||
|
||||
if not docs_dir.is_dir():
|
||||
print(f"[ERROR] docs-Verzeichnis nicht gefunden: {docs_dir}", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
# Veraltete Pfad-Prüfungen wurden entfernt; Fokus auf Link-Integrität.
|
||||
FORBIDDEN_SUBSTRINGS = []
|
||||
|
||||
md_files = sorted(docs_dir.rglob("*.md"))
|
||||
|
||||
link_pattern = re.compile(r"\]\(([^)]+)\)")
|
||||
|
||||
errors = 0
|
||||
|
||||
def is_external(target: str) -> bool:
|
||||
t = target.lower()
|
||||
return t.startswith("http://") or t.startswith("https://") or t.startswith("mailto:")
|
||||
|
||||
def strip_fragment_and_query(target: str) -> str:
|
||||
target = target.split("#", 1)[0]
|
||||
target = target.split("?", 1)[0]
|
||||
return target
|
||||
|
||||
for f in md_files:
|
||||
text = f.read_text(encoding="utf-8", errors="replace")
|
||||
|
||||
for forbidden in FORBIDDEN_SUBSTRINGS:
|
||||
if forbidden in text:
|
||||
print(f"[ERROR] Veralteter Pfad '{forbidden}' in {f}")
|
||||
errors += 1
|
||||
|
||||
for match in link_pattern.finditer(text):
|
||||
target = match.group(1).strip()
|
||||
|
||||
if not target:
|
||||
continue
|
||||
if is_external(target):
|
||||
continue
|
||||
if target.startswith("#"):
|
||||
continue
|
||||
|
||||
if target.startswith("<") and target.endswith(">"):
|
||||
target = target[1:-1]
|
||||
|
||||
target = unquote(strip_fragment_and_query(target))
|
||||
|
||||
if target.startswith("/"):
|
||||
continue
|
||||
|
||||
if ":" in target.split("/", 1)[0]:
|
||||
# z.B. "vscode:..."
|
||||
continue
|
||||
|
||||
resolved = (f.parent / target).resolve()
|
||||
|
||||
try:
|
||||
resolved.relative_to(root.resolve())
|
||||
except ValueError:
|
||||
print(f"[ERROR] Link zeigt außerhalb des Repos: {f} -> {target}")
|
||||
errors += 1
|
||||
continue
|
||||
|
||||
if resolved.is_dir():
|
||||
if not (resolved / "README.md").is_file():
|
||||
print(f"[ERROR] Verlinktes Verzeichnis ohne README.md: {f} -> {target}")
|
||||
errors += 1
|
||||
continue
|
||||
|
||||
if not resolved.exists():
|
||||
print(f"[ERROR] Broken link: {f} -> {target}")
|
||||
errors += 1
|
||||
|
||||
if errors:
|
||||
print(f"[ERROR] Link-Validierung fehlgeschlagen: {errors} Fehler")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"[OK] Link-Validierung erfolgreich: {len(md_files)} Markdown-Dateien geprüft")
|
||||
PY
|
||||
@@ -193,7 +193,7 @@ secrets/
|
||||
# ===================================================================
|
||||
TODO*.md
|
||||
NOTES*.md
|
||||
**/.junie/
|
||||
.junie/
|
||||
|
||||
# ===================================================================
|
||||
# Keep essential files (override exclusions)
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
desktop-tests:
|
||||
# Komplett deaktivierbar über Repo-Variable: Settings → Variables → DESKTOP_CI_ENABLED=true
|
||||
# Zusätzlich: Für Plan‑B‑Builds überspringen, wenn Commit-Message [planb] enthält
|
||||
if: ${{ vars.DESKTOP_CI_ENABLED == 'true' && !contains(github.event.head_commit.message, '[planb]') }}
|
||||
if: ${{ vars.DESKTOP_CI_ENABLED == 'true' && !contains(gitea.event.head_commit.message, '[planb]') }}
|
||||
name: Compose Desktop — Tests (headless) & Build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
name: Build and Publish Docker Images
|
||||
run-name: Build & Publish by @${{ github.actor }}
|
||||
run-name: Build & Publish by @${{ gitea.actor }}
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
tags:
|
||||
- 'v*'
|
||||
paths:
|
||||
- 'backend/**'
|
||||
- 'platform/**'
|
||||
@@ -114,8 +116,9 @@ jobs:
|
||||
with:
|
||||
images: ${{ env.REGISTRY_INTERNAL }}/${{ env.IMAGE_PREFIX }}/${{ matrix.image }}
|
||||
tags: |
|
||||
type=raw,value=latest
|
||||
type=sha,format=long
|
||||
type=ref,event=tag
|
||||
type=raw,value=latest,enable=${{ gitea.ref == 'refs/heads/main' }}
|
||||
type=sha,format=long,enable=${{ gitea.ref == 'refs/heads/main' }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
@@ -129,5 +132,5 @@ jobs:
|
||||
provenance: false
|
||||
sbom: false
|
||||
build-args: |
|
||||
BUILD_DATE=${{ github.event.head_commit.timestamp || 'unknown' }}
|
||||
VERSION=${{ github.sha }}
|
||||
BUILD_DATE=${{ gitea.event.head_commit.timestamp || 'unknown' }}
|
||||
VERSION=${{ gitea.sha }}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
name: Feature Build — Windows MSI (via Conveyor)
|
||||
on:
|
||||
workflow_dispatch: # Nur noch manueller Start möglich, da ARM64-Runner inkompatibel
|
||||
# push:
|
||||
# branches: [ "feature/*" ] # Deaktiviert wegen ARM64 Exec Format Error
|
||||
|
||||
jobs:
|
||||
package-windows:
|
||||
name: 📦 Windows .msi Packaging
|
||||
# Desktop-CI ist nun via Conveyor auf Linux möglich
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup JDK 21 (Temurin)
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '21'
|
||||
cache: gradle
|
||||
|
||||
- name: Gradle Build (Uber-JAR)
|
||||
run: |
|
||||
./gradlew :frontend:shells:meldestelle-desktop:jvmJar --no-daemon
|
||||
ls -lh frontend/shells/meldestelle-desktop/build/libs/
|
||||
|
||||
- name: Setup Conveyor
|
||||
run: |
|
||||
# Conveyor-Installation via Debian-Paket (stabiler in CI)
|
||||
sudo apt-get update && sudo apt-get install -y curl
|
||||
# Wir nutzen die offizielle Empfehlung für Debian-basierte Systeme
|
||||
curl -L https://conveyor.hydraulic.dev/install.sh -o install-conveyor.sh
|
||||
# Validierung: Wenn es kein Shell-Skript ist (sondern HTML), abbrechen
|
||||
if grep -q "<!DOCTYPE HTML" install-conveyor.sh; then
|
||||
echo "Fehler: Download-URL lieferte HTML statt Skript. Nutze npm-Fallback."
|
||||
npm install -g @hydraulic/conveyor
|
||||
else
|
||||
chmod +x install-conveyor.sh
|
||||
./install-conveyor.sh
|
||||
fi
|
||||
echo "$HOME/.conveyor/bin" >> $GITEA_PATH
|
||||
|
||||
- name: Windows .msi mit Conveyor bauen
|
||||
run: |
|
||||
# HINWEIS: Erfordert aktuell einen x64-Linux-Runner.
|
||||
# Schlägt auf ARM64 (Zora) mit 'Exec format error' fehl.
|
||||
CONVEYOR_BIN=$(which conveyor || echo "$HOME/.conveyor/bin/conveyor")
|
||||
$CONVEYOR_BIN make windows-msi
|
||||
|
||||
- name: .msi Artefakt hochladen
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: meldestelle-windows-feature-build
|
||||
path: output/*.msi
|
||||
if-no-files-found: error
|
||||
@@ -5,7 +5,7 @@ on:
|
||||
jobs:
|
||||
no-hardcoded-versions:
|
||||
# Für Plan-B-Builds überspringen: Commit-Message enthält [planb]
|
||||
if: ${{ !contains(github.event.head_commit.message, '[planb]') }}
|
||||
if: ${{ !contains(gitea.event.head_commit.message, '[planb]') }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
tag-release:
|
||||
name: 🏷️ Git-Tag setzen
|
||||
# Für Plan-B-Builds überspringen: Commit-Message enthält [planb]
|
||||
if: ${{ !contains(github.event.head_commit.message, '[planb]') }}
|
||||
if: ${{ !contains(gitea.event.head_commit.message, '[planb]') }}
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.read-version.outputs.version }}
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Git-Tag erstellen & pushen
|
||||
if: steps.check-tag.outputs.already_tagged == 'false' && github.event.inputs.dry_run != 'true'
|
||||
if: steps.check-tag.outputs.already_tagged == 'false' && gitea.event.inputs.dry_run != 'true'
|
||||
run: |
|
||||
TAG="${{ steps.read-version.outputs.tag }}"
|
||||
VERSION="${{ steps.read-version.outputs.version }}"
|
||||
@@ -80,7 +80,7 @@ jobs:
|
||||
package-linux:
|
||||
name: 📦 Linux .deb Packaging
|
||||
# Nur ausführen, wenn Desktop-CI explizit aktiviert ist UND kein Plan‑B Commit
|
||||
if: ${{ vars.DESKTOP_CI_ENABLED == 'true' && !contains(github.event.head_commit.message, '[planb]') }}
|
||||
if: ${{ vars.DESKTOP_CI_ENABLED == 'true' && !contains(gitea.event.head_commit.message, '[planb]') }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: tag-release
|
||||
|
||||
@@ -88,11 +88,11 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup JDK 21 (Temurin)
|
||||
- name: Setup JDK 25 (Temurin)
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '21'
|
||||
java-version: '25'
|
||||
|
||||
- name: Gradle cache
|
||||
uses: actions/cache@v4
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
package-windows:
|
||||
name: 📦 Windows .msi Packaging
|
||||
# Nur ausführen, wenn Desktop-CI explizit aktiviert ist UND kein Plan‑B Commit
|
||||
if: ${{ vars.DESKTOP_CI_ENABLED == 'true' && !contains(github.event.head_commit.message, '[planb]') }}
|
||||
if: ${{ vars.DESKTOP_CI_ENABLED == 'true' && !contains(gitea.event.head_commit.message, '[planb]') }}
|
||||
runs-on: windows-latest
|
||||
needs: tag-release
|
||||
|
||||
@@ -136,11 +136,11 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup JDK 21 (Temurin)
|
||||
- name: Setup JDK 25 (Temurin)
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '21'
|
||||
java-version: '25'
|
||||
|
||||
- name: Gradle cache
|
||||
uses: actions/cache@v4
|
||||
@@ -179,11 +179,11 @@ jobs:
|
||||
steps:
|
||||
- name: Summary ausgeben
|
||||
run: |
|
||||
echo "## 🚀 Release ${{ needs.tag-release.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Artefakt | Status |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|----------|--------|" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Linux .deb | ${{ needs.package-linux.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Windows .msi | ${{ needs.package-windows.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Git-Tag:** \`${{ needs.tag-release.outputs.tag }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "## 🚀 Release ${{ needs.tag-release.outputs.version }}" >> $GITEA_STEP_SUMMARY
|
||||
echo "" >> $GITEA_STEP_SUMMARY
|
||||
echo "| Artefakt | Status |" >> $GITEA_STEP_SUMMARY
|
||||
echo "|----------|--------|" >> $GITEA_STEP_SUMMARY
|
||||
echo "| Linux .deb | ${{ needs.package-linux.result }} |" >> $GITEA_STEP_SUMMARY
|
||||
echo "| Windows .msi | ${{ needs.package-windows.result }} |" >> $GITEA_STEP_SUMMARY
|
||||
echo "" >> $GITEA_STEP_SUMMARY
|
||||
echo "**Git-Tag:** \`${{ needs.tag-release.outputs.tag }}\`" >> $GITEA_STEP_SUMMARY
|
||||
|
||||
@@ -56,3 +56,7 @@ desktop.ini
|
||||
docs/temp/
|
||||
docs/Bin/
|
||||
docs/_archive/
|
||||
|
||||
# Conveyor
|
||||
conveyor.rootkey
|
||||
output/
|
||||
|
||||
@@ -1,43 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# check-docs-drift.sh
|
||||
# Zweck: sehr schlanke Drift-Checks gegen die neue Doku-Struktur.
|
||||
# - Kein Guidelines-System mehr.
|
||||
# - Single Source of Truth: `docs/`
|
||||
|
||||
err=0
|
||||
|
||||
has() { grep -q "$2" "$1" || { echo "[DRIFT] '$2' fehlt in $1"; err=1; }; }
|
||||
miss() { grep -q "$2" "$1" && { echo "[DRIFT] Veralteter Begriff '$2' in $1"; err=1; }; }
|
||||
|
||||
# Harte Altlast-Pfade dürfen nicht mehr vorkommen
|
||||
if git grep -n "docs/00_Domain/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/00_Domain/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
if git grep -n "docs/adr/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/adr/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
if git grep -n "docs/c4/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/c4/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
if git grep -n "docs/how-to/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/how-to/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
if git grep -n "docs/reference/" -- docs >/dev/null 2>&1; then
|
||||
echo "[DRIFT] Veralteter Pfad 'docs/reference/' in docs/* gefunden"
|
||||
err=1
|
||||
fi
|
||||
|
||||
# Quelle der Wahrheit: Gateway-Technologie (sollte in Architektur/ADRs/C4 konsistent sein)
|
||||
has docs/01_Architecture/ARCHITECTURE.md "Spring Cloud Gateway"
|
||||
has docs/01_Architecture/adr/0007-api-gateway-pattern-de.md "Spring Cloud Gateway"
|
||||
miss docs/01_Architecture/adr/0007-api-gateway-pattern-de.md "Ktor"
|
||||
has docs/01_Architecture/c4/02-container-de.puml "Spring Cloud Gateway"
|
||||
miss docs/01_Architecture/c4/02-container-de.puml "Ktor"
|
||||
|
||||
exit $err
|
||||
# Shim: Weiterleitung auf zentrale Guardrail in .ai/
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd)"
|
||||
ROOT_DIR="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || echo "$SCRIPT_DIR")"
|
||||
exec "$ROOT_DIR/.ai/scripts/check-docs-drift.sh" "$@"
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
mkdir -p build/diagrams
|
||||
shopt -s nullglob
|
||||
for f in docs/architecture/c4/*.puml; do
|
||||
docker run --rm -v "$PWD":/data plantuml/plantuml -tsvg "/data/$f" -o "/data/build/diagrams"
|
||||
echo "Rendered build/diagrams/$(basename "${f%.puml}").svg"
|
||||
done
|
||||
# Shim: Weiterleitung auf zentrale Guardrail in .ai/
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd)"
|
||||
ROOT_DIR="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || echo "$SCRIPT_DIR")"
|
||||
exec "$ROOT_DIR/.ai/scripts/render-plantuml.sh" "$@"
|
||||
|
||||
@@ -1,136 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# validate-links.sh - Link-Validierung für Projektdokumentation (`docs/**`).
|
||||
# Zweck: Guardrail für die "Docs-as-Code"-Strategie.
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
QUICK_MODE=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--quick)
|
||||
QUICK_MODE=true
|
||||
shift
|
||||
;;
|
||||
--help|-h)
|
||||
cat << 'EOF'
|
||||
Docs Link-Validierung
|
||||
|
||||
USAGE:
|
||||
./.junie/scripts/validate-links.sh [--quick]
|
||||
|
||||
BESCHREIBUNG:
|
||||
Prüft Markdown-Links in `docs/**/*.md` auf gebrochene relative Pfade.
|
||||
Ignoriert externe Links (http/https/mailto) sowie reine Anchors (#...).
|
||||
|
||||
OPTIONEN:
|
||||
--quick Führt nur eine Teilmenge der Prüfungen durch (aktuell nicht implementiert).
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "[ERROR] Unbekannter Parameter: $1" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
python3 - <<'PY'
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from urllib.parse import unquote
|
||||
|
||||
root = Path.cwd()
|
||||
docs_dir = root / "docs"
|
||||
|
||||
if not docs_dir.is_dir():
|
||||
print(f"[ERROR] docs-Verzeichnis nicht gefunden: {docs_dir}", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
# Veraltete Pfad-Prüfungen wurden entfernt, da sie zu wartungsintensiv waren.
|
||||
# Das Skript konzentriert sich nun auf die Validierung der Link-Integrität.
|
||||
FORBIDDEN_SUBSTRINGS = []
|
||||
|
||||
md_files = sorted(docs_dir.rglob("*.md"))
|
||||
|
||||
link_pattern = re.compile(r"\]\(([^)]+)\)")
|
||||
|
||||
errors = 0
|
||||
|
||||
def is_external(target: str) -> bool:
|
||||
t = target.lower()
|
||||
return t.startswith("http://") or t.startswith("https://") or t.startswith("mailto:")
|
||||
|
||||
def strip_fragment_and_query(target: str) -> str:
|
||||
# remove fragment and query parts
|
||||
target = target.split("#", 1)[0]
|
||||
target = target.split("?", 1)[0]
|
||||
return target
|
||||
|
||||
for f in md_files:
|
||||
text = f.read_text(encoding="utf-8", errors="replace")
|
||||
|
||||
for forbidden in FORBIDDEN_SUBSTRINGS:
|
||||
if forbidden in text:
|
||||
print(f"[ERROR] Veralteter Pfad '{forbidden}' in {f}")
|
||||
errors += 1
|
||||
|
||||
for match in link_pattern.finditer(text):
|
||||
target = match.group(1).strip()
|
||||
|
||||
if not target:
|
||||
continue
|
||||
if is_external(target):
|
||||
continue
|
||||
if target.startswith("#"):
|
||||
continue
|
||||
|
||||
# drop angle brackets <...> used in markdown for urls with spaces
|
||||
if target.startswith("<") and target.endswith(">"):
|
||||
target = target[1:-1]
|
||||
|
||||
target = unquote(strip_fragment_and_query(target))
|
||||
|
||||
# ignore absolute paths in the repo (we treat them as doc-style links; validate only if relative)
|
||||
if target.startswith("/"):
|
||||
continue
|
||||
|
||||
# ignore non-file targets (e.g. empty or protocol-less anchors)
|
||||
if ":" in target.split("/", 1)[0]:
|
||||
# things like "vscode:..." etc.
|
||||
continue
|
||||
|
||||
# treat as file path relative to markdown file
|
||||
resolved = (f.parent / target).resolve()
|
||||
|
||||
# keep validation within repo
|
||||
try:
|
||||
resolved.relative_to(root.resolve())
|
||||
except ValueError:
|
||||
print(f"[ERROR] Link zeigt außerhalb des Repos: {f} -> {target}")
|
||||
errors += 1
|
||||
continue
|
||||
|
||||
# allow directories if they contain README.md
|
||||
if resolved.is_dir():
|
||||
if not (resolved / "README.md").is_file():
|
||||
print(f"[ERROR] Verlinktes Verzeichnis ohne README.md: {f} -> {target}")
|
||||
errors += 1
|
||||
continue
|
||||
|
||||
if not resolved.exists():
|
||||
print(f"[ERROR] Broken link: {f} -> {target}")
|
||||
errors += 1
|
||||
|
||||
if errors:
|
||||
print(f"[ERROR] Link-Validierung fehlgeschlagen: {errors} Fehler")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"[OK] Link-Validierung erfolgreich: {len(md_files)} Markdown-Dateien geprüft")
|
||||
PY
|
||||
# Shim: Weiterleitung auf zentrale Guardrail in .ai/
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd)"
|
||||
ROOT_DIR="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || echo "$SCRIPT_DIR")"
|
||||
exec "$ROOT_DIR/.ai/scripts/validate-links.sh" "$@"
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# .aiignore - Verhindert Token-Waste für Nolik
|
||||
|
||||
# Abhängigkeiten & Binaries
|
||||
build/
|
||||
.gradle/
|
||||
*.jar
|
||||
*.deb
|
||||
*.msi
|
||||
|
||||
# Sensible Daten (auch lokal!)
|
||||
.env
|
||||
.env.*
|
||||
config/docker/certs/
|
||||
*.pem
|
||||
*.jks
|
||||
postgres-data/
|
||||
valkey-data/
|
||||
|
||||
# Doku-Builds (Nolik soll die Source-Files in docs/ lesen, nicht die HTML-Exporte)
|
||||
build/dokka/
|
||||
docs/Neumarkt2026/*.pdf
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Shim: Weiterleitung auf zentrale Guardrail in .ai/
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd)"
|
||||
ROOT_DIR="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || echo "$SCRIPT_DIR")"
|
||||
exec "$ROOT_DIR/.ai/scripts/check-docs-drift.sh" "$@"
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Shim: Weiterleitung auf zentrale Guardrail in .ai/
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd)"
|
||||
ROOT_DIR="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || echo "$SCRIPT_DIR")"
|
||||
exec "$ROOT_DIR/.ai/scripts/validate-links.sh" "$@"
|
||||
@@ -3,12 +3,15 @@
|
||||
Dieses Dokument definiert die Zusammenarbeit zwischen dem User (Owner) und den spezialisierten KI-Agenten.
|
||||
Es dient als zentraler **System-Prompt-Erweiterung** für neue Chat-Sessions.
|
||||
|
||||
## 🚀 Strategische Ausrichtung
|
||||
## 🚀 Strategische Ausrichtung (Reality-Reset 28.04.2026)
|
||||
|
||||
Das Projekt **"Meldestelle"** entwickelt eine ÖTO/FEI-konforme, offline-fähige Turnier-Software.
|
||||
1. **Desktop-First:** Primäres Ziel ist die Compose Desktop App (KMP). UX & Performance sind auf Profis optimiert.
|
||||
2. **Offline-First:** Das System muss autark (ohne Internet) funktionieren. Sync-Logik ist Kernbestandteil.
|
||||
3. **Domain-Driven:** 6 Bounded Contexts (SCS) bilden den fachlichen Rahmen.
|
||||
2. **Offline-First:** Das System muss autark (ohne Internet) funktionieren.
|
||||
3. **Domain-Driven:** Die Hierarchie **Veranstaltung -> Turnier -> Bewerb/Abteilung** ist das absolute Fundament.
|
||||
|
||||
**WICHTIG:** Alle Agenten arbeiten ab sofort nur noch auf Basis von verifiziertem Code. "Halluzinationen" über
|
||||
abgeschlossene Phasen ohne entsprechende Implementierung sind untersagt.
|
||||
|
||||
## 1. Protokoll & Rollen-Badges
|
||||
Jede Agenten-Antwort **muss** mit dem entsprechenden Badge beginnen, um den Kontext und die Verantwortlichkeit zu klären.
|
||||
@@ -37,7 +40,9 @@ Jede Agenten-Antwort **muss** mit dem entsprechenden Badge beginnen, um den Kont
|
||||
4. **Doku-as-Code:** Änderungen an Code/Architektur müssen sofort in `docs/` (ADR/Reference) reflektiert werden.
|
||||
5. **Session-Abschluss:** Jede Session endet mit einem Eintrag durch den **Curator** (Journal oder Artefakt).
|
||||
|
||||
## 3. Projekt-Philosophie
|
||||
* **Information Density over White Space:** Wir bauen ein Profi-Werkzeug, kein Spielzeug.
|
||||
* **Speed over Animation:** Reaktionsgeschwindigkeit der UI hat höchste Priorität.
|
||||
* **Offline-Authentizität:** Lokale Daten sind die "Source of Truth" für den User; der Server ist das Backup/Sync-Target.
|
||||
## 🚫 Anti-Halluzinations-Protokoll (WICHTIG)
|
||||
Um Fehlentscheidungen und falsche Status-Meldungen zu verhindern, gelten ab sofort folgende Regeln:
|
||||
1. **Kein "Erledigt" ohne Beweis:** Ein Task darf erst dann als abgeschlossen markiert werden, wenn ein Test-Log, ein erfolgreicher Build oder eine explizite Bestätigung des Users vorliegt.
|
||||
2. **Status "Verifikation ausstehend":** Code, der geschrieben, aber nicht auf Hardware getestet wurde, muss zwingend diesen Zusatz tragen.
|
||||
3. **Fakten-Check vor Abschluss:** Vor dem Senden der `submit`-Meldung muss der Agent prüfen: "Habe ich das wirklich laufen sehen oder nehme ich es nur an?"
|
||||
4. **Fehler-Eingeständnis:** Bei Entdeckung einer Halluzination ist sofort der User zu informieren und der Status in allen Dokumenten (Roadmap, Journal) zu korrigieren.
|
||||
|
||||
@@ -17,218 +17,19 @@ Versionierung folgt [Semantic Versioning](https://semver.org/lang/de/).
|
||||
|
||||
### Hinzugefügt
|
||||
|
||||
- **Onboarding & Desktop-UX - 15.04.2026:**
|
||||
- **Desktop-App:** Dynamisierung der Statusanzeigen im App-Footer ("Cloud synchronisiert" & "Verbunden").
|
||||
- **Connectivity-Tracking:** Implementierung des `ConnectivityTracker` (KMP) zur Echtzeit-Überwachung der API-Gateway
|
||||
Erreichbarkeit.
|
||||
- **LAN-Erkennung:** Integration des `NetworkDiscoveryService` (mDNS) im Footer zur Anzeige aktiver Instanzen im
|
||||
lokalen Netzwerk.
|
||||
- **Onboarding:** Datenfluss vom `SettingsManager` bis in den Footer finalisiert (Anzeige des echten Gerätenamens).
|
||||
- **Online-Nennung & Integration - 15.04.2026:**
|
||||
- **Backend (Mail-Service):** Finalisierung des `MailController` für Web-Nennungen inkl. SMTP-Versand via World4You.
|
||||
- **Frontend (Desktop):** `NennungsEingangScreen` an Live-Daten vom `mail-service` angebunden.
|
||||
- **Repository:** `NennungRemoteRepository` (KMP) um `holeNennungen()` erweitert.
|
||||
- **Billing & ÖTO - 15.04.2026:**
|
||||
- **Sportförderbeitrag:** Automatische Buchung von 1,00 EUR (§16 ÖTO) bei jeder Nennung im `entries-service`
|
||||
implementiert.
|
||||
- **Basis-Infrastruktur & Domain-Definition:**
|
||||
- DDD-Modelle für `Veranstaltung`, `Turnier`, `Bewerb` und `Abteilung` gemäß ÖTO definiert.
|
||||
- ZNS-Parser Prototyp für Dateiformate (VEREIN01, LIZENZ01, PFERD01, RICHT01).
|
||||
- Plan-B Mail-Service (Spring Boot) für Nennungs-Versand via World4You.
|
||||
- Desktop-App Skelett mit Navigation und UI-Hüllen (Compose Desktop).
|
||||
|
||||
### Behoben
|
||||
### Reality-Reset (28.04.2026)
|
||||
|
||||
- **Frontend (Desktop):** Behebung von Kompilierungsfehlern in `ScreenPreviews.kt` durch Implementierung der fehlenden
|
||||
`getStats()` Methode in den `MasterdataRepository`-Mocks.
|
||||
- **Identity-Modul:** Umstellung auf `kotlin.time.Instant` zur Vermeidung von Deprecation-Warnungen und Behebung von
|
||||
Persistenz-Konflikten im `ExposedDeviceRepository`.
|
||||
- **Koin DI:** Korrektur von Typ-Inferenz-Fehlern beim `HttpClient` im `nennung-feature` durch explizite Qualifier.
|
||||
- **Turnier-Feature:** Behebung eines unsicheren Casts (`Any!` zu `List<String>`) in `TurnierStammdatenTab.kt`.
|
||||
- **Konfiguration:** Harmonisierung der Ports (Mail-Service auf 8083) in `.env`, `dc-backend.yaml` und
|
||||
`PlatformConfig.jvm.kt`.
|
||||
- **Korrektur:** Vormalige Einträge über "abgeschlossene" Billing-, Results- und Zeitplan-Features wurden entfernt, da
|
||||
diese im Code nicht funktional hinterlegt waren.
|
||||
- **Status:** Fokus zurück auf die Kern-Hierarchie (Veranstaltung -> Turnier -> Bewerb).
|
||||
|
||||
### Hinzugefügt
|
||||
- **Phase 12 (Abrechnung & Infrastruktur) - 12.04.2026:**
|
||||
- **Infrastruktur:** Docker-Integration für `billing-service` (Port 8087) und API-Gateway Routing vervollständigt.
|
||||
- **Service Discovery:** Alle relevanten Microservices (`masterdata`, `events`, `results`, `series`, `billing`) sind nun bei Consul registriert.
|
||||
- **Frontend Billing:** `BillingRepository` und `BillingViewModel` auf reale API-Anbindung (Ktor) umgestellt; `BillingScreen` funktionalisiert.
|
||||
- **Backend (Series):** JPA-Entitäten `Serie` und `SeriePunkt` im `series-service` stabilisiert und Flyway-Migrationen für das Datenbankschema erstellt.
|
||||
- **Fix:** Behebung von IDE-Mapping-Warnungen durch explizite `@Column` Namen in den JPA-Entitäten.
|
||||
- **Backend Fixes - 12.04.2026:**
|
||||
- **Infrastruktur:** Behebung von Startfehlern im `events-service` (DataSource) und `masterdata-service` (Consul).
|
||||
- **Build:** Integration von `results-service` und `series-service` in `settings.gradle.kts`.
|
||||
- **Domain:** `Serie` und `SeriePunkt` zu `data class` konvertiert (copy() Unterstützung).
|
||||
- **Phase 11 (Ergebniserfassung & Platzierung) - 12.04.2026:**
|
||||
- **Backend (Results):** `results-service` um JPA-Entitäten, Repositories und Business-Logik für Platzierungsberechnungen (Wertnote, Zeit, Fehler) ergänzt.
|
||||
- **Infrastructure:** `dc-backend.yaml` und `GatewayConfig.kt` um den Service `results` (Port 8088) erweitert.
|
||||
- **Frontend Domain:** `ErgebnisRepository` und `Ergebnis`-Modell für Wertnoten, Zeiten und Status erstellt.
|
||||
- **Frontend UI:** `ErgebnisEditDialog` zur schnellen Ergebniserfassung hinzugefügt; `TurnierStartlistenTab` ermöglicht nun Erfassung per Zeilen-Klick.
|
||||
- **Frontend UI:** `TurnierErgebnislistenTab` vervollständigt: Buttons für "Platzierung berechnen" und "Drucken" (PDF) funktionalisiert.
|
||||
- **Fix:** Kompilierungsprobleme im `TurnierFeatureModule` und `ScreenPreviews.kt` behoben (fehlende `ergebnisRepo` Parameter).
|
||||
|
||||
### Hinzugefügt
|
||||
- **Phase 10.4 (Series-Context Vertiefung) - 12.04.2026:**
|
||||
- **Backend (Series):** `series-service` um Logik für Streichresultate (`ReglementTyp`) und Bindungsarten (Reiter-zentriert, Pferde-zentriert, Paar-Bindung) erweitert.
|
||||
- **Infrastructure:** `dc-backend.yaml` und `GatewayConfig.kt` um den Service `series` (Port 8089) erweitert.
|
||||
- **Frontend Domain:** `SeriesRepository` und Modelle an das neue Ranking-Format (`SerieStandEntry`) angepasst.
|
||||
- **UI:** `SeriesScreen.kt` überarbeitet: Zeigt nun Reiter- und Pferde-IDs sowie Fortschritt pro Teilnehmer an.
|
||||
- **Dokumentation:** `MASTER_ROADMAP.md` aktualisiert (Phase 10 & 11 auf 'Completed' gesetzt).
|
||||
|
||||
### Hinzugefügt
|
||||
- **Phase 10.3 (Echter Datenverkehr & Infrastruktur) - 12.04.2026:**
|
||||
- **Infrastructure:** Docker-Services für `masterdata`, `events` und `zns-import` in `dc-backend.yaml` ergänzt.
|
||||
- **Gateway:** API-Gateway Routing für Masterdata (`/api/v1/masterdata`) und Events (`/api/v1/events`) konfiguriert.
|
||||
- **Frontend (Vereine):** `VereinRepository` (Ktor) und `VereinViewModel` implementiert für echtes Anlegen von Veranstaltern.
|
||||
- **Frontend (Events):** `TurnierViewModel` an das reale `TurnierRepository` angebunden.
|
||||
- **Fix:** `verein-feature` Abhängigkeiten korrigiert (Network/Ktor).
|
||||
- **Fix:** Polling-Endpoints im `ZnsImportViewModel` an das neue Gateway-Routing angepasst.
|
||||
|
||||
### Hinzugefügt
|
||||
- **Phase 10.2 (Masterdata-Editoren & Organisation) - 12.04.2026:**
|
||||
- **Frontend:** `MasterdataEditDialogs.kt` für die Bearbeitung von Reiter- und Pferdedaten direkt im Turnier-Kontext.
|
||||
- **Frontend:** Erweiterung des `MasterdataRepository` um Schreibzugriffe (`saveReiter`, `savePferd`).
|
||||
- **Frontend:** Funktionale Suche für Turnierleiter im `Organisation`-Tab via `NennungViewModel` und Masterdata-API.
|
||||
- **Frontend:** State-Management für Stammdaten-Editoren im `NennungViewModel`.
|
||||
- **Fix:** Kompilierungsfehler in `ScreenPreviews.kt` behoben (fehlende Interface-Methoden in Mocks).
|
||||
- **Fix (Desktop Shell):** Fehlendes `turnierFeatureModule` in `main.kt` registriert und Login-Gate in `DesktopApp.kt` optimiert.
|
||||
|
||||
### Hinzugefügt
|
||||
- **Phase 10 (Series-Context & Stammdaten) - 11.04.2026:**
|
||||
- **Frontend:** Stammdaten-Infrastruktur im `turnier-feature` (Repositories, DTOs, Domänenmodelle) für Reiter, Pferde, Funktionäre und Vereine.
|
||||
- **Frontend:** `NennungViewModel` zur Steuerung der Suche und Status-Verwaltung von Nennungen.
|
||||
- **Frontend:** Funktionalisierung des `Nennungen`-Tabs (Suche, Echt-Datenanbindung) und Vorbereitung des `Organisation`-Tabs.
|
||||
- **Frontend:** `DefaultMasterdataRepository` zur Suche in Reitern, Pferden und Funktionären via Backend-API.
|
||||
- **Netzwerk:** Erweiterung der `ApiRoutes` um Endpunkte für Masterdata und Nennungen.
|
||||
- **Phase 10 (Series-Context) Vorbereitung:**
|
||||
- **Frontend:** Neuer `SeriesScreen.kt` für die Verwaltung von Cups und Meisterschaften (konfigurierbare Reglements).
|
||||
- **Frontend:** Erweiterung des `AdminUebersichtScreen` (Cockpit) um KPI-Kacheln mit Direkt-Links zu Cups und Meisterschaften.
|
||||
- **Frontend:** Integration der Series-Navigation in die Breadcrumbs und das globale Routing (`Meisterschaften`, `Cups`).
|
||||
- **Turnier-Feature Hardening:**
|
||||
- **Frontend:** `STARTLISTEN` und `ERGEBNISLISTEN` Tabs vollständig an das `BewerbViewModel` angebunden (Bewerbs-Auswahl mit echten Daten).
|
||||
- **Frontend:** Implementierung der Starter-Anzeige in der Startliste (LazyColumn).
|
||||
|
||||
### Geändert
|
||||
- **Turnier-Feature:** Sichtbarkeit von `BewerbViewModel.generateStartliste()` auf `public` geändert, um den Aufruf aus dem Tab zu ermöglichen.
|
||||
- **Frontend (Desktop):** `ScreenPreviews.kt` aktualisiert zur Berücksichtigung der neuen ViewModel-Abhängigkeiten (`NennungViewModel`, `MasterdataRepository`).
|
||||
|
||||
### [Phase 9] - 11.04.2026
|
||||
- **Frontend:** Interaktiver Drag & Drop Zeitplan mit automatischem 5-Minuten-Snapping und Konflikt-Visualisierung.
|
||||
- **Frontend:** "B-Satz Export (ZNS)" Toolbar-Aktion mit integriertem Vorschau-Dialog.
|
||||
- **Frontend:** "Änderungs-Historie" (Audit-Log) Sektion zur Nachverfolgung von Zeitplan-Anpassungen.
|
||||
- **Backend:** `audit_log` Persistenz und Abfrage-API für manuelle Eingriffe in Bewerbe.
|
||||
- **Backend:** ZNS B-Satz Export Endpunkt (`/export/zns/b-satz`) zur Generierung von `BBEWERBE` Datensätzen.
|
||||
- **Core:** `FixedWidthLineBuilder` zur präzisen Generierung von ZNS-konformen Festbreiten-Formaten.
|
||||
|
||||
### Behoben
|
||||
- **Infrastruktur:** Veraltete `newSuspendedTransaction` in `DatabaseFactory.kt` durch moderne `suspendTransaction` (Exposed v1) ersetzt.
|
||||
- **Frontend (Desktop):** Kompilierfehler in `ScreenPreviews.kt` behoben, indem fehlende Interface-Methoden im Mock-Repository implementiert wurden.
|
||||
- **Backend (Tests):** `JdbcSQLSyntaxErrorException` im `BewerbeZeitplanIntegrationTest` durch Korrektur des Schema-Setups (Audit-Log Tabelle) gelöst.
|
||||
|
||||
### Hinzugefügt
|
||||
- **Bugfix**: Behebung von Build-Fehlern im `veranstalter-feature` nach der Paket-Konsolidierung.
|
||||
- **Frontend**: `FakeVeranstalterRepository` in `commonMain` implementiert, um saubere KMP-DI zu ermöglichen.
|
||||
- **Frontend**: Veraltete Imports und Referenzen im `meldestelle-desktop` Shell und Previews korrigiert.
|
||||
- **Architektur:** Fachliches Konzept für Zeitplan-Optimierung (Drag & Drop) erstellt (`konzept-zeitplan-optimierung-de.md`).
|
||||
- **Architektur:** Spezifikation des Status-Automaten für Nennungen und Synchronisations-Logik (`status-automat-nennungen-de.md`).
|
||||
- **Rulebook:** Überprüfung und Spezifikation der Parcoursbesichtigung zu Pferd (§43 ÖTO) inkl. 5-Minuten-Puffer-Regel.
|
||||
- **Backend (Entries):** Erweiterung der Domain-Modelle `Bewerb` und `Abteilung` um Besichtigungs- und Pausen-Konfigurationen.
|
||||
- **Backend (Entries):** Neues Datenmodell `BesichtigungsBlock` für wettbewerbsübergreifende Parcoursbesichtigungen.
|
||||
- **Backend (Entries):** API-Endpunkt `PATCH /bewerbe/{id}/zeitplan` für schnelle Zeitplan-Updates implementiert.
|
||||
- **Backend (Entries):** `StartlistenService` um ÖTO-konforme Zeitberechnung (Besichtigungs-Puffer, Pausen-Intervalle) erweitert.
|
||||
|
||||
### Geändert
|
||||
- Masterdata/Domain: Umbenennungen zur Vereinheitlichung der Terminologie (DE):
|
||||
- `MasterdataLicenseRepository` → `LizenzRepository`
|
||||
- `LicenseMatrixService` → `LizenzMatrixService`
|
||||
- `LicenseMatrixServiceImpl` → `LizenzMatrixServiceImpl`
|
||||
- Test: `LicenseMatrixServiceTest` → `LiznezMatrixServiceTest` (exakt nach Vorgabe)
|
||||
- Infrastructure (Exposed): `LicenseTable` → `LizenzTable`
|
||||
- Docs: Begriff „reit_lizenzen“ → „reiterlizenzen“ in Glossar/UL konsolidiert.
|
||||
|
||||
### Hinzugefügt
|
||||
|
||||
- **Events-Service Bundle:** Vollständige Stabilisierung der `events` Services (Domain, Infrastructure, API, Service).
|
||||
- **Domain:** Umstellung auf `kotlin.time.Instant` zur Vermeidung von Deprecation-Warnungen (Kotlin 2.1.20+) und Harmonisierung mit dem Rulebook-Expert.
|
||||
- **Infrastructure:** Anpassung an den `org.jetbrains.exposed.v1` Namespace und Implementierung von UUID-Konvertierungen zwischen `kotlin.uuid.Uuid` (Domain) und `java.util.UUID` (DB).
|
||||
- **API:** Refactoring des `VeranstaltungController` zur direkten Repository-Nutzung (Alignment mit `entries` Service).
|
||||
- **Service-Config:** Umstellung auf Flyway-basiertes Tenant-Schema-Management in `EventsDatabaseConfiguration`.
|
||||
- **Build:** Behebung des `shadowJar` Fehlers in `events-infrastructure` durch Entfernen des unnötigen `ktor` Plugins in der Library-Schicht.
|
||||
|
||||
- Masterdata: Automatisches Seeding aller Reiterlizenzen (license_matrix) beim Start des `masterdata-service` via `ReiterlizenzenSeeder` (idempotent; SPRINGEN: LIZENZFREI,R1–R4; DRESSUR: LIZENZFREI,RD1–RD3).
|
||||
|
||||
- **ZNS-Import (LIZENZ01.dat):** Robuster Lizenz-Tokenizer und Normalizer implementiert.
|
||||
- Erkennung: `RD1..RD4`, `R1..R4`, `S1..S4`, `D2..D4`, Kombis `R{n}D{m}`, `R{n}S{k}`, `RDS4` (rechts-/letztes Vorkommen gewinnt).
|
||||
- Normalisierung: `S*→R*`, `D*→RD*`, `RD4→RD3` (bis Enum verfügbar), `R{n}S{k}→Rmax(n,k)`, `R{n}D{m}→R{n}+RD{m}`.
|
||||
- Integration: `ZnsReiterParser` füllt `lizenzen`-Liste (1:n) entsprechend und leitet `lizenzKlasse` bei fehlendem 4‑Spalten‑Code aus Token ab.
|
||||
- QA: Neue Unit-Tests (Tokenizer) für Beispiele `R2S3`, `R2D4`, `RD2` u. a.; alle Parser-Tests grün.
|
||||
|
||||
- **Core:** Modularisierte ZNS-Parser eingeführt (`ZnsVereinParser`, `ZnsReiterParser`, `ZnsPferdParser`, `ZnsFunktionaerParser`) zur Verbesserung der Wartbarkeit und Unterstützung von Einzelimporten.
|
||||
- **Fix:** SQL-Migrationsfehler in `V010` behoben, indem die Umbenennung der Spalte `name` in `verein_name` durch einen idempotenten `DO`-Block abgesichert wurde (behebt "Unable to resolve column 'name'").
|
||||
- **Infrastructure:** Datenbank-Migration `V010` hinzugefügt, um das Schema final mit den `Exposed`-Modellen zu synchronisieren.
|
||||
- **Infrastructure:** Datei-Archivierung für hochgeladene ZNS-ZIP-Dateien im `ZnsImportOrchestrator` implementiert.
|
||||
- **Infrastructure:** `ZnsImportService` vollständig auf die neuen spezialisierten Parser umgestellt und als Spring-Bean im Backend registriert.
|
||||
- **QA:** Umfassende Test-Suite `ZnsParserTest.kt` mit realen ZNS-Daten (Hämmerle, Neuwirth, etc.) erstellt; Korrektur der Extraktions-Logik für Mitgliedsnummern (Position 147) und Funktionär-Daten (RICHT01).
|
||||
- **QA:** Neue Betriebsanleitung für ZNS-Importer Tests erstellt: `docs/07_Infrastructure/runbooks/ZNS_Importer_Test_Manual.md`.
|
||||
- **Infrastructure:** `MasterdataDatabaseConfiguration` korrigiert: Expliziter Aufruf von `Database.connect()` hinzugefügt, um Abstürze beim Anwendungsstart ("No database specified") zu beheben.
|
||||
- **Infrastructure:** `application.yml` im `masterdata-service` vervollständigt (DataSource-Konfiguration mit `pg-user`/`pg-password` und Flyway-Aktivierung).
|
||||
- **Domain:** Legacy-Spezifikationen für ZNS-Schnittstellen (Import/Export) formalisiert:
|
||||
- `docs/03_Domain/02_Reference/Legacy_Specs/OETO-2026_Meldestelle_Pflichtenheft_V2.4.md` (Basis-Satzarten A-N)
|
||||
- `docs/03_Domain/02_Reference/Legacy_Specs/OETO-2026_Meldestelle_Erweiterung-Schnittstelle_2014.md` (XML-Erweiterung, LinkID-Logik)
|
||||
- **QA B-2:** `OnboardingValidator`-Objekt extrahiert; `OnboardingValidatorTest.kt` (17 Unit-Tests: Pflichtfeld-Guard,
|
||||
Doppelklick-Schutz, Abbrechen-Reset, rememberSaveable-Regression)
|
||||
- **QA B-3:** `AbteilungsRegelServiceTest.kt` um 14 Tests erweitert: CSN-C-NEU ≤95 cm / ≥100 cm Pflicht-Teilung,
|
||||
ORGANISATORISCH, SEPARATE_SIEGEREHRUNG, Caprilli-Regression, Grenzfälle 90/110 cm
|
||||
- **Domain:** `AbteilungsTeilungsTypE` um `ORGANISATORISCH` und `SEPARATE_SIEGEREHRUNG` erweitert
|
||||
|
||||
### Behoben
|
||||
|
||||
- **Masterdata/Infrastructure:** Kompilierfehler in `AltersklasseRepositoryImpl` durch Vereinheitlichung der Exposed-Tabellendefinition behoben:
|
||||
- `AltersklassenTable` → `AltersklasseTable`
|
||||
- Spalte `altersklassen_code` → `altersklasse_code`
|
||||
- Tabellenname `altersklassen` → `altersklasse`
|
||||
- **Masterdata/API:** Fehlendes Interface-Mapping ergänzt: `RegulationRepository` enthält nun `findAllTurnierklassen()`; `ExposedRegulationRepository` implementiert die Methode und `RegulationController` kompiliert wieder.
|
||||
- **ZNS-Import:** `AltersklassenExposedRepository` korrigiert (richtiger Domain-Typ `AltersklasseDefinition`, Mapping von `SparteE` und Zeitstempeln).
|
||||
|
||||
- **Migration V013:** Idempotent und robust gemacht. Alle `ALTER TABLE ... RENAME`-Operationen laufen nun nur, wenn die Quell-Tabelle existiert (Fix für "Unable to resolve table 'bundesland'/'turnierklasse'").
|
||||
- **Lizenz-Validierung:** `LicenseMatrixServiceImpl` um Cross-Discipline-Mapping R↔RD (ÖTO-Äquivalenzen) erweitert. Damit funktionieren Fälle wie Dressur-Starts mit Spring-Lizenz (R1→RD1, R2→RD2, R3/R4→RD3) bzw. umgekehrt konsistent.
|
||||
|
||||
- **Domain:** Striktere Spartenlizenz-Prüfung in `Reiter.hasLizenzForSparte` implementiert (RD1..RD3 nur DRESSUR; R1..R4 nur SPRINGEN). Behebt Testfehler „isEligible verweigert Start ohne passende Spartenlizenz“ im `LicenseMatrixServiceTest`.
|
||||
|
||||
### Behoben
|
||||
- **Backend (Entries):** Fehlschlagenden Unit-Test `berechneStartzeiten sollte Zeiten korrekt aufsummieren` korrigiert; der Test berücksichtigt nun den neuen 5-minütigen ÖTO-konformen Puffer nach der Parcoursbesichtigung (§43).
|
||||
- **Frontend (Desktop):** Build-Fehler ("No matching variant") beim `funktionaer-feature` behoben; fehlendes `build.gradle.kts` mit JVM-Target und Compose/Koin-Abhängigkeiten ergänzt.
|
||||
- **Frontend (Desktop):** Massive Inkonsistenzen in der Paketstruktur des `veranstalter-feature` bereinigt; alle Komponenten (ViewModel, Screens, Mocks) auf das Standardpaket `at.mocode.frontend.features.veranstalter` konsolidiert, um Redeklarationen und Import-Fehler zu beheben.
|
||||
- **Frontend (Desktop):** Kompilierfehler im `VeranstalterDetailScreen` durch korrekte Paket-Referenzierung des `FakeVeranstaltungStore` gelöst.
|
||||
|
||||
### Dokumentation
|
||||
- **Masterdata/Docs:** `REITER_LIZENZEN.md` überarbeitet:
|
||||
- Strikte Sparten-Trennung dokumentiert (RD1..RD3 nur Dressur; R1..R4 nur Springen).
|
||||
- Dressur-Tabelle korrigiert (R-Lizenzen entfernen; RD-Pflicht je Klasse).
|
||||
- Validierungslogik ergänzt (2-stufig: Spartenlizenz → Max-Turnierklasse; R↔RD Mapping nur zur Kappung, nicht zur Eligibility).
|
||||
- Vielseitigkeit (CCN/CCI) ergänzt: kumulative Anforderungen (Dressur RD* UND Springen R* je Klasse); Startkartenregel für Einsteiger.
|
||||
- Fahren (CAN/CAI) ergänzt: aktueller Systemzustand ohne `F*`‑Lizenzen dokumentiert; Teilnahme über Startkarte/Ausschreibung, geplante Enum‑Erweiterung vermerkt.
|
||||
- §15‑Tabelle (kompakt) integriert und auf ÖTO‑Referenz verlinkt; Bedeutungen „B,C“ und „LP“ erläutert. Hinweis aufgenommen, dass `RD4` derzeit nicht als Enum vorhanden ist und wie `RD3` behandelt wird.
|
||||
- Kombinationsreihen gemäß §15 ergänzt: `R1S2`, `R1S3`, `R1S4`, `R2S3`, `R2S4`, `R3S4` (neuer Unterabschnitt 2.6 mit Tabelle, identische Spalten wie 2.5).
|
||||
|
||||
### Behoben
|
||||
|
||||
- **Masterdata:** Qualifikations-Management für Funktionäre (Richter/Parcoursbauer) professionalisiert: Umstellung von unstrukturiertem Text auf offizielle ÖTO/FEI Master-Daten Referenzen (`QualifikationMasterTable`).
|
||||
- **Masterdata:** Fehlende Tabelle `funktionaer_qualifikation` in der Initialisierung beider Services (`masterdata` und `zns-import`) ergänzt, um `PSQLException` während des ZNS-Imports zu beheben.
|
||||
- **Infrastructure:** Start-Probleme des `masterdata-service` endgültig behoben: Port-Konflikt zwischen Spring Boot (Management/Actuator) und dem Gateway (8081) durch Umzug auf Port 8086 (gemäß Infrastruktur-Vorgaben) gelöst.
|
||||
- **Infrastructure:** Port-Konflikt im `masterdata-service` durch Trennung der Bind-Adressen (Spring: 127.0.0.1, Ktor: 0.0.0.0) und Bereinigung verwaister Prozesse stabilisiert.
|
||||
- **Core:** Veraltete `ZnsLegacyParsersTest.kt` entfernt; alle Tests sind nun in `ZnsParserTest.kt` konsolidiert.
|
||||
- **Domain:** Fehlschlagenden `LicenseMatrixServiceTest` behoben; fehlende `reiterLizenz`-Daten in Test-Reitern ergänzt und Fallback-Logik in `LicenseMatrixServiceImpl` für spartenübergreifende Lizenzen (z.B. Springlizenz für Dressur-Basis) stabilisiert.
|
||||
- **Infrastructure:** Fehlschlagenden `RegulationSeedVerificationTest` behoben; Testdaten an das neue Modell (`reiterLizenz` Feld) angepasst.
|
||||
- **Infrastructure:** Kompilierfehler 'Unresolved reference lizenzKlasse' in `ReiterExposedRepository` behoben; fehlendes Feld `lizenzKlasse` zu `ReiterTable` und Datenbank-Migration `V010` hinzugefügt.
|
||||
- **Onboarding:** `remember` → `rememberSaveable` für `geraetName`, `sharedKey`, `znsStatus` in `OnboardingScreen.kt` (
|
||||
Felder gingen bei Zurück-Navigation verloren)
|
||||
- **AbteilungsRegelService:** CSN-C-NEU Pflicht-Teilungslogik implementiert (≤95 cm: ohne/mit Lizenz; ≥100 cm: R1/R2+);
|
||||
`SparteE`-Import ergänzt
|
||||
|
||||
- Desktop-Packaging konfiguriert: `.deb` (Linux), `.msi` (Windows), `.dmg` (macOS)
|
||||
- Zentrale Versionsdatei `version.properties` (Single Source of Truth für SemVer)
|
||||
- Automatisches Git-Tagging via CI/CD (`release.yml` Gitea Actions Workflow)
|
||||
- `CHANGELOG.md` eingeführt (dieses Dokument)
|
||||
|
||||
---
|
||||
|
||||
## [1.0.6-SNAPSHOT] — 2026-04-10
|
||||
### [1.0.6-SNAPSHOT] — 2026-04-10
|
||||
|
||||
### Hinzugefügt
|
||||
- **Entries-Domain:** Strukturiertes Abteilungs-Warnungssystem gemäß ÖTO § 39 implementiert.
|
||||
|
||||
@@ -13,14 +13,14 @@ Die gesamte Projektdokumentation (Architektur, Fachdomäne, Entwickler-Anleitung
|
||||
|
||||
**Starte hier:** [**→ docs/README.md**](./docs/README.md)
|
||||
|
||||
| Bereich | Inhalt |
|
||||
|-----------------------------------------------|---------------------------------------------|
|
||||
| Bereich | Inhalt |
|
||||
|-----------------------------------------------|---------------------------------------------------|
|
||||
| [01_Architecture](./docs/01_Architecture) | Master Roadmap, ADRs, C4‑Modelle, Desktop‑Konzept |
|
||||
| [02_Guides](./docs/02_Guides) | Setup-Anleitungen, Entwickler-Guidelines |
|
||||
| [03_Domain](./docs/03_Domain) | Fachlichkeit, Turnierregeln, Entities |
|
||||
| [07_Infrastructure](./docs/07_Infrastructure) | Docker, Keycloak, CI/CD, Zora-Infrastruktur |
|
||||
| [02_Guides](./docs/02_Guides) | Setup-Anleitungen, Entwickler-Guidelines |
|
||||
| [03_Domain](./docs/03_Domain) | Fachlichkeit, Turnierregeln, Entities |
|
||||
| [07_Infrastructure](./docs/07_Infrastructure) | Docker, Keycloak, CI/CD, Zora-Infrastruktur |
|
||||
|
||||
Wesentliche Architektur-Referenz: [Offline‑First Desktop & Backend (Kurzkonzept)](./docs/01_Architecture/konzept-offline-first-desktop-backend-de.md)
|
||||
Wesentliche Architektur-Referenz: [Offline‑First Desktop & Backend (Kurzkonzept)](./docs/01_Architecture/Concepts/konzept-offline-first-desktop-backend-de.md)
|
||||
|
||||
---
|
||||
|
||||
@@ -113,3 +113,9 @@ Beiträge sind willkommen. Bitte lies zunächst die Entwickler-Guides unter [`do
|
||||
## 📜 Lizenz
|
||||
|
||||
Dieses Projekt steht unter der [MIT License](LICENSE).
|
||||
|
||||
---
|
||||
|
||||
## Test
|
||||
|
||||
Das ist der 2. Versuch über Remote zu Committen
|
||||
|
||||
@@ -8,7 +8,7 @@ import io.valkey.springframework.data.valkey.core.ValkeyTemplate
|
||||
import io.valkey.springframework.data.valkey.serializer.StringValkeySerializer
|
||||
import kotlinx.coroutines.joinAll
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.testcontainers.containers.GenericContainer
|
||||
@@ -70,7 +70,7 @@ class ValkeyDistributedCachePerformanceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test cache performance with high concurrent access`() = runTest {
|
||||
fun `test cache performance with high concurrent access`() = runBlocking {
|
||||
logger.info { "Starting concurrent access test" }
|
||||
val numberOfCoroutines = 100
|
||||
val operationsPerCoroutine = 50
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# ===================================================================
|
||||
|
||||
# === CENTRALIZED BUILD ARGUMENTS ===
|
||||
ARG GRADLE_VERSION=9.4.1
|
||||
ARG JAVA_VERSION=25
|
||||
ARG GRADLE_VERSION=9.5.0
|
||||
ARG JAVA_VERSION=25.0.2
|
||||
ARG BUILD_DATE
|
||||
ARG VERSION=1.0.0-SNAPSHOT
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
package at.mocode.zns.importer
|
||||
|
||||
import at.mocode.core.domain.model.ReiterLizenz
|
||||
import at.mocode.masterdata.domain.repository.*
|
||||
import at.mocode.zns.parser.ZnsFunktionaerParser
|
||||
import at.mocode.zns.parser.ZnsPferdParser
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# ===================================================================
|
||||
|
||||
# === CENTRALIZED BUILD ARGUMENTS ===
|
||||
ARG GRADLE_VERSION=9.4.1
|
||||
ARG JAVA_VERSION=25
|
||||
ARG GRADLE_VERSION=9.5.0
|
||||
ARG JAVA_VERSION=25.0.2
|
||||
ARG BUILD_DATE
|
||||
ARG VERSION=1.0.0-SNAPSHOT
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# ===================================================================
|
||||
|
||||
# === CENTRALIZED BUILD ARGUMENTS ===
|
||||
ARG GRADLE_VERSION=9.4.1
|
||||
ARG JAVA_VERSION=25
|
||||
ARG GRADLE_VERSION=9.5.0
|
||||
ARG JAVA_VERSION=25.0.2
|
||||
ARG BUILD_DATE
|
||||
ARG VERSION=1.0.0-SNAPSHOT
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# ===================================================================
|
||||
|
||||
# === CENTRALIZED BUILD ARGUMENTS ===
|
||||
ARG GRADLE_VERSION=9.4.1
|
||||
ARG JAVA_VERSION=25
|
||||
ARG GRADLE_VERSION=9.5.0
|
||||
ARG JAVA_VERSION=25.0.2
|
||||
ARG BUILD_DATE
|
||||
ARG VERSION=1.0.0-SNAPSHOT
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
# ===================================================================
|
||||
|
||||
# === CENTRALIZED BUILD ARGUMENTS ===
|
||||
ARG GRADLE_VERSION=9.4.1
|
||||
ARG JAVA_VERSION=25
|
||||
ARG GRADLE_VERSION=9.5.0
|
||||
ARG JAVA_VERSION=25.0.2
|
||||
ARG BUILD_DATE
|
||||
ARG VERSION=1.0.0-SNAPSHOT
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# ===================================================================
|
||||
|
||||
# === CENTRALIZED BUILD ARGUMENTS ===
|
||||
ARG GRADLE_VERSION=9.4.1
|
||||
ARG JAVA_VERSION=25
|
||||
ARG GRADLE_VERSION=9.5.0
|
||||
ARG JAVA_VERSION=25.0.2
|
||||
ARG BUILD_DATE
|
||||
ARG VERSION=1.0.0-SNAPSHOT
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package at.mocode.masterdata.domain.model
|
||||
|
||||
import at.mocode.core.domain.model.DatenQuelleE
|
||||
import at.mocode.core.domain.model.ReiterLizenz
|
||||
import at.mocode.core.domain.model.ReiterLizenzKlasseE
|
||||
import at.mocode.core.domain.serialization.InstantSerializer
|
||||
import at.mocode.core.domain.serialization.LocalDateSerializer
|
||||
@@ -14,16 +15,6 @@ import kotlin.time.Clock
|
||||
import kotlin.time.Instant
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
@Serializable
|
||||
data class ReiterLizenz(
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val lizenzId: Uuid = Uuid.random(),
|
||||
val lizenzTyp: String, // STARTKARTE, REITERLIZENZ, FAHRLIZENZ
|
||||
val kuerzel: String,
|
||||
@Serializable(with = LocalDateSerializer::class)
|
||||
val gueltigBis: LocalDate? = null
|
||||
)
|
||||
|
||||
/**
|
||||
* Domain model representing a rider (Reiter) in the actor-context.
|
||||
*
|
||||
|
||||
@@ -4,10 +4,10 @@ package at.mocode.masterdata.infrastructure.persistence.reiter
|
||||
|
||||
import at.mocode.core.domain.model.DatenQuelleE
|
||||
import at.mocode.core.domain.model.ReiterAltersKlasseE
|
||||
import at.mocode.core.domain.model.ReiterLizenz
|
||||
import at.mocode.core.domain.model.ReiterLizenzKlasseE
|
||||
import at.mocode.core.utils.database.DatabaseFactory
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
import at.mocode.masterdata.domain.model.ReiterLizenz
|
||||
import at.mocode.masterdata.domain.repository.ReiterRepository
|
||||
import org.jetbrains.exposed.v1.core.ResultRow
|
||||
import org.jetbrains.exposed.v1.core.and
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# ===================================================================
|
||||
|
||||
# === CENTRALIZED BUILD ARGUMENTS ===
|
||||
ARG GRADLE_VERSION=9.4.1
|
||||
ARG JAVA_VERSION=25
|
||||
ARG GRADLE_VERSION=9.5.0
|
||||
ARG JAVA_VERSION=25.0.2
|
||||
ARG BUILD_DATE
|
||||
ARG VERSION=1.0.0-SNAPSHOT
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# ===================================================================
|
||||
|
||||
# === CENTRALIZED BUILD ARGUMENTS ===
|
||||
ARG GRADLE_VERSION=9.4.1
|
||||
ARG JAVA_VERSION=25
|
||||
ARG GRADLE_VERSION=9.5.0
|
||||
ARG JAVA_VERSION=25.0.2
|
||||
ARG BUILD_DATE
|
||||
ARG VERSION=1.0.0-SNAPSHOT
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# ===================================================================
|
||||
|
||||
# === CENTRALIZED BUILD ARGUMENTS ===
|
||||
ARG GRADLE_VERSION=9.4.1
|
||||
ARG JAVA_VERSION=25
|
||||
ARG GRADLE_VERSION=9.5.0
|
||||
ARG JAVA_VERSION=25.0.2
|
||||
ARG BUILD_DATE
|
||||
ARG VERSION=1.0.0-SNAPSHOT
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# ===================================================================
|
||||
|
||||
# === CENTRALIZED BUILD ARGUMENTS ===
|
||||
ARG GRADLE_VERSION=9.4.1
|
||||
ARG JAVA_VERSION=25
|
||||
ARG GRADLE_VERSION=9.5.0
|
||||
ARG JAVA_VERSION=25.0.2
|
||||
ARG BUILD_DATE
|
||||
ARG VERSION=1.0.0-SNAPSHOT
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# ===================================================================
|
||||
|
||||
# === CENTRALIZED BUILD ARGUMENTS ===
|
||||
ARG GRADLE_VERSION=9.4.1
|
||||
ARG JAVA_VERSION=25
|
||||
ARG GRADLE_VERSION=9.5.0
|
||||
ARG JAVA_VERSION=25.0.2
|
||||
ARG BUILD_DATE
|
||||
ARG VERSION=1.0.0-SNAPSHOT
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ plugins {
|
||||
// ### ALLPROJECTS CONFIGURATION ###
|
||||
// ##################################################################
|
||||
|
||||
val isWasmEnabled = findProperty("enableWasm")?.toString()?.toBoolean() ?: false
|
||||
val isWasmEnabled: Boolean = findProperty("enableWasm")?.toString()?.toBoolean() ?: false
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Zentrale Versionierung — liest version.properties (SemVer)
|
||||
@@ -47,10 +47,10 @@ val versionProps =
|
||||
java.util.Properties().also { props ->
|
||||
rootProject.file("version.properties").inputStream().use { props.load(it) }
|
||||
}
|
||||
val vMajor = versionProps.getProperty("VERSION_MAJOR", "1")
|
||||
val vMinor = versionProps.getProperty("VERSION_MINOR", "0")
|
||||
val vPatch = versionProps.getProperty("VERSION_PATCH", "0")
|
||||
val vQualifier = versionProps.getProperty("VERSION_QUALIFIER", "").trim()
|
||||
val vMajor: String = versionProps.getProperty("VERSION_MAJOR", "1")
|
||||
val vMinor: String = versionProps.getProperty("VERSION_MINOR", "0")
|
||||
val vPatch: String = versionProps.getProperty("VERSION_PATCH", "0")
|
||||
val vQualifier: String = versionProps.getProperty("VERSION_QUALIFIER", "").trim()
|
||||
val semVer = if (vQualifier.isBlank()) "$vMajor.$vMinor.$vPatch" else "$vMajor.$vMinor.$vPatch-$vQualifier"
|
||||
|
||||
allprojects {
|
||||
@@ -90,7 +90,7 @@ subprojects {
|
||||
jvmArgs("--add-opens=java.base/java.nio=ALL-UNNAMED")
|
||||
// Suppress ByteBuddy/Mockito dynamic agent loading warnings (Java 21+)
|
||||
jvmArgs("-XX:+EnableDynamicAgentLoading")
|
||||
// Increase test JVM memory with a stable configuration
|
||||
jvmArgs("--enable-native-access=ALL-UNNAMED")
|
||||
minHeapSize = "512m"
|
||||
maxHeapSize = "2g"
|
||||
// Parallel test execution for better performance
|
||||
@@ -113,7 +113,7 @@ subprojects {
|
||||
// (A) Source map configuration is handled via `gradle.properties` (global Kotlin/JS settings)
|
||||
// to avoid compiler-flag incompatibilities across toolchains.
|
||||
|
||||
// (B) Conditional Wasm/JS Target handling based on `enableWasm` property
|
||||
// (B) Conditional Wasm/JS Target handling based on the ` enableWasm ` property
|
||||
// This significantly reduces build times during Desktop development.
|
||||
// Flag is defined at the beginning of the script.
|
||||
|
||||
@@ -166,6 +166,7 @@ subprojects {
|
||||
jvmArgs("-Xshare:auto", "-Djdk.instrument.traceUsage=false")
|
||||
jvmArgs("--add-opens=java.base/java.nio=ALL-UNNAMED")
|
||||
jvmArgs("-XX:+EnableDynamicAgentLoading")
|
||||
jvmArgs("--enable-native-access=ALL-UNNAMED")
|
||||
maxHeapSize = "2g"
|
||||
dependsOn("testClasses")
|
||||
}
|
||||
@@ -175,20 +176,30 @@ subprojects {
|
||||
// Applies to all Exec-based tasks (covers Yarn/NPM invocations used by Kotlin JS plugin)
|
||||
tasks.withType<Exec>().configureEach {
|
||||
// Merge existing NODE_OPTIONS with --no-deprecation
|
||||
val current = (environment["NODE_OPTIONS"] as String?) ?: System.getenv("NODE_OPTIONS")
|
||||
val merged = if (current.isNullOrBlank()) "--no-deprecation" else "$current --no-deprecation"
|
||||
val current: String? = (environment["NODE_OPTIONS"] as String?) ?: System.getenv("NODE_OPTIONS")
|
||||
val merged: String = if (current.isNullOrBlank()) "--no-deprecation" else "$current --no-deprecation"
|
||||
environment("NODE_OPTIONS", merged)
|
||||
// Also set the legacy switch to silence warnings entirely
|
||||
environment("NODE_NO_WARNINGS", "1")
|
||||
// Set a Chrome binary path to avoid snap permission issues
|
||||
environment("CHROME_BIN", "/usr/bin/google-chrome-stable")
|
||||
environment("CHROMIUM_BIN", "/usr/bin/chromium")
|
||||
environment("PUPPETEER_EXECUTABLE_PATH", "/usr/bin/chromium")
|
||||
if (System.getProperty("os.name").contains("Linux", ignoreCase = true)) {
|
||||
environment("CHROME_BIN", "/usr/bin/google-chrome-stable")
|
||||
environment("CHROMIUM_BIN", "/usr/bin/chromium")
|
||||
environment("PUPPETEER_EXECUTABLE_PATH", "/usr/bin/chromium")
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// Detekt & Ktlint default setup
|
||||
// ------------------------------
|
||||
// PERFORMANCE: Deaktiviert standardmäßig in jedem Build, nur explizit ausführen
|
||||
tasks.withType<Detekt>().configureEach {
|
||||
enabled = project.hasProperty("runStaticAnalysis")
|
||||
}
|
||||
tasks.matching { it.name == "ktlintCheck" }.configureEach {
|
||||
enabled = project.hasProperty("runStaticAnalysis")
|
||||
}
|
||||
|
||||
plugins.withId("io.gitlab.arturbosch.detekt") {
|
||||
extensions.configure(DetektExtension::class.java) {
|
||||
buildUponDefaultConfig = true
|
||||
@@ -267,7 +278,6 @@ tasks.register("checkBundleBudget") {
|
||||
}
|
||||
|
||||
shells.forEach { shell ->
|
||||
val key = shell.path.trimStart(':').replace(':', '/') // or use a colon form for budgets keys below
|
||||
val colonKey = shell.path.trimStart(':').replace('/', ':').trim() // ensure ":a:b:c"
|
||||
// Budgets are keyed by a Gradle path with colons but without leading colon in config for readability
|
||||
val budgetKeyCandidates =
|
||||
@@ -362,8 +372,8 @@ tasks.register("staticAnalysis") {
|
||||
|
||||
// Apply Dokka (V2) automatically to Kotlin subprojects
|
||||
subprojects {
|
||||
plugins.withId("org.jetbrains.kotlin.jvm") { apply(plugin = "org.jetbrains.dokka") }
|
||||
plugins.withId("org.jetbrains.kotlin.multiplatform") { apply(plugin = "org.jetbrains.dokka") }
|
||||
plugins.withId("org.jetbrains.kotlin.jvm") { pluginManager.apply("org.jetbrains.dokka") }
|
||||
plugins.withId("org.jetbrains.kotlin.multiplatform") { pluginManager.apply("org.jetbrains.dokka") }
|
||||
}
|
||||
|
||||
// Aggregate tasks to build multi-module docs in Markdown (GFM) and HTML
|
||||
@@ -372,27 +382,36 @@ val dokkaAll =
|
||||
tasks.register("dokkaAll") {
|
||||
group = "documentation"
|
||||
description = "Builds Dokka (V2) for all modules and aggregates outputs under build/dokka/all"
|
||||
// Trigger Dokka generation in all subprojects that have the Dokka plugin
|
||||
dependsOn(
|
||||
// PERFORMANCE: Nur ausführen wenn explizit gefordert
|
||||
enabled = project.hasProperty("runDokka")
|
||||
|
||||
// Capture required values for configuration cache
|
||||
val rootBuildDir = layout.buildDirectory.get().asFile
|
||||
val subprojectData =
|
||||
subprojects
|
||||
.filter { it.plugins.hasPlugin("org.jetbrains.dokka") }
|
||||
.map { "${it.path}:dokkaGenerate" },
|
||||
)
|
||||
.map { p ->
|
||||
Triple(p.path, p.name, p.layout.buildDirectory.get().asFile)
|
||||
}
|
||||
|
||||
// Trigger Dokka generation in all subprojects that have the Dokka plugin
|
||||
dependsOn(subprojectData.map { "${it.first}:dokkaGenerate" })
|
||||
|
||||
doLast {
|
||||
val dest = layout.buildDirectory.dir("dokka/all").get().asFile
|
||||
val dest = File(rootBuildDir, "dokka/all")
|
||||
if (dest.exists()) dest.deleteRecursively()
|
||||
dest.mkdirs()
|
||||
|
||||
val modules = mutableListOf<Pair<String, String>>()
|
||||
|
||||
subprojects.filter { it.plugins.hasPlugin("org.jetbrains.dokka") }.forEach { p ->
|
||||
subprojectData.forEach { (pPath, pName, pBuildDir) ->
|
||||
// Dokka V2 writes into build/dokka/html
|
||||
val outHtml = p.layout.buildDirectory.dir("dokka/html").get().asFile
|
||||
val outHtml = File(pBuildDir, "dokka/html")
|
||||
if (outHtml.exists()) {
|
||||
val modulePath = p.path.trimStart(':').replace(':', '/')
|
||||
val modulePath = pPath.trimStart(':').replace(':', '/')
|
||||
val targetDir = File(dest, modulePath)
|
||||
outHtml.copyRecursively(targetDir, overwrite = true)
|
||||
modules.add(p.name to modulePath)
|
||||
modules.add(pName to modulePath)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,17 +470,19 @@ tasks.register("docs") {
|
||||
// Apply Node warning suppression on root project Exec tasks as well
|
||||
// Ensures aggregated Kotlin/JS tasks created at root (e.g., kotlinNpmInstall) inherit the env
|
||||
tasks.withType<Exec>().configureEach {
|
||||
val current = (environment["NODE_OPTIONS"] as String?) ?: System.getenv("NODE_OPTIONS")
|
||||
val merged = if (current.isNullOrBlank()) "--no-deprecation" else "$current --no-deprecation"
|
||||
val current: String? = (environment["NODE_OPTIONS"] as String?) ?: System.getenv("NODE_OPTIONS")
|
||||
val merged: String = if (current.isNullOrBlank()) "--no-deprecation" else "$current --no-deprecation"
|
||||
environment("NODE_OPTIONS", merged)
|
||||
environment("NODE_NO_WARNINGS", "1")
|
||||
// Set a Chrome binary path to avoid snap permission issues
|
||||
environment("CHROME_BIN", "/usr/bin/google-chrome-stable")
|
||||
environment("CHROMIUM_BIN", "/usr/bin/chromium")
|
||||
environment("PUPPETEER_EXECUTABLE_PATH", "/usr/bin/chromium")
|
||||
if (System.getProperty("os.name").contains("Linux", ignoreCase = true)) {
|
||||
environment("CHROME_BIN", "/usr/bin/google-chrome-stable")
|
||||
environment("CHROMIUM_BIN", "/usr/bin/chromium")
|
||||
environment("PUPPETEER_EXECUTABLE_PATH", "/usr/bin/chromium")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.wrapper {
|
||||
gradleVersion = "9.4.1"
|
||||
gradleVersion = "9.5.0"
|
||||
distributionType = Wrapper.DistributionType.BIN
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
include required("/stdlib/jdk/21/amazon.conf")
|
||||
include required("https://raw.githubusercontent.com/hydraulic-software/conveyor/master/configs/jvm/extract-native-libraries.conf")
|
||||
app {
|
||||
display-name = "Meldestelle"
|
||||
rdns-name = "at.mocode.meldestelle"
|
||||
vendor = "mo-code.at"
|
||||
contact-email = "support@mo-code.at"
|
||||
version = "1.0.1"
|
||||
description = "ÖTO-konforme Turnier-Meldestelle – Profi Desktop App"
|
||||
|
||||
# Ziel-Plattformen: Windows und Linux
|
||||
machines = [ windows.amd64, linux.amd64.glibc ]
|
||||
|
||||
site.base-url = "localhost"
|
||||
|
||||
# Icons werden im Ordner gesucht
|
||||
icons = "frontend/shells/meldestelle-desktop/src/jvmMain/resources/icon.png"
|
||||
|
||||
jvm {
|
||||
gui {
|
||||
main-class = "at.mocode.frontend.shell.desktop.MainKt"
|
||||
}
|
||||
|
||||
jvm-options = [
|
||||
"-Xms256m",
|
||||
"-Xmx1024m",
|
||||
"-Dfile.encoding=UTF-8",
|
||||
"--enable-native-access=ALL-UNNAMED"
|
||||
]
|
||||
}
|
||||
|
||||
# JARs aus dem Gradle-Build
|
||||
inputs += "frontend/shells/meldestelle-desktop/build/libs/*.jar"
|
||||
|
||||
windows {
|
||||
upgrade-uuid = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
|
||||
menu-group = "Meldestelle"
|
||||
desktop-shortcut = true
|
||||
}
|
||||
|
||||
linux {
|
||||
debian.control.depends = "libasound2, libgl1-mesa-glx, libx11-6"
|
||||
}
|
||||
}
|
||||
|
||||
conveyor.compatibility-level = 22
|
||||
@@ -0,0 +1,19 @@
|
||||
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||
|
||||
package at.mocode.core.domain.model
|
||||
|
||||
import at.mocode.core.domain.serialization.LocalDateSerializer
|
||||
import at.mocode.core.domain.serialization.UuidSerializer
|
||||
import kotlinx.datetime.LocalDate
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
@Serializable
|
||||
data class ReiterLizenz(
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val lizenzId: Uuid = Uuid.random(),
|
||||
val lizenzTyp: String, // STARTKARTE, REITERLIZENZ, FAHRLIZENZ
|
||||
val kuerzel: String,
|
||||
@Serializable(with = LocalDateSerializer::class)
|
||||
val gueltigBis: LocalDate? = null
|
||||
)
|
||||
@@ -1,10 +1,10 @@
|
||||
package at.mocode.zns.parser
|
||||
|
||||
import at.mocode.core.domain.model.DatenQuelleE
|
||||
import at.mocode.core.domain.model.ReiterLizenz
|
||||
import at.mocode.core.domain.model.ReiterLizenzKlasseE
|
||||
import at.mocode.core.utils.parser.FixedWidthLineReader
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
import at.mocode.masterdata.domain.model.ReiterLizenz
|
||||
import kotlin.uuid.ExperimentalUuidApi
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ services:
|
||||
context: .
|
||||
dockerfile: backend/infrastructure/gateway/Dockerfile
|
||||
args:
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.4.1}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25}"
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.5.0}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25.0.2}"
|
||||
VERSION: "${DOCKER_VERSION:-1.0.0-SNAPSHOT}"
|
||||
BUILD_DATE: "${DOCKER_BUILD_DATE}"
|
||||
labels:
|
||||
@@ -102,8 +102,8 @@ services:
|
||||
context: .
|
||||
dockerfile: backend/services/ping/Dockerfile
|
||||
args:
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.4.1}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25}"
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.5.0}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25.0.2}"
|
||||
VERSION: "${DOCKER_VERSION:-1.0.0-SNAPSHOT}"
|
||||
BUILD_DATE: "${DOCKER_BUILD_DATE}"
|
||||
labels:
|
||||
@@ -179,8 +179,8 @@ services:
|
||||
context: .
|
||||
dockerfile: backend/services/masterdata/Dockerfile
|
||||
args:
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.4.1}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25}"
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.5.0}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25.0.2}"
|
||||
VERSION: "${DOCKER_VERSION:-1.0.0-SNAPSHOT}"
|
||||
BUILD_DATE: "${DOCKER_BUILD_DATE}"
|
||||
labels:
|
||||
@@ -256,8 +256,8 @@ services:
|
||||
context: .
|
||||
dockerfile: backend/services/events/Dockerfile
|
||||
args:
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.4.1}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25}"
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.5.0}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25.0.2}"
|
||||
VERSION: "${DOCKER_VERSION:-1.0.0-SNAPSHOT}"
|
||||
BUILD_DATE: "${DOCKER_BUILD_DATE}"
|
||||
labels:
|
||||
@@ -331,8 +331,8 @@ services:
|
||||
context: .
|
||||
dockerfile: backend/services/zns-import/Dockerfile
|
||||
args:
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.4.1}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25}"
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.5.0}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25.0.2}"
|
||||
VERSION: "${DOCKER_VERSION:-1.0.0-SNAPSHOT}"
|
||||
BUILD_DATE: "${DOCKER_BUILD_DATE}"
|
||||
labels:
|
||||
@@ -407,8 +407,8 @@ services:
|
||||
context: .
|
||||
dockerfile: backend/services/results/results-service/Dockerfile
|
||||
args:
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.4.1}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25}"
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.5.0}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25.0.2}"
|
||||
VERSION: "${DOCKER_VERSION:-1.0.0-SNAPSHOT}"
|
||||
BUILD_DATE: "${DOCKER_BUILD_DATE}"
|
||||
labels:
|
||||
@@ -482,8 +482,8 @@ services:
|
||||
context: .
|
||||
dockerfile: backend/services/billing/billing-service/Dockerfile
|
||||
args:
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.4.1}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25}"
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.5.0}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25.0.2}"
|
||||
VERSION: "${DOCKER_VERSION:-1.0.0-SNAPSHOT}"
|
||||
BUILD_DATE: "${DOCKER_BUILD_DATE}"
|
||||
labels:
|
||||
@@ -555,8 +555,8 @@ services:
|
||||
context: .
|
||||
dockerfile: backend/services/mail/Dockerfile
|
||||
args:
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.4.1}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25}"
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.5.0}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25.0.2}"
|
||||
VERSION: "${DOCKER_VERSION:-1.0.0-SNAPSHOT}"
|
||||
BUILD_DATE: "${DOCKER_BUILD_DATE}"
|
||||
labels:
|
||||
@@ -627,8 +627,8 @@ services:
|
||||
context: .
|
||||
dockerfile: backend/services/scheduling/scheduling-service/Dockerfile
|
||||
args:
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.4.1}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25}"
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.5.0}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25.0.2}"
|
||||
VERSION: "${DOCKER_VERSION:-1.0.0-SNAPSHOT}"
|
||||
BUILD_DATE: "${DOCKER_BUILD_DATE}"
|
||||
labels:
|
||||
@@ -700,8 +700,8 @@ services:
|
||||
context: .
|
||||
dockerfile: backend/services/series/series-service/Dockerfile
|
||||
args:
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.4.1}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25}"
|
||||
GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.5.0}"
|
||||
JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25.0.2}"
|
||||
VERSION: "${DOCKER_VERSION:-1.0.0-SNAPSHOT}"
|
||||
BUILD_DATE: "${DOCKER_BUILD_DATE}"
|
||||
labels:
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
name: "${PROJECT_NAME:-meldestelle}"
|
||||
|
||||
services:
|
||||
# ==========================================
|
||||
# 3. FRONTEND (UI)
|
||||
# ==========================================
|
||||
# services:
|
||||
# # ==========================================
|
||||
# # 3. FRONTEND (UI)
|
||||
# # ==========================================
|
||||
|
||||
# --- WEB-APP ---
|
||||
# web-app:
|
||||
|
||||
@@ -3,7 +3,7 @@ name: "${PROJECT_NAME:-meldestelle}"
|
||||
include:
|
||||
- dc-infra.yaml
|
||||
- dc-backend.yaml
|
||||
- dc-gui.yaml
|
||||
#- dc-gui.yaml
|
||||
- dc-ops.yaml
|
||||
|
||||
# Globale Definitionen, falls nötig (meistens reichen die in den Teil-Dateien,
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
---
|
||||
type: Reference
|
||||
status: ACTIVE
|
||||
owner: Lead Architect
|
||||
last_update: 2026-03-15
|
||||
---
|
||||
# Frontend-Architektur & Modularisierungsstrategie
|
||||
|
||||
**Status:** ENTWURF
|
||||
**Zuletzt aktualisiert:** 2026-01-19
|
||||
**Kontext:** Migration zu Clean Architecture & Feature-Modulen
|
||||
|
||||
---
|
||||
|
||||
## 1. Übersicht
|
||||
Die Frontend-Architektur von **Meldestelle** basiert auf **Kotlin Multiplatform (KMP)** mit **Compose Multiplatform** für die Benutzeroberfläche. Wir folgen einem strikten **Clean Architecture**-Ansatz, um Testbarkeit, Skalierbarkeit und Trennung der Zuständigkeiten sicherzustellen.
|
||||
|
||||
## 2. Modulstruktur
|
||||
Das Projekt ist in folgende Schichten unterteilt:
|
||||
|
||||
### 2.1 Core-Module (`frontend/core`)
|
||||
Wiederverwendbare Komponenten, die unabhängig von spezifischen Geschäftsfunktionen sind.
|
||||
* `core-network`: Zentrale HTTP-Client-Konfiguration (Auth, Logging, ContentNegotiation).
|
||||
* `core-sync`: Generische Synchronisierungslogik (`SyncManager`, `SyncableRepository`).
|
||||
* `core-ui`: Gemeinsame UI-Komponenten und Design-System.
|
||||
|
||||
### 2.2 Feature-Module (`frontend/features`)
|
||||
Jede Geschäftsdomäne (z.B. `ping`, `auth`, `events`) liegt in ihrem eigenen Modul.
|
||||
Ein Feature-Modul MUSS die **Clean Architecture** Paketstruktur einhalten:
|
||||
|
||||
* `at.mocode.{feature}.feature.domain`
|
||||
* **Entitäten:** Reine Datenklassen.
|
||||
* **Interfaces:** Repository-Interfaces, Service-Interfaces.
|
||||
* **Use Cases:** Geschäftslogik (optional, für komplexe Logik).
|
||||
* `at.mocode.{feature}.feature.data`
|
||||
* **Implementierungen:** Repository-Implementierungen, API-Clients.
|
||||
* **DTOs:** Data Transfer Objects (wenn von Domain-Entitäten abweichend).
|
||||
* `at.mocode.{feature}.feature.presentation`
|
||||
* **ViewModels:** Zustandsverwaltung.
|
||||
* **Screens:** Composable-Funktionen.
|
||||
* `at.mocode.{feature}.feature.di`
|
||||
* **Koin-Modul:** Konfiguration der Dependency Injection.
|
||||
|
||||
### 2.3 Shells (`frontend/shells`)
|
||||
Anwendungs-Einstiegspunkte, die alles zusammenführen.
|
||||
* `meldestelle-portal`: Die Haupt-Web-/Desktop-Anwendung.
|
||||
|
||||
## 3. Migrationsstrategie (Übergangsphase)
|
||||
Wir migrieren aktuell von einer monolithischen `clients`-Paketstruktur zu modularen Feature-Modulen.
|
||||
|
||||
**Regeln für die Migration:**
|
||||
1. **Neue Features:** Müssen direkt in `frontend/features/{name}` unter Verwendung der Clean Architecture-Struktur implementiert werden.
|
||||
2. **Bestehende Features:** Werden schrittweise migriert.
|
||||
3. **Koexistenz:** Während des Übergangs ist Legacy-Code in `clients/` erlaubt, aber als veraltet markiert.
|
||||
4. **Dependency Injection:** Legacy-Code muss die neuen Koin-Module verwenden, sofern verfügbar.
|
||||
5. **Keine Ghost-Klassen:** Klassen nicht duplizieren. Wenn eine Klasse in ein Feature-Modul verschoben wird, muss die alte in `clients/` gelöscht werden.
|
||||
|
||||
## 4. Wichtige Entscheidungen (ADRs)
|
||||
|
||||
### ADR-001: Entkopplung der Sync-Logik
|
||||
* **Entscheidung:** ViewModels dürfen nicht direkt vom `SyncManager` abhängen.
|
||||
* **Begründung:** Um einfacheres Testen zu ermöglichen und die Komplexität des generischen Sync-Mechanismus zu verbergen.
|
||||
* **Umsetzung:** Ein Domain-Service-Interface (z.B. `PingSyncService`) einführen, das den `SyncManager`-Aufruf kapselt.
|
||||
|
||||
### ADR-002: Feature-Modul-Isolation
|
||||
* **Entscheidung:** Feature-Module sollten nach Möglichkeit nicht direkt voneinander abhängen.
|
||||
* **Kommunikation:** Gemeinsame Core-Module oder lose Kopplung über Interfaces/Events verwenden, wenn modulübergreifende Kommunikation nötig ist.
|
||||
|
||||
---
|
||||
|
||||
**Freigegeben von:** Lead Architect
|
||||
@@ -1,51 +0,0 @@
|
||||
---
|
||||
type: Reference
|
||||
status: ACTIVE
|
||||
owner: Lead Architect
|
||||
---
|
||||
# Open-Source-Konformität & Lizenz-Checkliste
|
||||
|
||||
Dieses Dokument dient der Überwachung und Sicherstellung der Open-Source-Konformität des Projekts **Meldestelle**. Es wird vom Lead Architect gepflegt.
|
||||
|
||||
## Status der Kern-Komponenten (Stand: Januar 2026)
|
||||
|
||||
| Komponente | Lizenz | Status | Risiko | Maßnahme / Kommentar |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| **Kotlin / JVM** | Apache 2.0 / GPLv2+CE | ✅ OK | Sehr gering | Standard-Stack. |
|
||||
| **Spring Boot / Cloud** | Apache 2.0 | ✅ OK | Sehr gering | |
|
||||
| **PostgreSQL** | PostgreSQL (BSD-like) | ✅ OK | Sehr gering | |
|
||||
| **Redis** | **RSALv2 / SSPL** | ⚠️ KRITISCH | Hoch | **Umstieg auf Valkey (BSD) geplant.** |
|
||||
| **Consul** | **BSL 1.1** | ⚠️ BEOBACHTEN | Mittel | Lizenzänderung durch HashiCorp. Für interne Nutzung aktuell unkritisch. |
|
||||
| **Keycloak** | Apache 2.0 | ✅ OK | Gering | |
|
||||
| **SQLDelight** | Apache 2.0 | ✅ OK | Sehr gering | |
|
||||
| **Redisson** | Apache 2.0 (Core) | ✅ OK | Gering | Sicherstellen, dass keine PRO-Features genutzt werden. |
|
||||
|
||||
---
|
||||
|
||||
## Checkliste für neue Abhängigkeiten
|
||||
|
||||
Bevor eine neue Bibliothek oder Infrastruktur-Komponente hinzugefügt wird, muss sie folgende Kriterien erfüllen:
|
||||
|
||||
1. **Lizenz-Typ:**
|
||||
* Bevorzugt: Apache 2.0, MIT, BSD (3-Clause).
|
||||
* Akzeptabel: MPL 2.0.
|
||||
* Einzelfallprüfung: LGPL (nur als dynamische Bibliothek).
|
||||
* **Verboten:** AGPL, SSPL, RSAL, BSL (sofern nicht explizit vom Architect freigegeben).
|
||||
|
||||
2. **Community & Governance:**
|
||||
* Wird das Projekt von einer neutralen Foundation (Apache, CNCF, Linux Foundation) verwaltet?
|
||||
* Gibt es eine "Single Vendor" Abhängigkeit (Risiko einer plötzlichen Lizenzänderung)?
|
||||
|
||||
3. **Transitive Abhängigkeiten:**
|
||||
* Bringt die Bibliothek "versteckte" Copyleft-Lizenzen mit? (Check via Gradle License Plugin).
|
||||
|
||||
---
|
||||
|
||||
## TODOs & Strategische Entscheidungen
|
||||
|
||||
- [ ] **Migration Redis -> Valkey:** Umstellung der Docker-Images und Test der Kompatibilität.
|
||||
- [ ] **Consul Review:** Jährliche Prüfung der BSL-Auswirkungen auf unser Deployment-Modell.
|
||||
- [ ] **Automatisierung:** Integration eines License-Check-Plugins in den CI-Build (z.B. `com.github.jk1.dependency-license-report`).
|
||||
|
||||
---
|
||||
*Dieses Dokument ist Teil der "Docs-as-Code" Strategie und muss bei jeder Änderung am Tech-Stack aktualisiert werden.*
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
type: Reference
|
||||
status: ACTIVE
|
||||
owner: Lead Architect
|
||||
---
|
||||
|
||||
# Open-Source-Konformität & Lizenz-Checkliste
|
||||
|
||||
Dieses Dokument dient der Überwachung und Sicherstellung der Open-Source-Konformität des Projekts **Meldestelle**. Es
|
||||
wird vom Lead Architect gepflegt.
|
||||
|
||||
## Status der Kern-Komponenten (Stand: Januar 2026)
|
||||
|
||||
| Komponente | Lizenz | Status | Risiko | Maßnahme / Kommentar |
|
||||
|:------------------------|:----------------------|:--------------|:------------|:------------------------------------------------------------------------|
|
||||
| **Kotlin / JVM** | Apache 2.0 / GPLv2+CE | ✅ OK | Sehr gering | Standard-Stack. |
|
||||
| **Spring Boot / Cloud** | Apache 2.0 | ✅ OK | Sehr gering | |
|
||||
| **PostgreSQL** | PostgreSQL (BSD-like) | ✅ OK | Sehr gering | |
|
||||
| **Redis** | **RSALv2 / SSPL** | ⚠️ KRITISCH | Hoch | **Umstieg auf Valkey (BSD) geplant.** |
|
||||
| **Consul** | **BSL 1.1** | ⚠️ BEOBACHTEN | Mittel | Lizenzänderung durch HashiCorp. Für interne Nutzung aktuell unkritisch. |
|
||||
| **Keycloak** | Apache 2.0 | ✅ OK | Gering | |
|
||||
| **SQLDelight** | Apache 2.0 | ✅ OK | Sehr gering | |
|
||||
| **Redisson** | Apache 2.0 (Core) | ✅ OK | Gering | Sicherstellen, dass keine PRO-Features genutzt werden. |
|
||||
|
||||
---
|
||||
|
||||
## Checkliste für neue Abhängigkeiten
|
||||
|
||||
Bevor eine neue Bibliothek oder Infrastruktur-Komponente hinzugefügt wird, muss sie folgende Kriterien erfüllen:
|
||||
|
||||
1. **Lizenz-Typ:**
|
||||
* Bevorzugt: Apache 2.0, MIT, BSD (3-Clause).
|
||||
* Akzeptabel: MPL 2.0.
|
||||
* Einzelfallprüfung: LGPL (nur als dynamische Bibliothek).
|
||||
* **Verboten:** AGPL, SSPL, RSAL, BSL (sofern nicht explizit vom Architect freigegeben).
|
||||
|
||||
2. **Community & Governance:**
|
||||
* Wird das Projekt von einer neutralen Foundation (Apache, CNCF, Linux Foundation) verwaltet?
|
||||
* Gibt es eine "Single Vendor" Abhängigkeit (Risiko einer plötzlichen Lizenzänderung)?
|
||||
|
||||
3. **Transitive Abhängigkeiten:**
|
||||
* Bringt die Bibliothek "versteckte" Copyleft-Lizenzen mit? (Check via Gradle License Plugin).
|
||||
|
||||
---
|
||||
|
||||
## TODOs & Strategische Entscheidungen
|
||||
|
||||
- [ ] **Migration Redis -> Valkey:** Umstellung der Docker-Images und Test der Kompatibilität.
|
||||
- [ ] **Consul Review:** Jährliche Prüfung der BSL-Auswirkungen auf unser Deployment-Modell.
|
||||
- [ ] **Automatisierung:** Integration eines License-Check-Plugins in den CI-Build (z.B.
|
||||
`com.github.jk1.dependency-license-report`).
|
||||
|
||||
---
|
||||
*Dieses Dokument ist Teil der "Docs-as-Code" Strategie und muss bei jeder Änderung am Tech-Stack aktualisiert werden.*
|
||||
@@ -3,6 +3,7 @@
|
||||
Status: April 2026
|
||||
|
||||
## ✅ Abgeschlossene Migrationen (Feature-Module)
|
||||
|
||||
- `billing-feature`: `at.mocode.frontend.features.billing` (KMP)
|
||||
- `verein-feature`: `at.mocode.frontend.features.verein` (KMP)
|
||||
- `nennung-feature`: `at.mocode.frontend.features.nennung` (KMP)
|
||||
@@ -13,11 +14,14 @@ Status: April 2026
|
||||
- `ping-feature`: `at.mocode.ping.feature` (muss noch auf `at.mocode.frontend.features.ping` vereinheitlicht werden)
|
||||
|
||||
## 🚧 Ausstehende Migrationen (von `at.mocode.desktop.v2` zu Features)
|
||||
Die folgenden Komponenten in `meldestelle-desktop/src/jvmMain/kotlin/at/mocode/desktop/v2/` basieren noch auf `StoreV2` (In-Memory Mock) und sollten in KMP-Module überführt werden:
|
||||
|
||||
Die folgenden Komponenten in `meldestelle-desktop/src/jvmMain/kotlin/at/mocode/desktop/v2/` basieren noch auf
|
||||
`StoreV2` (In-Memory Mock) und sollten in KMP-Module überführt werden:
|
||||
|
||||
1. **Onboarding**: `OnboardingScreen.kt` -> Design-System Integration erfolgt, KMP-Modul folgt.
|
||||
|
||||
## 🧹 Architektur-Cleanup
|
||||
|
||||
- [ ] `at.mocode.desktop.v2.StoreV2` entfernen, sobald alle Screens auf ViewModels und API-Repositories umgestellt sind.
|
||||
- [ ] `at.mocode.desktop.v2.TurnierStoreV2` konsolidieren mit dem `turnier-feature`.
|
||||
- [ ] Paketnamen vereinheitlichen: `at.mocode.ping.feature` -> `at.mocode.frontend.features.ping`.
|
||||
@@ -26,6 +30,7 @@ Die folgenden Komponenten in `meldestelle-desktop/src/jvmMain/kotlin/at/mocode/d
|
||||
- [ ] `DesktopMainLayout.kt`: Die `when`-Zweige für `v2` Screens aufräumen, sobald die Module bereit sind.
|
||||
|
||||
## ✅ Abgeschlossen am 11.04.2026
|
||||
|
||||
- Migration `pferde-feature`, `reiter-feature`, `funktionaer-feature`, `veranstalter-feature`.
|
||||
- Integration in `DesktopMainLayout` und `AppScreen`.
|
||||
- Bereinigung der Repository-Pakete.
|
||||
@@ -9,7 +9,9 @@ last_update: 2026-04-03
|
||||
|
||||
## Ziel und Rahmen
|
||||
|
||||
Dieses Dokument definiert das Synchronisations-Konzept zwischen der Compose Desktop App (Meldestelle-Zentrale) und dem Backend in einem Offline-First Szenario. Es baut auf ADR-0021 (Tenant-Isolation) und ADR-0022 (LAN-Sync mit Lamport-Uhren) auf und erweitert sie um die WAN/Backend-Synchronisation.
|
||||
Dieses Dokument definiert das Synchronisations-Konzept zwischen der Compose Desktop App (Meldestelle-Zentrale) und dem
|
||||
Backend in einem Offline-First Szenario. Es baut auf ADR-0021 (Tenant-Isolation) und ADR-0022 (LAN-Sync mit
|
||||
Lamport-Uhren) auf und erweitert sie um die WAN/Backend-Synchronisation.
|
||||
|
||||
Nicht-Ziele: Cloud-Realtime für Endnutzer, kollaboratives Editieren außerhalb des Veranstaltungsbetriebs.
|
||||
|
||||
@@ -18,32 +20,38 @@ Nicht-Ziele: Cloud-Realtime für Endnutzer, kollaboratives Editieren außerhalb
|
||||
1. Offline-First: Die Desktop-App ist voll funktionsfähig ohne Netzwerk; Synchronisation erfolgt opportunistisch.
|
||||
2. Event-isoliert: Pro Veranstaltung eigener Datenraum (gemäß ADR-0021). Keine Vermischung von Events.
|
||||
3. Einheitliches Änderungsmodell: Wiederverwendung des `SyncEvent`-Logs (ADR-0022) für Desktop↔Backend.
|
||||
4. Domänen-Mastership: Klare Schreibhoheiten reduzieren Konflikte, fachliche Regeln haben Vorrang vor rein technischen Timestamps.
|
||||
4. Domänen-Mastership: Klare Schreibhoheiten reduzieren Konflikte, fachliche Regeln haben Vorrang vor rein technischen
|
||||
Timestamps.
|
||||
5. Deterministische Konfliktauflösung: Lamport-Uhren + Regel-Matrix; keine Abhängigkeit von Systemuhren.
|
||||
|
||||
## Topologie & Rollen
|
||||
|
||||
- Backend (Zentrale Plattform):
|
||||
- Master für: Stammdaten (Reiter, Pferde, Vereine, Funktionäre), Identität/Rollen, Gebührenkataloge, globale Referenzen.
|
||||
- Master für: Stammdaten (Reiter, Pferde, Vereine, Funktionäre), Identität/Rollen, Gebührenkataloge, globale
|
||||
Referenzen.
|
||||
- Aggregations-/Archiv-Quelle nach Veranstaltungsende (finale Ergebnisse, Abrechnungen).
|
||||
- Desktop (Meldestelle-Zentrale):
|
||||
- Master während der Veranstaltung für: Nennungen (operativ), Startreihenfolgen, Startlisten-Status, Ergebnisse/Protokolle (falls Richter nicht direkt am Backend), Kassa-Operationen vor Ort.
|
||||
- Hält lokales `SyncEvent`-Log + Snapshots (vgl. ADR-0022) und synchronisiert mit Backend, sobald Konnektivität besteht.
|
||||
- Master während der Veranstaltung für: Nennungen (operativ), Startreihenfolgen, Startlisten-Status,
|
||||
Ergebnisse/Protokolle (falls Richter nicht direkt am Backend), Kassa-Operationen vor Ort.
|
||||
- Hält lokales `SyncEvent`-Log + Snapshots (vgl. ADR-0022) und synchronisiert mit Backend, sobald Konnektivität
|
||||
besteht.
|
||||
|
||||
Hinweis Mehrfach-Desktops: Genau eine „Zentrale“ pro Veranstaltung besitzt Schreibhoheit (Konfig-Flag `isEventAuthority=true`). Weitere Geräte sind Replikate/Clients.
|
||||
Hinweis Mehrfach-Desktops: Genau eine „Zentrale“ pro Veranstaltung besitzt Schreibhoheit (Konfig-Flag
|
||||
`isEventAuthority=true`). Weitere Geräte sind Replikate/Clients.
|
||||
|
||||
## Datenkategorien & Mastership
|
||||
|
||||
| Kategorie | Master | Desktop Rechte | Backend Rechte |
|
||||
|--------------------------|----------------|--------------------------------|-----------------------------------|
|
||||
| Stammdaten (Actor) | Backend | Lesen, lokal „provisional“ anlegen (Temp-ID) | Vollzugriff, ID-Zuteilung, Merge |
|
||||
| Veranstaltungs-Stammdaten| Backend | Lesen | Vollzugriff |
|
||||
| Nennungen operativ | Desktop | Vollzugriff | Lesen, Import nach Sync |
|
||||
| Startreihenfolge/Status | Desktop | Vollzugriff | Lesen, Import nach Sync |
|
||||
| Bewertungen/Ergebnisse | Desktop/Richter| Vollzugriff (Eventzeitraum) | Lesen, Publikation/Archiv |
|
||||
| Kassa/Finanzen vor Ort | Desktop | Vollzugriff | Lesen, Abgleich Summen |
|
||||
| Kategorie | Master | Desktop Rechte | Backend Rechte |
|
||||
|---------------------------|-----------------|----------------------------------------------|----------------------------------|
|
||||
| Stammdaten (Actor) | Backend | Lesen, lokal „provisional“ anlegen (Temp-ID) | Vollzugriff, ID-Zuteilung, Merge |
|
||||
| Veranstaltungs-Stammdaten | Backend | Lesen | Vollzugriff |
|
||||
| Nennungen operativ | Desktop | Vollzugriff | Lesen, Import nach Sync |
|
||||
| Startreihenfolge/Status | Desktop | Vollzugriff | Lesen, Import nach Sync |
|
||||
| Bewertungen/Ergebnisse | Desktop/Richter | Vollzugriff (Eventzeitraum) | Lesen, Publikation/Archiv |
|
||||
| Kassa/Finanzen vor Ort | Desktop | Vollzugriff | Lesen, Abgleich Summen |
|
||||
|
||||
Konflikte über Kategoriegrenzen werden durch Mastership-Regeln verhindert; verbleibende Konflikte werden per Regel-Matrix gelöst.
|
||||
Konflikte über Kategoriegrenzen werden durch Mastership-Regeln verhindert; verbleibende Konflikte werden per
|
||||
Regel-Matrix gelöst.
|
||||
|
||||
## Änderungsmodell (Wiederverwendung `SyncEvent`)
|
||||
|
||||
@@ -71,11 +79,13 @@ data class SyncEvent(
|
||||
## Lamport-Uhren & Vector-Clock (Optional)
|
||||
|
||||
- Primär: Lamport-Uhren wie ADR-0022. Gleichstand → lexikografisch größere `originNodeId` gewinnt (Determinismus).
|
||||
- Optional für feingranulare Erkennung: Per-Aggregat Vector-Clock (`Map<nodeId, lamport>`) zur Diagnose; Entscheidungsgrundlage bleibt Lamport + Fachregeln.
|
||||
- Optional für feingranulare Erkennung: Per-Aggregat Vector-Clock (`Map<nodeId, lamport>`) zur Diagnose;
|
||||
Entscheidungsgrundlage bleibt Lamport + Fachregeln.
|
||||
|
||||
## Sync-Protokoll Desktop ↔ Backend (HTTPS)
|
||||
|
||||
Transport: HTTPS (HTTP/2), JSON oder Protobuf, idempotente Endpunkte. Auth: mTLS zwischen Desktop und Backend ODER OAuth2 Client Credentials + Signatur der Batch-Payload.
|
||||
Transport: HTTPS (HTTP/2), JSON oder Protobuf, idempotente Endpunkte. Auth: mTLS zwischen Desktop und Backend ODER
|
||||
OAuth2 Client Credentials + Signatur der Batch-Payload.
|
||||
|
||||
Empfohlene Endpunkte (pro `eventId`):
|
||||
|
||||
@@ -94,42 +104,55 @@ Idempotenz: Jeder `SyncEvent` wird durch `(eventId, originNodeId, sequenceNumber
|
||||
## Konfliktauflösung
|
||||
|
||||
1) Strukturkonflikte (gleiches Aggregat, konkurrierende Events):
|
||||
- Wenn eine Seite nicht Master ist → Event wird angenommen, aber als `PENDING_REVIEW` markiert; fachliche Entscheidung erforderlich (Backend-UI oder Desktop-Review-Queue).
|
||||
|
||||
- Wenn eine Seite nicht Master ist → Event wird angenommen, aber als `PENDING_REVIEW` markiert; fachliche Entscheidung
|
||||
erforderlich (Backend-UI oder Desktop-Review-Queue).
|
||||
- Beide Master (Sonderfälle, z. B. Ergebnisse während parallelem Backend-Fix):
|
||||
- Lamport höher gewinnt.
|
||||
- Gleichstand → `originNodeId`-Tiebreaker.
|
||||
- Zusätzlich fachliche Heuristik optional: „Korrektur-Events“ (z. B. `ErgebnisKorrigiert`) schlagen normale `ErgebnisErfasst` bei gleichem Lamport.
|
||||
- Zusätzlich fachliche Heuristik optional: „Korrektur-Events“ (z. B. `ErgebnisKorrigiert`) schlagen normale
|
||||
`ErgebnisErfasst` bei gleichem Lamport.
|
||||
|
||||
2) Identitätskonflikte (provisionale Stammdaten):
|
||||
|
||||
- Desktop darf temporäre Einträge (Temp-ID `tmp-...`) erzeugen.
|
||||
- Beim Push führt Backend `Upsert+Merge` aus, weist finale IDs zu und liefert `IdMapping { tmpId -> finalId }` zurück.
|
||||
- Desktop ersetzt Referenzen transaktional und emittiert ein lokales `IdRemapped`-Event (kein Re-Upload nötig, außer für Diagnose).
|
||||
- Desktop ersetzt Referenzen transaktional und emittiert ein lokales `IdRemapped`-Event (kein Re-Upload nötig, außer für
|
||||
Diagnose).
|
||||
|
||||
3) Reihenfolge-/Kausalitätskonflikte:
|
||||
- Bei fehlenden Vorgänger-Events antwortet Backend mit `rejected: [id]` und `requiredSinceSeq`. Desktop zieht Delta (`pull`) und wiederholt den `push`.
|
||||
|
||||
- Bei fehlenden Vorgänger-Events antwortet Backend mit `rejected: [id]` und `requiredSinceSeq`. Desktop zieht Delta (
|
||||
`pull`) und wiederholt den `push`.
|
||||
|
||||
## Snapshots & Recovery
|
||||
|
||||
- Snapshot-Intervall: standardmäßig 100 Events pro `(aggregateType, scope)` (wie ADR-0022), für WAN-Sync zusätzlich Full-State-Snapshot pro Veranstaltung vor Event-Abschluss.
|
||||
- Recovery: Desktop kann mit leerem Log starten → `snapshot/request` → Full-State + `snapshotSeq` → weitere Deltas über `pull`.
|
||||
- USB-Fallback (Notbetrieb): Export/Import von `sync_events` und `sync_snapshots` als verschlüsselte Archive (`.msync`). Offene Spezifikation; separater PoC.
|
||||
- Snapshot-Intervall: standardmäßig 100 Events pro `(aggregateType, scope)` (wie ADR-0022), für WAN-Sync zusätzlich
|
||||
Full-State-Snapshot pro Veranstaltung vor Event-Abschluss.
|
||||
- Recovery: Desktop kann mit leerem Log starten → `snapshot/request` → Full-State + `snapshotSeq` → weitere Deltas über
|
||||
`pull`.
|
||||
- USB-Fallback (Notbetrieb): Export/Import von `sync_events` und `sync_snapshots` als verschlüsselte Archive (`.msync`).
|
||||
Offene Spezifikation; separater PoC.
|
||||
|
||||
## Sicherheit
|
||||
|
||||
- Mandantentrennung: Jeder Request trägt `X-Event-Id` (ADR-0021). Backend validiert gegen `control.tenants`.
|
||||
- Transport: `https` + mTLS (bevorzugt) oder `https` + OAuth2 Client Credentials. Payload-Signatur (HMAC-SHA256) empfohlen.
|
||||
- Transport: `https` + mTLS (bevorzugt) oder `https` + OAuth2 Client Credentials. Payload-Signatur (HMAC-SHA256)
|
||||
empfohlen.
|
||||
- Integrität: `checksum` pro Event wird serverseitig geprüft; Mismatch → Reject.
|
||||
- Rechte: Backend erzwingt Mastership-Regeln serverseitig; Verstöße → `PENDING_REVIEW` + Audit-Log.
|
||||
|
||||
## Fehlerfälle & Resilienz
|
||||
|
||||
- Netzwerkfehler: Exponentielles Backoff (bis 5 min), Offline-Queue unbegrenzt (bounded by disk quota), Telemetrie im UI.
|
||||
- Netzwerkfehler: Exponentielles Backoff (bis 5 min), Offline-Queue unbegrenzt (bounded by disk quota), Telemetrie im
|
||||
UI.
|
||||
- Schema-Divergenz: `minSupportedSchema` aus `hello`; Desktop migriert vor weiterem Sync oder schaltet in Read-Only.
|
||||
- Duplikate: Idempotenz-Keys verhindern Doppelverarbeitung. ACK enthält höchste verarbeitete `sequenceNumber`.
|
||||
|
||||
## Observability
|
||||
|
||||
- Metriken: `sync_push_events_total`, `sync_pull_events_total`, `sync_rejected_total`, `sync_latency_ms` (p50/p95), `offline_duration_s`.
|
||||
- Metriken: `sync_push_events_total`, `sync_pull_events_total`, `sync_rejected_total`, `sync_latency_ms` (p50/p95),
|
||||
`offline_duration_s`.
|
||||
- Logs: pro Event `tenant`, `originNodeId`, `seq`, `aggType`, `eventType`, `result`.
|
||||
- UI: Status-Anzeige (Verbunden, Getrennt, Ausstehend X), Konflikt-Review-Queue.
|
||||
|
||||
@@ -5,72 +5,96 @@
|
||||
> **Kontext:** Phase 9 — Zeitplan & Protokollierung
|
||||
|
||||
## 1. Vision & Zielsetzung
|
||||
Die Zeitplan-Optimierung ist das zentrale Werkzeug für die Meldestelle, um den Turnierablauf dynamisch an die Gegebenheiten vor Ort anzupassen. Ziel ist eine intuitive, visuelle Oberfläche (Kalender-Ansicht), in der Bewerbe und Abteilungen per Drag & Drop verschoben werden können, wobei das System automatisch Auswirkungen auf Folge-Bewerbe berechnet und vor Konflikten warnt.
|
||||
|
||||
Die Zeitplan-Optimierung ist das zentrale Werkzeug für die Meldestelle, um den Turnierablauf dynamisch an die
|
||||
Gegebenheiten vor Ort anzupassen. Ziel ist eine intuitive, visuelle Oberfläche (Kalender-Ansicht), in der Bewerbe und
|
||||
Abteilungen per Drag & Drop verschoben werden können, wobei das System automatisch Auswirkungen auf Folge-Bewerbe
|
||||
berechnet und vor Konflikten warnt.
|
||||
|
||||
## 2. Fachliche Anforderungen (Use Cases)
|
||||
|
||||
### UC-1: Verschieben eines Bewerbs/einer Abteilung
|
||||
|
||||
- Ein Benutzer zieht einen Bewerb oder eine Abteilung auf eine neue Startzeit oder einen anderen Austragungsplatz.
|
||||
- **System-Reaktion:**
|
||||
- Neuberechnung der Endzeit basierend auf `reitdauerMinuten * starterAnzahl + besichtigungMinuten + umbauMinuten`.
|
||||
- Prüfung auf Überschneidungen am selben Austragungsplatz.
|
||||
- Warnung bei Konflikten (z.B. Richter-Doppelbelegung).
|
||||
- Neuberechnung der Endzeit basierend auf `reitdauerMinuten * starterAnzahl + besichtigungMinuten + umbauMinuten`.
|
||||
- Prüfung auf Überschneidungen am selben Austragungsplatz.
|
||||
- Warnung bei Konflikten (z.B. Richter-Doppelbelegung).
|
||||
|
||||
### UC-2: Dynamische Zeitplan-Anpassung („Anschließend“)
|
||||
|
||||
- Bewerbe können als `ANSCHLIESSEND` markiert werden (`beginnZeitTyp`).
|
||||
- **System-Reaktion:** Wenn der vorangehende Bewerb verschoben wird oder länger dauert, verschiebt sich der anschließende Bewerb automatisch mit.
|
||||
- **System-Reaktion:** Wenn der vorangehende Bewerb verschoben wird oder länger dauert, verschiebt sich der
|
||||
anschließende Bewerb automatisch mit.
|
||||
|
||||
### UC-3: Drag & Drop in der Startliste
|
||||
|
||||
- Innerhalb einer Startliste können Teilnehmer per Drag & Drop umsortiert werden.
|
||||
- **System-Reaktion:** Automatische Aktualisierung der Kopfnummern (Startnummern) und Neuberechnung der individuellen Startzeiten.
|
||||
- **System-Reaktion:** Automatische Aktualisierung der Kopfnummern (Startnummern) und Neuberechnung der individuellen
|
||||
Startzeiten.
|
||||
|
||||
### UC-4: Protokollierung (Audit Log)
|
||||
|
||||
- Jede manuelle Änderung am Zeitplan oder der Startlisten-Reihenfolge muss protokolliert werden.
|
||||
- **Grund:** Nachvollziehbarkeit bei Einsprüchen und Synchronisation zwischen verschiedenen Arbeitsplätzen (Meldestelle ↔ Richterturm).
|
||||
- **Grund:** Nachvollziehbarkeit bei Einsprüchen und Synchronisation zwischen verschiedenen Arbeitsplätzen (
|
||||
Meldestelle ↔ Richterturm).
|
||||
|
||||
## 3. Datenmodell-Erweiterungen & Logik
|
||||
|
||||
### 3.1 Erweiterung `Bewerb` & `Abteilung`
|
||||
|
||||
Das bestehende Modell in `entries-domain` deckt bereits viele Felder ab. Für die Optimierung präzisieren wir:
|
||||
|
||||
- **`Umbauzeit`:** Zeit zwischen zwei Abteilungen oder Bewerben.
|
||||
- **`Pausen`:** Geplante Unterbrechungen (z.B. Mittagspause, Platzpflege) werden als spezielle „Blocker-Events“ im Zeitplan geführt.
|
||||
- **`Pausen`:** Geplante Unterbrechungen (z.B. Mittagspause, Platzpflege) werden als spezielle „Blocker-Events“ im
|
||||
Zeitplan geführt.
|
||||
- **`BesichtigungsBlock` (NEU):** Eigenständiges Objekt für Parcoursbesichtigungen.
|
||||
- Kann mit mehreren Bewerben/Abteilungen verknüpft werden (Cross-Competition Inspection).
|
||||
- Unterstützt Typen: `ZU_FUSS` (Standard) und `ZU_PFERD` (Spezialfall für Springpferde bis 110cm gemäß ÖTO).
|
||||
- Validierung: Mindestens 5 Min. Puffer vor dem ersten Start (ÖTO §43).
|
||||
- Kann mit mehreren Bewerben/Abteilungen verknüpft werden (Cross-Competition Inspection).
|
||||
- Unterstützt Typen: `ZU_FUSS` (Standard) und `ZU_PFERD` (Spezialfall für Springpferde bis 110cm gemäß ÖTO).
|
||||
- Validierung: Mindestens 5 Min. Puffer vor dem ersten Start (ÖTO §43).
|
||||
|
||||
### 3.2 Zeitberechnungs-Algorithmus (Präzisierung)
|
||||
|
||||
Die Logik in `StartlistenService.berechneStartzeiten` wird erweitert:
|
||||
|
||||
1. **Basis:** `Startzeit` der Abteilung.
|
||||
2. **Vorlauf:** `besichtigungMinuten`.
|
||||
3. **Starter-Loop:**
|
||||
- `individuelleStartzeit = aktuelleZeit`.
|
||||
- `aktuelleZeit += bewerb.reitdauerMinuten`.
|
||||
- *Neu:* Berücksichtigung von festen Pausen nach X Startern (z.B. 10 Min. Pause alle 20 Starter).
|
||||
- `individuelleStartzeit = aktuelleZeit`.
|
||||
- `aktuelleZeit += bewerb.reitdauerMinuten`.
|
||||
- *Neu:* Berücksichtigung von festen Pausen nach X Startern (z.B. 10 Min. Pause alle 20 Starter).
|
||||
4. **Nachlauf:** `umbauMinuten` am Ende der Abteilung/des Bewerbs.
|
||||
|
||||
### 3.3 Drag & Drop Logik (Frontend & Backend)
|
||||
|
||||
- **Frontend (Compose Desktop):**
|
||||
- Implementierung eines `DraggableBewerbItem`.
|
||||
- Visuelle Darstellung von Konflikten (Rote Markierung bei Überlappung).
|
||||
- Implementierung eines `DraggableBewerbItem`.
|
||||
- Visuelle Darstellung von Konflikten (Rote Markierung bei Überlappung).
|
||||
- **Backend (API):**
|
||||
- Neuer Endpunkt `PATCH /bewerbe/{id}/zeitplan` für schnelle Updates.
|
||||
- Validierung der neuen Zeiten gegen den `austragungsplatzId` und `richterEinsaetze`.
|
||||
- Neuer Endpunkt `PATCH /bewerbe/{id}/zeitplan` für schnelle Updates.
|
||||
- Validierung der neuen Zeiten gegen den `austragungsplatzId` und `richterEinsaetze`.
|
||||
|
||||
## 4. Konflikt-Management
|
||||
|
||||
Das System arbeitet nach dem Prinzip **„Warnen statt Blockieren“** (ADR-0016):
|
||||
|
||||
- **Harte Fehler:** Nur bei technischer Unmöglichkeit (z.B. Datum in der Vergangenheit bei Live-Betrieb).
|
||||
- **Warnungen:**
|
||||
- Überlappung auf dem Platz.
|
||||
- Richter hat gleichzeitig Einsatz in anderem Bewerb.
|
||||
- Zeitunterschreitung für Reiter (Reiter startet in zwei kurz aufeinanderfolgenden Bewerben).
|
||||
- Überlappung auf dem Platz.
|
||||
- Richter hat gleichzeitig Einsatz in anderem Bewerb.
|
||||
- Zeitunterschreitung für Reiter (Reiter startet in zwei kurz aufeinanderfolgenden Bewerben).
|
||||
|
||||
## 5. Synchronisation (Offline-First)
|
||||
|
||||
Änderungen am Zeitplan erzeugen `SyncEvents` (gemäß ADR-0022).
|
||||
- **Lamport-Uhren:** Stellen sicher, dass bei gleichzeitigen Änderungen an zwei Laptops die zeitlich spätere Änderung (oder die mit höherer Priorität) gewinnt.
|
||||
- **Echtzeit-Update:** Über WebSockets werden Zeitplan-Änderungen sofort an alle verbundenen Clients (z.B. Anzeige-Monitor, Richter-Tablet) gepusht.
|
||||
|
||||
- **Lamport-Uhren:** Stellen sicher, dass bei gleichzeitigen Änderungen an zwei Laptops die zeitlich spätere Änderung (
|
||||
oder die mit höherer Priorität) gewinnt.
|
||||
- **Echtzeit-Update:** Über WebSockets werden Zeitplan-Änderungen sofort an alle verbundenen Clients (z.B.
|
||||
Anzeige-Monitor, Richter-Tablet) gepusht.
|
||||
|
||||
## 6. Nächste Schritte
|
||||
|
||||
1. **Backend:** ✅ Implementiert (BewerbService, API, Zeitberechnungs-Pausen).
|
||||
2. **Frontend:** Prototyping der Kalender-Ansicht mit Compose Desktop.
|
||||
3. **QA:** Test-Szenarien für komplexe Verschiebungen (Kettenreaktionen bei „Anschließend“).
|
||||
@@ -5,42 +5,63 @@
|
||||
> **Kontext:** Zeitplan-Optimierung & Praxis-Szenarien
|
||||
|
||||
## 1. Parcoursbesichtigung zu Pferd
|
||||
|
||||
Die Aussage des Users wurde geprüft und bestätigt.
|
||||
|
||||
### 1.1 Regelwerks-Referenz (ÖTO 2026)
|
||||
|
||||
Gemäß **ÖTO Teil B, § 43 (Abweichungen)** gilt:
|
||||
|
||||
- **Normalfall:** Parcoursbesichtigung erfolgt zu Fuß.
|
||||
- **Springpferde- & Jungpferdeprüfungen (bis 110 cm):** Eine Besichtigung **zu Pferd im Schritt** kann von der Richtergruppe erlaubt werden.
|
||||
- **Zweck:** Junge, unerfahrene Pferde sollen stressfrei an optische Reize (Fangständer, Farben, Unterbauten) herangeführt werden.
|
||||
- **Springpferde- & Jungpferdeprüfungen (bis 110 cm):** Eine Besichtigung **zu Pferd im Schritt** kann von der
|
||||
Richtergruppe erlaubt werden.
|
||||
- **Zweck:** Junge, unerfahrene Pferde sollen stressfrei an optische Reize (Fangständer, Farben, Unterbauten)
|
||||
herangeführt werden.
|
||||
|
||||
### 1.2 Organisatorische Implikationen
|
||||
- **Dauer:** Die Besichtigung zu Pferd benötigt oft etwas mehr Zeit für die Koordination am Einlass (15-20 Min. sind praxisnah).
|
||||
- **Sicherheit:** Da Pferde im Parcours sind, während andere Reiter eventuell noch draußen warten, muss der Zeitplan einen Puffer von mindestens **5 Minuten** zwischen Ende Besichtigung und erstem Start vorsehen (ÖTO Vorschrift).
|
||||
|
||||
- **Dauer:** Die Besichtigung zu Pferd benötigt oft etwas mehr Zeit für die Koordination am Einlass (15-20 Min. sind
|
||||
praxisnah).
|
||||
- **Sicherheit:** Da Pferde im Parcours sind, während andere Reiter eventuell noch draußen warten, muss der Zeitplan
|
||||
einen Puffer von mindestens **5 Minuten** zwischen Ende Besichtigung und erstem Start vorsehen (ÖTO Vorschrift).
|
||||
|
||||
## 2. Zusammengelegte Besichtigungen (Cross-Competition Inspection)
|
||||
|
||||
In der Praxis üblich, wenn der Parcours für aufeinanderfolgende Bewerbe identisch bleibt.
|
||||
|
||||
### 2.1 Szenario
|
||||
|
||||
- **Bewerb A:** Springpferdeprüfung 105cm (Besichtigung zu Pferd erlaubt).
|
||||
- **Bewerb B:** Standardspringprüfung 105cm (Besichtigung zu Fuß).
|
||||
- **Lösung:** Eine gemeinsame Besichtigungszeit vor Bewerb A.
|
||||
|
||||
### 2.2 Regelwerks-Konformität
|
||||
- Es gibt kein Verbot für gemeinsame Besichtigungen, solange die Teilnehmer beider Bewerbe die Möglichkeit haben, den Parcours regelkonform zu besichtigen.
|
||||
- **Wichtig:** Wenn Bewerb B erst 2 Stunden später startet, muss für Teilnehmer von Bewerb B theoretisch eine zweite Besichtigungsmöglichkeit (oder ein "Refresh") angeboten werden, falls der Parcours zwischenzeitlich verändert wurde. Wenn er identisch bleibt, reicht die einmalige Bekanntgabe.
|
||||
|
||||
- Es gibt kein Verbot für gemeinsame Besichtigungen, solange die Teilnehmer beider Bewerbe die Möglichkeit haben, den
|
||||
Parcours regelkonform zu besichtigen.
|
||||
- **Wichtig:** Wenn Bewerb B erst 2 Stunden später startet, muss für Teilnehmer von Bewerb B theoretisch eine zweite
|
||||
Besichtigungsmöglichkeit (oder ein "Refresh") angeboten werden, falls der Parcours zwischenzeitlich verändert wurde.
|
||||
Wenn er identisch bleibt, reicht die einmalige Bekanntgabe.
|
||||
|
||||
## 3. Anforderungen für die Software (Zeitplan-Modul)
|
||||
|
||||
### 3.1 Datenmodell
|
||||
|
||||
- `Abteilung` oder `Bewerb` benötigt ein Flag `besichtigungZuPferdErlaubt` (Boolean).
|
||||
- `BesichtigungsBlock` als eigenständiges Entitätsobjekt im Zeitplan, das mit **mehreren** Bewerben/Abteilungen verknüpft werden kann.
|
||||
- `BesichtigungsBlock` als eigenständiges Entitätsobjekt im Zeitplan, das mit **mehreren** Bewerben/Abteilungen
|
||||
verknüpft werden kann.
|
||||
|
||||
### 3.2 Validierung & Warnungen
|
||||
- **Warnung:** Wenn ein Besichtigungsblock mit "zu Pferd" markiert ist, aber ein verbundener Bewerb (z.B. L-Springen) dies laut ÖTO normalerweise nicht vorsieht (Diskretionsspielraum der Richter).
|
||||
- **Puffer-Check:** Automatische Prüfung, ob zwischen `Ende Besichtigung` und `Start Erster Reiter` mindestens 5 Minuten liegen.
|
||||
|
||||
- **Warnung:** Wenn ein Besichtigungsblock mit "zu Pferd" markiert ist, aber ein verbundener Bewerb (z.B. L-Springen)
|
||||
dies laut ÖTO normalerweise nicht vorsieht (Diskretionsspielraum der Richter).
|
||||
- **Puffer-Check:** Automatische Prüfung, ob zwischen `Ende Besichtigung` und `Start Erster Reiter` mindestens 5 Minuten
|
||||
liegen.
|
||||
|
||||
## 4. Fazit für Architect & Entwickler
|
||||
Die "Besichtigung zu Pferd" ist ein valider Spezialfall für Springpferdeprüfungen. Die Software muss erlauben, Besichtigungszeiten flexibel vor einen oder mehrere Bewerbe zu lagern und den Typ (Fuß/Pferd) zu kennzeichnen.
|
||||
|
||||
Die "Besichtigung zu Pferd" ist ein valider Spezialfall für Springpferdeprüfungen. Die Software muss erlauben,
|
||||
Besichtigungszeiten flexibel vor einen oder mehrere Bewerbe zu lagern und den Typ (Fuß/Pferd) zu kennzeichnen.
|
||||
|
||||
---
|
||||
*Geprüft durch den 📜 ÖTO/FEI Rulebook Expert am 11.04.2026*
|
||||
@@ -0,0 +1,62 @@
|
||||
# 🤖 Konzept: Status-Automat für Nennungen & Zeitplan-Synchronisation
|
||||
|
||||
Dieses Dokument spezifiziert die Logik des Status-Automaten für Nennungen (Sprint C-1) und dessen Auswirkungen auf den
|
||||
dynamischen Zeitplan.
|
||||
|
||||
## 1. Status-Definitionen (NennStatusE)
|
||||
|
||||
Basierend auf `core-domain/Enums.kt`:
|
||||
|
||||
| Status | Bedeutung | Auswirkung auf Zeitplan |
|
||||
|:-------------------|:--------------------------------------------------|:--------------------------------------------------------|
|
||||
| `EINGEGANGEN` | Nennung wurde erstellt (Initialzustand) | Belegt Zeitslot (basierend auf `reitdauerMinuten`) |
|
||||
| `BESTAETIGT` | Meldestelle hat Nennung geprüft | Belegt Zeitslot |
|
||||
| `NACHNENNUNG` | Nennung nach Nennschluss | Belegt Zeitslot (ggf. am Ende der Liste) |
|
||||
| `TRANSFERIERT` | Nennung wurde auf anderes Paar übertragen | **Inaktiv** (Original-Eintrag wird durch neuen ersetzt) |
|
||||
| `ZURUECKGEZOGEN` | Reiter hat abgemeldet (vor Startlistenerstellung) | **Inaktiv** (Slot wird frei) |
|
||||
| `GESTARTET` | Paar ist in die Prüfung eingeritten | Startzeitpunkt fixiert, Folgestarts ggf. anpassen |
|
||||
| `NICHT_ANGETRETEN` | Paar ist zum Startzeitpunkt nicht erschienen | **Zeitslot verfällt** oder Folgestarts rücken nach |
|
||||
|
||||
## 2. Status-Übergänge & Validierung
|
||||
|
||||
### 2.1 Gültige Übergänge (Beispiele)
|
||||
|
||||
- `EINGEGANGEN` -> `BESTAETIGT` (Normalfall)
|
||||
- `EINGEGANGEN` -> `ZURUECKGEZOGEN` (Abmeldung)
|
||||
- `BESTAETIGT` -> `TRANSFERIERT` (Reitertausch)
|
||||
- `BESTAETIGT` -> `GESTARTET` (Während des Turniers)
|
||||
|
||||
### 2.2 Side-Effects (Side-Effect-Engine)
|
||||
|
||||
Wenn sich der Status einer Nennung ändert, müssen folgende Systeme informiert werden:
|
||||
|
||||
1. **Billing-Service:** Bei `ZURUECKGEZOGEN` ggf. Stornogebühren prüfen. Bei `TRANSFERIERT` Guthaben übertragen.
|
||||
2. **Startlisten-Service:** Bei `ZURUECKGEZOGEN` nach Veröffentlichung der Startliste -> Eintrag als
|
||||
`istGestrichen = true` markieren.
|
||||
3. **Zeitplan-Optimierung:** Bei `NICHT_ANGETRETEN` -> Alle folgenden Startzeiten rücken um `reitdauerMinuten` nach
|
||||
vorne (sofern im Kalender-Modus "Dynamisch" aktiv ist).
|
||||
|
||||
## 3. Dynamische Zeitplan-Anpassung (C-1 Extension)
|
||||
|
||||
Der `StartlistenService` muss eine Methode `aktualisiereZeitplanNachStatusAenderung` erhalten:
|
||||
|
||||
- **Szenario A (Nicht angetreten):** Wenn Nennung X `NICHT_ANGETRETEN` wird, rücken alle folgenden Nennungen in der
|
||||
Abteilung nach vorne.
|
||||
- **Szenario B (Verspätung):** Wenn Nennung X `GESTARTET` wird, aber 2 Minuten später als geplant, verschieben sich alle
|
||||
Folgetermine um +2 Minuten (Kettenreaktion).
|
||||
|
||||
### Puffer-Regel (ÖTO-Konformität)
|
||||
|
||||
- Eine dynamische Verschiebung nach *vorne* darf nie dazu führen, dass ein Reiter vor seiner ursprünglich kommunizierten
|
||||
Startzeit (oder einem definierten Puffer-Zeitraum von z.B. 15 Minuten) starten muss, ohne dass dies explizit bestätigt
|
||||
wurde.
|
||||
|
||||
## 4. Implementierungs-Leitfaden für Backend (C-1)
|
||||
|
||||
1. Erweiterung von `NennungUseCases.statusAendern` um Aufrufe der Side-Effect-Handler.
|
||||
2. Implementierung des `NennungStatusListener` in `entries-service`.
|
||||
3. Anbindung an den `StartlistenService` zur Zeitre-Kalkulation.
|
||||
|
||||
---
|
||||
**Status:** Entwurf (Lead Architect)
|
||||
**Datum:** 11. April 2026
|
||||
@@ -2,12 +2,12 @@
|
||||
type: Roadmap
|
||||
status: ACTIVE
|
||||
owner: Lead Architect
|
||||
last_update: 2026-04-21
|
||||
last_update: 2026-05-06
|
||||
---
|
||||
|
||||
# MASTER ROADMAP: Meldestelle
|
||||
|
||||
🏗️ **[Lead Architect]** | 20. April 2026
|
||||
🏗️ **[Lead Architect]** | 30. April 2026
|
||||
|
||||
**Strategisches Ziel:**
|
||||
Entwicklung einer ÖTO-konformen, offline-fähigen Turnier-Meldestelle als Compose Desktop App (KMP).
|
||||
@@ -17,7 +17,7 @@ Vollständige Self-Hosted Infrastruktur (Gitea, Pangolin, Zora). Datensouveräni
|
||||
- Desktop-App ist der primäre Client (Compose Desktop, KMP) — „Desktop-First“ gilt für UX und Architektur.
|
||||
- Offline-First Betrieb mit lokaler Persistenz und opportunistischer Synchronisation.
|
||||
|
||||
**Aktueller technischer Stand (30.03.2026):**
|
||||
**Aktueller technischer Stand (30.04.2026):**
|
||||
* **Infrastruktur:** ✅ "Zora" (MS-R1, ARM64) ist live. Gitea & Registry laufen.
|
||||
* **Networking:** ✅ Pangolin Tunnel ersetzt Cloudflare.
|
||||
* **CI/CD:** ✅ Gitea Actions mit ARM64-Runner (VM 102) aktiv. Docker-Publish Pipeline grün.
|
||||
@@ -51,403 +51,128 @@ und über definierte Schnittstellen kommunizieren.
|
||||
|
||||
---
|
||||
|
||||
## 1. Abgeschlossene Phasen
|
||||
## 1. Abgeschlossene Phasen (Verifiziert)
|
||||
|
||||
### PHASE 1: Documentation Cleanup ✅ ABGESCHLOSSEN
|
||||
*Ziel: Eine einzige, vertrauenswürdige Quelle der Wahrheit (SSOT) schaffen.*
|
||||
### PHASE 1: Domain-Design & Ubiquitous Language ✅
|
||||
|
||||
#### 🧹 Agent: Curator
|
||||
* [x] **Archivierung:** Veraltete Docs (Cloudflare, GitHub-Workflows, alte Roadmaps) nach `docs/_archive/` verschoben.
|
||||
* [x] **Konsolidierung:** `Zora_System_Architektur.md` als zentrale Infrastruktur-Doku etablieren.
|
||||
* [x] **Struktur:** `docs/` Ordner aufräumen (unnötige Root-Files in Unterordner).
|
||||
* [x] **Index:** `README.md` im Root als Einstiegspunkt aktualisieren.
|
||||
*Status: Fachliche Grundlage vorhanden.*
|
||||
|
||||
### PHASE 2: Infrastructure Hardening ✅ ABGESCHLOSSEN
|
||||
*Ziel: Stabilisierung der neuen Self-Hosted Umgebung.*
|
||||
* [x] **DDD-Analyse:** 6 Bounded Contexts (SCS-Architektur) definiert.
|
||||
* [x] **Terminologie:** `Veranstaltung` ≠ `Turnier` gemäß ÖTO § 2 Abs. 1 festgelegt.
|
||||
* [x] **Ubiquitous Language:** Offizielle Domänen-Terminologie erstellt.
|
||||
|
||||
#### 🐧 Agent: DevOps Engineer
|
||||
### PHASE 2: Infrastruktur & ZNS-Importer (Prototyp) ✅
|
||||
|
||||
* [x] **Keycloak Fix:** Verbindungsprobleme innerhalb des Docker-Netzwerks behoben (Alias `auth.mo-code.at`).
|
||||
* [x] **Backup Strategy:** Automatisierte Backups für Gitea & Datenbanken auf Zora (`config/scripts/backup.sh`).
|
||||
* [x] **Monitoring:** Prometheus/Grafana Dashboard für Zora finalisiert (`dc-ops.yaml`).
|
||||
* [x] **Deployment:** Git-basiertes Deployment-Skript (`config/scripts/deploy.sh`) erstellt.
|
||||
*Status: Grundgerüst steht, Performance-Probleme bekannt.*
|
||||
|
||||
### PHASE 3: Domain-Design & Ubiquitous Language ✅ ABGESCHLOSSEN
|
||||
|
||||
*Ziel: Fachliche Grundlage für die Implementierung schaffen.*
|
||||
|
||||
#### 🏗️ Agent: Lead Architect
|
||||
|
||||
* [x] **DDD-Analyse:** 6 Bounded Contexts (SCS-Architektur) definiert und priorisiert.
|
||||
* [x] **Terminologie:** `Veranstaltung` ≠ `Turnier` gemäß ÖTO § 2 Abs. 1 festgelegt (ADR).
|
||||
* [x] **Design-Baseline:** Vision_03 (Figma) als offizieller Design-Baseline festgelegt.
|
||||
* [x] **Technologie:** Desktop-First-Strategie mit KMP/Compose Desktop beschlossen.
|
||||
|
||||
#### 📜 Agent: ÖTO/FEI Rulebook Expert
|
||||
|
||||
* [x] **Ubiquitous Language:** Offizielle Domänen-Terminologie mit ÖTO-Referenzen erstellt.
|
||||
* [x] **Abteilungs-Schwellenwerte:** Alle Trennungs-Schwellenwerte (§ 39 + spartenspezifisch) dokumentiert.
|
||||
→ `docs/03_Domain/02_Reference/OETO_Regelwerk/Abteilungs-Trennungs-Schwellenwerte.md`
|
||||
|
||||
#### 👷 Agent: Backend Developer
|
||||
|
||||
* [x] **Enums:** `SparteE`, `TurnierkategorieE`, `VeranstaltungsTypE`, `LizenzKlasseE`, `NennungsStatusE`,
|
||||
`StartwunschE` – ÖTO-konform.
|
||||
* [x] **Domain-Modelle:** `DomReiter` (actor-context), `DomNennung`, `DomNennungsTransfer` (registration-context).
|
||||
* [x] **Modul:** `entries-domain` als KMP-Modul aufgesetzt und in `settings.gradle.kts` registriert.
|
||||
* [x] **ZNS-Parser:** Grundsätzliche Fähigkeit zum Parsen von ZNS-Daten (Reiter, Pferde, Vereine, Funktionäre).
|
||||
* [x] **UI-Gerüst:** Navigation und Dialog-Hüllen in Compose Desktop vorhanden.
|
||||
* [x] **Plan-B:** Rudimentärer Mail-Service für Nennungs-Versand (funktional).
|
||||
|
||||
---
|
||||
|
||||
## 2. Aktuelle Phase
|
||||
## 2. Der neue Weg: Fachliche Realität (Roadmap 2026)
|
||||
|
||||
### PHASE 4: MVP-Implementierung ✅ ABGESCHLOSSEN
|
||||
Fokus: Physische Implementierung der Turnier-Hierarchie und technisches Onboarding.
|
||||
|
||||
*Ziel: Lauffähiger MVP für `registration-context` und `actor-context` (P1-Contexts).*
|
||||
### MEILENSTEIN 0: Technische Geräte-Initialisierung (Prio 1) 🚧 IN ARBEIT (STABILISIERUNG)
|
||||
|
||||
#### 🧐 Agent: QA Specialist
|
||||
*Ziel: Ein stabiles, offline-fähiges technisches Fundament für die Desktop-App.*
|
||||
|
||||
* [x] **Actor Context Stabilization:** Funktionär-Datenmodell (Richter/Parcoursbauer) auf professionelle Master-Daten-Referenzierung umgestellt und mit Reiter-Daten verknüpft (Import-Idempotenz via `satzNummer`). Redundante Kontakt-/Adressdaten entfernt. Alle ZNS-Import-Tests (9/9) stabilisiert und verwaiste Parser-Reste entfernt.
|
||||
* [x] **Masterdata Standardization:** Bereinigung und Standardisierung der Masterdaten-Tabellen (Mehrzahl-Konvention: `bundeslaender`, `funktionaers_qualifikationen`, `reit_lizenzen`, `turnier_klassen`).
|
||||
* [x] **ÖTO Data Seeding:** Umfassende Seeder für Funktionärs-Qualifikationen, Turnierklassen und Turnier-Sparten gemäß ÖTO implementiert. Einführung der Tabelle `turnier_sparten`.
|
||||
* [x] **ZNS-Import Optimization:** Automatische Verknüpfung von Funktionären mit Reitern (Reihenfolge: VEREIN -> LIZENZ -> PFERDE -> RICHT). `ZnsImportService` für sequentielle Imports in Tests gehärtet.
|
||||
* [x] **Service Stability:** Port-Konflikt des `masterdata-service` (Spring Management Port 8081 vs. Gateway) durch Umzug auf Port 8086 und explizite Bind-Adressen (Spring: 127.0.0.1, Ktor: 0.0.0.0) dauerhaft gelöst.
|
||||
* [x] **Documentation:** `CHANGELOG.md` aktualisiert und Port-Konfiguration in `application.yml` dokumentiert.
|
||||
→ Note: `IdempotencyApiIntegrationTest` bleibt vorerst @Disabled, da das Hochfahren des Spring-Contexts in der
|
||||
Testumgebung blockiert (unabhängig vom Plugin).
|
||||
→ Task: Integration-Test Umgebung (Port-Binding/Server-Lifecycle) für `masterdata-service` untersuchen.
|
||||
* [x] **App-Icons (PNG/ICO):** Implementiert (Fix für Build-Fehler).
|
||||
* [x] **Docker-Fix:** "services must be a mapping" behoben (dc-gui.yaml).
|
||||
* [x] **Chat-Funktion (Desktop):** MVP implementiert (Navigation & UI).
|
||||
* [x] **Geführte Discovery ("Zero-Config"):** Master-Namen statt IPs, "Wait-State" für Clients.
|
||||
* [x] **Native FileDialogs:** Stabile Pfad-Auswahl für Plan-USB auf allen Systemen.
|
||||
* [x] **Handshake-Feedback:** Visuelle Signalisierung des Verbindungsstatus (Grün/Rot).
|
||||
* [x] **Client-Konfiguration:** Master kann nun Clients in der UI hinzufügen und bearbeiten.
|
||||
* [x] **Master-UX:** Konfiguration beim Start nicht mehr zwangsgesperrt.
|
||||
* [x] **Cross-Packaging (Conveyor):** Windows-Build auf Linux-CI ermöglicht (x64-Abhängigkeit identifiziert).
|
||||
* [x] **Build-Performance:** WASM standardmäßig deaktiviert, um Desktop-Build-Zeiten zu reduzieren (11.05.2026).
|
||||
* [ ] **PoC Verifikation:** 🔴 **BLOCKIERT** (Log 483: ARM64-Runner inkompatibel mit Conveyor-Binary; Workflow auf
|
||||
manuell gesetzt).
|
||||
|
||||
#### 🏗️ Agent: Lead Architect
|
||||
### MEILENSTEIN 1: Die Basis-Hierarchie (Prio 1) ⚪ GEPLANT
|
||||
|
||||
* [x] **ADRs vervollständigen:** Bounded Context Mapping und Context Map dokumentieren.
|
||||
→ `docs/01_Architecture/adr/0014-bounded-context-mapping-de.md`
|
||||
→ `docs/01_Architecture/adr/0015-context-map-de.md`
|
||||
* [x] **API-Design:** Schnittstellen zwischen den Contexts definieren (Anti-Corruption Layer).
|
||||
→ `docs/01_Architecture/adr/0016-api-design-acl-de.md`
|
||||
* [x] **ÖTO-Validation-Seeds:** Seed-Daten für Lizenz-Matrix und Altersklassen finalisiert (V008).
|
||||
*Ziel: Veranstaltung -> Turnier -> Bewerb/Abteilung physisch anlegen und speichern.*
|
||||
|
||||
#### 👷 Agent: Backend Developer
|
||||
* [ ] **Persistenz-Layer:** Implementierung der lokalen Speicherung für alle Ebenen der Hierarchie.
|
||||
* [ ] **Turnier-Wizard (Echt):** Umstellung des Wizards von `println`-Dummies auf echte Datenbank-Transaktionen.
|
||||
* [ ] **Validierung:** Sicherstellen, dass Pflichtfelder (Turniernummer, Sparte) korrekt erfasst werden.
|
||||
|
||||
* [x] **ZNS-Importer:** Support für Richter-Import (RICHT01.DAT) und Reiter-Refactoring (LIZENZ01.DAT) vervollständigt. ✓
|
||||
* [x] **Masterdata:** Qualifikations-System und Personen-Referenzen (Vereine, Bundesländer, Nationen) stabilisiert (Consul & MasterdataSeeder). ✓
|
||||
* [x] **Infrastruktur:** Service-Discovery (Consul) für alle Microservices (incl. Masterdata) aktiviert.
|
||||
* [x] **Infrastruktur:** Bean-Definitionen und Dependency-Injection im `zns-import-service` bereinigt.
|
||||
* [x] **Database:** Initialisierung der Funktionärs-Tabellen stabilisiert (PSQLException Fix).
|
||||
* [x] **`actor-context`:** Domain-Modelle für `Pferd`, `Funktionaer`, `Verein` implementiert.
|
||||
* [x] **`registration-context`:** `DomBewerb`, `DomAbteilung`, `DomStartliste` implementiert.
|
||||
* [x] **`event-management-context`:** `DomVeranstaltung`, `DomTurnier`, `DomAusschreibung` implementiert.
|
||||
* [x] **Persistenz:** Repository-Interfaces und erste DB-Migrationen (Flyway/Liquibase).
|
||||
* [x] **API:** REST-Endpunkte für Nennungs-Workflow (Kern-Use-Cases).
|
||||
* [x] **Infrastruktur-Stabilisierung:** Kompilierfehler in `masterdata-infrastructure` behoben.
|
||||
* [x] **Identity-Schnittstellen:** Endpunkte für ZNS-Linking über `identity-service` bereitgestellt.
|
||||
### MEILENSTEIN 2: ZNS-Performance & Daten-Qualität (Prio 2)
|
||||
|
||||
#### 🎨 Agent: Frontend Expert
|
||||
*Ziel: Import der ZNS.zip in < 2 Minuten statt 30+ Minuten.*
|
||||
|
||||
* [x] **KMP/Compose Desktop:** Projektstruktur aufgesetzt (`frontend/shells/meldestelle-desktop`).
|
||||
* [x] **Navigation:** Sidebar-Navigation gemäß Vision_03 implementiert (Veranstaltungen, Reiter, Pferde, Funktionäre,
|
||||
Meisterschaften, Cups).
|
||||
* [x] **Nennungs-Screen:** `TurnierDetailScreen` integriert `NennungsMaske` aus `nennung-feature` (Bewerbe-Tab ⭐).
|
||||
* [ ] **Batch-Processing:** Umstellung des `ZnsImportService` auf Batch-Inserts (JDBC/Exposed).
|
||||
* [ ] **Fortschritts-Anzeige:** Reale Rückmeldung über den Import-Status in der UI.
|
||||
|
||||
#### 📜 Agent: ÖTO/FEI Rulebook Expert
|
||||
### MEILENSTEIN 3: Richtverfahren & Bewerbs-Konfiguration (Prio 3)
|
||||
|
||||
* [x] **Voltigieren (CVN):** Abteilungs-Trennungsregeln aus B-Teil § 400 ff. ausgewertet (offene Frage #3 teilweise
|
||||
geklärt).
|
||||
→ B IV enthält keine eigenen Regeln – verweist auf OEPS-Reglement CVN. § 39 Abs. 1 gilt nicht für CVN. § 39 Abs.
|
||||
2 (> 80 Starter) gilt als Fallback.
|
||||
→ `docs/03_Domain/02_Reference/OETO_Regelwerk/Abteilungs-Trennungs-Schwellenwerte.md` (Abschnitt 2.6)
|
||||
* [x] **Fahren (CAN):** Starter-Schwellenwerte jenseits der Reitertreffen-Regel geklärt (offene Frage #4 teilweise
|
||||
geklärt).
|
||||
→ B VII enthält keine eigenen Regeln – verweist auf OEPS-Reglement „Turnierordnung für Gespanne". § 39 Abs. 1 gilt
|
||||
nicht für CAN. § 39 Abs. 2 (> 80 Starter) gilt als Fallback. Einzige gesicherte Lizenzregel: § 850 Abs. 9 (F1+ bei
|
||||
Fahrertreffen).
|
||||
→ `docs/03_Domain/02_Reference/OETO_Regelwerk/Abteilungs-Trennungs-Schwellenwerte.md` (Abschnitt 2.5)
|
||||
* [x] **Warn-Logik:** Spezifikation der `competition-context` Warn-Logik für Abteilungs-Schwellenwerte.
|
||||
→ `docs/03_Domain/02_Reference/OETO_Regelwerk/Warn-Logik-Spezifikation-competition-context.md`
|
||||
*Ziel: Bewerbe mit fachlich korrekten Regeln (ÖTO) anlegen.*
|
||||
|
||||
#### 🧹 Agent: Curator & Lead Architect (ZNS-Importer)
|
||||
|
||||
* [x] **ZNS-Importer (MVP) – Phase 1 & 2:** `core:zns-parser` (KMP), `ZnsLegacyParsers` (alle 4 Dateitypen, CP850),
|
||||
`ZnsImportService` (Orchestrator, ZIP in-memory, Upsert), Unit-Tests grün.
|
||||
→ Detaillierte Planung: `docs/01_Architecture/Roadmap_ZNS_Importer.md`
|
||||
* [x] Backend-Infrastruktur & CP850 Parser (Phase 1 – Parser/Modul)
|
||||
* [x] Domain-Mapping & Upsert in DB (Phase 2)
|
||||
* [x] REST-API & Job-Management (Phase 1 – Controller/Job-Registry)
|
||||
* [x] Frontend-Integration mit File-Picker & Status-Polling (Phase 3)
|
||||
* [ ] **Richtverfahren-Engine:** Validierungslogik für verschiedene Richtverfahren (Fehler/Zeit, Wertnoten).
|
||||
* [ ] **Abteilungs-Logik:** Automatische Teilungsvorschläge gemäß ÖTO § 39.
|
||||
|
||||
---
|
||||
|
||||
## 3. Initiative: Wizard-Orchestrator & Offline-Drafts (Q2/Q3 2026)
|
||||
## 3. Zukünftige Module (Status: Geplant / Vision)
|
||||
|
||||
🏗️ Verantwortlich: Lead Architect · 🎨 Frontend · 🖌️ UI/UX · 👷 Backend · 🧐 QA · 🧹 Curator
|
||||
*Diese Module existieren derzeit nur als Konzepte oder leere Hüllen.*
|
||||
|
||||
Ziel: Konsolidierung aller „Wizards“ auf ein deklaratives Orchestrierungs-Framework (Graph + Guards + Effects), vereinheitlichte Validierung und Offline-Draft-Fähigkeit inkl. Delta‑Sync. Desktop-first, tastaturbedienbar, testbar.
|
||||
|
||||
### 3.1 Kernbausteine
|
||||
- Orchestrator Runtime & DSL: `StepId`, `WizardContext`, `WizardState`, `Guard`, `Transition`, `StepEffects`.
|
||||
- WizardScaffold: Breadcrumb, Kontext-Chips, Footer mit Hotkeys (Enter/Shift+Enter/Alt+S), Fehler-Summary.
|
||||
- DraftStore: Autosave pro Step (`onLeave`), Resume, `flowVersion`, Konfliktanzeige.
|
||||
- DevTools: strukturierte Transition-Logs, Graph-Export (DOT/PlantUML).
|
||||
|
||||
Referenzen/Dokumente:
|
||||
- ADR‑0025: Wizard-Orchestrator (State‑Machine, DSL, Guards, Effects) → `docs/01_Architecture/adr/0025-wizard-orchestrator-de.md`
|
||||
- ADR‑0026: Step-Validation-Policy (sync vs. async, Fehlersichtbarkeit, Hotkeys) → `docs/01_Architecture/adr/0026-validation-policy-de.md`
|
||||
- ADR‑0027: Draft-Domain & Delta‑Sync (Versionierung, Konfliktlösung, Idempotenz) → `docs/01_Architecture/adr/0027-draft-domain-and-delta-sync-de.md`
|
||||
- Reference: Wizard‑DSL README (Beispiel-Flow Event) → `docs/01_Architecture/Reference/Wizard-DSL-README.md`
|
||||
|
||||
### 3.2 Migrationsstrategie (Strangler)
|
||||
1) Parallelbetrieb: Neuer Orchestrator in `frontend/core/wizard`; bestehende VMs delegieren schrittweise.
|
||||
2) Inkrement 1: Event‑Flow – zunächst 2 Steps (ZNS_CHECK, VERANSTALTER_SELECTION), dann alle 6 Steps.
|
||||
3) Feature‑Flag `WizardRuntimeEnabled` für risikoarmen Rollout.
|
||||
|
||||
### 3.3 Phasenplanung (Auszug)
|
||||
- Phase 1 (Core & Tooling, 2–3 Wochen): Runtime/DSL, DevLogs, Graph‑Export, Scaffold‑MVP, Unit‑Tests.
|
||||
- Phase 2 (Event‑Flow, 2–3 Wochen): `EventStep/Acc/Guards`, Flow‑DSL, VM‑Delegation, Validierung, Autosave/Resume.
|
||||
- Phase 3 (Backend, 2–4 Wochen): Draft-/Validate‑APIs, Offline‑Queue, Delta‑Sync für Turniere.
|
||||
- Phase 4 (Skalierung, 6–10 Wochen, parallel): Weitere Flows je Bounded Context.
|
||||
- Phase 5–7 (2–3 + 1–2 + 1–2 Wochen): UX‑Härtung, Observability/Rollout‑Gates, Stabilisierung & Abschaltung Altlogik.
|
||||
|
||||
Grobe Gesamtdauer: 17–29 Wochen je nach Parallelisierung.
|
||||
|
||||
### 3.4 Akzeptanzkriterien (DoD Initiative)
|
||||
- Alle priorisierten Flows laufen über Orchestrator; Next/Back/History deterministisch; Graph‑Export aktuell.
|
||||
- DraftStore produktiv; Resume deterministisch; Delta‑Sync idempotent; Konflikte nicht‑blockierend sichtbar.
|
||||
- Validierungs‑Policy konsistent; Tastatur‑Bedienung vollständig; Performance‑Gates eingehalten.
|
||||
- ADR‑0025/0026/0027 veröffentlicht; Wizard‑DSL‑Reference vorhanden; CI grün; Metriken/Alerts aktiv.
|
||||
|
||||
### 3.5 10‑Tage‑Startplan
|
||||
- Tag 1–2: Runtime/DSL‑Skelett, Scaffold‑MVP, Feature‑Flag, README Skeleton.
|
||||
- Tag 3: EventStep/Acc/Guards, EventFlow (2 Steps), VM‑Delegation minimal.
|
||||
- Tag 4: Tests Runtime/Guards, Graph‑Export, Dev‑Logs.
|
||||
- Tag 5–6: META_DATA/ANSPRECHPERSON migrieren, Validierungs‑API, Fehler‑Summary.
|
||||
- Tag 7: DraftStore lokal (Autosave/Resume), Property‑Test Resume.
|
||||
- Tag 8: TURNIER_ANLAGE einbetten, Sync via `onComplete`.
|
||||
- Tag 9: SUMMARY + Finalisierung, Offload in Offline‑Queue (Stub).
|
||||
- Tag 10: ADR‑0025/0026/0027 Review+Merge; Journal‑Eintrag.
|
||||
|
||||
Journal: `docs/99_Journal/2026-04-21_Wizard-Orchestrator_Roadmap_Anchoring.md`
|
||||
* **Nennungs-Management:** Erfassung von Nennungen gegen den ZNS-Datenbestand.
|
||||
* **Zeitplan:** Dynamische Zeitplanung (Drag & Drop).
|
||||
* **Ergebnisse:** Erfassung von Wertungen und Platzierungsberechnung.
|
||||
* **Abrechnung:** Vollständiger `billing-context`.
|
||||
|
||||
---
|
||||
|
||||
## 3. Aktuelle Phase
|
||||
## 4. Archiv der fiktiven Meilensteine (Reality-Check am 28.04.2026)
|
||||
|
||||
### Progress Checkpoint – 2026-04-21 (Wizard-Orchestrator Initiative)
|
||||
*Die folgenden Einträge wurden in früheren Sitzungen als "Abgeschlossen" markiert, entsprachen aber nicht dem realen
|
||||
Code-Stand.*
|
||||
|
||||
- Core/DSL: angelegt in `frontend/core/wizard` (Runtime, DSL), erste Tests grün.
|
||||
- UI: `WizardScaffold` (MVP) + Hotkeys-Wrapper (Enter/Shift+Enter/Alt+S) vorhanden.
|
||||
- Feature-Integration: Veranstaltungs-Wizard hinter Flag teilweise delegiert.
|
||||
- Drafts: In‑Memory DraftStore (Autosave/Resume Hooks) angebunden.
|
||||
- DI: Koin-Parameterübergabe für `EventWizardViewModel` vereinheitlicht.
|
||||
- Flag: `WizardRuntimeEnabled = false` (Standard AUS; Dev-Verprobung manuell).
|
||||
<details>
|
||||
<summary>Frühere (fiktive) Meilensteine anzeigen</summary>
|
||||
|
||||
Nächste Schritte (Kurz): Tests für `needsContactPerson` (beide Zweige), VM‑Delegation für weitere Steps, Footer‑Fehler‑Summary, persistenter DraftStore, Dev‑Overlay.
|
||||
### PHASE 4: MVP-Implementierung (Früherer Status: Abgeschlossen)
|
||||
|
||||
### PHASE 5: P2-Contexts & Integration ✅ ABGESCHLOSSEN
|
||||
* [ ] ZNS-Import Optimierung (Batching) -> In MEILENSTEIN 2 verschoben.
|
||||
* [ ] `event-management-context` Implementierung -> In MEILENSTEIN 1 verschoben.
|
||||
|
||||
*Ziel: `competition-context` und `event-management-context` implementieren.*
|
||||
### PHASE 5-13 (Früherer Status: Abgeschlossen/In Arbeit)
|
||||
|
||||
* [x] **`competition-context`:** Bewerbe, Startlisten, Ergebnisse, Abteilungs-Warn-Logik.
|
||||
* [x] **`event-management-context`:** Veranstaltungs- und Turnier-Verwaltung, Ausschreibungs-Generator.
|
||||
* [x] **ZNS-Integration:** Schnittstelle zum Zentralen Nennungs-System (A-Satz / B-Satz).
|
||||
* [x] **Offline-Sync:** Offline-First-Strategie für Desktop-App implementieren.
|
||||
* [ ] `competition-context` (Bewerbe, Startlisten) -> Fachlogik fehlt weitgehend.
|
||||
* [ ] `billing-context` (Abrechnung) -> Nur Infrastruktur-Hülle vorhanden.
|
||||
* [ ] `results-service` -> Geschäftslogik fehlt.
|
||||
|
||||
### PHASE 6: P3-Contexts & Billing ✅ ABGESCHLOSSEN
|
||||
|
||||
*Ziel: `billing-context` und `identity-context` implementieren.*
|
||||
|
||||
* [x] **`billing-context`:** Gebührenberechnung, Kassa, Abrechnung.
|
||||
* [x] **`identity-context`:** Rollen-Modell (TBA, Veranstalter, Richter etc.) mit Keycloak.
|
||||
* [x] **Reporting:** Startlisten- und Ergebnislisten-Druck (PDF).
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
## 4. Geplante Phasen
|
||||
|
||||
### PHASE 7: Desktop-Vernetzung & Zentrale Verwaltung ✅ ABGESCHLOSSEN
|
||||
|
||||
*Ziel: LAN-Kommunikation Vorbereitung und Etablierung der "Veranstaltung-Verwaltung" als zentrale Schaltstelle.*
|
||||
|
||||
* [x] **Zentrale Verwaltung:** Etablierung der `Veranstaltung-Verwaltung` (Zentrale) als administratives Cockpit.
|
||||
* [x] **Navigation:** Implementierung eines Back-Stack-Systems für intelligente "Zurück"-Navigation.
|
||||
* [x] **Domänen-Synchronisation:** Anpassung der Frontend-Stores an die Backend-Masterdata-Modelle (Reiter, Pferde,
|
||||
Vereine, Funktionäre).
|
||||
* [x] **ZNS-Integration (Frontend):** ZNS-Importer in die Zentrale integriert; Konzept "Globaler Pool -> Lokale
|
||||
Synchronisation" gefestigt.
|
||||
* [x] **Terminologie:** UI-weit Umstellung von "Event" auf "Veranstaltung" (ÖTO-konform).
|
||||
* [x] **Konzept:** LAN-Discovery (mDNS) und Echtzeit-Sync (WebSockets) entworfen.
|
||||
* [x] **ADR:** ADR-0020 (Lokale Netzwerk-Kommunikation) erstellt.
|
||||
|
||||
### PHASE 8: Bewerbe-Management & Startlisten ✅ ABGESCHLOSSEN
|
||||
|
||||
*Ziel: Fachliche Tiefe in den Turnieren (Import, Generierung, Zeitberechnung).*
|
||||
|
||||
* [x] **Konzept/ADR:** LAN‑Sync (ADR‑0022) und Offline‑First Desktop↔Backend Konzept definiert und verlinkt.
|
||||
* [x] **Bewerbe-Import:** Implementierung der Merge-Logik (ZNS-XML -> BewerbUiModel). ✓
|
||||
* [x] **Startlisten-Automatisierung:** Generierung und Zeitberechnung (Pausen, Umbauzeiten). ✓
|
||||
* [x] **Discovery:** Implementierung des mDNS-Service (JmDNS) für die Geräte-Suche. ✓
|
||||
* [x] **Transport:** Aufbau der WebSocket-Infrastruktur für P2P-Sync (Ktor WebSockets, SyncManager). ✓
|
||||
* [x] **Offline-First Desktop↔Backend:** Umsetzung gemäß Konzept „Offline-First Synchronisation (Desktop ↔ Backend)“ → `docs/01_Architecture/konzept-offline-first-desktop-backend-de.md`. ✓
|
||||
* [x] **Regelwerks-Validierung:** Implementierung des strukturierten Abteilungs-Warnungssystems gemäß ÖTO § 39 inkl. UI-Integration. ✓
|
||||
|
||||
### PHASE 9: Zeitplan-Optimierung & Protokollierung ✅ ABGESCHLOSSEN
|
||||
|
||||
*Ziel: Dynamische Zeitplan-Anpassungen, Protokollierung von Änderungen und Export-Funktionen.*
|
||||
|
||||
* [x] **Billing-Service:** Initialisierung, Teilnehmer-Konten & Buchungs-Logik (v1). ✓
|
||||
* [x] **Entries-Integration:** Automatische Buchung von Nenngeldern bei Nennungs-Abgabe. ✓
|
||||
* [x] **ZNS-Importer:** Hardening & Integrationstests für Funktionärs-Updates. ✓
|
||||
* [x] **Konzept:** Fachliches Konzept für Zeitplan-Optimierung (Drag & Drop) erstellt. ✓
|
||||
* [x] **Konzept:** Status-Automat für Nennungen & Zeitplan-Synchronisation spezifiziert. ✓
|
||||
* [x] **Frontend-Standardisierung:** `nennung-feature` refactored und in Desktop-Shell integriert. ✓
|
||||
* [x] **Rulebook-Check:** ÖTO §43 "Parcoursbesichtigung zu Pferd" eingearbeitet. ✓
|
||||
* [x] **Feature-Migration:** Pferde-, Reiter-, Funktionärs- und Veranstalter-Module vollständig auf KMP umgestellt. ✓
|
||||
* [x] **Cleanup:** `FRONTEND_CLEANUP_TODO.md` für Migration von `v2` Screens weitestgehend abgeschlossen. ✓
|
||||
* [x] **Zeitplan:** Dynamische Verschiebung von Bewerben (Drag & Drop im Kalender). ✓
|
||||
* [x] **Protokoll:** Implementierung eines Event-Logs für manuelle Eingriffe in Startlisten (Audit-Log). ✓
|
||||
* [x] **Export:** Startlisten-Export für ZNS (XML-B-Satz). ✓
|
||||
|
||||
### PHASE 10: Series-Context & Stammdaten ✅ ABGESCHLOSSEN
|
||||
|
||||
*Ziel: Stammdaten-Integration (Reiter, Pferde, Funktionäre) und Series-Context (Cups).*
|
||||
|
||||
* [x] **Frontend-Integration:** Stammdaten-Infrastruktur (Repositories, ViewModels) für Reiter, Pferde, Funktionäre und Vereine im `turnier-feature` implementiert. ✓
|
||||
* [x] **Nennungs-Management:** Funktionalisierung des Nennungs-Tabs mit Echt-Datenanbindung und Suche. ✓
|
||||
* [x] **`series-context`:** Pluggable Berechnungsmodell (Streichresultate, Alles zählt), konfigurierbare Paar-Bindung (Reiter+Pferd vs. Einzelwertung) implementiert. ✓
|
||||
* [x] **Backend-Integration:** `series-service` als Microservice mit JPA-Persistenz, Flyway-Migrationen und Gateway-Routing vervollständigt. ✓
|
||||
|
||||
## 4. Geplante Phasen
|
||||
|
||||
### PHASE 11: Ergebniserfassung & Platzierung ✅ ABGESCHLOSSEN
|
||||
|
||||
*Ziel: Vollständige Ergebniserfassung und automatisierte Platzierungsberechnung.*
|
||||
|
||||
* [x] **Backend (Results):** Implementierung der Geschäftslogik für Wertnoten, Zeitfehler und ÖTO-konforme Platzierungen. ✓
|
||||
* [x] **Backend-Infrastruktur:** `results-service` in Docker-Compose und API-Gateway integriert; Service-Discovery via Consul aktiviert. ✓
|
||||
* [x] **Frontend UI:** `ErgebnisEditDialog` zur schnellen Ergebniserfassung und `TurnierErgebnislistenTab` zur Anzeige realer Ergebnisse. ✓
|
||||
* [x] **PDF-Export:** Generierung von PDF-Ergebnislisten (Bewerbe und Serien). ✓
|
||||
|
||||
### PHASE 12: Abrechnung & Billing 🔵 IN ARBEIT
|
||||
|
||||
*Ziel: Vollständige Kassa-Funktionalität und Turnier-Abrechnung.*
|
||||
|
||||
* [x] **Backend-Infrastruktur:** `billing-service` initialisiert, Docker-Integration und Gateway-Routing (Port 8087) konfiguriert. ✓
|
||||
* [x] **Frontend-Anbindung:** `BillingRepository` (Ktor) und `BillingViewModel` auf reale API-Kommunikation umgestellt. ✓
|
||||
* [x] **Buchungs-Logik:** Implementierung von Soll/Haben-Buchungen (Startgebühren, Nenngelder, Boxen). ✓
|
||||
* [x] **Offene Posten:** Liste aller unbezahlten Beträge pro Teilnehmer/Pferd. ✓
|
||||
* [x] **Rechnungserstellung:** Generierung von PDF-Rechnungen und Zahlungsbestätigungen. ✓
|
||||
* [x] **Kassa-Management:** Tagesabschluss, Storno-Logik und verschiedene Zahlungsarten. ✓
|
||||
|
||||
---
|
||||
|
||||
## 4. Geplante Phasen
|
||||
|
||||
### PHASE 13: Frontend-Modernisierung & Cleanup ✅ ABGESCHLOSSEN (20. April 2026)
|
||||
*Ziel: Finalisierung der Turnier-Daten, Rückübermittlung an den OEPS und architektonische Bereinigung.*
|
||||
|
||||
* [x] **"V2"-Bereinigung:** Vollständige Eliminierung aller "V2"-Suffixe in Dateinamen und Symbolen (z.B. `TurnierWizardV2`, `VeranstalterAuswahlV2`). ✓ (20. April 2026)
|
||||
* [x] **Plug-and-Play (Turnier):** Umstellung des `turnier-feature` auf ADR-0024. Entfernung von Reflection-Zugriffen auf die Shell und Einführung von ViewModel-Hoisting. ✓ (20. April 2026)
|
||||
* [x] **Plug-and-Play (Veranstalter):** Umstellung des `veranstalter-feature` auf ADR-0024. Einführung des `VeranstalterDetailViewModel` und Konsolidierung der Screens in der Desktop-Shell. ✓ (20. April 2026)
|
||||
* [x] **Device-Setup ("Lock-and-Edit"):** Einführung eines Review-Modus mit Konfigurations-Sperre, Drucker-Integration und Maskierung des SharedKeys. ✓ (20. April 2026)
|
||||
* [x] **Veranstaltungs-Wizard:** Implementierung eines 6-stufigen Profi-Workflows mit Sticky Preview-Card (WYSIWYG), ZNS-Guard und OEPS-Satznummer-Mapping. ✓ (20. April 2026)
|
||||
* [x] **Code-Hygiene:** Beseitigung von Code-Smells, redundanten Validierungen und ungenutzten Parametern in den zentralen Frontend-Modulen. ✓ (20. April 2026)
|
||||
* [x] **Connectivity-Diagnose:** Stabiles Diagnose-Tool für Backend-, DB- und Auth-Verbindung in der Desktop-App. ✓ (18. April 2026)
|
||||
* [x] **WASM-Transition:** Projektweite Umstellung auf JVM (Desktop) und wasmJs (Web). Eliminierung von `js(IR)`. ✓ (18. April 2026)
|
||||
* [x] **Geräte-Initialisierung:** Refactoring des Onboarding-Prozesses in das Plug-and-Play Modul `device-initialization`. ✓ (18. April 2026)
|
||||
* [ ] **XML-Export:** Vollständiger B-Satz Export (inkl. Ergebnisse und Platzierungen).
|
||||
* [ ] **ZNS-Portal:** Upload-Integration in das OEPS-ZNS.
|
||||
* [ ] **Archivierung:** Langzeit-Archivierung abgeschlossener Turniere.
|
||||
|
||||
---
|
||||
|
||||
## 5. Wichtige Architektur-Entscheidungen (ADRs)
|
||||
|
||||
| # | Entscheidung | Status | Dokument |
|
||||
|----|--------------------------------------------------------------|--------|------------------------------|
|
||||
| 1 | Vision_03 = Design-Baseline | ✅ | Session Log 2026-03-24 |
|
||||
| 2 | Desktop-First mit KMP/Compose Desktop | ✅ | ADR-0009 |
|
||||
| 3 | `Veranstaltung` ≠ `Turnier` (ÖTO § 2 Abs. 1) | ✅ | Ubiquitous Language |
|
||||
| 4 | 6 Bounded Contexts als SCS-Architektur | ✅ | Session Log 2026-03-24 |
|
||||
| 5 | `series-context` ist Phase 2+ (Architektur vorbereitet) | ✅ | Session Log 2026-03-24 |
|
||||
| 6 | Cups/Serien benötigen konfigurierbare Reglements | ✅ | Session Log 2026-03-24 |
|
||||
| 7 | Warn-Logik statt harter Fehler (Override-Event) | ✅ | Abteilungs-Schwellenwerte.md |
|
||||
| 8 | 6 Bounded Contexts: Mapping & Aggregate Roots | ✅ | ADR-0014 |
|
||||
| 9 | Context Map: Integration Patterns & ACL-Strategie | ✅ | ADR-0015 |
|
||||
| 10 | API-Design & ACL: Ports, DTOs, REST-Endpunkte, Domain Events | ✅ | ADR-0016 |
|
||||
| 11 | Masterdata: Importer-Einbettung als Worker | ✅ | ADR-0017 |
|
||||
| 12 | Masterdata: Rule-Versionierung (Regulation-as-Data) | ✅ | ADR-0018 |
|
||||
| 13 | Masterdata: API-Schichten (REST vs. Ingestion) | ✅ | ADR-0019 |
|
||||
| 14 | Lokale Netzwerk-Kommunikation und Daten-Isolierung | ✅ | ADR-0020 |
|
||||
| 15 | Masterdata: Observability & Operations | ✅ | masterdata-ops.md, CHANGELOG |
|
||||
| 16 | Tenant-Resolution: Schema-per-Tenant | ✅ | ADR-0021 |
|
||||
| 17 | LAN-Sync-Protokoll (Lamport-Uhren, Event-Sourcing Light) | ✅ | ADR-0022 |
|
||||
| 18 | Domain-Naming: Kein `Dom`-Präfix für Entitäten | ✅ | ADR-0023 |
|
||||
| 19 | Plug-and-Play Architektur für UI-Komponenten | ✅ | ADR-0024 |
|
||||
|
||||
---
|
||||
|
||||
## 5. Wichtige Referenzen
|
||||
|
||||
| Dokument | Pfad |
|
||||
|---------------------------|----------------------------------------------------------------------------------------------|
|
||||
| Ubiquitous Language | `docs/03_Domain/01_Glossary/Ubiquitous_Language.md` |
|
||||
| Abteilungs-Schwellenwerte | `docs/03_Domain/02_Reference/OETO_Regelwerk/Abteilungs-Trennungs-Schwellenwerte.md` |
|
||||
| Warn-Logik-Spezifikation | `docs/03_Domain/02_Reference/OETO_Regelwerk/Warn-Logik-Spezifikation-competition-context.md` |
|
||||
| Session Log (DDD) | `docs/99_Journal/2026-03-24_Session_Log_DDD_Ubiquitous_Language.md` |
|
||||
| Infrastruktur | `docs/07_Infrastructure/Zora_System_Architektur.md` |
|
||||
| Deployment Guide | `docs/07_Infrastructure/Guides/Setup_Git_Deployment_Zora.md` |
|
||||
| Backup Guide | `docs/07_Infrastructure/Guides/Setup_Backup_Zora.md` |
|
||||
| CI/CD | `.gitea/workflows/docker-publish.yaml` |
|
||||
| Agent Playbooks | `docs/04_Agents/Playbooks/` |
|
||||
| ADR-Verzeichnis | `docs/01_Architecture/adr/` |
|
||||
| ZNS-Importer Roadmap | `docs/01_Architecture/Roadmap_ZNS_Importer.md` |
|
||||
| Masterdata Roadmap | `backend/services/masterdata/docs/ROADMAP.md` |
|
||||
| Masterdata Changelog | `backend/services/masterdata/docs/CHANGELOG.md` |
|
||||
| Masterdata Operations | `backend/services/masterdata/docs/runbooks/masterdata-ops.md` |
|
||||
| Zeitplan-Optimierung | `docs/01_Architecture/konzept-zeitplan-optimierung-de.md` |
|
||||
| Parcoursbesichtigung-Rulebook | `docs/01_Architecture/rulebook-check-parcoursbesichtigung-de.md` |
|
||||
| Status-Automat-Nennungen | `docs/01_Architecture/status-automat-nennungen-de.md` |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 3. Zukünftige Phase (April 2026)
|
||||
|
||||
### PHASE 5: Web-App & Neumarkt-Vorbereitung 🔵 IN ARBEIT (Start 13. April 2026)
|
||||
|
||||
*Ziel: Fertigstellung der Web-App für Online-Nennungen und Vorbereitung des Neumarkt-Turniers (24. April).*
|
||||
|
||||
#### 🎨 Agent: Frontend Expert
|
||||
* [x] **Web-App Shell:** Modul `frontend:shells:meldestelle-web` (Compose WasmJS) initialisiert.
|
||||
* [x] **UI-Komponenten:** `VeranstaltungsCard` und `TurnierCard` für Web implementiert (mit PDF- & Nenn-Button).
|
||||
* [x] **Workflow:** `NennungWebFormular` Prototyp erstellt (mit simuliertem Mail-Versand).
|
||||
|
||||
#### 👷 Agent: Backend Developer
|
||||
* [x] **Daten-Seeding:** Desktop-Stores mit echten Daten für Neumarkt (April 2026) vorbefüllt.
|
||||
* [ ] **Mail-Service:** Integration eines E-Mail-Dienstes für eingehende Nennungen.
|
||||
|
||||
#### 🧐 Agent: QA Specialist
|
||||
* [x] **Verifikation:** Desktop-Screens (Veranstalter, Turnier, Bewerbe) mit echten Daten geprüft.
|
||||
* [ ] **End-to-End Test:** Online-Nennung (Web) -> E-Mail -> Desktop-Verarbeitung.
|
||||
|
||||
---
|
||||
|
||||
### PHASE 5: Desktop-Zentrale & Synchronisation 🔵 IN ARBEIT
|
||||
|
||||
*Ziel: Ein einsatzbereiter Desktop-Client für das Neumarkt-Turnier.*
|
||||
|
||||
#### 🎨 Agent: Frontend Expert
|
||||
|
||||
* [x] **Onboarding UI:** Implementierung des Onboarding-Screens (Name, Key, Backup, Rolle, Sync, Drucker) mit
|
||||
validierten Eingaben.
|
||||
* [x] **Navigation:** Navigations-Rail mit Hover-Tooltips und dedizierten Icons für "Setup" und "Sync".
|
||||
* [x] **Settings:** Persistente Speicherung der Onboarding-Daten in `settings.json`.
|
||||
|
||||
#### 👷 Agent: Backend Developer
|
||||
|
||||
* [x] **Device Management:** Domain-Modell (`Device`), Tabelle (`identity_devices`) und Repository zur
|
||||
Geräteverwaltung implementiert.
|
||||
* [x] **Security Key Auth:** Implementierung des `DeviceSecurityFilter` zur Authentifizierung via `X-Security-Key`
|
||||
Header.
|
||||
* [x] **Onboarding API:** REST-Endpunkte zur Registrierung und Abfrage von Desktop-Instanzen erstellt.
|
||||
|
||||
#### 🧹 Agent: Curator
|
||||
|
||||
* [x] **Dokumentation:** Erstellung der Architektur-Doku für das Onboarding-Backend.
|
||||
| Dokument | Pfad |
|
||||
|-------------------------------|----------------------------------------------------------------------------------------------|
|
||||
| Ubiquitous Language | `docs/03_Domain/01_Glossary/Ubiquitous_Language.md` |
|
||||
| Abteilungs-Schwellenwerte | `docs/03_Domain/02_Reference/OETO_Regelwerk/Abteilungs-Trennungs-Schwellenwerte.md` |
|
||||
| Warn-Logik-Spezifikation | `docs/03_Domain/02_Reference/OETO_Regelwerk/Warn-Logik-Spezifikation-competition-context.md` |
|
||||
| Session Log (DDD) | `docs/99_Journal/2026-03-24_Session_Log_DDD_Ubiquitous_Language.md` |
|
||||
| Infrastruktur | `docs/07_Infrastructure/Zora_System_Architektur.md` |
|
||||
| Deployment Guide | `docs/07_Infrastructure/Guides/Setup_Git_Deployment_Zora.md` |
|
||||
| Backup Guide | `docs/07_Infrastructure/Guides/Setup_Backup_Zora.md` |
|
||||
| CI/CD | `.gitea/workflows/docker-publish.yaml` |
|
||||
| Agent Playbooks | `docs/04_Agents/Playbooks/` |
|
||||
| ADR-Verzeichnis | `docs/01_Architecture/adr/` |
|
||||
| ADR-0025: Plan-USB | `docs/01_Architecture/adr/0025-plan-usb-offline-integritaet.md` |
|
||||
| ADR-0026: Lizenzierung | `docs/01_Architecture/adr/0026-offline-lizenzierung-pay-per-event.md` |
|
||||
| ADR-0027: Discovery | `docs/01_Architecture/adr/0027-netzwerk-discovery-interface-binding.md` |
|
||||
| Docker-Fix: dc-gui.yaml | `dc-gui.yaml` |
|
||||
| ZNS-Importer Roadmap | `docs/01_Architecture/Roadmaps/Roadmap_ZNS_Importer.md` |
|
||||
| Masterdata Roadmap | `backend/services/masterdata/docs/ROADMAP.md` |
|
||||
| Masterdata Changelog | `backend/services/masterdata/docs/CHANGELOG.md` |
|
||||
| Masterdata Operations | `backend/services/masterdata/docs/runbooks/masterdata-ops.md` |
|
||||
| Zeitplan-Optimierung | `docs/01_Architecture/Concepts/konzept-zeitplan-optimierung-de.md` |
|
||||
| Parcoursbesichtigung-Rulebook | `docs/01_Architecture/Concepts/rulebook-check-parcoursbesichtigung-de.md` |
|
||||
| Status-Automat-Nennungen | `docs/01_Architecture/Concepts/status-automat-nennungen-de.md` |
|
||||
|
||||
@@ -1,358 +0,0 @@
|
||||
---
|
||||
type: Reference
|
||||
status: ACTIVE
|
||||
owner: Lead Architect
|
||||
date: 2026-03-07
|
||||
---
|
||||
# Meldestelle — Tech-Stack Zusammenfassung
|
||||
|
||||
> **Zweck:** Vollständige Referenz des eingesetzten Tech-Stacks im Projekt "Meldestelle".
|
||||
> Dient als Basis für Recherchen zu Self-Hosted AI (Codegenerierung, RAG, Agenten).
|
||||
> **Stand:** 07. März 2026
|
||||
|
||||
---
|
||||
|
||||
## 1. Überblick
|
||||
|
||||
Das Projekt "Meldestelle" ist eine **Kotlin-first, Cloud-native Microservices-Plattform** für die Verwaltung von Reitsport-Meldungen (FEI / ÖTO). Es kombiniert ein **Kotlin Multiplatform (KMP) Frontend** mit einem **Spring Boot Microservices Backend** auf einer vollständig self-hosted Infrastruktur.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Frontend (KMP) │ Backend (Spring Boot / Kotlin JVM) │
|
||||
│ Kotlin 2.3 / Compose │ Java 25 / Spring Boot 3.5.9 │
|
||||
│ JS + WASM (geplant) │ Microservices + API-Gateway │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Infrastruktur (Self-Hosted auf Zora / Proxmox) │
|
||||
│ Keycloak · Consul · Valkey · PostgreSQL · Zipkin │
|
||||
│ Prometheus · Grafana · Caddy · Pangolin-Tunnel │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Sprachen & Laufzeiten
|
||||
|
||||
| Komponente | Sprache / Runtime | Version |
|
||||
|:------------------|:-------------------------|:------------|
|
||||
| Backend | Kotlin (JVM) | 2.3.0 |
|
||||
| Frontend | Kotlin (KMP / JS) | 2.3.0 |
|
||||
| JVM | Java (Eclipse Temurin) | 25 (EA) |
|
||||
| Build | Gradle (Kotlin DSL) | 9.3.1 |
|
||||
| Plattform | ARM64 (AArch64) | Linux |
|
||||
|
||||
---
|
||||
|
||||
## 3. Frontend — Kotlin Multiplatform (KMP)
|
||||
|
||||
### 3.1 Core-Framework
|
||||
|
||||
| Bibliothek | Version | Zweck |
|
||||
|:------------------------------|:----------|:-----------------------------------|
|
||||
| Kotlin Multiplatform | 2.3.0 | Cross-Platform-Basis (JS + WASM) |
|
||||
| Compose Multiplatform | 1.10.0 | UI-Framework (Deklarativ) |
|
||||
| Compose Hot Reload | 1.0.0 | Live-Reload im Dev-Modus |
|
||||
| Koin (DI) | 4.1.1 | Dependency Injection |
|
||||
| Koin Compose | 4.1.1 | DI-Integration für Compose |
|
||||
| Ktor Client | 3.4.0 | HTTP-Client (Multiplatform) |
|
||||
| Kotlin Serialization | 2.3.0 | JSON-Serialisierung |
|
||||
|
||||
### 3.2 Persistenz (Offline-First)
|
||||
|
||||
| Bibliothek | Version | Zweck |
|
||||
|:------------------------------|:----------|:-----------------------------------|
|
||||
| SQLDelight | 2.2.1 | Cross-Platform SQL-Datenbank |
|
||||
| SQLite (WASM) | 3.51.1 | SQLite für Browser/WASM |
|
||||
| SQLite (Native) | 2.6.2 | SQLite für JVM/Desktop |
|
||||
|
||||
### 3.3 Build-Targets
|
||||
|
||||
| Target | Status | Anmerkung |
|
||||
|:--------------|:------------|:-----------------------------------|
|
||||
| KotlinJS | ✅ Aktiv | Primäres Build-Target |
|
||||
| WASM | ⏳ Geplant | Warten auf Alpha-Version |
|
||||
| Desktop (JVM) | ⚙️ Möglich | uiDesktop 1.7.0 vorhanden |
|
||||
|
||||
### 3.4 Modul-Struktur
|
||||
|
||||
```
|
||||
frontend/
|
||||
├── core/
|
||||
│ ├── core-network/ # Ktor HTTP-Client, Auth-Interceptor
|
||||
│ ├── core-ui/ # Design-System, Tokens, Komponenten
|
||||
│ ├── core-domain/ # Shared Domain-Models
|
||||
│ └── core-data/ # Repository-Interfaces
|
||||
├── features/
|
||||
│ ├── ping-feature/ # ✅ Blueprint: MVVM + Repository + DI + Tests
|
||||
│ └── members-feature/ # ⏳ Auskommentiert (nächste Phase)
|
||||
└── shells/
|
||||
└── meldestelle-portal/ # Web-App Shell (Caddy-served)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Backend — Spring Boot Microservices
|
||||
|
||||
### 4.1 Core-Framework
|
||||
|
||||
| Bibliothek | Version | Zweck |
|
||||
|:------------------------------|:----------|:-----------------------------------|
|
||||
| Spring Boot | 3.5.9 | Microservices-Framework |
|
||||
| Spring Cloud | 2025.0.1 | Service Discovery, Config |
|
||||
| Spring Security (OAuth2) | (Boot) | JWT-Validierung, Resource Server |
|
||||
| Spring Data JPA | (Boot) | ORM-Layer |
|
||||
| Spring Data Valkey | 0.2.0 | Cache-Integration (Valkey/Redis) |
|
||||
| Spring WebFlux | (Boot) | Reaktive API (Gateway) |
|
||||
| Kotlin Coroutines | 2.3.0 | Async/Non-blocking |
|
||||
|
||||
### 4.2 Persistenz
|
||||
|
||||
| Bibliothek | Version | Zweck |
|
||||
|:------------------------------|:----------|:-----------------------------------|
|
||||
| PostgreSQL Driver | 42.7.8 | JDBC-Treiber |
|
||||
| Exposed (JetBrains) | 1.0.0 | Kotlin-native SQL DSL |
|
||||
| Flyway | 11.19.1 | Datenbank-Migrationen |
|
||||
| HikariCP | 7.0.2 | Connection Pool |
|
||||
|
||||
> **Strategie (ADR-001):** Hybrid — JPA für einfache CRUD-Entities, Exposed für komplexe Queries und Domain-Logik.
|
||||
|
||||
### 4.3 Caching & Messaging
|
||||
|
||||
| Bibliothek | Version | Zweck |
|
||||
|:------------------------------|:----------|:-----------------------------------|
|
||||
| Lettuce | 6.6.0 | Valkey/Redis-Client (reaktiv) |
|
||||
| Redisson | 4.0.0 | Distributed Locks, Pub/Sub |
|
||||
| Caffeine | 3.2.3 | In-Memory Cache (L1) |
|
||||
| Reactor Kafka | 1.3.23 | Kafka-Client (Phase 3 / Outbox) |
|
||||
|
||||
### 4.4 Observability & Tracing
|
||||
|
||||
| Bibliothek | Version | Zweck |
|
||||
|:------------------------------|:----------|:-----------------------------------|
|
||||
| Micrometer | 1.16.1 | Metriken (Prometheus-Export) |
|
||||
| Micrometer Tracing | 1.6.1 | Distributed Tracing |
|
||||
| Zipkin Reporter | 3.5.1 | Trace-Export zu Zipkin |
|
||||
| Logback | 1.5.25 | Logging |
|
||||
|
||||
### 4.5 Security
|
||||
|
||||
| Bibliothek | Version | Zweck |
|
||||
|:------------------------------|:----------|:-----------------------------------|
|
||||
| Keycloak Admin Client | 26.0.7 | Keycloak-API-Integration |
|
||||
| Spring Security OAuth2 | (Boot) | JWT Resource Server |
|
||||
| Jackson (Kotlin) | 3.0.3 | JSON-Serialisierung |
|
||||
|
||||
### 4.6 API & Dokumentation
|
||||
|
||||
| Bibliothek | Version | Zweck |
|
||||
|:------------------------------|:----------|:-----------------------------------|
|
||||
| Springdoc OpenAPI | 3.0.0 | Swagger / OpenAPI 3.1 |
|
||||
| Jakarta Annotation | 3.0.0 | Jakarta EE Annotations |
|
||||
|
||||
### 4.7 Modul-Struktur
|
||||
|
||||
```
|
||||
backend/
|
||||
├── infrastructure/
|
||||
│ ├── gateway/ # ✅ API-Gateway (Spring Cloud Gateway)
|
||||
│ ├── security/ # ✅ Zentrales OAuth2/JWT-Modul (DRY)
|
||||
│ ├── cache/
|
||||
│ │ ├── cache-api/ # Interface-Abstraktion
|
||||
│ │ └── valkey-impl/ # Valkey-Implementierung
|
||||
│ ├── event-store/
|
||||
│ │ ├── event-store-api/ # Interface-Abstraktion
|
||||
│ │ └── valkey-impl/ # Valkey-Implementierung
|
||||
│ ├── persistence/ # Hybrid JPA + Exposed
|
||||
│ └── messaging/ # Kafka (Phase 3 / Outbox-Pattern)
|
||||
└── services/
|
||||
├── ping/ # ✅ Deployed — Test/Blueprint-Service
|
||||
├── entries/ # ⚙️ Registriert, noch nicht deployed
|
||||
├── events/ # 👻 Ghost Service (nicht registriert)
|
||||
├── horses/ # 👻 Ghost Service (nicht registriert)
|
||||
├── masterdata/ # 👻 Ghost Service (nicht registriert)
|
||||
├── registry/ # 👻 Ghost Service (nicht registriert)
|
||||
├── results/ # 👻 Ghost Service (nicht registriert)
|
||||
└── scheduling/ # 👻 Ghost Service (nicht registriert)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Infrastruktur-Services (Docker)
|
||||
|
||||
### 5.1 Laufende Services
|
||||
|
||||
| Service | Image / Version | Port(s) | Zweck |
|
||||
|:---------------|:--------------------------|:--------------|:-----------------------------|
|
||||
| PostgreSQL | postgres:16-alpine | 5432 | Primäre Datenbank |
|
||||
| Keycloak | keycloak:26.4 (custom) | 8180, 9000 | IAM / OAuth2 / OIDC |
|
||||
| Valkey | valkey:8-alpine | 6379 | Cache + Event-Store |
|
||||
| Consul | consul:1.21 | 8500, 8600 | Service Discovery + Config |
|
||||
| Zipkin | openzipkin/zipkin:3.5 | 9411 | Distributed Tracing |
|
||||
| Prometheus | prom/prometheus:v3.4 | 9090 | Metriken-Sammlung |
|
||||
| Grafana | grafana/grafana:11.6 | 3000 | Dashboards / Visualisierung |
|
||||
| Caddy | caddy:2.10-alpine | 4000 | Web-App Serving (Frontend) |
|
||||
| API-Gateway | (custom Spring Boot) | 8081 | Zentraler Eintrittspunkt |
|
||||
| Ping-Service | (custom Spring Boot) | 8082 | Test/Blueprint-Service |
|
||||
|
||||
### 5.2 CI/CD & DevOps
|
||||
|
||||
| Tool | Version / Details | Zweck |
|
||||
|:----------------|:--------------------------|:-----------------------------|
|
||||
| Gitea | Self-Hosted (CT 101) | Git-Repository + Registry |
|
||||
| Gitea Actions | (Runner VM 102) | CI/CD-Pipeline |
|
||||
| Docker Buildx | ARM64 (linux/arm64) | Multi-Arch Image Build |
|
||||
| Pangolin | Self-Hosted Tunnel | Reverse Proxy / Extern-Zugang|
|
||||
|
||||
### 5.3 Netzwerk & Routing
|
||||
|
||||
| Subdomain | Intern (Zora) | Zweck |
|
||||
|:-----------------------|:--------------------|:-------------------------|
|
||||
| `git.mo-code.at` | `10.0.0.22:3000` | Gitea |
|
||||
| `api.mo-code.at` | `10.0.0.50:8081` | API-Gateway |
|
||||
| `auth.mo-code.at` | `10.0.0.50:8180` | Keycloak |
|
||||
| `app.mo-code.at` | `10.0.0.50:4000` | Web-App |
|
||||
| `photos.mo-code.at` | `10.0.0.24:2283` | Immich (Fotos) |
|
||||
|
||||
---
|
||||
|
||||
## 6. Code-Qualität & Build-Tools
|
||||
|
||||
| Tool | Version | Zweck |
|
||||
|:------------------|:----------|:-----------------------------------|
|
||||
| Detekt | 1.23.6 | Kotlin Static Analysis |
|
||||
| ktlint | 12.1.1 | Kotlin Code Formatter |
|
||||
| ArchUnit | 1.4.1 | Architektur-Tests (Layer-Regeln) |
|
||||
| Dokka | 2.1.0 | API-Dokumentation (KDoc) |
|
||||
| Ben-Manes Versions| 0.51.0 | Dependency-Update-Check |
|
||||
| KSP | 2.3.4 | Kotlin Symbol Processing |
|
||||
|
||||
### Build-Konfiguration
|
||||
|
||||
```properties
|
||||
# gradle.properties
|
||||
org.gradle.parallel=true
|
||||
org.gradle.caching=true
|
||||
org.gradle.workers.max=8
|
||||
org.gradle.configuration-cache=false # wegen JS-Test Serialisierungsproblem
|
||||
org.gradle.dependency.verification=strict
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Test-Stack
|
||||
|
||||
| Bibliothek | Version | Zweck |
|
||||
|:------------------------------|:----------|:-----------------------------------|
|
||||
| JUnit Jupiter | 5.11.3 | Unit-Tests |
|
||||
| JUnit Platform | 1.11.3 | Test-Runner |
|
||||
| MockK | 1.14.7 | Kotlin Mocking |
|
||||
| AssertJ | 3.27.7 | Fluent Assertions |
|
||||
| Testcontainers | 2.0.3 | Integration-Tests (Docker) |
|
||||
| Testcontainers Keycloak | 4.0.1 | Keycloak-Integration-Tests |
|
||||
| Testcontainers PostgreSQL | 1.21.4 | DB-Integration-Tests |
|
||||
| Testcontainers Kafka | 1.21.4 | Kafka-Integration-Tests |
|
||||
| ArchUnit | 1.4.1 | Architektur-Compliance-Tests |
|
||||
|
||||
---
|
||||
|
||||
## 8. Architektur-Prinzipien (ADRs)
|
||||
|
||||
| ADR | Entscheidung | Status |
|
||||
|:------|:--------------------------------------------------|:---------|
|
||||
| 0001 | Modulare Architektur (DDD, Clean Architecture) | ✅ Aktiv |
|
||||
| 0003 | Microservices-Architektur | ✅ Aktiv |
|
||||
| 0004 | Event-Driven Communication (Kafka Phase 3) | ✅ Aktiv |
|
||||
| 001 | Backend-Infrastruktur: Hybrid JPA+Exposed, Valkey | ✅ Aktiv |
|
||||
| 0013 | Tech-Stack-Stabilisierung 2026 (Versionen) | ✅ Aktiv |
|
||||
|
||||
**Kern-Prinzipien:**
|
||||
- **Offline-First:** SQLDelight als Cross-Platform-DB, Sync-Mechanismus
|
||||
- **Docs-as-Code:** `/docs` als Single Source of Truth
|
||||
- **DRY-Infrastruktur:** Shared Security/Cache/EventStore-Module
|
||||
- **ARM64-Native:** Alle Images für `linux/arm64` gebaut
|
||||
|
||||
---
|
||||
|
||||
## 9. Relevanz für Self-Hosted AI
|
||||
|
||||
### 9.1 Welche AI-Aufgaben entstehen im Projekt?
|
||||
|
||||
| Aufgabe | Häufigkeit | Komplexität |
|
||||
|:---------------------------------|:-----------|:------------|
|
||||
| Kotlin/Spring Boot Code-Completion| Täglich | Mittel |
|
||||
| Compose Multiplatform UI-Code | Täglich | Mittel |
|
||||
| SQL / Exposed DSL Queries | Häufig | Mittel |
|
||||
| Gradle Kotlin DSL Build-Skripte | Gelegentlich| Niedrig |
|
||||
| Docker / YAML Konfigurationen | Gelegentlich| Niedrig |
|
||||
| Architektur-Entscheidungen (ADR) | Selten | Hoch |
|
||||
| Fachlogik FEI/ÖTO Regelwerk | Selten | Sehr hoch |
|
||||
|
||||
### 9.2 Anforderungen an das AI-Modell
|
||||
|
||||
```
|
||||
MUSS:
|
||||
✅ Kotlin (JVM + Multiplatform) — sehr gute Unterstützung
|
||||
✅ Spring Boot / Spring Cloud — sehr gute Unterstützung
|
||||
✅ Compose Multiplatform — gute Unterstützung (neuere Modelle)
|
||||
✅ SQL / PostgreSQL — sehr gute Unterstützung
|
||||
✅ Docker / YAML — sehr gute Unterstützung
|
||||
✅ Deutsch (Fachsprache Reitsport) — für RAG-Dokumente
|
||||
|
||||
NICE-TO-HAVE:
|
||||
⭐ Gradle Kotlin DSL
|
||||
⭐ Keycloak / OAuth2 / OIDC
|
||||
⭐ Microservices-Architektur-Patterns
|
||||
```
|
||||
|
||||
### 9.3 Empfohlene Modelle für diesen Stack
|
||||
|
||||
| Modell | Größe | Stärke | RAM-Bedarf |
|
||||
|:------------------------|:-------|:------------------------------------|:-----------|
|
||||
| `qwen2.5-coder:14b` | 14B | Code (Kotlin, Java, SQL) — Top | ~10 GB |
|
||||
| `deepseek-coder-v2:16b` | 16B | Code-Completion, Refactoring | ~12 GB |
|
||||
| `llama3.1:8b` | 8B | Allgemein + Deutsch, schnell | ~6 GB |
|
||||
| `qwen2.5:32b` | 32B | Architektur, Planung, Fachlogik | ~22 GB |
|
||||
| `codellama:13b` | 13B | Code-Completion (IntelliJ-Plugin) | ~9 GB |
|
||||
|
||||
> **Empfehlung für Zora (64 GB RAM):**
|
||||
> - **Primär:** `qwen2.5-coder:14b` — bester Kotlin/Spring-Support
|
||||
> - **Sekundär:** `qwen2.5:32b` — für Architektur und Fachlogik
|
||||
> - **IntelliJ-Integration:** `codellama:13b` oder `qwen2.5-coder:14b`
|
||||
|
||||
### 9.4 RAG-Dokumente (Priorität)
|
||||
|
||||
Folgende Projekt-Dokumente sind besonders wertvoll als RAG-Kontext:
|
||||
|
||||
```
|
||||
Hohe Priorität:
|
||||
├── docs/01_Architecture/MASTER_ROADMAP_2026_Q1.md
|
||||
├── docs/01_Architecture/adr/ (alle ADRs)
|
||||
├── docs/04_Agents/Playbooks/ (Agenten-Rollen)
|
||||
├── gradle/libs.versions.toml (Versions-SSoT)
|
||||
└── docs/07_Infrastructure/ (Infrastruktur-Referenz)
|
||||
|
||||
Mittlere Priorität:
|
||||
├── docs/05_Backend/ (Backend-Guides)
|
||||
├── docs/06_Frontend/ (Frontend-Guides)
|
||||
└── docs/03_Domain/ (Fachlogik-Konzepte)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Zusammenfassung
|
||||
|
||||
```
|
||||
TECH-STACK KOMPLEXITÄT
|
||||
──────────────────────────────────────────────────────
|
||||
Sprachen: Kotlin (JVM + KMP/JS)
|
||||
Build: Gradle 9.3.1 + Kotlin DSL + libs.versions.toml
|
||||
Frontend: Compose Multiplatform 1.10 + SQLDelight 2.2 + Koin 4.1
|
||||
Backend: Spring Boot 3.5.9 + Spring Cloud 2025.0.1
|
||||
Persistenz: PostgreSQL 16 + Exposed 1.0 + Flyway 11 + HikariCP 7
|
||||
Cache: Valkey 8 + Lettuce 6.6 + Caffeine 3.2
|
||||
Security: Keycloak 26.4 + Spring Security OAuth2 + JWT
|
||||
Observability: Micrometer 1.16 + Zipkin 3.5 + Prometheus + Grafana 11.6
|
||||
Service Mesh: Consul 1.21 + Spring Cloud Gateway
|
||||
Messaging: Kafka (Phase 3) + Reactor Kafka 1.3
|
||||
CI/CD: Gitea Actions + Docker Buildx (ARM64)
|
||||
Hosting: Proxmox VE 8.4 + Docker Compose + Pangolin-Tunnel
|
||||
```
|
||||
@@ -5,23 +5,23 @@ owner: Lead Architect
|
||||
date: 2026-02-02
|
||||
---
|
||||
|
||||
# Engineering Moderner Frontend-Architekturen: Kotlin 2.3.0, Compose Multiplatform 1.10.0 und Gradle 9.0 für Modulare Monolithen
|
||||
# Engineering Moderner Frontend-Architekturen: Kotlin 2.3.21, Compose Multiplatform 1.10.0 und Gradle 9.5.0 für Modulare Monolithen
|
||||
|
||||
Der architektonische Übergang zu modularen Monolithen bietet Unternehmen die Möglichkeit, die Komplexität von
|
||||
Microservices zu reduzieren und gleichzeitig eine klare Trennung der Domänenlogik beizubehalten. In Kombination mit
|
||||
Kotlin Multiplatform (KMP) für Single Page Applications (SPAs) lässt sich Geschäftslogik effizient über den gesamten
|
||||
Stack teilen. Die Einführung von Kotlin 2.3.0, Compose Multiplatform 1.10.0 und Gradle 9.0 stellt dabei neue Best
|
||||
Stack teilen. Die Einführung von Kotlin 2.3.21, Compose Multiplatform 1.10.0 und Gradle 9.5.0 stellt dabei neue Best
|
||||
Practices für Build-Performance und Deployment auf.
|
||||
|
||||
## 1. Gradle 9.x Optimierung in der CI/CD
|
||||
|
||||
Gradle 9.0 führt signifikante Änderungen ein, die speziell für große Multi-Modul-Projekte wie modulare Monolithen
|
||||
Gradle 9.5.0 führt signifikante Änderungen ein, die speziell für große Multi-Modul-Projekte wie modulare Monolithen
|
||||
optimiert sind.
|
||||
|
||||
- **Configuration Cache als Standard:** In Gradle 9.0 ist der Configuration Cache der bevorzugte Ausführungsmodus. Durch
|
||||
- **Configuration Cache als Standard:** In Gradle 9.5.0 ist der Configuration Cache der bevorzugte Ausführungsmodus. Durch
|
||||
das Caching des Task-Graphen werden nachfolgende Builds erheblich beschleunigt, da die Konfigurationsphase
|
||||
übersprungen wird.
|
||||
- **Kotlin DSL Script Compilation Avoidance:** Durch den Einsatz von ABI-Fingerprinting erkennt Gradle 9.0, ob
|
||||
- **Kotlin DSL Script Compilation Avoidance:** Durch den Einsatz von ABI-Fingerprinting erkennt Gradle 9.5.0, ob
|
||||
Änderungen an `.kts`-Dateien die Build-Logik tatsächlich beeinflussen. Nicht-relevante Änderungen (wie Kommentare)
|
||||
führen nicht mehr zur Neukompilierung, was die Konfigurationszeit um bis zu 60 % reduzieren kann.
|
||||
- **Parallel Configuration Store and Load:** Gradle 8.11 und 9.0 unterstützen das parallele Laden und Speichern von
|
||||
@@ -74,14 +74,14 @@ Die Wahl des Webservers beeinflusst das Routing und die Performance der Compose
|
||||
|
||||
| Komponente | Empfehlung | Vorteil |
|
||||
|---------------|-------------------------------------|--------------------------------------------------------|
|
||||
| Build-Tool | Gradle 9.0 mit Configuration Cache | Extreme Verkürzung der Konfigurationsphase |
|
||||
| Build-Tool | Gradle 9.5.0 mit Configuration Cache | Extreme Verkürzung der Konfigurationsphase |
|
||||
| CI Caching | Remote Cache Action (Proxy) | Wiederverwendung von Task-Outputs auf frischen Runnern |
|
||||
| Konfiguration | Runtime config.json Fetch | Ein Docker-Image für alle Umgebungen (Dev/Prod) |
|
||||
| Webserver | Caddy oder Nginx | Optimiertes SPA-Routing und Web Cache Support |
|
||||
|
||||
## Fazit
|
||||
|
||||
Die Kombination aus Gradle 9.0 und Kotlin 2.3.0 ermöglicht hocheffiziente Build-Pipelines für modulare Monolithen. Durch
|
||||
Die Kombination aus Gradle 9.5.0 und Kotlin 2.3.21 ermöglicht hocheffiziente Build-Pipelines für modulare Monolithen. Durch
|
||||
den Einsatz von Multi-Stage Docker-Builds und dem `config.json`-Fetch-Muster wird eine moderne, skalierbare
|
||||
Deployment-Strategie umgesetzt, die die neuen Performance-Features von Compose Multiplatform 1.10.0 optimal nutzt.
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ Hier ist der Quellcode des Berichts im Markdown-Format:
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
Die Softwareentwicklungslandschaft des Jahres 2026, geprägt durch die Veröffentlichung von Kotlin 2.3.0 und Gradle 9.1.0, bietet Entwicklern beispiellose Möglichkeiten zur Vereinheitlichung komplexer Geschäftslogik über Plattformgrenzen hinweg. Dieser Forschungsbericht analysiert detailliert die architektonischen Muster, Implementierungsstrategien und zugrundeliegenden Mechanismen, die für den Aufbau einer robusten, asynchronen Offline-First-Anwendung erforderlich sind. Der Fokus liegt hierbei auf der Integration von SQLDelight in einer Kotlin Multiplatform (KMP) Umgebung, die sowohl Desktop (JVM) als auch Web (Kotlin/JS) Ziele bedient, eingebettet in eine Mikro-Frontend-Architektur.
|
||||
Die Softwareentwicklungslandschaft des Jahres 2026, geprägt durch die Veröffentlichung von Kotlin 2.3.21 und Gradle 9.5.0, bietet Entwicklern beispiellose Möglichkeiten zur Vereinheitlichung komplexer Geschäftslogik über Plattformgrenzen hinweg. Dieser Forschungsbericht analysiert detailliert die architektonischen Muster, Implementierungsstrategien und zugrundeliegenden Mechanismen, die für den Aufbau einer robusten, asynchronen Offline-First-Anwendung erforderlich sind. Der Fokus liegt hierbei auf der Integration von SQLDelight in einer Kotlin Multiplatform (KMP) Umgebung, die sowohl Desktop (JVM) als auch Web (Kotlin/JS) Ziele bedient, eingebettet in eine Mikro-Frontend-Architektur.
|
||||
|
||||
Ein zentraler Schwerpunkt dieser Arbeit ist die Überbrückung der Dichotomie zwischen der synchronen Natur klassischer JVM-Datenbanktreiber und der inhärent asynchronen, Event-Loop-basierten Umgebung des modernen Web (insbesondere unter Nutzung von Web Workern und OPFS). Darüber hinaus wird die fortgeschrittene Integration von Persistenzschichten in einem Mikro-Frontend-Ökosystem untersucht, um sicherzustellen, dass eine einzige Quelle der Wahrheit („Single Source of Truth“) über unabhängig bereitgestellte Frontend-Einheiten hinweg konsistent bleibt.
|
||||
|
||||
@@ -17,11 +17,11 @@ Ein zentraler Schwerpunkt dieser Arbeit ist die Überbrückung der Dichotomie zw
|
||||
|
||||
### 1.1 Die Evolution von Kotlin Multiplatform
|
||||
|
||||
Mit der Veröffentlichung von Kotlin 2.3.0 im Dezember 2025 hat sich das Ökosystem von einer experimentellen Technologie zu einem stabilen Standard für Enterprise-Architekturen entwickelt. Während frühere Versionen oft mit Inkonsistenzen zwischen den Compilern (JVM vs. JS/Native) zu kämpfen hatten, bietet der K2-Compiler in Version 2.3.0 eine vereinheitlichte Frontend-IR (Intermediate Representation), die eine robustere statische Analyse und performantere Kompilierung ermöglicht. Dies ist entscheidend für komplexe Multi-Modul-Projekte, wie sie in Mikro-Frontend-Architekturen üblich sind.
|
||||
Mit der Veröffentlichung von Kotlin 2.3.21 im Dezember 2025 hat sich das Ökosystem von einer experimentellen Technologie zu einem stabilen Standard für Enterprise-Architekturen entwickelt. Während frühere Versionen oft mit Inkonsistenzen zwischen den Compilern (JVM vs. JS/Native) zu kämpfen hatten, bietet der K2-Compiler in Version 2.3.21 eine vereinheitlichte Frontend-IR (Intermediate Representation), die eine robustere statische Analyse und performantere Kompilierung ermöglicht. Dies ist entscheidend für komplexe Multi-Modul-Projekte, wie sie in Mikro-Frontend-Architekturen üblich sind.
|
||||
|
||||
### 1.2 Gradle 9.1.0: Die Build-Infrastruktur
|
||||
### 1.2 Gradle 9.5.0: Die Build-Infrastruktur
|
||||
|
||||
Gradle 9.1.0, veröffentlicht im September 2025, hat die Art und Weise, wie KMP-Projekte konfiguriert werden, grundlegend verändert. Mit der vollständigen Unterstützung des „Configuration Cache“ und der strikten „Project Isolation“ zwingt es Entwickler zu sauberen Modulgrenzen. Für unser Szenario bedeutet dies, dass die Abhängigkeiten zwischen dem `shared`-Modul (Datenbank) und den konsumierenden Mikro-Frontends explizit und ohne Seiteneffekte definiert werden müssen, um die parallele Ausführung und inkrementelle Kompilierung nicht zu gefährden.
|
||||
Gradle 9.5.0, veröffentlicht im September 2025, hat die Art und Weise, wie KMP-Projekte konfiguriert werden, grundlegend verändert. Mit der vollständigen Unterstützung des „Configuration Cache“ und der strikten „Project Isolation“ zwingt es Entwickler zu sauberen Modulgrenzen. Für unser Szenario bedeutet dies, dass die Abhängigkeiten zwischen dem `shared`-Modul (Datenbank) und den konsumierenden Mikro-Frontends explizit und ohne Seiteneffekte definiert werden müssen, um die parallele Ausführung und inkrementelle Kompilierung nicht zu gefährden.
|
||||
|
||||
### 1.3 Die Problemstellung: Synchron vs. Asynchron
|
||||
|
||||
@@ -38,12 +38,12 @@ SQLDelight 2.0+ adressiert dieses Problem mit der Konfiguration `generateAsync =
|
||||
|
||||
In einer Offline-First-Architektur fungiert die lokale Datenbank nicht als bloßer Cache, sondern als primäre Quelle der Wahrheit. Die Benutzeroberfläche (UI) kommuniziert niemals direkt mit dem Netzwerk.
|
||||
|
||||
| Konzept | Traditionelle Architektur | Offline-First Architektur |
|
||||
| --- | --- | --- |
|
||||
| **Datenquelle** | Remote API (REST/GraphQL) | Lokale Datenbank (SQLite) |
|
||||
| **Lesepfad** | UI ruft Netzwerk auf -> Wartet -> Zeigt an | UI beobachtet Datenbank (Flow) -> Zeigt an |
|
||||
| **Schreibpfad** | UI sendet an API -> Wartet auf OK -> Aktualisiert UI | UI schreibt in DB -> DB emittiert neue Daten -> Sync im Hintergrund |
|
||||
| **Netzwerkstatus** | Voraussetzung für Funktionalität | Optional; beeinflusst nur Synchronisation |
|
||||
| Konzept | Traditionelle Architektur | Offline-First Architektur |
|
||||
|--------------------|------------------------------------------------------|---------------------------------------------------------------------|
|
||||
| **Datenquelle** | Remote API (REST/GraphQL) | Lokale Datenbank (SQLite) |
|
||||
| **Lesepfad** | UI ruft Netzwerk auf -> Wartet -> Zeigt an | UI beobachtet Datenbank (Flow) -> Zeigt an |
|
||||
| **Schreibpfad** | UI sendet an API -> Wartet auf OK -> Aktualisiert UI | UI schreibt in DB -> DB emittiert neue Daten -> Sync im Hintergrund |
|
||||
| **Netzwerkstatus** | Voraussetzung für Funktionalität | Optional; beeinflusst nur Synchronisation |
|
||||
|
||||
Dieses Prinzip der „Inversion of Control“ entkoppelt die User Experience von Netzwerklatenz und -verfügbarkeit. In SQLDelight wird dies durch Reactive Extensions realisiert, die SQL-Abfragen als `Flow<T>` exponieren, die sich bei Datenänderungen automatisch aktualisieren.
|
||||
|
||||
@@ -60,8 +60,8 @@ Das Fundament eines stabilen KMP-Projekts ist eine präzise Gradle-Konfiguration
|
||||
### 3.1 Version Catalog (`gradle/libs.versions.toml`)toml
|
||||
|
||||
[versions]
|
||||
kotlin = "2.3.0"
|
||||
gradle = "9.1.0"
|
||||
kotlin = "2.3.21"
|
||||
gradle = "9.5.0"
|
||||
sqldelight = "2.1.0"
|
||||
coroutines = "1.10.1" # Hypothetische Version passend zu Kotlin 2.3
|
||||
ktor = "3.1.0"
|
||||
|
||||
@@ -5,20 +5,20 @@ owner: Lead Architect
|
||||
tags: [kotlin, java, configuration, setup]
|
||||
---
|
||||
|
||||
# Tech-Stack Referenz: Kotlin 2.3.0 & Java 25 (KMP)
|
||||
# Tech-Stack Referenz: Kotlin 2.3.21 & Java 25 (KMP)
|
||||
|
||||
**Kontext:** Dieses Dokument beschreibt die notwendigen Konfigurationen, um Kotlin 2.3.0 mit Java 25 in einem Kotlin Multiplatform (KMP) Projekt mit Gradle 9.x zu verwenden.
|
||||
**Kontext:** Dieses Dokument beschreibt die notwendigen Konfigurationen, um Kotlin 2.3.21 mit Java 25 in einem Kotlin Multiplatform (KMP) Projekt mit Gradle 9.x zu verwenden.
|
||||
|
||||
---
|
||||
|
||||
### 1. Kern-Spezifikationen
|
||||
|
||||
| Komponente | Version | Status |
|
||||
| --- |----------| --- |
|
||||
| **Kotlin** | `2.3.0` | Stabil (K2 Compiler standardmäßig aktiv) |
|
||||
| **Java (JDK)** | `25` | LTS (Long-Term Support) |
|
||||
| **Gradle** | `9.2.1` | Erforderlich für JDK 25 Support |
|
||||
| **Android Plugin (AGP)** | `8.8.0+` | Empfohlen für Gradle 9.x Kompatibilität |
|
||||
| Komponente | Version | Status |
|
||||
|--------------------------|----------|------------------------------------------|
|
||||
| **Kotlin** | `2.3.21` | Stabil (K2 Compiler standardmäßig aktiv) |
|
||||
| **Java (JDK)** | `25` | LTS (Long-Term Support) |
|
||||
| **Gradle** | `9.5.0` | Erforderlich für JDK 25 Support |
|
||||
| **Android Plugin (AGP)** | `8.8.0+` | Empfohlen für Gradle 9.x Kompatibilität |
|
||||
|
||||
---
|
||||
|
||||
@@ -28,7 +28,7 @@ Für ein **Kotlin Multiplatform (KMP)** Projekt ist die Java Toolchain-Konfigura
|
||||
|
||||
```kotlin
|
||||
plugins {
|
||||
kotlin("multiplatform") version "2.3.0"
|
||||
kotlin("multiplatform") version "2.3.21"
|
||||
id("com.android.library") version "8.8.0" // Falls Android Target genutzt wird
|
||||
}
|
||||
|
||||
@@ -60,15 +60,15 @@ Damit das Projekt Java 25 erkennt, muss der Wrapper auf dem neuesten Stand sein:
|
||||
|
||||
**Terminal-Befehl:**
|
||||
```bash
|
||||
./gradlew wrapper --gradle-version 9.2.1 --distribution-type all
|
||||
./gradlew wrapper --gradle-version 9.5.0 --distribution-type all
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. Wichtige Kompatibilitätshinweise
|
||||
|
||||
* **IDE-Version:** IntelliJ IDEA 2025.3 (oder neuer) wird für die volle Unterstützung von JDK 25 und dem Kotlin 2.3.0 Plugin empfohlen.
|
||||
* **K2 Compiler:** Kotlin 2.3.0 nutzt den K2-Compiler.
|
||||
* **IDE-Version:** IntelliJ IDEA 2025.3 (oder neuer) wird für die volle Unterstützung von JDK 25 und dem Kotlin 2.3.21 Plugin empfohlen.
|
||||
* **K2 Compiler:** Kotlin 2.3.21 nutzt den K2-Compiler.
|
||||
* **Bytecode:** Java 25 Bytecode wird nur generiert, wenn das `jvmTarget` explizit auf `25` gesetzt ist.
|
||||
|
||||
---
|
||||
@@ -76,4 +76,4 @@ Damit das Projekt Java 25 erkennt, muss der Wrapper auf dem neuesten Stand sein:
|
||||
### 5. Bekannte Features in diesem Setup
|
||||
|
||||
* **Java 25 Features:** Unterstützung für die finalen Versionen von *Scoped Values* und *Structured Concurrency*.
|
||||
* **Kotlin 2.3.0 Features:** Nutzung von `explicit backing fields` und dem verbesserten `unused return value` Checker.
|
||||
* **Kotlin 2.3.21 Features:** Nutzung von `explicit backing fields` und dem verbesserten `unused return value` Checker.
|
||||
|
||||
@@ -5,7 +5,7 @@ owner: Lead Architect
|
||||
tags: [kotlin, release-notes, tech-stack]
|
||||
---
|
||||
|
||||
# Was ist neu in Kotlin 2.3.0
|
||||
# Was ist neu in Kotlin 2.3.21
|
||||
|
||||
**Quelle:** [Offizielle Kotlin-Dokumentation](https://kotlinlang.org/docs/whatsnew23.html)
|
||||
**Datum des Dokuments:** 16. Dezember 2025
|
||||
@@ -13,7 +13,7 @@ tags: [kotlin, release-notes, tech-stack]
|
||||
|
||||
---
|
||||
|
||||
Kotlin 2.3.0 ist erschienen! Hier sind die wichtigsten Highlights:
|
||||
Kotlin 2.3.21 ist erschienen! Hier sind die wichtigsten Highlights:
|
||||
|
||||
* **Sprache:** Mehr stabile und standardmäßig aktivierte Features, Checker für ungenutzte Rückgabewerte, explizite Backing Fields und Änderungen bei der kontextsensitiven Auflösung.
|
||||
* **Kotlin/JVM:** Unterstützung für Java 25.
|
||||
@@ -26,7 +26,7 @@ Kotlin 2.3.0 ist erschienen! Hier sind die wichtigsten Highlights:
|
||||
|
||||
## Sprache
|
||||
|
||||
Kotlin 2.3.0 konzentriert sich auf die Stabilisierung von Features, führt einen neuen Mechanismus zur Erkennung ungenutzter Rückgabewerte ein und verbessert die kontextsensitive Auflösung.
|
||||
Kotlin 2.3.21 konzentriert sich auf die Stabilisierung von Features, führt einen neuen Mechanismus zur Erkennung ungenutzter Rückgabewerte ein und verbessert die kontextsensitive Auflösung.
|
||||
|
||||
### Stabile Features
|
||||
|
||||
@@ -38,13 +38,13 @@ Folgende Features sind nun stabil:
|
||||
* Unterstützung für `return`-Anweisungen in Ausdrucks-Bodies mit explizitem Rückgabetyp ist nun standardmäßig aktiviert.
|
||||
|
||||
### Experimentell: Checker für ungenutzte Rückgabewerte
|
||||
Kotlin 2.3.0 führt den Checker für ungenutzte Rückgabewerte ein, um das versehentliche Ignorieren von Ergebnissen zu verhindern.
|
||||
Kotlin 2.3.21 führt den Checker für ungenutzte Rückgabewerte ein, um das versehentliche Ignorieren von Ergebnissen zu verhindern.
|
||||
|
||||
### Experimentell: Explizite Backing Fields
|
||||
Eine neue Syntax zur expliziten Deklaration des zugrundeliegenden Felds, das den Wert einer Property hält – vereinfacht das verbreitete Backing-Properties-Muster.
|
||||
|
||||
## Kotlin/JVM: Unterstützung für Java 25
|
||||
Ab Kotlin 2.3.0 kann der Compiler Klassen mit Java-25-Bytecode generieren.
|
||||
Ab Kotlin 2.3.21 kann der Compiler Klassen mit Java-25-Bytecode generieren.
|
||||
|
||||
## Kotlin/Native
|
||||
* **Verbesserter Swift-Export:** Direkte Zuordnung für native Enum-Klassen und variadische Funktionsparameter.
|
||||
|
||||
@@ -3,22 +3,26 @@
|
||||
## 🏗️ [Lead Architect] | 14. April 2026
|
||||
|
||||
Dieses Dokument beschreibt die Umsetzung der Online-Nennung für das Turnier in Neumarkt (24. April 2026).
|
||||
Ziel ist ein schlankes Web-Formular, das strukturierte E-Mails an den `Mail-Service` sendet, welcher diese verarbeitet und in der Desktop-Zentrale zur manuellen Übernahme bereitstellt.
|
||||
Ziel ist ein schlankes Web-Formular, das strukturierte E-Mails an den `Mail-Service` sendet, welcher diese verarbeitet
|
||||
und in der Desktop-Zentrale zur manuellen Übernahme bereitstellt.
|
||||
|
||||
---
|
||||
|
||||
### Phase 1: E-Mail-Infrastruktur (Vorbereitung) ✅
|
||||
|
||||
* [x] Definition des Adress-Schemas: `meldestelle-[Turnier-Nr]@mo-code.at`.
|
||||
* [x] Konfiguration der World4You SMTP/IMAP Zugangsdaten.
|
||||
* [x] Mailpit Integration für lokale Tests (bereits in `dc-ops.yaml`).
|
||||
|
||||
### Phase 2: Das Web-Formular (WasmJS Frontend) ✅
|
||||
|
||||
* [x] **Basis-UI:** Erstellung des Formulars gemäß Spezifikation (Reiter, Pferd, Lizenz, Bewerbe).
|
||||
* [x] **Validierung:** Implementierung der Pflichtfeld-Prüfung (Buttonsperre bis alles ok).
|
||||
* [x] **Mail-Versand:** Integration des API-Calls an das Backend (`mail-service`), um die Nennung zu speichern.
|
||||
* [x] **DSGVO:** Checkbox und Hinweistext eingebaut.
|
||||
|
||||
### Phase 3: Mail-Service (Backend-Verarbeitung) 🏗️
|
||||
|
||||
* [x] **Endpoint:** POST-Endpunkt für direkte Nennungen aus dem Web-Formular implementiert.
|
||||
* [ ] **Polling:** Implementierung des IMAP-Pollers (imap.world4you.com).
|
||||
* [ ] **Parsing:** Extraktion der Turnier-Nummer aus dem `To`-Header und Mapping auf das Datenbank-Schema (Tenant).
|
||||
@@ -26,12 +30,14 @@ Ziel ist ein schlankes Web-Formular, das strukturierte E-Mails an den `Mail-Serv
|
||||
* [x] **Persistence:** Speichern der eingegangenen "Nennungs-Mails" in einer temporären Tabelle.
|
||||
|
||||
### Phase 4: Desktop-Zentrale Integration ✅
|
||||
|
||||
* [x] **UI-Tab:** Neuer Reiter "Online-Eingang" in der Turnierverwaltung (`TurnierDetailScreen`).
|
||||
* [x] **Vorschau:** Anzeige der eingegangenen Nennungen mit Details (`OnlineNennungEingangTabContent`).
|
||||
* [x] **Übernahme:** "Übernehmen"-Button, der Reiter/Pferd in die Nennung vorausfüllt (`NennungViewModel`).
|
||||
* [ ] **Abschluss:** Manueller "Bestätigen"-Button zum Versenden der finalen Bestätigungsmail.
|
||||
|
||||
### Phase 5: End-to-End Test & Deployment 🚀 (Deadline: 21.04.2026)
|
||||
|
||||
* [ ] Test-Nennung über Web-Formular (Mailpit).
|
||||
* [ ] Verifikation der Schema-Zuordnung im Backend.
|
||||
* [ ] Live-Test mit `online-nennen@mo-code.at`.
|
||||
@@ -40,6 +46,7 @@ Ziel ist ein schlankes Web-Formular, das strukturierte E-Mails an den `Mail-Serv
|
||||
---
|
||||
|
||||
### Meilensteine
|
||||
|
||||
1. **16.04.:** Web-Formular ist funktionsfähig (Senden möglich).
|
||||
2. **18.04.:** Mail-Service verarbeitet Mails und sendet Auto-Antworten.
|
||||
3. **20.04.:** Desktop-UI zur Übernahme ist fertig.
|
||||
@@ -10,7 +10,9 @@ last_update: 2026-03-25
|
||||
10. **🏗️ [Lead Architect]** | 5. April 2026
|
||||
|
||||
**Kontext:**
|
||||
Der ZNS-Importer wurde für die Verarbeitung der Datei `RICHT01.dat` optimiert. Es wurde klargestellt, dass Richter (SatzID 'X') und Parcoursbauer (SatzID 'Y') gemeinsam in dieser Datei geliefert werden. Eine separate `PARCO01.dat` existiert nicht.
|
||||
Der ZNS-Importer wurde für die Verarbeitung der Datei `RICHT01.dat` optimiert. Es wurde klargestellt, dass Richter (
|
||||
SatzID 'X') und Parcoursbauer (SatzID 'Y') gemeinsam in dieser Datei geliefert werden. Eine separate `PARCO01.dat`
|
||||
existiert nicht.
|
||||
Um den `registration-context` und `actor-context` unter realistischen Bedingungen testen zu können, benötigen wir echte
|
||||
Stammdaten (Reiter, Pferde, Vereine, Funktionäre). Diese Daten werden vom ÖPS (Österreichischer Pferdesportverband) in
|
||||
Form einer `ZNS.zip` bereitgestellt.
|
||||
@@ -51,7 +53,8 @@ gesteuert wird und die Daten persistent im Backend (`actor-context`) ablegt.
|
||||
* ZIP-Entpackung in-memory implementiert (`ZnsImportService`).
|
||||
* [x] **Legacy-Parser (CP850 Fixed-Width):**
|
||||
* `ZnsLegacyParsers` in `core:zns-parser` (KMP-Modul) implementiert.
|
||||
* Alle 4 Dateitypen (VEREIN01, LIZENZ01, PFERDE01, RICHT01) bytegenau gemappt. RICHT01 verarbeitet Richter ('X') und Parcoursbauer ('Y'). ✅
|
||||
* Alle 4 Dateitypen (VEREIN01, LIZENZ01, PFERDE01, RICHT01) bytegenau gemappt. RICHT01 verarbeitet Richter ('X') und
|
||||
Parcoursbauer ('Y'). ✅
|
||||
|
||||
### Phase 2: Domain-Mapping & Persistenz (👷 Backend Developer)
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
---
|
||||
type: Reference
|
||||
status: ACTIVE
|
||||
owner: Lead Architect
|
||||
last_update: 2026-03-15
|
||||
---
|
||||
|
||||
# Frontend-Architektur & Modularisierungsstrategie
|
||||
|
||||
**Status:** ENTWURF
|
||||
**Zuletzt aktualisiert:** 2026-01-19
|
||||
**Kontext:** Migration zu Clean Architecture & Feature-Modulen
|
||||
|
||||
---
|
||||
|
||||
## 1. Übersicht
|
||||
|
||||
Die Frontend-Architektur von **Meldestelle** basiert auf **Kotlin Multiplatform (KMP)** mit **Compose Multiplatform**
|
||||
für die Benutzeroberfläche. Wir folgen einem strikten **Clean Architecture**-Ansatz, um Testbarkeit, Skalierbarkeit und
|
||||
Trennung der Zuständigkeiten sicherzustellen.
|
||||
|
||||
## 2. Modulstruktur
|
||||
|
||||
Das Projekt ist in folgende Schichten unterteilt:
|
||||
|
||||
### 2.1 Core-Module (`frontend/core`)
|
||||
|
||||
Wiederverwendbare Komponenten, die unabhängig von spezifischen Geschäftsfunktionen sind.
|
||||
|
||||
* `core-network`: Zentrale HTTP-Client-Konfiguration (Auth, Logging, ContentNegotiation).
|
||||
* `core-sync`: Generische Synchronisierungslogik (`SyncManager`, `SyncableRepository`).
|
||||
* `core-ui`: Gemeinsame UI-Komponenten und Design-System.
|
||||
|
||||
### 2.2 Feature-Module (`frontend/features`)
|
||||
|
||||
Jede Geschäftsdomäne (z.B. `ping`, `auth`, `events`) liegt in ihrem eigenen Modul.
|
||||
Ein Feature-Modul MUSS die **Clean Architecture** Paketstruktur einhalten:
|
||||
|
||||
* `at.mocode.{feature}.feature.domain`
|
||||
* **Entitäten:** Reine Datenklassen.
|
||||
* **Interfaces:** Repository-Interfaces, Service-Interfaces.
|
||||
* **Use Cases:** Geschäftslogik (optional, für komplexe Logik).
|
||||
* `at.mocode.{feature}.feature.data`
|
||||
* **Implementierungen:** Repository-Implementierungen, API-Clients.
|
||||
* **DTOs:** Data Transfer Objects (wenn von Domain-Entitäten abweichend).
|
||||
* `at.mocode.{feature}.feature.presentation`
|
||||
* **ViewModels:** Zustandsverwaltung.
|
||||
* **Screens:** Composable-Funktionen.
|
||||
* `at.mocode.{feature}.feature.di`
|
||||
* **Koin-Modul:** Konfiguration der Dependency Injection.
|
||||
|
||||
### 2.3 Shells (`frontend/shells`)
|
||||
|
||||
Anwendungs-Einstiegspunkte, die alles zusammenführen.
|
||||
|
||||
* `meldestelle-portal`: Die Haupt-Web-/Desktop-Anwendung.
|
||||
|
||||
## 3. Migrationsstrategie (Übergangsphase)
|
||||
|
||||
Wir migrieren aktuell von einer monolithischen `clients`-Paketstruktur zu modularen Feature-Modulen.
|
||||
|
||||
**Regeln für die Migration:**
|
||||
|
||||
1. **Neue Features:** Müssen direkt in `frontend/features/{name}` unter Verwendung der Clean Architecture-Struktur
|
||||
implementiert werden.
|
||||
2. **Bestehende Features:** Werden schrittweise migriert.
|
||||
3. **Koexistenz:** Während des Übergangs ist Legacy-Code in `clients/` erlaubt, aber als veraltet markiert.
|
||||
4. **Dependency Injection:** Legacy-Code muss die neuen Koin-Module verwenden, sofern verfügbar.
|
||||
5. **Keine Ghost-Klassen:** Klassen nicht duplizieren. Wenn eine Klasse in ein Feature-Modul verschoben wird, muss die
|
||||
alte in `clients/` gelöscht werden.
|
||||
|
||||
## 4. Wichtige Entscheidungen (ADRs)
|
||||
|
||||
### ADR-001: Entkopplung der Sync-Logik
|
||||
|
||||
* **Entscheidung:** ViewModels dürfen nicht direkt vom `SyncManager` abhängen.
|
||||
* **Begründung:** Um einfacheres Testen zu ermöglichen und die Komplexität des generischen Sync-Mechanismus zu
|
||||
verbergen.
|
||||
* **Umsetzung:** Ein Domain-Service-Interface (z.B. `PingSyncService`) einführen, das den `SyncManager`-Aufruf kapselt.
|
||||
|
||||
### ADR-002: Feature-Modul-Isolation
|
||||
|
||||
* **Entscheidung:** Feature-Module sollten nach Möglichkeit nicht direkt voneinander abhängen.
|
||||
* **Kommunikation:** Gemeinsame Core-Module oder lose Kopplung über Interfaces/Events verwenden, wenn modulübergreifende
|
||||
Kommunikation nötig ist.
|
||||
|
||||
---
|
||||
|
||||
**Freigegeben von:** Lead Architect
|
||||
@@ -3,11 +3,15 @@ type: Reference
|
||||
status: ACTIVE
|
||||
owner: Lead Architect
|
||||
---
|
||||
|
||||
# Architektur: Das Platform-Modul
|
||||
|
||||
## Überblick
|
||||
|
||||
Das **Platform-Modul** ist das Rückgrat der Build-Infrastruktur des Meldestelle-Projekts. Seine alleinige Aufgabe ist die zentrale Verwaltung und Bereitstellung von Abhängigkeiten und deren Versionen. Dies stellt sicher, dass alle Module im gesamten Projekt dieselben Bibliotheksversionen verwenden, was Inkonsistenzen ("JAR Hell") verhindert und die Wartbarkeit drastisch verbessert.
|
||||
Das **Platform-Modul** ist das Rückgrat der Build-Infrastruktur des Meldestelle-Projekts. Seine alleinige Aufgabe ist
|
||||
die zentrale Verwaltung und Bereitstellung von Abhängigkeiten und deren Versionen. Dies stellt sicher, dass alle Module
|
||||
im gesamten Projekt dieselben Bibliotheksversionen verwenden, was Inkonsistenzen ("JAR Hell") verhindert und die
|
||||
Wartbarkeit drastisch verbessert.
|
||||
|
||||
Das Modul agiert als eine interne "Single Source of Truth" für alle externen Bibliotheken.
|
||||
|
||||
@@ -24,17 +28,21 @@ platform/
|
||||
|
||||
### `platform-bom`
|
||||
|
||||
Dies ist das wichtigste Modul der Plattform. Es ist als "Bill of Materials" (BOM) konfiguriert und nutzt das `java-platform`-Plugin von Gradle.
|
||||
Dies ist das wichtigste Modul der Plattform. Es ist als "Bill of Materials" (BOM) konfiguriert und nutzt das
|
||||
`java-platform`-Plugin von Gradle.
|
||||
|
||||
* **Zweck:** Definiert eine umfassende Liste von Abhängigkeiten und deren exakten, geprüften Versionen. Es importiert auch andere wichtige BOMs (z.B. von Spring Boot und Kotlin).
|
||||
* **Funktionsweise:** Andere Module importieren diese BOM mit `platform(projects.platform.platformBom)`. Gradle sorgt dann dafür, dass alle transitiven und deklarierten Abhängigkeiten den in der BOM festgelegten Versionen entsprechen.
|
||||
* **Zweck:** Definiert eine umfassende Liste von Abhängigkeiten und deren exakten, geprüften Versionen. Es importiert
|
||||
auch andere wichtige BOMs (z.B. von Spring Boot und Kotlin).
|
||||
* **Funktionsweise:** Andere Module importieren diese BOM mit `platform(projects.platform.platformBom)`. Gradle sorgt
|
||||
dann dafür, dass alle transitiven und deklarierten Abhängigkeiten den in der BOM festgelegten Versionen entsprechen.
|
||||
* **Vorteil:** Absolute Versionskontrolle über das gesamte Projekt.
|
||||
|
||||
### `platform-dependencies`
|
||||
|
||||
Ein einfaches "Sammelmodul", das die am häufigsten benötigten Laufzeit-Abhängigkeiten bündelt.
|
||||
|
||||
* **Zweck:** Vereinfacht die `build.gradle.kts`-Dateien der Service-Module. Anstatt 5-6 einzelne `kotlinx`- und Logging-Bibliotheken hinzuzufügen, genügt eine einzige Abhängigkeit zu diesem Modul.
|
||||
* **Zweck:** Vereinfacht die `build.gradle.kts`-Dateien der Service-Module. Anstatt 5-6 einzelne `kotlinx`- und
|
||||
Logging-Bibliotheken hinzuzufügen, genügt eine einzige Abhängigkeit zu diesem Modul.
|
||||
* **Verwendung:**
|
||||
|
||||
```kotlin
|
||||
@@ -48,7 +56,8 @@ Ein einfaches "Sammelmodul", das die am häufigsten benötigten Laufzeit-Abhäng
|
||||
|
||||
Analog zu `platform-dependencies`, aber speziell für Test-Bibliotheken.
|
||||
|
||||
* **Zweck:** Stellt ein konsistentes Set an Test-Frameworks (JUnit 5, MockK, AssertJ) und Werkzeugen (Testcontainers) für alle Module bereit.
|
||||
* **Zweck:** Stellt ein konsistentes Set an Test-Frameworks (JUnit 5, MockK, AssertJ) und Werkzeugen (Testcontainers)
|
||||
für alle Module bereit.
|
||||
* **Verwendung:**
|
||||
|
||||
```kotlin
|
||||
@@ -58,4 +67,5 @@ Analog zu `platform-dependencies`, aber speziell für Test-Bibliotheken.
|
||||
}
|
||||
```
|
||||
|
||||
* **Optimierung:** Dieses Modul nutzt die in `libs.versions.toml` definierten `[bundles]`, um die Build-Datei extrem kurz und lesbar zu halten.
|
||||
* **Optimierung:** Dieses Modul nutzt die in `libs.versions.toml` definierten `[bundles]`, um die Build-Datei extrem
|
||||
kurz und lesbar zu halten.
|
||||
@@ -0,0 +1,362 @@
|
||||
---
|
||||
type: Reference
|
||||
status: ACTIVE
|
||||
owner: Lead Architect
|
||||
date: 2026-03-07
|
||||
---
|
||||
|
||||
# Meldestelle — Tech-Stack Zusammenfassung
|
||||
|
||||
> **Zweck:** Vollständige Referenz des eingesetzten Tech-Stacks im Projekt "Meldestelle".
|
||||
> Dient als Basis für Recherchen zu Self-Hosted AI (Codegenerierung, RAG, Agenten).
|
||||
> **Stand:** 07. März 2026
|
||||
|
||||
---
|
||||
|
||||
## 1. Überblick
|
||||
|
||||
Das Projekt "Meldestelle" ist eine **Kotlin-first, Cloud-native Microservices-Plattform** für die Verwaltung von
|
||||
Reitsport-Meldungen (FEI / ÖTO). Es kombiniert ein **Kotlin Multiplatform (KMP) Frontend** mit einem **Spring Boot
|
||||
Microservices Backend** auf einer vollständig self-hosted Infrastruktur.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Frontend (KMP) │ Backend (Spring Boot / Kotlin JVM) │
|
||||
│ Kotlin 2.3.21 / Compose │ Java 25 / Spring Boot 3.5.9 │
|
||||
│ JS + WASM (geplant) │ Microservices + API-Gateway │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Infrastruktur (Self-Hosted auf Zora / Proxmox) │
|
||||
│ Keycloak · Consul · Valkey · PostgreSQL · Zipkin │
|
||||
│ Prometheus · Grafana · Caddy · Pangolin-Tunnel │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Sprachen & Laufzeiten
|
||||
|
||||
| Komponente | Sprache / Runtime | Version |
|
||||
|:-----------|:-----------------------|:--------|
|
||||
| Backend | Kotlin (JVM) | 2.3.21 |
|
||||
| Frontend | Kotlin (KMP / JS) | 2.3.21 |
|
||||
| JVM | Java (Eclipse Temurin) | 25 (EA) |
|
||||
| Build | Gradle (Kotlin DSL) | 9.5.0 |
|
||||
| Plattform | ARM64 (AArch64) | Linux |
|
||||
|
||||
---
|
||||
|
||||
## 3. Frontend — Kotlin Multiplatform (KMP)
|
||||
|
||||
### 3.1 Core-Framework
|
||||
|
||||
| Bibliothek | Version | Zweck |
|
||||
|:----------------------|:--------|:---------------------------------|
|
||||
| Kotlin Multiplatform | 2.3.21 | Cross-Platform-Basis (JS + WASM) |
|
||||
| Compose Multiplatform | 1.10.0 | UI-Framework (Deklarativ) |
|
||||
| Compose Hot Reload | 1.0.0 | Live-Reload im Dev-Modus |
|
||||
| Koin (DI) | 4.1.1 | Dependency Injection |
|
||||
| Koin Compose | 4.1.1 | DI-Integration für Compose |
|
||||
| Ktor Client | 3.4.0 | HTTP-Client (Multiplatform) |
|
||||
| Kotlin Serialization | 2.3.21 | JSON-Serialisierung |
|
||||
|
||||
### 3.2 Persistenz (Offline-First)
|
||||
|
||||
| Bibliothek | Version | Zweck |
|
||||
|:----------------|:--------|:-----------------------------|
|
||||
| SQLDelight | 2.2.1 | Cross-Platform SQL-Datenbank |
|
||||
| SQLite (WASM) | 3.51.1 | SQLite für Browser/WASM |
|
||||
| SQLite (Native) | 2.6.2 | SQLite für JVM/Desktop |
|
||||
|
||||
### 3.3 Build-Targets
|
||||
|
||||
| Target | Status | Anmerkung |
|
||||
|:--------------|:-----------|:--------------------------|
|
||||
| KotlinJS | ✅ Aktiv | Primäres Build-Target |
|
||||
| WASM | ⏳ Geplant | Warten auf Alpha-Version |
|
||||
| Desktop (JVM) | ⚙️ Möglich | uiDesktop 1.7.0 vorhanden |
|
||||
|
||||
### 3.4 Modul-Struktur
|
||||
|
||||
```
|
||||
frontend/
|
||||
├── core/
|
||||
│ ├── core-network/ # Ktor HTTP-Client, Auth-Interceptor
|
||||
│ ├── core-ui/ # Design-System, Tokens, Komponenten
|
||||
│ ├── core-domain/ # Shared Domain-Models
|
||||
│ └── core-data/ # Repository-Interfaces
|
||||
├── features/
|
||||
│ ├── ping-feature/ # ✅ Blueprint: MVVM + Repository + DI + Tests
|
||||
│ └── members-feature/ # ⏳ Auskommentiert (nächste Phase)
|
||||
└── shells/
|
||||
└── meldestelle-portal/ # Web-App Shell (Caddy-served)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Backend — Spring Boot Microservices
|
||||
|
||||
### 4.1 Core-Framework
|
||||
|
||||
| Bibliothek | Version | Zweck |
|
||||
|:-------------------------|:---------|:---------------------------------|
|
||||
| Spring Boot | 3.5.9 | Microservices-Framework |
|
||||
| Spring Cloud | 2025.0.1 | Service Discovery, Config |
|
||||
| Spring Security (OAuth2) | (Boot) | JWT-Validierung, Resource Server |
|
||||
| Spring Data JPA | (Boot) | ORM-Layer |
|
||||
| Spring Data Valkey | 0.2.0 | Cache-Integration (Valkey/Redis) |
|
||||
| Spring WebFlux | (Boot) | Reaktive API (Gateway) |
|
||||
| Kotlin Coroutines | 2.3.21 | Async/Non-blocking |
|
||||
|
||||
### 4.2 Persistenz
|
||||
|
||||
| Bibliothek | Version | Zweck |
|
||||
|:--------------------|:--------|:----------------------|
|
||||
| PostgreSQL Driver | 42.7.8 | JDBC-Treiber |
|
||||
| Exposed (JetBrains) | 1.0.0 | Kotlin-native SQL DSL |
|
||||
| Flyway | 11.19.1 | Datenbank-Migrationen |
|
||||
| HikariCP | 7.0.2 | Connection Pool |
|
||||
|
||||
> **Strategie (ADR-001):** Hybrid — JPA für einfache CRUD-Entities, Exposed für komplexe Queries und Domain-Logik.
|
||||
|
||||
### 4.3 Caching & Messaging
|
||||
|
||||
| Bibliothek | Version | Zweck |
|
||||
|:--------------|:--------|:--------------------------------|
|
||||
| Lettuce | 6.6.0 | Valkey/Redis-Client (reaktiv) |
|
||||
| Redisson | 4.0.0 | Distributed Locks, Pub/Sub |
|
||||
| Caffeine | 3.2.3 | In-Memory Cache (L1) |
|
||||
| Reactor Kafka | 1.3.23 | Kafka-Client (Phase 3 / Outbox) |
|
||||
|
||||
### 4.4 Observability & Tracing
|
||||
|
||||
| Bibliothek | Version | Zweck |
|
||||
|:-------------------|:--------|:-----------------------------|
|
||||
| Micrometer | 1.16.1 | Metriken (Prometheus-Export) |
|
||||
| Micrometer Tracing | 1.6.1 | Distributed Tracing |
|
||||
| Zipkin Reporter | 3.5.1 | Trace-Export zu Zipkin |
|
||||
| Logback | 1.5.25 | Logging |
|
||||
|
||||
### 4.5 Security
|
||||
|
||||
| Bibliothek | Version | Zweck |
|
||||
|:-----------------------|:--------|:-------------------------|
|
||||
| Keycloak Admin Client | 26.0.7 | Keycloak-API-Integration |
|
||||
| Spring Security OAuth2 | (Boot) | JWT Resource Server |
|
||||
| Jackson (Kotlin) | 3.0.3 | JSON-Serialisierung |
|
||||
|
||||
### 4.6 API & Dokumentation
|
||||
|
||||
| Bibliothek | Version | Zweck |
|
||||
|:-------------------|:--------|:-----------------------|
|
||||
| Springdoc OpenAPI | 3.0.0 | Swagger / OpenAPI 3.1 |
|
||||
| Jakarta Annotation | 3.0.0 | Jakarta EE Annotations |
|
||||
|
||||
### 4.7 Modul-Struktur
|
||||
|
||||
```
|
||||
backend/
|
||||
├── infrastructure/
|
||||
│ ├── gateway/ # ✅ API-Gateway (Spring Cloud Gateway)
|
||||
│ ├── security/ # ✅ Zentrales OAuth2/JWT-Modul (DRY)
|
||||
│ ├── cache/
|
||||
│ │ ├── cache-api/ # Interface-Abstraktion
|
||||
│ │ └── valkey-impl/ # Valkey-Implementierung
|
||||
│ ├── event-store/
|
||||
│ │ ├── event-store-api/ # Interface-Abstraktion
|
||||
│ │ └── valkey-impl/ # Valkey-Implementierung
|
||||
│ ├── persistence/ # Hybrid JPA + Exposed
|
||||
│ └── messaging/ # Kafka (Phase 3 / Outbox-Pattern)
|
||||
└── services/
|
||||
├── ping/ # ✅ Deployed — Test/Blueprint-Service
|
||||
├── entries/ # ⚙️ Registriert, noch nicht deployed
|
||||
├── events/ # 👻 Ghost Service (nicht registriert)
|
||||
├── horses/ # 👻 Ghost Service (nicht registriert)
|
||||
├── masterdata/ # 👻 Ghost Service (nicht registriert)
|
||||
├── registry/ # 👻 Ghost Service (nicht registriert)
|
||||
├── results/ # 👻 Ghost Service (nicht registriert)
|
||||
└── scheduling/ # 👻 Ghost Service (nicht registriert)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Infrastruktur-Services (Docker)
|
||||
|
||||
### 5.1 Laufende Services
|
||||
|
||||
| Service | Image / Version | Port(s) | Zweck |
|
||||
|:-------------|:-----------------------|:-----------|:----------------------------|
|
||||
| PostgreSQL | postgres:16-alpine | 5432 | Primäre Datenbank |
|
||||
| Keycloak | keycloak:26.4 (custom) | 8180, 9000 | IAM / OAuth2 / OIDC |
|
||||
| Valkey | valkey:8-alpine | 6379 | Cache + Event-Store |
|
||||
| Consul | consul:1.21 | 8500, 8600 | Service Discovery + Config |
|
||||
| Zipkin | openzipkin/zipkin:3.5 | 9411 | Distributed Tracing |
|
||||
| Prometheus | prom/prometheus:v3.4 | 9090 | Metriken-Sammlung |
|
||||
| Grafana | grafana/grafana:11.6 | 3000 | Dashboards / Visualisierung |
|
||||
| Caddy | caddy:2.10-alpine | 4000 | Web-App Serving (Frontend) |
|
||||
| API-Gateway | (custom Spring Boot) | 8081 | Zentraler Eintrittspunkt |
|
||||
| Ping-Service | (custom Spring Boot) | 8082 | Test/Blueprint-Service |
|
||||
|
||||
### 5.2 CI/CD & DevOps
|
||||
|
||||
| Tool | Version / Details | Zweck |
|
||||
|:--------------|:---------------------|:------------------------------|
|
||||
| Gitea | Self-Hosted (CT 101) | Git-Repository + Registry |
|
||||
| Gitea Actions | (Runner VM 102) | CI/CD-Pipeline |
|
||||
| Docker Buildx | ARM64 (linux/arm64) | Multi-Arch Image Build |
|
||||
| Pangolin | Self-Hosted Tunnel | Reverse Proxy / Extern-Zugang |
|
||||
|
||||
### 5.3 Netzwerk & Routing
|
||||
|
||||
| Subdomain | Intern (Zora) | Zweck |
|
||||
|:--------------------|:-----------------|:---------------|
|
||||
| `git.mo-code.at` | `10.0.0.22:3000` | Gitea |
|
||||
| `api.mo-code.at` | `10.0.0.50:8081` | API-Gateway |
|
||||
| `auth.mo-code.at` | `10.0.0.50:8180` | Keycloak |
|
||||
| `app.mo-code.at` | `10.0.0.50:4000` | Web-App |
|
||||
| `photos.mo-code.at` | `10.0.0.24:2283` | Immich (Fotos) |
|
||||
|
||||
---
|
||||
|
||||
## 6. Code-Qualität & Build-Tools
|
||||
|
||||
| Tool | Version | Zweck |
|
||||
|:-------------------|:--------|:---------------------------------|
|
||||
| Detekt | 1.23.6 | Kotlin Static Analysis |
|
||||
| ktlint | 12.1.1 | Kotlin Code Formatter |
|
||||
| ArchUnit | 1.4.1 | Architektur-Tests (Layer-Regeln) |
|
||||
| Dokka | 2.1.0 | API-Dokumentation (KDoc) |
|
||||
| Ben-Manes Versions | 0.51.0 | Dependency-Update-Check |
|
||||
| KSP | 2.3.4 | Kotlin Symbol Processing |
|
||||
|
||||
### Build-Konfiguration
|
||||
|
||||
```properties
|
||||
# gradle.properties
|
||||
org.gradle.parallel=true
|
||||
org.gradle.caching=true
|
||||
org.gradle.workers.max=8
|
||||
org.gradle.configuration-cache=false # wegen JS-Test Serialisierungsproblem
|
||||
org.gradle.dependency.verification=strict
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Test-Stack
|
||||
|
||||
| Bibliothek | Version | Zweck |
|
||||
|:--------------------------|:--------|:-----------------------------|
|
||||
| JUnit Jupiter | 5.11.3 | Unit-Tests |
|
||||
| JUnit Platform | 1.11.3 | Test-Runner |
|
||||
| MockK | 1.14.7 | Kotlin Mocking |
|
||||
| AssertJ | 3.27.7 | Fluent Assertions |
|
||||
| Testcontainers | 2.0.3 | Integration-Tests (Docker) |
|
||||
| Testcontainers Keycloak | 4.0.1 | Keycloak-Integration-Tests |
|
||||
| Testcontainers PostgreSQL | 1.21.4 | DB-Integration-Tests |
|
||||
| Testcontainers Kafka | 1.21.4 | Kafka-Integration-Tests |
|
||||
| ArchUnit | 1.4.1 | Architektur-Compliance-Tests |
|
||||
|
||||
---
|
||||
|
||||
## 8. Architektur-Prinzipien (ADRs)
|
||||
|
||||
| ADR | Entscheidung | Status |
|
||||
|:-----|:--------------------------------------------------|:--------|
|
||||
| 0001 | Modulare Architektur (DDD, Clean Architecture) | ✅ Aktiv |
|
||||
| 0003 | Microservices-Architektur | ✅ Aktiv |
|
||||
| 0004 | Event-Driven Communication (Kafka Phase 3) | ✅ Aktiv |
|
||||
| 001 | Backend-Infrastruktur: Hybrid JPA+Exposed, Valkey | ✅ Aktiv |
|
||||
| 0013 | Tech-Stack-Stabilisierung 2026 (Versionen) | ✅ Aktiv |
|
||||
|
||||
**Kern-Prinzipien:**
|
||||
|
||||
- **Offline-First:** SQLDelight als Cross-Platform-DB, Sync-Mechanismus
|
||||
- **Docs-as-Code:** `/docs` als Single Source of Truth
|
||||
- **DRY-Infrastruktur:** Shared Security/Cache/EventStore-Module
|
||||
- **ARM64-Native:** Alle Images für `linux/arm64` gebaut
|
||||
|
||||
---
|
||||
|
||||
## 9. Relevanz für Self-Hosted AI
|
||||
|
||||
### 9.1 Welche AI-Aufgaben entstehen im Projekt?
|
||||
|
||||
| Aufgabe | Häufigkeit | Komplexität |
|
||||
|:-----------------------------------|:-------------|:------------|
|
||||
| Kotlin/Spring Boot Code-Completion | Täglich | Mittel |
|
||||
| Compose Multiplatform UI-Code | Täglich | Mittel |
|
||||
| SQL / Exposed DSL Queries | Häufig | Mittel |
|
||||
| Gradle Kotlin DSL Build-Skripte | Gelegentlich | Niedrig |
|
||||
| Docker / YAML Konfigurationen | Gelegentlich | Niedrig |
|
||||
| Architektur-Entscheidungen (ADR) | Selten | Hoch |
|
||||
| Fachlogik FEI/ÖTO Regelwerk | Selten | Sehr hoch |
|
||||
|
||||
### 9.2 Anforderungen an das AI-Modell
|
||||
|
||||
```
|
||||
MUSS:
|
||||
✅ Kotlin (JVM + Multiplatform) — sehr gute Unterstützung
|
||||
✅ Spring Boot / Spring Cloud — sehr gute Unterstützung
|
||||
✅ Compose Multiplatform — gute Unterstützung (neuere Modelle)
|
||||
✅ SQL / PostgreSQL — sehr gute Unterstützung
|
||||
✅ Docker / YAML — sehr gute Unterstützung
|
||||
✅ Deutsch (Fachsprache Reitsport) — für RAG-Dokumente
|
||||
|
||||
NICE-TO-HAVE:
|
||||
⭐ Gradle Kotlin DSL
|
||||
⭐ Keycloak / OAuth2 / OIDC
|
||||
⭐ Microservices-Architektur-Patterns
|
||||
```
|
||||
|
||||
### 9.3 Empfohlene Modelle für diesen Stack
|
||||
|
||||
| Modell | Größe | Stärke | RAM-Bedarf |
|
||||
|:------------------------|:------|:----------------------------------|:-----------|
|
||||
| `qwen2.5-coder:14b` | 14B | Code (Kotlin, Java, SQL) — Top | ~10 GB |
|
||||
| `deepseek-coder-v2:16b` | 16B | Code-Completion, Refactoring | ~12 GB |
|
||||
| `llama3.1:8b` | 8B | Allgemein + Deutsch, schnell | ~6 GB |
|
||||
| `qwen2.5:32b` | 32B | Architektur, Planung, Fachlogik | ~22 GB |
|
||||
| `codellama:13b` | 13B | Code-Completion (IntelliJ-Plugin) | ~9 GB |
|
||||
|
||||
> **Empfehlung für Zora (64 GB RAM):**
|
||||
> - **Primär:** `qwen2.5-coder:14b` — bester Kotlin/Spring-Support
|
||||
> - **Sekundär:** `qwen2.5:32b` — für Architektur und Fachlogik
|
||||
> - **IntelliJ-Integration:** `codellama:13b` oder `qwen2.5-coder:14b`
|
||||
|
||||
### 9.4 RAG-Dokumente (Priorität)
|
||||
|
||||
Folgende Projekt-Dokumente sind besonders wertvoll als RAG-Kontext:
|
||||
|
||||
```
|
||||
Hohe Priorität:
|
||||
├── docs/01_Architecture/MASTER_ROADMAP_2026_Q1.md
|
||||
├── docs/01_Architecture/adr/ (alle ADRs)
|
||||
├── docs/04_Agents/Playbooks/ (Agenten-Rollen)
|
||||
├── gradle/libs.versions.toml (Versions-SSoT)
|
||||
└── docs/07_Infrastructure/ (Infrastruktur-Referenz)
|
||||
|
||||
Mittlere Priorität:
|
||||
├── docs/05_Backend/ (Backend-Guides)
|
||||
├── docs/06_Frontend/ (Frontend-Guides)
|
||||
└── docs/03_Domain/ (Fachlogik-Konzepte)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Zusammenfassung
|
||||
|
||||
```
|
||||
TECH-STACK KOMPLEXITÄT
|
||||
──────────────────────────────────────────────────────
|
||||
Sprachen: Kotlin (JVM + KMP/JS)
|
||||
Build: Gradle 9.5.0 + Kotlin DSL + libs.versions.toml
|
||||
Frontend: Compose Multiplatform 1.10 + SQLDelight 2.2 + Koin 4.1
|
||||
Backend: Spring Boot 3.5.9 + Spring Cloud 2025.0.1
|
||||
Persistenz: PostgreSQL 16 + Exposed 1.0 + Flyway 11 + HikariCP 7
|
||||
Cache: Valkey 8 + Lettuce 6.6 + Caffeine 3.2
|
||||
Security: Keycloak 26.4 + Spring Security OAuth2 + JWT
|
||||
Observability: Micrometer 1.16 + Zipkin 3.5 + Prometheus + Grafana 11.6
|
||||
Service Mesh: Consul 1.21 + Spring Cloud Gateway
|
||||
Messaging: Kafka (Phase 3) + Reactor Kafka 1.3
|
||||
CI/CD: Gitea Actions + Docker Buildx (ARM64)
|
||||
Hosting: Proxmox VE 8.4 + Docker Compose + Pangolin-Tunnel
|
||||
```
|
||||
@@ -13,7 +13,7 @@ Feature-Implementierung an der verfeinerten DDD-Struktur (ADR-0014) sowie der De
|
||||
|
||||
### 🟢 Technische Stabilisierung
|
||||
|
||||
* **Kotlin 2.3.20:** Alle Module wurden auf Kotlin 2.3.20 migriert. Deprecation-Warnungen für `Clock` und `Instant`
|
||||
* **Kotlin 2.3.21:** Alle Module wurden auf Kotlin 2.3.21 migriert. Deprecation-Warnungen für `Clock` und `Instant`
|
||||
wurden durch Standardisierung auf `kotlin.time.*` behoben.
|
||||
* **Zentralisierte Serialisierung:** Erstellung der `Serializers.kt` im `core-domain` Modul für `Uuid`, `Instant`,
|
||||
`LocalDate`, `LocalDateTime` und `LocalTime`.
|
||||
@@ -10,23 +10,27 @@ Cups/Serien.
|
||||
## 1) Fokus-Themen und Deliverables (heute Nacht)
|
||||
|
||||
1. Reporting & Output (Vorbereitung)
|
||||
- [Owner] Vorlagen sammeln/übermitteln: Startlisten, Ergebnislisten (PDF/Scan/Excel)
|
||||
- [Owner] Spring-Protokolle: Inhalte/Felder definieren (Fehler, Zeit, Stechen)
|
||||
- [Owner] Dressur-Protokolle: Vorlage für personalisierten Ausdruck (Kopfzeile Reiter/Pferd)
|
||||
- [Arch/BE] Technik-Entscheidung PDF: KMP-Library vs. Server-Side Rendering (ADR-Entwurf)
|
||||
- [FE] UI-Draft „Druckvorschau“ in V2-Screens: Platzhalter mit Beispiel-Daten
|
||||
|
||||
- [Owner] Vorlagen sammeln/übermitteln: Startlisten, Ergebnislisten (PDF/Scan/Excel)
|
||||
- [Owner] Spring-Protokolle: Inhalte/Felder definieren (Fehler, Zeit, Stechen)
|
||||
- [Owner] Dressur-Protokolle: Vorlage für personalisierten Ausdruck (Kopfzeile Reiter/Pferd)
|
||||
- [Arch/BE] Technik-Entscheidung PDF: KMP-Library vs. Server-Side Rendering (ADR-Entwurf)
|
||||
- [FE] UI-Draft „Druckvorschau“ in V2-Screens: Platzhalter mit Beispiel-Daten
|
||||
|
||||
2. Events/Turniere (Backend-Readiness für Neumarkt)
|
||||
- [BE] DB-Migrationen finalisieren: `turniere`, `ausschreibungen` (Flyway)
|
||||
- [BE] Seed-Datensatz „Veranstaltung Neumarkt 2026“ (+ 1–2 Turniere)
|
||||
- [BE] Repositories prüfen und Test-Cases anlegen (Roundtrip CRUD)
|
||||
|
||||
- [BE] DB-Migrationen finalisieren: `turniere`, `ausschreibungen` (Flyway)
|
||||
- [BE] Seed-Datensatz „Veranstaltung Neumarkt 2026“ (+ 1–2 Turniere)
|
||||
- [BE] Repositories prüfen und Test-Cases anlegen (Roundtrip CRUD)
|
||||
|
||||
3. Identity & Profil (Verifikation)
|
||||
- [QA] E2E-Check „ZNS-Link“: Login → Profile → Satznummer verknüpfen → Refresh
|
||||
- [FE] Validation/UX-Polish im `profile-feature`
|
||||
|
||||
- [QA] E2E-Check „ZNS-Link“: Login → Profile → Satznummer verknüpfen → Refresh
|
||||
- [FE] Validation/UX-Polish im `profile-feature`
|
||||
|
||||
4. Live-Ergebnisse – Vision (Input sammeln)
|
||||
- [Owner] Skizze/Mock für mobile Web-Ansicht (Zuschauer): Bewerb → Abteilungen → Live-Board
|
||||
|
||||
- [Owner] Skizze/Mock für mobile Web-Ansicht (Zuschauer): Bewerb → Abteilungen → Live-Board
|
||||
|
||||
---
|
||||
|
||||
@@ -11,17 +11,17 @@ last_update: 2026-01-20
|
||||
Angenommen
|
||||
|
||||
## Kontext
|
||||
Das Projekt "Meldestelle" setzt auf einen sehr modernen Technologie-Stack (Java 25, Kotlin 2.3.0, Spring Boot 3.5.9). Eine Analyse im Januar 2026 hat jedoch kritische Versionskonflikte aufgedeckt, die die Stabilität des Builds und der Laufzeitumgebung gefährden.
|
||||
Das Projekt "Meldestelle" setzt auf einen sehr modernen Technologie-Stack (Java 25, Kotlin 2.3.21, Spring Boot 3.5.9). Eine Analyse im Januar 2026 hat jedoch kritische Versionskonflikte aufgedeckt, die die Stabilität des Builds und der Laufzeitumgebung gefährden.
|
||||
|
||||
1. **Spring Cloud Konflikt:** Der Release Train `2025.1.0` (Oakwood) ist für Spring Boot 4.0 konzipiert und inkompatibel mit Spring Boot 3.5.9 (führt zu `NoSuchMethodError`).
|
||||
2. **Compose Multiplatform:** Version `1.9.3` führt zu Compiler-Crashes in Verbindung mit Kotlin 2.3.0.
|
||||
3. **Exposed:** Version `0.61.0` ist veraltet und inkompatibel mit Kotlin 2.3.0.
|
||||
2. **Compose Multiplatform:** Version `1.9.3` führt zu Compiler-Crashes in Verbindung mit Kotlin 2.3.21.
|
||||
3. **Exposed:** Version `0.61.0` ist veraltet und inkompatibel mit Kotlin 2.3.21.
|
||||
|
||||
## Entscheidung
|
||||
Wir führen folgende Korrekturen am Tech-Stack durch, um eine stabile "Best Compatibility List" zu etablieren:
|
||||
|
||||
1. **Spring Cloud Downgrade:** Wechsel auf Release Train `2025.0.1` (Northfields), der offiziell für Spring Boot 3.5.x freigegeben ist.
|
||||
2. **Compose Multiplatform Upgrade:** Wechsel auf `1.10.0-rc02` (oder stable), um volle Kotlin 2.3.0 Kompatibilität zu gewährleisten.
|
||||
2. **Compose Multiplatform Upgrade:** Wechsel auf `1.10.0-rc02` (oder stable), um volle Kotlin 2.3.21 Kompatibilität zu gewährleisten.
|
||||
3. **Exposed Upgrade:** Wechsel auf `1.0.0-rc-4` (oder neuer), um Bytecode-Inkompatibilitäten zu beheben.
|
||||
4. **Micrometer Upgrade:** Explizites Setzen von Version `1.16.1` für verbesserten Java 25 (Virtual Threads) Support.
|
||||
|
||||
@@ -29,7 +29,7 @@ Wir führen folgende Korrekturen am Tech-Stack durch, um eine stabile "Best Comp
|
||||
|
||||
### Positiv
|
||||
* **Stabilität:** Der Build und die Application Context Initialisierung sind wieder stabil.
|
||||
* **Zukunftssicherheit:** Wir nutzen weiterhin die neuesten Features von Java 25 und Kotlin 2.3.0, aber in einer validierten Kombination.
|
||||
* **Zukunftssicherheit:** Wir nutzen weiterhin die neuesten Features von Java 25 und Kotlin 2.3.21, aber in einer validierten Kombination.
|
||||
* **Wartbarkeit:** Die `libs.versions.toml` spiegelt nun eine getestete Konfiguration wider.
|
||||
|
||||
### Negativ
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# ADR-0025: "Plan-USB" & Offline-Datenintegrität
|
||||
|
||||
## Status
|
||||
In Prüfung (Wartet auf PoC)
|
||||
|
||||
## Kontext
|
||||
Im professionellen Turniersport ist eine stabile Netzwerkverbindung (LAN/WLAN) nicht immer garantiert. Ein Ausfall des Netzwerks darf den laufenden Betrieb (Ergebniserfassung, Meldestelle) nicht blockieren. Zudem müssen sensible Reiter- und Pferdedaten (DSGVO) auch auf physischen Datenträgern geschützt sein.
|
||||
|
||||
## Entscheidung
|
||||
Wir führen die "Plan-USB" Strategie als primären Fallback und parallelen Sicherungsmechanismus ein.
|
||||
|
||||
1. **Permanenter Delta-Export:** Der Master-PC schreibt kontinuierlich verschlüsselte Delta-Pakete (JSON-basiert) in ein definiertes Backup-Verzeichnis. Dies ist bereits in der UI als Pfad-Option vorbereitet.
|
||||
2. **Verschlüsselung:** Alle Daten auf dem USB-Stick werden mit dem `Shared Key` (AES-256) verschlüsselt. Der Benutzer legt diesen Schlüssel einmalig während der Initialisierung fest.
|
||||
3. **Datenintegrität:** Pakete werden signiert, um Manipulationen durch Texteditoren zu verhindern.
|
||||
4. **Sync-Vorschau:** Die UI bietet eine visuelle Bestätigung ("Sync-Dashboard"), welche Daten zuletzt erfolgreich auf den Stick geschrieben wurden. (Umgesetzt im UI-Design der Initialisierung).
|
||||
5. **Manueller Not-Import:** Clients erhalten eine Funktion, um Delta-Pakete manuell von einem Stick einzulesen und eigene Ergebnisse dorthin zurückzuschreiben.
|
||||
|
||||
## Konsequenzen
|
||||
- Erhöhte Komplexität in der Sync-Logik (Hybrid-Modus: Netzwerk + Datei).
|
||||
- Benutzer muss initial einen `Shared Key` festlegen.
|
||||
- Rechtliche Absicherung bei Verlust von Hardware durch Verschlüsselung.
|
||||
- Maximale Ausfallsicherheit: Das Turnier kann rein via USB-Stick ("Turnschuh-Netzwerk") zu Ende geführt werden.
|
||||
@@ -0,0 +1,23 @@
|
||||
# ADR-0026: Offline-Lizenzierung ("Pay-per-Event")
|
||||
|
||||
## Status
|
||||
Vorgeschlagen
|
||||
|
||||
## Kontext
|
||||
Die Software wird als Service pro Veranstaltung lizenziert. Da die App primär offline betrieben wird (Meldestelle am Turnierplatz), kann keine permanente Online-Verbindung zur Lizenzprüfung vorausgesetzt werden.
|
||||
|
||||
## Entscheidung
|
||||
Wir implementieren ein ticketbasiertes Offline-Lizenzmodell.
|
||||
|
||||
1. **Online-Erwerb:** Der Veranstalter kauft ein "Event-Ticket" über das zentrale Web-Backend.
|
||||
2. **Lizenz-Datei:** Das Backend generiert eine digital signierte Lizenz-Datei (`.mlic`). Diese enthält:
|
||||
- Veranstalter-Identität (OEPS-Nummer).
|
||||
- Gültigkeitszeitraum (Von-Bis).
|
||||
- Event-Typ (z.B. CSN-B*).
|
||||
3. **Offline-Aktivierung:** Im `EventWizard` der Desktop-App wird die Lizenz-Datei hochgeladen. Die App validiert die Signatur gegen unseren Public-Key (völlig offline).
|
||||
4. **Hardware-Fingerprint:** Die Lizenz wird beim ersten Import an die Hardware-ID des Master-PCs gebunden, um unkontrollierte Vervielfältigung zu verhindern.
|
||||
|
||||
## Konsequenzen
|
||||
- Benutzer muss einmalig (vor dem Turnier) Internetzugang haben, um die Lizenzdatei herunterzuladen.
|
||||
- Keine Abhängigkeit von Server-Verfügbarkeit während des Turniers.
|
||||
- Sicherer Schutz unseres Geschäftsmodells ohne Gängelung des ehrlichen Nutzers.
|
||||
@@ -0,0 +1,33 @@
|
||||
# ADR-0027: Netzwerk-Discovery & Interface-Binding
|
||||
|
||||
## Status
|
||||
|
||||
Akzeptiert & Implementiert (05.05.2026)
|
||||
|
||||
## Kontext
|
||||
|
||||
Desktop-Rechner auf Turnieren sind oft mit mehreren Netzwerken gleichzeitig verbunden (z.B. LAN für das
|
||||
Turnier-Netzwerk, WLAN für Internet-Hotspot). Automatische Discovery-Dienste (mDNS) wählen ohne explizite Konfiguration
|
||||
oft ein Interface, das für die anderen Teilnehmer nicht erreichbar ist (Bridging-Probleme zwischen LAN und WLAN). Zudem
|
||||
blockieren einige Router Multicast-Pakete zwischen WLAN und LAN-Segmenten.
|
||||
|
||||
## Entscheidung
|
||||
|
||||
Wir führen ein robustes, mehrstufiges Netzwerk-Management für die Initialisierung ein:
|
||||
|
||||
1. **Multi-Interface Broadcast:** Der Master registriert seinen Dienst proaktiv auf **allen** verfügbaren
|
||||
Netzwerk-Interfaces (IPv4). Dies erhöht die Chance massiv, dass Clients in verschiedenen Segmenten (WLAN/LAN) den
|
||||
Master finden.
|
||||
2. **Interface-Selektion:** Der Benutzer kann weiterhin ein bevorzugtes Interface wählen. Die Master-Info-Card zeigt die
|
||||
Erreichbarkeit transparent an.
|
||||
3. **Manueller IP-Fallback:** Wenn mDNS fehlschlägt, kann die IP des Masters manuell eingegeben werden. Dies ist der "
|
||||
Ultima-Ratio"-Weg für restriktive Netzwerke.
|
||||
4. **Konnektivitäts-Check (Chat & Self-Test):** Nach dem Handshake wird ein Modal geöffnet, das einen automatischen
|
||||
Ping-Pong Test durchführt und einen Test-Chat bietet. Dies verifiziert die reale Datenübertragung (Serialisierung,
|
||||
WebSockets) noch vor Abschluss des Setups.
|
||||
|
||||
## Konsequenzen
|
||||
|
||||
- Deutlich höhere Stabilität in heterogenen Netzwerkumgebungen.
|
||||
- Transparenteres Feedback für den Anwender bei Verbindungsproblemen.
|
||||
- Der Chat dient als "Connectivity-Proof" für das Support-Personal vor Ort.
|
||||
@@ -1,51 +0,0 @@
|
||||
# 🤖 Konzept: Status-Automat für Nennungen & Zeitplan-Synchronisation
|
||||
|
||||
Dieses Dokument spezifiziert die Logik des Status-Automaten für Nennungen (Sprint C-1) und dessen Auswirkungen auf den dynamischen Zeitplan.
|
||||
|
||||
## 1. Status-Definitionen (NennStatusE)
|
||||
|
||||
Basierend auf `core-domain/Enums.kt`:
|
||||
|
||||
| Status | Bedeutung | Auswirkung auf Zeitplan |
|
||||
| :--- | :--- | :--- |
|
||||
| `EINGEGANGEN` | Nennung wurde erstellt (Initialzustand) | Belegt Zeitslot (basierend auf `reitdauerMinuten`) |
|
||||
| `BESTAETIGT` | Meldestelle hat Nennung geprüft | Belegt Zeitslot |
|
||||
| `NACHNENNUNG` | Nennung nach Nennschluss | Belegt Zeitslot (ggf. am Ende der Liste) |
|
||||
| `TRANSFERIERT` | Nennung wurde auf anderes Paar übertragen | **Inaktiv** (Original-Eintrag wird durch neuen ersetzt) |
|
||||
| `ZURUECKGEZOGEN`| Reiter hat abgemeldet (vor Startlistenerstellung) | **Inaktiv** (Slot wird frei) |
|
||||
| `GESTARTET` | Paar ist in die Prüfung eingeritten | Startzeitpunkt fixiert, Folgestarts ggf. anpassen |
|
||||
| `NICHT_ANGETRETEN`| Paar ist zum Startzeitpunkt nicht erschienen | **Zeitslot verfällt** oder Folgestarts rücken nach |
|
||||
|
||||
## 2. Status-Übergänge & Validierung
|
||||
|
||||
### 2.1 Gültige Übergänge (Beispiele)
|
||||
- `EINGEGANGEN` -> `BESTAETIGT` (Normalfall)
|
||||
- `EINGEGANGEN` -> `ZURUECKGEZOGEN` (Abmeldung)
|
||||
- `BESTAETIGT` -> `TRANSFERIERT` (Reitertausch)
|
||||
- `BESTAETIGT` -> `GESTARTET` (Während des Turniers)
|
||||
|
||||
### 2.2 Side-Effects (Side-Effect-Engine)
|
||||
Wenn sich der Status einer Nennung ändert, müssen folgende Systeme informiert werden:
|
||||
1. **Billing-Service:** Bei `ZURUECKGEZOGEN` ggf. Stornogebühren prüfen. Bei `TRANSFERIERT` Guthaben übertragen.
|
||||
2. **Startlisten-Service:** Bei `ZURUECKGEZOGEN` nach Veröffentlichung der Startliste -> Eintrag als `istGestrichen = true` markieren.
|
||||
3. **Zeitplan-Optimierung:** Bei `NICHT_ANGETRETEN` -> Alle folgenden Startzeiten rücken um `reitdauerMinuten` nach vorne (sofern im Kalender-Modus "Dynamisch" aktiv ist).
|
||||
|
||||
## 3. Dynamische Zeitplan-Anpassung (C-1 Extension)
|
||||
|
||||
Der `StartlistenService` muss eine Methode `aktualisiereZeitplanNachStatusAenderung` erhalten:
|
||||
|
||||
- **Szenario A (Nicht angetreten):** Wenn Nennung X `NICHT_ANGETRETEN` wird, rücken alle folgenden Nennungen in der Abteilung nach vorne.
|
||||
- **Szenario B (Verspätung):** Wenn Nennung X `GESTARTET` wird, aber 2 Minuten später als geplant, verschieben sich alle Folgetermine um +2 Minuten (Kettenreaktion).
|
||||
|
||||
### Puffer-Regel (ÖTO-Konformität)
|
||||
- Eine dynamische Verschiebung nach *vorne* darf nie dazu führen, dass ein Reiter vor seiner ursprünglich kommunizierten Startzeit (oder einem definierten Puffer-Zeitraum von z.B. 15 Minuten) starten muss, ohne dass dies explizit bestätigt wurde.
|
||||
|
||||
## 4. Implementierungs-Leitfaden für Backend (C-1)
|
||||
|
||||
1. Erweiterung von `NennungUseCases.statusAendern` um Aufrufe der Side-Effect-Handler.
|
||||
2. Implementierung des `NennungStatusListener` in `entries-service`.
|
||||
3. Anbindung an den `StartlistenService` zur Zeitre-Kalkulation.
|
||||
|
||||
---
|
||||
**Status:** Entwurf (Lead Architect)
|
||||
**Datum:** 11. April 2026
|
||||
@@ -0,0 +1,92 @@
|
||||
# 🛠️ Guide: Conveyor Installation
|
||||
|
||||
Dieses Dokument beschreibt die Installation von **Hydraulic Conveyor** auf verschiedenen Linux-Distributionen (Ubuntu
|
||||
26.04 und Fedora 44).
|
||||
|
||||
---
|
||||
|
||||
## 1. Ubuntu 26.04 (Debian-basiert)
|
||||
|
||||
Der am einfachsten Weg für Ubuntu ist der direkte Download des `.deb`-Pakets. Dieses konfiguriert bei der Installation
|
||||
automatisch das APT-Repository für zukünftige Updates.
|
||||
|
||||
### Installation via .deb (Empfohlen)
|
||||
|
||||
```bash
|
||||
# Aktuelles Paket herunterladen (Beispiel v12.0 - bitte Version ggf. anpassen)
|
||||
VERSION="12.0"
|
||||
curl -L https://downloads.hydraulic.dev/conveyor/conveyor_${VERSION}_amd64.deb -o conveyor.deb
|
||||
|
||||
# Installieren (konfiguriert auch das Repo automatisch)
|
||||
sudo apt update
|
||||
sudo apt install ./conveyor.deb
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Fedora 44 (RPM-basiert)
|
||||
|
||||
Für Fedora wird die Installation via Tarball empfohlen, da Conveyor als autarkes Binary geliefert wird.
|
||||
|
||||
### Installation via Tarball (Systemweit)
|
||||
|
||||
Dies ist der zuverlässigste Weg für Fedora:
|
||||
|
||||
```bash
|
||||
# Version definieren (Beispiel v12.0, bitte aktuelle Version prüfen)
|
||||
VERSION="12.0"
|
||||
curl -L https://downloads.hydraulic.dev/conveyor/conveyor-${VERSION}-linux-amd64.tar.gz -o conveyor.tar.gz
|
||||
|
||||
# Entpacken nach /opt
|
||||
sudo tar -xzf conveyor.tar.gz -C /opt/
|
||||
sudo ln -s /opt/conveyor-${VERSION}/bin/conveyor /usr/local/bin/conveyor
|
||||
|
||||
# Test
|
||||
conveyor --version
|
||||
```
|
||||
|
||||
### Installation via RPM (Falls verfügbar)
|
||||
|
||||
Prüfen Sie auf der Hydraulic Website, ob mittlerweile ein natives RPM-Repository existiert. Falls ja:
|
||||
|
||||
```bash
|
||||
sudo dnf config-manager --add-repo https://conveyor.hydraulic.dev/rpm/conveyor.repo
|
||||
sudo dnf install conveyor
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Post-Installation & Verifikation
|
||||
|
||||
Nach der Installation sollten Sie den Pfad und die Version prüfen:
|
||||
|
||||
```bash
|
||||
conveyor --version
|
||||
```
|
||||
|
||||
### Root-Key Initialisierung
|
||||
|
||||
Beim ersten Ausführen von `conveyor` wird ein Root-Key generiert. **Sichern Sie diesen unbedingt!**
|
||||
|
||||
```bash
|
||||
conveyor make site
|
||||
```
|
||||
|
||||
*Folgen Sie den Anweisungen im Terminal zur Sicherung des Root-Keys.*
|
||||
|
||||
---
|
||||
|
||||
## 4. Troubleshooting
|
||||
|
||||
### Fehlende Bibliotheken (Fedora)
|
||||
|
||||
Falls Conveyor native Hilfe benötigt (z.B. für Icons oder Kompression):
|
||||
|
||||
```bash
|
||||
sudo dnf install libX11 libXext libXrender
|
||||
```
|
||||
|
||||
### Berechtigungen
|
||||
|
||||
Stellen Sie sicher, dass Ihr Benutzer in der Gruppe `docker` ist, falls Sie Conveyor innerhalb von Containern nutzen
|
||||
oder Docker-basierte Inputs verwenden (für dieses Projekt primär lokal relevant).
|
||||
@@ -0,0 +1,112 @@
|
||||
# 📦 Guide: Desktop App Packaging (Conveyor & Gradle)
|
||||
|
||||
Dieses Dokument beschreibt den professionellen Packaging-Prozess für die Meldestelle Desktop App. Wir nutzen **Conveyor** als primäres Werkzeug für das Cross-Platform Packaging (Windows, Linux, macOS), da es stabile Installer inklusive signierter Updates und gebündelter JREs erzeugt.
|
||||
|
||||
---
|
||||
|
||||
## 1. Strategie: Conveyor vs. Gradle
|
||||
|
||||
| Feature | Conveyor (Empfohlen) | Gradle (Compose Plugin) |
|
||||
| :--- | :--- | :--- |
|
||||
| **Zielgruppe** | Endanwender (Produktion) | Entwickler (Lokaler Test) |
|
||||
| **Plattformen** | Windows (.msix), Linux (.deb), macOS | Nur Host-OS (Linux auf Linux) |
|
||||
| **Updates** | Automatisch integriert | Manuell |
|
||||
| **JRE** | Amazon Corretto (isoliert) | System JRE oder Toolchain |
|
||||
|
||||
---
|
||||
|
||||
## 2. Cross-Packaging mit Conveyor
|
||||
|
||||
Conveyor ist so konfiguriert, dass es von Linux aus Pakete für alle Zielsysteme schnüren kann.
|
||||
|
||||
### Voraussetzungen
|
||||
1. **JAR-Dateien:** Die App muss kompiliert sein:
|
||||
```bash
|
||||
./gradlew :frontend:shells:meldestelle-desktop:jvmJar
|
||||
```
|
||||
2. **Icons:** Das System sucht nach `icon.png` in `frontend/shells/meldestelle-desktop/src/jvmMain/resources/`.
|
||||
|
||||
### Pakete bauen
|
||||
Führen Sie Conveyor im Projekt-Root aus:
|
||||
|
||||
```bash
|
||||
# Komplette Release-Site (Windows & Linux)
|
||||
conveyor make site
|
||||
|
||||
# Nur ein spezifisches Paket (schneller für Tests)
|
||||
conveyor make debian-package # Linux .deb
|
||||
conveyor make windows-msix # Windows .msix
|
||||
```
|
||||
|
||||
Die Ergebnisse liegen im Ordner `output/`.
|
||||
|
||||
---
|
||||
|
||||
## 3. Konfiguration (`conveyor.conf`)
|
||||
|
||||
Wichtige Parameter der aktuellen Konfiguration (v1.0.1):
|
||||
* **JDK:** Nutzt `Amazon Corretto 21` für maximale Cross-Platform Stabilität.
|
||||
* **Heap-Size:** Erhöht auf `-Xmx1024m`, um auch große Stammdaten-Importe zu bewältigen.
|
||||
* **Linux-Deps:** Automatische Installation von `libasound2`, `libgl1-mesa-glx` und `libx11-6`.
|
||||
* **Native Access:** `--enable-native-access=ALL-UNNAMED` ist für Netty/SQLite aktiviert.
|
||||
|
||||
---
|
||||
|
||||
## 4. Netzwerk & Sicherheit (WICHTIG)
|
||||
|
||||
Damit die P2P-Funktionen (Chat, Discovery, Sync) nach der Installation funktionieren, müssen folgende Ports auf dem Host-System offen sein:
|
||||
|
||||
| Port | Protokoll | Funktion |
|
||||
| :--- | :--- | :--- |
|
||||
| **8080** | TCP | P2P Sync & Datenabgleich |
|
||||
| **8090** | TCP | Veranstaltungs-Chat (WebSocket) |
|
||||
| **5353** | UDP | mDNS Discovery (Geräte finden) |
|
||||
|
||||
### Firewall-Einrichtung (Linux)
|
||||
Nutzen Sie das optimierte Setup-Script:
|
||||
```bash
|
||||
sudo ./setup-firewall-linux.sh
|
||||
```
|
||||
|
||||
### Windows-Besonderheit
|
||||
Beim ersten Start der `.msix` App wird Windows fragen, ob der Netzwerkzugriff erlaubt werden soll. **Wichtig:** Sowohl "Private" als auch "Öffentliche" Netzwerke anhaken, falls auf Turnieren oft Gast-WLANs oder Hotspots genutzt werden.
|
||||
|
||||
---
|
||||
|
||||
## 5. Troubleshooting
|
||||
|
||||
### Problem: "No main class specified"
|
||||
**Lösung:** Stellen Sie sicher, dass in der `Main.kt` eine saubere Top-Level `fun main()` existiert und in der `conveyor.conf` auf `at.mocode.frontend.shell.desktop.MainKt` verwiesen wird.
|
||||
|
||||
### Problem: SQLite / Native Libs laden nicht
|
||||
**Lösung:** Prüfen Sie, ob `extract-native-libraries.conf` in der `conveyor.conf` inkludiert ist.
|
||||
|
||||
### Problem: JmDNS findet keine Teilnehmer
|
||||
**Lösung:** Prüfen Sie die Ports via `ss -tulpn`. Auf Linux blockieren oft Docker-Interfaces (`br-*`) den Broadcast. Die App filtert diese nun automatisch, aber ein aktives `setup-firewall-linux.sh` ist zwingend erforderlich.
|
||||
|
||||
## 6. Performance-Optimierung (Gradle)
|
||||
|
||||
Der Build-Prozess kann bei aktivierter Web-Kompilierung (WASM/JS) sehr lange dauern. Für die reine Desktop-Entwicklung
|
||||
wurde WASM standardmäßig deaktiviert.
|
||||
|
||||
* **WASM aktivieren (z.B. für CI/Portal):** `./gradlew -PenableWasm=true ...`
|
||||
* **WASM deaktivieren (Default):** `./gradlew ...` (Spart bis zu 70% Build-Zeit).
|
||||
|
||||
## 7. Gradle Deep-Optimierung
|
||||
|
||||
Neben dem Deaktivieren von WASM wurden folgende systemweite Optimierungen in der `gradle.properties` vorgenommen:
|
||||
|
||||
* **Configuration Cache:** Aktiviert. Gradle merkt sich die Projektstruktur, was den Start jedes Befehls um Sekunden bis
|
||||
Minuten verkürzt.
|
||||
* **JVM G1GC & 12GB Heap:** Optimiert für große Multi-Modul-Projekte auf Systemen mit viel RAM (ab 16GB).
|
||||
* **Parallel Workers:** Erhöht auf 12, um die 16 logischen Kerne Ihres Rechners besser auszulasten.
|
||||
|
||||
### Optionale Analysen
|
||||
|
||||
Statische Analysen sind nun standardmäßig **deaktiviert**, um den täglichen Workflow nicht zu bremsen.
|
||||
|
||||
* **Analyse laufen lassen:** `./gradlew staticAnalysis -PrunStaticAnalysis=true`
|
||||
* **Dokka Dokumentation bauen:** `./gradlew dokkaAll -PrunDokka=true`
|
||||
|
||||
Stellen Sie in der `gradle.properties` sicher, dass `enableWasm=false` gesetzt ist, wenn Sie primär an der Desktop-App
|
||||
arbeiten.
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
type: Guide
|
||||
status: ACTIVE
|
||||
owner: Lead Architect
|
||||
last_update: 2026-04-28
|
||||
---
|
||||
|
||||
# Git Branching & Deployment Strategy (Meldestelle)
|
||||
|
||||
Um parallele Weiterentwicklung und stabile Feld-Tests zu ermöglichen, nutzen wir einen vereinfachten **GitHub Flow** mit Release-Tags. Da wir ein kleines Team (bzw. Solo-Entwickler mit KI-Agents) sind, verzichten wir auf übermäßig komplexe Git-Flow-Modelle (wie `develop`, `release/*`, `hotfix/*`), stellen aber Stabilität für Deployments sicher.
|
||||
|
||||
## 1. Branching-Struktur
|
||||
|
||||
### `main` (Source of Truth / Production)
|
||||
* **Zweck:** Enthält *immer* den aktuellen, stabilen und im Feld getesteten/auslieferbaren Code.
|
||||
* **Regel:** Direkte Commits auf `main` sind tabu (außer Notfall-Hotfixes).
|
||||
* **Deployment:** Ein Push/Merge auf `main` bedeutet **nicht** zwingend ein sofortiges Deployment auf Zora, aber der Code ist *bereit* dafür.
|
||||
|
||||
### Feature Branches (`feature/*` oder `fix/*`)
|
||||
* **Zweck:** Hier findet die eigentliche Entwicklung statt (z.B. neue Bounded Contexts, Wizards).
|
||||
* **Namenskonvention:** `feature/event-wizard-neu`, `fix/zns-import-bug`
|
||||
* **Lebensdauer:** So kurz wie möglich. Sobald ein Feature/Fix *in sich geschlossen* und lokal getestet ist, wird ein Pull Request (PR) auf `main` erstellt.
|
||||
|
||||
### Release Tags (`v1.x.x`)
|
||||
* **Zweck:** Markiert einen spezifischen, stabilen Punkt auf dem `main`-Branch, der tatsächlich für ein Turnier (Feld-Test) deployed wurde.
|
||||
* **Szenario:** Du hast Version `v1.2.0` (Plan-B) für ein Turnier deployed. Du entwickelst weiter auf `feature/*` und mergest in `main`. Das nächste Turnier bekommt dann Tag `v1.3.0`.
|
||||
|
||||
## 2. Der Workflow im Alltag
|
||||
|
||||
1. **Start:** `git checkout main` -> `git pull` -> `git checkout -b feature/mein-neues-feature`
|
||||
2. **Entwicklung:** Arbeiten, KI-Agents nutzen, Commits machen.
|
||||
3. **Abschluss:** Feature ist fertig.
|
||||
4. **Merge:** Pull Request in Gitea erstellen (oder lokal: `git checkout main`, `git merge feature/mein-neues-feature`, `git push`).
|
||||
5. **Aufräumen:** `git branch -d feature/mein-neues-feature`
|
||||
|
||||
## 3. Strategie für Feld-Tests (Turnier-Einsatz)
|
||||
|
||||
Wenn ein Turnier ansteht und ein stabiler Stand eingefroren werden muss:
|
||||
|
||||
1. Stelle sicher, dass `main` den gewünschten Zustand hat.
|
||||
2. Setze einen Tag in Git: `git tag -a v1.2.0 -m "Release für Turnier in Neumarkt"`
|
||||
3. Pushe den Tag: `git push origin v1.2.0`
|
||||
4. **Deployment:** Das Deployment-Skript zieht sich *diesen* Tag auf Zora (oder baut den Docker-Container aus diesem Tag).
|
||||
|
||||
### Was passiert, wenn während des Turniers ein Bug auftritt (Hotfix)?
|
||||
|
||||
*Szenario: Das Turnier läuft auf `v1.2.0`. Auf `main` gibt es schon neuere Features (unfertig).*
|
||||
|
||||
1. Checkout des stabilen Tags: `git checkout -b hotfix/turnier-fix v1.2.0`
|
||||
2. Bug fixen, committen.
|
||||
3. Neuen Tag für das Deployment setzen: `git tag -a v1.2.1 -m "Hotfix ZNS Import"`
|
||||
4. `git push origin v1.2.1` -> Fix wird auf Zora deployed.
|
||||
5. **WICHTIG (Backport):** Damit der Fix nicht verloren geht, den Hotfix-Branch danach in `main` mergen: `git checkout main`, `git merge hotfix/turnier-fix`.
|
||||
|
||||
## 4. Gitea Actions (CI/CD)
|
||||
* **Pushes auf `feature/*`:** Führen Code-Checks/Tests aus.
|
||||
* **Pushes auf `main`:** Führen erweiterte Tests aus und bauen Docker-Images mit dem Tag `latest` sowie dem Git-SHA in die interne Registry (`10.0.0.22:3000`).
|
||||
* **Erstellung eines Tags (`v*`):** Triggert automatisch den Build und Push von Docker-Images in die interne Registry. Das Image erhält den Namen des Tags (z.B. `:v1.2.0`). Dies ist die Basis für stabile Deployments auf Zora.
|
||||
@@ -0,0 +1,123 @@
|
||||
A26128CSN-C-NEU CSNP-C-NEU NEUM2026042520260425CSN-C-Neu CSNP-C_Neu 2.2PSO v1.07
|
||||
B010Stilspringprüfung - CSNP-C_N006000000001
|
||||
C010001307002129000000000000000000000000000000000000021771000000
|
||||
D001PG47Paddy's Nikita 170107Remplbauer Selina 00080000000 000000AUT*
|
||||
D002PK06H-S Button 196040Gillinger Marlene 00067000000 000000AUT*
|
||||
D003P824Pit 3 184759Krenn Eva 00055000000 000000AUT*
|
||||
D004P814Balu 6 193244Remplbauer Sophia 00000000000 000000AUT
|
||||
D004P901Daneder's Blitz 195501Weidinger Janina 00000000000 000000AUT
|
||||
D004PB70Daneder's Caramello 163545Montgomery Helena 00000000000 000000AUT
|
||||
B021Einlaufspringprüfung - CSN-C-Ne008000000002
|
||||
C021001307002129000000000000000000000000000000000000021771000000
|
||||
D0001781Ritual Do Vizo 126532Layr Bianca 00000000000 000000AUT*
|
||||
D000P816Aldensfarm Breaking Dawn 159405Starzengruber Marie-Theres 00000000000 000000AUT*
|
||||
D000P901Daneder's Blitz 195501Weidinger Janina 00000000000 000000AUT*
|
||||
D000PB70Daneder's Caramello 163545Montgomery Helena 00000000000 000000AUT*
|
||||
D000PE14SD Antonette 929451Mayrhofer Simon 00000000000 000000AUT*
|
||||
D000PG47Paddy's Nikita 170107Remplbauer Selina 00000000000 000000AUT*
|
||||
D000P824Pit 3 184759Krenn Eva 00003000000 000000AUT
|
||||
D000P814Balu 6 193244Remplbauer Sophia 00000000000 000000AUT
|
||||
B022Einlaufspringprüfung - CSN-C-Ne003000000002
|
||||
C022001307002129000000000000000000000000000000000000021771000000
|
||||
D000AR70Chocolate Kiss 2 147265Vanova Nina 00000000000 000000AUT*10258795
|
||||
D000P561Ginger Bread Girl 153601Winter Maja Sophie 00000000000 000000AUT*
|
||||
D997Z001Wildberry Gold RPZ 168660Zechmeister-Paster Diana A00000000000 000000AUT
|
||||
B030Stilspringprüfung - CSNP-C_N006000000003
|
||||
C030001307002129000000000000000000000000000000000000021771000000
|
||||
D001PA53Rathcline Star 178474Schmidmayr Nena Sophie 00072000000 000000AUT*
|
||||
D002P152Verena 3 170454Krenn Miriam 00070000000 000000AUT*
|
||||
D003P816Aldensfarm Breaking Dawn 159405Starzengruber Marie-Theres 00068000000 000000AUT*
|
||||
D004P561Ginger Bread Girl 153601Winter Maja Sophie 00067000000 000000AUT*
|
||||
D997PE14SD Antonette 929451Mayrhofer Simon A00000000000 000000AUT
|
||||
D997PK06H-S Button 196040Gillinger Marlene A00000000000 000000AUT
|
||||
B041Einlaufspringprüfung - CSNP-C_N006000000004
|
||||
C041001307002129000000000000000000000000000000000000021771000000
|
||||
D0002M80Handsome 186927Lengauer Jelena 00000000000 000000AUT* 106KB09
|
||||
D000AN19Exklusiv EM 187665Mück Hannah 00000000000 000000AUT*
|
||||
D0001781Ritual Do Vizo 126532Layr Bianca 00040000000 000000AUT
|
||||
D0004Y59Legolas 196 925183Schreiber Tamina 00047000000 000000GER
|
||||
D000AB83HB Vijola 920327Reisinger Marlene 00056000000 000000AUT
|
||||
D0003E99Quinet 906586Kapeller Emilia 00000000000 000000AUT
|
||||
B042Einlaufspringprüfung - CSNP-C_N007000000004
|
||||
C042001307002129000000000000000000000000000000000000021771000000
|
||||
D0003K69Lillet 18 150620Reitetschläger Lena 00000000000 000000AUT*
|
||||
D0005789Furiosa de la Bryere CE 140156Ehrentraut Carina 00000000000 000000AUT*
|
||||
D000A099Quintessa 2 609548Aichinger Bianca 00000000000 000000AUT*
|
||||
D0003M58Samantha 25 609771Karl Reinhard 00040000000 000000AUT
|
||||
D000H606Moondancer 070156Alberer Manuela 00040000000 000000AUT
|
||||
D000Z001Wildberry Gold RPZ 168660Zechmeister-Paster Diana 00092500000 000000AUT
|
||||
D000AR70Chocolate Kiss 2 147265Vanova Nina 00129000000 000000AUT 10258795
|
||||
B050Stilspringprüfung - CSNP-C_N003000000005
|
||||
C050001307002129000000000000000000000000000000000000021771000000
|
||||
D001P152Verena 3 170454Krenn Miriam 00074000000 000000AUT*
|
||||
D002P985Taffy 2 193430Schartmüller Sarah 00072000000 000000AUT*
|
||||
D003PA53Rathcline Star 906580Egger Julia 00065000000 000000AUT*
|
||||
B061Stilspringprüfung - CSNP-C_N009000000006
|
||||
C061001307002129000000000000000000000000000000000000021771000000
|
||||
D0012B41Guccini 922710Simlinger Marlies 00075000000 000000AUT*
|
||||
D002AN19Exklusiv EM 187665Mück Hannah 00072000000 000000AUT*
|
||||
D0033E99Quinet 906586Kapeller Emilia 00071000000 000000AUT*
|
||||
D0042M80Handsome 186927Lengauer Jelena 00070000000 000000AUT* 106KB09
|
||||
D004AF41Cäsar 55 916541Dugandzic Sarah 00070000000 000000AUT*
|
||||
D006PA53Rathcline Star 906580Egger Julia 00068000000 000000AUT
|
||||
D0074Y59Legolas 196 925183Schreiber Tamina 00062000000 000000GER
|
||||
D0083785Coeur 17 145963Obermüller Hannah 00061000000 000000AUT
|
||||
D009AB83HB Vijola 920327Reisinger Marlene 00057000000 000000AUT
|
||||
B062Stilspringprüfung - CSNP-C_N007000000006
|
||||
C062001307002129000000000000000000000000000000000000021771000000
|
||||
D001A099Quintessa 2 609548Aichinger Bianca 00082000000 000000AUT*
|
||||
D0025789Furiosa de la Bryere CE 140156Ehrentraut Carina 00072000000 000000AUT*
|
||||
D0033K69Lillet 18 150620Reitetschläger Lena 00067000000 000000AUT*
|
||||
D004KSS1Charity Coke 053749Eichler Eva 00065000000 000000AUT*
|
||||
D0053M58Samantha 25 609771Karl Reinhard 00060000000 000000AUT
|
||||
D005H606Moondancer 070156Alberer Manuela 00060000000 000000AUT
|
||||
D9971A11Gradan 102783Steyrer Anna A00000000000 000000AUT
|
||||
B070Stilspringprüfung - CSNP-C_N002000000007
|
||||
C070001307002129000000000000000000000000000000000000021771000000
|
||||
D001Y001Bella Graziella 144315Gaugl Laura 00075000000 000000AUT*
|
||||
D002P985Taffy 2 193430Schartmüller Sarah 00000000000 000000AUT
|
||||
B080Springreiterbewerb - CSNP-C_N003000000008
|
||||
C080001307002129000000000000000000000000000000000000021771000000
|
||||
D0013785Coeur 17 145963Obermüller Hannah 00080000000 000000AUT*
|
||||
D0022M80Handsome 186927Lengauer Jelena 00072000000 000000AUT* 106KB09
|
||||
D9973E99Quinet 178474Schmidmayr Nena Sophie A00000000000 000000AUT
|
||||
B091Standardspringprüfung - CSNP-C_N005000000009
|
||||
C091001307002129000000000000000000000000000000000000021771000000
|
||||
D0012062Grover 157407Pröll Leonie 00000005416 000000AUT*
|
||||
D0022B41Guccini 160813Grubmüller Lea 00000005463 000000AUT*
|
||||
D0031317Quality's Finest 612295Stroblmair Victoria 00000005492 000000AUT*
|
||||
D0041A11Gradan 102783Steyrer Anna 00000005858 000000AUT*
|
||||
D005KSS1Charity Coke 053749Eichler Eva 00040006428 000000AUT
|
||||
B092Standardspringprüfung - CSNP-C_N007000000009
|
||||
C092001307002129000000000000000000000000000000000000021771000000
|
||||
D001A024D Day 075374Ambros Susanne 00000005940 000000AUT*10071068 108EH50
|
||||
D0021G88Hamira 3 074007Beißmann Andreas 00000005991 000000AUT*
|
||||
D0032G77S Mirrallas 605835Ellmer Kassandra 00000006298 000000AUT*
|
||||
D0043966Capitaine 601366Madlmayr Carina 00040005862 000000AUT
|
||||
D0051942Obora's Agnetha 601300Hofer Michaela 00040005966 000000AUT
|
||||
D006Y001Bella Graziella 144315Gaugl Laura 00080005012 000000AUT
|
||||
D9972785Herr Frodo 144315Gaugl Laura A00000000000 000000AUT
|
||||
B100Springpferdeprüfung - CSN-C-Ne000000000010
|
||||
C100001307002129000000000000000000000000000000000000021771000000
|
||||
B110Stilspringprüfung - CSN-C-Ne002000000011
|
||||
C110001307002129000000000000000000000000000000000000021771000000
|
||||
D0012062Grover 157407Pröll Leonie 00085000000 000000AUT*
|
||||
D0021317Quality's Finest 612295Stroblmair Victoria 00080000000 000000AUT*
|
||||
B121Standardspringprüfung - CSN-C-Ne002000000012
|
||||
C121001307002129000000000000000000000000000000000000021771000000
|
||||
D0012062Grover 157407Pröll Leonie 00040005651 000000AUT*
|
||||
D0022B41Guccini 160813Grubmüller Lea 00080005774 000000AUT
|
||||
B122Standardspringprüfung - CSN-C-Ne004000000012
|
||||
C122001307002129000000000000000000000000000000000000021771000000
|
||||
D001AS94Landliebe 3 162776Höllmüller Anna 00000005557 000000AUT*10294537
|
||||
D0022G77S Mirrallas 605835Ellmer Kassandra 00000006212 000000AUT*
|
||||
D0031942Obora's Agnetha 601300Hofer Michaela 00000006723 000000AUT*
|
||||
D004A024D Day 075374Ambros Susanne 00040005943 000000AUT 10071068 108EH50
|
||||
B130Stilspringprüfung - CSN-C-Ne001000000013
|
||||
C130001307002129000000000000000000000000000000000000021771000000
|
||||
D0014258Casino East 601300Hofer Michaela 00075000000 000000AUT*
|
||||
B140Standardspringprüfung - CSN-C-Ne003000000014
|
||||
C140001307002129000000000000000000000000000000000000021771000000
|
||||
D0012010Leonidas van de Zuuthoeve Z 145960Fischerlehner Leonie 00000005368 000000AUT*
|
||||
D002AS94Landliebe 3 162776Höllmüller Anna 00000005745 000000AUT*10294537
|
||||
D0034258Casino East 601300Hofer Michaela 00000006261 000000AUT*
|
||||
@@ -0,0 +1,96 @@
|
||||
A26129CDN-C-NEU CDNP-C_NEU NEUM2026042620260426 2.2PSO v1.07
|
||||
B010Dressurprüfung lzf CDN-C_Ne002000000001
|
||||
C010000000038705000000000000000000000000000000000000000000000000
|
||||
D001PB70Daneder's Caramello 163545Montgomery Helena 00062000000 000000AUT*
|
||||
D0022892Amore 5 AUT Stadler Caroline 00060000000 000000AUT*
|
||||
B020Dressurprüfung lzf CDN-C_Ne003000000002
|
||||
C020000000038705000000000000000000000000000000000000000000000000
|
||||
D0014208Sahib Silver G 195331Neuhauser Lara 00075000000 000000AUT*
|
||||
D0022892Amore 5 AUT Stadler Caroline 00068000000 000000AUT*
|
||||
D003PB70Daneder's Caramello 163545Montgomery Helena 00060000000 000000AUT*
|
||||
B030Dressurreiterprüfung lzf CDN-C_Ne005000000003
|
||||
C030035110000000000000000000000000000000000000000000000000000000
|
||||
D001PC62Flora HP 917397Altendorfer Pia 00080000000 000000AUT*
|
||||
D002Z002Abrakadabra S 107926Fürbäck Melanie 00077000000 000000AUT*
|
||||
D0034Y59Legolas 196 184074Stöbich Enya 00068000000 000000AUT*
|
||||
D004HKTBAcceptius FA 196261Salzinger Luisa Marie 00064000000 000000AUT
|
||||
D005PA53Rathcline Star 922380Kropfreiter Ines 00062000000 000000AUT
|
||||
B040Dressurreiterprüfung lzf CDN-C_Ne006000000004
|
||||
C040000000038705000000000000000000000000000000000000000000000000
|
||||
D001PC62Flora HP 917397Altendorfer Pia 00078000000 000000AUT*
|
||||
D0024208Sahib Silver G 195331Neuhauser Lara 00076000000 000000AUT*
|
||||
D003Z002Abrakadabra S 107926Fürbäck Melanie 00068000000 000000AUT*
|
||||
D004HKTBAcceptius FA 196261Salzinger Luisa Marie 00064000000 000000AUT
|
||||
D0054Y59Legolas 196 184074Stöbich Enya 00062000000 000000AUT
|
||||
D006PA53Rathcline Star 922380Kropfreiter Ines 00060000000 000000AUT
|
||||
B050Dressurreiterprüfung lzf CDN-C_Ne001000000005
|
||||
C050035110000000000000000000000000000000000000000000000000000000
|
||||
D001PF06Domino N AUT Stelzl Helena 00080000000 000000AUT*
|
||||
B060Dressurreiterprüfung lzf CDN-C_Ne000000000006
|
||||
C060035110000000000000000000000000000000000000000000000000000000
|
||||
B070Pony Dressurprüfung A CSNP-C_N003000000007
|
||||
C070000000038705000000000000000000000000000000000000000000000000
|
||||
D001PT24Daneder's Captain 146663Steinmetz Sinah-Marie 00065000000 000000AUT*
|
||||
D002P561Ginger Bread Girl 153601Winter Maja Sophie 00060000000 000000AUT*
|
||||
D003PA53Rathcline Star 906592Emsenhuber Tanja 00058000000 000000AUT
|
||||
B081Dressurreiterprüfung A CDN-C_Ne006000000008
|
||||
C081035110038705000000000000000000000000000000000000000000000000
|
||||
D0013888Ravasz 123156Scheiblechner Sonja 00072000000 000000AUT*
|
||||
D0024307Makker 146066Gstöttenbauer Olivia 00064000000 000000AUT*
|
||||
D003P561Ginger Bread Girl 153601Winter Maja Sophie 00062000000 000000AUT*
|
||||
D0042083Light Blue 194297Hazoth Anna-Maria 00060000000 000000AUT*
|
||||
D0053M58Samantha 25 609771Karl Reinhard 00058000000 000000AUT
|
||||
D005KSS1Charity Coke 053749Eichler Eva 00058000000 000000AUT
|
||||
B082Dressurreiterprüfung A CDN-C_Ne002000000008
|
||||
C082035110038705000000000000000000000000000000000000000000000000
|
||||
D001GIGIGigi D'Agostidinina 076742Klein Elisabeth 00068000000 000000AUT*10144403
|
||||
D002A590Queeny 8 612592Panzirsch Anna 00064000000 000000AUT*
|
||||
B091Dressurprüfung A CDN-C_Ne007000000009
|
||||
C091035110038705000000000000000000000000000000000000000000000000
|
||||
D0013888Ravasz 123156Scheiblechner Sonja 00070000000 000000AUT*
|
||||
D002AN19Exklusiv EM 187665Mück Hannah 00064000000 000000AUT*
|
||||
D0032083Light Blue 194297Hazoth Anna-Maria 00062000000 000000AUT*
|
||||
D0044B66Vingino's Victory 616957Kiesenhofer Sarah 00058000000 000000AUT
|
||||
D0053M58Samantha 25 609771Karl Reinhard 00055000000 000000AUT
|
||||
D005KSS1Charity Coke 053749Eichler Eva 00055000000 000000AUT
|
||||
D0074307Makker 146066Gstöttenbauer Olivia 00053000000 000000AUT
|
||||
B092Dressurprüfung A CDN-C_Ne004000000009
|
||||
C092035110038705000000000000000000000000000000000000000000000000
|
||||
D001GIGIGigi D'Agostidinina 076742Klein Elisabeth 00068000000 000000AUT*10144403
|
||||
D002AL46Superbunt 616836Lengauer Julia 00065000000 000000AUT*
|
||||
D0032010Leonidas van de Zuuthoeve Z 145960Fischerlehner Leonie 00064000000 000000AUT*
|
||||
D004A590Queeny 8 612592Panzirsch Anna 00058000000 000000AUT
|
||||
B100Pony Dressurprüfung L CSNP-C_N001000000010
|
||||
C100035110038705000000000000000000000000000000000000000000000000
|
||||
D001P540Pieter V 153601Winter Maja Sophie 00056000000 000000AUT*
|
||||
B110Dressurreiterprüfung L CDN-C_Ne003000000011
|
||||
C110035110038705000000000000000000000000000000000000000000000000
|
||||
D0011317Quality's Finest 612295Stroblmair Victoria 00074000000 000000AUT*
|
||||
D0021F34Ferro Felicis 146066Gstöttenbauer Olivia 00064000000 000000AUT*
|
||||
D003P540Pieter V 153601Winter Maja Sophie 00062000000 000000AUT*
|
||||
B121Dressurprüfung L CDN-C_Ne003000000012
|
||||
C121035110038705000000000000000000000000000000000000000000000000
|
||||
D001AN19Exklusiv EM 187665Mück Hannah 00068000000 000000AUT*
|
||||
D0021F34Ferro Felicis 146066Gstöttenbauer Olivia 00062000000 000000AUT*
|
||||
D003AE11Merlin SH 061601Povacz Gisela 00060000000 000000AUT*
|
||||
B122Dressurprüfung L CDN-C_Ne002000000012
|
||||
C122035110038705000000000000000000000000000000000000000000000000
|
||||
D001A024D Day 075374Ambros Susanne 00066000000 000000AUT*10071068 108EH50
|
||||
D0023966Capitaine 601366Madlmayr Carina 00060000000 000000AUT*
|
||||
B131Dressurpferdeprüfung A CDN-C_Ne003000000013
|
||||
C131035110038705000000000000000000000000000000000000000000000000
|
||||
D001AX99Bon Sai 102783Steyrer Anna 00073400000 000000AUT*
|
||||
D0020214SHS Donna Verdi 169981Süss Sarah 00066000000 000000AUT*
|
||||
D003PT24Daneder's Captain 146663Steinmetz Sinah-Marie 00061200000 000000AUT*
|
||||
B132Dressurpferdeprüfung A CDN-C_Ne005000000013
|
||||
C132035110038705000000000000000000000000000000000000000000000000
|
||||
D001MAXIVerstappen 2 075374Ambros Susanne 00074600000 000000AUT*10071068
|
||||
D0022H08SHS Weltmädel 169981Süss Sarah 00074200000 000000AUT*
|
||||
D003P983Daneders Tornado 153601Winter Maja Sophie 00064800000 000000AUT*
|
||||
D0044B03SHS Roubinjo 169981Süss Sarah 00064200000 000000AUT*
|
||||
D0054B66Vingino's Victory 616957Kiesenhofer Sarah 00063000000 000000AUT*
|
||||
B140Dressurpferdeprüfung L CDN-C_Ne003000000014
|
||||
C140035110038705000000000000000000000000000000000000000000000000
|
||||
D0012H08SHS Weltmädel 169981Süss Sarah 00067800000 000000AUT*
|
||||
D002P983Daneders Tornado 153601Winter Maja Sophie 00064800000 000000AUT*
|
||||
D0034B03SHS Roubinjo 169981Süss Sarah 00063000000 000000AUT*
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 325 KiB |
@@ -8,7 +8,7 @@
|
||||
|
||||
#### 1. Standardized Dockerfile Template (v2.5.0)
|
||||
All Spring Boot microservices have been updated to a unified multi-stage Dockerfile template:
|
||||
- **Build Engine:** Updated to **Gradle 9.4.1** and **JDK 25** (eclipse-temurin).
|
||||
- **Build Engine:** Updated to **Gradle 9.5.0** and **JDK 25** (eclipse-temurin).
|
||||
- **Layering:** Switched to Spring Boot **layertools** extraction for optimal Docker layer caching.
|
||||
- **Security:**
|
||||
- Integrated **tini** as init process to handle signals correctly.
|
||||
@@ -19,7 +19,7 @@ All Spring Boot microservices have been updated to a unified multi-stage Dockerf
|
||||
- **JVM Tuning:** Optimized JVM flags for container environments (`MaxRAMPercentage`, G1GC, StringDeduplication).
|
||||
|
||||
#### 2. Docker Compose Synchronization (`dc-backend.yaml`)
|
||||
- **Global Args:** Synchronized `GRADLE_VERSION` (9.4.1) and `JAVA_VERSION` (25) across all service build definitions.
|
||||
- **Global Args:** Synchronized `GRADLE_VERSION` (9.5.0) and `JAVA_VERSION` (25) across all service build definitions.
|
||||
- **Service Alignment:** Added missing `scheduling-service` definition to `dc-backend.yaml`.
|
||||
- **Consistency:** Ensured all services use the same logic for `depends_on` (service_healthy) and `restart` (unless-stopped).
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ Deine Aufgaben:
|
||||
6. **Handover:** Stelle Architekturentscheidungen nicht nur als Text, sondern auch als Diagramm (Mermaid/PlantUML) bereit.
|
||||
7. Erstelle und pflege die MASTER ROADMAP. Du bist der "Hüter des Plans". Du delegierst Aufgaben an die spezialisierten Agenten (Backend, Frontend, DevOps, QA), führst sie aber nicht selbst aus, es sei denn, es betrifft direkt die Architektur oder das Build-System.
|
||||
8. **Bounded Context Awareness:** Stelle sicher, dass Änderungen immer einem der 6 SCS (Self-Contained Systems) zugeordnet sind und die Grenzen gewahrt bleiben.
|
||||
9. **Active Task Manifest:** Nutze die Datei `docs/ACTIVE_TASK.md`, um den aktuellen Arbeitsstand zu dokumentieren und für die nächste Session/KI bereitzustellen.
|
||||
10. **Scout-Prinzip:** Wenn eine Aufgabe unklar ist, delegiere zuerst an Junie als "Scout", um Code-Snippets in `docs/04_Agents/Research_Snippet.md` zu sammeln, bevor architektonische Entscheidungen getroffen werden.
|
||||
|
||||
Don't:
|
||||
- Implementiere keine Business-Logik in Backend-Services (→ Backend Developer).
|
||||
|
||||
@@ -23,6 +23,7 @@ Ziel:
|
||||
- Jede Session endet mit genau einem Artefakt in `docs/`.
|
||||
- Veraltetes Wissen wird sauber archiviert.
|
||||
- Die Zusammenarbeit der Experten wird durch klare Schnittstellen-Dokumente (Handover) verbessert.
|
||||
- **Context-Handover:** Am Ende jeder Session wird ein standardisierter `🔄 NEXT SESSION CONTEXT` Block ausgegeben und die Datei `docs/ACTIVE_TASK.md` aktualisiert.
|
||||
|
||||
Regeln:
|
||||
1. Single Source of Truth ist `docs/`.
|
||||
@@ -31,11 +32,22 @@ Regeln:
|
||||
- Reference / technische Wahrheit pro System (z.B. `docs/05_Backend/Services/<service>.md`)
|
||||
- How-to / Runbook (passender Bereich)
|
||||
- Journal Entry (`docs/99_Journal/`)
|
||||
3. **Quality Gate:** Prüfe, ob die Artefakte den Standards entsprechen:
|
||||
3. **Session-Abschluss Checkliste:**
|
||||
- [ ] Wurden alle geänderten/neuen Dateien im Journal/Artefakt mit absolutem Pfad erwähnt?
|
||||
- [ ] Wurde ein "Warum" dokumentiert (nicht nur das "Was")?
|
||||
- [ ] Wurde die Datei `docs/ACTIVE_TASK.md` auf den neuesten Stand gebracht?
|
||||
- [ ] Enthält die finale Antwort den `🔄 NEXT SESSION CONTEXT` Block?
|
||||
4. **🔄 NEXT SESSION CONTEXT Struktur:**
|
||||
- **Focus:** [SCS / Feature-Name]
|
||||
- **Last State:** [Kurz-Zusammenfassung des aktuellen Stands]
|
||||
- **Critical Files:** [Liste der wichtigsten Dateien für die nächste Session]
|
||||
- **Open Threads:** [Offene Fragen oder nächste konkrete Schritte]
|
||||
- **Agent-Handover:** [Spezifische Anweisungen für die nächste KI-Rolle]
|
||||
5. **Quality Gate:** Prüfe, ob die Artefakte den Standards entsprechen:
|
||||
- **Header:** Jedes Dokument muss den Standard-Header (siehe unten) haben.
|
||||
- **Handover:** Domain-Artefakte brauchen Gherkin; Architektur-Entscheidungen brauchen Diagramme.
|
||||
- **ADR-Pflicht:** Bei größeren Entscheidungen (z.B. Tech-Stack-Änderungen) muss ein ADR eingefordert werden.
|
||||
4. **Lifecycle & Archivierung:**
|
||||
6. **Lifecycle & Archivierung:**
|
||||
- Veraltete Dokumente (z.B. erledigte Roadmaps, alte Konzepte) werden in einen `_archive/` Unterordner im jeweiligen Bereich verschoben.
|
||||
- Dateiname bei Archivierung: `YYYY-MM-DD_OriginalName.md`.
|
||||
- Status im Header auf `ARCHIVED` setzen.
|
||||
|
||||
@@ -17,6 +17,8 @@ Gemini wird genutzt für **Konzeptarbeit**: Varianten vergleichen, Argumente/Tra
|
||||
* Immer 2–4 Optionen mit Vor-/Nachteilen liefern.
|
||||
* Offene Fragen explizit als Liste zurückgeben.
|
||||
* Formuliere Outputs so, dass sie **direkt** in ein `docs/*` Artefakt übernommen werden können.
|
||||
* **Richter-Prinzip:** Nutze von Junie bereitgestellte Code-Snippets in `docs/04_Agents/Research_Snippet.md`, um fundierte Entscheidungen zu treffen, ohne den Code selbst im Detail lesen zu müssen.
|
||||
* **Manifest-Pflicht:** Nutze die `docs/ACTIVE_TASK.md`, um den Kontext-Handover zwischen Sessions zu gewährleisten.
|
||||
|
||||
## Don’t
|
||||
* Keine Annahmen als Fakten verkaufen.
|
||||
|
||||
@@ -21,6 +21,8 @@ Junie wird genutzt für **Repo-nahe Arbeit**: Code lesen, reale Pfade/Module fin
|
||||
## Don’t
|
||||
* Keine „zweite Wahrheit“ in `.junie/*` etablieren (Tooling bleibt Tooling).
|
||||
* Keine Entscheidungen „im Chat verlieren“ – am Ende muss ein Artefakt in `docs/` stehen.
|
||||
* **Scout-Prinzip:** Agiere bei Bedarf als technischer Scout für Gemini. Sammele Code-Beweise und Snippets in `docs/04_Agents/Research_Snippet.md`, um architektonische Entscheidungen vorzubereiten.
|
||||
* **Manifest-Pflicht:** Lies bei Session-Start immer zuerst die `MASTER_ROADMAP` und dann die `docs/ACTIVE_TASK.md`.
|
||||
|
||||
## Abschluss (Pflicht)
|
||||
Am Ende der Session genau **ein** Artefakt gemäß `docs/03_Agents/README.md` erzeugen (oder aktualisieren).
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
🏗️ **[Lead Architect]**
|
||||
Datum: 30. April 2026
|
||||
|
||||
# 🧪 POC-Anleitung: Zero-Config Initialisierung
|
||||
|
||||
Dieses Dokument beschreibt die Schritte für den technischen Hardware-POC der "Meldestelle" Desktop-App.
|
||||
|
||||
## 1. Bauen der App
|
||||
Führen Sie auf Ihrem Entwicklungsrechner aus:
|
||||
```bash
|
||||
./gradlew :frontend:shells:meldestelle-desktop:createDistributable
|
||||
```
|
||||
Kopieren Sie den Ordner `frontend/shells/meldestelle-desktop/build/compose/binaries/main/app` auf einen USB-Stick.
|
||||
|
||||
## 2. Test am Master-PC (PC-1)
|
||||
1. Starten Sie die App vom Stick.
|
||||
2. Wählen Sie die Rolle **Master (Host)**.
|
||||
3. Vergeben Sie einen Namen (z.B. "Meldestelle-Zentrale").
|
||||
4. Geben Sie den **Sicherheitsschlüssel** (Demo: `1234`) ein.
|
||||
5. Wählen Sie den USB-Pfad für **Plan-USB** aus (Native FileDialog öffnet sich).
|
||||
6. Klicken Sie auf "Initialisierung abschließen".
|
||||
|
||||
## 3. Test am Client-PC (PC-2)
|
||||
1. Starten Sie die App auf dem zweiten PC im selben LAN.
|
||||
2. Wählen Sie die Rolle **Client**.
|
||||
3. **Wait-State:** Sie sollten nun die Meldung "Suche nach der Meldestelle..." sehen.
|
||||
4. Sobald der Master aktiv ist, erscheint er in der Liste.
|
||||
5. Klicken Sie auf den Master-Eintrag.
|
||||
6. Geben Sie denselben Sicherheitsschlüssel (`1234`) ein.
|
||||
7. Klicken Sie auf **"Jetzt verbinden"**.
|
||||
8. **Verifikation:** Bei Erfolg erscheint ein grüner Haken und die Meldung "Verbunden mit Meldestelle-Zentrale".
|
||||
|
||||
## 4. Erfolgskriterien
|
||||
- [ ] Master wird vom Client automatisch gefunden (mDNS).
|
||||
- [ ] Client kann sich per Klick verbinden.
|
||||
- [ ] Native Dateidialoge sind lesbar und stabil.
|
||||
- [ ] Handshake-Feedback (Grün/Rot) funktioniert.
|
||||
@@ -0,0 +1,94 @@
|
||||
---
|
||||
type: How-to
|
||||
status: ACTIVE
|
||||
owner: DevOps Engineer
|
||||
---
|
||||
|
||||
# Runbook: Caddy & Pangolin Deployment (Plan-B Setup)
|
||||
|
||||
Dieses Dokument sichert das Wissen über die Konfiguration von Caddy als Webserver/Reverse-Proxy in Kombination mit Pangolin-Tunneln, welches während der "Plan-B" Online-Nennung erarbeitet wurde.
|
||||
|
||||
## 1. Architektur-Übersicht
|
||||
|
||||
* **Pangolin:** Stellt den sicheren Tunnel vom lokalen Netzwerk (Zora) ins Internet her (ersetzt Cloudflare). Leitet Traffic auf spezifische lokale Ports weiter.
|
||||
* **Caddy:** Agiert als Reverse-Proxy und TLS-Terminierungspunkt. Nimmt Traffic von Pangolin (und lokalem Netz) an und routet ihn zu den internen Docker-Services (z.B. Frontend-Web, API-Gateway).
|
||||
|
||||
## 2. Caddy Konfiguration (`Caddyfile`)
|
||||
|
||||
Die Konfiguration befindet sich in `config/docker/caddy/web-app/Caddyfile`.
|
||||
|
||||
### Wichtige Erkenntnisse / Fallstricke:
|
||||
* **TLS/SSL:** Caddy wurde mit `auto_https off` konfiguriert, da die SSL-Terminierung extern (Pangolin/Edge) erfolgt. Caddy läuft intern auf Port 80.
|
||||
* **Same-Origin Strategy:** Um CORS-Probleme im Browser zu vermeiden, werden alle API-Anfragen (`/api/*`) über Caddy an den `mail-service:8085` geproxt. Dies macht die App robuster gegen Browser-Security-Policies.
|
||||
* **MIME-Types:** Explizite Setzung von `application/wasm` für `.wasm` Dateien ist für KMP-Web-Apps kritisch (siehe Snippet).
|
||||
* **COOP/COEP Header:** Für WASM/KMP-Web-Apps sind `Cross-Origin-Embedder-Policy "require-corp"` und `Cross-Origin-Opener-Policy "same-origin"` essentiell, damit SharedArrayBuffer etc. funktionieren.
|
||||
* **Caching:**
|
||||
* Assets mit Hashes im Namen sind `immutable` (max-age 1 Jahr).
|
||||
* `.wasm` und `.js` Dateien wurden während Plan-B auf `no-store, no-cache, must-revalidate` gesetzt, um sicherzustellen, dass Teilnehmer immer die aktuellste Logik erhalten.
|
||||
* **Header-Weiterleitung:** Wichtige Header für das Backend: `X-Real-IP`, `X-Forwarded-For`, `X-Forwarded-Proto`.
|
||||
|
||||
### Aktuelles Plan-B Snippet:
|
||||
```caddyfile
|
||||
{
|
||||
auto_https off
|
||||
}
|
||||
|
||||
:80 {
|
||||
root * /usr/share/caddy
|
||||
|
||||
header {
|
||||
Cross-Origin-Embedder-Policy "require-corp"
|
||||
Cross-Origin-Opener-Policy "same-origin"
|
||||
}
|
||||
|
||||
# API Proxy (Same-Origin Strategy)
|
||||
handle /api/* {
|
||||
reverse_proxy mail-service:8085 {
|
||||
header_up Host {upstream_hostport}
|
||||
header_up X-Real-IP {remote_host}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
}
|
||||
}
|
||||
|
||||
# Wasm MIME & Caching
|
||||
@wasm path *.wasm
|
||||
header @wasm Content-Type "application/wasm"
|
||||
|
||||
@wasm_js path *.wasm *.js
|
||||
header @wasm_js Cache-Control "no-store, no-cache, must-revalidate"
|
||||
|
||||
# SPA Fallback
|
||||
handle {
|
||||
try_files {path} /index.html
|
||||
file_server
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 3. Pangolin Konfiguration
|
||||
|
||||
### Erkenntnisse aus Plan-B:
|
||||
* **Tunnel-Endpunkt:** Pangolin leitet den Traffic von der öffentlichen Domain (z.B. `meldestelle.mo-code.at`) auf den lokalen Port der Zora-Instanz weiter (standardmäßig Port 80, gemappt auf Host-Port via Docker).
|
||||
* **Stabilität:** Der Pangolin-Client läuft als persistenter Dienst auf der Zora-Node. Er ist extrem stabil gegenüber IP-Wechseln des ISP (DSL-Reconnect).
|
||||
* **Konfiguration:** Erfolgt primär über das Pangolin-Dashboard (Web-UI). Wichtig ist das Mapping der Resource auf die interne IP von Zora.
|
||||
|
||||
## 4. Deployment-Workflow (Erkenntnisse)
|
||||
|
||||
### SMTP-Härtung (Plan-B Mail-Service)
|
||||
In `dc-planb.yaml` wurden folgende Einstellungen für World4You (SMTP) als stabil verifiziert:
|
||||
```yaml
|
||||
SPRING_MAIL_HOST: "smtp.world4you.com"
|
||||
SPRING_MAIL_PORT: "587"
|
||||
SPRING_MAIL_PROPERTIES_MAIL_SMTP_STARTTLS_ENABLE: "true"
|
||||
SPRING_MAIL_PROPERTIES_MAIL_SMTP_STARTTLS_REQUIRED: "true"
|
||||
```
|
||||
Wichtig: `STARTTLS_REQUIRED` verhindert den Versand, falls keine verschlüsselte Verbindung aufgebaut werden kann.
|
||||
|
||||
### Infrastruktur-Optimierung
|
||||
* **Zero-Downtime:** `docker compose exec web-app caddy reload --config /etc/caddy/Caddyfile` ermöglicht Konfigurationsänderungen ohne Container-Neustart.
|
||||
* **Health-Check:** Der `/health` Endpunkt in Caddy wurde genutzt, um die Erreichbarkeit des Containers zu prüfen.
|
||||
* **In-Memory DB:** Für Plan-B wurde die H2-Datenbank (In-Memory) genutzt, da keine Persistenz über den Turnier-Zeitraum hinaus (außer E-Mail-Kopien) nötig war. Dies vereinfachte das Deployment massiv.
|
||||
|
||||
---
|
||||
*Hinweis: Dieses Dokument basiert auf den erfolgreichen Feld-Tests vom April 2026.*
|
||||
@@ -26,7 +26,7 @@ Der Runner ist das "Arbeitstier" des Systems.
|
||||
|
||||
* **Software:** `act_runner` (v0.2.11).
|
||||
* **Ressourcen:** 16 GiB RAM (optimiert für schwere Kotlin/JS-Builds).
|
||||
* **Build-Stack:** Java 25 (Temurin), Gradle 9.3.1.
|
||||
* **Build-Stack:** Java 25 (Temurin), Gradle 9.5.0.
|
||||
* **Besonderheiten:**
|
||||
* **Sequenzieller Build:** Um GitHub Rate-Limits und RAM-Spitzen zu vermeiden, arbeitet der Runner die Matrix-Jobs kontrolliert ab.
|
||||
* **Docker Buildx:** Native ARM64-Builds mit Optimierungs-Flags (`-XX:+UseTransparentHugePages`, `-XX:+UseSVE=1`).
|
||||
@@ -42,13 +42,13 @@ Die Zielumgebung für das Deployment.
|
||||
* **Verzeichnis:** `~/meldestelle/`
|
||||
* **Service-Übersicht:**
|
||||
|
||||
| Dienst | Externer Port | Interner Port | Image-Name (Registry) |
|
||||
| --- | --- | --- | --- |
|
||||
| **Web-App** | 4000 | 4000 (Caddy) | `web-app` |
|
||||
| **API-Gateway** | 8081 | 8081 | `api-gateway` |
|
||||
| **Keycloak** | 8180 (Admin) | 8080 | `keycloak` |
|
||||
| **Ping-Service** | 8082 | 8082 | `ping-service` |
|
||||
| **Consul** | 8500 | 8500 | `hashicorp/consul` |
|
||||
| Dienst | Externer Port | Interner Port | Image-Name (Registry) |
|
||||
|------------------|---------------|---------------|-----------------------|
|
||||
| **Web-App** | 4000 | 4000 (Caddy) | `web-app` |
|
||||
| **API-Gateway** | 8081 | 8081 | `api-gateway` |
|
||||
| **Keycloak** | 8180 (Admin) | 8080 | `keycloak` |
|
||||
| **Ping-Service** | 8082 | 8082 | `ping-service` |
|
||||
| **Consul** | 8500 | 8500 | `hashicorp/consul` |
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 109 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |