Compare commits
2
Commits
4b2e5608c2
...
4727aaa5ad
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4727aaa5ad | ||
|
|
ae59c31a84 |
No files matched your search
@@ -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
|
||||
|
||||
+27
@@ -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.**
|
||||
|
||||
@@ -1,181 +1,271 @@
|
||||
# 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` | `ae59c31` (documents + gate + evidence) → the compression commit on top |
|
||||
| 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=<remote sha>..<local sha>`. 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.
|
||||
|
||||
`python3 scripts/unproven.py --summary`: 55 claims, walked 20 / partial 17 / built 14 / missing 4,
|
||||
**NOT WALKED 35 of 55 — unchanged** (nothing in this session walked a capability claim).
|
||||
|
||||
**CI, by `head_sha`:** app-catalog job **536** for `3525e35` → `completed` / `success`. The
|
||||
felhom.eu run for this push is quoted in the follow-up commit that records it.
|
||||
|
||||
## 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` in the second commit, citing `ae59c31` for the full text; nothing deleted).
|
||||
`OPEN-ITEMS.md`: 433 845 → 434988 bytes with the four new rows and two closures written out, → 429692 bytes after compression.
|
||||
|
||||
## 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. **The stack restart recreated only the changed service** — bookstack-db got a new ID, the bookstack
|
||||
app container kept its 4-hour uptime — because the restart is compose up -d, which the update
|
||||
architecture §1.3 records as a chosen behaviour.
|
||||
**NOT-A-FINDING: documented design, and "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.**
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
+8
@@ -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
|
||||
+12
@@ -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
|
||||
+12
@@ -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
|
||||
+12
@@ -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 — <what changed>' 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-<VER>-<DATE>/ directory — never leave it to read as shipped.
|
||||
|
||||
exit=1
|
||||
@@ -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
|
||||
+8
@@ -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
|
||||
+23
@@ -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
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"privatebin": {
|
||||
"status": "running",
|
||||
"health": "healthy",
|
||||
"restarts": 0,
|
||||
"exit": 0
|
||||
}
|
||||
}
|
||||
@@ -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" "-"
|
||||
@@ -0,0 +1 @@
|
||||
null
|
||||
Whitespace-only changes.
@@ -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
|
||||
Whitespace-only changes.
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"privatebin": {
|
||||
"status": "restarting",
|
||||
"health": "unhealthy",
|
||||
"restarts": 0,
|
||||
"exit": 0
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"bookstack": {
|
||||
"status": "running",
|
||||
"health": "healthy",
|
||||
"restarts": 0,
|
||||
"exit": 0
|
||||
},
|
||||
"bookstack-db": {
|
||||
"status": "running",
|
||||
"health": "healthy",
|
||||
"restarts": 0,
|
||||
"exit": 0
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"bookstack": {
|
||||
"status": "running",
|
||||
"health": "healthy",
|
||||
"restarts": 0,
|
||||
"exit": 0
|
||||
},
|
||||
"bookstack-db": {
|
||||
"status": "running",
|
||||
"health": "healthy",
|
||||
"restarts": 0,
|
||||
"exit": 0
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"bookstack": {
|
||||
"status": "running",
|
||||
"health": "healthy",
|
||||
"restarts": 0,
|
||||
"exit": 0
|
||||
},
|
||||
"bookstack-db": {
|
||||
"status": "running",
|
||||
"health": "healthy",
|
||||
"restarts": 0,
|
||||
"exit": 0
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"bookstack": {
|
||||
"status": "running",
|
||||
"health": "healthy",
|
||||
"restarts": 0,
|
||||
"exit": 0
|
||||
},
|
||||
"bookstack-db": {
|
||||
"status": "running",
|
||||
"health": "healthy",
|
||||
"restarts": 0,
|
||||
"exit": 0
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
]
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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 ---
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -256,3 +256,5 @@ Compressed here to title, shipping version, evidence, and the sentences that sta
|
||||
| **R-408** | **`RestoreOffboxScratch` took no single-writer flag while a comment asserted every off-site operation did.** Shipped in controller **v0.232.0**. **Reasoning kept:** *the real deliverable is the WALK, not the acquire* — the sentence was false for months and nothing checked it, the ninth instance of this project's most-repeated class; *it is an AST pass and not `strings.Contains`, because a commented-out call still contains the string*; *adding a line to `offsiteExempt` is a deliberate act and belongs in the commit that adds it*; *the R-87 proof's exemption is kept HONEST by a second test that fails if that path ever gains `unlockStale`, routes through `resticStep`, or loses `--no-lock`*. | **CLOSED — SHIPPED** (controller v0.232.0, 2026-09-01) | full text: `git show 22e1c95:documentation/backlog/OPEN-ITEMS.md` |
|
||||
| **R-411** | **A background job deleted the lock of a live customer restore and logged it as a crash that did not happen.** Shipped in controller **v0.232.0**. Evidence: `audits/DRILL-soak-2026-08-31/phase1-lock-collision/`, `audits/R411-R414-2026-09-01/`. **Reasoning kept:** *`restic stats` TAKES a repository lock* — the fact nobody had, and the one that made the chain reachable; *`restic check` takes one too, `restic snapshots` and `restic list` do not*; *the fix was wider than the row — FOUR entry points were unflagged, three of them found by R-408's walk rather than by the report*; *the escalation in `resticStep` was NOT removed — real stale locks exist and it clears them; the defect was that a sibling could be live*. | **CLOSED — SHIPPED + PROVEN-LIVE** (controller v0.232.0, 2026-09-01) | full text: `git show 22e1c95:documentation/backlog/OPEN-ITEMS.md` |
|
||||
| **R-403** | **A poorer copy deleted a richer one: an EMPTY recovery unit on the primary drive was mirrored over a COMPLETE copy on the second drive, with `--delete`.** Shipped in controller **v0.230.0**. **MEASURED before it was fixed** — on the shipped v0.229.0, on demo-hp: 120 082 104 B (4 database dumps + 3 volume tars) -> 7 036 B (none of either) in one nightly run, recorded as a success. Evidence: `audits/DRILL-r403-tier2-delete-2026-08-31/`. **Reasoning kept:** *hollowness is a MANIFEST question, never a size question* - a unit with a fat compose capture and no dumps is the dangerous shape and a 360-byte unit for a tiny app is healthy; absent or unparseable manifest counts as hollow, fail closed. *The guard fences ONE shape and not shrinking* - `07` §8 row 5's derived-copy rebuild is a DESIGN DECISION, `--delete` stays, the data legs are untouched, and only source-hollow-over-destination-complete is refused (§8.2 records the exception beside the rule so nobody 'fixes' it back). *The rehydrate happens INSIDE the restore* - the hollow manifest was written two seconds later by the 5-minute capture job, so any follow-up job races it; and *the capture is deliberately NOT guarded*, because a capture describing an empty drive as empty is correct and guarding it would make the manifest lie. *A warning that fires on everything costs the same as the comforting lie it replaces* - the first draft flagged 'package older than the run', which is true of every healthy app, and four healthy apps on the box would have been warned. | **CLOSED 2026-08-31 - controller v0.230.0, PROVEN-LIVE both ways** (the loss reproduced on v0.229.0, then the same state preserved on v0.230.0 with all 7 files sha256-identical) | full text: `git show 66156c619fd2:documentation/backlog/OPEN-ITEMS.md` |
|
||||
| **R-459** | **The skipped MariaDB conversion is STABLE but never self-resolving; converting costs 7 s and keeps the abort — RULED YES and shipped 2026-09-13: `MARIADB_AUTO_UPGRADE=1` on `bookstack-db`, `kimai-db`, `nextcloud-db`, `romm-db`** (catalog `eec1228`/`bd32830`/`3525e35`; no image moved, `catalog_since` untouched). Measured `audits/SPIKE-r459-mariadb-upgrade-2026-09-06.md`; proven `audits/r459-close-2026-09-13/` — harness E3/E3b `proven` with `engine_state_after` = `already upgraded to 12.3.3-MariaDB [exit=1]`, `skipped due to $MARIADB_AUTO_UPGRADE` 0 lines, C3 still `failed`; landed on demo-hp via the real 15-min cycle with both container IDs unchanged, one deliberate restart → `MariaDB upgrade not required`, `/login` 200. **Reasoning kept:** *ask the engine, not the log* — the entrypoint prints `MariaDB upgrade not required` on an unsupported downgrade too (R-464); `mariadb-upgrade --check-if-upgrade-is-needed` exit 0 = needed, 1 = not. *Not established, unchanged:* whether any MariaDB feature misbehaves on an UNCONVERTED datadir. *The precaution that keeps the setting inert until Slice 4:* the engine-major rule + gate, removal tracked as R-469. | **CLOSED 2026-09-13 — shipped in the catalog, PROVEN by harness and live** | full text: `git show ae59c31:documentation/backlog/OPEN-ITEMS.md` |
|
||||
| **R-467** | **Controller v0.236.0 owed a golden — PAID 2026-09-13:** golden `0.236.0` baked (`GOLDEN_SHA256=58a3cc24…958bf`, 654 115 664 B), round-tripped from the DOWNLOADED bytes, `./etc/felhom-controller-image` says `felhom-controller:0.236.0`, hub dropdown agreed, three-field vouch re-read (`0.236.0` / `agent 0.130.0` / `min_agent 0.129.0`, not the R-216 shape), floor raised 0.232.0 → 0.236.0. Evidence `documentation/tests/golden-0.236.0-2026-09-13/`. **Reasoning kept:** *this bake carried FOUR unbaked releases and is the LAST per-release bake* — goldens are weekly and before any install from today (R-468); *the MinAgent line was missing from four headers* (R-470). | **CLOSED 2026-09-13 — baked, vouched, floor raised** | full text: `git show ae59c31: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 — Line truncated
|
||||
| **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 — Line truncated
|
||||
| **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,6 @@ 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-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 +697,12 @@ 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/<app>/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-<ver>-<date>/`. 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-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** |
|
||||
|
||||
<!-- DUE-CHECKS-BEGIN — machine-readable. Parsed by scripts/due_checks_gate.py.
|
||||
One row per dated check. The R-number must have a row above. Dates are UTC.
|
||||
|
||||
@@ -202,8 +202,51 @@ bake's own acceptance check. The real guard was never weak: the script's own
|
||||
back is a form submission, not a rebuild.
|
||||
|
||||
A golden is only needed when a publish train wants fresh installs current — demo deploys never need it.
|
||||
**Since 2026-09-13 the cadence is §4.2: weekly, and before any drill or fresh install.**
|
||||
The full 0.188.0 run, with the observables: `documentation/audits/tester-gate-golden-0.188.0-2026-07-31.md`.
|
||||
|
||||
### 4.2 Cadence — goldens are WEEKLY and before any install, not per release (operator ruling 2026-09-13)
|
||||
|
||||
**What was measured before the ruling:** 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 of those by 2026-09-01 — R-404/R-417). **The
|
||||
ruling:** bake on a cadence. Every release still raises the FLOOR (§4.1 step 5), 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 cadence, and it is a step in a routine, not a memory:**
|
||||
|
||||
1. **Weekly.** Bake + vouch + raise the floor per §4.1, one golden carrying whatever is newest.
|
||||
2. **Before ANY drill or fresh install**, whether or not the week is up. A drill on a fresh install
|
||||
with a stale golden measures the wrong controller (that is how R-120 surfaced).
|
||||
3. **The first external install retires the arrangement.** The waiver's own register row says so.
|
||||
|
||||
**The gate reads a dated waiver** — `documentation/tests/golden-waiver.yml`, four lines:
|
||||
|
||||
```yaml
|
||||
# documentation/tests/golden-waiver.yml — read by scripts/golden_currency_gate.py
|
||||
issued: 2026-09-13
|
||||
expires: 2026-09-27 # HARD LIMIT: at most 14 days after issued, or the gate refuses the waiver
|
||||
reason: pre-customer development; goldens on a weekly cadence (operator ruling 2026-09-13)
|
||||
register_row: R-468 # must exist as a `**R-468**` row in OPEN-ITEMS.md
|
||||
```
|
||||
|
||||
While it is 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. **It never covers a golden
|
||||
that is UNRECORDED** (no `## vX.Y.Z` heading — R-385): that is not a cadence choice. A waiver longer
|
||||
than 14 days, with a missing or unparseable date, an empty reason, or a row that does not exist, is
|
||||
**INCONCLUSIVE (exit 2)** — refused, and refused out loud. The cap lives in the gate
|
||||
(`WAIVER_MAX_DAYS`), not here, because a cap in prose is what failed the first time (R-242).
|
||||
|
||||
**To issue or renew:** edit the two dates (issue = today, expiry ≤ 14 days later), keep the row,
|
||||
commit it **on its own** with a message saying why the bake is deferred, and push. Renewal is a diff
|
||||
someone can see — that is the point. **Do not issue a waiver over a bake that could be done today**;
|
||||
that is the habit the gate's docstring warns about. **To retire it:** delete the file in the commit
|
||||
that records the first external install.
|
||||
|
||||
**What the waiver does NOT do:** it does not touch the vouch half of R-242 (still open — nothing
|
||||
gates the vouch), it does not change what the gate checks, and it does not stop the floor.
|
||||
|
||||
## 5. Hub (felhom.eu/hub → k3s, GitOps)
|
||||
|
||||
**The manifest is the truth** — a built image deploys NOTHING until `manifests/hub.yaml`'s `image:`
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
pve-manager/9.2.2/b9984c6d90a4bd80 (running kernel: 7.0.2-6-pve)
|
||||
@@ -0,0 +1,20 @@
|
||||
=== preconditions 2026-09-13T07:46:03Z ===
|
||||
/dev/sda1 9.1T 3.1T 5.5T 37% /mnt/5_hdd
|
||||
/dev/sdb1 445G 214G 209G 51% /
|
||||
felhom-controller clean=[] HEAD=1552716 origin=1552716
|
||||
felhom.eu clean=[] HEAD=4b2e560 origin=4b2e560
|
||||
felhom-agent clean=[?? scripts/__pycache__/;] HEAD=4586f0f origin=4586f0f
|
||||
controller CHANGELOG top: ## v0.236.0 — "delete my data too" deletes the data, or says that it could not (2026-09-
|
||||
MinAgent lines in the top FOUR entries (v0.233.0..v0.236.0): 0 <- none; newest MinAgent statement is v0.232.0's: **MinAgent: 0.129.0** (unchanged)
|
||||
controller image 0.236.0 in registry: HTTP 200
|
||||
404 pre-gate on the golden package: HTTP 404
|
||||
control — the 0.232.0 package that DOES exist: HTTP 200
|
||||
|
||||
=== drill VM ===
|
||||
Snapshot list:
|
||||
ID TAG VM_SIZE DATE VM_CLOCK ICOUNT
|
||||
1 virgin 0 B 2026-07-03 14:12:15 0000:00:00.000 0
|
||||
no qemu running
|
||||
|
||||
=== bake script fingerprint on DooPlex (compared across the hop later) ===
|
||||
7b0fb5cf082fa3301a45578d1624e375d205b4e538d602e7d198a015e573b6a1 felhom-agent/configs/build-golden.sh
|
||||
@@ -0,0 +1,28 @@
|
||||
=== pveam update (the virgin snapshot's INDEX is stale too) ===
|
||||
update successful
|
||||
perl: warning: Setting locale failed.
|
||||
perl: warning: Please check that your locale settings:
|
||||
LANGUAGE = (unset),
|
||||
LC_ALL = (unset),
|
||||
LC_CTYPE = "UTF-8",
|
||||
LC_NUMERIC = (unset),
|
||||
LC_COLLATE = (unset),
|
||||
LC_TIME = (unset),
|
||||
LC_MESSAGES = (unset),
|
||||
LC_MONETARY = (unset),
|
||||
LC_ADDRESS = (unset),
|
||||
LC_IDENTIFICATION = (unset),
|
||||
LC_MEASUREMENT = (unset),
|
||||
LC_PAPER = (unset),
|
||||
LC_TELEPHONE = (unset),
|
||||
LC_NAME = (unset),
|
||||
LANG = "en_US.UTF-8"
|
||||
are supported and installed on your system.
|
||||
perl: warning: Falling back to a fallback locale ("en_US.UTF-8").
|
||||
debian-13-standard_13.6-1_amd64.tar.zst
|
||||
calculating checksum...OK, checksum verified
|
||||
download of 'http://download.proxmox.com/images/system/debian-13-standard_13.6-1_amd64.tar.zst' to '/var/lib/vz/template/cache/debian-13-standard_13.6-1_amd64.tar.zst' finished
|
||||
|
||||
=== bake script + token, file -> file ===
|
||||
in the VM: 7b0fb5cf082fa3301a45578d1624e375d205b4e538d602e7d198a015e573b6a1
|
||||
DooPlex : 7b0fb5cf082fa3301a45578d1624e375d205b4e538d602e7d198a015e573b6a1
|
||||
@@ -0,0 +1,6 @@
|
||||
Running as unit: golden-bake.service; invocation ID: c011a9b879364141982db8d7654bf3fe
|
||||
=== token-leak check on the unit properties (must be 0) ===
|
||||
0
|
||||
=== and the grep is PROVEN to work (must be 1) ===
|
||||
1
|
||||
active
|
||||
@@ -0,0 +1,18 @@
|
||||
=== acceptance markers, counted on the COMMITTED log ===
|
||||
docker OK (overlay2 : 1
|
||||
including mount point :
|
||||
316:INFO: including mount point rootfs ('/') in backup
|
||||
317:INFO: including mount point mp0 ('/var/lib/felhom') in backup
|
||||
upload OK (HTTP 201) : 1
|
||||
MUST BE ZERO - excluding : 0
|
||||
MUST BE ZERO - FATAL : 0
|
||||
|
||||
=== the result ===
|
||||
GOLDEN_VERSION=0.236.0
|
||||
GOLDEN_SHA256=58a3cc24c61dc2271f2cb508ef5a269af97005f386b671f18011258df5f958bf
|
||||
archive volid: local:backup/vzdump-lxc-9100-2026_09_13-09_51_44.tar.zst
|
||||
script: build-golden.sh v3.0.0
|
||||
|
||||
=== token-leak grep on the COMMITTED log (must be 0), and the grep PROVEN to work ===
|
||||
bake.log: 0
|
||||
seeded throwaway copy (must be 1): 1
|
||||
@@ -0,0 +1,5 @@
|
||||
Logical volume "vm-9100-disk-1" successfully removed.
|
||||
purging CT 9100 from related configurations..
|
||||
leftovers in the VM: 0
|
||||
qemu exited
|
||||
1 virgin 0 B 2026-07-03 14:12:15 0000:00:00.000 0
|
||||
@@ -0,0 +1,8 @@
|
||||
=== READER 2: the ROUND TRIP — hash the DOWNLOADED bytes, not the bake's printout ===
|
||||
http=200 bytes=654115664
|
||||
downloaded sha256: 58a3cc24c61dc2271f2cb508ef5a269af97005f386b671f18011258df5f958bf
|
||||
bake printed : 58a3cc24c61dc2271f2cb508ef5a269af97005f386b671f18011258df5f958bf
|
||||
|
||||
=== THE DELIVERED ARTIFACT MUST NAME ITS OWN CONTROLLER ===
|
||||
gitea.dooplex.hu/admin/felhom-controller:0.236.0
|
||||
docker store entries in the archive: 19382
|
||||
@@ -0,0 +1,11 @@
|
||||
=== READER 3: the hub's Day-0 dropdown, reading Gitea on a different code path ===
|
||||
agent_version — none — sha=
|
||||
agent_version 0.130.0 sha=a56a92a7bd68f5b46736eaec <-- currently SELECTED
|
||||
agent_version 0.129.0 sha=53a54f0620afbd6d4a1b8660
|
||||
agent_version 0.128.0 sha=c6eba73bf9b9ad6980cfef57
|
||||
golden_version — none — sha=
|
||||
golden_version 0.236.0 sha=58a3cc24c61dc2271f2cb508
|
||||
golden_version 0.232.0 sha=5f8a53ed5b19a6cb2006298c <-- currently SELECTED
|
||||
golden_version 0.230.0 sha=9287f7cef5f13166276e8406
|
||||
min_controller_version = 0.232.0
|
||||
min_agent = 0.129.0
|
||||
@@ -0,0 +1,10 @@
|
||||
=== VOUCH: the THREE fields, moved together ===
|
||||
golden_version 0.232.0 -> 0.236.0 (this bake carries FOUR releases: 0.233.0..0.236.0 were never baked)
|
||||
agent_version 0.130.0 -> 0.130.0 UNCHANGED, already >= MinAgent
|
||||
min_agent 0.129.0 -> 0.129.0 UNCHANGED — no header since v0.232.0 declares a change (R-470 filed for the missing line)
|
||||
min_agent (0.129.0) <= agent_version (0.130.0): NOT the R-216 shape
|
||||
golden_sha256 sent = 58a3cc24c61dc227… (must equal the bake's 58a3cc24c61dc227…)
|
||||
|
||||
POST http=303
|
||||
Location: /configuration?flash=artifacts_set
|
||||
(read from -D, never %{redirect_url} — R-132)
|
||||
@@ -0,0 +1,10 @@
|
||||
=== RE-READ FROM THE PAGE — a 303 and a success flash are not proof ===
|
||||
agent_version SELECTED = 0.130.0 sha=a56a92a7bd68f5b46736eaec...
|
||||
golden_version SELECTED = 0.236.0 sha=58a3cc24c61dc2271f2cb508...
|
||||
min_agent = 0.129.0
|
||||
golden_sha256 = 58a3cc24c61dc2271f2cb508ef5a269af97005f386b671f18011258df5f958bf
|
||||
R-120 refusal banner present: False
|
||||
=== raise the fleet floor 0.232.0 -> 0.236.0 (both demo guests already run 0.236.0 by hand — the floor moves nothing today; it makes a fresh install land current) ===
|
||||
POST http=303
|
||||
Location: /configuration?flash=floor_set
|
||||
after: name="min_controller_version" value="0.236.0"
|
||||
@@ -0,0 +1,74 @@
|
||||
# Golden bake 0.236.0 — 2026-09-13
|
||||
|
||||
Baked, published, round-trip verified, **vouched**, and the fleet floor raised 0.232.0 → 0.236.0.
|
||||
**This bake carries FOUR releases: 0.233.0, 0.234.0, 0.235.0 and 0.236.0 were never baked** (R-467).
|
||||
It is the last per-release bake: from today goldens are on a **weekly cadence, and before any drill or
|
||||
fresh install** (operator ruling 2026-09-13, R-468 — `RUNBOOK-manual-build.md` §4.2).
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| `GOLDEN_SHA256` | `58a3cc24c61dc2271f2cb508ef5a269af97005f386b671f18011258df5f958bf` |
|
||||
| size | **654 115 664 B** |
|
||||
| baked controller | `gitea.dooplex.hu/admin/felhom-controller:0.236.0` |
|
||||
| `MinAgent` | **0.129.0** — the newest header that STATES one is v0.232.0's; v0.233.0…v0.236.0 carry no line (**R-470**) |
|
||||
| script | `build-golden.sh v3.0.0`, sha `7b0fb5cf…73b6a1`, **compared across the hop** (`02-template.txt`) |
|
||||
| template | `debian-13-standard_13.6-1_amd64.tar.zst`, after `pveam update` |
|
||||
| archive volid | `local:backup/vzdump-lxc-9100-2026_09_13-09_51_44.tar.zst` |
|
||||
|
||||
## Acceptance markers — counted on the COMMITTED log (`04-markers.txt`)
|
||||
|
||||
```
|
||||
docker OK (overlay2 : 1
|
||||
including mount point rootfs : 1 (line 316)
|
||||
including mount point mp0 : 1 (line 317) <- no mp1 since v3.0.0 (R-165/R-233)
|
||||
upload OK (HTTP 201) : 1
|
||||
--- must be ZERO ---
|
||||
excluding : 0
|
||||
FATAL : 0
|
||||
```
|
||||
|
||||
## Three independent readers agreed before anything was vouched
|
||||
|
||||
1. **The bake** printed `GOLDEN_SHA256=58a3cc24…958bf`.
|
||||
2. **The round trip** (`07-roundtrip.txt`) — the published bytes downloaded back: `HTTP 200`,
|
||||
**654 115 664 B**, sha `58a3cc24…958bf`, hashed from the **downloaded** bytes.
|
||||
3. **The hub's Day-0 dropdown** (`08-hub-before-vouch.txt`), a different code path reading Gitea:
|
||||
`0.236.0 sha=58a3cc24c61dc2271f2cb508`.
|
||||
|
||||
The delivered artifact names the controller it will start, read out of the downloaded archive:
|
||||
`./etc/felhom-controller-image` → `gitea.dooplex.hu/admin/felhom-controller:0.236.0`, with **19 382**
|
||||
entries under `var/lib/felhom/docker/`.
|
||||
|
||||
## Pre-gates, each proven able to see something first (`01-preconditions.txt`, `03-bake-launch.txt`)
|
||||
|
||||
| gate | result | the control that makes it believable |
|
||||
|---|---|---|
|
||||
| 404 pre-gate | `HTTP 404` for 0.236.0 before the bake | the 0.232.0 package returns `HTTP 200` on the same URL shape |
|
||||
| token-leak grep on the committed log | **0** | the token appended to a throwaway copy greps **1**; the copy was `shred -u`'d |
|
||||
| token off every command line | unit properties grep **0** | same seeded control returns **1** |
|
||||
|
||||
## The vouch — three fields, and only one moved (`09-vouch.txt`, `11-vouch-verified.txt`)
|
||||
|
||||
| field | before | after | why |
|
||||
|---|---|---|---|
|
||||
| `golden_version` | 0.232.0 | **0.236.0** | the new bake |
|
||||
| `agent_version` | 0.130.0 | 0.130.0 | unchanged — already ≥ MinAgent |
|
||||
| `min_agent` | 0.129.0 | 0.129.0 | unchanged — no header since v0.232.0 declares a change (R-470) |
|
||||
|
||||
`POST /configuration/artifacts` → `303 flash=artifacts_set`; the page was **re-read** (golden
|
||||
`0.236.0` selected, sha `58a3cc24…`), the R-120 refusal banner **absent**. Floor
|
||||
`POST /configuration/global-floor` → `303 flash=floor_set`, re-read `0.236.0`.
|
||||
|
||||
## The floor, and why no box moved
|
||||
|
||||
**Both demo guests were already on 0.236.0 by hand** (proven during R-442's live validation the same
|
||||
morning), so the floor raise changes nothing on the fleet today. It clears `golden_currency_gate.py`
|
||||
and makes a fresh install land on the current release — which the nightly drills need. The chain
|
||||
itself was exercised on 2026-09-01 (`golden-0.232.0-2026-09-01/12-selfupdate.txt`) and is not
|
||||
re-proven here; nothing about it changed.
|
||||
|
||||
## Teardown (`05-teardown.txt`)
|
||||
|
||||
`pct destroy 9100 --purge`, `shred -u` of the token, runner, script and log **after** the log was
|
||||
copied out (leftovers in `/root`: 0), `poweroff`, qemu confirmed exited with `ps -eo comm`, and
|
||||
`qemu-img snapshot -a virgin`. The disk carries the single `virgin` snapshot.
|
||||
@@ -0,0 +1,327 @@
|
||||
[golden] build-golden.sh v3.0.0 — baking controller gitea.dooplex.hu/admin/felhom-controller:0.236.0
|
||||
[golden] creating build LXC 9100 (nesting=1,keyctl=1, unprivileged; rootfs 32G + ONE data volume 24G @ /var/lib/felhom, backup=1) …
|
||||
Logical volume "vm-9100-disk-0" created.
|
||||
Logical volume pve/vm-9100-disk-0 changed.
|
||||
Creating filesystem with 8388608 4k blocks and 2097152 inodes
|
||||
Filesystem UUID: 2f235e82-2a88-4be0-b7b7-75778991837c
|
||||
Superblock backups stored on blocks:
|
||||
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
|
||||
4096000, 7962624
|
||||
Logical volume "vm-9100-disk-1" created.
|
||||
Logical volume pve/vm-9100-disk-1 changed.
|
||||
Creating filesystem with 6291456 4k blocks and 1572864 inodes
|
||||
Filesystem UUID: 39948d21-08ac-4cde-b5d3-997c54b68f36
|
||||
Superblock backups stored on blocks:
|
||||
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
|
||||
extracting archive '/var/lib/vz/template/cache/debian-13-standard_13.6-1_amd64.tar.zst'
|
||||
Total bytes read: 553512960 (528MiB, 94MiB/s)
|
||||
Detected container architecture: amd64
|
||||
Creating SSH host key 'ssh_host_ed25519_key' - this may take some time ...
|
||||
done: SHA256:e56AH6TbE0URIv25xegROJSnKt2yI9lK+kjeinRAeIE root@felhom-golden
|
||||
Creating SSH host key 'ssh_host_ecdsa_key' - this may take some time ...
|
||||
done: SHA256:VUZj3qbCDwZzz7pZsp5QlPisPDJ5KwjVShkoQEQuAZ4 root@felhom-golden
|
||||
Creating SSH host key 'ssh_host_rsa_key' - this may take some time ...
|
||||
done: SHA256:7n/yEy8Nfqo8I4pX5L2b3Kg3d2K2sfgYYAZeH9XqWaI root@felhom-golden
|
||||
[golden] starting + installing Docker (official repo, trixie channel) …
|
||||
apt-listchanges: Can't set locale; make sure $LC_* and $LANG are correct!
|
||||
perl: warning: Setting locale failed.
|
||||
perl: warning: Please check that your locale settings:
|
||||
LANGUAGE = (unset),
|
||||
LC_ALL = (unset),
|
||||
LC_CTYPE = (unset),
|
||||
LC_NUMERIC = (unset),
|
||||
LC_COLLATE = (unset),
|
||||
LC_TIME = (unset),
|
||||
LC_MESSAGES = (unset),
|
||||
LC_MONETARY = (unset),
|
||||
LC_ADDRESS = (unset),
|
||||
LC_IDENTIFICATION = (unset),
|
||||
LC_MEASUREMENT = (unset),
|
||||
LC_PAPER = (unset),
|
||||
LC_TELEPHONE = (unset),
|
||||
LC_NAME = (unset),
|
||||
LANG = "en_US.UTF-8"
|
||||
are supported and installed on your system.
|
||||
perl: warning: Falling back to the standard locale ("C").
|
||||
locale: Cannot set LC_CTYPE to default locale: No such file or directory
|
||||
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
|
||||
locale: Cannot set LC_ALL to default locale: No such file or directory
|
||||
apt-listchanges: Can't set locale; make sure $LC_* and $LANG are correct!
|
||||
perl: warning: Setting locale failed.
|
||||
perl: warning: Please check that your locale settings:
|
||||
LANGUAGE = (unset),
|
||||
LC_ALL = (unset),
|
||||
LC_CTYPE = (unset),
|
||||
LC_NUMERIC = (unset),
|
||||
LC_COLLATE = (unset),
|
||||
LC_TIME = (unset),
|
||||
LC_MESSAGES = (unset),
|
||||
LC_MONETARY = (unset),
|
||||
LC_ADDRESS = (unset),
|
||||
LC_IDENTIFICATION = (unset),
|
||||
LC_MEASUREMENT = (unset),
|
||||
LC_PAPER = (unset),
|
||||
LC_TELEPHONE = (unset),
|
||||
LC_NAME = (unset),
|
||||
LANG = "en_US.UTF-8"
|
||||
are supported and installed on your system.
|
||||
perl: warning: Falling back to the standard locale ("C").
|
||||
locale: Cannot set LC_CTYPE to default locale: No such file or directory
|
||||
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
|
||||
locale: Cannot set LC_ALL to default locale: No such file or directory
|
||||
[golden] baking daemon.json: classic overlay2 driver (containerd-snapshotter OFF) + log rotation …
|
||||
[golden] wiring the single data volume (R-165 variant V-c): /var/lib/felhom/{docker,sys_drive} -> binds …
|
||||
[golden] verifying Docker works in the build guest (storage driver should be overlay2 on the ext4 data volume) …
|
||||
Unable to find image 'hello-world:latest' locally
|
||||
latest: Pulling from library/hello-world
|
||||
4f55086f7dd0: Pulling fs layer
|
||||
4f55086f7dd0: Verifying Checksum
|
||||
4f55086f7dd0: Download complete
|
||||
4f55086f7dd0: Pull complete
|
||||
Digest: sha256:5e23090353324d887c48ad5e5c56d294eab81588df9605b07d1afe895f9cc8f8
|
||||
Status: Downloaded newer image for hello-world:latest
|
||||
docker OK (overlay2; data-root /var/lib/docker)
|
||||
/var/lib/docker is a real mount: /dev/mapper/pve-vm--9100--disk--1[/docker] ext4
|
||||
/mnt/sys_drive is a real mount: /dev/mapper/pve-vm--9100--disk--1[/sys_drive] ext4
|
||||
both paths are ONE filesystem: /dev/mapper/pve-vm--9100--disk--1 23317576
|
||||
[golden] baking the in-guest controller image gitea.dooplex.hu/admin/felhom-controller:0.236.0 (no registry cred at deploy) …
|
||||
|
||||
WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
|
||||
Configure a credential helper to remove this warning. See
|
||||
https://docs.docker.com/go/credential-store/
|
||||
|
||||
0.236.0: Pulling from admin/felhom-controller
|
||||
a8ac7f6c67ab: Pulling fs layer
|
||||
bf30769d36e7: Pulling fs layer
|
||||
044b66fbe46c: Pulling fs layer
|
||||
b5c41a28e83f: Pulling fs layer
|
||||
4051fe1934c3: Pulling fs layer
|
||||
7879c9030fd8: Pulling fs layer
|
||||
b5c41a28e83f: Waiting
|
||||
4051fe1934c3: Waiting
|
||||
7879c9030fd8: Waiting
|
||||
a8ac7f6c67ab: Verifying Checksum
|
||||
a8ac7f6c67ab: Download complete
|
||||
044b66fbe46c: Verifying Checksum
|
||||
044b66fbe46c: Download complete
|
||||
b5c41a28e83f: Verifying Checksum
|
||||
b5c41a28e83f: Download complete
|
||||
4051fe1934c3: Verifying Checksum
|
||||
4051fe1934c3: Download complete
|
||||
7879c9030fd8: Verifying Checksum
|
||||
7879c9030fd8: Download complete
|
||||
bf30769d36e7: Verifying Checksum
|
||||
bf30769d36e7: Download complete
|
||||
a8ac7f6c67ab: Pull complete
|
||||
bf30769d36e7: Pull complete
|
||||
044b66fbe46c: Pull complete
|
||||
b5c41a28e83f: Pull complete
|
||||
4051fe1934c3: Pull complete
|
||||
7879c9030fd8: Pull complete
|
||||
Digest: sha256:ec94c3298040ae9061555c1dbdd0fc6221d64ba42f7154ce71739ec1d8f09176
|
||||
Status: Downloaded newer image for gitea.dooplex.hu/admin/felhom-controller:0.236.0
|
||||
gitea.dooplex.hu/admin/felhom-controller:0.236.0
|
||||
[golden] asking the controller which infra images it manages …
|
||||
[golden] baking infra images (4): traefik:v3.6.7 cloudflare/cloudflared:2026.6.0 gtstef/filebrowser:1.3.3-stable gitea.dooplex.hu/admin/felhom-samba:1.1.0 …
|
||||
v3.6.7: Pulling from library/traefik
|
||||
589002ba0eae: Pulling fs layer
|
||||
ef63511ea6cc: Pulling fs layer
|
||||
0738e5cb835e: Pulling fs layer
|
||||
3e6813f70c64: Pulling fs layer
|
||||
3e6813f70c64: Waiting
|
||||
ef63511ea6cc: Verifying Checksum
|
||||
ef63511ea6cc: Download complete
|
||||
589002ba0eae: Verifying Checksum
|
||||
589002ba0eae: Download complete
|
||||
3e6813f70c64: Verifying Checksum
|
||||
3e6813f70c64: Download complete
|
||||
0738e5cb835e: Verifying Checksum
|
||||
0738e5cb835e: Download complete
|
||||
589002ba0eae: Pull complete
|
||||
ef63511ea6cc: Pull complete
|
||||
0738e5cb835e: Pull complete
|
||||
3e6813f70c64: Pull complete
|
||||
Digest: sha256:a9890c898f379c1905ee5b28342f6b408dc863f08db2dab20e46c267d1ff463a
|
||||
Status: Downloaded newer image for traefik:v3.6.7
|
||||
docker.io/library/traefik:v3.6.7
|
||||
2026.6.0: Pulling from cloudflare/cloudflared
|
||||
47de5dd0b812: Pulling fs layer
|
||||
c172f21841df: Pulling fs layer
|
||||
99515e7b4d35: Pulling fs layer
|
||||
99ba982a9142: Pulling fs layer
|
||||
d6b1b89eccac: Pulling fs layer
|
||||
2780920e5dbf: Pulling fs layer
|
||||
7c12895b777b: Pulling fs layer
|
||||
3214acf345c0: Pulling fs layer
|
||||
52630fc75a18: Pulling fs layer
|
||||
dd64bf2dd177: Pulling fs layer
|
||||
b839dfae01f6: Pulling fs layer
|
||||
ebddc55facdc: Pulling fs layer
|
||||
bdfd7f7e5bf6: Pulling fs layer
|
||||
2d4d7adf6272: Pulling fs layer
|
||||
40008157d8d2: Pulling fs layer
|
||||
bd8962e29291: Pulling fs layer
|
||||
cac2ae0193cb: Pulling fs layer
|
||||
74d1dac84ecc: Pulling fs layer
|
||||
b839dfae01f6: Waiting
|
||||
ebddc55facdc: Waiting
|
||||
bdfd7f7e5bf6: Waiting
|
||||
2d4d7adf6272: Waiting
|
||||
40008157d8d2: Waiting
|
||||
bd8962e29291: Waiting
|
||||
cac2ae0193cb: Waiting
|
||||
74d1dac84ecc: Waiting
|
||||
99ba982a9142: Waiting
|
||||
d6b1b89eccac: Waiting
|
||||
2780920e5dbf: Waiting
|
||||
7c12895b777b: Waiting
|
||||
3214acf345c0: Waiting
|
||||
52630fc75a18: Waiting
|
||||
dd64bf2dd177: Waiting
|
||||
47de5dd0b812: Download complete
|
||||
c172f21841df: Verifying Checksum
|
||||
c172f21841df: Download complete
|
||||
47de5dd0b812: Pull complete
|
||||
99515e7b4d35: Verifying Checksum
|
||||
99515e7b4d35: Download complete
|
||||
99ba982a9142: Verifying Checksum
|
||||
99ba982a9142: Download complete
|
||||
d6b1b89eccac: Verifying Checksum
|
||||
d6b1b89eccac: Download complete
|
||||
2780920e5dbf: Verifying Checksum
|
||||
2780920e5dbf: Download complete
|
||||
7c12895b777b: Verifying Checksum
|
||||
7c12895b777b: Download complete
|
||||
c172f21841df: Pull complete
|
||||
3214acf345c0: Verifying Checksum
|
||||
3214acf345c0: Download complete
|
||||
52630fc75a18: Verifying Checksum
|
||||
52630fc75a18: Download complete
|
||||
dd64bf2dd177: Verifying Checksum
|
||||
dd64bf2dd177: Download complete
|
||||
b839dfae01f6: Verifying Checksum
|
||||
b839dfae01f6: Download complete
|
||||
ebddc55facdc: Verifying Checksum
|
||||
ebddc55facdc: Download complete
|
||||
bdfd7f7e5bf6: Verifying Checksum
|
||||
bdfd7f7e5bf6: Download complete
|
||||
40008157d8d2: Verifying Checksum
|
||||
40008157d8d2: Download complete
|
||||
bd8962e29291: Verifying Checksum
|
||||
bd8962e29291: Download complete
|
||||
2d4d7adf6272: Verifying Checksum
|
||||
2d4d7adf6272: Download complete
|
||||
cac2ae0193cb: Verifying Checksum
|
||||
cac2ae0193cb: Download complete
|
||||
99515e7b4d35: Pull complete
|
||||
74d1dac84ecc: Verifying Checksum
|
||||
74d1dac84ecc: Download complete
|
||||
99ba982a9142: Pull complete
|
||||
d6b1b89eccac: Pull complete
|
||||
2780920e5dbf: Pull complete
|
||||
7c12895b777b: Pull complete
|
||||
3214acf345c0: Pull complete
|
||||
52630fc75a18: Pull complete
|
||||
dd64bf2dd177: Pull complete
|
||||
b839dfae01f6: Pull complete
|
||||
ebddc55facdc: Pull complete
|
||||
bdfd7f7e5bf6: Pull complete
|
||||
2d4d7adf6272: Pull complete
|
||||
40008157d8d2: Pull complete
|
||||
bd8962e29291: Pull complete
|
||||
cac2ae0193cb: Pull complete
|
||||
74d1dac84ecc: Pull complete
|
||||
Digest: sha256:ba461b8aa9c042156dbd39c38657fe7431bafa063220eab8d5330a523863da9f
|
||||
Status: Downloaded newer image for cloudflare/cloudflared:2026.6.0
|
||||
docker.io/cloudflare/cloudflared:2026.6.0
|
||||
1.3.3-stable: Pulling from gtstef/filebrowser
|
||||
6a0ac1617861: Pulling fs layer
|
||||
ef8806083e82: Pulling fs layer
|
||||
b74107c861c7: Pulling fs layer
|
||||
adc935def003: Pulling fs layer
|
||||
4f4fb700ef54: Pulling fs layer
|
||||
18695ccc900a: Pulling fs layer
|
||||
45d119d5c397: Pulling fs layer
|
||||
dac52db4fc51: Pulling fs layer
|
||||
6d598f86b2f2: Pulling fs layer
|
||||
8aa349c8396c: Pulling fs layer
|
||||
dac52db4fc51: Waiting
|
||||
6d598f86b2f2: Waiting
|
||||
8aa349c8396c: Waiting
|
||||
4f4fb700ef54: Waiting
|
||||
18695ccc900a: Waiting
|
||||
45d119d5c397: Waiting
|
||||
adc935def003: Waiting
|
||||
6a0ac1617861: Verifying Checksum
|
||||
6a0ac1617861: Download complete
|
||||
adc935def003: Verifying Checksum
|
||||
adc935def003: Download complete
|
||||
6a0ac1617861: Pull complete
|
||||
4f4fb700ef54: Verifying Checksum
|
||||
4f4fb700ef54: Download complete
|
||||
b74107c861c7: Verifying Checksum
|
||||
b74107c861c7: Download complete
|
||||
ef8806083e82: Verifying Checksum
|
||||
ef8806083e82: Download complete
|
||||
45d119d5c397: Verifying Checksum
|
||||
45d119d5c397: Download complete
|
||||
18695ccc900a: Verifying Checksum
|
||||
18695ccc900a: Download complete
|
||||
dac52db4fc51: Verifying Checksum
|
||||
dac52db4fc51: Download complete
|
||||
6d598f86b2f2: Verifying Checksum
|
||||
6d598f86b2f2: Download complete
|
||||
8aa349c8396c: Verifying Checksum
|
||||
8aa349c8396c: Download complete
|
||||
ef8806083e82: Pull complete
|
||||
b74107c861c7: Pull complete
|
||||
adc935def003: Pull complete
|
||||
4f4fb700ef54: Pull complete
|
||||
18695ccc900a: Pull complete
|
||||
45d119d5c397: Pull complete
|
||||
dac52db4fc51: Pull complete
|
||||
6d598f86b2f2: Pull complete
|
||||
8aa349c8396c: Pull complete
|
||||
Digest: sha256:eb3733681db8757412632c61a99ad656f0d94ed6781bb2ea114b4d70babab78c
|
||||
Status: Downloaded newer image for gtstef/filebrowser:1.3.3-stable
|
||||
docker.io/gtstef/filebrowser:1.3.3-stable
|
||||
1.1.0: Pulling from admin/felhom-samba
|
||||
897d797d2723: Pulling fs layer
|
||||
3051591aa250: Pulling fs layer
|
||||
ce57a3f93416: Pulling fs layer
|
||||
fb94eeec2fe1: Pulling fs layer
|
||||
fb94eeec2fe1: Waiting
|
||||
ce57a3f93416: Verifying Checksum
|
||||
ce57a3f93416: Download complete
|
||||
fb94eeec2fe1: Verifying Checksum
|
||||
fb94eeec2fe1: Download complete
|
||||
897d797d2723: Download complete
|
||||
3051591aa250: Verifying Checksum
|
||||
3051591aa250: Download complete
|
||||
897d797d2723: Pull complete
|
||||
3051591aa250: Pull complete
|
||||
ce57a3f93416: Pull complete
|
||||
fb94eeec2fe1: Pull complete
|
||||
Digest: sha256:1c17c09422bec0366d7cf0e0fcfc1486ba6c90334a0a5d5c851073a9342f8f10
|
||||
Status: Downloaded newer image for gitea.dooplex.hu/admin/felhom-samba:1.1.0
|
||||
gitea.dooplex.hu/admin/felhom-samba:1.1.0
|
||||
[golden] baking the controller-bootstrap unit (deploys the BAKED controller from the config mount) …
|
||||
Created symlink '/etc/systemd/system/multi-user.target.wants/felhom-controller-bootstrap.service' → '/etc/systemd/system/felhom-controller-bootstrap.service'.
|
||||
[golden] baking the controller-bootstrap PATH unit (starts the service on bootstrap-mount hot-plug — B1) …
|
||||
Created symlink '/etc/systemd/system/multi-user.target.wants/felhom-controller-bootstrap.path' → '/etc/systemd/system/felhom-controller-bootstrap.path'.
|
||||
[golden] baking the first-boot SSH host-key regeneration unit (F3) …
|
||||
Created symlink '/etc/systemd/system/multi-user.target.wants/felhom-regen-hostkeys.service' → '/etc/systemd/system/felhom-regen-hostkeys.service'.
|
||||
[golden] identity-clean + minimize …
|
||||
[golden] stop + archive …
|
||||
INFO: including mount point rootfs ('/') in backup
|
||||
INFO: including mount point mp0 ('/var/lib/felhom') in backup
|
||||
INFO: archive file size: 623MB
|
||||
INFO: Finished Backup of VM 9100 (00:00:43)
|
||||
[golden] DONE. golden archive volid: local:backup/vzdump-lxc-9100-2026_09_13-09_51_44.tar.zst (rootfs 32G + ONE data volume 24G @ /var/lib/felhom, all in the archive)
|
||||
[golden] publishing golden (654115664 bytes, sha256 58a3cc24c61dc227…) → https://gitea.dooplex.hu/api/packages/admin/generic/felhom-golden/0.236.0/golden.tar.zst
|
||||
[golden] pre-delete existing: HTTP 404 (404/204 expected)
|
||||
[golden] upload OK (HTTP 201)
|
||||
GOLDEN_VERSION=0.236.0
|
||||
GOLDEN_SHA256=58a3cc24c61dc2271f2cb508ef5a269af97005f386b671f18011258df5f958bf
|
||||
[golden] Record in the hub operator UI (Configs → Day-0 artifacts): golden 0.236.0 / 58a3cc24c61dc2271f2cb508ef5a269af97005f386b671f18011258df5f958bf
|
||||
[golden] (the build guest 9100 is stopped; destroy it with: pct destroy 9100 --purge)
|
||||
@@ -0,0 +1,11 @@
|
||||
# documentation/tests/golden-waiver.yml — read by scripts/golden_currency_gate.py
|
||||
#
|
||||
# Goldens are on a CADENCE, not per release (operator ruling 2026-09-13, R-468): weekly, and always
|
||||
# before any drill or fresh install. While this waiver is valid a golden BEHIND the record makes the
|
||||
# gate ADVISORY instead of red. It never covers a golden that is UNRECORDED (R-385). At most 14 days
|
||||
# after `issued`, or the gate refuses it. Renew with a new dated commit; delete it at the first
|
||||
# external install. Issued AFTER the 0.236.0 bake landed — not over a bake that could have been done.
|
||||
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
|
||||
@@ -1,3 +1,31 @@
|
||||
## the golden waiver — goldens on a cadence, not per release (2026-09-13, R-468 / R-242) — NOT A RELEASE
|
||||
|
||||
**No product code, no version bump, no image.** A scripts change is not a release.
|
||||
|
||||
`golden_currency_gate.py` now reads a dated waiver, `documentation/tests/golden-waiver.yml` (`issued`,
|
||||
`expires`, `reason`, `register_row`). Operator ruling 2026-09-13: **bake on a cadence — weekly, and
|
||||
always before any drill or fresh install — not per release.** The gate had tripped on every release
|
||||
by design and the only honest ways past it were a bake or a declared `--no-verify`; August measured
|
||||
25 goldens in 26 days and thirteen bypasses.
|
||||
|
||||
- **Valid waiver + golden BEHIND the record** → a loud ADVISORY naming the waiver, its expiry and how
|
||||
many releases the golden lags; exit 0. A waived conviction stays visible on every push.
|
||||
- **Expired waiver** → exit 1 exactly as before, and the message says it EXPIRED on `<date>`.
|
||||
- **Unrecorded golden (R-385)** → exit 1 regardless; the waiver is named and declared NOT to cover
|
||||
it. **The asymmetry is the design:** behind is a cadence choice, unrecorded is the fleet running
|
||||
something nobody wrote down.
|
||||
- **Malformed waiver** — more than 14 days, absent or unparseable date, empty reason, a row that does
|
||||
not exist in `OPEN-ITEMS.md` — → exit 2 INCONCLUSIVE, never 0, never silently ignored. The 14-day
|
||||
cap lives in the gate (`WAIVER_MAX_DAYS`), not in prose. The register is read for ONE fact (does
|
||||
the row exist), never for meaning (R-421).
|
||||
- `GOLDEN_GATE_*` environment variables are a **test seam**: they move where the gate reads, never
|
||||
what it decides. `test_golden_currency_gate.py` gains cases 5–15 (Scenarios E/F/G/H, each with its
|
||||
wrong direction; the R-421 decoy — a file saying only `expires` — returns 2). **Red-proof:** the
|
||||
old gate on the real tree with a valid waiver planted → exit 1 (it cannot read one); the new gate on
|
||||
synthetic "behind" trees → 0 with the advisory present.
|
||||
- The docstring's *"honest fix is a recorded waiver, never a habit of bypassing"* is now a mechanism.
|
||||
**R-242's OTHER half — nothing gates the VOUCH — is unchanged and still open.**
|
||||
|
||||
## the decoy sweep — can this gate be fooled by a label? (2026-09-01, R-421) — NOT A RELEASE
|
||||
|
||||
**No product code, no version bump, no image, no golden.** A scripts change is not a release.
|
||||
|
||||
@@ -37,7 +37,8 @@ That limit is forced, not chosen, and the reasoning is recorded so nobody re-der
|
||||
and is therefore the step this repo can see; the vouch is an operator act against the hub and needs a
|
||||
different mechanism. That gap is real and is recorded as R-242's remaining half, NOT papered over
|
||||
here. In practice the two are minutes apart in the same session, and the recurrence this gate is
|
||||
built for was a missing BAKE.
|
||||
built for was a missing BAKE. **That vouch half is STILL open after 2026-09-13** — the waiver below
|
||||
covers a different thing, and this sentence is kept so the two are not confused.
|
||||
|
||||
WHY VERSION AND NOT BEHAVIOUR. It compares version numbers, so a controller release that changed
|
||||
nothing a customer can see also trips it. That is accepted deliberately: deciding "customer-visible"
|
||||
@@ -45,7 +46,8 @@ mechanically is not possible, judging it by hand is what already failed twice, a
|
||||
false trip is one bake — which is the operation the project wants to be routine anyway. **A gate that
|
||||
cries wolf is one people learn to bypass, and `--no-verify` exists**, so the tolerance is stated
|
||||
rather than assumed: if this ever fires on a release nobody wants a golden for, the honest fix is a
|
||||
recorded waiver in the register, never a habit of bypassing.
|
||||
recorded waiver in the register, never a habit of bypassing. **That waiver is now BUILT — see
|
||||
"THE WAIVER" below (2026-09-13).**
|
||||
|
||||
FAIL-CLOSED, BUT HONEST ABOUT NOT KNOWING. An absent controller clone, or a CHANGELOG whose top
|
||||
header cannot be parsed, exits **2 (INCONCLUSIVE)** — never 0. The runner reports 2 distinctly for
|
||||
@@ -72,7 +74,47 @@ it is absent. An unrecorded golden is convicted (exit 1) exactly like a stale on
|
||||
**Why membership and not `baked > released`.** A comparison against the newest heading alone would go
|
||||
green again the moment ANY later entry was written, leaving 0.221.1 permanently unrecorded and the
|
||||
gate permanently silent about it. Membership cannot be satisfied by an unrelated later release.
|
||||
|
||||
── THE WAIVER — goldens on a CADENCE, not per release (added 2026-09-13, operator ruling) ────────
|
||||
|
||||
What happened between 2026-08-07 and 2026-09-01: **25 goldens in 26 days**, almost one per release,
|
||||
because this gate trips on every release by design (see WHY VERSION AND NOT BEHAVIOUR) and the only
|
||||
honest ways past it were a bake or a `--no-verify`. Thirteen bypasses were counted by 2026-09-01
|
||||
(R-404/R-417). The operator ruled on 2026-09-13: **bake on a cadence — weekly, and always before any
|
||||
drill or fresh install — not per release.** Every release still raises the FLOOR, so the fleet keeps
|
||||
getting each release in ~20 s; only the golden, which protects a fresh install and nothing else,
|
||||
moves to a cadence.
|
||||
|
||||
The mechanism is a small tracked file, `documentation/tests/golden-waiver.yml`:
|
||||
|
||||
issued: 2026-09-13
|
||||
expires: 2026-09-27 # at most 14 days after issued, or the gate REFUSES the waiver
|
||||
reason: pre-customer development; goldens on a weekly cadence (operator ruling 2026-09-13)
|
||||
register_row: R-468 # must exist as a `**R-468**` row in OPEN-ITEMS.md
|
||||
|
||||
While the waiver is VALID, the "behind" conviction becomes a **loud ADVISORY** (exit 0) that names
|
||||
the waiver, its expiry and how many releases the golden lags. When it runs out, the gate is red
|
||||
again until someone bakes or renews. **A dated waiver cannot be forgotten — it just expires.** That
|
||||
is what makes it different from R-242's original rule, which recurred the day after it was written:
|
||||
renewal is a new commit with a diff, a deliberate act someone can see.
|
||||
|
||||
THE ASYMMETRY, stated because it is the whole design: **the waiver covers a golden that is BEHIND the
|
||||
record. It never covers a golden that is UNRECORDED (R-385).** The first is a cadence choice; the
|
||||
second is the fleet running something nobody wrote down, and no schedule makes that acceptable.
|
||||
|
||||
WHAT REFUSES THE WAIVER (exit 2, INCONCLUSIVE — never 0, never silently ignored): an expiry more
|
||||
than 14 days after issue; an absent or unparseable date; a missing or empty reason; a register row
|
||||
that is absent or whose `**R-n**` row does not exist. The 14-day cap is enforced HERE, not in the
|
||||
runbook, because a cap in prose is the thing that failed. A file at the right path containing only
|
||||
the word `expires` is the R-421 decoy and is refused like any other malformed waiver.
|
||||
|
||||
The register is read for exactly ONE fact — does the named row exist — never for meaning. Reading
|
||||
prose for meaning is the R-421 class.
|
||||
|
||||
WHAT IT DOES NOT COVER: the vouch (still R-242's open half); an unrecorded golden (R-385); anything
|
||||
after the first external install — the waiver's own row says it is a pre-customer arrangement.
|
||||
"""
|
||||
import datetime
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
@@ -81,8 +123,21 @@ import sys
|
||||
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
# The controller clone sits beside this one. The same sibling assumption reuse_refs_check.py and
|
||||
# instructions_gate.py already make — an absent sibling is INCONCLUSIVE, never a silent pass.
|
||||
CONTROLLER_CHANGELOG = os.path.join(os.path.dirname(ROOT), "felhom-controller", "CHANGELOG.md")
|
||||
EVIDENCE_DIR = os.path.join(ROOT, "documentation", "tests")
|
||||
#
|
||||
# The GOLDEN_GATE_* environment variables are a TEST SEAM (2026-09-13): they move WHERE the gate
|
||||
# reads, never WHAT it decides, so test_golden_currency_gate.py can build a "behind" or an
|
||||
# "unrecorded" tree without depending on the real controller's release history. Unset in every real
|
||||
# run — the hook and CI export nothing.
|
||||
CONTROLLER_CHANGELOG = os.environ.get(
|
||||
"GOLDEN_GATE_CHANGELOG",
|
||||
os.path.join(os.path.dirname(ROOT), "felhom-controller", "CHANGELOG.md"))
|
||||
EVIDENCE_DIR = os.environ.get("GOLDEN_GATE_EVIDENCE_DIR", os.path.join(ROOT, "documentation", "tests"))
|
||||
WAIVER_PATH = os.environ.get("GOLDEN_GATE_WAIVER",
|
||||
os.path.join(ROOT, "documentation", "tests", "golden-waiver.yml"))
|
||||
REGISTER_PATH = os.environ.get("GOLDEN_GATE_REGISTER",
|
||||
os.path.join(ROOT, "documentation", "backlog", "OPEN-ITEMS.md"))
|
||||
# The HARD LIMIT on a waiver's life. Enforced here and nowhere else — see the module docstring.
|
||||
WAIVER_MAX_DAYS = 14
|
||||
|
||||
# `## v0.206.0 — …` on the FIRST such line: the CHANGELOG is newest-first by convention.
|
||||
RELEASED_RE = re.compile(r"^##\s+v(\d+)\.(\d+)\.(\d+)\b")
|
||||
@@ -182,6 +237,82 @@ def newest_baked():
|
||||
return found[-1]
|
||||
|
||||
|
||||
WAIVER_KEY_RE = re.compile(r"^\s*([a-z_]+)\s*:\s*(.*?)\s*$")
|
||||
ROW_RE = re.compile(r"^R-\d+$")
|
||||
|
||||
|
||||
def read_waiver(path=None, register=None, today=None):
|
||||
"""(state, info) — state is 'absent', 'valid', 'expired' or 'malformed'.
|
||||
|
||||
The file is four `key: value` lines; comments (`# …`) and blank lines are ignored. It is parsed by
|
||||
hand so the gate stays stdlib-only and `--fast`. Every way the file can be wrong returns
|
||||
'malformed' with the reason in info["why"] — the caller turns that into exit 2, never into 0 and
|
||||
never into a silent 'absent'. A decoy — the word `expires` with no date — lands here too.
|
||||
"""
|
||||
path = path or WAIVER_PATH
|
||||
register = register or REGISTER_PATH
|
||||
today = today or datetime.datetime.now(datetime.timezone.utc).date()
|
||||
if not os.path.isfile(path):
|
||||
return "absent", {"path": path}
|
||||
try:
|
||||
text = io.open(path, encoding="utf-8").read()
|
||||
except OSError as e:
|
||||
return "malformed", {"path": path, "why": "cannot be read (%s)" % e}
|
||||
fields = {}
|
||||
for line in text.splitlines():
|
||||
line = line.split("#", 1)[0]
|
||||
m = WAIVER_KEY_RE.match(line)
|
||||
if m and m.group(2):
|
||||
fields[m.group(1)] = m.group(2).strip().strip("'\"")
|
||||
info = {"path": path, "fields": fields}
|
||||
|
||||
def date_of(key):
|
||||
v = fields.get(key, "")
|
||||
try:
|
||||
return datetime.date.fromisoformat(v)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
issued, expires = date_of("issued"), date_of("expires")
|
||||
if issued is None:
|
||||
info["why"] = "`issued:` is absent or not a YYYY-MM-DD date (got %r)" % fields.get("issued", "")
|
||||
return "malformed", info
|
||||
if expires is None:
|
||||
info["why"] = "`expires:` is absent or not a YYYY-MM-DD date (got %r)" % fields.get("expires", "")
|
||||
return "malformed", info
|
||||
if expires <= issued:
|
||||
info["why"] = "`expires:` (%s) is not after `issued:` (%s)" % (expires, issued)
|
||||
return "malformed", info
|
||||
span = (expires - issued).days
|
||||
if span > WAIVER_MAX_DAYS:
|
||||
info["why"] = ("`expires:` is %d days after `issued:` — the hard limit is %d. A waiver that "
|
||||
"tries to be permanent is refused; renew it with a new dated commit instead."
|
||||
% (span, WAIVER_MAX_DAYS))
|
||||
return "malformed", info
|
||||
if not fields.get("reason"):
|
||||
info["why"] = "`reason:` is absent or empty"
|
||||
return "malformed", info
|
||||
row = fields.get("register_row", "")
|
||||
if not ROW_RE.match(row):
|
||||
info["why"] = "`register_row:` is absent or not of the form R-<n> (got %r)" % row
|
||||
return "malformed", info
|
||||
# The register is read for ONE fact — does the row exist — never for meaning (R-421).
|
||||
try:
|
||||
reg = io.open(register, encoding="utf-8").read()
|
||||
except OSError as e:
|
||||
info["why"] = "register %s cannot be read (%s)" % (register, e)
|
||||
return "malformed", info
|
||||
if ("**%s**" % row) not in reg:
|
||||
info["why"] = "`register_row: %s` names a row that does not exist in %s" % (
|
||||
row, os.path.relpath(register, ROOT) if register.startswith(ROOT) else register)
|
||||
return "malformed", info
|
||||
info.update({"issued": issued, "expires": expires, "row": row, "reason": fields["reason"],
|
||||
"days_left": (expires - today).days})
|
||||
if today >= expires:
|
||||
return "expired", info
|
||||
return "valid", info
|
||||
|
||||
|
||||
def vstr(v):
|
||||
return ".".join(str(p) for p in v)
|
||||
|
||||
@@ -201,6 +332,23 @@ def main():
|
||||
print(" newest released controller : %s (%s)" % (vstr(released), rel_note))
|
||||
print(" newest golden baked : %s (documentation/tests/%s)" % (vstr(baked), bake_note))
|
||||
|
||||
# The waiver is read BEFORE any verdict, because a malformed one is a result of its own (exit 2)
|
||||
# whatever the golden's state — a file that says `expires` and means nothing must not lie there
|
||||
# looking like cover.
|
||||
wstate, winfo = read_waiver()
|
||||
if wstate == "malformed":
|
||||
print("")
|
||||
print("GOLDEN CURRENCY GATE INCONCLUSIVE: the waiver at %s is MALFORMED — %s"
|
||||
% (os.path.relpath(winfo["path"], ROOT), winfo["why"]))
|
||||
print("A malformed waiver is neither cover nor absence. Fix it (four lines: issued, expires "
|
||||
"<= %d days later, reason, register_row) or delete it." % WAIVER_MAX_DAYS)
|
||||
sys.exit(2)
|
||||
if wstate == "valid":
|
||||
print(" waiver : VALID until %s (%d day(s) left) — %s, reason: %s"
|
||||
% (winfo["expires"], winfo["days_left"], winfo["row"], winfo["reason"]))
|
||||
elif wstate == "expired":
|
||||
print(" waiver : EXPIRED on %s (%s)" % (winfo["expires"], winfo["row"]))
|
||||
|
||||
# R-385 — UNRECORDED, checked before "behind". A golden whose version has no heading of its own
|
||||
# was built from something never written down, and that is a different (worse) fault than a
|
||||
# forgotten bake: there is nothing to read to find out what the fleet is running.
|
||||
@@ -208,6 +356,12 @@ def main():
|
||||
print("")
|
||||
print("GOLDEN CURRENCY GATE FAILED: golden %s is baked but UNRECORDED — the controller "
|
||||
"CHANGELOG has no '## v%s' heading." % (vstr(baked), vstr(baked)))
|
||||
if wstate == "valid":
|
||||
# THE ASYMMETRY. A waiver is a cadence choice about a golden that is BEHIND; it says
|
||||
# nothing about a golden nobody wrote down, and must not be read as if it did.
|
||||
print("A waiver exists (%s, until %s) and DOES NOT COVER THIS: it covers a golden that is "
|
||||
"behind the record, never one that is unrecorded (R-385)."
|
||||
% (winfo["row"], winfo["expires"]))
|
||||
print("The newest heading is %s. A golden ahead of the record was built from a version "
|
||||
"nobody wrote down, so no one can read what the fleet is running." % vstr(released))
|
||||
print("Fix: give v%s its own '## v%s — <what changed>' heading in "
|
||||
@@ -220,17 +374,40 @@ def main():
|
||||
sys.exit(1)
|
||||
|
||||
if released > baked:
|
||||
lag = sorted(v for v in every_released if v > baked)
|
||||
if wstate == "valid":
|
||||
print("")
|
||||
print("GOLDEN CURRENCY GATE ADVISORY — WAIVED, NOT CLEAN: controller v%s is released and "
|
||||
"NO golden carries it (newest bake is %s; %d release(s) behind: %s)."
|
||||
% (vstr(released), vstr(baked), len(lag), ", ".join(vstr(v) for v in lag)))
|
||||
print("A machine installed right now would receive v%s and reach v%s by self-update."
|
||||
% (vstr(baked), vstr(released)))
|
||||
print("Waived by %s until %s (%d day(s) left): %s"
|
||||
% (winfo["row"], winfo["expires"], winfo["days_left"], winfo["reason"]))
|
||||
print("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.")
|
||||
print("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)")
|
||||
return
|
||||
print("")
|
||||
print("GOLDEN CURRENCY GATE FAILED: controller v%s is released and NO golden carries it "
|
||||
"(newest bake is %s)." % (vstr(released), vstr(baked)))
|
||||
"(newest bake is %s; %d release(s) behind)." % (vstr(released), vstr(baked), len(lag)))
|
||||
if wstate == "expired":
|
||||
print("The waiver at documentation/tests/golden-waiver.yml EXPIRED on %s (%s). It ran "
|
||||
"out, as a dated waiver is meant to: bake a golden, or renew it with a new dated "
|
||||
"commit (at most %d days)." % (winfo["expires"], winfo["row"], WAIVER_MAX_DAYS))
|
||||
print("A machine installed right now would receive v%s — the release is written, tested and "
|
||||
"pushed, and NOT delivered." % vstr(baked))
|
||||
print("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).")
|
||||
print("If this release deliberately needs no golden, record a waiver in "
|
||||
"documentation/backlog/OPEN-ITEMS.md — never a bypass.")
|
||||
print("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.")
|
||||
sys.exit(1)
|
||||
|
||||
if wstate == "expired":
|
||||
print(" NOTE: the waiver expired on %s and covers nothing today (the golden is current). "
|
||||
"Renew or delete it so it does not read as cover." % winfo["expires"])
|
||||
print("golden currency gate OK — the newest released controller has a golden "
|
||||
"(NOTE: this checks the BAKE, not the vouch — see the module docstring)")
|
||||
|
||||
|
||||
@@ -18,6 +18,12 @@ satisfied by a gate that fails on everything.
|
||||
|
||||
Run: python3 scripts/test_golden_currency_gate.py
|
||||
Exit 0 all pass · 1 a case failed.
|
||||
|
||||
2026-09-13: the WAIVER (Scenarios E-H of the task that built it) is tested below in `waiver_cases`,
|
||||
against a synthetic tree through the gate's GOLDEN_GATE_* seam — a valid waiver passes with the
|
||||
advisory PRESENT; an expired one convicts and NAMES the date; a valid one does NOT save an
|
||||
unrecorded golden (R-385); a 15-day, absent-expiry, unparseable, bad-row and empty-reason waiver
|
||||
each return 2; and the R-421 decoy (a file saying only `expires`) returns 2.
|
||||
"""
|
||||
import io
|
||||
import os
|
||||
@@ -111,13 +117,132 @@ def main():
|
||||
else:
|
||||
print("CASE 4 ok: the tree is unchanged; the gate's verdict is the same as the baseline")
|
||||
|
||||
fails += waiver_cases()
|
||||
|
||||
if fails:
|
||||
print()
|
||||
for f in fails:
|
||||
print("FAIL: %s" % f)
|
||||
return 1
|
||||
print("\ngolden-currency gate self-test OK — a directory name alone cannot satisfy it (R-410)")
|
||||
print("\ngolden-currency gate self-test OK — a directory name alone cannot satisfy it (R-410), "
|
||||
"and the waiver is judged on its dates, its row and its direction (2026-09-13)")
|
||||
return 0
|
||||
|
||||
|
||||
# ── THE WAIVER (2026-09-13) — Scenarios E, F, G, H, each with its red-proof ─────────────────────
|
||||
#
|
||||
# These run the gate against a SYNTHETIC tree through the GOLDEN_GATE_* seam (a fake controller
|
||||
# CHANGELOG, a fake evidence dir with a real-shaped bake log, a fake register, a waiver file), so the
|
||||
# verdicts do not depend on what the real controller happens to have released this week. The seam
|
||||
# moves where the gate reads, never what it decides.
|
||||
|
||||
import datetime
|
||||
import tempfile
|
||||
|
||||
|
||||
def run_gate_env(env):
|
||||
e = dict(os.environ)
|
||||
e.update(env)
|
||||
p = subprocess.run([sys.executable, GATE], capture_output=True, text=True, env=e)
|
||||
return p.returncode, p.stdout + p.stderr
|
||||
|
||||
|
||||
def synthetic_tree(released, baked, waiver_text, register_rows=("R-468",)):
|
||||
"""Build a tree where the CHANGELOG lists `released` (newest first) and one golden `baked` has a
|
||||
real-shaped bake log. Returns (env, tmpdir)."""
|
||||
tmp = tempfile.mkdtemp(prefix="golden-waiver-")
|
||||
ch = os.path.join(tmp, "CHANGELOG.md")
|
||||
with io.open(ch, "w", encoding="utf-8") as fh:
|
||||
for v in released:
|
||||
fh.write("## v%s — synthetic (2026-01-01)\n\nbody\n\n" % v)
|
||||
ev = os.path.join(tmp, "tests")
|
||||
os.makedirs(os.path.join(ev, "golden-%s-2026-01-01" % baked))
|
||||
with io.open(os.path.join(ev, "golden-%s-2026-01-01" % baked, "bake.log"), "w",
|
||||
encoding="utf-8") as fh:
|
||||
fh.write("[golden] upload OK (HTTP 201)\nGOLDEN_VERSION=%s\nGOLDEN_SHA256=%s\n" % (baked, REAL_SHA))
|
||||
reg = os.path.join(tmp, "OPEN-ITEMS.md")
|
||||
with io.open(reg, "w", encoding="utf-8") as fh:
|
||||
for r in register_rows:
|
||||
fh.write("| **%s** | synthetic row | READY | CC |\n" % r)
|
||||
wv = os.path.join(tmp, "golden-waiver.yml")
|
||||
if waiver_text is not None:
|
||||
with io.open(wv, "w", encoding="utf-8") as fh:
|
||||
fh.write(waiver_text)
|
||||
env = {"GOLDEN_GATE_CHANGELOG": ch, "GOLDEN_GATE_EVIDENCE_DIR": ev,
|
||||
"GOLDEN_GATE_WAIVER": wv, "GOLDEN_GATE_REGISTER": reg}
|
||||
return env, tmp
|
||||
|
||||
|
||||
def waiver(issued, expires, reason="pre-customer development; weekly cadence", row="R-468"):
|
||||
lines = ["# synthetic waiver"]
|
||||
if issued is not None:
|
||||
lines.append("issued: %s" % issued)
|
||||
if expires is not None:
|
||||
lines.append("expires: %s" % expires)
|
||||
if reason is not None:
|
||||
lines.append("reason: %s" % reason)
|
||||
if row is not None:
|
||||
lines.append("register_row: %s" % row)
|
||||
return "\n".join(lines) + "\n"
|
||||
|
||||
|
||||
def waiver_cases():
|
||||
fails = []
|
||||
today = datetime.date.today()
|
||||
d = lambda n: (today + datetime.timedelta(days=n)).isoformat()
|
||||
BEHIND = (["9.9.9", "9.9.8", "9.9.7"], "9.9.7") # released 9.9.9, golden 9.9.7: two behind
|
||||
UNRECORDED = (["9.9.9", "9.9.7"], "9.9.8") # golden 9.9.8 has no heading (R-385)
|
||||
|
||||
def check(label, released_baked, wtext, want_rc, must=(), must_not=(), rows=("R-468",)):
|
||||
env, tmp = synthetic_tree(released_baked[0], released_baked[1], wtext, rows)
|
||||
try:
|
||||
rc, out = run_gate_env(env)
|
||||
finally:
|
||||
shutil.rmtree(tmp, ignore_errors=True)
|
||||
bad = [m for m in must if m not in out] + ["NOT expected: " + m for m in must_not if m in out]
|
||||
if rc != want_rc or bad:
|
||||
fails.append("%s: rc=%d (wanted %d) %s\n%s" % (label, rc, want_rc, bad, out[-900:]))
|
||||
else:
|
||||
print("%s ok" % label)
|
||||
|
||||
# BASELINE for the synthetic tree — behind, no waiver: convicted exactly as before this change.
|
||||
check("CASE 5 (baseline, behind, no waiver -> 1)", BEHIND, None, 1,
|
||||
must=("GOLDEN CURRENCY GATE FAILED", "2 release(s) behind"))
|
||||
# E — a valid waiver turns the conviction into a LOUD advisory, exit 0.
|
||||
check("CASE 6 (E: valid waiver, behind -> ADVISORY, 0)", BEHIND, waiver(d(0), d(13)), 0,
|
||||
must=("ADVISORY", "WAIVED", "R-468", d(13), "2 release(s) behind", "OK (WAIVED)"),
|
||||
must_not=("GOLDEN CURRENCY GATE FAILED",))
|
||||
# F — the same waiver, expired: red again, and the reader learns it RAN OUT.
|
||||
check("CASE 7 (F: expired waiver, behind -> 1, names the date)", BEHIND,
|
||||
waiver(d(-10), d(0)), 1, must=("GOLDEN CURRENCY GATE FAILED", "EXPIRED on %s" % d(0)))
|
||||
check("CASE 7b (F: waiver expired yesterday -> 1)", BEHIND, waiver(d(-10), d(-1)), 1,
|
||||
must=("EXPIRED on %s" % d(-1),))
|
||||
# G — a valid waiver never saves an UNRECORDED golden (R-385).
|
||||
check("CASE 8 (G: valid waiver, UNRECORDED golden -> 1)", UNRECORDED, waiver(d(0), d(13)), 1,
|
||||
must=("UNRECORDED", "DOES NOT COVER THIS", "R-385"))
|
||||
# H — a waiver that tries to be permanent, or is malformed, is INCONCLUSIVE — never 0.
|
||||
check("CASE 9 (H: 15-day waiver -> 2)", BEHIND, waiver(d(0), d(15)), 2,
|
||||
must=("MALFORMED", "hard limit is 14"))
|
||||
check("CASE 9b (H: exactly 14 days is the limit and PASSES)", BEHIND, waiver(d(0), d(14)), 0,
|
||||
must=("ADVISORY",))
|
||||
check("CASE 10 (H: absent expiry -> 2)", BEHIND, waiver(d(0), None), 2,
|
||||
must=("MALFORMED", "expires"))
|
||||
check("CASE 11 (H: unparseable expiry -> 2)", BEHIND, waiver(d(0), "next week"), 2,
|
||||
must=("MALFORMED", "expires"))
|
||||
check("CASE 12 (H: register row does not exist -> 2)", BEHIND, waiver(d(0), d(13), row="R-999999"),
|
||||
2, must=("MALFORMED", "R-999999", "does not exist"))
|
||||
check("CASE 12b (H: empty reason -> 2)", BEHIND, waiver(d(0), d(13), reason=""), 2,
|
||||
must=("MALFORMED", "reason"))
|
||||
# THE DECOY (R-421): a file at the right path saying only `expires` must not pass.
|
||||
check("CASE 13 (DECOY: a file containing only the word `expires` -> 2)", BEHIND, "expires\n", 2,
|
||||
must=("MALFORMED",), must_not=("ADVISORY", "OK (WAIVED)"))
|
||||
# A malformed waiver is refused EVEN WHEN the golden is current — it must not lie there as cover.
|
||||
check("CASE 14 (malformed waiver, golden CURRENT -> still 2)", (["9.9.9"], "9.9.9"),
|
||||
waiver(d(0), d(30)), 2, must=("MALFORMED",))
|
||||
# An expired waiver with a current golden: OK, but the expiry is NAMED.
|
||||
check("CASE 15 (expired waiver, golden current -> 0 with a note)", (["9.9.9"], "9.9.9"),
|
||||
waiver(d(-10), d(-1)), 0, must=("expired on %s" % d(-1), "golden currency gate OK"))
|
||||
return fails
|
||||
|
||||
|
||||
sys.exit(main())
|
||||
Reference in new issue
Block a user