Phase 4: Steuerendpunkte absichern, Kultur und Log-Pfad plattformfest

Die schreibenden API-Endpunkte waren ungeschuetzt. /api/capabilities meldete
zwar CanControl und AuthRequired aus der Konfiguration, erzwungen wurde davon
nichts: MapPredictalyticsControlEndpoints mappte Jobs, Trader-Steuerung und
Dev-Endpunkte bedingungslos.

Neu entscheidet die Bind-Adresse:
- localhost ohne Token: aktiv wie bisher, das Betriebssystem schuetzt
- localhost mit Token: aktiv, Token wird verlangt
- extern ohne Token: Endpunkte werden gar nicht gemappt, dazu ein Log.Error
- extern mit Token: Endpunkte verlangen X-Predictalytics-Key

Bewusst fail-safe herum, damit eine unbedachte Umstellung der Bind-Adresse
nicht stillschweigend die Steuerschnittstelle oeffnet. ApiTokenFilter
vergleicht laufzeitkonstant ueber CryptographicOperations.FixedTimeEquals.
Swagger ist bei externer Bindung abgeschaltet. /api/capabilities meldet jetzt
den tatsaechlichen Zustand statt einer Konfigurationsabsicht.

Weiter:
- RuntimeSetup.UseInvariantCulture als Erstes in beiden Startpfaden, damit
  die Systemlocale nicht auf Zahlen und Zeitstempel durchschlaegt
- Logverzeichnis neben den Einstellungen statt neben der Programmdatei,
  ueber PREDICTALYTICS_LOG_DIR uebersteuerbar
- CORS erlaubt immer die eigene Bind-URL, zusaetzliche Herkuenfte weiter
  ueber appsettings.json
- fehlendes Schwester-Repo Deploymentcenter scheitert mit verstaendlicher
  Meldung samt Klon-URL statt mit einem Fehler ueber eine fehlende csproj
- EgressPoolService: Linux-Verhalten von Socket.Bind kommentiert

24 neue Tests: IsPubliclyBound fuer Loopback-Schreibweisen, Leerwerte und
externe Adressen; dass leere Eingaben bestehende DB-Zugangsdaten nicht
ueberschreiben; und der Token-Filter gegen fehlende, falsche, zu kurze,
zu lange und abweichend geschriebene Token.

Build: 0 Fehler, 8 Warnungen (alle vorbestehend).
Tests: 124 bestanden, 0 Fehler, 1 uebersprungen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-08-08 21:13:49 +02:00
co-authored by Claude Opus 5
parent 0e01886640
commit b175df6d3e
15 changed files with 464 additions and 19 deletions
+69 -1
View File
@@ -544,7 +544,75 @@ Leitfaden liegt unter `Deploymentcenter/docs/WATCHDOG_INTEGRATION_GUIDE.md`.
---
## 6. Phase 4 — Aufräumen und Absichern (11,5 PT)
## 6. Phase 4 — Aufräumen und Absichern ✅ **erledigt (2026-08-08)**
**Abnahme:** Build 0 Fehler, 8 Warnungen (alle vorbestehend).
`dotnet test` → **124 bestanden** (vorher 100; 24 neue Tests zur Absicherung).
### AP 4.1 — Steuerendpunkte werden jetzt tatsächlich geschützt ✅
Der Befund war schlimmer als in der Analyse notiert: `/api/capabilities` **meldete**
`CanControl`/`AuthRequired` aus der Konfiguration, **erzwungen wurde nichts**.
`MapPredictalyticsControlEndpoints()` mappte Jobs, Trader-Steuerung und die Dev-Endpunkte
bedingungslos und ungeschützt.
Neu:
| Bindung | Token | Verhalten |
|---|---|---|
| localhost | — | Steuerendpunkte aktiv, ungeschützt (das Betriebssystem schützt) |
| localhost | gesetzt | Steuerendpunkte aktiv, Token wird verlangt |
| **extern** | **fehlt** | **Steuerendpunkte werden gar nicht gemappt**, dazu ein `Log.Error` |
| extern | gesetzt | Steuerendpunkte verlangen `X-Predictalytics-Key` |
Bewusst fail-safe: eine unbedachte Umstellung der Bind-Adresse öffnet nichts stillschweigend.
`ApiTokenFilter` vergleicht laufzeitkonstant (`CryptographicOperations.FixedTimeEquals`),
damit die Antwortzeit nicht verrät, wie viele Zeichen stimmen.
Swagger ist bei externer Bindung abgeschaltet — es legt die gesamte API-Oberfläche offen.
`/api/capabilities` meldet nun den tatsächlichen Zustand statt einer Konfigurationsabsicht.
### AP 4.2 — Globalisierung ✅
`RuntimeSetup.UseInvariantCulture()`, aufgerufen als Erstes in beiden Startpfaden.
Bewusst **nicht** über `InvariantGlobalization` im Projekt: das änderte zusätzlich die
Semantik von Zeichenkettenvergleichen und wäre ein größerer Eingriff als nötig.
### AP 4.3 — Log-Verzeichnis ✅
Standard ist jetzt `%APPDATA%\Predictalytics\logs` bzw. `~/.config/Predictalytics/logs` —
neben den Einstellungen statt neben der Programmdatei, die unter Linux üblicherweise nicht
beschreibbar ist und beim Update überschrieben würde. Übersteuerbar über
`PREDICTALYTICS_LOG_DIR`, etwa auf `/var/log/predictalytics` im systemd-Betrieb.
### AP 4.4 — Solution und Repo-Kopplung ✅
Der WinFormsHost-Sonderfall entfällt, weil das Projekt entfernt ist — die Solution baut
unter Linux ohne Bedingung durch. Die relative Referenz auf das Schwester-Repo bleibt
(vier Ebenen aufwärts), scheitert jetzt aber mit einer verständlichen Meldung samt
Klon-URL statt mit einem Fehler über eine fehlende Projektdatei.
**Offen:** Git-Submodul oder NuGet-Paket statt Pfadreferenz — für CI und Container relevant,
aber eine Entscheidung über Repo-Grenzen hinweg.
### AP 4.5 — Egress `SourceIp` ✅ (dokumentiert)
Code ist korrekt; der Unterschied ist zur Laufzeit. Linux verlangt, dass die Adresse
tatsächlich auf einem Interface konfiguriert ist (sonst `EADDRNOTAVAIL`), Windows ist
toleranter. Als Kommentar an der Bind-Stelle hinterlegt. Praktischer Test steht in Phase 6 aus.
### Neue Tests
* `PredictalyticsOptionsTests` — `IsPubliclyBound` für Loopback-Schreibweisen, Leerwerte
und externe Adressen; `WebserverUrl`; SSL-Modus im Connection-String; und dass leere
Eingaben bestehende DB-Zugangsdaten **nicht** überschreiben.
* `ApiTokenFilterTests` — richtiger Token passiert, fehlender/falscher/zu kurzer/zu langer
sowie abweichend geschriebener Token werden abgewiesen.
### ⚠️ Nicht Ende-zu-Ende verifiziert
Die Entscheidungslogik und der Filter sind einzeln getestet, die Verdrahtung dazwischen
nicht: `StartWebServerAsync` bricht ohne Datenbankkonfiguration vorher ab. Nachzuholen,
sobald die DB-Zugangsdaten wieder hinterlegt sind.
---
## 6a. Phase 4 — ursprüngliche Planung
### AP 4.1 — Kestrel-Binding und Absicherung ⚠️
`UseUrls($"http://localhost:{port}")` (`EmbeddedWebServer.cs:122`) konfigurierbar machen