Pairing:
- Refresh the paired-devices list after a native PIN pairing (the happy path never
invalidated it, so a newly paired device stayed hidden until remount).
- Moonlight PIN: a 204 means "PIN delivered to the waiting handshake", NOT paired, so
it now reads "PIN sent" instead of a false "Paired successfully".
- Hide the Moonlight pairing card on native-only hosts (HostInfo.gamestream) — it could
never receive a PIN there.
- Per-row pending on unpair/approve/deny; PIN input maxLength 16 (was 8).
Displays / Library:
- "Arrange displays" save refreshes the settings card (it rewrites the policy), without
clobbering unsaved Custom edits (re-seed only when the draft still matches the server).
- Live-display list wrapped in QueryState so errors don't read as "no displays".
- "Forever" keep-alive option in the custom editor; edit-game form round-trips the logo
artwork (was dropped on save); per-card delete pending.
Stats:
- Distinct colour for the native "queue" latency stage (it collided with "capture").
- "Not measured on this path" note on the GameStream health chart; configured-bitrate
target line on throughput; host-authoritative elapsed timer; LiveCard surfaces
non-404 errors.
Shell / auth / i18n:
- SSR-stable locale: first client render matches the base-locale SSR (no hydration
mismatch), then adopts the persisted/browser locale post-hydration.
- BFF proxy maps an upstream (mgmt-token) 401 to 502 so a logged-in user isn't bounced
into a post-login redirect loop.
- Logout checks the POST result before navigating; logs dedup by seq (StrictMode);
login "next" keeps query/hash; Dashboard shows the active-session count.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Web console
- Pairing/Library/Stats refactored into self-contained subsections that each own
their own queries + mutations; a shared slot-based layout (view.tsx) is filled by
the live page (containers) and Storybook (pure cards + fixtures) so the layout can't
drift.
- All paired devices in one list on Pairing with a protocol column (punktfunk/1 +
Moonlight), routing each unpair to the right endpoint; the redundant Clients page is
removed.
- Library: overview grid split from the add/edit form into separate files.
- Login screen links out to the docs.
Docs
- "Console login password" section on every host page (apt/RPM/Bazzite/SteamOS/Windows)
plus a new "Forgot your Password?" troubleshooting page, linked from the login screen.
- Console served as HTTP/1.1 over TLS (drop the unusable HTTP/3 advertising) across the
Bun entry, launchers, systemd units, and packaging.
Tooling
- Biome now respects .gitignore (stops linting generated code), config migrated to
2.5.1; all lint issues fixed cleanly.
Also includes this branch's in-progress host, Apple client, packaging, and CI changes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Marketing/store screenshots of the console, captured from the built Storybook
with headless Chromium (web/tools/screenshots.mjs) — every Pages/* + Shell/*
story rendered at 1440x900@2x. The page stories render from fixtures, so no live
mgmt API, login, or GPU is needed (the web analogue of apple.yml's screenshots
job). Gated to stable release tags in a standalone best-effort workflow; PNGs
upload as a 30-day artifact, not committed.
- Add Stats + Pairing stories (the two pages that lacked them) with stats/pairing
fixtures typed against the generated models.
- Extract a pure PairingView (index.tsx -> view.tsx), matching the
Dashboard/Clients/Stats split, so the page renders host-free from mock state
instead of racing its polling queries. Container wiring is behaviour-identical.
- Playwright driver + a chromium-capable tag-gated job.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>