Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .agents/skills/hapsign-hap-deploy/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
name: hapsign-hap-deploy
description: Authenticate, sign, install, or deploy unsigned and signed HarmonyOS HAPs on an explicitly selected connected device through the hapsign CLI. Use for HAP deployment; not for building HAPs, emulator-only workflows, or manual DevEco/HDC signing.
---

# HapSign HAP Deploy

Use the installed `hapsign` CLI as the only implementation layer. It owns Huawei
authentication, token caching, device-bound Profiles, signing, HDC installation,
and post-install bundle checks. Do not recreate those steps with DevEco, raw HDC,
or skill-local scripts.

## Commands

Always request JSON and pass an explicit HDC serial:

```bash
hapsign devices list --connected-only --json
hapsign auth status --json
hapsign auth --json
hapsign sign --hap <unsigned.hap> --serial <serial> --json
hapsign install --hap <signed.hap> --serial <serial> --json
hapsign deploy --hap <hap> --serial <serial> --json
```

- Honor a serial supplied by the user. Otherwise select the sole
`physical_candidate=true` target; ask the user if zero or multiple physical
candidates remain. Do not select `likely_emulator=true` unless requested.
- Use `sign` for signing only, `install` for an already signed HAP, and `deploy`
for end-to-end signing and installation. `deploy` also accepts signed HAPs.
- Check `auth status` before an operation that may need login. If no current cache
exists and the request does not already authorize account authentication, tell
the user that browser authorization is required before running `auth`.

Treat success as exit code `0` plus JSON `ok=true`. Parse stdout as JSON and treat
stderr as diagnostic logs. On failure, report `error.type`, `error.message`, and
the exit code; do not fall back to manual signing or raw HDC installation. Never
print or copy tokens, passwords, signing keys, Profiles, or device UDIDs.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ htmlcov/

# 签名产物(证书、密钥、Profile、签名后的 hap)
signing_files/
.hapsign/
signed_haps/
logs/
hapsign-config.json
Expand Down
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@

### Added

- 新增面向 Agent 的 `auth`、`devices list`、`sign`、`install`、`deploy` CLI
子命令;支持单行 JSON stdout、stderr 日志、明确退出码与输入校验。
- CLI 支持显式 HDC `--serial`、真机/模拟器候选标记、签名与安装分离,以及安装后
`bm dump` 校验;Token 可跨目标设备复用,Profile 缓存按 UDID 隔离。
- CLI 默认状态目录改为跨平台用户主目录 `~/.hapsign`,Windows 对应
`%USERPROFILE%\.hapsign`,不再受 Agent 当前工作目录影响。
- macOS 支持:按平台解析 DevEco JBR / hap-sign-tool / hdc 路径,可用 `hapsign` 命令行签名安装。
- 可安装的 `hapsign` 命令和标准 Python 项目元数据。
- Ruff、pytest、覆盖率、pre-commit 和 Windows CI 配置。
Expand Down Expand Up @@ -48,8 +54,19 @@
哈希、许可材料及 libusb 对应源码。DevEco 工具链只保留为显式排障回退。
- 便携构建在 ZIP 旁自动生成标准 `.sha256` 校验文件,降低发布时手工抄录哈希出错的风险。

### Changed

- CLI 现在必须显式使用 `auth`、`devices`、`sign`、`install` 或 `deploy`
子命令,并为设备相关命令传入非空 `--serial`;旧的 `hapsign --hap ...`
调用方式不再兼容。

### Fixed

- Agent CLI 会拒绝空白 HDC serial,避免退回隐式设备选择;`auth` 仅在 Token
缓存成功落盘后返回成功;`devices list` 不再把退出码为 0 的 HDC `[Fail]`
输出误报为空设备列表。
- CLI 不再把缺少 HDC 可执行文件归类为输入错误;`devices`、`install` 等运行时
HDC 失败现在返回 `operation_failed` 和退出码 1。
- HTTP 客户端正确发送 `User-Agent` / `Accept-Language` 请求头。
- Token 缓存缺少 `jwt_token` 时不再复用,避免后续刷新失败。
- 设备注册将业务层重复错误码视为成功,并保留 HTTP 错误信息中的兼容判定。
Expand All @@ -68,6 +85,8 @@

### Security

