7.5 KiB
API 与契约
Brain → Bell 事件契约 v0.1、Sense Control API v1 与 Bell 站点配额只读投影 v1 已冻结;其他 API 仍在设计阶段。不得把本文的“待定”自行具体化为公共契约。
1. 已冻结:Brain → Bell 事件契约
- Schema:
raw/contracts/event-v0.1.schema.json - 语义、kind 注册表、映射和代码级断言:
raw/contracts/README.md - 示例:
raw/contracts/event-v0.1.example-*.json
关键规则:
- 顶层未知字段拒绝;扩展只能放
ext。 - Brain 提供
source_event_id,Bell 生成平台 ULID。 confidence允许 null,当前判定链路必须为 null。detected_at >= occurred_at,时间与latency_seconds自洽。- 证据文件名只含事件 ID 与日期目录,不含 IP、端口、凭据或客户名。
sensors中恰有一个 primary,且其device_id与顶层一致。
2. 跨系统接口状态
| 调用方 → 提供方 | 用途 | 当前约束 | 状态 |
|---|---|---|---|
| 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 设计 |
| Worker → 控制面 | 注册、心跳、容量 | max_sources 来自 profile/压测,不固定为 16 |
待 M3 设计 |
冻结签名和失败语义见 contracts/README.md 与 contracts/site-quota-v1.sql。Bell 拥有源数据和视图,Sense 数据库角色只有 SELECT;未来分库必须发布新版本,不能在 v1 下把本地视图静默替换为网络调用。
3. 已冻结:Sense Control API v1
- OpenAPI:
contracts/sense-control-v1.openapi.json - 语义、资源所有权、幂等、并发与兼容规则:
contracts/README.md - 范围:设备分页查询、创建、读取、修改、单项启停、最多 128 项的批量启停和批量操作查询。
关键规则:
- 所有业务路径使用
/api/v1和 Bearer 认证;tenant 只来自认证上下文,跨租户访问与不存在统一为404 not_found。 - Site、Area、RBAC、配额和全局审计仍由 Bell 持有;Sense 只管理 Device 期望态和收敛状态,不提供这些 Bell 资源的 CRUD。
- 列表使用稳定顺序和不透明 cursor,默认 50、最大 100;创建与批量写要求
Idempotency-Key,资源修改与单项期望态写要求If-Match。 endpoint_ref、credential_ref、profile_token只写不读;设备 ID 由服务端生成。普通响应和错误不得包含凭据、完整流 URI、token 或 MediaMTX 内部配置。- v1 不提供删除设备;停用设备保留历史。写入受理只表示期望态已持久化,不能表示实际态已收敛。
T-008 冻结契约;T-009 已实现 PostgreSQL bell.sites/配额视图、最小权限和 Sense repository,但尚未实现 Sense HTTP handler、认证中间件或 Bell 管理服务。
4. 待冻结的 Bell 公共 API
资源范围预计包括:租户、站点、设备只读投影、规则、事件、预警、ack、处置、误报反馈、审计和报表。设计时必须满足:
- URL 版本化,例如
/api/v1/...;具体路径须由对应任务冻结。 - 租户从认证上下文确定,不信任客户端随意传入的 tenant ID。
- 列表强制分页、稳定排序和可组合筛选;批量操作返回逐项结果。
- 写操作支持幂等键或等价机制;并发更新使用版本/ETag 或明确冲突响应。
- 错误体包含稳定错误码、可读消息和 trace ID,不返回内部堆栈或凭据。
- 人脸功能未授权时表现为能力不存在,而非仅按钮置灰。
5. MediaMTX 接口边界
Sense 使用 MediaMTX 官方 OpenAPI 生成客户端并加薄封装。业务代码不得散落硬编码 path API;生成代码不可手改。MediaMTX path 不是租户/站点/设备的业务真相源。
5.1 T-003 已实现的内部适配契约
以下是 Sense 内部 Go port,不是 Bell 或第三方可依赖的公共 HTTP API:
| Port | 操作 | 数据所有者 / 失败语义 |
|---|---|---|
| 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 默认开发路径;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 生成包。
5.2 设备台账语义
- 设备类型由
modality表达物理类别,由多值capabilities表达视频采集、音频、空间规则或遥测能力,避免把“摄像头”固化为唯一设备模型。 - 视频配额只统计
desired_state=enabled且具有video_capturecapability 的设备;站点默认 16、可配置 1~128。禁用设备和非视频传感器不占视频路数。 - 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 表示所选数据库已打开且 schema/权限前置检查完成。两者返回 JSON,均不等价于摄像头、MediaMTX path 或里程碑健康。T-008 已冻结站点作用域的 /api/v1/sites/{site_id}/devices 等设备管理契约,但尚未实现对应 handler;当前可运行进程仍只暴露探针,后续实现不得发布 /api/v1/devices 等无站点边界的临时接口。
6. 变更流程
- 在对应任务文件写清调用方、提供方、数据所有者、失败语义、幂等与兼容策略。
- 更新本文和 schema/OpenAPI。
- 同步生产者、消费者、契约测试和示例。
- 记录迁移、回滚与版本废弃策略。
事件 v0.1、Sense Control API v1 或站点配额投影 v1 的破坏性变化必须发布新版本,不能原地修改已被生产者/消费者使用的契约。