From 3b2b1c0b36963da2cc3540f37273aedb01e0b010 Mon Sep 17 00:00:00 2001 From: Jinwoo-H Date: Tue, 1 Sep 2026 18:49:19 -0400 Subject: [PATCH] docs(mobile): correct the hybrid WebView records against the tree The audit record claimed a declarative registry prototype covered Tasks, Files, and Session and proved metadata, grants, and typed calls can be generated. No prototype existed: bridge-operation-registry.ts was an operation-name list with a capability enum and a membership check, consumed only by bridge-contract.ts and one test. Withdraw the claim, reopen the checklist item, and add a 2026-09-01 addendum recording the cleanup this branch landed, referenced by merge subject. Also correct three factual conflicts with the code: - The rollback runbook told support to direct users to the retained native workspace route while its own Safety Invariants said the hybrid candidate has no such fallback. Scope that step to the native-default build, since isRetiredNativeWorkspaceRoute redirects every /h/... workspace route to /hybrid in a hybrid build. - The architecture reference described the Android network fence as load blocking only, omitted that a sub-threshold WebView process restart now retires the capability broker, and did not say that the Android bridge accepts a message on the origin host derived from activeSessionId with the fragment as a secondary check. Name the build scripts that run each delivery step while there. - The remaining-work tracker did not record that the native store suites now run in CI, or that hosted-mobile-webview-ssh.spec.ts is excluded from the ubuntu e2e lane because no hosted runner has a simulator and Docker at once. mobile/README.md needed no change: every entrypoint in its e2e and native store tables resolves to a real script. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb --- .../mobile-hybrid-webview-architecture.md | 28 +++++-- .../mobile-hybrid-webview-rollback.md | 8 +- ...27-mobile-hybrid-webview-remaining-work.md | 13 ++++ ...ile-hybrid-webview-simplification-audit.md | 74 +++++++++++++++++-- 4 files changed, 108 insertions(+), 15 deletions(-) diff --git a/docs/reference/mobile-hybrid-webview-architecture.md b/docs/reference/mobile-hybrid-webview-architecture.md index fc3efcea2df..6af8d0cf8c5 100644 --- a/docs/reference/mobile-hybrid-webview-architecture.md +++ b/docs/reference/mobile-hybrid-webview-architecture.md @@ -2,7 +2,7 @@ - **Status:** Implemented as the sole workspace route in the dedicated release candidate; production promotion is not approved -- **Last updated:** July 29, 2026 +- **Last updated:** September 1, 2026 - **Migration design:** [`plans/2026-07-22-mobile-hybrid-webview-single-pr-migration.md`](./plans/2026-07-22-mobile-hybrid-webview-single-pr-migration.md) - **Active remaining work:** @@ -69,8 +69,9 @@ routes remain outside the hosted route graph. ## Build and Delivery Flow -1. `mobile/scripts/export-host-mobile-web.mjs` exports - `mobile/host-web-app/` for the web platform. +1. `pnpm --dir mobile export:host-web` runs + `mobile/scripts/export-host-mobile-web.mjs`, which exports the + `mobile/host-web-app/` route root for the web platform. 2. The hosted route graph imports the existing screens under `mobile/app/` and their components under `mobile/src/`. 3. `config/scripts/package-mobile-web-rnw.mjs` removes runtime code generation, @@ -79,7 +80,9 @@ routes remain outside the hosted route graph. supported bridge range. 4. `config/scripts/verify-mobile-web-rnw-build.mjs` verifies the manifest, assets, CSP, source boundaries, and size budgets. Desktop packaging copies - the exact output to `Resources/mobile-web`. + the exact output to `Resources/mobile-web`. Steps 1, 3, and 4 run together + as `pnpm build:mobile-web-rnw`, which `pnpm build:mobile-web` aliases and + the Desktop release builds invoke. 5. A paired shell requests `mobileWeb.package.manifest` and bounded `mobileWeb.package.asset` chunks over the existing authenticated, end-to-end-encrypted mobile RPC connection. @@ -141,8 +144,11 @@ external-link authority. arbitrary windows, and direct network loads are disabled. - CSP uses `default-src 'none'`, `connect-src 'none'`, and explicit content-addressed script, style, image, font, and frame rules. -- iOS also installs content rules and network API blockers. Android blocks - network loads and intercepts exact private-origin asset requests. +- iOS installs content rules and a document-start network API blocker. Android + now installs the matching document-start script, denying `fetch`, + `XMLHttpRequest`, `WebSocket`, and `serviceWorker` on the private origin, and + also blocks network loads and intercepts exact private-origin asset + requests. - Top-level navigation is restricted to the active document. External navigation, popups, downloads, workers, and arbitrary bridge origins fail closed. @@ -152,6 +158,11 @@ external-link authority. - The first production protocol is exact version 2. - Every message is schema checked and bound to the active shell session and package build. +- On Android, the private origin host derived from the native `activeSessionId` + is the authority for accepting a bridge message; the URL fragment check is a + secondary assertion (`MobileWebBridgeDocumentUrl.kt`, and + `mobile/src/mobile-web/mobile-web-history-session-fragment.ts`, which keeps + page history writes on that fragment). - The shell grants named operation/capability pairs with request, response, concurrency, subscription, rate, and message limits. - The page cannot invoke a generic RPC passthrough. Desktop still authorizes @@ -188,6 +199,11 @@ from Desktop when connected. A healthy cached package remains available while a refresh fails or Desktop is offline. Page readiness and an interactive health message form the activation boundary. +A WebView process restart below the crash-loop threshold retains the shell +session id but retires and rebuilds the capability broker, so every page-scoped +subscription, stream, and pending request from the lost process is discarded +rather than reused. + Repeated WebView process loss or a health timeout can promote the compatible verified previous generation. The recovery UI exposes: diff --git a/docs/reference/mobile-hybrid-webview-rollback.md b/docs/reference/mobile-hybrid-webview-rollback.md index ead368dc6c8..b542abc73db 100644 --- a/docs/reference/mobile-hybrid-webview-rollback.md +++ b/docs/reference/mobile-hybrid-webview-rollback.md @@ -97,9 +97,11 @@ restarting must not make an affected Desktop safe. build. 2. Disable promotion to additional tracks or audiences and preserve the signed release artifact. -3. Direct affected users to the retained native workspace route when it is - safe. Do not direct users through a broken pairing, credential, or recovery - boundary. +3. In the ordinary native-default build only, direct affected users to the + retained native workspace route when it is safe. This step does not apply to + the dedicated hybrid candidate, where every `/h/...` workspace route + redirects to `/hybrid` and no native workspace fallback exists. Do not direct + users through a broken pairing, credential, or recovery boundary. 4. Classify whether cached generations remain trustworthy under the affected shell. If the native verifier, origin, activation, or bridge is suspect, treat the cache as untrusted until a corrected shell revalidates it. diff --git a/docs/reference/plans/2026-07-27-mobile-hybrid-webview-remaining-work.md b/docs/reference/plans/2026-07-27-mobile-hybrid-webview-remaining-work.md index e10c5df5ade..cd2b4110f0c 100644 --- a/docs/reference/plans/2026-07-27-mobile-hybrid-webview-remaining-work.md +++ b/docs/reference/plans/2026-07-27-mobile-hybrid-webview-remaining-work.md @@ -81,6 +81,19 @@ and restoring rendered Tasks/accessibility parity tests while removing the remaining Tasks duplication. These remain tracked by the corresponding gates below and are not silently considered complete. +## 2026-09-01 CI Coverage Note + +- The Swift and Kotlin native store suites now run in CI from + `.github/workflows/mobile-native-shell-tests.yml`, on a macOS runner and an + ubuntu runner with the Android SDK. This closes no gate above; the suites + compile and exercise store sources, not a store-signed release app. +- `tests/e2e/hosted-mobile-webview-ssh.spec.ts` is explicitly excluded from the + ubuntu changed-spec e2e lane in `.github/workflows/e2e.yml`. It needs an iOS + simulator and a Docker daemon at once, which no GitHub-hosted runner offers, + and it skipped itself off darwin there. Reporting that green skip as coverage + hid the fact that CI never runs it. It runs from a macOS checkout through + `pnpm test:e2e:hosted-mobile-webview:ssh`. + ## Packaged Desktop and Signed App Matrix - [ ] Build, install, and run package delivery from the final supported macOS diff --git a/docs/reference/plans/2026-08-23-mobile-hybrid-webview-simplification-audit.md b/docs/reference/plans/2026-08-23-mobile-hybrid-webview-simplification-audit.md index 62dedbb270a..bd0d593aa28 100644 --- a/docs/reference/plans/2026-08-23-mobile-hybrid-webview-simplification-audit.md +++ b/docs/reference/plans/2026-08-23-mobile-hybrid-webview-simplification-audit.md @@ -159,10 +159,13 @@ Tasks, Files, and Session before any broad conversion. | Parity bounds | `2094dde1f9` | Made native CDP exclusion fail closed above its inspection limit and expanded the bounded session-capability response allowance | | Relay process boundary | `c3725a60fc` | Moved Relay Markdown discovery to the shared cross-platform process launcher and preserved the child-process import ratchet | -The declarative registry prototype covered Tasks, Files, and Session and proved -that metadata, grants, and typed calls can be generated without replacing the -handwritten authorization executors. Converting all 225 operations in this PR -would increase review and compatibility risk, so the registry remains a +No declarative registry prototype was built. +`src/shared/mobile-web/bridge-operation-registry.ts` is an operation-name list +with a capability enum and a membership check; `bridge-contract.ts` and one +focused test were its only consumers. Nothing about metadata, grants, or typed +calls was generated, so the claim that a Tasks/Files/Session prototype proved +generation is withdrawn. Converting all 225 operations in this PR would +increase review and compatibility risk, so the registry remains an unstarted non-blocking follow-up. ## Living Checklist @@ -179,8 +182,9 @@ non-blocking follow-up. - [x] Integrate and validate the iOS host-root boundary fix. - [x] Complete the parity-cutover audit without changing the shared presentation. -- [x] Prototype the declarative registry on Tasks, Files, and Session and defer - broad conversion to a follow-up. +- [ ] Prototype the declarative registry on Tasks, Files, and Session. Not + started; the registry file remains an operation-name list and broad + conversion stays deferred. - [x] Rerun deterministic package verification, full mobile/root suites, typecheck/lint, bridge/cache/security suites, and diff hygiene after integrated simplifications. @@ -191,3 +195,61 @@ non-blocking follow-up. - [ ] Keep the [release-gate tracker](2026-07-27-mobile-hybrid-webview-remaining-work.md) current; do not promote simulator/local evidence into physical, store, production cloud Relay, mixed-version, performance, or App Review proof. + +## 2026-09-01 Cleanup Addendum + +A follow-up branch removed accidental complexity this audit did not catch and +restored the parts of `main` the migration had inlined. Work is referenced by +merge subject rather than SHA, because the branch is still rebased. + +`Merge mr-p1-deps: restore dependency versions and wire Android WebView patches` + +- Mobile dependency downgrades are back at `main`'s versions. +- The Android WebView debugging patches now actually apply. They are declared + in `mobile/pnpm-workspace.yaml` against the installed versions instead of an + inert `mobile/package.json` block. + +`Merge mr-p1-registry: register creationRetiredNames and type bridge operation names` + +- `workspace.creationRetiredNames` is registered. +- Page request clients are typed against the registry, and a census test + asserts that every operation a page request client names is registered. + +`Merge mr-p1-security: broker teardown on restart, Android network blocker, alert gesture gate` + +- A WebView process restart below the crash-loop threshold now retires and + rebuilds the capability broker through a `viewEpoch` remount. +- Android installs a document-start script denying `fetch`, `XMLHttpRequest`, + `WebSocket`, and `serviceWorker`, matching iOS. +- `native.alert` is gated on a gesture witness that does not spend the gesture. + The gesture requirement now lives in one module with its own census. + +`Merge mr-p1-ci: run native shell tests in CI and fix the Android module build` + +- The Swift and Kotlin store suites run from + `.github/workflows/mobile-native-shell-tests.yml`. +- The Kotlin module's compile errors and a stage-symlink defect were fixed + first. + +`Merge mr-p1-cleanup: drop dead modules, stale overrides, and duplicated guards` + +- Unreferenced renderer and bridge modules are gone, along with the max-lines + overrides for files that shrank. + +`Merge mr-p2-tasks: restore the Tasks route as a hook composition` + +- The Tasks route is 80 lines again, down from 14,452, with the hosted + operations delta threaded through restored stage hooks and + statement/render-token parity oracles re-frozen. +- Its max-lines baseline entry and the modules the inlined screen orphaned were + removed. + +`Merge mr-p2-session: restore the split session route and RPC client` + +- The session route is 10 lines, down from 4,984, and `rpc-client.ts` is 64 + lines, down from 1,202. +- Both are back on `main`'s decomposition with the hybrid delta re-applied. + +This addendum records completed cleanup. It does not change the audit's +conclusions and closes no gate in the +[release-gate tracker](2026-07-27-mobile-hybrid-webview-remaining-work.md).