From 96dac236e8e85a9c927df61f16965c71d3fe13bf Mon Sep 17 00:00:00 2001 From: nexxo Date: Mon, 27 Jul 2026 20:18:04 +0200 Subject: [PATCH] Write the handoff, and rescue the approved templates into the repo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The three templates the design was signed off against lived in a session-scoped scratchpad and would have disappeared with the session — the one artefact the whole conversion is measured against. They are in docs/design/ now, with the measurements that were got wrong at least once written down beside them, and a note that the way to check is to render and measure rather than to read the source. That distinction already settled one disagreement: the source said the metric grid used a 20px gap, rendered it is 14px. Co-Authored-By: Claude Opus 5 --- docs/design/README.md | 37 + docs/design/tpl-console.html | 532 +++++++ docs/design/tpl-home.html | 1270 +++++++++++++++++ docs/design/tpl-portal.html | 507 +++++++ .../2026-07-27-portal-design-handoff.md | 163 +++ 5 files changed, 2509 insertions(+) create mode 100644 docs/design/README.md create mode 100644 docs/design/tpl-console.html create mode 100644 docs/design/tpl-home.html create mode 100644 docs/design/tpl-portal.html create mode 100644 docs/handoffs/2026-07-27-portal-design-handoff.md diff --git a/docs/design/README.md b/docs/design/README.md new file mode 100644 index 0000000..fade56c --- /dev/null +++ b/docs/design/README.md @@ -0,0 +1,37 @@ +# Freigegebene Vorlagen + +Diese drei Dateien sind der **abgenommene** Entwurf für Startseite, Kundenportal +und Konsole. Sie sind der Maßstab, gegen den umgesetzt wird — nicht eine +Inspiration. + +Sie lagen ursprünglich in einem sitzungsgebundenen Scratchpad und wären mit der +Sitzung verschwunden. + +## Wie man dagegen prüft + +Nicht im Quelltext lesen — **rendern und messen**. Das hat schon einmal einen +Streit entschieden: eine Quelltext-Prüfung behauptete 20px Rasterabstand, +gerendert sind es 14px. + +```bash +cp docs/design/tpl-portal.html public/__tpl.html # danach wieder löschen +``` + +Dann im Browser beide Seiten mit `getComputedStyle` abmessen und Spalte gegen +Spalte vergleichen. + +## Maße, die schon einmal danebenlagen + +| | Vorlage | +|---|---| +| Rasterabstand | 14px | +| Kartenpolsterung | 18px 20px | +| Kartenradius | 16px | +| Beschriftung | 11.5px, `.07em`, Mono | +| Wert | 25px / 600 / `-.02em` / 9px oben | +| Einheit | 13px / 450 | +| Fußzeile | 12px / 6px oben | +| h1 | 30px / 700 / `-.03em` / 1.12 — unter 900px 23px | +| Badge | 12px / 500, 4px 11px, 7px Abstand → 29px hoch | +| Button | 14px / 600, 0 18px, `min-height` 40px, Radius 10px | +| Spalten | 4 → 2 ab 1100px → 1 ab 560px | diff --git a/docs/design/tpl-console.html b/docs/design/tpl-console.html new file mode 100644 index 0000000..732be3f --- /dev/null +++ b/docs/design/tpl-console.html @@ -0,0 +1,532 @@ +CluPilot — Konsole + +
+
+ + +
+
+ + + Produktion +
+ +
+ BB + Boban +
+
+ +
+
+
+

Betrieb · Stand 27.07.2026, 11:12 CET

+

Übersicht

+
+ Bericht exportieren + + + Host aufnehmen + +
+ +
+
+
MRR
+
+
+

4.317

+

+312 € gegenüber Vormonat

+
+ +
+
+ +
+
Aktive Instanzen
+

23· 1 in Bereitstellung

+
+

22 gesund · 1 mit Hinweis

+
+ +
+
Hosts
+
+
+

4

+

6,2 von 9,0 TB vergeben

+
+
+ + 69% +
+
+
+ +
+
Offene Vorgänge
+

3

+

1 Bereitstellung läuft · 1 Wartung geplant · 1 Zertifikat prüfen

+
+
+ +
+
+
+ Hosts + Alle ansehen +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HostRechenzentrumBelegungStatus
pve-fsn-0110.66.0.11 · 8 InstanzenFalkenstein +
+ 1,6 / 2,25 TB +
Aktiv
pve-fsn-0210.66.0.12 · 7 InstanzenFalkenstein +
+ 1,3 / 2,25 TB +
Aktiv
pve-vie-0110.66.0.21 · 6 InstanzenWien +
+ 1,98 / 2,25 TB +
Knapp
pve-vie-0210.66.0.22 · 2 InstanzenWien +
+ 0,54 / 2,25 TB +
Aktiv
+
+
+ +
+
+
Bereitstellung läuftSchritt 9 / 15
+
+

Ordination Dr. Fux

+

Gestartet 11:04 · Host pve-vie-02

