Storage wizard: Basic-auth popup after restart handover + no language selector #166

Closed
opened 2026-08-09 23:31:59 +00:00 by Cordy · 1 comment
Owner

Found by Nikola in the first live setup-mode walkthrough (#160 acceptance, v0.5.5, Edge on macOS). Two UX faults, one surface:

1. Native browser auth popup interrupts the restart handover. After "storage connected — restarting", the wizard polls /api/setup/storage/status. That endpoint only exists in setup mode; once the process restarts into normal boot, the path falls through to the authenticated API, which answers 401 with a WWW-Authenticate: Basic challenge — and the browser throws its native sign-in dialog over the page mid-flow (confirmed in the pod log: repeated GET /api/setup/storage/status status=401 right after the bootstrap boot). Fix: poll an endpoint that is unauthenticated in normal mode and gated in setup mode — /auth/mode (503 via the setup catch-all before, 200 JSON after) — and hand over to /login rather than /, since / is where the branded-login redirect logic lives for navigations, not fetches.

2. No language selector. The wizard auto-detects from cairn-prefs/navigator.language, but first-run means there are usually no prefs and the browser language may not be the operator's choice. Add a visible EN/DE/FR/IT selector that re-translates live and persists into cairn-prefs.lang so the rest of the first-run flow (and the app after login) inherits it.

Found by Nikola in the first live setup-mode walkthrough (#160 acceptance, v0.5.5, Edge on macOS). Two UX faults, one surface: **1. Native browser auth popup interrupts the restart handover.** After "storage connected — restarting", the wizard polls `/api/setup/storage/status`. That endpoint only exists in setup mode; once the process restarts into normal boot, the path falls through to the authenticated API, which answers **401 with a `WWW-Authenticate: Basic` challenge** — and the browser throws its native sign-in dialog over the page mid-flow (confirmed in the pod log: repeated `GET /api/setup/storage/status status=401` right after the bootstrap boot). Fix: poll an endpoint that is unauthenticated in normal mode and gated in setup mode — `/auth/mode` (503 via the setup catch-all before, 200 JSON after) — and hand over to `/login` rather than `/`, since `/` is where the branded-login redirect logic lives for navigations, not fetches. **2. No language selector.** The wizard auto-detects from `cairn-prefs`/`navigator.language`, but first-run means there are usually no prefs and the browser language may not be the operator's choice. Add a visible EN/DE/FR/IT selector that re-translates live and persists into `cairn-prefs.lang` so the rest of the first-run flow (and the app after login) inherits it.
Author
Owner

Fixed in v0.5.6 (PR #167), image published.

Popup: root cause confirmed in the pod log — after the bootstrap restart, the wizard's poll target /api/setup/storage/status no longer existed and fell through to the authenticated API: 401 with a WWW-Authenticate: Basic challenge, which browsers surface as their native sign-in dialog even for fetch() responses. The poll now targets /auth/mode — swallowed by the setup-mode catch-all (503) before the restart, unauthenticated 200 {"mode":…} after — and hands over to /login, where the branded flow lives. Rule extracted into a code comment: never poll an authenticated endpoint from a pre-auth page; the 401's Basic challenge belongs to WebDAV clients, not browsers.

Language selector: top-right of the wizard card, EN/DE/FR/IT, defaulting to the detected language, re-translating live, and persisting into cairn-prefs.lang so /setup, /login and the app come up in the operator's chosen language rather than the browser's guess.

Retest path: delete the throwaway pod (fresh emptyDir → fresh setup mode on the v0.5.6 image once the manifest is bumped) and run the wizard again — no dialog should appear between "restarting" and the login page.

Fixed in **v0.5.6** (PR #167), image published. **Popup:** root cause confirmed in the pod log — after the bootstrap restart, the wizard's poll target `/api/setup/storage/status` no longer existed and fell through to the authenticated API: `401` with a `WWW-Authenticate: Basic` challenge, which browsers surface as their native sign-in dialog even for `fetch()` responses. The poll now targets `/auth/mode` — swallowed by the setup-mode catch-all (503) before the restart, unauthenticated `200 {"mode":…}` after — and hands over to `/login`, where the branded flow lives. Rule extracted into a code comment: never poll an authenticated endpoint from a pre-auth page; the 401's Basic challenge belongs to WebDAV clients, not browsers. **Language selector:** top-right of the wizard card, EN/DE/FR/IT, defaulting to the detected language, re-translating live, and persisting into `cairn-prefs.lang` so `/setup`, `/login` and the app come up in the operator's chosen language rather than the browser's guess. Retest path: delete the throwaway pod (fresh emptyDir → fresh setup mode on the v0.5.6 image once the manifest is bumped) and run the wizard again — no dialog should appear between "restarting" and the login page.
Cordy closed this issue 2026-08-09 23:39:16 +00:00
Sign in to join this conversation.
No labels
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/Cairn#166
No description provided.