# cdrop iOS 真机分发手册

把 cdrop 装到你自己的 iPhone（开发签名）。代码侧全部就绪并经模拟器验证；真机只差**账号 + 签名**这一层。本手册走 **ASC API Key 自动 provisioning + 全 CLI** 路线——一把 App Store Connect API Key，`-allowProvisioningUpdates` 自动登记连接的设备 + 创建/更新 App ID / App Group / Push / profile / 开发证书，构建装机一条命令，**全程不碰 Xcode GUI、不必手动建 profile**（绕过手动 profile「设备列表只剩 Mac」的坑）。

## 包名与标识

| 项 | 值 |
|---|---|
| 主 app Bundle ID | `net.commilitia.Commilitia-Drop` |
| Share Extension | `net.commilitia.Commilitia-Drop.share` |
| 控件扩展 | `net.commilitia.Commilitia-Drop.widgets` |
| App Group | `group.net.commilitia.Commilitia-Drop` |
| APNs topic（服务端 `CDROP_APNS_TOPIC`） | `net.commilitia.Commilitia-Drop` |

## 前置
- 付费 Apple Developer Program（$99/年）。
- 一台 iPhone（iOS 26）+ Mac（Xcode 26 命令行工具）。
- 一个已登录的 cdrop（网页 / 桌面）——用来扫码批准本机登录。

---

## A. ASC API Key + .env（核心，一次性）

`-allowProvisioningUpdates` 凭一把 App Store Connect API Key 替你在门户自动登记设备、建/改 App ID（含 App Groups + Push 能力）、建 App Group、建 profile、建/下开发证书——**不必手动建 profile**。

**生成 API Key**：appstoreconnect.apple.com → **用户和访问** → **集成** → **App Store Connect API** → **团队密钥** → 「＋」→ 角色 **Admin**（要能管设备 / profile / 标识符）→ 命名 → 生成 → 下载 `AuthKey_XXXXX.p8`（**仅一次**）。记下三样：

- **Key ID**（密钥行里那串，10 位）
- **Issuer ID**（密钥页顶部，UUID 形）
- **Team ID**（账号 **Membership** 里，10 位）

**配 `.env`**（仓库根目录，已 gitignore，公开仓库不留账号凭据）：

```
CDROP_TEAM_ID=ABCDE12345
CDROP_ASC_KEY_PATH=/绝对路径/AuthKey_XXXXX.p8
CDROP_ASC_KEY_ID=XXXXXXXXXX
CDROP_ASC_ISSUER_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
```

`.p8` 放仓库外即可，`CDROP_ASC_KEY_PATH` 指它绝对路径（落本目录则被 `*.p8` 忽略）。

> 你若已在门户手动建过 App ID / App Group / 证书，自动 provisioning 会复用、不冲突。**「手动建 profile 时设备列表只剩 Mac」**＝那台 iPhone 在 **Devices** 里被登记成了 macOS 平台（登记表单 Platform 默认 macOS）；自动 provisioning 直接按连接的真机重登记，绕过此坑。

**顺手：APNs Auth Key**（发推送用，与上面 ASC Key 是两码事）：门户 **Keys** → ＋ → 勾 **Apple Push Notifications service** → 下载 `AuthKey_YYYYY.p8`（仅一次），记 Key ID + Issuer ID（服务端配，见 C）。

---

## B. 构建装机（全 CLI）

```sh
just ios-devices                 # 手机插 USB，读 UDID
just ios-device <你的设备UDID>   # 自动 provisioning 构建 + devicectl 装机
```

- `just ios-device` ＝ `xcodegen generate` → `xcodebuild -allowProvisioningUpdates`（凭 .env 的 ASC Key 自动签名 + 登记设备 + 建 profile）→ `xcrun devicectl device install app`。无 Xcode GUI。
- 首次装机后，iPhone 上首启该开发者 app 即可直接跑（付费 ADP 开发证书，无需手动「信任开发者」）。

---

## C. 服务端前置

1. **引擎可达**：真机上引擎 WebView 加载 `https://drop.commilitia.net/engine.html`——该文件随 cdrop 二进制部署到 prod（`//go:embed` 进 binary，`just docker-image` 含最新 `dist`）。手机要用，prod 须是含本轮改动的最新部署。
2. **APNs 真发**：把 A 里那把 **APNs Auth Key** `.p8` 放到服务器，给后端容器配 `CDROP_APNS_KEY_PATH` / `CDROP_APNS_KEY_ID` / `CDROP_APNS_TEAM_ID` / `CDROP_APNS_TOPIC=net.commilitia.Commilitia-Drop` / `CDROP_APNS_ENV`（Xcode 开发构建的 device token 属 **sandbox**，故联调填 `sandbox`）。缺配置则推送惰性关闭，其余功能照常。
3. 本机联调可选：环境变量 `CDROP_ENGINE_URL` 指向可达引擎。

---

## D. 只能真机验的清单

代码已实现，下列是真机才能验的点：

- [ ] 液态玻璃真机渲染（陀螺仪高光 / 动效）。
- [ ] 扫码登录：本机显码 → 已登录 cdrop 扫码批准 → 进主界面（强制 full/persist）。
- [ ] **本地网络权限 + 同内网直连**（R-iOS-6）：首次同内网传输弹 `NSLocalNetworkUsageDescription`；授予后 ICE 收 host 候选、走真直连；拒绝则回退中继仍可传。
- [ ] 发送 / 接收：选文件 → 选设备 → 对端收到；对端发来落 Files（Documents）。
- [ ] **大文件流式发送**（R-iOS-4 已实现）：发大文件，WebView 内存应有界（按 Range 块拉取，不整文件入内存）。
- [ ] **后台续传**（R-iOS-1 / R-iOS-3）：传输中切后台 → `BGContinuedProcessingTask` 系统进度 UI；验 WKWebView JS 是否随之保活（不保活则退化为回前台续传，可接受）。
- [ ] **APNs 推送**：离线设备收「收到文件」通知（需 C2 的 `.p8`）。
- [ ] **Share Extension**：别的 app 分享 → 选 Commilitia Drop → 唤起主 app 选设备发送。
- [ ] **控制中心剪贴板两控件**：控制中心加「上传 / 拉取剪贴板」控件 → 锁屏 / 解锁态点按 → 云剪贴板读写。
