收紧宿主壳结构文档门禁

新增三端桥接层文件清单的文档反查

同步宿主壳方案与协议文档的当前结构

记录桥接层结构文档反查决策
This commit is contained in:
2026-06-19 05:27:35 +08:00
parent e4b9cbf09d
commit 93ded284c3
4 changed files with 72 additions and 9 deletions
@@ -103,7 +103,7 @@
- 2026-06-18 移动壳 WebView 安全开关:Expo 移动壳 WebView 必须显式禁用 JS 自动开窗、多窗口、文件访问、file URL 跨源访问、HTTPS 混合内容、第三方 Cookie、共享 Cookie 和 WebView 远程调试;同源主站页面才能留在带 HostBridge 的 WebView 内,外链只通过受控协议离开容器交给系统。配置检查和移动壳导航测试会拒绝这些边界被放宽。
- 2026-06-18 移动壳 WebView 默认下载边界:Expo WebView 内网页自动下载和 `<a download>` 直接落盘默认关闭;壳层注入脚本阻断 download 链接,iOS `onFileDownload` 只丢弃不落盘,Android 包配置通过 `blockedPermissions` 移除外部存储读写、管理外部存储和请求安装包权限。移动端文本、图片、音频保存只能通过 `file.exportText``file.exportImage``file.exportAudio` 等 HostBridge 受控导出能力进入系统分享 / 保存面板。
- 2026-06-18 移动壳 HostBridge 消息来源校验:Expo 移动壳 `onMessage` 必须根据 `event.nativeEvent.url` 校验消息来源,只有同源主站页面能进入 `handleMobileHostBridgeMessage``about:blank`、外域、协议降级和危险协议页面消息直接丢弃,不返回宿主能力错误细节。该规则与 WebView 导航留壳规则共用同源判断,配置检查和移动壳导航测试会拒绝移除。
- 2026-06-18 三端桥接层目录同构:微信小程序、Expo 移动壳和 Tauri 桌面壳都按 `host-bridge / shell` 两层管理宿主桥接代码。微信 `miniprogram/host-bridge/webView.js``payment.js``shareGrid.js``subscribeMessage.js` 只放协议归一、支付 / 订阅 / 分享结果编解码和可测试桥接函数,`miniprogram/shell/` 下同名职责文件承接 Page 生命周期、`wx.*` 容器调用、WebView 容器行为和页面工厂;页面目录只保留 `Page(createWechat...Page())` 装配。Expo `protocol.ts``files.ts``share.ts` 和 facade `bridge.ts` 分别对齐 Tauri `host_bridge/protocol.rs``files.rs``share.rs``mod.rs`,根 `App.tsx` 只装配 `src/shell/ShellApp.tsx`,不直接进口 HostBridge。Tauri `shell/runtime.rs``url.rs``navigation.rs``network.rs``lifecycle.rs``file_drop.rs``events.rs``deep_link.rs``tray.rs``webview.rs` 分别承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘和 WebView 门面。`npm run check:native-shells` 会校验微信、移动和桌面三端目录清单,新增宿主能力必须按同一边界落文件和测试。
- 2026-06-18 三端桥接层目录同构:微信小程序、Expo 移动壳和 Tauri 桌面壳都按 `host-bridge / shell` 两层管理宿主桥接代码。微信 `miniprogram/host-bridge/webView.js``payment.js``shareGrid.js``subscribeMessage.js` 只放协议归一、支付 / 订阅 / 分享结果编解码和可测试桥接函数,`miniprogram/shell/` 下同名职责文件承接 Page 生命周期、`wx.*` 容器调用、WebView 容器行为和页面工厂;页面目录只保留 `Page(createWechat...Page())` 装配。Expo `protocol.ts``capabilities.ts``dispatch.ts``files.ts``scanner.ts``share.ts` 和 facade `bridge.ts` 分别对齐 Tauri `host_bridge/protocol.rs``capabilities.rs``dispatch.rs``files.rs``share.rs``mod.rs`,根 `App.tsx` 只装配 `src/shell/ShellApp.tsx`,不直接进口 HostBridge。Tauri `shell/runtime.rs``url.rs``navigation.rs``network.rs``lifecycle.rs``file_drop.rs``events.rs``deep_link.rs``tray.rs``menu.rs``window_state.rs``webview.rs` 分别承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘、应用菜单、窗口状态持久化和 WebView 门面。`npm run check:native-shells` 会校验微信、移动和桌面三端目录清单,新增宿主能力必须按同一边界落文件和测试。
- 影响范围:`src/services/host-bridge/`、未来 `apps/mobile-shell/`、未来 `apps/desktop-shell/`、移动端支付 / 分享 / 深链 / 推送、桌面端系统能力、AI H5 sandbox 的 GameBridge 边界。
- 验证方式:普通浏览器、小程序、Expo 壳、Tauri 壳都能返回正确 `getHostRuntime()`;未支持能力能回退 H5;固定玩法在各宿主中读取同一作品数据和运行态 snapshot;AI sandbox 无法直接调用 HostBridgeTauri release 不允许任意远端页面调用桌面命令。
- 关联文档:`docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md``docs/【前端架构】宿主壳能力统一协议-2026-06-17.md`
@@ -2515,10 +2515,17 @@
## 2026-06-18 三端宿主桥接层文件结构对齐
- 背景:微信小程序壳、Expo 移动壳和 Tauri 桌面壳都在承接宿主能力;如果微信页面继续散落 `index.shared.js`,桌面端继续把桥接分发堆在 `main.rs`,后续新增登录、支付、文件、通知或 sandbox 转发能力时会很难跨端对照 owner。
- 决策:三端桥接层按职责对齐,但保留各宿主真实边界。微信小程序页面路由不改,`miniprogram/host-bridge/protocol.js` 只沉淀微信壳能力、页面 URL、结果 hash / storage key 和分享消息类型等常量,`dispatch.js` 只作为 `protocol``webView``payment``shareGrid``subscribeMessage` 的薄索引,真实协议归一、支付 / 订阅 / 分享结果编解码仍分别放在 `webView.js``payment.js``shareGrid.js``subscribeMessage.js`,页面目录只保留生命周期和装配,不把微信小程序硬改成 Expo / Tauri 的 request 总线;Expo 移动壳拆成 `apps/mobile-shell/src/host-bridge/protocol.ts``capabilities.ts``dispatch.ts``files.ts``share.ts` 和 facade `bridge.ts`,分别负责 envelope / request 校验 / ok-failure 响应 / replay 基础类型、能力清单与 iOS 差异、method 分发、文件能力、分享能力和 WebView message 入口 / request id replay 编排;根 `App.tsx` 只装配 `apps/mobile-shell/src/shell/ShellApp.tsx``apps/mobile-shell/src/shell/*.ts(x)` 负责 WebView 容器、URL、导航、网络、生命周期、安全区和 WebView policyTauri 桌面壳拆成 `apps/desktop-shell/src-tauri/src/app.rs``host_bridge/protocol.rs``capabilities.rs``dispatch.rs``files.rs``share.rs` 和 command facade `mod.rs`,分别负责 Tauri builder / plugin / window 装配、envelope / method 白名单 / request 校验 / replay 状态、能力清单、method 分发、文件能力、分享能力和 `host_bridge_request` command / replay 编排;`apps/desktop-shell/src-tauri/src/shell/*.rs` 承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘和 WebView 门面,`main.rs` 只做薄入口并调用 `app::run()``scripts/check-native-shells.mjs` 锁定三端桥接层目录清单,并拒绝移动根入口和桌面根入口重新承接宿主能力装配。
- 决策:三端桥接层按职责对齐,但保留各宿主真实边界。微信小程序页面路由不改,`miniprogram/host-bridge/protocol.js` 只沉淀微信壳能力、页面 URL、结果 hash / storage key 和分享消息类型等常量,`dispatch.js` 只作为 `protocol``webView``payment``shareGrid``subscribeMessage` 的薄索引,真实协议归一、支付 / 订阅 / 分享结果编解码仍分别放在 `webView.js``payment.js``shareGrid.js``subscribeMessage.js`,页面目录只保留生命周期和装配,不把微信小程序硬改成 Expo / Tauri 的 request 总线;Expo 移动壳拆成 `apps/mobile-shell/src/host-bridge/protocol.ts``capabilities.ts``dispatch.ts``files.ts``scanner.ts``share.ts` 和 facade `bridge.ts`,分别负责 envelope / request 校验 / ok-failure 响应 / replay 基础类型、能力清单与 iOS 差异、method 分发、文件能力、扫码能力、分享能力和 WebView message 入口 / request id replay 编排;根 `App.tsx` 只装配 `apps/mobile-shell/src/shell/ShellApp.tsx``apps/mobile-shell/src/shell/*.ts(x)` 负责 WebView 容器、URL、导航、网络、生命周期、安全区、扫码 overlay 和 WebView policyTauri 桌面壳拆成 `apps/desktop-shell/src-tauri/src/app.rs``host_bridge/protocol.rs``capabilities.rs``dispatch.rs``files.rs``share.rs` 和 command facade `mod.rs`,分别负责 Tauri builder / plugin / window 装配、envelope / method 白名单 / request 校验 / replay 状态、能力清单、method 分发、文件能力、分享能力和 `host_bridge_request` command / replay 编排;`apps/desktop-shell/src-tauri/src/shell/*.rs` 承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘、应用菜单、窗口状态持久化和 WebView 门面,`main.rs` 只做薄入口并调用 `app::run()``scripts/check-native-shells.mjs` 锁定三端桥接层目录清单,并拒绝移动根入口和桌面根入口重新承接宿主能力装配。
- 影响范围:`miniprogram/host-bridge/``miniprogram/pages/*/index.js``apps/mobile-shell/src/``apps/desktop-shell/src-tauri/src/``scripts/check-native-shells.mjs`、宿主壳方案文档。
- 验证方式:`npm run test -- miniprogram/host-bridge/webView.test.js miniprogram/host-bridge/payment.test.js miniprogram/host-bridge/shareGrid.test.js miniprogram/host-bridge/subscribeMessage.test.js miniprogram/pages/web-view/index.style.test.js``npm run check:native-shells``npm run typecheck``npm run check:encoding``git diff --check`
## 2026-06-19 三端宿主桥接层结构文档反查
- 背景:三端桥接层已经拆出移动 `scanner.ts`、桌面 `menu.rs``window_state.rs` 等职责文件,但如果只更新代码和目录门禁,`宿主壳能力统一协议``ExpoReactNative与Tauri宿主壳方案` 可能继续保留旧清单,后续开发者按文档扩展时仍会把能力放回错误 owner。
- 决策:`scripts/check-native-shells.mjs` 的三端桥接层目录清单同时作为文档反查来源。根级门禁会确认两份前端架构文档都显式列出微信桥接层、微信 shell、移动桥接层、移动 shell、桌面入口、桌面桥接层和桌面 shell 的当前生产文件;新增、删除或改名这些职责文件时,必须同时更新脚本清单、两份架构文档和相关实现,不允许只改一端。
- 影响范围:`scripts/check-native-shells.mjs``docs/【前端架构】宿主壳能力统一协议-2026-06-17.md``docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md`、三端宿主壳源码布局。
- 验证方式:`npm run check:native-shells``npm run check:encoding``git diff --check`
## 2026-06-19 HostBridge 载荷边界单一来源
- 背景:文件导入导出、剪贴板、角标、本地通知和 request id 都已经在 Expo 与 Tauri 两套壳里有运行时校验;如果 MIME 清单、字节上限或文本长度只靠人工同步,新增文件类型或调整上限时会出现 H5 契约、移动壳和桌面壳互相漂移。
@@ -64,7 +64,9 @@ src/
已落地:`packages/shared/src/contracts/hostBridge.ts` 保存消息 envelope、method、payload 和错误码,H5、Expo 壳与 Tauri 壳共享同一份协议类型。
三端宿主桥接层按职责对齐命名:微信小程序页面路由仍保留在 `miniprogram/pages/*``miniprogram/host-bridge/protocol.js` 只沉淀微信壳能力、页面 URL、结果 hash / storage key 和分享消息类型等常量,`dispatch.js` 只作为 `protocol``webView``payment``shareGrid``subscribeMessage` 的薄索引,真实协议归一、支付 / 订阅 / 分享结果编解码仍分别在 `webView.js``payment.js``shareGrid.js``subscribeMessage.js`,不把微信小程序硬改成 Expo / Tauri 的 request 总线;Page 生命周期、`wx.*` 容器调用、WebView 容器行为和页面工厂统一放在 `miniprogram/shell/webView.js``payment.js``shareGrid.js``subscribeMessage.js`,页面入口只做 `Page(createWechat...Page())` 装配。Expo 移动壳使用 `apps/mobile-shell/src/host-bridge/protocol.ts` 承接 envelope、request 校验、ok / failure 响应和 replay 基础类型,`capabilities.ts` 只引用共享 HostBridge capability profile 并选择 iOS 差异能力,`dispatch.ts` 承接 method 分发和宿主能力调用,`files.ts` / `share.ts` 分别承接文件分享能力,`bridge.ts` 只作为 WebView message 入口、request id replay 编排和对外 facade`apps/mobile-shell/App.tsx` 只装配 `apps/mobile-shell/src/shell/ShellApp.tsx`,由 `apps/mobile-shell/src/shell/*.ts(x)` 承接 WebView 容器、URL、导航、网络、生命周期、安全区和 WebView policy。Tauri 桌面壳使用 `apps/desktop-shell/src-tauri/src/host_bridge/protocol.rs` 承接 envelope、method 白名单、request 校验和 replay 状态,`capabilities.rs` 承接共享桌面 capability profile 的 Rust 运行时镜像,`dispatch.rs` 承接 method 分发和宿主能力调用,`files.rs` / `share.rs` 分别承接文件和分享能力,`mod.rs` 只保留模块声明、必要 re-export、`host_bridge_request` command facade 和 replay 编排;`apps/desktop-shell/src-tauri/src/shell/runtime.rs``url.rs``navigation.rs``network.rs``lifecycle.rs``file_drop.rs``events.rs``deep_link.rs``tray.rs``menu.rs``window_state.rs``webview.rs` 分别承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘、应用菜单、窗口状态持久化和 WebView 门面,`apps/desktop-shell/src-tauri/src/app.rs` 承接 Tauri builder / plugin / window 装配,`main.rs` 只保留薄入口并调用 `app::run()`
三端宿主桥接层按职责对齐命名:微信小程序页面路由仍保留在 `miniprogram/pages/*``miniprogram/host-bridge/protocol.js` 只沉淀微信壳能力、页面 URL、结果 hash / storage key 和分享消息类型等常量,`dispatch.js` 只作为 `protocol``webView``payment``shareGrid``subscribeMessage` 的薄索引,真实协议归一、支付 / 订阅 / 分享结果编解码仍分别在 `webView.js``payment.js``shareGrid.js``subscribeMessage.js`,不把微信小程序硬改成 Expo / Tauri 的 request 总线;Page 生命周期、`wx.*` 容器调用、WebView 容器行为和页面工厂统一放在 `miniprogram/shell/webView.js``payment.js``shareGrid.js``subscribeMessage.js`,页面入口只做 `Page(createWechat...Page())` 装配。Expo 移动壳使用 `apps/mobile-shell/src/host-bridge/protocol.ts` 承接 envelope、request 校验、ok / failure 响应和 replay 基础类型,`capabilities.ts` 只引用共享 HostBridge capability profile 并选择 iOS 差异能力,`dispatch.ts` 承接 method 分发和宿主能力调用,`files.ts` / `share.ts` / `scanner.ts` 分别承接文件分享和扫码能力,`bridge.ts` 只作为 WebView message 入口、request id replay 编排和对外 facade`apps/mobile-shell/App.tsx` 只装配 `apps/mobile-shell/src/shell/ShellApp.tsx`,由 `apps/mobile-shell/src/shell/*.ts(x)` 承接 WebView 容器、URL、导航、网络、生命周期、安全区、扫码 overlay 和 WebView policy。Tauri 桌面壳使用 `apps/desktop-shell/src-tauri/src/host_bridge/protocol.rs` 承接 envelope、method 白名单、request 校验和 replay 状态,`capabilities.rs` 承接共享桌面 capability profile 的 Rust 运行时镜像,`dispatch.rs` 承接 method 分发和宿主能力调用,`files.rs` / `share.rs` 分别承接文件和分享能力,`mod.rs` 只保留模块声明、必要 re-export、`host_bridge_request` command facade 和 replay 编排;`apps/desktop-shell/src-tauri/src/shell/runtime.rs``url.rs``navigation.rs``network.rs``lifecycle.rs``file_drop.rs``events.rs``deep_link.rs``tray.rs``menu.rs``window_state.rs``webview.rs` 分别承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘、应用菜单、窗口状态持久化和 WebView 门面,`apps/desktop-shell/src-tauri/src/app.rs` 承接 Tauri builder / plugin / window 装配,`main.rs` 只保留薄入口并调用 `app::run()`
当前 `npm run check:native-shells` 锁定的生产文件清单为:微信桥接层 `dispatch.js``payment.js``protocol.js``shareGrid.js``subscribeMessage.js``webView.js`;微信 shell 层 `payment.js``shareGrid.js``subscribeMessage.js``webView.js`;移动桥接层 `bridge.ts``capabilities.ts``dispatch.ts``files.ts``protocol.ts``scanner.ts``share.ts`;移动 shell 层 `QrScannerOverlay.tsx``ShellApp.tsx``deepLink.ts``lifecycle.ts``loadFailure.ts``navigation.ts``network.ts``runtime.ts``safeArea.ts``url.ts``webViewGlobals.d.ts``webViewHistory.ts``webViewPolicy.ts`;桌面入口 `app.rs``main.rs`;桌面桥接层 `capabilities.rs``dispatch.rs``files.rs``mod.rs``protocol.rs``share.rs`;桌面 shell 层 `deep_link.rs``events.rs``file_drop.rs``lifecycle.rs``menu.rs``mod.rs``navigation.rs``network.rs``runtime.rs``tray.rs``url.rs``webview.rs``window_state.rs`
## HostBridge 消息协议
@@ -189,7 +191,7 @@ Tauri 壳同样只负责桌面宿主能力,不承接玩法业务。
- Release 包默认打包当前 H5 `dist`,保证桌面包版本可复现。
- Dev 模式允许加载本地 Vite URL,方便调试。
- H5 通过 `window.__TAURI__.core.invoke('host_bridge_request', request)` 或后续封装的 `nativeAppHostBridge` 调用桌面能力
- H5 通过 `nativeAppHostBridge` 超时封装调用 `window.__TAURI__.core.invoke('host_bridge_request', request)`,不直接调用其它 Tauri command
- Rust 侧只暴露一个受控 `host_bridge_request` command,再在 Rust 内部按 method 白名单分发。
- Tauri capabilities 只授予主窗口所需命令;默认不开放文件系统、shell、全局剪贴板或任意插件能力。
- 主窗口 capability 只授予 `allow-host-bridge-request`;不得使用 `core:default``core:*:default` 或插件 command 权限作为兜底。窗口、菜单、托盘、剪贴板、文件、通知和外链能力只能由 Rust 壳内部调用,再通过 `host_bridge_request` 的 HostBridge method 白名单分发给 H5。
@@ -470,7 +472,7 @@ GameBridge 禁止:
2026-06-18 追加:`app.openExternalUrl` 的协议白名单以共享 HostBridge 契约 `HOST_BRIDGE_EXTERNAL_URL_PROTOCOLS` 为唯一来源,当前只允许 `http:``https:``mailto:``tel:`。Expo 壳直接复用共享归一化逻辑,Tauri 壳 Rust 侧用 URL parser 镜像同一清单;`npm run check:native-shells` 会反查共享契约与桌面壳协议清单,防止某一端单独放宽外链协议。
2026-06-18 追加:微信、移动端和桌面端桥接层文件结构按职责对齐。微信小程序的 `web-view`、支付、九宫切图和订阅消息桥接逻辑统一迁入 `miniprogram/host-bridge/webView.js``payment.js``shareGrid.js``subscribeMessage.js`,页面目录只保留页面生命周期、WXML/WXSS 和装配;移动壳拆成 `apps/mobile-shell/src/host-bridge/protocol.ts``files.ts``share.ts` 和 facade `bridge.ts`,与桌面端 `host_bridge/protocol.rs``files.rs``share.rs``mod.rs` 对齐;移动壳根 `App.tsx` 也保持薄入口,只装配 `src/shell/ShellApp.tsx`,WebView 容器、深链、网络、生命周期和安全策略全部留在 `src/shell/`;桌面壳 Rust 源码拆成 `apps/desktop-shell/src-tauri/src/app.rs``host_bridge/*.rs``shell/*.rs`,其中 `app.rs` 承接 Tauri builder / plugin / window 装配,`runtime.rs``url.rs``navigation.rs``network.rs``lifecycle.rs``file_drop.rs``events.rs``deep_link.rs``tray.rs``menu.rs``window_state.rs``webview.rs` 分别承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘、应用菜单、窗口状态持久化和 WebView 门面,薄 `main.rs` 只声明模块并调用 `app::run()`。根级 `npm run check:native-shells` 会锁定三端桥接层目录清单,避免后续把能力逻辑重新散落到页面、移动入口或桌面入口。
2026-06-18 追加:微信、移动端和桌面端桥接层文件结构按职责对齐。微信小程序的 `web-view`、支付、九宫切图和订阅消息桥接逻辑统一迁入 `miniprogram/host-bridge/webView.js``payment.js``shareGrid.js``subscribeMessage.js`,页面目录只保留页面生命周期、WXML/WXSS 和装配;移动壳拆成 `apps/mobile-shell/src/host-bridge/protocol.ts``capabilities.ts``dispatch.ts``files.ts``scanner.ts``share.ts` 和 facade `bridge.ts`,与桌面端 `host_bridge/protocol.rs``capabilities.rs``dispatch.rs``files.rs``share.rs``mod.rs` 对齐;移动壳根 `App.tsx` 也保持薄入口,只装配 `src/shell/ShellApp.tsx`,WebView 容器、深链、网络、生命周期、安全区、扫码 overlay 和安全策略全部留在 `src/shell/`;桌面壳 Rust 源码拆成 `apps/desktop-shell/src-tauri/src/app.rs``host_bridge/*.rs``shell/*.rs`,其中 `app.rs` 承接 Tauri builder / plugin / window 装配,`runtime.rs``url.rs``navigation.rs``network.rs``lifecycle.rs``file_drop.rs``events.rs``deep_link.rs``tray.rs``menu.rs``window_state.rs``webview.rs` 分别承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘、应用菜单、窗口状态持久化和 WebView 门面,薄 `main.rs` 只声明模块并调用 `app::run()`。根级 `npm run check:native-shells` 会锁定三端桥接层目录清单,避免后续把能力逻辑重新散落到页面、移动入口或桌面入口。
2026-06-19 追加:HostBridge 载荷边界以共享契约为单一声明来源。`packages/shared/src/contracts/hostBridge.ts` 导出文本 / 图片 / 音频 MIME 清单、导入 / 导出字节上限、导出文件名 fallback 与长度上限,以及 request id、角标、剪贴板和本地通知文本长度边界;Expo 移动壳必须直接导入这些共享常量,不再本地重声明文件大小或 MIME 清单,并且文本 / 音频导入必须在读取内容前通过 picker `size` 或 Expo `File.size` 完成大小门禁,无法拿到可信 byte count 时直接拒绝导入;Tauri 桌面壳的配置检查会反查 Rust 镜像实现,拒绝文件大小、MIME 清单、文件名、通知、剪贴板或 request id 边界与共享契约漂移。新增文件类型或调整体积上限必须先更新共享契约、壳实现和门禁,再进入玩法或 H5 facade。
@@ -20,7 +20,7 @@
- 不重写 React 主站和现有玩法 runtime。
- 不把固定玩法迁成远程代码包。
- 不在本阶段实现 React Native / Expo
- 不在 HostBridge 层重写 React Native / Expo 或 Tauri 业务 UI
- 不改变支付到账、任务、排行榜、发布、统计等后端裁决口径。
## 分层
@@ -37,7 +37,9 @@ AI H5 sandbox
-> parent HostBridge adapter
```
桥接层文件结构按宿主统一为“协议 / 能力清单 / 分发 / 宿主容器行为”四类职责。微信小程序不硬套 Expo / Tauri 的 request 总线:`miniprogram/host-bridge/protocol.js` 只沉淀微信壳能力、页面 URL、结果 hash / storage key 和分享消息类型等常量,`dispatch.js` 只作为 `protocol``webView``payment``shareGrid``subscribeMessage` 的薄索引,真实协议归一、支付 / 订阅 / 分享结果编解码仍分别放在 `webView.js``payment.js``shareGrid.js``subscribeMessage.js``miniprogram/shell/webView.js``payment.js``shareGrid.js``subscribeMessage.js` 承接 Page 生命周期、`wx.*` 容器调用、WebView 容器行为、支付页和订阅页装配,页面目录只保留 `Page(createWechat...Page())` 装配。Expo 移动壳使用 `apps/mobile-shell/src/host-bridge/protocol.ts` 承接 envelope、request 校验、ok / failure 响应和 replay 基础类型,`capabilities.ts` 只引用共享 HostBridge capability profile 并选择 iOS 差异能力,`dispatch.ts` 承接 method 分发和宿主能力调用,`files.ts` / `share.ts` 分别承接文件分享能力,`bridge.ts` 只作为 WebView message 入口、request id replay 编排和对外 facade`apps/mobile-shell/App.tsx` 只装配 `apps/mobile-shell/src/shell/ShellApp.tsx`,由 `apps/mobile-shell/src/shell/*.ts(x)` 承接 WebView 容器、URL、导航、网络、生命周期、安全区和 WebView policy。Tauri 桌面壳使用 `apps/desktop-shell/src-tauri/src/host_bridge/protocol.rs` 承接 envelope、method 白名单、request 校验和 replay 状态,`capabilities.rs` 承接共享桌面 capability profile 的 Rust 运行时镜像,`dispatch.rs` 承接 method 分发和宿主能力调用,`files.rs` / `share.rs` 分别承接文件和分享能力,`mod.rs` 只保留模块声明、必要 re-export、`host_bridge_request` command facade 和 replay 编排;`apps/desktop-shell/src-tauri/src/shell/runtime.rs``url.rs``navigation.rs``network.rs``lifecycle.rs``file_drop.rs``events.rs``deep_link.rs``tray.rs``webview.rs` 分别承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘和 WebView 门面,`apps/desktop-shell/src-tauri/src/app.rs` 承接 Tauri builder / plugin / window 装配,`main.rs` 只保留薄入口并调用 `app::run()``npm run check:native-shells` 会检查这些目录清单。
桥接层文件结构按宿主统一为“协议 / 能力清单 / 分发 / 宿主容器行为”四类职责。微信小程序不硬套 Expo / Tauri 的 request 总线:`miniprogram/host-bridge/protocol.js` 只沉淀微信壳能力、页面 URL、结果 hash / storage key 和分享消息类型等常量,`dispatch.js` 只作为 `protocol``webView``payment``shareGrid``subscribeMessage` 的薄索引,真实协议归一、支付 / 订阅 / 分享结果编解码仍分别放在 `webView.js``payment.js``shareGrid.js``subscribeMessage.js``miniprogram/shell/webView.js``payment.js``shareGrid.js``subscribeMessage.js` 承接 Page 生命周期、`wx.*` 容器调用、WebView 容器行为、支付页和订阅页装配,页面目录只保留 `Page(createWechat...Page())` 装配。Expo 移动壳使用 `apps/mobile-shell/src/host-bridge/protocol.ts` 承接 envelope、request 校验、ok / failure 响应和 replay 基础类型,`capabilities.ts` 只引用共享 HostBridge capability profile 并选择 iOS 差异能力,`dispatch.ts` 承接 method 分发和宿主能力调用,`files.ts` / `share.ts` / `scanner.ts` 分别承接文件分享和扫码能力,`bridge.ts` 只作为 WebView message 入口、request id replay 编排和对外 facade`apps/mobile-shell/App.tsx` 只装配 `apps/mobile-shell/src/shell/ShellApp.tsx`,由 `apps/mobile-shell/src/shell/*.ts(x)` 承接 WebView 容器、URL、导航、网络、生命周期、安全区、扫码 overlay 和 WebView policy。Tauri 桌面壳使用 `apps/desktop-shell/src-tauri/src/host_bridge/protocol.rs` 承接 envelope、method 白名单、request 校验和 replay 状态,`capabilities.rs` 承接共享桌面 capability profile 的 Rust 运行时镜像,`dispatch.rs` 承接 method 分发和宿主能力调用,`files.rs` / `share.rs` 分别承接文件和分享能力,`mod.rs` 只保留模块声明、必要 re-export、`host_bridge_request` command facade 和 replay 编排;`apps/desktop-shell/src-tauri/src/shell/runtime.rs``url.rs``navigation.rs``network.rs``lifecycle.rs``file_drop.rs``events.rs``deep_link.rs``tray.rs``menu.rs``window_state.rs``webview.rs` 分别承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘、应用菜单、窗口状态持久化和 WebView 门面,`apps/desktop-shell/src-tauri/src/app.rs` 承接 Tauri builder / plugin / window 装配,`main.rs` 只保留薄入口并调用 `app::run()``npm run check:native-shells` 会检查这些目录清单。
当前 `npm run check:native-shells` 锁定的生产文件清单为:微信桥接层 `dispatch.js``payment.js``protocol.js``shareGrid.js``subscribeMessage.js``webView.js`;微信 shell 层 `payment.js``shareGrid.js``subscribeMessage.js``webView.js`;移动桥接层 `bridge.ts``capabilities.ts``dispatch.ts``files.ts``protocol.ts``scanner.ts``share.ts`;移动 shell 层 `QrScannerOverlay.tsx``ShellApp.tsx``deepLink.ts``lifecycle.ts``loadFailure.ts``navigation.ts``network.ts``runtime.ts``safeArea.ts``url.ts``webViewGlobals.d.ts``webViewHistory.ts``webViewPolicy.ts`;桌面入口 `app.rs``main.rs`;桌面桥接层 `capabilities.rs``dispatch.rs``files.rs``mod.rs``protocol.rs``share.rs`;桌面 shell 层 `deep_link.rs``events.rs``file_drop.rs``lifecycle.rs``menu.rs``mod.rs``navigation.rs``network.rs``runtime.rs``tray.rs``url.rs``webview.rs``window_state.rs`
## 首批能力
@@ -88,7 +90,6 @@ HostBridge 事件名以 `packages/shared/src/contracts/hostBridge.ts` 的 `HOST_
## 后续
- 设计 `native_app``postMessage` 消息格式和回包超时策略。
- 原生 App 壳的移动端采用 `Expo + React Native`,桌面端采用 `Tauri`;壳层只作为 HostBridge adapter,不重写现有 H5 主站和固定玩法 runtime。详细方案见 `docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md`
- 为 AI H5 sandbox 单独定义 GameBridge,禁止直接依赖 HostBridge。
- 将宿主能力、支付渠道和分享策略补充进移动端发布检查清单。
- 原生登录、渠道支付、远程推送、自动更新、崩溃上报和 analytics 等能力必须等真实 SDK、后端契约、发布流程和隐私口径确定后逐项接入。
+53
View File
@@ -171,6 +171,44 @@ const expectedDesktopShellRustFiles = [
'webview.rs',
'window_state.rs',
];
const documentedShellLayerGroups = [
{
label: 'wechat host bridge files',
files: expectedWechatHostBridgeFiles.filter(
(fileName) => !fileName.includes('.test.'),
),
},
{
label: 'wechat shell files',
files: expectedWechatShellFiles.filter(
(fileName) => !fileName.includes('.test.'),
),
},
{
label: 'mobile host bridge files',
files: expectedMobileHostBridgeFiles.filter(
(fileName) => !fileName.includes('.test.'),
),
},
{
label: 'mobile shell files',
files: expectedMobileShellFiles.filter(
(fileName) => !fileName.includes('.test.'),
),
},
{
label: 'desktop entrypoint files',
files: ['app.rs', 'main.rs'],
},
{
label: 'desktop host bridge files',
files: expectedDesktopHostBridgeRustFiles,
},
{
label: 'desktop shell files',
files: expectedDesktopShellRustFiles,
},
];
const capabilityListMarkers = {
desktop: '桌面壳当前真实能力完整清单为',
mobile: '移动壳当前通用真实能力完整清单为',
@@ -539,6 +577,16 @@ function assertSameList(actual, expected, label) {
}
}
function assertShellLayerLayoutDocumented(source, label) {
for (const group of documentedShellLayerGroups) {
for (const fileName of group.files) {
if (!source.includes(fileName)) {
throw new Error(`${label} missing ${group.label}: ${fileName}`);
}
}
}
}
function extractTsStringArray(source, exportName, seen = new Set()) {
if (seen.has(exportName)) {
throw new Error(`cyclic string array export ${exportName}`);
@@ -665,6 +713,11 @@ function assertNativeShellCapabilityPlan() {
decisionLogDocSource,
'decision log document',
);
assertShellLayerLayoutDocumented(planSource, 'native shell plan');
assertShellLayerLayoutDocumented(
hostBridgeProtocolDocSource,
'HostBridge protocol document',
);
const desktopCapabilitySource = fs.readFileSync(
'apps/desktop-shell/src-tauri/src/host_bridge/capabilities.rs',