Files
yovision/docs/tasks/T-009.md
T
QiuSW 04231d006a
Harness governance / validate (push) Has been cancelled
chore(task): claim T-009
2026-08-07 17:32:48 +08:00

92 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: T-009
title: 建立 PostgreSQL 双 Schema 与 Bell 配额投影基础
phase: 2
deps: [T-008]
status: DOING
created: 2026-08-07
issue: 31
context_ref: 8a4514076e9921b12bc26380b2aceee9334e947d
claim_branch: claims/T-009
work_branch: agent/codex/T-009
write_paths:
- docs/tasks/T-009.md
- deploy/postgres/
- scripts/test_postgres.ps1
- Sense/internal/store/
- Sense/internal/config/
- Sense/cmd/sense-api/main.go
- Sense/go.mod
- Sense/go.sum
- Sense/README.md
- docs/03-tech-stack.md
- docs/04-architecture.md
- docs/06-tasks.md
- docs/api.md
- docs/current-state.md
- tests/test_postgres_contract.py
---
## 问题 / 背景
T-008 已冻结 Sense Control API v1 和 `bell.site_quota_v1` 只读投影,但当前 Sense 仍只使用 M1 SQLite,Bell 也没有 PostgreSQL 源表、schema、角色或 migration。若直接实现 HTTP handler,tenant、配额读取、并发准入和事务语义仍会绑定 SQLite,后续迁移必然返工。
项目负责人指定使用本机现有 `D:\pgsql17`,已核实二进制与服务版本为 PostgreSQL `17.10`、默认端口 `5432`。现有实例要求 SCRAM 且当前执行环境没有管理员密码,因此自动验收必须使用同一套本机二进制启动隔离临时集群;不得修改现有实例的认证、角色、数据库或数据。生产/共享实例安装只有在操作者显式提供管理员连接信息时才执行。
## 关联需求与交互(如适用)
- 用户故事:US-001、US-002、US-008、US-009、US-010。
- 交互清单:IX-001~IX-004、IX-013~IX-016、IX-019、IX-020;本任务是数据基础,不修改已确认原型或实现 HTTP 页面交互。
- 前置契约:`docs/contracts/sense-control-v1.openapi.json`、`docs/contracts/site-quota-v1.sql` 和 `docs/contracts/README.md`。
## 方案
1. 冻结 PostgreSQL `17.10` 与 Go PostgreSQL driver;增加可审计、顺序执行的初始化 SQL,创建 NOLOGIN 权限角色 `bell_app`/`sense_app`、`bell`/`sense` schema、Bell Site 配额源表和 Sense 设备/能力/调和表。
2. migration 创建与 T-008 完全一致的 `bell.site_quota_v1(tenant_id, site_id, max_video_channels, source_version, source_updated_at)`;Bell 拥有源表和视图,Sense 只有 Bell schema `USAGE` 与视图 `SELECT`,没有 Bell 源表或写权限。
3. Bell Site 在数据库层执行默认 16、范围 1~128、逻辑删除和单调版本;配额更新通过 trigger 增加版本,不能由 Sense 修改。
4. 新增 Sense PostgreSQL repository,覆盖现有 SQLite 被对账/探活使用的全部 port;设备新增/启用在同一事务内按 tenant/site 读取配额投影、串行化同站点准入、统计 `enabled + video_capture`,并拒绝投影缺失、越界或版本回退。
5. Sense 进程增加显式 `SENSE_DB_DRIVER=sqlite|postgres`;默认继续使用 SQLite 保持单摄像头开发路径,生产选择 PostgreSQL 时必须显式提供 DSN。不得把 DSN、密码或完整连接串写入日志、错误、任务证据或仓库。
6. 使用 `D:\pgsql17\bin` 的 `initdb/pg_ctl/psql` 启动仅绑定回环地址的隔离临时集群,执行 migration、权限断言和 PostgreSQL repository 集成测试,结束后验证目标路径再清理临时数据目录;不停止或重启现有 Windows PostgreSQL 服务。
7. 增加无 PostgreSQL 也能运行的静态契约测试,校验 migration 顺序、角色权限、配额视图签名、范围、版本 trigger 和禁止的宽权限;同步技术栈、架构、API、路线图、Sense 启动说明与当前状态。
## 不可变约束
- 阈值 / 数值边界:`max_video_channels` 默认 16、有效范围 1~128;16/128 不是单机承载保证。只统计 `desired_state=enabled` 且具有 `video_capture` capability 的设备;同站点并发创建/启用不能突破配额。
- 判定式 / 状态转换:配额行缺失、读取失败、值越界或 `source_version` 回退时,PostgreSQL repository 只拒绝相关视频新增/启用,不停已有设备、不修改期望态;降低配额不会自动停用已有流。相同期望态重复提交不增加 generation。
- 数据所有权:Bell 是 Tenant/Site/配额真相源;Sense 不建立可写 Site 真相副本,不写 Bell schema、不读取 `bell.sites` 源表。Sense 设备和调和状态只写 `sense` schema;两个 schema 只以 tenant/site 逻辑 ID 关联。
- 安全边界:仓库、测试输出、Issue/PR 和日志不得出现 PostgreSQL 密码、DSN 凭据或私有数据。自动测试只使用临时 trust 集群且只绑定 `127.0.0.1`;现有 `D:\pgsql17\data`、Windows 服务和其他数据库严格只读。
- 兼容与恢复:M1 SQLite 默认路径和现有五路集成工具继续可用;T-009 不搬迁或删除现有 SQLite 数据。生产切换失败时可回到 SQLite 配置;初始 PostgreSQL schema 不提供自动破坏性 down migration,清理由管理员在备份/确认后限定到 YoVision 专用数据库执行。
- 既有契约:不修改 T-008 OpenAPI 路径、字段、错误语义、配额视图列签名或 Brain 事件 v0.1;PostgreSQL repository 的出现不表示 Sense HTTP handler、认证或 Bell 管理服务已经实现。
## 验收要点
- 任务相关验证:在本机执行 `./scripts/test_postgres.ps1 -PgRoot D:\pgsql17`,必须完成隔离集群启动、migration 重放、权限断言、tenant/配额/并发/版本回退 repository 集成测试和自动清理;运行 `python -m unittest tests/test_postgres_contract.py` 或对应 discovery 命令,静态负例能够拦截 Bell 写权限与契约漂移。
- 完整门禁:运行 `./init.ps1`、`python scripts/validate_agent_context.py`、`python -m unittest discover -s tests -p "test_*.py"`、`python scripts/validate_harness_governance.py`、`go -C Sense test ./...`、`go -C Sense vet ./...`、`go -C Sense build ./...` 和 `git diff --check`,全部通过。
- 人工 / 设备验收:不需要摄像头、UI 或客户现场;任务所有者必须核对隔离集群确实没有使用 `D:\pgsql17\data`,现有服务 PID/端口在测试前后保持运行,且共享实例未新增 YoVision 对象。
- 构建产物:PostgreSQL migration、权限/迁移断言、本机隔离测试入口、Sense PostgreSQL repository 和配置/运维文档;不提交临时数据目录、数据库 dump 或秘密。
## 边界(不改什么)
不实现 Sense Control API HTTP handler、Bearer 认证、RBAC、幂等收据、ETag/cursor/batch operation、Area/capture policy 投影、Bell Go 服务、SQLite→PostgreSQL 数据搬迁、WireGuard、孤儿删除、16 路容量压测或 T-007 现场验收;不修改 Brain、MediaMTX API、摄像头适配器、事件契约或已确认 UI 原型。
## 协作约束
- 责任 Agent:由 dispatcher 分配。
- 唯一写入者:同责任 Agent。
- 委派:默认不启用。
- Gitea:任务文件先进入默认分支,再创建唯一 Issue 并回填编号;领取时记录 `context_ref`、claim 与工作分支。
任何新增写路径先检查与其他活跃任务是否重叠;同一时刻只有一个 Agent 修改本任务的 `write_paths`。
## 执行记录
### 2026-08-07 领取任务
- dispatcher `ila` 将任务分配给 `codex`;`context_ref` 为 `8a4514076e9921b12bc26380b2aceee9334e947d`,claim 为 `claims/T-009`,工作分支为 `agent/codex/T-009`。
- 接受任务文件声明的全部写路径;当前其他任务无活跃写路径冲突,T-007 仍因外部真实设备保持 waiting。
### 2026-08-07 任务定义
- 项目负责人批准创建并实施 T-009,并指定复用本机 `D:\pgsql17`;核实版本为 PostgreSQL `17.10`。
- 当前实例监听 `5432` 且 SCRAM 认证有效,执行环境未持有管理员密码;任务据此选择“本机同版二进制 + 隔离临时集群”作为自动验收,不触碰现有数据目录和服务。