Die Plandokumente waren durchweg veraltet: 85 von 91 Punkten im
UMSETZUNGSPLAN standen auf offen, obwohl der Code sie enthielt, und in
FIXPLAN-UI-Ranglisten war keine einzige der 18 Aufgaben abgehakt, obwohl
beide zugehoerigen Commits laengst im Zweig stecken. Alles abschnittsweise
gegen den Code geprueft und die Haekchen gesetzt - mit Belegstellen, damit
die naechste Pruefung nicht wieder bei null anfaengt.
Neu: STATUS.md als Einstiegsseite - wo das Projekt steht, was fertig ist,
was offen ist, und was beim Aufraeumen bewusst stehengeblieben ist. CLAUDE.md
verweist darauf.
Nachgezogen:
* UMSETZUNGSPLAN.md - 66 Punkte abgehakt. Offen bleiben A4 (Strategie-
Klassifikation), B2 (Secrets) sowie C3/D1/D2 (SQL-Arbeiten des Nutzers).
* FIXPLAN-UI-Ranglisten.md - abgeschlossen bis auf den als "Optional"
markierten Pfeilrichtungs-Punkt.
* FIXPLAN-TODO.md - Teil D und F abgehakt; die Test-Baseline "16 gruen"
auf die heutigen 126 korrigiert. Offen: F5 und zwei Tests aus F6.
* FIXPLAN-G-Speicher.md - G1 bis G4 als erledigt vermerkt, Baseline "39/1"
korrigiert, Pfad auf die nicht mehr existierende WinFormsHost/appsettings.json
richtiggestellt.
* docs/PLAN-Linux-Portierung.md - der Watchdog-Warnhinweis war ueberholt
(DcHeartbeatService meldet an /api/watchdog/v1/ping). Abschnitt 11 empfahl
noch, mit Phase 0 zu beginnen; jetzt benennt er Phase 5 und 6 als das, was
wirklich aussteht. Die Randnotiz zu Zugangsdaten in LicenseGuard.cs ist
gegenstandslos, die Datei laeuft ueber den Deploymentcenter.Client.
Zwei Befunde, die keine Aufraeumarbeit sind und deshalb nur dokumentiert
wurden - beide in STATUS.md Abschnitt 3:
1. In src/Predictalytics.Api/appsettings.json steht ein echter
OpenRouter-API-Key im Klartext, versioniert seit 7045002. Nicht
eigenmaechtig entfernt: ohne Rotation beim Anbieter bringt das nichts
(die History behaelt ihn), wuerde aber die KI-Analyse abschalten.
Der Schluessel muss zurueckgezogen und neu ausgestellt werden.
2. Die Portierung ist auf keinem Linux-System je ausgefuehrt worden. Die
Verifikation vom 2026-08-08 lief unter Windows.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Toter Code:
* ApiConfiguration.ConfigureApi (29 Z.) hatte keinen Aufrufer mehr.
PredictalyticsHost baut die WebApplication seit Phase 2 selbst auf
(Kestrel, CORS, Swagger, Static Files); ConfigureApi war der
zurueckgebliebene Zwilling aus der Zeit davor.
* IAnalyticsService.GetTraitsAsync samt Implementierung. Die Methode gab
konstant eine leere Liste zurueck; ihr eigener Kommentar hielt fest, dass
sie ungenutzt ist. Der Endpunkt /api/traders/traits liest direkt aus dem
DbContext und bleibt unveraendert.
Ungenutzte Paketreferenzen:
* Swashbuckle.AspNetCore aus Predictalytics.Api - wurde nur von ConfigureApi
gebraucht; Swagger baut Hosting auf, das die Referenz selbst haelt.
* Microsoft.EntityFrameworkCore.Design aus Predictalytics.Worker - die
Design-Time-Factory liegt in Infrastructure.
* Serilog.Sinks.File/.Console und Serilog.Formatting.Compact aus
Predictalytics.Infrastructure - dort wird kein Logger konfiguriert, nur
Serilog.Core/Events/Context verwendet. Die Sinks haengen am Hosting.
Altlast-Dateien:
* Spike/ - Projektdatei ohne eine einzige Quelldatei, net8.0, nicht in der
Solution.
* query.csx - Ad-hoc-Abfrageskript von Juli mit fest eingetragenen
DB-Zugangsdaten.
* NewDesign.zip (388 KB) und temp_new_design/ - Rohmaterial des
Design-Entwurfs vom 15.07. Das Ergebnis liegt fertig in
wwwroot/landing.html und wwwroot/docs.html.
Veraltete Verweise auf den entfernten WinForms-Host:
* CLAUDE.md nannte fuer die Release-Version eine csproj, die es nicht mehr
gibt - sie steht seit der Zentralisierung in Directory.Build.props.
* docs/BETRIEB-Deploymentcenter.md: Anbindung und BuildInfo sitzen in
Predictalytics.Hosting.
* docs/API.md: Die Aussage "ohne Authentifizierung" galt vor Phase 4. Jetzt
mit Header X-Predictalytics-Key und den heutigen Methodennamen.
* Kommentare in Directory.Build.props, DevEndpoints.cs, PredictalyticsHost.cs.
Build ohne neue Warnungen (die 8 bestehenden CS86xx sind unveraendert),
126 Tests gruen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der in Phase 4 offen gebliebene Ende-zu-Ende-Nachweis ist nachgeholt. Geprueft
mit einem Wegwerf-Host, der ausschliesslich den Webserver startet - die Worker
blieben aus, weil parallel eine aeltere Instanz auf derselben Datenbank laeuft.
Zusaetzlich mit ApiSettings__ReadOnlyDatabase=true, sodass weder Migrationen
noch Seeding liefen.
Als externe Bindung diente 127.0.0.2: gilt der Pruefung als oeffentlich,
bleibt aber Loopback, oeffnet also nichts im Netz.
Ergebnis:
- localhost ohne Token: Steuerendpunkte 200, Swagger 200
- extern ohne Token: Steuerendpunkte 404, Swagger 404, capabilities meldet
canControl false
- extern mit Token: ohne Header 401, falscher Token 401, richtiger 200,
Swagger 404
Nebenbei verifiziert: Datenbankverbindung steht (37.803 MB), Web-UI und
Assets werden ausgeliefert, /api/dashboard liefert echte Daten
(151.094 Trader, 38.187.946 Trades).
Nur Dokumentation - keine Codeaenderung.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>
Merge von main: die dort entstandene Deployment-Center-Integration (Lizenz,
Heartbeat mit DB-Health-Check, Fehler-Stream, UpdateService) ist jetzt Teil
des plattformneutralen Kerns. Predictalytics.WinFormsHost ist entfernt.
Nach Predictalytics.Hosting gezogen:
- DcConfig, DcApiClient, DcErrorSink, DcHeartbeatService, DcUpdateService
unveraendert - sie waren bereits plattformneutral
- DcErrorReporter ohne Application.ThreadException und MessageBox; der
UI-Thread-Handler liegt jetzt beim Host und ruft ReportUiThreadException
- LicenseGuard/LicenseSession ohne Dialog und ohne WinForms-Timer. Neu:
TryUseCachedAsync, ActivateAsync, StartPeriodicRevalidation ueber
PeriodicTimer. Die Unterscheidung transienter Fehler und die Warnung vor
ablaufender Gnadenfrist sind unveraendert uebernommen.
- Dc-Einstellungen von AppSettings nach PredictalyticsOptions; die
Watchdog-Einstellungen entfallen
- DcErrorSink im LoggingSetup, Startbanner nutzt DcConfig.AppVersion
BuildInfo.targets wird jetzt von Predictalytics.Hosting importiert.
In der Avalonia-Shell nachgezogen:
- Menue Deployment Center mit Update-Suche und Lizenzstatus
- Einstellungsgruppe Deployment Center statt Watchdog, Update-Kanal als
ComboBox, Server-URL nur zur Anzeige
- Heartbeat-Snapshot mit SELECT-1-Probe wie in der WinForms-Fassung
- Update-Pruefung still beim Start und interaktiv ueber das Menue, mit
NotifyStopping vor dem Start des Update-Agenten
- Lizenzfenster wertet IsTransient aus: bei fehlender Serververbindung wird
nicht behauptet, die Lizenz sei ungueltig
- TextBox.Watermark auf PlaceholderText (in Avalonia 12 veraltet)
Build: 0 Fehler, 8 Warnungen (alle vorbestehend).
Tests: 100 bestanden, 0 Fehler, 1 uebersprungen.
Verifiziert: --license-status meldet gueltig samt Gnadenfrist; die GUI
startet durch, prueft die Lizenz und laeuft gegen den UpdateService.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Loest die getrennten Server Watchdog (watchdog.mhdf.de) und LicenseLabrador
(license.mhdf.de) durch das Deployment Center (dc.mhdf.de) ab.
- DcConfig: einkompilierte Basis-URL und Produkt-Slug, Version aus BuildInfo
- DcApiClient: gemeinsamer HTTP-Zugang
- DcHeartbeatService: Heartbeat mit Metriken und DB-Health-Check
- DcErrorReporter/DcErrorSink: Error- und Fatal-Meldungen an den Fehler-Stream
- DcUpdateService: Update-Pruefung gegen den UpdateService
- LicenseGuard/LicenseDialog: Lizenzgate ueber /api/license/v1/validate,
mit LicenseSession, Hardware-ID v2 und Unterscheidung transienter Fehler
WatchdogHeartbeatService entfernt, Betriebsdoku ersetzt.
Build: 0 Fehler.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Predictalytics hing noch am abgeloesten LicenseLabrador (license.mhdf.de),
waehrend die Lizenzen inzwischen im Deploymentcenter (dc.mhdf.de) gepflegt
werden. Vor dem Umbau mit einem Wegwerf-Probelauf gegen den echten Client
abgesichert: Slug predictalytics, HWID v2 aus machine-guid, Server meldet valid.
Hosting/LicenseGuard.cs auf Deploymentcenter.Client umgeschrieben. Die
Aufteilung bleibt: plattformneutrale Pruefung im Hosting, interaktive
Aktivierung in den Hosts.
Gewinn fuer die Linux-Portierung:
- Hardware-ID v2 mit Quellen-Kaskade /etc/machine-id, dbus, DMI-UUID, MAC,
Schluesseldatei; Container ueber DEPLOYMENTCENTER_HWID
- Der Rechnername steckt nicht mehr im Hash, Umbenennen verbraucht keinen
Aktivierungsplatz
- Cache mit AES-256-GCM statt DPAPI, ohne stillen Klartext-Rueckfall unter
Linux. Damit erledigt sich Punkt 3.2 Nr. 2 der Portierungsanalyse.
- XDG_CONFIG_HOME wird beruecksichtigt
- Keine Basic-Auth-Zugangsdaten mehr im Quelltext
Neue CLI-Schalter aus dem Integrationsleitfaden, ausgewertet vor jeder
Avalonia-Initialisierung: --license-status, --license-set-key,
--license-deactivate. Schluessel werden in der Ausgabe maskiert.
Die Lizenzfenster beider Hosts zeigen jetzt die Hardware-ID an, an die der
Server die Aktivierung bindet.
Build: 0 Fehler. Tests: 100 bestanden.
Verifiziert: --license-status meldet gueltig; die GUI startet vollstaendig
durch bis MainWindowViewModel.Start(), belegt durch die Logdateien.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Neues Projekt Predictalytics.Shell (Avalonia 12.1.1, net10.0) als
plattformuebergreifender Ersatz fuer den WinForms-Host. Setzt auf dem in
Phase 2 extrahierten Predictalytics.Hosting auf.
Oberflaeche:
- MainWindow mit Menue, Werkzeugleiste, Terminal-Tab, Einstellungen-Tab und
Statusleiste. Die feste Fenstergroesse von 1886x1088 ist aufgeloest.
- Terminal als ListBox ueber ObservableCollection mit Einfaerbung nach
Loglevel. Ringpuffer statt des bisherigen kompletten Leerens bei 500 Zeilen.
- Einstellungsansicht handgeschrieben als Ersatz fuer den PropertyGrid, den
es in Avalonia nicht gibt: vier Gruppen, Passwortfelder, mehrzeiliges
Textfeld fuer die Egress-Kanaele, ComboBox fuer den SSL-Modus. Gespeichert
wird explizit statt bei jeder Einzeloperation.
- LicenseWindow ersetzt den WinForms-LicenseDialog.
- Dialogs.cs als schlanker Ersatz fuer MessageBox.Show, ohne Drittanbieter.
Headless-Modus (--headless) im selben Binary: fuer Linux-Server ohne
Desktop-Session. Die Argumentauswertung steht vor jeder Avalonia-
Initialisierung, sonst stirbt der Prozess ohne X11 bevor der Schalter greift.
Lizenz ueber PREDICTALYTICS_LICENSE_KEY statt Dialog, SIGTERM und SIGINT
ueber PosixSignalRegistration fuer sauberes systemd-Stop.
Exit-Codes: 0 planmaessig, 2 keine nutzbare Lizenz, 3 Fehler.
Plattformdetails: Schrift-Fallbackkette fuers Terminal, Avalonia.Fonts.Inter
als mitgelieferte UI-Schrift, UTF-8 fuer die Windows-Konsole im
Headless-Modus.
Die Avalonia-Basisklasse wird als global::Avalonia.Application angegeben:
innerhalb von Predictalytics.* loest der kurze Name auf den eigenen
Namespace Predictalytics.Application auf.
Build: 0 Fehler, 0 Warnungen. Tests: 100 bestanden.
Verifiziert: --headless laeuft bis zur Lizenzschranke und beendet sich mit
Exit-Code 2; GUI startet und zeigt das Lizenzfenster. Das Hauptfenster
konnte nicht geprueft werden, weil die hinterlegte Lizenz abgelaufen ist.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Neues Projekt Predictalytics.Hosting nimmt auf, was bisher im
windows-gebundenen WinFormsHost feststeckte, aber portabel ist:
- PredictalyticsHost (aus EmbeddedWebServer): Kestrel- und Worker-Lifecycle,
Wartungsaktionen, DB-Groesse. Meldet Zustandswechsel ueber StateChanged.
- PredictalyticsOptions (aus AppSettings): ohne WinForms-Bezug. Die
System.ComponentModel-Attribute sind plattformneutral und bleiben, damit
das PropertyGrid Gruppen und Beschreibungen behaelt.
- LoggingSetup (aus Program.cs): Serilog-Aufbau, Terminal-Sink als optionale
Action statt fester RichTextBox.
- LicenseGuard: GUI-frei. Periodische Revalidierung ueber PeriodicTimer statt
WinForms-Timer, Abbruch ueber Callback statt Application.Exit. Der
interaktive Dialogaufruf bleibt als LicenseGate im WinForms-Host.
- WatchdogHeartbeatService unveraendert verschoben.
Infrastructure: RichTextBoxSink -> DelegateSink umbenannt (war nie
WinForms-abhaengig, nur missverstaendlich benannt).
Einstellungen liegen jetzt unter %APPDATA%/Predictalytics bzw.
~/.config/Predictalytics statt neben der Programmdatei, mit einmaliger
Uebernahme aus dem alten Ort. Das Installationsverzeichnis ist unter Linux
ueblicherweise nicht beschreibbar.
wwwroot wird ueber einen Content-Eintrag neben die Programmdatei kopiert;
die frueheren Pfad-Heuristiken entfallen.
Hosting und WinFormsHost nutzen Microsoft.NET.Sdk statt Sdk.Web: der Web-SDK
globbt wwwroot automatisch als Static Web Asset und kollidiert mit dem
Content-Eintrag. WebApplication kommt ueber FrameworkReference.
Neu konfigurierbar (verhaltensgleiche Defaults): WebserverHost fuer die
Kestrel-Bind-Adresse, DbSslMode fuer die MySQL-Verschluesselung.
explorer.exe-Aufrufe durch ProcessStartInfo mit UseShellExecute ersetzt —
funktioniert unter Windows und Linux.
Build: 0 Fehler. Tests: 100 bestanden, 0 Fehler, 1 uebersprungen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zielframework aller Projekte auf net10.0 (WinFormsHost: net10.0-windows),
zentral in Directory.Build.props statt je csproj. SatelliteResourceLanguages
ebenfalls zentralisiert.
Neue Directory.Packages.props mit ManagePackageVersionsCentrally: 21 Pakete,
Versionsangaben aus allen csproj entfernt.
EF Core bleibt bewusst auf 9.0.18 mit Pomelo 9.0.0. Pomelo hat keine
EF-Core-10-Version; 9.0.0 pinnt EntityFrameworkCore.Relational auf
[9.0.0, 9.0.999]. Die EF-9-Pakete zielen auf net8.0 und laufen auf der
net10.0-Runtime. Begruendung als Kommentar in Directory.Packages.props.
Uebrige Pakete auf aktuellen Stand: Swashbuckle 10.2.3 (ohne Bruchstellen),
Serilog 4.4.0, Microsoft.Extensions 10.0.10, Test-SDK 18.8.1, coverlet 10.0.1.
Sicherheits-Pin: SQLitePCLRaw 2.1.12 statt transitiv 2.1.10
(GHSA-2m69-gcr7-jv3q, High). Dazu CentralPackageTransitivePinningEnabled.
Build: 0 Fehler, 8 Warnungen (alle vorbestehend).
Tests: 100 bestanden, 0 Fehler, 1 uebersprungen, Testhost net10.0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Vorarbeiten fuer die Linux-/NET-10-Portierung (siehe docs/PLAN-Linux-Portierung.md).
DateTime.TryParse ohne DateTimeStyles liefert bei Z-Zeitstempeln Kind=Local und
rechnet in Lokalzeit um. An 13 Stellen in PolymarketProvider und LimitlessProvider
wurden so ISO-Zeitstempel der Plattform-APIs eingelesen, waehrend der Fallback
derselben Zuweisungen (DateTime.UtcNow) korrektes UTC schrieb - die Spalten
enthielten also gemischt verschobene und korrekte Werte. Auf einem Server mit
TZ=UTC haette derselbe Code andere Werte erzeugt als unter Windows.
Neuer Helfer Infrastructure/Helpers/DateParsing.cs kapselt das Parsen mit
InvariantCulture und AdjustToUniversal|AssumeUniversal; alle Fundstellen umgestellt.
Ausserdem:
- LimitlessProvider: Volume-Parsing auf InvariantCulture umgestellt
- EmbeddedWebServer: hartkodierten j:\-Absolutpfad als wwwroot-Fallback entfernt
Ein Backfill der Altdaten erfolgt bewusst nicht.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Shutdown-Event sendet stopped_graceful statt stopping: der Server
kennt "stopping" im Router, aber event_log.kind ist ein ENUM ohne
diesen Wert. Folge war HTTP 500 nach dem Zustandswechsel, das Event
fehlte in der Historie.
- Default-Source auf "Predictalytics" korrigiert (Schreibweise des
bereits angelegten Monitors auf dem Server).
Heartbeat, Metrics-Payload, Lizenzvalidierung und der Startpfad ueber
den Cache sind end-to-end gegen die Produktivserver getestet.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bindet die beiden neuen Betriebsprojekte an:
- WatchdogHeartbeatService: periodischer POST /api/heartbeat an
watchdog.mhdf.de (Dead-Man's-Switch), stopping-Event beim Beenden,
Konfiguration ueber AppSettings-Kategorie "Watchdog". Fehler sind
best effort und beeintraechtigen die App nie.
- LicenseGuard + LicenseDialog: Lizenzpruefung vor dem Start der
MainForm, 12h-Revalidierung zur Laufzeit, Checksum-Haertung.
Produkt-Slug/Endpoint/Public-Key sind einkompiliert.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- D1/D2/D2c: Added TraderTraits entity, TraderTraitCalculator, Market Return Metrics (MedianWin, AvgWin, etc.), and trait filters
- D3: Implemented HF-Trader Tiering via IngestMode (Full, Aggregated, SnapshotOnly) and updated TradeHistoryWorker to respect tiers
- E1-E5: Added MasterStatus to Trader, TraderWindowMetrics for rolling analytics, Fingerprint metrics (PriceBandProfile, P50/P90), Copyability aggregates (Volume, Drift, Edge)
- E6: Implemented GET /api/traders/{id}/profile and GET /api/traders/correlation
- Replaced FIXPLAN-2026-07-09.md with FIXPLAN-TODO.md and FIXPLAN-DONE.md
- Cleaned up API docs and plan to use generic terms (removed hardcoded PolyTrader references)
- Added respective EF Core Migrations
- TraderDetailDto now exposes PnL7d/WinRate7d/PnL24h/WinRate24h and
CurrentBalance — the engine has computed these all along but the API
never delivered them.
- Removed POST /api/dev/repair-db: its raw SQL referenced non-existent
columns/tables (Trades.Type/Payout, Traders.LastPositionsUpdatedAt,
table "Jobs") and would have deleted ALL TraderPositions including
pruned-history conserves. The supported repair path is the WinForms
"Recalculate All Traders" action.
- Swagger tags for Jobs and Dev groups; full endpoint reference in
docs/API.md (kept generic — external consumers like PolyTrader adapt
to our API, not vice versa).
- FIXPLAN Teil E: master-selection gap analysis as generic extensions
(profile endpoint, out-of-sample window metrics, price-band profile
with per-band win rate, stop-loss ratio, copyability aggregates with
category fees, correlation endpoint, martingale trait).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>