- CLI、Pipeline 和诊断日志会脱敏异常文本中的完整 64 位设备 UDID;失败 JSON
stdout 不再泄露 `DeviceAPI.find_device_id()` 等异常携带的设备标识。
- 登录回调服务仅监听 loopback 地址。
- 日志默认不包含 token、完整请求体、CSRF code 或完整登录 URL;只有用户主动开启
“敏感诊断”且使用 DEBUG 级别时才记录完整网络载荷,密钥库密码始终排除。
Expand Down
9 changes: 6 additions & 3 deletions PRIVACY.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,13 @@ Profile。重复 UDID 会复用已有设备记录。用户应确认自己有权

## 本地保存

根据设置,以下文件保存在程序目录、用户 Local AppData 或用户选择的目录:
根据入口和设置,以下文件保存在 CLI 用户主目录、程序目录、用户 Local AppData
或用户选择的目录:

- `signing_files/.token_cache.json`:访问令牌、刷新令牌、JWT 和账号基本字段;
- `signing_files/<bundle>/`:私钥密钥库、CSR、证书、Profile 和缓存元数据;
- CLI 的 `~/.hapsign/.token_cache.json`(桌面/便携版为
`signing_files/.token_cache.json`):访问令牌、刷新令牌、JWT 和账号基本字段;
- CLI 的 `~/.hapsign/<bundle>/`(桌面/便携版为 `signing_files/<bundle>/`):
私钥密钥库、CSR、证书、Profile 和缓存元数据;
- `signed_haps/`:可选保留的最后一个已签名 HAP;
- `logs/hapsign.log*`:诊断日志;
- `hapsign-config.json`:日志级别、保存位置和功能开关。
Expand Down
103 changes: 74 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ set HAPSIGN_PYTHON=C:\path\to\your\python.exe
$env:HAPSIGN_PYTHON = "C:\path\to\your\python.exe"
```

拖拽脚本还需要明确的 HDC 目标序列号,可设 `HAPSIGN_SERIAL`,也可把序列号作为
第二个参数传入。运行 `hapsign devices list` 可以查看候选设备。

## 使用

### 方式一:桌面应用(推荐)
Expand Down Expand Up @@ -164,18 +167,39 @@ hapsign-app

### 方式二:bat 拖拽

将 `.hap` 文件直接拖到 `sign_install.bat` 上,自动完成签名+安装。
先设置 `HAPSIGN_SERIAL`,再将 `.hap` 文件拖到 `sign_install.bat` 上;或从 CMD
显式传入 HAP 和设备序列号:

```bat
set HAPSIGN_SERIAL=5XQ0225613000233
sign_install.bat path\to\app-unsigned.hap 5XQ0225613000233
```

### 方式三:命令行(Windows / macOS)

```bash
hapsign --hap path/to/app-unsigned.hap
hapsign --hap path/to/app-signed.hap # 已签名则跳过签名,直接安装
hapsign devices list --connected-only --json
hapsign auth status --json
hapsign auth --json
hapsign sign --hap path/to/app-unsigned.hap --serial <serial> --json
hapsign install --hap path/to/app-signed.hap --serial <serial> --json
hapsign deploy --hap path/to/app-unsigned.hap --serial <serial> --json
```

包名会自动从 hap 内的 `module.json` 提取,无需手动指定。
若 HAP 已包含签名块(Hap Signing Block),会跳过登录与签名,直接安装原文件。
源码目录中仍可使用 `python main.py --hap ...`。
`sign` 只签名并返回签名 HAP 的绝对路径;`install` 只接受已有 Hap Signing Block
的 HAP;`deploy` 端到端签名并安装,输入已经签名时会直接安装。包名默认从 HAP
里的 `module.json` 提取。源码目录中可用 `python3 main.py <command> ...`。

所有执行命令都支持 `--json`。此模式下 stdout 只输出单行 JSON,日志写到 stderr,
且不会输出 Token、密码或 UDID。Agent 应先从 `devices list` 中选择
`connected=true` 的目标,优先选择 `physical_candidate=true` 的 USB 真机,再把其
`serial` 原样传给后续命令。`serial` 是 HDC 连接标识,不是签名 Profile 中的 UDID。

`auth` 可以单独调用并持久化当天 Token。同一份 Token 缓存不绑定目标设备,在同一
台运行 HapSign 的电脑上可继续给不同 HarmonyOS 手机、平板或 PC 目标签名;每台
目标设备的 Profile 仍绑定自己的 UDID,切换设备会重新申请 Profile。Token 不会在
多台运行 HapSign 的电脑之间自动同步,也不建议手工复制缓存。`auth status` 只检查
本地当日缓存,因此 JSON 中 `online_verified` 固定为 `false`。

### 构建便携版

Expand Down Expand Up @@ -215,31 +239,48 @@ python scripts/build_portable.py --keep-bundled-browser
> [开源发布门禁](docs/OPEN_SOURCE_RELEASE.md) 完成真实设备安装回归。
> `--allow-deveco-toolchain` 只用于排障回退,其产物不得冒充锁定的公开构建。

### 完整参数
### Agent CLI 接口

```
hapsign --hap <hap路径> [选项]

