From 4c8840788e16677030838a1388460e346c88669d Mon Sep 17 00:00:00 2001 From: nexxo Date: Fri, 31 Jul 2026 16:07:45 +0200 Subject: [PATCH] Hand over the three open threads, and what they have in common MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Written so the next session can start without rediscovering anything: where the code stands, the three open pieces in the order they matter, and the two release traps that cost two version numbers today. The second piece is the owner's own point, and it is the right one: a readiness page that flags things only a shell can fix has moved the work rather than done it. Three places do that today — generating the host keypair, syncing the Stripe catalogue, and nothing else. The rest already links where it should. The Stripe sync gets a note about not running it inside a Livewire call: it talks to Stripe and creates products, so it belongs in a queue with a visible result, and the dry run belongs in the interface beside it rather than only in a terminal. Last section names the pattern the whole session kept turning up: a display more confident than what it rests on. A green badge over a red measurement, a claim about somebody's Hetzner account derived from an HTML page, a comment promising a file the installer never created. Worth reading the code with that in mind. Co-Authored-By: Claude Opus 5 --- .../2026-07-31-stand-und-offene-punkte.md | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 docs/handoffs/2026-07-31-stand-und-offene-punkte.md diff --git a/docs/handoffs/2026-07-31-stand-und-offene-punkte.md b/docs/handoffs/2026-07-31-stand-und-offene-punkte.md new file mode 100644 index 0000000..18822be --- /dev/null +++ b/docs/handoffs/2026-07-31-stand-und-offene-punkte.md @@ -0,0 +1,145 @@ +# Stand am 31. Juli 2026 und was offen ist + +Für die nächste Sitzung. Alles unten ist gemessen oder committet, nichts davon +ist Erinnerung. + +## Wo es steht + +`main` auf **v1.3.77**, alle Releases getaggt und gepusht, **2053 Tests grün**. +`feature/host-bootstrap` ist deckungsgleich mit `main`. + +Ausgeliefert in dieser Sitzung: der **Betriebsmodus** (Test-/Livebetrieb mit je +eigenem Platz pro Zugangsdatum, seit v1.3.64 — er lag fertig und ohne Tag +herum), das **Bootstrap-Skript** für die Host-Übernahme, der **Adminbereich** +dafür, der **Datei-Hostname** `files.clupilot.com`, die Seite **Betrieb → +Hostnamen** mit Zertifikatsübersicht, und mehrere Korrekturen an der +Bereitschaftsseite. + +## Offen 1 — Hetzner-DNS-Migration (dringend, blockiert Bestellungen) + +Steht vollständig in **`docs/handoffs/2026-07-31-hetzner-dns-api-migration.md`**: +Endpunkte aus `cloud.spec.json` gezogen, RRSet-Modell, beide Fallen im Namen. + +Kurz: die alte DNS-API ist abgeschaltet (301 auf die Weboberfläche). Der Token +des Betreibers ist bereits ein Cloud-Token und antwortet mit **200** an +`api.hetzner.cloud/v1/zones`. Es fehlt nur der Code — in `DnsTokenCheck` **und** +in `HttpHetznerDnsClient`. Solange das so steht, stirbt jede Bereitstellung in +`ConfigureDnsAndTls`, nachdem der Kunde bezahlt hat. + +**Das zuerst.** Es ist das Einzige auf dieser Liste, das laufendes Geschäft +verhindert. + +## Offen 2 — Die Bereitschaftsseite muss aus sich heraus behebbar sein + +Der Betreiber hat den Punkt gemacht, und er ist richtig: eine Seite, die Dinge +bemängelt, die man nur über eine Shell beheben kann, verschiebt die Arbeit +lediglich. Drei Stellen tun heute genau das. + +### a) Schlüsselpaar für Hosts erzeugen + +`ssh.private_key` liegt im Tresor und muss von Hand hineingelegt werden — es +gibt **keinen Erzeuger**. Heute: + +```bash +ssh-keygen -t ed25519 -N "" -C "clupilot" -f /tmp/clupilot-host +cat /tmp/clupilot-host # privater Teil in die Konsole +shred -u /tmp/clupilot-host /tmp/clupilot-host.pub +``` + +Ein Knopf **„Schlüsselpaar erzeugen"** neben dem Feld wäre klein und klar +begrenzt. `App\Services\Wireguard\Keypair::generate()` macht dasselbe für +WireGuard längst in PHP, mit der Begründung im Kopfkommentar — dort steht auch, +warum nicht in eine Shell ausgelagert wird. Für SSH braucht es ein +Ed25519-Paar; `sodium_crypto_sign_keypair()` liefert es, das OpenSSH-Format ist +die einzige Arbeit daran. + +Ein erzeugter privater Schlüssel darf **nicht** angezeigt werden — er geht +direkt in den Tresor, und angezeigt wird nur der öffentliche Teil. + +### b) Stripe-Katalog aus der Konsole abgleichen + +Der Befehl existiert und funktioniert: + +```bash +docker compose exec -T -u www-data app php artisan stripe:sync-catalogue --dry-run +``` + +Er soll aus der Konsole laufen. **Nicht synchron in einem Livewire-Aufruf**: er +spricht mit Stripe, legt Produkte und Preise an und kann Sekunden bis Minuten +brauchen. Also als Auftrag in die Warteschlange, mit einem Ergebnis, das die +Seite anzeigt — dasselbe Muster wie `UpdateChannel`, nur ohne den Agenten, denn +hier braucht es kein root. + +Der Trockenlauf gehört mit in die Oberfläche: erst zeigen, was entstünde, dann +ein zweiter Knopf. Der Befehl kann das schon, es fehlt nur der Weg dorthin. + +**Achtung:** `SyncStripeCatalogue` verweigert den Dienst, wenn der gespeicherte +Katalog zu einem anderen Konto gehört (Betriebsmodus). Diese Fehlermeldung muss +die Konsole wörtlich zeigen — sie ist eine Warnung vor dem Leeren eines +Katalogs, an dem laufende Verträge hängen. + +### c) Der Rest + +Stripe-Schlüssel, Signaturschlüssel, Firmendaten, Mailtransport: alles Felder, +die **Beheben** schon richtig verlinkt. Da ist nichts zu bauen. + +Beim Mailtransport reicht `mail.default` ungleich `log`/`array` — die +Arbeiterprozesse starten nach dem Speichern von selbst neu, weil sie ihre +Umgebung nur beim Start lesen. + +## Offen 3 — Die Abnahme des Bootstrap-Skripts + +**Von den zehn Aufgaben ist keine einzige auf echter Hardware gelaufen.** Der +Plan (`docs/superpowers/plans/2026-07-30-host-uebernahme-bootstrap-skript.md`) +hat 19 abgehakte und 12 offene Punkte, und alle zwölf sind Hardware-Abnahmen. + +Zwei bestehen ausdrücklich darauf und sind sonst bloße Behauptungen: + +- Die **Selbstrücknahme der Brücke** muss absichtlich ausgelöst werden — eine + Brücke bauen, die die Maschine vom Netz nimmt, und zusehen, wie sie von selbst + zurückkommt. +- Die **Vorlage** muss wirklich geklont, gestartet und mit `occ status` als + `www-data` befragt werden. + +Die Vorbedingungen stehen inzwischen: `files.clupilot.com` liefert das Archiv +aus (404 ohne gültigen Code, gemessen), der Adminbereich zeigt die Zeile, und +`--fqdn` wird mitgegeben. Was fehlt, ist eine dedizierte Maschine mit +`/dev/kvm` im Rettungssystem. + +Was beim ersten Lauf stehenbleibt, gehört ins Runbook +(`docs/runbooks/host-bootstrap.md`) — dessen letzter Abschnitt sagt selbst, dass +er aus dem Skript geschrieben ist und nicht aus Vorfällen. + +## Zwei lose Enden + +- **Die zwei Phantom-Hosts** stehen weiter im Pool. In dieser Sitzung nicht + angefasst. +- **`feature/betriebsmodus`** ist inhaltlich in `main` (über + `feature/host-bootstrap`), der Zweig selbst kann weg. + +## Was diese Sitzung über das Ausliefern gelernt hat + +Steht auch in den Projektnotizen, aber hier, weil es zweimal Geld gekostet hat: + +**Release-Schritte nie mit `&&` verketten.** Mergen, Version setzen, committen, +taggen, pushen — getrennte Aufrufe, mit `git log --oneline -1` dazwischen. In +einer Kette hat ein gescheiterter Merge trotzdem einen Tag am falschen Commit +erzeugt und gepusht. Betraf v1.3.66 und v1.3.69; beide gelöscht, beide Nummern +übersprungen. + +**Vor jedem Release `pwd` UND `git branch --show-current`.** `cd` hält zwischen +Aufrufen nicht. v1.3.68 wurde im Worktree geschnitten und landete auf dem +Feature-Zweig statt auf `main`. + +**Ein falscher Tag wird gelöscht und die Nummer übersprungen**, nie verschoben. + +## Wiederkehrendes Muster in den Funden + +Fast jeder Fehler dieser Sitzung war dieselbe Sorte: **eine Anzeige, die +zuversichtlicher war als ihre Grundlage.** Grünes „Erfüllt" über rotem „nicht in +Ordnung". „In diesem Konto liegt keine Zone", hergeleitet aus einer HTML-Seite. +Ein Kommentar, der behauptete, der Installer lege eine Datei an, die er nie +angelegt hat. + +R19 nennt das beim Namen, und es lohnt sich, beim Lesen dieses Codes danach zu +suchen: **eine Zusage, die keine ist, hält den Nächsten vom Nachsehen ab.**