Files
Deploymentcenter/docs/UPGRADE.md
T
Deploymentcenter BotandClaude Opus 5 60e34b29f6 feat(errors, watchdog): Fehler-Stream mit Ignore-Regeln, Metrik-Verlauf, Abhängigkeits-Alarme
Fehler-Schnittstelle
- Neuer schlanker Eingang POST /api/errors/v1/report für den globalen
  Exception-Handler einer Anwendung. Titel und Dringlichkeit leitet der Server
  ab; gespeichert wird in derselben Tabelle wie der Bugtracker. Ein zweiter
  Speicher wäre nur ein zweiter Ort, an dem man suchen müsste.
- error_level (fatal/error/warning) trennt die technische Art des Ereignisses
  von der geschäftlichen Dringlichkeit. Ein Duplicate-Entry ist technisch ein
  error, geschäftlich belanglos — beides zu vermischen war der Grund, warum
  solche Meldungen als Bug im Dashboard landeten.

Ignore-Regeln gegen bekanntes Rauschen
- bugtracker_ignore_rules mit contains/regex/exception_class, Pflichtfeld für
  die Begründung und optionaler Alarmschwelle.
- Ein Treffer bedeutet nicht "wegwerfen": Der Fehler wird weiterhin erfasst und
  hochgezählt, bleibt aber aus der Übersicht heraus und löst keine
  Benachrichtigung aus. Der Zähler ist der eigentliche Zweck — dass ein
  bekannter Fehler auftritt, ist normal; dass er plötzlich hundertmal so oft
  auftritt, ist ein Signal. Dafür das rollende Stundenfenster und
  error.rate_exceeded.
- Neue Regeln lassen sich rückwirkend auf bestehende Einträge anwenden.

Gruppierung überarbeitet
- Der Schlüssel nahm bisher 300 Zeichen Stacktrace auf. Derselbe Fehler
  zersplitterte dadurch, sobald ein Aufrufer den Stack einmal mitschickte und
  einmal nicht. Jetzt zählt der Ursprungsort: bevorzugt die Dateiangabe, sonst
  der erste Rahmen des Stacktrace.
- Die Normalisierung ersetzte nur Zahlen ab vier Stellen, wodurch
  'AA-1' und 'BB-2' getrennt blieben. Werte in Anführungszeichen, die Ziffern
  enthalten, gelten jetzt als veränderlich — der Schlüsselname bleibt erhalten,
  sodass verschiedene Unique-Keys unterscheidbar sind. Mit 9 Testfällen belegt.

Metrik-Verlauf
- watchdog_metrics speichert numerische Heartbeat-Werte mit Zeitstempel.
  Zuvor wurde metrics_json bei jedem Heartbeat überschrieben; damit ließ sich
  "die Platte läuft seit drei Tagen voll" nicht erkennen, nur "sie ist voll".
- GET /api/watchdog/v1/metrics liefert den verdichteten Verlauf und die
  Abweichung vom eigenen Sieben-Tage-Durchschnitt. Dieser relative Ansatz
  braucht keine projektspezifischen Schwellwerte.
- Aufbewahrung 14 Tage, Bereinigung stündlich durch den Evaluator.

Health-Checks per Push statt Abruf
- Der Heartbeat nimmt ein checks-Objekt entgegen, das die Anwendung selbst
  ermittelt. Das Deploymentcenter interpretiert die Namen nicht, es liest nur
  ok und message — was "gesund" bedeutet, entscheidet jede Anwendung selbst.
  Schlägt eine Prüfung fehl, wird ein als ok gemeldeter Heartbeat auf warning
  herabgestuft.
- Bewusst ausgehend: auf den Zielmaschinen müssen keine Ports geöffnet werden.

Abhängigkeitsbewusste Alarmierung
- Fällt ein Monitor aus, dessen Parent selbst unten ist, wird der Alarm
  unterdrückt. Der Zustand bleibt sichtbar. Vorher erzeugte ein ausgefallener
  Hypervisor mit zwölf VMs dreizehn Meldungen für ein Problem.
