Files
railwaysystem/docs/iot/ROUND5V4_SOFTWARE_QA.md
T

15 KiB
Raw Blame History

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。本文件保留历史证据,不倒改当时结果。

收尾状态(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 安装与许可检查。

新容器 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 原始实现。 首页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执行证据。