fix: 收口融合 QA 构建与验收安全基线

This commit is contained in:
wangzhibiao committed 2026-10-14 11:32:31 +08:00
1 parent 47bc6604e5
commit 5560a3ac04
28 files changed
+22947 -352

No files matched your search

+79
View File
@@ -0,0 +1,79 @@
# Round 5V 验收记录 — 部分通过,迁移待授权
日期:2026-10-14;分支 `fix/iot-safety-hardening`;基线
`47bc6604e53b841e9070b890e65e0a75df1c1e1c`。本文件描述本轮实际结果,
不继承此前 Agent 的通过声明。最终本地提交号见 Git HEAD。
## 真实 Kingbase 结果
- JDBC 实际连接仅限 `192.168.139.218:4321/railwaysystem_fusion_qa_20261013`。
账号 `fusion_qa_app`,KingbaseES V009R003C018,current_schema=public。
只读 repeatable-read 事务结束 rollback;未执行 DDL、业务 INSERT/UPDATE/DELETE、
全量初始化、GRANT、账号修改或共享库访问。
- 迁移前 `iotlocks.lock_auth` 10条,`lock_command` 15条;最终只读复查不变。
005的新增列/索引缺失,迁移未执行,`MIGRATION_WAITING_APPROVAL`。
- 角色非 superuser/createdb/createrole,public/iotlocks 均无 CREATE,表属 kingbase。
但3张 public 表具有额外 TRUNCATE/TRIGGER/REFERENCES,见迁移计划,待管理员审查。
- 两张受影响表的 WebRowSet 私有快照10/15行,SHA256及XML解析通过:
`.qa-runtime/snapshot-baf7eb8fede1`。不是原生全库备份,未做数据库恢复演练。
- **八类生命周期/并发/跨事务 Kingbase 测试均未执行**。只读事务成功不是它们的证明。
当前历史数据未被改写;新增默认 LEGACY/QUARANTINED 的实际迁移效果尚未验证。
证据:`scripts/qa/QaDatabaseProbe.java`、`.qa-runtime/final-database-inspection.log`、
`.qa-runtime/snapshot-report.log`、[迁移/回退计划](ROUND5V_KINGBASE_MIGRATION_PLAN.md)。
## 构建与自动化结果
- Java 21.0.2 / Maven 3.9.x 打包成功;所有模块 release21,抽查 class major65。
当前85项选定JUnit测试,失败0、错误0:原81项加4项住宿异常/事务声明测试。
它们主要为H2/替身,不是Kingbase生命周期验收。
- 修复入住/直接新增在住/调宿吞掉IoT持久化异常;checkIn增加事务边界。
`Round5vAccommodationAtomicityTest`覆盖入住/调宿/退宿异常传播及事务声明。
新增修复的真实Kingbase回滚语义待验证,未夸称原子性已通过。
- 11项Python QA工具测试通过:目标库白名单、URL凭据拒绝、配置权限、无Shell
执行、过滤继承覆盖、迁移缺失不启动、强制安全参数和PID复用拒绝。
- JDBC已从授权本机文件校验后安装为私有Maven依赖9.0.0,正常打入Boot JAR,
不再依赖systemPath;未提交供应商二进制。安装/预检脚本从旧8.6.0同步至9.0.0。
- 前端Node22.23.2/npm10.9.8,`npm ci --ignore-scripts --no-audit --no-fund`
实际安装1753依赖,生产构建通过。核心版本对齐实验工程,新增受跟踪lockfile。
初次构建暴露Quill2语法转译缺失,补回实验已有transpileDependencies后通过。
旧Vue2/CLI4废弃依赖、node-ipc engine/ESLint peer警告未在本轮整体迁移。
- 登录表单残留固定测试账号/密码预填已清空,未重置任何数据库账号。
证据:`RuoYi-Vue/ruoyi-*/target/surefire-reports/`、
`.qa-runtime/backend-build.log`、`.qa-runtime/frontend-build.log`、
`.qa-runtime/qa-tools-tests.log`;准确复现命令见根目录DEMO_RUNBOOK.md。
## 实际 Chrome 与运行结果
- Playwright使用已安装的 `/Applications/Google Chrome.app/Contents/MacOS/Google Chrome`,
UA Chrome155。实际打开生产dist(loopback18088),可见原SYFJGYD品牌登录页。
截图 `output/playwright/round5v-login-backend-blocked.png`,已目视检查。
- 新后端未启动:`qa.py start`执行真实目标库预检后以MIGRATION_REQUIRED拒绝,
未启动Redis或Spring Boot。前端的captchaImage如实返回502,没有替身API或旧后端。
因此管理员登录、动态路由、首页图表、培训/IoT API、九页功能、住宿E2E均未验收。
九个IoT页面源码被生产构建编译不代表页面运行无404。
- 独立端口方案18096/18088/16389,实际只为登录页检查启动了前端服务;
交付前关闭本任务前端和本任务Chrome会话。既有Java PID51901/53305未被停止。
## 配置与工程边界
- 所有安全默认保持关闭真实MQTT/设备写入、空白名单、关闭人脸HTTP、OpenAPI、
QA危险接口、Druid控制台、补偿任务和Quartz自动启动;旧DMS关闭。
运行器不清端口、不杀既有进程、不修改共享Redis或Mac网络;JWT/Redis密钥在
私有0600外部运行配置中生成并仅经环境注入,数据库/身份密钥从受保护文件读取。
- DEMO_RUNBOOK已移除不存在脚本/错误路径/固定登录口令/100%真实执行等声明,
提供实际存在的inspect/snapshot/start/frontend/stop入口和未通过项。
- CI YAML静态解析通过:Java21、私有JDBC预检、npm ci,显式web+变量门禁,
无部署job、无push自动流水线。本轮未Push、Merge、触发远程CI或部署;Runner未验证。
- 变更范围私钥/常见Token模式扫描无发现,未将快照/日志/浏览器缓存/驱动加入Git。
原工程无tracked diff;历史实验工程clean,未改写两者源码或历史。
## 仍需完成
1. 明确仅针对目标QA库的005授权、合规原生备份及回退演练,协调该库写入窗口。
2. 授权后执行并核验增量迁移、历史LEGACY隔离和实际Kingbase八类事务测试。
3. 启动新隔离后端,以真实Chrome完成管理员/菜单/首页/九页/API/住宿Mock闭环。
4. 管理员审查3张表额外权限;老师协议/单台现场测试批准仍独立待办。
READY_FOR_SUPERVISED_HARDWARE_TEST = false。Mock/H2成功不等于真实门锁联调成功。
@@ -0,0 +1,86 @@
# Round 5V — isolated Kingbase migration and rollback gate
## Scope and observed prestate
2026-10-14 read-only JDBC probe: database `railwaysystem_fusion_qa_20261013`, user
`fusion_qa_app`, KingbaseES `V009R003C018`, current schema `public`, search path
`"$user", public`. Application account is not superuser and cannot create databases
or roles. Existing `iotlocks.lock_auth`: 10 rows; `lock_command`: 15 rows. Existing
sequence-backed primary keys, unique auth number, unique person/device/type, and
unique command number remain unchanged. Round 5S columns/indexes were absent.
No migration authorization is inferred from an instruction conditional on approval.
The application role has USAGE but not CREATE on both schemas and does not own
the affected tables. However, existing grants on `public.sys_menu`,
`public.sys_notice_read`, and `public.sys_role_menu` include TRUNCATE, TRIGGER and
REFERENCES. Administrator least-privilege review is pending; no grants were changed.
## Static review of 005
`RuoYi-Vue/sql/iot/005_round5s_execution_safety.sql` only adds nullable metadata,
NOT NULL defaults for mode/version/state, two unique intent-key indexes, and two
recovery indexes. All objects are schema-qualified; no sequences are reset, no
existing business uniqueness is removed, no data is deleted, and there is no REAL
backfill. Existing records must become `LEGACY / 0 / QUARANTINED`, not trusted Mock
or REAL. Two nullable intent-key indexes must allow multiple nulls on this actual
Kingbase instance; validate this with rollback-only synthetic rows after approval.
`ADD COLUMN IF NOT EXISTS` and `CREATE INDEX IF NOT EXISTS` are PostgreSQL-style
syntax supported by the H2 substitute, **not yet a Kingbase execution result**.
Do not use existence checks as proof of correct definitions: inspect names,
types, nullability, defaults and index uniqueness/column order before/after.
Use a bounded lock timeout and a single explicit transaction. DDL rollback and
concurrent unique-index behavior still require actual Kingbase verification.
Application sessions use `iotlocks, public, pg_catalog, sys_catalog`; do not change
the global/database/user search path or accidentally query system `sys_user` views.
## Required approvals and backup
1. Record authorization explicitly naming this database, migration 005 and its
SHA256, maintenance window, account and approving administrator. App-account
credentials do not grant authority to migrate; do not expand its privileges.
2. Inspect active sessions in this target only. Have owners pause *only* writers
targeting this QA database. Do not kill the experiment, teacher or shared service.
3. Run `python3 scripts/qa/qa.py snapshot --config /protected/qa.env`. It captures
both affected tables with JDBC metadata in a repeatable-read **read-only**
transaction, private WebRowSet XML and SHA256 manifest under `.qa-runtime/`.
These contain credentials/personal data from rows: never commit, print or upload.
This is an affected-table snapshot, **not a native full-database backup**.
4. Before executing DDL, the administrator must also produce an authorized native
Kingbase full QA backup (schema/data/sequences/ACLs) using the matching licensed
vendor tools and validate it in an approved isolated restore destination. No
native backup utility or restore destination is assumed or provisioned here.
Do not use a mismatched PostgreSQL client or restore into any shared database.
## Execution and failure rollback (not executed in this round without approval)
With an approved migration account, enforce `current_database()` equals the exact
target before any change. Begin a transaction, set a local lock timeout (5s),
capture prechange schema/index definitions and row counts, execute only migration
005, then verify the following **before commit**:
- All 16 new columns have the reviewed types/defaults/nullability; index definitions
match exactly; existing constraints/sequences and row counts are unchanged.
- Existing rows have `execution_mode='LEGACY'`, `intent_version=0`,
`execution_state='QUARANTINED'`, null intent key/environment/action/attempt time.
- No existing row is REAL, READY or eligible for automatic dispatch.
- A savepoint-based synthetic insert validates null uniqueness and a duplicate
nonnull intent key is rejected; roll back the synthetic savepoint. Sequence gaps
from rolled-back inserts are expected and must not be "repaired" by setval.
Any error: **ROLLBACK the entire DDL transaction**, inspect from a second connection
to prove original schema/counts/data fingerprints are unchanged. If actual Kingbase
DDL is not transactional, stop; never guess or issue automated DROP/CASCADE.
After commit, prefer keeping the additive schema and stopping the new application
over a destructive down migration. Rollback to old software is NOT automatic once
new lifecycle rows exist. Administrator-reviewed selective/native restore requires
fresh approval and a proven isolated restore; no generic destructive down.sql.
## Required acceptance after migration
Run production XML Mappers, real Services and `DataSourceTransactionManager` using
`fusion_qa_app`, with MQTT/face transport substitutes only. Persist synthetic QA
rows with unique run marker; preserve existing training rows and history. Cover
check-in/out intents, commit-before-command crash, never-attempted restart recovery,
unknown outcome -> MANUAL_REVIEW without resend, unique-intent concurrent claims,
late ACK vs new version, cross-transaction visibility/rollback. Preserve test rows
for audit or explicitly scoped cleanup only. H2 results cannot satisfy this gate.