# Round 5V — isolated Kingbase migration and rollback gate ## Current Round 5V-4 outcome The separately authorized new offline V9 recovery container actually restored the native backup; 005 rehearsal, repeatability, transactional rollback and fresh-target backup recovery passed. Only afterwards, the exact approved 16-column/4-index script committed on the named source QA database. Real Kingbase service/transaction/process-interruption tests and Chrome software acceptance now passed. See [Round 5V-4 evidence](ROUND5V4_SOFTWARE_QA.md). Do not rerun initialization or overwrite a live database. The following sections retain the pre-migration plan/observations, not current missing-approval claims. ## Historical Round 5V-3 decision The user explicitly authorized migration 005 **only** on `railwaysystem_fusion_qa_20261013`, together with protected backup and isolated restore rehearsal. Scope SHA256 remains `90648b6ac67470f9a14f0795c4479dfb4811d4907e41a13ee5eeada16582b87f`. Authorization is no longer missing. Status: `MIGRATION_AUTHORIZED_BLOCKED_ISOLATED_RESTORE`. SSH access, matching native tools, existing management-role access and consistent native backup are now verified. Actual independent database restore is still unverified. No DDL or business DML has been performed. Do not create a database, initialize an instance, start a new container or elevate privileges to overcome this gate without separate authorization. See [current evidence and minimal resource proposal](ROUND5V3_SERVER_BACKUP.md). The previous Round5V2 report remains historical evidence, not the current infrastructure status. ## 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, produce an authorized native Kingbase full QA backup (schema/data/sequences/ACLs) using matching licensed vendor tools and validate it in an approved isolated restore destination. Round5V3 completed the native backup; the restore destination is still neither confirmed nor provisioned. Do not use a mismatched PostgreSQL client or restore into any shared database. ## Execution and failure rollback (authorized, blocked on isolated restore) 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.