Host Agent: - One-time local operator account bootstrap (PBKDF2-HMAC-SHA256, atomic 0600-permission write) gating the daemon's first unattended start via a new `setup` CLI subcommand. - Default control-plane URL now https://amcp.home.jerryyan.top (env var override unchanged). - Enrollment no longer requires a pre-issued token; falls back to zero-token self-service enrollment when none is configured. Cloud control plane: - CLOUD_SELF_SERVICE_ENROLLMENT_ENABLED (default false) opt-in flag. - SelfServiceEnrollmentAuthProvider + ChainedEnrollmentAuthProvider: configured tokens still take priority; self-service only applies when no token matches, preserving edge-host-enrollment's token-bound path. - Fixed a latent bug in sql_repository.py::enroll_host: the token-conflict lookup used `== enrollment_token_digest`, which SQLAlchemy compiles to `IS NULL` when the value is None, so every self-service enrollment after the first would have falsely collided with an existing NULL-digest host. Skipped that lookup entirely when the digest is None. Docs/deploy: .env.example, compose.yaml, compose.deploy.yaml, CLOUD_DEPLOYMENT.md, MACOS_IPHONE_SETUP.md updated for the new flag, URL default, and required `device-host-agent setup` step. Verification: 494 non-integration tests pass; openspec validate --strict passes. PostgreSQL-backed contract tests and full manual end-to-end verification were not run (no Postgres/Docker or reachable cloud-api in this environment); noted as unchecked in tasks.md 7.2/7.4.
This commit is contained in:
@@ -367,11 +367,21 @@ DeviceConfigStore("tasks/device_config.sqlite3").add(
|
||||
PY
|
||||
```
|
||||
|
||||
从云端管理员获取一枚未使用的一次性 enrollment token,然后启动:
|
||||
首次启动前,先在交互式终端创建一次性本地操作账号(仅用于门禁"首次启动"这个
|
||||
动作本身,后续无人值守重启不会再次要求):
|
||||
|
||||
```bash
|
||||
uv run --package device-host-agent device-host-agent setup
|
||||
```
|
||||
|
||||
`HOST_AGENT_CONTROL_PLANE_URL` 默认已固定为 `https://amcp.home.jerryyan.top`;
|
||||
仅在连接其他云端环境(如本地/测试用的 `cloud-api`)时才需要覆盖该变量。未设置
|
||||
`HOST_AGENT_ENROLLMENT_TOKEN` 时,Host Agent 会直接向云端发起零 token 自助注册
|
||||
(需要云端 `CLOUD_SELF_SERVICE_ENROLLMENT_ENABLED=true`);若仍持有云端管理员
|
||||
签发的一次性 enrollment token,也可以继续设置 `HOST_AGENT_ENROLLMENT_TOKEN`
|
||||
走原有的 token 注册路径:
|
||||
|
||||
```bash
|
||||
export HOST_AGENT_CONTROL_PLANE_URL="https://cloud.example.com"
|
||||
export HOST_AGENT_ENROLLMENT_TOKEN="<one-time enrollment token>"
|
||||
export HOST_AGENT_IDENTITY_PATH="tasks/host_identity.json"
|
||||
export HOST_AGENT_DISPLAY_NAME="Edge Mac 01"
|
||||
|
||||
@@ -384,9 +394,13 @@ uv run --package device-host-agent device-host-agent
|
||||
|
||||
首次启动顺序为:持久化候选 Host secret、向云端换取 `host_id`、为每个本地设备
|
||||
换取 `device_id`、保存映射、连接 WDA、发送 heartbeat、开始 long-poll 领取任务。
|
||||
Host Agent 不监听入站端口。成功后可以从边缘环境移除 enrollment token,但必须
|
||||
保留并保护 `tasks/host_identity.json` 和 `tasks/device_config.sqlite3`;前者等同于
|
||||
Host bearer credential。
|
||||
Host Agent 不监听入站端口。若使用了一次性 enrollment token,成功后可以将其从
|
||||
边缘环境移除;但必须保留并保护 `tasks/host_identity.json` 和
|
||||
`tasks/device_config.sqlite3`;前者等同于 Host bearer credential。
|
||||
|
||||
零 token 自助注册意味着任何能访问该云端地址的设备都能自行注册成为 Host,没有
|
||||
审批环节,也没有限流保护;这一取舍依赖网络边界(防火墙/反向代理)而非应用层
|
||||
限制,仅应在受控网络中开启 `CLOUD_SELF_SERVICE_ENROLLMENT_ENABLED`。
|
||||
|
||||
需要回滚到静态模式时,停止 Host Agent,由云端管理员配置匹配的静态 Host
|
||||
credential,然后显式设置 `HOST_AGENT_HOST_ID` 与 `HOST_AGENT_TOKEN`。这两个变量
|
||||
|
||||
Reference in New Issue
Block a user