Files
pikasTech-HWLAB/docs/reference/spec-v02-hwlab-cloud-api.md
T
2026-06-05 09:39:49 +08:00

112 lines
18 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.
# v0.2 hwlab-cloud-api 服务规格
`hwlab-cloud-api``v0.2` 应用层核心服务,运行在 `hwlab-v02` namespace,内部端口 `6667`,公网经 `hwlab-edge-proxy` 和 FRP 暴露为 `http://74.48.78.17:19667`
## 在系统中的职责划分
- 承担 runtime health、DB readiness、登录鉴权、`AuthPrincipal`、OpenFGA 授权 check/write、用户/session/API key 权限、Code Agent 对话、trace/result 轮询、gateway outbound registry、M3 IO 控制、device-pod authority/job 和 live build inventory。
-`hwlab-cloud-web`、Code Agent session、device-pod 用户态操作、Admin Access API、AgentRun 工具注入和 gateway outbound poll 的唯一应用层收口点;普通用户不直接访问内部 `hwlab-device-pod` Service 或 OpenFGA Service。
- 读取 `hwlab-cloud-api-v02-db/database-url``hwlab-v02-code-agent-provider/openai-api-key``hwlab-v02-code-agent-codex-auth/auth.json` 等 v02 独立 SecretRef;用户 API key 存在 Postgres `api_keys`,不得再以 `hwlab-v02-device-pod-api-key/api-key` 这类跨用户 SecretRef 授权 device-pod。文档和日志只允许记录 SecretRef 名称、key、字节数或哈希指纹,不记录值。
- 读取 OpenFGA URL、auth token、store/model 指针和 mode 时只能通过 env/SecretRef/Postgres runtime config`/health/live``/v1/admin/access/summary` 只输出 readiness、mode、storeId/modelId 摘要和 degraded reason,不输出 token、Postgres URL 或 tuple secret。
## 内部架构
- `cmd/hwlab-cloud-api/main.ts` 负责启动 HTTP server、解析端口和 Code Agent timeout。
- `internal/cloud/server.ts` 负责 HTTP route、REST/RPC bridge、health、live-builds、device-pod authority、gateway poll/result 和 Code Agent chat。
- `internal/cloud/openfga-authorization.ts` 或等价模块负责 OpenFGA client、store/model bootstrap、`off/shadow/enforce` 策略、check/write、tuple import 和 structured authorization decision;最终规格见 [spec-v02-openfga-authorization.md](spec-v02-openfga-authorization.md)。
- `internal/cloud/access-control.ts` 负责 `/auth/*`、OIDC callback、Web session、用户 API key、admin/user、device pod profile/grant legacy compatibility、device job lifecycle 和 Code Agent owner binding;登录与鉴权 authority 见 [spec-v02-auth.md](spec-v02-auth.md)。当前本地 `/auth/login` 只作为 bootstrap/legacy fallback。
- `internal/cloud/access-control.ts` 也是账号 workspace authority`account_workspaces` 记录同一账号的 Workbench 当前 workspace、selected conversation/session、active trace、provider profile 和 revision。
- Code Agent session 生命周期必须显式化。Cloud API 目标入口为 `POST /v1/agent/sessions` 创建 session、`GET/PATCH /v1/agent/sessions*` 查询/选择/标记状态;`POST /v1/agent/chat` 只接受显式传入或账号 workspace 中已显式选中的 usable session。没有 session 时返回 `session_required`session failed/stale/canceled 时返回 `session_not_usable`,不得自动创建、滚动或替换 session。
- Code Agent session record 是 provider profile authority。`POST /v1/agent/chat` 带显式 session 且请求未显式给出 provider profile 时,Cloud API 必须继承该 session 的 `providerProfile` 并映射为 AgentRun `backendProfile`;请求显式覆盖 provider profile 时,覆盖必须进入 trace/result 可见字段。账号 workspace 的 provider profile 只能在 selected session 与目标 session 完全一致时作为 fallback,不得让旧 workspace 覆盖显式 session。
- `internal/db/runtime-store.ts``internal/cloud/db-contract.ts` 负责 Postgres runtime store 与 readiness 分层。
- `internal/cloud/code-agent-*.ts` 负责 Codex stdio session、trace store、result cache、provider profile 和取消/轮询。
- AgentRun dispatch 的 policy 字段由 Cloud API adapter 固定归一化:`tenantId=hwlab``projectId=pikasTech/HWLAB``providerId=G14`。Workbench project/workspace 只能作为 HWLAB metadata 或 `workspaceRef` 子字段保存,不能污染 AgentRun `projectId`;出现 project/tenant 混乱时,临时处理是修 adapter 字段映射并用真实运行面最小请求复测,不放宽 AgentRun manager policy。
- AgentRun v0.1 接入只使用标准 `threadId` 路径:`POST /v1/agent/chat` 收到的 `conversationId/sessionId/threadId` 必须写入 AgentRun command `payload.threadId``SessionRef.threadId`;协议字段、trace、result 和 conversation facts 都以该字段为唯一 thread identity。
- AgentRun run 级 events 写回 HWLAB trace 时必须按当前 `commandId` 归属过滤;同一 run 的旧 command 尾部事件不能混入后续 command trace。取消、失败或 blocked 轮次如果已有 assistant/tool 可读进展,必须以脱敏、限长的 conversation facts 写入 UI/trace/inspect 证据,供后续 `inspect`/`--from-trace` 可见性使用;这些 facts 不得作为下一轮模型上下文或 prompt 拼接来源。
- AgentRun completed 轮次续接必须依赖 Codex stdio 原生 session continuation。Cloud API 只把本轮原始 `message/prompt` 和显式 session 的标准 `conversationId/sessionId/threadId` 写入 AgentRun command payload 与 `SessionRef`;不得从请求、account workspace 或 account conversation 生成 `conversationContext`,不得把历史消息拼入 prompt,也不得把请求体里的 `conversationContext/messages` 当作模型上下文。历史 conversation facts 只用于 UI、inspect、trace 和 `--from-trace` 的可见性证据;收到 synthetic context 字段时只能记录 ignored trace 并剥离。`thread/resume` 失败时按 AgentRun `thread-resume-failed` 终止本轮并标记当前 session failed/stale,不自动创建新 session。
- Code Agent 不允许存在 turn/session/conversation 总时长 timeout;只允许无新 app-server 响应、无 notification、无 assistant/tool/event activity 的 idle timeout。AgentRun command 失败、provider 失败或 idle timeout 只终结当前 command,并按 session policy 标记当前 session 状态;系统不得自动滚动到新 session。后续消息要么继续同一个 usable session/thread,要么由用户显式创建或选择另一个 session。
- runner pod 被删、runner Job 被重建或旧 lease 失效后,同一 HWLAB session 的恢复判定必须基于同一个 `sessionId``threadId``providerProfile/backendProfile`、AgentRun `SessionRef` 和 PVC。replacement run/job 只能作为恢复执行壳;Cloud API 仍要把它映射为同一业务 session 的后续 turn,并在 trace/result 中分离业务 session identity 与执行 run/job identity。长期目标仍是在 runner reuse window 内复用同一 AgentRun run/runner。
- Cloud API 通过 AgentRun v0.1 `runner-jobs.transientEnv` 传递本次 Code Agent turn 的短期上下文,例如 `HWLAB_RUNTIME_*``HWLAB_CODE_AGENT_ASSEMBLED_RUNTIME` 和映射到当前 session owner 的 `HWLAB_API_KEY``transientEnv` 不设固定 8 项上限,新增短期上下文时必须按 name 去重、只传本次 Job 需要的 value;`HWLAB_RUNTIME_API_URL` 必须指向当前 namespace 内的 `hwlab-cloud-api` Service`HWLAB_RUNTIME_WEB_URL` 才指向 `hwlab-cloud-web``HWLAB_API_KEY` 必须对应当前 `agent_sessions.owner_user_id`,并继续禁止承载 GitHub token、provider key、长期 SSH key 或其他无关 credential;文档、日志和 trace 只允许保留脱敏后的 name、来源或摘要,不打印 Secret 值。
- AgentRun runner 工具环境注入必须经过 OpenFGA tool capability check。用户没有 `tool:hwpod#can_use` 时不注入可用 `HWLAB_API_KEY``hwpod`;没有 `tool:unidesk_ssh#can_use` 时不注入 UniDesk SSH token、route alias 或相关 helper;没有 `tool:trans_cmd#can_use` 时不暴露 trans cmd 透传入口;GitHub issue/PR 写工具也必须独立授权。工具授权不绕过 UniDesk route/operation 边界。
- 同 Pod sidecar `hwlab-codex-api-forwarder` 监听 `127.0.0.1:49280/responses`,用于 `codex-api` profile 直连 hyueapi,并保持 hyueapi 在 `NO_PROXY` 中。
- `hwlab-code-agent-workspace` PVC 挂载到 `/workspace/hwlab`,用于长会话 workspace;它是 cloud-api 运行资源,不是独立用户入口。
## API 接口说明
| 接口 | 说明 |
| --- | --- |
| `GET /health``GET /health/live` | 返回 service identity、environment、revision、DB/runtime/Code Agent readiness 和 blocker。 |
| `GET /live` | 轻量 live 标记。 |
| `GET /v1` | REST adapter 索引、RPC 方法、runtime readiness 和 device-pod/M3 能力摘要。 |
| `POST /rpc``POST /json-rpc` | JSON-RPC 入口,支持 system、adapter、gateway、hardware、audit、evidence 和 M3 方法。 |
| `POST /v1/rpc/{method}` | REST 到 JSON-RPC 的桥接入口。 |
| `GET /v1/device-pods...` | 经 cloud-api 鉴权后读取服务端 profile/grant/job authorityprobe GET 会创建只读 device job 并经 `hwlab-device-pod` executor/gateway 执行或返回同源 blocker,不会回退到 fake device pod 数据。 |
| `GET /auth/oidc/login``GET /auth/oidc/callback``GET /auth/session``POST /auth/logout` | Keycloak OIDC、Web session 24 小时轮换和 logout 入口,最终规格见 [spec-v02-auth.md](spec-v02-auth.md)。 |
| `POST /auth/login` | 本地账号密码 bootstrap/legacy fallback;目标 Web/CLI 登录不依赖该入口。 |
| `GET /v1/auth/session``GET /v1/users/me``GET /v1/access/status``GET /v1/setup/status` | v0.2 用户/session/setup 的 REST 状态和兼容入口;响应不得暴露 password hash、session token 原文或 Secret 值。 |
| `GET/POST /v1/api-keys...` | 用户 API key 管理入口;CLI 和 AgentRun runner 内 `hwpod` 都使用 `HWLAB_API_KEY`,映射到用户后再按权限表授权。 |
| `POST /v1/admin/users``POST/PUT /v1/admin/device-pods``POST/DELETE /v1/admin/device-pod-grants...` | `admin` 管理用户、device pod profile 和 grant 的入口。 |
| `GET/PATCH/PUT/DELETE /v1/admin/access...` | Admin Access API;读写 OpenFGA 细粒度授权、tool capability、role/status 和 effective matrix。 |
| `POST /v1/admin/access/check` | 管理员调试授权 check;返回 mode、decision、object/relation 和 redacted actor,不返回 OpenFGA token。 |
| `GET/PATCH /v1/workbench/workspace``POST /v1/workbench/workspace/{id}/reset``GET /events` | 账号级共享 workspace authority;所有读写按 ownerUserId 隔离,写入使用 revision 观测冲突,active trace 只表示最近活动/当前选中 trace,不作为同账号 Code Agent 并发互斥锁。 |
| `POST /v1/agent/sessions``GET/PATCH /v1/agent/sessions...` | 显式 Code Agent session 生命周期入口;创建/选择/状态标记 session,并与账号 workspace selection 同步。 |
| `GET /v1/m3/status``POST /v1/m3/io` | M3 只读/受控 IO 入口;写操作必须有明确 approval。 |
| `GET /v1/diagnostics/gate``GET /v1/live-builds` | 诊断和 live build inventory。 |
| `GET /v1/gateway/sessions``POST /v1/gateway/poll``POST /v1/gateway/result` | gateway 主动出站注册、取任务和回传结果。 |
| `POST /v1/internal/device-pod/gateway-dispatch` | 仅接受 `hwlab-device-pod` 内部服务凭据,用于把 executor job dispatch 到 gateway poll/result;普通用户和 Code Agent 不可调用。 |
| `POST /v1/agent/chat``POST /v1/agent/chat/steer``GET /v1/agent/chat/result/{traceId}``GET /v1/agent/chat/trace/{traceId}``POST /v1/agent/chat/cancel` | Code Agent 短连接提交、运行中 steer、轮询、trace 和取消;普通 chat 必须绑定显式 usable session。 |
### `/v1/live-builds` 语义
`/v1/live-builds` 返回的是运行面服务清单,不是 Cloud Web 专属 health。`latest` 字段按所有 HWLAB runtime service 的 build time 排序,可能指向 `hwlab-cloud-api``hwlab-cloud-web``hwlab-agent-skills` 或其他本轮最近滚动的服务;当 API 比 Web 更新时,`latest.serviceId=hwlab-cloud-api` 是正常状态,不能据此判断 Cloud Web 构建时间缺失或 Web rollout 失败。
需要验证 Cloud Web 时必须读取 `services[]``serviceId=hwlab-cloud-web` 的行,并区分 `build.createdAt``image.tag/digest``commit.id``revision``build.liveMetadataMatch``/health/live` 只能证明当前服务 health/revisionCloud Web 顶部 build chip 和详情弹窗展示的构建时间、env image 和实际 runtime commit 以 `/v1/live-builds` 的对应 service row 为准。
登录鉴权 API 的最终规格见 [spec-v02-auth.md](spec-v02-auth.md);用户、权限、device-pod 管理 API 的最终规格见 [spec-user-access.md](spec-user-access.md) 和 [spec-device-pod.md](spec-device-pod.md)。
OpenFGA、Access API、工具能力和 shadow/enforce 策略的最终规格见 [spec-v02-openfga-authorization.md](spec-v02-openfga-authorization.md)。
## 测试规格
## T1
阅读 docs/reference/spec-v02-hwlab-cloud-api.md,然后用 cli 手动测试以下内容:访问 `http://74.48.78.17:19667/health/live`,确认 `environment=v02``ready=true`、DB runtime 为 Postgres,且响应不包含 Secret 值。
## T2
阅读 docs/reference/spec-v02-hwlab-cloud-api.md,然后用 cli 手动测试以下内容:先显式创建 Code Agent session,再使用短连接 `POST /v1/agent/chat` 绑定该 session 提交一次对话,并轮询 `/v1/agent/chat/result/{traceId}`;只有 `status=completed` 且 assistant reply 非空才算 Code Agent 通过。未绑定 session 的普通 chat 必须返回 `session_required`。对运行中请求使用 `POST /v1/agent/chat/steer` 时,响应必须包含 target trace、steerTraceId、AgentRun runId/targetCommandId/steerCommandId 和继续观察原 trace 的 result/trace URL。
## T2.1
阅读 docs/reference/spec-v02-hwlab-cloud-api.md,然后用 cli 手动测试以下内容:在同一个显式 `conversationId/sessionId/threadId` 中先发起一轮会产生可见 assistant/tool 进展的 Code Agent 请求并取消,再发送“回答一下刚才调查结果”这类后续消息;如果 session 仍 usable,第二轮必须继续使用同一个标准 `threadId`,且 trace/result 不能混入上一 command 的尾部事件。如果取消导致 session failed/staleAPI 必须拒绝继续并要求显式创建新 session,不能自动滚动。
## T2.2
阅读 docs/reference/spec-v02-hwlab-cloud-api.md,然后用 cli 手动测试以下内容:在同一个显式 `conversationId/sessionId/threadId` 中先完成一轮“看看 device-pod 可用性?”这类 Code Agent 请求,再发送“总结我们刚才的对话内容”;第二轮 AgentRun command 必须只包含本轮原始 message/prompt、同一个标准 threadId 和必要运行元数据,不得包含 `conversationContext/messages` 或历史 prompt 拼接。assistant reply 必须通过 Codex stdio 原生 `thread/resume` 记住第一轮,不能回答“这是本会话第一条消息”或等价的新会话结论;若 `thread/resume` 失败,应以 `thread-resume-failed` 终止并标记 session failed/stale,继续前必须显式创建新 session。
## T3
阅读 docs/reference/spec-v02-hwlab-cloud-api.md,然后用 cli 手动测试以下内容:未登录访问 `/v1/device-pods` 必须返回认证错误;登录后访问 device-pod list/status 时必须显示 `contractVersion=device-pod-authority-v1``fake=false` 来源,不得出现 fake fallback。
## T4
阅读 docs/reference/spec-v02-hwlab-cloud-api.md 和 docs/reference/spec-v02-openfga-authorization.md,然后用 cli 手动测试以下内容:用 admin 调用 `GET /v1/admin/access/summary``POST /v1/admin/access/check`,确认 OpenFGA mode/readiness/store/model/decision 可见且 Secret 不泄漏;普通用户调用 admin access API 必须返回 403。
## T5
阅读 docs/reference/spec-v02-hwlab-cloud-api.md 和 docs/reference/spec-v02-openfga-authorization.md,然后用 cli 手动测试以下内容:撤销某用户 `tool:unidesk_ssh``tool:hwpod` 后创建 Code Agent session,确认 runner transient env 和 trace 摘要不再注入对应工具能力,强行调用返回结构化 authorization blocker。
## 规格的实现情况
| 规格项 | 状态 | 说明 |
| --- | --- | --- |
| health/readiness | 已实现 | `/health/live` 汇总 DB、runtime、Code Agent 和 blocker。 |
| Code Agent 短连接 submit/steer/result/trace/cancel | 已实现 | repo-owned Codex stdio、运行中 steer 和 provider profile 已接入。 |
| 显式 Code Agent session 生命周期 | 目标状态 | `/v1/agent/sessions*` 管理 session create/select/status`/v1/agent/chat` 无 session 时返回 `session_required`,失败 session 不自动滚动。 |
| Postgres durable runtime | 已实现 | 通过 v02 独立 DB SecretRef 和 migration ledger 判定。 |
| gateway outbound poll/result | 已实现 | 支持 gateway 主动轮询和 `hardware.invoke.shell` 分发。 |
| device-pod 正式权限/profile/job | 部分实现 | profile/grant/list/status/job 持久化在 cloud-api;用户态 probe GET 已收敛为只读 job;已提供内部 gateway dispatch route 供 `hwlab-device-pod` executor 下发到 device-host-cli,无在线 gateway/device-host-cli 时返回 blocker。 |
| v0.2 登录鉴权与 admin/user 权限模型 | 部分实现 | 当前 `/auth/*` 是本地账号密码和 7 天 sessionKeycloak OIDC、24 小时 Web session、CLI API key 和 `AuthPrincipal` 归一仍需按 spec-v02-auth 收敛。admin user/device-pod/grant API 和 Code Agent owner binding 已接入;生产 bootstrap 依赖 SecretRef。 |
| OpenFGA 细粒度授权与 Admin Access API | 目标状态 | 需要实现 OpenFGA client/bootstrap、`off/shadow/enforce``/v1/admin/access*`、tool capability check 和 runner env 过滤。 |
| 账号共享 workspace authority | 已实现 | `account_workspaces` 持久化同账号 Web/CLI 共享 workspace,支持 revision 冲突可见性、账号隔离、最近 active trace 记录和 reset;同一用户不同 session/run 允许并发,互斥只在 session/thread/run 层处理。 |