补齐桌面壳媒体权限说明

为 Tauri macOS 包加入摄像头和麦克风用途说明

将 macOS Info.plist 路径和文案纳入桌面壳配置门禁

同步宿主壳方案文档和项目共享决策记录
This commit is contained in:
2026-06-19 13:06:30 +08:00
parent 68d0208e2d
commit d4bc8fcddf
5 changed files with 41 additions and 0 deletions
@@ -13,6 +13,8 @@ const capabilityPath = new URL(
import.meta.url,
);
const capability = JSON.parse(fs.readFileSync(capabilityPath, 'utf8'));
const macInfoPlistPath = new URL('../src-tauri/Info.plist', import.meta.url);
const macInfoPlist = fs.readFileSync(macInfoPlistPath, 'utf8');
const buildScriptPath = new URL('../src-tauri/build.rs', import.meta.url);
const buildScript = fs.readFileSync(buildScriptPath, 'utf8');
const cargoManifestPath = new URL('../src-tauri/Cargo.toml', import.meta.url);
@@ -79,6 +81,7 @@ const desktopShellNetworkSource = fs.readFileSync(
const productionSourceRoots = [
new URL('../package.json', import.meta.url),
new URL('../src-tauri/Cargo.toml', import.meta.url),
new URL('../src-tauri/Info.plist', import.meta.url),
new URL('../src-tauri/build.rs', import.meta.url),
new URL('../src-tauri/capabilities/main.json', import.meta.url),
new URL('../src-tauri/src/', import.meta.url),
@@ -1419,6 +1422,28 @@ if (config.bundle?.active !== true || config.bundle?.targets !== 'all') {
throw new Error('desktop shell bundle targets must remain enabled for all platforms');
}
if (config.bundle?.macOS?.infoPlist !== 'Info.plist') {
throw new Error('desktop shell macOS bundle must merge the checked Info.plist');
}
for (const [key, value] of [
[
'NSCameraUsageDescription',
'允许 Genarrative 使用摄像头运行需要实时动作输入的同源 H5 体验。',
],
[
'NSMicrophoneUsageDescription',
'允许 Genarrative 使用麦克风运行需要实时声音输入的同源 H5 玩法。',
],
]) {
if (!macInfoPlist.includes(`<key>${key}</key>`)) {
throw new Error(`desktop shell macOS Info.plist missing ${key}`);
}
if (!macInfoPlist.includes(`<string>${value}</string>`)) {
throw new Error(`desktop shell macOS Info.plist ${key} text drifted`);
}
}
const csp = String(config.app?.security?.csp ?? '');
const devCsp = String(config.app?.security?.devCsp ?? '');
for (const blockedCspToken of ["'unsafe-eval'", 'tauri:', 'file:']) {
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSCameraUsageDescription</key>
<string>允许 Genarrative 使用摄像头运行需要实时动作输入的同源 H5 体验。</string>
<key>NSMicrophoneUsageDescription</key>
<string>允许 Genarrative 使用麦克风运行需要实时声音输入的同源 H5 玩法。</string>
</dict>
</plist>
@@ -31,6 +31,9 @@
"bundle": {
"active": true,
"targets": "all",
"macOS": {
"infoPlist": "Info.plist"
},
"icon": [
"icons/32x32.png",
"icons/128x128.png",
@@ -95,6 +95,7 @@
- 2026-06-18 HostBridge method 白名单跨壳门禁:`packages/shared/src/contracts/hostBridge.ts``HOST_BRIDGE_METHODS` 是唯一协议来源;Expo 壳 HostBridge 分发不得处理共享契约外 methodTauri 壳 Rust `HOST_BRIDGE_METHODS` 必须与共享契约逐项一致。新增宿主 method 必须先更新共享契约,再落两端壳实现或明确 unsupported。
- 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-19 桌面壳 macOS 媒体权限说明:Tauri 桌面壳不新增摄像头 / 麦克风 HostBridge method,但同源 H5 可以继续通过浏览器标准 `getUserMedia` 承接儿童动作热身 Demo 的实时摄像头输入和汪汪声浪正式 runtime 的实时麦克风输入;macOS 分发包必须通过 `bundle.macOS.infoPlist="Info.plist"` 合并 `NSCameraUsageDescription``NSMicrophoneUsageDescription`,文案只描述同源 H5 实时动作 / 声音玩法。桌面壳配置检查会校验 plist 路径与文案,防止缺少系统授权说明或把媒体权限扩成通用宿主采集能力。
- 2026-06-18 壳生产代码禁用临时替身:微信 / Expo / Tauri 三端壳的生产源码和配置不得出现 mock / fake / placeholder / stub / TODO / FIXME 以及对应中文脚手架词;测试文件仍可使用 mock。两端原生壳配置检查会扫描生产入口、配置和壳实现,根级 `npm run check:native-shells` 会统一扫描 `miniprogram``apps/mobile-shell``apps/desktop-shell`、H5 HostBridge transport 和共享 HostBridge 契约生产源码,防止把临时替身、占位文案或伪实现带进可分发壳或真实调用链。
- 2026-06-19 H5 HostBridge 调用链自动扫描:根级 `npm run check:native-shells``src/` 生产文件自动收集真实宿主能力 facade 的直接消费者,以及 `useHostLifecycleActive``useHostNetworkOnline``platformProfileHostClipboard` 等薄 wrapper 的消费者。H5 业务文件允许正常表单 `placeholder` 属性和业务占位图文案,但不得出现 mock / fake / stub / TODO / FIXME / 模拟 / 伪造等替身痕迹;壳源码和配置仍继续禁用 placeholder / 占位。
- 2026-06-18 原生壳本地生成物边界:Expo `.expo/`、Expo export smoke 临时目录、Tauri `target/`、Tauri schema `gen/` 和 Tauri 自动生成权限目录都必须保持 gitignored,不作为生产源码敏感词扫描输入;手写 capability / 权限配置仍在扫描范围内。
@@ -465,6 +465,8 @@ GameBridge 禁止:
2026-06-18 追加:桌面壳 release CSP 与 dev CSP 分离。Release `csp` 不再包含 `http://127.0.0.1:*``ws://127.0.0.1:*`,只允许打包资产、自身脚本、生产 HTTPS / WSS API、图片、媒体和 sandbox frame 所需来源;本地 Vite、HMR WebSocket 和开发 frame 只写入 Tauri `devCsp``apps/desktop-shell/scripts/check-config.mjs` 会拒绝 release CSP 混入本机调试源,也会校验 dev CSP 仍保留本机开发源。
2026-06-19 追加:桌面壳 macOS 媒体权限说明进入门禁。Tauri 桌面壳仍不新增摄像头或麦克风 HostBridge method,不把系统媒体能力暴露成桌面命令;同源 H5 页面可继续使用浏览器标准 `getUserMedia` 承接儿童动作热身 Demo 的实时摄像头输入和汪汪声浪正式 runtime 的实时麦克风输入。macOS 分发包必须通过 `bundle.macOS.infoPlist="Info.plist"` 合并受控用途说明:`NSCameraUsageDescription` 只描述同源 H5 实时动作输入,`NSMicrophoneUsageDescription` 只描述同源 H5 实时声音玩法。`apps/desktop-shell/scripts/check-config.mjs` 会校验 plist 路径和两条文案,防止桌面包缺少系统授权说明或把媒体权限扩写成通用采集能力。
2026-06-18 追加:桌面壳 release 构建烟测进入统一验收。`npm run check:native-shells` 会在 H5 HostBridge、Expo 壳和 Tauri 单测通过后执行 `npm run desktop-shell:build -- --no-bundle`,确认根 `dist` H5 资产、Tauri release 入口、受控命令白名单、图标和 Rust release 编译可以共同产出桌面二进制;该烟测不生成平台安装包,避免把 Linux 本机缺少的系统打包器误判为 HostBridge 回归。
2026-06-18 追加:移动壳 Expo managed config 烟测进入统一验收。`npm run check:native-shells` 会执行 `npm run mobile-shell:config`,在 `apps/mobile-shell` 目录内调用 `expo config --type public --json`,校验 Expo CLI 实际解析结果中的包名、scheme、深链、ATS / cleartext / backup / 相机与麦克风权限、启动页、adaptive icon、插件配置和 HostBridge 版本没有漂移。