fix(setup): resolve setup state before first paint (VAPP-85) #93
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/VAPP-85-setup-page-flash"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fixes the flash when creating the first admin user. Originally filed as VA-140 against
vervain-agent, which has no password-creation code at all; the screen is this repo'spages/setup.rs.The bug
get_setup_statedecides which of three shells a visitor belongs in (onboarding, sign-in, or the app), so it has to be answered before anything paints. It was fetched withuse_resource, which is client-only: SSR emits the not-yet-resolved arm, the browser hydrates that placeholder, and real content swaps in a round-trip later. Onboarding took that hit twice, from two separate fetches of the same endpoint:Layoutpainted the whole shell (sidebar, topbar, statusbar, dashboard) and only then bounced to/setupfrom ause_effect, so the visitor watched a full app they have no account for get yanked away./setupthen rendered its own "Checking setup…" card before swapping in the password form. That card is centered and auto-height, so the swap moved and resized it.Every other page already uses
use_server_future(...)?; the setup path was the one that did not. It is the same failure mode as VAPP-37 (paint-then-correct), one level up.The fix
A
SetupGateabove the router does the fetch once withuse_server_future, which SSR resolves and serializes into the hydrated page, and publishes it as aSetupResourcecontext.Layoutand the setup page read that resolved value instead of each fetching, so both render final content on the first paint.Layoutalso declines to paint at all for a visitor it is about to redirect, and its session check moves touse_server_futurefor the same reason (has_sessionreads the request cookie viaFullstackContext, which SSR populates).One wrinkle worth flagging for review: the gate is fetched per page load and does not remount on navigation, so registration would leave it reporting a stale
NeedsFirstUserand the shell would bounce the brand-new admin right back to/setup.FirstUserFormrefreshes it before navigating, and holdssubmittingthrough the redirect so the button stays at "Creating…".Verification
Driven against the real server-rendered HTML with a stub
/api/setup, on both branches, so the before-state is reproduced rather than assumed.main)GET /setup, onboarding pendingGET /, onboarding pending/api/setupfetches per loadRegression checks with setup
Complete: a request with a session cookie still gets the shell, one without still gets none, and/setupstill renders the "Setup finished" arm.setup_gate_guard.rsfails the build if either consumer returns touse_resourceor the router leaves the gate, the same waylayout_guardpins VAPP-37, since the regression compiles and still shows the right thing eventually.fmt, wasm and server checks, and 90 unit tests pass. The six
clippy::unnecessary_sort_byerrors inserver_fns/mod.rsare pre-existing: they reproduce on a cleanmainand come from my local toolchain being newer than CI's.Not covered
I have not watched this in a browser. The evidence above is the served HTML, which is where the flash originates, so a load-time flash is addressed. If "flickering" turns out to mean a repeating flicker or one while typing, that is a different bug and this does not fix it.