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 → 验证首个构建。 -
-

⚠️ 动手前唯一的阻塞项:新 Team ID

-

代码替换需要美国账号的 10 位 Team ID。登录 developer.apple.com/account → 左栏 Membership detailsTeam ID(形如 A1B2C3D4E5)。把它发我,我就执行全量代码替换。本文中一律用 <NEW_TEAM> 占位。

+
+

✅ 进度:代码侧已完成(Team ID = 44WULXM6SV

+

仓库代码(§3)已全量迁到美国身份并收敛成单一真相源 scripts/signing.env + codegen。剩下的是你在 Apple 后台建资产(§1)、本机公证凭据(§2)、gitea 换 secret(§4)、首个构建验证(§5)。建资产时把两张证书精确全名 + ASC Key 的 Key/Issuer ID 发我,我做 §2。

0 · 命名总表(新账号下的目标身份)

- + - - + +
旧(中国,待清除)新(美国 Yanmei AI LLC)
Team IDBYL4KQHMTN<NEW_TEAM>(你提供)
Team IDBYL4KQHMTN44WULXM6SV(你提供)
法人实体(证书 CN 内含)Yanmei (beijing) Technology Co., LtdYanmei AI LLC
macOS 主 app Bundle IDcom.pangolin.pangolincom.yanmeiai.pangolin
macOS 扩展 Bundle IDcom.pangolin.pangolin.PacketTunnelcom.yanmeiai.pangolin.PacketTunnel
iOS 主 app Bundle IDcom.pangolin.pangolinVpncom.yanmeiai.pangolin
iOS 扩展 Bundle IDcom.pangolin.pangolinVpn.PacketTunnelcom.yanmeiai.pangolin.PacketTunnel
iOS App Groupgroup.com.pangolin.pangolinVpngroup.com.yanmeiai.pangolin
macOS App Group(原生 <Team>. 格式)BYL4KQHMTN.com.pangolin.pangolin<NEW_TEAM>.com.yanmeiai.pangolin
macOS NEMachServiceNameBYL4KQHMTN.com.pangolin.pangolin.PacketTunnel<NEW_TEAM>.com.yanmeiai.pangolin.PacketTunnel
macOS App Group(原生 <Team>. 格式)BYL4KQHMTN.com.pangolin.pangolin44WULXM6SV.com.yanmeiai.pangolin
macOS NEMachServiceNameBYL4KQHMTN.com.pangolin.pangolin.PacketTunnel44WULXM6SV.com.yanmeiai.pangolin.PacketTunnel

iOS App Group 不含 Team ID(group. 前缀,跨账号可移植);macOS 用原生 <TeamID>.<name> 格式,Team 一换前缀必变——这也是必须改代码而非纯换证书的根本原因。旧 macOS 安装的登录态存在旧 App Group 容器里,切换后清空、用户需重登(重签本就如此,可接受)。

@@ -105,7 +105,7 @@

1.3 创建 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 使用。

1.4 生成 2 张证书(Certificates)

用「钥匙串访问 → 证书助理 → 从证书颁发机构请求证书」生成一个 CertificateSigningRequest.certSigningRequest(存到磁盘),后台上传它换证书;下载后双击导入 login 钥匙串

@@ -113,7 +113,7 @@
  • Developer ID Application(macOS 站外分发 + 公证用)→ 下载 developerID_application.cer
  • Apple Distribution(iOS ad-hoc / App Store / TestFlight)→ 下载 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

    1.5 导出 .p12(给 CI 用)

    钥匙串里分别右键两张证书(连带私钥)→ 导出为 .p12,设一个导出密码(记进 Bitwarden,别写文件)。得到 developerID.p12ios_dist.p12——第 4 节转 base64 传 gitea。

    @@ -142,40 +142,28 @@
  • (可选)清理旧账号残留:删除 login 钥匙串里旧的 … Yanmei (beijing) Technology 两张证书,避免签名时误选旧身份。
  • -

    3 · 仓库代码全量替换 我做(拿到 Team ID + 证书全名后)

    -

    下述文件里的旧 Team ID / Bundle ID / App Group / 实体名一次性替换。改完 flutter build ios --no-codesign + macOS 构建自检,确保工程仍自洽。

    +

    3 · 仓库代码替换 已完成(单一真相源 + codegen)

    +

    已落地,且不再是「散落硬编码」。签名身份收敛成单一真相源,今后迁账号/改 Bundle ID 只改一个文件跑一次 codegen,不用再全仓找替换。

    -

    3.1 Team ID BYL4KQHMTN<NEW_TEAM>

    - - - - - - - - - - - -
    文件
    scripts/local_test.shTEAM_ID + 签名主体串
    scripts/ci/compile-macos.shTEAM_ID=(App Group 由它派生)
    scripts/ci/compile-ios.shTEAM_ID=
    client/macos/Runner.xcodeproj/project.pbxprojDEVELOPMENT_TEAM
    client/ios/Runner.xcodeproj/project.pbxprojDEVELOPMENT_TEAM
    client/macos/Runner/Release.entitlementsApp Group 值
    client/macos/PacketTunnel/PacketTunnel.entitlementsApp Group 值
    client/macos/PacketTunnel/Info.plistNEMachServiceName 前缀
    client/macos/PacketTunnel/PacketTunnelProvider.swiftprivate let appGroup
    +

    3.1 单一真相源 scripts/signing.env

    +

    Team ID / 实体名 / Bundle ID / App Group 全在这里(当前已是美国身份:Team 44WULXM6SVYanmei AI LLCcom.yanmeiai.pangolin)。三个签名脚本(local_test.sh / ci/compile-macos.sh / ci/compile-ios.sh)直接 source 它。

    -

    3.2 Bundle ID 换新(com.pangolin.*com.yanmeiai.pangolin[.PacketTunnel]

    - - - - - - - - -
    文件
    client/macos/Runner.xcodeproj/project.pbxprojPRODUCT_BUNDLE_IDENTIFIER(app / 扩展 / Tests)+ PRODUCT_NAME(扩展 = 标识符,铁律)
    client/ios/Runner.xcodeproj/project.pbxprojPRODUCT_BUNDLE_IDENTIFIER(app + 扩展)
    macOS/iOS 各 *.entitlementsapplication-identifier、App Group 值、NEMachServiceName
    client/ios/{Runner,PacketTunnel} 的 SwiftappGroup 常量(group.com.pangolin.pangolinVpngroup.com.yanmeiai.pangolin
    macOS Swift PacketTunnelProvider.swiftappGroup 常量
    scripts/ci/compile-macos.sh / compile-ios.sh / local_test.shApp Bundle ID / SYSEXT Bundle ID 常量
    -

    macOS 扩展铁律:PRODUCT_NAME 必须等于扩展 Bundle ID(com.yanmeiai.pangolin.PacketTunnel)——否则 sysext 无法 realize。见 macOS sysext 排障复盘

    +

    3.2 原生文件由 codegen 回填

    +

    Xcode/Swift 侧的标识符无法 source 变量、只能字面量,故由 node scripts/gen-signing.mjs 从 signing.env 结构化回填 16 个原生文件(两端 project.pbxprojDEVELOPMENT_TEAM/Bundle ID、各 *.entitlements 的 App Group/app-identifier、macOS Info.plistNEMachServiceName、各 Swift 的 appGroup/subsystem/loginHelper 等)。codegen 用「形状」匹配、不含任何旧字面值——自身无痕,未来再迁仍生效。

    +
    # 迁账号/改 Bundle ID 的唯一操作:
    +vim scripts/signing.env          # 改 3 个基值
    +node scripts/gen-signing.mjs      # 回填全部原生文件
    -

    3.3 实体名 → Yanmei AI LLC

    -

    scripts/local_test.sh 3 行签名主体串(SIGN_IDIOS_EXPECT_SIGNER、注释)改成 1.4 你发我的证书精确全名。二进制里的签名主体来自证书,换证后自动为美国实体;这几行只是本机签名/自检时的匹配串。

    +

    3.3 drift 闸防漂移

    +

    ci/check-codegen-drift.shgen-signing.mjs --check:若改了 signing.env 没重生成、或手改了原生标识符,即失败。与 token/l10n 同一套 codegen 单源治理。

    -

    3.4 文档去痕(可选但符合「无痕」要求)

    -

    docs/ 下多份历史文档写死了 BYL4KQHMTN 与中国实体名。这些是内部文档不进产物,但为彻底无痕,我会在同一批把 docs/ 里的 Team ID / 实体名一并改为新值或标注「已迁移」。

    +

    3.4 已验证

    + +

    范围说明:未动 Android 包名 com.pangolin.pangolin_vpn(Play Store 身份、自签名、非 Apple 账号痕迹,改动会破坏 Play 更新,另议)与 Windows/桌面少量元数据串。codesign 层面 Apple 产物已零中国痕迹。

    4 · gitea Secrets 换新 你做

    gitea → 仓库 wangjia/pangolin → Settings → Actions → Secrets(注意历史经验:Apple 签名 secret 配在 用户级非仓库级,见记忆 pangolin-apple-signing-assets——按你当初配的层级更新)。名字不变,只换值

    @@ -202,17 +190,17 @@
  • CI 发版:打 tag 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 应为空。
  • ✅ 无痕验收清单

    @@ -224,7 +212,7 @@ 1Apple 后台建 Team/App ID/Group/证书/Profile/ASC Key(§1)— 2把 Team ID + 两张证书全名 + ASC Key 信息发我1 3本机钥匙串核对 + 建 pangolin-notary 公证凭据(§2)2 -4仓库代码全量替换(§3)+ 构建自检2 +4仓库代码替换 → signing.env 单源 + codegen(§3)已完成— 5gitea 12 个 secret 换新值(§4)1 6本机 macOS/iOS 构建验证(§5.1–5.2)3,4 7打 tag 触发 CI 发版 + 无痕核验(§5.3–5.4)+4,5