diff --git a/docs/apple-account-migration-runbook.html b/docs/apple-account-migration-runbook.html index 9b59e36..a99237b 100644 --- a/docs/apple-account-migration-runbook.html +++ b/docs/apple-account-migration-runbook.html @@ -66,23 +66,23 @@ 顺序很重要:先建 Apple 资产 → 我改代码 → 传 gitea → 验证首个构建。 -
代码替换需要美国账号的 10 位 Team ID。登录 developer.apple.com/account → 左栏 Membership details → Team ID(形如 A1B2C3D4E5)。把它发我,我就执行全量代码替换。本文中一律用 <NEW_TEAM> 占位。
44WULXM6SV)仓库代码(§3)已全量迁到美国身份并收敛成单一真相源 scripts/signing.env + codegen。剩下的是你在 Apple 后台建资产(§1)、本机公证凭据(§2)、gitea 换 secret(§4)、首个构建验证(§5)。建资产时把两张证书精确全名 + ASC Key 的 Key/Issuer ID 发我,我做 §2。
| 项 | 旧(中国,待清除) | 新(美国 Yanmei AI LLC) |
|---|---|---|
| Team ID | BYL4KQHMTN | <NEW_TEAM>(你提供) |
| Team ID | BYL4KQHMTN | 44WULXM6SV(你提供) |
| 法人实体(证书 CN 内含) | Yanmei (beijing) Technology Co., Ltd | Yanmei AI LLC |
| macOS 主 app Bundle ID | com.pangolin.pangolin | com.yanmeiai.pangolin |
| macOS 扩展 Bundle ID | com.pangolin.pangolin.PacketTunnel | com.yanmeiai.pangolin.PacketTunnel |
| iOS 主 app Bundle ID | com.pangolin.pangolinVpn | com.yanmeiai.pangolin |
| iOS 扩展 Bundle ID | com.pangolin.pangolinVpn.PacketTunnel | com.yanmeiai.pangolin.PacketTunnel |
| iOS App Group | group.com.pangolin.pangolinVpn | group.com.yanmeiai.pangolin |
macOS App Group(原生 <Team>. 格式) | BYL4KQHMTN.com.pangolin.pangolin | <NEW_TEAM>.com.yanmeiai.pangolin |
macOS NEMachServiceName | BYL4KQHMTN.com.pangolin.pangolin.PacketTunnel | <NEW_TEAM>.com.yanmeiai.pangolin.PacketTunnel |
macOS App Group(原生 <Team>. 格式) | BYL4KQHMTN.com.pangolin.pangolin | 44WULXM6SV.com.yanmeiai.pangolin |
macOS NEMachServiceName | BYL4KQHMTN.com.pangolin.pangolin.PacketTunnel | 44WULXM6SV.com.yanmeiai.pangolin.PacketTunnel |
iOS App Group 不含 Team ID(group. 前缀,跨账号可移植);macOS 用原生 <TeamID>.<name> 格式,Team 一换前缀必变——这也是必须改代码而非纯换证书的根本原因。旧 macOS 安装的登录态存在旧 App Group 容器里,切换后清空、用户需重登(重签本就如此,可接受)。
Identifiers → 右上下拉切到 App Groups → + → 填 group.com.yanmeiai.pangolin(Description 随意)。回到上面 4 个 App ID,编辑其 App Groups capability → Configure → 勾上这个 group。
macOS 端说明:macOS 用的是原生 <NEW_TEAM>.com.yanmeiai.pangolin(team 作用域容器,不带 group.),不需要在后台单独注册——只要 App ID 勾了 App Groups capability、且用该 Team 的证书签名即可生效。后台注册的 group.com.yanmeiai.pangolin 供 iOS 使用。
macOS 端说明:macOS 用的是原生 44WULXM6SV.com.yanmeiai.pangolin(team 作用域容器,不带 group.),不需要在后台单独注册——只要 App ID 勾了 App Groups capability、且用该 Team 的证书签名即可生效。后台注册的 group.com.yanmeiai.pangolin 供 iOS 使用。
用「钥匙串访问 → 证书助理 → 从证书颁发机构请求证书」生成一个 CertificateSigningRequest.certSigningRequest(存到磁盘),后台上传它换证书;下载后双击导入 login 钥匙串。
developerID_application.cer。distribution.cer。导入后,两张证书的主体会是 Developer ID Application: Yanmei AI LLC (<NEW_TEAM>) 与 Apple Distribution: Yanmei AI LLC (<NEW_TEAM>)。请把这两串完整名字发我(security find-identity -v -p codesigning 可打印),我要把它们精确写进 local_test.sh。
导入后,两张证书的主体会是 Developer ID Application: Yanmei AI LLC (44WULXM6SV) 与 Apple Distribution: Yanmei AI LLC (44WULXM6SV)。请把这两串完整名字发我(security find-identity -v -p codesigning 可打印),我要把它们精确写进 local_test.sh。
钥匙串里分别右键两张证书(连带私钥)→ 导出为 .p12,设一个导出密码(记进 Bitwarden,别写文件)。得到 developerID.p12 与 ios_dist.p12——第 4 节转 base64 传 gitea。
… Yanmei (beijing) Technology 两张证书,避免签名时误选旧身份。下述文件里的旧 Team ID / Bundle ID / App Group / 实体名一次性替换。改完 flutter build ios --no-codesign + macOS 构建自检,确保工程仍自洽。
已落地,且不再是「散落硬编码」。签名身份收敛成单一真相源,今后迁账号/改 Bundle ID 只改一个文件跑一次 codegen,不用再全仓找替换。
BYL4KQHMTN → <NEW_TEAM>| 文件 | 处 |
|---|---|
scripts/local_test.sh | TEAM_ID + 签名主体串 |
scripts/ci/compile-macos.sh | TEAM_ID=(App Group 由它派生) |
scripts/ci/compile-ios.sh | TEAM_ID= |
client/macos/Runner.xcodeproj/project.pbxproj | 6× DEVELOPMENT_TEAM |
client/ios/Runner.xcodeproj/project.pbxproj | 6× DEVELOPMENT_TEAM |
client/macos/Runner/Release.entitlements | App Group 值 |
client/macos/PacketTunnel/PacketTunnel.entitlements | App Group 值 |
client/macos/PacketTunnel/Info.plist | NEMachServiceName 前缀 |
client/macos/PacketTunnel/PacketTunnelProvider.swift | private let appGroup |
scripts/signing.envTeam ID / 实体名 / Bundle ID / App Group 全在这里(当前已是美国身份:Team 44WULXM6SV、Yanmei AI LLC、com.yanmeiai.pangolin)。三个签名脚本(local_test.sh / ci/compile-macos.sh / ci/compile-ios.sh)直接 source 它。
com.pangolin.* → com.yanmeiai.pangolin[.PacketTunnel])| 文件 | 处 |
|---|---|
client/macos/Runner.xcodeproj/project.pbxproj | PRODUCT_BUNDLE_IDENTIFIER(app / 扩展 / Tests)+ PRODUCT_NAME(扩展 = 标识符,铁律) |
client/ios/Runner.xcodeproj/project.pbxproj | PRODUCT_BUNDLE_IDENTIFIER(app + 扩展) |
macOS/iOS 各 *.entitlements | application-identifier、App Group 值、NEMachServiceName |
client/ios/{Runner,PacketTunnel} 的 Swift | appGroup 常量(group.com.pangolin.pangolinVpn → group.com.yanmeiai.pangolin) |
macOS Swift PacketTunnelProvider.swift | appGroup 常量 |
scripts/ci/compile-macos.sh / compile-ios.sh / local_test.sh | App Bundle ID / SYSEXT Bundle ID 常量 |
macOS 扩展铁律:PRODUCT_NAME 必须等于扩展 Bundle ID(com.yanmeiai.pangolin.PacketTunnel)——否则 sysext 无法 realize。见 macOS sysext 排障复盘。
Xcode/Swift 侧的标识符无法 source 变量、只能字面量,故由 node scripts/gen-signing.mjs 从 signing.env 结构化回填 16 个原生文件(两端 project.pbxproj 的 DEVELOPMENT_TEAM/Bundle ID、各 *.entitlements 的 App Group/app-identifier、macOS Info.plist 的 NEMachServiceName、各 Swift 的 appGroup/subsystem/loginHelper 等)。codegen 用「形状」匹配、不含任何旧字面值——自身无痕,未来再迁仍生效。
# 迁账号/改 Bundle ID 的唯一操作: +vim scripts/signing.env # 改 3 个基值 +node scripts/gen-signing.mjs # 回填全部原生文件-
scripts/local_test.sh 3 行签名主体串(SIGN_ID、IOS_EXPECT_SIGNER、注释)改成 1.4 你发我的证书精确全名。二进制里的签名主体来自证书,换证后自动为美国实体;这几行只是本机签名/自检时的匹配串。
ci/check-codegen-drift.sh 跑 gen-signing.mjs --check:若改了 signing.env 没重生成、或手改了原生标识符,即失败。与 token/l10n 同一套 codegen 单源治理。
docs/ 下多份历史文档写死了 BYL4KQHMTN 与中国实体名。这些是内部文档不进产物,但为彻底无痕,我会在同一批把 docs/ 里的 Team ID / 实体名一并改为新值或标注「已迁移」。
plutil -lint 全 OK;两端 project.pbxproj xcodebuild -list 可解析,Runner build settings 解析为新 Team/Bundle。gen-signing.mjs --check 幂等 0 drift;完整 codegen drift 闸(token/l10n/proto-i18n/signing)全绿。范围说明:未动 Android 包名 com.pangolin.pangolin_vpn(Play Store 身份、自签名、非 Apple 账号痕迹,改动会破坏 Play 更新,另议)与 Windows/桌面少量元数据串。codesign 层面 Apple 产物已零中国痕迹。
gitea → 仓库 wangjia/pangolin → Settings → Actions → Secrets(注意历史经验:Apple 签名 secret 配在 用户级非仓库级,见记忆 pangolin-apple-signing-assets——按你当初配的层级更新)。名字不变,只换值:
client-vX.Y.Z 触发 gitea 流水线,用新 secret 构建。首次建议先跑一次看签名步骤绿。codesign -dvvv # 看 Authority / TeamIdentifier Runner.app 2>&1 | grep -E "Authority|TeamIdentifier" -# 期望:Yanmei AI LLC + <NEW_TEAM>,无 BYL4KQHMTN / beijing+# 期望:Yanmei AI LLC + 44WULXM6SV,无 BYL4KQHMTN / beijing 再全仓
grep -rn "BYL4KQHMTN\|beijing" client scripts .gitea 应为空。codesign -dvvv:Authority = Yanmei AI LLC、TeamIdentifier = <NEW_TEAM>。codesign -dvvv:Authority = Yanmei AI LLC、TeamIdentifier = 44WULXM6SV。grep -rn "BYL4KQHMTN" client scripts .gitea docs → 空。grep -rin "beijing\|岩美" client scripts .gitea → 空。<NEW_TEAM>.com.yanmeiai.pangolin*。44WULXM6SV.com.yanmeiai.pangolin*。pangolin-notary 公证凭据(§2)