15 KiB
SYFJGYD 学员管理系统 — Java 21 / Spring Boot 4 隔离 QA 运行手册
本手册仅对应 boot4-iot-fusion-archive 的 fix/iot-safety-hardening 本地候选版本。
原 RailwaySystem 和历史实验工程只读;不执行 Push、Merge、共享部署或硬件操作。
当前验收边界
当前分项结论(2026-10-15,Round 5V-7),三项必须分开:
SOFTWARE_FUNCTIONAL_QA_PASSED=YES;Round 5V-6的SOFTWARE_FINAL_SIGNOFF=PENDING_OPERATING_ISOLATION已在
Round 5V-7完成受管QA运行/退出路径验证,现为PASS_MANAGED_QA_SCOPE;
REAL_HARDWARE_VERIFIED=NO。
Round 5V-5 已经通过 Tailscale 跳板恢复访问,并对新融合后端完成登录、培训页、IoT页和既有Mock状态冒烟。
此前的断网不是撤销已通过的功能验收。两条旧授权的同步时间现已定位到旧实验进程的补偿写入,
不是新融合后端的正常Mock回执,也不能再标成“原因未知”。
完整时间线和脱敏归因见Round 5V-6;
实际隔离、观察窗口、故障退出和签署范围见Round 5V-7。
Round 5V-4 已在获准的新建离线 Kingbase V9 容器中实际恢复原生备份,完成
005 的提交、重复执行、异常/断连/锁超时回滚及原备份恢复演练,然后才对
railwaysystem_fusion_qa_20261013 执行 16 列 / 4 索引增量迁移。
11 项真实 Kingbase Service/Mapper/事务测试(含独立测试 JVM 强制中断)已通过。
当前 QA 后端、15 个 Chrome 路由与合成学员入住/调宿/退宿的 Mock 双回执闭环已实际验收。
详见 本轮软件验收记录。
Round 5V-4 收尾18:27实测服务器22/4321均超时,后端出现08001/EOF;当时状态为
BLOCKED_NETWORK,不是软件功能失败或迁移未执行。Round 5V-5 已恢复合法链路并完成最小冒烟,
且已停止该轮本机QA三进程和临时隧道。不要重做005、覆盖恢复或修改系统路由。
不能将 H2/替身测试、构建成功或登录页显示称为
Kingbase 事务/浏览器业务闭环验收。真实硬件验收始终未进行。
迁移前置、失败回滚和核验清单见 迁移计划。
不要执行 qa-bootstrap 全量初始化、清空测试数据、重建库、重置已有账号或序列。
1. 构建前提
- Java 21(本机验证 21.0.2)、Maven 3.9.x;全部模块统一 release 21。
- Node 22.23.2、npm 10.9.8(
build_ui/.nvmrc/ packageManager / lockfile)。 - Python 3.9+、本机
redis-server(新实例只监听 loopback 的独立端口)。 - 合法取得当前商业 JDBC 9.0.0;不向 Git 或公共 Maven 上传二进制。
从本工作树根目录执行(路径以实际 checkout 为准,不引用 RuoYi-Vue-master):
java -version
mvn -version
export KINGBASE_JDBC_JAR='/absolute/path/to/authorized/kingbase8-9.0.0.jar'
bash scripts/bootstrap/install-kingbase-jdbc.sh
bash scripts/bootstrap/check-kingbase-jdbc.sh
mvn -B -f RuoYi-Vue/pom.xml -pl ruoyi-admin -am '-Dtest=Round5s*,Round5vAccommodationAtomicityTest,RealIotSecurityGateTest,FaceExtractClientMockTest,CommandRespHandlerMockTest,DmsHttpClientTest,DmsTokenManagerTest,TrainIotLockAuthBridgeMockTest' -Dsurefire.failIfNoSpecifiedTests=false package
python3 -m unittest discover -s scripts/qa -p 'test_qa*.py' -v
mvn -B -f RuoYi-Vue/pom.xml -pl ruoyi-admin -am -Dtest=Round5v4MissingResourceTest -Dsurefire.failIfNoSpecifiedTests=false test
驱动私有坐标:cn.com.kingbase:kingbase8:9.0.0;SHA256:
e439bd1c48ce654748c4f333b874a61465702ceb18f29ee017c3f9bc47738c23。
安装脚本先校验供应商文件,再用固定版本 Maven install plugin 安装到本机私有仓库。
ruoyi-admin/lib 不再是构建依赖来源。CI 由管理员合规预置同一私有依赖,缺失即失败。
cd build_ui
node --version
npm --version
npm ci --ignore-scripts --no-audit --no-fund
npm run build:prod
cd ..
不得用实验工程/node_modules1/node_modules2、服务器 symlink 或临时依赖目录替代 lockfile 安装。Quill 2 的转译配置与实验工程一致。Vue 2/CLI 4 的废弃依赖及旧版 node-ipc engine/ESLint peer 警告仍存在:本轮不做整套前端框架迁移,不声称无漏洞。
2. 凭据和只读身份检查
将 qa-bootstrap/round5v.env.example 的键名交给管理员,在 Git 外受保护文件中
填写真实 QA 配置并设置 owner-only 权限 0600。不要把密码放命令行、截图或报告。
脚本也兼容本机已有 ~/.railwaysystem-qa.env 中的 FUSION_QA_APP_PASSWORD 和
身份加密键,但不会复用其中可能指向旧库的 QA_DB_URL。
python3 scripts/qa/qa.py inspect --config /protected/round5v.env
python3 scripts/qa/qa.py snapshot --config /protected/round5v.env
python3 scripts/qa/qa.py verify-snapshot --snapshot-dir .qa-runtime/snapshot-REPLACE_WITH_ACTUAL_ID
固定目标:railwaysystem_fusion_qa_20261013;固定运行账号:fusion_qa_app。
检查使用只读 repeatable-read 事务并 rollback,记录版本、schema、列、索引和计数;
不打印业务行。快照含两张受影响表的敏感内容,仅存 .qa-runtime/(目录0700,
数据0600);其 XML 解析和 SHA 验证不等同于原生全库备份或数据库恢复演练。
服务器现有kingbase容器的 /home/kingbase/install/kingbase/bin/ 已确认具备
V009R003C018原生工具;现有kingbase管理角色可经容器本地连接认证,不需要给
fusion_qa_app提权。已完成原生备份,服务器及本机副本均在非Git目录,目录0700、文件0600。
最新位置、SHA及独立恢复解阻方案见 本轮记录。
sys_restore --file=/dev/null成功仅证明归档可完整读取,不能替代实际数据库恢复。
Round 5V-4 已另获明确授权,复用服务器现有 V9 镜像创建专用隔离恢复容器,
原生恢复及迁移/回滚均已实际验证;该授权不扩展到其他实例或数据库。
恢复证据及新建资源身份见本轮记录;不要把一次性演练脚本当作通用初始化脚本重跑,
不要复用共享库进行覆盖恢复。历史 Round 5V-3 文档保留为当时的真实阻塞记录。
3. 启停隔离 QA(目标库 005 已完成)
经跳板访问时的受管运行隔离(强制)
旧实验进程曾配置 DB_HOST=127.0.0.1 / DB_PORT=14321。端口没有监听者,不代表没有旧客户端等着重连。
Round 5V-5 在该端口建立隧道时,旧实验进程重新访问同一QA库,补偿任务写了两条旧授权的同步时间。
不要手工开放14321或用普通SSH转发替代下面的守卫;单纯更换端口不算隔离。
先只读核对现有Java进程、SSH监听者和非秘密数据源Host/Port。从本工作树根目录,终端A运行:
python3 scripts/qa/qa_isolation.py
# 默认选择临时空闲端口;需固定端口时可显式 --port 14327,但仍会检查客户端依赖。
工具首先持有14321的拒绝连接专用socket,不读写数据库协议、不连接任何上游; 已有未知监听者会导致安全失败,不停止它。新版SSH仅监听127.0.0.1的独占端口, 通过既有wzbmatebook链路访问目标4321;不继承SSH配置中的额外转发/本地命令,不复用共享ControlMaster。 身份认证只走既有合法密钥/Agent或交互密码提示,不将密码放参数、配置或日志。
必须看到QA_ISOLATION_READY后,才在终端B执行下面的启动命令。
Git外0600配置可不设置FUSION_QA_DB_URL,启动器会采用当前受管账本的确切URL;
如显式设置,必须与该账本的127.0.0.1端口和固定QA库完全匹配,否则拒绝。
只读inspect/snapshot在存在活动账本时也采用同一默认端点;无账本时允许其原有只读预检,但不允许应用start。
启动器核对守卫/SSH的PID、出生时间、cwd、命令、loopback监听归属及新端点Java客户端冲突。
看门狗持续核验并更新心跳;隧道退出或核验失败会清理同一租约的前端/后端/Redis,
再关自己的SSH,最后释放拒绝端口。账本/退出证据在.qa-runtime/,不进Git。
正常停止可先执行qa.py stop,再在终端A按Ctrl+C;只停止本任务所属资源,不按名字pkill。
旧实验进程不被停止、旧配置/账号不被修改;受管工作流以外的管理员手动重开14321仍可恢复旧链路, 这不是永久数据库权限撤销或系统级网络隔离。不得绕过受管入口进行QA写入演示。 若需要永久停用旧服务或调整账号,须另获对应批准。原始Kingbase全矩阵驱动仍锁定旧原地址, 不要拿当前隧道配置重跑它;本轮只做启动/登录/查询,不重做005或完整业务矩阵。
python3 scripts/qa/qa.py start --config /protected/round5v.env
python3 scripts/qa/qa.py frontend
默认端口:后端18096、前端18088、独立 Redis16389,仅监听127.0.0.1;端口占用即 失败,不杀旧进程、不改共享 Redis。启动器先确认目标数据库和16列/4索引存在, 缺迁移拒绝启动;列/索引的完整定义仍须按迁移计划人工核验。PID 输出不代表就绪。
安全值强制为 MQTT Mock=true / enabled=false / real-device-write-enabled=false /
whitelist空 / protocol-verified=false / retry-task-enabled=false;人脸 HTTP关闭;
OpenAPI、QA危险接口、Druid控制台和Quartz自动启动关闭;旧DMS关闭。
继承环境中的 Spring/IoT/DMS/JVM 注入覆盖被过滤,数据库 URL/账号由命令行固定。
启动器将构建包复制为 .qa-runtime/ruoyi-admin-<SHA前缀>.jar 并校验散列,防止 Maven
覆盖正在运行的嵌套 JAR。Druid URL 去除 JDBC 秒单位超时参数,池统一使用连接30秒/
网络60秒;实际 Kingbase/Druid 探针验证了 60000ms,不能把 URL 的 15 当成池毫秒值。
JWT和独立Redis密钥由安全随机数首次生成至 .qa-runtime/runtime-secrets.env,0600,
以进程环境注入,不写源码/命令行;数据库及身份密钥仅取受保护配置文件。
不得为演示去打开真实门禁或危险接口。
curl --noproxy '*' --fail http://127.0.0.1:18096/captchaImage
# 真实 Chrome 访问 http://127.0.0.1:18088 ,使用管理员单独提供的 QA 账号。
python3 scripts/qa/qa.py stop
stop只处理本脚本账本中且进程命令身份仍匹配的PID,等待其退出再移除账本;不会清端口、杀其他Chrome、 停止实验工程或修改系统网络。JWT、访问日志、快照、浏览器证据均不进入Git。
4. 可复现的真实 Kingbase / Chrome 软件验收
仅在已迁移、已批准合成写入的同名 QA 库执行:
python3 scripts/qa/run_kingbase_tests.py --approve-synthetic-qa-writes --config /protected/round5v.env
# 真实 Kingbase 11 项;不使用 H2,不启动任何真实 MQTT / 人脸客户端。
# 合成数据有 R5V4 标识并保留审计,不删除既有数据,不重置序列。
Chrome 验收使用 Playwright CLI 技能(本轮实际 Chrome 155.0.8059.40),打开独立
round5v4 会话后运行:
python3 scripts/qa/browser_login.py --config /protected/round5v.env
# 若 QA 自身启用验证码:从实际截图识别后,加 --use-current-page --captcha ACTUAL_ANSWER;
# 不关闭验证码。本轮现有配置的 captchaImage 返回 captchaEnabled=false,未改其开关。
playwright-cli -s=round5v4 run-code --filename=scripts/qa/browser_regression.js
python3 scripts/qa/browser_fixture.py seed --approve-synthetic-qa-writes --config /protected/round5v.env
登录配置额外需要受保护文件中的 QA_ADMIN_USERNAME / QA_ADMIN_PASSWORD。登录驱动仅 在独立 about:blank 页内存中读取配置,关闭该页后填写登录表单,不把配置上传至应用。 CLI 不具备本机工具时使用技能自带 wrapper;不要为此修改工程依赖或系统浏览器设置。
seed 仅首次执行,生成 .qa-runtime/round5v4/browser-fixture.properties;已存在则拒绝覆盖。
按该文件学号在动态菜单 /equip/accommodation 搜索,依次入住、调房至同标识 B 宿舍、退宿。
每次操作后,先观察 AWAITING_ACK,然后执行受控回执驱动,再到授权和指令页面核对:
python3 scripts/qa/browser_fixture.py state --approve-synthetic-qa-writes --config /protected/round5v.env
python3 scripts/qa/browser_fixture.py ack --approve-synthetic-qa-writes --config /protected/round5v.env
python3 scripts/qa/browser_fixture.py verify --approve-synthetic-qa-writes --config /protected/round5v.env
驱动使用真实 Mapper/Service,只接受该文件合成人员与两把合成门锁、MOCK 来源及
round5v-local-mock 环境的当前 AWAITING_ACK 指令,不开放任何 HTTP 回执端点。
授权页按人员编号过滤,指令页按 fixture.marker(分组编号)过滤,应有四条 CONFIRMED 指令。
住宿 V2 模型只持久化分配与最后变更时间,页面已按真实字段标注,不捏造独立入住/退宿时间戳。
- 管理员真实登录、getInfo/getRouters、原品牌菜单和首页图表;培训核心查询。
- IoT九页:group/gateway/device/face/auth/command/accesslog/mqttlog/config, 必须验证组件渲染及实际QA查询,不能把SPA fallback HTTP200当作无404证明。
- 为本轮创建可追踪的合成业务样本,不复用/覆盖既有培训测试记录:报名、
住宿预分配、入住、调宿、退宿、授权意图与
iotlocks.lock_command流水。 - 用实际Kingbase Mapper/Service/事务管理器覆盖迁移计划中的崩溃、并发、晚到ACK、 提交/回滚场景;外部MQTT和人脸只能是可控替身。危险Mock HTTP端点保持关闭, ACK由隔离的Service测试驱动,不通过开放生产式控制接口来换取通过。
- 受控Mock ACK成功只能证明软件闭环,不能证明真实门锁已授权或撤权。
现有 H2 与替身测试仍不等于真实数据库证据;本轮新增
Round5v4KingbaseIntegrationTest 才是上述 Kingbase 事务和应用进程中断验证的执行入口。
5. CI与硬件边界
.gitlab-ci.yml 已改为显式web+RUN_FUSION_VALIDATION=true才允许的验证流水线;
Java21、私有JDBC预检及npm ci,无部署job。本轮未Push,也未触发/验证远程Runner。
本轮数据库、事务、启动和 Chrome 软件验收已经完成;仍未做真实门锁、人脸或网关验收。
硬件测试另需老师批准、确认协议中未验证的帧校验字段/回执及重传策略、单台白名单和人工核对流程。
商业驱动和恢复容器许可仅按现有合法 QA/试用环境验证,不代表生产部署许可。
应用账号既有的三张系统表过宽权限未扩大也未自动收回,应由管理员另行最小化。
任何安全前提不满足时,不得用旧实验后端或伪造 API 响应冒充新版本验收。