Commit Graph

5 Commits (feature/host-bootstrap)

Author SHA1 Message Date
nexxo 559a466630 Show that the update is running, and stop showing the rsync log
tests / pest (push) Failing after 12m32s Details
tests / assets (push) Successful in 21s Details
tests / release (push) Has been skipped Details
The maintenance screen answered a question nobody was asking. Under the
headline sat a card with the deployment's raw output in it — rsync
listing every font file it had copied — and, before a step was known, a
box drawn around the words "Wird jetzt gestartet." A person waiting on
this page wants one thing settled: is anything happening, or am I looking
at a dead page.

So: an indeterminate bar, in CSS. Indeterminate because a deployment has
no honest percentage and a bar that claims one always stalls at 90 %; in
CSS because this page is served while the application is down, so it may
not depend on JavaScript having loaded or on the server answering another
request. Motion off gets a steady bar rather than none — the point is to
show the page is alive, and a still bar says that better than a gap.

Shown to everybody, not only in the console: a customer on the 503 is
asking exactly the same question.

What is left of the operator detail is the current step, as one quiet
line, because a run that stops on a step is worth seeing without a shell.
The elapsed time and the log are gone from the overlay entirely — with
them goes a file read on EVERY console page load, running or not. The
settings page still shows the log, where somebody is actually looking for
it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 20:33:02 +02:00
nexxo a4626d2569 Stop root workers breaking every page, and let the panel be closed
tests / pest (push) Failing after 12m38s Details
tests / assets (push) Successful in 26s Details
tests / release (push) Has been skipped Details
── The 500 ─────────────────────────────────────────────────────────────────
"touch(): Utime failed: Operation not permitted", from BladeCompiler, on
every request for the affected view.

Blade compiles a view and then touch()es the compiled file to the source's
mtime. touch() with an explicit time needs ownership of the file. A compose
service without `user:` runs as ROOT — and queue, scheduler and reverb had
none — so the first worker to render a view wrote a root-owned compiled file
that the web process, as www-data, could never refresh again. The queue is
what renders mails, which is why this surfaced now.

queue, reverb and scheduler run as www-data. queue-provisioning stays root
and says why: it brings wg0 up and runs `wg set` for every peer change, which
needs NET_ADMIN on the running process. It renders no mail.

And update.sh normalises ownership at the END of a run as well as at the
start. The first call heals what a previous run left; the second heals what
this one made — `git checkout` rewrites the tree as the service account while
the old build is still serving.

── The panel that would not go away ─────────────────────────────────────────
The same 500 is why it kept coming back: every poll failed, the watcher
treats a failed request as "still restarting" (which it normally is), and the
overlay stayed up over a console nobody could then reach to find out why.

A restart is seconds. After two minutes of nothing the panel now says so and
offers a way out — for an operator only, behind the same flag as the step and
the log, so a customer on the 503 page is not shown a button suggesting they
can call the deployment off. A successful answer clears it again: one bad
minute must not leave a "something is wrong" notice sitting there for the
rest of the run.

Not an always-present close button. The deployment does not stop because
somebody dismissed a panel, and offering that at the wrong moment is a lie.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 15:43:54 +02:00
nexxo 17a6fabcc2 One wordmark, one typeface, and the address the server actually issues
tests / pest (push) Failing after 11m28s Details
tests / assets (push) Successful in 19s Details
tests / release (push) Has been skipped Details
Reported as "logo and font are different everywhere" — maintenance page,
customer panel, console, homepage. They were. Counting them up: the site
header set the name in ink at -0.02em, the sidebar split it into "Clu" plus
an orange "Pilot", the sign-in plate set it white at a third size, the
customer two-factor page set it in MONO with no mark at all, the error pages
and the placeholder each inlined their own — and the maintenance screen had
no wordmark whatsoever. Nine surfaces, seven ideas of the brand.

There is one now: resources/views/components/ui/brand.blade.php. Mark plus
wordmark in one piece, in ink, with an optional muted "Cloud". No orange half
— that made the accent a permanent fixture instead of something used
sparingly. The four places that cannot use a Blade component (the two
self-contained pages, the error layout, the mail layout) inline it and are
held to the same shape by a test.

The typeface. The console loads IBM Plex through Vite; the 503 page has no
stylesheet at all, so the maintenance screen — the one page shown when
somebody is already worried — was rendering in the system sans. It declares
the fonts itself now. And the bold weight was missing from public/fonts
entirely: the placeholder and the error pages both asked for
ibm-plex-sans-latin-700-normal.woff2, which was not there. A @font-face
pointing at nothing fails silently, which is why nobody noticed.

The error pages carried the same two faults the placeholder shipped with: an
empty gradient tile where the mark belongs, and `gap` on an inline-flex row
spacing "Clu", "Pilot" and "Cloud" apart as three separate words.

And the price sheet promised "Adresse auf clupilot.cloud" — a domain the
company does not own — while provisioning was issuing addresses under
whatever CLUPILOT_DNS_ZONE says. It is assembled from that setting now, the
same reason the prices are read from the catalogue rather than typed into the
page.

welcome.blade.php removed: Laravel's leftover, reachable from no route.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 14:30:44 +02:00
nexxo b843c10ec3 Give the update screen the product's colours, and only one window
tests / pest (push) Failing after 8m16s Details
tests / assets (push) Successful in 20s Details
tests / release (push) Has been skipped Details
Two complaints, both correct, both mine.

Dark blue. The panel carried a `prefers-color-scheme: dark` block — the only
one in a product that has no dark mode. On a phone set to dark the update
screen, and nothing else, turned dark blue. A dark mode for one page is not a
dark mode; it is one page that does not match. It is gone.

And even in daylight the panel was not this product's colours: it used
Tailwind's slate ramp (#0f172a, #64748b, #e2e8f0), which is blue-tinted,
against neutrals that are warm. Every value is now a copy of a token from
portal-tokens.css, with the comment saying so, because this file cannot
import them — it renders when the asset build may not exist.

The small window then the big one. The settings card grew its own little
"läuft gerade" block the instant a run started; up to three seconds later the
full-page overlay covered it and said the same thing in a different size. The
card no longer says it at all, and the overlay now opens on the button's own
click — requestUpdate dispatches an event, but only once a run is actually
pending, so a refused second press does not black out the console.

Two more things found while looking:

The panel had `min-height: 100%`, which resolves against the parent's height.
On the 503 page the parent is <body>, whose height is auto — so it computed
to zero, the panel was only as tall as its text, and the bottom two thirds of
the screen stayed the browser's default white. Viewport units now, dvh so a
phone's collapsing address bar leaves no strip either.

And the mark was a plain orange tile again, the same empty-square that was
just fixed on the placeholder. The real logo is inlined.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 14:11:01 +02:00
nexxo 0671e8e119 Show one design while updating, not two swapping mid-run
Reported from live: pressing update showed a blue panel first, which then
vanished and was replaced by a completely different "we are updating"
screen. Both were mine. The console drew its own overlay in the app's light
tokens; a moment later the containers went down and Laravel's 503 page took
over with its own standalone styling. One event, two faces, swapping while
an operator watches.

There is now one panel — resources/views/partials/updating-panel.blade.php —
rendered by both. It carries its own inline CSS and cpu- prefixed class
names because the 503 page is served with the application down: no compiled
stylesheet, no Tailwind, nothing but what is in that file. Dark mode comes
from prefers-color-scheme for the same reason.

The operator detail (step, running since, log tail) rides inside the panel
behind a flag, since the same file is shown to customers on the 503 page.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 10:20:40 +02:00