- Mehrere Ebenen und fehlerhafte Hierarchien (Zyklen, gelöschte Parents) sind
  abgesichert; mit 10 Testfällen belegt.

WebUI
- Neue Ansicht "Fehler-Stream" mit Filtern nach Projekt, Fehlerklasse,
  Umgebung, Zeitraum und Sichtbarkeit sowie Volltextsuche und Pagination.
  Stummgeschaltete Einträge sind standardmäßig ausgeblendet.
- Verwaltung der Ignore-Regeln inklusive Trefferzähler.
- Die Detailansicht zeigt Fehlerklasse, Stummschaltungsgrund und die Häufung
  im laufenden Stundenfenster.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 21:55:23 +02:00

10 KiB

Umstellung auf Version 2.0 — Ablaufplan

Diese Fassung enthält Sicherheitskorrekturen, die das Verhalten der Schnittstellen ändern. Bitte in dieser Reihenfolge vorgehen.


1. Vor dem Deployment: Zugangsdaten wechseln

Serverdaten.txt, config/config.php, config/.htpasswd und scripts/deploy_config.json lagen im Git-Repository. Sie sind jetzt per .gitignore ausgeschlossen und aus dem Index entfernt — die Git-Historie enthält sie aber weiterhin. Alle betroffenen Zugangsdaten sind daher als kompromittiert zu behandeln:

  • MySQL-Passwort ändern, danach in config/config.php eintragen
  • FTP-Passwort ändern, danach in scripts/deploy_config.json eintragen
  • .htpasswd-Passwort für deploy neu setzen
  • Git-Token eb429575… widerrufen und neu ausstellen
  • Admin-Passwort im WebUI ändern (die alte Fassung setzte es bei jedem Aufruf von install_db.php auf Admin1337! zurück — jeder im Internet konnte das auslösen)

Wenn die Historie bereinigt werden soll, geht das mit git filter-repo. Das schreibt alle Commit-Hashes um; bei einem Repository mit mehreren Nutzern vorher abstimmen.


2. Konfiguration ergänzen

config/config.php braucht drei neue Schlüssel unter security. Die mitgelieferte Datei enthält bereits erzeugte Werte; für eine neue Installation:

cp config/config.example.php config/config.php
openssl rand -hex 32   # je einmal für shared_key, webhook_key, license_key
Schlüssel Zweck
security.shared_key Server-zu-Server-Aufrufe: Evaluator-Cron, Migration, Deaktivierung
security.webhook_key HMAC-Signatur ausgehender Webhooks
security.license_key Signatur der Offline-Lizenzdateien (.lic)
app.debug Auf Produktivsystemen false — steuert, ob Exception-Texte ausgeliefert werden

Der bisherige shared_key (DC_MASTER_SECURE_TOKEN_2026_x98f) stand im Repository und wurde ersetzt. Wer ihn irgendwo eingetragen hat — etwa für /api/license/v1/deactivate — muss den neuen Wert nachziehen.


3. Deployment

python scripts/deploy.py

Das Skript überträgt unter anderem die neuen Verzeichnisse var/ (Logs) und die zusätzlichen .htaccess-Dateien in config/, src/ und sql/.


4. Migration ausführen

Im WebUI anmelden, dann System → DB-Migration → Migration jetzt ausführen.

Alternativ über die Kommandozeile:

php public/install_db.php

Oder mit dem Shared Key:

curl -H "Authorization: Bearer <SHARED_KEY>" https://dc.mhdf.de/install_db.php

Die Migration ist additiv und legt an bzw. korrigiert:

  • dc_migrations — vermerkt angewendete Versionen, damit nichts doppelt läuft
  • dc_login_attempts — Drosselung fehlgeschlagener Anmeldungen
  • dc_webhooks — ausgehende Benachrichtigungen
  • Bugtracker: Claim/Lease, client_ref, dedup_key, Code-Kontextfelder, Indizes
  • Watchdog: last_state_change_utc, down_since_utc, Zustand unknown
  • Reparatur von Migration 005 — deren Spalten (push_id, target_agent, tags) fehlten bisher auf Datenbanken, die aus Migration 004 stammen. Die alte Fassung nutzte dynamisches SQL, dessen Semikolons in String-Literalen vom damaligen Installer als Statement-Ende gelesen wurden; die Fehler wurden stillschweigend verschluckt.
  • Reparatur der Token-Hashes — die Validierung vergleicht jetzt nur noch den SHA-256-Hash. Die geseedeten Beispiel-Tokens trugen Hashes, die nicht zu ihrem Klartext passten; sie werden korrigiert, damit bestehende Tokens weiterhin funktionieren.

