15 KiB
v0.1 Provider Profile 管理规格
本文是 AgentRun v0.1 provider profile 管理能力的长期规格。实施跟踪见 pikasTech/agentrun#28,HWLAB v0.2 WebUI 配置入口见 pikasTech/HWLAB#917。
设计目标
- 由
agentrun-mgr提供 provider profile 状态查询、API Key 写入、Secret/config 更新和 canary 验证 REST API。 - AgentRun 后端直接信任来自 HWLAB
hwlab-cloud-api的服务端委托调用,不实现浏览器用户登录、Web session、HWLAB 用户角色或 OpenFGA 判断。 - 浏览器和 HWLAB Cloud Web 不直接访问 AgentRun,也不把原始 API Key 传入 run/session/command payload。
- AgentRun 只返回脱敏状态:profile、SecretRef、resourceVersion、hash 后缀、validation result、run/command/job identity 和 failureKind。
- provider profile 仍通过现有
backendProfile、executionPolicy.secretScope.providerCredentials[]、profile-scoped SecretRef 和 writableCODEX_HOME装配到 runner。
职责边界
| 组件 | 职责 |
|---|---|
agentrun-mgr |
provider profile 管理 API、Secret/config 写入、状态查询、canary 创建、validation 状态聚合和脱敏审计。 |
agentrun-runner |
按既有 backendProfile/SecretRef 装配 runtime,执行 canary run,不读取管理 API 的用户上下文。 |
HWLAB hwlab-cloud-api |
用户鉴权、业务授权、Web/CLI 同源 API、审计 actor、调用 AgentRun 管理 API。 |
HWLAB hwlab-cloud-web |
“管理”页面和 API Key 表单;不直接调用 AgentRun。 |
AgentRun 不承担 HWLAB 用户鉴权。它只做机器层 contract 校验:调用来源、tenant/project/profile allowlist、SecretRef scope、payload schema、redaction 和幂等性。AgentRun 不判断某个 HWLAB 用户是否能配置 API Key,也不保存 HWLAB Web session、API key 或 OpenFGA decision。
Profile 列表
v0.1 可管理 profile 分为内建 profile 与动态 profile slug。内建 profile 是无需 Secret 也必须出现在列表中的稳定能力;动态 profile 是管理员通过 HWLAB Cloud API / HWLAB CLI 或 AgentRun CLI 写入受控 Secret 后立即可见、可配置、可验证的 profile,不需要为每个新 slug 修改 AgentRun 或 HWLAB 服务代码。
| profile | backendKind | 默认 SecretRef | 说明 |
|---|---|---|---|
codex |
codex-app-server-stdio |
agentrun-v01/agentrun-v01-provider-codex |
Codex API profile。 |
deepseek |
codex-app-server-stdio |
agentrun-v01/agentrun-v01-provider-deepseek |
DeepSeek profile,经 HWLAB Moon Bridge 到 DeepSeek 官方 upstream。 |
minimax-m3 |
codex-app-server-stdio |
agentrun-v01/agentrun-v01-provider-minimax-m3 |
MiniMax-M3 profile。 |
dsflash-go |
codex-app-server-stdio |
agentrun-v01/agentrun-v01-provider-dsflash-go |
DeepSeek V4 Flash profile,经 HWLAB Moon Bridge 到 OpenCode Zen Go upstream。 |
动态 profile slug 必须匹配小写 slug 规则 ^[a-z0-9][a-z0-9-]{0,63}$,并固定映射到同 namespace 内 agentrun-v01-provider-<profile> SecretRef,required keys 仍为 auth.json 与 config.toml。profile 管理 API 不得允许任意 namespace、任意 Secret name、runtime-default 或不符合 slug 规则的 profile。新增普通 OpenAI/Codex-compatible provider profile 时,管理员应优先通过 provider-profiles set-config / set-key / validate 创建动态 slug;只有需要新的 backend kind、特殊装配规则、额外 Secret key、租户策略或产品级固定友好名时,才更新本规格、内建 capability、CLI 示例和验证规格。
REST API
Provider profile 管理 API 属于 agentrun-mgr 公共 REST API 的服务端委托面:
GET /api/v1/provider-profiles
GET /api/v1/provider-profiles/:profile
DELETE /api/v1/provider-profiles/:profile
GET /api/v1/provider-profiles/:profile/config
PUT /api/v1/provider-profiles/:profile/config
PUT /api/v1/provider-profiles/:profile/credential
POST /api/v1/provider-profiles/:profile/validate
GET /api/v1/provider-profiles/:profile/validations/:validationId
所有成功和失败响应都必须是 JSON。失败响应至少包含 failureKind、message 和 requestId。除显式 GET /api/v1/provider-profiles/:profile/config 返回 config.toml 明文供 HWLAB admin 管理页查看外,其他响应不得包含 API Key 原文、Codex auth.json 明文、Codex config.toml 明文、base64 Secret data、Authorization header、Kubernetes token 或 provider request header。
GET /api/v1/provider-profiles
返回所有内建 profile 与已存在动态 profile 的脱敏状态。动态 profile 通过受控 Secret 的 name、label 或 annotation 发现;删除动态 profile 的最后一个 Secret 后,它不再出现在 collection list 中。字段至少包含:
profilebackendKindconfiguredsecretRef.namespace/name/keysresourceVersionkeyHashSuffix或credentialHashSuffixconfigHashSuffixupdatedAtlastValidation.status/failureKind/message/runId/commandId/jobName
Secret 缺失时仍要返回 profile capability,并把状态标为 configured=false 或 failureKind=secret-unavailable;不得因为 Secret 未配置而隐藏 profile。
DELETE /api/v1/provider-profiles/:profile
删除 profile 对应 Kubernetes Secret。
- 内建 profile(
codex、deepseek、minimax-m3、dsflash-go)删除后,capability 仍必须保留在GET /api/v1/provider-profiles列表中,但状态回到configured=false/failureKind=secret-unavailable。 - 动态 slug 删除后,若没有剩余 Secret,对应 slug 不再出现在 collection list 中;显式
GET /api/v1/provider-profiles/:profile仍可返回该 slug 的未配置状态。 - 响应必须返回
removed或alreadyAbsent,并保持 Secret/API Key 脱敏。
GET/PUT /api/v1/provider-profiles/:profile/config
GET 返回当前 profile 的 configToml、SecretRef、resourceVersion 和 hash 后缀,供 HWLAB admin 管理页查看。PUT 接收 configToml,保存时只替换同一 Secret 的 config.toml,保留现有 auth.json,并返回 resourceVersion 和 configHashSuffix。
PUT /api/v1/provider-profiles/:profile/credential
请求体由 HWLAB 后端或受控 CLI 发送,最小形态:
{
"apiKey": "<write-only>",
"config": {
"model": "<optional>",
"baseUrl": "<optional>"
},
"delegatedBy": {
"system": "hwlab-v02",
"userId": "<hwlab-user-id>",
"username": "<hwlab-username>",
"requestId": "<hwlab-request-id>"
},
"reason": "hwlab-provider-management"
}
规则:
apiKey只在本次 request 内用于生成 Secret data,不能落入 Postgres、event、trace、日志或响应。- Manager 写入 profile 对应 Kubernetes Secret 的
auth.json和config.toml,并返回新的resourceVersion与不可逆 hash 后缀。 - Manager 可记录
delegatedBy的脱敏审计信息,但不把它作为用户鉴权依据。 - 非 HWLAB 委托调用可以用于 operator CLI,但也必须走同一 schema 和 redaction。
- 非法 profile、非法 baseUrl、SecretRef scope 越界、Kubernetes 写入失败和 config render 失败必须结构化失败。
POST /api/v1/provider-profiles/:profile/validate
触发一个真实 canary。它必须通过 AgentRun 自身 run/command/runner-job 路径执行,不得只做静态 Secret 读取、mock provider 或直接 curl provider 作为通过证据。响应短返回:
{
"validationId": "val_...",
"profile": "deepseek",
"runId": "run_...",
"commandId": "cmd_...",
"jobName": "agentrun-v01-runner-...",
"status": "running",
"pollUrl": "/api/v1/provider-profiles/deepseek/validations/val_..."
}
GET /validations/:validationId 聚合 command result、runner job status、events 和 provider failureKind,返回 running|completed|failed|cancelled。成功时必须能证明当前 backendProfile、SecretRef、CODEX_HOME、provider status 和 assistant reply;失败时必须保留 provider/secret/runner failureKind。
DeepSeek 配置规则
deepseek profile 的 Codex config 必须指向 HWLAB v0.2 Moon Bridge,而不是 hyue:
baseUrl: http://hwlab-deepseek-proxy.hwlab-v02.svc.cluster.local:4000/v1
expected request path: /v1/responses
upstream: DeepSeek 官方 API
AgentRun 不直接拥有 DeepSeek 官方 upstream URL 的业务路由;它只把 Codex app-server 请求送到 HWLAB Moon Bridge。若 HWLAB bridge 需要独立 upstream Secret 或 rollout,AgentRun 管理 API 必须在响应中返回 requiresExternalBridgeUpdate=true 或由 HWLAB 委托请求显式声明 bridge 同步已完成。AgentRun 不得把 deepseek 配置改到 hyueapi.com,也不得因 DeepSeek 失败 fallback 到 codex。
Secret 与 RBAC
Manager ServiceAccount 需要最小 Secret 管理权限,只允许 get、list、create、replace、delete、patch 受控 provider profile Secret:
agentrun-v01-provider-codexagentrun-v01-provider-deepseekagentrun-v01-provider-minimax-m3agentrun-v01-provider-dsflash-goagentrun-v01-provider-<dynamic-lowercase-slug>
不得授予 Manager 更新 namespace 内任意 Secret 的宽权限;动态 Secret 必须受 agentrun-v01-provider- 前缀、profile label/annotation 和 slug 校验约束。状态查询只读取受控 Secret metadata 和 key presence/hash,不返回 Secret value。
Secret 写入后,runner Job 仍按 spec-v01-secret-distribution.md 通过 SecretRef projection 装配;run/command payload 中不出现 API Key。
Secret 写入不得留下包含 Secret data 的 Kubernetes last-applied 注解。Manager 更新 credential 时应使用不会生成 kubectl.kubernetes.io/last-applied-configuration 的 patch/update 路径,或在写入完成后显式删除该注解;状态响应、event、trace 和 CLI 输出仍只能返回 SecretRef、resourceVersion、hash 后缀和 redacted validation identity。
CLI
AgentRun CLI 提供 operator 和综合联调入口:
./scripts/agentrun provider-profiles list
./scripts/agentrun provider-profiles show deepseek
./scripts/agentrun provider-profiles config deepseek
./scripts/agentrun provider-profiles remove deepseek
./scripts/agentrun provider-profiles set-key deepseek --key-stdin
./scripts/agentrun provider-profiles set-config deepseek --config-stdin
./scripts/agentrun provider-profiles validate deepseek --wait --timeout-ms 120000
./scripts/agentrun provider-profiles set-config my-provider --config-stdin
./scripts/agentrun provider-profiles set-key my-provider --key-stdin
CLI 必须调用 manager REST API,不直连 Postgres,不读取 Kubernetes Secret value。set-key --key-stdin 从 stdin 读入 API Key,默认输出只包含 SecretRef、resourceVersion、hash 后缀、failureKind 和下一步验证命令。
审计与脱敏
Manager 审计事件允许记录:profile、action、delegatedBy.system、delegatedBy.userId、requestId、SecretRef、old/new hash 后缀、resourceVersion、validationId、runId、commandId、jobName、failureKind。禁止记录:API Key 原文、Secret data、Codex auth/config 明文、Authorization header、provider request header/body、Kubernetes token。
验收规格
T1 profile 状态
阅读本文和 spec-v01-secret-distribution.md,调用 GET /api/v1/provider-profiles 或 ./scripts/agentrun provider-profiles list。确认 codex、deepseek、minimax-m3、dsflash-go 等内建 profile 全部可见,缺 Secret 时显示 configured=false 或 secret-unavailable,不隐藏 capability;已创建的动态 slug 也会列出;所有输出都不得包含 Secret value。
T2 DeepSeek 写入
用 ./scripts/agentrun provider-profiles set-key deepseek --key-stdin 写入测试 key。确认输出只有 resourceVersion/hash 后缀和 redacted SecretRef;Postgres、event、trace、日志和 CLI 输出不含完整 key。
T3 DeepSeek canary
用 ./scripts/agentrun provider-profiles validate deepseek --wait 触发真实 runner canary。通过证据必须包含 validationId、runId、commandId、jobName、backendProfile=deepseek、SecretRef=agentrun-v01-provider-deepseek、terminal completed 和非空 assistant reply。
T4 HWLAB 委托
通过 HWLAB v0.2 Cloud API /v1/admin/provider-profiles/deepseek/credential 和 /validate 调用本 API,确认 AgentRun 不要求 HWLAB 用户凭据,不读取 Web session,不返回用户权限判断;但会记录 delegatedBy.system=hwlab-v02 和 requestId 的脱敏审计。
T5 redaction
检查 manager 日志、AgentRun events、CLI 输出和 validation result,确认不包含 API Key 原文、Codex auth.json、config.toml、Secret data 或 Authorization header。
T6 profile 删除
用 ./scripts/agentrun provider-profiles remove <profile> 删除一个动态 slug,再删除一个内建 profile。确认动态 slug 从 collection list 消失;内建 profile 仍留在 list 中但 configured=false;CLI/日志/响应不输出 Secret value。
T7 动态 profile 无代码变更
用 HWLAB CLI 或 AgentRun CLI 对一个临时动态 slug 执行 set-config、set-key、list、remove。通过证据必须显示 profile SecretRef 为 agentrun-v01-provider-<slug>、configured=true 只在 auth.json 和 config.toml 同时存在时成立、删除后 collection list 不再包含该 slug,并且整个过程没有 AgentRun/HWLAB service code change、PR、PipelineRun 或 rollout 作为前置条件。
实现状态
| 能力 | 状态 | 说明 |
|---|---|---|
| Provider profile 管理规格 | 已定义/已落地 | 本文为 AgentRun v0.1 profile 管理权威规格。 |
| REST 管理 API | 已实现 | agentrun-mgr 提供 /api/v1/provider-profiles*,覆盖 list/show/remove/set-key/validate/validation。 |
| 动态 profile slug | 已实现 | 小写 slug 通过 agentrun-v01-provider-<slug> SecretRef 动态生效;普通 provider API Key/config 轮换不需要为每个新 slug 修改服务代码或触发专门 CI/CD。 |
| CLI 管理入口 | 已实现 | ./scripts/agentrun provider-profiles list/show/remove/set-key/set-config/validate 调用 manager REST API,不直连 Secret value。 |
| DeepSeek Secret 写入 | 已实现/需硬化 | 已按受控 SecretRef 更新 auth.json/config.toml 并保持 HWLAB Moon Bridge 官方链路;后续必须去除 credential update 产生 last-applied-configuration 注解的副作用。 |
| Provider canary | 已实现 | canary 通过真实 run/command/runner-job 路径执行,并返回 validationId、runId、commandId、jobName 和 terminal status。 |
| HWLAB 委托信任边界 | 已验证 | HWLAB v0.2 通过 Cloud API 委托调用本 API;AgentRun 不读取 HWLAB Web session,也不做用户级鉴权。 |