# UX packages 4–6 — implementation and release evidence, 2026-10-07 The operator approved implementation, checks and rollout of packages 4–6 after accepting the package-0–3 live push test. In that earlier test, the operator confirmed the notification and replied “Jo funktioniert”; the audit account received it readably and all three test messages showed Displayed. This is one operator-confirmed delivery/reply check, not blanket native-device certification. Sol High retained; no model switch or delegation. ## Slow-start and reconnect follow-up (2026-10-07) The operator clarified that the delay concerned Connecting/Retry. Two session defects were reproduced: a socket closed before opening left the reconnect promise pending and suppressed later attempts; Retry restarted the automatic backoff, which can reach 30 seconds. `3b38c1c` releases the guard on disconnect without letting an older completion clear a newer attempt, and starts a coalesced stream-resume attempt immediately on Retry/network/app wakeups. The baseline test stopped after one failed automatic reconnect; the corrected test makes two failed attempts and then recovers on Retry. Dedicated audit accounts and existing browser identities were reused. An additional shell delay was demonstrated: the old navigation handler waited for bundle/config/manifest/icon caching before returning HTML. A 1.5-second manifest delay held HTML for about 1.6 seconds. With `c7d39e7` and the updated worker explicitly activated, the same candidate fixture returns HTML in 21–54 ms; caching finishes in the background via synchronously registered `waitUntil`. The offline HTML is still replaced only after its dependencies are cached. Delayed-download/storage unit tests verify this ordering and that a failed update retains the previous complete offline shell. Checks: zero svelte-check errors/warnings, 68 passing tests, production build, runner syntax and diff checks. Chromium candidate report `state-chromium-1791408201264/report.json`: offline restart/history/draft, automatic retries and token retention pass; Retry opens a socket in 48 ms and is online in 331 ms. WebKit candidate `state-webkit-1791408238917/report.json`: remembered startup online in 1242 ms, Retry socket in 119 ms and online in 426 ms; zero page errors. These are Linux measurements, not timings from the operator's phone. Blunix `5e9207c` enables gzip only for this chat vhost: the previous live 467 KB JS response was uncompressed even when compression was requested. Release input advances to `3b38c1c` via `a6825e0`. Switch succeeded as **generation 554**, system `/nix/store/a8chqbya79yhnf53vsn0amdrlmci5sw9-nixos-system-blunix-26.11.20260910.8ce4ef6`; nginx root `/nix/store/7pck4q3nhl5cwp742g6cdbq0bhqgkswl-0ff-chat-0.1.0`. Live/store/candidate JS and worker hashes match. HTTPS 200, unchanged CSP, gzip and `Vary: Accept-Encoding` verified: JS transfers 229623 compressed bytes instead of 467547, about half the original transfer. Default gzip level is used. Only nginx restarted; all ten checked platform services remain active and there are zero failed units. Rollback is **553**. Live Chromium `state-chromium-1791408360190/report.json`: remembered startup online in 814 ms; Retry socket in 41 ms and online in 220 ms after two failed attempts; closed-profile offline history/draft recovery passes. Live WebKit `state-webkit-1791408400472/report.json`: remembered startup online in 891 ms; Retry socket in 113 ms and online in 296 ms. Both load the matching HTTPS bundle, retain the FAST token and report zero page errors. The fully offline WebKit/native-iPhone limitations below remain; no personal account or server authentication policy was changed. Original 177 handoff additions in blunix remain unstaged and preserved. Live delayed-manifest probe `load-probe-1791408463910.json`: with a confirmed active updated worker, HTML first byte arrives in 25–82 ms despite the same 1.5-second manifest delay, zero page errors. The probe explicitly updates and awaits worker activation; an immediate navigation can still be controlled by the previous worker while its replacement installs. Existing PWA users should reload, then close and reopen the app to pick up the update. ## Implementation - `75f0875`: account/conversation drafts, revision-conditional clearing, tab notifications, previews and visible-message reading anchors. - `dd9ebfe`: opted-in local account startup, offline history, retry/backoff, reconnect coalescing and credential-rejection handling; candidate runner. - `c0294d6`: participant records, affiliation queries, group/person view and navigation. No server privacy configuration changes. - `6d6b787`: distinct resources keep concurrent tabs connected; login displays the credential-rejection reason. Device identity remains stable. - `55d7d05`: explicit latest-message jumps survive pending refresh/resize; anchor writes tolerate a closing account DB. - `7e3e3aa`: handle transports closing during initial presence and room joins. - `9bb9cd1`: store the offline page only with its referenced bundles cached. - `6806242`: expanded candidate checks and explicit WebKit limitations. ## Candidate verification - `npm run check`: zero errors/warnings. `npm test -- --test-isolation=none`: 65 passing tests (draft account/peer/tab revisions, required anchor page, presence identity/role/nickname/reset, closing transports, distinct affiliation outcomes and complete/failed shell updates, plus prior crypto/status/media tests). `npm run build`: passed. Script syntax and whitespace/diff review passed. - Chromium initial reading probe: 542px before navigation, 543px after. `/tmp/chat-ux-runner/results/direct-pwa-chromium-1791394391830/report.json`. - Chromium package-5 candidate: draft navigation/reload; closed-profile offline startup with real worker/local history/draft; restored connectivity without reload; network failures retain token and retry; last-jid without token shows login; a deliberately invalid token returns to login and hides cached history. All passed, zero page errors: `/tmp/chat-ux-runner/results/state-chromium-1791395243602/report.json`. - Final Chromium: `/tmp/chat-ux-runner/results/state-chromium-1791400348937/report.json`. Every check passed, zero page errors: multiline/independent drafts through list/settings/reload; visible-message key and offset through navigation, reload and pagination; simulated late sizing above the viewport; latest jump; failed send/typing-during-send/tab edit with both tabs connected; closed-profile offline history/draft and recovery without reload; network backoff/token retention/Retry; last-jid-only and invalid-token gates; full group/person checks; empty offline store; logout deletes the local account DB/draft. Reading anchor offset was exactly preserved in the final run. - Final Linux WebKit: `state-webkit-1791400170578/report.json`, with corrected offline-step runner `state-webkit-1791400293209/report.json`, under the same private results directory. Drafts, anchors/pagination/late-size simulation, latest jump, send races/tabs, network Retry, account gates, group/person checks, empty store and logout passed; zero page errors. A Retry click raced with automatic reconnection and is corrected in the runner. - WebKit's **fully offline closed-profile navigation is not tested**: the Linux runtime rejects worker-controlled navigation under `setOffline`, even with cache data. The alternative restarted the same profile with the shell online but XMPP blocked: local history/draft appeared and sending was disabled; unblocking XMPP recovered without reload. The empty-store check uses the same alternative. Do not call this a native iOS offline result. Upstream report: [Playwright #42775](https://github.com/microsoft/playwright/issues/42775). - Group checks use a disposable room: owner/admin/ordinary-member, denied lists distinct from empty, loading/error/retry, absent member, usable disclosed identity versus occupant nickname, private-chat target, message nickname action, actual nickname-change presence, invite/leave and draft restoration. No horizontal overflow at 320/402/874/1280px. Temporary admin affiliation is restored; room destroyed and bookmarks removed. - Cleanup confirmed every recorded temporary room absent, including a leftover from the first failed probe: `/tmp/chat-ux-runner/state-room-cleanup.json`. No new audit devices were deliberately added; stable profiles were reused. ## Proven shell-cache defect Before the worker fix, Chromium's controlled cache contained only the old `index-DLDjjWaX.js`/`index-BL9qAZyP.css`, while its cached HTML referenced the current candidate. Offline JS/CSS requests failed and rendered no app. `state-chromium-1791398778899/report.json` records those cached paths and zero rendered app views; `state-chromium-1791398594769/report.json` records failed current bundle requests. This established the package-5 worker defect rather than extrapolating from WebKit's runtime limitation. Navigation now caches the referenced hashed assets and shell metadata before replacing the offline page; failed bundle download retains the old complete page. Fetch-handler writes are awaited. Push/notification logic and cache namespaces remain unchanged. Worker updates require script-byte changes; a client-only build does not by itself repeat install precaching: [service worker lifecycle](https://web.dev/articles/service-worker-lifecycle). ## Release The final candidate is `assets/index-B__HlxBv.js`, SHA-256 `a1414b26a67fab8cdd8ceecf24b48434e3f8a41f7b7421963f0e4afabc68e12a`. Worker SHA-256: `81833691c4d2f4198daca7aef3c57b92b2a4ac645bdf7d132dfccacfffa7368f`. Client `97b35d6` is pushed to main and pinned by blunix `0b33e06`, pushed on capability-layout. `sudo nixos-rebuild switch --flake .#blunix` succeeded: **generation 553**, system `/nix/store/rfsmizmpsp76cr26kw87nia8py7idsfg-nixos-system-blunix-26.11.20260910.8ce4ef6`. nginx config `/nix/store/8zb3f1m6fq0q3qbrcxs7nhlgs6lwp5rw-nginx.conf`, root `/nix/store/b6jdy7dbw97482sgnc0mjz3f5lvanfz6-0ff-chat-0.1.0`. Live, Nix-store and candidate hashes match for both JS and worker. HTTPS 200 and the existing strict CSP verified. Only nginx restarted; nginx, Prosody, Traefik, LLDAP, Dex, Headscale, Forgejo, GoToSocial, sshd and Tailscale active; zero failed units. Live Chromium `state-chromium-1791400807461/report.json`: matching bundle/CSP, draft navigation, actual closed-profile offline worker/history/draft recovery, and full group/person checks passed, zero page errors. Live WebKit `state-webkit-1791401226266/report.json`: matching HTTPS bundle/CSP, draft navigation and full group/person checks passed, zero page errors. Prior encryption/status/media/worker regressions also passed against this candidate, with zero page errors: `direct-pwa-chromium-1791400531631/report.json`. Delivered→Displayed, retained decrypt errors with no marker for the error, blocked selection/paste/drop with zero slots/PUTs, group file/image and cancellation, and real worker control. Before our bump, this checkout's newer network/calendar commits were already active: `nix eval --raw .#nixosConfigurations.blunix.config.system.build.toplevel` matched the running generation 552 at `/nix/store/0v92cnnw5igmkrq6mpwphnxbf0ggpspm-nixos-system-blunix-26.11.20260910.8ce4ef6`. Use **552** as the rollback generation, preserving that intervening work. Pre-existing 177 added handoff lines remain unstaged/preserved in blunix. Physical iPhone keyboard/safe areas, background/lock and VoiceOver remain operator checks; no blanket native certification. No package 7–9 or personal account/server privacy changes. Profiles, credentials, screenshots and reports remain private under `/tmp/chat-ux-runner`.