+
+

Zuletzt: Nextcloud installiert · als Nächstes: TLS-Zertifikat anfordern

+ Lauf ansehen +
+
+ +
+
Systemhinweise
+
+
+
PrüfenZertifikat pve-vie-01
in 9 Tagen
+
GeplantWartung Falkenstein
28.07. 21:00
+
AktuellAktualisierung
heute 12:40
+
+
+
+
+
+ +
+ + + Aktualisierung startenLäuft binnen 5 Minuten an + + + + Host aufnehmenProxmox einrichten und verbinden + + + + Wartung ankündigenFenster planen, Kunden informieren + +
+
+
+
+ + diff --git a/docs/design/tpl-home.html b/docs/design/tpl-home.html new file mode 100644 index 0000000..bf22a73 --- /dev/null +++ b/docs/design/tpl-home.html @@ -0,0 +1,1270 @@ +CluPilot Cloud — Betriebene Private Cloud + + + +
+ +
+ +
+ +
+
+
+ Betriebene Private Cloud · Österreich +

Ihre firmeneigene Cloud.
Betrieben, gesichert, belegbar.

+

Eine eigene, isolierte Instanz für Ihr Unternehmen — eingerichtet, täglich gesichert und laufend überwacht. Was wir tun, können Sie nachweisen: mit Protokoll, Prüfbericht und AV-Vertrag.

+ +
+ Serverstandort EU + Einrichtung inklusive + Support Deutsch + Preis pro Firma +
+
+ +
+
+
ihre-kanzlei.clupilot.com
+
+
+
+
Speicher
+
+

235/ 500 GB

47 % belegt

+
+ + 47% +
+
+
+
+
Benutzer
+

8von 25

+
+

3 Gruppen · 2 Gastzugänge

+
+
+
+
NachweiseJuli 2026
+
+ + + + + + +
Sicherung27.07. 03:12 · 18,4 GBGeprüft
Wiederherstellungstest01.07. 02:40 · 14 MinutenBestanden
Sicherheitsupdates24.07. 04:05 · nachtsErledigt
+
+
+
+
+ +
+ Sicherung geprüft + heute, 03:12 + 18,4 GB · verschlüsselt +
+
+ EU-Standort + kein Drittlandtransfer +
+
+
+
+ + +
+
+
0% Verfügbarkeit, letzte 12 Monate
+
0Sicherungen pro Jahr
+
0Wiederherstellungstests pro Jahr
+
0Werktag Antwortzeit auf Ihre Anfrage
+
+
+ + +
+
+
+ Für wen +

Gebaut für Betriebe, die Unterlagen aufbewahren müssen.

+

Kein leerer Baukasten, sondern eine Ablage, die zu Ihrem Fach passt — Ordnerstruktur, Zugriffsrechte und Aufbewahrung nach Branchenvorlage, ab dem ersten Tag.

+
+ +
+
+ +

Steuerberatung

+

Mandantentrennung mit sauberen Rechten, Jahresordner, Belegeingang.

+

Mandanten / Jahresabschluss / Belege

+
+
+ +

Rechtsanwälte

+

Akten pro Verfahren, strikte Vertraulichkeit, nachvollziehbare Zugriffe.

+

Akten / Schriftsätze / Fristen

+
+
+ +

Ärzte & Therapeuten

+

Getrennte Ablage für Verwaltung und Befunde, klar geregelte Rechte.

+

Verwaltung / Befunde / Abrechnung

+
+
+ +

Architektur & Planung

+

Projektordner mit Plandateien, Versionen und Freigaben an Externe.

+

Projekte / Pläne / Freigaben

+
+
+ +

Handwerk & Bau

+

Baustellen mit Fotos vom Handy, Aufmaß und Abnahmeprotokollen.

+

Baustellen / Aufmaß / Abnahme

+
+
+ +

Immobilien & Verwaltung

+

Objekte und Einheiten, Verträge, Abrechnungen, Freigaben an Eigentümer.

+

Objekte / Verträge / Abrechnung

+
+
+
+
+ + +
+
+
+
+ Das Produkt +

Eine Ablage, die aussieht wie Ihre.

+

Ihre Ordnerstruktur, Ihre Rechte, Ihr Logo. Für Ihr Team ist es einfach die Ablage der Firma — die Technik dahinter ist unser Teil.

+
    +
  • Dateien und Ordner mit Freigaben, Versionen und Papierkorb — auf Windows, Mac und am Handy
  • +
  • Texte und Tabellen gemeinsam bearbeiten, ohne dass eine Datei das Haus verlässt
  • +
  • Kalender und Kontakte im Team, synchron mit Outlook und iPhone
  • +
  • Videobesprechung über Ihre eigene Adresse, ohne Konto beim Anbieter
  • +
  • Passwortmanager und Dokumentenarchiv zubuchbar
  • +
