19 KiB
v0.2 hwlab-cloud-api 服务规格
hwlab-cloud-api 是 v0.2 应用层核心服务,运行在 hwlab-v02 namespace,内部端口 6667,公网经 hwlab-edge-proxy 和 FRP 暴露为 http://74.48.78.17:19667。
Provider API Key 管理属于 Cloud API 的 authenticated admin surface:前端只调用 /v1/admin/provider-profiles*,Cloud API 使用 HWLAB AuthPrincipal 和授权模型判定后,把 provider profile 状态查询、API Key 写入和 canary 验证委托给 AgentRun 后端。Cloud API 不直接写 AgentRun Secret,不把 API Key 原文写入日志或响应;详细合同见 spec-v02-provider-management.md。
在系统中的职责划分
- 承担 runtime health、DB readiness、登录鉴权、
AuthPrincipal、OpenFGA 授权 check/write、用户/session/API key 权限、Code Agent 对话、trace/result 轮询、gateway outbound registry、M3 IO 控制、HWPOD node-ops 转发和 live build inventory。 - 是
hwlab-cloud-web、Code Agent session、HWPOD CLI、Admin Access API、AgentRun 工具注入和 gateway outbound poll 的唯一应用层收口点;普通用户不直接访问 OpenFGA Service 或 host 侧 node 资源。 - 读取
hwlab-cloud-api-v02-db/database-url、hwlab-v02-master-server-admin-api-key/api-key、hwlab-v02-code-agent-provider/openai-api-key和hwlab-v02-code-agent-codex-auth/auth.json等 v02 独立 SecretRef;用户 API key 存在 Postgresapi_keys,HWPOD 用户态授权只能从该表恢复到用户 actor。master server 管理员 API key 通过 bootstrap env 同步为usr_v02_admin的固定key_master_server_admin,只记录 SecretRef、key id、scope 摘要、字节数或哈希指纹,不记录值。 - 读取 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、HWPOD node-ops、gateway poll/result 和 Code Agent chat。internal/cloud/openfga-authorization.ts或等价模块负责 OpenFGA client、store/model bootstrap、enforce策略、check/write 和 structured authorization decision;最终规格见 spec-v02-openfga-authorization.md。internal/cloud/access-control.ts负责/auth/*、OIDC callback、Web session、用户 API key、admin/user、tool capability 和 Code Agent owner binding;登录与鉴权 authority 见 spec-v02-auth.md。当前本地/auth/login只作为 bootstrap 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并映射为 AgentRunbackendProfile;请求显式覆盖 provider profile 时,覆盖必须进入 trace/result 可见字段。AgentRun dispatch、dynamic profile slug 和 nested childspawnenv-only 继承的权威规则见 agentrun-code-agent-dispatch.md。 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子字段保存,不能污染 AgentRunprojectId;出现 project/tenant 混乱时,临时处理是修 adapter 字段映射并用真实运行面最小请求复测,不放宽 AgentRun manager policy。 - AgentRun v0.1 接入只使用标准
threadId路径:POST /v1/agent/chat收到的conversationId/sessionId/threadId必须写入 AgentRun commandpayload.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失败时按 AgentRunthread-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、AgentRunSessionRef和 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、HWLAB_CODE_AGENT_PROVIDER_PROFILE、HWLAB_CODE_AGENT_PARENT_TRACE_ID和映射到当前 session owner 的HWLAB_API_KEY。transientEnv不设固定 8 项上限,新增短期上下文时必须按 name 去重、只传本次 Job 需要的 value;HWLAB_RUNTIME_API_URL必须指向当前 namespace 内的hwlab-cloud-apiService,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-apiprofile 直连 hyueapi,并保持 hyueapi 在NO_PROXY中。 hwlab-code-agent-workspacePVC 挂载到/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、HWPOD node-ops 和 M3 能力摘要。 |
POST /rpc、POST /json-rpc |
JSON-RPC 入口,支持 system、adapter、gateway、hardware、audit、evidence 和 M3 方法。 |
POST /v1/rpc/{method} |
REST 到 JSON-RPC 的桥接入口。 |
POST /v1/hwpod-node-ops |
接收 hwpod-node-ops-v1 plan,经 cloud-api 鉴权和工具能力校验后转发到 hwpod-node 执行,返回 node/action/result/blocker 摘要;不回退到 fake 数据或旧内部 executor。 |
GET /auth/oidc/login、GET /auth/oidc/callback、GET /auth/session、POST /auth/logout |
Keycloak OIDC、Web session 24 小时轮换和 logout 入口,最终规格见 spec-v02-auth.md。 |
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 |
admin 管理用户 role/status 的入口。 |
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/PUT/POST/DELETE /v1/admin/provider-profiles... |
Provider API Key 管理入口;Cloud API 鉴权和审计后委托 AgentRun 后端,返回脱敏 profile 状态、SecretRef 摘要和 canary 结果,不返回 Secret value。 |
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/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/revision;Cloud Web 顶部 build chip 和详情弹窗展示的构建时间、env image 和实际 runtime commit 以 /v1/live-builds 的对应 service row 为准。
登录鉴权 API 的最终规格见 spec-v02-auth.md;用户、权限和工具能力管理 API 的最终规格见 spec-user-access.md。HWPOD 概念体系见 spec-hwpod-harness.md。 OpenFGA、Access API、工具能力和 shadow/enforce 策略的最终规格见 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/stale,API 必须拒绝继续并要求显式创建新 session,不能自动滚动。
T2.2
阅读 docs/reference/spec-v02-hwlab-cloud-api.md,然后用 cli 手动测试以下内容:在同一个显式 conversationId/sessionId/threadId 中先完成一轮“检查 HWPOD node 状态”这类 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 手动测试以下内容:未登录访问 POST /v1/hwpod-node-ops 必须返回认证错误;登录后提交 node.health 只读 plan 时必须显示 contractVersion=hwpod-node-ops-v1、目标 node/action 摘要和真实 blocker/result,不得出现 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。
T4.1
阅读 docs/reference/spec-v02-provider-management.md,然后用 cli 手动测试以下内容:用 admin 调用 GET /v1/admin/provider-profiles、PUT /v1/admin/provider-profiles/deepseek/credential 和 POST /v1/admin/provider-profiles/deepseek/validate,确认 Cloud API 先恢复 HWLAB actor,再委托 AgentRun 后端,响应只包含 SecretRef/resourceVersion/hash 后缀和 validation/run/command/job/trace 摘要;普通用户或未登录请求必须返回 auth/authorization blocker,响应、日志和 trace 不输出 API Key 原文。
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 | 已实现 | AgentRun v0.1 delegated execution、运行中 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 分发。 |
| HWPOD node-ops 转发 | 已实现 | POST /v1/hwpod-node-ops 接收 hwpod-compiler-cli 生成的 plan,经 cloud-api 转发到 hwpod-node;无在线 node 时返回结构化 blocker。 |
| Provider API Key 管理委托 | 已实现 | /v1/admin/provider-profiles* 由 HWLAB 鉴权后委托 AgentRun 后端管理 profile Secret/配置和 canary;HWLAB 不直写 AgentRun Secret。 |
| v0.2 登录鉴权与 admin/user 权限模型 | 部分实现 | 当前 /auth/* 是本地账号密码 bootstrap fallback 和 Web session;Keycloak OIDC、24 小时 Web session、CLI API key 和 AuthPrincipal 归一仍需按 spec-v02-auth 收敛。admin user/tool capability API 和 Code Agent owner binding 已接入;生产 bootstrap 依赖 SecretRef。 |
| OpenFGA 细粒度授权与 Admin Access API | 目标状态 | 需要实现 OpenFGA client/bootstrap、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 层处理。 |