Files
railwaysystem/docs/iot/ROUND5V4_SOFTWARE_QA.md
T

187 lines
15 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.
# Round 5V-4 — Kingbase 隔离恢复、005 迁移与软件融合 QA
执行日期:2026-10-14。工作树:`boot4-iot-fusion-archive`;分支:`fix/iot-safety-hardening`。
本轮基线:`ba5dc7a6af9e6bb6b5166ef04d49af621c4f8de2`。
GitLab 已归档融合基线仍为 `feat/boot4-iot-fusion@37392144`;本轮没有 Push、Merge 或共享部署。
后续状态说明(2026-10-15):以下网络阻塞是本轮当时的真实状态,不覆盖后来已完成的恢复。
Round 5V-5 已通过跳板复核共享服务并通过新后端最小冒烟;Round 5V-6 已定位两条旧授权同步时间的
后续变化。当前功能通过、最终签署待运行隔离收口、硬件未验收的分项结论见
[Round 5V-6](ROUND5V6_FINAL_SIGNOFF.md)。本文件保留历史证据,不倒改当时结果。
**收尾状态(18:27之后):BLOCKED_NETWORK,不声明当前 SOFTWARE_QA_READY=YES。**
下列迁移、11项真实Kingbase测试、15路由及浏览器业务闭环在17:35前已实际通过并保留证据。
之后数据库连接中断(后端首条记录17:50:55,SQLSTATE08001;后续EOF),18:27独立TCP探测
192.168.139.218:22和:4321均超时。无法仅凭本机证据区分服务器离线、链路或路由原因,
未修改Mac/服务器网络、代理、服务或数据库配置。已停止本轮本机QA前端/后端/Redis,
不把端口仍监听当成数据库可用。恢复合法连接后只需重新预检、启动与关键读验收,
**005已经成功提交,不要因为断网而重复初始化、覆盖恢复或重做迁移。**
## 1. 授权与实际边界
本轮用户另行批准在 192.168.139.218 新建离线、资源受限 V9 临时恢复容器及恢复库;
只有原生备份恢复、005 演练及失败恢复通过,才能迁移独立 QA 库。
所有 Kingbase 业务写入均限定 `railwaysystem_fusion_qa_20261013`,或本轮新隔离容器中的专用恢复库。
未修改共享 `training`、独立 `iotlocks` 等数据库;目标 QA 内的 `iotlocks` 是 Schema,不是另一个数据库。
未扩大业务账号权限、修改系统网络、控制 MQTT/人脸/门锁设备、重启共享服务。
## 2. 镜像、许可、资源和共享服务
服务器只读确认:root UID0,hostname `localhost.localdomain`,NFSChina Server 4.0,
128 CPU、512 GiB 内存、可用约 372000 MiB,磁盘剩余约 535 GiB,负载低。
现有 `kingbase` 容器 `dcd88030ca5a`,4321→54321,版本 `KingbaseES V009R003C018`;
原挂载 `/opt/kingbase-docker/data` 未修改或复用。原生工具目录 `/home/kingbase/install/kingbase/bin/`。
仅复用已存在镜像 `kingbase_v009r003c018b0003_single_x86:v1`:
`sha256:540fa4d0c8f365c8d363a801404e93f8401c7bc5035ecd7b621f0dba862f2515`。
宿主机已有导入 tar 的 manifest/config 散列与 Docker image ID 相符;无 RepoDigest,
未拉取新镜像,不声称额外验证了供应商签名或生产供应链来源。
从镜像原始层读取并用原生许可工具检查:V009 企业版试用授权,180天,容器名/MAC不绑定,
未见 vCPU 限额;未改写许可、复制生产凭据或连接许可服务器。新服务实际通过原生启动许可校验。
这只证明现有获准 QA/试用范围可启动,不代表长期或生产部署许可。
参考:[Kingbase Docker 安装与许可检查](https://bbs.kingbase.com.cn/kingbase-html/v9/install-updata/install-docker/install-docker-1.html)。
新容器 `railwaysystem-qa-restore-round5v4`:
`c11ca10490c242651c0e87c2778102cd9de32cd703b48b57c26801686d4ef41f`。
实际运行过;Docker inspect 与 cgroup 实测确认 network=none、只有 lo、路由为空、
PortBindings={}、2 CPU、2 GiB memory+swap总额、pids=256、privileged=false、drop NET_RAW,
没有 Docker Socket 或正式数据卷。唯一新数据挂载:
`/opt/railwaysystem-qa-restore-round5v4/data` → `/home/kingbase/userdata`。
创建前检查 realpath、符号链接、名称和挂载冲突;专用随机凭据仅在 root0700 目录中的0600文件。
存储不是 5 GiB 硬配额。按用户允许的替代条件,独立监护进程每2秒统计任务目录、overlay及日志,
达到4 GiB或宿主机空闲低于100 GiB即核验容器身份后停止;日志有轮转上限。
实际观测用量约219 MB,远低于阈值;没有 OOM。监护实现:`scripts/qa/round5v4_storage_guard.py`。
共享 Kingbase/GitLab 的容器 ID 和启动时间一直未变(均为2026-10-06),GitLab healthy,其他服务持续运行。
本轮恢复完成后仅停止上述新容器;不删除其数据、恢复证据或备份。
首次Docker stop因镜像入口未响应而超时退出137(非OOM);仅重启该新实例后,
实际复核恢复库和原备份恢复库全量清单仍一致,再用原生sys_ctl fast正常停库(exit0),
sys_controldata确认cluster state=shut down,最后停止容器入口。没有重启共享实例。
## 3. 原生备份与实际恢复(不是文件读取替代)
备份源:`railwaysystem_fusion_qa_20261013`;原生 V9 `sys_dump` 自定义归档,
此前同一导出快照的63表清单/指纹,与本轮迁移前源库及新恢复库再次逐项匹配。
远端:`/opt/railway-fusion-qa-backup-20261014.YLjmJ0/fusion-qa-pre005-v2.dump`;
本机:`/Users/wzb/railway-fusion-qa-backup-20261014.6cgPn7/fusion-qa-pre005-v2.dump`。
380907字节,SHA256:`caa62bc985bd433b5d428b36e34d684b557c82576b69e5e5d9d348edfdf316b4`。
两份均在 Git 外受保护目录,原备份未改写、未删除。
在新实例创建 `railwaysystem_fusion_restore_round5v4`,用匹配版本 `sys_restore -O -x -1 -e`
实际恢复成功,退出0,stderr为空。Owner 映射到仅在新实例存在的 `round5v4_admin`,
不恢复源库认证配置/ACL;此为明确的恢复映射,而非遗漏生产认证。
实测恢复对象:public54表 + iotlocks9表;所有63表行数及排序行指纹一致;
892列、146索引、113约束、39序列、20扩展及Schema/默认值/触发器清单完成对账。
旧授权10条、旧指令15条,培训学员47、参训57、住宿34条。
唯一 native dump/reparse 语法差异是 `chk_external_operation_status` 的数组/元素 text cast:
只对这一个精确约束做规范化,另用原生SQL对10个允许值、4个非法值及NULL共15例验证语义无差异。
其他元数据不宽泛忽略。恢复后基本只读查询通过。
清单生成器:`scripts/qa/kingbase_manifest.sql`;受保护证据包含原生清单和JSON摘要。
## 4. 005 的隔离演练、回滚与源 QA 执行
005 SHA256:`90648b6ac67470f9a14f0795c4479dfb4811d4907e41a13ee5eeada16582b87f`。
审计完整20条语句:16项新增列、4项新增索引(含唯一意图索引);无DROP/TRUNCATE/DELETE/覆写业务数据。
隔离 V9 实际通过:
| 场景 | 实际结果 |
|---|---|
| 迁移中故意调用不存在函数 | SQLSTATE42883;全量DDL回滚,原结构和数据指纹一致 |
| 客户端在未提交005后断开 | 服务器自动回滚;结构/指纹一致 |
| 另一连接持读锁,DDL等锁500ms | SQLSTATE55P03;安全回滚,未破坏数据 |
| 005正常COMMIT | 16列/4索引、默认值、旧记录隔离均正确 |
| 同一005重复执行 | 全量结构/数据清单不变 |
| 重复意图键 | 原生唯一约束23505,事务回滚 |
| 从原备份进行失败恢复 | 在同一新容器内另建专用 recovery 库并实际恢复,完整清单与迁移前一致 |
上述为真实数据库的事务、连接中断及恢复验证;另有收尾时仅临时实例非优雅停止后的重启完整性复核,
不是对共享/源QA数据库服务器断电作测试,也不是完整灾难恢复/长期故障注入认证。
没有在源QA库上删除列/表或全库覆盖演练。
之后重新核验源数据库名/Schema、原备份SHA、63表清单均未变化、其他源库连接数0;
使用已有管理角色,不提权业务账号。设置 lock_timeout=3s、statement_timeout=30s,
显式事务及两表ACCESS EXCLUSIVE锁,在锁内再次核对原行指纹,执行相同005并COMMIT。
源 QA 的后验清单与隔离迁移后清单完全对应。旧10授权/15命令为 LEGACY/QUARANTINED、
version0、无来源环境/意图key,未转换为REAL。业务验收后17:23保存的过滤LEGACY核验摘要报告其完整原记录指纹仍一致。
该结论仅对应当时核验点;Round 5V-5之后观察到的两条sync_time变化及其旧实验写入来源,
见Round 5V-6追补,不将历史核验外推为永久不变。
一次性执行/核验代码:`scripts/qa/round5v4_database_stage.py`。不要对已在使用的QA库重跑该一次性编排。
`fusion_qa_app` 真实连接成功,现有SELECT/INSERT/UPDATE及序列权限足够全部业务测试;
无superuser/createdb/createrole、无schema CREATE。既有 sys_menu/sys_notice_read/sys_role_menu
三表仍有TRUNCATE/TRIGGER/REFERENCES旧授权:本轮未使用、未扩大,也未擅自收回,建议管理员另行最小化。
## 5. 真实 Kingbase Service / Mapper / 事务与故障恢复
`Round5v4KingbaseIntegrationTest`:11项真实Kingbase测试,使用生产XML、Service、
DataSourceTransactionManager及真实AOP事务代理;账号固定 fusion_qa_app;URL强校验仅允许目标QA库。
外部仅替换 MQTT 传输,未加载真实MQTT或人脸HTTP客户端。恢复扫描前拒绝无关READY工作。
合成 R5V4 数据保留审计,不删除原数据,不重置序列;用例后仅关闭自己的未尝试任务。
覆盖:入住、调宿撤旧建新、退宿意图;意图提交/命令创建前、命令创建/发送前、
DISPATCHING占用提交/传输结果未知三种独立JVM `Runtime.halt`,再创建新Service读取持久化状态恢复;
UNKNOWN转MANUAL_REVIEW且零盲目重发;未尝试的FAIL撤权可补偿;4线程原生行锁仅发送一次;
唯一意图冲突;入住和退宿故障注入时住宿状态与意图同事务回滚;旧撤权ACK不覆盖新授权;MOCK到REAL边界隔离。
数据库提交、Mock发送、双Mock回执均分别断言;不等于设备最终执行。
真实测试发现并修复此前未暴露的事务边界缺陷:桥接 AFTER_COMMIT 调用 REQUIRED 时仍可能
加入已提交但尚未清理的事务,命令滞留READY。现在桥接回调通过 `LockExecutionTransactions.committed`
明确在 REQUIRES_NEW 中生成命令,再由它自己的提交回调占用/发送;业务原子性仍留在原事务内。
修改位于 `TrainIotLockAuthBridgeServiceImpl.dispatchPushSafe/dispatchClearSafe`。
另通过85项选定后端回归、新增1项Boot4缺路由处理回归、12项QA工具测试及前端生产构建,
不把这些替代真实数据库结论。
## 6. 实际后端与 Chrome 验收
当前归档工程新进程,Java21.0.2 / Boot4.1.0,127.0.0.1:18096;生产前端127.0.0.1:18088;
独立Redis127.0.0.1:16389,口令随机、无持久化。不复用实验PID51901/8096或其他工程PID53305/8080。
运行JAR有SHA绑定私有副本;停机核验账本/PID出生时间/命令/cwd并等待退出,无粗暴清端口。
有效参数强制:mqtt.enabled=false、mock=true、real-device-write-enabled=false、whitelist空、
protocol-verified=false、retry-task-enabled=false、QA/OpenAPI关闭、人脸HTTP关闭且Mock、DMS关闭、Quartz不自动运行。
数据库用户名/URL固定QA,秘密只从本机0600配置及私有随机运行配置注入。
Kingbase/Druid实际探针发现URL中的socketTimeout=15被池解析为15ms;启动器移除URL超时并明确池60000ms,
同一探针实际验证60000ms。参考 [Druid 1.2.28 原始实现](https://github.com/alibaba/druid/blob/1.2.28/core/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java)。
首页Kingbase分析SQL的 `::numeric` 改为等价标准CAST,消除Druid统计SQL解析异常;没有关闭SQL安全检查。
负向运行检查还发现被禁用的MQTT/QA端点会被旧全局处理器误报成HTTP200/业务500;
新增对Boot4 NoResourceFoundException的脱敏404处理,并以单元及真实HTTP复验,不注册或开放控制接口。
真实 Google Chrome155.0.8059.40(headed)管理员登录成功,getInfo/getRouters=200;
现有QA验证码配置返回 captchaEnabled=false,未改开关,不声称完成启用状态验证码挑战。
15路由逐页通过组件名、实际表格/图表、HTTP/业务code、JS错误检查:
首页Index/AdminDashboard四张真实ECharts、学员Student、教师Teacher、开班Plan、宿舍Dormitory、动态菜单住宿Accommodation,
以及9个IoT组件Group/Gateway/Device/Face/Auth/AccessLog/Command/MqttLog/ServiceConfig。
最后一轮浏览器请求仅出现127.0.0.1:18088,无外部主机;浏览器设有外发拒绝保护,未发生外部请求阻断事件。
品牌/Logo/侧边栏/动态菜单保留,无404/登录替身页;17:35前最终验收期间后端无SQL或未捕获异常。
后续网络连接异常见本报告顶部,不能将该时点的成功外推为当前在线状态。
浏览器合成 fixture `R5V4463c944c9547465b`,学号后缀S、人员P5463c94:
预分配2043 → 真UI入住 → Mock grant确认 → 真UI调房到B/新住宿2044 → 旧权revoke+新权grant确认
→ 真UI退宿 → revoke确认;两个授权1035/1036最终REVOKE版本2、CONFIRMED、sync4;
四条0011/0012命令均MOCK、CONFIRMED、网关/设备双ACK,住宿两条已退宿;UI与数据库再次一致核对。
离线回执驱动只接受该fixture的当前MOCK命令,危险HTTP回执入口未启用。
住宿履历和指令流水在真实Chrome中查看,不是仅调用API或替身页面。
前端旧页面引用模型不存在的checkInTime/checkOutTime,已改为真实assignedTime/updateTime,
标签为“分配时间/最近状态变更”;无额外DDL,不将updateTime冒充精确入住/退宿专用时间戳。
原生备份、数据库/浏览器运行日志和截图仅保存在受保护Git外/忽略目录,不提交个人资料。
## 7. 证据位置、复现与剩余边界
- 远端专用根:`/opt/railwaysystem-qa-restore-round5v4/`,含原生恢复输出、结构/行指纹、
isolated-results.json、source-migration-results.json、container-safety.json、historical-preservation.json、空间监护日志。
- 本机受保护忽略目录 `.qa-runtime/round5v4/`:同名JSON、真实Kingbase JUnit/子JVM日志、
后端/前端构建、浏览器15页结果和闭环数据验证;JUnit XML在ruoyi-train/target/surefire-reports。
- `output/playwright/`:最终首页、IoT九页(敏感数据行遮罩)、合成住宿履历/退宿/授权/指令证据;均不入Git。
- 具体构建、隔离启停、Kingbase选定测试及浏览器夹具流程见根 `DEMO_RUNBOOK.md`。
软件功能QA已通过,但当前可运行就绪状态受上述网络问题阻塞,更不代表生产发布或真实硬件验收。
仍须老师明确批准单台测试、确认真实协议校验字段/回执语义、
提供现场设备与单台白名单、核对UNKNOWN人工处置流程;门禁保持关闭。
Vue2/CLI4废弃依赖、旧历史素材/外部凭据轮换、既有账号过宽权限及长期商业许可仍须单独治理。
本轮没有远程CI/部署验证,没有数据库服务器断电测试,没有真实IoT执行证据。