From e6de69649b02180c32fd81c1f7878bb60907b893 Mon Sep 17 00:00:00 2001 From: kdletters Date: Thu, 18 Jun 2026 13:45:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B6=E5=8F=A3=E5=8E=9F=E7=94=9F=E5=A3=B3?= =?UTF-8?q?=E6=9C=AC=E5=9C=B0=E7=94=9F=E6=88=90=E7=89=A9=E8=BE=B9=E7=95=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 忽略Expo本地状态目录并保持导出烟测目录不入库 统一原生壳扫描排除Tauri schema和自动生成权限产物 更新原生壳方案和共享决策记录 --- .gitignore | 1 + docs/project-memory/shared-memory/decision-log.md | 8 ++++++++ ...架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md | 2 ++ scripts/check-native-shells.mjs | 10 ++++++++++ 4 files changed, 21 insertions(+) diff --git a/.gitignore b/.gitignore index 8de32f4a9..8d9a69f68 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ temp*build*/ /apps/desktop-shell/src-tauri/target/ /apps/desktop-shell/src-tauri/gen/ /apps/desktop-shell/src-tauri/permissions/autogenerated/ +/apps/mobile-shell/.expo/ /apps/mobile-shell/.expo-export-smoke/ /server-rs/.spacetimedb/ /server-rs/.data/ diff --git a/docs/project-memory/shared-memory/decision-log.md b/docs/project-memory/shared-memory/decision-log.md index 4806ebd31..80363cd26 100644 --- a/docs/project-memory/shared-memory/decision-log.md +++ b/docs/project-memory/shared-memory/decision-log.md @@ -73,6 +73,7 @@ - 2026-06-18 HostBridge capability / handler 关系门禁:两端壳声明 request method capability 时必须有对应 HostBridge handler;壳 handler 处理的 method 必须已被该壳声明,登录 / 支付等 SDK-backed method 只能保留明确 `unsupported_method` 路径。事件类 capability 不要求 request handler。 - 2026-06-18 桌面壳 CSP 分层:Tauri release `csp` 不得包含 `http://127.0.0.1:*`、`ws://127.0.0.1:*` 或其它本机调试源,本机 Vite、HMR WebSocket 和开发 frame 只允许出现在 `devCsp`。桌面壳配置检查会同时拒绝 release CSP 混入本机调试源、dev CSP 缺失本机开发源,以及 release / dev CSP 加入 `unsafe-eval`、`tauri:` 或 `file:`。 - 2026-06-18 壳生产代码禁用临时替身:Expo 与 Tauri 壳的生产源码和配置不得出现 mock / fake / placeholder / stub / TODO / FIXME 以及对应中文脚手架词;测试文件仍可使用 mock。两端壳配置检查会扫描生产入口、配置和壳实现,根级 `npm run check:native-shells` 也会统一扫描两端壳生产源码,防止把临时替身、占位文案或伪实现带进可分发壳。 +- 2026-06-18 原生壳本地生成物边界:Expo `.expo/`、Expo export smoke 临时目录、Tauri `target/`、Tauri schema `gen/` 和 Tauri 自动生成权限目录都必须保持 gitignored,不作为生产源码敏感词扫描输入;手写 capability / 权限配置仍在扫描范围内。 - 2026-06-18 移动壳启动页与 adaptive icon:Expo 移动壳启动页和 Android adaptive icon 复用现有真实品牌图标 `apps/mobile-shell/assets/icon.png`,背景色固定为 H5 壳根背景 `#fffdf9`。该 PNG 是 1024x1024 RGBA 透明前景品牌资产,不新增占位图;配置检查会校验图标尺寸、透明像素、splash 和 adaptive icon 指向,避免后续换成非品牌或占位素材。 - 2026-06-18 桌面壳 bundle 图标集:Tauri 桌面壳从现有真实品牌 PNG `apps/desktop-shell/src-tauri/icons/icon.png` 派生 `32x32.png`、`128x128.png`、`128x128@2x.png`、`icon.ico` 和 `icon.icns`,并在 `bundle.icon` 中同时声明这些平台图标。检查脚本会校验 PNG 尺寸、ICO 多尺寸头部、ICNS 容器长度和 bundle 图标列表,避免后续退回单图标或替换为非品牌 / 占位素材。 - 2026-06-18 移动壳网络安全元数据:Expo 移动壳默认包配置显式禁用 Android 明文流量 `usesCleartextTraffic=false`,iOS ATS 禁用任意加载 `NSAllowsArbitraryLoads=false`,并设置 `ITSAppUsesNonExemptEncryption=false` 作为当前未接入自定义加密能力的出口合规声明;本地 Vite 联调只通过 development build 显式环境变量进入,不把任意明文流量开关带进默认包配置。 @@ -2416,6 +2417,13 @@ - 影响范围:`apps/mobile-shell/scripts/check-config.mjs`、`apps/desktop-shell/scripts/check-config.mjs`、Expo / Tauri HostBridge 方案文档。 - 验证方式:`npm run check:native-shells`、`npm run mobile-shell:typecheck`、`npm run desktop-shell:typecheck`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。 +## 2026-06-18 原生壳本地生成物边界 + +- 背景:`npm run check:native-shells` 会生成 Expo `.expo/` 日志、Expo export smoke 临时目录、Tauri schema、Tauri 自动生成权限和 Rust `target/` 产物。这些文件是本机工具输出,不是生产源码;如果进入生产壳敏感词扫描或被误提交,会让门禁受工具版本、构建日志或自动生成格式影响。 +- 决策:`.gitignore` 显式忽略 Expo `.expo/`、Expo export smoke、Tauri `target/`、Tauri `gen/` 和 Tauri `permissions/autogenerated/`;根级 `check:native-shells` 的生产壳扫描同样排除这些本地生成目录,只扫描可提交的壳源码和配置。手写 capability / 权限配置仍保留在扫描范围内。 +- 影响范围:`.gitignore`、`scripts/check-native-shells.mjs`、Expo / Tauri HostBridge 方案文档。 +- 验证方式:`git check-ignore -v` 检查本地生成目录,`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,让壳边界绕过真实渠道契约。 diff --git a/docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md b/docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md index a3c3d5278..0ebd564ce 100644 --- a/docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md +++ b/docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md @@ -368,6 +368,8 @@ GameBridge 禁止: 2026-06-18 追加:两端壳的生产源码和配置禁止出现 mock / fake / placeholder / stub / TODO / FIXME 以及对应中文脚手架词;测试文件仍可使用 `vi.mock` 或等价测试替身。`apps/mobile-shell/scripts/check-config.mjs` 与 `apps/desktop-shell/scripts/check-config.mjs` 会扫描各自生产入口、配置和壳实现;根级 `npm run check:native-shells` 也会统一扫描 `apps/mobile-shell` 与 `apps/desktop-shell` 的生产源码,防止把临时替身或占位文案带进可分发壳。 +2026-06-18 追加:原生壳本地生成物不作为生产源码门禁输入。Expo `.expo/`、Expo export smoke 临时目录、Tauri `target/`、Tauri schema `gen/` 和 Tauri 自动生成权限目录都必须保持 gitignored;根级生产壳敏感词扫描只检查可提交的壳源码和配置,避免本机工具输出影响生产门禁。手写 capability / 权限配置仍需保留在扫描范围内。 + 2026-06-18 追加:移动壳启动页与 Android adaptive icon 复用现有真实品牌图标 `apps/mobile-shell/assets/icon.png`,背景色固定为 H5 壳根背景 `#fffdf9`。该 PNG 是 1024x1024 RGBA 透明前景品牌资产,不新增占位图;Expo `splash` 使用同一图标 `contain` 展示,Android `adaptiveIcon.foregroundImage` 使用同一透明前景图,`check-config.mjs` 会校验图标尺寸、透明像素、启动页和 adaptive icon 配置。 2026-06-18 追加:桌面壳 bundle 图标集从现有真实品牌 PNG `apps/desktop-shell/src-tauri/icons/icon.png` 派生,补齐 `32x32.png`、`128x128.png`、`128x128@2x.png`、`icon.ico` 和 `icon.icns`,Tauri `bundle.icon` 同时声明这些平台图标。没有引入外部素材或占位图;`apps/desktop-shell/scripts/check-config.mjs` 会校验 PNG 尺寸、ICO 多尺寸头部、ICNS 容器长度和 bundle 图标列表,避免后续退回单图标或替换为非品牌素材。 diff --git a/scripts/check-native-shells.mjs b/scripts/check-native-shells.mjs index 361590bc2..c2fe747bc 100644 --- a/scripts/check-native-shells.mjs +++ b/scripts/check-native-shells.mjs @@ -16,10 +16,15 @@ const productionShellExtensions = new Set([ '.tsx', ]); const productionShellExcludedSegments = new Set([ + '.expo', '.expo-export-smoke', 'node_modules', 'target', ]); +const productionShellExcludedPaths = new Set([ + 'apps/desktop-shell/src-tauri/gen', + 'apps/desktop-shell/src-tauri/permissions/autogenerated', +]); const productionShellDevScaffoldTerms = [ 'mo' + 'ck', 'fa' + 'ke', @@ -99,6 +104,11 @@ function shouldScanProductionShellFile(filePath) { } function collectProductionShellFiles(entryPath) { + const normalizedPath = entryPath.split(path.sep).join('/'); + if (productionShellExcludedPaths.has(normalizedPath)) { + return []; + } + const stats = fs.statSync(entryPath); if (stats.isDirectory()) { const name = path.basename(entryPath);