# 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`](https://github.com/newren/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: ```bash 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 ```bash 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: ```bash php public/install_db.php ``` Oder mit dem Shared Key: ```bash curl -H "Authorization: Bearer " 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. ```bash * * * * * curl -fsS -H "Authorization: Bearer " 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 ```bash curl https://dc.mhdf.de/api/health -H "Authorization: Bearer " ``` 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: ```json { "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: ```sql 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= ``` Nach 20 Fehlversuchen in Folge deaktiviert sich ein Webhook selbst.