0f18f562c77bc470d65b684cbb61c08f7bbae962
11
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
bc96807d81 |
WebUI: Update-Status anzeigen, installiert wird im Desktop
Umsetzung von #565. GET /api/updates liefert die laufende Fassung (BuildInfo), die verfuegbare, den Hinweis auf ein Sicherheitsupdate und den Changelog. Geprueft wird mit demselben Aufruf wie beim Start des Desktops (UpdateClient gegen das Deploymentcenter). Den Lizenzschluessel fuer den Paketabruf liest der Server, er verlaesst ihn nicht. Zwischenspeicher: UpdateStatusService haelt das Ergebnis 30 Minuten vor. "Jetzt pruefen" umgeht das, aber fruehestens nach 60 Sekunden; bis dahin kommt der vorige Stand mit der Wartezeit zurueck. Gleichzeitige Aufrufe loesen eine einzige Pruefung aus. Ohne das fragte jeder Seitenaufruf, jedes offene Browserfenster, das Deploymentcenter. Die Pruefung liegt hinter IUpdateChecker und ist damit ohne Netz testbar. Kein Installieren ueber das WebUI, und ein Test haelt fest, dass es keine solche Route gibt: Die Installation startet den Update-Agent und beendet danach die Anwendung und mit ihr den Webserver. Richards Vorgabe beschraenkt das Beenden ueber das WebUI auf das Trading (#563). Oberflaeche: - Karte "Version & Updates" in den Einstellungen, mit "Jetzt pruefen". - Im Dashboard ein Banner wie im Desktop-Launcher, sobald ein Update vorliegt. Er verweist zur Installation auf den Desktop. Nicht durch Unit-Tests abgedeckt: DeploymentcenterUpdateChecker selbst, weil er ueber das Netz geht. Er wird auf der VM gegen das echte Deploymentcenter geprueft. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
0067e0b761 |
WebUI: Log-Viewer fuer vergangene Tage und Kopieren
Umsetzung von #564. Das WebUI zeigte bisher nur den Live-Stream seit dem Prozessstart. GET /api/logs lieferte den Verlauf im Speicher, die Oberflaeche nutzte ihn nicht. Der Desktop hat einen Log-Viewer ueber die Tagesdateien. Den gibt es jetzt auch im WebUI. - GET /api/logs/files listet die vorhandenen Tage (Logs/yyyy-MM-dd.jsonl), neueste zuerst. Die .log-Textdateien und fremde Dateien bleiben aussen vor. - GET /api/logs/file filtert nach Level, Korrelations-ID und Text, alle ohne Gross-/Kleinschreibung. Hoechstens 20000 Treffer wie im Desktop, dazu Seitenaufteilung. Unlesbare Zeilen werden uebersprungen und gezaehlt. - Der Dateiname entsteht aus dem geprueften Datum, nie aus der Eingabe. "../../etc/passwd" kommt deshalb gar nicht erst in den Pfad; die Tests halten das fest. - Gelesen wird mit FileShare.ReadWrite, weil der Logger laufend an die Tagesdatei anhaengt. Oberflaeche: "Live" und "Log-Viewer (vergangene Tage)" als Unter-Tabs. "Alles kopieren" im Live-Tab, "Seite kopieren" im Viewer. navigator.clipboard gibt es nur in sicheren Kontexten, ueber LAN/VPN laeuft das WebUI aber per http. Dafuer gibt es einen Rueckweg ueber ein unsichtbares Textfeld, sonst schluege das Kopieren dort still fehl. Logzeilen werden per textContent eingesetzt, nicht per innerHTML: Logtexte enthalten, was andere eingegeben haben. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
c1e13f5441 |
WebUI: Server-Einstellungen ohne Geheimnisse bearbeiten
Umsetzung von #561. Entscheidung Richard, 13.09.2026: Alles, was keine Geheimnisse beruehrt, soll ueber das WebUI gehen; Geheimnisse ausschliesslich im Desktop. Eine ausdrueckliche Freigabeliste (ServerSettingsCatalog) statt Reflection. Der Desktop zeigt per Reflection alles, was ServerSettings hat. Uebernaehme das WebUI das, stuende jedes kuenftige Feld automatisch im Netz, auch ein Geheimnis. Bearbeitbar, je Feld mit Pruefung: - Farbschema und Zeitzone: nach Neustart - VPN an/aus und VPN-Standort: sofort - Blockchain-Listener: nach Neustart - Polymarket-WSS: sofort - Watchdog an/aus, Source, Instance und Intervall: sofort "Sofort" und "nach Neustart" sind am Code belegt, nicht am Feldnamen geraten. Zeitzone und Blockchain-Listener werden nur beim Start gelesen, das Farbschema haelt der ThemeManager. Nur im Desktop, Aenderungsversuch 403 und protokolliert: - Geheimnisse: Mullvad-Account, Polygon-RPC-URL (enthaelt den Alchemy-Key), Watchdog-Token, Lizenzschluessel - Watchdog-URL: an diese Adresse geht der Watchdog-Token, wer sie aendert, bekommt ihn - Mullvad-CLI-Pfad: dieses Programm wird ausgefuehrt Von den Geheimnissen zeigt das WebUI nur, ob sie gesetzt sind. OpenRouter- und Master-Key werden dafuer nicht gelesen. Gefunden dabei: MullvadVpnService baut die Kommandozeile als eine Zeichenkette ("relay set location <Wert>"). Der VPN-Standort nimmt deshalb nur Mullvad- Kennungen an (cz, cz-prg). "cz account login 999" wird abgelehnt, ein Test haelt das fest. Source und Instance gehen als JSON ans Deploymentcenter und sind auf Kennungszeichen begrenzt. POST prueft alle Werte zuerst und schreibt dann alles oder nichts, ueber ServerSettingsFile. Danach zieht er den laufenden Stand nach: das Singleton, MullvadVpnService.ReloadSettings und WatchdogHeartbeatService.ReloadSettings. Desktop - bisher schrieb er eine WebUI-Aenderung still zurueck: Die Einstellungen wurden einmal beim Oeffnen geladen, und "Speichern", "Watchdog-Token setzen" und "Lizenzschluessel setzen" schrieben jeweils das ganze alte Objekt zurueck. Jetzt: - Speichern vergleicht innerhalb der Dateisperre den Dateistand vom Laden und verweigert, wenn sich die Datei inzwischen geaendert hat. - Token und Lizenzschluessel schreiben nur noch ihr eigenes Feld. - Eine unlesbare Datei sperrt das Speichern, statt Vorgaben zu zeigen, die beim Speichern die Schluessel geloescht haetten. Die WebUI-Ansicht zeigt je Feld den Wirkungsvermerk und schickt nur, was geaendert wurde. Der Leak-Test legt seine Kanarienwerte jetzt auch in die Einstellungsdatei, sonst liefe die neue Route gegen eine leere Datei. Nicht durch Unit-Tests abgedeckt: die Desktop-Aenderung an SettingsWindow (Oberflaechenklasse). Sie wird mit der Sichtpruefung auf der VM abgenommen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
68d8d6f8d2 |
Module im WebUI aktivieren und deaktivieren
Umsetzung von #560. Die Ansicht "Moduleinstellungen" zeigte bisher nur an, ob ein Modul laeuft. Jetzt laesst sich dort wie im Modul-Tab des Desktops festlegen, welche Module beim naechsten Start geladen werden. POST /api/modules/{name}/enabled nimmt den gewuenschten Zustand ausdruecklich entgegen ({"enabled": true|false}) und schaltet nicht einfach um. Zwei Klicks aus zwei Fenstern heben sich damit nicht auf, und ein wiederholter Aufruf aendert nichts mehr. Fehlerfaelle: - Unbekanntes Modul: 404. - Modul mit Aktivierungs-Blocker: 409. - Fehlender Zustand: 400. Die Pruefung war zuerst lueckenhaft, der Test hat es gefunden: Mit "bool Enabled" machte ein leerer Rumpf {} daraus false, und ein unvollstaendiger Aufruf haette das Modul deaktiviert. Gemeinsame Quelle statt Kopien: - KnownModules: Die Modulliste stand viermal im Code (Program, CoreViews, ModuleViews, hartkodiert im WebUI). Der Start registriert jetzt die eine Liste. - ModuleActivationView: Die Statusregeln des Desktops ("Aktiv - stoppt nach Neustart" usw.) liegen im Core. Desktop und WebUI zeigen dasselbe. ServerSettingsFile - gefunden, bevor das WebUI in die Datei schreiben durfte: ServerSettings.Load verschluckt jeden Lesefehler und liefert Vorgaben. "Frisch lesen, ein Feld aendern, speichern" haette eine gesperrte oder beschaedigte server_settings.xml durch Vorgaben ersetzt, und mit ihr Lizenzschluessel, Watchdog-Token, Mullvad-Account und Alchemy-Key. Genau so schrieb auch der Modul-Schalter des Desktops. ServerSettingsFile: - liest streng und schreibt bei unlesbarer Datei nichts, - schreibt atomar ueber eine Nachbardatei, - erhaelt unter Linux die Dateirechte, - serialisiert Aenderungen prozessweit. Der Desktop-Schalter benutzt ihn jetzt ebenfalls. Tests: Lizenzschluessel, Token und Alchemy-Key bleiben beim Umschalten in der Datei; eine kaputte Datei bleibt Byte fuer Byte unveraendert und die Anzeige bietet dann kein Umschalten an; Blocker, 404, 400, Idempotenz; die Statustabelle; strenges Lesen, atomares Schreiben und Rechte am Dateiobjekt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
d33d695db5 |
WebUI: Trading beenden, ohne die Anwendung zu beenden
Umsetzung von #563. Entscheidung Richard, 13.09.2026: Beenden soll ueber das WebUI gehen, aber beschraenkt auf das Trading. Ein Ende der ganzen Anwendung naehme den Webserver mit; danach waere das WebUI nicht mehr erreichbar. POST /api/dashboard/stop-trading setzt Live- und Demo-Modus auf Inaktiv und schaltet die Pause ein. Damit halten CopyTrading und ResolutionFarming (#569) an, wie beim Ende der Anwendung. Offene Orders an der Boerse werden bewusst nicht storniert: Das tut auch das Beenden der App nicht, und ein Eingriff in die CLOB-Integration gehoert nicht in einen Notschalter. Der Dialog sagt das ausdruecklich. Die Route verlangt {"confirmed": true}. Ein Aufruf ohne Absicht, etwa aus einem alten Skript, beendet nichts. Der Vorgang wird als Warnung protokolliert, mit den Modi vorher. Im Dashboard steht unter der Notfall-Pause jetzt "Trading beenden ...". Der Dialog ist wie im Desktop 10 Sekunden gesperrt, Abbrechen und Esc gehen jederzeit. Wieder aufgenommen wird nur ueber die Modus-Schalter. Die Pause aufzuheben genuegt nicht, das haelt ein Test fest. Offen bis #570: Laufende Verkaufsleitern und der REST-Pre-Redeem pruefen die Pause nicht. Der Inaktiv-Modus, den dieser Knopf setzt, sperrt den Pre-Redeem bereits; die Leitern friert erst #570 ein. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
99172a6be2 |
WebUI gibt keine Geheimnisse mehr heraus und aendert keine Zugangseinstellungen
Behebt #562. Entscheidung Richard, 13.09.2026: Geheimnisse verwalten wir ausschliesslich im Desktop. Bis dahin lieferte GET /api/settings/webui das Zugangs-Token im Klartext. Ueber das WebUI liessen sich ausserdem ein Token setzen, ein neues erzeugen und LocalOnly abschalten. Wer das Token hatte, konnte das WebUI damit ueber unverschluesseltes HTTP ins Netz oeffnen, sich den Zugang verlegen oder sich selbst aussperren. Jetzt: - GET /api/settings/webui liefert Enabled, Port, LocalOnly und vom Token nur hasToken. - POST /api/settings/webui und /webui/generate-token antworten mit 403 und protokollieren den Versuch. Sie bleiben als ausdrueckliche Ablehnung stehen: Ohne eigene Route faengt die Fallback-Route den POST ab und antwortet mit 200, ein altes Skript hielte das fuer einen Erfolg. - Die WebUI-Einstellungsansicht zeigt den Zugang nur noch an. Gepflegt wird er im Desktop unter Einstellungen -> WebUI. WebUiSecretsTests zaehlt alle GET-Routen selbst auf und prueft jede Antwort gegen Kanarienwerte. Geprueft werden ApiKey, ApiSecret, ApiPassphrase und PrivateKey eines Kontos, Mullvad-Account, Alchemy-Key, Watchdog-Token, Lizenzschluessel und das WebUI-Token. Eine neue Route, die ein Konto oder die Server-Einstellungen serialisiert, faellt damit auf, ohne dass jemand an diesen Test denken muss. Gegen die alte Route schlug er fehl ("GET /api/settings/webui liefert ein Geheimnis aus"), jetzt ist er gruen. Ausserdem festgehalten: /api/accounts kennt nur GET. Polymarket-Konten bleiben im WebUI lesbar und nicht aenderbar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
b70d5e5f00 |
WebUI-Tests rufen jetzt echte Routen auf
Behebt #568. Keine der Testdateien mit "EndpointsTests" im Namen hat je einen Endpunkt aufgerufen. CopyTradingAndResolutionFarmingEndpointsTests beruehrte gar keinen Produktionscode: Die Tests summierten Listen im Test und verglichen das Ergebnis mit sich selbst. Modules_KnownModules pruefte, ob ein Array seine eigenen Elemente enthaelt. Settings_UpdateRequest pruefte die Portbegrenzung an einer im Test nachgebauten Lambda. Solche Tests bleiben gruen, egal was der Endpunkt tut. Neu startet WebUiTestHost das WebUI in einem Testserver (Microsoft.AspNetCore.TestHost) und spricht es ueber HTTP an. Damit der Test die Kette aus dem Betrieb prueft und keine nachgebaute, liegt sie jetzt in UsePolyTraderWebPipeline(): statische Dateien, Token-Pruefung, alle Routen. ConfigurePolyTraderWeb ruft genau diese Methode. Ersetzt wird nur, was ausserhalb des Prozesses liegt - Kestrel durch den Testserver, MySQL durch den InMemory-Provider. Die acht CopyTrading/ResolutionFarming-Tests pruefen dieselben Absichten wie vorher, jetzt an der Antwort der Route. Neu hinzugekommen sind Tests fuer: - Zugangssperre: ohne Token, mit falschem Token, ohne konfiguriertes Token - die Modulliste - Job-Umschalten samt 404 - die Ablehnung einer leeren Supervisor-Frage Die beiden Tests, die schon echten Code prueften, bleiben. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
4c556be57d |
Einstellungen: erst schreiben, dann uebernehmen
Behebt #534. Die vier schreibenden Endpunkte verschluckten die Ausnahme des Repositories und meldeten anschliessend unbedingt Erfolg. Das Verschlucken war unschoen; die Reihenfolge war gefaehrlich: copyState wurde auch dann geaendert, wenn die Datenbank abgelehnt hatte. Das Modul handelte danach mit Risikolimits, die nirgends standen, und nach dem naechsten Neustart konnte niemand mehr rekonstruieren, womit es gehandelt hatte. Neu geht der Schreibvorgang zuerst, und der Hauptspeicher wird nur nachgezogen, wenn er gelang. Sonst 500 mit Klartext und unveraenderter Zustand. Fehlt die Ablage ganz, ist die Aenderung ebenso rein fluechtig — auch das wird abgelehnt, mit 503. Betroffen: CopyTrading-Kontoeinstellungen, ResolutionFarming-Kontoeinstellungen, Master-Trader anlegen/aendern, Master-Trader loeschen. Dass alle vier denselben Helfer (PersistenceGuard) benutzen, ist der eigentliche Punkt: Aus je eigenem try/catch je Endpunkt ist die Ungleichheit ueberhaupt erst entstanden. Bewusst anders behandelt bleibt das Archivieren eines Supervisor-Berichts: Die Antwort des Agenten steht dort bereits und hat Geld gekostet: sie wegen eines fehlgeschlagenen Archiveintrags zu verwerfen, waere schlimmer als der fehlende Eintrag, und an diesem Schreibvorgang haengt kein Verhalten des Systems. Stillschweigend verschwindet er aber nicht mehr, sondern wird protokolliert. In der Oberflaeche zeigten die Schreibwege bisher nur "HTTP 500" an und verschenkten damit genau die Begruendung, die der Server jetzt mitliefert. errorText() liest sie aus der Antwort. Entscheidung von Richard: ablehnen statt fluechtig uebernehmen. Damit sind waehrend eines Datenbankausfalls keine Aenderungen an den Einstellungen mehr moeglich; das Handeln selbst laeuft weiter. Geprueft auf der Linux-Test-VM mit angehaltener MariaDB: alle drei Schreibwege antworten mit 500 und nennen den Grund, das Limit bleibt bei 11,25 statt auf 99,99 zu springen, der Phantom-Trader entsteht weder im Hauptspeicher noch in der Datenbank, jeder Fehlschlag steht im Protokoll. Nach dem Wiederanlauf speichert es wieder. 556 von 556 Tests bestanden (5 neue). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
dcc764dec1 |
WebUI: Module, Analytics und Buchhaltung als eigene Ansichten
Das WebGUI konnte bisher Dashboard, Konten, Jobs, Logs und Einstellungen.
Die vier Strategie- und Analysemodule waren nur in der Avalonia-Oberflaeche
erreichbar - wer den Server aus der Ferne bediente, sah sie nicht.
Fuenf neue Endpunktgruppen holen sie herein:
/api/analytics KPIs, Equity-Kurve, PnL je Modul und Tag,
durchsuchbare Trade-Historie mit Seitenlauf
/api/modules/copytrading Master-Trader (CRUD), offene und
geschlossene Trades, Risikolimits je Konto
/api/modules/resolutionfarming Scanner-Kandidaten, Positionen, Historie,
Farming-Parameter je Konto
/api/modules/supervisor Profile, Agentenfragen, Berichtsarchiv,
Signal-Dossiers, Counterfactuals
/api/modules/accounting BWA-Periodenabrechnung, Ledger-Journal,
PDF- und CSV-Export, Ingest-Laeufe
Dazu im Bestand:
- Dashboard bekommt /overview-widgets: Modul-KPIs (heute/7T/30T), auffaellige
Trades der letzten 24 Stunden, Warnungen und Fehler des Tages, den letzten
Supervisor-Bericht.
- Die Kontenliste zeigt 3-Tage-PnL, Winrate, Gesamtergebnis und die
beteiligten Module statt nur Salden.
- Jobs lassen sich ueber /toggle und /state ein- und ausschalten, nicht nur
ausloesen.
Die Oberflaeche bleibt ohne Fremdbibliotheken: alle Diagramme sind Inline-SVG,
kein CDN, kein npm. Alle neuen Pfade liegen unter /api/ und damit hinter der
bestehenden Token-Pruefung.
Zwei Fehler nebenbei behoben:
- AccountingReportService.ResolveCurrency lief in eine NullReferenceException,
wenn der FX-Dienst nicht gesetzt war. Betrifft jeden EUR-Aufruf ohne
geladene EZB-Kurse.
- Ein Master-Trader, dessen Name ein Apostroph enthaelt, hatte einen toten
Loeschen-Knopf: escapeHtml laesst ' unberuehrt, und im onclick-Attribut
beendete das Zeichen das JavaScript-Literal vorzeitig. Laengerer Text mit
Anfuehrungszeichen konnte darueber eigenen Code einschleusen. Neu setzt
jsArg() den Wert als JSON-Literal ein; geprueft mit
O'Brien "quote" <b>bold</b> \ backslash.
McpLightServerTests weicht jetzt aus, wenn HttpListener mangels URL-ACL nicht
binden darf, statt den Lauf scheitern zu lassen.
Geprueft auf der Linux-Test-VM (Ubuntu 26.04, .NET 10): Build ohne Fehler,
533 von 533 Tests bestanden, alle 11 Ansichten und 15 Unteransichten geladen,
alle Endpunkte mit 200 beantwortet, Schreibwege bis in die Datenbank
nachverfolgt, PDF- und CSV-Export gueltig, SSE-Logstrom live.
Offene Befunde aus der Abnahme liegen als #532 (Kopfleiste laeuft unter
1623 px ueber), #533 (EUR-PDF ohne EZB-Kurse liefert Nullbetraege) und #534
(Einstellungen melden Erfolg trotz gescheitertem Speichern) im Bugtracker.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
78a2f85b94 | Standardport für WebUI von 5001 auf 6001 geändert | ||
|
|
10f928eb4e | Paralleles WebGUI mit Kestrel, Token-Sicherung und SSE-Logs implementiert |