feat(bell): add alert acknowledgement vertical slice
Harness governance / validate (pull_request) Has been cancelled

This commit is contained in:
QiuSW
2026-08-11 17:01:53 +08:00
parent 477afa6ba2
commit 8208118904
29 changed files with 1820 additions and 56 deletions
+12 -1
View File
@@ -1,6 +1,6 @@
# YoVision 控制面、审计与内部事件传输契约 v1
> 冻结日期:2026-08-11。Control API、审计 relay 与 Brain 事件 ingress 契约版本:`1.0.0`。Sense 是设备期望态的提供方;Bell 是 Tenant、Site、Area、RBAC、配额、事件与全局审计的所有者。T-016 已实现 Sense Outbox 审计 relay,T-019 已实现 Brain 事件 Outbox ingress;Bell 公共管理服务与 JWT/OIDC 仍未实现。
> 冻结日期:2026-08-11。Control API、审计 relay、Brain 事件 ingress 与 Bell 回环 Alert 控制台契约版本:`1.0.0`。Sense 是设备期望态的提供方;Bell 是 Tenant、Site、Area、RBAC、配额、事件、Alert 与全局审计的所有者。T-016 已实现 Sense Outbox 审计 relay,T-019 已实现 Brain 事件 Outbox ingress,T-020 已实现 Bell 规则→Alert→ack/close 工程纵切;Bell 公共管理服务与 JWT/OIDC 仍未实现。
## 契约文件
@@ -13,6 +13,7 @@
| [`sense-device-audit-v2.schema.json`](sense-device-audit-v2.schema.json) | Sense | 本地 Outbox;Bell relay | v1 后继,增加脱敏配置修改受理事实;v1 文件保持不变 |
| [`sense-audit-relay-v1.openapi.json`](sense-audit-relay-v1.openapi.json) | Bell | Sense | 内部批量端点、HMAC、逐项确认、nonce 防重与重试边界 |
| [`brain-event-ingress-v1.openapi.json`](brain-event-ingress-v1.openapi.json) | Bell | Brain | 单业务事件入站、producer/key 绑定、Bell ID 与跨重启幂等语义 |
| [`bell-alert-console-v1.openapi.json`](bell-alert-console-v1.openapi.json) | Bell | 回环工程值班台 | Alert 分页/详情、首次 ack、确认后关闭与永久幂等收据 |
OpenAPI 的 `/api/v1` 路径是公共控制面边界;`/healthz`、`/readyz` 仍是非业务运维探针。v1 不提供设备删除:停用设备使用期望态接口,保留设备、操作和审计历史。Site、Area、配额、RBAC 和审计聚合不由 Sense 提供 CRUD。
@@ -87,6 +88,14 @@ Bell 的永久 `event_ingress_receipts` 以 `(producer_id, source_event_id)` 唯
数字 `tenant_id/site_id/device_id` 通过 Bell 所有的 `event_ingress_bindings` 映射到当前 Bell Site/Area 和 Sense Device 逻辑 ID。运行时只读取 Sense 设备的 ID、Area 与 modality 列,不获得 endpoint、credential、profile token 或 path;绑定缺失/禁用、设备或 Area 不一致、删除、非视频或 `capture_policy != video_allowed` 均失败关闭。首版绑定只由受控 migration/admin SQL 配置,没有公共 CRUD。
## Bell 回环规则与 Alert 控制台
T-020 的 [`bell-alert-console-v1.openapi.json`](bell-alert-console-v1.openapi.json) 只冻结工程 API,不占用未来 Bell 公共 `/api/v1`。整个 `bell-api` 必须显式监听回环,规则、token、tenant/Site 和 actor 上下文均从仓库外启动配置读取;请求不得自报这些上下文。列表按 `created_at DESC,id DESC` 稳定分页,默认 16、最大 100。
规则文件 v1 只支持精确 `event_kind`、最小严重度、可选 Site、启用状态和生效时间。相同 `(tenant_id,rule_key)` 的配置按 canonical SHA-256 幂等发布;变化生成不可变新版本。Event 无论有无规则/是否命中都会留下 durable sweep;每个被考虑版本写 matched/no_match evaluation,命中时 Bell 创建独立 `alt_` ULID 和 Event 多对多关联。Event、规则版本、evaluation、Alert 身份、关联和 transition 均只追加。
Alert 状态机为 `open → acknowledged → closed`。ack 由数据库事务与 advisory lock 串行化,只有首个竞争者成功;后到者返回 `409 already_acknowledged` 和实际首位 actor/time,不覆盖历史。close 只允许从 acknowledged 进入。所有命令要求 8~128 字符 `Idempotency-Key`;同租户同 key/同命令永久重放原 status/body,同 key/不同命令返回 `409 idempotency_conflict`。当前详情固定返回 `evidence_status=not_enabled`、`delivery_status=not_enabled`,不得伪造切片、升级或送达事实。
## 兼容与废弃
- v1 可增加不改变已有语义的可选响应字段和新错误细节;客户端必须忽略未知响应字段。
@@ -103,10 +112,12 @@ python -m json.tool docs/contracts/sense-control-v1.openapi.json | Out-Null
python -m json.tool docs/contracts/sense-device-audit-v2.schema.json | Out-Null
python -m json.tool docs/contracts/sense-audit-relay-v1.openapi.json | Out-Null
python -m json.tool docs/contracts/brain-event-ingress-v1.openapi.json | Out-Null
python -m json.tool docs/contracts/bell-alert-console-v1.openapi.json | Out-Null
python -m unittest discover -s tests -p "test_sense_control_contract.py"
python -m unittest discover -s tests -p "test_sense_control_implementation.py"
python -m unittest discover -s tests -p "test_sense_audit_relay_contract.py"
python -m unittest discover -s tests -p "test_brain_event_ingress_contract.py"
python -m unittest discover -s tests -p "test_bell_alert_contract.py"
```
测试同时校验 OpenAPI 结构、生成 server glue、HTTP handler 与 PostgreSQL migration/事务;它不替代 Bell 消费方联合验收或客户现场容量验证。