# Local PWA checkpoint v0.21.0

The first PWA slice is ready for local fictional-data review. It adds neutral installation metadata and 192/512 icons, a checked cache of five basic files, a connection-unavailable page and deliberate updates that protect unfinished work. It does not enable offline saving or establish phone or production readiness.

## What to expect

Open **App & connection** at the bottom of a page. Use **Check for app update** when wanted. A ready update leaves the page open. **Apply update and reopen this tab** first checks every open app tab. Unsaved edits, in-flight or uncertain requests, running field timers and unresponsive tabs postpone it. Save or deliberately discard edits, resolve the same uncertain save and pause timers before trying again. Other tabs stay open and can be reopened when their work is finished. There is no periodic forced reload.

For small forms without the shared draft hook, a conservative in-memory field check may continue to postpone after a save until the form is closed or its values return to their initial state. No draft is persisted in browser storage. Keep the page open if a save is uncertain; retry that same operation after reconnecting. Closing a page still loses unsaved input and volatile retry information.

A browser install option may be offered. Metadata identifies only the neutral local workspace, with `/workspace` as its ID/start URL and `/` as its scope. No customer, tenant, token, photo or private URL is placed in the metadata. Actual phone installation, standalone use and OS integration remain unverified.

## What was checked

Desktop Chrome used only the public pages at `http://pwa-qa.localhost:8794`, with a separate fresh fictional dataset. A baseline carrying the same source and a different version label updated to the exact final 0.21.0 assets. A corrupt shell failed installation without replacing the usable worker. An unfinished enquiry in another tab blocked the update. A simulated 503 retained the enquiry as uncertain; browser reconnect did not send it. A deliberate retry, delayed by the test harness, saved exactly one enquiry and blocked the update while saving. Once finished, only the requesting tab reopened; the other retained its success page and old app bundle. Reopening that tab removed obsolete app caches while preserving a separate synthetic unrelated cache.

The final cache's five file hashes matched the build. A real shutdown of the QA server produced the neutral fallback without customer details or a success claim. Browser offline emulation separately blocked page API calls; that emulation alone did not establish service-worker network loss. No authenticated PWA browser flow is claimed. The approved v0.20.2 removed-holiday check passed separately; its supplement is preserved alongside the unchanged old release.

181 client tests, including 14 worker/activity tests; 89 structural render cases; 22 selected backend boundary/asset tests; and the build passed. Worker tests cover all non-GET requests, APIs, private/media URLs, query strings, ranges, foreign origins, mismatched/missing shell bytes, denial responses, unknown clients, update deferral and namespace cleanup. The earlier full 694-case backend run is historical, not rerun for this static/PWA slice. The external package proof records an extracted-package restore of the old format-12 browser dataset and a second backup.

## Cache and update boundaries

The build generates an exact path/content-hash/type allowlist: one hashed JavaScript bundle, one hashed stylesheet, two fixed-version neutral icons and a content-addressed neutral offline page. Every install fetch omits credentials, rejects redirects, checks status/type/SHA-256 and validates the whole list before caching. An incomplete install fails. No runtime response grows the cache.

API calls, documents, business photos, authenticated HTML, private previews, portal tokens, mutations and published customer content are never cached. Navigations use the network with no-store; connection failure or 5xx returns only the neutral 503 fallback. Access denials are returned unchanged. Old bundles remain available while any old or unresponsive app tab remains. Cleanup deletes only `shs-local-shell-v1-` caches; unrelated caches are untouched. Browser eviction can remove any cached files; there is no promise of durable offline availability.

Updates do not automatically call skipWaiting or claim clients. A deliberate request asks every same-origin window to prepare, with a short bounded hold on clean pages and new requests. Changed/unresponsive window sets fail closed. Held controls are inert and automatically released on failure/timeout. Only the requesting page may reload, with another unfinished-work check. If work starts or the activation reply is late, the page stays open. In-memory update messages carry protocol flags and asset identity, never field values or request bodies. Existing account/session clearing and retry keys remain in place.

The local server retains no-store private responses and exact same-origin writes; it serves the worker with no-cache and explicit `/` scope. Missing worker/manifest/icon/offline files return 404 rather than app HTML. The only added hostname is fixed `pwa-qa.localhost`; listening remains IPv4 loopback. A port is not a cookie boundary.

## Safe local trial

Preserve the current v0.19 review at localhost:8789. Use a newly extracted copy, fresh data directory, unused loopback port and isolated browser profile/hostname. Do not register this worker on an existing review origin. Follow the existing Python dependency instructions; this ZIP contains built frontend files but no installed runtimes or business data. When changing source, build from `frontend` so the checked worker is regenerated. Before trying older data, use that version's stopped backup procedure and restore into a new folder.

Schema/recovery format remains 12 and backup metadata remains 0.20.0. Dependencies, lockfiles and 207 access policies are unchanged. All 45 capabilities and all 14 original findings stay tracked; none of the original SHS findings is closed by this independent local implementation.

## Remaining work

PWA01 is partial. Durable account-scoped offline queues/field replay, stable durable retry identities, background timing, push, authenticated update journeys, phones/standalone/OS shortcuts, accessibility/device coverage, HTTPS/custom domains and production update/rollback policy remain separate stages. The blocked photo picker was not retried; wider image formats and native dependency/licensing decisions remain. No live SHS, real records, external messages, payments, deployment or DNS were operated.

Source mapping and hashes: [source-map.json](pwa-evidence/source-map.json). Check results and evidence hashes: [pwa-milestone-checks.json](pwa-milestone-checks.json). Lifecycle references consulted: [W3C Service Workers](https://www.w3.org/TR/service-workers/), [MDN skipWaiting](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/skipWaiting), [controller changes](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/controllerchange_event) and [manifest scope](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/scope).
