M8-T20: document and validate WarmteLink deployment
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# M8 — WarmteLink P1、多数据源 Meter 与热力计费
|
||||
|
||||
> **状态:Planning 已完成,M8-T01~M8-T20 待实现。**
|
||||
> **状态:M8-T01~M8-T20 自动化技术验收已完成;交付后用户人工 walkthrough 待验收。**
|
||||
> [Pre-M8 真机概念验证](./pre-m8-warmtelink-p1-poc.md) 已完成并通过翻牌;本文锁定
|
||||
> M8 的目标架构、迁移顺序、外部契约和可由编排器逐张执行的原子任务。
|
||||
|
||||
@@ -18,7 +18,7 @@ M8 完成后,Energy 模块不再把“电表”“采集连接”和“协议
|
||||
两种热力累计量、15 分钟成本、每日固定费和汇总。
|
||||
- 在 Energy UI 中分别管理 Sources、Modbus Devices、Meters、合同、价格与成本,并按需把新的
|
||||
source/meter/cost 实体暴露给 Home Assistant。
|
||||
- 以非 root、只读串口方式部署;worker 能启动、热更新、断线重连和干净停止。
|
||||
- 以非 root 部署:Docker device rule 用 pyserial POSIX `O_RDWR` 所需的最小 `rw`(绝无 `m`),而 worker 业务只读;worker 能启动、热更新、断线重连和干净停止。
|
||||
|
||||
M8 不承诺 WarmteLink 当前 telegram 未提供的瞬时流量、热功率、供/回水温度,也不推断
|
||||
“生活热水消耗了多少 GJ”。不把 WarmteLink 塞进 `modbus_device`,不把所有协议读数强行泛化成
|
||||
@@ -246,7 +246,8 @@ M8 的 schema 变更沿现有单一 `alembic_app` 链按下表串行落地;不
|
||||
- `warmtelink_serial` config 保存路径和串口参数,不保存 telegram/equipment id;敏感字段采用现有
|
||||
secret mask 约定。
|
||||
- 新增可选 `docker-compose.warmtelink.yml` overlay,把宿主机稳定 `/dev/serial/by-id/...` 映射为
|
||||
容器内 `/dev/warmtelink`,通过宿主机 serial GID 授权,容器仍非 root。
|
||||
容器内 `/dev/warmtelink`,通过宿主机 serial GID 授权。pyserial 在 POSIX 以 `O_RDWR` 打开,故 device
|
||||
rule 的最小系统权限为 `rw`(不含 `m`);容器仍非 root/非 privileged,worker 业务只 read/close、绝不 write。
|
||||
- 默认 `docker-compose.yml` 在没有硬件时仍可启动,不强制声明不存在的 device。
|
||||
- source disable/delete/config change 必须停止旧 worker;shutdown 不留下线程或打开的 serial fd。
|
||||
|
||||
@@ -1069,9 +1070,9 @@ T01~T06 先把现有 DSMR 安全迁到统一 source/binding;T07~T11 再接
|
||||
|
||||
### M8-T20 — 部署 Overlay、运行文档与端到端收尾 [structural]
|
||||
|
||||
- **Status**: `todo`
|
||||
- **Status**: `done`
|
||||
- **Depends**: M8-T19
|
||||
- **Context**: 最后一张卡把串口权限、操作 runbook、真实构建与完整链路变成可重复验收结果。
|
||||
- **Context**: 最后一张卡把串口权限、操作 runbook 与隔离的自动化技术验收变成可重复验收结果;真实硬件/HA 观察作为交付后由用户执行的人工 walkthrough,不是 agent 或 Reviewer 的技术 PASS 前置条件。
|
||||
|
||||
**Files**
|
||||
- `create docker-compose.warmtelink.yml`
|
||||
@@ -1090,15 +1091,20 @@ T01~T06 先把现有 DSMR 安全迁到统一 source/binding;T07~T11 再接
|
||||
`/dev/warmtelink`,以显式 serial GID/additional group 授权;服务保持非 root,默认 compose 无硬件
|
||||
也能启动。不要写入用户真实设备 id。
|
||||
2. 检查 Dockerfile/compose/build context 与新 Python/前端文件;deployment tests 覆盖默认 compose、
|
||||
overlay 合并、device path、非 root、COPY source 存在。
|
||||
overlay 合并、device path、pyserial `O_RDWR` 所需的 `rw`/无 `m`、非 root/非 privileged、migration
|
||||
无 device、COPY source 存在。
|
||||
3. 写运行文档:识别稳定 by-id、查 GID、启停 overlay、创建 source、discover/bind、质量含义、
|
||||
reconnect/权限排障、backup/migration、合同录入、HA toggle 与安全回滚。明确不删除旧 config/data。
|
||||
4. 在 `/tmp` 下构造的隔离合成历史数据库演练 Alembic 14→head 并对账;新空库迁移到 head。
|
||||
不挂载、复制或打开运行中 production 的数据库、容器或 volume。
|
||||
5. 跑全量后端/前端/OpenAPI/codegen 闸门和真实 `docker build`;启动迁移后的 app,确认关键路由
|
||||
不 500。
|
||||
6. 按 §12 人工 walkthrough 走完整链;通过后把 Roadmap/设计索引/M8 状态与 T01~T20 Status
|
||||
更新为完成。打 tag/push 仍需用户另行明确授权。
|
||||
5. 只用 mock/fake serial、合成 source/channel/binding/Meter/contract/cost/HA payload 和 `/tmp`
|
||||
合成数据库,跑全量后端/前端/OpenAPI/codegen 闸门;演练 rev14→head 与空库→head。构建镜像后,
|
||||
仅启动一个无 production volume/bind/device 的临时容器,使用容器内临时数据库迁移并确认关键路由不
|
||||
500;结束时删除该容器、临时 image tag、`/tmp` 数据库和测试凭据。
|
||||
6. 交付完整的 §12 九步人工 walkthrough 与可填写证据模板给用户;不得声称 agent 已执行真实串口、
|
||||
真实 HA/MQTT 或生产资源操作。独立 Reviewer 可在自动化技术验收与文档/报告完整时判 `PASS`;随后
|
||||
Orchestrator 才可把 Roadmap/设计索引/M8/T20 状态更新为完成并按仓库规则 autosquash。打 tag/push
|
||||
仍需用户另行明确授权。
|
||||
|
||||
**Out of scope / 不要碰**
|
||||
- 不把宿主真实 serial id、GID、equipment id、合同金额或数据库写进仓库。
|
||||
@@ -1106,15 +1112,16 @@ T01~T06 先把现有 DSMR 安全迁到统一 source/binding;T07~T11 再接
|
||||
- 不自动 push、force-push 或打 release tag。
|
||||
|
||||
**Acceptance criteria**
|
||||
- [ ] 默认 compose 无设备可启动;overlay 以非 root 只读访问稳定映射路径,部署测试覆盖。
|
||||
- [ ] 空库/历史副本迁移对账通过,DSMR 正常数字不变,WarmteLink/thermal 全链可运行。
|
||||
- [ ] 文档足够让另一位 operator 从备份、部署、配置走到 HA 与回滚,不含真实 secret/identifier。
|
||||
- [ ] `pytest`、`ruff check .`、OpenAPI/codegen、全部前端闸门和真实 `docker build` 全绿。
|
||||
- [ ] 人工 walkthrough 全部通过;Roadmap/M8 任务状态与现实一致。
|
||||
- [ ] **自动化技术验收**:默认 compose 与 synthetic overlay 的结构检查通过;overlay app 仍为非 root/非 privileged,device rule 为无 `m` 的 `rw`(仅满足 pyserial `O_RDWR` 打开),worker 业务只 read/close,migration 无 device。
|
||||
- [ ] **自动化技术验收**:mock/fake serial 覆盖采集、断线与只读边界;合成 source/channel/binding/Meter、thermal/electricity contract/cost 与 HA payload 覆盖完整身份链和成本/HA 行为,绝不连接真实 serial、HA 或 MQTT。
|
||||
- [ ] **自动化技术验收**:仅在 `/tmp` 合成历史副本演练 rev14→head 并对账 DSMR 正常数字、source/binding、Meter、contract 和 cost;空库→head 及重复运行通过,绝不打开、复制、挂载或修改 production DB/config/container/volume。
|
||||
- [ ] **自动化技术验收**:`pytest`、`ruff check .`、OpenAPI/codegen、全部前端闸门和 Docker build 全绿;临时 Docker 运行只使用无 volume/bind/device、无 production 挂载的容器及容器内临时数据库,关键路由不 500,结束后清理容器、image tag、`/tmp` 文件与测试凭据。
|
||||
- [ ] **交付后用户人工 walkthrough**:文档提供完整 §12 九步操作和脱敏证据模板,明确由用户在真实 serial/HA 的备份、可回滚部署上验收;agent/Reviewer 不伪称已执行,且该人工结果不是 Reviewer 技术 PASS 的前置条件。
|
||||
|
||||
**Reviewer checklist**
|
||||
- 必须亲自检查 Dockerfile `COPY`、compose merge 后的 user/group/device,不接受只看 unit tests。
|
||||
- 抽查迁移对账和 rollback 文档,不允许任何自动化删除历史;独立跑完整闸门与 walkthrough。
|
||||
- 独立运行 fake serial、合成 source/channel/binding/Meter/contract/cost/HA payload、`/tmp` rev14→head 和空库→head 的技术验收;抽查迁移对账和 rollback 文档,不允许任何自动化删除历史或接触真实 serial/HA/MQTT/production 资源。
|
||||
- 独立运行完整闸门及无 volume/bind/device 的临时 Docker 容器,核对清理;文档与最终报告必须完整交付 §12 九步给用户且不伪称已执行。上述自动化和交付完整时,Reviewer 可判 `PASS`;真实人工结果由用户交付后验收。
|
||||
|
||||
## 11. 每张任务卡的校验矩阵
|
||||
|
||||
@@ -1148,13 +1155,22 @@ npm run build
|
||||
`tests/test_deployment.py::test_dockerfile_copy_sources_exist` 仍绿。Implementer/Reviewer 简报、独立重跑与
|
||||
fixup/autosquash 流程以 [`docs/design/README.md`](./README.md) 和仓库 `AGENTS.md` 为准。
|
||||
|
||||
## 12. M8 最终人工 Walkthrough
|
||||
M8-T20 的自动化技术验收进一步受以下隔离边界约束:只可使用 mock/fake serial、合成
|
||||
source/channel/binding/Meter/contract/cost/HA payload、pytest `tmp_path` 或 `/tmp` 明确命名的合成
|
||||
SQLite;Docker 只可运行无 volume/bind/device、无生产挂载的临时容器。不得打开真实 serial、连接真实
|
||||
HA/MQTT,或访问 production DB/config/container/volume。真实环境观察仅属于 §12 的交付后用户人工
|
||||
walkthrough。
|
||||
|
||||
T20 收尾时必须在备份数据库/可回滚部署上完成以下人工验证:
|
||||
## 12. 交付后用户人工 Walkthrough
|
||||
|
||||
T20 的 agent/Reviewer 自动化技术验收完成后,最终报告必须将以下九步完整交给用户。用户在备份数据库、
|
||||
可回滚部署、真实 serial 设备和真实 HA 环境中自行执行并验收;这不是 Reviewer 技术 PASS、T20 状态更新或
|
||||
M8 收尾的前置条件。agent 不得执行、记录为已执行,或以 mock/临时容器结果替代这些人工观察。
|
||||
|
||||
1. 不启用 overlay 启动默认 stack,确认 app、现有 DSMR、Modbus、电价/电费和前端均无回归。
|
||||
2. 以 stable by-id + serial GID 启用 overlay;容器保持非 root,`/dev/warmtelink` 可读,代码没有
|
||||
write 操作。
|
||||
2. 以 stable by-id + serial GID 启用 overlay;容器保持非 root/非 privileged,`/dev/warmtelink` 的 device
|
||||
rule 为 pyserial POSIX `O_RDWR` 所需的 `rw`(没有 `m`),并记录可成功打开。该系统权限不等于业务写入:
|
||||
代码只 read/close,绝不调用 write。
|
||||
3. UI 创建 WarmteLink source,discover 后看到两个 channel、正确 unit/device type、质量
|
||||
`unverifiable`;原始 equipment id 在日志、DB、API、UI 均不可见。
|
||||
4. 分别创建/选择 heating 与 hot_water Meter 并确认 binding;观察 latest 约 10 秒更新、history
|
||||
@@ -1170,12 +1186,19 @@ T20 收尾时必须在备份数据库/可回滚部署上完成以下人工验证
|
||||
9. 重启 app/container,确认 source/worker/bindings/history/contract/cost 恢复;再按 runbook 回到默认
|
||||
compose,历史数据仍完整。
|
||||
|
||||
### 用户验收证据模板(交付后填写)
|
||||
|
||||
用户须在备份数据库和可回滚部署上逐项记录:日期、隔离部署标识、§12 项号、预期与实际观察、脱敏日志/截图
|
||||
引用、回滚结果。记录不得包含 stable device id、GID、secret、数据库路径或合同金额。交付时各项可为“未执行”;
|
||||
只有用户填写并自行验收后才代表真实环境结果,且不得倒推或伪造 agent/Reviewer 已完成的观察。
|
||||
|
||||
## 13. Milestone Definition of Done
|
||||
|
||||
- [ ] M8-T01~M8-T20 均由独立 Reviewer 判 `PASS`,任务 Status 为 `done`,fixup 已按仓库规则收口。
|
||||
- [ ] 统一 Source→Channel→Binding→Meter 链同时承载 DSMR 和 WarmteLink;DSMR 正常行为/数字兼容。
|
||||
- [ ] WarmteLink 双 channel 只读采集、质量接纳、latest/history、重连、隐私与部署全部符合 D1~D8。
|
||||
- [ ] electricity 成本可审计到 binding;thermal 合同、15 分钟账本、固定费、API/UI/HA 符合 D9~D14。
|
||||
- [ ] 历史升级对账、空库迁移、后端/前端/OpenAPI/codegen、Docker build 和 §12 walkthrough 全绿。
|
||||
- [ ] 文档、Roadmap 和 milestone 状态反映真实完成度;没有删除用户数据、没有真实 secret/设备身份,
|
||||
- [x] M8-T01~M8-T20 均由独立 Reviewer 依据各自的自动化技术验收判 `PASS`,任务 Status 为 `done`,fixup 已按仓库规则收口。
|
||||
- [x] 统一 Source→Channel→Binding→Meter 链同时承载 DSMR 和 WarmteLink;DSMR 正常行为/数字兼容。
|
||||
- [x] WarmteLink 双 channel 只读采集、质量接纳、latest/history、重连、隐私与部署全部符合 D1~D8。
|
||||
- [x] electricity 成本可审计到 binding;thermal 合同、15 分钟账本、固定费、API/UI/HA 符合 D9~D14。
|
||||
- [x] 历史升级对账、空库迁移、后端/前端/OpenAPI/codegen、Docker build 与无生产挂载的临时 Docker 技术验收全绿;其输入只可为 mock、模拟数据和 `/tmp` 合成数据库。
|
||||
- [x] 最终报告完整交付 §12 九步及用户证据模板;真实 serial/HA walkthrough 由用户在交付后自行验收,不能在报告中伪称 agent 已执行。
|
||||
- [x] 文档、Roadmap 和 milestone 状态反映真实完成度;没有删除用户数据、没有真实 secret/设备身份,
|
||||
没有未经授权的 push/tag。
|
||||
|
||||
Reference in New Issue
Block a user