92 lines
5.3 KiB
Markdown
92 lines
5.3 KiB
Markdown
|
|
# 第 8 轮工作计划(轻量合并版):审计事件独立介质镜像(AuditMirror)
|
|||
|
|
|
|||
|
|
更新日期:2026-08-01
|
|||
|
|
|
|||
|
|
## 1. 本轮目标
|
|||
|
|
|
|||
|
|
新增审计事件独立介质镜像:`APS_AUDIT_MIRROR=1` 启用时,`write_audit` 在写世界内 `auditEvents` 的同时,把每条审计事件同步追加到独立 append-only JSONL 镜像(按租户/项目隔离);`/api/gov/audit` 优先读取镜像(事件以镜像为准),业务进程修改 world 无法抹掉独立介质证据;矩阵 116 行「审计 append-only 且可检测篡改」剩余项(业务进程不可改写历史事件/独立介质)前进一步。
|
|||
|
|
|
|||
|
|
## 2. 背景和当前状态
|
|||
|
|
|
|||
|
|
- 当前已完成:第 6 轮 AuditLedger 锚定根(篡改可检测,但审计事件本体仍只存 world 内);`verify_audit_chain` 链式校验;`write_audit` 105 个调用点统一走同一函数。
|
|||
|
|
- 当前缺口:审计事件只存世界内 `auditEvents`,业务进程改 world 可抹掉历史(虽会被锚定根揭穿,但证据本体缺失);无独立介质事件副本。
|
|||
|
|
- 本轮为什么现在做:矩阵 116 行剩余「业务进程也无法修改历史事件;独立介质」;本地可验证(显式启用 + tmp 目录)。
|
|||
|
|
- Workspace preflight:第 7 轮收口(451 passed);服务 8003/5173 正常;共享脏工作区、无提交。
|
|||
|
|
- 方向分析:Q1 推荐选项 B(审计事件独立存储镜像),目标续跑轮授权执行。
|
|||
|
|
|
|||
|
|
## 3. 本轮工作方向
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
write_audit 只写 world auditEvents(105 调用点)
|
|||
|
|
-> audit_mirror.py:AuditMirror append-only JSONL(按租户/项目隔离,原子追加)
|
|||
|
|
-> write_audit 条件镜像(APS_AUDIT_MIRROR=1;失败不影响业务写)
|
|||
|
|
-> /api/gov/audit 优先读镜像(有镜像以镜像为准,无镜像回退 world)
|
|||
|
|
-> 黄金测试:镜像追加、改 world 不影响镜像、隔离、启用/禁用
|
|||
|
|
-> 矩阵 116 行注记;CHANGELOG
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 4. 已确认决策
|
|||
|
|
|
|||
|
|
任务重量:
|
|||
|
|
- 档位:轻型(audit_mirror 新模块 + write_audit 条件分支 + 网关读取优先 + 黄金测试)。
|
|||
|
|
- 规模依据:调用点签名不变(0 处调用点改动);改动集中在 audit.py(1 处定义)+ gateway(1 处读取)+ 新模块;风险 LOW。
|
|||
|
|
- 选择原因:独立介质是矩阵 116 行明确剩余项;镜像方案避免 105 处签名重构。
|
|||
|
|
|
|||
|
|
P0/P1 决策(按 Q1 推荐采纳):
|
|||
|
|
- 决策 1(P0):本轮切片 = 审计事件独立介质镜像(选项 B)。
|
|||
|
|
- 决策 2(P1):不新建分支、不提交、不推送。
|
|||
|
|
- 决策 3(P1):验证深度 = 聚焦 audit_mirror 测试 + 全量黄金回归。
|
|||
|
|
|
|||
|
|
默认假设:
|
|||
|
|
- 假设 1:镜像默认关闭(`APS_AUDIT_MIRROR=1` 显式启用),避免侵入未配置环境与常规测试;生产启用由运维显式开启。
|
|||
|
|
- 假设 2:镜像文件路径 `APS_AUDIT_MIRROR_DIR` 或 `server/data/audit-mirror/<tenant>/<world>.jsonl`;写入失败仅记日志不影响业务(镜像尽力而为,主证据仍在 world+锚定)。
|
|||
|
|
- 假设 3:`/api/gov/audit` 有镜像时事件列表以镜像为准(且镜像计数≥world 时用镜像),否则回退 world(兼容旧数据)。
|
|||
|
|
- 假设 4:镜像行 `{event, mirroredAt}` 保留完整事件 JSON,供链校验与锚定复用。
|
|||
|
|
|
|||
|
|
未决但不阻塞:镜像 WORM 介质/加密、自动清理策略、跨进程锁强化(后续轮)。
|
|||
|
|
|
|||
|
|
## 5. 范围
|
|||
|
|
|
|||
|
|
In scope:
|
|||
|
|
- `server/agent_core/audit_mirror.py`(新):`AuditMirror.append_event(event)` / `read_events()` / `count()`,按租户/项目隔离。
|
|||
|
|
- `server/agent_core/audit.py`:`write_audit` 在返回前,若 `APS_AUDIT_MIRROR=1` 则调用镜像追加(try/except 容错)。
|
|||
|
|
- `server/gateway/app.py`:`gov_audit` 优先读镜像(镜像存在且非空时以镜像为事件源)。
|
|||
|
|
- `tests/golden/test_audit_mirror.py`(新):镜像追加/读取、改 world 不影响镜像、租户隔离、启用/禁用开关、链校验仍可作用于镜像事件。
|
|||
|
|
- 文档:`docs/architecture/harness.md`、`docs/product/plan-completion-matrix.md`(116 行注记)、`docs/CHANGELOG.md`。
|
|||
|
|
|
|||
|
|
Out of scope:
|
|||
|
|
- 105 处调用点签名重构、WORM/加密、清理策略、跨进程锁强化。
|
|||
|
|
- 提交/推送/合并/清理用户改动。
|
|||
|
|
|
|||
|
|
## 6. 成功标准
|
|||
|
|
|
|||
|
|
- 聚焦:`python -m pytest -q tests/golden/test_audit_mirror.py -p no:cacheprovider` 通过(≥4 项)。
|
|||
|
|
- 全量:`python -m pytest tests/golden -q -p no:cacheprovider`(固定 .venv)≥ 451。
|
|||
|
|
- ruff 干净;git diff --check 无空白错误。
|
|||
|
|
|
|||
|
|
## 7. 验证方式
|
|||
|
|
|
|||
|
|
- audit_mirror 单测(追加/读取/隔离/开关/篡改);gov_audit 镜像优先 API 测试;全量回归。
|
|||
|
|
|
|||
|
|
## 8. 关键风险
|
|||
|
|
|
|||
|
|
| 风险 | 影响 | 控制方式 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 镜像写入失败影响业务 | 审计丢失但业务中断 | try/except 容错,仅记日志 |
|
|||
|
|
| 测试污染共享目录 | 断言漂移 | tmp 目录 + 环境变量隔离 |
|
|||
|
|
| 镜像与 world 不一致 | 读取歧义 | gov_audit 有镜像以镜像为准 + 测试锁定 |
|
|||
|
|
|
|||
|
|
## 9. 停止条件
|
|||
|
|
|
|||
|
|
- 全量黄金测试非本轮相关回归无法快速定位时暂停。
|
|||
|
|
- 任何提交/推送/合并/清理操作停下等待授权。
|
|||
|
|
|
|||
|
|
## 10. 本轮完成定义
|
|||
|
|
|
|||
|
|
- 实现、测试、文档完成;聚焦与全量通过;矩阵/CHANGELOG 回写;不提交。
|
|||
|
|
- 收口:报告主要结论、关键洞察、需要特别留意的地方。
|
|||
|
|
|
|||
|
|
## 11. 下一步
|
|||
|
|
|
|||
|
|
轻量合并版:主 agent 实现 + 验证 + 收口报告。
|