Files
yovision/docs/tasks/T-015.md
T
QiuSW 8b11b39093
Harness governance / validate (push) Has been cancelled
Harness governance / validate (pull_request) Has been cancelled
docs(tasks): map T-015 to issue 51
2026-08-10 23:37:08 +08:00

6.5 KiB
Raw Blame History

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-015 建立 Bell 事件 v0.1 校验与不可变 PostgreSQL 存储 3
T-014
TODO 2026-08-10 51 null null null
docs/tasks/T-015.md
Bell/
deploy/postgres/012_bell_events.sql
deploy/postgres/013_privileges_bell_events.sql
deploy/postgres/tests/assertions.sql
deploy/postgres/README.md
scripts/test_postgres.ps1
tests/test_bell_event_contract.py
docs/raw/contracts/README.md
docs/00-ai-start-here.md
docs/03-tech-stack.md
docs/04-architecture.md
docs/06-tasks.md
docs/api.md
docs/current-state.md
AGENTS.md
init.ps1
init.sh

问题 / 背景

M3 要求 Bell 首次真实消费冻结的事件契约 v0.1,生成平台 ULID,并把事件事实保存为不可变记录。当前 Bell 只有目录占位,PostgreSQL 也只有 Site/Area 投影源表;如果先做规则或 Alert,会把未经校验、可被覆盖的事件数据变成后续状态机的错误基础。

冻结契约中还存在一处文档自相矛盾:docs/raw/contracts/README.md 的修订记录、雷达示例和 JSON Schema 均允许非成像事件的 snapshot_uris=[],但 §5 的旧句仍把空数组列为 schema 可拒绝项。本任务先把该句校正为现有冻结事实,不修改 schema 或字段语义。

关联需求与交互(如适用)

  • 用户故事:无直接 UI;为 US-003、US-004、US-006 的后续事件/处置流程提供数据基础。
  • 交互清单:不适用;本任务不实现 Bell Web/H5 页面或公共查询 API。
  • 相关页面 / 路由:不适用。

方案

  1. 在 Bell/ 建立独立 Go module,复用项目冻结的 Go 1.26.5、PostgreSQL 17.10 和 pgx/v5 v5.10.0;冻结 Draft 2020-12 校验器与 ULID 库版本、许可证和退出路线,不引入前端或消息总线。
  2. 把冻结 schema 逐字节复制到 Bell/contracts/event-v0.1.schema.json 并以测试阻止漂移。Bell 内部 ingest factory 接收不含平台 id 的候选事实,拒绝上游自报 id,由 Bell 生成 evt_ ULID 后再执行 schema 与代码级断言。Brain→Bell 的 HTTP/消息总线 transport 继续待定,本任务不借内部 Go 类型冻结公共网络协议。
  3. 代码级校验覆盖时间顺序/延迟自洽、confidence=null、证据 URI 脱敏、唯一 primary 且与顶层设备一致,以及视频隐私准入。隐私与客户敏感名称通过必需 port 注入;解析/映射不可用时失败关闭,不使用 allow-all 生产默认值。
  4. 新增 Bell event repository。bell.events 保存最终规范化 JSON、摘要和可查询的最小索引字段;平台 ID 冲突时仅允许“同 ID + 同摘要”的幂等重放,不同摘要稳定冲突。后续 outcome 写入独立的 append-only bell.event_outcomes,不得更新原事件事实。
  5. migration 增加独立 NOLOGIN bell_runtime 最小权限角色。migration owner bell_app 持有对象;运行时只获得必需的 SELECT/INSERT,明确没有事件表的 UPDATE/DELETE/TRUNCATE,并以数据库 trigger 拒绝事实改写。生产/共享实例仍由管理员离线 migration,不由 Bell 高权限自迁移。
  6. 扩展隔离 PostgreSQL 17.10 harness,使用 bell_runtime 登录运行真实 repository/权限/重放/不可变性集成测试;同步根启动入口、技术栈、架构、API 状态和当前仓库现实。

不可变约束

  • 阈值 / 数值边界:请求体/单事件规范化 JSON 上限 1 MiB;延迟自洽误差严格小于 100 ms;事件列表/公共 API 不在本任务内;任何默认 16 路值不成为事件数量上限。
  • 判定式 / 状态转换:Bell 是 evt_ ULID 唯一生成者;候选事实不得携带 id;最终事实必须同时通过 Draft 2020-12 schema 和 README 六项代码级断言。相同平台 ID/相同摘要为幂等成功,相同 ID/不同摘要为冲突;原事件永不 UPDATE/DELETE,后续 outcome 只能追加。
  • 安全边界:未知顶层字段拒绝;视频隐私映射或敏感名称策略不可用时失败关闭;普通错误和测试证据不回显事件全文、证据 URI、客户名、凭据或内部堆栈;bell_runtime 不拥有 migration 对象且没有事件事实改写权限。
  • 既有契约:docs/raw/contracts/event-v0.1.schema.json 字段、枚举与 v0.1 语义不变;只修正文档中与 schema/示例冲突的旧句。Brain transport、规则、Alert、证据回捞、RBAC/JWT/OIDC 和事件公共 API 均另立任务。

验收要点

  • 任务相关验证:go -C Bell test ./...、go -C Bell vet ./...、go -C Bell build ./...;python -m unittest discover -s tests -p "test_bell_event_contract.py" -v;验证三个冻结示例、负向 schema/六断言、ULID 所有权、幂等冲突和 append-only outcome。
  • 完整门禁:因命中 Bell 脚手架、PostgreSQL migration、权限、根启动入口和冻结契约消费者,运行 ./scripts/test_postgres.ps1 -PgRoot D:\pgsql17、./init.ps1、三条 Python 治理命令和 git diff --check。隔离测试必须证明现有 5432 listener 前后不变并自动清理临时集群。
  • 人工 / 设备验收:不适用;本任务不依赖摄像头、客户网络、GPU、MinIO 或产品 UI。生产上线仍受法务/客户留存政策和 M3 现场 dry-run 门禁约束。
  • 构建产物:go -C Bell build ./... 可构建全部 Bell 包;不生成可部署 Bell API 二进制,因为 Brain transport、认证和公共 API 尚未冻结。

边界(不改什么)

  • 不实现 Brain mapper/投递、HTTP 或消息总线事件入口、规则引擎、Alert、ack、升级链、对象存储、证据切片、反馈回流、Bell Web/H5 或 JWT/OIDC。
  • 不修改冻结事件 schema、示例字段或 Sense 业务代码;不把整数事件契约 ID 与现有文本逻辑 ID 的待定映射悄悄固化为跨系统规则。
  • 不把 bell_app owner 凭据交给运行进程,不在仓库保存 DSN、密钥、客户数据、真实事件或真实证据 URI。

协作约束

  • 责任 Agent:codex
  • 唯一写入者:codex
  • 委派:不启用。
  • Gitea:Issue、context_ref、claim 与工作分支在双向映射及 dispatcher 分配后回填。

任何新增写路径先检查与其他活跃任务是否重叠;同一时刻只有一个 Agent 修改本任务的 write_paths。

执行记录

  • 2026-08-10:按 M3 建议拆出本任务;完成仓库/远端状态检查和 ./init.ps1 基线,现有 58 个 Python 测试及 Sense generate/test/vet/build 全部通过。实现尚未开始。