docs: add v0.2 device pod spec

This commit is contained in:
Codex
2026-05-28 18:00:12 +08:00
parent 792e307d99
commit ecc97e7b05
9 changed files with 400 additions and 330 deletions
+2 -1
View File
@@ -38,7 +38,8 @@ For M3 hardware proof, the required runtime participants are:
真实设备目标以 `device-pod` 作为运行时能力单元。`device-pod`
统一封装 `deviceTarget``debugInterface``projectWorkspace`
`ioInterface` 四要素,并通过拆分的 debug/io 接口提供受控 REST/job
能力;权威模型见 [device-pod.md](device-pod.md)。
能力;正式 profile authority、REST/job 和服务部署规格见
[spec-device-pod.md](spec-device-pod.md)。
`v0.2` 多用户访问模型只保留 `admin``user` 两类角色:code agent
session 归属于创建用户,device pod 由 `admin` 管理并按用户授权,授权即全权限;
+9 -217
View File
@@ -1,221 +1,13 @@
# Device Pod 设备目标能力模型
# Device Pod 参考入口
本文是 HWLAB `device-pod` 的长期参考口径。`device-pod` 是一个逻辑实验台抽象,用于把一个可开发、可编译、可下载、可复位、可观测 I/O 的设备目标封装成统一能力单元。进入 server 阶段后,该能力单元可以由单副本 k8s Pod 承载,并对外提供统一 REST/job API;对外稳定身份由 Service/Deployment 承载,不依赖实际 Pod name
本文保留为旧链接兼容入口。HWLAB `v0.2` 正式 `device-pod` 接入规格以 [spec-device-pod.md](spec-device-pod.md) 为权威
`device-pod` 不等同于裸物理设备,也不是泛化远程 shell。它是以下四个要素的运行时组合
关键口径
```text
device-pod
= deviceTarget
+ debugInterface
+ projectWorkspace
+ ioInterface
```
- `device-pod` 是逻辑设备能力单元,不是 Kubernetes Pod name。
- profile 定义 `device-pod`,因此正式接入后 profile 必须由 `admin``cloud-api` 服务端权威管理。
- code agent 本地 `.device-pod/` profile 只属于早期 CLI MVP 闭环;正式多用户系统中不得作为路由、授权或硬件资源边界的 source of truth。
- v0.2 第一阶段使用一个 `hwlab-device-pod` Deployment/Service 管理多个逻辑 `devicePodId`,避免过早引入 per-device k8s workload 运维压力。
- 正式访问路径是 `device-pod-cli/cloud-web -> cloud-api -> hwlab-device-pod -> gateway -> device-host-cli -> target`
## 设计抽象
`device-pod` 可以理解成云端可拥有和调度的一张嵌入式实验台。云端拥有的是 `device-pod` 这个逻辑能力单元,不是直接拥有某一块裸板、某一根探针或某一台用户 PC。只要 profile 能把 `deviceTarget``debugInterface``projectWorkspace``ioInterface` 四要素绑定清楚,code agent 就可以围绕同一个 `devicePodId` 完成源码修改、构建、下载、复位、状态读取和 I/O 观察,从而覆盖嵌入式开发的完整闭环。
四要素的物理落点可以不同,也可以复用同一个硬件实体的不同能力:
- `deviceTarget` 是被调试和被验证的目标设备。
- `debugInterface` 提供下载、烧录、复位、debug probe 状态和芯片识别等调试能力。
- `projectWorkspace` 承载源码、工程、Keil/GCC 等工具链和编译产物。
- `ioInterface` 提供 AI、AO、DI、DO、UART、截图、日志和其他实时或近实时观测/控制能力。
`device-pod` 因此是逻辑打包关系,而不是一对一物理设备关系。一个 DAPLink/MKLink 类探针可以同时拆出 `debugInterface` 的 SWD/CMSIS-DAP 能力和 `ioInterface` 的 UART 能力;同一个 `device-pod` 也可以把该探针与调试 box、USB 摄像头、串口工具或厂商上位机组合起来,共同形成对同一个 `deviceTarget` 的完整访问能力。
## 平台化服务模式
`device-pod` 把设备目标和访问能力封装成统一逻辑单元后,HWLAB 可以在同一技术模型上承载多种交付模式。不同模式的差异主要在于 `deviceTarget`、probe、workspace、云平台和运维责任分别由谁提供,但对 code agent 和用户界面暴露的仍应是稳定的 `devicePodId`、能力边界、锁、job、trace 和 evidence。
- **Device Pod 租赁**HWLAB 运营常用开发板、调试探针、I/O 工具和 workspace 的设备机房,用户无需自备硬件即可在云端基于真实原型开发;软件验证后可以自行找硬件工程师,或委托平台侧硬件工程师继续绘制 PCB。
- **用户 PCB 托管**:用户已经完成 PCB 或样机,委托 HWLAB 托管该 `deviceTarget`,平台提供或代管 probe、I/O 工具、workspace 和 `device-pod` 运行面,用户通过云端继续开发、测试和迭代。
- **用户自有设备接入**:用户保留自己的 `deviceTarget`、debug probe 和 I/O probe,只接入 HWLAB 云;平台把这些资源通过 profile/gateway/device-host-cli 抽象为 `device-pod`,供用户自己远程开发。
- **委托开发与运维**:在用户自有设备接入的基础上,用户可以授权平台内其他开发者、维护人员或自动化 code agent 围绕同一个 `device-pod` 进行软件开发、调试、故障复现、在线维护和验收。
- **私有 HWLAB 云部署**:用户公司内部部署自有 HWLAB 云和自有设备池,平台提供安装、升级、运维和最佳实践支持;设备、数据和权限留在用户私有环境内,`device-pod` 模型保持一致。
这些模式都不能绕过 `device-pod` 的安全边界:profile 仍不得携带长期 secretmutating operation 仍需 approval、reason、锁和 evidence;平台不得把缓存、dry-run、前端状态或本地模拟误报为真实 DEV-LIVE 设备证据。
## 实施计划
长期模型以本文为准;分阶段实现计划单独维护,避免把一次性开发步骤写进长期参考:
- [Device Pod CLI MVP 计划](../plan/device-pod-cli-mvp.md):先做 code agent 可调用的独立 CLI,通过 profile、gateway 和用户 PC 侧 `device-host-cli` 跑通 workspace、debug-probe 和 io-probe 的最小闭环。
- [Device Pod Server MVP 计划](../plan/device-pod-server-mvp.md):在 CLI 跑通后再实现真正的 `device-pod-server`,提供与 CLI 对应的 RESTful API、后台监控缓存和前端最小可视化。
## Profile 注册与同步
MVP 不使用刚性的中心 profile 注册表。`device-pod` profile 的灵活源头是 HWLAB code agent workspace 下的 `.device-pod/` 目录,推荐按 `devicePodId` 存放 profile 文件,例如 `.device-pod/device-pod-71-freq.json`
`device-pod-cli` 每次执行都从当前 code agent workspace 的 `.device-pod/` 读取 profile,并在输出中保留 `profilePath``profileHash`。进入 `device-pod-server` 阶段后,CLI 或 code agent 仍以 `.device-pod/` 为 profile source-of-truth;每次连接 server 前自动上传或刷新 profileserver 只把 active profile 当作运行时缓存,不把它变成长期配置真相。
profile 必须只描述 target、debugInterface、projectWorkspace、ioInterface、gateway route、host CLI 能力和受控路径边界;不得放入 Git key、云端 token、kubeconfig、数据库 URL 或其他长期 secret。profile 校验失败时应返回 `profile-invalid``profile-missing` blocker,而不是回退到默认设备或任意 shell。
## Selector 路径纪律
`device-pod-cli` selector 是稳定 API 语法,不是自然语言路径猜测器。`workspace``debug-probe``io-probe` selector 后的路径必须由调用方拼对,尤其是 I/O probe 必须把路径写成一个 shell token,例如 `device-pod-71-freq:io-probe:/uart/1 read`
不要迁就透传路径拼错、`/` 两侧空格或 argv 被模型拆开的写法。`io-probe:/uart / 1 read``io-probe:/uart/ 1 read` 这类输入应在 runner 侧直接返回 `invalid-request` 并给出正确写法 hint,不应被自动归一化成 `uart/1`,更不应继续透传到 gateway 或 Windows `device-host-cli`。这样可以把“命令写错”和“硬件/串口不可达”明确区分,避免下游工具为模型 spacing drift 背锅。
## HWLAB coder 预装合同
HWLAB coder / code agent runner 镜像必须通过正式 CI/CD 预装 device-pod 最小闭环所需的三类入口:
- **cmd 透传入口**`/app/tools/tran.mjs` 是 runner 内的稳定合同入口,负责通过已注册 gateway session 对 Windows PC 执行 `cmd`、PowerShell、upload 和 download,并承担 UTF-8、cwd、stdout/stderr、quoting 和文件传输边界。`/app/tools/hwlab-gateway-tran.mjs` 是同一能力的兼容实现入口,不是第二套 transport;若兼容入口存在但 `/app/tools/tran.mjs` 缺失,CI/CD 预装判定不通过,必须补齐 `tran.mjs` 短名,而不是让 device-pod 逻辑适配多个临时入口。
- **device-pod-cli 入口**runner 内必须预装 `device-pod-cli` skill,稳定入口为 `/app/skills/device-pod-cli/scripts/device-pod-cli.mjs`,其实现指向 `/app/tools/device-pod-cli.mjs`。code agent 应通过该 CLI 读取 workspace 下 `.device-pod/<devicePodId>.json`,再走 cloud-api/gateway/device-host-cli 调用设备能力。
- **device-host-cli 资产**runner 内必须随 `device-pod-cli` skill 打包 Windows 侧自包含 host CLI 资产,稳定路径为 `/app/skills/device-pod-cli/assets/device-host-cli.mjs`。新 Windows 硬件 PC 接入时,不运行独立安装器;code agent 使用预装 cmd 透传入口把该资产发送到目标 workspace 的 `tools\device-host-cli.mjs`,再通过同一 cmd 透传入口执行 `node tools\device-host-cli.mjs health` 验证。
`/app/skills` 是 HWLAB coder 镜像内 code agent skill 的唯一 canonical 位置。`device-pod-cli` 不再同步到 `/root/.agents/skills``/home/ubuntu/.agents/skills` 或 workspace 下的 skill 副本;这些副本会造成 discovery 口径、wrapper 相对路径和 CI/CD 预装内容不同步。默认 prompt、`HWLAB_CODE_AGENT_SKILLS_DIRS`、skill discovery 和验收都必须指向 `/app/skills`。如果某个运行时只能读取 home 目录,应先修复 runner 的 skill discovery 或环境变量,而不是复制第二份 skill。
`device-host-cli` 不是一次性预装脚本,而是 HWLAB 内部 code agent 可继续热开发的 host 侧工具。DeepSeek、Codex runner 或其他 HWLAB 内部 code agent 在真实硬件闭环中遇到 Keil、debug probe、串口、文件工作区或硬件启动路径不顺手时,优先在目标 Windows workspace 的 `tools\device-host-cli.mjs` 上新增或修复具名设备能力,并通过 `device-pod-cli -> cloud-api -> gateway -> device-host-cli` 的真实链路热验证;验证通过后再把同一实现回填到 `/app/skills/device-pod-cli/assets/device-host-cli.mjs` 对应的 HWLAB repo 资产,进入下一次 CI/CD 预装。不得因为 host CLI 暂时不顺手而把 `device-pod-cli` 退化为泛化 cmd/shell 入口。
目标 Windows workspace 的最小布局为:
```text
<windows-workspace>\tools\device-host-cli.mjs
<windows-workspace>\.device-pod\<devicePodId>.json
```
完成上述布局后,profile 中的 `hostCli` 应指向 `node tools\device-host-cli.mjs``device-pod-cli` 才能稳定执行 workspace、debug-probe 和 io-probe 操作。`device-host-cli` 必须自包含,不能在运行时依赖 Windows 侧 skill 目录;Keil、serial-monitor、mklink、文件编辑等 skill 只允许作为实现参考。
CI/CD 判定口径是:构建产物中同时存在 `/app/tools/tran.mjs``/app/tools/hwlab-gateway-tran.mjs``/app/tools/device-pod-cli.mjs``/app/skills/device-pod-cli/SKILL.md``/app/skills/device-pod-cli/scripts/device-pod-cli.mjs``/app/skills/device-pod-cli/assets/device-host-cli.mjs``node /app/tools/tran.mjs --help` 能展示 cmd/ps/upload/download 透传帮助,`HWLAB_CODE_AGENT_SKILLS_DIRS=/app/skills`,且 code agent skill discovery 从 `/app/skills` 发现 `device-pod-cli`。只有这些入口都在 runner 中可见,才能称为 HWLAB coder 已具备 device-pod 最小预装能力。
## 四要素
### `deviceTarget`
`deviceTarget` 是被测设备目标本身,可以是一个 MCU 最小系统板、完整业务板卡、仪器模块或其他可被 HWLAB 操作的目标对象。它必须有稳定的 `targetId`,用于锁、trace、evidence 和用户界面归因。
### `debugInterface`
`debugInterface` 是设备的开发和调试接口,代表下载、烧录、复位、debug probe 状态等能力。典型物理实现包括 DAPLink、J-Link、ST-Link 或厂商下载器。
第一版路径固定为:
```text
device-pod -> cloud-api -> gateway -> cmd -> device-host-cli -> downloader/debug probe -> target
```
`debugInterface` 只暴露设备语义能力,例如 `debug.probe``debug.download``debug.reset`。不得把它退化成任意 shell 执行入口。
`device-host-cli` 必须是用户 PC 侧自包含组件;Keil、串口、DAPLink、J-Link 或其他 skill 代码只能作为实现参考,不能成为运行时依赖。
`debugInterface` 不承载源码编译、工程发现或工具链定义;这些属于
`projectWorkspace``debugInterface` 可以消费 `projectWorkspace` 产生的
artifact,例如 `.hex``.bin``.elf`,并负责把该 artifact 下载、校验、
复位或附着调试到 `deviceTarget`
### `projectWorkspace`
`projectWorkspace` 是设备对应的源码、工程文件和编译工具链上下文,例如 Keil 工程、target 名称、构建脚本和 workspace root。它描述如何从源码生成可下载产物,也为 debug/download job 提供工程路径和工具链边界。
`projectWorkspace` 可以和 `debugInterface` 位于同一台用户 PC,也可以只通过 gateway 暴露受控 CLI。HWLAB 不直接读取 secret、kubeconfig、DB URL 或完整源码内容;探测必须有界。
工程源码的编译和工具链归属 `projectWorkspace`,包括:
- 源码根目录、工程文件和 target 名称;
- build profile、编译参数和工具链入口;
- build、clean、artifact list 等工程动作;
- `.hex``.bin``.elf` 等下载产物的位置和元数据。
因此 build 失败应归类为 workspace/toolchain blockerdownload、reset 或
probe attach 失败才归类为 debug/probe/target blocker。
典型流程为:
```text
projectWorkspace.build
-> artifact
-> debugInterface.download
-> debugInterface.reset
-> ioInterface.status/sample/uart
```
### `ioInterface`
`ioInterface` 是设备的实时或近实时 I/O 观测与控制接口,代表 UART、AI、AO、DI、DO、状态采样、日志抓取、截图等能力。典型实现包括 DAPLink/MKLink 自带串口、独立串口工具、调试 box、USB 摄像头、USB/WiFi/厂商协议上位机或 `device-host-cli`
MVP 推荐路径为:
```text
device-pod -> cloud-api -> gateway -> cmd -> device-host-cli -> serial/WiFi/USB/vendor protocol -> target
```
这里 `cmd` 只作为启动受控 PC 侧 CLI 的 transport;串口、WiFi、厂商协议和硬件细节必须隔离在 `device-host-cli` 或等价上位机 CLI 后面。
## 接口拆分
`debugInterface``ioInterface` 必须在模型和 API 中拆开,即使它们由同一个物理探针提供。例如 DAPLink 可以同时提供 SWD/CMSIS-DAP 下载调试口和 UART 串口:
```text
DAPLink physical probe
-> debugInterface: SWD/CMSIS-DAP
-> ioInterface: UART
```
拆分原因:
- `debug.download``debug.reset` 是低频强副作用动作,通常需要 approval 和 target 互斥锁。
- `io.status.read``io.sample` 是短读或短窗口采样,关注 freshness、采样窗口和输出有界性。
- `io.write` 类能力属于硬件 I/O 控制,未来也需要 approval,但不能和下载/烧录混成同一类风险。
- trace、audit、evidence 必须能区分 `debug` 路径和 `io` 路径。
MVP 不拆成两个 k8s Pod;同一个 `device-pod` 内保留两个一等接口,共享 `deviceTarget``projectWorkspace`、锁、job 和 evidence 归因。
## 最小 REST 口径
同步 API 只用于短状态和短探测:
```text
GET /health
GET /v1/profile
GET /v1/status
GET /v1/capabilities
GET /v1/workspace/status
GET /v1/debug/status
GET /v1/io/status
```
异步 API 用于下载、复位、采样等动作;每个 HTTP 调用必须短,长耗时由 job 轮询表达:
```text
POST /v1/workspace/jobs
POST /v1/debug/jobs
POST /v1/io/jobs
GET /v1/jobs/{jobId}
GET /v1/jobs/{jobId}/output
POST /v1/jobs/{jobId}/cancel
```
第一版可接受的 intent 示例:
```text
workspace.detect
workspace.build
workspace.clean
workspace.artifact.list
debug.probe
debug.download
debug.reset
io.status.read
io.sample
io.uart.fetch
```
所有响应必须保留 `devicePodId``targetId``traceId``operationId``gatewaySessionId``interface``intent``route``status` 和 blocker/evidence 字段。真实控制动作不得用 `SOURCE``LOCAL``DRY-RUN` 或前端状态冒充 `DEV-LIVE`
## 最小系统示例
一个 STM32F103 最小系统加 DAPLink 可以完整构成一个 `device-pod`
```text
deviceTarget: STM32F103 最小系统
debugInterface: DAPLink SWD/CMSIS-DAP
projectWorkspace: STM32F103 源码、Keil 工程和编译工具链
ioInterface: DAPLink UART 串口
```
最小真实闭环也可以表述为:STM32F103 最小系统板作为 `deviceTarget`,一只 MKLink/DAPLink 类探针同时提供 `debugInterface` 和第一版 `ioInterface`,其中 debug 侧负责下载、复位和芯片识别,I/O 侧先只开放 UART;`projectWorkspace` 映射到用户 PC 上的源码目录、Keil 工程和工具链,再通过 gateway/device-host-cli 暴露受控构建和 artifact 能力。这样四要素齐备后,云端 code agent 就能围绕同一个 `device-pod` 完成改源码、编译、下载、复位、读串口的最小嵌入式开发闭环。
该模型后续可以扩展到更多 target 或更复杂 I/O probe,但每个 `device-pod` 仍只代表一个明确的设备目标能力单元。
迁移计划见 [../plan/v02-device-pod-spec-migration.md](../plan/v02-device-pod-spec-migration.md)。历史 CLI MVP 闭环见 [../plan/device-pod-cli-mvp.md](../plan/device-pod-cli-mvp.md),但其中本地 profile 权威口径不适用于正式 v0.2 多用户接入。
+5 -4
View File
@@ -92,21 +92,22 @@ CREATE INDEX IF NOT EXISTS idx_agent_sessions_conversation ON agent_sessions(con
### `device_pods`
设备能力单元的管理表;profile 语义以 [device-pod.md](device-pod.md) 为准。
设备能力单元的管理表;正式 profile authority 和执行语义以 [spec-device-pod.md](spec-device-pod.md) 为准。profile 定义 device pod,因此 profile 必须由 `admin` 通过 cloud-api 管理,不能由 code agent 本地 `.device-pod/` 文件决定。
```sql
CREATE TABLE IF NOT EXISTS device_pods (
id TEXT PRIMARY KEY,
name TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'disabled')),
profile_ref TEXT NOT NULL DEFAULT '',
gateway_ref TEXT NOT NULL DEFAULT '',
device_pod_json TEXT NOT NULL DEFAULT '{}',
profile_json TEXT NOT NULL DEFAULT '{}',
profile_hash TEXT NOT NULL DEFAULT '',
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
```
`profile_json` 中的 gateway route、host workspace、probe UID、串口端口和 host CLI 都是服务端权威字段;普通用户响应只能看到脱敏 profile 摘要和 `profile_hash`
### `device_pod_grants`
普通用户对 device pod 的授权关系;存在即全权限。
+228
View File
@@ -0,0 +1,228 @@
# Device Pod 正式接入规格
本文是 HWLAB `v0.2` 正式接入 `device-pod` 的规格说明。`device-pod` 是一个逻辑设备能力单元,不是 Kubernetes Pod 名称,也不是 code agent 本地 profile 文件。正式接入后,profile 定义 `device-pod`,因此 profile 必须由管理员和服务端权威存储管理,不能由 code agent 本地文件决定路由或资源边界。
旧的 `device-pod-cli` 本地 profile 闭环只用于 CLI MVP 和真实硬件最小验证。进入正式多用户系统后,所有用户态设备访问必须收敛到:
```text
device-pod-cli or cloud-web
-> cloud-api auth + device_pod_grants + lease
-> hwlab-device-pod internal REST
-> gateway transport
-> device-host-cli
-> Keil / pyOCD / UART / target
```
## 设计目标
- 用最少组件把 `device-pod-cli` 从“本地 profile + RPC/gateway 调用”迁到“1:1 REST 请求”。
- `cloud-api` 是用户身份、device grant、profile authority 和 lease 判断入口。
- `hwlab-device-pod` 承接设备业务:profile 校验后的运行、job 生命周期、freshness、blocker、bounded output 和 gateway 调用。
- `device-pod-cli` 只做 selector 解析、REST 请求和 JSON 输出,不再保存或上传权威 profile。
- 第一阶段只部署一个 `hwlab-device-pod` Deployment/Service,管理多个逻辑 `devicePodId`,避免为每台设备创建独立 k8s Service/Deployment。
- 普通用户和 code agent session 不获得 Kubernetes 用户、Service 直连权限、gateway route 或 host workspace route。
## 逻辑模型
一个 `device-pod` 由四个设备能力要素组成:
```text
device-pod
= deviceTarget
+ debugInterface
+ projectWorkspace
+ ioInterface
```
- `deviceTarget`:被测设备目标,例如开发板、用户 PCB 或仪器模块。
- `debugInterface`:下载、复位、chip-id、probe 状态和调试连接能力。
- `projectWorkspace`:源码、工程、构建工具链和 artifact 边界。
- `ioInterface`:UART、DI/DO、采样、日志和其他设备 I/O 观测/控制能力。
`devicePodId` 是云端和用户界面的稳定身份。实际 k8s Pod 可以重建、滚动或扩容;用户和 code agent 不依赖实际 Pod name。
## Profile Authority
正式接入后,profile 是管理员侧资源:
```text
admin UI/API
-> cloud-api
-> device_pods.profile_json + profile_hash
-> hwlab-device-pod internal execution
```
code agent 本地文件只能作为非权威 hint/cache,最多包含:
```json
{
"devicePodId": "device-pod-71-freq",
"profileHash": "sha256:...",
"cloudApiUrl": "..."
}
```
本地 hint/cache 不得包含以下字段,也不得参与授权或执行路由:
- `gatewaySessionId`
- `resourceId`
- `capabilityId`
- `hostWorkspaceRoot`
- `hostCli`
- Windows workspace 路径
- probe UID、串口端口、Keil 路径等硬件路由字段
正式 profile 必须由 `cloud-api` 从 DB 读取;`hwlab-device-pod` 不接受浏览器、code agent 或 CLI 上传的 profile 作为执行依据。若 `hwlab-device-pod` 需要 profile snapshot,应只接受 `cloud-api` 内部服务凭据转发的 snapshot,或通过内部服务凭据向 `cloud-api` 拉取。该凭据不得挂载进 code agent session Pod。
## Profile Shape
`device_pods.profile_json` 至少表达以下 server-side 字段:
```json
{
"schemaVersion": 1,
"devicePodId": "device-pod-71-freq",
"target": {
"id": "target-id"
},
"projectWorkspace": {
"workspaceRoot": "F:\\Work\\Project",
"projectPath": "FirmWare/MDK-ARM/app.uvprojx",
"targetName": "app",
"hexPath": "FirmWare/MDK-ARM/app/app.hex"
},
"debugInterface": {
"type": "cmsis-dap",
"probeUid": "...",
"uv4Path": "C:\\Keil_v5\\UV4\\UV4.exe"
},
"ioInterface": {
"uart": [
{ "id": "uart/1", "port": "COM4", "baudRate": 921600 }
]
},
"route": {
"gatewaySessionId": "gws_...",
"resourceId": "res_...",
"capabilityId": "cap_...",
"hostWorkspaceRoot": "F:\\Work\\Project",
"hostCli": "node tools\\device-host-cli.mjs"
}
}
```
`profile_json` 不得保存 Git key、云 token、kubeconfig、数据库 URL 或长期 secret。`profile_hash``cloud-api` 对规范化 profile JSON 计算并在所有响应中返回;用户可见响应只能返回脱敏 profile 摘要和 hash。
## 数据表口径
正式规格推荐 `device_pods` 直接保存权威 profile 和 hash,避免额外 profile 微服务:
```sql
CREATE TABLE IF NOT EXISTS device_pods (
id TEXT PRIMARY KEY,
name TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'disabled')),
profile_json TEXT NOT NULL DEFAULT '{}',
profile_hash TEXT NOT NULL DEFAULT '',
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
```
历史版本中的 `profile_ref``gateway_ref``device_pod_json` 可以在迁移时折叠进 `profile_json`。第一阶段不新增 `device_pod_profile_revisions`;需要审计版本、回滚或多环境批准时再引入 profile revision 表。
`device_pod_grants` 仍只表达用户是否拥有完整使用权;它不保存 profile,也不拆 capability。
## REST API
用户态 API 只经过 `cloud-api` 暴露:
```text
GET /v1/device-pods
GET /v1/device-pods/{devicePodId}/status
GET /v1/device-pods/{devicePodId}/debug-probe/chip-id
GET /v1/device-pods/{devicePodId}/io-probe/uart/1
GET /v1/device-pods/{devicePodId}/io-probe/uart/1/tail?maxBytes=12000
POST /v1/device-pods/{devicePodId}/jobs
GET /v1/device-pods/{devicePodId}/jobs/{jobId}
GET /v1/device-pods/{devicePodId}/jobs/{jobId}/output
POST /v1/device-pods/{devicePodId}/jobs/{jobId}/cancel
```
管理员 API 由 `cloud-api` 提供:
```text
POST /v1/admin/device-pods
PUT /v1/admin/device-pods/{devicePodId}
POST /v1/admin/device-pod-grants
DELETE /v1/admin/device-pod-grants/{devicePodId}/{userId}
```
`POST /v1/device-pods/{devicePodId}/jobs``intent` 表达具体业务,避免把 REST surface 扩张成大量一次性 route
```json
{
"intent": "workspace.build",
"args": { "profile": "debug" },
"reason": "DEV smoke"
}
```
第一阶段 intent 集合:
- `workspace.ls`
- `workspace.cat`
- `workspace.rg`
- `workspace.apply-patch`
- `workspace.build`
- `debug.status`
- `debug.chip-id`
- `debug.download`
- `debug.reset`
- `io.ports`
- `io.uart.read`
- `io.uart.write`
所有响应必须包含 `devicePodId``targetId``profileHash``traceId``operationId``status``freshness``blocker` 和 bounded output metadata。真实硬件响应不得把 fake、dry-run、SOURCE、LOCAL 或过期缓存标为 `DEV-LIVE`
## 微服务职责
| 服务 | 职责 |
| --- | --- |
| `hwlab-cloud-api` | 用户身份、admin/user、device grant、lease、profile authority、用户态 REST API、转发到内部 device-pod。 |
| `hwlab-device-pod` | 多 `devicePodId` 运行 registry、profile runtime validation、job store、freshness、bounded output、gateway/device-host-cli adapter。 |
| `device-pod-cli` | 把 `devicePodId:surface:path operation args` 1:1 转成 cloud-api REST;不保存权威 profile、不直连 gateway。 |
| `device-host-cli` | Windows host 侧自包含业务工具,负责 Keil、pyOCD、UART、workspace 文件操作。 |
| `hwlab-gateway` | 只做受控 transport,不理解用户权限和 device-pod 授权。 |
| `hwlab-cloud-web` | 展示用户可见 device pod、admin 管理 profile/grant、显示 job/status/freshness。 |
## Kubernetes 口径
v0.2 第一阶段使用一个 `hwlab-device-pod` Deployment 和一个 ClusterIP Service
```text
hwlab-v02/hwlab-device-pod
replicas: 1
manages: many devicePodId
```
不为每个 `devicePodId` 创建 Deployment、Service、Ingress、Secret 或 namespace。这样更符合当前规模:运维对象少、GitOps diff 少、问题定位简单,也不会把设备数量直接放大成 k8s 资源数量。
只有在满足以下条件时,才考虑拆分为多个 `hwlab-device-pod` shard 或 per-device workload
- 单个服务内 job 队列和 freshness 监控互相影响;
- 不同设备需要不同 host network、USB、Secret 或资源 request
- 设备数量增长到单实例状态管理明显吃力;
- 强隔离需求超过应用层 grant 和内部服务凭据能覆盖的范围。
普通用户和 code agent session Pod 不应直接调用 `hwlab-device-pod` Service。正式路径是 `code agent -> cloud-api -> hwlab-device-pod`
## 验收标准
- `device-pod-cli` 在正式模式下不读取 `.device-pod/<devicePodId>.json` 作为权威 profile,只向 cloud-api 提交 `devicePodId`、intent 和 args。
- 普通用户无授权时不能看到或使用任何 device pod;授权后拥有对应 device pod 的完整使用权。
- code agent 不能通过修改本地文件改变 gateway session、resource、host workspace、probe UID 或 UART port。
- `hwlab-device-pod` 不接受无内部服务凭据的 profile snapshot 或 job 请求。
- `hwlab-device-pod` 一个实例可以列出并执行多个 `devicePodId` 的状态/job。
- fake fallback 只能标记为 fake/source,不得作为正式 device-pod DEV-LIVE 证据。
- 强副作用 job 必须有 reason,并在物理互斥需要时获取 `device_leases`