Files
Holzleitner---Backend--aktu…/README.md
Dennis Nemec d30d43df3a Backend als Windows-Dienst registrierbar (SCM, wie Mail-Client)
Das Backend kann jetzt — analog zum Mail-Client — als Windows-Dienst laufen.

- main() refaktoriert: App-Logik in run_app(shutdown, service_mode); eigene
  tokio-Runtime statt #[tokio::main]. Windows startet zuerst den SCM-Dispatcher,
  fällt bei interaktivem Start auf Konsolenmodus zurück (--console erzwingt ihn).
- src/service.rs (windows-only): SCM-Integration via windows-service-Crate,
  Stop/Shutdown-Handler, Running/Stopped-Status. Setzt das Arbeitsverzeichnis
  aufs EXE-Verzeichnis (Dienst startet sonst in System32), damit config.toml/
  data/logs daneben liegen. Fallback-Log bei Boot-Fehler.
- Graceful Shutdown: GSD-Lizenz-Freigabe in den Serve-Wrapper gezogen (greift
  in beiden Modi); Stop-Trigger ist das übergebene shutdown-Future.
- Logging: Konsolenmodus → stderr (wie bisher); Dienst-Modus → rollende
  Tagesdatei (tracing-appender) unter [logging] dir (Default logs/).
- install-service.ps1 / uninstall-service.ps1 (Dienst "Holzleitner Backend").
- README: Windows-Dienst-Abschnitt; .gitignore: /logs + Fatal-Log.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 18:12:12 +02:00