选项:
--hap hap 文件路径(必填;已签名则直接安装)
--bundle-name 应用包名(不传则从 hap 内自动提取)
--country 国家码,默认 CN
--device-type 设备类型码,默认 4
--work-dir 签名文件存储目录,默认 signing_files/{bundle_name}/
--enable-capability 使用 Real Profile(APL=system_basic),用于需要高权限的应用
--refresh-token 强制刷新 token 缓存(重新登录,连带刷新签名文件)
--refresh-signing 强制刷新签名文件缓存(重新申请,不重新登录)
-v, --verbose 显示调试日志
--version 显示版本号
hapsign auth [login|status] [--refresh] [--state-dir DIR] [--json]
hapsign devices [list] [--connected-only] [--json]
hapsign sign --hap HAP --serial SERIAL [签名选项] [--json]
hapsign install --hap SIGNED_HAP --serial SERIAL [--bundle-name NAME] [--json]
hapsign deploy --hap HAP --serial SERIAL [签名选项] [--json]

sign / deploy 签名选项:
--bundle-name NAME 覆盖 HAP 中的包名
--country CODE 华为账号国家码,默认 CN
--device-type TYPE 签名平台注册的设备类型码,默认 4
--state-dir DIR Token 与默认签名材料根目录,默认 ~/.hapsign
--work-dir DIR 当前 bundle 签名材料目录,默认 <state-dir>/<bundle>
--output-dir DIR 签名 HAP 输出目录,默认与 work-dir 相同
--browser MODE system、system_controlled 或 playwright
--enable-capability 使用 Real Profile(APL=system_basic)
--refresh-token 强制浏览器认证,同时刷新签名材料
--refresh-signing 只重新申请证书/Profile,复用有效 Token
-v, --verbose 将 DEBUG 日志写到 stderr

设备类型码:
4 手机/平板(默认)
4 手机/平板/2in1(默认)
2 穿戴设备
8 智慧屏
9 路由器
1 轻量级穿戴设备

退出码:
0 命令成功
1 认证、签名、HDC 或安装运行失败
2 参数或输入 HAP 无效
130 用户取消
```

成功 JSON 至少包含 `ok=true` 和 `command`。`sign` / `deploy` 还包含 `input_hap`、
`signed_hap`、`bundle_name`、`serial`、`input_signed` 和 `installed`;`devices list`
包含 `count`、`connected_count` 与 `targets`。失败 JSON 使用
`{"ok":false,"command":"...","error":{"type":"...","message":"..."}}`。
完整、随版本同步的帮助以 `hapsign --help` 和各子命令 `--help` 为准。

### 首次运行

会弹出浏览器窗口,打开华为登录页。手动输入账号密码登录,如果有验证码或二次验证也手动处理。登录成功后浏览器会自动关闭,后续自动完成签名和安装。
Expand All @@ -251,7 +292,7 @@ hapsign --hap <hap路径> [选项]
如果应用需要 `system_basic` 级别的 APL,加 `--enable-capability` 参数走 Real Provision 路径:

```bash
hapsign --hap app.hap --enable-capability
hapsign deploy --hap app.hap --serial <serial> --enable-capability
```

此模式通过 `add.real.provision` API 创建 Real Profile(provisionType=1),对应 DevEco Studio 6.1+ 的 `enableCapability` 路径。需要应用已在 AGC(AppGallery Connect)注册且当前账号有访问权限,否则自动回退到 Test Profile。
Expand All @@ -269,8 +310,10 @@ HapSign/
└── signed_haps/ # 最新一个签名 HAP(可在设置中关闭)
```