+
+ +
+
+
ihre-kanzlei.clupilot.com
+
+ +
+
+
+ Ordnerstruktur steht + nach Branchenvorlage +
+
+
+
+
+ + +
+
+
+ Umstieg +

Sie bestellen. Den Rest machen wir.

+

Nichts zu installieren, nichts vorzubereiten. Wir melden uns bei Ihnen, stimmen jeden Schritt ab — und umgestellt wird erst, wenn Sie es freigegeben haben.

+
+ +
+
+ 1 +

Sie wählen ein Paket

+

Mehr ist von Ihnen nicht nötig. Wir melden uns bei Ihnen.

+ Ihr Schritt +
+
+ 2 +

Wir richten alles ein

+

Sie bekommen Ihre Ablage fertig: Ordner, Zugänge und Rechte stehen, wenn Sie das erste Mal hineinsehen.

+ ohne Ihr Zutun +
+
+ 3 +

Wir übernehmen Ihre Daten

+

Zuerst als Probe, die Sie prüfen. Umgestellt wird nur, was Sie freigegeben haben.

+ nach Absprache +
+
+ 4 +

Wir bleiben dran

+

Einschulung für Ihr Team, danach Sicherung, Updates und Überwachung im laufenden Betrieb.

+ dauerhaft +
+
+ +
+

Was Sie dafür tun müssen: nichts.

+
    +
  • + Keine Installation + Ihr Team öffnet einen Browser. Wer möchte, bekommt zusätzlich die Ordner am eigenen Rechner. +
  • +
  • + Keine Vorarbeit + Sie müssen nichts sortieren, umbenennen oder aufräumen, bevor wir anfangen. +
  • +
  • + Kein Sprung ins Ungewisse + Sie arbeiten im Alten weiter, bis die Probeübernahme geprüft ist und Sie zustimmen. +
  • +
+
+
+
+ + +
+
+
+ Sicherheit & Nachweis +

Sicherheit, die Sie vorlegen können.

+

Jede Maßnahme hat einen Rhythmus und einen Nachweis. Beides bekommen Sie schriftlich — für Ihre Dokumentation, Ihre Prüfung, Ihre Versicherung.

+
+ +
+ + + + + + + + + + +
MaßnahmeRhythmusNachweis
Eigene isolierte InstanzEine virtuelle Maschine je Kunde, strikt getrennt von allen anderen.dauerhaftInstanzkennung im Kundenbereich
Verschlüsselte SicherungClientseitig verschlüsselt, getrennt vom Produktivsystem gelagert.täglichSicherungsprotokoll mit Zeitstempel
WiederherstellungstestEine Sicherung wird tatsächlich zurückgespielt — nicht nur geprüft.monatlichTestbericht mit Ergebnis
SicherheitsupdatesBetriebssystem und Anwendung, eingespielt außerhalb Ihrer Arbeitszeit.laufendWartungsprotokoll
ÜberwachungErreichbarkeit, Speicher und Dienste — Alarm, bevor Sie es merken.rund um die UhrVerfügbarkeitsbericht
Serverstandort EUKein Transfer in Drittländer, keine Abhängigkeit von US-Anbietern.vertraglichAV-Vertrag & TOM-Dokumentation
+
+ +
+
+ 0 +

% Verfügbarkeit, letzte 12 Monate

+
+
+ 0 +

Tage Aufbewahrung der Sicherungen

+
+
+ 0 +

Datenverluste seit Betriebsaufnahme

+
+
+
+
+ + +
+
+
+ Der ehrliche Vergleich +

Warum nicht einfach …?

+

Berechtigte Frage. Hier die Antwort ohne Marketing-Nebel — samt der Fälle, in denen etwas anderes für Sie besser ist.

+
+ +
+
+

… bei der US-Cloud bleiben?

+
    +
  • Bequem und sofort verfügbar
  • +
  • Wenn Ihr Haus stark an Microsoft 365 hängt, ist das oft die bessere Wahl — sagen wir Ihnen im Gespräch auch so
  • +
  • Daten bei US-Konzernen — Drittlandtransfer als Dauerthema Ihrer Dokumentation
  • +
  • Preis pro Kopf: Jeder neue Mitarbeiter erhöht die Rechnung
  • +
  • Support über ein Ticketsystem in Übersee
  • +
+
+ +
+

… einen eigenen Server?

+
    +
  • Maximale physische Kontrolle — wenn jemand im Haus ihn betreiben und absichern kann
  • +
  • Updates, Sicherung und Ausfälle sind Ihr Problem — auch am Wochenende
  • +
  • Braucht dauerhaft echtes IT-Wissen im Haus
  • +
  • Ein vergessenes Update kann sehr teuer werden
  • +
+
+ +
+

CluPilot Cloud

+
    +
  • Eigene isolierte Instanz, Standort EU, AV-Vertrag inklusive
  • +
  • Fixer Firmenpreis, unabhängig von der Kopfzahl
  • +
  • Betrieb, Sicherung und Überwachung nachweislich durch uns
  • +
  • Umgestellt wird erst nach einer geprüften Testübernahme
  • +
  • Einrichtung kostet einmalig — wir richten wirklich ein, statt nur freizuschalten
  • +
