Files
Sybil-2/docs/mobile-web-qa.md
T

8.0 KiB
Raw Blame History

Mobile web QA — 2026-11-02

This change is limited to the web client and its tests/documentation, with no backend contract or native app release changes. This report records the focused mobile QA and remaining device verification limits.

Reproduction and fixes

The production bundle was exercised with local API/socket fixtures in touch-enabled Chromium at 390×844. Before/after measurements use identical messages and viewport dimensions.

Area Before After
Installed display Manifest preferred fullscreen, including display_override standalone, no fullscreen override; normal Apple status-bar style
Horizontal table pan touch-action: pan-y on the workspace; table stayed at scrollLeft=0, swipe created a new chat Native table scrolled to scrollLeft=160, current chat retained
Regular assistant width 304.30px of a 358px transcript at 390px viewport 358px; desktop width rule retained
Agent message width 287.52px 287.52px; bubble/avatar styling retained
Compact model Hidden Provider and active model beneath title; updates after changing model in settings
Context menu Assistant context-menu event canceled for a Fork-only menu Native event allowed for text, links and composer; explicit message-actions button opens Fork
Zoom Viewport disabled user scaling Fixed-scale viewport retained (maximum-scale=1.0, user-scalable=no)
Notification failures Browser exception names and server statuses replaced by a generic error; background refresh erased errors Stage-specific, redacted recovery guidance, retained until explicit retry/refresh

Text owns gestures across regular chat, search markdown and Agent. Dynamic horizontal scrollers and code/table/quote elements are protected even at both ends. Selections, multi-touch, long-press starts and touch cancellation abandon navigation tracking. Blank workspace chrome still supports sidebar/new-chat swipes. Notification help is bounded and scrollable; sidebar content remains reachable on shorter screens.

Notification diagnosis and official sources

A read-only authenticated request to the running server's GET /v1/agent/push/config returned HTTP 200 with enabled=true, webPushAvailable=true, a known source, quarantined=false, and a public key present. Credentials/key values were not printed. This rules out disabled transport configuration at the time of inspection; it does not prove delivery or identify the actual phone's failed step.

Chromium's Android GCM driver uses GoogleCloudMessagingV2, which checks for com.google.android.gms and rejects registration when Google Play services is absent. Vanadium is GrapheneOS's Chromium browser, as documented in the official browsing guide. Missing/unreachable Play services is therefore a plausible cause on GrapheneOS; the old generic message cannot establish that cause.

The official sandboxed Google Play guide requires dependent apps and Play in the same profile and recommends a battery optimization exception for background push. Check network access, Sybil's site notification permission and Vanadium's Android notification permission, then reload and explicitly enable again. Users choosing not to install Play need a browser with an independent push service. Sybil cannot replace that browser service or inspect installed Android packages, so it does not disable Vanadium based on user-agent detection.

Permission and subscription are separate: PushManager.subscribe() can fail after permission was granted. Diagnostics identify the failed layer and known exception name without echoing arbitrary browser/provider messages. No permissions are requested in the background; opt-in still requests permission synchronously from the user's click. Registration failures retain rollback and revocation behavior, including storage failure after browser subscription.

standalone can retain the device status bar, unlike fullscreen (manifest display reference). Existing installations may retain older manifest metadata until their browser updates it. Chrome documents manifest update scheduling; Vanadium installation/update behavior still needs device verification. The manifest URL, app ID, start URL and service-worker scope remain stable.

Automated verification

  • npm run build and npm test in web.
  • mobile-workspace.browser.mjs: trusted CDP touch pans on tables, nested quotation code and code blocks; both scroll edges; selection/clipboard copy and text paste; uncanceled context-menu events; explicit Fork menu; synthetic multi-touch/long-press/cancel scenarios; both navigation directions; model change; widths 320, 390, 430 and 767; 1280px desktop check; 450px-height composer checks; unchanged Agent width; manifest and zoom settings. Screenshots were inspected.
  • agent-push-errors.browser.mjs: mobile permission dismissal/denial, worker failure, AbortError, NotAllowedError, NotSupportedError, InvalidStateError, subscription timeout, HTTP 400/401/403/409/429/503, rollback, preserved error after background refresh, successful retry, missing APIs/insecure context, iOS Home Screen guidance, and reachable notification controls at 320×568 and 390×450. API/push-provider outcomes are mocked; worker registration is real except the deliberate failure case.
  • Existing agent-push.browser.mjs: real worker activation/notification display/IndexedDB and read-close, explicit consent, source changes, multiple sessions, credential rotation, revocation and offline logout with mocked push provider/backend.
  • Existing pwa.browser.mjs: production service-worker activation/reload and authentication flows.

Run browser checks after building, using an existing Playwright/Chromium installation. These fixtures intentionally reject non-loopback targets and mock backend/provider traffic.

cd web
npm run build
npm test
npm run preview -- --host 127.0.0.1 --port 5197 --strictPort

In another shell, with PLAYWRIGHT_MODULE=/absolute/path/to/playwright-core/index.mjs and CHROME_EXECUTABLE=/absolute/path/to/chrome exported:

cd web
node tests/mobile-workspace.browser.mjs
node tests/agent-push-errors.browser.mjs
node tests/agent-push.browser.mjs
node tests/pwa.browser.mjs

MOBILE_ARTIFACT_DIR saves layout screenshots. PUSH_ERROR_SCREENSHOT saves notification settings. MOBILE_BASELINE=1 records the original layout/gesture failures against a separately served original build.

Device verification limits

No physical GrapheneOS/Vanadium, Android Chrome, or iPhone/Safari device was available. Desktop Chromium touch emulation cannot verify Android system status-bar visibility, native long-press menu rendering/selection handles, actual pinch/keyboard behavior, installed-PWA metadata updates or background FCM delivery. Clipboard tests use the browser engine's keyboard copy/paste and synthetic context-menu dispatch; cancellation/selection assertions are not a claim that Android's system menu was displayed. A shorter viewport approximates keyboard space, without emulating the keyboard itself.

On the user's device after an authorized deployment: check the installed status bar and fixed-scale viewport, pan both ways through wide tables/quotes/code without navigation, long-press/copy/paste, change model, then explicitly enable notifications and inspect the new error if registration fails. Verify actual background delivery with all Sybil web sessions inactive. The underlying phone-specific notification failure remains unconfirmed until that check.