收口移动壳渠道SDK依赖边界

扩展移动壳配置检查,根包和移动壳包都禁止提前安装移动渠道SDK

更新原生壳方案,说明根依赖不得绕过移动壳发布通道边界

同步共享决策记录,明确真实渠道契约前不接入移动崩溃上报和analytics依赖
This commit is contained in:
2026-06-18 12:35:37 +08:00
parent 6a5869596c
commit ce66b69ad8
3 changed files with 15 additions and 5 deletions
+7 -4
View File
@@ -19,6 +19,8 @@ const sharedContractPath = new URL(
const sharedContractSource = fs.readFileSync(sharedContractPath, 'utf8');
const packagePath = new URL('../package.json', import.meta.url);
const packageConfig = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
const rootPackagePath = new URL('../../../package.json', import.meta.url);
const rootPackageConfig = JSON.parse(fs.readFileSync(rootPackagePath, 'utf8'));
const iconPath = new URL('../assets/icon.png', import.meta.url);
const icon = PNG.sync.read(fs.readFileSync(iconPath));
const brandBackgroundColor = '#fffdf9';
@@ -131,7 +133,7 @@ function extractStringConstExport(source, exportName) {
return match[1];
}
function assertNoBlockedMobileChannelDependencies() {
function assertNoBlockedMobileChannelDependencies(packageJson, packageLabel) {
const dependencySections = [
'dependencies',
'devDependencies',
@@ -141,9 +143,9 @@ function assertNoBlockedMobileChannelDependencies() {
for (const dependency of blockedMobileChannelDependencies) {
for (const section of dependencySections) {
if (packageConfig[section]?.[dependency]) {
if (packageJson[section]?.[dependency]) {
throw new Error(
`mobile shell must not depend on ${dependency} before the real channel contract exists`,
`${packageLabel} must not depend on ${dependency} before the real mobile channel contract exists`,
);
}
}
@@ -250,7 +252,8 @@ function assertSameList(actual, expected, label) {
assertNoDevScaffoldTerms(
productionSourceRoots.flatMap((root) => collectProductionSourceFiles(root)),
);
assertNoBlockedMobileChannelDependencies();
assertNoBlockedMobileChannelDependencies(packageConfig, 'mobile shell package');
assertNoBlockedMobileChannelDependencies(rootPackageConfig, 'root H5 package');
assertNoBlockedMobileChannelSnippets();
const sharedCapabilities = extractStringArrayExport(
@@ -2383,3 +2383,10 @@
- 决策:根 H5 `package.json``apps/desktop-shell/package.json` 不安装 `@tauri-apps/api` 或任何 `@tauri-apps/plugin-*` JS guest 包;opener、clipboard、dialog、notification 等桌面系统能力只保留 Rust Cargo 插件,由 `host_bridge_request` 内部分发。`apps/desktop-shell/scripts/check-config.mjs` 对两个 package 都做依赖门禁,Tauri CLI 仅作为构建工具保留。
- 影响范围:根依赖、桌面壳依赖、桌面壳配置检查和 Expo / Tauri HostBridge 方案文档。
- 验证方式:`npm run check:native-shells``npm run typecheck``npm run check:encoding``git diff --check`
## 2026-06-18 移动壳渠道 SDK 依赖收口
- 背景:Expo 移动壳运行时依赖可能从根安装树解析;如果只检查 `apps/mobile-shell/package.json`,根 H5 包仍可能直接引入 Expo Updates、Sentry、Firebase Analytics、PostHog、Amplitude、Segment、CodePush 等移动端发布通道、崩溃上报或 analytics SDK,让壳边界绕过真实渠道契约。
- 决策:`apps/mobile-shell/scripts/check-config.mjs` 同时检查移动壳包和根 H5 包的直接依赖;在真实发布通道、采集字段、用户授权、隐私披露、签名 / 回滚策略和团队发布流程落地前,两处都不得安装上述移动渠道 SDK。现有即时本地通知、系统分享、文件导入导出等真实宿主能力不受影响。
- 影响范围:移动壳配置检查、根依赖边界和 Expo / Tauri HostBridge 方案文档。
- 验证方式:`npm run check:native-shells``npm run typecheck``npm run check:encoding``git diff --check`
@@ -298,7 +298,7 @@ GameBridge 禁止:
2026-06-18 追加:移动壳 H5 入口 query 和 `host.getRuntime` 回包统一读取 `MOBILE_SHELL_HOST_VERSION`,该常量必须与 Expo `app.json` / `package.json` 版本一致。配置检查会拒绝在 `App.tsx``mobileHostBridge.ts` 内重新散落硬编码版本,避免升级移动安装包时 H5 首屏上下文和宿主 runtime 回读版本不一致。
2026-06-18 追加:移动壳默认显式关闭 Expo OTA 更新,直到存在真实发布通道、更新端点、签名 / 回滚策略和团队发布流程后再接入。`app.json` 只允许 `updates.enabled=false`,不得配置 `runtimeVersion`、release channel、EAS channel、`expo-updates` 插件或移动端 crash / analytics / CodePush 依赖;`apps/mobile-shell/scripts/check-config.mjs` 和 Expo public config smoke 会共同拒绝这些发布通道能力被提前打开,移动壳生产入口、HostBridge 和 URL/runtime 配置也不得提前初始化 Sentry、Firebase Analytics、PostHog、Amplitude、Segment、CodePush 或 Expo Updates。
2026-06-18 追加:移动壳默认显式关闭 Expo OTA 更新,直到存在真实发布通道、更新端点、签名 / 回滚策略和团队发布流程后再接入。`app.json` 只允许 `updates.enabled=false`,不得配置 `runtimeVersion`、release channel、EAS channel、`expo-updates` 插件或移动端 crash / analytics / CodePush 依赖;`apps/mobile-shell/scripts/check-config.mjs` 和 Expo public config smoke 会共同拒绝这些发布通道能力被提前打开,移动壳生产入口、HostBridge 和 URL/runtime 配置也不得提前初始化 Sentry、Firebase Analytics、PostHog、Amplitude、Segment、CodePush 或 Expo Updates。由于移动壳运行依赖会从根安装树解析,根 H5 `package.json` 也不得直接安装这些移动端发布通道、崩溃上报、analytics 或 CodePush SDK。
2026-06-18 追加:移动壳可分发身份、外观和默认权限进入配置门禁。Expo `name` 固定为 `Genarrative``slug` 固定为 `genarrative-mobile-shell``userInterfaceStyle` 固定为 `automatic``assetBundlePatterns` 固定为 `["**/*"]``extra.genarrativeHostBridgeVersion` 固定为 `1`Android `permissions` 默认不得显式请求任何权限,所有当前不需要的高风险权限只能通过 `blockedPermissions` 阻断,后续新增权限必须先有真实宿主能力、系统权限说明和 H5 fallback 方案,再补配置与检查。`apps/mobile-shell/scripts/check-config.mjs` 会检查源 `app.json``apps/mobile-shell/scripts/check-expo-config.mjs` 会检查 Expo CLI 最终解析出的 public config,避免 config plugin 或 Expo 解析阶段引入身份、资源或权限漂移。