feat(sense): implement Control API v1 [T-011]
Harness governance / validate (push) Has been cancelled
Harness governance / validate (pull_request) Has been cancelled

This commit is contained in:
QiuSW
2026-08-07 20:54:41 +08:00
parent 0d3d7a22ed
commit a0d239811f
45 changed files with 4844 additions and 83 deletions
+1 -1
View File
@@ -85,7 +85,7 @@ MVP 以默认 16 路跑通一个场景的端到端闭环;架构、数据和 UI
python scripts/validate_agent_context.py
python -m unittest discover -s tests -p "test_*.py"
python scripts/validate_harness_governance.py
go -C Sense generate ./internal/mtx
go -C Sense generate ./internal/mtx ./internal/controlapi
go -C Sense test ./...
go -C Sense vet ./...
go -C Sense build ./...
+4 -2
View File
@@ -50,6 +50,8 @@ MediaMTX 官方 `v1.19.3` OpenAPI 固定保存于 `Sense/api/vendor/mediamtx-v1.
M2 仍保留 SQLite 作为单机开发与 T-006 回归入口,但生产真相源切换目标是 PostgreSQL。运行时必须显式设置 `SENSE_DB_DRIVER=postgres` 和私有 `SENSE_DB_DSN` 才使用 PostgreSQL;仓库不提供带密码 DSN。初始 schema 由 `deploy/postgres/` 的顺序 migration 创建,不在 Sense 进程启动时使用高权限自动迁移。
T-011 复用同一套冻结的 Go、PostgreSQL、pgx 与 `oapi-codegen`,未增加第三方依赖。Sense Control API v1 从仓库 OpenAPI 生成 `net/http` server glue;首版认证是可替换 port 下的外部静态 SHA-256 注册表,公共路由默认关闭且只在 PostgreSQL v4 schema 上启用。静态适配器是私有部署启动方案,不替代后续 Bell/JWT/OIDC 身份服务。
## 2. 外部项目边界
- MiBeeNvr:只用于 M0 隔离实验室、ONVIF兼容性和交互参考,不作为生产依赖。
@@ -86,7 +88,7 @@ Sense 单独执行:
```powershell
go -C Sense mod download
go -C Sense generate ./internal/mtx
go -C Sense generate ./internal/mtx ./internal/controlapi
go -C Sense test ./...
go -C Sense vet ./...
go -C Sense build ./...
@@ -107,7 +109,7 @@ python scripts/validate_harness_governance.py
| --- | --- | --- | --- |
| Harness 文档/任务/Gitea 模板 | 上述三条 Python 命令 | 任一治理协议、清单或任务 schema 变化 | 不适用 |
| `docs/raw/contracts/` | JSON Schema 校验 + 契约代码断言(实现后补命令) | schema/示例/mapper 任一变化 | 生产者与消费者联合评审 |
| Sense Go | `go -C Sense generate ./internal/mtx`、`go -C Sense test ./...`、`go -C Sense vet ./...`、`go -C Sense build ./...` | ONVIF、存储、MediaMTX、对账或公共 API 变化 | T-006 使用 1 路指定实机 + 4 路独立合成源;T-007 才要求客户/借用/租赁的真实多路矩阵 |
| Sense Go | `go -C Sense generate ./internal/mtx ./internal/controlapi`、`go -C Sense test ./...`、`go -C Sense vet ./...`、`go -C Sense build ./...` | ONVIF、存储、MediaMTX、对账或公共 API 变化 | T-006 使用 1 路指定实机 + 4 路独立合成源;T-007 才要求客户/借用/租赁的真实多路矩阵 |
| PostgreSQL schema/repository | `python -m unittest discover -s tests -p "test_postgres_contract.py"`;Windows 本机再运行 `./scripts/test_postgres.ps1 -PgRoot D:\pgsql17` | migration、权限、配额判定或 PostgreSQL driver 变化 | 不需要摄像头;必须核对临时集群未使用现有 data 目录,现有 5432 listener 前后不变 |
| Brain Python | 单元测试、类型/格式检查(命令待项目脚手架冻结) | mapper、判定状态机、模型接口变化 | 命中模型任务时用冻结数据集和目标硬件 |
| Bell Go/Web | 后端测试 + 前端 lint/test/build(命令待脚手架冻结) | schema、RBAC、预警状态机或公共 UI 变化 | P0 流程由产品/值班角色验收 |
+1 -1
View File
@@ -95,7 +95,7 @@ Sense ── 视频流/触发信号 ──> Brain
## 8. 数据与契约
- Bell 核心实体:Tenant → Site → Area(含 `capture_policy`)以及 Role/Binding/Quota/Audit;Sense 核心实体:Device(含 `modality + capabilities`)→ StreamBinding/Zone,以及只记录已观察版本的 SiteQuota/AreaPolicyProjection。两个 schema 以稳定逻辑 ID 关联,不跨 schema 写入;配额 v1 为五列,Area v1 固定为 `tenant_id/site_id/area_id/capture_policy/source_version/source_updated_at` 六列。
- Sense Control API v1 使用站点作用域路径、认证上下文 tenant、cursor 分页、幂等键与 ETag;敏感连接引用只写不读。正式签名和兼容规则以 [`contracts/`](contracts/) 为准。T-009/T-010 已实现 PostgreSQL 准入与审计事务基础,不等于 handler、认证、Bell 管理服务或 Outbox relay 已实现。
- Sense Control API v1 使用站点作用域路径、认证上下文 tenant、HMAC cursor 分页、PostgreSQL 幂等收据与资源 ETag;敏感连接引用只写不读。T-011 已实现 7 个 handler,并以 feature flag 限定到 PostgreSQL 路径;首版外部静态 SHA-256 注册表只实现认证 port 的私有部署适配器。正式签名和兼容规则以 [`contracts/`](contracts/) 为准,Bell 管理服务、JWT/OIDC 与 Outbox relay 仍未实现。
- 业务实体:Rule → Event → Alert → DeliveryAttempt/Ack;Event 与 Alert 不合并。
- Bell 通知域分为三个聚合:Contact/Team 保存身份、成员关系和已验证通道;OnCallSchedule/ScheduleVersion/ShiftException 保存时区、轮换与例外;EscalationPolicy/Step 通过 `person / team / on_call_schedule` 类型化 `target_ref` 引用目标。三者共享逻辑 ID,不复制手机号、班次或轮换字段。
- 每个 DeliveryAttempt 创建时解析当时生效的排班版本,并保存实际收件人、通道、`schedule_version` 和解析时间快照;之后联系人或排班修改不得回写既有投递事实。
+1 -1
View File
@@ -25,7 +25,7 @@
- T-008:冻结 Sense Control API v1 与 Bell `site_quota_v1` 只读投影契约;只建立接口和测试门禁,不等于 handler、Bell 表或 migration 已实现。
- T-009:使用 PostgreSQL 17.10 建立 `sense`/`bell` schema、Bell 配额源表/只读视图、最小权限和 Sense PostgreSQL repository;SQLite 保留为 M1 本地路径。
- T-010:建立 Bell Area/`capture_policy` 只读投影、Sense 成像准入与设备操作审计 Outbox 原子写入;relay 传输协议留给后续任务。
- 后续 T-011 按 T-008 契约实现认证 tenant 上下文、设备管理 handler、幂等/ETag/cursor 与批量操作;公共控制 API 只在 PostgreSQL 路径启用,不得把 T-009/T-010 数据基础误报为 API 已交付。
- T-011:按 T-008 契约实现认证 tenant 上下文、7 个设备/operation handler、PostgreSQL 幂等收据、ETag/HMAC cursor、最多 128 项批量操作和停用精确 path 收敛;公共控制 API 默认关闭且只在 PostgreSQL 路径启用。
- 对账器幂等/退避/并发/10% 安全闸。
- WireGuard 边缘隧道与断网恢复。
- 16 路批量开通、停用和容量基准。
+3 -3
View File
@@ -1,6 +1,6 @@
# API 与契约
> Brain → Bell 事件契约 v0.1、Sense Control API v1、Bell 配额/Area 只读投影 v1 与 Sense 本地设备审计事件 v1 已冻结;其他 API 仍在设计阶段。不得把本文的“待定”自行具体化为公共契约。
> Brain → Bell 事件契约 v0.1、Sense Control API v1、Bell 配额/Area 只读投影 v1 与 Sense 本地设备审计事件 v1/v2 已冻结;其他 API 仍在设计阶段。不得把本文的“待定”自行具体化为公共契约。
## 1. 已冻结:Brain → Bell 事件契约
@@ -45,7 +45,7 @@
- `endpoint_ref`、`credential_ref`、`profile_token` 只写不读;设备 ID 由服务端生成。普通响应和错误不得包含凭据、完整流 URI、token 或 MediaMTX 内部配置。
- v1 不提供删除设备;停用设备保留历史。写入受理只表示期望态已持久化,不能表示实际态已收敛。
T-008 冻结公共控制契约;T-009/T-010 已实现 PostgreSQL Site/Area 源表、两个只读视图、最小权限、Sense 准入 repository 和本地审计 Outbox,但尚未实现 Sense HTTP handler、认证中间件、Bell 管理服务或 Outbox relay。
T-008 冻结公共控制契约;T-009/T-010 建立 PostgreSQL 投影、准入和本地审计基础;T-011 已实现 7 个 HTTP handler、外部静态摘要认证适配器、tenant/Site scope、幂等收据、ETag/HMAC cursor 和持久化 batch operation。业务路由默认关闭且仅可在 PostgreSQL 上开启;Bell 管理服务、JWT/OIDC 和 Outbox relay 尚未实现。
## 4. 待冻结的 Bell 公共 API
@@ -83,7 +83,7 @@ MediaMTX 薄封装调用同版官方 OpenAPI 的 `/v3/config/paths/get|add|patch
### 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` 等无站点边界的临时接口。
`GET /healthz` 表示进程存活,`GET /readyz` 表示所选数据库已打开且 schema/权限前置检查完成;两者不要求认证,也不等价于摄像头、MediaMTX path 或里程碑健康。T-011 在 `SENSE_CONTROL_API_ENABLED=true`、PostgreSQL v4 schema 和外部安全文件全部有效时注册冻结的 `/api/v1` 路由;默认 SQLite 运行仍只暴露探针。业务路由不提供无 Site 边界的 `/api/v1/devices` 临时接口。
## 6. 变更流程
+6 -3
View File
@@ -1,6 +1,6 @@
# Sense 控制面、准入投影与本地审计契约 v1
> 冻结日期:2026-08-07。契约版本:`1.0.0`。Sense 是设备期望态的提供方;Bell 是 Tenant、Site、Area、RBAC、配额与全局审计的所有者。T-009/T-010 已实现两个只读投影和本地审计事务基础;HTTP handler、Bell 管理服务和 Outbox relay 仍未实现。
> 冻结日期:2026-08-07。Control API 契约版本:`1.0.0`。Sense 是设备期望态的提供方;Bell 是 Tenant、Site、Area、RBAC、配额与全局审计的所有者。T-011 已实现 Control API handler 与 PostgreSQL 一致性边界;Bell 管理服务、JWT/OIDC 和 Outbox relay 仍未实现。
## 契约文件
@@ -10,6 +10,7 @@
| [`site-quota-v1.sql`](site-quota-v1.sql) | Bell | Sense | 单 PostgreSQL 实例内的站点视频配额只读投影 |
| [`area-policy-v1.sql`](area-policy-v1.sql) | Bell | Sense | Area 归属与 `capture_policy` 只读投影 |
| [`sense-device-audit-v1.schema.json`](sense-device-audit-v1.schema.json) | Sense | 本地 Outbox;未来 Bell relay | 脱敏设备操作审计事实,不包含传输协议 |
| [`sense-device-audit-v2.schema.json`](sense-device-audit-v2.schema.json) | Sense | 本地 Outbox;未来 Bell relay | v1 后继,增加脱敏配置修改受理事实;v1 文件保持不变 |
OpenAPI 的 `/api/v1` 路径是公共控制面边界;`/healthz`、`/readyz` 仍是非业务运维探针。v1 不提供设备删除:停用设备使用期望态接口,保留设备、操作和审计历史。Site、Area、配额、RBAC 和审计聚合不由 Sense 提供 CRUD。
@@ -54,7 +55,7 @@ T-010 冻结 `bell.area_policy_v1` 的列顺序为 `tenant_id/site_id/area_id/ca
## 本地设备操作审计
`sense-device-audit-v1.schema.json` 冻结本地审计事实的逻辑 envelope。当前事件只有 `device.created` 和 `device.desired_state.accepted`;主体类型为 `user | service | system`,投影版本与 generation 随事实保存。`data` 只包含 Area、模态、能力和状态变化等脱敏字段,禁止 endpoint、credential、profile token、path、密码、完整流 URI 或 MediaMTX 配置。
`sense-device-audit-v1.schema.json` 继续冻结创建与期望态两类事实且不原地扩展严格枚举。T-011 新增 v2 后继,兼容 v1 两类事件并增加 `device.configuration.accepted`;该 payload 只保存是否变化、字段名和 Area 逻辑 ID,不保存字段值。主体类型为 `user | service | system`,投影版本与 generation 随事实保存;endpoint、credential、profile token、path、密码、完整流 URI 或 MediaMTX 配置始终禁止进入审计。
PostgreSQL repository 必须在设备创建/期望态事务内写 `sense.device_operation_outbox`;Outbox 失败回滚业务写入。相同期望态不增加 generation,但仍产生独立审计事实。Schema 不是 Bell relay 协议:传输端点、签名、批量确认、重放窗口和留存由后续任务冻结。
@@ -71,7 +72,9 @@ PostgreSQL repository 必须在设备创建/期望态事务内写 `sense.device_
```powershell
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 unittest discover -s tests -p "test_sense_control_contract.py"
python -m unittest discover -s tests -p "test_sense_control_implementation.py"
```
测试校验本仓库依赖的 OpenAPI 结构与安全不变量,并不替代后续实现任务对完整 OpenAPI 标准验证器、HTTP handler 和 PostgreSQL migration 的验证。
测试同时校验 OpenAPI 结构、生成 server glue、HTTP handler 与 PostgreSQL migration/事务;它不替代 Bell 消费方联合验收或客户现场容量验证。
@@ -0,0 +1,124 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://yovision.local/contracts/sense-device-audit-v2.schema.json",
"title": "Sense Device Audit Event v2",
"description": "v1 的向后兼容后继:增加脱敏设备配置受理事实,仍不定义 Bell relay。",
"type": "object",
"additionalProperties": false,
"required": [
"event_id", "event_type", "tenant_id", "site_id", "device_id",
"actor", "reason", "trace_id", "aggregate_generation",
"projection_versions", "data", "occurred_at"
],
"properties": {
"event_id": {"type": "string", "pattern": "^audit_[0-9a-f]{32}$"},
"event_type": {
"enum": [
"device.created",
"device.desired_state.accepted",
"device.configuration.accepted"
]
},
"tenant_id": {"$ref": "#/$defs/logicalId"},
"site_id": {"$ref": "#/$defs/logicalId"},
"device_id": {"$ref": "#/$defs/logicalId"},
"actor": {
"type": "object",
"additionalProperties": false,
"required": ["type", "id"],
"properties": {
"type": {"enum": ["user", "service", "system"]},
"id": {"type": "string", "minLength": 1, "maxLength": 200}
}
},
"reason": {"type": ["string", "null"], "maxLength": 500},
"trace_id": {"type": ["string", "null"], "maxLength": 128},
"aggregate_generation": {"type": "integer", "minimum": 1},
"projection_versions": {
"type": "object",
"additionalProperties": false,
"required": ["quota_source_version", "area_policy_source_version"],
"properties": {
"quota_source_version": {"type": ["integer", "null"], "minimum": 1},
"area_policy_source_version": {"type": ["integer", "null"], "minimum": 1}
}
},
"data": {
"oneOf": [
{"$ref": "#/$defs/deviceCreatedData"},
{"$ref": "#/$defs/desiredStateData"},
{"$ref": "#/$defs/configurationData"}
]
},
"occurred_at": {"type": "string", "format": "date-time"}
},
"allOf": [
{
"if": {"properties": {"event_type": {"const": "device.created"}}},
"then": {"properties": {"data": {"$ref": "#/$defs/deviceCreatedData"}}}
},
{
"if": {"properties": {"event_type": {"const": "device.desired_state.accepted"}}},
"then": {"properties": {"data": {"$ref": "#/$defs/desiredStateData"}}}
},
{
"if": {"properties": {"event_type": {"const": "device.configuration.accepted"}}},
"then": {"properties": {"data": {"$ref": "#/$defs/configurationData"}}}
}
],
"$defs": {
"logicalId": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
},
"desiredState": {"enum": ["disabled", "enabled"]},
"deviceCreatedData": {
"type": "object",
"additionalProperties": false,
"required": ["kind", "area_id", "modality", "capabilities", "desired_state"],
"properties": {
"kind": {"const": "device_created"},
"area_id": {"$ref": "#/$defs/logicalId"},
"modality": {"enum": ["video", "radar", "contact", "button", "wearable", "other"]},
"capabilities": {
"type": "array",
"maxItems": 16,
"uniqueItems": true,
"items": {"enum": ["video_capture", "audio_capture", "spatial_rule", "telemetry"]}
},
"desired_state": {"$ref": "#/$defs/desiredState"}
}
},
"desiredStateData": {
"type": "object",
"additionalProperties": false,
"required": ["kind", "previous_desired_state", "desired_state", "changed"],
"properties": {
"kind": {"const": "desired_state_accepted"},
"previous_desired_state": {"$ref": "#/$defs/desiredState"},
"desired_state": {"$ref": "#/$defs/desiredState"},
"changed": {"type": "boolean"}
}
},
"configurationData": {
"type": "object",
"additionalProperties": false,
"required": ["kind", "changed", "changed_fields", "area_id"],
"properties": {
"kind": {"const": "configuration_accepted"},
"changed": {"type": "boolean"},
"changed_fields": {
"type": "array",
"maxItems": 5,
"uniqueItems": true,
"items": {
"enum": ["name", "area_id", "endpoint_ref", "credential_ref", "profile_token"]
}
},
"area_id": {"$ref": "#/$defs/logicalId"}
}
}
}
}
+3 -3
View File
@@ -20,7 +20,7 @@
- T-006 正式使用 1 台准入实机和 4 个独立合成 publisher 连续观察 `1806.6 s` / 180 次采样,四类恢复均通过,最大与最终 `unconverged` 均为 0;详细证据见 `docs/research/sense-5-stream-integration.md`。
- `docs/raw/01`~`08` 已记录需求、分析、方案、客户场景、事件比对和三系统职责。
- `docs/raw/contracts/event-v0.1.schema.json` 已冻结,并有多份示例与语义说明。
- `docs/contracts/sense-control-v1.openapi.json` 已冻结站点作用域的设备查询、创建、修改、启停与最多 128 项批量操作;配额/Area 只读视图和本地设备审计事件均已冻结并实现数据库基础。HTTP handler、认证、Bell 管理服务和 Outbox relay 尚未实现。
- `docs/contracts/sense-control-v1.openapi.json` 的 7 个站点作用域/operation endpoint 已由 T-011 实现:外部静态 SHA-256 主体注册表、tenant/Site scope、HMAC cursor、ETag、PostgreSQL 24 小时幂等收据和最多 128 项 batch operation 均有代码与隔离集成测试。默认 SQLite 仍只暴露探针;Bell 管理服务、JWT/OIDC 和 Outbox relay 尚未实现。
- harness coding 文档、上下文清单、Gitea Issue/PR 模板和治理脚本已接入。
- Gitea 已初始化 12 个协作标签;`status/waiting` 用于依赖或外部条件未满足的未领取任务,实时可领取状态必须从 Gitea 查询,不在本文复制。
- T-002 已关闭架构影响型问题:首期 S2 民办寄宿学校、客户侧私有部署、ONVIF/RTSP、NVIDIA 主路径、自研 Bell、Web/H5 与客户侧证据存储等边界已批准。
@@ -66,12 +66,12 @@ Sense 默认监听 `127.0.0.1:8080`,提供 `/healthz` 与 `/readyz` 运维探
- 人脸方向已延后至 M5 的 S4 成人园区候选试点;必要性/PIP 影响评估、单独同意与替代方式、合法底库来源和删除流程未完成,阻塞人脸能力上线。
- 短信/语音具体供应商未选;生产前必须选定两条独立投递路径并验证故障切换。
- Python/Savant 的精确版本、目标硬件和 Bell 前端栈尚未冻结;Sense M1 的 Go、SQLite driver、MediaMTX、生成器及生成运行时版本已在 T-003 冻结,PostgreSQL/pgx 版本已在 T-009 冻结。
- 本机现有 PostgreSQL 5432 实例使用 SCRAM 且当前开发进程没有管理员密码;T-009/T-010 不绕过认证,自动验收使用隔离临时集群。向共享/生产实例安装 migration 前仍需管理员私下提供专用数据库、登录角色与备份方案。
- 本机现有 PostgreSQL 5432 实例使用 SCRAM 且当前开发进程没有管理员密码;T-009~T-011 不绕过认证,自动验收使用隔离临时集群。向共享/生产实例安装 migration 前仍需管理员私下提供专用数据库、登录角色、外部 Control API 安全文件与备份方案。
- 代码知识图谱在无业务代码阶段可能为空;工具不可用时使用 `rg` 处理文档与配置。
## 下一步
下一步按 Gitea 流程建立 T-011 Sense Control API v1 实现任务:基于 T-009/T-010 PostgreSQL repository 实现认证 tenant 上下文、7 个设备/operation handler、幂等收据、ETag/cursor 和最多 128 项批量操作;公共 API 不在 SQLite 路径启用。客户授权、借用或租赁条件具备后再执行 T-007 五条独立真实上游现场门禁。T-006 的合成结果不解除 T-007,也不形成容量或生产 SLA 承诺。
下一项建议创建 T-012,补齐 M2 对账安全闸、孤儿检测(只报告/受控处置)与多实例可观测性,再进入 WireGuard 和 16 路批量开通基准;不要把 Control API 完成误报为 M2 容量出口。客户授权、借用或租赁条件具备后再执行 T-007 五条独立真实上游现场门禁。T-006 的合成结果不解除 T-007,也不形成容量或生产 SLA 承诺。
## 已知风险
+10 -1
View File
@@ -3,7 +3,7 @@ id: T-011
title: 实现 Sense Control API v1 与 PostgreSQL 一致性边界
phase: 2
deps: [T-010]
status: DOING
status: DONE
created: 2026-08-07
issue: 39
context_ref: 6402d4384d5c2b1c0f3852858c3cf0d63d948262
@@ -96,6 +96,15 @@ T-008 已冻结 Sense Control API v1 的 7 个 endpoint,T-009/T-010 已提供
## 执行记录
### 2026-08-07 完成 Sense Control API v1
- 使用冻结的 `oapi-codegen v2.8.0` 从 T-008 OpenAPI 生成 Go 1.22+ `net/http` server glue(生成 SHA-256 `39a52e4f54bb1a742f58b64dcf15ce98359385236da5ccc0dae77e8ded2b218b`),实现全部 7 个 endpoint、严格 JSON/1 MiB body、稳定 Problem、write-only 字段脱敏和 `Cache-Control: no-store`;生成漂移已进入 `init.ps1`/`init.sh`。
- 新增可替换认证 port 与 `static-sha256` 私有部署适配器:外部注册表只保存 token 摘要、主体、tenant、Site scope 与两项权限,摘要 constant-time 比较;业务路由默认关闭,只能在 PostgreSQL v4 schema 与外部 32 字节 HMAC cursor key 有效时开启。SQLite 默认路径继续只暴露探针。
- 新增 `008`/`009` migration:设备 `resource_version`/write-only profile token、24 小时摘要幂等收据、持久化 batch operation/逐项结果与最小权限。创建收据与设备/审计同事务;batch 以 savepoint 隔离逐项失败,并先按设备 ID 排序锁定目标,避免相反请求顺序死锁。ETag 只在配置/期望态实际变化时前进;相同期望态仍审计但不增加 generation/resource version。
- 保留严格审计 v1 文件不变,新增 v2 后继和 `device.configuration.accepted` 脱敏事实;Area 修改重新准入。停用调和只对台账中的精确 path 做幂等删除,成功后 observed generation 收敛且 actual state 为 offline,不枚举或清理未知 path。
- `./scripts/test_postgres.ps1 -PgRoot D:\pgsql17` 通过:`001`~`009` 连续重放、SQL 权限断言和 25 个 `TestPostgres*` 全绿,覆盖列表稳定分页/过滤、创建并发幂等、收据脱敏/冲突、ETag/PATCH、审计 v2、逐项 batch、operation tenant 隐藏、相反顺序批量锁与 PUBLIC 权限负例;随机回环临时集群已停止并清理,现有 `D:\pgsql17\data`/5432 listener 未读取、停止或修改。
- `./init.ps1` 通过;Python 契约/治理测试共 47 项通过;`go -C Sense test ./...`、`go -C Sense vet ./...`、`go -C Sense build ./...`、生成漂移和 `git diff --check` 均通过;`go test -race ./internal/auth ./internal/controlapi ./internal/reconcile ./internal/store` 通过。不需要摄像头或 UI,本结果不解除 T-007,也不形成 16/128 路容量承诺。
### 2026-08-07 领取任务
- dispatcher `ila` 将 Issue #39 分配给 `codex`;`context_ref` 为 `6402d4384d5c2b1c0f3852858c3cf0d63d948262`,claim 为 `claims/T-011`,工作分支为 `agent/codex/T-011`。