5. Cron für den Watchdog-Evaluator einrichten

Ohne diesen Schritt sind die Monitor-Zustände wertlos. Der Evaluator fehlte bisher vollständig — der Zustand änderte sich nur beim Eintreffen eines Heartbeats, ein ausgefallener Server blieb dauerhaft grün.

* * * * * curl -fsS -H "Authorization: Bearer <SHARED_KEY>" https://dc.mhdf.de/api/watchdog/v1/evaluate > /dev/null

Solange der Job fehlt, zeigt das WebUI oben einen Warnhinweis mit einer Schaltfläche für einen einmaligen Lauf.


6. Agenten-Tokens ausstellen

Die Ingest-Endpunkte verlangen jetzt zwingend ein Token.

  1. WebUI → Token-Verwaltung → Master-Token erstellen
  2. Scopes wählen (für einen Coding-Agenten: bugtracker:report, bugtracker:read, bugtracker:manage)
  3. Master-Token einmalig kopieren und auf dem Agenten-Rechner als DC_TOKEN hinterlegen — oder den Agenten per /api/tokens/v1/provision ein eigenes Sub-Token ziehen lassen

7. Bestehende Integrationen anpassen

Betroffen Was zu tun ist
Aufrufe von /api/bugtracker/v1/report ohne Token Token-Header ergänzen
Aufrufe von /api/bugtracker/v1/projects ohne Token Token-Header ergänzen
Skripte, die Releases veröffentlichen Token mit updateservice:publish ergänzen
Auswertung der Antworten Neues Format: {"status":"success",…} bzw. {"status":"error","error":{"code":…}}
Watchdog-Agenten mit wd_live_…-Token Laufen unverändert weiter
Clients, die /api/updateservice/v1/check aufrufen Unverändert, weiterhin ohne Token
Clients, die /api/license/v1/validate aufrufen Unverändert, weiterhin ohne Token

8. Zeitzonen

Datenbankzeitstempel liegen jetzt durchgängig in UTC; das WebUI rechnet für die Anzeige in app.timezone (Europe/Berlin) um. Vorhandene Datensätze wurden in Serverzeit geschrieben und erscheinen daher einmalig um den Zeitzonenversatz verschoben. Für Monitoring-Daten ist das ohne Bedeutung, für den Audit-Log gegebenenfalls beachten.


9. Prüfen, ob alles läuft

curl https://dc.mhdf.de/api/health -H "Authorization: Bearer <SHARED_KEY>"

Erwartet wird "healthy": true, eine leere schema.pending-Liste und ein checks.evaluator.ok von true.

Zusätzlich stichprobenartig im WebUI prüfen:

  • Anmeldung funktioniert
  • Projekt anlegen und wieder löschen
  • Monitor bearbeiten — das Feld Betriebssystem bleibt nach dem Speichern erhalten (wurde zuvor bei jedem Speichern geleert)
  • Bugtracker: „🔍 Details" öffnet den Dialog, „✔" öffnet den Lösen-Dialog (dessen HTML fehlte bisher komplett)
  • Token widerrufen und löschen (warf zuvor HY093)
  • Lizenz-Aktivierung freigeben (warf zuvor Class "Audit" not found)
  • Nach dem Speichern F5 drücken — es entsteht kein zweiter Eintrag mehr

10. Fehler-Stream (Migration 007)

Neu ist eine eigene Schnittstelle für Laufzeitfehler, gedacht für den globalen Exception-Handler einer Anwendung:

POST /api/errors/v1/report

