Phase quick-261002-k67 Plan 01: Modul Nextcloud-Status mit Ampel-Kacheln
Neues Modul „Nextcloud-Status“ (Gruppe Infrastruktur): Verwalter tragen Nextcloud-Clouds ihrer Kunden ein, Tessera ruft stündlich <Adresse>/status.php ab, bewertet die Version gegen die Daten von endoflife.date (Ampel grün/gelb/rot/grau) und zeigt je Cloud eine Kachel sowie eine Übersichtskachel auf dem Dashboard.
Was gebaut wurde
Aufgabe 1 (Tracer), Commit 5ef7b0c: Tabelle NextcloudInstance samt Zeilenschutz (Migration 20261002150000, lokal angewendet, migrate status aktuell, Drift-Prüfung Exit 0). Reine Funktion rateNextcloud (alle Regeln aus L-05 einschließlich der Grenzen 90/91 Tage und Support-Ende-Tag gelb, Tag danach rot), normalizeCloudUrl, parseNextcloudStatus, fetchNextcloudStatus (nur GET <Adresse>/status.php, 10 s, 3 Weiterleitungen, 64 KiB, keine Zugangsdaten, nur eigene Fehlerkürzel). NextcloudReleaseService als Zwischenspeicher (12 h, veraltete Daten sofort, Erneuerung im Hintergrund, 15 min Pause nach Fehlschlag, geteilte Anfrage). Dienst, Controller (GET instances, POST instances, POST instances/:id/check), Seed, Modul, RLS-Inventar. Web: Modulseite mit Kacheln (Ampelleiste, Pille mit Klartext, Logo oder Initialen, Version, letzte Prüfung), Registrierungen in Loader, Identität (Wolkensymbol), Seitenleisten-Titel, Layout-Test, Texte de/en.
Aufgabe 2, Commit 6698ef1: Ändern, Entfernen, Logo hochladen/abrufen/entfernen, „Jetzt prüfen“ (POST instances/check, statisch vor allen :id-Routen) und Einzelprüfung, alle mit @ModuleManage('nextcloud-status') und ohne Rollen-Decorator; Logo per Magic Bytes (PNG/JPEG/GIF/WebP, kein SVG, 1 MiB, multer plus Zweitprüfung). Stündlicher Auftrag nextcloud-status-poll (0 * * * *) in onApplicationBootstrap ohne Datenbankzugriff; je Durchlauf ein forSystem-Aufruf (nur id, tenantId), danach jede Cloud an ihren Mandanten gebunden, höchstens vier gleichzeitig, Überlappungsschutz. Web: Sortierung (Kundenname, Status, Version, Support-Ende; je Benutzer in localStorage), Formular (Anlegen/Bearbeiten/Löschen mit Bestätigung/Logo), Verwalten-Knöpfe nur mit useCanManageModule. FORSYSTEM_ALLOWED_CALL_SITES und die Zugriffsklassifikation nachgezogen.
Aufgabe 3, Commit 87a7b7c: Dashboard-Kachel nextcloud-status (geteilte Typliste, Modulzuordnung nextcloud-status → nextcloud-status, Registry, Symbol, Rahmenkopf, Katalog nur mit Modulzugriff): Zähler grün/gelb/rot (und „ohne Bewertung“ nur wenn > 0), darunter rote, dann gelbe Clouds mit Grund; Klick öffnet das Modul, im Bearbeitungsmodus keine Links, ruft nie eine Prüfung auf. CHANGELOG, Anwender- und Administrationsanleitung.
keine Meldungen auf neuen Dateien; die zehn verbleibenden Warnungen der Gesamtläufe stammen aus bestehenden Widget-Dateien (z. B. Stoppuhr) und wurden nicht angefasst
Biome check --write
nur auf neuen Dateien angewendet
Schlüsselabgleich de/en (nextcloudStatus, widgets.nextcloudStatus) und Prüfung auf Mandanten-Wörter
74 Schlüssel je Sprache, deckungsgleich, kein Treffer
Neue Tests: Rating (22), Fetch/Parser/URL (35), Release-Cache (10), Service (18), Controller (11), Scheduler (5), Logo-Regeln (6), module-manage-handlers (+9), Web: Seite (13), CloudForm (9), sort-clouds (8), Widget (8) sowie angepasste Aufzählungstests der Widget-Typen.
Lokaler Stand
Migration lokal angewendet (Container-IP 172.19.0.2), docker compose up -d --build api web gebaut, api healthy, web läuft.
API-Log: „Nextcloud-Status module seeded in registry“, „Nextcloud-Status cron job registered: 0 * * * *“, alle neun Routen gemappt (instances/check vor instances/:id), „No pending migrations to apply“.
Datenbank: Module-Zeile nextcloud-status, Kategorie infrastructure, isSystem true; Tabelle NextcloudInstance vorhanden.
Nicht gepusht. SUMMARY/STATE/PLAN nicht committiert (macht der Orchestrator).
Abweichungen vom Plan
Keine funktionalen Abweichungen. Drei kleine Anmerkungen:
[Hinweis] Zugriffsklassifikation in zwei Schritten: Task 1 trug nextcloud-status.service.ts/nextcloudInstance als gebunden ein (0/4/0), Task 2 stellte es wie geplant auf system-gebunden (0/14/1) um. Die Zahlen stammen aus der Gate-Schleife (grep -cE 'tenantPrisma\.[a-zA-Z]*\.' über die nicht-Spec-Dateien), nicht aus Annahmen.
[Rule 1 - Fehler] Zählerstand im Registry-Test: Die Erwartung counted (44) im bestehenden Registry-Test musste auf 48 steigen (zwölf Typen mal vier Felder); dazu mussten die Aufzählungen aus dem Plan angepasst werden (Katalog-, Registry-, Modulkarten-Tests). Beim ersten Voll-Lauf war zusätzlich widget-module-map.spec.ts noch auf einen Modulbezug eingestellt; im selben Task behoben, danach alle Tests grün.
[Hinweis] Ledger für commits:: Der Ledger-Eintrag wurde erst nach dem ersten Commit angelegt und aus dessen Elternkommit (7188733) gebildet; die Zählung (3) entspricht git rev-list --count 7188733..HEAD.
Bekannte Stubs
Keine.
Bedrohungen (Threat Model)
Alle als mitigate eingestuften Punkte sind umgesetzt und getestet: T-k67-02 (Logo: Magic Bytes, nosniff, Sandbox-CSP, 1 MiB), -03 (@ModuleManage ohne Rollen-Decorator, Metadaten-Specs), -04 (forTenant, where { id, tenantId }, ein einziger forSystem-Aufruf mit select { id, tenantId }), -05 (nur https, referrerPolicy="no-referrer", API ruft die Logo-Adresse nie ab), -06 (Nebenläufigkeit 4, Überlappungsschutz, Zeitlimits), -07 (PUBLIC_SELECT ohne logoData, Spec prüft), -08 (statische Route vor :id, Reihenfolge-Test), -09 (normalizeCloudUrl). T-k67-01 (SSRF auf manuell eingegebene, auch interne Adressen) ist wie geplant akzeptiert und im Code und in der Administrationsanleitung dokumentiert.
Threat Flags
Keine neuen Angriffsflächen außerhalb des Plans.
Für die Browser-Prüfung (Orchestrator)
Als Administrator im Marktplatz „Nextcloud-Status“ aktivieren (falls noch nicht), Freigabe erteilen; die Seite unter /modules/infrastructure/nextcloud-status und /modules/nextcloud-status öffnen (Seitenleiste, Gruppe Infrastruktur).
„Cloud hinzufügen“: eine öffentlich erreichbare Nextcloud eintragen (Kundenname + Adresse, z. B. eine echte Kunden-Cloud). Erwartung: Kachel mit Version, Ampel und Klartext, „Zuletzt geprüft vor …“; Kopfzeile nennt die neueste Nextcloud-Version. Außerdem eine nicht erreichbare Adresse (rot „Nicht erreichbar“) und eine Adresse ohne Nextcloud (rot „Keine gültige Nextcloud-Antwort“) probieren.
Logo: einmal PNG hochladen (Kachel zeigt es), einmal https-Bildadresse, „Logo entfernen“ (Initialen); eine Nicht-Bilddatei und eine Datei über 1 MB (Fehlermeldung im Formular).
Sortierung: alle vier Optionen, danach neu laden (Auswahl bleibt, im Dunkelmodus ebenfalls prüfen).
Verwalten-Stufe: Benutzer nur mit „Benutzen“ anmelden (sieht Kacheln und Sortierung, aber weder „Cloud hinzufügen“, „Jetzt prüfen“, Kachel-Knöpfe noch Bearbeiten), Benutzer mit „Verwalten“ (sieht alles). „Jetzt prüfen“ und Kachel-Prüfung ausprobieren.
Dashboard: im Bearbeitungsmodus „Widget hinzufügen“ → „Nextcloud-Status“ (nur mit Modulzugriff im Katalog). Zähler, rote/gelbe Liste mit Grund, Klick öffnet das Modul; kleine Kachel zeigt nur die Zähler.
Optional: docker compose logs api nach der vollen Stunde — Prüfläufe der Clouds laufen ohne Fehler.
Self-Check: PASSED
Dateien vorhanden: Migration, apps/api/src/nextcloud-status/*, apps/web/src/app/(portal)/modules/nextcloud-status/*, Widget und Tests (alle per Commit nachgewiesen).