diff --git a/REPORT.md b/REPORT.md index 52806a0..b2d1d84 100644 --- a/REPORT.md +++ b/REPORT.md @@ -1,122 +1,88 @@ -# REPORT — v0.169.0/.1: Disk-health card + degradation notification ("Lemezek állapota") +# REPORT — v0.170.0: root→Indítópult; gofmt normalization; stale-note; gate-denial check; SMART spike -Part of the disk-health train (agent v0.94.0 + controller v0.169.0/.1 + hub v0.73.1). Appended above -the previous report (kept below). +**Date:** 2026-07-25 · **REPORT overwritten** (the standing rule; the prior append was a sanctioned one-off). -**Baselines:** controller `e164fef` (v0.168.0) → `c97975c` (v0.169.0) → `dbf6313` (v0.169.1). Clean at start. - -**What shipped:** -- `agentapi`: `SmartSummary` extended to the full counter set; `DiskInfo.Smart *SmartSummary`; pure - `DiskVerdictFor` (shared by card + check) + `Label` + `DegradedAttributes`. Verdicts: FAILING→Hiba; - PASSED+any(reallocated/pending/offline/critical/media >0 or percentage_used ≥90)→Figyelmeztetés; - PASSED clean→Rendben; nil/UNKNOWN→Nincs adat (never alarms). -- `web`: dashboard "Lemezek állapota" card (physical disks only — pbs/lvm/nfs/cifs excluded in v0.169.1) - via a 60s /disks TTL cache; unreachable agent → "Nincs adat", page never blocks. 6h `disk-health-check` - emits `disk_health_degraded` on a degradation only (in-memory baseline; first run silent; recovery/ - UNKNOWN never notify; multi-attr → one event). `notify.NotifyDiskHealthDegraded` (warn/critical). - **No global banner** (deliberate). - -**Tests + red-proofs (all recorded):** verdict table (red-proof: ≥90→>90 → boundary FAIL); notifier -emit (type/severity/subject); check first-run-silent (red-proof: disable the guard → first run notifies -FAIL); degradation-once; recovery-silent; UNKNOWN-excluded; FAILING→critical; nil-smart card graceful; -TTL cache. Full controller suite: 27 packages pass, 0 fail; build + vet clean; template/emoji/mojibake -gates OK. - -**Deploy + live validation (guest 9201):** built + deployed 0.169.0 → Up (healthy); dashboard rendered -the card. **§13(2):** first render showed 4 rows (pbs/lvm carried a default UNKNOWN SMART) → shipped -**v0.169.1** to exclude logical/network types; re-verified the card now shows exactly **2 physical rows** -(`local`, USB), both "Nincs adat" — the correct real verdict on the virtualized demo hardware. -**§13(3) notification path** (proven with the hub, see hub REPORT): a `disk_health_degraded` POST — the -exact wire call `notify.PushEvent` makes — was **400-rejected by hub v0.73.0** and **200-accepted + -emailed by hub v0.73.1**. Method: direct endpoint POST via curl (no fixture code committed → nothing to -revert; the demo's real disks stay "Nincs adat" so normal operation is quiet). - -**Awaiting operator:** browser visual check of the card layout (rendered HTML strings confirmed). A real -FAILING/Figyelmeztetés verdict can't occur on the virtualized demo hardware (no real SMART) — the verdict -logic + transitions are covered by unit tests + the live event-pipeline proof. - ---- - -# REPORT — v0.168.0: Customer-configurable backup window ("Mentési időablak") - -**Date:** 2026-07-24 · **Deployed & verified live on guest 9201; box left configured at 02:30.** - -## 1. Baseline +## 1. Baselines | Repo | `main` @ start | version | → | |------|----------------|---------|---| -| felhom-controller | `e33c1ae` | v0.167.1 | **v0.168.0** (committed `82c67e3`) | +| felhom-controller | `0a582ea` | v0.169.1 | v0.170.0 | +| felhom.eu | `e49f20f` | — | docs-only | -Verified against live Gitea at task start (HEAD == origin == live). No agent coupling; MinAgent unchanged. +Re-verified clean at start. -## 2. What shipped -ONE customer setting — **"Mentési időablak kezdete"** (window start W) — drives every nightly leg at -FIXED, never-stored offsets so misordering is impossible: DB dump at **W**, tier-2 at **W+60m**, off-box -at **W+105m** (wrap-safe). The whole-guest (agent PBS/vzdump) cycle is gated to **[W+2h, W+6h)** with a -safety valve. Precedence: settings > controller.yaml `db_dump_schedule` > "02:30". Changes apply -**without restart**. +## 2. Commits (feature commit NOT squashed with the gofmt commit — Scenario B) +- **`2487681`** — `style: gofmt normalization — no logic changes` (commit 1, style-only). +- **`9cc8424`** — `v0.170.0: root → Indítópult (302); Vezérlőpult at /dashboard; CLAUDE.md stale-note fix` (commit 2, feature). +- **felhom.eu `770ee5a`** — the SMART-coverage spike doc (+ nothing else). -## 3. Files -- **New** `internal/backupwindow/` (backupwindow.go + _test.go) — pure time math: `ParseHHMM`/`FmtHHMM`/ - `LegTimes`/`GateWindow`/`EffectiveWindow`/`Valid`; offsets are constants (derived, never stored). -- `internal/scheduler/scheduler.go` (+ new _test.go) — `UpdateDaily(name,timeStr) bool`, per-daily-job - buffered `resched` chan, a `case <-job.resched` in `runDailyJob`, Schedule read under the mutex. -- `internal/settings/settings.go` — `BackupWindowStart` field + Get/Set. -- `internal/quiesce/quiesce.go` (+ new quiesce_window_test.go; fakes updated in quiesce_test.go / - quiesce_8b2_test.go) — `Backend.Due` now returns the backup age; `Options.WindowStartFn`/`Cadence`; - `scheduledRunAllowed` predicate + Budapest helper; gate on the scheduled path in `runOnce`. -- `internal/web/backup_handlers.go` (+ new backup_window_test.go), `handlers.go`, `server.go` route, - `templates/backups.html` — the "Mentési időablak" card + POST `/backups/window`. -- `cmd/controller/main.go` — the three Daily legs + backup-cache + initial-cache + quiesce loop wired - from the effective window. -- Docs: `CHANGELOG.md`, `CONTEXT.md`, `controller/README.md`, `REUSE.md` (UpdateDaily + backupwindow + - 3rd Budapest-loader duplication note), this `REPORT.md`. +## 3. Part 1 — Root → Indítópult +`server.go` route split: `"/"` → `http.Redirect(…"/launcher", 302)`; `"/dashboard"` keeps the handler. +`layout.html`: Vezérlőpult `href="/dashboard"` (topbar logo keeps `/` → redirects to launcher). +`auth.go` unchanged (post-login default `/` flows through the redirect to the launcher — verified). +Two dashboard-card tests repointed `/`→`/dashboard`. +- Tests (all pass): `TestRoot_RedirectsToLauncher` (302 + `Location: /launcher` + no launcher body at `/`), + `TestDashboard_ServedAtDashboardURL` (200), `TestNav_LauncherAndDashboardHrefsAndActive`. +- **Red-proof (recorded):** fold `/` back into the dashboard case → `GET / status = 200, want 302` — FAIL, then restored. -> Note: a stray `gofmt -w internal/ cmd/` reformatted ~46 unrelated (non-gofmt-clean) files; all were -> restored to `origin/main` so the commit is surgical — only the files above are in the diff. +## 4. Part 2 — gofmt normalization (46 files) +`gofmt -w` across the controller tree; `gofmt -l` now **empty**. Pure formatting: whitespace + +optional-semicolon removal in reflowed inline closures. **One caveat handled:** this system's Go-1.26 +`gofmt` doc-comment reformatter rewrites `''`→`”` in doc comments; it hit exactly one comment +(`app_export_domain_test.go`, "yields ''") — reworded to "yields the empty string" so the result is +gofmt-clean without a garbled quote. Build+vet+test green before and after; separate prior commit. -## 4. Tests + red-proofs (all recorded) -`go build ./... && go vet ./... && go test ./...` — **27 packages pass, 0 fail.** Template/design gates -(template_id / emoji / mojibake / native-confirm) all OK. +## 5. Part 3 — CLAUDE.md stale note +Corrected the "vacation — agent DOWN at a remote site" block: felhom-pve is back on the home LAN, the +agent is **up** (`localapi` binds `192.168.0.162:8443`, `active`, capabilities 68/68), Tailscale alias +still available. (Inside the feature commit.) -| Group | Test(s) | Red-proof (mutate → FAIL → restore) | -|-------|---------|--------------------------------------| -| A | `LegTimes` (02:30/23:30/22:00/00:00, wrap), `LegTimes_InvalidRejected`, `GateWindow` | drop the FmtHHMM modulo → `LegTimes("23:30")` yields "24:30"/"25:15" → **FAIL confirmed** | -| B | `EffectiveWindow` precedence table (settings>yaml>"02:30", corrupt falls through) | — | -| C | `UpdateDaily_MutatesAndSignals`, `_UnknownAndInvalid`, `_GoroutineConsumesReschedule` | remove `case <-job.resched` → signal stays buffered → immediacy test **FAIL confirmed** | -| D | `scheduledRunAllowed` truth table (inside/boundary/outside/valve/wrap/nil-age) + Loop integration (defer outside / run inside / valve runs / **manual TriggerNow never gated**) | invert the valve `>`→`<` → starving-box + no-valve cases **FAIL confirmed** | -| E | `BackupWindowSave_Valid` (settings + 3× UpdateDaily + flash), `_Invalid` (nothing stored + error flash) | skip the `Valid()` check → invalid value gets stored → **FAIL confirmed** | +## 6. Green gates + build/deploy +`go build ./... && go vet ./... && go test ./...` — **27 packages pass, 0 fail**; template/emoji/mojibake +gates OK. Built `felhom-controller:0.170.0`, deployed to guest 9201 → **Up (healthy)**, +`Controller elindult (0.170.0)`. -Existing quiesce/scheduler/web suites still pass unchanged. +**Live (authed curl to `172.17.0.2:8080`, `Host: felhom.demo-felhom.eu`, login 302):** +- `GET /` → **302 → /launcher**. +- `GET /dashboard` → **200**, renders `