From a117c02e3f80d598b3bbd4888400040ea39e8d72 Mon Sep 17 00:00:00 2001 From: gongzhiyong Date: Sun, 14 Jun 2026 17:12:27 +0800 Subject: [PATCH] =?UTF-8?q?docs(#56):=20=E6=9B=B4=E6=AD=A3=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=20key=20=E5=BA=93=E5=90=8D=20heicode-kv=20=E2=86=92?= =?UTF-8?q?=20heicode-vault=EF=BC=88HM=20=E5=AE=9E=E6=B5=8B=E5=8F=A3?= =?UTF-8?q?=E5=BE=84=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit agent_swarm#56 评论:模型 key 的真实 Key Vault 库名是 `heicode-vault` (`https://heicode-vault.vault.azure.net`),早期契约文档误写为 `heicode-kv`; 且生产 `SECRET_RESOLVER` 须指向 `heicode-vault`。 - runtime-contract.md §3.3.1 A.3:库名更正 + 标注 SECRET_RESOLVER 指向 heicode-vault + 明确 Swarm 需提供 Pod 身份的 clientId+objectId 给 HM 授权(只读、限 swarm-model-key-*)。 - security-boundary.md:secret_ref 示例 host 同步更正。 - test-key-injection-contract.py:模型 key fixture host 同步更正(resolver 仅取末段名, 功能不变;测试仍全绿)。 纯文档/fixture 更名,无事件 schema/契约字段改动。 Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/integration/runtime-contract.md | 2 +- docs/integration/security-boundary.md | 2 +- scripts/test-key-injection-contract.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/integration/runtime-contract.md b/docs/integration/runtime-contract.md index 1b90d57..820f32b 100644 --- a/docs/integration/runtime-contract.md +++ b/docs/integration/runtime-contract.md @@ -99,7 +99,7 @@ HM 实现 #60(计费 key 注入)前需 Swarm 定死的参数,逐条口径 | A.1 | `sk-` 粒度 + mint 时机 | **每用户一把**(首次蜂群开通 mint、跨该用户所有 run 复用);同一用户的专家 agent 注入同一把 `sk-`、计费归一到发起用户。 | | A.1 | KV secret 命名约定 | `swarm-model-key-`(Swarm 只取 `secret_ref` 末段做名,不强约束路径;命名供 HM 定位)。 | | A.2 | KV secret **value 格式** | **JSON `{"openai_api_key":"sk-..."}`**(对齐 callback 签名密钥的 `{"callback_signing_secret":"..."}` 约定,可扩展)。Swarm 解析字段名 = `openai_api_key`;裸 `sk-` 字符串亦兼容(`_extract_model_key`);解析不到/字段缺失 → 不伪造、agent keyless 明确报错。 | -| A.3 | Swarm 读 KV 身份 / RBAC | **⚠ 联调阻塞前置(分两步)**:① **Swarm 侧先 provision Pod 的 Workload Identity**(建 UAMI → federate 到 `orchestrator-sa` SA → 用 `client-id` 注解 SA)——当前**尚未建**(仓内无 `azure.workload.identity/client-id` 注解、无 IaC);② **HM/运维** 在其库 `heicode-kv`(`https://heicode-kv.vault.azure.net`)给该身份授 `Key Vault Secrets User`(只读、限 `swarm-model-key-*`)。`heicode-kv` 是 HM 侧库,故授权由 HM/运维做;Swarm 只提供 Pod 身份 id + 收窄作用域。不通则 `secret_ref` 解不出。生产 KV 适配器(`SECRET_RESOLVER`)在仓外经部署接线;dev/CI 用 `HEICODE_SECRET_` 环境映射。 | +| A.3 | Swarm 读 KV 身份 / RBAC | **⚠ 联调阻塞前置(分两步)**:① **Swarm 侧先 provision Pod 的 Workload Identity**(建 UAMI → federate 到 `orchestrator-sa` SA → 用 `client-id` 注解 SA)——当前**尚未建**(仓内无 `azure.workload.identity/client-id` 注解、无 IaC);② **HM/运维** 在其库 **`heicode-vault`**(`https://heicode-vault.vault.azure.net`)给该身份授 `Key Vault Secrets User`(只读、限 `swarm-model-key-*`)。`heicode-vault` 是 HM 侧库,故授权由 HM/运维做;Swarm 只提供 Pod 身份 id(`clientId` + `objectId`)+ 收窄作用域。不通则 `secret_ref` 解不出。生产 KV 适配器(`SECRET_RESOLVER`)在仓外经部署接线,**须指向 `heicode-vault`**;dev/CI 用 `HEICODE_SECRET_` 环境映射。(库名更正自 agent_swarm#56:实库为 `heicode-vault`,非早期文档的 `heicode-kv`。) | | A.4 | `OPENAI_API_BASE` | **Swarm 部署常量**(`AGENT_OPENAI_API_BASE`/`OPENAI_API_BASE`,设为 HM 网关 `https://code.xinghanlab.com/v1`),**不**经 create 的 `billing_context` 下发。 | | A.5 | 吊销信号 | **事件驱动(方案 A)**:`sk-` per-user 长存;`stop` 是唯一**终态**(`completed`/`failed` 可经 `POST …/input` 重开,故仍保留 key)。当某用户**所有 run 均被 stop**(retained 集清空)时,运行时发**恰好一次** `swarm.pool_terminated{user_id, secret_ref}`,HM 收到即吊销 `sk-` + 清 KV。单 run 的 `swarm.stopped` **不**触发吊销(key per-user 复用);账户停用 / HM 主动 delete 走同一 stop 路径。 | diff --git a/docs/integration/security-boundary.md b/docs/integration/security-boundary.md index 122fd61..d19b211 100644 --- a/docs/integration/security-boundary.md +++ b/docs/integration/security-boundary.md @@ -30,7 +30,7 @@ `secret_context`(HM 下发,仅引用与审批结果): ```jsonc "secret_context": { - "secret_refs": ["azkv://heicode-kv.vault.azure.net/secrets/res_git_1"], + "secret_refs": ["azkv://heicode-vault.vault.azure.net/secrets/res_git_1"], "inject_short_lived_credentials": true, "approval_id": "approval_123" } diff --git a/scripts/test-key-injection-contract.py b/scripts/test-key-injection-contract.py index 9e77e07..8986492 100644 --- a/scripts/test-key-injection-contract.py +++ b/scripts/test-key-injection-contract.py @@ -44,7 +44,7 @@ async def stored_events(swarm_id): return [json.loads(r) for r in raw] -async def new_run(user_id, secret_ref="azkv://heicode-kv/secrets/swarm-model-key-u1"): +async def new_run(user_id, secret_ref="azkv://heicode-vault/secrets/swarm-model-key-u1"): body = { "mode": "swarm", "orchestration_plan": {"objective": "key-contract test"}, @@ -76,7 +76,7 @@ def test_kv_value_format(): os.environ.pop("AGENT_LAUNCH_MODEL_KEY", None) os.environ.pop("OPENAI_API_KEY", None) os.environ["HEICODE_SECRET_swarm-model-key-u1"] = '{"openai_api_key": "sk-RESOLVED"}' - body = {"billing_context": {"secret_ref": "azkv://heicode-kv/secrets/swarm-model-key-u1"}} + body = {"billing_context": {"secret_ref": "azkv://heicode-vault/secrets/swarm-model-key-u1"}} check("resolve_model_key resolves the azkv JSON secret to the bare sk-", agent_launcher.resolve_model_key(body) == "sk-RESOLVED") os.environ.pop("HEICODE_SECRET_swarm-model-key-u1", None)