Files
felhom-controller/REPORT.md
T
admin 4d349d1106
gates / gates (push) Successful in 10s
REPORT + CONTEXT for v0.203.0: the retry shape, the marker answer, R-220's shape
Records the decisions rather than only the code:
- POLL not ACK, decided on Scenario B against the ACTUAL promises — the
  no-target message gives no deadline and the card says 'within a day', so a
  5-minute tick is inside both and no text needed changing. If either promise
  tightens to minutes, go ACK-driven.
- The marker question: applied_marker lives in the guest's DataDir, which a
  rebuild destroys, so it cannot suppress a legitimate re-run. Left alone.
- R-220 candidate (b), corroborated rather than a wider prefix, reading
  /proc/mounts because the lsblk args are pinned in sudoers.

Live: Scenario C proven on demo-hp WITH a positive control — the job ran once
and logged nothing. A first reading counted 2 lines that turned out to be the
start-up reconcile, not the retry; the instrument was corrected before the
conclusion. Scenarios A and E are deliberately NOT live-proven here: both need a
rebuilt box, and that state arises naturally in Part 4.
2026-08-06 13:05:30 +02:00

102 lines
5.9 KiB
Markdown

# REPORT — felhom-controller v0.203.0 (+ felhom-agent v0.127.0)
**The two dead ends that kept the recovery journey failing are closed in code.** R-218's consume half
and R-220 (both halves: the host-side detection and the customer-facing refusal).
## 1. R-218 — which retry shape, and why (§7.1)
**Poll**, on a 5-minute scheduler tick, driven from the box's own published declaration
(`OffboxReportStatus().State`) — **the very statement the hub acts on**, so the two cannot disagree
about whether a retry is wanted.
**Decided on Scenario B, measured against the actual promises:**
| surface | what it promises |
|---|---|
| the no-target unlock message | „…**amint megvannak**, a mentéseid listája megjelenik…" — **no deadline** |
| the backups card | „…**Ha egy napon belül nem áll be**, jelezd az üzemeltetőnek." — **within a day** |
A 5-minute tick is inside both by a wide margin, and it needs **no hub change** (which §0 expected).
**No text needed changing.** If either promise ever tightens to minutes, the ACK-driven shape is the
one to reach for.
**It stops by construction** (Scenario C) and **the settle gate is kept** (Scenario D) — the retry goes
through `ReconcileWhenSettled`, unchanged.
## 2. The marker question (§7.2) — answered, and left alone
`applied_marker` lives at `<DataDir>/offbox/applied_marker` — **inside the guest's data dir, which a
rebuild destroys.** It therefore cannot suppress a legitimate post-rebuild re-run, and it is not part
of this defect. Untouched.
## 3. R-220's shape (§7.3) — corroboration, not a wider prefix
**Candidate (b)**, the claimed check distinguishing our own mount from a foreign one — because the host
and its knowledge survive the rebuild while the guest's registry does not. Candidate (a) (a cleanup
that clears the raw mounts) would have made correctness depend on a step running, and a step that does
not run leaves exactly today's defect.
**The discriminator is corroborated:** a non-managed mountpoint is forgiven **only when the same device
is ALSO mounted under `/mnt/felhom-drives`** — a pairing only our enrolment produces.
**`/proc/mounts`, not `lsblk MOUNTPOINTS`**, because the lsblk invocation is pinned verbatim in the
sudoers file and changing it would have coupled this fix to a config rollout.
**The fence holds and has its own test** (Scenario F): `/srv/data`, `/media/photos`,
`/mnt/someone-elses-disk`, `/var/lib/other` are all still refused. **Fail-safe:** an unreadable mount
table corroborates nothing.
## 4. Every changed Hungarian string
**The deploy refusal (R-220, Scenario G).** Was:
> „A megadott tárhely nem azonosítható regisztrált meghajtóként, ezért alkalmazás adatkönyvtáraként nem
> használható. **Válasszon a listából csatlakoztatott meghajtót.**"
Now:
> „A megadott tárhely nem azonosítható regisztrált meghajtóként, ezért alkalmazás adatkönyvtáraként nem
> használható. **Ha a gépet nemrég telepítettük újra, a meghajtóid megvannak, de még nincsenek újra
> csatlakoztatva ehhez a géphez — a Tárhely → Meghajtók oldalon csatlakoztathatod őket, és utána
> indítsd újra a telepítést. Ha ott sem látszanak, keresd a Felhom ügyfélszolgálatát.**"
**No other customer-facing string changed.** The NAS refusal is a different situation and is untouched.
## 5. Tests and red-proofs — every one demonstrated failing, then restored
| Scenario | Test | Red-proof mutation | Result |
|---|---|---|---|
| **A** | a credential staged after start-up is collected | make `RetryIfDeclared` return `(false, nil)` — the pre-v0.203.0 world | **FAILS**: "the box declared a need and no reconcile was attempted" |
| **C** | a healthy box does nothing, and logs nothing | drop the `!declared()` stop condition | **FAILS**: a healthy box reconciles |
| **D** | the settle gate holds on the retry path | call `Reconcile` instead of `ReconcileWhenSettled` | **FAILS**: "SETTLE GATE BYPASSED" |
| **E** | the customer's own drive is offered after a rebuild | remove the `felhomOwnedMounts` exemption | **FAILS**: "device is mounted at /mnt/adatok (sdb)" |
| **F** | a genuinely foreign mount is still refused | over-widen to any `/mnt/*` path | **FAILS**: "/mnt/someone-elses-disk was offered for formatting" |
| **G** | an empty list explains itself | restore the old sentence | **FAILS**: "the refusal tells the customer to choose from a list that may be empty" |
Plus: a nil bridge is a silent no-op; the corroboration requires both mounts of the **same** device,
and another device's managed mount does not vouch for a foreign one.
**Green:** controller **28 packages ok**, agent **29 packages ok**, both `go vet` clean, all gates OK
in both repos.
## 6. Live checks (§7.4)
**Deployed to demo-hp** from the **published** bytes (agent sha verified against the artifact before
installing): agent **0.127.0**, controller **0.203.0**, healthy.
**Scenario C — PROVEN LIVE, with a positive control.** The retry job is registered
(`Registered periodic job: offsite-credential-retry (every 5m0s)`), **ran once**
(`Running job: offsite-credential-retry` = 1) and produced **zero** log lines on a box whose tier is
configured. The positive control matters: without it, silence could have meant the job never fired.
*(A first reading counted 2 lines and looked like noise; they were the START-UP reconcile's settle-gate
lines, not the retry job — the instrument was corrected before the conclusion.)*
**Scenarios A and E are NOT live-proven yet, and deliberately so.** Both need a *rebuilt* box: A needs
one declaring `needs_credential` (no target), E needs one whose registry lost its drives while the raw
mounts survived. Contriving either on a demo box means dismantling its real off-site state; the state
arises **naturally in Part 4**, which is where they belong and where the last re-walk measured them.
## 7. Not changed
No hub change. No sudoers, no allowlisted command, no PVE surface. The settle gate, the marker, every
other claim signal, and the NAS refusal are untouched.