feat(sense): implement Control API v1 [T-011]
This commit is contained in:
+38
-7
@@ -1,20 +1,20 @@
|
||||
# Sense M1/M2 接入骨架
|
||||
|
||||
本目录是 YoVision Sense 的 M1/M2 接入骨架。数据库保存期望态,ONVIF 和 MediaMTX 通过端口隔离;M1 默认使用 SQLite,T-009/T-010 增加 PostgreSQL 双 schema、Area 准入和本地审计 Outbox 生产基础。默认关闭真实 ONVIF,显式设置 `SENSE_ONVIF_MODE=standard` 后才启用标准 SOAP/WS-Security 适配器。T-006 的真实样机结论仅覆盖已批准的精确海康基线,不能据此宣称多品牌兼容。
|
||||
本目录是 YoVision Sense 的 M1/M2 接入骨架。数据库保存期望态,ONVIF 和 MediaMTX 通过端口隔离;M1 默认使用 SQLite,T-009~T-011 增加 PostgreSQL 双 schema、Area 准入、本地审计 Outbox 和 Control API v1。默认关闭真实 ONVIF 与公共业务路由;T-006 的真实样机结论仅覆盖已批准的精确海康基线,不能据此宣称多品牌兼容。
|
||||
|
||||
## 常用命令
|
||||
|
||||
```powershell
|
||||
cd Sense
|
||||
go mod download
|
||||
go generate ./internal/mtx
|
||||
go generate ./internal/mtx ./internal/controlapi
|
||||
go test ./...
|
||||
go vet ./...
|
||||
go build -o bin/sense-api.exe ./cmd/sense-api
|
||||
go run ./cmd/sense-api
|
||||
```
|
||||
|
||||
Unix 将构建产物改为 `bin/sense-api`。服务默认监听 `127.0.0.1:8080`,SQLite 默认写入 `Sense/data/sense.db`,MediaMTX 控制 API 默认是 `http://127.0.0.1:9997`。当前运行代码只有 `/healthz` 与 `/readyz`;Sense Control API v1 虽已冻结,但 HTTP handler 和认证尚未实现。
|
||||
Unix 将构建产物改为 `bin/sense-api`。服务默认监听 `127.0.0.1:8080`,SQLite 默认写入 `Sense/data/sense.db`,MediaMTX 控制 API 默认是 `http://127.0.0.1:9997`。默认运行只暴露 `/healthz` 与 `/readyz`;只有显式选择 PostgreSQL 并完成安全配置后才注册 7 个 `/api/v1` Control API 路由。
|
||||
|
||||
常用环境变量:
|
||||
|
||||
@@ -31,6 +31,11 @@ Unix 将构建产物改为 `bin/sense-api`。服务默认监听 `127.0.0.1:8080`
|
||||
| `SENSE_ONVIF_RTSP_REWRITE_HOST` | 空 | NAT 或故障代理场景下重写 ONVIF 返回的 RTSP 主机 |
|
||||
| `SENSE_ONVIF_RTSP_REWRITE_PORT` | `0` | 非零时重写 ONVIF 返回的 RTSP 端口 |
|
||||
| `SENSE_ONVIF_RTSP_STRIP_QUERY` | `false` | 仅在已验证设备返回不可用查询串时显式移除;默认保留标准 URI 语义 |
|
||||
| `SENSE_CONTROL_API_ENABLED` | `false` | 显式开启 Control API v1;只允许与 PostgreSQL 一起使用 |
|
||||
| `SENSE_CONTROL_AUTH_MODE` | `static-sha256` | 首版外部摘要注册表适配器;token 格式不属于公共 API 契约 |
|
||||
| `SENSE_CONTROL_AUTH_FILE` | 空 | 仓库外绝对路径;version 1 JSON 只保存 token SHA-256、主体、tenant、Site scope 和权限 |
|
||||
| `SENSE_CONTROL_CURSOR_KEY_FILE` | 空 | 仓库外绝对路径;内容为至少 32 字节随机值的无填充 base64url |
|
||||
| `SENSE_CONTROL_ALLOW_INSECURE_HTTP` | `false` | Control API 非回环明文监听的独立风险接受;正常部署应保持回环并在受控代理终止 TLS |
|
||||
|
||||
设备台账只保存 `env://<key>` 凭据引用。真实适配器从进程环境读取以下变量,不把秘密写入 SQLite、日志或 MediaMTX 错误:
|
||||
|
||||
@@ -45,11 +50,11 @@ SENSE_CREDENTIAL_<KEY>_RTSP_PASSWORD
|
||||
|
||||
MediaMTX `v1.19.3` 应作为独立二进制启动并只在可信网络开放 API。获取与 SHA-256 校验值见 `docs/03-tech-stack.md`。生成客户端使用固定版本工具和 vendored 官方 OpenAPI;`internal/mtx/generated/client.gen.go` 不可手改。
|
||||
|
||||
## T-009/T-010 PostgreSQL 17.10
|
||||
## T-009~T-011 PostgreSQL 17.10
|
||||
|
||||
初始化与增量 SQL 位于 `deploy/postgres/`,由高权限部署步骤按文件名前缀执行;Sense 进程不会自动创建角色、schema 或 Bell 对象。`bell_app` 拥有 Site/Area、配额、`capture_policy` 及两个版本化视图,`sense_app` 只能读取 `bell.site_quota_v1` 和 `bell.area_policy_v1`,不能读取或写入 Bell 源表。应用登录角色和密码由部署环境创建,不进入仓库。
|
||||
初始化与增量 SQL 位于 `deploy/postgres/`,由高权限部署步骤按文件名前缀执行;Sense 进程不会自动创建角色、schema 或 Bell 对象。`bell_app` 拥有 Site/Area、配额、`capture_policy` 及两个版本化视图,`sense_app` 只能读取两个视图,不能读取或写入 Bell 源表。T-011 的 v4 schema 另有资源版本、24 小时幂等收据和 batch operation 表;收据只保存 scope/body 摘要与脱敏响应快照。应用登录角色和密码由部署环境创建,不进入仓库。
|
||||
|
||||
PostgreSQL 新建设备必须携带匹配 tenant/Site 的 `area_id`。具有 `video_capture` 能力的设备在创建和从 disabled 切到 enabled 时执行 Area 准入;`non_imaging_only` 拒绝成像设备但允许非成像设备。投影缺失、非法或版本回退只拒绝新变更,不关闭已有流。设备创建和期望态受理与 `sense.device_operation_outbox` 在同一事务写入;Outbox 不保存 endpoint、credential、完整 URI 或 MediaMTX 配置。Bell relay 尚未实现。
|
||||
PostgreSQL 新建设备必须携带匹配 tenant/Site 的 `area_id`。具有 `video_capture` 能力的设备在创建、移动 Area 和从 disabled 切到 enabled 时执行 Area 准入;`non_imaging_only` 拒绝成像设备但允许非成像设备。投影缺失、非法或版本回退只拒绝新变更,不关闭已有流。创建、配置修改和期望态受理都与对应脱敏 Outbox 事实同事务;停用后调和器只删除该设备的精确 MediaMTX path 并收敛为 offline,不枚举未知 path。Bell relay 尚未实现。
|
||||
|
||||
Windows 本机集成测试从仓库根目录执行:
|
||||
|
||||
@@ -67,7 +72,33 @@ $env:SENSE_DB_DSN = '由部署环境私下设置'
|
||||
go run ./cmd/sense-api
|
||||
```
|
||||
|
||||
PostgreSQL 启动会检查 Sense migration 版本及当前角色对两个 Bell 投影视图的最小权限;权限过宽、视图不可读或 schema 未安装时 readiness 初始化失败。默认 SQLite 路径和 `cmd/sense-lab` 保持不变,但 SQLite 不实现生产 Area/Outbox 一致性,后续公共控制 API 不得在 SQLite 上启用。
|
||||
PostgreSQL 启动会检查 Sense migration 版本及当前角色对两个 Bell 投影视图的最小权限;权限过宽、视图不可读或 schema 未安装时 readiness 初始化失败。默认 SQLite 路径和 `cmd/sense-lab` 保持不变,但 SQLite 不实现生产 Area/Outbox 一致性,Control API feature flag 在 SQLite 下会直接拒绝启动。
|
||||
|
||||
### 开启 Control API
|
||||
|
||||
复制 [`api/control-auth.example.json`](api/control-auth.example.json) 到仓库外受限目录并替换占位项。`token_sha256` 是至少 128 bit 随机 Bearer token 的 64 位小写 SHA-256,不是 token 明文;`site_ids` 支持精确 ID 或 `"*"`,权限只接受 `sense.devices.read`、`sense.devices.write`。注册表在启动时读取,轮换后需要受控重启。
|
||||
|
||||
另在仓库外生成 cursor key。PowerShell 示例只把 key 写入指定秘密文件,不把值打印到日志:
|
||||
|
||||
```powershell
|
||||
$cursorBytes = [byte[]]::new(32)
|
||||
[Security.Cryptography.RandomNumberGenerator]::Fill($cursorBytes)
|
||||
$cursorKey = [Convert]::ToBase64String($cursorBytes).TrimEnd('=').Replace('+', '-').Replace('/', '_')
|
||||
Set-Content -LiteralPath 'D:\private\sense-cursor.key' -Value $cursorKey -NoNewline
|
||||
```
|
||||
|
||||
完成 PostgreSQL migration、专用登录角色和外部文件权限后,以私有环境开启:
|
||||
|
||||
```powershell
|
||||
$env:SENSE_DB_DRIVER = 'postgres'
|
||||
$env:SENSE_DB_DSN = '由部署环境私下设置'
|
||||
$env:SENSE_CONTROL_API_ENABLED = 'true'
|
||||
$env:SENSE_CONTROL_AUTH_FILE = 'D:\private\sense-auth.json'
|
||||
$env:SENSE_CONTROL_CURSOR_KEY_FILE = 'D:\private\sense-cursor.key'
|
||||
go run ./cmd/sense-api
|
||||
```
|
||||
|
||||
业务响应使用 `Cache-Control: no-store`;ETag 是写并发令牌,cursor 与认证 tenant/Site/筛选绑定。静态摘要文件只是首版私有部署适配器;公网/TLS、Bell 会话、JWT/OIDC 与热加载需后续任务,不能靠设置 `SENSE_CONTROL_ALLOW_INSECURE_HTTP=true` 冒充完成。
|
||||
|
||||
Windows 本地准备 MediaMTX(从仓库根目录执行):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user