Files
Commilitia-Drop/docs/client-build-install.md
T

349 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Commilitia Drop 全客户端构建与安装手册
本文记录 Web、服务端、Windows、macOS、iPhone 与 iPad 的正式构建、签名、安装和验证流程。
命令默认从仓库根目录执行。项目内部目录名和稳定系统身份可以继续使用 `cdrop`;所有用户可见名称、
协议和诊断界面统一使用 “Commilitia Drop” 或 `commilitia-drop` 命名空间。
## 1. 正式客户端矩阵
| 平台 | 唯一正式实现 | 架构/设备 | 正式产物 |
|---|---|---|---|
| Web | `web/` React SPA / PWA | 现代浏览器 | `web/dist/`,嵌入服务端 |
| Windows | `desktop/` Wails | x86-64 | `Commilitia Drop.exe` |
| macOS | `desktop/` Wails | Apple Silicon ARM64 | `Commilitia Drop.app``.dmg` |
| iPhone | `ios/CDrop` SwiftUI | 已登记真机 | `CommilitiaDrop.app` |
| iPad | `ios/CDrop` SwiftUI | 已登记真机 | 与 iPhone 共用 target |
`ios/CDrop` 中的原生 macOS target 只是迁移候选。它在功能对等、三语界面、签名扩展和真机验收
全部完成前,不得替代 Wails,也不得作为第二个 macOS 客户端发布。macOS 只考虑 ARM64。
## 2. 命名与兼容边界
- 用户可见产品名:`Commilitia Drop`,桌面应用名中不再出现 `Desktop`
- iOSiPadOS 登录回调:`commilitia-drop://auth-callback`
- WebRTC DataChannel 与 iOS 文件流 Scheme`commilitia-drop-file`
- Bonjour 服务类型:`_commilitia-drop._tcp`
- Auth Broker application key`commilitia-drop`。它会出现在 OAuth 参数和 JWT scope 中,属于
用户可见/可诊断协议文本。
- Bundle ID、App Group、Keychain service、LaunchAgent label、环境变量、数据库和配置目录不直接
决定显示名,保持稳定以保护系统权限、钥匙串数据和既有配置。
- 每个平台只保留上表的一份正式客户端;迁移验证成功后删除同平台旧名称副本。
命名复扫时应区分用户可见文本和内部身份。建议至少检查:
```sh
rg -n -i 'commilitia drop desktop|cdrop desktop|cdrop://|_cdrop\._tcp|cdrop-file' \
README.md docs auth desktop ios web
```
允许保留的典型内部值包括 `CDROP_*` 环境变量、`net.commilitia.cdrop` LaunchAgentBundle ID、
源码 package 和存储目录。若某个内部值直接、不可更改地成为系统显示名,则必须单独迁移。
## 3. 通用前置与密钥规则
本地需要 Go、Node.js、Wails v2、Just、Xcode Command Line Tools、XcodeGen,以及 iOS 依赖所需的
Swift Package Manager。环境配置放在仓库根目录、已被 Git 忽略的 `.env`;变量说明见
`.env.example`
签名和密钥遵循以下规则:
- 不在仓库记录 `.p8`、私钥、Broker internal key、VAPID 私钥或证书导出文件。
- iPhoneiPad 必须复用钥匙串中既有 Apple Development 证书。把其 SHA-1 写入
`CDROP_APPLE_DEVELOPMENT_IDENTITY`;recipe 会在构建前检查身份并把该值固定传给
`xcodebuild`。不得用 Xcode GUI,不得新建证书或修改私钥 ACL。
- macOS 正式分发必须复用既有 Developer ID Application 证书;完整身份名写入
`CDROP_DEVID_IDENTITY`
- App Store Connect API Key 只通过 `CDROP_ASC_KEY_PATH``CDROP_ASC_KEY_ID`
`CDROP_ASC_ISSUER_ID` 引用。
- 登录钥匙串必须已经解锁。`errSecInternalComponent` 通常表示签名进程不能使用私钥;先在用户的
普通 Terminal 解锁登录钥匙串,再重试同一证书,不要创建替代证书。
构建前可做基础检查:
```sh
git status --short
go version
node --version
just desktop-doctor
security find-identity -v -p codesigning
xcrun devicectl list devices
```
## 4. Web 与服务端
### 4.1 构建和验证 Web
```sh
just typecheck-front
just build-front
```
正式 Web 构建输出在 `web/dist/`。服务端通过嵌入静态文件提供 SPA、PWA manifest、service worker
和 iOS 原生引擎页,因此发布 Web 改动时必须重新构建服务端镜像,不能只替换单个 HTML 文件。
```sh
just test
just docker-image
```
部署新镜像后至少验证:
```text
/healthz
/api/auth/config
/site.webmanifest
/engine.html
```
`/api/auth/config` 应返回 `broker_app=commilitia-drop`manifest 的 `name``short_name` 均应为
“Commilitia Drop”。登录、扫码批准、设备续期和传输必须各做一次实际冒烟。
### 4.2 Auth Broker 原位迁移
Broker application 不创建并行副本,直接把既有 `cdrop` 项改为:
```text
key: commilitia-drop
callback: commilitia-drop://auth-callback
```
只需在修改前备份一次 Broker 配置;客户端和服务端源码由 Git 历史恢复,不另做文件备份。迁移后旧
session 可以全部失效,客户端重新登录。Broker、Caddy 和服务端的 application key 必须同时一致;
否则批准可以完成,但客户端会在兑换或 scope 校验阶段显示“登录失败”。
若 Caddyfile 以单文件 bind mount 进入容器,宿主机上的 `sed -i`/原子替换会生成新 inode,而运行
容器仍可能读旧 inode。修改后必须热加载,并从 Caddy admin API 或容器内实际挂载内容验证生效;
不能只查看宿主机路径。
## 5. macOS 正式客户端(Wails ARM64
### 5.1 开发构建
```sh
just desktop-build-mac
```
任务先构建最新 Web 前端,再执行 `wails build -clean -s -platform darwin/arm64`。输出为:
```text
desktop/build/bin/Commilitia Drop.app
```
`-clean` 是必要的:macOS 与 Windows 共用 `desktop/build/bin/`,另一平台的残留产物可能被 Wails/Go
误判为构建输入。不要把原生 macOS 候选 target 的产物放进正式分发目录。
### 5.2 Developer ID 签名、公证与 DMG
`.env` 配齐以下变量:
```text
CDROP_DEVID_IDENTITY
CDROP_ASC_KEY_PATH
CDROP_ASC_KEY_ID
CDROP_ASC_ISSUER_ID
```
然后运行:
```sh
just desktop-dist-mac
```
该 recipe 会依次完成:
1. ARM64 Wails 构建;
2. 使用既有 Developer ID Application 身份、hardened runtime 和 secure timestamp 签名 `.app`
3.`.app``ditto` 打包提交 Apple 公证,等待 `Accepted`,再 staplevalidate
4. 生成含 `.app``/Applications` 链接的压缩 DMG
5. 对 DMG 签名、单独提交公证并 staplevalidate
6. 用 Gatekeeper `spctl` 分别评估 app 和 DMG。
最终文件为 `desktop/build/bin/Commilitia Drop.dmg`。发布前再次检查:
```sh
codesign --verify --deep --strict --verbose=2 \
'desktop/build/bin/Commilitia Drop.app'
xcrun stapler validate 'desktop/build/bin/Commilitia Drop.app'
xcrun stapler validate 'desktop/build/bin/Commilitia Drop.dmg'
spctl --assess --type execute --verbose=2 \
'desktop/build/bin/Commilitia Drop.app'
spctl --assess --type open --context context:primary-signature --verbose=2 \
'desktop/build/bin/Commilitia Drop.dmg'
```
2026-07-31 已用既有 Developer ID 证书验证完整链路:app 与 DMG 均获 Apple `Accepted`,并完成
staple 和 Gatekeeper 的 `Notarized Developer ID` 评估。
### 5.3 本机安装
先验证新 app,再替换 `/Applications` 中的正式客户端;不保留第二个 `Desktop` 副本:
```sh
ditto 'desktop/build/bin/Commilitia Drop.app' \
'/Applications/Commilitia Drop.app'
```
LaunchAgent label `net.commilitia.cdrop` 是稳定内部身份,可以保留;但其 `ProgramArguments` 必须指向:
```text
/Applications/Commilitia Drop.app/Contents/MacOS/Commilitia Drop
```
更新磁盘 plist 后需要重新 bootstrap,不能只看文件,因为 launchd 可能仍缓存旧路径。最终检查已安装
app 的签名、公证、架构、进程路径,以及“登录后启动”开关。
## 6. Windows 正式客户端(Wails x64
### 6.1 构建
```sh
just desktop-build-win
```
输出为 `desktop/build/bin/Commilitia Drop.exe`。在 macOS 上交叉构建无需 MinGWWindows 特有通知
和 WebView2 绑定不依赖 Darwin CGO。当前 EXE 尚无 Authenticode 签名,Windows 会报告
`NotSigned`,并可能显示 SmartScreen 提示;获得 Windows 代码签名证书后应把签名步骤加入 recipe。
### 6.2 通过 mDNS 无代理直连安装
目标主机使用 `Desktop-C.local`、SSH 端口 `223`、用户 `commilitia`。访问该主机不得使用任何代理。
先确认 shell、系统和 SSH 配置没有代理:
```sh
env | rg -i '^(http|https|all|ftp|no)_proxy='
scutil --proxy
ssh -G -p 223 commilitia@Desktop-C.local | \
rg -i '^(hostname|user|port|proxycommand|proxyjump) '
```
mDNS 可能先返回不可达 IPv6,使 SSH 看似超时;继续保留 mDNS 主机名并用 `-4` 强制 IPv4。显式清除
代理变量、禁用 SSH 代理和跳板,并建立任务专用、10 分钟 TTL 的复用连接:
```sh
env -u HTTP_PROXY -u HTTPS_PROXY -u ALL_PROXY \
-u http_proxy -u https_proxy -u all_proxy \
ssh -4 -M -S /tmp/commilitia-drop-windows-%C \
-o ControlPersist=600 -o ProxyCommand=none -o ProxyJump=none \
-p 223 commilitia@Desktop-C.local exit
```
复用前用 `stat` 检查 socket 创建时间仍在 TTL 内,并执行 `ssh -O check`。安装流程为:
1. 在 Windows 上只读侦查 `D:\Tools`、匹配进程和
`HKCU\Software\Microsoft\Windows\CurrentVersion\Run`
2. 本地记录 EXE 的 SHA-256
3. 用同一 `-4``ProxyCommand=none``ProxyJump=none` 连接上传到用户目录暂存;
4. 远端再次校验 SHA-256
5. 停止旧 `D:\Tools\Commilitia Drop Desktop.exe` 进程;
6. 先复制为 `Commilitia Drop.installing.exe` 并再次校验,再原子移到
`D:\Tools\Commilitia Drop.exe`
7. 把既有 “Commilitia Drop” Run 项改为
`"D:\Tools\Commilitia Drop.exe" --hidden`
8. 只有新文件哈希正确后才删除旧 `Desktop` 文件与上传暂存文件;
9. 从 SSH 服务会话直接 `Start-Process` 可能因没有交互桌面而立即退出。使用当前用户完整 Windows
身份注册 `LogonType=Interactive` 的一次性计划任务,启动后立即删除任务;
10. 独立复核新进程在交互 Session、旧文件不存在、Run 项正确且应用日志无新错误。
2026-07-31 在 `Desktop-C.local` 已完成上述流程,正式路径为
`D:\Tools\Commilitia Drop.exe`,旧 `Desktop` 文件已删除,登录启动项和运行进程均指向新路径。
## 7. iPhone 与 iPad
两种设备共用 `CommilitiaDrop` scheme 和一套签名约束。全程使用 CLI,不打开 Xcode GUI。
### 7.1 模拟器验证
```sh
just ios-sim-build
```
该任务会拉取/生成品牌字体、运行 XcodeGen、解析 SPM 的 libwebrtc,并针对通用 iOS Simulator
目标编译。模拟器不需要 Apple 签名,但不能替代真机的 URL Scheme、本地网络、APNs、Share
Extension 和后台行为验收。
### 7.2 复用既有证书真机构建
`.env` 配齐:
```text
CDROP_TEAM_ID
CDROP_ASC_KEY_PATH
CDROP_ASC_KEY_ID
CDROP_ASC_ISSUER_ID
CDROP_APPLE_DEVELOPMENT_IDENTITY=<既有 Apple Development 证书 SHA-1>
```
确认设备与身份:
```sh
just ios-devices
security find-identity -v -p codesigning | \
rg -F "$CDROP_APPLE_DEVELOPMENT_IDENTITY"
```
分别覆盖安装 iPhone 与 iPad
```sh
just ios-device <iPhone-UDID>
just ios-device <iPad-UDID>
```
`ios-device` 会把 SHA-1 作为 `CODE_SIGN_IDENTITY` 固定传入 `xcodebuild`ASC API Key 仅用于自动
provisioning 的设备、能力和 profile 更新。若签名测试返回 `errSecInternalComponent`,应解锁当前
登录钥匙串后重试,不得生成新证书或修改私钥 ACL。
安装后验证:
- 设备端显示名为“Commilitia Drop”;
- Bundle ID 保持 `net.commilitia.Commilitia-Drop`
- `commilitia-drop://auth-callback` 已登记;
- 旧 session 失效时能进入登录页,经 Broker 批准后回到 app 并成功建立新 session
- iPhone 与 iPad 各自完成一次发送、接收、本地网络权限和后台/扩展冒烟。
更完整的真机能力清单见 `ios/CDrop/REALDEVICE.md`
## 8. 发布顺序与分发目录
Wails 的 macOS 和 Windows recipe 都用 `-clean` 且共享 `desktop/build/bin/`,因此不能假设两个产物
会同时保留。推荐固定顺序:
1. `just desktop-dist-mac`
2. 复制 `Commilitia Drop.dmg` 到分发目录;
3. `just desktop-build-win`
4. 复制 `Commilitia Drop.exe` 到分发目录;
5. 检查分发目录只保留这两个正式文件,不保留 `Commilitia Drop Desktop.*`
6. 记录两者 SHA-256。
当前分发目录约定为:
```text
~/Library/CloudStorage/Dropbox/软件客户端/Commilitia Drop/
```
不要把 `.app` bundle 当成 Dropbox 的正式发布物;macOS 使用已签名、公证、装订的 DMG。
## 9. 提交前验证矩阵
```sh
git diff --check
go test ./...
(cd desktop && go test ./...)
(cd web && npm run typecheck)
(cd web && npm run build)
just ios-sim-build
bash -n desktop/scripts/make-dmg.sh
just --dry-run desktop-dist-mac
```
平台产物还需验证:
| 对象 | 必验项 |
|---|---|
| Web/服务端 | health、auth config、manifest、登录、传输 |
| Mac appDMG | ARM64、Developer ID、hardened runtime、Accepted、staple、Gatekeeper |
| Windows EXE | PE32+ x86-64、SHA-256、唯一文件、Run 项、交互 Session 进程 |
| iPhoneiPad | 既有证书 SHA-1、签名验证、显示名、URL Scheme、Broker 登录、真机传输 |
提交时不加入 `.env``.p8`、构建产物、临时 PowerShell/安装脚本或 Broker 备份。客户端源码和构建
流程由 Git 历史恢复;Auth Broker 配置备份由服务端运维位置单独保留。