issue #17 要求「每步 trace 可回放(谁/何模型/何工具/何审批)+ schema 冻结 + 测试」。 本仓已持久化事件流 + 任务谱系 + 每任务 usage(model_id) + 审批;本 PR 把它们规整为 统一、有序、可回放的审计记录并冻结 schema。 代码: - orchestrator/audit.py(新,纯模块,无 Redis/WS/FastAPI/模型):build_audit_trace( events, task_facts, approvals, lineage) 逐事件产审计记录(who/when/model_id/tool_count/ approval{id,decision}/result/lineage),audit_id 由序位确定(非随机,可字节级复现); replay(records) 产人读步骤行。无内容、无密钥、缺信号不伪造(model/tool 缺则 null)。 - orchestrator/main.py:build_audit_trace_for_run(装配器,从 list_events + 任务 usage + run.approvals 取数)+ 读接口 GET …/{id}/audit(三别名路由,复用既有鉴权)。 文档:docs/integration/audit-trace-schema.md → FROZEN v1:§3.1 回放装配、§5 冻结记录形; 诚实标注**有意排除**(prompt/代码原文、model 请求响应体刻意不留痕——无内容原则; 无 SK/MCP 工具层故无工具名谱系),按规则 #9 不伪造、不在本次扩展。 测试:scripts/test-audit-trace.py(纯模块 + 集成):逐步 who/model/tool/approval 重建、 result 归类、有序回放、**断言无 secret_ref/azkv/明文泄漏**;接入 CI。 影响范围:仅 agent_swarm(orchestrator 新增只读审计接口 + 纯模块 + 文档 + 测试 + CI)。 - Manager:新增只读 GET …/{id}/audit;不改回调/契约/计费/审批链。 - 密钥/审计:审计记录只含非内容元数据 + secret_ref 永不写入;归因按 user/channelId,不引入 tenant。 Refs #17 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7.3 KiB
审计与链路追踪 Schema(Audit / Lineage / Trace)
状态:FROZEN v1(可回放审计记录已落地) —— 回应 issue #17。每步 trace(谁/何时/何模型/何工具/何审批/结果/lineage)可由
orchestrator/audit.py的纯装配器从已持久化的事件流 + 任务谱系 + 审批重建并按序回放;读接口GET …/{id}/audit。契约测试scripts/test-audit-trace.py。诚实边界(规则 #9,本次不扩展):审计记录只含非内容元数据——prompt 原文/代码/对话刻意不留痕(与回调脱敏同源原则);model trace =
model_id+ token 计数(不留请求/响应体);tool trace = 文件/Git 资源动作计数(本运行时无 SK/MCP 工具层,故无工具名谱系)。这些为有意取舍/后续层,不在本次冻结内。依据:
heicode-mananger/docs/heicode.md §五/§九、docs/heicode-runtime-auth-newapi-secret-design.md §三。配套:event-schema.md、security-boundary.md。
1. 原则
- 审计要能回答:谁、在什么时候、让哪个子 Agent、使用了什么资源、做了什么、结果如何。
- AGENT.md / resource context 面向模型理解;permission manifest 面向系统强制执行;审计以结构化记录为准,不以 Markdown 为准。
- 审计记录不得含明文密钥:只记
secret_ref(azkv://)、审批approval_id、范围与 TTL。
2. 追踪域(Lineage)
2.1 部署 / 运行链路
manager_deployment_id ↔ deployment_id ↔ swarm_id(workflow_id) ↔ correlation_id(trace_id),四者贯穿一次交付,事件按 swarm_id 持久化。
2.2 任务链路(已实现)
每个任务携带:task_id、parent_task_id、root_task_id、child_task_ids、depends_on、source(runtime_bridge / planner / dynamic_handoff)、agent_role、assigned_agent_id、retry_count、时间戳。可由此重建任务 DAG 与重做/移交谱系。
2.3 执行链路(已实现,基于事件流)
按 swarm_id 顺序持久化的事件即执行轨迹:task.created/claimed/running/heartbeat/blocked/retried/failed/completed、handoff.requested/completed、artifact.created、timeline.updated、deployment.status_changed,每条含 event_id、occurred_at、agent_instance_id、correlation_id。
2.4 审批链路(已实现)
run.approvals[approval_id]:operation、risk_level、decision(approved/rejected)、credential_ref、lease_id、reason、决策时间。客户端审批,运行时仅记录与校验。
2.5 资源 / 凭证访问链路
secret_refs(azkv://,仅引用)、resource grant 的 allowed_actions/constraints/status/created_by/revoked_by/created_at/revoked_at(字段定义在 Manager 侧 heicode.md §五)。本仓只透传与引用,不落明文。
2.6 回调投递链路(已实现)
run.metadata.callback_attempts:每次回调的 event_id、event_type、url、status、attempted_at,用于回调可靠性审计(/diagnostics 暴露)。
3. 已实现(本仓)
| 能力 | 实现 |
|---|---|
| 事件流持久化 + 分页查询 | _store_event(按 swarm_id 追加)、list_events(cursor/limit);/logs、/events 暴露 |
| 任务谱系字段 | parent/root/child_task_ids、depends_on、source、retry_count |
| 审批记录 | run.approvals、record_approval_decision |
| 回调投递审计 | callback_attempts、/diagnostics |
| 用量归因 | usage + X-Agent-* 归因头(见 usage-billing) |
| 脱敏 | _redact_sensitive(保留 secret_ref,脱敏明文密钥) |
| 可回放审计装配 + 回放 | orchestrator/audit.py:build_audit_trace(events, task_facts, approvals, lineage) 纯函数把事件流 + 任务(含 usage.model_id/工具计数)+ 审批规整为有序审计记录(§5 冻结形);replay(records) 产人读步骤行。读接口 GET …/{id}/audit(build_audit_trace_for_run)。纯净、确定性、无内容/无密钥。 |
3.1 回放装配(issue #17)
audit.build_audit_trace 对每条事件产一条审计记录,按存储顺序排列,audit_id 由序位确定(aud_000001…,非随机,同一 run 字节级可复现)。逐步可答:
- 谁:
actor.agent_instance_id(事件携带)/actor.agent_role(任务谱系回填)。 - 何模型:
model.model_id(取自任务usage.model_id,缺则null,不伪造)。 - 何工具:
tool.count(取自任务tool_calls/tool_count;无工具层时为null)。 - 何审批:
approval.{approval_id, decision}(取自 payload +run.approvals,绝不含secret_ref)。 - 结果:
result由 event_type 归类(completed→success / failed→failed / blocked|approval.rejected→blocked / stopped→stopped / 其余→info)。 - lineage:四 ID 全量。每条
redacted: true。
4. 覆盖与边界
| 追踪项 | 状态 |
|---|---|
| Task lineage / execution trace | ✅ 已实现(事件流 + 任务字段) |
| Approval trace | ✅ 已实现(审计记录 approval.{id,decision}) |
Model trace(model_id + token 计数) |
✅ 已实现(审计记录 model.model_id;无请求/响应体——见下「有意排除」) |
| Tool trace(计数) | ✅ 计数已实现(tool.count);工具名谱系 N/A(无 SK/MCP 工具层) |
| 统一审计记录 schema + 回放 | ✅ 已冻结(§5)+ 可回放(audit.build_audit_trace/replay,GET …/{id}/audit) |
| 有意排除(非缺口) | Prompt/代码/对话原文——刻意不留痕(无内容原则);model 请求/响应体——同上;SK/MCP 工具名谱系——无工具层。这些属取舍/后续层,按规则 #9 不伪造、不在本次冻结。 |
| 留存期 / 合规归档策略 | 🟡 由 Audit & Compliance Team 定(留存期、外部归档),非本仓编排器。 |
5. 审计记录 Schema(FROZEN v1 —— orchestrator/audit.py 产出形)
{
"audit_id": "aud_000001", // 序位确定(非随机),同一 run 可复现
"occurred_at": "2026-06-08T...Z",
"action": "task.completed", // = event_type
"actor": { "agent_role": "impl", "agent_instance_id": "agent-7" }, // 谁
"task_id": "swarm-...-t | null",
"model": { "model_id": "gpt-x" } | null, // 何模型(缺则 null,不伪造)
"tool": { "count": 2 } | null, // 何工具(计数;无工具层为 null)
"approval": { "approval_id": "approval_...", "decision": "approved|rejected" } | null, // 何审批(无 secret_ref)
"result": "success | failed | blocked | stopped | info", // 结果
"lineage": { "manager_deployment_id": "...", "deployment_id": "...", "swarm_id": "...", "correlation_id": "..." },
"redacted": true
}
归因主轴为
user.id/channelId(见 usage-billing),不引入 tenant;actor 在审计记录中以agent_role/agent_instance_id表达执行主体,用户主体由 lineage→Manager 侧关联。
6. 待对齐对象
Audit & Compliance Team:留存期与外部归档策略、合规要求;prompt/model 请求体留痕是否在他处(受隐私/安全约束,本仓默认不留);与 telemetry-architecture(benchmark 目录)数据源对齐。