Gespeichert wird in derselben Tabelle wie der Bugtracker — ein zweiter Speicher wäre nur ein zweiter Ort, an dem man suchen müsste. Die Trennung von Rauschen und Signal leisten stattdessen Ignore-Regeln.

Bekannte, harmlose Fehler stummschalten

Im WebUI unter Bugtracker → 🔇 Ignore-Regeln. Ein Treffer bedeutet nicht „wegwerfen": Der Fehler wird weiterhin erfasst und hochgezählt, bleibt aber aus der Übersicht heraus und löst keine Benachrichtigung aus.

Der Zähler ist dabei der eigentliche Zweck. Zu jeder Regel lässt sich eine Alarmschwelle hinterlegen — dass ein bekannter Fehler auftritt, ist normal; dass er plötzlich hundertmal so oft auftritt, bedeutet, dass sich etwas geändert hat.

Eine deaktivierte Vorlage für den Duplicate-Entry-Fall liegt bereits vor; sie lässt sich im WebUI anpassen und einschalten.

Gruppierung

Veränderliche Anteile werden beim Zusammenfassen ausgeblendet: Werte in Anführungszeichen, die Ziffern enthalten, Speicheradressen, GUIDs, Zeitstempel und Zeilennummern. Duplicate entry 'MKT-88213' und Duplicate entry 'AA-1' landen damit in einer Gruppe — ein anderer Unique-Key dagegen nicht.

Hinweis: Migration 007 ändert die Berechnung des Gruppenschlüssels. Bereits erfasste Einträge behalten ihren alten Schlüssel; ein erneut auftretender Fehler legt daher einmalig eine neue Gruppe an. Danach ist der Zustand wieder konsistent.

11. Metrik-Verlauf und Health-Checks

Numerische Werte aus dem Heartbeat-Feld metrics werden jetzt mit Zeitstempel abgelegt (Aufbewahrung 14 Tage) und lassen sich über GET /api/watchdog/v1/metrics abfragen. Zuvor wurde metrics_json bei jedem Heartbeat überschrieben — es gab immer nur den letzten Moment.

Zusätzlich kann eine Anwendung ihren Gesundheitszustand selbst mitschicken:

{ "source": "polytrader-worker", "status": "ok", "interval": 60,
  "checks": {
    "db":          { "ok": true },
    "market_feed": { "ok": false, "message": "Letzter Tick vor 14 min" }
  } }

Das Deploymentcenter interpretiert die Namen nicht — es liest nur ok und message. Schlägt eine Prüfung fehl, wird ein als ok gemeldeter Heartbeat auf warning herabgestuft. Es müssen keine Ports geöffnet werden, der Weg ist ausgehend.

12. Abhängigkeitsbewusste Alarmierung

Fällt ein Monitor aus, für den parent_source gesetzt ist, und ist der übergeordnete Monitor selbst unten, wird der Alarm für das Kind unterdrückt. Der Zustand bleibt im Dashboard sichtbar.

Vorher erzeugte ein ausgefallener Hypervisor mit zwölf VMs dreizehn Meldungen für ein Problem.

Damit das greift, muss die Hierarchie gepflegt sein — im WebUI unter WatchDog → System-Hierarchie über das Feld Übergeordnete Entität.

13. Optional: Webhooks

Ereignisgesteuerte Benachrichtigung statt Polling. Ziel direkt in der Datenbank eintragen:

INSERT INTO dc_webhooks (name, url, project_slug, events, secret, enabled)
VALUES ('Telegram Alarm', 'https://n8n.example.com/webhook/dc',
        NULL, 'bug.critical,monitor.down', 'geheimnis', 1);

Verfügbare Ereignisse: bug.created, bug.critical, bug.resolved, feature.created, monitor.down, monitor.recovered, release.published, oder * für alle.

Jede Zustellung trägt eine Signatur:

X-DC-Timestamp: 1754563200
X-DC-Signature: sha256=<hex(hmac_sha256(secret, timestamp + "." + body))>

Nach 20 Fehlversuchen in Folge deaktiviert sich ein Webhook selbst.