CluPilotCloud/lang/en
nexxo ab4b0311d4
tests / pest (push) Failing after 11m24s Details
tests / assets (push) Successful in 21s Details
tests / release (push) Has been skipped Details
Copy every invoice to the archive when it is issued, and notice when that fails
The application knows nothing about NFS and should not. It writes to a
directory; whether that is a local disk, a bind mount or a NAS over NFS 4.1
belongs to the mount. No protocol library, the target changes without code
changing with it, and the whole thing is testable against a temp directory.

The finding that shaped it: mkdir -p on a path whose mount is NOT there
succeeds. It creates the empty directory beneath the mountpoint, writes the
invoice onto the container's own disk and reports success — so an unmounted NAS
would quietly collect invoices locally while every check said it worked. An
archive that silently is not the archive is worse than none. The root is
therefore never created, only used: a missing root means a missing mount, and
that is a failure. Only the year subdirectory is created, inside a root already
proven to exist.

Written to a .part and renamed. A rename within one filesystem is atomic, so
whatever watches that folder never sees a truncated PDF and takes it for a
finished invoice. The size is read back afterwards rather than the write being
trusted: over a network mount a short write can report success, and an archive
of truncated files looks exactly like one that worked.

Queued, not done during the request. A network mount can block for its whole
timeout, and an invoice must not fail to be issued because a NAS is rebooting.
Dispatched after the commit, or a worker could look for an invoice that has not
landed yet.

And copy-on-issue is not enough on its own: an invoice issued while the office
connection was down never arrives, the queue eventually gives up, and nobody
opens an archive to check whether last Tuesday is in it. An hourly sweep
re-queues whatever is still missing, the failure is recorded on the invoice
rather than only in a log, and the Finance page says how many are outstanding.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 02:32:08 +02:00
..
admin.php List issued invoices in the console, with no way to change one 2026-07-29 02:21:15 +02:00
admin_settings.php Restart the workers automatically after saving .env, instead of handing the operator back to the shell 2026-07-29 02:26:34 +02:00
auth.php Give the console a front door of its own 2026-07-28 11:45:22 +02:00
backups.php feat(portal): full sidebar — Cloud, Users, Backups, Invoices, Support 2026-07-25 08:08:33 +02:00
billing.php Measure availability, and let a customer move down again 2026-07-27 16:41:15 +02:00
cloud.php Measure availability, and let a customer move down again 2026-07-27 16:41:15 +02:00
coming_soon.php Dress the placeholder page, and record why the obvious VPN fix cannot work 2026-07-27 09:19: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
dashboard.php Stop mailing the initial admin password, hold it in the panel until noted 2026-07-28 23:19:20 +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
devices.php Recognise the devices an account signs in from, and warn about a new one 2026-07-28 23:28:34 +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 Copy every invoice to the archive when it is issued, and notice when that fails 2026-07-29 02:32:08 +02:00
hosts.php Show WireGuard tunnel state per host in the hosts list 2026-07-29 00:10:15 +02:00
impersonate.php feat(admin): impersonate customer portal — session login + return banner 2026-07-25 13:46:48 +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 Restart the workers automatically after saving .env, instead of handing the operator back to the shell 2026-07-29 02:26:34 +02:00
invoice.php Issue an invoice from what somebody bought, and freeze it there 2026-07-29 02:09:05 +02:00
invoice_mail.php Send the invoice with the invoice attached 2026-07-29 02:13:41 +02:00
invoices.php feat(portal): full sidebar — Cloud, Users, Backups, Invoices, Support 2026-07-25 08:08:33 +02:00
invoices_admin.php List issued invoices in the console, with no way to change one 2026-07-29 02:21:15 +02:00
mail.php Recognise the devices an account signs in from, and warn about a new one 2026-07-28 23:28:34 +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
orders.php Keep the shop window off the portal's front door 2026-07-29 00:26:22 +02:00
plans.php Make the console's access list reach the proxy, price in euros, and answer errors 2026-07-27 06:51:05 +02:00
provisioning.php Keep the shop window off the portal's front door 2026-07-29 00:26:22 +02:00
secrets.php Add the SSH identity to the vault, and give deployment config a console page 2026-07-29 00:52:44 +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 Replace native confirm() dialogs with the app's own modal pattern 2026-07-28 19:34:27 +02:00
status.php Make the console's access list reach the proxy, price in euros, and answer errors 2026-07-27 06:51:05 +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
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 feat(ops): update page, automatic 419 recovery, CI workflow 2026-07-26 00:58:27 +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 Require a confirmed address before an account can use anything 2026-07-28 23:43:20 +02:00
vpn.php Replace native confirm() dialogs with the app's own modal pattern 2026-07-28 19:34:27 +02:00