Files
pl_mail/docs/install
Paul LütznerandClaude Opus 5 6e9a441333 fix: an install page a demo cannot close, and eleven flashes nobody translated
Two bugs found by using the thing.

**A demo visitor could lock an install out of /install.** InstallGuard closes
that page as soon as a user exists, and demo mode mints one per arrival — so on
a fresh demo instance the first passer-by or crawler took the install page away
with them, permanently, before the operator had made themselves an
administrator. Nothing announced it either: the page 404s, which is exactly
what it does on a correctly installed instance, so the symptom is
indistinguishable from working. Both the guard and createFirstAdmin's
advisory-locked re-check now count real users only.

**Flash messages reached the page as raw translation keys.** The flash bag on
this install holds sentences, not keys — the toast region prints what it finds,
and cannot translate, because most of these interpolate a name or a count only
the controller has. Eleven call sites across TwoFactorController,
SecurityStepHandler and AdminDashboardController pushed keys instead, so a
rejected code produced a red toast reading "two_factor.flash.code_rejected".
The strings existed and had been translated into all three locales months ago;
nothing looked them up. A static test now scans src/ for flash calls passing a
dotted literal, because nothing about that failure is visible in review — the
call site reads exactly like a correct one.

That fix broke two E2E tests, which is the interesting part: they asserted on
"Two-factor authentication is on" and had been matching the panel heading ALONE
because the toast beside it was showing a key. Translating it made both match
and strict mode rightly refused. They were passing because of the bug.

**Demo mode, from running one publicly.** The account form opened in a
turbo-frame, so the guard's redirect had nowhere to land and the modal span
forever — it now renders a panel saying why the form is not coming. The receive
button was a full browser navigation, which reloaded the page on top of mail
Mercure had already delivered AND wiped motion.js's in-memory set of seen rows,
so the whole list replayed its entrance; it is a stream touching only the demo
bar now, and mail simply arrives. Plus an Impressum, because a public demo in
Germany needs one — blank by default and loudly saying so, since § 5 TMG wants
a real operator and a notice naming nobody looks compliant without being so.

**Interface, all reported from use.** The snooze menu's two distant options were
taller than the near ones, because anything past two days carries the date and
"Sat, Aug 29, 08:00" wrapped inside min-w-56. Clicking a dropdown trigger
focused it, and focus shows a tooltip — so opening the user menu painted its own
hint across the menu. The eight recovery codes ran together on one line: they
were joined with real newlines and <code> collapses those without
whitespace-pre-line, so nothing was rendering what was already there. Confirming
a 2FA code gave no sign anything was happening, and the reply carries codes
shown exactly once. Layout was the last <select> on a panel where every other
short choice is a segmented group. Solar and paper put a white field on a warm
off-white surface, which under the boxed layout's translucency left the search
box with no visible edge. Read receipts had a tab of their own coming — the card
holds nothing else, and signatures left the alias tab before it for the same
reasons. And /settings opened on its fourth entry.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 11:03:08 +02:00
..