CluPilotCloud/app
nexxo 85fcc154b8 Measure availability, and let a customer move down again
Availability is now counted from our own monitoring answers. Uptime Kuma knows
the figure, but the REST bridge in front of it only answers "healthy, yes or
no", and waiting for the bridge to grow an endpoint would have left the panel
without the number indefinitely. The sync already asks on a schedule; counting
the answers gives a percentage that is ours and explainable.

An unanswered check is not a failed one — the counter only moves when a real
answer arrived, so our monitoring going down does not become the customer's
outage on the one figure they are asked to trust. An instance nobody has ever
checked shows no availability rather than 100 %.

The downgrade path existed nowhere. Going down is not the mirror of going up:
it can ask an instance to hold more than the target plan allows. Smaller plans
are now listed even when they cannot be taken, with the obstacle in the
customer's own numbers — "you have 31 users, this package allows 10" — because
a greyed-out button that does not name what is in the way is the thing people
ring about. Storage is checked against the last real reading rather than the
contractual allowance, or anyone who once bought a large plan could never leave
it. The limit is re-checked in the action: a rule enforced only in markup is
not enforced.

And the smaller corrections from this round:

- The cloud tab carried a hardcoded "B" as the instance's initial, and the PHP
  and MariaDB versions, which tell a tenant nothing they can act on.
- "EU — Serverstandort im Angebot festgehalten" under a label already reading
  "Serverstandort" was two sentences saying nothing. It is the country.
- Support promised a reply "binnen 4 Std." with nothing behind it. What is true
  everywhere else is an answer on the same working day.
- The actions column appeared even when no row in the table had an action.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 16:41:15 +02:00
..
Actions fix(billing): hold only what cannot be matched, and let migrations roll back 2026-07-26 13:57:11 +02:00
Console Make the private hostnames look like nothing is there, and close the way past the proxy 2026-07-27 11:26:48 +02:00
Http Let the console keep its recovery hostnames without breaking route caching 2026-07-27 06:20:44 +02:00
Livewire Measure availability, and let a customer move down again 2026-07-27 16:41:15 +02:00
Mail fix(admin): confirm maintenance delivery via MessageSent (retryable until sent); guard resend/cancel on derived state; fix flaky non-unique host wg_ip 2026-07-25 16:14:01 +02:00
Models Measure availability, and let a customer move down again 2026-07-27 16:41:15 +02:00
Notifications fix(engine-b): default-deny firewall, disk-based capacity, synchronous credential mail 2026-07-25 12:39:15 +02:00
Policies fix(vpn): losing the operator roles closes the owner doors by itself 2026-07-25 22:50:13 +02:00
Providers Land a sign-in where it was performed, not always in the customer portal 2026-07-27 06:15:16 +02:00
Provisioning Measure availability, and let a customer move down again 2026-07-27 16:41:15 +02:00
Services Measure availability, and let a customer move down again 2026-07-27 16:41:15 +02:00
Support One definition of the navigation, and the country instead of the building 2026-07-27 16:09:39 +02:00