30891c1bcedcfdb94e25d09792a20120118ed5a1
12
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
30891c1bce |
WebUI: Hellmodus, Supervisor-Verlauf leeren, API-Status beschriftet
Umsetzung von #566. Hell-/Dunkelmodus Das WebUI hatte nur eine dunkle Palette. Jetzt gibt es "System", "Hell" und "Dunkel" als Umschalter in der Kopfleiste. Die Wahl gilt je Browser; ohne gespeicherte Wahl folgt das WebUI dem Betriebssystem. data-theme auf <html> ueberstimmt prefers-color-scheme in beide Richtungen. Ein kleines Skript im <head> setzt die Wahl vor dem ersten Zeichnen, sonst blitzte beim Laden kurz das falsche Schema auf; die Login-Seite macht es genauso. Kontrast der hellen Palette auf Weiss: - Text 8:1 - gedaempfter Text 6,3:1 - Akzent, Gewinn, Verlust und Warnung je mindestens 4,5:1 Fuenf feste Farben haetten im Hellmodus gebrochen und sind jetzt Tokens: - #11111b als Schrift auf Akzentfarbe (Primaerknopf, Profil-Hover, aktive Waehrung): im Hellmodus dunkel auf dunklem Blau. - rgba(255,255,255,0.02 bis 0.08) fuer Zeilen-Hover und Trennlinien: auf Weiss unsichtbar. Das Terminal bleibt in beiden Modi dunkel und bringt seine Palette lokal mit. Es hatte einen festen dunklen Hintergrund, erbte aber var(--text), und das waere im Hellmodus dunkle Schrift auf Schwarz geworden. Die uebrigen festen Farben sind halbtransparente Toenungen und Schatten, die auf beiden Gruenden funktionieren. Supervisor "Verlauf leeren" wie im Desktop. Geleert wird nur die Unterhaltung im Browser, die Begruessung kommt zurueck, gespeicherte Berichte bleiben erhalten. Statusanzeige Der WSS-Punkt ist jetzt beschriftet, "WSS aktiv" oder "Polling", wie "API: ..." in der Statusleiste des Desktops. Dazu kommt "Module x/y". Reine Oberflaeche, keine Aenderung am Server. Die Pruefung erfolgt im Browser auf der VM. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
2c0ab79dcd |
WebUI-Kopfleiste: Aufklappmenues statt elf Tabs
Umsetzung von #541, folgt auf #532. Elf Tabs nebeneinander waren nicht mehr zu ueberblicken. Die Leiste hat jetzt vier Eintraege, gruppiert nach dem, was man dort tut: - Dashboard - Analytics: Analytics, Accounting, Supervisor - Module: Moduleinstellungen (die allgemeine Modulansicht), danach alle Module - Einstellungen: Einstellungen, Jobs, Konten, Terminal / Logs Supervisor und Accounting stehen unter Analytics und zusaetzlich in der Modulliste, weil dort alle Module stehen sollen. Hervorgehoben wird das Oberelement nur an ihrem Hauptplatz (Analytics); der zweite Zugang traegt data-secondary. Sonst leuchteten bei geoeffnetem Supervisor zwei Menues. switchView() findet den aktiven Eintrag jetzt ueber data-view statt ueber eine Teilzeichenkette im onclick-Attribut. Das alte Verfahren hing am Zufall der Namen: Eine Ansicht, deren Name in einer anderen enthalten ist, haette beide markiert. Die Modulliste zeigt den Zustand aus /api/modules: Ein deaktiviertes Modul erscheint ausgegraut mit "deaktiviert" und ist nicht anklickbar, statt in eine leere Ansicht zu fuehren. Ein Modul, das der Server fuehrt, fuer das es im WebUI aber keine Ansicht gibt, wird mit "keine Ansicht" gelistet. Bedienbar mit Maus und Tastatur: Klick ausserhalb und Esc schliessen (Esc gibt den Fokus ans Oberelement zurueck), Pfeil nach unten oeffnet und springt in das Menue, Pfeiltasten laufen um und ueberspringen deaktivierte Eintraege, Tab verlaesst das Menue. aria-haspopup, aria-expanded und aria-current sind gesetzt. Unter 760 px haengen die Menues an der ganzen Leiste statt am Eintrag. Bei 400 px ragte "Module" sonst 35 px ueber den rechten Rand. Ein Nachmessen per Skript taugt dagegen nicht: In der Mobilansicht waechst der Layout-Viewport mit dem Ueberstand mit, und die Messung meldet genau dann "passt". Die Modulansicht heisst jetzt wie ihr Menueeintrag "Moduleinstellungen". Geprueft auf der Linux-Test-VM im Browser: Alle 12 Eintraege schalten die richtige Ansicht und heben das richtige Oberelement hervor, das Menue schliesst danach; Tastaturbedienung, deaktiviertes und unbekanntes Modul (simuliert) verhalten sich wie beschrieben. Vermessen bei 400, 700, 768 und 1024 px: kein Menue ragt aus dem Fenster, die Seite scrollt nie waagerecht. 556 von 556 Tests bestanden. 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> |
||
|
|
72ad38518b |
EZB-Tageskurse selbst abrufen, Kopfleiste umbrechen lassen
Behebt #532 und #533. #532 — Kopfleiste bricht um statt zu scrollen Mit elf Ansichten brauchte die Leiste 1623 px. Darunter scrollte sie seitlich weg, ohne dass ein Hinweis darauf sichtbar war: Wer einen rechten Tab anklickte, verlor "Dashboard" aus dem Blick und fand den Weg zurueck nicht mehr. Statt overflow-x nun flex-wrap auf Leiste und Kopfzeile. Geprueft von 1920 bis 768 px — nichts wird mehr abgeschnitten, der Koerper scrollt nie waagerecht. #533 — Kurse holen, statt EUR still auf null zu setzen Die Tabelle acc_fx_rates gab es seit A-2, befuellt hat sie nie jemand. Deshalb war EUR nicht verfuegbar, und der PDF-Export machte daraus wortlos einen Beleg mit lauter Nullbetraegen. Neu holt EcbFxRateSource die amtlichen Referenzkurse ueber die EZB-Daten-API (Reihe EXR/D.USD.EUR.SP00.A, CSV). FxRateSyncService stoesst das beim ersten Ingest-Lauf des Tages an: erstmalig 400 Tage rueckwirkend, danach nur noch der Rand. Die Kurse werden gespeichert, nicht bei Bedarf geholt — eine Abrechnung fuer einen vergangenen Monat muss den Kurs von damals nehmen und beim naechsten Aufruf dasselbe Ergebnis liefern. Zwei Fallen, die dabei zu umgehen waren: - Die Reihe liefert USD je EUR (1 EUR = 1,1652 USD), FxRate.UsdToEur meint die Gegenrichtung. Wer das verwechselt, bekommt eine Abrechnung, die um rund 35 % danebenliegt und trotzdem plausibel aussieht. Gespeichert wird der Kehrwert. - Die CSV-Antwort enthaelt in TITLE_COMPL ein Komma innerhalb von Anfuehrungszeichen; naives Splitten verschoebe die Spalten. Die Warnung erscheint, sobald der verwendete Kurs mehr als drei Tage vor dem Stichtag liegt. Drei Tage, weil genau so gross die planmaessige Wochenendluecke ist: Der Freitagskurs gilt bis Montag und ist dabei kein Mangel. Der Beleg bleibt trotzdem erzeugbar — die Warnung steht sichtbar darauf und im WebUI ueber der Abrechnung. Nur ohne jeden Kurs lehnt der Export jetzt mit 400 ab, statt Nullbetraege auszugeben. PDF und CSV laufen deshalb nicht mehr ueber window.open: Eine nackte JSON-Fehlermeldung in einem neuen Reiter ist keine Antwort. downloadExport() holt die Datei, meldet Fehler im Klartext und stoesst sonst den Download an. Nebenbei im Testlauf gefunden und behoben: Der manuelle Anstoss aus dem WebUI und die stuendliche Schleife trafen sich in derselben Sekunde — im Log standen "280 Kurse uebernommen" und "53 Kurse uebernommen" untereinander, beide hatten die EZB gefragt. SyncDailyAsync serialisiert jetzt und prueft den Tag ein zweites Mal innerhalb der Sperre. Geprueft auf der Linux-Test-VM gegen die echte EZB-API: 280 Kurse vom 06.08.2025 bis 09.09.2026 uebernommen, Umrechnung stimmt (1/1,1652 = 0,858222), eine Maerz-Abrechnung nimmt den Kurs vom 31.03. und nicht den heutigen, das Warnbanner erscheint ab dem vierten Tag, der Export verweigert ohne Kurs und liefert sonst ein gueltiges PDF. 551 von 551 Tests bestanden (18 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>
|
||
|
|
10f928eb4e | Paralleles WebGUI mit Kestrel, Token-Sicherung und SSE-Logs implementiert |