Updater-System (OpenNIT-Modell) im isolierten updater/-Ordner

Zieht Quellcode + DB-Migrationen über einen HTTP-Update-Proxy nach.
Vollständig isoliert: eigener Namespace Updater\, eigener Autoloader,
eigene Settings (updater/storage/updater-settings.json), eigenes
Migrations-System (_updater_migrations), eigener AuditLogger.

Komponenten (alle in updater/):
- UpdateManager: Version/.version, Maintenance, Progress, checkForUpdates,
  installUpdate (Staging + PROTECTED_PATHS + Migrationen + opcache + finally)
- MigrationRunner: MySQL-Tracking, string-/kommentar-bewusster SQL-Splitter,
  isIgnorableSqlError, 60s-Lockfile-Cache
- UpdateController + admin/update.php (dünner Entry-Shim), Inline-Admin-UI
  mit Channel-Selector, Update-Check, Progress-Bar, Migrations-Tab
- UpdaterFactory (zentraler Channel-Fallback), AuditLogger (audit_log)
- Templates: maintenance.html, update.php; routes.php (Doku)
- README.md mit vollständiger Rückbau-Anleitung

Einzige Bestandscode-Änderung: 4-Zeilen-Maintenance-Hook in index.php
(markiert mit "// Updater maintenance hook").

Proxy: update.loheide.eu/openvouchertool[-development]
This commit is contained in:
Claude 2026-06-05 18:51:51 +00:00
parent 3483da274f
commit 43149074c9
No known key found for this signature in database
14 changed files with 1374 additions and 0 deletions

88
updater/README.md Normal file
View file

@ -0,0 +1,88 @@
# Updater (OpenVoucherTool)
Auto-Update-System nach dem OpenNIT-Modell: zieht Quellcode + DB-Migrationen
aus einem zentralen Repository über einen HTTP-Update-Proxy nach.
```
[diese App] ←HTTPS→ [Update-Proxy] ←pull→ [Git-Repo]
```
- **Versions-Identität:** 40-stelliger Git-Commit-SHA in `updater/storage/.version`
- **Channels:** `stable``https://update.loheide.eu/openvouchertool`,
`development``https://update.loheide.eu/openvouchertool-development`
- **User-Agent:** `OpenVoucherTool-Updater/1.0`
- **DB-Treiber:** MySQL/MariaDB (Migrations-Tracking-Tabelle `_updater_migrations`)
## Aufruf
Admin-Oberfläche: **`/admin/update.php`** (nur für angemeldete Admins).
| Endpoint | Methode | Zweck |
|---|---|---|
| `admin/update.php` | GET | Admin-UI |
| `admin/update.php?action=check` | GET | Update-Prüfung (JSON) |
| `admin/update.php?action=progress` | GET | Fortschritt (JSON) |
| `admin/update.php?action=migrations` | GET | Migrations-Status (JSON) |
| `admin/update.php` `action=install` | POST | Update installieren (+`csrf_token`) |
| `admin/update.php` `action=set_channel` | POST | Channel wählen (+`csrf_token`) |
> Optional: In der Admin-Navigation (`admin/index.php`) einen Link zu
> `update.php` ergänzen, damit die Seite auffindbar ist. Das ist bewusst
> **nicht** automatisch geschehen (Isolations-Prinzip siehe unten).
## Isolation
Der Updater liegt vollständig in `updater/` (eigener Namespace `Updater\`) plus
zwei dünne, klar markierte Anknüpfungen:
1. **Front-Controller-Hook** in `index.php` (Maintenance-Check, markiert mit
`// Updater maintenance hook`).
2. **Entry-Shim** `admin/update.php` (lädt nur Basis + Bootstrap, delegiert an
den Controller).
Eigene Settings (`updater/storage/updater-settings.json`), eigener Autoloader
(`updater/bootstrap.php`), eigener AuditLogger (schreibt in die vorhandene
`audit_log`-Tabelle), eigenes Migrations-System (`updater/migrations/` +
Tabelle `_updater_migrations`). Es werden **keine** Projekt-Klassen erweitert
`\Database` und `\Auth` werden nur per Injection genutzt.
### Geschützte Pfade (werden bei Updates nie überschrieben)
`config.php`, `.htaccess`, `.env*`, `.git/`, `.gitignore`, `public/uploads/`,
`vendor/`, `composer.lock`, `updater/storage/`.
## Rückbau (restlos entfernen)
1. In `index.php` den Block **„Updater maintenance hook"** (die Zeilen 28,
beginnend mit `$maintenanceFile = …` bis zum schließenden `}`) entfernen.
2. `rm -r updater/`
3. `rm admin/update.php`
4. *(optional)* In der Datenbank: `DROP TABLE _updater_migrations;`
5. *(optional, falls vorhanden)* Laufzeitdateien sind bereits in `updater/`
und damit mit Schritt 2 weg. Nichts liegt außerhalb.
Danach ist keine Spur des Updaters mehr im Bestandscode der Beweis für die
Isolation.
## Smoke-Test
```bash
# 1) Syntax aller Updater-Dateien
php -l updater/UpdateManager.php
php -l updater/MigrationRunner.php
php -l updater/UpdateController.php
php -l updater/UpdaterFactory.php
php -l updater/AuditLogger.php
# 2) Admin-Seite aufrufen (eingeloggt als Admin):
# https://<host>/admin/update.php
# -> "Auf Updates prüfen" klicken. Erwartung: Proxy-Antwort oder klare
# Fehlermeldung (wenn Proxy/Channel nicht erreichbar).
# 3) Maintenance-Mode manuell testen:
touch updater/storage/.maintenance # index.php zeigt jetzt 503-Wartungsseite
rm updater/storage/.maintenance # wieder normal
```
> Hinweis: Ein vollständiger Installations-Durchlauf (`action=install`) setzt
> einen erreichbaren Update-Proxy unter den oben genannten URLs voraus.