Files
felhom-controller/REPORT.md
T
admin 2f8ff2414c
gates / gates (push) Successful in 17s
v0.244.0: the backup page stops promising what it does not hold (R-537/R-538/R-536)
R-537 — the contents label is now PER TIER. One string computed from the app's
shape was rendered on all three tier rows; a Tier-1 unit has no file-copy step, so
for the four class-A apps it was claiming „Adatok" for files it does not hold.

R-538 — a unit restore REFUSES before anything is touched when the unit cannot
return the app's drive-side files, and names the route that can. It runs before the
stack is stopped because the measured harm included the app's own wastebasket going
unreachable, which still held every byte.

R-536 — „Alkalmazás telepítve" moved from the deploy's acceptance to its completion,
with app_deploy_started and app_deploy_failed as the honest pair.

Each fix red-proofed: seen failing with its own sentence, passing when restored.
Requires hub v0.116.0 for the two new event types. MinAgent unchanged (0.131.0).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-16 16:55:55 +02:00

3.5 KiB

REPORT — controller v0.244.0: the backup page stops promising what it does not hold

2026-09-16. Three defects the 2026-09-16 drill measured on a fresh box, all in the same family: the product said a thing that was not true about a customer's data.

What shipped

R-537 — the label is now per tier. BackupContents was one string, computed from the app's shape (HasHDDData || HasVolumeData → "Adatok") and rendered on the Tier-1, Tier-2 and Tier-3 rows alike. One string cannot be true for three tiers that capture different things: a Tier-1 unit holds compose

  • app.yaml + DB dumps + volume tars and has no file-copy step at all (CaptureRecoveryUnit; RecoveryManifest has no field for one), so for the four class-A apps the customer's own files are carried by Tier 2 and Tier 3 and by nothing else. The row now carries Tier1Contents, Tier23Contents and DriveFilesNote, and the template renders the right one per row.

R-538 — the restore refuses instead of lying. RestoreFromRecoveryUnitAt now returns *ErrUnitLacksFileLegs before the lock, before the stack is stopped and before any volume is replaced, when the app declares drive-side file legs the unit cannot hold. The web handler turns that into a Hungarian sentence naming the route that CAN return the files — the off-site wizard's „Teljes visszaállítás (fájlok + adatbázis)", or the second drive's „Fájlok visszaállítása" — and says plainly when no copy exists. UnitRestoreOptions{AcceptMissingFiles} is the explicit, separately worded second step; it is a per-call argument and never a field on the Manager.

Why the refusal runs that early: in the measured failure the replayed database also stopped referencing the app's own wastebasket, which still held every byte on the drive. A refusal that has already stopped the app would have destroyed the customer's last route while declining to help.

R-536 — „telepítve" now means installed. The API emits app_deploy_started beside its 202; app_deployed moved to the async path's own end via stacks.SetDeployDoneHook, and app_deploy_failed (warning) replaces the silence an interrupted install used to get. The accept-time app.yaml is deliberately kept on failure: it is the crash-safe record written with Deployed:false, it holds the settings the customer typed, and the state every surface reads is not_deployed.

Also folded in: the pending „0 B" whole-system tile fix (R-517 follow-up).

Red-proofs — each seen failing, then passing

fix break what failed
R-537 label restore the app-shaped label „the Tier-1 label claims it holds the app's data: Konfig + Adatok"
R-538 refusal disable the guard „a restore that cannot return the files must refuse; got err=<nil>"
R-536 accept-time put NotifyAppDeployed back beside the 202 „the deploy handler announces an INSTALLED app at accept time"
R-536 completion remove the success-path hook „the deploy ended and nothing was told about it"

Each test also carries a negative control: an app whose data really is in the captured volumes keeps its „Adatok" and is not refused.

Gates

go build ./... && go vet ./... && go test ./... — green. controller_gates.py --fast — all 15 OK.

Requires

Hub v0.116.0, which registers app_deploy_started / app_deploy_failed in allowedEventTypes and customerMessages. Against an older hub those two POSTs 400 and the events are simply absent; app_deployed keeps working. MinAgent unchanged at 0.131.0.