Watchdog-Anleitung vollständig überarbeitet - Alle drei Codebeispiele trugen das geseedete Demo-Token fest im Quelltext. Es ist an die Source "srv-db-01" gebunden — wer es übernommen hätte, wäre für jeden anderen Dienst abgewiesen worden. Jetzt Umgebungsvariable und eine Anleitung, wie man ein eigenes Token erzeugt. - Der Ratschlag "sende beim Beenden einen Ping mit Status stopped" beschrieb etwas, das die API nicht konnte. Statt die Anleitung an die Lücke anzupassen, ist die Lücke geschlossen: status akzeptiert jetzt "stopped" und "maintenance". Der Evaluator lässt solche Monitore in Ruhe, statt wenige Minuten nach jedem sauberen Shutdown einen Fehlalarm zu erzeugen. - Neu dokumentiert: checks (Gesundheitszustand per Push, ohne offene Ports), metrics samt Verlauf und Abweichungsvergleich, Alarmunterdrückung über die Hierarchie, die Schwellen des Evaluators (2x warning, 4x down) und der erforderliche Cron-Job. Lizenz-Anleitung - Neuer Abschnitt zum Antwortformat. Die Lizenz-Endpunkte antworten bewusst ohne den status/error-Umschlag der übrigen API; das Feld status auf oberster Ebene trägt den Lizenzzustand. Genau diese Besonderheit hatte ich beim Umbau übersehen, weshalb sie jetzt ausdrücklich festgehalten ist — samt Tabelle aller Zustände. - Ergänzt: Deaktivierung braucht den shared_key, mit Beispiel für den .NET- Client und curl. Verhalten bei Ratenbegrenzung. UpdateService-Anleitung - Prüf-Endpunkte dokumentiert (check, latest, releases) samt Antwortformat. - Tabelle zum Versionsvergleich mit den Fällen, die vorher falsch liefen. - Auto-Resolve beim Veröffentlichen beschrieben. Agent-Prompt-Vorlage - Fehler-Schnittstelle ergänzt, inklusive Hinweis auf "ignored": true, damit ein Agent bekannte Fehler nicht untersucht. Alle in der Dokumentation genannten API-Pfade und Scopes wurden maschinell gegen Routing und TokenManager abgeglichen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.phpeintragen - FTP-Passwort ändern, danach in
scripts/deploy_config.jsoneintragen .htpasswd-Passwort fürdeployneu setzen- Git-Token
eb429575…widerrufen und neu ausstellen - Admin-Passwort im WebUI ändern (die alte Fassung setzte es bei jedem
Aufruf von
install_db.phpaufAdmin1337!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äuftdc_login_attempts— Drosselung fehlgeschlagener Anmeldungendc_webhooks— ausgehende Benachrichtigungen- Bugtracker: Claim/Lease,
client_ref,dedup_key, Code-Kontextfelder, Indizes - Watchdog:
last_state_change_utc,down_since_utc, Zustandunknown - 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.
- WebUI → Token-Verwaltung → Master-Token erstellen
- Scopes wählen (für einen Coding-Agenten:
bugtracker:report,bugtracker:read,bugtracker:manage) - Master-Token einmalig kopieren und auf dem Agenten-Rechner als
DC_TOKENhinterlegen — oder den Agenten per/api/tokens/v1/provisionein 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.
Neu sind außerdem die Statuswerte stopped und maintenance. Ohne sie erzeugte
jedes geplante Herunterfahren wenige Minuten später einen Fehlalarm — es gab
schlicht keinen Weg, ein beabsichtigtes Ende mitzuteilen:
{ "source": "polytrader-worker", "status": "stopped",
"message": "Dienst planmäßig beendet" }
Der Evaluator lässt solche Monitore in Ruhe, bis wieder ein normaler Heartbeat eintrifft.
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.