@huoye/app-ship 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # App Ship
2
2
 
3
- 多平台应用商店上传引擎 — CLI 命令行工具 & npm 库,使用官方API来完成 APK / IPA / AAB / HAP 一键分发。
3
+ 本机凭据配置、在线体检与浏览器助手接入见 [发布凭据配置](docs/browser-credentials.md)。凭据仅留本机,上传仍需具体人工确认。
4
+
5
+ 多平台应用发布与分发引擎 — CLI 命令行工具 & npm 库,按平台真实动作处理测试分发、商店上传、草稿与送审。
4
6
 
5
7
  [![npm version](https://img.shields.io/npm/v/@huoye/app-ship.svg)](https://www.npmjs.com/package/@huoye/app-ship)
6
8
  [![npm downloads](https://img.shields.io/npm/dm/@huoye/app-ship.svg)](https://www.npmjs.com/package/@huoye/app-ship)
@@ -38,24 +40,38 @@ app-ship init
38
40
 
39
41
  这会生成 `app-ship.yaml` 配置文件。
40
42
 
41
- ### 3️⃣ 编辑配置文件
43
+ ### 3️⃣ 迁移凭据
44
+
45
+ 如果已有包含凭据或环境变量占位符的旧配置,先迁移到 macOS Keychain 与本地加密 vault:
46
+
47
+ ```bash
48
+ app-ship credentials migrate -c app-ship.yaml -o app-ship.safe.yaml
49
+ app-ship credentials list
50
+ ```
42
51
 
43
- 在 `app-ship.yaml` 中填入你的平台 API Key(从各平台官方后台申请):
52
+ 新配置只引用不含秘密的 `credentialProfile`:
44
53
 
45
54
  ```yaml
46
55
  publish:
47
56
  pgyer:
48
57
  enable: true
49
- apiKey: "YOUR_PGYER_API_KEY" # 替换为你的 API Key
58
+ credentialProfile: app-ship-pgyer
59
+ access:
60
+ type: public # 必须显式选择 public / password / invite
50
61
  ```
51
62
 
52
63
  ### 4️⃣ 上传应用
53
64
 
54
65
  ```bash
55
- app-ship upload -c app-ship.yaml -f app-release.apk
66
+ app-ship upload -c app-ship.safe.yaml -f app-release.apk
56
67
  ```
57
68
 
58
- ✅ 完成!应用已上传到所有启用的平台。
69
+ CLI 会先显示绑定产物 SHA-256 的发布计划。需要显式确认的平台应在核对后使用当前计划 ID 重跑:
70
+
71
+ ```bash
72
+ app-ship upload -c app-ship.safe.yaml -f app-release.apk \
73
+ --confirm-plan <preview 中的 planId>
74
+ ```
59
75
 
60
76
  > 💡 需要上传到特定平台?使用 `--platform` 参数:
61
77
  >
@@ -67,11 +83,14 @@ app-ship upload -c app-ship.yaml -f app-release.apk
67
83
 
68
84
  ## 特性
69
85
 
86
+ 荣耀、魅族、三星新增渠道已进入开发分支,支持 APK 与本机自动凭据配置,尚待真实账号验收;独立 MCP 默认不接入这三家。火叶原生管理 App 的可信执行包可显式启用已授权的十二渠道合同,新增商店预览必须提供 configPath,并绑定配置中的账号引用、应用 ID 和目标指纹;工具参数不能启用此范围。具体动作边界见[发布凭据配置](docs/browser-credentials.md#flu-cli-新增渠道2026-10-17)。
87
+
70
88
  - **8 大平台实测通过** ✅:蒲公英、华为、小米、OPPO、vivo、腾讯应用宝、App Store、鸿蒙
71
89
  - **并行上传**:多平台同时上传,可配置并发数
72
90
  - **智能分发**:自动路由 APK → Android 商店、IPA → Apple、HAP → 鸿蒙
91
+ - **两类发布目标**:测试分发渠道与正式商店渠道使用同一套产物校验、计划和回执
73
92
  - **指数退避重试**:网络波动自动重试,可配置退避策略
74
- - **YAML 单配置**:一个配置文件管理所有平台凭据
93
+ - **安全发布合同**:发布计划绑定平台、动作、包名、版本和产物 SHA-256
75
94
  - **三种使用方式**:CLI 命令行、npm 库、VSCode 插件
76
95
  - **框架无关**:Flutter、React Native、原生 Android/iOS、鸿蒙均可使用
77
96
  - **官方 API**:直接调用各平台官方 API,无第三方转接,透明开源
@@ -96,10 +115,14 @@ app-ship upload -c app-ship.yaml -f app-release.apk
96
115
  # 仅上传到指定平台
97
116
  app-ship upload -c app-ship.yaml -f app-release.apk --platform pgyer,huawei
98
117
 
99
- # Google Play 必须在核对预览后显式确认,首版只进入 internal 草稿
118
+ # Google Play 必须确认当前产物对应的计划,按配置保存 internal 或 production 草稿,不送审或上线
100
119
  app-ship upload -c app-ship.yaml -f app-release.aab \
101
120
  --platform google_play \
102
- --confirm-google-play
121
+ --confirm-plan <planId>
122
+
123
+ # 将旧 YAML 凭据迁移到本机安全存储,并输出不含秘密的新配置
124
+ app-ship credentials migrate -c app-ship.yaml -o app-ship.safe.yaml
125
+ app-ship credentials list
103
126
 
104
127
  # 带元数据上传
105
128
  app-ship upload -c app-ship.yaml -f app-release.apk \
@@ -121,16 +144,16 @@ app-ship --version
121
144
 
122
145
  **CLI 参数说明**:
123
146
 
124
- | 参数 | 简写 | 说明 |
125
- | -------------------- | ---- | ---------------------------- |
126
- | `--config <path>` | `-c` | 配置文件路径 (YAML) |
127
- | `--file <path>` | `-f` | 安装包路径 (APK/IPA/AAB/HAP) |
128
- | `--platform <list>` | `-p` | 逗号分隔的平台列表(可选) |
129
- | `--version <ver>` | `-v` | 版本号(默认:"1.0.0") |
130
- | `--build-number <n>` | `-b` | 构建号(默认:"1") |
131
- | `--changelog <text>` | - | 更新日志 |
132
- | `--confirm-google-play` | - | 确认上传 Google Play internal 草稿 |
133
- | `--verbose` | - | 显示详细输出 |
147
+ | 参数 | 简写 | 说明 |
148
+ | ---------------------- | ---- | ----------------------------- |
149
+ | `--config <path>` | `-c` | 配置文件路径 (YAML) |
150
+ | `--file <path>` | `-f` | 安装包路径 (APK/IPA/AAB/HAP) |
151
+ | `--platform <list>` | `-p` | 逗号分隔的平台列表(可选) |
152
+ | `--version <ver>` | `-v` | 版本号(默认:"1.0.0") |
153
+ | `--build-number <n>` | `-b` | 构建号(默认:"1") |
154
+ | `--changelog <text>` | - | 更新日志 |
155
+ | `--confirm-plan <ids>` | - | 确认预览中的一个或多个计划 ID |
156
+ | `--verbose` | - | 显示详细输出 |
134
157
 
135
158
  上传完成后会自动在 `~/.flu-cli/release-receipts/` 保存项目隔离的结构化回执。回执只记录产物路径、大小、SHA-256、渠道状态和白名单远端标识;不会保存 Token、密钥、服务账号内容或完整平台响应。每个项目最多保留 100 条。
136
159
 
@@ -138,68 +161,87 @@ app-ship --version
138
161
 
139
162
  ### 2️⃣ npm 库(编程集成)
140
163
 
141
- 适合自建发布系统或集成到现有工作流。
164
+ `UploadManager` 与各平台 adapter 是可信进程内的低层能力,不会替调用方生成发布计划或取得用户确认,不能直接暴露给 MCP、Web 请求或其它不可信入口。
165
+ CLI `upload` 和导出的 `executeReleasePlan(s)` 共享同一条可信本机编排:先绑定产物生成每个平台的
166
+ `ReleasePlan`,再校验人工提供的 `ReleaseConfirmation`,二次核对普通文件、SHA-256、包名和版本,随后才解析 Profile 并调用低层上传器。
167
+ MCP 的 `execute_release` 也只通过这条执行边界工作:宿主必须逐平台弹出人工确认,确认结果不会由模型参数传入,执行器仍会重新校验计划、产物和 Profile。
168
+
169
+ **可信本地集成**:
142
170
 
143
- **多平台上传**:
171
+ 以下展示可信本地发布执行边界。`confirmation` 必须来自用户核对过的当前计划;调用方不得记录或序列化
172
+ 解析后的配置,也不得跳过执行器的二次产物校验:
144
173
 
145
174
  ```typescript
146
- import { UploadManager, ConfigValidator } from "@huoye/app-ship";
175
+ import {
176
+ ConfigValidator,
177
+ createReleasePlan,
178
+ createDefaultCredentialProfileStore,
179
+ executeReleasePlan,
180
+ } from '@huoye/app-ship'
181
+
182
+ const config = ConfigValidator.loadAndValidate('./app-ship.yaml')
183
+ if (!config) throw new Error('配置无效')
184
+ const plan = createReleasePlan({
185
+ platform: 'google_play',
186
+ action: 'create_draft',
187
+ packageName: 'com.example.app',
188
+ versionName: '1.0.0',
189
+ buildNumber: '1',
190
+ artifact: { path: './app-release.aab', sha256: '<sha256>', sizeBytes: 123 },
191
+ credentialProfile: 'play-production',
192
+ })
193
+ const result = await executeReleasePlan({
194
+ plan,
195
+ confirmation: {
196
+ planId: plan.planId,
197
+ platform: plan.platform,
198
+ action: plan.action,
199
+ artifactSha256: plan.artifact.sha256,
200
+ confirmedAt: new Date().toISOString(),
201
+ },
202
+ config,
203
+ projectRoot: process.cwd(),
204
+ dependencies: { credentialStore: createDefaultCredentialProfileStore() },
205
+ })
206
+ console.log(result.receipt.id)
207
+ ```
147
208
 
148
- // 加载并验证配置
149
- const config = ConfigValidator.loadAndValidate("./app-ship.yaml");
209
+ ---
150
210
 
151
- // 创建上传管理器
152
- const manager = new UploadManager({
153
- maxConcurrent: 3, // 最大并发数
154
- continueOnError: true, // 部分失败后继续
155
- verbose: true, // 显示详细日志
156
- });
211
+ ### 3️⃣ 本机 MCP(AI 宿主集成)
157
212
 
158
- // 执行上传
159
- const report = await manager.uploadToMultiplePlatforms(
160
- "./app-release.apk",
161
- config,
162
- {
163
- version: "2.0.0",
164
- buildNumber: "42",
165
- changelog: "修复了已知问题",
166
- },
167
- );
168
-
169
- // 查看结果
170
- console.log(`成功: ${report.successCount}, 失败: ${report.failureCount}`);
171
- for (const result of report.results) {
172
- if (result.success) {
173
- console.log(`✅ ${result.platform}: ${result.url || result.consoleUrl}`);
174
- } else {
175
- console.log(`❌ ${result.platform}: ${result.message}`);
176
- }
177
- }
213
+ App Ship 现在提供独立的 `app-ship-mcp` 本机 MCP 入口,供 OpenHands、Codex 等 MCP 宿主读取并执行发布能力。当前提供十一个工具,分别覆盖五项产物/执行能力与六项账号配置/核验能力:
214
+
215
+ - `inspect_artifact`:读取安装包真实格式、包名、版本、构建号、大小和 SHA-256
216
+ - `preview_release`:生成测试分发或商店发布的 `ReleasePlan`,不读取凭据、不执行远端动作
217
+ - `preview_draft_upload`:生成绑定产物的草稿上传 `ReleasePlan`,不读取凭据、不上传
218
+ - `list_release_receipts`:读取脱敏的本地发布回执摘要
219
+ - `execute_release`:在宿主通过 MCP elicitation 取得逐平台人工确认后,重新校验并执行上传,返回脱敏发布回执
220
+ - `begin_credential_setup`、`credential_setup_status`、`complete_credential_setup`、`cancel_credential_setup`:管理明确项目的本机账号配置任务,不上传安装包
221
+ - `preflight_release`、`verify_credential_profile`:只读核验凭据与目标,不等于实际上传已通过
222
+
223
+ 构建并启动:
224
+
225
+ ```bash
226
+ npm run build
227
+ node dist/mcp.js
178
228
  ```
179
229
 
180
- **单平台上传**:
230
+ MCP 入口使用 Node.js 20 或更高版本,SDK 会打包进 MCP 可执行文件;现有 App Ship CLI / npm 库仍保持 Node.js 18 的声明。`execute_release` 需要宿主支持 MCP elicitation;用户拒绝或宿主不支持确认时不会读取凭据或发起上传。
181
231
 
182
- ```typescript
183
- import { PgyerUploader } from "@huoye/app-ship";
184
-
185
- const uploader = new PgyerUploader();
186
- const result = await uploader.upload(
187
- "./app-release.apk",
188
- { enable: true, apiKey: "YOUR_API_KEY" },
189
- { version: "1.0.0", buildNumber: "1", changelog: "首次发布" },
190
- );
191
-
192
- if (result.success) {
193
- console.log(`✅ 下载地址: ${result.url}`);
194
- console.log(`✅ 二维码: ${result.qrCode}`);
195
- } else {
196
- console.log(`❌ 失败: ${result.message}`);
197
- }
232
+ 确认流程兼容 2025 年协议的 `elicitation/create` 与 `2026-07-28` 协议的 `input_required`。确认状态由服务器签名,十分钟内有效且只能使用一次;确认期间修改配置目标、发布参数或产物会阻断执行。宿主取消会在上传开始前阻断执行,已开始的远端请求仍需根据回执判断结果,不能自动重试。
233
+
234
+ Codex 本机接入示例(先构建,再把路径替换为实际绝对路径):
235
+
236
+ ```bash
237
+ codex mcp add app-ship -- /absolute/path/to/node /absolute/path/to/app-ship/dist/mcp.js
198
238
  ```
199
239
 
240
+ 大文件上传建议在宿主配置的 `[mcp_servers.app-ship]` 中设置 `tool_timeout_sec = 600`。重新加载 MCP 后先检查十一个工具和拒绝确认行为,再执行真实草稿上传;Android APK 与 Harmony App Pack 是不同产物,应分别执行。
241
+
200
242
  ---
201
243
 
202
- ### 3️⃣ VSCode 插件(可视化)
244
+ ### 4️⃣ VSCode 插件(可视化)
203
245
 
204
246
  安装 **Flu CLI** VSCode 插件,在 IDE 内点击操作即可完成构建和上传。
205
247
 
@@ -218,30 +260,34 @@ if (result.success) {
218
260
 
219
261
  本工具直接调用各平台**官方 API**,所有 API 地址和文档均为平台官方提供。
220
262
 
221
- | 平台 | 文件 | 认证 | 官方 API 文档 | 状态 |
222
- | ---------------------- | -------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
223
- | 🐧 **蒲公英** | APK, IPA | API Key | [pgyer.com/api](https://www.pgyer.com/doc/view/api_basic) | ✅ 已实测 |
224
- | 🟥 **华为** | APK, AAB | OAuth2 | [AppGallery Connect](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/publish-app-0000001100974822) | ✅ 已实测 |
225
- | 🔴 **小米** | APK | RSA 签名 | [小米开放平台](https://dev.mi.com/console/doc/detail?pId=1695) | ✅ 已实测 |
226
- | 🟠 **OPPO** | APK | HMAC-SHA256 | [OPPO 开发者平台](https://open.oppomobile.com/wiki/doc#id=10106) | ✅ 已实测 |
227
- | 🔵 **vivo** | APK | HMAC + MD5 | [vivo 开放平台](https://dev.vivo.com.cn/openAbility/interface) | ✅ 已实测 |
228
- | 🐧 **腾讯应用宝** | APK | HMAC-SHA256 | [应用宝平台](https://open.qq.com/doc/?id=11016) | ✅ 已实测 |
229
- | 🍎 **Apple App Store** | IPA | Apple ID / API | [App Store Connect API](https://developer.apple.com/app-store-connect/api/) | ✅ 已实测 |
230
- | 🟣 **鸿蒙** | HAP | OAuth2 | [AppGallery Connect](https://developer.huawei.com/consumer/cn/doc/development/AppGallery-connect-Guides/agcapi-getstarted-0000001111209402) | ✅ 已实测 |
231
- | 🍎 **TestFlight** | IPA | Apple API | [TestFlight API](https://developer.apple.com/testflight/testers/) | ⚠️ 开发中 |
232
- | 🍎 **Ad Hoc** | IPA | 证书 | [Apple 文档](https://developer.apple.com/documentation/xcode/distributing-your-app-for-beta-testing) | ⚠️ 开发中 |
233
- | 🎮 **Google Play** | AAB | Service Account | [Android Publisher API](https://developers.google.com/android-publisher/api-ref/rest) | ✅ internal 草稿已实测 |
263
+ | 平台 | 文件 | 认证 | 官方 API 文档 | 状态 |
264
+ | ---------------------- | ------------ | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- |
265
+ | 🐧 **蒲公英** | APK, IPA | API Key | [pgyer.com/api](https://www.pgyer.com/doc/view/api_basic) | ✅ 已实测 |
266
+ | 🟥 **华为** | APK, AAB | OAuth2 | [AppGallery Connect](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/publish-app-0000001100974822) | ✅ 已实测 |
267
+ | 🔴 **小米** | APK | RSA 签名 | [小米开放平台](https://dev.mi.com/console/doc/detail?pId=1695) | ✅ 已实测 |
268
+ | 🟠 **OPPO** | APK | HMAC-SHA256 | [OPPO 开发者平台](https://open.oppomobile.com/wiki/doc#id=10106) | ✅ 已实测 |
269
+ | 🔵 **vivo** | APK | HMAC + MD5 | [vivo 开放平台](https://dev.vivo.com.cn/openAbility/interface) | ✅ 已实测 |
270
+ | 🐧 **腾讯应用宝** | APK | HMAC-SHA256 | [应用宝平台](https://open.qq.com/doc/?id=11016) | ✅ 已实测 |
271
+ | 🍎 **Apple App Store** | IPA | Apple ID / API | [App Store Connect API](https://developer.apple.com/app-store-connect/api/) | ✅ 已实测 |
272
+ | 🟣 **鸿蒙** | HAP | OAuth2 | [AppGallery Connect](https://developer.huawei.com/consumer/cn/doc/development/AppGallery-connect-Guides/agcapi-getstarted-0000001111209402) | ✅ 已实测 |
273
+ | 🍎 **TestFlight** | IPA | Apple API | [TestFlight API](https://developer.apple.com/testflight/testers/) | ⚠️ 开发中 |
274
+ | 🍎 **Ad Hoc** | IPA | 证书 | [Apple 文档](https://developer.apple.com/documentation/xcode/distributing-your-app-for-beta-testing) | ⚠️ 开发中 |
275
+ | 🎮 **Google Play** | AAB | Service Account | [Android Publisher API](https://developers.google.com/android-publisher/api-ref/rest) | ✅ internal 草稿已实测 |
276
+ | **荣耀** | APK | Client ID/Secret | [官方发布接口](https://developer.honor.com/cn/doc/guides/101359) | 草稿,待真实账号验收 |
277
+ | **魅族** | APK(64 位) | Client ID/Secret + SHA-256 签名 | [官方开放接口](https://open.flyme.cn/docs?id=333) | 仅文件上传,待真实账号验收 |
278
+ | **Samsung** | APK | Service Account + RS256 | [Galaxy Store API](https://developer.samsung.com/galaxy-store/galaxy-store-developer-api.html) | 草稿,待真实账号验收 |
234
279
 
235
280
  ---
236
281
 
237
282
  ## 详细配置参考
238
283
 
239
- ### 完整的 app-ship.yaml 配置
284
+ ### 安全的 app-ship.yaml 配置
240
285
 
241
- 所有 API 地址均来自官方平台,凭证需从各平台官方后台申请。
286
+ 所有凭据从平台官方后台申请,但 YAML 只保存 `credentialProfile` 引用。旧配置用
287
+ `app-ship credentials migrate` 一次性导入;迁移命令拒绝覆盖源文件。
242
288
 
243
289
  ```yaml
244
- version: "1.0.0"
290
+ version: '1.0.0'
245
291
 
246
292
  # 重试策略(可选)
247
293
  retry:
@@ -254,94 +300,86 @@ publish:
254
300
  # ── 蒲公英 (官方 API: https://www.pgyer.com/doc/view/api_basic) ──
255
301
  pgyer:
256
302
  enable: true
257
- apiKey: "${PGYER_API_KEY}"
258
- description: "测试版本"
303
+ credentialProfile: app-ship-pgyer
304
+ description: '测试版本'
305
+ access:
306
+ type: password
259
307
 
260
308
  # ── 华为 (官方 API: https://developer.huawei.com/consumer/cn/service/josp/agc/index.html) ──
261
309
  huawei:
262
310
  enable: false
263
- auth:
264
- clientId: "${HUAWEI_CLIENT_ID}"
265
- clientSecret: "${HUAWEI_CLIENT_SECRET}"
266
- appId: "YOUR_APP_ID"
311
+ credentialProfile: app-ship-huawei
312
+ appId: 'YOUR_APP_ID'
313
+ packageName: 'com.example.app'
267
314
  releaseType: draft
268
315
 
269
316
  # ── 小米 (官方 API: https://dev.mi.com/console/doc/detail?pId=1695) ──
270
317
  xiaomi:
271
318
  enable: false
272
- auth:
273
- userName: "your@email.com"
274
- privateKey: "${XIAOMI_KEY}"
275
- packageName: "com.example.app"
319
+ credentialProfile: app-ship-xiaomi
320
+ packageName: 'com.example.app'
276
321
 
277
322
  # ── OPPO (官方 API: https://open.oppomobile.com/wiki/doc#id=10106) ──
278
323
  oppo:
279
324
  enable: false
280
- auth:
281
- clientId: "${OPPO_CLIENT_ID}"
282
- clientSecret: "${OPPO_CLIENT_SECRET}"
325
+ credentialProfile: app-ship-oppo
283
326
 
284
327
  # ── vivo (官方 API: https://dev.vivo.com.cn/openAbility/interface) ──
285
328
  vivo:
286
329
  enable: false
287
- auth:
288
- accessKey: "${VIVO_ACCESS_KEY}"
289
- accessSecret: "${VIVO_ACCESS_SECRET}"
330
+ credentialProfile: app-ship-vivo
290
331
 
291
332
  # ── 腾讯应用宝 (官方 API: https://open.qq.com/doc/?id=11016) ──
292
333
  tencent:
293
334
  enable: false
294
- auth:
295
- userId: "${TENCENT_USER_ID}"
296
- appId: "${TENCENT_APP_ID}"
297
- accessSecret: "${TENCENT_SECRET}"
335
+ credentialProfile: app-ship-tencent
298
336
 
299
337
  # ── 鸿蒙 (官方 API: https://developer.huawei.com/consumer/cn/doc/development/AppGallery-connect-Guides/agcapi-getstarted-0000001111209402) ──
300
338
  harmony:
301
339
  enable: false
302
- auth:
303
- clientId: "${HARMONY_CLIENT_ID}"
304
- clientSecret: "${HARMONY_CLIENT_SECRET}"
305
- appId: "YOUR_APP_ID"
340
+ credentialProfile: app-ship-harmony
341
+ appId: 'YOUR_APP_ID'
342
+ packageName: 'com.example.app'
306
343
 
307
344
  # ── App Store / TestFlight (官方 API: https://developer.apple.com/app-store-connect/api/) ──
308
345
  app_store:
309
346
  enable: false
310
347
  mode: app_store
311
- auth:
312
- appleId: "${APPLE_ID}"
313
- appPassword: "${APP_PASSWORD}"
348
+ credentialProfile: app-ship-app_store
314
349
 
315
- # ── Google Play(首版仅上传内部测试草稿;API 轨道标识为 internal)──
350
+ # ── Google Play(保存 internal 或 production 草稿,不送审或上线)──
316
351
  google_play:
317
352
  enable: false
318
- auth:
319
- serviceAccountJsonPath: "./service-account.json"
320
- packageName: "com.example.app"
353
+ credentialProfile: app-ship-google_play
354
+ packageName: 'com.example.app'
321
355
  track: internal
322
356
  ```
323
357
 
324
358
  Google Play 连接器只从用户本机读取服务账号文件,并直接请求 Android Publisher API。
325
- 应用需已在 Play Console 创建且包名一致;首版只接受 AAB,并固定写入 `internal` 轨道的
326
- `draft` 发布记录,不提交审核,也不发布到测试用户或生产用户。
359
+ 应用需已在 Play Console 创建且包名一致;只接受 AAB,按明确配置保存 internal 或 production 草稿。
360
+ production 在发送 AAB 前原样校验本次未提交事务;失败不发送包、不提交并清理事务。
361
+ 服务账号须有目标应用的生产轨道权限,测试轨道权限不能替代;本机工具不自动增加权限。
362
+ 当前真实成功证据仍为 internal,production 代码及夹具通过不等于商店实传通过。
327
363
  如果应用从未上传过 APK/AAB,需先在 Play Console 手工上传并保存首个版本,之后才能使用
328
- Edits API;CLI 上传还必须显式提供 `--confirm-google-play`。
364
+ Edits API;CLI 上传还必须显式提供预览中的 `--confirm-plan <planId>`。
329
365
 
330
366
  ### 环境变量支持
331
367
 
332
- 配置值支持 `${VAR_NAME}` 语法引用环境变量,避免敏感信息硬编码:
368
+ 旧配置在迁移时仍可使用 `${VAR_NAME}`。迁移完成后,安全配置只保留 Profile:
333
369
 
334
370
  ```yaml
335
371
  pgyer:
336
372
  enable: true
337
- apiKey: ${PGYER_API_KEY} # 运行时自动替换
373
+ credentialProfile: app-ship-pgyer
374
+ access:
375
+ type: invite
338
376
  ```
339
377
 
340
378
  在 CI/CD 中设置环境变量即可:
341
379
 
342
380
  ```bash
343
381
  export PGYER_API_KEY="your-actual-key"
344
- app-ship upload -c app-ship.yaml -f app.apk
382
+ app-ship credentials migrate -c app-ship.legacy.yaml -o app-ship.yaml
345
383
  ```
346
384
 
347
385
  ---
@@ -382,28 +420,15 @@ app-ship upload -c app-ship.yaml -f app.apk
382
420
 
383
421
  ### Q: 支持 Windows / Mac 吗?
384
422
 
385
- 支持!本工具是跨平台的,可在以下环境运行:
386
-
387
- - Windows 10+
388
- - macOS 10.15+
389
- - Linux (Ubuntu 18+, Fedora, etc.)
423
+ 上传适配器仍可在 Node.js 支持的平台运行,但本批安全凭据存储只完成 macOS Keychain
424
+ 垂直切片。CLI 在 Linux / Windows 会明确停止,不会退回 YAML 明文凭据。
390
425
 
391
426
  ---
392
427
 
393
428
  ### Q: 可以在 CI/CD 中使用吗?
394
429
 
395
- 当然可以!使用环境变量存储凭证:
396
-
397
- **GitHub Actions 示例**:
398
-
399
- ```yaml
400
- - name: Upload App
401
- run: app-ship upload -c app-ship.yaml -f app.apk
402
- env:
403
- PGYER_API_KEY: ${{ secrets.PGYER_API_KEY }}
404
- HUAWEI_CLIENT_ID: ${{ secrets.HUAWEI_CLIENT_ID }}
405
- # ... 其他平台凭证
406
- ```
430
+ 当前不把无界面 CI Keychain 会话声明为已验证能力。CI 专用凭据提供器及身份边界完成后再开放;
431
+ 不要通过回退到 YAML 明文或命令行参数绕过限制。
407
432
 
408
433
  ---
409
434
 
@@ -411,10 +436,14 @@ app-ship upload -c app-ship.yaml -f app.apk
411
436
 
412
437
  ### 🔐 密钥管理
413
438
 
414
- - **用户掌控**:所有凭证仅保存在本地 `app-ship.yaml`,不上传到任何服务器
439
+ - **目标边界**:项目 YAML、Git、日志、回执、MCP 参数和模型上下文不得包含原始凭据
440
+ - **本地保管**:普通 Secret 进入操作系统安全存储,JSON / `.p8` 进入本地加密凭据库或经检查的外部路径
441
+ - **MCP 脱敏**:MCP 只能读取 `credentialProfile`、`configured`、`verified` 等元数据,不能读取或导出秘密
415
442
  - **本地处理**:所有认证和签名操作都在你的机器本地执行
416
443
  - **官方渠道**:直接调用各平台官方 API,无第三方转接
417
444
 
445
+ > 当前安全存储垂直切片只验证 macOS Keychain。Linux / Windows 会明确停止,待对应系统安全存储完成验证后再开放。旧 YAML / 环境变量只允许作为 `credentials migrate` 的迁移输入,`upload` 要求使用 `credentialProfile`。
446
+
418
447
  ### 🛡️ 最佳实践
419
448
 
420
449
  1. **保护配置文件** - 将 `app-ship.yaml` 加入 `.gitignore`:
@@ -535,3 +564,7 @@ npm run dev
535
564
  ## License
536
565
 
537
566
  MIT | Copyright © 2025-2026 火叶工作室
567
+
568
+ ### 按语言提供版本说明
569
+
570
+ 可在配置根级使用 `releaseNotes` 按 BCP-47 提供各语言正文,适配器负责与商店实际语言匹配和回读。详细边界与定向检查见 [本地化发行说明](docs/localized-release-notes.md)。