8.4 KiB
8.4 KiB
id, title, phase, deps, status, created, issue, context_ref, claim_branch, work_branch, write_paths
| id | title | phase | deps | status | created | issue | context_ref | claim_branch | work_branch | write_paths | |||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| T-016 | 冻结并实现 Sense Outbox 到 Bell 全局审计幂等 relay | 3 |
|
DONE | 2026-08-10 | 55 | aca22f4667 |
claims/T-016 | agent/codex/T-016 |
|
问题 / 背景
T-010 已保证 Sense 设备创建、配置和期望态变更与脱敏 sense.device_operation_outbox 同事务,但 Outbox 仍不会离开 Sense;Bell 因而没有完整的跨系统全局审计事实。直接让 Sense 写 bell schema 会破坏三系统所有权,简单“POST 后标记成功”又无法处理崩溃重试、重复投递、多实例竞争、消息篡改或重放攻击。
T-015 已提供 Bell 的独立运行角色和不可变事实模式。本任务只冻结并实现设备操作审计 relay,不顺带定义 Brain 事件 transport、业务规则、Alert 或公共管理 API。
关联需求与交互(如适用)
- 用户故事:为 US-009、US-010 的全局审计追溯提供后端事实基础。
- 交互清单:IX-020 的审计归属后端基础;本任务不实现
/auditUI、筛选或深链页面。 - 相关页面 / 路由:公共 UI 不适用;新增仅内部使用的
/internal/v1/audit-events:batch。
方案
- 冻结
sense-audit-relay-v1.openapi.json:Sense 通过 HTTP POST 批量发送 1~100 个 v1/v2 设备审计事实,Bell 返回与输入逐项对应的accepted | duplicate | rejected;完整批次响应可按签名 nonce 幂等重放。 - 请求使用 key ID、Unix 秒时间戳、随机 nonce 与 HMAC-SHA256。canonical string 固定为
METHOD + path + timestamp + nonce + SHA256(body)的换行拼接;允许时钟偏差 5 分钟,nonce 收据保留 10 分钟。相同 key/nonce/请求摘要返回原响应,不同摘要返回409 replay_conflict。密钥只从仓库外绝对路径文件读取,至少 32 个随机字节,不进数据库、日志或 Issue。 - 非回环 transport 必须使用 HTTPS;回环 HTTP 只用于同机私有部署和测试,不提供跳过远端 TLS 的 flag。单次请求体最大 1 MiB、超时 10 秒,Bell 不回显原始 body、签名或敏感字段。
- PostgreSQL v6 为 Sense Outbox 增加数据库时钟 lease、fencing token、last error 和 dead-letter 状态。最多 100 行用
FOR UPDATE SKIP LOCKED领取;过期 worker 不能确认。accepted/duplicate标记 delivered,逐项永久拒绝进入 dead letter,网络/5xx/整批认证失败按指数退避重试且不删除事实。 - Bell 新增不可变
bell.audit_events和可过期bell.audit_relay_receipts。全局审计用(source_system,event_id)唯一;相同摘要为 duplicate,不同摘要逐项id_conflict。审计事实没有 UPDATE/DELETE/TRUNCATE 权限并复用不可变 trigger;收据允许 Bell runtime 在限定表内维护过期记录。 - 建立最小
cmd/bell-api,默认仅回环监听,暴露 health/ready 与内部 relay endpoint;数据库、监听地址、TLS 和 key 文件均来自私有环境。Sense relay 默认关闭,仅在 PostgreSQL v6、合法 Bell URL 和外部 key 文件齐备时启动后台 worker。 - 单元测试覆盖签名向量、时间窗/nonce、body 限制、逐项确认、重复/冲突、配置失败关闭、退避和崩溃重领;隔离 PostgreSQL 17.10 测试覆盖 migration 重放、两端 repository、fencing、权限和安全清理。
不可变约束
- 阈值 / 数值边界:每批 1~100 项;body ≤1 MiB;HTTP deadline 10 秒;lease 30 秒;签名时钟偏差 ≤300 秒;nonce 收据 TTL 600 秒;退避从 1 秒指数增长并封顶 300 秒。16 不是审计批量或队列上限。
- 判定式 / 状态转换:只有
accepted/duplicate可设置delivered_at;rejected必须带稳定错误码并 dead-letter;批次级网络/5xx/认证/响应缺项不得误标成功。所有完成/失败写入必须匹配 worker + fencing token + 未过期数据库 lease。 - 安全边界:非回环只允许 HTTPS;HMAC 使用至少 32 字节外部 secret 和 constant-time compare;时间戳、nonce、key ID、签名格式失败统一安全拒绝。Sense 不获得 Bell schema 权限,Bell 不读取 Sense Outbox;日志、响应、测试和指标不包含 secret、Authorization、原始 DSN、完整 payload 或租户/设备标签。
- 既有契约:本地事实继续符合
sense-device-audit-v1/v2,不原地修改两份 schema;relay v1 只增加传输 envelope/确认语义。Bell 全局审计是追加事实,不能改写 Sense 原事件或设备状态。
验收要点
- 任务相关验证:
go -C Sense test ./internal/auditrelay ./internal/store ./internal/config ./cmd/sense-api、go -C Bell test ./internal/audit ./internal/store ./cmd/bell-api;python -m unittest discover -s tests -p "test_sense_audit_relay_contract.py" -v;OpenAPI JSON 可解析且签名/状态/阈值与实现一致。 - 完整门禁:因命中 Sense/Bell Go、PostgreSQL schema/权限和内部 HTTP 安全边界,运行
./scripts/test_postgres.ps1 -PgRoot D:\pgsql17、./init.ps1、三条 Python 治理命令及git diff --check。临时 PostgreSQL 必须重放001~015两次,现有 5432 listener 不变。 - 人工 / 设备验收:不适用;回环
httptest和隔离 PostgreSQL 足以验收协议与持久化。跨主机证书、客户网络、防火墙和密钥轮换演练留给部署任务,不能据此宣称生产网络已验收。 - 构建产物:
go -C Sense build ./...与go -C Bell build ./...;Bell 最小 receiver 可由go -C Bell build ./cmd/bell-api构建,未配置 DSN/key 时必须拒绝启动。
边界(不改什么)
- 不实现 Brain→Bell 事件 transport、规则引擎、Alert/ack/升级、Bell 公共审计查询 API、Web/H5、JWT/OIDC、消息总线或客户网络部署。
- 不删除本地 delivered/dead-letter Outbox 行,不擅自冻结法务审计留存期;本版本只自动清理 10 分钟后 relay nonce 收据,全局审计事实不自动删除。
- 不提交 key 文件、DSN、客户标识、真实 payload 或私有实例配置;不为测试修改现有 PostgreSQL data 目录或 5432 服务。
协作约束
- 责任 Agent:codex
- 唯一写入者:codex
- 委派:不启用。
- Gitea:Issue、
context_ref、claim 与工作分支在双向映射及 dispatcher 分配后回填。
任何新增写路径先检查与其他活跃任务是否重叠;同一时刻只有一个 Agent 修改本任务的 write_paths。
执行记录
- 2026-08-10:在 T-015 合并并关闭后拆出本任务;实现尚未开始。
- 2026-08-11:冻结
sense-audit-relay-v1.openapi.json,实现 Sense 外部 key/HMAC client、30 秒数据库 lease/fencing worker、逐项结果/dead letter/1~300 秒退避,以及 PostgreSQL v6 Outbox relay repository;默认关闭且远端 URL 强制 HTTPS。 - 2026-08-11:实现 Bell 最小
cmd/bell-api、300 秒时间窗与 constant-time HMAC 校验、600 秒 nonce 幂等收据、逐项 v1/v2 校验,以及 PostgreSQL v4 不可变bell.audit_events;Sense/Bell 登录权限保持单向隔离,只有 Bell 可清理过期收据。 - 2026-08-11:
./init.ps1、三条 Python 治理命令、Sense/Belltest/vet/build与git diff --check全部通过;Python 共 68 项测试通过。 - 2026-08-11:
./scripts/test_postgres.ps1 -PgRoot D:\pgsql17通过;PostgreSQL 17.10 临时集群将001~015重放两次,Sense fencing、Bell receipt/重复/冲突/不可变性和双方权限断言通过,随机端口与临时目录已清理,现有 5432 listener 未改变。