master
8
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9d0261306c |
chore(cleanup): Altlasten entfernt, Webroot-Sperre und Supervisor-Route ergaenzt
Fruehjahrsputz. Alles hier ist unabhaengig von der laufenden Supervisor- Arbeit im Arbeitsverzeichnis - die bleibt unangetastet. Entfernt: - Die zwoelf Symbole unter public/assets/ waren bitgleiche Dubletten der Dateien in public/assets/icons/. Referenziert wurde ausschliesslich der Pfad mit icons/. getMonitorIconUrl() setzt flach gespeicherte Altwerte aus der Datenbank jetzt auf icons/ um, damit bestehende Monitore ihr Symbol behalten. - System.CommandLine (2.0.0-beta4) aus dem Packager. Kein using, kein Symbol, die Argumente werden von Hand geparst. Build bleibt fehlerfrei. Geschlossen: - client-php/ und mcp/ wurden weder von der .htaccess gesperrt noch vom Deployment ausgeschlossen. Die .mjs-Datei haette der Webserver im Klartext ausgeliefert. Beide gehoeren nicht ins Webroot: die PHP-Datei wird ins Zielprojekt kopiert, der MCP-Server laeuft lokal ueber stdio. Jetzt in beiden Ausschlusslisten - wie client-dotnet. - Fuer /api/supervisor/v1/ fehlte die Rewrite-Regel. Der Datei-Fallback haette /api/supervisor/v1/findings auf eine nicht vorhandene Datei geleitet, obwohl Code und OpenAPI diese Schreibweise vorsehen. Ergaenzt: - __pycache__/ und *.pyc in .gitignore. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
e579ca1acc |
chore(security): Signierschluessel-Datei von git ausschliessen
config/*.pem ergaenzt, damit der neue RSA-Signierschluessel fuer Releases (config/release-signing.pem) nie versehentlich eingecheckt wird. |
||
|
|
c8f3e78635 |
feat(setup): Erstinstallation ueber den Update-Agent, Installationskonto, Downloads
Bisher gab es nur den Update-Weg: eine Anwendung musste bereits installiert und eingerichtet sein, damit sich etwas aktualisieren liess. Die Erstinstallation auf einem neuen System war Handarbeit - Paket kopieren, Konfiguration abtippen, Token besorgen. Setup-API (neu) - POST /api/setup/v1/login tauscht Benutzername und Passwort gegen ein Token mit 30 Minuten Gueltigkeit und ausschliesslich setup:install. Es wird nicht mitgeschrieben und lebt im Installer nur im Speicher. - GET /api/setup/v1/catalog zeigt nur, was zur Laufzeitkennung des anfragenden Systems passt. Ein Projekt mit ausschliesslich Windows-Paket taucht auf einem Linux-Rechner gar nicht erst auf. - POST /api/setup/v1/token stellt das Dauertoken der Anwendung aus. Welche Rechte vergeben werden, entscheidet der Server; die Anfrage kann nur einschraenken. Sonst waere der Umweg ueber ein kurzlebiges Token wirkungslos. Rollentrennung (Migration 012) - dc_users bekommt role, disabled und last_login_at. Die Rolle "installer" darf sich ueber den Setup-Weg anmelden und nicht am WebUI. Die Zugangsdaten werden auf jedem Zielsystem eingetippt; mit einem Administratorkonto verteilte man damit den Zugang zu Tokens, Lizenzen und Monitoren auf jeden Rechner, auf dem je etwas installiert wurde. - Auth::verifyCredentials() prueft sessionfrei, damit Setup- und WebUI-Login nicht zwei verschiedene Haertungsgrade haben (Drosselung, Timing-Angleichung, Rehash gelten fuer beide). - Konten mit hinterlegtem TOTP-Geheimnis werden am Setup-Weg mit 501 abgewiesen. Eine TOTP-Pruefung gibt es im Deploymentcenter noch nicht; sie stillschweigend zu uebergehen waere ein Rueckschritt. - Benutzerverwaltung im WebUI - es gab bisher gar keine, nur den einen von install_db.php angelegten Admin. Das letzte aktive Administratorkonto laesst sich weder deaktivieren noch loeschen. Installer - update-agent --action install fuehrt durch Anmeldung, Auswahl, Zielverzeichnis, Installation und Einrichtung. Die Dateien kommen ueber denselben Pfad wie ein Update - mit Pruefsumme, Signatur, Staging und Rollback. Ein zweiter Download-Weg waere ein zweiter Ort fuer dieselben Fehler. - --action configure holt die Einrichtung nachtraeglich. - setup.json im Paket beschreibt die benoetigten Werte. Bewusst im Paket und nicht zentral: so ist sie mit der Anwendung versioniert. - Gefragt wird nur, was uebrig bleibt: bereits gesetzt -> detect:... -> provision -> fragen. Platzhalter wie changeme oder <dein-wert> gelten dabei nicht als eingerichtet, sonst liefe die Anwendung mit der Vorlage los. - SetupWriter erhaelt vorhandene Inhalte. Eine appsettings.json fuehrt neben den abgefragten Werten meist Logging und anderes; sie neu zu erzeugen waere bequemer und verloere das - bei einer Neuinstallation ohne Backup. int und bool landen als JSON-Typ, nicht als Zeichenkette. Downloads - scripts/build_installer.ps1 baut selbstenthaltende Einzeldateien fuer win-x64, linux-x64 und linux-arm64 (rund 34 MB, .NET-Laufzeit inbegriffen). Ohne NativeAOT und ohne Trimming: Spectre.Console loest ueber Reflexion auf und braeche sonst erst beim Anwender. - scripts/upload_installer.py laedt sie nach /installer/. Getrennt von deploy.py, das client-dotnet bewusst ausklammert. - Bereich "Installer" auf der UpdateService-Seite mit Groessen, Pruefsummen und den wget-Befehlen; die Angaben stammen aus installer.json statt aus fest eingetragenem Text. - install.sh und install.ps1 laden, pruefen die Pruefsumme und legen ab - sie richten bewusst nichts selbst ein. Das Manifest wird BOM-frei geschrieben, sonst scheitert json_decode() daran. Enthaelt ausserdem die bislang nicht committete Arbeit an den RocketChat-Benachrichtigungen (Migrationen 010 und 011) sowie die Loesch- und Editierfunktion des UpdateService; die betroffenen Dateien liessen sich nicht getrennt stagen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
2388b5abe1 |
feat(updateservice): Plattform-Dimension, signierte Releases, Update mit Rollback
Behebt eine Reihe zusammenhaengender Fehler im Update-Weg, die zusammen verhindert haben, fuer mehr als eine Plattform auszuliefern - und die im Fehlerfall halb aktualisierte Installationen hinterliessen. Server - Migration 009: Spalte platform samt neuem Unique-Key. Zuvor verdraengte das zuletzt veroeffentlichte Paket alle anderen Plattformen derselben Version, weil ON DUPLICATE KEY auf (slug, version, channel) griff. Ein Linux-System zog sich damit das Windows-Paket. - Aufloesungsregel: je Version das plattformgenaue Paket, sonst das plattformunabhaengige. Ein Client ohne Plattformangabe sieht ausschliesslich 'any' - lieber kein Update als das falsche. - manifest_json wird endlich befuellt; die Spalte blieb bisher immer leer, wodurch die API nie der Rueckfall sein konnte, als der sie gedacht war. - Releases werden serverseitig mit RSA-SHA256 signiert, neuer Endpunkt /api/updateservice/v1/pubkey. Bewusst kein HMAC: der Pruefende laeuft auf fremden Systemen und darf den Signierschluessel nicht besitzen. Packager - Bricht ab, statt die Versionshistorie zu verlieren. Schlug das Lesen der bestehenden latest.json fehl, ersetzte ein leeres catch die komplette Historie durch einen einzigen Eintrag - ohne jede Meldung. - Echte Glob-Muster. Zuvor trafen "logs/**" und "scratch/**" aus der mitgelieferten Beispielkonfiguration nie zu. - preservePatterns: Konfigurationsvorlagen werden ausgeliefert, ersetzen am Ziel aber keine vorhandene Datei. Eine settings.json mit Zugangsdaten ueberschrieb bisher beim Update die Konfiguration jedes Zielsystems. - Warnt vor Dateien, die nach Zugangsdaten aussehen und auf keiner Liste stehen. - Prueft --version gegen die Hauptassembly. Eine Abweichung fuehrte zu einer Endlosschleife: Clients aktualisieren, melden weiter die alte Version, halten das Release erneut fuer neu. - --platform mit Ableitung aus dem Publish-Pfad. Agent - Anwenden mit Plan, Backup und vollstaendigem Rollback. Die Stelle war als "Atomic Replace with Backup" kommentiert und war eine Kopierschleife. - Verwaiste Dateien werden entfernt, aber nur solche aus dem Manifest der Vorversion. Was nicht aus einem Release stammt, bleibt liegen. - Das laufende Agent-Binary wird zur Seite gelegt statt ueberschrieben. - API-Rueckfall in FetchManifestAsync; bisher nur im SDK vorhanden, weshalb die Anwendung "Update verfuegbar" und der Agent "kein Release" sagen konnte. - Installierte Version aus --current-version oder manifest.json statt des Textes "Unbekannt", der als 0 gelesen wurde und jede Version neuer erscheinen liess. Reparatur funktioniert damit auch ohne manifest.json. - Setzt das Ausfuehrungsbit fuer Linux-Pakete, die unter Windows gebaut wurden. SDK - ResolveAgentPath() liefert den plattformrichtigen Namen; ein fest verdrahtetes "update-agent.exe" wird unter Linux nie gefunden. - LaunchUpdateAgent uebergibt jetzt --restart (wurde nie uebergeben, die Anwendung blieb nach dem Update zu), --wait-for-pid (kein Wettlauf mehr mit dem Herunterfahren) und --platform. Enthaelt ausserdem die bislang nicht committete Arbeit an Watchdog, Lizenz- Client und cli/tick.php samt Migration 008; die betroffenen Dateien liessen sich nicht getrennt stagen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
a74c6fd990 |
fix(clients, docs): Lizenz-Antwortformat wiederherstellen, Packager absichern
Regression aus dem vorigen Commit - /api/license/v1/validate lieferte die Antwort im neuen status/error-Umschlag. Der Vertrag dieses Endpunkts ist aber bereits ausgerollt: das Feld "status" auf oberster Ebene trägt den Lizenzzustand (valid, revoked, expired ...). LicenseClient las dadurch "success" statt "valid" — jeder ausgelieferte Client hätte seine Lizenz für ungültig gehalten. Die Lizenz-Endpunkte antworten jetzt wieder ohne Umschlag (Http::raw). Gefunden durch Ausführen der projekteigenen Test-Suite gegen den Server. Packager - FTP-Zugangsdaten standen als Standardwerte im Quelltext und zusätzlich in packager.config.json und in der Integrationsanleitung. Alle drei Fundstellen bereinigt; die Konfigurationsdatei ist nicht mehr versioniert. Zugangsdaten kommen aus Datei, Umgebungsvariablen oder CLI-Argument, sonst bricht das Programm mit einer klaren Meldung ab. - Das Veröffentlichen sendet jetzt ein Token (updateservice:publish) und nutzt den Endpunkt /api/updateservice/v1/publish. - Fehler wurden von einem leeren catch verschluckt, und ohne Erfolgsfall wurde gar nichts ausgegeben. Das Werkzeug meldete am Ende immer Erfolg und lieferte Rückgabewert 0, selbst wenn FTP-Upload und API-Aufruf fehlgeschlagen waren. Jetzt ehrliche Meldungen und Rückgabewerte 0/1/2. - packager.config.json wurde vom csproj nie ins Ausgabeverzeichnis kopiert, weshalb sie dort nie gefunden wurde und stets die hartkodierten Werte griffen. UpdateClient - IsVersionNewer entfernte die Vorabkennung, aber kein führendes "v". Damit scheiterte Version.TryParse bei "v1.4.2" und es wurde auf einen alphabetischen Vergleich zurückgefallen, in dem "v1.9.0" als neuer gilt als "v1.10.0" — derselbe Fehler wie zuvor serverseitig im SQL. Ersetzt durch einen vollständigen semantischen Vergleich, verifiziert mit 16 Testfällen. - Der Rückfall auf die API lag in einem catch-Block, aber GetAsync wirft bei einem 404 keine Exception. Fehlte die statische latest.json, brach die Prüfung ab, statt die API zu befragen. Dokumentation - BUGTRACKER_INTEGRATION_GUIDE.md beschrieb denselben Workflow ein zweites Mal und war bereits auseinandergelaufen: Aufrufe ohne Token, alte Pfade, weder Claim/Lease noch Idempotenz. Ersetzt durch einen Verweis auf das gepflegte Agenten-Handbuch samt Übersicht der Änderungen. - UPDATESERVICE_INTEGRATION_GUIDE.md um Token, Umgebungsvariablen und Rückgabewerte ergänzt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
e7fbc85db4 |
fix(security, core): Auth-Pflicht für Ingest-APIs, 500er-Ursachen beheben, Agenten-Workflow
Sicherheit
- install_db.php war ohne Authentifizierung erreichbar und setzte bei jedem
Aufruf das Admin-Passwort auf einen fest im Code stehenden Wert zurück.
Jetzt Auth-Pflicht; ein Konto wird nur bei leerer Benutzertabelle angelegt.
- Stored XSS im Bugtracker-Detail-Modal: Titel, Beschreibung, Fehlermeldung,
Stacktrace und Kommentare gingen ungefiltert durch innerHTML.
- report.php, projects.php und das Veröffentlichen von Releases verlangen jetzt
zwingend ein Token. Publish war zuvor völlig ungeschützt.
- CSRF-Token in allen Formularen, Session-Regenerierung nach Login,
Drosselung fehlgeschlagener Anmeldeversuche.
- Zugangsdaten aus der Versionskontrolle entfernt (Serverdaten.txt,
config.php, .htpasswd, deploy_config.json). Historie enthält sie weiterhin,
Rotation erforderlich (siehe docs/UPGRADE.md).
- Token-Validierung nur noch über SHA-256-Hash; expires_at wird ausgewertet.
Behobene 500er
- Audit::log() war in index.php weder eingebunden noch importiert. Jeder
Klick auf "Aktivierung freigeben" endete in einem Fatal Error.
- Derselbe benannte PDO-Platzhalter mehrfach je Statement (:id in
revokeToken/deleteToken, :q siebenfach in der Volltextsuche). Bei
EMULATE_PREPARES=false ist das nicht zulässig und warf HY093.
- Migration 005 nutzte dynamisches SQL, dessen Semikolons in String-Literalen
vom alten explode(';')-Installer als Statement-Ende gelesen wurden. Sie
schlug still fehl, wodurch push_id/target_agent/tags dauerhaft fehlten.
- Monitor-Umbenennung ohne Transaktion, verschachtelte Transaktionen im
RateLimiter.
Funktionale Korrekturen
- Der Watchdog-Evaluator fehlte vollständig: Monitor-Zustände änderten sich nur
beim Eintreffen eines Heartbeats, ein ausgefallenes System blieb dauerhaft
"up". Erster Lauf auf dem Produktivsystem: 7 von 10 Monitoren waren
tatsächlich seit über einem Tag nicht erreichbar.
- Das Feld "os" fehlte im Monitor-Dialog, wurde aber gespeichert und löschte
damit bei jedem Speichern das Betriebssystem.
- Der Resolve-Dialog existierte im HTML nicht; der Button war funktionslos.
- Versionsvergleich erfolgte lexikografisch, wodurch 1.9.0 als neuer galt
als 1.10.0.
- Schreiboperationen meldeten Erfolg auch für nicht existierende IDs.
- Post/Redirect/Get gegen doppelte Einträge beim Neuladen.
Neue Struktur
- src/bootstrap.php mit PSR-4-Autoloader ersetzt die require-Ketten.
- Core: Config, Http, Csrf, ApiAuth, Logger, Migrator, ErrorReporter.
- Migrator mit zeichenweisem SQL-Parser, dc_migrations und Baseline-Verfahren,
damit bestehende Installationen keine Beispieldaten zurückbekommen.
Agenten-Workflow
- Claim/Lease: Items werden exklusiv übernommen, damit nicht zwei Agenten am
selben Problem arbeiten. action=next holt und reserviert in einem Zug.
- Idempotenz über client_ref, Deduplizierung auch für Feature Requests,
Erkennung von Regressionen, automatische Eskalation des Schweregrads.
- Strukturierter Code-Kontext (repo_url, commit_sha, file_path, line_no).
- Delta-Abfragen über updated_since, Pagination, Bulk-Update.
- Beim Veröffentlichen eines Releases schließen sich Items mit passendem
resolved_in_build selbst.
- Ausgehende Webhooks mit HMAC-Signatur, /api/health, /api/openapi.json.
- Unbehandelte Fehler meldet die Plattform in ihren eigenen Bugtracker.
WebUI
- Serverseitige Filterung mit Pagination statt Rendern aller Datensätze.
- Migrations-Schranke, Evaluator-Warnung, Übersicht aktiver Agenten.
Zeitstempel liegen in der Datenbank durchgängig in UTC und werden für die
Anzeige in die App-Zeitzone umgerechnet.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
fe9f95584e | Refactor UI with purple dark theme glassmorphism, projects management, license editing, agent installer scripts, unmaskable tokens, C# test suite | ||
|
|
3a38fd4837 | Initial commit: Modular Deploymentcenter platform |