feat: implement T-019 reliable event ingress
Harness governance / validate (pull_request) Has been cancelled

This commit is contained in:
QiuSW
2026-08-11 15:41:07 +08:00
parent b7fe44eeb0
commit bd964e8831
33 changed files with 2762 additions and 57 deletions
+23 -4
View File
@@ -3,16 +3,18 @@ id: T-019
title: 建立 Brain 到 Bell 的可靠事件入站链路
phase: 3
deps: [T-015, T-017]
status: TODO
status: DONE
created: 2026-08-11
issue: 67
context_ref: null
claim_branch: null
work_branch: null
context_ref: b7fe44eeb0caf8d41abef365ec2100c74373321f
claim_branch: claims/T-019
work_branch: agent/codex/T-019
write_paths:
- docs/tasks/T-019.md
- docs/contracts/
- docs/raw/contracts/README.md
- Brain/
- docs/design/brain/index.html
- Bell/
- deploy/postgres/
- scripts/test_postgres.ps1
@@ -41,6 +43,7 @@ T-017 已能产生匿名区域事件候选,T-015 已能在 Bell 内部校验
## 方案
1. 在 `docs/contracts/brain-event-ingress-v1.openapi.json` 冻结单事件 envelope、响应、稳定错误码和 HMAC 规则。请求包含 `schema_version=1`、`producer_id` 与不含 Bell `id` 的完整 event v0.1 candidate;Brain 提供 `source_event_id`,Bell 生成并返回平台 `evt_` ULID。正文上限 1 MiB,deadline 10 秒。
同步把 T-017 已产生的 `zone_entry` 登记到 event v0.1 kind 注册表;不修改冻结 JSON Schema 或既有 kind 语义。
2. 复用 T-016 已验证的 HMAC-SHA256 canonical 形式:method、path、Unix 秒、随机 nonce、body SHA-256 以换行连接;使用独立的仓库外 key 文件,并把每个 key 绑定到一个 `producer_id`。允许 300 秒时钟偏差,nonce 防重收据保留 600 秒。回环可用 HTTP,非回环必须 HTTPS;事件 key 与审计 relay key 不混用。
3. 新增 Bell 所有的 `event_ingress_bindings`,把 `(producer_id, tenant_id, site_id, device_id)` 数字事件身份绑定到现有 Bell tenant/site/device/area 逻辑身份和 `video` 模态。入站必须 fail closed:绑定缺失、禁用、站点/Area 已删除、设备或 Area 归属不一致、非视频或 `capture_policy != video_allowed` 均拒绝。首版只提供受控 SQL 配置方式,不新增公共绑定管理 API。
4. 新增永久 append-only `event_ingress_receipts`,以 `(producer_id, source_event_id)` 唯一,保存 canonical candidate SHA-256 与 Bell event ID;另用短期 `event_ingress_nonces` 防请求重放。Bell 用单事务和事务级 advisory lock 完成 nonce、来源收据、事件创建与响应:同来源且同 payload 返回原 Bell ID 和 `duplicate`,同来源不同 payload 返回 `source_event_conflict`,不得产生第二条事件。
@@ -84,3 +87,19 @@ T-017 已能产生匿名区域事件候选,T-015 已能在 Bell 内部校验
- T-019 独立冻结 Brain→Bell 业务事件身份、持久重试、认证和幂等 ingress;不复用 T-017 内存事件环,也不扩张到规则、Alert 或证据链。
- 当前会话未暴露 codebase-memory MCP 图工具,代码发现按仓库规则降级为定向读取与 `rg`;任务定义前主分支 `./init.ps1` 基线通过:72 项根测试、19 项 Brain 测试,以及 Sense/Bell generate/test/vet/build 全绿。
- 任务定义已合入默认分支并创建唯一 Gitea Issue #67;本映射提交合入后才添加 `status/todo` 并允许 dispatcher 分配。
### 2026-08-11 领取与基线
- dispatcher `ila` 检查依赖和开放工单后,从默认分支 `b7fe44eeb0caf8d41abef365ec2100c74373321f` 创建并读回 `claims/T-019` 与 `agent/codex/T-019`;Issue #67 已分配给 `ila`,标签为 `status/doing`,结构化 CLAIM 评论与本文件 `write_paths` 一致。
- T-007 保持 `status/waiting`,不构成活跃写路径预留;本任务不启用委派。
### 2026-08-11 实现与自动化验收
- 冻结并实现 `brain-event-ingress-v1` 单事件 envelope。Bell event key 独立于审计 key,并把 `key_id` 绑定到唯一 `producer_id`;两端共享 method/path/timestamp/nonce/body-hash 五行 HMAC-SHA256,允许 300 秒时钟偏差,正文上限 1 MiB,非回环必须 HTTPS。Brain client 禁用环境代理和重定向,避免内部事件被旁路转发。
- PostgreSQL 新增可重放 `016`~`017`:Bell 所有的数字→逻辑身份绑定引用现有 Site/Area/Sense Device;运行时只能读取设备 ID、Area 与 modality 列,不能读取 endpoint、credential、profile token 或 path。永久来源收据和事件不可更新/删除,只有 10 分钟 nonce 表允许清理。
- Bell 在相同事务中提交最终 event、`(producer_id,source_event_id,candidate_hash)` 永久收据和成功 nonce 响应;同来源/同 canonical candidate 返回原 Bell ID,不同 candidate 返回稳定冲突。隔离 PostgreSQL 测试以 8 个并发重投确认只生成 1 条 event/1 条来源收据,并验证 Area 改为 `non_imaging_only` 后新视频事件失败关闭。
- Brain 新增完整 v0.1-minus-id mapper、WAL/`synchronous=FULL` SQLite Outbox、HMAC client 和 worker。Outbox 首次打开绑定 producer/tenant/site/device,禁止换身份复用旧队列;候选持久化成功后才进入页面内存环。fixture 显式映射为 `outcome=test/outcome_source=auto`,URI/凭据/`source_ref` 不出 Brain。队列执行 1~300 秒退避、100 次/10,000 条边界,`accepted/duplicate` 才 delivered,稳定 4xx 进入 dead letter;租约崩溃恢复与 Bell 成功后本地未 ack 的重投均有测试。
- Brain 工程原型在既有“最近候选事实”卡片内展示脱敏 Outbox 状态与待投递/投递中/已送达/死信计数;以文字和状态点共同区分未启用、正常、重试和死信,且明确单条候选的“仅内存观察”或“Outbox 已持久化”。状态无变化时不重复触发 `aria-live`,页面不暴露 Bell 地址、key 文件或 SQLite 路径。
- `zone_entry` 已登记到 event v0.1 kind 注册表;冻结 JSON Schema 未修改。Bell/Brain/部署 README、API、架构、技术栈和当前状态均同步,未扩张到证据、规则、Alert、公共认证或生产模型。
- 最终门禁通过:`./init.ps1`(77 项根测试、30 项 Brain 测试及 Sense/Bell generate/test/vet/build);独立 `go -C Bell test/vet/build ./...`、Brain compileall、4 项跨语言 ingress 契约测试和三项治理校验;`./scripts/test_postgres.ps1` 在 PostgreSQL 17.10 临时集群将 `001`~`017` 重放两次并通过真实 repository、权限、并发幂等、隐私和不可变性验证,随机端口/临时目录已清理且现有 5432 listener 未改变;`git diff --check` 通过。
- 本任务不需要真实摄像头或目标 GPU;synthetic fixture mapper、SQLite 崩溃恢复、真实本地 HTTP HMAC client、Bell handler 和真实 PostgreSQL consumer 的联合自动化证据满足本地验收。结果不构成算法效果、真实多路或生产 SLA。