Commit Graph

4 Commits (daeea1db0e88bacac72a52debe13627f36a9dd3e)

Author SHA1 Message Date
nexxo 19a770e1eb Kuendigung B1, Fix-Welle: der Platz wird frei, und das Loeschen ist vollzogen
K1 — abgebaute Instanzen zaehlten weiter als belegend. `scopeOccupyingHost`
filtert jetzt `torn_down_at`: eine abgebaute Instanz behaelt `ended`, `vmid`
und `disk_gb` als Nachweis, `status != 'failed'` war fuer sie also wahr. Der
Knoten wurde physisch leer und die Buchhaltung blieb voll — die naechste
bezahlte Bestellung derselben Groesse waere geparkt und verworfen worden.

K2 — `deleteVm()` gibt die UPID zurueck, der Abbau wartet den qmdestroy-Auftrag
ab und schreibt `torn_down_at` erst danach. Ein 200 heisst nur, dass Proxmox
den Auftrag angenommen hat; scheitert die Zerstoerung danach, stand bisher eine
laufende Maschine mit einem Datensatz da, der "abgebaut" sagte — und niemand
sah sie je wieder an. Die Attrappe bildet die Asynchronitaet ab
(`destroyedVmids`, `destroyExitStatus`, `destroyHangs`). Die Fristen des
Auftrags wandern mit: Sichern 900 s, Zerstoeren 300 s, Summe unveraendert 1800 s
unter der Uhr des Arbeiters.

K3 — vor `shutdownVm()` steht derselbe `vmStatus()`-Riegel wie im
Nachbarschritt. Eine wegen offener Zahlung gesperrte Cloud und jeder
Wiederholungslauf nach einem Teilfehlschlag treffen einen gestoppten Gast; der
Wurf haette die Instanz unheilbar gemacht und den echten Grund am Datensatz
ueberschrieben. Die Attrappe weist eine Bitte gegen eine stehende Maschine
jetzt ab, und ein Test faehrt erstmals einen zweiten Lauf nach einem
Fehlschlag durch.

W2 — der rote Kasten "Abbau haengt" filtert `status = 'ended'`. Eine
wiederbelebte Instanz waere sonst fuer immer darin stehengeblieben.

Neun Pruefungen im Mahnwesen lassen ihre Cloud jetzt laufen, bevor sie gesperrt
wird — die geschaerfte Attrappe legt offen, dass `SuspendInstance` denselben
fehlenden Riegel hat (Folgepunkt im Bericht).

Zu jedem der vier Punkte eine Zusicherung, die ohne den Fix rot ist; die
Rotproben stehen im Bericht.
2026-08-04 12:39:06 +02:00
nexxo d7d116e9a5 Jede Mail faehrt wieder ueber ihren eigenen Mailer
Mail::to(...) loest den Standard-Mailer auf, und dessen queue() schreibt
danach `$view->mailer($this->name)`. Damit war der im Konstruktor gewaehlte
Mailer (cp_mail_<typ>) durch 'smtp' ersetzt, bevor der Auftrag ueberhaupt
gebaut war.

Mit dem Mailer fiel alles weg, was an ihm haengt: MailboxTransport, die
Postfachsuche samt passendem Absender — und der Notschalter aus
App\Support\MailDelivery, der genau dort sitzt. Eine abgeschaltete Zustellung
schaltete deshalb nichts ab, und die Mails meldeten sich mit den Zugangsdaten
aus der Konfiguration an, waehrend der Absender aus der Mail kam: „553 Sender
address rejected". Das lief hier im Minutentakt.

Zwei Stellen hatten es schon richtig — MaintenanceNotifier und MailPreview,
beide mit der Erklaerung an der Zeile. Neun andere nicht. Alle beginnen jetzt
mit Mail::mailer($mail->mailer), sodass das Ueberschreiben denselben Wert
zurueckschreibt.

Die Attrappen in drei Tests zielten auf to() und trafen damit nicht mehr den
Einstieg; drei von ihnen bestanden ohnehin nur zufaellig, weil ein Aufruf auf
null ebenfalls warf. Sie zielen jetzt auf mailer().

Erzwungen durch tests/Feature/MailDispatchTest.php: Mail::to( ist in app/
verboten, und ein Gegentest haelt das Framework-Verhalten fest, damit die
Regel fallen darf, wenn Laravel sie eines Tages unnoetig macht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 20:36:20 +02:00
nexxo b15fcc53a5 Fix-Runde: Reichweite der Sperre, keine doppelte Gebuehr, verlorene Nachricht 2026-07-31 22:57:56 +02:00
nexxo a64d41639b Mahnwesen: die sechs Kundenmails 2026-07-31 22:31:04 +02:00