150 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Holzleitner-Backend
Rust-Backend für die Holzleitner-Lieferservice-App. Workspace mit Clean
Architecture: `domain``application``infrastructure``api`.
## Schnellstart (lokale Entwicklung)
```bash
# 1) Postgres + Keycloak hochfahren
docker compose up -d
# Keycloak braucht ~30s bis "Listening on http://0.0.0.0:8080" im Log steht.
# 2) Konfiguration vorbereiten
cp config.example.toml config.toml
# Werte in config.toml anpassen (DB-URL, Keycloak-Issuer, ERP-Zugang, …).
# 3) Backend starten
cargo run -p holzleitner-api
```
Migrations laufen beim Start automatisch über `sqlx::migrate!`.
Smoke-Test danach:
```bash
curl http://127.0.0.1:3000/health
# → ok
curl http://127.0.0.1:3000/accounts/1001
# → {"personalnummer":1001,"name":"Müller Logistik GmbH","active":true}
```
## Keycloak (Dev)
| Wo | URL / Credentials |
|---|---|
| Admin-Console | http://localhost:8080/admin/ (admin / admin) |
| Realm | `holzleitner` |
| Client | `holzleitner-app` (public, PKCE) |
| Test-User | `testfahrer` / `test` · Personalnummer 1001 · Rolle `driver` |
| Audience im Access-Token | `holzleitner-api` |
Der Realm wird bei jedem `docker compose up` aus
`keycloak/import/realm-holzleitner.json` frisch importiert. Wer in der
Admin-UI Änderungen macht, sollte sie **in die JSON zurückspielen**,
sonst sind sie beim nächsten `docker compose down` weg.
### Token für Dev-Tests holen
```bash
curl -s -X POST \
http://localhost:8080/realms/holzleitner/protocol/openid-connect/token \
-d 'grant_type=password' \
-d 'client_id=holzleitner-app' \
-d 'username=testfahrer' \
-d 'password=test' | jq -r .access_token
```
Den Token in den `Authorization`-Header packen, sobald die JWT-Middleware
in der API-Schicht aktiv ist:
```bash
TOKEN=$(curl -s -X POST .../token -d ... | jq -r .access_token)
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:3000/accounts/1001
```
## Crate-Layout
| Crate | Inhalt | Abhängigkeiten |
|---|---|---|
| `holzleitner-domain` | Reines Domänenmodell (serde + UUID + chrono) | — |
| `holzleitner-application` | Use Cases und Ports (Trait-Definitionen für Repository, AuthService) | `domain` |
| `holzleitner-infrastructure` | Konkrete Adapter (sqlx-Postgres, später Keycloak) | `domain`, `application` |
| `holzleitner-api` | Axum HTTP-Layer + Composition Root | alle |
## Konfiguration
Werte werden aus `config.toml` gelesen (Vorlage: `config.example.toml`),
gruppiert in TOML-Sections. Der Dateipfad ist über die Env-Variable
`HOLZLEITNER_CONFIG` überschreibbar (z. B. im Deployment); Default ist
`config.toml` im Arbeitsverzeichnis. Die echte `config.toml` enthält
Secrets und ist `.gitignore`-t.
| Section | Bereich | Pflicht? |
|---|---|---|
| `[server]` | Bind-Host/Port | ja |
| `[database]` | Postgres-URL, Pool-Größe | ja |
| `[keycloak]` | OIDC-Issuer, Audience, JWKS-Cache, Provisioning | ja |
| `[gsd]` | DOCUframe-REST (Datei-Upload) | ja |
| `[erp]` | ERPframe-MSSQL (Touren-Pull) | optional |
| `[import]` | Import-Scheduler (Cron, Offset) | optional |
| `[report]` / `[signature]` / `[attachment]` | Lokale Speicher-Pfade | optional |
| `[dev]` | `today_override`, `sync_enabled` (DEV-ONLY) | optional |
| `[admin]` | `api_key` für das `/admin`-Gate | optional |
| `[logging]` | Log-Filter (Default; `RUST_LOG`-Env hat Vorrang) | optional |
Unbekannte Schlüssel werden beim Laden abgewiesen (`deny_unknown_fields`),
sodass Tippfehler sofort als Startfehler auffallen.
## Migrations
Migrations liegen im Workspace-Root `migrations/`. Eingebettet via
`sqlx::migrate!()` — kein zusätzlicher Laufzeit-Dateizugriff nötig.
Neue Migration anlegen:
```bash
# Format: <epoch>_<beschreibung>.sql, z.B.:
touch migrations/0002_tour.sql
```
## Logging
`tracing` + `tracing-subscriber` mit `EnvFilter`. Der Default-Filter steht
in `config.toml` unter `[logging] filter`; die Env-Variable `RUST_LOG` hat
Vorrang (Ad-hoc-Debugging ohne Datei-Edit, z. B. `RUST_LOG=debug cargo run`).
Im **Konsolenmodus** geht alles auf `stderr`. Im **Windows-Dienst-Modus**
(keine Konsole) wird stattdessen in rollende Tages-Logdateien unter
`[logging] dir` (Default `logs/`, relativ zur EXE) geschrieben.
## Windows-Dienst
Das Backend kann als Windows-Dienst laufen (gleiches Muster wie der
Mail-Client). Beim Start versucht die EXE zuerst, sich beim Service Control
Manager zu registrieren; gelingt das nicht (interaktiver Start), fällt sie in
den Konsolenmodus zurück. `--console` (bzw. `-c`) erzwingt den Konsolenmodus.
Der Dienst setzt sein Arbeitsverzeichnis auf das EXE-Verzeichnis — `config.toml`,
`data/` und `logs/` müssen also **neben der EXE** liegen.
```powershell
# 1) Release-Build (auf dem Zielsystem oder per Cross-Build)
cargo build --release -p holzleitner-api
# 2) target\release\holzleitner-server.exe + config.toml + die *.ps1-Skripte
# in ein Installationsverzeichnis kopieren, z. B. C:\HolzleitnerBackend\
# 3) Als Administrator registrieren (Dienst "Holzleitner Backend")
.\install-service.ps1
# Optional mit Dienstkonto (DB-/Netzwerkzugriff):
.\install-service.ps1 -Credential (Get-Credential)
# Entfernen
.\uninstall-service.ps1
```
Der Dienst startet verzögert-automatisch (nach den System-/DB-Diensten) und
wird bei Absturz 3× im Abstand von 60 s neu gestartet. Interner Dienst-Name:
`HolzleitnerBackend`. Boot-Fehler **vor** der Logger-Initialisierung (z. B.
fehlende `config.toml`) landen in `holzleitner-backend-fatal.log` neben der EXE.