9d05fa5c35
MinAgent: 0.81.0 (unchanged). Controller-only; no agent-API change, no backup-engine behavior change. Fixes the self-contradicting /backups page (v0.120.0 live): - Remove the dead "Részletek" card (redundant; kills never-set Tier2DriveGroups/ ResticPassword fields + restic-pw element + toggleTier/toggleResticPw/copyResticPw JS). - Per-app "3. mentés" row shows real off-box state via pure tier3State (unconfigured/off/escrow_pending/active) — "Hamarosan" placeholder gone. - SQLite-honest DB messaging via pure dbSectionState (dumps/pending/embedded). - Populate Tier1LastRun/Tier1LastStatus from ListRestorePoints; Tier-1/Tier-2 labels via timeAgoStr (relative), confirm() dialog keeps raw timestamp. - Terminology split: "Távoli mentés (3. mentés)" (off-box, +#offbox-section anchor) vs "Távoli rendszermentés" (PBS whole-CT). - Deploy page: add "Mentési beállítások →" link. +9 internal/web tests (pure helper tables + buildAppBackupRows wiring + template renders), 4 companion red-proofs run→fail→revert.
80 lines
5.4 KiB
Markdown
80 lines
5.4 KiB
Markdown
# REPORT — v0.121.0: backups page truth pass
|
||
|
||
**Date:** 2026-07-12 · **Version:** controller v0.121.0 (from v0.120.0) · **MinAgent:** 0.81.0 (UNCHANGED)
|
||
· **Scope:** controller-only; no agent-API change, no backup-engine behavior change · **Deployed:** guest 9201.
|
||
|
||
**Confirmed baseline:** `felhom-controller` @ `92d670e8a6` (main), v0.120.0 → v0.121.0.
|
||
|
||
## Problem
|
||
|
||
On the live demo (`/backups`, v0.120.0) the page contradicted itself: a dead "Részletek" card claimed
|
||
"Nincs 2. szintű mentés konfigurálva" (the never-set `.Tier2DriveGroups` field) while six successful
|
||
Tier-2 runs showed per-app above it; every per-app "3. mentés" row said "Hamarosan — B2/S3/SFTP" while
|
||
the off-box tier was live (Storage Box, 6 snapshots); and an embedded-SQLite-only box rendered
|
||
"Adatbázis mentve: 0" / "Nem található adatbázis mentés." as if backups were failing.
|
||
|
||
## What shipped
|
||
|
||
1. **Dead "Részletek" card removed** — operator-approved as redundant (per-app rows + Adatbázisok
|
||
section carry the truth). Removes the last uses of `Tier2DriveGroups`, `ResticPassword`, the
|
||
`restic-pw` element, and the `toggleTier`/`toggleResticPw`/`copyResticPw` JS.
|
||
2. **Per-app "3. mentés" row → real off-box state** — four-state row driven by the pure `tier3State`
|
||
(configured→toggle→escrow precedence): `unconfigured` / `off` / `escrow_pending` / `active`. Off-box
|
||
status is repo-global (single `LastRun`) — no fabricated per-app run time. "hamarosan" gone.
|
||
3. **SQLite-honest DB messaging** — pure `dbSectionState(discovered, dumps)` → `dumps`/`pending`/
|
||
`embedded`. Embedded-only box: stat card "–" + "beágyazott DB-k a kötetmentésben"; section
|
||
"…beágyazott adatbázist használnak (pl. SQLite)…". Discovered-not-dumped: "…az első ütemezett mentés
|
||
éjjel fut le."
|
||
4. **Dead/raw display fields fixed** — `Tier1LastRun`/`Tier1LastStatus` populated from
|
||
`ListRestorePoints` (correct per-drive resolution; no time for unit-less apps); Tier-1/Tier-2 labels
|
||
via `timeAgoStr` (relative), confirm() dialog keeps the precise timestamp.
|
||
5. **Terminology split** — off-box section retitled "Távoli mentés (3. mentés) — titkosított, offsite"
|
||
(+ `#offbox-section` anchor); whole-guest PBS stat card relabeled "Távoli rendszermentés".
|
||
6. **Deploy page** — app backup card gains "Mentési beállítások →" → `/stacks/<name>/backup`.
|
||
|
||
## Files
|
||
|
||
- **Created:** `controller/internal/web/backup_page_state.go` (pure `dbSectionState`, `tier3State`);
|
||
`controller/internal/web/backup_page_state_test.go` (9 tests).
|
||
- **Modified:** `controller/internal/web/handlers.go` (`AppBackupRow` +`OffboxEnabled`/`Tier3State`;
|
||
`buildAppBackupRows` Tier-1 + Tier-3 plumbing; `backupsHandler` `DBSectionState`);
|
||
`controller/internal/web/templates/backups.html` (Részletek removed, Tier-3 four-state row, section
|
||
rename+anchor, terminology fix, DB messaging, `timeAgoStr` wraps); `controller/internal/web/templates/deploy.html`
|
||
(settings link); `CHANGELOG.md`, `REPORT.md`, `CONTEXT.md`, `controller/README.md`.
|
||
|
||
## Tests
|
||
|
||
- **New (9, all green):** `TestDBSectionState` (table), `TestTier3State` (table, all 4 states +
|
||
precedence), `TestBuildAppBackupRows_OffboxMapping` (Scenario A), `_EscrowPendingPrecedence`
|
||
(Scenario B), `_Tier1FromRestorePoints` (Scenario D — unit→RFC3339, no-unit→""),
|
||
`TestBackupsTemplate_Tier3Live` (Scenario A + removal assertions), `_Tier3EscrowPending` (Scenario B),
|
||
`_DBMessaging` (Scenario C embedded/pending), `_Tier2RelativeTime` (Scenario D).
|
||
- **Test count (internal/web):** 108 → 117 test funcs.
|
||
- **Companion red-proofs (run → FAIL → revert), all verified:**
|
||
1. Re-insert "hamarosan elérhető" into the rendered Tier-3 `off` block → `TestBackupsTemplate_Tier3Live`
|
||
FAILED on the no-"hamarosan" assertion → reverted. ✓
|
||
2. Hardcode `row.OffboxEnabled = false` in `buildAppBackupRows` → `TestBuildAppBackupRows_OffboxMapping`
|
||
FAILED (calibre OffboxEnabled:false, Tier3State:off) → reverted. ✓
|
||
3. `dbSectionState` drops the `discovered` branch → `TestDBSectionState` FAILED on `(2,0)` want "pending"
|
||
→ reverted. ✓
|
||
4. Drop the `row.Tier1LastRun = pts[0].Time` assignment → `TestBuildAppBackupRows_Tier1FromRestorePoints`
|
||
FAILED (hasunit Tier1LastRun "") → reverted. ✓
|
||
- **Green gate:** `go build ./...` + `go vet ./internal/web/` + `go test ./internal/web/` all green.
|
||
Template gates `template_id_gate.py` + `emoji_gate.py` OK. (Pre-existing, unrelated: `internal/backup`
|
||
`TestDumpAppVolumes_*` fail in this environment — docker-dependent; confirmed failing on the clean
|
||
`92d670e` baseline too, and I did not touch `internal/backup`.)
|
||
|
||
## Deploy & live validation
|
||
|
||
- **Deployed:** guest 9201 — _see "Live validation" below (filled after deploy)._
|
||
|
||
## Observations (documented, NOT acted on)
|
||
|
||
- **Orphaned style.css classes** left by the Részletek removal (not cleaned per task §9.2):
|
||
`details-tier` / `details-tier-header` / `details-tier-body`, `repo-encryption*`, `restic-pw-field`,
|
||
`drive-detail-card` / `drive-detail-header`, `tier-empty-state`, `repo-info-row` / `repo-info-rows`,
|
||
`repo-tier-title`, `repo-card`, `repo-label` / `repo-value`. Candidates for a later CSS sweep.
|
||
- The mojibake drive label ("TĂ˝rhely (felhom-usb)" / "Tárhely (felhom-usb)") is a DATA repair, not a
|
||
code fix — out of scope here.
|
||
- `felhom.eu/documentation/controller/backup-architecture.md` off-box refresh is a separate queued doc task.
|