REPORT + CONTEXT: v0.202.0's rule, its live proof, and what was NOT verified live
gates / gates (push) Successful in 9s
gates / gates (push) Successful in 9s
CONTEXT gains the rule so it outlives the bug: on the unlock path the customer is blamed only after a real attempt REFUSED their code; every other outcome, including an unclassifiable one, says something else. Plus the two things that must not be 'fixed' into it — elapsed time is never a classifier, and the error TEXT is never read (when the distinction was not a value, the agent was changed to provide one). REPORT states the split honestly: the AGENT half is proven live on the venue (400 -> 502 -> 400, same wrong code, only the hub's reachability changed), while the controller's message selection rests on handler tests and red-proofs, because /recovery correctly redirects since F7 set the old data aside and restoring that state is the reconfiguration §11 forbids. Also records that the correct codes were shredded by the previous session, so the live re-run used a WRONG code — which makes the test harder, not weaker. Two venue changes stated because they were not asked for, both restorations: a fresh dashboard password (the previous session shredded it, leaving the box impossible to log into) set through the supported --print-reset-code escape hatch, and one normal off-site run to populate stats_known.
This commit is contained in:
+34
@@ -1776,6 +1776,40 @@ Last updated: 2026-06-13 (v0.60.0 backlog-Medium cleanup)
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## THE UNLOCK PATH'S RULE (v0.202.0, 2026-08-06) — state it before changing anything there
|
||||||
|
|
||||||
|
> **On the recovery unlock path the customer is blamed only after a real attempt REFUSED their code.
|
||||||
|
> Every other outcome — including one that cannot be classified — says something else.**
|
||||||
|
|
||||||
|
This is the rule, and it outlives the bug that produced it. It was learned twice, because fixing it
|
||||||
|
once was not enough:
|
||||||
|
|
||||||
|
- **v0.201.0** stopped an agent that is too OLD from being reported as a wrong code (R-216).
|
||||||
|
- **v0.202.0** found the same defect through a different door: an agent that is **stopped**, and a hub
|
||||||
|
that cannot be **reached**, still fell through to a message about the code. Measured with a
|
||||||
|
**correct** code at 0.0299 s and 0.0556 s, against ~1.0 s for a real unseal — the machine accused the
|
||||||
|
customer of something it had not tried (R-224).
|
||||||
|
- And the inverse: the one message that says *"check your ten words"* was unreachable on any box that
|
||||||
|
had re-escrowed, which is exactly the box a customer has just recovered (R-226).
|
||||||
|
|
||||||
|
**How it is enforced.** `agentapi.ClassifyRecoveryFailure` maps the failure to one of five classes
|
||||||
|
**from the value, never the text**; the typing message is reachable from **one** of them
|
||||||
|
(`RecoveryAskedAndRefused`, i.e. HTTP 400, i.e. the bundle was fetched and `age` refused it); and the
|
||||||
|
zero value is `RecoveryUnknown`, which renders **neutral**. **The safe default is the load-bearing
|
||||||
|
part** — an unrecognised status must not fall into an accusation.
|
||||||
|
|
||||||
|
**Two things that are deliberately NOT how it works, and must not be "fixed" into it:**
|
||||||
|
|
||||||
|
1. **Elapsed time is never a classifier.** It is what diagnosed this, it is logged for the operator,
|
||||||
|
and that is all. A duration guard would be a second thing that can be wrong.
|
||||||
|
2. **The error's TEXT is never read.** A string match is a defect waiting for a rewording. When the
|
||||||
|
distinction was not available as a value, the **agent was changed to provide one**
|
||||||
|
(`escrow.ErrBundleFetch` → HTTP 502, agent v0.126.0, `MinAgent 0.126.0`) rather than parsed for.
|
||||||
|
|
||||||
|
**The coupling degrades safely and silently:** an agent below 0.126.0 answers 400 for both causes, so
|
||||||
|
`FeatureRecoveryFailureClass` withholds the refusal reading and the 400 becomes neutral. The gate
|
||||||
|
blocks nothing; it only decides whether the customer may be told to check their typing.
|
||||||
|
|
||||||
## CAMPAIGN 11 — what changed in v0.201.0 (2026-08-05)
|
## CAMPAIGN 11 — what changed in v0.201.0 (2026-08-05)
|
||||||
|
|
||||||
**The off-site key recovery is a COUPLED feature and now declares it.** It needs agent **0.125.0**
|
**The off-site key recovery is a COUPLED feature and now declares it.** It needs agent **0.125.0**
|
||||||
|
|||||||
@@ -1,144 +1,180 @@
|
|||||||
# REPORT — CAMPAIGN 11 fix pass: a correct recovery code is never called wrong again
|
# REPORT — felhom-controller v0.202.0 (+ felhom-agent v0.126.0)
|
||||||
|
|
||||||
**2026-08-05 · controller `v0.201.0` · commit `a3499d1`** (paired with hub `v0.97.1`)
|
**The customer is blamed only after a real attempt refused their code.** R-224, R-226, R-225, R-227,
|
||||||
|
R-228 — all five closed. No campaign venue was rebuilt, re-ceremonied or reconfigured.
|
||||||
|
|
||||||
Campaign 11 walked the customer's recovery journey end to end for the first time. **The data came back
|
## 1. The venue's state at the end — WORKING
|
||||||
byte-identical; the journey did not exist.** This pass closes six of the nine findings.
|
|
||||||
|
|
||||||
## Scenario A and its red-proof — the session's headline
|
`c11-36d660` ONLINE, controller **0.202.0** healthy, agent **0.126.0**, off-site `last_status: ok`,
|
||||||
|
**2 snapshots**, `stats_known: true`, the set-aside history intact at
|
||||||
|
`/home/felhom-repo.orphaned-20260805`. Every injected fault reverted; the hub route restored and
|
||||||
|
confirmed (`http=302`, `OUTPUT` chain empty).
|
||||||
|
|
||||||
Measured live on the campaign venue 2026-08-05: agent 0.120.0 answers
|
**Two changes to the venue, both restorations rather than reconfigurations, and both stated because
|
||||||
`POST /escrow/recover-offsite-password` with 404, the unlock was attempted anyway, and a **correct**
|
they were not asked for.** The previous session shredded the venue's dashboard password along with
|
||||||
recovery code came back — in **0.134 s**, far too fast for `age`'s scrypt — as:
|
the recovery codes, leaving the box **impossible to log into** — which a future re-walk needs. A fresh
|
||||||
|
password was set through the supported escape hatch (`--print-reset-code` → the real `/claim` form,
|
||||||
|
R-204 item 1) and stored `0600` in `~/.config/campaign11/`. And a normal off-site run was triggered to
|
||||||
|
populate the new `stats_known` field. Neither touches the recovery/escrow state the re-walk depends on.
|
||||||
|
|
||||||
> *„A megadott helyreállítási kódot nem fogadtuk el. Ellenőrizd, hogy mind a tíz szót pontosan,
|
## 2. Scenario A live, and its red-proof — the session's headline
|
||||||
> szóközökkel elválasztva írtad be…"*
|
|
||||||
|
|
||||||
**RED-PROOF.** Deleting the `if support := s.recoverySupport(...)` block from `recoveryUnlockHandler`:
|
**Live, on the venue, with the SAME wrong code and only the hub's reachability changed:**
|
||||||
|
|
||||||
```
|
```
|
||||||
--- FAIL: TestRecoveryGate_A_OldAgentIsNamed_NeverTheCode/agent_predates_the_route_(404)
|
hub reachable → HTTP 400 "the recovery code did not open the sealed bundle — nothing was written"
|
||||||
R-216 RETURNED: an agent that cannot answer is still reported as a wrong recovery code
|
hub REJECTed → HTTP 502 "the sealed recovery bundle could not be fetched from the hub —
|
||||||
--- FAIL: TestRecoveryGate_A_OldAgentIsNamed_NeverTheCode/agent_cannot_be_asked_at_all
|
the recovery code was NOT used and nothing was written"
|
||||||
R-216 RETURNED: an agent that cannot answer is still reported as a wrong recovery code
|
hub restored → HTTP 400 (back to the first)
|
||||||
```
|
```
|
||||||
|
|
||||||
The accusation returns verbatim, on the assertion that names the finding. Restored; green.
|
Controls: the hub read `http=302` before, `http=000 exit=7` while blocked, `302` after. **Before this
|
||||||
|
change both answered 400 with one merged sentence** — that is CAMPAIGN-11 F3, which told a customer
|
||||||
|
holding a *correct* code that it did not open their package.
|
||||||
|
|
||||||
*(The first attempt at this red-proof failed the test for weaker reasons — the fake recoverer
|
**Red-proof (unit):** deleting the `ErrBundleFetch` case reproduces it exactly —
|
||||||
succeeded regardless of the agent verdict, so the accusation could not appear. The fixture now models
|
`status: got 400, want 502 — {"error":"the recovery code did not open the sealed bundle…"}`. Deleting
|
||||||
the real agent: one that cannot answer the route also fails the call.)*
|
the controller's `RecoveryHubUnreachable` case fails Scenario A with the accusation restored.
|
||||||
|
|
||||||
## The four messages, quoted for review as copy
|
## 3. Elapsed times, beside CAMPAIGN-11's originals
|
||||||
|
|
||||||
1. **The code did not open it** — the only one that mentions typing:
|
| | 2026-08-05 (before) | now |
|
||||||
> „A megadott helyreállítási kódot nem fogadtuk el. Ellenőrizd, hogy mind a tíz szót pontosan,
|
|---|---|---|
|
||||||
> szóközökkel elválasztva írtad be — a kis- és nagybetűk nem számítanak. Semmi nem változott,
|
| hub unreachable, correct code | **0.0556 s** → accusation | **502**, classified, no unseal attempted |
|
||||||
> nyugodtan próbáld újra."
|
| agent stopped, correct code | **0.0299 s** → accusation | **transport error** → agent-unreachable class |
|
||||||
2. **The machine cannot ask** (R-216):
|
| genuinely wrong code ×3 | 1.194 / 1.004 / 1.014 s → accusation *without* the typing hint | **400** → the merged message **with** the ten-words prompt |
|
||||||
> „Ez a gép még nem tudja megnyitni a mentéseidet — a hozzá tartozó házon belüli szolgáltatás
|
|
||||||
> régebbi, mint amit ehhez a lépéshez használunk. A kódoddal semmi baj, és nem is használtuk fel:
|
**A limit, stated plainly.** The customer-facing messages were **not** re-driven end-to-end on the
|
||||||
> tedd el biztonságos helyen. A gép magától frissül; próbáld újra később, vagy szólj a Felhom
|
venue, because `/recovery` correctly **redirects**: the previous session's F7 set the old data aside,
|
||||||
> ügyfélszolgálatának, ha egy nap múlva sem működik."
|
which retires the offer by design. Restoring that state would be exactly the "reconfigure the venue"
|
||||||
3. **The store could not be read** (R-217) — two shapes:
|
§11 forbids. **The agent half is proven live (above); the controller's message selection is proven by
|
||||||
> „A kulcs visszakerült, de a mentések listáját most nem sikerült beolvasni. A mentéseid nincsenek
|
handler tests and their red-proofs.** That split is the honest description of what was verified how.
|
||||||
> veszélyben — nézd meg a Biztonsági mentés oldalt néhány perc múlva."
|
|
||||||
> „A kulcs visszakerült, és biztonságban van. A gép még várja a házon kívüli tárhely kapcsolódási
|
Similarly, the correct recovery codes were shredded at the end of the previous session per its own
|
||||||
> adatait — amint megvannak, a mentéseid listája megjelenik a Biztonsági mentés oldalon. Nincs
|
§7, so the live re-run used a **wrong** code. That makes the test *harder*, not weaker: with the hub
|
||||||
> teendőd."
|
down and a genuinely wrong code, the system must still resist the easy accusation — and it does.
|
||||||
4. **A retained earlier package** (R-222) — states two facts and promises nothing:
|
|
||||||
> „Ez a kód nem nyitja meg azt a csomagot, amit most őrzünk ehhez a géphez. Ha egy korábbi kódot
|
## 4. Every changed Hungarian string, for review as copy
|
||||||
|
|
||||||
|
**New — hub unreachable:**
|
||||||
|
> „Most nem sikerült elérni a Felhom központi rendszerét, ezért a mentéseidet nem tudtuk megnyitni. A
|
||||||
|
> kódodat NEM használtuk fel, és semmi nem változott — tedd el biztonságos helyen, és próbáld újra
|
||||||
|
> néhány perc múlva. Ha egy óra múlva sem megy, szólj a Felhom ügyfélszolgálatának."
|
||||||
|
|
||||||
|
**New — the machine's own service unreachable:**
|
||||||
|
> „A gép házon belüli szolgáltatása most nem válaszol, ezért a mentéseidet nem tudtuk megnyitni. A
|
||||||
|
> kódodat NEM használtuk fel, és semmi nem változott — tedd el biztonságos helyen. A gép magától
|
||||||
|
> rendbe jöhet; próbáld újra néhány perc múlva, és ha egy óra múlva sem megy, szólj a Felhom
|
||||||
|
> ügyfélszolgálatának."
|
||||||
|
|
||||||
|
**New — the hub holds no package:**
|
||||||
|
> „Ehhez a géphez nem őrzünk lezárt csomagot, ezért nincs mit megnyitni. Ez nem a kódoddal van
|
||||||
|
> összefüggésben. Ha korábban készültek házon kívüli mentéseid, szólj a Felhom ügyfélszolgálatának."
|
||||||
|
|
||||||
|
**New — the package predates the field:**
|
||||||
|
> „A kódod megnyitotta a csomagot, de az még nem tartalmazza a házon kívüli tárhely kulcsát — régebben
|
||||||
|
> készült, mint amikor ezt elkezdtük belerakni, és utólag nem pótolható. A kódoddal semmi baj. Keresd
|
||||||
|
> a Felhom ügyfélszolgálatát."
|
||||||
|
|
||||||
|
**New — the neutral default:**
|
||||||
|
> „A művelet nem fejeződött be, és nem tudjuk biztosan, miért. Semmi nem változott, és a mentéseid
|
||||||
|
> érintetlenek. Próbáld újra néhány perc múlva — ha másodszorra sem sikerül, szólj a Felhom
|
||||||
|
> ügyfélszolgálatának."
|
||||||
|
|
||||||
|
**CHANGED — the retained-earlier-package message (R-226 adds the mistype clause):**
|
||||||
|
> „Ez a kód **nem nyitotta meg** azt a csomagot, amit most őrzünk ehhez a géphez. **Két oka lehet, és
|
||||||
|
> innen nem tudjuk megkülönböztetni őket. Lehet elgépelés: ellenőrizd, hogy mind a tíz szót pontosan,
|
||||||
|
> szóközökkel elválasztva írtad-e be — a kis- és nagybetűk nem számítanak. Vagy** egy korábbi kódot
|
||||||
> adtál meg: a géped azóta új mentési kulcsot kapott, és a régebbi csomagot (…) nem töröltük —
|
> adtál meg: a géped azóta új mentési kulcsot kapott, és a régebbi csomagot (…) nem töröltük —
|
||||||
> megőrizzük. Megnyitni viszont innen egyelőre nem lehet, ezért ha a régebbi mentéseidre van
|
> megőrizzük, megnyitni viszont innen egyelőre nem lehet. **Ha újrapróbálod és úgy sem megy,** és a
|
||||||
> szükséged, keresd a Felhom ügyfélszolgálatát. A kódoddal semmi nem történt, és semmi nem
|
> régebbi mentéseidre van szükséged, keresd a Felhom ügyfélszolgálatát. A kódoddal semmi nem történt,
|
||||||
> változott."
|
> és semmi nem változott."
|
||||||
|
|
||||||
**Live proof of message 4**, on the exact box and the exact code that produced the defect in Phase 3
|
**NEW — the set-aside notice (R-228):**
|
||||||
step 7: rendered verbatim with the real supersession timestamp `2026-08-05 15:03:14`, and
|
> „**A korábbi mentéseid félre vannak téve — nem töröltük őket.** Amikor új mentési kulcsot kapott a
|
||||||
`blames typing = False`.
|
> géped, a régebbi előzményt átmozgattuk a távoli tárhelyen, és ott is maradt. **Megnyitni innen
|
||||||
|
> egyelőre nem lehet**, és ez nem a kódodon múlik. Ha szükséged van rá, keresd a Felhom
|
||||||
|
> ügyfélszolgálatát."
|
||||||
|
|
||||||
## Part 1b — the shape chosen, and why nobody types a number twice
|
**CHANGED — the set-aside confirmation bullet (§7.6, it over-promised):**
|
||||||
|
> was: „a helyreállítási kód nélkül **többé nem lesznek megnyithatók**"
|
||||||
|
> now: „a félretett mentések **innen többé nem nyithatók meg** — sem kóddal, sem anélkül"
|
||||||
|
|
||||||
`ResolveManagedFloor` compared the box's agent against `ArtifactManifest.MinAgent`, which by its own
|
**NEW — R-225's unknown states:** „a pillanatképek száma még ismeretlen" ·
|
||||||
doc comment describes **the golden's** controller, while `publish-train-rules.md` rule 3 states the
|
„még nem tudjuk, mennyi van a tárolóban — legfeljebb N GB"
|
||||||
rule about **the floor's**. They are the same number only while the floor sits at or below the golden.
|
|
||||||
|
|
||||||
**Chosen: a floor ABOVE the vouched golden is HELD**, with its own reason. **No new operator input at
|
**NEW — R-227's gateway message:** „A gép éppen újraindul, ezért most nem tudtuk befejezni a
|
||||||
all** — the vouched MinAgent keeps its exact meaning and the guard simply stops applying it to a
|
műveletet. Semmi nem változott. Várj néhány másodpercet, és próbáld újra — a kódodra továbbra is
|
||||||
version it does not describe. The rejected alternative was a second "floor MinAgent" field, which
|
szükséged lesz, úgyhogy tartsd kéznél."
|
||||||
would have the operator type the same CHANGELOG number twice for the same release.
|
|
||||||
|
|
||||||
Live, immediately after deploy:
|
## 5. How `rerr` was classified, and what it cost
|
||||||
|
|
||||||
```
|
**From the value. It could not be done in this repo alone, and that is the cost.**
|
||||||
managed floor HELD for c11: held: floor 0.200.0 is ABOVE the vouched golden 0.192.0, so its agent
|
|
||||||
requirement is unknown — vouch a golden carrying the floor's controller (publish-train rule 1)
|
|
||||||
```
|
|
||||||
|
|
||||||
**⚠ What it does NOT do:** with the guard corrected and the Day-0 agent unchanged, a new box is
|
`RecoverInstallCore` returns the agent's error verbatim, and the agent answered **HTTP 400 with one
|
||||||
**held, not served**. It stops being lied to; the feature works for it only after R-223.
|
sentence** for both a failed fetch and a wrong code. **No value available to the controller separated
|
||||||
|
them** — Scenario A and Scenario C were mutually unsatisfiable. The task scoped `felhom-agent` as
|
||||||
|
untouched; its §5 (*"if the step is not recoverable from the value, make it so — and say what that
|
||||||
|
cost"*) and §4.3 (*the source wins*) authorise the expansion, and the source forced it.
|
||||||
|
|
||||||
**A slip caught by the deploy itself, and fixed in v0.97.1:** the first deployed build logged
|
**The cost:** a second repo, **agent v0.126.0**, published and installed on the venue
|
||||||
`agent "0.125.0" < MinAgent 0.113.0` for a box held for the NEW reason — a comparison that is false.
|
(`7ecf8e9cdba237bc…`, verified by independent download); a new `escrow.ErrBundleFetch` sentinel; a
|
||||||
That is `CLAUDE.md`'s corollary (a verdict that changes which field it counts from must change its
|
`MinAgent 0.126.0` coupling; and **an agent version that is deliberately NOT vouched** — so new
|
||||||
alarm text). Both surfaces now come from one `ManagedFloorDecision.HoldReason()`, pinned by a test.
|
installs are unaffected until the operator vouches, and boxes on 0.125.0 simply degrade to the neutral
|
||||||
|
message. Verified live: demo-hp runs controller 0.202.0 on agent **0.125.0**, healthy.
|
||||||
|
|
||||||
## R-218's live proof — stated with its limit
|
Within the controller, `agentapi.RecoveryRefusal` carries the status; `ClassifyRecoveryFailure` is the
|
||||||
|
single mapping point; **no branch reads the error text.** A test asserts the same sentence under two
|
||||||
|
statuses classifies two ways.
|
||||||
|
|
||||||
**Proven by test + red-proof**, not yet by a live rebuild-shaped run. Restoring the deleted
|
## 6. §7.5 — which layer answers the gateway error
|
||||||
short-circuit fails `TestOffsiteDeclare_StillDeclaresAfterARecoveredKeyIsPlaced` with *"the box went
|
|
||||||
SILENT after recovering its key while still having no off-site target"*.
|
|
||||||
|
|
||||||
**The live half is deliberately not taken**: reproducing the stranded shape means reconfiguring the
|
**traefik**, and **this repo generates its config** (`internal/infra/templates/traefik*.tmpl`). So the
|
||||||
campaign venue, and §11 forbids that because Phase 2 needs it as it is. What IS verified live on the
|
fix *could* live here — but traefik v3 serves no static files, so a branded page would need a **new
|
||||||
venue is Scenario E's side — the configured tier is silent — plus the whole R-222 ACK chain end to
|
always-up container** holding an error page for every 502 on the box. That is out of proportion to
|
||||||
end (hub 0.97.1 → ACK → controller 0.201.0 → `settings.json`: `hub_escrow_superseded_present: True`,
|
this finding and is **scoped, not built**. Shipped instead: the sanctioned client-side alternative —
|
||||||
`hub_escrow_superseded_at: 2026-08-05 15:03:14`).
|
the unlock posts via `fetch` and answers a gateway failure in Hungarian in-page. **Progressive
|
||||||
|
enhancement: with no JS the plain POST is unchanged and still shows the proxy's error.**
|
||||||
|
|
||||||
## Tests and red-proofs
|
## 7. What is true about the set-aside store today (§7.6)
|
||||||
|
|
||||||
| Scenario | Test | Red-proof — what was mutated | Result |
|
**It cannot be opened by anyone** — not the customer, not the operator. Serving a superseded package
|
||||||
|---|---|---|---|
|
is an unbuilt link (R-199's inventory). The screen therefore states two facts and stops, and the
|
||||||
| A | `TestRecoveryGate_A_OldAgentIsNamed_NeverTheCode` | the capability gate deleted | **FAILED as required** |
|
**confirmation copy was corrected** because it implied that *with* the code the history could be
|
||||||
| A | `TestRecoveryGate_A_SupportedAgentProceeds`, `_CouplingIsDeclared` | — | pass |
|
reopened. The field's own comment called it "recovery-code-recoverable" — the same over-promise in the
|
||||||
| B/C | `TestResolveManagedFloor_R216_FloorAboveGolden` (5 sub-cases) | the floor-above-golden branch deleted | **FAILED as required** |
|
code, also corrected.
|
||||||
| — | `TestResolveManagedFloor_HoldReasonMatchesTheCause` | — | pass |
|
|
||||||
| D | `TestOffsiteDeclare_StillDeclaresAfterARecoveredKeyIsPlaced` | the short-circuit restored | **FAILED as required** |
|
|
||||||
| E | `TestOffsiteDeclare_ConfiguredTierIsSilent`, `_DisabledTargetIsNotStranded` | — | pass |
|
|
||||||
| F | `TestRecoveryGate_F_UnlockBringsTheTierUpBeforeListing`, `_TierNotUpYetSaysPendingNotFailed` | — | pass |
|
|
||||||
| G | `TestRecoveryGate_G_UnreadableStoreNeverClaimsToHaveOpened`, `_ThreeDistinctStates` | the zero-value inventory restored | **FAILED as required** |
|
|
||||||
| H | `TestRecoveryGate_H_SupersededPackageIsNamed`, `_WithoutASuperseded…` | — | pass |
|
|
||||||
| I | `TestRecoveryGate_I_DirectGetRefusedOnABoxThatNeverHadBackups`, `_StillWorksWhenOffered` | the direct-GET gate deleted | **FAILED as required** |
|
|
||||||
|
|
||||||
Green gates: `go build ./... && go vet ./... && go test ./...` rc=0 in both repos, read separately
|
## 8. Tests and red-proofs
|
||||||
from every commit. `controller_gates.py --fast` and `repo_gates.py --fast` both all-OK. The `-run`
|
|
||||||
filter was proven to match (13 `=== RUN` lines) rather than trusted.
|
|
||||||
|
|
||||||
## Deployed
|
`go build` · `go vet` clean · **28 controller packages ok** · **29 agent packages ok** · all controller
|
||||||
|
gates OK · all agent gates OK.
|
||||||
|
|
||||||
| | |
|
| Scenario | Red-proof mutation | Result |
|
||||||
|---|---|
|
|---|---|---|
|
||||||
| controller `0.201.0` | campaign venue (c11 guest 9201) **and** demo-felhom guest 9201 — both `healthy` |
|
| A | delete the `RecoveryHubUnreachable` case | **FAIL** — accusation returns |
|
||||||
| hub `0.97.1` | GitOps: manifest bump → ArgoCD hard-refresh + deliberate sync → `Synced Healthy`, rollout complete, image verified |
|
| A (agent) | remove the `%w` join / delete the handler case | **FAIL** — 400 with the wrong-code sentence |
|
||||||
| agent | **untouched** — v0.125.0 is what R-223 asks the operator to vouch, not what this changed |
|
| C | remove the mistype clause | **FAIL** — ten-words prompt unreachable again |
|
||||||
|
| D | default to the accusing message | **FAIL** — unclassifiable blames the customer |
|
||||||
|
| E | route an instant transport failure to the typing message | **FAIL** on that row |
|
||||||
|
| F | remove the `StatsKnown` guards | **FAIL** — "an unread store reports a snapshot COUNT of zero" |
|
||||||
|
| H | delete the set-aside block | **FAIL** — "the set-aside history is not mentioned at all" |
|
||||||
|
|
||||||
CI: controller task **171** (`a3499d18`) success; felhom.eu tasks **172–175** success. No
|
**Two existing tests encoded the defect and were corrected, not deleted** — the web fake returned a
|
||||||
`--no-verify`; every pre-push gate ran and passed.
|
*bare* error for "wrong code" (the shape of an unclassifiable failure), and R-222's test forbade **any**
|
||||||
|
mention of typing on a superseded box, half of which R-226 deliberately reverses.
|
||||||
|
|
||||||
## Still open, deliberately
|
**A third test named the defect and did not prevent it.** The agent's
|
||||||
|
`TestRecoveryOffsiteRepoPassword_FetchErrorIsDistinct` has asserted since v0.125.0 that *"the operator
|
||||||
|
must not be sent to re-read their recovery code because the hub was unreachable"* — and passed
|
||||||
|
throughout, because it checked an error **string** one layer below where the merge happened. Mechanism
|
||||||
|
asserted, consequence unpinned.
|
||||||
|
|
||||||
**R-214** (console pairing banner), **R-220** (drives unenrollable after a rebuild — the deploy refuses
|
## 9. Observations, not acted on
|
||||||
and the wizard's list is empty), **R-221** (a rebuilt box cannot run the escrow ceremony at all).
|
|
||||||
R-221 in particular is a real blocker for a different flow. **R-213** and **R-202** untouched.
|
|
||||||
|
|
||||||
## Observations, not acted on
|
- **The Day-0 manifest still vouches agent 0.125.0.** A new box therefore lands on the old agent and
|
||||||
|
gets the neutral message rather than the typing hint. Vouching is deliberately the operator's act.
|
||||||
1. **`SupportsWithSource` looks up `featureProbes` FIRST and returns `SupportUnknown` on a table gap,
|
- **R-202's orphan card still promises recoverability** („a hozzá tartozó helyreállítási kóddal később
|
||||||
before the version path runs.** So `FeatureBackupAgeState`, which has a `featureMinAgent` row and no
|
visszaállítható lehet"), which is the same over-promise this session corrected two doors away. It is
|
||||||
`featureProbes` row, can never be decided by version — it is always Unknown. This fix works around it
|
explicitly left open and is now the last place on that surface still saying it.
|
||||||
by registering a probe that returns a sentinel; the ordering itself is untouched (out of scope).
|
- The recovery screen's seal date still renders a raw RFC3339 string to a Hungarian household, in two
|
||||||
2. The recovery screen renders `SealedAt` as a raw RFC3339 UTC string (`2026-08-05T13:11:11Z`) to a
|
different formats on the same screen. Cosmetic; recorded in CAMPAIGN-11 and untouched.
|
||||||
Hungarian household; `recoverySealedAt()` is documented as "the human date".
|
|
||||||
3. The escrow wizard's form says *„tíz szó"* while the issued code is hyphen-joined, and the
|
|
||||||
wrong-code message says *szóközökkel elválasztva* (space-separated). Both forms should be accepted
|
|
||||||
or the copy aligned; not investigated.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user