+
+
+
+
+ + +
+
+
+ Pakete & Preise +

Ein fixer Preis pro Firma. Nicht pro Kopf.

+

Alle Preise netto pro Monat. Keine Staffelung nach Benutzern, keine Nachverrechnung bei Zuwachs. Einrichtung einmalig.

+
+ +
+
+

Start

+

Einzelkanzlei, kleine Ordination

+
89€ / Monat
+
    +
  • bis 10 Benutzer
  • +
  • 200 GB Speicher
  • +
  • 1 TB Datenvolumen
  • +
+ Start anfragen +
+ +
+ Empfohlen +

Team

+

Der übliche Zuschnitt für ein Büro

+
179€ / Monat
+
    +
  • bis 25 Benutzer
  • +
  • 500 GB Speicher
  • +
  • 3 TB Datenvolumen
  • +
  • Eigene Domain und Logo
  • +
+ Team anfragen +
+ +
+

Business

+

Mehrere Standorte, hoher Durchsatz

+
329€ / Monat
+
    +
  • bis 60 Benutzer
  • +
  • 1,5 TB Speicher
  • +
  • 8 TB Datenvolumen
  • +
  • Erweiterte Leistung
  • +
+ Business anfragen +
+ +
+

Enterprise

+

Verbund, eigene Anforderungen

+
ab 690€ / Monat
+
    +
  • unbegrenzte Benutzer
  • +
  • Speicher nach Bedarf
  • +
  • Dedizierter Host
  • +
  • Eigenes Wartungsfenster
  • +
+ Enterprise anfragen +
+
+ +
+

In jedem Paket enthalten

+
    +
  • Eigene isolierte Instanz
  • +
  • Tägliche verschlüsselte Sicherung
  • +
  • Monatlicher Wiederherstellungstest
  • +
  • Updates und Wartung
  • +
  • Überwachung rund um die Uhr
  • +
  • AV-Vertrag und TOM-Dokumentation
  • +
  • Ordnerstruktur nach Branchenvorlage
  • +
  • Einschulung Ihres Teams
  • +
  • Datenexport jederzeit, offene Formate
  • +
+
+
+
+ + +
+
+
+ Häufige Fragen +

Klare Antworten, bevor Sie fragen müssen.

+
+ +
+
+ Was passiert mit unseren Daten, wenn wir kündigen? +

Sie erhalten vor Vertragsende einen vollständigen Export in offenen Standardformaten. Ihre Cloud basiert auf Open-Source-Software — Sie sind nie eingesperrt. Nach der Übergabe löschen wir Instanz und Sicherungen und bestätigen das schriftlich.

+
+
+ Ersetzt das Microsoft 365? +

Es ersetzt den Dateiteil. Viele Kunden behalten Microsoft für E-Mail und nutzen die Cloud als zentrale, sichere Ablage statt OneDrive oder Dropbox — zum fixen Firmenpreis statt pro Benutzer. Wenn Ihr Haus stark an Microsoft-Werkzeugen hängt, sagen wir Ihnen offen, dass ein Wechsel wenig bringt.

+
+
+ Wie lange dauert die Einrichtung? +

Wir nennen Ihnen im Erstgespräch einen Zeitplan, der zu Ihrem Bestand passt — statt einer Zahl, die davon abhängt, wie viele Daten übernommen werden und wie viele Mitarbeiter eingeschult werden wollen. Was wir zusagen können: Wir melden uns am selben Werktag, wir stimmen jeden Schritt vorher ab, und umgeschaltet wird erst nach einer geprüften Testübernahme mit schriftlichem Protokoll.

+
+
+ Was, wenn jemand versehentlich Dateien löscht? +

Papierkorb und Versionierung fangen den Alltag ab. Darüber hinaus gibt es tägliche Sicherungen mit 30 Tagen Aufbewahrung: Ein Anruf genügt, wir stellen den gewünschten Stand wieder her.

+
+
+ Brauchen wir eigene IT-Kenntnisse? +

Nein. Bedienen kann es jeder, der mit Ordnern und Dateien umgeht — dafür gibt es die Einschulung. Alles Technische übernehmen wir dauerhaft. Wenn Sie einen IT-Betreuer haben, arbeiten wir mit ihm zusammen, statt ihn zu ersetzen.

+
+
+ Mit wem spreche ich bei Fragen? +

Direkt mit uns, per E-Mail oder Telefon, auf Deutsch, mit Antwort am selben Werktag. Kein Callcenter, keine Warteschleife.

+
+
+ Wo genau stehen die Server? +

In Rechenzentren innerhalb der EU. Es findet kein Transfer in Drittländer statt. Den konkreten Standort Ihrer Instanz nennen wir Ihnen vor Vertragsabschluss, halten ihn im AV-Vertrag fest und zeigen ihn dauerhaft in Ihrem Panel an.

