CluPilotCloud/app
nexxo 34874adec3
tests / pest (push) Failing after 8m6s Details
tests / assets (push) Successful in 21s Details
tests / release (push) Has been skipped Details
Apply a bought plan change instead of only pricing it
PlanChange could say what a move would cost and whether it was allowed, and
that was all it could do. Billing::purchase() wrote an upgrade order and
nothing ever consumed it: same snapshot, same machine, same quota. A customer
could pay for a bigger package and receive nothing.

ApplyPlanChange is now the single place a change lands — it moves the contract
onto the target's current version, writes one register row, settles the custom
domain, and starts a run that resizes the machine. Applying the same order
twice is a no-op, enforced by a unique event key rather than by a check two
callers could both pass.

Two things a plan change must not do, and now does not. A disk is never shrunk
— Proxmox cannot, so the QUOTA shrinks instead, which is what was sold anyway.
And a live machine is never rebooted as a side effect: cores and RAM are
written, and where they need a restart the instance says so where an operator
and the customer can both see it.

The storage allowance also joins the build pipeline. ApplyStorageQuota was
written for plan changes and ran only there, so a brand-new customer still got
no quota at all — quota_gb reached the instance row and stopped, and every
package delivered the whole disk. The test guarding that pipeline only counted
its steps, which is how a list missing the one step that makes a package's
storage real stayed green for its whole life. It now names the step.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 17:18:55 +02:00
..
Actions Apply a bought plan change instead of only pricing it 2026-07-29 17:18:55 +02:00
Console Apply a bought plan change instead of only pricing it 2026-07-29 17:18:55 +02:00
Exceptions Refuse a portal login for an address that already belongs to an operator 2026-07-28 14:42:16 +02:00
Http Merge branch 'feat/plan-reopen' 2026-07-29 16:20:07 +02:00
Jobs Let the export have as many destinations as somebody wants 2026-07-29 02:43:15 +02:00
Listeners Recognise the devices an account signs in from, and warn about a new one 2026-07-28 23:28:34 +02:00
Livewire Apply a bought plan change instead of only pricing it 2026-07-29 17:18:55 +02:00
Mail Give people a way back in, and put the URL in English 2026-07-29 16:50:29 +02:00
Models Apply a bought plan change instead of only pricing it 2026-07-29 17:18:55 +02:00
Notifications Add the SSH identity to the vault, and give deployment config a console page 2026-07-29 00:52:44 +02:00
Observers Apply a bought plan change instead of only pricing it 2026-07-29 17:18:55 +02:00
Policies Move the console's identity out of the customer table 2026-07-28 10:31:43 +02:00
Providers Close the domain page to packages that may not have one 2026-07-29 16:20:21 +02:00
Provisioning Apply a bought plan change instead of only pricing it 2026-07-29 17:18:55 +02:00
Services Apply a bought plan change instead of only pricing it 2026-07-29 17:18:55 +02:00
Support Always name the host we are being served from, and stop promising a duration 2026-07-29 17:10:06 +02:00