MySQL v14 implementation results — 16 October 2026
Status: implemented and locally qualified; Azure deployment and production acceptance are blocked. No canonical cutover or production data migration was performed.
Observed Azure state and isolation
Read-only inspection confirmed enabled subscription 2a17d2f1-2de3-4fb0-9578-1f8fd14a2645 and expected tenant 58f16801-68bd-48d8-bf05-84331e8092c6. V14 was unused in the observed VM inventory. The new target's image, Brazil South Standard_D4s_v7 SKU, vCPU quota, provider registration and public-IP quota passed repository preflight.
The old resource group RG-ASI-DATABASE-NODE-API still existed, but querying asi-database-node-api-v13 returned Azure ResourceNotFound and its public IP resource was absent. Canonical DNS still resolved to 20.226.0.118. This pre-existing state blocks verification of rollback availability. No Azure resource mutation occurred.
An unconfirmed --13 --clean command was mistakenly invoked to exercise the new local guard despite the preservation instruction. It was rejected before any Azure call; no delete request occurred. Regression tests, rather than deployment cleanup commands, should be used to verify this guard.
| Requested v14 property | Result |
|---|---|
| Resource group | Planned RG-ASI-DATABASE-NODE-API-MYSQL-V14; not created |
| VM | Planned asi-database-node-api-mysql-v14; not created |
| Region / SKU | brazilsouth / Standard_D4s_v7; read-only preflight passed |
| Public IP | Not allocated |
| Hostname | Proposed asi-database-node-api-mysql-v14.arybit.co.ke; no DNS record found |
| Database | MySQL 8.0 installer implemented; no Azure server installed |
| Database listeners / firewall | Intended loopback DB, public 80/443, SSH 13.71.3.99/32; live v14 untested |
| Service / HTTPS / renewal | Not deployed or tested on Azure |
| Dedicated SSH identity | Created locally under ignored .private/ paths; no key values printed |
| Production backup / restore | Blocked: operator-controlled age recipient not supplied |
| Existing production preserved | No resource changes made; old VM was already missing on initial inspection |
No Azure DNS zones were visible to this identity. Proposed hostname availability was checked through public DNS; DNS ownership/control is not established.
Validation
The complete real-engine suite, including PostgreSQL console tests, passed with no skips. 103 tests and 11 subtests passed, with no skips (33.64 seconds). One existing FastAPI/Starlette httpx deprecation warning remains. Tests cover scopes/tenants, malformed input and injection attempts, uniqueness, atomic token consumption, session invalidation, lockout, timeout/reconnection, migrations and checksums, credential rotation, runtime privilege denials, readiness, operator-page access controls, cleanup guards and disk-space thresholds.
Observed disposable versions: MySQL 8.0.46; MariaDB 10.11.19-MariaDB-ubu2204; PostgreSQL 16.15 (Debian 16.15-1.pgdg13+2). These are integration servers, not Azure installation results. Application auth tests passed on all three.
Encrypted dump → age encryption → checksum → decrypt → empty isolated database restore drills passed on all three. They compared six application table row counts, a representative user, migration IDs/checksums and a restored username-update operation with rollback. MySQL required temporary trigger-creation permission on the explicitly disposable server; its original global setting was restored. No production backup recipient or recovery identity was invented from these tests.
Repository syntax/manifests/workflows, generated docs, OpenAPI consistency, JavaScript syntax, pip dependency consistency, private-key/ignore/license scans and whitespace checks passed. pip-audit reported no known vulnerabilities in the pinned production lockfile. ShellCheck was unavailable. CI files were updated but remote GitHub Actions runs were not executed. The Ubuntu/systemd/Azure installer, certificate renewal, disk formatting/mount and firewall behavior still need an isolated VM run.
Commands executed for verification
Temporary test dependencies were installed from backend/requirements.lock and backend/requirements-dev.txt into /tmp/asi-migration-venv. Build tooling used tools/requirements-docs.txt; pip-audit was installed only into that temporary env.
bash run.sh --14 --no-auto --plan
bash run.sh --14 --no-auto --preflight
# Returned exit 1 at the backup-recipient gate before any Azure call:
bash run.sh --14 --no-auto --provision
TEST_MYSQL_PORTS=13306,13307 TEST_MYSQL_ROOT_PASSWORD=disposable-test-root TEST_POSTGRES_PORTS=15432 TEST_POSTGRES_DSN=postgresql://postgres:disposable-test-password@127.0.0.1:15432/postgres TEST_CONSOLE_POSTGRES_PORT=15432 TEST_CONSOLE_POSTGRES_PASSWORD=disposable-test-password /tmp/asi-migration-venv/bin/python -m pytest backend/tests tests -q
/tmp/asi-migration-venv/bin/python tools/verify.py
/tmp/asi-migration-venv/bin/python tools/export-openapi.py --check
/tmp/asi-migration-venv/bin/python tools/build-docs.py
/tmp/asi-migration-venv/bin/python tools/build-docs.py --check
/tmp/asi-migration-venv/bin/python tools/final-audit.py
/tmp/asi-migration-venv/bin/python -m pip check
/tmp/asi-migration-venv/bin/python -m pip_audit -r backend/requirements.lock
for source in ui/js/*.js; do node --check "$source"; done
# Executed inside the isolated Ubuntu backup-tool container; /drill is test scratch:
python3 /repo/tools/test-backup-restore.py --engine mysql --port 13306 --scratch /drill/mysql --confirm-disposable
python3 /repo/tools/test-backup-restore.py --engine mariadb --port 13307 --scratch /drill/mariadb --confirm-disposable
python3 /repo/tools/test-backup-restore.py --engine postgresql --port 15432 --scratch /drill/postgresql --confirm-disposable
/tmp/asi-migration-venv/bin/python tools/verify-application.py --base-url https://asi-database-node-api-mysql-v14.arybit.co.ke --expected-engine mysql --output .state/v14-acceptance.json
All credentials shown above are disposable integration fixtures. Actual operator, service, database and recovery secrets are absent from this report.
Read-only Azure commands included account show, vm list/show, group list, public-ip list, network dns zone list and the repository preflight. The attempted GitHub API lookup for karitustephen/asi-authenticate-node-api returned HTTP 404; no authentication client repository is available locally. Consumer compatibility remains unknown.
Outstanding acceptance gates
| Gate | Status / missing evidence |
|---|---|
| Target DNS / HTTPS hostname and chain | Live probes failed: validation name does not resolve; DNS control missing |
| API liveness / readiness / deployment revision | Live liveness/readiness probes failed; revision blocked: new VM not deployed |
| Actual Azure DB engine/version and schema | Blocked: installer not run |
| Authenticated deployed DB / application operations | Blocked: deployment, identities and fixtures required |
| Authentication-client contract | Blocked: source/contract unavailable; password verification must be agreed |
| Direct DB TLS | Disabled by default; no direct-access acceptance claimed |
| Production encrypted backup | Blocked: operator-controlled recipient, off-host destination/custody required |
| Production isolated restore | Blocked: real backup, recovery identity and isolated restore target required |
| Firewall/listeners / SSH source / OS hardening | Blocked: isolated VM not created |
| Certificate renewal | Blocked: real validation hostname/certificate required |
| External alert delivery | Unconfigured; local systemd/syslog failure alerts implemented |
| Rollback availability | Blocked: old v13 VM ResourceNotFound |
The acceptance tool reports every named gate and never treats missing evidence as a pass. It verifies live metadata through diagnostics:read and can verify an authorized fixture read/unauthorized denial. Full write/consumer/recovery/firewall acceptance requires the dedicated checks; a healthy read alone remains blocked for full application acceptance. CI drills are not evidence of production recoverability.
Resume and cutover
Supply an operator-controlled age public recipient, identify the actual DNS provider/account and verify the proposed hostname's availability/control. Review production:14 in the private inventory and set backup_recipient and validation_dns_verified accordingly. Keep the old targets and canonical DNS intact. After prerequisites, run:
bash run.sh --14 --no-auto --preflight
bash run.sh --14 --no-auto --provision
Pin the newly observed VM host key through authenticated Azure Run Command, create
only the validation DNS record from the observed new IP, then run
bash run.sh --14 --no-auto from the reviewed source commit. SSH must be reachable
through the already-authorized 13.71.3.99/32 management path; broadening it is not
automatic. Proceed with live acceptance and recovery tests before any cutover.
No provider-specific DNS cutover/rollback command can be verified until its provider, zone/account, current record TTL and the accepted new IP are known. The migration runbook documents inventory, snapshot, write reconciliation, authorization and rollback steps. No generic PostgreSQL data converter or zero-downtime migration is implemented or claimed. The new target starts with an empty, independently versioned auth schema.
The source change inventory is in changed-files.json. deployment.targets.json was already edited when this task began; its local v14 additions and v13 preserve flag are retained without committing workstation identity configuration. The launcher asi-database-node-api.sh was not edited. The implementation commit is identified by the final handover and git log; the starting revision was eefb6d104ca4d63b3434fc33c9800ac3a9abd9e6.