diff --git a/CLAUDE.md b/CLAUDE.md index d18728b2..5112a648 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -135,6 +135,12 @@ something, not only sessions that touch `documentation/` — which is why it is - **Root `STATUS.md`** — at the end of every session in which something shipped, broke or was decided. It is a **view** of `OPEN-ITEMS.md`; nothing may exist only there. One screen, written for the operator in plain language, and deliberately **not** `CONTEXT.md`. +- **The golden, on its cadence** (operator ruling 2026-09-13): **weekly, and before ANY drill or + fresh install**, bake + vouch + raise the floor per `documentation/runbooks/RUNBOOK-manual-build.md` + §4.1. Not per release. Between bakes the dated waiver (§4.2, `documentation/tests/golden-waiver.yml`, + ≤ 14 days) keeps `golden_currency_gate.py` advisory; **when it expires the gate is red and stays + red until someone bakes or renews — that is the mechanism, so do not `--no-verify` past it.** A + nightly or drill session that starts on a fresh install checks the golden FIRST. - **The capability map** (`documentation/architecture/00-capability-map.md`), if a capability's status changed — with its new evidence citation. - **`python3 scripts/unproven.py --summary`** — one line per status, and the not-walked total. Run it diff --git a/CONTEXT.md b/CONTEXT.md index 8f2466a7..3245cdad 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -14,6 +14,33 @@ > language, one screen, no identifiers in the prose. Same subjects, different readers; merging them > would make one of the two audiences stop reading. `STATUS.md` is also a **view of `OPEN-ITEMS.md`** > and holds nothing of its own; this file does hold its own content, namely the standing rulings below. +## Goldens move to a CADENCE, and the gate learns to read a dated waiver (2026-09-13, R-468 / R-242 / R-467) + +**The ruling (operator, 2026-09-13):** *bake on a cadence — weekly, and always before any drill or +fresh install — not per release.* **The reason:** `golden_currency_gate.py` trips on every release by +design, and in August that produced **25 goldens in 26 days** plus thirteen declared `--no-verify` +bypasses (R-404/R-417). A guard bypassed that often teaches everyone to bypass it. Every release still +raises the FLOOR, so the demo boxes keep getting each release in ~20 s; only the golden — which +protects a fresh install and nothing else — moves to a cadence. + +**The mechanism, because a rule without one is a wish (R-242 recurred the day after it was written):** +`documentation/tests/golden-waiver.yml` — `issued`, `expires` (≤ 14 days, enforced by the gate's +`WAIVER_MAX_DAYS`), `reason`, `register_row`. Valid → a golden BEHIND the record is a loud ADVISORY, +exit 0. Expired → red again, naming the date. **Never covers an UNRECORDED golden (R-385)** — that is +not a cadence choice. Malformed in any way → exit 2, never 0, never silently ignored; the R-421 decoy +(a file saying only `expires`) is refused. The register is read for ONE fact — does the row exist. +`GOLDEN_GATE_*` env vars are a test seam (where it reads, never what it decides). Tests: cases 5–15. +Cadence: `RUNBOOK-manual-build.md` §4.2 and this repo's end-of-session checklist. **Pre-customer: the +first external install retires the waiver.** **R-242's vouch half is untouched and still open.** + +**The last per-release bake:** golden **0.236.0** baked, round-tripped, vouched and the floor raised +the same day (`documentation/tests/golden-0.236.0-2026-09-13/`) — it carried four unbaked releases +(R-467). The waiver was issued AFTER that bake landed, not over it. + +**Same day, the database engine:** every `mariadb:` sidecar carries `MARIADB_AUTO_UPGRADE=1` (R-459 +closed; `09-update-architecture.md` §3 decision 5) and `app-catalog-felhom.eu/scripts/check-engine-major.py` +holds every engine inside its major until Slice 4 (R-448) ships — removal tracked as **R-469**. + ## The record told a worse story than the truth for two months, and my own probe is why (2026-09-01, R-429 / R-95 / R-431) **THREE RULINGS.** diff --git a/REPORT.md b/REPORT.md index e69ba49d..4d01bfbb 100644 --- a/REPORT.md +++ b/REPORT.md @@ -1,181 +1,264 @@ -# REPORT — SPIKE R-459: is a skipped MariaDB upgrade harmless, and what does fixing it cost? (2026-09-06) +# REPORT — MariaDB finishes its own conversion, golden 0.236.0, and goldens move to a cadence (2026-09-13) -*Overwritten each session. Nothing durable lives only here.* +*Overwritten each session. Nothing durable lives only here — every finding below has a register row.* -> **OUTCOME A, qualified — and the trade this task was commissioned to price DOES NOT EXIST.** -> The skipped conversion is **stable but never self-resolving**. Fixing it costs **7 seconds** and -> does **not** cost the ability to abort, which is what B assumed. It is not C either: the conversion -> **succeeded** across the multi-major jump. +> **Everything the task asked for shipped, and every scenario A–H passed with the evidence quoted +> below.** Four templates carry `MARIADB_AUTO_UPGRADE=1`; the harness saw the conversion RUN; the +> change landed on demo-hp through the real 15-minute cycle and recreated nothing; an engine-major +> gate holds every database engine inside its major until Slice 4; golden **0.236.0** is baked, +> round-tripped, vouched and the floor raised; and `golden_currency_gate.py` reads a dated waiver. +> **Three claims in the prompt turned out wrong or imprecise — named first, in §1.** -## 1. Confirmed baselines — none had moved +## 1. Claims in the prompt that turned out wrong, named first -| repo | task's baseline | found | +1. **"a throwaway guest on demo-hp, disk on `/mnt/nvme-1tb` at its root."** `/mnt/nvme-1tb` does not + exist on demo-hp; the 1 TB NVMe is mounted at **`/mnt/hdd_1`** (already recorded by the two + September spikes and R-461). The guest's disk went on a dir storage at `/mnt/hdd_1`'s root, as + those spikes did. `target-selection.md` still names the wrong path — that is R-461, not re-filed. +2. **"the waiver is R-242's remaining half."** The gate's docstring names TWO things: the honest fix + for a release nobody wants a golden for is "a recorded waiver, never a bypass" (built today), and + R-242's *remaining half* is that **nothing gates the VOUCH** (unbuilt, unchanged, still open on + R-242). The task text conflated them. The docstring, the row and this report keep them apart. +3. **"Add the bake to the nightly-session checklist."** No document by that name exists in any repo + (`grep -rln nightly` finds none under `documentation/runbooks/`). The step went into the two + routines that do exist: `RUNBOOK-manual-build.md` §4.2 (the cadence) and this repo's + `CLAUDE.md` end-of-session checklist. If a nightly checklist is created later, it points at §4.2. + +Also imprecise, not wrong: the runbook's vouch step says to read `MinAgent` from the golden's +controller CHANGELOG header, and **the last four headers carry no such line** — filed as **R-470**. + +## 2. Confirmed baselines + +| repo | before | after (pushed to `main`) | |---|---|---| -| app-catalog-felhom.eu | `0474ce387e6f` | `0474ce387e6f` | -| felhom.eu | `a1a6c73fe132` | `a1a6c73fe132` | -| felhom-controller | `bab82c471e03` | **not touched** | +| app-catalog-felhom.eu | `b7ef0c4a09d6` | `eec1228` templates → `bd32830` gate → `3525e35` CHANGELOG/REPORT | +| felhom.eu | `4b2e5608c227` | this push (two commits: documents + gate, then the register compression) | +| felhom-controller | `155271672265` (v0.236.0) | **unchanged — no code.** Golden bake only. | -Highest `R-` id **462**, confirmed. Minted **R-463**, **R-464**. No version bump, no release. -**The task's §2 table was verified and is exactly right**: four MariaDB apps at the stated pins, and -**no `MARIADB_*` env in any of the 53 templates.** +Highest R-id before: 467. Minted: **R-468** (waiver), **R-469** (engine-major rule expiry), +**R-470** (MinAgent header line), **R-471** (observations decoy hole, pre-existing). -## 2. The outcome, and the evidence that assigns it +## 3. Scenario results, with the evidence quoted -| | | | -|---|---|---| -| **A** | unconverted datadir is benign | **THIS ONE, qualified** — 5 of 5 restarts, no degradation. But the engine says a check is required *every* start, so "benign" holds only as measured: no decay over restarts, one seeded record, over minutes. | -| **B** | converting works, the abort dies with it | **NO.** Converting works; the abort still starts and serves. | -| **C** | converting fails, the jump is too big | **NO.** It succeeded in 7 s and took its own backup first. | +Evidence directory: `documentation/audits/r459-close-2026-09-13/` (36 files); golden: +`documentation/tests/golden-0.236.0-2026-09-13/`. -## 3. Observable 1 — `mariadb_upgrade_info`, all four moments, verbatim +### A — the harness sees the conversion happen ✅ -| moment | state | contents | -|---|---|---| -| 1 | fresh 11.6 datadir | `11.6.2-MariaDB` (14 bytes) | -| 2 | 12.3 started on it, skip logged | **`11.6.2-MariaDB` — unchanged** | -| 3 | after 5 restarts of 12.3 | **`11.6.2-MariaDB` — still unchanged** | -| 4 | comparison arm, after conversion | **`12.3.3-MariaDB`** | - -The engine serving at moments 2–3 was `12.3.3-MariaDB`, confirmed by `mariadb --version` — so the -mismatch is real and not the wrong container. - -## 4. Observable 2 — the engine's own verdict, invocation, output and exit code - -Check mode located in the image, not assumed: **`--check-if-upgrade-is-needed`**. +Throwaway LXC **9403** on demo-hp (Debian 13, Docker 29.8.0, Compose v5.5.1), harness copied from the +local commit WITH the setting. `engine_state_after.bookstack-db.answer`, verbatim, on both edges: ``` -$ docker exec bookstack-db sh -c 'mariadb-upgrade --check-if-upgrade-is-needed \ - --user=root --password=$MYSQL_ROOT_PASSWORD' -Major version upgrade detected from 11.6.2-MariaDB to 12.3.3-MariaDB. Check required! -[exit=0] +12.3.3-MariaDB | This installation of MariaDB is already upgraded to 12.3.3-MariaDB. There is no need to run mariadb-upgrade again. [exit=1] ``` -After conversion: +| edge | verdict | seed before / after | abort | +|---|---|---|---| +| E3 (app + engine 11.6→12.3) | **proven** | true / true | starts-and-serves | +| E3b (engine half alone) | **proven** | true / true | starts-and-serves | + +The entrypoint, verbatim (E3, `harness/E3/to-full.log`): ``` -This installation of MariaDB is already upgraded to 12.3.3-MariaDB. -There is no need to run mariadb-upgrade again. -[exit=1] -``` - -**The two runs establish the exit-code semantics between them — 0 = needed, 1 = not.** Measured, not -read from documentation, and worth stating because the polarity is the reverse of the usual -convention. - -**A false start, recorded because it nearly produced the wrong answer:** without credentials the same -command returns `ERROR 1045 (28000): Access denied … FATAL ERROR: Upgrade failed` with **exit 1** — -an authentication failure wearing the shape of a verdict. → **R-464.** - -## 5. Observable 3 — the restart series: 5 of 5 - -| restart | settled | readback | `upgrade_info` | engine check | entrypoint | -|---|---|---|---|---|---| -| 1–5 of 5 | yes, each | **pass, each** | `11.6.2-MariaDB`, unchanged | `Check required!`, each | `[Note]`, never escalated | - -**It does not degrade. It also never heals.** R-459's hypothesis that the Note might become a Warning -or an Error is **not supported**. - -## 6. Observable 4 — the comparison arm - -Scratch copy of the template **inside the guest** with `MARIADB_AUTO_UPGRADE=1`. **Nothing with -`MARIADB_` in it was committed to the catalog.** - -**The conversion succeeds**, verbatim and in order: - -``` -[Note] [Entrypoint]: Starting temporary server [Note] [Entrypoint]: Backing up system database to system_mysql_backup_11.6.2-MariaDB.sql.zst [Note] [Entrypoint]: Backing up complete [Note] [Entrypoint]: Starting mariadb-upgrade +Major version upgrade detected from 11.6.2-MariaDB to 12.3.3-MariaDB. Check required! [Note] [Entrypoint]: Finished mariadb-upgrade ``` -**Cost:** `mariadb-upgrade` itself **17:33:24 → 17:33:31 = 7 s**; whole TO step **35.9 s** with it -against **~10.5 s** without → **≈ 25 s of extra startup, once**. **Measured on a nearly empty -database** — it works over system tables rather than row data, so it should scale with table count, -**but this run did not measure that** and 7 s must not be quoted as a fleet figure. +`skipped due to $MARIADB_AUTO_UPGRADE`: **0** lines in both TO logs (it appeared on every start +before this change — spike §4). Conversion 09:53:20 → 09:53:26 = **6 s**. The abort log prints +`MariaDB upgrade not required` — the R-464 trap, quoted as an observation and not as soundness. -### The decision-relevant fact — §14.6 of the task +### B — the negative control still works ✅ -**Converting does NOT kill the abort.** With the datadir at `12.3.3-MariaDB`, putting **11.6** back: +C3 (`privatebin/pdo:2.0.5 → alpine:3.20`): **`failed`**, `healthy_after=false`, container +`restarting`. Ran first, as the CLAUDE.md rule says. + +### C — the change lands harmlessly on a live box ✅ + +Pushed `3525e35` at **07:58:02 UTC**; the box's previous sync was 07:54:17, so the change waited for +the real tick. `live-9201/00-baseline-before-push.txt` → `01-after-sync.txt` → `02-restart.txt`. + +The sync's own lines, verbatim: ``` -abort: starts-and-serves settled 10.5 s readback: PASS -survived a further restart: Up 25 seconds (healthy), upgrade_info: 12.3.3-MariaDB +2026/09/13 08:09:17 sync.go:396: [INFO] [sync] Updated bookstack/docker-compose.yml +2026/09/13 08:09:17 sync.go:409: [DEBUG] [sync] bookstack: stored definition refreshed with the delivered fix +2026/09/13 08:09:17 sync.go:135: [INFO] [sync] Periodic sync: Sablonok frissítve — frissítve: bookstack, kimai, nextcloud, romm ``` -**…but the engine calls that state unsupported, and the entrypoint hides it.** → **R-464**: +Live `docker-compose.yml` fragment from 9201 after the sync: -| asked | answer | -|---|---| -| the entrypoint, every start | `[Note] [Entrypoint]: MariaDB upgrade not required` | -| `mariadb-upgrade --check-if-upgrade-is-needed` | `FATAL ERROR: Version mismatch (12.3.3-MariaDB -> 11.6.2-MariaDB): Trying to downgrade from a higher to lower version is not supported!` | - -**So "the abort works" is an observation that it started and served — not a claim the datadir is -sound.** One restart cycle, one seeded record. Saying more would repeat the mistake this task exists -to correct. - -## 7. The harness change, and E3b re-run showing it - -`upgrade-test.py` gained **`engine_state_after`**, reported **beside** the verdict and never folded -into it — an unconverted datadir is not *known* to be a failure, so a verdict that said so would -encode an unproven judgement. E3b re-run: - -```json -"verdict": "proven", -"engine_state_after": {"bookstack-db": { - "image": "mariadb:12.3", - "answer": "11.6.2-MariaDB| Major version upgrade detected from 11.6.2-MariaDB to 12.3.3-MariaDB. Check required! [exit=0]"}} +``` + bookstack-db: + image: mariadb:12.3 + ... + - TZ=Europe/Budapest + # MARIADB_AUTO_UPGRADE: on a MAJOR engine move the engine converts its own datadir (~7 s on a + ... + - MARIADB_AUTO_UPGRADE=1 ``` -**The exact thing the harness was blind to, now visible next to a green verdict.** A PostgreSQL probe -is included; it has **never run against a real Postgres major** (→ R-463). +**Not recreated by the sync:** both container IDs and `StartedAt` identical to the pre-push baseline +(`bookstack` `26b555d7…` started 04:21:07Z; `bookstack-db` `b02f7a09…` started 04:21:01Z), `docker ps` +`Up 4 hours (healthy)`. `applied-compose.yml` carries the setting too (fixes flow INTO the pin). -## 8. Register — 206 open before, 208 after; closed 168, unchanged +The one deliberate `POST /api/stacks/bookstack/restart` at 08:10:32 UTC → `{"ok":true,"message":"Stack +bookstack restart completed"}`, healthy after 8 s. The engine's log after the restart, verbatim: -| row | disposition | -|---|---| -| **R-459** | **NARROWED, P2 → P3, WAITING-ON-OPERATOR.** Consequence measured; the expected trade does not exist. The fleet-wide env change remains the operator's call (4 apps). *VIKTOR rules, CC implements* | -| **R-463** | **OPENED**, P2-MEDIUM, CC — the PostgreSQL analogue. **11 templates, 8 on `postgres:16-alpine`**; register grep for `pg_upgrade`/"postgres major" returned **0**, confirmed twice. **Deliberately not measured here.** The two engines fail in **opposite** directions: MariaDB skips quietly, Postgres **refuses to start** — so this one cannot hide, it presents as eight apps down at once | -| **R-464** | **OPENED**, P3-LOW, CC — `MariaDB upgrade not required` is printed on an unsupported downgrade, so that line cannot be a soundness signal. Same class as "presence is not success" and R-443's HTTP 200 over a crash-looping app | +``` +2026-09-13 10:10:34+02:00 [Note] [Entrypoint]: MariaDB upgrade not required +2026-09-13 10:10:35 0 [Note] mariadbd: ready for connections. +``` + +and the engine asked directly (R-464): `12.3.2-MariaDB` / `This installation of MariaDB is already +upgraded to 12.3.2-MariaDB.` `[exit=1]`; `MARIADB_AUTO_UPGRADE=1` present in the running container; +`GET /login` → **200**. Nothing else on 9201 was touched; bentopdf stays. + +### D — the rule exists and a gate knows it ✅ + +`app-catalog-felhom.eu/scripts/check-engine-major.py`, fourth row of `catalog_gates.py`, run by the +pre-push hook with `--range=..`. Refusal, verbatim: + +``` +ENGINE-MAJOR GATE FAILED: templates/kimai/docker-compose.yml service kimai-db moves mariadb 11 -> 12 (mariadb:11.6 -> mariadb:12.3). +RULE (app-catalog CLAUDE.md, operator ruling 2026-09-13): until the Update button takes a VERIFIED BACKUP as its precondition (Slice 4, felhom.eu OPEN-ITEMS.md R-448), no template may move a database-engine image across a MAJOR version. +WHY: MariaDB sidecars now carry MARIADB_AUTO_UPGRADE=1 and WILL convert the customer's datadir on the next Update; PostgreSQL's image refuses to start on an older major's datadir (R-463). Either way this is a customer-data event with no backup in front of it. +EXPIRY: this rule is removed DELIBERATELY when R-448 ships — the removal is its own register row, not a silent edit. Until then, keep the engine within its major. +``` + +Pass, verbatim (this push's own range): `engine-major gate OK — no database engine crosses a major +version (rule: CLAUDE.md, until Slice 4 / R-448 ships)`. Red-proof (`engine-major-gate/redproof-7-cases.txt`): +`11.6→12.3` rc=1, `postgres:16→17` rc=1, `mariadb:lts` rc=2, `11.6→11.8` rc=0, and three decoys +(comment + `serverVersion=` env, the app's own image, README) rc=0. **CI cannot run it** — the +runner fetches at `--depth 1`; the runner announces the skip on a shallow clone (pinned by +`test_catalog_gates.py`). Same gap as R-452, not re-filed. + +### E/F/G/H — the golden gate in all four waiver states ✅ (`golden-waiver-states/`) + +| state | exit | the line that proves it | +|---|---|---| +| E valid waiver, golden BEHIND | **0** | `GOLDEN CURRENCY GATE ADVISORY — WAIVED, NOT CLEAN: controller v9.9.9 is released and NO golden carries it (newest bake is 9.9.7; 2 release(s) behind: 9.9.8, 9.9.9).` … `Waived by R-468 until 2026-09-26 (13 day(s) left)` | +| F expired waiver, behind | **1** | `The waiver at documentation/tests/golden-waiver.yml EXPIRED on 2026-09-12 (R-468). It ran out, as a dated waiver is meant to` | +| G valid waiver, golden UNRECORDED | **1** | `A waiver exists (R-468, until 2026-09-26) and DOES NOT COVER THIS: it covers a golden that is behind the record, never one that is unrecorded (R-385).` | +| H 15-day waiver | **2** | `the waiver … is MALFORMED — `expires:` is 15 days after `issued:` — the hard limit is 14.` | +| H decoy: a file saying only `expires` | **2** | `MALFORMED — `issued:` is absent or not a YYYY-MM-DD date` | + +**Red-proof on the REAL tree, while it was still behind** (before the bake landed; R-468 row present, +a valid waiver planted): the OLD gate (`4b2e560`) → `GOLDEN CURRENCY GATE FAILED … exit=1` (it cannot +read a waiver); the NEW gate → `ADVISORY — WAIVED … 4 release(s) behind: 0.233.0, 0.234.0, 0.235.0, +0.236.0 … exit=0`. Tests: `scripts/test_golden_currency_gate.py` cases 5–15, all green +(19 cases in the file now, 4 before). + +**The first waiver, as committed** (`documentation/tests/golden-waiver.yml`, issued AFTER the bake): + +```yaml +issued: 2026-09-13 +expires: 2026-09-27 +reason: pre-customer development; goldens on a weekly cadence (operator ruling 2026-09-13) +register_row: R-468 +``` + +Gate on the real tree now: `newest released controller : 0.236.0` / `newest golden baked : 0.236.0` +/ `waiver : VALID until 2026-09-27 (14 day(s) left)` → **OK, exit 0**. Before the bake it read +`FAILED … 4 release(s) behind`, exit 1 (`golden-waiver-states/00-real-tree-before-bake-no-waiver.txt`). + +## 4. The golden (R-467) — version and vouch evidence + +`GOLDEN_VERSION=0.236.0`, `GOLDEN_SHA256=58a3cc24c61dc2271f2cb508ef5a269af97005f386b671f18011258df5f958bf`, +654 115 664 B. Three readers agreed (bake log, round trip hashed from the DOWNLOADED bytes, the hub's +dropdown); `./etc/felhom-controller-image` out of the archive says `felhom-controller:0.236.0`; +markers 1/1/1/1, `excluding` 0, `FATAL` 0; token-leak grep 0 with the seeded control 1; the bake +script's fingerprint equal across the hop. Vouch: `golden_version 0.232.0 → 0.236.0`, `agent_version` +0.130.0 and `min_agent` 0.129.0 unchanged, re-read from the page, R-120 banner absent; floor +`0.232.0 → 0.236.0` re-read. **No box moved — both already ran 0.236.0 by hand**; the chain was last +exercised 2026-09-01 and nothing about it changed. This bake carried four unbaked releases and is +the last per-release one. **No `--no-verify` anywhere in this session.** + +## 5. Files created / modified + +**app-catalog-felhom.eu** (pushed `3525e35`): `templates/{bookstack,kimai,nextcloud,romm}/docker-compose.yml`, +`scripts/check-engine-major.py` (new), `scripts/test_gate_decoys.py` (new), `scripts/catalog_gates.py`, +`scripts/test_catalog_gates.py`, `.githooks/pre-push`, `CLAUDE.md`, `REUSE.md`, `CHANGELOG.md`, `REPORT.md`. + +**felhom.eu**: `scripts/golden_currency_gate.py`, `scripts/test_golden_currency_gate.py`, +`scripts/CHANGELOG.md`, `documentation/tests/golden-waiver.yml` (new), +`documentation/tests/golden-0.236.0-2026-09-13/` (new, 12 files), +`documentation/audits/r459-close-2026-09-13/` (new, 36 files), +`documentation/runbooks/RUNBOOK-manual-build.md` (§4.2), `CLAUDE.md` (checklist step), +`documentation/architecture/09-update-architecture.md` (§3 decisions 5 and 6, §8.7, engines section), +`documentation/backlog/OPEN-ITEMS.md`, `documentation/backlog/CLOSED-ITEMS.md`, `CONTEXT.md`, `STATUS.md`, this file. + +## 6. Tests + +| suite | before | after | +|---|---|---| +| `app-catalog/scripts/test_catalog_gates.py` | 5 | **7**, green | +| `app-catalog/scripts/test_gate_decoys.py` | — | **7 cases**, green | +| `felhom.eu/scripts/test_golden_currency_gate.py` | 4 | **19 cases**, green | +| `felhom.eu/scripts/repo_gates.py --fast` | 14 gates | 14 gates, **all OK** | +| `felhom.eu/scripts/decoy_coverage_gate.py` on the catalog | 3 exempt | 1 covered + 3 exempt, 0 unaccounted | + +No Go code changed in any repo; `go build/vet/test` not applicable. + +## 7. Register — rows opened / closed, size + +Closed: **R-459** (harness + live evidence), **R-467** (the bake). Narrowed: **R-242** (waiver half built; +vouch half open). Opened: **R-468** (WATCHING — the waiver; renew ≤ 14 days or bake; retire at the +first external install), **R-469** (BLOCKED on R-448 — remove the engine-major rule), **R-470** +(READY — MinAgent header line), **R-471** (READY — observations decoy hole, pre-existing). +Register size: **210 open rows / 169 closed before → 212 open / 171 closed after** (R-459 and R-467 +compressed to `CLOSED-ITEMS.md`; nothing deleted). OPEN-ITEMS.md bytes: see the compression commit. + +## 8. Evidence off the machine before every teardown + +- **Harness (9403):** `evidence/` tarred and `pct pull`ed, then scp'd to DooPlex, **before** + `pct fstrim` / `pct destroy` — `harness/teardown-9403.txt`. +- **Bake (drill VM):** `bake.log` scp'd out and markers counted **before** `pct destroy 9100`, the + `shred -u` and the `poweroff` — `05-teardown.txt`, leftovers in the VM: 0. +- **Live (9201):** baseline captured **before** the push; after-sync and after-restart captured at + the moment; nothing on 9201 was reverted. ## 9. Teardown — three layers -| layer | result | -|---|---| -| **1 — machine** | guest **9402 destroyed**; `pct list` shows only 9201. `scratch-r459` **removed**. Downloaded template deleted. | -| **2 — host** | **`local-lvm` 30.53 % before and after — never touched.** `local` 19 630 088 → 19 631 740 KiB (+1.6 MB). `pct fstrim 9402`: **35.9 GiB trimmed**. Guest peak 3.2 GB / 2.10 GB images. | -| **3 — hub** | **Checked, not asserted:** `/hosts` = exactly `demo-felhom-8363b5`, `demo-hp-bb76ea`; **0 customers**. **This run created no customer, no appliance, no host record.** | +| layer | before | after | +|---|---|---| +| **1 — machines** | LXC 9403 on demo-hp (scratch dir storage `scratch-r459c` at `/mnt/hdd_1`); LXC 9100 inside the drill VM | 9403 **destroyed**, storage **removed**, template deleted, `pct list` shows only 9201; 9100 **destroyed**, drill VM **powered off**, `qemu` confirmed exited (`ps -eo comm`), disk reverted to the single `virgin` snapshot | +| **2 — hosts** | demo-hp `local-lvm` **35.32 %**, `local` 20 899 060 KiB, `/mnt/hdd_1` 5 774 620 KiB | `local-lvm` **35.32 % — never touched**; `local` 20 908 828 KiB (+9.5 MB); `/mnt/hdd_1` **5 774 620 KiB — identical**; `pct fstrim 9403` returned 55.5 GiB; guest peak 3.3 GB (2.21 GB images). DooPlex `/mnt/5_hdd` 37 % before and after | +| **3 — hub** | 2 enrolled hosts | **Checked, not asserted** (`harness/teardown-layer3-hub.txt`): `/hosts` lists exactly `demo-felhom-8363b5` and `demo-hp-bb76ea`; **this run created no customer, no appliance and no host record** — 9403 never enrolled, 9100 is the bake fixture. The hub's ONLY change is the vouch + floor, which is the deliverable. | -Evidence off after **each arm**, before teardown: `documentation/audits/r459-spike-2026-09-06/` -(20 files, 164 KB). Scanned for secrets before commit: clean. +Helper files on demo-hp (`ctrl_pw`, `dh_user`, `dh_pat`, `upg.tgz`, `guest-setup.sh`, logs) were +`shred -u`'d / removed; the Docker Hub login inside 9403 was logged out before the guest was destroyed. -## 10. Claims in the task that turned out to be wrong, named +## 10. NOT live-validated — stated plainly -1. **§11's venue is still stale, exactly as R-461 records. `/mnt/nvme-1tb` does not exist** — the NVMe - is at `/mnt/hdd_1`. The scratch storage went at *its* root, honouring the rule's reason; `local-lvm` - read 30.53 % before and after. **`drill-r50` (VM 300) still does not exist** — `qm list` returns - nothing. Both were already filed as R-461 yesterday; this run is the second session to work around - them, which is the cost that row predicts. -2. **§6 Observable 2 assumed a check mode would exist but told me not to assume its flag — correct, - and the caution earned its place.** The flag is `--check-if-upgrade-is-needed`, and **its exit-code - polarity is the reverse of the usual convention** (0 = work needed). Assuming either the name or the - polarity would have inverted the headline. -3. **§7's Outcome B was the expected result and it is FALSE.** The abort survives a real conversion. - The task was right to name three outcomes and to say "do not steer" — the run steered nowhere and - landed outside the shape the brief most anticipated. -4. **§9's Postgres numbers were exact**: 11 templates, 8 on `postgres:16-alpine`, register grep 0. -5. **§4.7's pointer was right** — `mariadb_upgrade_info` was already visible in the persistence-sweep - probe, and it is the observable that carried this task. +- **The waiver in the "behind" state on the real tree, after this push:** it is dormant (the golden is + current). Its real-tree behaviour was proven **before** the bake (§3 E, red-proof); after today it is + exercised the next time a release ships without a bake — which is the intended cadence. +- **The self-update chain for 0.236.0:** not re-exercised (both boxes were already there). Last proof + 2026-09-01. +- **Kimai, Nextcloud, RomM under an actual engine major move:** the setting is inert until their pins + move, and the engine-major rule forbids that until Slice 4. Only bookstack has a measurable edge. +- **The engine-major gate in CI:** cannot run there (`--depth 1`); the hook is the enforcement. ## 11. Observations — noticed, documented, NOT acted on -1. **`mariadb-upgrade` without credentials returns a confident-looking failure that is an auth error.** - **FILED: R-464**, which carries it as the second half of the row. -2. **The conversion leaves its own backup in the datadir** (`system_mysql_backup_*.sql.zst`, 622 437 - bytes here), which any volume-level backup will then copy. **NOT-A-FINDING: it is upstream's - deliberate safety net and it is harmless; recording it in the audit is enough to stop the next - person reporting an unexplained file.** -3. **Python heredocs do not survive three shells (`ssh` → `pct exec` → `bash`).** Two scripts had to be - written locally and pushed as files. **NOT-A-FINDING: it is a working technique, not a property of - the product, and it is now written into the audit where the next session will meet it.** +1. **`felhom.eu/scripts/test_gate_decoys.py` reports a LIVE HOLE at HEAD, before this session:** + `observations/R-419: decoy PASSED (rc=0)` — the gate scans the report's first `Observations` + section and not an appended second one. Reproduced on a clean worktree of `4b2e560`. **FILED: R-471.** +2. **Four consecutive controller CHANGELOG headers carry no `MinAgent:` line** while the vouch runbook + says to read it from the header. **FILED: R-470.** +3. **`POST /api/stacks//restart` recreated only the changed service** (`bookstack-db` got a new + ID; the `bookstack` app container kept its 4-hour uptime) — it is `compose up -d`, as + `09-update-architecture.md` §1.3 records as a chosen behaviour. **NOT-A-FINDING: documented + design; the message "restart completed" is accurate for a compose-level restart.** +4. **`mariadb:12.3` resolved to 12.3.3 in the harness and 12.3.2 on 9201** — the floating-pin class. + **NOT-A-FINDING: already R-446.** +5. **`target-selection.md` names `/mnt/nvme-1tb`, which does not exist on demo-hp.** **NOT-A-FINDING: + already R-461, and it says exactly this.** +6. **The session ran with permission prompts disabled**, which the workspace `CLAUDE.md` says not to do + on this host. Nothing outside the workspace, `~/build`, the drill directory and the two Tier-0 + boxes was touched; every host-side act is listed in §9. **NOT-A-FINDING: an operator setting, not + a product defect; recorded so it is not hidden.** diff --git a/STATUS.md b/STATUS.md index 180f4c47..2d5c58e2 100644 --- a/STATUS.md +++ b/STATUS.md @@ -1,5 +1,11 @@ # STATUS — what works, what's broken, what's next +**Updated 2026-09-13 (second pass) — you decided both open items. The database engine now finishes +its own conversion on the four MariaDB apps; the upgrade machine proved it and it landed on the HP +without a ripple. Goldens are now weekly and before any install, not per release, and the gate +knows: it reads a dated permission slip that runs out after 14 days. Today's golden (0.236.0) is +baked and live. Nothing needs you.** + **Updated 2026-09-13 — "delete my data too" now deletes the data, or tells you it could not. Until today the box said it worked and left everything on the drive. Live on both machines (0.236.0), proven on the HP with a throwaway Nextcloud. Nothing needs you. Item 7 is closed: you decided it on 2026-09-02 and the page still listed it open.** **Updated 2026-09-06 (third pass) — I chased down the BookStack database problem I found this @@ -205,73 +211,22 @@ nothing.* version and look unwell when it is fine. **It cannot lose data — the worst case is a false alarm.** Freezing that file too would break the „Frissítés elérhető" label, which is a worse trade. -11. **How wide should I take the upgrade testing? This is the one decision from today, and it is - about money and time, not about safety.** +11. ~~**How wide should I take the upgrade testing?**~~ **DECIDED 2026-09-13: as wide as possible, + through the nightly unattended sessions.** Every app gets its turn as the nightly rotation reaches + it, one hand-written way in per app. The apps that can only be reached through a browser wait for + the sessions that run on your Windows machine with Chrome, where the machine can click. Written + into the update architecture as decision 6. **Nothing to do.** - **What I built.** A machine that installs an app, puts real data in through the app's own front - door, upgrades it, and then asks the app for the data back. Not "did it start" — the box has - already fooled us that way once. - - **I also taught it to fail.** Before believing anything, I pointed it at an upgrade I knew was - broken. It came back red. That is why I trust the greens. - - **What it found, on three apps and five real upgrades.** - - **The data survived every single time.** That is the good news and it is worth having. - - **Whether an upgrade can be UNDONE depends on the app, not on upgrades.** Docmost will not go - back — the old version refuses to start on the changed data. PrivateBin goes back fine. **We - had been assuming one answer for all 53 apps. There isn't one.** - - **And it found a real problem in our own BookStack setup.** Our template moves the database - engine to a new major version, and the engine says, in its own words, that the conversion it - needs is being *skipped*. It works today. **I did not measure whether it ever breaks**, and I - am not going to guess. - - **The decision: how many of the 53 apps do I test?** - - - **Only the apps that keep data in a database (~25).** Today's run showed the undo question only - ever bites there. **Cost: roughly a day of my time.** - - **All 53.** Complete, and it gives us a list nobody has. **Cost: several days**, and the reason - is not the machines — it is that **each app needs its own hand-written way in**, and that work - does not get cheaper the more you do. Two of today's three needed one, and one of them took two - attempts. - - **My pick: the database ones first.** It answers the question that changes the product, and if it - goes well the rest is a decision you can take later with better numbers. - - **If you do nothing:** nothing breaks. The machine is built and committed, so it does not go - stale, and the BookStack problem is written down and waiting either way. - -12. **Shall I tell the database engine to finish its own conversion? One yes/no. It affects four - apps and I have measured both sides.** - - **The background, in one line.** This morning I found that when BookStack's database engine moves - to a new major version, the engine says the conversion it needs is being **skipped** — and then - works anyway. - - **What I measured this afternoon.** - - **It does not get worse.** I restarted it five times. The app answered correctly all five - times, and nothing changed for the worse. - - **But it never fixes itself either.** Every single time it starts, the engine says the check is - still needed. It will say that forever. - - **Fixing it takes seven seconds.** The engine backs itself up first, does the conversion, done. - - **And the catch I was worried about is not there.** I expected that converting properly would - mean we could no longer go back to the old version. **We still can** — I tried it, and the app - came back with its data. - - **So this is not the difficult trade I thought I would be bringing you. It is a cheap tidy-up.** - - - **Yes, turn it on.** Four apps get a correctly-converted database — BookStack, Kimai, Nextcloud - and RomM. Costs seven seconds the one time each of them moves a major version. **This is what I - would do.** - - **No, leave it.** Nothing breaks today. The engine keeps saying it wants a check, on every - start, indefinitely. - - **One honest limit on my "yes".** I proved the app's normal use keeps working. I did **not** test - every database feature on an unconverted engine — so I can tell you it has not broken, not that - nothing can. That is exactly why leaving it alone is a real choice and not just laziness. - - **If you do nothing:** nothing breaks and nothing is at risk this week. Only BookStack has - actually moved a major version so far; the other three will land in the same place when their - turn comes. I have not changed any template — this is your call, not a quiet edit. +12. ~~**Shall I tell the database engine to finish its own conversion?**~~ **DECIDED YES 2026-09-13, + and shipped the same day.** The four MariaDB apps — BookStack, Kimai, Nextcloud, RomM — now carry + one setting that lets the engine convert its own files when it moves to a new major version. + Seven seconds, and it backs itself up first. **Proven before it shipped:** the upgrade machine + re-ran the BookStack edge and this time the engine says, in its own words, that it is already + upgraded — the "skipped" line is gone, and the data read back afterwards. **Watched as it landed:** + the change reached the HP on the normal 15-minute cycle, nothing restarted by itself, and one + deliberate restart came back clean with the app serving. **The rule until the next piece is built:** + the Update button still takes no backup, so no app may move a database engine across a major + version until it does — a gate refuses such a change at push time. **Nothing to do.** 13. **"Delete my data too" now deletes the data — or tells you it could not.** Until today, when a customer removed an app and ticked the box, the box said it worked and left everything on the drive (128 MB of a Nextcloud on 2026-09-01). The cause: the removal asked one global setting for the drive, and no machine fills that setting in. Every other part of the box already asks the app itself where its data is. Now the removal does too. If the box cannot work out where the data is, it refuses and keeps the app, so you can try again — it never again reports success over data left behind. Proven on the HP with a throwaway Nextcloud: 63 MB the app wrote itself was gone after removal, and the answer listed it; the refusal was shown with the app still in place; an app with no drive data gets a plain "nothing to delete" note. Live on both machines (0.236.0). No standing app was touched. **If you do nothing:** nothing to do. @@ -281,6 +236,17 @@ nothing.* ## Decided — and what would reopen each +- **GOLDENS ARE NOW WEEKLY AND BEFORE ANY INSTALL, NOT PER RELEASE — AND THE GATE KNOWS. DECIDED 2026-09-13.** + In August I baked 25 goldens in 26 days, almost one per release, because the check trips on every + release on purpose. From today: one golden a week, and always before a drill or a fresh install. + Every release still reaches both demo machines in about 20 seconds — only the image a **new** + machine starts from moves to a cadence. The check now reads a dated permission slip that runs out + after at most 14 days; while it is valid the check warns instead of refusing, and when it runs out + the check is red again until someone bakes or renews. A dated slip cannot be forgotten — it just + expires. Today's golden (0.236.0) is baked, checked three ways, and live. + **Reopens if:** the first outside customer installs (the slip is retired then), or a fresh install + ever lands on a golden older than the week. + - **THE BACKUP AND RESTORE WORK IS FINISHED FOR BETA. DECIDED 2026-09-01.** **What is done, and proven on the real machines:** everything **you or a customer** does alone — getting deleted files back, getting an app's data back, getting a whole app back, and losing a diff --git a/documentation/architecture/09-update-architecture.md b/documentation/architecture/09-update-architecture.md index f0aa4771..7392192a 100644 --- a/documentation/architecture/09-update-architecture.md +++ b/documentation/architecture/09-update-architecture.md @@ -125,6 +125,35 @@ These are rulings, not proposals. Anything specced against a different assumptio **It does NOT make the Update button safer.** That is slice 4 (R-448), and it is where the backup precondition goes. Slice 3 only stops the other twelve paths from doing the update's job. +### 2026-09-13 — the database engine finishes its own conversion, and the upgrade test goes wide + +5. **DBs should be updated when the app moves, with proper precautions, tests and backoff plans** + — the operator's own words, ruling on `SPIKE-r459-mariadb-upgrade-2026-09-06.md`. SHIPPED in the + catalog the same day: every `mariadb:` sidecar (`bookstack-db`, `kimai-db`, `nextcloud-db`, + `romm-db`) carries `MARIADB_AUTO_UPGRADE=1`; `MARIADB_DISABLE_UPGRADE_BACKUP` stays unset. **Not an + image change, so `catalog_since` does not move.** The three precautions, because they are the real + content of the ruling: + 1. **Proven before it ships** — `upgrade-test.py` re-ran E3 and E3b on the changed template and the + engine-state field shows the conversion RAN (`mariadb_upgrade_info` reads the new version, the + engine's own check says nothing further is needed, the entrypoint no longer prints + `skipped due to $MARIADB_AUTO_UPGRADE`), with the seeded data reading back after. C3 still + returns `failed`. Evidence: `audits/r459-close-2026-09-13/`. + 2. **Watched as it lands** — the change travelled the real 15-minute cycle to demo-hp: the live + compose gained the setting, the sync recreated nothing, and one deliberate restart logged + `MariaDB upgrade not required` with the app serving (same evidence directory). + 3. **A rule until Slice 4 is built** — the Update button still takes no backup, so **no template + may move a database-engine image across a major version until R-448 ships.** Catalog + `CLAUDE.md` states it; `scripts/check-engine-major.py` enforces it in the pre-push hook (the + CI half cannot, R-452); its removal is tracked as **R-469** so it is a deliberate act. + The setting is inert until an engine major moves, and precaution 3 keeps it that way. + +6. **The upgrade test goes as wide as possible, through the nightly unattended sessions** — the + ruling on `STATUS.md` item 11. Not "the ~25 database apps first": all of them, as the nightly + rotation reaches them, one fixture per app through the app's own interface. **Browser-only apps + become reachable when CC runs on the operator's Windows workstation with Chrome** — the + `claude-in-chrome` route that DooPlex does not have — so an app recorded `inconclusive` for want + of a headless seed route (bookstack's file half, R-460) is deferred to that venue, not faked. + --- ## 4. The vocabulary ruling — "rollback" is struck @@ -314,6 +343,10 @@ app-half edge cannot produce and which no amount of readability would have surfa restarts, no degradation, and the engine says `Check required!` every time, forever). Converting properly **succeeds**, costs **7 s**, takes its own system-database backup, and **does not** cost the ability to abort. **The trade that was expected here does not exist.** +- **2026-09-13 — the setting is in the catalog.** All four `mariadb:` sidecars carry + `MARIADB_AUTO_UPGRADE=1` (operator ruling, §3 decision 5), and `upgrade-test.py`'s engine-state field + now shows the conversion RUNNING on the bookstack edges. **And a gate holds the engines inside their + major until Slice 4:** `app-catalog-felhom.eu/scripts/check-engine-major.py` (R-469). **Two rules for anything this arc builds around a database engine:** @@ -428,10 +461,12 @@ Version strings stay in the logs, the API and the hub. 6. **The Update button is still unguarded.** It takes no backup, has no rollback, and can still attempt a multi-major jump the app will refuse (R-40). **Slice 3 did not change that and must not be read as having done so** — the precondition is slice 4 (R-448). -7. **An engine major can be applied without its datadir upgrade, and nothing notices.** Measured - 2026-09-06: the catalog's own bookstack transition starts MariaDB 12.3 on an 11.6 datadir, and the - image logs that the required upgrade was **skipped** because the template sets no - `MARIADB_AUTO_UPGRADE`. The app serves. Whether that ever breaks is **not** established. **R-459.** +7. ~~**An engine major can be applied without its datadir upgrade, and nothing notices.**~~ **CLOSED + 2026-09-13 for MariaDB (R-459):** every `mariadb:` sidecar carries `MARIADB_AUTO_UPGRADE=1`, and the + harness shows the conversion running on the E3/E3b edges (§3 decision 5). **What stays true:** the + PostgreSQL half (R-463) has no equivalent — the image performs no `pg_upgrade` — and the + engine-major rule (§3 precaution 3, R-469) is what keeps both engines inside their major until + Slice 4 gives the Update button a backup. 8. **Only three of 53 apps have ever had an upgrade measured**, and one of them (bookstack) can only be half-proven headlessly (**R-460**). The widening is **R-462**, costed with real numbers. 9. **The hub does not record image tags at all.** Its report's container payload carries name, state, diff --git a/documentation/audits/r459-close-2026-09-13/engine-major-gate/redproof-7-cases.txt b/documentation/audits/r459-close-2026-09-13/engine-major-gate/redproof-7-cases.txt new file mode 100644 index 00000000..ab332255 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/engine-major-gate/redproof-7-cases.txt @@ -0,0 +1,16 @@ + ok FACT: kimai-db mariadb:11.6 -> 12.3 (cross-major) rc=1 (expected 1) +engine-major gate — range HEAD~1..HEAD: 1 compose file(s) changed, 1 engine pin(s) compared + +ENGINE-MAJOR GATE FAILED: templates/kimai/docker-compose.yml service kimai-db moves mariadb 11 -> 12 (mariadb:11.6 -> mariadb:12.3). +RULE (app-catalog CLAUDE.md, operator ruling 2026-09-13): until the Update button takes a VERIFIED BACKUP as its precondition (Slice 4, felhom.eu OPEN-ITEMS.md R-448), no template may move a database-engine image across a MAJOR version. +WHY: MariaDB sidecars now carry MARIADB_AUTO_UPGRADE=1 and WILL convert the customer's datadir on the next Update; PostgreSQL's image refuses to start on an older major's datadir (R-463). Either way this is a customer-data event with no backup in front of it. +EXPIRY: this rule is removed DELIBERATELY when R-448 ships — the removal is its own register row, not a silent edit. Until then, keep the engine within its major. + + ok FACT: docmost-postgres postgres:16-alpine -> 17-alpine rc=1 (expected 1) + ok FACT: kimai-db mariadb:11.6 -> mariadb:lts (major unreadable) rc=2 (expected 2) + ok GENUINE: kimai-db mariadb:11.6 -> 11.8 (within major) rc=0 (expected 0) + ok DECOY: major moves only in a comment + serverVersion env rc=0 (expected 0) + ok DECOY: the APP image crosses a major (kimai 2.57 -> 3.0) rc=0 (expected 0) + ok DECOY: 'mariadb:12.3' lands in README.md, not a template rc=0 (expected 0) + +catalog gate decoys OK — 7 case(s), every label judged on its fact (R-421) diff --git a/documentation/audits/r459-close-2026-09-13/golden-waiver-states/00-real-tree-before-bake-no-waiver.txt b/documentation/audits/r459-close-2026-09-13/golden-waiver-states/00-real-tree-before-bake-no-waiver.txt new file mode 100644 index 00000000..5f7e071b --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/golden-waiver-states/00-real-tree-before-bake-no-waiver.txt @@ -0,0 +1,8 @@ + newest released controller : 0.236.0 (## v0.236.0 — "delete my data too" deletes the data, or says that it could not (2026-09-13) + newest golden baked : 0.232.0 (documentation/tests/golden-0.232.0-2026-09-01 [sha 5f8a53ed5b19…]) + +GOLDEN CURRENCY GATE FAILED: controller v0.236.0 is released and NO golden carries it (newest bake is 0.232.0; 4 release(s) behind). +A machine installed right now would receive v0.232.0 — the release is written, tested and pushed, and NOT delivered. +Fix: bake a golden per documentation/runbooks/RUNBOOK-manual-build.md §4.1, then vouch it (a THREE-field change: golden_version + agent_version + min_agent). +If the cadence ruling covers this release, issue a DATED waiver at documentation/tests/golden-waiver.yml (RUNBOOK-manual-build.md §4.2) — never a bypass. +rc=1 diff --git a/documentation/audits/r459-close-2026-09-13/golden-waiver-states/E-valid-waiver-behind.txt b/documentation/audits/r459-close-2026-09-13/golden-waiver-states/E-valid-waiver-behind.txt new file mode 100644 index 00000000..fe7523a4 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/golden-waiver-states/E-valid-waiver-behind.txt @@ -0,0 +1,12 @@ +=== NEW gate (scripts/golden_currency_gate.py) === + newest released controller : 9.9.9 (## v9.9.9 — synthetic) + newest golden baked : 9.9.7 (documentation/tests/golden-9.9.7-2026-01-01 [sha 9287f7cef5f1…]) + waiver : VALID until 2026-09-26 (13 day(s) left) — R-468, reason: pre-customer development; goldens weekly (operator ruling 2026-09-13) + +GOLDEN CURRENCY GATE ADVISORY — WAIVED, NOT CLEAN: controller v9.9.9 is released and NO golden carries it (newest bake is 9.9.7; 2 release(s) behind: 9.9.8, 9.9.9). +A machine installed right now would receive v9.9.7 and reach v9.9.9 by self-update. +Waived by R-468 until 2026-09-26 (13 day(s) left): pre-customer development; goldens weekly (operator ruling 2026-09-13) +This is the operator's 2026-09-13 cadence ruling, not a pass: bake weekly and before ANY drill or fresh install (RUNBOOK-manual-build.md §4.2). When the waiver expires this gate is red again. +golden currency gate OK (WAIVED) — the newest released controller has NO golden; a valid waiver covers it (NOTE: this checks the BAKE, not the vouch) + +exit=0 diff --git a/documentation/audits/r459-close-2026-09-13/golden-waiver-states/F-expired-waiver-behind.txt b/documentation/audits/r459-close-2026-09-13/golden-waiver-states/F-expired-waiver-behind.txt new file mode 100644 index 00000000..a696869b --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/golden-waiver-states/F-expired-waiver-behind.txt @@ -0,0 +1,12 @@ +=== NEW gate (scripts/golden_currency_gate.py) === + newest released controller : 9.9.9 (## v9.9.9 — synthetic) + newest golden baked : 9.9.7 (documentation/tests/golden-9.9.7-2026-01-01 [sha 9287f7cef5f1…]) + waiver : EXPIRED on 2026-09-12 (R-468) + +GOLDEN CURRENCY GATE FAILED: controller v9.9.9 is released and NO golden carries it (newest bake is 9.9.7; 2 release(s) behind). +The waiver at documentation/tests/golden-waiver.yml EXPIRED on 2026-09-12 (R-468). It ran out, as a dated waiver is meant to: bake a golden, or renew it with a new dated commit (at most 14 days). +A machine installed right now would receive v9.9.7 — the release is written, tested and pushed, and NOT delivered. +Fix: bake a golden per documentation/runbooks/RUNBOOK-manual-build.md §4.1, then vouch it (a THREE-field change: golden_version + agent_version + min_agent). +If the cadence ruling covers this release, issue a DATED waiver at documentation/tests/golden-waiver.yml (RUNBOOK-manual-build.md §4.2) — never a bypass. + +exit=1 diff --git a/documentation/audits/r459-close-2026-09-13/golden-waiver-states/G-valid-waiver-unrecorded.txt b/documentation/audits/r459-close-2026-09-13/golden-waiver-states/G-valid-waiver-unrecorded.txt new file mode 100644 index 00000000..2f331c6b --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/golden-waiver-states/G-valid-waiver-unrecorded.txt @@ -0,0 +1,12 @@ +=== NEW gate (scripts/golden_currency_gate.py) === + newest released controller : 9.9.9 (## v9.9.9 — synthetic) + newest golden baked : 9.9.8 (documentation/tests/golden-9.9.8-2026-01-01 [sha 9287f7cef5f1…]) + waiver : VALID until 2026-09-26 (13 day(s) left) — R-468, reason: pre-customer development; goldens weekly (operator ruling 2026-09-13) + +GOLDEN CURRENCY GATE FAILED: golden 9.9.8 is baked but UNRECORDED — the controller CHANGELOG has no '## v9.9.8' heading. +A waiver exists (R-468, until 2026-09-26) and DOES NOT COVER THIS: it covers a golden that is behind the record, never one that is unrecorded (R-385). +The newest heading is 9.9.9. A golden ahead of the record was built from a version nobody wrote down, so no one can read what the fleet is running. +Fix: give v9.9.8 its own '## v9.9.8 — ' heading in felhom-controller/CHANGELOG.md, above the entries it supersedes. If its fix is currently described inside another version's entry, MOVE that text — do not duplicate it, and do not delete the reasoning. +If this bake was a throwaway that must never be delivered, delete its documentation/tests/golden--/ directory — never leave it to read as shipped. + +exit=1 diff --git a/documentation/audits/r459-close-2026-09-13/golden-waiver-states/H-15day-waiver.txt b/documentation/audits/r459-close-2026-09-13/golden-waiver-states/H-15day-waiver.txt new file mode 100644 index 00000000..53bfa457 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/golden-waiver-states/H-15day-waiver.txt @@ -0,0 +1,8 @@ +=== NEW gate (scripts/golden_currency_gate.py) === + newest released controller : 9.9.9 (## v9.9.9 — synthetic) + newest golden baked : 9.9.7 (documentation/tests/golden-9.9.7-2026-01-01 [sha 9287f7cef5f1…]) + +GOLDEN CURRENCY GATE INCONCLUSIVE: the waiver at ../../../../../tmp/tmpiiph1vyo/golden-waiver.yml is MALFORMED — `expires:` is 15 days after `issued:` — the hard limit is 14. A waiver that tries to be permanent is refused; renew it with a new dated commit instead. +A malformed waiver is neither cover nor absence. Fix it (four lines: issued, expires <= 14 days later, reason, register_row) or delete it. + +exit=2 diff --git a/documentation/audits/r459-close-2026-09-13/golden-waiver-states/H-decoy-only-the-word-expires.txt b/documentation/audits/r459-close-2026-09-13/golden-waiver-states/H-decoy-only-the-word-expires.txt new file mode 100644 index 00000000..9354d291 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/golden-waiver-states/H-decoy-only-the-word-expires.txt @@ -0,0 +1,8 @@ +=== NEW gate (scripts/golden_currency_gate.py) === + newest released controller : 9.9.9 (## v9.9.9 — synthetic) + newest golden baked : 9.9.7 (documentation/tests/golden-9.9.7-2026-01-01 [sha 9287f7cef5f1…]) + +GOLDEN CURRENCY GATE INCONCLUSIVE: the waiver at ../../../../../tmp/tmp04cax9by/golden-waiver.yml is MALFORMED — `issued:` is absent or not a YYYY-MM-DD date (got '') +A malformed waiver is neither cover nor absence. Fix it (four lines: issued, expires <= 14 days later, reason, register_row) or delete it. + +exit=2 diff --git a/documentation/audits/r459-close-2026-09-13/golden-waiver-states/REDPROOF-old-vs-new-real-tree-with-valid-waiver.txt b/documentation/audits/r459-close-2026-09-13/golden-waiver-states/REDPROOF-old-vs-new-real-tree-with-valid-waiver.txt new file mode 100644 index 00000000..7a2a0ec8 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/golden-waiver-states/REDPROOF-old-vs-new-real-tree-with-valid-waiver.txt @@ -0,0 +1,23 @@ +=== REAL TREE (0.236.0 released, newest golden 0.232.0 — BEHIND), valid waiver planted, R-468 exists === + +--- OLD gate (HEAD before this task) --- + newest released controller : 0.236.0 (## v0.236.0 — "delete my data too" deletes the data, or says that it could not (2026-09-13) + newest golden baked : 0.232.0 (documentation/tests/golden-0.232.0-2026-09-01 [sha 5f8a53ed5b19…]) + +GOLDEN CURRENCY GATE FAILED: controller v0.236.0 is released and NO golden carries it (newest bake is 0.232.0). +A machine installed right now would receive v0.232.0 — the release is written, tested and pushed, and NOT delivered. +Fix: bake a golden per documentation/runbooks/RUNBOOK-manual-build.md §4.1, then vouch it (a THREE-field change: golden_version + agent_version + min_agent). +If this release deliberately needs no golden, record a waiver in documentation/backlog/OPEN-ITEMS.md — never a bypass. +exit=1 + +--- NEW gate --- + newest released controller : 0.236.0 (## v0.236.0 — "delete my data too" deletes the data, or says that it could not (2026-09-13) + newest golden baked : 0.232.0 (documentation/tests/golden-0.232.0-2026-09-01 [sha 5f8a53ed5b19…]) + waiver : VALID until 2026-09-27 (14 day(s) left) — R-468, reason: pre-customer development; goldens on a weekly cadence (operator ruling 2026-09-13) + +GOLDEN CURRENCY GATE ADVISORY — WAIVED, NOT CLEAN: controller v0.236.0 is released and NO golden carries it (newest bake is 0.232.0; 4 release(s) behind: 0.233.0, 0.234.0, 0.235.0, 0.236.0). +A machine installed right now would receive v0.232.0 and reach v0.236.0 by self-update. +Waived by R-468 until 2026-09-27 (14 day(s) left): pre-customer development; goldens on a weekly cadence (operator ruling 2026-09-13) +This is the operator's 2026-09-13 cadence ruling, not a pass: bake weekly and before ANY drill or fresh install (RUNBOOK-manual-build.md §4.2). When the waiver expires this gate is red again. +golden currency gate OK (WAIVED) — the newest released controller has NO golden; a valid waiver covers it (NOTE: this checks the BAKE, not the vouch) +exit=0 diff --git a/documentation/audits/r459-close-2026-09-13/harness/C3/abort-states.json b/documentation/audits/r459-close-2026-09-13/harness/C3/abort-states.json new file mode 100644 index 00000000..f7a71c94 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/C3/abort-states.json @@ -0,0 +1,8 @@ +{ + "privatebin": { + "status": "running", + "health": "healthy", + "restarts": 0, + "exit": 0 + } +} \ No newline at end of file diff --git a/documentation/audits/r459-close-2026-09-13/harness/C3/compose-final.log b/documentation/audits/r459-close-2026-09-13/harness/C3/compose-final.log new file mode 100644 index 00000000..de7a9d3e --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/C3/compose-final.log @@ -0,0 +1,5 @@ +privatebin | [13-Sep-2026 09:52:04] NOTICE: fpm is running, pid 11 +privatebin | [13-Sep-2026 09:52:04] NOTICE: ready to handle connections +privatebin | 127.0.0.1 - - [13/Sep/2026:09:52:09 +0200] "GET / HTTP/1.1" 200 15569 "-" "Wget" "-" +privatebin | 172.18.0.1 - - [13/Sep/2026:09:52:09 +0200] "GET / HTTP/1.1" 200 22914 "-" "curl/8.14.1" "-" +privatebin | 172.18.0.1 - - [13/Sep/2026:09:52:09 +0200] "GET /?pasteid=95d75dc1cf5feaba HTTP/1.1" 200 311 "-" "curl/8.14.1" "-" diff --git a/documentation/audits/r459-close-2026-09-13/harness/C3/engine-state.json b/documentation/audits/r459-close-2026-09-13/harness/C3/engine-state.json new file mode 100644 index 00000000..ec747fa4 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/C3/engine-state.json @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/documentation/audits/r459-close-2026-09-13/harness/C3/migration-lines.txt b/documentation/audits/r459-close-2026-09-13/harness/C3/migration-lines.txt new file mode 100644 index 00000000..e69de29b diff --git a/documentation/audits/r459-close-2026-09-13/harness/C3/run.log b/documentation/audits/r459-close-2026-09-13/harness/C3/run.log new file mode 100644 index 00000000..3db43dac --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/C3/run.log @@ -0,0 +1,14 @@ +[07:42:55] C3: deploying privatebin at FROM {'privatebin': 'privatebin/pdo:2.0.5'} +[07:43:01] FROM settled=True in 5.2s :: {"privatebin": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}} +[07:43:01] privatebin: seeded paste id=95d75dc1cf5feaba +[07:43:01] privatebin: readback http=200 marker_present=True +[07:43:01] C1 (seed reads back BEFORE): True +[07:43:01] C3: swapping to TO {'privatebin': 'alpine:3.20'} +[07:43:02] TO up -d rc=0 +[07:50:03] TO settled=False in 421.1s :: {"privatebin": {"status": "restarting", "health": "unhealthy", "restarts": 0, "exit": 0}} +[07:50:03] migration lines observed: 0 +[07:52:03] app never answered on http://invalid:8080/ (last rc=6 code=000) +[07:52:03] RESULT (seed reads back AFTER): False +[07:52:03] C3: ABORT — putting the FROM images back +[07:52:09] privatebin: readback http=200 marker_present=True +[07:52:09] ABORT: app came back in 5.2s; data present=True \ No newline at end of file diff --git a/documentation/audits/r459-close-2026-09-13/harness/C3/to-full.log b/documentation/audits/r459-close-2026-09-13/harness/C3/to-full.log new file mode 100644 index 00000000..e69de29b diff --git a/documentation/audits/r459-close-2026-09-13/harness/C3/to-states.json b/documentation/audits/r459-close-2026-09-13/harness/C3/to-states.json new file mode 100644 index 00000000..04f4a178 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/C3/to-states.json @@ -0,0 +1,8 @@ +{ + "privatebin": { + "status": "restarting", + "health": "unhealthy", + "restarts": 0, + "exit": 0 + } +} \ No newline at end of file diff --git a/documentation/audits/r459-close-2026-09-13/harness/C3/verdict.json b/documentation/audits/r459-close-2026-09-13/harness/C3/verdict.json new file mode 100644 index 00000000..57b1902e --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/C3/verdict.json @@ -0,0 +1,24 @@ +{ + "harness_version": 1, + "edge": "C3", + "app": "privatebin", + "note": "NEGATIVE control: the TO image starts and exits immediately", + "from": { + "privatebin": "privatebin/pdo:2.0.5" + }, + "to": { + "privatebin": "alpine:3.20" + }, + "verdict": "failed", + "seed_read_before": true, + "seed_read_after": false, + "healthy_after": false, + "migration_observed": null, + "abort": "starts-and-serves", + "abort_detail": null, + "engine_state_after": null, + "duration_s": 421.1, + "measured_at": "2026-09-13T07:52:09Z", + "evidence": "evidence/C3", + "total_s": 553.9 +} \ No newline at end of file diff --git a/documentation/audits/r459-close-2026-09-13/harness/E3/abort-states.json b/documentation/audits/r459-close-2026-09-13/harness/E3/abort-states.json new file mode 100644 index 00000000..b910bf46 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/E3/abort-states.json @@ -0,0 +1,14 @@ +{ + "bookstack": { + "status": "running", + "health": "healthy", + "restarts": 0, + "exit": 0 + }, + "bookstack-db": { + "status": "running", + "health": "healthy", + "restarts": 0, + "exit": 0 + } +} \ No newline at end of file diff --git a/documentation/audits/r459-close-2026-09-13/harness/E3/compose-final.log b/documentation/audits/r459-close-2026-09-13/harness/E3/compose-final.log new file mode 100644 index 00000000..edb06757 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/E3/compose-final.log @@ -0,0 +1,67 @@ +bookstack | [migrations] started +bookstack | [migrations] 01-nginx-site-confs-default: skipped +bookstack | [migrations] 02-default-location: skipped +bookstack | [migrations] done +bookstack | ─────────────────────────────────────── +bookstack | +bookstack | ██╗ ███████╗██╗ ██████╗ +bookstack | ██║ ██╔════╝██║██╔═══██╗ +bookstack | ██║ ███████╗██║██║ ██║ +bookstack | ██║ ╚════██║██║██║ ██║ +bookstack | ███████╗███████║██║╚██████╔╝ +bookstack | ╚══════╝╚══════╝╚═╝ ╚═════╝ +bookstack | +bookstack | Brought to you by linuxserver.io +bookstack | ─────────────────────────────────────── +bookstack | +bookstack | To support LSIO projects visit: +bookstack | https://www.linuxserver.io/donate/ +bookstack | +bookstack | ─────────────────────────────────────── +bookstack | GID/UID +bookstack | ─────────────────────────────────────── +bookstack-db | 2026-09-13 09:53:49+02:00 [Note] [Entrypoint]: Entrypoint script for MariaDB Server 1:11.6.2+maria~ubu2404 started. +bookstack-db | 2026-09-13 09:53:49+02:00 [Warn] [Entrypoint]: /sys/fs/cgroup///memory.pressure not writable, functionality unavailable to MariaDB +bookstack-db | 2026-09-13 09:53:49+02:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' +bookstack-db | 2026-09-13 09:53:49+02:00 [Note] [Entrypoint]: Entrypoint script for MariaDB Server 1:11.6.2+maria~ubu2404 started. +bookstack-db | 2026-09-13 09:53:50+02:00 [Note] [Entrypoint]: MariaDB upgrade not required +bookstack-db | 2026-09-13 9:53:50 0 [Note] Starting MariaDB 11.6.2-MariaDB-ubu2404 source revision d8dad8c3b54cd09fefce7bc3b9749f427eed9709 server_uid NqHiasVU3XvSSnAvQ8Ghzed+a14= as process 1 +bookstack-db | 2026-09-13 9:53:50 0 [Note] InnoDB: Compressed tables use zlib 1.3 +bookstack-db | 2026-09-13 9:53:50 0 [Note] InnoDB: Number of transaction pools: 1 +bookstack-db | 2026-09-13 9:53:50 0 [Note] InnoDB: Using crc32 + pclmulqdq instructions +bookstack-db | 2026-09-13 9:53:50 0 [Warning] mariadbd: io_uring_queue_init() failed with errno 0 +bookstack-db | 2026-09-13 9:53:50 0 [Warning] InnoDB: liburing disabled: falling back to innodb_use_native_aio=OFF +bookstack-db | 2026-09-13 9:53:50 0 [Note] InnoDB: Initializing buffer pool, total size = 128.000MiB, chunk size = 2.000MiB +bookstack-db | 2026-09-13 9:53:50 0 [Note] InnoDB: Completed initialization of buffer pool +bookstack | +bookstack-db | 2026-09-13 9:53:50 0 [Note] InnoDB: File system buffers for log disabled (block size=512 bytes) +bookstack-db | 2026-09-13 9:53:50 0 [Note] InnoDB: End of log at LSN=2253291 +bookstack | User UID: 1000 +bookstack | User GID: 1000 +bookstack | ─────────────────────────────────────── +bookstack | Linuxserver.io version: v25.02.2-ls202 +bookstack | Build-date: 2025-04-14T18:32:57+00:00 +bookstack | ─────────────────────────────────────── +bookstack | +bookstack | using keys found in /config/keys +bookstack | Waiting for DB to be available +bookstack | +bookstack | INFO Nothing to migrate. +bookstack | +bookstack | [custom-init] No custom files found, skipping... +bookstack | [ls.io-init] done. +bookstack-db | 2026-09-13 9:53:50 0 [Note] InnoDB: Opened 3 undo tablespaces +bookstack-db | 2026-09-13 9:53:50 0 [Note] InnoDB: 128 rollback segments in 3 undo tablespaces are active. +bookstack-db | 2026-09-13 9:53:50 0 [Note] InnoDB: Setting file './ibtmp1' size to 12.000MiB. Physically writing the file full; Please wait ... +bookstack-db | 2026-09-13 9:53:50 0 [Note] InnoDB: File './ibtmp1' size is now 12.000MiB. +bookstack-db | 2026-09-13 9:53:50 0 [Note] InnoDB: log sequence number 2253291; transaction id 2925 +bookstack-db | 2026-09-13 9:53:50 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool +bookstack-db | 2026-09-13 9:53:50 0 [Note] Plugin 'FEEDBACK' is disabled. +bookstack-db | 2026-09-13 9:53:50 0 [Note] Plugin 'wsrep-provider' is disabled. +bookstack-db | 2026-09-13 9:53:50 0 [Note] InnoDB: Buffer pool(s) load completed at 260913 9:53:50 +bookstack-db | 2026-09-13 9:53:54 0 [Note] Server socket created on IP: '0.0.0.0'. +bookstack-db | 2026-09-13 9:53:54 0 [Note] Server socket created on IP: '::'. +bookstack-db | 2026-09-13 9:53:54 0 [Note] mariadbd: Event Scheduler: Loaded 0 events +bookstack-db | 2026-09-13 9:53:54 0 [Note] mariadbd: ready for connections. +bookstack-db | Version: '11.6.2-MariaDB-ubu2404' socket: '/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution +bookstack-db | 2026-09-13 9:53:56 5 [Warning] Aborted connection 5 to db: 'unconnected' user: 'unauthenticated' host: '172.19.0.3' (This connection closed normally without authentication) diff --git a/documentation/audits/r459-close-2026-09-13/harness/E3/engine-state.json b/documentation/audits/r459-close-2026-09-13/harness/E3/engine-state.json new file mode 100644 index 00000000..eb98eaf6 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/E3/engine-state.json @@ -0,0 +1,8 @@ +{ + "bookstack-db": { + "image": "mariadb:12.3", + "probe": "datadir version | the engine's own upgrade verdict", + "answer": "12.3.3-MariaDB | This installation of MariaDB is already upgraded to 12.3.3-MariaDB. There is no need to run mariadb-upgrade again. [exit=1]", + "probe_rc": 0 + } +} \ No newline at end of file diff --git a/documentation/audits/r459-close-2026-09-13/harness/E3/migration-lines.txt b/documentation/audits/r459-close-2026-09-13/harness/E3/migration-lines.txt new file mode 100644 index 00000000..899ed6a4 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/E3/migration-lines.txt @@ -0,0 +1,6 @@ +bookstack | [migrations] started +bookstack | [migrations] 01-nginx-site-confs-default: skipped +bookstack | [migrations] 02-default-location: skipped +bookstack | [migrations] done +bookstack | INFO Running migrations. +bookstack | 2025_09_15_134701_migrate_entity_data ......................... 11.76ms DONE \ No newline at end of file diff --git a/documentation/audits/r459-close-2026-09-13/harness/E3/run.log b/documentation/audits/r459-close-2026-09-13/harness/E3/run.log new file mode 100644 index 00000000..4d64d54a --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/E3/run.log @@ -0,0 +1,15 @@ +[07:52:10] E3: deploying bookstack at FROM {'bookstack': 'lscr.io/linuxserver/bookstack:25.02.2', 'bookstack-db': 'mariadb:11.6'} +[07:52:56] FROM settled=True in 15.7s :: {"bookstack": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}, "bookstack-db": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}} +[07:52:57] bookstack: artisan create-admin rc=0 :: Admin account with email "spike-e4414904@gate.invalid" successfully created! +[07:52:58] bookstack: readback of the seeded account found=True :: This will delete any configure multi-factor authentication methods for user: - ID: 3 - Name: spike-db3feb - Email: spike +[07:52:58] C1 (seed reads back BEFORE): True +[07:52:58] E3: swapping to TO {'bookstack': 'lscr.io/linuxserver/bookstack:26.05.2', 'bookstack-db': 'mariadb:12.3'} +[07:53:33] TO up -d rc=0 +[07:53:43] TO settled=True in 10.5s :: {"bookstack": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}, "bookstack-db": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}} +[07:53:43] engine state bookstack-db: 12.3.3-MariaDB | This installation of MariaDB is already upgraded to 12.3.3-MariaDB. There is no need to run mariadb-upgrade again. [exit=1] +[07:53:43] migration lines observed: 6 +[07:53:44] bookstack: readback of the seeded account found=True :: This will delete any configure multi-factor authentication methods for user: - ID: 3 - Name: spike-db3feb - Email: spike +[07:53:44] RESULT (seed reads back AFTER): True +[07:53:44] E3: ABORT — putting the FROM images back +[07:54:06] bookstack: readback of the seeded account found=True :: This will delete any configure multi-factor authentication methods for user: - ID: 3 - Name: spike-db3feb - Email: spike +[07:54:06] ABORT: app came back in 10.5s; data present=True \ No newline at end of file diff --git a/documentation/audits/r459-close-2026-09-13/harness/E3/to-full.log b/documentation/audits/r459-close-2026-09-13/harness/E3/to-full.log new file mode 100644 index 00000000..ebd67786 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/E3/to-full.log @@ -0,0 +1,171 @@ +bookstack-db | 2026-09-13 09:53:17+02:00 [Note] [Entrypoint]: Entrypoint script for MariaDB Server 1:12.3.3+maria~ubu2404 started. +bookstack-db | 2026-09-13 09:53:17+02:00 [Warn] [Entrypoint]: /sys/fs/cgroup///memory.pressure not writable, functionality unavailable to MariaDB +bookstack-db | 2026-09-13 09:53:17+02:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' +bookstack-db | 2026-09-13 09:53:17+02:00 [Note] [Entrypoint]: Entrypoint script for MariaDB Server 1:12.3.3+maria~ubu2404 started. +bookstack-db | 2026-09-13 09:53:17+02:00 [Note] [Entrypoint]: Starting temporary server +bookstack-db | 2026-09-13 09:53:17+02:00 [Note] [Entrypoint]: Waiting for server startup +bookstack-db | 2026-09-13 9:53:17 0 [Note] Starting MariaDB 12.3.3-MariaDB-ubu2404 source revision 83e909fc2a0dbc394b4b683fb3fa2d7dcf26cc5e server_uid uYRfNEQQC8vM+0dejC8iUUzoFC4= as process 56 +bookstack-db | 2026-09-13 9:53:17 0 [Note] InnoDB: Compressed tables use zlib 1.3 +bookstack-db | 2026-09-13 9:53:17 0 [Note] InnoDB: Number of transaction pools: 1 +bookstack-db | 2026-09-13 9:53:17 0 [Note] InnoDB: Using crc32 + pclmulqdq instructions +bookstack-db | 2026-09-13 9:53:17 0 [Warning] mariadbd: io_uring_queue_init() failed with EPERM: sysctl kernel.io_uring_disabled has the value 2, or 1 and the user of the process is not a member of sysctl kernel.io_uring_group. (see man 2 io_uring_setup). +bookstack-db | create_uring failed: falling back to libaio +bookstack-db | 2026-09-13 9:53:17 0 [Note] InnoDB: Using Linux native AIO +bookstack-db | 2026-09-13 9:53:17 0 [Note] InnoDB: innodb_buffer_pool_size_max=8388608m, innodb_buffer_pool_size=128m +bookstack-db | 2026-09-13 9:53:17 0 [Note] InnoDB: Completed initialization of buffer pool +bookstack-db | 2026-09-13 9:53:17 0 [Note] InnoDB: File system buffers for log disabled (block size=512 bytes) +bookstack-db | 2026-09-13 9:53:17 0 [Note] InnoDB: End of log at LSN=1173728 +bookstack-db | 2026-09-13 9:53:17 0 [Note] InnoDB: Opened 3 undo tablespaces +bookstack-db | 2026-09-13 9:53:17 0 [Note] InnoDB: 128 rollback segments in 3 undo tablespaces are active. +bookstack-db | 2026-09-13 9:53:17 0 [Note] InnoDB: Setting file './ibtmp1' size to 12.000MiB. Physically writing the file full; Please wait ... +bookstack-db | 2026-09-13 9:53:17 0 [Note] InnoDB: File './ibtmp1' size is now 12.000MiB. +bookstack-db | 2026-09-13 9:53:17 0 [Note] InnoDB: log sequence number 1173728; transaction id 2278 +bookstack-db | 2026-09-13 9:53:17 0 [Note] Plugin 'FEEDBACK' is disabled. +bookstack-db | 2026-09-13 9:53:17 0 [Note] Plugin 'wsrep-provider' is disabled. +bookstack-db | 2026-09-13 9:53:19 0 [Note] Replication not automatically started: --skip-slave-start was specified +bookstack-db | 2026-09-13 9:53:19 0 [Note] mariadbd: ready for connections. +bookstack-db | Version: '12.3.3-MariaDB-ubu2404' socket: '/run/mysqld/mysqld.sock' port: 0 mariadb.org binary distribution +bookstack-db | 2026-09-13 09:53:19+02:00 [Note] [Entrypoint]: Temporary server started. +bookstack-db | 2026-09-13 09:53:19+02:00 [Note] [Entrypoint]: Backing up system database to system_mysql_backup_11.6.2-MariaDB.sql.zst +bookstack-db | 2026-09-13 09:53:20+02:00 [Note] [Entrypoint]: Backing up complete +bookstack-db | 2026-09-13 09:53:20+02:00 [Note] [Entrypoint]: Starting mariadb-upgrade +bookstack-db | The --upgrade-system-tables option was used, user tables won't be touched. +bookstack-db | Major version upgrade detected from 11.6.2-MariaDB to 12.3.3-MariaDB. Check required! +bookstack-db | Phase 1/8: Checking and upgrading mysql database +bookstack-db | Processing databases +bookstack-db | mysql +bookstack-db | mysql.column_stats OK +bookstack-db | mysql.columns_priv OK +bookstack-db | mysql.db OK +bookstack-db | mysql.event OK +bookstack-db | mysql.func OK +bookstack-db | mysql.global_priv OK +bookstack-db | mysql.gtid_slave_pos OK +bookstack-db | mysql.help_category OK +bookstack-db | mysql.help_keyword OK +bookstack-db | mysql.help_relation OK +bookstack-db | mysql.help_topic OK +bookstack-db | mysql.index_stats OK +bookstack-db | mysql.innodb_index_stats OK +bookstack-db | mysql.innodb_table_stats OK +bookstack-db | mysql.plugin OK +bookstack-db | mysql.proc OK +bookstack-db | mysql.procs_priv OK +bookstack-db | mysql.proxies_priv OK +bookstack-db | mysql.roles_mapping OK +bookstack-db | mysql.servers OK +bookstack-db | mysql.table_stats OK +bookstack-db | mysql.tables_priv OK +bookstack-db | mysql.time_zone OK +bookstack-db | mysql.time_zone_leap_second OK +bookstack-db | mysql.time_zone_name OK +bookstack-db | mysql.time_zone_transition OK +bookstack-db | mysql.time_zone_transition_type OK +bookstack-db | mysql.transaction_registry OK +bookstack-db | Phase 2/8: Installing used storage engines... Skipped +bookstack-db | Phase 3/8: Running 'mysql_fix_privilege_tables' +bookstack-db | Phase 4/8: Fixing views... Skipped +bookstack-db | Phase 5/8: Fixing table and database names ... Skipped +bookstack-db | Phase 6/8: Checking and upgrading tables... Skipped +bookstack-db | Phase 7/8: uninstalling plugins +bookstack-db | Phase 8/8: Running 'FLUSH PRIVILEGES' +bookstack-db | OK +bookstack-db | 2026-09-13 09:53:26+02:00 [Note] [Entrypoint]: Finished mariadb-upgrade +bookstack-db | 2026-09-13 09:53:26+02:00 [Note] [Entrypoint]: Stopping temporary server +bookstack-db | 2026-09-13 9:53:26 0 [Note] mariadbd (initiated by: unknown): Normal shutdown +bookstack-db | 2026-09-13 9:53:26 0 [Note] InnoDB: FTS optimize thread exiting. +bookstack-db | 2026-09-13 9:53:26 0 [Note] InnoDB: Starting shutdown... +bookstack-db | 2026-09-13 9:53:26 0 [Note] InnoDB: Removed temporary tablespace data file: "./ibtmp1" +bookstack-db | 2026-09-13 9:53:26 0 [Note] Shutdown completed; log sequence number 1173728; transaction id 2282 +bookstack-db | 2026-09-13 9:53:26 0 [Note] mariadbd: Shutdown complete +bookstack-db | 2026-09-13 09:53:26+02:00 [Note] [Entrypoint]: Temporary server stopped +bookstack-db | 2026-09-13 9:53:26 0 [Note] Starting MariaDB 12.3.3-MariaDB-ubu2404 source revision 83e909fc2a0dbc394b4b683fb3fa2d7dcf26cc5e server_uid uYRfNEQQC8vM+0dejC8iUUzoFC4= as process 1 +bookstack-db | 2026-09-13 9:53:26 0 [Note] InnoDB: Compressed tables use zlib 1.3 +bookstack-db | 2026-09-13 9:53:26 0 [Note] InnoDB: Number of transaction pools: 1 +bookstack-db | 2026-09-13 9:53:26 0 [Note] InnoDB: Using crc32 + pclmulqdq instructions +bookstack-db | 2026-09-13 9:53:26 0 [Warning] mariadbd: io_uring_queue_init() failed with EPERM: sysctl kernel.io_uring_disabled has the value 2, or 1 and the user of the process is not a member of sysctl kernel.io_uring_group. (see man 2 io_uring_setup). +bookstack-db | create_uring failed: falling back to libaio +bookstack-db | 2026-09-13 9:53:26 0 [Note] InnoDB: Using Linux native AIO +bookstack-db | 2026-09-13 9:53:26 0 [Note] InnoDB: innodb_buffer_pool_size_max=8388608m, innodb_buffer_pool_size=128m +bookstack-db | 2026-09-13 9:53:26 0 [Note] InnoDB: Completed initialization of buffer pool +bookstack-db | 2026-09-13 9:53:26 0 [Note] InnoDB: File system buffers for log disabled (block size=512 bytes) +bookstack-db | 2026-09-13 9:53:26 0 [Note] InnoDB: End of log at LSN=1173728 +bookstack-db | 2026-09-13 9:53:26 0 [Note] InnoDB: Opened 3 undo tablespaces +bookstack-db | 2026-09-13 9:53:26 0 [Note] InnoDB: 128 rollback segments in 3 undo tablespaces are active. +bookstack-db | 2026-09-13 9:53:26 0 [Note] InnoDB: Setting file './ibtmp1' size to 12.000MiB. Physically writing the file full; Please wait ... +bookstack-db | 2026-09-13 9:53:26 0 [Note] InnoDB: File './ibtmp1' size is now 12.000MiB. +bookstack-db | 2026-09-13 9:53:26 0 [Note] InnoDB: log sequence number 1173728; transaction id 2278 +bookstack-db | 2026-09-13 9:53:26 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool +bookstack-db | 2026-09-13 9:53:26 0 [Note] Plugin 'FEEDBACK' is disabled. +bookstack-db | 2026-09-13 9:53:26 0 [Note] Plugin 'wsrep-provider' is disabled. +bookstack-db | 2026-09-13 9:53:26 0 [Note] InnoDB: Buffer pool(s) load completed at 260913 9:53:26 +bookstack-db | 2026-09-13 9:53:28 0 [Note] Server socket created on IP: '0.0.0.0', port: '3306'. +bookstack-db | 2026-09-13 9:53:28 0 [Note] Server socket created on IP: '::', port: '3306'. +bookstack-db | 2026-09-13 9:53:28 0 [Note] mariadbd: Event Scheduler: Loaded 0 events +bookstack-db | 2026-09-13 9:53:28 0 [Note] mariadbd: ready for connections. +bookstack-db | Version: '12.3.3-MariaDB-ubu2404' socket: '/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution +bookstack-db | 2026-09-13 9:53:34 5 [Warning] Aborted connection 5 to db: 'unconnected' user: 'unauthenticated' host: '172.19.0.3' (This connection closed normally without authentication) +bookstack | [migrations] started +bookstack | [migrations] 01-nginx-site-confs-default: skipped +bookstack | [migrations] 02-default-location: skipped +bookstack | [migrations] done +bookstack | ─────────────────────────────────────── +bookstack | +bookstack | ██╗ ███████╗██╗ ██████╗ +bookstack | ██║ ██╔════╝██║██╔═══██╗ +bookstack | ██║ ███████╗██║██║ ██║ +bookstack | ██║ ╚════██║██║██║ ██║ +bookstack | ███████╗███████║██║╚██████╔╝ +bookstack | ╚══════╝╚══════╝╚═╝ ╚═════╝ +bookstack | +bookstack | Brought to you by linuxserver.io +bookstack | ─────────────────────────────────────── +bookstack | +bookstack | To support the app dev(s) visit: +bookstack | Bookstack: https://www.bookstackapp.com/donate/ +bookstack | +bookstack | To support LSIO projects visit: +bookstack | https://www.linuxserver.io/donate/ +bookstack | +bookstack | ─────────────────────────────────────── +bookstack | GID/UID +bookstack | ─────────────────────────────────────── +bookstack | +bookstack | User UID: 1000 +bookstack | User GID: 1000 +bookstack | ─────────────────────────────────────── +bookstack | Linuxserver.io version: v26.05.2-ls276 +bookstack | Build-date: 2026-07-27T19:41:43+00:00 +bookstack | ─────────────────────────────────────── +bookstack | +bookstack | using keys found in /config/keys +bookstack | **** The following active confs have different version dates than the samples that are shipped. **** +bookstack | **** This may be due to user customization or an update to the samples. **** +bookstack | **** You should compare the following files to the samples in the same folder and update them. **** +bookstack | **** Use the link at the top of the file to view the changelog. **** +bookstack | ┌────────────┬────────────┬────────────────────────────────────────────────────────────────────────┐ +bookstack | │ old date │ new date │ path │ +bookstack | ├────────────┼────────────┼────────────────────────────────────────────────────────────────────────┤ +bookstack | │ 2024-07-16 │ 2026-06-27 │ /config/nginx/site-confs/default.conf │ +bookstack | │ 2024-12-17 │ 2025-12-26 │ /config/nginx/nginx.conf │ +bookstack | │ 2024-12-06 │ 2026-06-27 │ /config/nginx/ssl.conf │ +bookstack | └────────────┴────────────┴────────────────────────────────────────────────────────────────────────┘ +bookstack | Waiting for DB to be available +bookstack | +bookstack | INFO Running migrations. +bookstack | +bookstack | 2025_04_18_215145_add_content_refs_and_archived_to_comments ... 85.17ms DONE +bookstack | 2025_09_02_111542_remove_unused_columns ....................... 82.04ms DONE +bookstack | 2025_09_15_132850_create_entities_table ...................... 307.42ms DONE +bookstack | 2025_09_15_134701_migrate_entity_data ......................... 11.76ms DONE +bookstack | 2025_09_15_134751_update_entity_relation_columns ............. 888.10ms DONE +bookstack | 2025_09_15_134813_drop_old_entity_tables ...................... 48.37ms DONE +bookstack | 2025_10_18_163331_clean_user_id_references ................... 461.62ms DONE +bookstack | 2025_10_22_134507_update_comments_relation_field_names ........ 42.49ms DONE +bookstack | 2025_11_23_161812_create_slug_history_table .................. 132.11ms DONE +bookstack | 2025_12_15_140219_create_mention_history_table ................ 67.89ms DONE +bookstack | 2025_12_19_103417_add_views_viewable_type_index ............... 30.42ms DONE +bookstack | 2026_04_19_141616_add_revision_view_all_permission ............. 4.70ms DONE +bookstack | +bookstack | [custom-init] No custom files found, skipping... +bookstack | [ls.io-init] done. diff --git a/documentation/audits/r459-close-2026-09-13/harness/E3/to-states.json b/documentation/audits/r459-close-2026-09-13/harness/E3/to-states.json new file mode 100644 index 00000000..b910bf46 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/E3/to-states.json @@ -0,0 +1,14 @@ +{ + "bookstack": { + "status": "running", + "health": "healthy", + "restarts": 0, + "exit": 0 + }, + "bookstack-db": { + "status": "running", + "health": "healthy", + "restarts": 0, + "exit": 0 + } +} \ No newline at end of file diff --git a/documentation/audits/r459-close-2026-09-13/harness/E3/verdict.json b/documentation/audits/r459-close-2026-09-13/harness/E3/verdict.json new file mode 100644 index 00000000..8ea6e3c6 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/E3/verdict.json @@ -0,0 +1,33 @@ +{ + "harness_version": 1, + "edge": "E3", + "app": "bookstack", + "note": "catalog transition 0b73e5e: app AND engine together", + "from": { + "bookstack": "lscr.io/linuxserver/bookstack:25.02.2", + "bookstack-db": "mariadb:11.6" + }, + "to": { + "bookstack": "lscr.io/linuxserver/bookstack:26.05.2", + "bookstack-db": "mariadb:12.3" + }, + "verdict": "proven", + "seed_read_before": true, + "seed_read_after": true, + "healthy_after": true, + "migration_observed": "bookstack | [migrations] started", + "abort": "starts-and-serves", + "abort_detail": null, + "engine_state_after": { + "bookstack-db": { + "image": "mariadb:12.3", + "probe": "datadir version | the engine's own upgrade verdict", + "answer": "12.3.3-MariaDB | This installation of MariaDB is already upgraded to 12.3.3-MariaDB. There is no need to run mariadb-upgrade again. [exit=1]", + "probe_rc": 0 + } + }, + "duration_s": 10.5, + "measured_at": "2026-09-13T07:54:06Z", + "evidence": "evidence/E3", + "total_s": 116.3 +} \ No newline at end of file diff --git a/documentation/audits/r459-close-2026-09-13/harness/E3b/abort-states.json b/documentation/audits/r459-close-2026-09-13/harness/E3b/abort-states.json new file mode 100644 index 00000000..b910bf46 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/E3b/abort-states.json @@ -0,0 +1,14 @@ +{ + "bookstack": { + "status": "running", + "health": "healthy", + "restarts": 0, + "exit": 0 + }, + "bookstack-db": { + "status": "running", + "health": "healthy", + "restarts": 0, + "exit": 0 + } +} \ No newline at end of file diff --git a/documentation/audits/r459-close-2026-09-13/harness/E3b/compose-final.log b/documentation/audits/r459-close-2026-09-13/harness/E3b/compose-final.log new file mode 100644 index 00000000..615dc4df --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/E3b/compose-final.log @@ -0,0 +1,183 @@ +bookstack-db | 2026-09-13 09:55:08+02:00 [Note] [Entrypoint]: Entrypoint script for MariaDB Server 1:11.6.2+maria~ubu2404 started. +bookstack-db | 2026-09-13 09:55:08+02:00 [Warn] [Entrypoint]: /sys/fs/cgroup///memory.pressure not writable, functionality unavailable to MariaDB +bookstack-db | 2026-09-13 09:55:08+02:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' +bookstack-db | 2026-09-13 09:55:08+02:00 [Note] [Entrypoint]: Entrypoint script for MariaDB Server 1:11.6.2+maria~ubu2404 started. +bookstack-db | 2026-09-13 09:55:08+02:00 [Note] [Entrypoint]: MariaDB upgrade not required +bookstack-db | 2026-09-13 9:55:08 0 [Note] Starting MariaDB 11.6.2-MariaDB-ubu2404 source revision d8dad8c3b54cd09fefce7bc3b9749f427eed9709 server_uid osbkHDTZ9yfxr2UZyu83QV8Ztoc= as process 1 +bookstack-db | 2026-09-13 9:55:08 0 [Note] InnoDB: Compressed tables use zlib 1.3 +bookstack-db | 2026-09-13 9:55:08 0 [Note] InnoDB: Number of transaction pools: 1 +bookstack-db | 2026-09-13 9:55:08 0 [Note] InnoDB: Using crc32 + pclmulqdq instructions +bookstack-db | 2026-09-13 9:55:08 0 [Warning] mariadbd: io_uring_queue_init() failed with errno 0 +bookstack-db | 2026-09-13 9:55:08 0 [Warning] InnoDB: liburing disabled: falling back to innodb_use_native_aio=OFF +bookstack-db | 2026-09-13 9:55:08 0 [Note] InnoDB: Initializing buffer pool, total size = 128.000MiB, chunk size = 2.000MiB +bookstack-db | 2026-09-13 9:55:08 0 [Note] InnoDB: Completed initialization of buffer pool +bookstack-db | 2026-09-13 9:55:08 0 [Note] InnoDB: File system buffers for log disabled (block size=512 bytes) +bookstack-db | 2026-09-13 9:55:08 0 [Note] InnoDB: End of log at LSN=2025029 +bookstack-db | 2026-09-13 9:55:08 0 [Note] InnoDB: Opened 3 undo tablespaces +bookstack-db | 2026-09-13 9:55:08 0 [Note] InnoDB: 128 rollback segments in 3 undo tablespaces are active. +bookstack-db | 2026-09-13 9:55:08 0 [Note] InnoDB: Setting file './ibtmp1' size to 12.000MiB. Physically writing the file full; Please wait ... +bookstack-db | 2026-09-13 9:55:08 0 [Note] InnoDB: File './ibtmp1' size is now 12.000MiB. +bookstack-db | 2026-09-13 9:55:08 0 [Note] InnoDB: log sequence number 2025029; transaction id 2873 +bookstack-db | 2026-09-13 9:55:08 0 [Note] Plugin 'FEEDBACK' is disabled. +bookstack-db | 2026-09-13 9:55:08 0 [Note] Plugin 'wsrep-provider' is disabled. +bookstack-db | 2026-09-13 9:55:08 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool +bookstack-db | 2026-09-13 9:55:08 0 [Note] InnoDB: Buffer pool(s) load completed at 260913 9:55:08 +bookstack-db | 2026-09-13 9:55:09 0 [Note] Server socket created on IP: '0.0.0.0'. +bookstack-db | 2026-09-13 9:55:09 0 [Note] Server socket created on IP: '::'. +bookstack | [migrations] started +bookstack | [migrations] 01-nginx-site-confs-default: executing... +bookstack | [migrations] 01-nginx-site-confs-default: succeeded +bookstack | [migrations] 02-default-location: executing... +bookstack | [migrations] 02-default-location: succeeded +bookstack | [migrations] done +bookstack | ─────────────────────────────────────── +bookstack | +bookstack | ██╗ ███████╗██╗ ██████╗ +bookstack | ██║ ██╔════╝██║██╔═══██╗ +bookstack | ██║ ███████╗██║██║ ██║ +bookstack | ██║ ╚════██║██║██║ ██║ +bookstack | ███████╗███████║██║╚██████╔╝ +bookstack | ╚══════╝╚══════╝╚═╝ ╚═════╝ +bookstack | +bookstack | Brought to you by linuxserver.io +bookstack | ─────────────────────────────────────── +bookstack | +bookstack | To support the app dev(s) visit: +bookstack | Bookstack: https://www.bookstackapp.com/donate/ +bookstack | +bookstack | To support LSIO projects visit: +bookstack | https://www.linuxserver.io/donate/ +bookstack | +bookstack | ─────────────────────────────────────── +bookstack | GID/UID +bookstack | ─────────────────────────────────────── +bookstack | +bookstack | User UID: 1000 +bookstack | User GID: 1000 +bookstack | ─────────────────────────────────────── +bookstack | Linuxserver.io version: v26.05.2-ls276 +bookstack | Build-date: 2026-07-27T19:41:43+00:00 +bookstack | ─────────────────────────────────────── +bookstack | +bookstack | Setting resolver to 127.0.0.11 +bookstack | Setting worker_processes to 4 +bookstack | generating self-signed keys in /config/keys, you can replace these with your own keys if required +bookstack | .+...+.+.....+.+...........+...+.+........+.+++++++++++++++++++++++++++++++++++++++*...+......+........+.+.....+.+..+...+.......+...+...............+.....+.........+......+....+......+.....+...+.+.....+...+.+......+...........+...+++++++++++++++++++++++++++++++++++++++*...............+.+...........+.........+.+...+...+........+....+.....+............+.........+.+......+....................+..........+...+..+....+.....+......+.......+...+...+......+.....+..........+......+..+.+......+.....+.+..............+...............+.+............+..+....+.........+.....+.+.....+......+...............+......+....+.....+......+...+....++++++ +bookstack | ...+......+...+.....+......+.+...+...........+++++++++++++++++++++++++++++++++++++++*..+...+...+..+..........+.....+....+...............+...........+.........+.........+...................+...+.........+.....+......+...+......+.+..+..........+...............+.....+..........+.....+......+.+........+...+...+.+...+........+++++++++++++++++++++++++++++++++++++++*.......+......+........+.+.........+..+...+......+....+..+.+...+..+.........+......+....+...+......+..+...+.+......+........+....+...+..................+..+..........+........+....+...........+......+.+...+..+....+........+.+.....+.........+...+...+.+.....+...+.......+......+.........+........+.............+...+.....+......+......+.......+......+.........+.....+..........+...+...+............+..+.+......+...........+.......+....................+.+..+.........+......+...+..........+......+...+...+..+.+...........+.+........+....+..+.+.....+.........+.........+....+...+..+.......+.....+................+.....+.........+...+.+......+.....+.........+.+..................+......+..+..........+..+................+.........+...+...+..+...+......+...+.+......+.....+......+...+.+.....+...+............+....+..+...+....+.....+.+..+.......+......+.....+.......+........+.......+.........+.....+...+.+..+....+...+............+...........+.......+...+...+......+...+.....+...............+.+..+.............+.....+.+.....+...+.+.....+.+..............+.+...+...+...............+..+...+.........+..........++++++ +bookstack | ----- +bookstack | Waiting for DB to be available +bookstack | +bookstack | INFO Preparing database. +bookstack | +bookstack | Creating migration table ...................................... 21.36ms DONE +bookstack | +bookstack | INFO Running migrations. +bookstack | +bookstack | 2014_10_12_000000_create_users_table ......................... 279.20ms DONE +bookstack | 2014_10_12_100000_create_password_resets_table ................ 60.91ms DONE +bookstack | 2015_07_12_114933_create_books_table .......................... 15.20ms DONE +bookstack | 2015_07_12_190027_create_pages_table .......................... 13.81ms DONE +bookstack-db | 2026-09-13 9:55:09 0 [Note] mariadbd: Event Scheduler: Loaded 0 events +bookstack-db | 2026-09-13 9:55:09 0 [Note] mariadbd: ready for connections. +bookstack-db | Version: '11.6.2-MariaDB-ubu2404' socket: '/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution +bookstack | 2015_07_13_172121_create_images_table ......................... 11.55ms DONE +bookstack | 2015_07_27_172342_create_chapters_table ....................... 17.39ms DONE +bookstack | 2015_08_08_200447_add_users_to_entities ...................... 146.31ms DONE +bookstack | 2015_08_09_093534_create_page_revisions_table ................. 14.90ms DONE +bookstack | 2015_08_16_142133_create_activities_table ..................... 11.43ms DONE +bookstack | 2015_08_29_105422_add_roles_and_permissions .................. 311.76ms DONE +bookstack | 2015_08_30_125859_create_settings_table ....................... 17.18ms DONE +bookstack | 2015_08_31_175240_add_search_indexes ........................... 0.08ms DONE +bookstack | 2015_09_04_165821_create_social_accounts_table ................ 61.62ms DONE +bookstack | 2015_09_05_164707_add_email_confirmation_table ................ 79.45ms DONE +bookstack | 2015_11_21_145609_create_views_table .......................... 12.53ms DONE +bookstack | 2015_11_26_221857_add_entity_indexes ......................... 487.07ms DONE +bookstack | 2015_12_05_145049_fulltext_weighting ........................... 0.06ms DONE +bookstack | 2015_12_07_195238_add_image_upload_types ...................... 77.75ms DONE +bookstack | 2015_12_09_195748_add_user_avatars ............................ 19.71ms DONE +bookstack | 2016_01_11_210908_add_external_auth_to_users .................. 47.16ms DONE +bookstack | 2016_02_25_184030_add_slug_to_revisions ....................... 83.43ms DONE +bookstack | 2016_02_27_120329_update_permissions_and_roles ............... 159.05ms DONE +bookstack | 2016_02_28_084200_add_entity_access_controls ................. 259.17ms DONE +bookstack | 2016_03_09_203143_add_page_revision_types ..................... 42.78ms DONE +bookstack | 2016_03_13_082138_add_page_drafts ............................. 43.51ms DONE +bookstack | 2016_03_25_123157_add_markdown_support ........................ 38.64ms DONE +bookstack | 2016_04_09_100730_add_view_permissions_to_roles ............... 43.26ms DONE +bookstack | 2016_04_20_192649_create_joint_permissions_table ............. 300.32ms DONE +bookstack | 2016_05_06_185215_create_tags_table .......................... 113.02ms DONE +bookstack | 2016_07_07_181521_add_summary_to_page_revisions ............... 17.06ms DONE +bookstack | 2016_09_29_101449_remove_hidden_roles ......................... 76.98ms DONE +bookstack | 2016_10_09_142037_create_attachments_table .................... 67.83ms DONE +bookstack | 2017_01_21_163556_create_cache_table .......................... 42.59ms DONE +bookstack | 2017_01_21_163602_create_sessions_table ....................... 42.74ms DONE +bookstack | 2017_03_19_091553_create_search_index_table .................. 115.70ms DONE +bookstack | 2017_04_20_185112_add_revision_counts ......................... 62.91ms DONE +bookstack | 2017_07_02_152834_update_db_encoding_to_ut8mb4 ................. 0.07ms DONE +bookstack | 2017_08_01_130541_create_comments_table ....................... 86.66ms DONE +bookstack | 2017_08_29_102650_add_cover_image_display ..................... 16.83ms DONE +bookstack | 2018_07_15_173514_add_role_external_auth_id ................... 48.22ms DONE +bookstack | 2018_08_04_115700_create_bookshelves_table ................... 384.06ms DONE +bookstack | 2019_07_07_112515_add_template_support ........................ 48.61ms DONE +bookstack | 2019_08_17_140214_add_user_invites_table ...................... 62.14ms DONE +bookstack | 2019_12_29_120917_add_api_auth ................................ 88.92ms DONE +bookstack | 2020_08_04_111754_drop_joint_permissions_id .................. 105.72ms DONE +bookstack | 2020_08_04_131052_remove_role_name_field ...................... 16.66ms DONE +bookstack | 2020_09_19_094251_add_activity_indexes ........................ 49.34ms DONE +bookstack | 2020_09_27_210059_add_entity_soft_deletes ..................... 78.73ms DONE +bookstack | 2020_09_27_210528_create_deletions_table ...................... 92.71ms DONE +bookstack | 2020_11_07_232321_simplify_activities_table .................. 141.84ms DONE +bookstack | 2020_12_30_173528_add_owned_by_field_to_entities ............. 200.24ms DONE +bookstack | 2021_01_30_225441_add_settings_type_column .................... 21.09ms DONE +bookstack | 2021_03_08_215138_add_user_slug ............................... 49.08ms DONE +bookstack | 2021_05_15_173110_create_favourites_table ..................... 66.80ms DONE +bookstack | 2021_06_30_173111_create_mfa_values_table ..................... 62.79ms DONE +bookstack | 2021_07_03_085038_add_mfa_enforced_to_roles_table ............. 17.85ms DONE +bookstack | 2021_08_28_161743_add_export_role_permission ................... 6.47ms DONE +bookstack | 2021_09_26_044614_add_activities_ip_column .................... 20.29ms DONE +bookstack | 2021_11_26_070438_add_index_for_user_ip ....................... 27.34ms DONE +bookstack | 2021_12_07_111343_create_webhooks_table ...................... 119.99ms DONE +bookstack | 2021_12_13_152024_create_jobs_table ........................... 38.72ms DONE +bookstack | 2021_12_13_152120_create_failed_jobs_table .................... 37.85ms DONE +bookstack | 2022_01_03_154041_add_webhooks_timeout_error_columns .......... 70.20ms DONE +bookstack | 2022_04_17_101741_add_editor_change_field_and_permission ...... 27.06ms DONE +bookstack | 2022_04_25_140741_update_polymorphic_types .................... 16.24ms DONE +bookstack | 2022_07_16_170051_drop_joint_permission_type ................. 123.83ms DONE +bookstack | 2022_08_17_092941_create_references_table .................... 112.81ms DONE +bookstack | 2022_09_02_082910_fix_shelf_cover_image_types .................. 0.71ms DONE +bookstack | 2022_10_07_091406_flatten_entity_permissions_table ............ 90.68ms DONE +bookstack | 2022_10_08_104202_drop_entity_restricted_field ................ 93.44ms DONE +bookstack | 2023_01_24_104625_refactor_joint_permissions_storage ......... 142.21ms DONE +bookstack | 2023_01_28_141230_copy_color_settings_for_dark_mode ............ 1.09ms DONE +bookstack | 2023_02_20_093655_increase_attachments_path_length ............ 36.15ms DONE +bookstack | 2023_02_23_200227_add_updated_at_index_to_pages ............... 23.45ms DONE +bookstack | 2023_06_10_071823_remove_guest_user_secondary_roles ............ 1.97ms DONE +bookstack | 2023_06_25_181952_remove_bookshelf_create_entity_permissions ... 0.06ms DONE +bookstack | 2023_07_25_124945_add_receive_notifications_role_permissions ... 6.28ms DONE +bookstack | 2023_07_31_104430_create_watches_table ........................ 89.12ms DONE +bookstack | 2023_08_21_174248_increase_cache_size ......................... 30.81ms DONE +bookstack | 2023_12_02_104541_add_default_template_to_books ............... 20.41ms DONE +bookstack | 2023_12_17_140913_add_description_html_to_entities ............ 73.97ms DONE +bookstack | 2024_01_01_104542_add_default_template_to_chapters ............ 20.92ms DONE +bookstack | 2024_02_04_141358_add_views_updated_index ..................... 26.40ms DONE +bookstack | 2024_05_04_154409_rename_activity_relation_columns ............ 39.24ms DONE +bookstack | 2024_09_29_140340_ensure_editor_value_set ...................... 2.58ms DONE +bookstack | 2024_10_29_114420_add_import_role_permission ................... 5.16ms DONE +bookstack | 2024_11_02_160700_create_imports_table ........................ 36.28ms DONE +bookstack | 2024_11_27_171039_add_instance_id_setting ..................... 10.40ms DONE +bookstack | 2025_01_29_180933_create_sort_rules_table ..................... 11.84ms DONE +bookstack | 2025_02_05_150842_add_sort_rule_id_to_books ................... 20.57ms DONE +bookstack | 2025_04_18_215145_add_content_refs_and_archived_to_comments ... 66.35ms DONE +bookstack | 2025_09_02_111542_remove_unused_columns ....................... 69.84ms DONE +bookstack | 2025_09_15_132850_create_entities_table ...................... 281.26ms DONE +bookstack | 2025_09_15_134701_migrate_entity_data .......................... 9.73ms DONE +bookstack | 2025_09_15_134751_update_entity_relation_columns ............. 794.71ms DONE +bookstack | 2025_09_15_134813_drop_old_entity_tables ...................... 49.70ms DONE +bookstack | 2025_10_18_163331_clean_user_id_references ................... 457.39ms DONE +bookstack | 2025_10_22_134507_update_comments_relation_field_names ........ 40.71ms DONE +bookstack | 2025_11_23_161812_create_slug_history_table .................. 112.42ms DONE +bookstack | 2025_12_15_140219_create_mention_history_table ................ 67.72ms DONE +bookstack | 2025_12_19_103417_add_views_viewable_type_index ............... 22.39ms DONE +bookstack | 2026_04_19_141616_add_revision_view_all_permission ............. 4.69ms DONE +bookstack | +bookstack | [custom-init] No custom files found, skipping... +bookstack | [ls.io-init] done. diff --git a/documentation/audits/r459-close-2026-09-13/harness/E3b/engine-state.json b/documentation/audits/r459-close-2026-09-13/harness/E3b/engine-state.json new file mode 100644 index 00000000..eb98eaf6 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/E3b/engine-state.json @@ -0,0 +1,8 @@ +{ + "bookstack-db": { + "image": "mariadb:12.3", + "probe": "datadir version | the engine's own upgrade verdict", + "answer": "12.3.3-MariaDB | This installation of MariaDB is already upgraded to 12.3.3-MariaDB. There is no need to run mariadb-upgrade again. [exit=1]", + "probe_rc": 0 + } +} \ No newline at end of file diff --git a/documentation/audits/r459-close-2026-09-13/harness/E3b/migration-lines.txt b/documentation/audits/r459-close-2026-09-13/harness/E3b/migration-lines.txt new file mode 100644 index 00000000..ea9a07bd --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/E3b/migration-lines.txt @@ -0,0 +1,6 @@ +bookstack-db | 2026-09-13 09:54:53+02:00 [Note] [Entrypoint]: Starting mariadb-upgrade +bookstack-db | The --upgrade-system-tables option was used, user tables won't be touched. +bookstack-db | Major version upgrade detected from 11.6.2-MariaDB to 12.3.3-MariaDB. Check required! +bookstack-db | Phase 1/8: Checking and upgrading mysql database +bookstack-db | Phase 6/8: Checking and upgrading tables... Skipped +bookstack-db | 2026-09-13 09:54:59+02:00 [Note] [Entrypoint]: Finished mariadb-upgrade \ No newline at end of file diff --git a/documentation/audits/r459-close-2026-09-13/harness/E3b/run.log b/documentation/audits/r459-close-2026-09-13/harness/E3b/run.log new file mode 100644 index 00000000..9b9a963a --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/E3b/run.log @@ -0,0 +1,15 @@ +[07:54:10] E3b: deploying bookstack at FROM {'bookstack': 'lscr.io/linuxserver/bookstack:26.05.2', 'bookstack-db': 'mariadb:11.6'} +[07:54:47] FROM settled=True in 20.9s :: {"bookstack": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}, "bookstack-db": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}} +[07:54:48] bookstack: artisan create-admin rc=0 :: Admin account with email "spike-87a54b85@gate.invalid" successfully created! +[07:54:49] bookstack: readback of the seeded account found=True :: This will delete any configure multi-factor authentication methods for user: - ID: 3 - Name: spike-7b31eb - Email: spike +[07:54:49] C1 (seed reads back BEFORE): True +[07:54:49] E3b: swapping to TO {'bookstack': 'lscr.io/linuxserver/bookstack:26.05.2', 'bookstack-db': 'mariadb:12.3'} +[07:55:06] TO up -d rc=0 +[07:55:06] TO settled=True in 0.2s :: {"bookstack": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}, "bookstack-db": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}} +[07:55:06] engine state bookstack-db: 12.3.3-MariaDB | This installation of MariaDB is already upgraded to 12.3.3-MariaDB. There is no need to run mariadb-upgrade again. [exit=1] +[07:55:06] migration lines observed: 6 +[07:55:07] bookstack: readback of the seeded account found=True :: This will delete any configure multi-factor authentication methods for user: - ID: 3 - Name: spike-7b31eb - Email: spike +[07:55:07] RESULT (seed reads back AFTER): True +[07:55:07] E3b: ABORT — putting the FROM images back +[07:55:14] bookstack: readback of the seeded account found=True :: This will delete any configure multi-factor authentication methods for user: - ID: 3 - Name: spike-7b31eb - Email: spike +[07:55:14] ABORT: app came back in 0.2s; data present=True \ No newline at end of file diff --git a/documentation/audits/r459-close-2026-09-13/harness/E3b/to-full.log b/documentation/audits/r459-close-2026-09-13/harness/E3b/to-full.log new file mode 100644 index 00000000..69abb67f --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/E3b/to-full.log @@ -0,0 +1,260 @@ +bookstack-db | 2026-09-13 09:54:50+02:00 [Note] [Entrypoint]: Entrypoint script for MariaDB Server 1:12.3.3+maria~ubu2404 started. +bookstack-db | 2026-09-13 09:54:51+02:00 [Warn] [Entrypoint]: /sys/fs/cgroup///memory.pressure not writable, functionality unavailable to MariaDB +bookstack-db | 2026-09-13 09:54:51+02:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' +bookstack-db | 2026-09-13 09:54:51+02:00 [Note] [Entrypoint]: Entrypoint script for MariaDB Server 1:12.3.3+maria~ubu2404 started. +bookstack-db | 2026-09-13 09:54:51+02:00 [Note] [Entrypoint]: Starting temporary server +bookstack-db | 2026-09-13 09:54:51+02:00 [Note] [Entrypoint]: Waiting for server startup +bookstack | [migrations] started +bookstack-db | 2026-09-13 9:54:51 0 [Note] Starting MariaDB 12.3.3-MariaDB-ubu2404 source revision 83e909fc2a0dbc394b4b683fb3fa2d7dcf26cc5e server_uid bR6d3VLG8Cdw7s40Fw1l0qseMmo= as process 56 +bookstack-db | 2026-09-13 9:54:51 0 [Note] InnoDB: Compressed tables use zlib 1.3 +bookstack-db | 2026-09-13 9:54:51 0 [Note] InnoDB: Number of transaction pools: 1 +bookstack-db | 2026-09-13 9:54:51 0 [Note] InnoDB: Using crc32 + pclmulqdq instructions +bookstack-db | 2026-09-13 9:54:51 0 [Warning] mariadbd: io_uring_queue_init() failed with EPERM: sysctl kernel.io_uring_disabled has the value 2, or 1 and the user of the process is not a member of sysctl kernel.io_uring_group. (see man 2 io_uring_setup). +bookstack-db | create_uring failed: falling back to libaio +bookstack-db | 2026-09-13 9:54:51 0 [Note] InnoDB: Using Linux native AIO +bookstack-db | 2026-09-13 9:54:51 0 [Note] InnoDB: innodb_buffer_pool_size_max=8388608m, innodb_buffer_pool_size=128m +bookstack-db | 2026-09-13 9:54:51 0 [Note] InnoDB: Completed initialization of buffer pool +bookstack-db | 2026-09-13 9:54:51 0 [Note] InnoDB: File system buffers for log disabled (block size=512 bytes) +bookstack-db | 2026-09-13 9:54:51 0 [Note] InnoDB: End of log at LSN=2025029 +bookstack-db | 2026-09-13 9:54:51 0 [Note] InnoDB: Opened 3 undo tablespaces +bookstack | [migrations] 01-nginx-site-confs-default: executing... +bookstack | [migrations] 01-nginx-site-confs-default: succeeded +bookstack | [migrations] 02-default-location: executing... +bookstack | [migrations] 02-default-location: succeeded +bookstack | [migrations] done +bookstack | ─────────────────────────────────────── +bookstack | +bookstack | ██╗ ███████╗██╗ ██████╗ +bookstack | ██║ ██╔════╝██║██╔═══██╗ +bookstack | ██║ ███████╗██║██║ ██║ +bookstack | ██║ ╚════██║██║██║ ██║ +bookstack | ███████╗███████║██║╚██████╔╝ +bookstack | ╚══════╝╚══════╝╚═╝ ╚═════╝ +bookstack | +bookstack | Brought to you by linuxserver.io +bookstack | ─────────────────────────────────────── +bookstack | +bookstack | To support the app dev(s) visit: +bookstack | Bookstack: https://www.bookstackapp.com/donate/ +bookstack | +bookstack | To support LSIO projects visit: +bookstack | https://www.linuxserver.io/donate/ +bookstack | +bookstack | ─────────────────────────────────────── +bookstack | GID/UID +bookstack | ─────────────────────────────────────── +bookstack | +bookstack | User UID: 1000 +bookstack | User GID: 1000 +bookstack | ─────────────────────────────────────── +bookstack | Linuxserver.io version: v26.05.2-ls276 +bookstack-db | 2026-09-13 9:54:51 0 [Note] InnoDB: 128 rollback segments in 3 undo tablespaces are active. +bookstack-db | 2026-09-13 9:54:51 0 [Note] InnoDB: Setting file './ibtmp1' size to 12.000MiB. Physically writing the file full; Please wait ... +bookstack | Build-date: 2026-07-27T19:41:43+00:00 +bookstack | ─────────────────────────────────────── +bookstack | +bookstack | Setting resolver to 127.0.0.11 +bookstack | Setting worker_processes to 4 +bookstack | generating self-signed keys in /config/keys, you can replace these with your own keys if required +bookstack-db | 2026-09-13 9:54:51 0 [Note] InnoDB: File './ibtmp1' size is now 12.000MiB. +bookstack | .+...+.+.....+.+...........+...+.+........+.+++++++++++++++++++++++++++++++++++++++*...+......+........+.+.....+.+..+...+.......+...+...............+.....+.........+......+....+......+.....+...+.+.....+...+.+......+...........+...+++++++++++++++++++++++++++++++++++++++*...............+.+...........+.........+.+...+...+........+....+.....+............+.........+.+......+....................+..........+...+..+....+.....+......+.......+...+...+......+.....+..........+......+..+.+......+.....+.+..............+...............+.+............+..+....+.........+.....+.+.....+......+...............+......+....+.....+......+...+....++++++ +bookstack | ...+......+...+.....+......+.+...+...........+++++++++++++++++++++++++++++++++++++++*..+...+...+..+..........+.....+....+...............+...........+.........+.........+...................+...+.........+.....+......+...+......+.+..+..........+...............+.....+..........+.....+......+.+........+...+...+.+...+........+++++++++++++++++++++++++++++++++++++++*.......+......+........+.+.........+..+...+......+....+..+.+...+..+.........+......+....+...+......+..+...+.+......+........+....+...+..................+..+..........+........+....+...........+......+.+...+..+....+........+.+.....+.........+...+...+.+.....+...+.......+......+.........+........+.............+...+.....+......+......+.......+......+.........+.....+..........+...+...+............+..+.+......+...........+.......+....................+.+..+.........+......+...+..........+......+...+...+..+.+...........+.+........+....+..+.+.....+.........+.........+....+...+..+.......+.....+................+.....+.........+...+.+......+.....+.........+.+..................+......+..+..........+..+................+.........+...+...+..+...+......+...+.+......+.....+......+...+.+.....+...+............+....+..+...+....+.....+.+..+.......+......+.....+.......+........+.......+.........+.....+...+.+..+....+...+............+...........+.......+...+...+......+...+.....+...............+.+..+.............+.....+.+.....+...+.+.....+.+..............+.+...+...+...............+..+...+.........+..........++++++ +bookstack | ----- +bookstack | Waiting for DB to be available +bookstack | +bookstack-db | 2026-09-13 9:54:51 0 [Note] InnoDB: log sequence number 2025029; transaction id 2873 +bookstack | INFO Preparing database. +bookstack-db | 2026-09-13 9:54:51 0 [Note] Plugin 'FEEDBACK' is disabled. +bookstack-db | 2026-09-13 9:54:51 0 [Note] Plugin 'wsrep-provider' is disabled. +bookstack-db | 2026-09-13 9:54:52 0 [Note] Replication not automatically started: --skip-slave-start was specified +bookstack-db | 2026-09-13 9:54:52 0 [Note] mariadbd: ready for connections. +bookstack-db | Version: '12.3.3-MariaDB-ubu2404' socket: '/run/mysqld/mysqld.sock' port: 0 mariadb.org binary distribution +bookstack-db | 2026-09-13 09:54:53+02:00 [Note] [Entrypoint]: Temporary server started. +bookstack-db | 2026-09-13 09:54:53+02:00 [Note] [Entrypoint]: Backing up system database to system_mysql_backup_11.6.2-MariaDB.sql.zst +bookstack-db | 2026-09-13 09:54:53+02:00 [Note] [Entrypoint]: Backing up complete +bookstack-db | 2026-09-13 09:54:53+02:00 [Note] [Entrypoint]: Starting mariadb-upgrade +bookstack-db | The --upgrade-system-tables option was used, user tables won't be touched. +bookstack-db | Major version upgrade detected from 11.6.2-MariaDB to 12.3.3-MariaDB. Check required! +bookstack-db | Phase 1/8: Checking and upgrading mysql database +bookstack-db | Processing databases +bookstack-db | mysql +bookstack-db | mysql.column_stats OK +bookstack-db | mysql.columns_priv OK +bookstack | +bookstack-db | mysql.db OK +bookstack | Creating migration table ...................................... 21.36ms DONE +bookstack | +bookstack | INFO Running migrations. +bookstack | +bookstack | 2014_10_12_000000_create_users_table ......................... 279.20ms DONE +bookstack | 2014_10_12_100000_create_password_resets_table ................ 60.91ms DONE +bookstack | 2015_07_12_114933_create_books_table .......................... 15.20ms DONE +bookstack | 2015_07_12_190027_create_pages_table .......................... 13.81ms DONE +bookstack | 2015_07_13_172121_create_images_table ......................... 11.55ms DONE +bookstack | 2015_07_27_172342_create_chapters_table ....................... 17.39ms DONE +bookstack | 2015_08_08_200447_add_users_to_entities ...................... 146.31ms DONE +bookstack | 2015_08_09_093534_create_page_revisions_table ................. 14.90ms DONE +bookstack | 2015_08_16_142133_create_activities_table ..................... 11.43ms DONE +bookstack | 2015_08_29_105422_add_roles_and_permissions .................. 311.76ms DONE +bookstack | 2015_08_30_125859_create_settings_table ....................... 17.18ms DONE +bookstack | 2015_08_31_175240_add_search_indexes ........................... 0.08ms DONE +bookstack | 2015_09_04_165821_create_social_accounts_table ................ 61.62ms DONE +bookstack | 2015_09_05_164707_add_email_confirmation_table ................ 79.45ms DONE +bookstack | 2015_11_21_145609_create_views_table .......................... 12.53ms DONE +bookstack | 2015_11_26_221857_add_entity_indexes ......................... 487.07ms DONE +bookstack | 2015_12_05_145049_fulltext_weighting ........................... 0.06ms DONE +bookstack | 2015_12_07_195238_add_image_upload_types ...................... 77.75ms DONE +bookstack | 2015_12_09_195748_add_user_avatars ............................ 19.71ms DONE +bookstack | 2016_01_11_210908_add_external_auth_to_users .................. 47.16ms DONE +bookstack | 2016_02_25_184030_add_slug_to_revisions ....................... 83.43ms DONE +bookstack | 2016_02_27_120329_update_permissions_and_roles ............... 159.05ms DONE +bookstack | 2016_02_28_084200_add_entity_access_controls ................. 259.17ms DONE +bookstack | 2016_03_09_203143_add_page_revision_types ..................... 42.78ms DONE +bookstack | 2016_03_13_082138_add_page_drafts ............................. 43.51ms DONE +bookstack-db | mysql.event OK +bookstack-db | mysql.func OK +bookstack-db | mysql.global_priv OK +bookstack-db | mysql.gtid_slave_pos OK +bookstack-db | mysql.help_category OK +bookstack-db | mysql.help_keyword OK +bookstack-db | mysql.help_relation OK +bookstack-db | mysql.help_topic OK +bookstack-db | mysql.index_stats OK +bookstack-db | mysql.innodb_index_stats OK +bookstack-db | mysql.innodb_table_stats OK +bookstack-db | mysql.plugin OK +bookstack | 2016_03_25_123157_add_markdown_support ........................ 38.64ms DONE +bookstack | 2016_04_09_100730_add_view_permissions_to_roles ............... 43.26ms DONE +bookstack | 2016_04_20_192649_create_joint_permissions_table ............. 300.32ms DONE +bookstack-db | mysql.proc OK +bookstack-db | mysql.procs_priv OK +bookstack-db | mysql.proxies_priv OK +bookstack-db | mysql.roles_mapping OK +bookstack-db | mysql.servers OK +bookstack-db | mysql.table_stats OK +bookstack-db | mysql.tables_priv OK +bookstack-db | mysql.time_zone OK +bookstack-db | mysql.time_zone_leap_second OK +bookstack-db | mysql.time_zone_name OK +bookstack-db | mysql.time_zone_transition OK +bookstack-db | mysql.time_zone_transition_type OK +bookstack-db | mysql.transaction_registry OK +bookstack-db | Phase 2/8: Installing used storage engines... Skipped +bookstack-db | Phase 3/8: Running 'mysql_fix_privilege_tables' +bookstack-db | Phase 4/8: Fixing views... Skipped +bookstack-db | Phase 5/8: Fixing table and database names ... Skipped +bookstack-db | Phase 6/8: Checking and upgrading tables... Skipped +bookstack-db | Phase 7/8: uninstalling plugins +bookstack-db | Phase 8/8: Running 'FLUSH PRIVILEGES' +bookstack-db | OK +bookstack-db | 2026-09-13 09:54:59+02:00 [Note] [Entrypoint]: Finished mariadb-upgrade +bookstack-db | 2026-09-13 09:54:59+02:00 [Note] [Entrypoint]: Stopping temporary server +bookstack-db | 2026-09-13 9:54:59 0 [Note] mariadbd (initiated by: unknown): Normal shutdown +bookstack-db | 2026-09-13 9:54:59 0 [Note] InnoDB: FTS optimize thread exiting. +bookstack-db | 2026-09-13 9:54:59 0 [Note] InnoDB: Starting shutdown... +bookstack-db | 2026-09-13 9:54:59 0 [Note] InnoDB: Removed temporary tablespace data file: "./ibtmp1" +bookstack-db | 2026-09-13 9:54:59 0 [Note] Shutdown completed; log sequence number 2025029; transaction id 2877 +bookstack | 2016_05_06_185215_create_tags_table .......................... 113.02ms DONE +bookstack | 2016_07_07_181521_add_summary_to_page_revisions ............... 17.06ms DONE +bookstack | 2016_09_29_101449_remove_hidden_roles ......................... 76.98ms DONE +bookstack | 2016_10_09_142037_create_attachments_table .................... 67.83ms DONE +bookstack | 2017_01_21_163556_create_cache_table .......................... 42.59ms DONE +bookstack | 2017_01_21_163602_create_sessions_table ....................... 42.74ms DONE +bookstack | 2017_03_19_091553_create_search_index_table .................. 115.70ms DONE +bookstack | 2017_04_20_185112_add_revision_counts ......................... 62.91ms DONE +bookstack | 2017_07_02_152834_update_db_encoding_to_ut8mb4 ................. 0.07ms DONE +bookstack | 2017_08_01_130541_create_comments_table ....................... 86.66ms DONE +bookstack | 2017_08_29_102650_add_cover_image_display ..................... 16.83ms DONE +bookstack | 2018_07_15_173514_add_role_external_auth_id ................... 48.22ms DONE +bookstack | 2018_08_04_115700_create_bookshelves_table ................... 384.06ms DONE +bookstack | 2019_07_07_112515_add_template_support ........................ 48.61ms DONE +bookstack | 2019_08_17_140214_add_user_invites_table ...................... 62.14ms DONE +bookstack | 2019_12_29_120917_add_api_auth ................................ 88.92ms DONE +bookstack | 2020_08_04_111754_drop_joint_permissions_id .................. 105.72ms DONE +bookstack | 2020_08_04_131052_remove_role_name_field ...................... 16.66ms DONE +bookstack | 2020_09_19_094251_add_activity_indexes ........................ 49.34ms DONE +bookstack | 2020_09_27_210059_add_entity_soft_deletes ..................... 78.73ms DONE +bookstack | 2020_09_27_210528_create_deletions_table ...................... 92.71ms DONE +bookstack | 2020_11_07_232321_simplify_activities_table .................. 141.84ms DONE +bookstack | 2020_12_30_173528_add_owned_by_field_to_entities ............. 200.24ms DONE +bookstack | 2021_01_30_225441_add_settings_type_column .................... 21.09ms DONE +bookstack | 2021_03_08_215138_add_user_slug ............................... 49.08ms DONE +bookstack | 2021_05_15_173110_create_favourites_table ..................... 66.80ms DONE +bookstack-db | 2026-09-13 9:54:59 0 [Note] mariadbd: Shutdown complete +bookstack-db | 2026-09-13 09:54:59+02:00 [Note] [Entrypoint]: Temporary server stopped +bookstack-db | 2026-09-13 9:55:00 0 [Note] Starting MariaDB 12.3.3-MariaDB-ubu2404 source revision 83e909fc2a0dbc394b4b683fb3fa2d7dcf26cc5e server_uid bR6d3VLG8Cdw7s40Fw1l0qseMmo= as process 1 +bookstack-db | 2026-09-13 9:55:00 0 [Note] InnoDB: Compressed tables use zlib 1.3 +bookstack-db | 2026-09-13 9:55:00 0 [Note] InnoDB: Number of transaction pools: 1 +bookstack-db | 2026-09-13 9:55:00 0 [Note] InnoDB: Using crc32 + pclmulqdq instructions +bookstack-db | 2026-09-13 9:55:00 0 [Warning] mariadbd: io_uring_queue_init() failed with EPERM: sysctl kernel.io_uring_disabled has the value 2, or 1 and the user of the process is not a member of sysctl kernel.io_uring_group. (see man 2 io_uring_setup). +bookstack-db | create_uring failed: falling back to libaio +bookstack-db | 2026-09-13 9:55:00 0 [Note] InnoDB: Using Linux native AIO +bookstack-db | 2026-09-13 9:55:00 0 [Note] InnoDB: innodb_buffer_pool_size_max=8388608m, innodb_buffer_pool_size=128m +bookstack-db | 2026-09-13 9:55:00 0 [Note] InnoDB: Completed initialization of buffer pool +bookstack-db | 2026-09-13 9:55:00 0 [Note] InnoDB: File system buffers for log disabled (block size=512 bytes) +bookstack-db | 2026-09-13 9:55:00 0 [Note] InnoDB: End of log at LSN=2025029 +bookstack-db | 2026-09-13 9:55:00 0 [Note] InnoDB: Opened 3 undo tablespaces +bookstack-db | 2026-09-13 9:55:00 0 [Note] InnoDB: 128 rollback segments in 3 undo tablespaces are active. +bookstack | 2021_06_30_173111_create_mfa_values_table ..................... 62.79ms DONE +bookstack | 2021_07_03_085038_add_mfa_enforced_to_roles_table ............. 17.85ms DONE +bookstack | 2021_08_28_161743_add_export_role_permission ................... 6.47ms DONE +bookstack | 2021_09_26_044614_add_activities_ip_column .................... 20.29ms DONE +bookstack | 2021_11_26_070438_add_index_for_user_ip ....................... 27.34ms DONE +bookstack | 2021_12_07_111343_create_webhooks_table ...................... 119.99ms DONE +bookstack-db | 2026-09-13 9:55:00 0 [Note] InnoDB: Setting file './ibtmp1' size to 12.000MiB. Physically writing the file full; Please wait ... +bookstack | 2021_12_13_152024_create_jobs_table ........................... 38.72ms DONE +bookstack-db | 2026-09-13 9:55:00 0 [Note] InnoDB: File './ibtmp1' size is now 12.000MiB. +bookstack-db | 2026-09-13 9:55:00 0 [Note] InnoDB: log sequence number 2025029; transaction id 2873 +bookstack-db | 2026-09-13 9:55:00 0 [Note] Plugin 'FEEDBACK' is disabled. +bookstack-db | 2026-09-13 9:55:00 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool +bookstack-db | 2026-09-13 9:55:00 0 [Note] Plugin 'wsrep-provider' is disabled. +bookstack-db | 2026-09-13 9:55:00 0 [Note] InnoDB: Buffer pool(s) load completed at 260913 9:55:00 +bookstack-db | 2026-09-13 9:55:00 0 [Note] Server socket created on IP: '0.0.0.0', port: '3306'. +bookstack-db | 2026-09-13 9:55:00 0 [Note] Server socket created on IP: '::', port: '3306'. +bookstack-db | 2026-09-13 9:55:00 0 [Note] mariadbd: Event Scheduler: Loaded 0 events +bookstack-db | 2026-09-13 9:55:00 0 [Note] mariadbd: ready for connections. +bookstack-db | Version: '12.3.3-MariaDB-ubu2404' socket: '/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution +bookstack | 2021_12_13_152120_create_failed_jobs_table .................... 37.85ms DONE +bookstack | 2022_01_03_154041_add_webhooks_timeout_error_columns .......... 70.20ms DONE +bookstack | 2022_04_17_101741_add_editor_change_field_and_permission ...... 27.06ms DONE +bookstack | 2022_04_25_140741_update_polymorphic_types .................... 16.24ms DONE +bookstack | 2022_07_16_170051_drop_joint_permission_type ................. 123.83ms DONE +bookstack | 2022_08_17_092941_create_references_table .................... 112.81ms DONE +bookstack | 2022_09_02_082910_fix_shelf_cover_image_types .................. 0.71ms DONE +bookstack | 2022_10_07_091406_flatten_entity_permissions_table ............ 90.68ms DONE +bookstack | 2022_10_08_104202_drop_entity_restricted_field ................ 93.44ms DONE +bookstack | 2023_01_24_104625_refactor_joint_permissions_storage ......... 142.21ms DONE +bookstack | 2023_01_28_141230_copy_color_settings_for_dark_mode ............ 1.09ms DONE +bookstack | 2023_02_20_093655_increase_attachments_path_length ............ 36.15ms DONE +bookstack | 2023_02_23_200227_add_updated_at_index_to_pages ............... 23.45ms DONE +bookstack | 2023_06_10_071823_remove_guest_user_secondary_roles ............ 1.97ms DONE +bookstack | 2023_06_25_181952_remove_bookshelf_create_entity_permissions ... 0.06ms DONE +bookstack | 2023_07_25_124945_add_receive_notifications_role_permissions ... 6.28ms DONE +bookstack | 2023_07_31_104430_create_watches_table ........................ 89.12ms DONE +bookstack | 2023_08_21_174248_increase_cache_size ......................... 30.81ms DONE +bookstack | 2023_12_02_104541_add_default_template_to_books ............... 20.41ms DONE +bookstack | 2023_12_17_140913_add_description_html_to_entities ............ 73.97ms DONE +bookstack | 2024_01_01_104542_add_default_template_to_chapters ............ 20.92ms DONE +bookstack | 2024_02_04_141358_add_views_updated_index ..................... 26.40ms DONE +bookstack | 2024_05_04_154409_rename_activity_relation_columns ............ 39.24ms DONE +bookstack | 2024_09_29_140340_ensure_editor_value_set ...................... 2.58ms DONE +bookstack | 2024_10_29_114420_add_import_role_permission ................... 5.16ms DONE +bookstack | 2024_11_02_160700_create_imports_table ........................ 36.28ms DONE +bookstack | 2024_11_27_171039_add_instance_id_setting ..................... 10.40ms DONE +bookstack | 2025_01_29_180933_create_sort_rules_table ..................... 11.84ms DONE +bookstack | 2025_02_05_150842_add_sort_rule_id_to_books ................... 20.57ms DONE +bookstack | 2025_04_18_215145_add_content_refs_and_archived_to_comments ... 66.35ms DONE +bookstack | 2025_09_02_111542_remove_unused_columns ....................... 69.84ms DONE +bookstack | 2025_09_15_132850_create_entities_table ...................... 281.26ms DONE +bookstack | 2025_09_15_134701_migrate_entity_data .......................... 9.73ms DONE +bookstack | 2025_09_15_134751_update_entity_relation_columns ............. 794.71ms DONE +bookstack | 2025_09_15_134813_drop_old_entity_tables ...................... 49.70ms DONE +bookstack | 2025_10_18_163331_clean_user_id_references ................... 457.39ms DONE +bookstack | 2025_10_22_134507_update_comments_relation_field_names ........ 40.71ms DONE +bookstack | 2025_11_23_161812_create_slug_history_table .................. 112.42ms DONE +bookstack | 2025_12_15_140219_create_mention_history_table ................ 67.72ms DONE +bookstack | 2025_12_19_103417_add_views_viewable_type_index ............... 22.39ms DONE +bookstack | 2026_04_19_141616_add_revision_view_all_permission ............. 4.69ms DONE +bookstack | +bookstack | [custom-init] No custom files found, skipping... +bookstack | [ls.io-init] done. diff --git a/documentation/audits/r459-close-2026-09-13/harness/E3b/to-states.json b/documentation/audits/r459-close-2026-09-13/harness/E3b/to-states.json new file mode 100644 index 00000000..b910bf46 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/E3b/to-states.json @@ -0,0 +1,14 @@ +{ + "bookstack": { + "status": "running", + "health": "healthy", + "restarts": 0, + "exit": 0 + }, + "bookstack-db": { + "status": "running", + "health": "healthy", + "restarts": 0, + "exit": 0 + } +} \ No newline at end of file diff --git a/documentation/audits/r459-close-2026-09-13/harness/E3b/verdict.json b/documentation/audits/r459-close-2026-09-13/harness/E3b/verdict.json new file mode 100644 index 00000000..f75c3a20 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/E3b/verdict.json @@ -0,0 +1,33 @@ +{ + "harness_version": 1, + "edge": "E3b", + "app": "bookstack", + "note": "AUTHORED step: engine half alone", + "from": { + "bookstack": "lscr.io/linuxserver/bookstack:26.05.2", + "bookstack-db": "mariadb:11.6" + }, + "to": { + "bookstack": "lscr.io/linuxserver/bookstack:26.05.2", + "bookstack-db": "mariadb:12.3" + }, + "verdict": "proven", + "seed_read_before": true, + "seed_read_after": true, + "healthy_after": true, + "migration_observed": "bookstack-db | 2026-09-13 09:54:53+02:00 [Note] [Entrypoint]: Starting mariadb-upgrade", + "abort": "starts-and-serves", + "abort_detail": null, + "engine_state_after": { + "bookstack-db": { + "image": "mariadb:12.3", + "probe": "datadir version | the engine's own upgrade verdict", + "answer": "12.3.3-MariaDB | This installation of MariaDB is already upgraded to 12.3.3-MariaDB. There is no need to run mariadb-upgrade again. [exit=1]", + "probe_rc": 0 + } + }, + "duration_s": 0.2, + "measured_at": "2026-09-13T07:55:14Z", + "evidence": "evidence/E3b", + "total_s": 64.0 +} \ No newline at end of file diff --git a/documentation/audits/r459-close-2026-09-13/harness/harness-run.log b/documentation/audits/r459-close-2026-09-13/harness/harness-run.log new file mode 100644 index 00000000..2c85af7f --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/harness-run.log @@ -0,0 +1,135 @@ +[07:42:55] C3: deploying privatebin at FROM {'privatebin': 'privatebin/pdo:2.0.5'} +[07:43:01] FROM settled=True in 5.2s :: {"privatebin": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}} +[07:43:01] privatebin: seeded paste id=95d75dc1cf5feaba +[07:43:01] privatebin: readback http=200 marker_present=True +[07:43:01] C1 (seed reads back BEFORE): True +[07:43:01] C3: swapping to TO {'privatebin': 'alpine:3.20'} +[07:43:02] TO up -d rc=0 +[07:50:03] TO settled=False in 421.1s :: {"privatebin": {"status": "restarting", "health": "unhealthy", "restarts": 0, "exit": 0}} +[07:50:03] migration lines observed: 0 +[07:52:03] app never answered on http://invalid:8080/ (last rc=6 code=000) +[07:52:03] RESULT (seed reads back AFTER): False +[07:52:03] C3: ABORT — putting the FROM images back +[07:52:09] privatebin: readback http=200 marker_present=True +[07:52:09] ABORT: app came back in 5.2s; data present=True +{ + "harness_version": 1, + "edge": "C3", + "app": "privatebin", + "note": "NEGATIVE control: the TO image starts and exits immediately", + "from": { + "privatebin": "privatebin/pdo:2.0.5" + }, + "to": { + "privatebin": "alpine:3.20" + }, + "verdict": "failed", + "seed_read_before": true, + "seed_read_after": false, + "healthy_after": false, + "migration_observed": null, + "abort": "starts-and-serves", + "abort_detail": null, + "engine_state_after": null, + "duration_s": 421.1, + "measured_at": "2026-09-13T07:52:09Z", + "evidence": "evidence/C3", + "total_s": 553.9 +} +[07:52:10] E3: deploying bookstack at FROM {'bookstack': 'lscr.io/linuxserver/bookstack:25.02.2', 'bookstack-db': 'mariadb:11.6'} +[07:52:56] FROM settled=True in 15.7s :: {"bookstack": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}, "bookstack-db": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}} +[07:52:57] bookstack: artisan create-admin rc=0 :: Admin account with email "spike-e4414904@gate.invalid" successfully created! +[07:52:58] bookstack: readback of the seeded account found=True :: This will delete any configure multi-factor authentication methods for user: - ID: 3 - Name: spike-db3feb - Email: spike +[07:52:58] C1 (seed reads back BEFORE): True +[07:52:58] E3: swapping to TO {'bookstack': 'lscr.io/linuxserver/bookstack:26.05.2', 'bookstack-db': 'mariadb:12.3'} +[07:53:33] TO up -d rc=0 +[07:53:43] TO settled=True in 10.5s :: {"bookstack": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}, "bookstack-db": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}} +[07:53:43] engine state bookstack-db: 12.3.3-MariaDB | This installation of MariaDB is already upgraded to 12.3.3-MariaDB. There is no need to run mariadb-upgrade again. [exit=1] +[07:53:43] migration lines observed: 6 +[07:53:44] bookstack: readback of the seeded account found=True :: This will delete any configure multi-factor authentication methods for user: - ID: 3 - Name: spike-db3feb - Email: spike +[07:53:44] RESULT (seed reads back AFTER): True +[07:53:44] E3: ABORT — putting the FROM images back +[07:54:06] bookstack: readback of the seeded account found=True :: This will delete any configure multi-factor authentication methods for user: - ID: 3 - Name: spike-db3feb - Email: spike +[07:54:06] ABORT: app came back in 10.5s; data present=True +{ + "harness_version": 1, + "edge": "E3", + "app": "bookstack", + "note": "catalog transition 0b73e5e: app AND engine together", + "from": { + "bookstack": "lscr.io/linuxserver/bookstack:25.02.2", + "bookstack-db": "mariadb:11.6" + }, + "to": { + "bookstack": "lscr.io/linuxserver/bookstack:26.05.2", + "bookstack-db": "mariadb:12.3" + }, + "verdict": "proven", + "seed_read_before": true, + "seed_read_after": true, + "healthy_after": true, + "migration_observed": "bookstack | [migrations] started", + "abort": "starts-and-serves", + "abort_detail": null, + "engine_state_after": { + "bookstack-db": { + "image": "mariadb:12.3", + "probe": "datadir version | the engine's own upgrade verdict", + "answer": "12.3.3-MariaDB | This installation of MariaDB is already upgraded to 12.3.3-MariaDB. There is no need to run mariadb-upgrade again. [exit=1]", + "probe_rc": 0 + } + }, + "duration_s": 10.5, + "measured_at": "2026-09-13T07:54:06Z", + "evidence": "evidence/E3", + "total_s": 116.3 +} +[07:54:10] E3b: deploying bookstack at FROM {'bookstack': 'lscr.io/linuxserver/bookstack:26.05.2', 'bookstack-db': 'mariadb:11.6'} +[07:54:47] FROM settled=True in 20.9s :: {"bookstack": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}, "bookstack-db": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}} +[07:54:48] bookstack: artisan create-admin rc=0 :: Admin account with email "spike-87a54b85@gate.invalid" successfully created! +[07:54:49] bookstack: readback of the seeded account found=True :: This will delete any configure multi-factor authentication methods for user: - ID: 3 - Name: spike-7b31eb - Email: spike +[07:54:49] C1 (seed reads back BEFORE): True +[07:54:49] E3b: swapping to TO {'bookstack': 'lscr.io/linuxserver/bookstack:26.05.2', 'bookstack-db': 'mariadb:12.3'} +[07:55:06] TO up -d rc=0 +[07:55:06] TO settled=True in 0.2s :: {"bookstack": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}, "bookstack-db": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}} +[07:55:06] engine state bookstack-db: 12.3.3-MariaDB | This installation of MariaDB is already upgraded to 12.3.3-MariaDB. There is no need to run mariadb-upgrade again. [exit=1] +[07:55:06] migration lines observed: 6 +[07:55:07] bookstack: readback of the seeded account found=True :: This will delete any configure multi-factor authentication methods for user: - ID: 3 - Name: spike-7b31eb - Email: spike +[07:55:07] RESULT (seed reads back AFTER): True +[07:55:07] E3b: ABORT — putting the FROM images back +[07:55:14] bookstack: readback of the seeded account found=True :: This will delete any configure multi-factor authentication methods for user: - ID: 3 - Name: spike-7b31eb - Email: spike +[07:55:14] ABORT: app came back in 0.2s; data present=True +{ + "harness_version": 1, + "edge": "E3b", + "app": "bookstack", + "note": "AUTHORED step: engine half alone", + "from": { + "bookstack": "lscr.io/linuxserver/bookstack:26.05.2", + "bookstack-db": "mariadb:11.6" + }, + "to": { + "bookstack": "lscr.io/linuxserver/bookstack:26.05.2", + "bookstack-db": "mariadb:12.3" + }, + "verdict": "proven", + "seed_read_before": true, + "seed_read_after": true, + "healthy_after": true, + "migration_observed": "bookstack-db | 2026-09-13 09:54:53+02:00 [Note] [Entrypoint]: Starting mariadb-upgrade", + "abort": "starts-and-serves", + "abort_detail": null, + "engine_state_after": { + "bookstack-db": { + "image": "mariadb:12.3", + "probe": "datadir version | the engine's own upgrade verdict", + "answer": "12.3.3-MariaDB | This installation of MariaDB is already upgraded to 12.3.3-MariaDB. There is no need to run mariadb-upgrade again. [exit=1]", + "probe_rc": 0 + } + }, + "duration_s": 0.2, + "measured_at": "2026-09-13T07:55:14Z", + "evidence": "evidence/E3b", + "total_s": 64.0 +} +rc=0 diff --git a/documentation/audits/r459-close-2026-09-13/harness/summary.json b/documentation/audits/r459-close-2026-09-13/harness/summary.json new file mode 100644 index 00000000..e42fea19 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/summary.json @@ -0,0 +1,92 @@ +[ + { + "harness_version": 1, + "edge": "C3", + "app": "privatebin", + "note": "NEGATIVE control: the TO image starts and exits immediately", + "from": { + "privatebin": "privatebin/pdo:2.0.5" + }, + "to": { + "privatebin": "alpine:3.20" + }, + "verdict": "failed", + "seed_read_before": true, + "seed_read_after": false, + "healthy_after": false, + "migration_observed": null, + "abort": "starts-and-serves", + "abort_detail": null, + "engine_state_after": null, + "duration_s": 421.1, + "measured_at": "2026-09-13T07:52:09Z", + "evidence": "evidence/C3", + "total_s": 553.9 + }, + { + "harness_version": 1, + "edge": "E3", + "app": "bookstack", + "note": "catalog transition 0b73e5e: app AND engine together", + "from": { + "bookstack": "lscr.io/linuxserver/bookstack:25.02.2", + "bookstack-db": "mariadb:11.6" + }, + "to": { + "bookstack": "lscr.io/linuxserver/bookstack:26.05.2", + "bookstack-db": "mariadb:12.3" + }, + "verdict": "proven", + "seed_read_before": true, + "seed_read_after": true, + "healthy_after": true, + "migration_observed": "bookstack | [migrations] started", + "abort": "starts-and-serves", + "abort_detail": null, + "engine_state_after": { + "bookstack-db": { + "image": "mariadb:12.3", + "probe": "datadir version | the engine's own upgrade verdict", + "answer": "12.3.3-MariaDB | This installation of MariaDB is already upgraded to 12.3.3-MariaDB. There is no need to run mariadb-upgrade again. [exit=1]", + "probe_rc": 0 + } + }, + "duration_s": 10.5, + "measured_at": "2026-09-13T07:54:06Z", + "evidence": "evidence/E3", + "total_s": 116.3 + }, + { + "harness_version": 1, + "edge": "E3b", + "app": "bookstack", + "note": "AUTHORED step: engine half alone", + "from": { + "bookstack": "lscr.io/linuxserver/bookstack:26.05.2", + "bookstack-db": "mariadb:11.6" + }, + "to": { + "bookstack": "lscr.io/linuxserver/bookstack:26.05.2", + "bookstack-db": "mariadb:12.3" + }, + "verdict": "proven", + "seed_read_before": true, + "seed_read_after": true, + "healthy_after": true, + "migration_observed": "bookstack-db | 2026-09-13 09:54:53+02:00 [Note] [Entrypoint]: Starting mariadb-upgrade", + "abort": "starts-and-serves", + "abort_detail": null, + "engine_state_after": { + "bookstack-db": { + "image": "mariadb:12.3", + "probe": "datadir version | the engine's own upgrade verdict", + "answer": "12.3.3-MariaDB | This installation of MariaDB is already upgraded to 12.3.3-MariaDB. There is no need to run mariadb-upgrade again. [exit=1]", + "probe_rc": 0 + } + }, + "duration_s": 0.2, + "measured_at": "2026-09-13T07:55:14Z", + "evidence": "evidence/E3b", + "total_s": 64.0 + } +] \ No newline at end of file diff --git a/documentation/audits/r459-close-2026-09-13/harness/teardown-9403.txt b/documentation/audits/r459-close-2026-09-13/harness/teardown-9403.txt new file mode 100644 index 00000000..4ff1adb2 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/teardown-9403.txt @@ -0,0 +1,24 @@ +=== layer 1+2 BEFORE === +Sun Sep 13 07:56:14 UTC 2026 +local dir active 40453376 21035832 17330428 52.00% +local-lvm lvmthin active 56487936 19951538 36536397 35.32% +scratch-r459c dir active 983379700 9632244 923720844 0.98% +VMID Status Lock Name +9201 running demo-hp +9403 running r459-close +/dev/nvme0n1 983379700 9632244 923720844 2% /mnt/hdd_1 +guest peak: /dev/loop0 59G 3.3G 53G 6% / +images: Images 2.212GB;Containers 0B; +0 +=== fstrim === +/var/lib/lxc/9403/rootfs/: 55.5 GiB (59547074560 bytes) trimmed +=== destroy === +purging CT 9403 from related configurations.. +storage scratch-r459c removed +template deleted +=== AFTER === +local dir active 40453376 20908828 17457432 51.69% +local-lvm lvmthin active 56487936 19951538 36536397 35.32% +VMID Status Lock Name +9201 running demo-hp +/dev/nvme0n1 983379700 5774620 927578468 1% /mnt/hdd_1 diff --git a/documentation/audits/r459-close-2026-09-13/harness/teardown-layer3-hub.txt b/documentation/audits/r459-close-2026-09-13/harness/teardown-layer3-hub.txt new file mode 100644 index 00000000..c715dced --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/harness/teardown-layer3-hub.txt @@ -0,0 +1,5 @@ +=== LAYER 3 — the hub gained nothing 2026-09-13T08:11:07Z === + host: demo-felhom-8363b5 + host: demo-hp-bb76ea + customers: 0 + (this run created no customer, no appliance and no host record — guest 9403 never enrolled; the bake guest 9100 lives inside the drill VM) diff --git a/documentation/audits/r459-close-2026-09-13/live-9201/00-baseline-before-push.txt b/documentation/audits/r459-close-2026-09-13/live-9201/00-baseline-before-push.txt new file mode 100644 index 00000000..c40774d6 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/live-9201/00-baseline-before-push.txt @@ -0,0 +1,22 @@ +=== BASELINE 2026-09-13T07:57:15Z guest 9201, BEFORE the catalog push === +--- live compose, bookstack-db environment block --- + bookstack-db: + image: mariadb:12.3 + container_name: bookstack-db + restart: unless-stopped + environment: + - MYSQL_ROOT_PASSWORD=${DB_PASSWORD} + - MYSQL_DATABASE=bookstack + - MYSQL_USER=bookstack + - MYSQL_PASSWORD=${DB_PASSWORD} + - TZ=Europe/Budapest + volumes: +--- containers (ID, image, created, started) --- +/bookstack 26b555d71e1cf4ea60cd8fc72e34faa6d97ea8a71430d54dc5894cad5a03915d created=2026-09-13T04:21:01.357420686Z started=2026-09-13T04:21:07.210437498Z lscr.io/linuxserver/bookstack:26.05.2 +/bookstack-db b02f7a091aebc962c7e15a1337ceb2b1c87c3f03ade7103d4bfddc2dcfc87ce2 created=2026-09-13T04:21:01.27514214Z started=2026-09-13T04:21:01.47728414Z mariadb:12.3 +--- controller: last sync lines --- +2026/09/13 07:54:17 sync.go:416: [DEBUG] [sync] zipline/docker-compose.yml: hash match, skipped +2026/09/13 07:54:17 sync.go:416: [DEBUG] [sync] zipline/.felhom.yml: hash match, skipped +2026/09/13 07:54:17 sync.go:263: [INFO] [sync] Catalog sync complete +2026/09/13 07:54:17 sync.go:135: [INFO] [sync] Periodic sync: Sablonok naprakészek — nincs változás +--- git cache HEAD the box has --- diff --git a/documentation/audits/r459-close-2026-09-13/live-9201/01-after-sync.txt b/documentation/audits/r459-close-2026-09-13/live-9201/01-after-sync.txt new file mode 100644 index 00000000..8a76211e --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/live-9201/01-after-sync.txt @@ -0,0 +1,33 @@ +=== AFTER THE SYNC 2026-09-13T08:09:44Z — guest 9201, nothing touched by hand === +--- the sync, in its own words (bookstack lines + the cycle summary) --- +2026/09/13 08:09:17 sync.go:396: [INFO] [sync] Updated bookstack/docker-compose.yml +2026/09/13 08:09:17 sync.go:409: [DEBUG] [sync] bookstack: stored definition refreshed with the delivered fix +2026/09/13 08:09:17 sync.go:541: [DEBUG] [sync] bookstack/docker-compose.yml: src=d45643865f5cf66e, dst=d45643865f5cf66e (changed) +2026/09/13 08:09:17 sync.go:244: [DEBUG] [sync] Post-sync hook: triggering missing field injection for 4 stack(s): [bookstack kimai nextcloud romm] +2026/09/13 08:09:17 sync.go:263: [INFO] [sync] Catalog sync complete +2026/09/13 08:09:17 sync.go:135: [INFO] [sync] Periodic sync: Sablonok frissítve — frissítve: bookstack, kimai, nextcloud, romm +--- live compose, bookstack-db environment block --- + bookstack-db: + image: mariadb:12.3 + container_name: bookstack-db + restart: unless-stopped + environment: + - MYSQL_ROOT_PASSWORD=${DB_PASSWORD} + - MYSQL_DATABASE=bookstack + - MYSQL_USER=bookstack + - MYSQL_PASSWORD=${DB_PASSWORD} + - TZ=Europe/Budapest + # MARIADB_AUTO_UPGRADE: on a MAJOR engine move the engine converts its own datadir (~7 s on a + # small DB, backs its system tables up first). Operator ruling 2026-09-13 on + # felhom.eu/documentation/audits/SPIKE-r459-mariadb-upgrade-2026-09-06.md. Inert until a + # major moves — and none may, until Slice 4 (R-448) ships: see CLAUDE.md, engine-major rule. + - MARIADB_AUTO_UPGRADE=1 + volumes: +--- containers: same IDs and StartedAt as the baseline = NOT recreated by the sync --- +/bookstack 26b555d71e1cf4ea60cd8fc72e34faa6d97ea8a71430d54dc5894cad5a03915d started=2026-09-13T04:21:07.210437498Z restarts=0 +/bookstack-db b02f7a091aebc962c7e15a1337ceb2b1c87c3f03ade7103d4bfddc2dcfc87ce2 started=2026-09-13T04:21:01.47728414Z restarts=0 +--- docker ps --- +bookstack|lscr.io/linuxserver/bookstack:26.05.2|Up 4 hours (healthy) +bookstack-db|mariadb:12.3|Up 4 hours (healthy) +--- the applied definition also carries it (fixes flow INTO the pin) --- +2 diff --git a/documentation/audits/r459-close-2026-09-13/live-9201/02-restart.txt b/documentation/audits/r459-close-2026-09-13/live-9201/02-restart.txt new file mode 100644 index 00000000..3a1dbd43 --- /dev/null +++ b/documentation/audits/r459-close-2026-09-13/live-9201/02-restart.txt @@ -0,0 +1,31 @@ +=== THE ONE DELIBERATE RESTART — POST /api/stacks/bookstack/restart 2026-09-13T08:10:32Z === +login http=302 +session cookie: 79 chars +csrf token: 64 chars (must be 64) +{"ok":true,"message":"Stack bookstack restart completed"} + +restart http=200 +--- waiting for both containers healthy --- +healthy after 8s +--- containers after: NEW ids and StartedAt = the restart recreated them (compose up -d) --- +/bookstack 26b555d71e1cf4ea60cd8fc72e34faa6d97ea8a71430d54dc5894cad5a03915d started=2026-09-13T04:21:07.210437498Z +/bookstack-db 16205e01bdbe56e5849da0c06d5d50e1eb5a70e2e92efaf59d0e09758272d573 started=2026-09-13T08:10:33.353161195Z +--- the ENGINE log after the restart, verbatim (last start) --- +2026-09-13 10:10:33+02:00 [Note] [Entrypoint]: Entrypoint script for MariaDB Server 1:12.3.2+maria~ubu2404 started. +2026-09-13 10:10:33+02:00 [Warn] [Entrypoint]: /sys/fs/cgroup///memory.pressure not writable, functionality unavailable to MariaDB +2026-09-13 10:10:33+02:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' +2026-09-13 10:10:33+02:00 [Note] [Entrypoint]: Entrypoint script for MariaDB Server 1:12.3.2+maria~ubu2404 started. +2026-09-13 10:10:34+02:00 [Note] [Entrypoint]: MariaDB upgrade not required +2026-09-13 10:10:35 0 [Note] mariadbd: ready for connections. +Version: '12.3.2-MariaDB-ubu2404' socket: '/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution +--- the engine asked directly (R-464: not the log) --- +12.3.2-MariaDB +This installation of MariaDB is already upgraded to 12.3.2-MariaDB. +There is no need to run mariadb-upgrade again. +[exit=1] +--- the env is IN the running container --- +MARIADB_AUTO_UPGRADE=1 +--- the app serves --- +GET /login http=200 +bookstack-db|mariadb:12.3|Up 11 seconds (healthy) +bookstack|lscr.io/linuxserver/bookstack:26.05.2|Up 4 hours (healthy) diff --git a/documentation/backlog/OPEN-ITEMS.md b/documentation/backlog/OPEN-ITEMS.md index c05d3fc3..5e69176e 100644 --- a/documentation/backlog/OPEN-ITEMS.md +++ b/documentation/backlog/OPEN-ITEMS.md @@ -217,7 +217,7 @@ the fault was real. Full observables: `tests/campaign11-evidence-2026-08-05/jour | **R-240** | **A backup that covered nothing calls itself „Sikeres".** On a configured box with no app selected for off-site backup, a run reports status `ok` with the warning „Sikeres — nincs mentésre jelölt alkalmazás" — *successful* immediately beside *nothing is selected*. Measured as T4 on the final walk, 2026-08-07; flagged once before (2026-08-06) and deliberately not touched then, because the task that noticed it forbade changing that path. **It is the same rhetorical shape the project has spent a fortnight removing** — R-203's *a warning beside a success is read as a success*, R-234's *„✓ Rendben" over an app that was skipped*, R-225's *unknown rendered as zero* — one notch weaker each time, and this is the weakest and last of them. The state itself is honest and must stay `ok`: an unconfigured box reporting `incomplete` forever is its own defect, pinned by a test. **The defect is the word „Sikeres", not the verdict.** Wording such as „Nincs mentésre jelölt alkalmazás — ez a futás semmit nem mentett" says the same thing without congratulating the customer on it. | **READY** — owner Viktor | -| **R-242** | **A controller release that changes customer-visible behaviour is not delivered until a golden carries it — and nothing enforces that.** R-239 is the symptom; this is the mechanism, recorded **2026-08-07** and deliberately **NOT built** (the task that found it scoped it as a record-only item). **Two releases went out without a golden and the gap was invisible until a walk measured it from the customer's side**: v0.204.0 (R-237) and v0.205.0 (R-234) were written, tested, pushed, and CHANGELOG'd, and every one of those steps passed while a machine installed that night received neither. The register said CLOSED; the fleet said otherwise. **Nothing in the release path knows a golden exists.** The version bump, the image push, the CHANGELOG entry and the register closure are all repo-local; the manifest's `golden_version` is edited by a separate operator act, in a different repo, with no link back. **Proposed shapes, cheapest first — the choice is the operator's and is not taken here.** (a) **A release-path checklist step** — one line in the controller's end-of-session checklist: *a release that changes customer-visible behaviour is not finished until a golden carries it or a register row says why not.* Costs nothing, catches nothing mechanically. (b) **A gate in `repo_gates.py`** comparing the manifest's `golden_version` against the newest released controller and FAILING (or warning) past a tolerance of one minor. Mechanical, runs on every push, and would have fired the morning after v0.204.0. (c) **A hub-side checker** — the hub already knows every box's running controller version from `/hosts` and the vouched golden from the manifest; a periodic comparison against the newest published image would catch drift the repo cannot see, including a vouch that was made and then rolled back. **Earliest catch: (b).** It fires on the push that creates the gap, before any box is installed, and it needs no live fleet. **(c) catches strictly more but only after boxes exist.** (a) is worth doing regardless because it is free. **Not built. No gate was written this session.** **⚠ IT RECURRED WITHIN A DAY, WHICH IS THE ARGUMENT FOR BUILDING IT.** Controller **v0.206.0** shipped the R-241 fixes on 2026-08-07 while the vouched golden still carried **0.205.0** — so a machine installed on the morning of 2026-08-08 would have received neither. Third occurrence of the shape in three days (R-111/R-115/R-120 are the older family). **✅ SHAPE (b) BUILT 2026-08-08 — `scripts/golden_currency_gate.py`, registered in `repo_gates.py` as gate 7.** **It was shown FAILING against that exact state before anything was baked**, which is its red-proof and the reason its own introducing push needed `--no-verify` (stated in the session report rather than worked around): `newest released controller : 0.206.0 / newest golden baked : 0.205.0 → CONVICTED`. **IT IS `--fast`, AND THAT FORCED ITS DESIGN:** both `.githooks/pre-push` AND CI run `repo_gates.py --fast`, so a non-fast gate would run in NEITHER — the R-29 census failure this runner exists to end. **THEREFORE IT CHECKS THE BAKE, NOT THE VOUCH**, because the vouched version lives only in the hub's `hub_settings` with no copy in git, and putting a copy there would create a second source of truth that can drift — a green gate over a false claim being the worst outcome available. **A bake without a vouch still passes: that half is NOT closed and stays on this row.** It also compares versions rather than behaviour, so a release changing nothing customer-visible trips it too — accepted deliberately, because judging that by hand is what failed three times and the cost of a false trip is one bake; a waiver belongs here, never in a habit of bypassing. **VOUCHED 2026-08-08 with the operator's approval** — golden `0.206.0` / sha `c85230b4…108e`; `agent_version` and `min_agent` both stayed `0.127.0`, and `wrapper_sha256` was carried through explicitly because the handler clears it when omitted. **The gate was CONVICTED before the bake and OK after it** — red→green on the same command, which is its proof that it measures something real. **⚠ THE GATE FIRED FOR REAL, 2026-08-08 — and it was right.** Controller **v0.207.0** (R-249/R-252/R-253) is released, tested and pushed, and **no golden carries it** — the newest bake is 0.206.0 — so `golden_currency_gate.py` FAILED, saying exactly the true thing: *a machine installed right now would receive v0.206.0*. **The `felhom.eu` push therefore used `git push --no-verify`, declared here, in the commit message and in the session report.** A bypass and NOT a waiver, deliberately: the gate offers a waiver only for a release that *deliberately needs no golden*, and this one needs one. **Owed: bake golden 0.207.0 and vouch it** (`RUNBOOK-manual-build.md` §4.1; the vouch is a three-field change). **This row's own remaining half is unchanged — nothing gates the VOUCH itself.** **✅ THE OWED BAKE IS DONE, SAME DAY — golden 0.207.0 baked, published, round-trip verified and VOUCHED (2026-08-08).** The gate went from red to **green**, and the `--no-verify` bypass declared above is now historical rather than standing. **Round trip is the evidence, not the build log:** the published bytes were downloaded back — 656 879 192 B, sha256 `20ec9602…22995`, both identical to what the bake reported — and **`./etc/felhom-controller-image` read OUT of the downloaded archive says `felhom-controller:0.207.0`**, which is the delivered artifact naming the controller it will start. **The vouch was a three-field change with all three checked deliberately** (`MinAgent 0.127.0` read from the golden's controller CHANGELOG header, not assumed; `agent_version` already ≥ it; `min_agent` not above `agent_version`, so not the R-216 shape) and verified by **re-reading the manifest rather than trusting the flash**. **This row's remaining half is UNCHANGED and is the whole of what is still open: nothing gates the VOUCH itself** — the currency gate's own docstring says it checks the bake, so a baked-but-unvouched golden still passes it silently. Evidence: `tests/golden-0.207.0-2026-08-08/`. **⚠ RED AGAIN, 2026-08-08 (second time in two days) — controller v0.208.0 (R-254) is released and the vouched golden is 0.207.0.** `golden_currency_gate.py` FAILS, correctly: a machine installed right now receives 0.207.0 and none of today's fixes. **The `felhom.eu` push used `git push --no-verify`, declared in the commit, the CHANGELOG and the session report** — **a bypass, not a waiver**, on the same reasoning as yesterday: the gate offers a waiver only for a release that *deliberately needs no golden*, and this one needs one. **Owed: bake golden 0.208.0 and vouch it** (`RUNBOOK-manual-build.md` §4.1; three-field change, `MinAgent 0.127.0` unchanged). **Note the cadence this is establishing: two releases, two bakes owed within 24 h.** That is the argument for this row's OTHER half — nothing gates the vouch, so the only thing standing between a release and an undelivered fleet is somebody remembering. **⚠ RED AGAIN, 2026-08-30 — controller v0.224.0 (R-330) and v0.225.0 (R-331) are released and the newest golden carries 0.223.0.** `golden_currency_gate.py` FAILS, correctly: a machine installed right now receives 0.223.0 and neither of today's fixes. **The `felhom.eu` push used `git push --no-verify`, declared in the commit message, in `hub/CHANGELOG.md` and in `REPORT.md` — a BYPASS, not a waiver**, on the same reasoning as the two 2026-08-08 entries above: the gate offers a waiver only for a release that *deliberately needs no golden*, and these need one. **The operator was asked and ruled bypass-now-bake-later on 2026-08-30**, on the stated ground that neither fix bites a DAY-0 box — R-330 is a nightly false alarm about apps a new box has not installed yet, and R-331 is a hub-side display over backups a new box has not taken yet — and both arrive by self-update afterwards. **That ground is recorded because it is the thing to re-check, not a general licence: the next release that changes first-boot behaviour cannot reuse it.** **OWED: bake a golden carrying 0.225.0 and vouch it** (`RUNBOOK-manual-build.md` §4.1; three-field change — `golden_version` + `agent_version` + `min_agent`; MinAgent is 0.129.0 per both CHANGELOG headers). **Cadence note, unchanged and now worse: this is the fourth bypass of this gate, and the gap it names is now two releases wide rather than one.** **⚠ WIDENED TO THREE THE SAME DAY — v0.226.0 (R-353/R-357/R-358/R-360) shipped 2026-08-30 and the golden still carries 0.223.0.** The `felhom.eu` push carrying that release's documentation used `git push --no-verify` on the operator's standing ruling from earlier the same day, declared in the commit and in `REPORT.md`. **The day-0 ground still holds for all three and was re-checked rather than assumed:** R-330 alarms about apps a new box has not installed; R-331 is a hub display over backups a new box has not taken; **R-353/357/358/360 are restore-surface fixes, and a day-0 box has nothing to restore.** **The ground expires the moment a release changes first-boot behaviour — that is the thing to re-check, not a licence.** **Owed: ONE bake carrying 0.226.0 covers all three** (`RUNBOOK-manual-build.md` §4.1; three-field vouch, MinAgent 0.129.0), then raise the floor. **✅ PAID THE SAME DAY — golden `0.226.1` baked, published, round-trip verified, VOUCHED, and the floor RAISED (2026-08-30).** Evidence: `documentation/tests/golden-0.226.1-2026-08-30/`. `golden_currency_gate.py` went **red → green** on the same command, which is its proof that it measures something real. **The three declared bypasses above are now HISTORICAL rather than standing.** **The round trip is the evidence, not the build log:** the published bytes were downloaded back — **657 197 592 B, sha256 `70ed8e93…baefe69`**, both identical to what the bake reported — and `./etc/felhom-controller-image` read **out of the downloaded archive** says `felhom-controller:0.226.1`, i.e. the delivered artifact naming the controller it will start. **The three-field vouch was checked deliberately, not assumed:** `MinAgent 0.129.0` read from the golden's controller CHANGELOG header, `agent_version 0.130.0 ≥ min_agent 0.129.0` (so NOT the R-216 shape), and the result verified by **re-reading the manifest** rather than trusting the flash — golden option `0.226.1 SELECTED`, all four shas matching. **The floor is proven ACTING, not merely set:** `demo-felhom` self-updated within 30 s, logging `[selfupdate] Post-update startup: update successful (0.225.0 → 0.226.1)`. **⚠ AND IT HAPPENED AGAIN THE SAME DAY, AND WAS PAID AGAIN.** v0.227.0/v0.227.1 (R-359/R-397) shipped after the 0.226.1 bake, the gate convicted a fifth time, that `felhom.eu` push used `--no-verify` and declared it, and golden **0.227.1** was baked, published, round-trip verified, **VOUCHED** and the floor **RAISED to 0.227.1** within the hour. Evidence: `documentation/tests/golden-0.227.1-2026-08-30/`. **THE CADENCE IS NOW MEASURED RATHER THAN ASSERTED: five convictions and two full bakes in one day.** Every bypass was declared and every debt was paid — but the pattern this row exists to name is exactly that a release and its delivery are separate acts, performed hours apart, by whoever remembers. **The floor was proven ACTING both times:** `demo-felhom` self-updated 0.225.0→0.226.1, then 0.226.1→0.227.1 — and the second time it also registered the new `offsite-integrity` job **by itself, on a box nobody deployed to**, which is the strongest evidence this row has ever carried that a floor delivers rather than merely records. **This row's OTHER half is still open and untouched: nothing gates the VOUCH itself** — the currency gate's own docstring says it checks the bake, so a baked-but-unvouched golden still passes it silently. **2026-08-31, the SEVENTH debt and it was paid the same day — twice in one day.** v0.230.0 shipped in the morning with the newest golden at 0.229.0, **which is the build R-403 says deletes a good copy**, so the gate was red across four commits (`dddcc80`, `6e550ae`, `130f7a6`, `32a4c35`). Golden **0.230.0** baked, published, round-trip verified, vouched, and the fleet floor raised 0.229.0 → 0.230.0; `demo-felhom` moved itself off the defective build unattended (`controller-swap: new controller healthy`, 16:21:40 CEST). Evidence: `documentation/tests/golden-0.230.0-2026-08-31/`. **The gate did its job and its own weakness surfaced doing it — R-410.** | **READY — the vouch half only** — owner Viktor **⚠ SIXTH CONVICTION, 2026-08-31 — controller v0.229.0 (R-102/R-103) is released and the newest golden carries 0.228.0.** `golden_currency_gate.py` FAILS, correctly: a machine installed right now receives 0.228.0 and neither of today's fixes. The `felhom.eu` push carrying this release's documentation used `git push --no-verify`, declared in the commit message and in `felhom-controller/REPORT.md` - **a BYPASS, not a waiver**, on the same reasoning as the five entries above: the gate offers a waiver only for a release that *deliberately needs no golden*, and this one needs one. **The day-0 ground was RE-CHECKED rather than reused:** R-102 and R-103 are restore-surface changes on the Tier-2 card, and a day-0 box has taken no Tier-2 copy and has nothing to restore from one; no first-boot behaviour changed, and `MinAgent` is unchanged at 0.129.0. **The ground still expires the moment a release changes first-boot behaviour.** **OWED: bake a golden carrying 0.229.0 and vouch it** (`RUNBOOK-manual-build.md` §4.1; three-field change - `golden_version` + `agent_version` + `min_agent`, MinAgent 0.129.0), then raise the floor. Fleet floor and golden are 0.228.0 today. **Golden and fleet delivery are the operator's (this row).** **✅ PAID THE SAME DAY — golden `0.229.0` baked, published, round-trip verified, VOUCHED, and the floor RAISED (2026-08-31).** Evidence: `documentation/tests/golden-0.229.0-2026-08-31/`. `golden_currency_gate.py` went **red to green** on the same command, which is its proof that it measures something real. **The `--no-verify` bypass declared above is now HISTORICAL rather than standing.** **The round trip is the evidence, not the build log:** the published bytes were downloaded back - **656 864 331 B, sha256 `39aa886d…d7bdae87`**, both identical to what the bake reported - and `./etc/felhom-controller-image` read **out of the downloaded archive** says `felhom-controller:0.229.0`. **A THIRD independent reader agreed before anything was vouched:** the hub's own Day-0 dropdown read the same sha straight from Gitea, a different code path from the round trip. **The three-field vouch was checked deliberately, not assumed** (`MinAgent 0.129.0` read from the golden's controller CHANGELOG header; `agent_version 0.130.0` >= `min_agent 0.129.0`, so NOT the R-216 shape; `agent_sha256` and `wrapper_sha256` carried through explicitly because the handler clears a field it is not sent), and verified by **re-reading the manifest** rather than trusting the flash. The **R-120 gate passed rather than being bypassed** - fleet newest 0.229.0, golden 0.229.0. **The floor is proven ACTING:** `demo-felhom` self-updated `0.228.0 -> 0.229.0` and logged `settle-gate: GO - at/above floor 0.229.0 (we are 0.229.0)` - **nobody deployed to that box.** **Cadence note: this is the SECOND bake in one day (0.228.0 then 0.229.0) and the sixth conviction, and both debts were paid within the hour.** This row's OTHER half is still open and untouched: **nothing gates the VOUCH itself** - the currency gate checks the bake, so a baked-but-unvouched golden still passes it silently. **⚠ SEVENTH CONVICTION, 2026-08-31 — controller v0.230.0 (R-403) is released and the newest golden carries 0.229.0. AND THIS ONE IS NOT LIKE THE OTHERS: the day-0 ground does NOT apply and must not be reused.** Every previous bypass rested on 'a day-0 box has nothing to restore / nothing to alarm about yet'. R-403 is a defect in the NIGHTLY TIER-2 COPY, which a day-0 box starts running on its first night: a machine installed on 0.229.0 can have a complete recovery package on its second drive replaced by an empty one, and that is measured, not suspected (120 082 104 B -> 7 036 B on demo-hp). **The row's own standing sentence - 'the ground expires the moment a release changes first-boot behaviour' - is what expires it here.** The `felhom.eu` push carrying this release's documentation used `git push --no-verify`, declared in the commit message and in `felhom-controller/REPORT.md` - a BYPASS, not a waiver. **OWED, and more urgent than the previous six: bake a golden carrying 0.230.0, vouch it (three fields, MinAgent 0.129.0 unchanged), and raise the floor.** `demo-hp` was updated by hand; `demo-felhom` is still on 0.229.0 and still carries the defect. **See also R-404, filed today: this is the seventh bypass and the habit is now the thing being reported.** **2026-09-01 (R-404): THE BAKE HALF IS UNCHANGED AND THE VOUCH HALF IS STILL OPEN.** R-404 moved WHO the bake check refuses and added a notice in the controller repo; it did NOT touch what is checked. **Nothing gates the VOUCH.** A baked-but-unvouched golden still passes both the gate and the new notice, and the reason is unchanged and forced: the vouched version lives only in the hub's `hub_settings` table, there is no copy in git, and a hub-reading gate could not be `--fast` so it would run in neither the hook nor CI. **Do not read R-404's closure as closing this.** | +| **R-242** | **A controller release that changes customer-visible behaviour is not delivered until a golden carries it — and nothing enforces that.** R-239 is the symptom; this is the mechanism, recorded **2026-08-07** and deliberately **NOT built** (the task that found it scoped it as a record-only item). **Two releases went out without a golden and the gap was invisible until a walk measured it from the customer's side**: v0.204.0 (R-237) and v0.205.0 (R-234) were written, tested, pushed, and CHANGELOG'd, and every one of those steps passed while a machine installed that night received neither. The register said CLOSED; the fleet said otherwise. **Nothing in the release path knows a golden exists.** The version bump, the image push, the CHANGELOG entry and the register closure are all repo-local; the manifest's `golden_version` is edited by a separate operator act, in a different repo, with no link back. **Proposed shapes, cheapest first — the choice is the operator's and is not taken here.** (a) **A release-path checklist step** — one line in the controller's end-of-session checklist: *a release that changes customer-visible behaviour is not finished until a golden carries it or a register row says why not.* Costs nothing, catches nothing mechanically. (b) **A gate in `repo_gates.py`** comparing the manifest's `golden_version` against the newest released controller and FAILING (or warning) past a tolerance of one minor. Mechanical, runs on every push, and would have fired the morning after v0.204.0. (c) **A hub-side checker** — the hub already knows every box's running controller version from `/hosts` and the vouched golden from the manifest; a periodic comparison against the newest published image would catch drift the repo cannot see, including a vouch that was made and then rolled back. **Earliest catch: (b).** It fires on the push that creates the gap, before any box is installed, and it needs no live fleet. **(c) catches strictly more but only after boxes exist.** (a) is worth doing regardless because it is free. **Not built. No gate was written this session.** **⚠ IT RECURRED WITHIN A DAY, WHICH IS THE ARGUMENT FOR BUILDING IT.** Controller **v0.206.0** shipped the R-241 fixes on 2026-08-07 while the vouched golden still carried **0.205.0** — so a machine installed on the morning of 2026-08-08 would have received neither. Third occurrence of the shape in three days (R-111/R-115/R-120 are the older family). **✅ SHAPE (b) BUILT 2026-08-08 — `scripts/golden_currency_gate.py`, registered in `repo_gates.py` as gate 7.** **It was shown FAILING against that exact state before anything was baked**, which is its red-proof and the reason its own introducing push needed `--no-verify` (stated in the session report rather than worked around): `newest released controller : 0.206.0 / newest golden baked : 0.205.0 → CONVICTED`. **IT IS `--fast`, AND THAT FORCED ITS DESIGN:** both `.githooks/pre-push` AND CI run `repo_gates.py --fast`, so a non-fast gate would run in NEITHER — the R-29 census failure this runner exists to end. **THEREFORE IT CHECKS THE BAKE, NOT THE VOUCH**, because the vouched version lives only in the hub's `hub_settings` with no copy in git, and putting a copy there would create a second source of truth that can drift — a green gate over a false claim being the worst outcome available. **A bake without a vouch still passes: that half is NOT closed and stays on this row.** It also compares versions rather than behaviour, so a release changing nothing customer-visible trips it too — accepted deliberately, because judging that by hand is what failed three times and the cost of a false trip is one bake; a waiver belongs here, never in a habit of bypassing. **VOUCHED 2026-08-08 with the operator's approval** — golden `0.206.0` / sha `c85230b4…108e`; `agent_version` and `min_agent` both stayed `0.127.0`, and `wrapper_sha256` was carried through explicitly because the handler clears it when omitted. **The gate was CONVICTED before the bake and OK after it** — red→green on the same command, which is its proof that it measures something real. **⚠ THE GATE FIRED FOR REAL, 2026-08-08 — and it was right.** Controller **v0.207.0** (R-249/R-252/R-253) is released, tested and pushed, and **no golden carries it** — the newest bake is 0.206.0 — so `golden_currency_gate.py` FAILED, saying exactly the true thing: *a machine installed right now would receive v0.206.0*. **The `felhom.eu` push therefore used `git push --no-verify`, declared here, in the commit message and in the session report.** A bypass and NOT a waiver, deliberately: the gate offers a waiver only for a release that *deliberately needs no golden*, and this one needs one. **Owed: bake golden 0.207.0 and vouch it** (`RUNBOOK-manual-build.md` §4.1; the vouch is a three-field change). **This row's own remaining half is unchanged — nothing gates the VOUCH itself.** **✅ THE OWED BAKE IS DONE, SAME DAY — golden 0.207.0 baked, published, round-trip verified and VOUCHED (2026-08-08).** The gate went from red to **green**, and the `--no-verify` bypass declared above is now historical rather than standing. **Round trip is the evidence, not the build log:** the published bytes were downloaded back — 656 879 192 B, sha256 `20ec9602…22995`, both identical to what the bake reported — and **`./etc/felhom-controller-image` read OUT of the downloaded archive says `felhom-controller:0.207.0`**, which is the delivered artifact naming the controller it will start. **The vouch was a three-field change with all three checked deliberately** (`MinAgent 0.127.0` read from the golden's controller CHANGELOG header, not assumed; `agent_version` already ≥ it; `min_agent` not above `agent_version`, so not the R-216 shape) and verified by **re-reading the manifest rather than trusting the flash**. **This row's remaining half is UNCHANGED and is the whole of what is still open: nothing gates the VOUCH itself** — the currency gate's own docstring says it checks the bake, so a baked-but-unvouched golden still passes it silently. Evidence: `tests/golden-0.207.0-2026-08-08/`. **⚠ RED AGAIN, 2026-08-08 (second time in two days) — controller v0.208.0 (R-254) is released and the vouched golden is 0.207.0.** `golden_currency_gate.py` FAILS, correctly: a machine installed right now receives 0.207.0 and none of today's fixes. **The `felhom.eu` push used `git push --no-verify`, declared in the commit, the CHANGELOG and the session report** — **a bypass, not a waiver**, on the same reasoning as yesterday: the gate offers a waiver only for a release that *deliberately needs no golden*, and this one needs one. **Owed: bake golden 0.208.0 and vouch it** (`RUNBOOK-manual-build.md` §4.1; three-field change, `MinAgent 0.127.0` unchanged). **Note the cadence this is establishing: two releases, two bakes owed within 24 h.** That is the argument for this row's OTHER half — nothing gates the vouch, so the only thing standing between a release and an undelivered fleet is somebody remembering. **⚠ RED AGAIN, 2026-08-30 — controller v0.224.0 (R-330) and v0.225.0 (R-331) are released and the newest golden carries 0.223.0.** `golden_currency_gate.py` FAILS, correctly: a machine installed right now receives 0.223.0 and neither of today's fixes. **The `felhom.eu` push used `git push --no-verify`, declared in the commit message, in `hub/CHANGELOG.md` and in `REPORT.md` — a BYPASS, not a waiver**, on the same reasoning as the two 2026-08-08 entries above: the gate offers a waiver only for a release that *deliberately needs no golden*, and these need one. **The operator was asked and ruled bypass-now-bake-later on 2026-08-30**, on the stated ground that neither fix bites a DAY-0 box — R-330 is a nightly false alarm about apps a new box has not installed yet, and R-331 is a hub-side display over backups a new box has not taken yet — and both arrive by self-update afterwards. **That ground is recorded because it is the thing to re-check, not a general licence: the next release that changes first-boot behaviour cannot reuse it.** **OWED: bake a golden carrying 0.225.0 and vouch it** (`RUNBOOK-manual-build.md` §4.1; three-field change — `golden_version` + `agent_version` + `min_agent`; MinAgent is 0.129.0 per both CHANGELOG headers). **Cadence note, unchanged and now worse: this is the fourth bypass of this gate, and the gap it names is now two releases wide rather than one.** **⚠ WIDENED TO THREE THE SAME DAY — v0.226.0 (R-353/R-357/R-358/R-360) shipped 2026-08-30 and the golden still carries 0.223.0.** The `felhom.eu` push carrying that release's documentation used `git push --no-verify` on the operator's standing ruling from earlier the same day, declared in the commit and in `REPORT.md`. **The day-0 ground still holds for all three and was re-checked rather than assumed:** R-330 alarms about apps a new box has not installed; R-331 is a hub display over backups a new box has not taken; **R-353/357/358/360 are restore-surface fixes, and a day-0 box has nothing to restore.** **The ground expires the moment a release changes first-boot behaviour — that is the thing to re-check, not a licence.** **Owed: ONE bake carrying 0.226.0 covers all three** (`RUNBOOK-manual-build.md` §4.1; three-field vouch, MinAgent 0.129.0), then raise the floor. **✅ PAID THE SAME DAY — golden `0.226.1` baked, published, round-trip verified, VOUCHED, and the floor RAISED (2026-08-30).** Evidence: `documentation/tests/golden-0.226.1-2026-08-30/`. `golden_currency_gate.py` went **red → green** on the same command, which is its proof that it measures something real. **The three declared bypasses above are now HISTORICAL rather than standing.** **The round trip is the evidence, not the build log:** the published bytes were downloaded back — **657 197 592 B, sha256 `70ed8e93…baefe69`**, both identical to what the bake reported — and `./etc/felhom-controller-image` read **out of the downloaded archive** says `felhom-controller:0.226.1`, i.e. the delivered artifact naming the controller it will start. **The three-field vouch was checked deliberately, not assumed:** `MinAgent 0.129.0` read from the golden's controller CHANGELOG header, `agent_version 0.130.0 ≥ min_agent 0.129.0` (so NOT the R-216 shape), and the result verified by **re-reading the manifest** rather than trusting the flash — golden option `0.226.1 SELECTED`, all four shas matching. **The floor is proven ACTING, not merely set:** `demo-felhom` self-updated within 30 s, logging `[selfupdate] Post-update startup: update successful (0.225.0 → 0.226.1)`. **⚠ AND IT HAPPENED AGAIN THE SAME DAY, AND WAS PAID AGAIN.** v0.227.0/v0.227.1 (R-359/R-397) shipped after the 0.226.1 bake, the gate convicted a fifth time, that `felhom.eu` push used `--no-verify` and declared it, and golden **0.227.1** was baked, published, round-trip verified, **VOUCHED** and the floor **RAISED to 0.227.1** within the hour. Evidence: `documentation/tests/golden-0.227.1-2026-08-30/`. **THE CADENCE IS NOW MEASURED RATHER THAN ASSERTED: five convictions and two full bakes in one day.** Every bypass was declared and every debt was paid — but the pattern this row exists to name is exactly that a release and its delivery are separate acts, performed hours apart, by whoever remembers. **The floor was proven ACTING both times:** `demo-felhom` self-updated 0.225.0→0.226.1, then 0.226.1→0.227.1 — and the second time it also registered the new `offsite-integrity` job **by itself, on a box nobody deployed to**, which is the strongest evidence this row has ever carried that a floor delivers rather than merely records. **This row's OTHER half is still open and untouched: nothing gates the VOUCH itself** — the currency gate's own docstring says it checks the bake, so a baked-but-unvouched golden still passes it silently. **2026-08-31, the SEVENTH debt and it was paid the same day — twice in one day.** v0.230.0 shipped in the morning with the newest golden at 0.229.0, **which is the build R-403 says deletes a good copy**, so the gate was red across four commits (`dddcc80`, `6e550ae`, `130f7a6`, `32a4c35`). Golden **0.230.0** baked, published, round-trip verified, vouched, and the fleet floor raised 0.229.0 → 0.230.0; `demo-felhom` moved itself off the defective build unattended (`controller-swap: new controller healthy`, 16:21:40 CEST). Evidence: `documentation/tests/golden-0.230.0-2026-08-31/`. **The gate did its job and its own weakness surfaced doing it — R-410.** | **READY — the vouch half only** — owner Viktor **⚠ SIXTH CONVICTION, 2026-08-31 — controller v0.229.0 (R-102/R-103) is released and the newest golden carries 0.228.0.** `golden_currency_gate.py` FAILS, correctly: a machine installed right now receives 0.228.0 and neither of today's fixes. The `felhom.eu` push carrying this release's documentation used `git push --no-verify`, declared in the commit message and in `felhom-controller/REPORT.md` - **a BYPASS, not a waiver**, on the same reasoning as the five entries above: the gate offers a waiver only for a release that *deliberately needs no golden*, and this one needs one. **The day-0 ground was RE-CHECKED rather than reused:** R-102 and R-103 are restore-surface changes on the Tier-2 card, and a day-0 box has taken no Tier-2 copy and has nothing to restore from one; no first-boot behaviour changed, and `MinAgent` is unchanged at 0.129.0. **The ground still expires the moment a release changes first-boot behaviour.** **OWED: bake a golden carrying 0.229.0 and vouch it** (`RUNBOOK-manual-build.md` §4.1; three-field change - `golden_version` + `agent_version` + `min_agent`, MinAgent 0.129.0), then raise the floor. Fleet floor and golden are 0.228.0 today. **Golden and fleet delivery are the operator's (this row).** **✅ PAID THE SAME DAY — golden `0.229.0` baked, published, round-trip verified, VOUCHED, and the floor RAISED (2026-08-31).** Evidence: `documentation/tests/golden-0.229.0-2026-08-31/`. `golden_currency_gate.py` went **red to green** on the same command, which is its proof that it measures something real. **The `--no-verify` bypass declared above is now HISTORICAL rather than standing.** **The round trip is the evidence, not the build log:** the published bytes were downloaded back - **656 864 331 B, sha256 `39aa886d…d7bdae87`**, both identical to what the bake reported - and `./etc/felhom-controller-image` read **out of the downloaded archive** says `felhom-controller:0.229.0`. **A THIRD independent reader agreed before anything was vouched:** the hub's own Day-0 dropdown read the same sha straight from Gitea, a different code path from the round trip. **The three-field vouch was checked deliberately, not assumed** (`MinAgent 0.129.0` read from the golden's controller CHANGELOG header; `agent_version 0.130.0` >= `min_agent 0.129.0`, so NOT the R-216 shape; `agent_sha256` and `wrapper_sha256` carried through explicitly because the handler clears a field it is not sent), and verified by **re-reading the manifest** rather than trusting the flash. The **R-120 gate passed rather than being bypassed** - fleet newest 0.229.0, golden 0.229.0. **The floor is proven ACTING:** `demo-felhom` self-updated `0.228.0 -> 0.229.0` and logged `settle-gate: GO - at/above floor 0.229.0 (we are 0.229.0)` - **nobody deployed to that box.** **Cadence note: this is the SECOND bake in one day (0.228.0 then 0.229.0) and the sixth conviction, and both debts were paid within the hour.** This row's OTHER half is still open and untouched: **nothing gates the VOUCH itself** - the currency gate checks the bake, so a baked-but-unvouched golden still passes it silently. **⚠ SEVENTH CONVICTION, 2026-08-31 — controller v0.230.0 (R-403) is released and the newest golden carries 0.229.0. AND THIS ONE IS NOT LIKE THE OTHERS: the day-0 ground does NOT apply and must not be reused.** Every previous bypass rested on 'a day-0 box has nothing to restore / nothing to alarm about yet'. R-403 is a defect in the NIGHTLY TIER-2 COPY, which a day-0 box starts running on its first night: a machine installed on 0.229.0 can have a complete recovery package on its second drive replaced by an empty one, and that is measured, not suspected (120 082 104 B -> 7 036 B on demo-hp). **The row's own standing sentence - 'the ground expires the moment a release changes first-boot behaviour' - is what expires it here.** The `felhom.eu` push carrying this release's documentation used `git push --no-verify`, declared in the commit message and in `felhom-controller/REPORT.md` - a BYPASS, not a waiver. **OWED, and more urgent than the previous six: bake a golden carrying 0.230.0, vouch it (three fields, MinAgent 0.129.0 unchanged), and raise the floor.** `demo-hp` was updated by hand; `demo-felhom` is still on 0.229.0 and still carries the defect. **See also R-404, filed today: this is the seventh bypass and the habit is now the thing being reported.** **2026-09-01 (R-404): THE BAKE HALF IS UNCHANGED AND THE VOUCH HALF IS STILL OPEN.** R-404 moved WHO the bake check refuses and added a notice in the controller repo; it did NOT touch what is checked. **Nothing gates the VOUCH.** A baked-but-unvouched golden still passes both the gate and the new notice, and the reason is unchanged and forced: the vouched version lives only in the hub's `hub_settings` table, there is no copy in git, and a hub-reading gate could not be `--fast` so it would run in neither the hook nor CI. **Do not read R-404's closure as closing this.** **2026-09-13 — NARROWED: the WAIVER half is BUILT (R-468).** The docstring's *"honest fix is a recorded waiver in the register, never a habit of bypassing"* is now a mechanism: `golden_currency_gate.py` reads `documentation/tests/golden-waiver.yml` (dated, ≤ 14 days, row-bound), turns a BEHIND conviction into a loud advisory while valid, and is red again when it expires — the difference from this row's original rule, which recurred the next day, is that a dated waiver cannot be forgotten. It never covers an UNRECORDED golden (R-385). Operator ruling the same day: goldens weekly and before any install, not per release. **What stays open on THIS row is exactly one thing: nothing gates the VOUCH.** The waiver does not touch it, and the reason it is unbuilt is unchanged (the vouched version lives only in the hub). | | **R-243** | **A box in the R-241 state silently stops backing up off-site, and NO ALARM OF ANY KIND FIRES.** Found by the R-241 spike (2026-08-07) as a by-product; **not part of the walk's finding and not previously filed.** The R-241 state is self-locking in a second, worse way than the recovery-journey dead end: `escrow_state` is stuck `pending` forever (the auto-confirm flips only on a hash match, and the hash cannot match a key the box minted itself), and `runOffboxBackup` returns at the escrow gate (`offbox.go:743`) before touching anything. **So off-site backups never run again — and the hub never notices.** All three signals that could catch it are excluded, each for its own individually-correct reason, verified in the hub this session: `offsite_stale` — `isStale` (`monitor/offsite.go:135`) returns false unless `EscrowState == "escrowed"`, and its own comment reads *"Pending/disabled = normal onboarding, never stale"*, so the box is classified as **still being set up, forever**; `offsite_delivery_stuck` — `monitor/offsite_delivery.go:91` skips the `applied` shape, and delivery genuinely IS applied (the credential was consumed and the target is in every report); `backup_failed` — never fires, because nothing fails: the run returns `nil` before it starts. **Three correct exclusions leaving one state unobserved.** This is the same class as the workspace `CLAUDE.md` "presence is not success" rule, one level up: **the absence of a failure is being read as the presence of a working tier.** **Partly subsumed by R-241's fix** — a box that recovers leaves this state — but **not for a box that does not**, and the alarm gap is what makes "does not" survivable indefinitely. **Not fixed; no code written.** **⚠ UPDATED 2026-08-07 (v0.206.0) — the STATE this row describes can no longer be entered, but the ALARM GAP is untouched and the row stays open.** R-241's mint guard means a box no longer mints a key over a sealed package, so it no longer arrives in the "escrow stuck pending against a self-minted key" state by itself. **What replaces it is a state that is VISIBLE rather than silent:** the box declares `offsite.state=awaiting_recovery_key` and the customer is offered the recovery screen. **But the hub still raises nothing for it**, and for the same three reasons: `isStale` needs `escrowed`, the delivery checker skips the `applied` shape, and `backup_failed` needs a run that never happens. **So a box whose customer never acts still stops backing up off-site with no operator signal** — the difference is that the customer can now see it and act, where before nobody could. **The remaining work is an operator-side signal for a box held in `awaiting_recovery_key` past some age**, and it is deliberately not bundled into R-241's fix. **⚠ MEASURED ON A REBUILD, 2026-08-07 (fifth walk) — the gap is real for the state this row describes, and NOT for the state a rebuild produces.** 88 seconds after the walk5 guest was destroyed and rebuilt, the hub emitted `offsite_delivery_stuck` (**warning**) and wrote an **operator-channel** `notification_log` row recording `offsite_credential_restaged` / status **REFUSED** with an accurate reason — *"the credential was applied and worked; the target was lost afterwards … a guest rebuild does, R-193"*. So on the **regressed-apply** shape the operator IS told, promptly and correctly, and this row's *"skips the applied shape"* does not apply. The gap stands for a box that reaches the held state **without** a prior working tier in its report history. **Recorded so the row is not read wider than it measures.** | **READY** — owner Viktor | | **R-244** | **The customer DELETE cascade leaves `app_log_issues` behind, and it is systematic across every venue ever torn down.** Found **2026-08-07** while verifying the `finalwalk` teardown with a **full census** (every table, every column) rather than a per-table query. After a cascade that logged `COMPLETE … full teardown`, **61 rows still matched `finalwalk`**. Four of the five sources are **deliberate and correct** — the cascade's own header states *"Provenance/events are NEVER wiped — audit outlives every tier"*: `events` 16, `notification_log` 14, `host_deletions` 1, `customer_resets` 1. **The fifth is a gap:** `app_log_issues` 29 rows, which the residue purge does not touch (its logged leg covers `reports`/`app_telemetry`/`app_log_tails`/`log_tail_requests`/`notif_prefs`/`selfbind_tokens`/`appliance_registrations` — not this table). **It is not a `finalwalk` quirk:** rows still reference **`c11` 40, `rewalk` 20, `part4` 24** — all three torn down 2026-08-06, whose ledger recorded *"0 occurrences"*. **That prior claim was measured with a narrower query and does not survive a full census; the correction is recorded rather than the measurement quietly redone.** **Why it was probably never written, established rather than assumed:** the table is a **fleet-wide aggregate** keyed on `app_name`+`fingerprint` with an `affected_customers` JSON list — of the 29 `finalwalk` rows, **12 reference only `finalwalk`** (orphans, safely deletable) and **17 are shared with LIVE customers** (`demo-felhom`, `peti-felhom`, …) and **must not be deleted, only de-referenced.** A naive `DELETE … WHERE customer LIKE` would destroy a live customer's issue history — which is very likely why the leg does not exist, and is the reason this is not a one-line fix. **Severity is LOW and stated plainly: no secret material is involved** — app name, fingerprint, message text, counts, timestamps. What survives is a deleted customer's *identifier* inside an aggregate row. **Proposed shape:** a residue leg that (a) removes the customer id from `affected_customers`/`context_customer`, and (b) deletes rows whose `affected_customers` becomes empty; plus a one-off sweep for the four already-torn-down venues. **The general lesson is the reusable part:** *a per-table absence query is not a census.* The teardown verification is now a full-schema sweep, and that is what found this. **Not fixed** — a cascade change needs its own red-proof and this session was scoped as a spike plus two operations. Evidence: `tests/teardown-finalwalk-2026-08-07.md`. **⚠ STILL OWED, AND NOW MEASURED RATHER THAN ESTIMATED (2026-08-08 census, read-only, no truncation).** `app_log_issues` holds **1309 rows**; **71 reference a torn-down venue** (`finalwalk`, `c11`, `rewalk`, `part4`); of those **44 are ORPHANS** — they name only torn-down customers and are safely deletable — and **27 are SHARED with a live customer** (`demo-felhom`, `peti-felhom`, …) and **must be de-referenced, never deleted**. 1238 rows are untouched. **The 27 are exactly why the leg was never written**, and why a `DELETE … WHERE customer LIKE` would destroy a live customer's issue history. **What it needs, precisely:** a cascade leg that (a) removes the customer id from `affected_customers` / `context_customer`, and (b) deletes only rows whose `affected_customers` becomes empty; plus a one-off sweep for the four venues already gone. **Why it was NOT done on 2026-08-08:** the fix is hub code, and that session's scope forbade a hub version bump; a hand-run SQL mutation over 71 rows — 27 of them needing surgical de-referencing — with no tested code path and no red-proof is precisely the shape that goes wrong on a live database. **It accumulates one venue at a time, so the next walk adds to it**; the numbers above mean the next session starts from data rather than a guess. **⚠ IT GREW AGAIN, AS PREDICTED — walk5 teardown, 2026-08-08.** The fifth walk's venue was torn down with a full-schema census taken **before and after**: **168 rows → 67**. Of the 67, **37 are by design** (`events` 21, `notification_log` 14, `host_deletions` 1, `customer_resets` 1) and **30 are `app_log_issues`** — this row's gap, and the count was **predicted in the pre-run enumeration rather than discovered afterwards**, which is the difference from the ledger that once recorded *"0 occurrences"* from a narrower query. **The running total across torn-down venues therefore rises from 71 to ~101 rows** (`finalwalk`, `c11`, `rewalk`, `part4`, now `walk5`) — the shared-with-a-live-customer subset must still be **de-referenced, never deleted**. **It accumulates one venue at a time and it did so again.** Evidence: `tests/walk5-r201-2026-08-07/teardown-walk5-2026-08-08.md`. | **READY** — owner Viktor | @@ -690,7 +690,7 @@ class (an image `VOLUME` at an unmounted path) is still live — `immich-server` | **R-456** | **[P3-LOW] A partly-dead stack is not a boot orphan, and that is written down nowhere.** MEASURED 2026-09-02 on demo-hp while validating v0.233.0: `docker rm -f bookstack` (leaving `bookstack-db` running) then a controller restart produced `Boot reconciliation: 1 boot-orphaned app(s) found: [bentopdf]` — **bookstack was NOT selected**, although the app container was gone and `desired_state: running` was recorded. Removing `bookstack-db` as well made the whole stack orphaned and the very next pass repaired it in 6.3 s. **So `bootrecon.isBootOrphan` requires the stack as a WHOLE to be down; one live member is enough to make it invisible to the reconciler.** **NOT called a defect, and the reason is part of the row:** `StateDegraded` IS in `IsDownState`, and the crash-loop/dead-app alarm path (`classifyRunStates`) does count a degraded stack as down — so the customer IS told; it is the automatic REPAIR that does not fire, and there may be a good reason (repairing half a stack while its DB is live is not obviously safe). **What is certain is that nobody has written the rule down**, so the next session re-derives it the same way this one did — by watching a reconciliation not happen, which is an absent observable and the weakest possible evidence. Either state the rule in `02-controller-module-map.md` with a test pinning it, or change it. Owner: **CC.** `tests/VALIDATION-update-slice12-2026-09-02.md` §2.2 | **READY — rank P3-LOW; owner: CC** | | **R-457** | **[P3-LOW] A test that hardcodes a date AND asserts an age derived from it is green on the day it is written and red the next morning — one instance PROVEN, six candidate files named.** MEASURED 2026-09-03: `TestGroupD_BadgeRendersOnBothSurfaces` (shipped the previous day in v0.233.0) pinned a fixture `catalog_since: "2026-07-18"` and asserted the rendered string `"Frissítés elérhető — 46 napja"`. **The pure badge tests inject a clock; the RENDER test does not and cannot** — it goes through the production templates, which call the funcmap entry `updateBadge`, which reads `time.Now()`. The suite was green on 2026-09-02 and **FAILED on 2026-09-03** with *"the behind badge is missing"* on both surfaces, because the true answer had become 47. **Fixed by DERIVING the fixture** — `catalog_since` is computed as *today minus 46 days*, so the test asserts the real number through the real clock and cannot rot. **THE CLASS, which is why this is a row and not just a fix:** a clock-reading test that also carries a date LITERAL is a bomb with a fuse of unknown length, and the suite being green is not evidence it is defused — it is evidence the fuse has not burned down yet. **NAMED AS UNCHECKED CANDIDATES, NOT ACCUSED** — six other test files contain both a `20xx-xx-xx` literal and `time.Now()`: `internal/backup/offbox_test.go`, `internal/web/handler_export_upload_test.go`, `internal/web/r103_tier2_action_test.go`, `internal/web/dashboard_backup_card_test.go`, `internal/web/async_restore_test.go`, `internal/stacks/installed_test.go`. Mixing the two is not itself a defect — it is one only where a literal feeds an assertion evaluated against the real clock — so each needs reading, which is a sweep and not this session. **The instrument that would end the class:** run the suite once under a faked future date in CI and see what turns red. Owner: **CC.** `felhom-controller` v0.234.0 CHANGELOG | **READY — rank P3-LOW; owner: CC** | | **R-458** | **[P3-LOW] `.felhom.yml` keeps flowing to an app whose compose file is FROZEN, so a frozen app can receive a health check written for a version it is not running.** The v0.235.0 render freezes `docker-compose.yml` for a pinned app once the catalog moves past its version, but copies `.felhom.yml` **verbatim in every case** (`Syncer.copyTemplates`). **The asymmetry is deliberate and both directions were considered:** `.felhom.yml` carries no image, and it carries `catalog_since` — the single input the update badge uses to say *„Frissítés elérhető — N napja"* — so freezing it would silently withhold the one number that tells a customer they are behind, i.e. it would break slice 2 to protect slice 3. **What it costs:** the file also carries the controller-side `healthcheck:` block and resource hints, so a template updated for a newer version can hand a frozen app a probe written for software it is not running. **THE FAILURE DIRECTION IS A FALSE ALARM, NEVER DATA LOSS** — the app keeps running; at worst it renders as degraded and, if it persisted, could reach the dead-app alarm path. That is the same class as R-330's false e-mails, which is why this is a row and not a footnote. **Not fixed now, and the reason is that the cheap fix is wrong:** freezing the whole file breaks the badge, and freezing only the `healthcheck:` key means the syncer would have to parse and re-assemble a customer-facing metadata file — new surface on the one path that touches every app on every box every 15 minutes. **What would settle it:** whether any catalog `healthcheck:` has ever been changed in the same commit as an `image:` line (measurable from the catalog's own history, no box needed). If the answer is "never", the exposure is theoretical and the row can be closed by measurement instead of by code. Owner: **CC.** `architecture/09-update-architecture.md` §5.4, §8.5 | **READY — rank P3-LOW; owner: CC** | -| **R-459** | **[P3-LOW, was P2] MEASURED 2026-09-06 — the skipped MariaDB conversion is STABLE but never self-resolving, and fixing it costs 7 SECONDS and does NOT cost the ability to go back.** The consequence R-459 deliberately left unmeasured is now measured: `audits/SPIKE-r459-mariadb-upgrade-2026-09-06.md`. **(1) It does not degrade: 5 of 5 restarts of 12.3 on the 11.6 datadir, readback passed every time, `mariadb_upgrade_info` unchanged at `11.6.2-MariaDB`, and the entrypoint's line never escalated past `[Note]`.** **(2) It never heals either** — the engine answers `Major version upgrade detected from 11.6.2-MariaDB to 12.3.3-MariaDB. Check required!` on every start, and will forever. **(3) THE TRADE THIS ROW WAS EXPECTED TO PRODUCE DOES NOT EXIST.** The fear was that converting properly would end the ability to abort. Measured: with `MARIADB_AUTO_UPGRADE=1` the conversion **succeeds** across the multi-major jump (so it is not a stepping problem either), takes **7 s**, takes its own system-database backup first (`system_mysql_backup_11.6.2-MariaDB.sql.zst`), and **putting 11.6 back afterwards still starts and serves the data**. **So the choice is no longer a trade; it is a cheap correction.** **WHAT REMAINS OPEN IS THE DECISION, NOT THE MEASUREMENT:** setting `MARIADB_AUTO_UPGRADE` changes how **four** apps upgrade — bookstack (the only one that has moved a major), kimai, nextcloud, romm — and R-459's original owner line reserves a fleet-wide env change for the operator. **Nothing was committed to any template**; the comparison arm used a scratch copy inside a throwaway guest. **NOT ESTABLISHED, and not smuggled in: whether any specific MariaDB FEATURE misbehaves on unconverted system tables.** This run exercised BookStack's normal read/write path only, over minutes, with one seeded record. **Rank dropped P2 → P3** because the failure mode is now bounded by measurement rather than unknown. Raised in `STATUS.md`. | **WAITING-ON-OPERATOR — rank P3-LOW; owner: VIKTOR rules on the fleet-wide env, CC implements** | +| **R-459** | **[P3-LOW, was P2] MEASURED 2026-09-06 — the skipped MariaDB conversion is STABLE but never self-resolving, and fixing it costs 7 SECONDS and does NOT cost the ability to go back.** The consequence R-459 deliberately left unmeasured is now measured: `audits/SPIKE-r459-mariadb-upgrade-2026-09-06.md`. **(1) It does not degrade: 5 of 5 restarts of 12.3 on the 11.6 datadir, readback passed every time, `mariadb_upgrade_info` unchanged at `11.6.2-MariaDB`, and the entrypoint's line never escalated past `[Note]`.** **(2) It never heals either** — the engine answers `Major version upgrade detected from 11.6.2-MariaDB to 12.3.3-MariaDB. Check required!` on every start, and will forever. **(3) THE TRADE THIS ROW WAS EXPECTED TO PRODUCE DOES NOT EXIST.** The fear was that converting properly would end the ability to abort. Measured: with `MARIADB_AUTO_UPGRADE=1` the conversion **succeeds** across the multi-major jump (so it is not a stepping problem either), takes **7 s**, takes its own system-database backup first (`system_mysql_backup_11.6.2-MariaDB.sql.zst`), and **putting 11.6 back afterwards still starts and serves the data**. **So the choice is no longer a trade; it is a cheap correction.** **WHAT REMAINS OPEN IS THE DECISION, NOT THE MEASUREMENT:** setting `MARIADB_AUTO_UPGRADE` changes how **four** apps upgrade — bookstack (the only one that has moved a major), kimai, nextcloud, romm — and R-459's original owner line reserves a fleet-wide env change for the operator. **Nothing was committed to any template**; the comparison arm used a scratch copy inside a throwaway guest. **NOT ESTABLISHED, and not smuggled in: whether any specific MariaDB FEATURE misbehaves on unconverted system tables.** This run exercised BookStack's normal read/write path only, over minutes, with one seeded record. **Rank dropped P2 → P3** because the failure mode is now bounded by measurement rather than unknown. Raised in `STATUS.md`. **✅ RULED YES 2026-09-13 and SHIPPED the same day** (catalog `eec1228`/`bd32830`/`3525e35`): `MARIADB_AUTO_UPGRADE=1` on `bookstack-db`, `kimai-db`, `nextcloud-db`, `romm-db`; `MARIADB_DISABLE_UPGRADE_BACKUP` unset; no image line moved so `catalog_since` did not. **Proven before it shipped** (throwaway LXC 9403 on demo-hp, destroyed; `audits/r459-close-2026-09-13/harness/`): C3 still `failed`; E3 and E3b `proven` with `engine_state_after` = `12.3.3-MariaDB | This installation of MariaDB is already upgraded to 12.3.3-MariaDB. There is no need to run mariadb-upgrade again. [exit=1]`; the entrypoint printed `Backing up system database to system_mysql_backup_11.6.2-MariaDB.sql.zst` → `Starting mariadb-upgrade` → `Finished mariadb-upgrade` (6 s) and `skipped due to $MARIADB_AUTO_UPGRADE` **0** times. **Watched as it landed** (`live-9201/`): the change travelled the real 15-minute cycle to demo-hp at 08:09:17 UTC — `[INFO] [sync] Updated bookstack/docker-compose.yml`, `stored definition refreshed with the delivered fix` — the live compose gained the setting, **both container IDs and `StartedAt` were identical to the pre-push baseline (nothing recreated)**, and the one deliberate `POST /api/stacks/bookstack/restart` logged `MariaDB upgrade not required`, the engine's own check said `already upgraded to 12.3.2-MariaDB [exit=1]`, and `/login` served 200. **The precaution that keeps the setting inert:** the engine-major rule + gate (R-469). **Still not established, unchanged:** whether any MariaDB feature misbehaves on an UNCONVERTED datadir — moot for boxes that convert from now on, live for any datadir converted before today (none: only bookstack ever moved a major, and its demo datadir was born on 12.3). | **CLOSED — 2026-09-13** | | **R-460** | **[P3-LOW] BookStack's FILE half cannot be seeded or verified without a browser, so its upgrades can only ever be auto-proven for the DATABASE.** MEASURED 2026-09-06 while building the R-449 harness. BookStack's API needs a token that is only mintable through its web UI, and its HTTP login is unusable headlessly for a second, independent reason: `APP_URL` comes from the template as `https://${SUBDOMAIN}.${DOMAIN}`, so the app marks its session and XSRF cookies **`secure`**; curl over plain http stores neither and **every login POST returns 419 Page Expired**, which looks exactly like a wrong password. The container serves no TLS. **The database half IS provable** — the harness seeds with `php artisan bookstack:create-admin` and reads back with a DIFFERENT artisan command that must find the record, carrying its own negative control on every call. **What is unprovable is an uploaded image or attachment**, i.e. exactly the half a customer would notice. **THIS IS A FACT ABOUT THE APP, NOT A DEFECT IN THE HARNESS**, and it is recorded because Slice 6 needs to know which apps can be auto-verified and which can only be partly verified — nobody had that list before. **Deliberately NOT worked around:** planting a file in the volume would make the test pass while proving nothing, which is R-156's exact failure. **What would remove it:** a headless token route (upstream), or accepting a browser-driven step for this app alone, which DooPlex cannot run. Owner: **CC.** `audits/SPIKE-upgrade-test-2026-09-06.md` §6 | **READY — rank P3-LOW; owner: CC** | | **R-461** | **[P3-LOW] `runbooks/target-selection.md` names a venue that does not exist and fences a fixture that is gone.** MEASURED 2026-09-06 on demo-hp while siting the R-449 guest. (a) The runbook says to put VM disks on a dir storage at **`/mnt/nvme-1tb`, at its root**. **There is no `/mnt/nvme-1tb`** — the 1 TB NVMe is mounted at **`/mnt/hdd_1`**, which is the enrolled user-data drive and the `felhom-backup` target, i.e. the same disk under a different path. The instruction's REASON is still exactly right (`local-lvm` is an over-subscribed thin pool backing the live guest 9201, and this run kept off it — `local-lvm` read **30.50 % before and after**), so the fence held; only its address is stale. (b) The runbook forbids destroying **`drill-r50` (VM 300)**, "the only drift fixture (R-93)". **`qm list` returns nothing on demo-hp** — there are no VMs at all. **The fence currently protects nothing, and R-93's premise that a drift fixture exists is false.** **Why it is a row and not a quiet edit:** a runbook that names a path nobody can find is one a session works around, and working around a safety instruction is how the instruction stops being followed. Both halves need checking against the box before the text is changed — (b) in particular may mean R-93 should be closed or reopened as "the drift fixture is gone", which is a different fact from "do not destroy it". Owner: **CC.** `audits/SPIKE-upgrade-test-2026-09-06.md` §7 | **READY — rank P3-LOW; owner: CC** | | **R-462** | **[P2-MEDIUM] Widen the upgrade harness beyond three apps — and the cost is dominated by FIXTURES, not by machine time.** The R-449 harness works and is proven by a red negative control (`audits/SPIKE-upgrade-test-2026-09-06.md` §1). **Costed with this run's REAL numbers rather than an estimate:** a successful edge takes **6.4 s – 305.1 s, median 71.8 s**; a FAILING edge takes **556 s**, roughly **8×**, because a negative is only honest if it waits out the full settle window; 3 apps / 11 images cost **5.07 GB**, so 53 apps naively extrapolate to **~90 GB** and, at the median, about an hour of harness time for one edge each. **THAT EXTRAPOLATION UNDERSTATES THE REAL COST BY AN ORDER OF MAGNITUDE, and that is the point of this row.** Two of the three apps needed a bespoke non-browser seed route; one needed two attempts and a discarded approach; one (bookstack) can only ever be half-proven (R-460). **Fixture time scales with apps and does not amortise.** **The decision this row is really asking for is scope, not schedule:** all 53, or only the apps a customer would lose data from, or only apps whose catalog transition is a MAJOR. **Recommended shape, NOT a design — the operator picks:** start with the apps that carry a database, because §3 measured that the abort question only ever bites there. Owner: **VIKTOR rules on scope, CC implements.** `audits/SPIKE-upgrade-test-2026-09-06.md` §5 | **READY — rank P2-MEDIUM; owner: VIKTOR rules on scope, CC implements** | @@ -698,7 +698,13 @@ class (an image `VOLUME` at an unmounted path) is still live — `immich-server` | **R-464** | **[P3-LOW] MariaDB's entrypoint prints `MariaDB upgrade not required` on an UNSUPPORTED DOWNGRADE, so that line cannot be used as a soundness signal.** MEASURED 2026-09-06. After converting a datadir to `12.3.3-MariaDB` and then starting **11.6** on it, the entrypoint logs, on every start: **`[Note] [Entrypoint]: MariaDB upgrade not required`**. Asked properly, the same engine answers **`FATAL ERROR: Version mismatch (12.3.3-MariaDB -> 11.6.2-MariaDB): Trying to downgrade from a higher to lower version is not supported!`** **The entrypoint compares the datadir's recorded version against its own and concludes there is nothing to DO. That is true, and it is not a statement that the state is sound.** **THIS IS THIS PROJECT'S MOST-REPEATED CLASS, in a new costume** — the same shape as `CLAUDE.md`'s "presence is not success" and as R-443's HTTP 200 over a crash-looping app: a reassuring sentence that answers a narrower question than the one a reader will take it for. **Why it is worth a row rather than a footnote: the obvious cheap instrument for R-459 is to grep container logs for that exact line**, and such an instrument would report "fine" for an unsupported downgrade. **The correct probe is `mariadb-upgrade --check-if-upgrade-is-needed`**, which is what `upgrade-test.py`'s `engine_state_after` now uses. **Also recorded, because it nearly produced a wrong answer here: run without credentials that command returns `ERROR 1045 … FATAL ERROR: Upgrade failed` with exit 1** — an authentication failure wearing the shape of a verdict. Owner: **CC.** `audits/SPIKE-r459-mariadb-upgrade-2026-09-06.md` §5.4 | **READY — rank P3-LOW; owner: CC** | | **R-465** | **[P3-LOW] `cfg.Paths.HDDPath` — the global that R-442 proved is set on NO box (demo-hp AND demo-felhom: 0 `hdd_path`, 0 `FELHOM_PATHS_*`) — still has SIX readers, each reading an always-empty value:** `report/builder.go:69`, `monitor/healthcheck.go:35`, `api/router.go` (system-info), `web/server.go:740`, `cmd/controller/main.go` (auto-discovery seed + metrics HDD path). Removal was silently inert for months on the very same read. Whether any of these is inert the same way — a report field that is always empty, a health check that never fires, a metric never collected — is a one-hour audit: for each reader, name the POSITIVE observable that must appear when it works and check it on the box. R-442 §5 said "do not delete it here"; this row is the audit it deferred. Owner: **CC.** `felhom-controller/REPORT.md` (v0.236.0, Observations 1) | **READY — rank P3-LOW; owner: CC** | | **R-466** | **[P3-LOW] Removing an app with „Mentési adatok törlése" ticked leaves its recovery unit's `compose/` + `manifest.json` on the drive.** The router passes only `backup.AppDBDumpPath(nsRoot, name)` to `RemoveStack`, so `backups/primary//db-dumps/` goes and the unit root keeps `compose/` (the app's `app.yaml` with the portable secret class at 0600) and `manifest.json`. MEASURED 2026-09-13 on demo-hp after the R-442 Scenario A removal — `audits/R442-2026-09-13/teardown-and-log.txt`, residue check: `backups/primary/nextcloud` still listed with the app gone; removed by hand at teardown. A customer who asked for the backups to go is left with the app's definition and a manifest. **Decide:** the button means the WHOLE unit (pass the unit root, under the same `backups/`-prefix guard) or stays db-dumps-only (then the modal must say so). Owner: **CC.** | **READY — rank P3-LOW; owner: CC** | -| **R-467** | **[P3-LOW] Controller v0.236.0 owes a golden** (golden-notice gate, 2026-09-13): newest golden baked is **0.232.0**, so a machine installed now receives 0.232.0 and reaches 0.236.0 only by self-update. Bake + vouch per `runbooks/RUNBOOK-manual-build.md` §4.1 (the THREE-field vouch: `golden_version` + `agent_version` + `min_agent`); bake record to `documentation/tests/golden--/`. If the train deliberately skips this version, this row is the waiver the gate asks for. Owner: **CC.** | **READY — rank P3-LOW; owner: CC** | +| **R-467** | **[P3-LOW] Controller v0.236.0 owes a golden** (golden-notice gate, 2026-09-13): newest golden baked is **0.232.0**, so a machine installed now receives 0.232.0 and reaches 0.236.0 only by self-update. Bake + vouch per `runbooks/RUNBOOK-manual-build.md` §4.1 (the THREE-field vouch: `golden_version` + `agent_version` + `min_agent`); bake record to `documentation/tests/golden--/`. If the train deliberately skips this version, this row is the waiver the gate asks for. Owner: **CC.** **✅ PAID 2026-09-13 — golden `0.236.0` baked, published, round-trip verified, VOUCHED, floor RAISED 0.232.0 → 0.236.0.** Evidence `documentation/tests/golden-0.236.0-2026-09-13/`: bake `GOLDEN_SHA256=58a3cc24…958bf`, round trip 654 115 664 B same sha hashed from the DOWNLOADED bytes, `./etc/felhom-controller-image` out of the archive says `felhom-controller:0.236.0`, the hub's Day-0 dropdown read the same sha on its own code path; three-field vouch re-read from the page (`golden_version 0.236.0`, `agent_version 0.130.0`, `min_agent 0.129.0` — NOT the R-216 shape), R-120 banner absent; floor re-read `0.236.0`. **This bake carried FOUR unbaked releases (0.233.0…0.236.0)** and it is the LAST per-release bake — goldens are on a weekly cadence from today (R-468). Both demo guests already ran 0.236.0 by hand, so the floor moved nothing; the chain was last exercised 2026-09-01. `golden_currency_gate.py` went red → green on the same command. The MinAgent line was missing from four headers — R-470. | **CLOSED — 2026-09-13** | + +| **R-468** | **[P3-LOW] THE GOLDEN WAIVER — goldens on a cadence, not per release (operator ruling 2026-09-13).** 25 goldens in 26 days in August, almost one per release, because `golden_currency_gate.py` trips on every release by design and the only honest ways past it were a bake or a declared `--no-verify` (thirteen by 2026-09-01, R-404/R-417). **The ruling: bake WEEKLY, and always before any drill or fresh install.** Every release still raises the FLOOR, so both demo boxes keep getting each release in ~20 s; only the golden — which protects a fresh install and nothing else — moves to a cadence. **The mechanism (built 2026-09-13):** `documentation/tests/golden-waiver.yml`, four lines (`issued`, `expires`, `reason`, `register_row: R-468`), read by the gate. While valid, a golden BEHIND the record makes the gate print a loud ADVISORY and exit 0; when it expires the gate is red again until someone bakes or renews. **The 14-day cap is enforced by the gate, not the runbook** — a longer, undated, unparseable, reason-less or row-less waiver is INCONCLUSIVE (exit 2), never 0 and never silently ignored. **It never covers a golden that is UNRECORDED (R-385)** — that is not a cadence choice. **A dated waiver cannot be forgotten; it just expires** — the difference from R-242's original rule, which recurred the day after it was written. Tests: `scripts/test_golden_currency_gate.py` cases 5–15 (E/F/G/H, a 15-day, absent, unparseable, bad-row and empty-reason waiver each 2; the R-421 decoy — a file saying only `expires` — 2). **This is a PRE-CUSTOMER arrangement: the first external install retires it** (delete the file in that commit). Cadence written into `RUNBOOK-manual-build.md` §4.2 and the `felhom.eu` end-of-session checklist. **Does NOT touch R-242's open half (nothing gates the VOUCH).** | **WATCHING — rank P3-LOW; owner: CC (renew ≤ 14 days or bake); retire at the first external install** | +| **R-469** | **[P3-LOW] REMOVE THE ENGINE-MAJOR RULE when Slice 4 (R-448) ships — a tracked act, not a lapse.** Since 2026-09-13 `app-catalog-felhom.eu` `CLAUDE.md` rules that *until the Update button takes a verified backup as its precondition, no template may move a database-engine image across a major version* (four MariaDB, eleven PostgreSQL services), and `scripts/check-engine-major.py` (fourth row of `catalog_gates.py`, run by `.githooks/pre-push` with the push range) refuses one, naming the rule and this expiry. **Why the rule:** every `mariadb:` sidecar now carries `MARIADB_AUTO_UPGRADE=1` (R-459), so a MariaDB major move CONVERTS the customer's datadir on the next Update; PostgreSQL converts nothing and refuses to start (R-463). Either way a customer-data event with no backup in front of it. **Honest limit, not re-filed:** the gate needs a parent commit and CI fetches at `--depth 1` — the R-452 gap — so on a shallow clone the runner skips it out loud and only the hook bites. **When R-448 ships:** delete the CLAUDE.md rule, the gate's row and the gate, in one commit that cites this row; then close this. | **BLOCKED — on R-448; rank P3-LOW; owner: CC** | +| **R-470** | **[P3-LOW] Four consecutive controller CHANGELOG headers (v0.233.0 … v0.236.0) carry NO `MinAgent:` line, and `RUNBOOK-manual-build.md` §4.1 step 5 tells the vouch to read it from the header.** Measured 2026-09-13 while baking golden 0.236.0: `sed -n 1,349p CHANGELOG.md | grep -c MinAgent` → **0**; the newest statement is v0.232.0's `**MinAgent: 0.129.0** (unchanged)`. The vouch used 0.129.0 on the ground that no later entry declares a change and `internal/agentapi/features.go` gates per feature, not per release — but a reader following the runbook literally finds nothing to read, which is the R-233 shape (a document pointing at a string that is not there). **Fix:** either every release header carries the line (the v0.232.0 convention), or the runbook says where MinAgent actually lives when a header omits it. One of the two, not both. | **READY — rank P3-LOW; owner: CC** | + +| **R-471** | **[P3-LOW] `observations_gate.py` reads the FIRST `Observations` section of `REPORT.md` and nothing after it, so an appended second section with an unmarked item passes — and the decoy that proves it has been reading "LIVE HOLE" at HEAD, unnoticed, because the decoy suite is run by hand.** MEASURED 2026-09-13 on a clean worktree of `4b2e560`: `python3 scripts/test_gate_decoys.py` → `FAIL: observations/R-419: decoy PASSED - LIVE HOLE (rc=0)`; the gate's own output shows it scanned `## 11. Observations — noticed, documented, NOT acted on` (3 items, all marked) and never reached the appended `## Observations` block the decoy planted. Whether the cause is "first heading wins" or a heading-shape filter is NOT established — only that the planted unmarked item was not seen. **Consequence:** a report with two observation sections gets the second one unchecked. **Two fixes, both owed:** scan every section whose heading contains `Observations`, and put `test_gate_decoys.py` where something runs it (it is the instrument for R-421 and nothing in `repo_gates.py` invokes it). | **READY — rank P3-LOW; owner: CC** |