V1 Web PWA · Walk result

Journey result: Install as PWA

A dated evidence record for V1 Web PWA: observed behavior, current source reconciliation, automation evidence, and explicit proof limits.

verdict: partial· 2026-05-29
8sections5 minread1table

On this page
  • Walked: 2026-05-29 by Claude against commit eff6655269; that pass verified the repaired registration, manifest, prompt surface, and relaunch cookie in the then-current build.
  • Reconciled: 2026-07-18 against the current manifest/service worker, install education, native-prompt boundary, standalone launch, offline/update runtime, failure modes, push routing, and deep browser suites. This was a source reconciliation, not a fresh runtime walk.
  • Verdict: partial — deep automation proves the application-controlled PWA contract from manifest assets and install-prompt handling through standalone relaunch, offline shell/read/write behavior, update coordination, Background Sync, and failure recovery. OS-level installation/uninstall, Safari Add to Home Screen, deterministic storage-quota exhaustion, and real device push permission/delivery remain platform or manual boundaries.
  • Primary specs: pwa-smoke.spec.ts, pwa-install-update-offline.spec.ts, pwa-lifecycle-deepening.spec.ts, and pwa-failure-modes.spec.ts.

Result at a glance#

Evidence lane Current result Authority limit
Installability assets Manifest metadata, icons, screenshots, shortcuts, mobile tags, and JavaScript service worker Browser contract; not store/launcher review
Install prompt and education Captured beforeinstallprompt, accept/dismiss/cooldown/installed states, and Safari manual copy Browser event is simulated; OS install UI is not automated
Standalone launch Signed-in and anonymous cold launch, saved route, iOS/standard detection, and prompt suppression Emulated standalone context, not physical launcher lifecycle
Offline read/write Warm shell, uncached fallback, health/captive-portal guards, local writes, and real Background Sync Named routes/actions; not universal offline parity
Service-worker update Waiting worker, deferral, reading-safe state, refresh apply, multi-tab coordination, and cache purge Harness-controlled worker lifecycle
Failure and push boundaries Registration blocked, stuck apply, reload-loop guard, device registration, and push/click routing Browser/API shims; no real user permission or carrier delivery

Evidence map#

The automated contract reaches the browser/OS boundary and then continues from an emulated standalone launch. It cannot click the launcher or Safari share sheet, so those steps remain dashed rather than inferred.

flowchart LR A[Manifest and service worker] --> B[Browser install eligibility] B --> C[Captured install prompt] C --> D[Accepted or dismissed app state] C -. OS-controlled .-> E[Launcher installation] F[Safari education] -. manual share sheet .-> E E -. emulated boundary .-> G[Standalone cold launch] G --> H[Offline shell and fallback] H --> I[Local writes and Background Sync] G --> J[Waiting-worker update] J --> K[Deferral or coordinated apply] K --> L[Route-preserving reload and cache purge]

Proven observations#

Install and standalone boundary#

  • The document links one manifest; required icons, maskable assets, screenshots, shortcuts, theme/display fields, mobile metadata, and sw.js content type are pinned by the smoke suite.
  • /welcome/download explains Chrome/Edge/Android prompt behavior and Safari's Share → Add to Home Screen path. The shared install trigger consumes the captured beforeinstallprompt event when the browser supplies it.
  • Accept, dismiss, 14-day cooldown, installed state, standard standalone media query, and iOS navigator.standalone branches are covered. Signed-in launch restores the saved route; anonymous launch preserves it through /welcome.

Offline and update runtime#

  • Warm Home, Explore, Activity, and Library routes remain available offline. An uncached deep route receives the real service-worker document fallback and hydrates explicit retry, shell shortcuts, and recent-content states.
  • BFF health failure and captive-portal-shaped HTML keep the offline state honest. A valid health sentinel clears it.
  • Local Library/Nisaba/Tara writes expose their current queued state. A real service-worker Arete queue survives reload, replays through Chromium Background Sync, reaches the live BFF, and drains.
  • Waiting-worker prompts respect unresolved consent, standard versus reading copy, deferral, next-launch reappearance, queued writes, reduced motion, explicit refresh, controller change, multi-tab coordination, route/scroll preservation, and stale-cache purge.

Failure and push seams#

  • A blocked service-worker registration leaves a usable normal-web fallback. Offline and update overlays can coexist, a stuck apply exposes manual reload, and the controller-change guard prevents repeated reload loops.
  • Push-device registration and service-worker push/click routing have focused browser coverage. These tests exercise application and worker handlers, not a physical device's permission UX or external push network.

Boundaries and gaps#

  • A captured prompt is not an OS installation. Playwright can drive the application event handler and accepted state, but it cannot certify launcher icon creation, OS uninstall, app settings, or browser-specific install UI.
  • Safari instructions are not Safari installation evidence. Add to Home Screen is an OS/share-sheet path with no headless beforeinstallprompt.
  • Emulated standalone is not a device matrix. Media-query and navigator.standalone branches prove routing logic, not every Android/iOS/ desktop shell, safe-area, keyboard, orientation, and resume behavior.
  • Named offline paths are not universal offline parity. The suite covers core shell routes, specific cached content, and selected writes. Other dynamic pages, uploads, conflicts, and multi-user data remain online or need their own contracts.
  • Queued is not synchronized. Some domain features preserve local writes without a drain; only the Background Sync action proves replay and removal.
  • Harnessed update state is not every browser race. Real worker install timing, storage eviction, quota pressure, process death, and browser policy can still differ.
  • Push routing is not push delivery. App registration/worker handlers do not prove user permission comprehension, APNs/FCM delivery, OS notification presentation, or production click attribution.
  • Targeted checks replace a score, not product judgment. Lighthouse PWA scoring is intentionally not the release gate, while manual real-device installation remains necessary.

Re-run evidence#

The core application-controlled PWA suite can be run serially with:

bash
PW_BROWSER_CHANNEL=chrome pnpm exec playwright test \
  -c apps/oshun/web/playwright.config.ts \
  apps/oshun/web/e2e/pwa-smoke.spec.ts \
  apps/oshun/web/e2e/pwa-install-update-offline.spec.ts \
  apps/oshun/web/e2e/pwa-lifecycle-deepening.spec.ts \
  apps/oshun/web/e2e/pwa-failure-modes.spec.ts \
  --workers=1

Additional focused offline-write and push suites own their respective deep branches. A green run proves the browser/application PWA contract; it must not be summarized as a completed physical-device install or universal offline and push certification.

Source trail#

Cross-references#

Open questions#

  • What recurring physical-device matrix records Chrome/Edge/Android install, Safari Add to Home Screen, launcher relaunch, safe areas, orientation, update, and uninstall behavior?
  • Which routes and mutation types must join the offline contract, and how will each expose freshness, conflict, retry, and durable replay receipts?
  • How will deterministic quota/eviction testing complement cross-browser manual storage-pressure sessions?
  • Which production push gate covers permission UX, subscription rotation, APNs/FCM delivery, OS presentation, click routing, and revocation?
  • Where should service-worker/update telemetry and versioned cache inventories be retained so real-world failures can be compared with the deterministic harness?