CluPilotCloud/app/Actions
nexxo da11d70037 Der Deckel hielt außerhalb der Transaktion, das Fenster versprach einen Block zu viel
Zwei Befunde der Codex-Durchsicht an derselben Grenze — höchstens drei Blöcke
je Vertrag.

Die Mengenprüfung stand in __invoke(), also außerhalb der Buchungstransaktion,
und für Speicher wurde der Vertrag absichtlich nicht gesperrt. Zwei
Speicher-Bestellungen desselben Vertrags nahe der Grenze lasen damit beide
denselben alten Stand und fügten beide ein; der eindeutige Index über
(order_id, addon_key) greift dabei nicht, weil es zwei verschiedene
Bestellungen sind. Die Prüfung zählt jetzt in book(), unter der Sperre — und
die vorhandene Sperre gilt zusätzlich für gedeckelte Module, statt eine zweite
daneben zu nehmen. Der Idempotenz-Kurzschluss bleibt davor: eine wiederholte
Zustellung derselben Bestellung bekommt ihre Buchung zurück, statt ausgerechnet
am ausgefüllten Deckel zu scheitern (dieselbe Reihenfolge wie bei der
Kapazitätsprüfung).

Und im Bestätigungsfenster machte max(1, min($max, $packs)) aus null buchbaren
Blöcken wieder einen — dieselbe Falle, die in Billing::purchase() schon behoben
war. Bei null buchbaren Blöcken zeigt das Fenster jetzt die Absage in dem Satz,
den der Kunde zu dieser Grenze überall sonst liest, statt einen Kauf
anzubieten, den purchase() danach ablehnt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 18:53:00 +02:00
..
Fortify Passwortrichtlinie einstellbar, doppelte Anmelde-Mail behoben 2026-07-31 20:53:19 +02:00
ApplyPlanChange.php Stop charging VAT to the customers who owe us none 2026-07-30 02:15:41 +02:00
ApplyStorageAllowance.php Fix nine defects in the provisioning pipelines 2026-07-30 01:34:55 +02:00
ApplyStripeBillingEvent.php Mahnwesen: Sperre und Freigabe, zusammen gebaut 2026-07-31 22:19:42 +02:00
BookAddon.php Der Deckel hielt außerhalb der Transaktion, das Fenster versprach einen Block zu viel 2026-08-01 18:53:00 +02:00
EndInstanceService.php Fix nine defects in the provisioning pipelines 2026-07-30 01:34:55 +02:00
GrantAddon.php Decide who may have their own domain, and decide it in one place 2026-07-29 15:59:04 +02:00
GrantSubscription.php Let a subscription or add-on be opened for free, with who and why on the row 2026-07-29 12:41:06 +02:00
IssueStripeInvoice.php Charge the price the website shows, and hand a withdrawal back in full 2026-07-29 22:42:02 +02:00
MoveStripeSubscriptionPrice.php Stop charging VAT to the customers who owe us none 2026-07-30 02:15:41 +02:00
OpenDunningCase.php Zweite Fix-Runde: Regressionen der ersten (Trockenlauf, Doppelmail, Bestand, Isolierung) 2026-07-31 23:02:13 +02:00
OpenSubscription.php Stop charging VAT to the customers who owe us none 2026-07-30 02:15:41 +02:00
ReapplyInstanceAddress.php Fix nine defects in the provisioning pipelines 2026-07-30 01:34:55 +02:00
RecordCommercialEvent.php Stop charging VAT to the customers who owe us none 2026-07-30 02:15:41 +02:00
RestartInstance.php Fix nine defects in the provisioning pipelines 2026-07-30 01:34:55 +02:00
ResumeInstance.php Mahnwesen: Sperre und Freigabe, zusammen gebaut 2026-07-31 22:19:42 +02:00
SettleDunningCase.php Fix-Runde: Reichweite der Sperre, keine doppelte Gebuehr, verlorene Nachricht 2026-07-31 22:57:56 +02:00
StartCustomerProvisioning.php Say the same thing to the customer, the register and the bank 2026-07-30 01:30:24 +02:00
StartHostOnboarding.php Hostnamen vergibt CluPilot: ein Name statt zweier, und der Zaehler ueberlebt das Loeschen 2026-08-01 13:45:43 +02:00
SuspendInstance.php Mahnwesen: Sperre und Freigabe, zusammen gebaut 2026-07-31 22:19:42 +02:00
SyncStripeAddonItems.php Stop charging VAT to the customers who owe us none 2026-07-30 02:15:41 +02:00
VerifyCustomerVatId.php Ask the EU register whether a VAT number is real 2026-07-29 22:42:29 +02:00
WithdrawContract.php Stop charging for a service that has ended 2026-07-30 00:52:19 +02:00