+
+
+
+
+ + +
+
+
+

Bei uns hebt jemand ab, der Ihr System kennt.

+

Kein Ticketsystem, kein Callcenter, keine Warteschleife. Wer Ihre Cloud betreibt, beantwortet auch Ihre Frage — auf Deutsch, am selben Werktag. Ein Gespräch, ein Angebot, ein Termin für die Umstellung.

+ + Unverbindlich · kein Vertrieb, kein Callcenter +
+
+
+
+ + + + diff --git a/docs/design/tpl-portal.html b/docs/design/tpl-portal.html new file mode 100644 index 0000000..0d35f7a --- /dev/null +++ b/docs/design/tpl-portal.html @@ -0,0 +1,507 @@ +CluPilot — Kundenpanel + +
+
+ + +
+
+ + +
+ + +
+ SB + Dr. S. Berger +
+
+ +
+
+
+

Betriebsblatt · Stand 27.07.2026, 11:12 CET

+

Ihre Cloud läuft.

+
+ Alle Dienste aktiv + + + Cloud öffnen + +
+ +
+
+
Speicher
+
+
+

235/ 500 GB

+

47 % belegt · +3,4 GB diese Woche

+
+
+ + 47% +
+
+
+ +
+
Benutzer
+

8von 25 Plätzen

+
+

3 Gruppen · 2 Gastzugänge

+
+ +
+
Datenvolumen
+
+
+

412GB / 3 TB

+

setzt sich in 4 Tagen zurück

+
+ +
+
+ +
+
Verfügbarkeit
+
+
+

99,98%

+

letzte 30 Tage · gemessen, CET

