Files
felhom.eu/documentation/audits/update-night-2026-09-21/16-phase2.1-mariadb-major.md
T
admin 9c69b3ff07
gates / gates (push) Successful in 27s
Update night: Phases 2-4 evidence — both engines, the unattended HOLD, and five new findings
Evidence off the machine at the end of the phases that produced it (R-320). Teardown follows.

PHASE 2 — the two database engines, through the REAL Update button:
- MariaDB 11.6 -> 12.3 on nextcloud: PROVEN, and pressed through the button for the first time.
  All four SPIKE-r459 observables: the datadir's own record moved 11.6.2 -> 12.3.3; the engine
  itself says "already upgraded ... no need to run mariadb-upgrade again"; the entrypoint says
  "Major version upgrade detected ... Check required!" and then STARTED and FINISHED it (not the
  `skipped due to $MARIADB_AUTO_UPGRADE` line R-459 feared); and the engine took its own
  pre-upgrade backup, 631 905 B. The seeded Nextcloud account read back.
- PostgreSQL 16 -> 17 on docmost: FAILED exactly as R-463 predicted and nobody had measured.
  5.1 s to held; the pin named 17 while nothing ran; the restore brought it back in 29.1 s.
  The engine's REFUSAL LINE was destroyed by failAndHold before any probe could read it, so it
  was REPRODUCED INDEPENDENTLY with a control on every step (R-320).

PHASE 3 — the bad days. B1 produced THE UNATTENDED HOLD, which this project has never had: the
caller pressed once with nobody watching, the app held after 312.9 s, and passes 2 and 3 pressed
nothing. B2 put the pin back on a pull failure in 1.0 s. B3 refused `busy` six times. B4 showed
there is NO single-flight — 5 of 5 updates ran at once and all ended honest. B5 cut the power in
`backing-up` and the box recovered itself and said so. B7 refused under the 2 GB floor. B9 found
R-458's risk narrower than the row states.

PHASE 4 — every badge on the box is TRUE, and the held app answers all four of Q4's questions.

FINDINGS, five new and three corrections to existing rows. The one that matters: R-618 is P1 —
two templates name a health probe the app does not answer, and because the guarded update waits
on that same probe, a SUCCESSFUL update ends by STOPPING a working app. Measured: tandoor served
HTTP 200 on the new version at four samples across five minutes and was then stopped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-21 22:13:57 +02:00

3.8 KiB

Phase 2.1 — MariaDB across a major, through the REAL Update button. PROVEN.

The first time this has ever been pressed through the product. R-459 measured the conversion on the harness; R-469 lifted the gate on 2026-09-21 morning; the BUTTON had never been used for it.

Venue: guest 9202, controller v0.261.0. App: nextcloud — the app image does NOT move (nextcloud:34.0.1-apache throughout); only the mariadb: sidecar, 11.6 → 12.3.

Seeded and read back through the app's own CLI: occ user:add created drillb9a9d0 ("The account … was created successfully"), occ user:info found it before the move (control C1) and after it, each time with the fixture's own negative control — a uid that cannot exist must read as absent — passing.

The four observables of SPIKE-r459-mariadb-upgrade-2026-09-06

# observable before after
1 mariadb_upgrade_info — the datadir's own record 11.6.2-MariaDB 12.3.3-MariaDB
2 the engine's OWN check (R-464: never the log line) "Access denied" — the probe was unauthenticated, see the note below „This installation of MariaDB is already upgraded to 12.3.3-MariaDB. There is no need to run mariadb-upgrade again."
3 the entrypoint's own lines — „Major version upgrade detected from 11.6.2-MariaDB to 12.3.3-MariaDB. Check required!" → „Starting mariadb-upgrade" → „Finished mariadb-upgrade"
4 the engine's own pre-upgrade backup absent /var/lib/mysql/system_mysql_backup_11.6.2-MariaDB.sql.zst, 631 905 bytes
5 the version actually running 11.6.2-MariaDB-ubu2404 12.3.3-MariaDB-ubu2404
6 container mariadb:11.6 running, 0 restarts mariadb:12.3 running, 0 restarts

Observable 3 is the one that matters most, because R-459's whole finding was that MariaDB can apply a major and skip the conversion quietly, printing skipped due to $MARIADB_AUTO_UPGRADE. That line is absent; the entrypoint says the conversion was detected, started and finished.

And observable 2 confirms R-464's own warning about the instrument: the command exits 1 when it means no upgrade is needed. The exit code carries no usable information here; the SENTENCE is the discriminator, which is exactly what R-464 says.

The four version observables, all agreeing

pinned    nextcloud:34.0.1-apache · mariadb:12.3 · redis:7-alpine
installed nextcloud:34.0.1-apache · mariadb:12.3 · redis:7-alpine
compose   nextcloud:34.0.1-apache · mariadb:12.3 · redis:7-alpine
inspect   nextcloud-db mariadb:12.3 running=true restarts=0
          nextcloud    nextcloud:34.0.1-apache running=true restarts=0
          nextcloud-redis redis:7-alpine running=true restarts=0

Two honest notes on the instrument

  1. The first engine-before.txt capture asked the engine without credentials and got ERROR 1045 Access denied where observable 2 should be. The probe was corrected mid-run to pass --user=root --password=$MARIADB_ROOT_PASSWORD (the recipe upgrade-test.py's own ENGINE_PROBES already uses) and the AFTER capture above was retaken with it. The BEFORE value for observable 2 is therefore not measured, and is stated as such rather than inferred from observable 1.
  2. The ls in observable 4 printed (no pre-upgrade backup file present) after listing the file, because it globs two patterns and only one matched. The file is there; the fallback text is the shell's, not the engine's. Noted so nobody reads the line as a contradiction.

What this settles

The MariaDB half of 09 §3 decision 5 and R-469's lift is now proven through the button a household presses, not only on the harness — conversion detected, run, finished, the engine's own pre-upgrade backup taken, and the customer's account still there afterwards.