v0.260.0 — a box ahead of the catalog reads „Naprakész", and the pin never moves backwards (R-524)
gates / gates (push) Successful in 24s

MEASURED 2026-09-15 (BIGNIGHT Phase 6): privatebin updated 2.0.5 -> 2.0.6, catalog
reverted to 2.0.5, and the box read „Frissítés elérhető — ma" over an Update that
would have moved the pin BACKWARDS onto a possibly-migrated datadir.

- stacks.CatalogOrder: the comparison gains a fourth answer (Ahead) and moves out of
  web, so the badge and UpdatePreflight cannot drift apart.
- The badge: ahead reads „Naprakész"/"Up to date", tag-ok, with a title saying why.
- The refusal: UpdatePreflight returns `downgrade` (409), born as a bundle key; the
  API now renders update refusals through errText so it reaches English households.
- Ahead is narrow: every differing service must be orderable AND newer, else Behind.
- Ordering is util.Version.Compare behind a tag normaliser — no second comparator.
- Three red-proofs, each seen to fail.

R-589 was already fixed in v0.258.0; only its register row was stale.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-09-21 12:48:55 +02:00
parent 19ef0329ab
commit 8f8a64cad7
14 changed files with 597 additions and 42 deletions
+50
View File
@@ -1,3 +1,53 @@
## v0.260.0 — a box AHEAD of the catalog reads „Naprakész", and the pin never moves backwards (2026-09-21, R-524)
**MinAgent: 0.131.0** (unchanged). Hungarian pages byte-identical; the two new sentences are BORN AS
KEYS in both bundles and the Go-parity gate accounts for them.
**The defect was measured, not imagined.** BIGNIGHT Phase 6, 2026-09-15: privatebin was updated
2.0.5 → 2.0.6 through the guarded Update, the catalog was then reverted to 2.0.5, and the box read
the tag „**Frissítés elérhető — ma**" with the title inviting the household to press Frissítés. The
comparison asked only "does the installed reference DIFFER from the catalog's?", so a catalog revert
— an operator act on our side — presented itself to a customer as an update, and the guarded Update
behind it would have advanced the pin 2.0.6 → 2.0.5, onto a datadir the newer version may already
have migrated, with §4's ruling saying that cannot be undone.
- **`stacks.CatalogOrder` — the comparison gains a FOURTH answer, and moves house.** Unknown /
Current / Behind / **Ahead**. It now lives in `internal/stacks/updateorder.go` rather than in
`web`, because TWO callers must reach the same verdict — the badge and the update's refusal — and
a comparison implemented twice is a comparison that drifts. `web.compareInstalledToTemplate` is a
thin wrapper; every property it carried is carried still (absent means UNKNOWN and never
„Naprakész"; it reads `CatalogImages` and never `TemplateImages`; it queries NO registry).
- **The badge.** An app ahead of the catalog reads „Naprakész" / "Up to date" with `tag-ok` — the
same word and the same class as level, because there is nothing for the household to do — and a
title that says why (`badge.update.ahead.title`, both bundles). No version number reaches the
customer, as before.
- **The refusal.** `UpdatePreflight` returns `downgrade` (409) with
„Ez a változat újabb a katalógusban lévőnél — visszalépés csak az üzemeltető kérésére.", logged
with both image maps. **The API renders update refusals through `errText` now**, so a refusal
carrying a key reaches an English household in English — without that line the new key would have
been a seam built and never wired, which is a documented failure class in this repo.
- **Ahead is the NARROW arm, deliberately.** Every differing service must be orderable AND newer.
One service older, one tag unorderable, and the answer falls back to Behind — i.e. to exactly the
behaviour of v0.233.0..v0.259.0. This gate can BLOCK an update, so it errs towards letting one run.
- **Ordering is `util.Version.Compare` and nothing else** (the house rule: one comparator). The new
code is a tag NORMALISER in front of it: `X.Y` and `X.Y.Z`, optional leading `v`, a two-part tag
padded with `.0`, and a trailing suffix that must be IDENTICAL on both sides — so
`nextcloud:31.0.14-apache → 31.0.15-apache` orders, while `26.05.2-ls310 → 26.05.2-ls311`,
`postgres:16-alpine`, `kimai/kimai2:apache-2.57.0`, a date stamp and a digest pin do not.
**Measured against the real catalog**, not invented: 8 of the 66 pins float and `apache-2.57.0`
puts its version at the back.
- **Three red-proofs, each seen to fail.** (1) Make the Ahead arm return Behind →
`TestR524_PreflightRefusesDowngrade` fails with the update ALLOWED. (2) Treat an unorderable pair
as ahead → the floating-tag, different-image and digest-pin cases fail, which is the verdict that
would suppress a real „Frissítés elérhető" on the floating pins. (3) Delete the ahead arm from
`localeFuncs` → the English badge test fails.
**R-589 was NOT open, whatever the register said.** The row (P3-LOW, READY) claims the badge builds
from four raw Hungarian literals with no key. Those literals are real and DELIBERATE — they are the
parity guarantee — and the English form has been rebuilt from the bundle in `localeFuncs` since
**v0.258.0**, proven live on a fresh box the same day ("Up to date", English drill item 9). The row
is stale, not the code; it is closed in this session with that citation.
## v0.259.0 — the claim page and the backup warnings answer in the reader's language (2026-09-21, R-596/R-598)
**MinAgent: 0.131.0** (unchanged). The Hungarian pages are byte-identical; the Go-parity gate