feat(store): add PostgreSQL foundation [T-009]
Harness governance / validate (push) Has been cancelled
Harness governance / validate (pull_request) Has been cancelled

This commit is contained in:
QiuSW
2026-08-07 17:52:50 +08:00
parent 04231d006a
commit 2ff7ff5618
23 changed files with 1593 additions and 24 deletions
+5 -5
View File
@@ -21,7 +21,7 @@
| 调用方 → 提供方 | 用途 | 当前约束 | 状态 |
| --- | --- | --- | --- |
| Sense → Bell | 读取站点视频配额 | 同一 PostgreSQL 实例内只读 `bell.site_quota_v1`;默认 16、最大 128;失败时拒绝新增/启用但不影响已有流 | T-008 已冻结 |
| Sense → Bell | 读取站点视频配额 | 同一 PostgreSQL 实例内只读 `bell.site_quota_v1`;默认 16、最大 128;失败时拒绝新增/启用但不影响已有流 | T-008 冻结,T-009 已实现数据路径 |
| Bell → Sense | 请求事件证据/pre-roll 切片 | 幂等、按租户授权、异步结果、不得暴露原始凭据 | 待 M3 设计 |
| Bell → Brain | outcome/误报反馈 | 原事件不可变;反馈可重试、去重、审计 | 待 M3 设计 |
| Sense → Brain | 流绑定与设备型触发 | 分片可路由,触发入口与流控制解耦 | 待 M2/M3 设计 |
@@ -43,7 +43,7 @@
- `endpoint_ref`、`credential_ref`、`profile_token` 只写不读;设备 ID 由服务端生成。普通响应和错误不得包含凭据、完整流 URI、token 或 MediaMTX 内部配置。
- v1 不提供删除设备;停用设备保留历史。写入受理只表示期望态已持久化,不能表示实际态已收敛。
T-008 只冻结契约和仓库门禁,尚未实现 Sense HTTP handler、认证中间件、Bell 表或 PostgreSQL migration。
T-008 冻结契约;T-009 已实现 PostgreSQL `bell.sites`/配额视图、最小权限和 Sense repository,但尚未实现 Sense HTTP handler、认证中间件或 Bell 管理服务。
## 4. 待冻结的 Bell 公共 API
@@ -68,7 +68,7 @@ Sense 使用 MediaMTX 官方 OpenAPI 生成客户端并加薄封装。业务代
| --- | --- | --- |
| ONVIF adapter | `Probe(target)`、`SetSystemDateAndTime(target, time)` | 设备是外部来源;`target` 只含 endpoint ref 与不透明 credential ref。错误稳定映射为认证失败、超时、不可用、响应无效,不记录凭据或完整流地址 |
| MediaMTX paths | `CreatePath`、`GetPath`、`EnsurePath`、`DeletePath`、`PathReady` | SQLite 设备台账持有期望态,MediaMTX 只持有运行配置;`EnsurePath` 相同 source 不写、不同 source patch、缺失时 add;当前调和器绝不枚举或删除孤儿 |
| Device repository | 站点、设备、期望态、实际态、调和进度 | SQLite 是 M1 期望态真相源;调和失败次数与下次时间持久化,进程重启不清空退避;配额读取/写入失败时拒绝新增或启用,不关闭已有流 |
| Device repository | 设备、期望态、实际态、调和进度 | SQLite 是 M1 默认开发路径;PostgreSQL 是 M2 生产路径并只读 `bell.site_quota_v1`。调和失败次数与下次时间持久化,进程重启不清空退避;配额读取失败时拒绝新增或启用,不关闭已有流 |
MediaMTX 薄封装调用同版官方 OpenAPI 的 `/v3/config/paths/get|add|patch|delete/{name}` 与 `/v3/paths/get/{name}`。生成源、版本和 SHA-256 见 `docs/03-tech-stack.md`;业务包不得直接 import 生成包。
@@ -76,12 +76,12 @@ MediaMTX 薄封装调用同版官方 OpenAPI 的 `/v3/config/paths/get|add|patch
- 设备类型由 `modality` 表达物理类别,由多值 `capabilities` 表达视频采集、音频、空间规则或遥测能力,避免把“摄像头”固化为唯一设备模型。
- 视频配额只统计 `desired_state=enabled` 且具有 `video_capture` capability 的设备;站点默认 16、可配置 1~128。禁用设备和非视频传感器不占视频路数。
- SQLite 表使用 `sense_` 前缀对应未来 PostgreSQL `sense` schema:`sense_sites`、`sense_devices`、`sense_device_capabilities`、`sense_reconcile_state`。标识、唯一性、状态与时间字段语义保持一致;本地表名前缀不是跨系统公共契约。
- SQLite 表使用 `sense_` 前缀;T-009 PostgreSQL 使用 `sense.devices`、`sense.device_capabilities`、`sense.reconcile_state` 和只记录已观察版本的 `sense.site_quota_projection_state`。PostgreSQL 不建立可写 Site 真相副本,站点与配额只来自 Bell 视图;SQLite 的 `sense_sites` 仅是 M1 本地兼容表,不是跨系统公共契约。
- 摄像头密码不进入设备普通字段。`credential_ref` 只保存外部密钥引用;ONVIF 返回的 stream URI 只在内存中传给 MediaMTX,不写入设备台账或日志。
### 5.3 Sense 进程 HTTP 面
T-003 只实现了运维探针:`GET /healthz` 表示进程存活,`GET /readyz` 表示配置、SQLite 打开及 migration 已完成。两者返回 JSON,均不等价于摄像头、MediaMTX path 或 M1 里程碑健康。T-008 已冻结站点作用域的 `/api/v1/sites/{site_id}/devices` 等设备管理契约,但尚未实现对应 handler;当前可运行进程仍只暴露探针,后续实现不得发布 `/api/v1/devices` 等无站点边界的临时接口。
T-003 只实现了运维探针:`GET /healthz` 表示进程存活,`GET /readyz` 表示所选数据库已打开且 schema/权限前置检查完成。两者返回 JSON,均不等价于摄像头、MediaMTX path 或里程碑健康。T-008 已冻结站点作用域的 `/api/v1/sites/{site_id}/devices` 等设备管理契约,但尚未实现对应 handler;当前可运行进程仍只暴露探针,后续实现不得发布 `/api/v1/devices` 等无站点边界的临时接口。
## 6. 变更流程