From eb3bf4a391fa4455d3449b95b97d737dc5e45fff Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Tue, 14 Jul 2026 09:55:53 +0200 Subject: [PATCH] @ docs: REPORT covers v0.129.0 (F-B/F-A/F-C fixes, red-proofs, both guests live 0.129.0) Claude-Session: https://claude.ai/code/session_01LbMm4T7Ayzs1unB9pN6Uqd @ --- REPORT.md | 129 +++++++++++++++++++----------------------------------- 1 file changed, 46 insertions(+), 83 deletions(-) diff --git a/REPORT.md b/REPORT.md index afd72ff..6ac3970 100644 --- a/REPORT.md +++ b/REPORT.md @@ -1,95 +1,58 @@ -# REPORT — demo storage hygiene: USB class-badge suppression (v0.128.1) + legacy PVE dir-storage retirement +# REPORT — CAMPAIGN-4 fixes: rate-limiter key (F-B) + volume-blind estimate (F-A) + no-op claim status (F-C) -**Date:** 2026-07-13 · **Version:** controller v0.128.1 (commit `d752f15` on `main`) · Host op on -demo-felhom PVE (192.168.0.162), config-level only — no data moved or deleted. -**Sequencing note:** the TASK was numbered v0.127.3 and sequenced BEFORE the .fab upload task, but -v0.127.3 (escrow reveal copy) and v0.128.0 (upload) had already shipped — Part 1 ships as -**v0.128.1**; content unaffected. Baseline at start: `61c1391` (v0.128.0 REPORT), live Gitea == -local. +**Date:** 2026-07-14 · **Version:** controller **v0.129.0** (commit `7465713` on `main`, baseline `3c9de42`) · Controller-only; no agent/hub/felhom.eu change. -## Part 1 — controller: suppress the class badge for USB drives (ruling F5) +## Baselines (verified live at start) +- felhom-controller `main` @ `3c9de42` (docs commit on top of `d752f15`), v0.128.1 → v0.129.0. +- Demo guest 9201 was 0.128.1; drill guest 9201 was **0.128.0** (CAMPAIGN-4 DEV-2) — both brought to 0.129.0. -`storage.html` `classTag(d)`: `if(d.type==='usb') return '';` ahead of the class branches — one -guard covers both render sites (card badges L~324; metarow L~343, which additionally guards on -`d.class`). Non-USB storages keep the hint. **Hub-report `ClassHint` UNCHANGED** (UI-only -suppression). No existing test pinned the badge → new -`TestStorageTemplate_USBClassBadgeSuppressed` (renders the production template tree, asserts the -guard exists AND precedes the class branches). **Red-proof:** guard line removed → FAIL -`"classTag USB guard missing from the storage page"`; restored → PASS. Green gate: full module -build/vet/test clean; template gates (id/emoji/native-confirm) green. +## Files changed +- `controller/internal/web/claim.go` — `requestIP`→`clientIP` (net.SplitHostPort host, XFF first-hop, raw fallback); call sites updated. +- `controller/internal/web/auth.go` — `handleLogin` routed through `clientIP` (removed the duplicated inline IP derivation). +- `controller/internal/web/escrow_handlers.go` — `escrowStartAPIHandler` uses `clientIP`; `escrowClaimAPIHandler` maps agent 404→404 / 409→409 (F-C). +- `controller/internal/appexport/estimate.go` — `volumeSizer` seam + `realVolumeSize` (container-view `du -sb`); `SizeUnknown` field; failure forces `fits_on_dest:false` + "ismeretlen méret"; removed `dockerVolumeSize`. +- `controller/internal/appexport/export.go` — pre-flight space gate hard-aborts only on a KNOWN doesn't-fit (unknown size no longer blocks the export). +- Tests: `controller/internal/web/ratelimit_ip_test.go` (new), `controller/internal/appexport/estimate_volsize_test.go` (new), `controller/internal/web/escrow_wizard_test.go` (+3 subtests). +- `CHANGELOG.md` (v0.129.0), `controller/README.md` (anti-brute-force source-key note), this `REPORT.md`. -**Deployed:** image `0.128.1` → demo guest 9201, `Up (healthy)`. Drill guest skipped (task: -optional, no behavioral dependency). +## Per-commit +- `7465713` — v0.129.0 (all three fixes + tests + docs). One commit per the trunk-based rule. -## Part 2 — host op: retire `felhom-usb` + `felhom-flash` PVE dir storages +## Tests + red-proofs (all run → fail-on-revert → restore recorded) +**F-B (`ratelimit_ip_test.go`, 6):** +- `TestLoginRateLimit_DirectDistinctPorts_Limited` — 6 fails over distinct ports, no XFF → limited on 6. **PASS.** +- `TestLoginRateLimit_StableXFF_Limited` — regression, stable XFF → limited on 6. **PASS.** +- `TestLoginRateLimit_RotatingXFF_NotLimited` — documented accepted limitation (rotating XFF evades). **PASS.** +- `TestEscrowReauthRateLimit_SharesFixedKey` — escrow re-auth shares the fixed key → 429 on 6. **PASS.** +- `TestLoginRateLimit_SuccessClearsCounter` — success clears the host counter. **PASS.** +- `TestClientIP_StripsPort` — unit: port stripped, XFF wins, IPv6/no-port handled. **PASS.** +- **Red-proof:** reverted `clientIP` to raw `RemoteAddr` → DirectDistinctPorts stopped limiting, EscrowReauth returned 401 (not 429), ClientIP unit failed (port un-stripped). Restored → green. -### Gate evidence (all PASS) +**F-A (`estimate_volsize_test.go`, 3):** +- `TestEstimate_VolumeSize_RealNotZero` — injected 2 GiB → `DataSizeBytes=2 GiB`, GB-scale human (not 0/"3.6 KB"). **PASS.** +- `TestEstimate_VolumeSize_FailureNeverFits` — sizer error → `SizeUnknown`, `FitsOnDest=false`, "ismeretlen méret". **PASS.** +- `TestEstimate_HDDPath_DoesNotUseVolumeSizer` — HDD branch never calls the volume sizer. **PASS.** +- **Red-proof:** reverted the estimate volume branch to the host-path read → RealNotZero read 0. Restored → green. -**G1 — mount provenance:** both mounts are agent-owned systemd units, independent of the PVE -entries: -- `/mnt/felhom-usb` = `/dev/sdc1` (ext4) via `mnt-felhom\x2dusb.mount` — "`Managed by - felhom-agent`", `What=/dev/disk/by-uuid/da9e7089-cf8e-4617-adcb-a377743fae00`, - `WantedBy=multi-user.target`. -- `/mnt/felhom-flash` = `/dev/sdd1` (ext4) via `mnt-felhom\x2dflash.mount` — same shape, - `What=/dev/disk/by-uuid/81a26531-62d8-408d-812f-a178b1d35310`. -- `/etc/fstab`: no entries for either. The PVE `storage.cfg` blocks carried `is_mountpoint 1` - (checker, not owner) and no `mkdir`. +**F-C (`TestEscrowClaim_ProxySemantics` +3):** +- `no_active_ceremony_404_not_502` — agent 404 → clean 404 "Nincs aktív helyreállítási folyamat…". **PASS.** +- `conflict_409` — agent 409 → 409. **PASS.** +- `unreachable_stays_502` — status 0 → 502 (unchanged). **PASS.** +- `success` / `gone` (existing) still green. +- **Red-proof:** removed the 404 mapping → the no-ceremony claim returned 502. Restored → green. -**G2 — registry membership:** `/var/lib/felhom-agent/drive-intents.json` (read-only) lists both -UUIDs as `"enrolled"` (plus teszt_enroll's). Guest binds live under the drives tree: mp8 -`/mnt/felhom-drives` (no `backup=1`); `/mnt/felhom-drives/felhom-{usb,flash}` are `[/felhom-data]` -subdir mounts of the same devices (Model A). Controller settings register both stable paths -(`Tárhely (felhom-usb)` / `Tárhely (felhom-flash)`). +## Test counts / gate +Full module green gate: `go build ./... && go vet ./... && go test ./...` — **ALL GREEN** (all packages `ok`). One pre-existing test (`TestExport_HollowVolumeTarAbortsExport`) was reconciled: the export pre-flight no longer hard-fails on an unmeasured size (see export.go change). New tests: 9 top-level + 3 subtests, all red-proofed. -**G3 — zero references:** `grep -r 'felhom-usb\|felhom-flash' /etc/pve/` → only the two -`storage.cfg` blocks themselves + `/etc/pve/.rrd` metric rings (auto-generated stats, not config). -No jobs.cfg/vzdump/replication; both storages' `dump/` dirs EMPTY. No customer app on either -drive: the only stack referencing them is the protected infra FileBrowser, via the agent-owned -`/mnt/felhom-drives/...` bind chain — unaffected by the PVE entry. (Live re-verified, not from -the screenshot.) +## Deployed versions +- Image `gitea.dooplex.hu/admin/felhom-controller:0.129.0` (digest `sha256:957e0818…`), pushed from 180. +- **Demo guest 9201: 0.129.0, healthy.** **Drill guest 9201: 0.129.0, healthy** (was 0.128.0 — DEV-2 closed). -### storage.cfg blocks removed (before-state, verbatim) - -``` -dir: felhom-usb - path /mnt/felhom-usb - content backup - is_mountpoint 1 - -dir: felhom-flash - path /mnt/felhom-flash - content backup - is_mountpoint 1 -``` - -### Removal + verification - -Pre-removal marker files created under each drive's felhom-data namespace and confirmed readable -from the guest. Then `pvesm remove felhom-usb && pvesm remove felhom-flash` → OK. Verified in -order: -1. **Host mounts intact**, same sources: `/mnt/felhom-usb` = `/dev/sdc1`, `/mnt/felhom-flash` = - `/dev/sdd1`; drives-tree subdir mounts intact (`/dev/sdc1[/felhom-data]`, - `/dev/sdd1[/felhom-data]`). -2. **Guest binds intact**: both markers still readable from guest 9201 post-removal - (`retire-check-2026-07-13`); markers removed afterwards. -3. **Meghajtók data**: agent `GET /disks` (pinned local-API token, value never echoed) returns - both drives registry-sourced — `type: usb`, `role: user-data`, durable-ids intact, - `class: ""` (consistent with `teszt_enroll` and Part 1), mount+guest paths intact. -4. **storage.cfg clean**: zero `felhom-usb|felhom-flash` matches; `pvesm status` lists only - `local`, `local-lvm`, `felhom-pbs`, `felhom-offsite` — the untouchables all present and active. - -Post-op: controller `Up (healthy)` on 0.128.1; agent journal (last 10 min) free of -error/warn/detach — no false detach from the registry-sourced watchdog. +## Live verification +- **F-B (nice-to-have, run):** 6 direct wrong-password logins on the drill guest (loopback via `docker exec curl`, distinct ephemeral ports, no XFF) on live 0.129.0 → attempts 1–5 "Hibás jelszó", **attempt 6 "Túl sok sikertelen próbálkozás"**. Pre-fix (CAMPAIGN-4) this never limited. (Transiently locks 127.0.0.1 for 1 min — expected.) +- **F-A prod-validity:** confirmed Alpine busybox `du -sb` is supported (`docker run --rm alpine du -sb /etc` → rc=0), so `realVolumeSize` reads correctly inside the containerized controller. ## Observations - -- The guest-bind mounts are `[/felhom-data]` subdir mounts (Model A) — a marker written at - `/felhom-data/` on the host appears at the guest drive ROOT (`/mnt/felhom-drives//`). - First marker check looked one level too deep; corrected before the removal. -- `felhom-flash` still carries empty PVE-era skeleton dirs on-disk (`images/ private/ snippets/ - template/ dump/`) from a past content=all era; harmless, deliberately NOT cleaned (task §12: no - touching drive contents). -- The `/etc/pve/.rrd` stats ring keeps historical series for the removed storages; it's - append-only telemetry and stops updating on its own — not a reference. -- The demo node now matches the fresh-install storage shape: no legacy dir: storages; drives are - registry+units-sourced only. +- The `.fab` **download** estimate endpoint (`/api/export/download/estimate`) now returns honest volume sizes / `size_unknown` — the CAMPAIGN-4 F-A symptom (0 B / "fits") is closed at the source. +- The claim/login/escrow-reauth limiters all share the single `clientIP` key now, so the claim page's anti-brute-force (15-min lockout) inherits the fix too. +- Scope held: no captcha/lockout/persistence added, `loginMaxAttempts`/window untouched, XFF trust untouched (commented), export path + HDD estimate branch + 410/unreachable claim cases unchanged.