CluPilotCloud/lang/en
nexxo 3e7026407b
tests / pest (push) Failing after 8m12s Details
tests / assets (push) Successful in 20s Details
tests / release (push) Has been skipped Details
Stop inventing a package, and rebuild the booking page
Two pages said opposite things about one account, straight after
registering: the dashboard said "noch keine Instanz", and Paket & Addons
said "AKTUELLES PAKET Start — Status Aktiv". The dashboard was right. The
package page fell back to `$instance?->plan ?? 'start'` and rendered that
fallback as a contract the customer had entered into, complete with a status
of Aktiv, on the one page somebody opens to find out what they pay.

The contract is resolved from the CUSTOMER now, not from the instance — a
paid order parked for want of a machine has a subscription and no instance
yet, and asking the instance would tell somebody who has paid that they have
no package. An instance counts as well, whatever its subscription row says.
With neither, the page says so and points at the booking page: an "Upgrade"
from nothing is a purchase, and that has its own page.

The cart stays outside that gate. A customer can have something in it before
they have any contract at all, and hiding it there would hide the thing they
came to pay for — which is what my first version did, and seven existing
tests said so.

And the booking page. Five cards in a four-column grid left the fifth alone
on its own row, reading as a mistake; the consent box sat at the BOTTOM with
every buy button disabled until it was ticked, so the page arrived looking
broken before anybody had done anything wrong; and the price ran across the
card in one block with nothing to compare.

Now the consent comes first, because it is the condition for everything under
it, and it colours itself green once given. Three columns, so five plans read
as 3 + 2. Each card is the same four rows in the same order — price, delivery,
what you get, the button — so the eye can run across a row and compare like
with like. The button stays ENABLED with the reason it will not go through
said under it: a disabled control explains nothing, and the server is the gate
either way.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 14:29:22 +02:00
..
admin.php Say when no mail is being delivered at all 2026-07-30 13:55:55 +02:00
admin_incidents.php Let an incident be deleted, and start measuring whether the hosts answer 2026-07-29 15:16:48 +02:00
admin_settings.php Quote what a person pays, and tab the settings page 2026-07-29 19:18:10 +02:00
auth.php Ask whether they are a consumer, and let one change their mind 2026-07-29 21:06:06 +02:00
backups.php feat(portal): full sidebar — Cloud, Users, Backups, Invoices, Support 2026-07-25 08:08:33 +02:00
billing.php Stop inventing a package, and rebuild the booking page 2026-07-30 14:29:22 +02:00
capacity.php Take the order, park it, and say when it will be delivered 2026-07-29 18:50:46 +02:00
checkout.php Say the same thing to the customer, the register and the bank 2026-07-30 01:30:24 +02:00
cloud.php Restart a machine, enforce the quota that was sold, end a route that ended 2026-07-29 18:28:28 +02:00
coming_soon.php Say EU, and stop promising to fix somebody else's deleted folder 2026-07-29 14:17:30 +02:00
common.php Recover silently from an expired session, and show a connection banner when offline 2026-07-28 21:36:21 +02:00
customer_detail.php Let an operator correct a customer's details 2026-07-29 23:18:46 +02:00
customer_message.php Show the customer, and write the answers once 2026-07-29 22:37:30 +02:00
dashboard.php Let the customer buy it themselves, and tab the integrations page 2026-07-29 19:42:28 +02:00
datacenters.php Let a datacenter code be corrected while nothing depends on it, and say which building 2026-07-28 22:25:21 +02:00
delivery.php Quote what a person pays, and tab the settings page 2026-07-29 19:18:10 +02:00
devices.php Recognise the devices an account signs in from, and warn about a new one 2026-07-28 23:28:34 +02:00
domain.php Serve the custom domain, not just announce it 2026-07-29 16:44:52 +02:00
edit_customer.php Let an operator correct a customer's details 2026-07-29 23:18:46 +02:00
errors.php Refuse a portal login for an address that already belongs to an operator 2026-07-28 14:42:16 +02:00
finance.php Quote what a person pays, and tab the settings page 2026-07-29 19:18:10 +02:00
hosts.php Make host onboarding survive the machine it runs on 2026-07-30 00:54:16 +02:00
impersonate.php feat(admin): impersonate customer portal — session login + return banner 2026-07-25 13:46:48 +02:00
inbox.php Read the mailbox password where it actually is, and let the console test it 2026-07-30 13:12:29 +02:00
instances.php Pin the sidebar header and footer so only the nav list scrolls, and shorten two action labels that wrapped 2026-07-28 20:52:12 +02:00
integrations.php Read the mailbox password where it actually is, and let the console test it 2026-07-30 13:12:29 +02:00
invoice.php Say the same thing to the customer, the register and the bank 2026-07-30 01:30:24 +02:00
invoice_mail.php Send the invoice with the invoice attached 2026-07-29 02:13:41 +02:00
invoices.php Say the same thing to the customer, the register and the bank 2026-07-30 01:30:24 +02:00
invoices_admin.php Write an invoice for work that came off no price list 2026-07-29 20:12:26 +02:00
mail.php Put customer instances on their own domain, and say which domains are ours 2026-07-29 16:03:13 +02:00
mail_log.php Keep a register of what was sent, and answer the customer from here 2026-07-29 21:02:36 +02:00
mail_settings.php Bound the mail test-send and real send to a timeout instead of hanging 2026-07-28 16:36:14 +02:00
maintenance.php Put every mail in one design, and confirm an order when the money arrives 2026-07-29 00:14:04 +02:00
new_invoice.php Write an invoice for work that came off no price list 2026-07-29 20:12:26 +02:00
order.php Stop inventing a package, and rebuild the booking page 2026-07-30 14:29:22 +02:00
orders.php Keep the shop window off the portal's front door 2026-07-29 00:26:22 +02:00
plans.php Paketversionen: Verkauf wieder aufnehmen und saubere Übergabe 2026-07-29 14:58:11 +02:00
provisioning.php Deliver the storage a customer actually buys 2026-07-29 19:13:10 +02:00
reset_password.php Give people a way back in, and put the URL in English 2026-07-29 16:50:29 +02:00
secrets.php Read the support mailbox into the console 2026-07-29 21:41:29 +02:00
security.php Put customer instances on their own domain, and say which domains are ours 2026-07-29 16:03:13 +02:00
sessions.php Show where an account is signed in, and let it sign the other places out 2026-07-28 23:38:17 +02:00
settings.php Stop charging for a service that has ended 2026-07-30 00:52:19 +02:00
status.php Let an incident be deleted, and start measuring whether the hosts answer 2026-07-29 15:16:48 +02:00
support.php Editing in modals, an update button that is not gated on a stale reading, and a support page that is real 2026-07-27 17:55:49 +02:00
templates.php Show the customer, and write the answers once 2026-07-29 22:37:30 +02:00
two_factor_setup.php Let a half-finished two-factor enrolment be cancelled, and rework the setup page 2026-07-28 22:25:27 +02:00
updating.php Stop root workers breaking every page, and let the panel be closed 2026-07-29 15:43:54 +02:00
users.php Replace native confirm() dialogs with the app's own modal pattern 2026-07-28 19:34:27 +02:00
verify_email.php Discard an unconfirmed registration, and sweep the abandoned ones 2026-07-30 14:08:02 +02:00
vpn.php Replace native confirm() dialogs with the app's own modal pattern 2026-07-28 19:34:27 +02:00
withdrawal.php Charge the price the website shows, and hand a withdrawal back in full 2026-07-29 22:42:02 +02:00