+
+ +
+
+
+ +
+
+
+ Nachweise + Alle ansehen +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
ZeitpunktVorgangErgebnis
27.07. 03:12SicherungVerschlüsselt, getrennt gelagert · 18,4 GBGeprüft
01.07. 02:40WiederherstellungstestVollständig zurückgespielt, 14 MinutenBestanden
24.07. 04:05SicherheitsupdatesAußerhalb Ihrer Arbeitszeit eingespieltErledigt
28.07. 21:00Geplante WartungEtwa 20 Minuten, vorab angekündigtGeplant
+
+
+ +
+
+
Nächste Abrechnungmonatlich
+
+
+
Paket Team
179,00 €
+
Modul Vaultwarden
19,00 €
+
Betrag
198,00 €zzgl. USt.
+
Fällig
01.08.2026
+
+ Rechnungen ansehen +
+
+ +
+
Stammblatt
+
+
+
Betriebsform
Eigene isolierte Instanz
+
Serverstandort
DEkein Drittlandtransfer
+
Adresse
kanzlei-berger.clupilot.com
+
+
+
+
+
+ +
+ + + Benutzer hinzufügenZugang für neue Mitarbeiter anlegen + + + + Datei wiederherstellenAus den vorhandenen Sicherungen + + + + Paket erweiternSpeicher, Benutzer oder Datenvolumen + +
+
+
+
+ + diff --git a/docs/handoffs/2026-07-27-portal-design-handoff.md b/docs/handoffs/2026-07-27-portal-design-handoff.md new file mode 100644 index 0000000..bc9d794 --- /dev/null +++ b/docs/handoffs/2026-07-27-portal-design-handoff.md @@ -0,0 +1,163 @@ +# Handoff — CluPilot (Stand 2026-07-27) + +**Für:** frische Claude-Code-Session +**Art:** Zustands-/Fortsetzungs-Handoff +**Zuerst lesen:** dieses Dokument komplett, dann `CLAUDE.md` (R18–R20) und `git log --oneline -15`. +**Vorgänger:** `docs/handoffs/2026-07-25-clupilot-state-handoff.md` (Umgebung, Stack, Befehle, R1–R17 — gilt unverändert weiter). + +--- + +## 0. TL;DR + +Seit dem letzten Handoff: **34 Commits**, Zweig `feat/portal-design` ist in **`main`** gemerged und gepusht. **637 Pest-Tests grün.** + +Inhaltlich waren das drei Blöcke: + +1. **Ein Designsystem für alle drei Oberflächen**, gebaut gegen eine vom Nutzer freigegebene Vorlage — und diesmal **gemessen** statt geglaubt. +2. **Erfundene Daten raus, echte Messreihen rein.** Speicher, Datenvolumen und Verfügbarkeit werden jetzt tatsächlich erhoben; ein Demo-Kunde liegt als echte Datenbankzeilen vor. +3. **Drei gemeldete Fehlerklassen abgestellt und als Regeln festgeschrieben**: Icon-Layout (R18), Zeitzone (R19), Bearbeiten im Modal (R20). + +**Nächster Block:** die zwölf Konsolen-Ansichten auf das Designsystem umstellen, die Support-Anfragen in der Konsole beantwortbar machen, die Startseite ins Blade übertragen. + +--- + +## 1. Was fertig ist + +### 1.1 Designsystem + +- **Ein** Token-Satz in `resources/css/portal-tokens.css` (hell: ground `#f6f6f8`, card `#fff`, line `#e9e9ee`, ink `#17171c`, accent `#f97316`, Radien 9/11/16/22). `admin-tokens.css` trägt **nur noch Dichte** (13.5px Basis, engere Radien), keine eigenen Farben. +- Ein Shell für beide Layouts: `resources/views/components/shell/{head,nav,topbar}.blade.php`. Navigation und Brotkrume kommen aus **einer** Quelle, `app/Support/Navigation.php` — auf Route-Namen gematcht, weil sich der *Pfad* der Konsole zwischen host-gebundenem und Fallback-Modus ändert, ihre Route-Namen aber nicht. +- Komponenten: `ui/metric`, `ui/ring`, `ui/spark`, `ui/button`, `ui/badge`, `ui/icon`, `ui/nav-item`. +- Die Kleinkapitälchen-Beschriftung ist **eine** CSS-Klasse `.lbl` (11.5px, `.07em`). Vorher stand die Zahl an drei Stellen einzeln — so ist sie von der Vorlage weggedriftet. + +**Wie das Angleichen verifiziert wurde** (wichtig, weil es mehrfach schiefging): Vorlage *und* Umsetzung wurden im Browser gerendert und mit `getComputedStyle` **gemessen**, dann Spalte gegen Spalte verglichen. Das hat sofort einen Streit entschieden — eine Prüfung des Vorlagen-*Quelltexts* behauptete 20px Rasterabstand, gerendert sind es 14px. Codex-Urteil zum Schluss: *„Yes. Side by side, a person would call them the same design."*, einzige Abweichung 1px. + +### 1.2 Echte Daten statt Attrappen + +- `instance_metrics` (Migrationen `2026_07_27_150000` + `_160000`): eine Zeile je Instanz und Tag, `disk_used_bytes`/`disk_total_bytes` **nullable**, dazu `rx_bytes`, `tx_bytes`, `checks_total`, `checks_ok`. +- `CollectInstanceTraffic` liest den Plattenstand per Proxmox-`guestExec` (`df`), `SyncMonitoringStatus` zählt Prüfungen nur, wenn eine echte Antwort kam. +- **Regel dahinter:** eine Messung, die nicht genommen werden konnte, ist keine Messung von null. Fehlende Tage bleiben fehlend, eine ungeprüfte Instanz liefert `null` statt 100 %. +- `DemoCustomerSeeder`: ein vollständiger Kunde als echte Zeilen (Instanz, Abo, 6 Plätze über vier Rollen, Backup, Periodenverkehr, 30 Tage Messreihe mit Absicht-Zittern und einem Tag auf 286/288). Entfernen ist **eine** Löschung. Das Passwort kommt aus `DEMO_PASSWORD` oder wird zufällig erzeugt und einmalig ausgegeben — auf einem öffentlich erreichbaren Login liegt kein Passwort im Quelltext. +- Entfernt wurden: erfundene Support-Tickets, Dashboard-Fixtures, der Rechenzentrumsname (nur noch das Land), eine erfundene SLA, ein hartkodiertes „B", Laufzeit-Versionen, die keinen Kunden interessieren. + +### 1.3 Kundenportal + +- Dashboard mit vier Karten (Speicher/Benutzer/Datenvolumen/Verfügbarkeit) auf Vorlagenmaß, Ring 62px, Sparkline aus echter Reihe. +- **Downgrade** über `App\Services\Billing\DowngradeCheck` — geprüft wird gegen **gemessenen** Speicher, nicht gegen das verkaufte Kontingent, und die Blockade wird in den Zahlen des Kunden benannt („Sie haben 31 Benutzer, Start erlaubt 10"). +- Benutzer-Tabelle: Bearbeiten (Modal), Sperren/Entsperren, Entfernen. Aktionsspalte **immer** sichtbar. +- Support-Seite auf echte Daten: `support_requests` (Migration `2026_07_27_180000`), Anfrage-Modal, eigene Historie, FAQ mit Sprungzielen ins Panel. + +### 1.4 Betrieb + +- **VPN** funktioniert (iPhone + Laptop bestätigt). Der Bereitschafts-Test fragte vorher `https://127.0.0.1/`, während das Gateway nur auf `10.66.0.1:443` lauscht — dadurch blieb `VPN_READY` falsch und die App hielt `DNS = 10.66.0.1` zurück. Jetzt eigener Health-Port, 60-s-Fenster. +- **iOS-Zoom** beim Fokussieren abgestellt (`@media (pointer:coarse)` → Felder 16px). Bewusst **nicht** über die Viewport-Sperre, die das Pinch-Zoom mit töten würde. +- Update-Knopf und Update-Beobachter, siehe 2.3. + +### 1.5 Regeln (in `CLAUDE.md`, jeweils per Test erzwungen) + +| Regel | Inhalt | Test | +|---|---|---| +| **R18** | Icon neben dem Text, nie darüber, nie größer als bestellt | `IconLayoutTest` | +| **R19** | Gespeichert in UTC, angezeigt in `app.display_timezone` via `->local()` | `DisplayTimezoneTest` | +| **R20** | Bearbeiten mit Feldern passiert im Modal, nie in der Zeile | `EditInModalTest` | + +--- + +## 2. Was teuer gelernt wurde + +### 2.1 Das Muster hinter den meisten Rückmeldungen + +Ich habe eine Regel gelesen, sie geglaubt und **das gerenderte Ergebnis nicht gemessen**. Jede Runde Kritik („verwendest du die vorlage überhaupt", „das habe ich nun 3 mal geschrieben") hatte dieselbe Ursache. Konkrete Ausprägungen: + +- **CSS-Kaskade dreimal.** Gleiche Spezifität + Reihenfolge entscheidet; ein undefiniertes `var()` rechnet zu `unset` (bei `background-color` transparent); `.open p` schlägt `.tpl`. +- **Namenskollisionen mit Tailwind-Utilities.** Meine Klasse `.ring` kollidierte mit Tailwinds `ring` (`box-shadow: 0 0 0 3px rgb(59 130 246/.5)`) — daher der blaue Rahmen am Chart, den ich einmal fälschlich als Screenshot-Artefakt abtat. Ebenso `.num` gegen die Tabellenziffern-Utility. Umbenannt in `.metric-ring` / `.count`. +- **Eigene Sammeländerungen.** Ein früherer Massenlauf von mir hatte 23 Seitentiteln `sm:text-3xl` (40px) angehängt; die Vorlage hat 30px. + +**Konsequenz für die nächste Session:** bei allem Optischen im Browser messen, nicht im Quelltext lesen. `getComputedStyle` gegen die Vorlage, beide Seiten. + +### 2.2 Tests, die den Fehler mitrechnen + +Die Zeitzonen-Tests prüften nichts, weil sie den erwarteten Wert **mit demselben falschen Aufruf** bildeten wie die Ansicht. Ein Test, der die Implementierung nachrechnet, ist keiner. Sie prüfen jetzt die Wanduhr und zusätzlich, dass die UTC-Zeit *nicht* erscheint. + +### 2.3 Ein Wert ist eine Messung, kein Zustand + +Der Update-Knopf war nur freigeschaltet, wenn die letzte Agent-Prüfung `behind > 0` ergab. Die läuft alle fünf Minuten — nach einem Push behauptet die Konsole minutenlang, alles sei aktuell, und **weigert sich zu handeln**. Jetzt immer anbietbar, solange ein Agent lebt und kein Lauf aktiv ist. + +Und: **das Update startet die Container neu, auf denen das `wire:poll` läuft.** Mitten im Lauf scheitert jede Anfrage, danach befragt altes JavaScript einen neuen Build — deshalb kam die Fertigmeldung nie an. Ein Alpine-Beobachter (`updateWatcher` in `resources/js/app.js`) fragt jetzt `admin.update.state` (schlichtes JSON, kein Livewire), behandelt eine gescheiterte Anfrage als *den Neustart* und lädt neu, sobald der Build wechselt. + +### 2.4 Weitere Fallen + +- Blade-Anonymkomponenten müssen unter `resources/views/components/` liegen. +- Tailwind kann keinen Deckkraft-Modifikator auf ein blankes `var()` anwenden → `color-mix(in srgb, …)`. +- `#[Validate]` an einer Livewire-**Eigenschaft** gilt klassenweit: `$this->validate()` in einer anderen Aktion zieht sie mit. Regeln gehören an die Aktion. +- Carbon führt Makros in **einer globalen Tabelle** — zwei Registrierungen mit verschiedenem Rumpf, und die letzte gewinnt für alle Klassen. +- `Illuminate\Support\Carbon` ist **mutabel**: ohne `copy()` schreibt bloßes Anzeigen das Modellattribut um. +- Laravel gibt bei einer `null`-Übersetzung den **Schlüssel** aus (traf die Fehlerseiten). +- `php artisan view:clear` im Container als falscher Benutzer hinterlässt Rechte, die zu `touch(): Utime failed` führen. Danach `chown -R www-data:www-data storage/framework bootstrap/cache`. + +--- + +## 3. Offene Punkte + +### 3.1 Zwingend als Nächstes + +| # | Punkt | Umfang | +|---|---|---| +| 1 | **Konsolen-Ansichten aufs Designsystem** | 22 Blades unter `resources/views/livewire/admin/`. Sie laufen und sind funktionsfähig, tragen aber noch nicht durchgängig die Vorlagenmaße. | +| 2 | **Support in der Konsole** | Die Anfragen liegen in `support_requests` mit Kunde und Instanz daran, aber es gibt **keine Ansicht, in der man sie beantwortet**. Der Nutzer hat ausdrücklich gesagt, „wer stellt die Anfrage" gehöre in die Konsole und nicht zum Kunden. Fehlt: Warteschlange, Statuswechsel, Antwort + Mail. | +| 3 | **Startseite ins Blade** | Die freigegebene Vorlage liegt in `docs/design/tpl-home.html`; `resources/views/landing.blade.php` ist noch die alte Fassung. | + +### 3.2 Vereinbart, noch nicht gebaut + +- **Integrationen/Secrets erweitern.** Der Nutzer will *alle* Anbindungen dort: Hetzner DNS, Proxmox, Stripe, Monitoring, Backup-Speicher. `SecretVault::REGISTRY` hat vier Einträge. +- **Mehrere Absender:** no-reply, office, support, info, billing. +- **Automatische E-Mail-Vorlagen:** Bestellbestätigung, Störungsmeldung aus dem Dashboard heraus. + +### 3.3 Rollout + +- `main` ist gepusht; der Live-Server (`191.218.161.8`) folgt `main`, aktualisiert wird über **Konsole → Einstellungen → Update anfordern** (VPN-only), *nicht* per SSH. +- Der **Demo-Kunde ist auf live noch nicht angelegt.** Nach dem Update: + ``` + php artisan db:seed --class=DemoCustomerSeeder --force + ``` + Das Passwort wird einmalig ausgegeben. Entfernen: `User::where('email','demo@clupilot.com')->first()?->delete()`. +- SSH zum Live-Server und `pip install` sind in dieser Umgebung vom Berechtigungsfilter **blockiert**. Nicht umgehen — den Nutzer bitten oder ihn den Deploy auslösen lassen. + +### 3.4 Zwei Dinge, die eine Entscheidung brauchen + +1. **Badge gegen Button in der Kopfzeile.** Der Nutzer hatte beanstandet, dass der Button größer ist als das Badge. In der freigegebenen Vorlage sind sie *tatsächlich* verschieden hoch (29px gegen 40px, mittig zueinander). Ich bin der Vorlage gefolgt, weil „genauso erstellen" die deutlichere Ansage war. Angleichen wäre eine bewusste Abweichung — seine Entscheidung. +2. **Bestehende Wartungsfenster sind verschoben gespeichert.** Sie wurden über das alte Formular erfasst, das UTC hineinschrieb und UTC zurücklas. Die Anzeige ist ab R19 korrekt und zeigt ehrlich, was gespeichert wurde — wer damals 21:00 *meinte*, hat 23:00 in der Datenbank. Auf dev sichtbar: + ``` + test | gespeichert 28.07. 21:00 UTC | zeigt jetzt 28.07. 23:00 + ``` + **Bewusst nicht automatisch umgerechnet:** von außen ist nicht unterscheidbar, welches Fenster als Ortszeit gemeint war und welches absichtlich in UTC gesetzt wurde. Muss durchgesehen werden. + +--- + +## 4. Verifikations-Workflow (unverändert gültig) + +1. `docker compose exec -T app php artisan test` — muss vollständig grün sein. +2. `docker compose exec -T app npm run build`. +3. **Im Browser ansehen und messen**, bei Optischem gegen die Vorlage (siehe 2.1). Konsolenfehler: 0. +4. Codex-Review (**R15**) — Ablauf steht in der Nutzer-Memory `clupilot-r15-codex-review`. Kurz: `export PATH="$HOME/.local/bin:$PATH"`, dann `codex exec …`; im Hintergrund laufen lassen, der Aufruf überschreitet zwei Minuten. +5. Commit, Push auf `main`. + +--- + +## 5. Wichtige Dateien + +| Zweck | Pfad | +|---|---| +| Regeln R18–R20 | `CLAUDE.md` | +| Farben/Maße | `resources/css/portal-tokens.css` | +| Dichte Konsole | `resources/css/admin-tokens.css` | +| Navigation (eine Quelle) | `app/Support/Navigation.php` | +| Zeitzone: Anzeige | Makro `->local()` in `app/Providers/AppServiceProvider.php` | +| Zeitzone: Formularfelder | `app/Support/LocalTime.php` | +| Downgrade-Prüfung | `app/Services/Billing/DowngradeCheck.php` | +| Messreihen | `app/Models/InstanceMetric.php`, `app/Provisioning/Jobs/CollectInstanceTraffic.php` | +| Update-Kanal | `app/Services/Deployment/UpdateChannel.php`, `deploy/update-agent.sh` | +| Demo-Kunde | `database/seeders/DemoCustomerSeeder.php` | +| Vorlagen (freigegeben) | `docs/design/tpl-{home,portal,console}.html` + `docs/design/README.md` | + +> Die Vorlagen lagen ursprünglich im sitzungsgebundenen Scratchpad und sind jetzt im Repo. `docs/design/README.md` hält fest, **wie** man dagegen prüft (rendern und messen, nicht Quelltext lesen) und listet die Maße, die schon einmal danebenlagen.