源码 CLI 默认保存在启动命令时所在目录的
`signing_files/<bundle_name>/`;传入 `--work-dir` 可以指定其他目录。
源码 CLI 默认保存在用户主目录的 `~/.hapsign/<bundle_name>/`;Windows 对应
`%USERPROFILE%\.hapsign\<bundle_name>\`。该默认值不依赖启动命令时的工作目录。
传入 `--state-dir`、`--work-dir` 和 `--output-dir` 可以分别指定 Token/默认材料
根目录、当前 bundle 材料目录和签名 HAP 输出目录。
程序目录必须可写,不建议把便携版解压到 `Program Files` 等受保护目录。
桌面版“设置”中还可以改为用户 `AppData Local` 或任意自定义目录。

Expand All @@ -290,15 +333,17 @@ HapSign/

## 缓存策略

同一天内不会重复登录或重复申请签名文件:
同一天内不会重复登录;签名文件只在 bundle 和目标 UDID 都相同时复用:

- **Token 缓存**:`signing_files/.token_cache.json`,当天复用,不重新登录
- **签名文件缓存**:`signing_files/{bundle_name}/metadata.json`,当天复用,不重新申请证书/设备/Profile
- **Token 缓存**:`~/.hapsign/.token_cache.json`,当天可跨目标设备复用
- **签名文件缓存**:`~/.hapsign/{bundle_name}/metadata.json`,当天仅为匹配的
bundle 和设备 UDID 复用
- 跨天自动失效,重新走完整流程
- Token 失效时自动刷新,刷新失败才回退到重新登录

这些文件包含明文敏感信息,不要上传、分享或放入云同步目录。共享电脑使用完毕后应删除
`signing_files/`。详细说明见 [SECURITY.md](SECURITY.md)。
Windows 使用当前用户 DPAPI 加密 Token;macOS/Linux 以权限 `0600` 的明文保存。
签名材料与缓存都不要上传、分享或放入云同步目录。共享电脑使用完毕后应删除
`~/.hapsign/`。详细说明见 [SECURITY.md](SECURITY.md)。

## 限制

Expand Down
9 changes: 5 additions & 4 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ vulnerability reporting;启用后请使用仓库 Security 页的“Report a vu

## 本地敏感数据

hapsign 默认会在程序目录的 `signing_files/` 中保存当日 token 缓存、调试证书、
Profile 和 `.p12` 密钥库,以避免重复登录和申请。这些文件已被 `.gitignore`
排除,但仍是本机敏感数据。Windows 上 token 缓存通过当前用户作用域的 DPAPI
桌面/便携版默认会在程序目录的 `signing_files/` 中保存当日 token 缓存、调试证书、
Profile 和 `.p12` 密钥库;CLI 默认使用用户主目录的 `~/.hapsign/`(Windows 为
`%USERPROFILE%\.hapsign\`)。这些文件已被 `.gitignore` 排除,但仍是本机敏感
数据。Windows 上 token 缓存通过当前用户作用域的 DPAPI
(CryptProtectData)静态加密后落盘,其他平台退化为受限权限(仅当前用户可读)
的明文存储,并在首次保存时打印告警;请勿把缓存目录放入云同步目录,在共享电脑
上使用后应删除该目录。移动或分享便携目录前应先移除 `signing_files/`;桌面设置
上使用后应删除对应目录。移动或分享便携目录前应先移除 `signing_files/`;桌面设置
可改为用户 AppData Local 或自定义目录;同样应按敏感数据目录保护。
程序目录的 `signed_haps/` 可能包含用户应用代码,移动或分享便携目录前也应检查;
可在设置中关闭保留签名 HAP。
Expand Down
7 changes: 4 additions & 3 deletions docs/PACKAGING.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,10 @@ HapSign/
└── signed_haps/ # 最新一个签名 HAP,与材料目录设置无关
```

因此便携目录必须可写。源码 GUI 默认使用项目根目录,源码 CLI 默认使用当前工作
目录下的 `signing_files/<bundle_name>/`。可以用 `HAPSIGN_DATA_DIR` 覆盖桌面版
数据根目录,CLI 则可使用 `--work-dir`。已签名 HAP 会跳过签名流程,因此不会
因此便携目录必须可写。源码 GUI 默认使用项目根目录,源码 CLI 默认使用用户主目录
下的 `~/.hapsign/<bundle_name>/`。可以用 `HAPSIGN_DATA_DIR` 覆盖桌面版
数据根目录,CLI 则可使用 `--state-dir`、`--work-dir` 和 `--output-dir`。已签名
HAP 会跳过签名流程,因此不会
产生新的 `.p12`、`.cer`、`.p7b` 或签名后 HAP。

GUI 设置也可选择用户 `AppData Local` 或自定义签名目录。程序目录下的
Expand Down
Loading