From df7ad378f43a1244e17757edae6257b57b095113 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Mon, 13 Jul 2026 08:47:58 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20v0.123.0=20polish=20batch=20=E2=80=94?= =?UTF-8?q?=20CHANGELOG=20+=20REPORT=20+=20CONTEXT=20+=20REUSE=20(felhomCo?= =?UTF-8?q?nfirm=20pattern,=20new=20gates)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Claude-Session: https://claude.ai/code/session_01GzammAMzsJTgpQHqxwM2bC --- CHANGELOG.md | 35 +++++++++++++++++++ CONTEXT.md | 14 +++++++- REPORT.md | 97 ++++++++++++++++++++++++++++++---------------------- REUSE.md | 3 +- 4 files changed, 106 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46004eb..a3c7030 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,40 @@ ## Changelog +### v0.123.0 — polish batch: F-15 instant reset codes, F-11 inline confirms, Tier-3 "Távoli mentés" rename, zero-toggle honesty (2026-07-13) — MinAgent: 0.81.0 + +Four independent fixes from the take-two drill + operator review. Live-validated on the drill box +(qm 300 guest 9201) and demo 9201; hub v0.52.0 is the F-15 counterpart (an old hub's bare +reset-request response is a clean no-op — no coupling gate needed). + +- **F-15 instant reset codes** (`internal/web/claim.go`): `requestHubResetCode` now parses the + hub's reset-request RESPONSE (`{claim: {code_hash, generation, issued_at}}`, hub ≥0.52.0) and + applies it through the SAME generation-guarded consumer as the report ACK + (`report.ClaimSync.Reconcile`) — the emailed code works the moment it lands instead of after + the next ACK (~15 min; the take-two "Hibás vagy lejárt kód" failure). Replay/older-generation + responses can never downgrade the active hash (guard reused, not reimplemented). Live re-run of + the exact failure path: code applied 1 s after the request, accepted on first try. +- **F-11 inline confirms** (`layout.html` + templates): every native `confirm()` (an OS-modal + that freezes browser automation) replaced by the LIGHT inline two-step — `felhomConfirm(el, q, + onYes)` swaps the trigger in place to "kérdés + Igen/Mégse"; form buttons opt in via + `data-confirm="…"` (submitted with `requestSubmit`, so formaction/name-value survive). + Converted: offbox restore-to-verify, tier2 restore, whole-guest backup, app data migrate, + debug simulate-disconnect + DR trigger, deploy stale-data delete (keeps its DOUBLE + acknowledgement, chained inline). New gate `scripts/native_confirm_gate.py` (zero native + confirm/prompt in templates; red-proven). +- **Tier-3 rename** (`backups.html`, `offbox_handlers.go`, `backup/offbox.go`): customer-facing + "NAS-mentés" branding → **"Távoli mentés"** (the productized target is the Storage Box; the + tier concept is offsite). Manual-target form generalized to any SFTP target ("Cél címe (IP + vagy hosztnév — NAS vagy SFTP-kiszolgáló)", "Tároló útvonala a célgépen"). The "Hálózati + tárhely" NAS network-storage feature keeps its device-truthful wording (different feature). + Python sweep (multibyte rule) + committed gate `scripts/offbox_rename_gate.py` (red-proven). +- **Zero-toggle honesty** (`backup/offbox.go`, `handlers.go`, `backups.html`): a configured + + escrowed offbox with ZERO toggled apps shows "Nincs távoli mentésre jelölt alkalmazás — jelölj + ki legalább egyet." on the toggle list, and a run in that state reports "Sikeres — nincs + mentésre jelölt alkalmazás" via LastWarning instead of bare success (red-proven unit test). +- **Dev-box fix**: `atomicPromoteTar` fsyncs via an O_RDWR handle — read-only fsync is refused on + Windows, which kept the two F7 atomic-dump tests permanently red on the dev box (Linux + behavior unchanged). + ### v0.122.0 — customer-claim password gate (closes DRILL-day0-vm F-4/F-5) (2026-07-12) — MinAgent: 0.81.0 The customer sets + OWNS the dashboard password; the old "no password → open dashboard" is gone. diff --git a/CONTEXT.md b/CONTEXT.md index 260dabb..4a5e435 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -7,7 +7,19 @@ > > Ask Claude Code: "Please update CONTEXT.md with what we did today" -Last updated: 2026-07-12 (v0.122.0 — customer-claim password gate) +Last updated: 2026-07-13 (v0.123.0 — polish batch) + +> **2026-07-13 — v0.123.0: POLISH BATCH (take-two F-15/F-11 + rename + zero-toggle). MinAgent +> 0.81.0 unchanged; floor 0.122 unchanged. Requires hub v0.52.0 for F-15 (old hub = clean no-op).** +> (1) F-15: the reset-request RESPONSE carries the rotated code hash, applied via the ACK's +> generation-guarded ClaimSync — emailed codes work immediately (live: 1 s, first-try accept). +> (2) F-11: zero native `confirm()` — `felhomConfirm`/`data-confirm` inline Igen/Mégse (layout.html); +> gate `scripts/native_confirm_gate.py`. (3) Tier-3 customer branding is **"Távoli mentés"** +> (NAS-mentés gone; manual form generalized to any SFTP target; gate +> `scripts/offbox_rename_gate.py`; "Hálózati tárhely" feature untouched). (4) Zero-toggle honesty: +> hint + "Sikeres — nincs mentésre jelölt alkalmazás" run copy. Also: `atomicPromoteTar` O_RDWR +> fsync (Windows dev-box green gate was permanently red). Deployed drill qm300 + demo 9201. +> NOT started (separate queued task, operator fork pending): offbox `managed_by` coexistence. > **2026-07-12 — v0.122.0: CUSTOMER-CLAIM PASSWORD GATE (closes DRILL-day0-vm F-4/F-5). MinAgent > 0.81.0 unchanged. Requires hub v0.50.0.** The dashboard password is CUSTOMER-OWNED via a one-time diff --git a/REPORT.md b/REPORT.md index 95285e6..2d452c1 100644 --- a/REPORT.md +++ b/REPORT.md @@ -1,49 +1,64 @@ -# REPORT — v0.122.0: customer-claim password gate (closes DRILL-day0-vm F-4/F-5) +# REPORT — v0.123.0: polish batch (F-15 instant reset codes, F-11 inline confirms, "Távoli mentés" rename, zero-toggle honesty) -**Date:** 2026-07-12 · **Version:** controller v0.122.0 (from v0.121.0) · **MinAgent:** 0.81.0 (UNCHANGED) · **Requires:** hub v0.50.0 +**Date:** 2026-07-13 · **Version:** controller v0.123.0 (from v0.122.0) · **MinAgent:** 0.81.0 (UNCHANGED) · **Companion:** hub v0.52.0 (F-15 response; old hub = clean no-op) · **Floor:** 0.122 UNCHANGED (no raise in this task) -## What shipped +## What shipped (commits `b4e0a19`, `40b5304`, `8987ce0`, `a00afcc`, `b482860`) -The dashboard password is now **customer-owned**, set through a one-time claim code the hub emails -to the registered address. The old "no password → open dashboard" default is gone: a fresh box -(claim-code hash delivered, no password) serves ONLY the claim page — every other route answers the -claim page (`302 → /claim`) or `401` (API). This closes the DRILL-day0-vm F-4 exposure (every Day-0 -dashboard was open on the internet, with the full deploy API = RCE-equivalent) and F-5 (the -unauthenticated geo toggle is now behind the gate too). +1. **F-15 — reset code works the moment the email lands** (`internal/web/claim.go`). The + reset-request POST now reads the hub's response (`claim {code_hash, generation, issued_at}`, + hub ≥0.52.0) and applies it through the SAME generation-guarded consumer as the report ACK + (`report.ClaimSync.Reconcile` — one consumer, two feeds). Replayed/older generations can never + downgrade the active hash; a legacy hub's bare `{"status":"ok"}` is a no-op. +2. **F-11 — inline confirms** (`layout.html` helper + 7 call sites). `felhomConfirm(el, q, onYes)` + swaps the trigger IN PLACE to "kérdés + Igen/Mégse"; form buttons opt in with `data-confirm` + (delegated listener + `requestSubmit`). Zero native `confirm()`/`prompt()` remain — + enforced by the new committed gate `controller/scripts/native_confirm_gate.py`. The deploy + stale-data delete keeps its double acknowledgement (two chained inline steps). +3. **Tier-3 rename** — customer-facing "NAS-mentés" → **"Távoli mentés"** across `backups.html`, + `offbox_handlers.go` flashes, and the `backup/offbox.go` quota copy; the manual-target form is + generalized to any SFTP target. Executed as a count-guarded python sweep (multibyte rule); + enforced by `controller/scripts/offbox_rename_gate.py`. "Hálózati tárhely" (NAS network + storage) is a different feature and was deliberately untouched. +4. **Zero-toggle honesty** — configured+escrowed offbox with no app selected: muted hint + "Nincs távoli mentésre jelölt alkalmazás — jelölj ki legalább egyet." + the run reports + "Sikeres — nincs mentésre jelölt alkalmazás" (LastWarning; status stays ok). +5. **Dev-box green-gate fix** (`backup.go` `atomicPromoteTar`): fsync via O_RDWR — read-only + fsync is refused on Windows; the two F7 atomic-dump tests were permanently red on the dev box + since CAMPAIGN-3 (Linux unchanged). -- **`internal/web/claim.go`** — `claimGateActive()` / `effectiveClaimCode()` (ACK-cached settings - beats the config bake by generation), the claim page (`GET /claim`), submit (`POST /claim`: - verify code → set own password via `SetPasswordHash` → mark claimed → consume generation → - session), and `POST /claim/request-new-code` (forwards to the hub reset-request). Code checks: - bcrypt match AND generation-not-consumed (single-use) AND ≤ 72 h. Per-source + global limiter (5 - → 15-min lockout) raising the allowlisted `claim_lockout` event. Pre-auth CSRF = HMAC over - `web.session_secret` (fixes CTRL-007). Min password 12. -- **Gate wiring** (`auth.go`/`csrf.go`/`server.go`/`cmd`): gate atop `RequireAuth`; a SET password - disables it (auth wins — claimed boxes never regress). `/claim*` + `/static/*` reachable pre-auth. - Legacy-open (no password, no hash) → red transition banner (`layout.html`). Login "Elfelejtett - jelszó" link. -- **`internal/report/claim_sync.go`** — caches the ACK `claim {hash, generation}` into settings.json - idempotently by generation (one-way: newer advances; same/older/nil never rewrites; hub outage - never clears). Report carries `claimed` (set-only). Hub bakes `web.claim_code_*` for gate-from- - first-boot. -- **`--print-reset-code`** root escape hatch (one-time local code above cached/baked/consumed gen). +## Tests + red-proofs (all run → FAIL → restored) -## Tests + red-proofs +- `TestResetRequest_ResponseHashAppliedImmediately` (+ generation-guard + legacy-hub no-op + tests). **Red-proof:** response handling disabled → FAIL `gen=1 hash-is-new=false`. +- `native_confirm_gate.py` **red-proof:** one `onsubmit="return confirm('redproof')"` + reintroduced → exit 1; restored → 0. +- `offbox_rename_gate.py` **red-proof:** one 'A NAS-mentés…' flash reintroduced → exit 1. +- `TestOffbox_ZeroToggledRunReportsEmptiness` (+ covered-run negative). **Red-proof:** emptiness + branch disabled → FAIL `LastWarning = ""`. +- Full green gate (build+vet+test, all packages) + template_id/emoji/native_confirm/offbox_rename + gates green before every commit. -- Gate-coverage signature test (`TestClaimGate_EveryRouteGated`): every route → claim page/401, a - deploy POST reaches no handler. Plus happy-path / reuse-refused / expired / lockout+window-reopen - (fake clock), legacy-open vs password-set, claim-sync idempotence. -- **Four §10 red-proofs proven** (mutate → FAIL → revert → green): (1) gate skip-line, (2) single-use - generation — hub `RotateClaimCode` bump AND controller consumed-generation check, (3) reset - non-DoS (clearing claimed → fail), (4) rate-limiter (both scopes disabled → fail). -- Green gate: `go build ./... && go vet ./...` clean; all touched packages pass. Pre-existing - env-sensitive `internal/backup` volume-dump failures are unrelated (fail identically on the clean - baseline — no tar/zstd toolchain on the dev box). +## Live validation (drill box qm300/guest 9201 + demo 9201, controller 0.123.0 both, healthy) -## Live validation (drill guest 9201 on qm 300, controller 0.122.0, pre-floor) +- **F-15 exact-failure-path re-run:** "Visszaállító kód kérése" on felhom.enkisfelhom.hu/claim → + controller log `claim-sync: hub claim code cached (generation 3)` **1 second** after the POST → + Viktor entered the emailed code: **accepted immediately, first try** (take-two failure closed). +- **F-11 automation-completes proof:** offbox restore-to-verify driven END-TO-END by browser + automation — inline strip rendered, Igen → restore ran ("A távoli visszaállítás elindult…", + banner "Távoli visszaállítás folyamatban: actualbudget…"), zero freezing. +- **Rename:** /backups renders with ZERO 'NAS-mentés' strings (screenshots in session record); + only the allowlisted "saját NAS vagy Felhom offsite tárhely" intro mention remains. +- **Zero-toggle:** untoggled ActualBudget → hint appeared → run → "Sikeres — nincs mentésre + jelölt alkalmazás" + status Rendben → re-toggled (box left as found). -Deployed 0.122.0 → the ACK delivered the claim hash → gate flipped ON within a report cycle. Proven -via the REAL Cloudflare edge (`curl --resolve`): `/` → 302 → "A szerver beállítása" claim page; -`/claim` → 200; `/api/host-metrics` → 401. Controller log: `claim-sync: hub claim code cached -(generation 1)`. Hub log: claim code emailed to the registered address of demo-vm-felhom. The -customer-side claim + reset + the floor raise are the operator's supervised steps. +## Observations + +- The queued **customer-target coexistence** task (`managed_by` on OffboxTarget) remains a + SEPARATE task with a pending operator fork — not started, per spec. +- NAS-string inventory beyond backups.html: the two customer-facing quota strings in + `internal/backup/offbox.go` (renamed here); everything else is the distinct "Hálózati tárhely" + feature or English comments/tests (untouched by design). +- Windows-only pre-existing failure found+fixed: read-only-handle fsync in `atomicPromoteTar` + (the F7 tests were red on the dev box, green on Linux — a silent hole in the local green gate). +- Browser-automation note: `find`-ref clicks on plain submit buttons focused but did not submit + (coordinate clicks did); the data-confirm buttons worked via refs. Cosmetic, tooling-side. diff --git a/REUSE.md b/REUSE.md index 2630871..c404ac2 100644 --- a/REUSE.md +++ b/REUSE.md @@ -207,7 +207,8 @@ Cross-repo edges: - **New REST endpoint**: path dispatch in `Router.ServeHTTP` (controller/internal/api/router.go); use `writeJSON` + `limitBody`. - **New background job**: `sched.Every`/`sched.Daily` registration block in controller/cmd/controller/main.go. - **New template function**: `Server.templateFuncMap` (controller/internal/web/funcmap.go) — obey v2 state-suffix vocabulary. -- **New page/nav item**: `baseData` + sidebar in controller/internal/web/templates/ (nested sub-links pattern `.nav-links-nested`); must pass `controller/scripts/template_id_gate.py` + `controller/scripts/emoji_gate.py`. +- **New page/nav item**: `baseData` + sidebar in controller/internal/web/templates/ (nested sub-links pattern `.nav-links-nested`); must pass `controller/scripts/template_id_gate.py` + `controller/scripts/emoji_gate.py` + `controller/scripts/native_confirm_gate.py` + `controller/scripts/offbox_rename_gate.py`. +- **Consequential-action confirm (LIGHT)**: `felhomConfirm(el, question, onYes)` in layout.html (v0.123.0) — the trigger swaps in place to "kérdés + Igen/Mégse"; form buttons opt in with `data-confirm="…"` (delegated listener, `requestSubmit` keeps formaction/name-value). NEVER native `confirm()`/`prompt()` (OS-modals freeze browser automation — drill F-11; `native_confirm_gate.py` enforces). Heavy destructive flows keep the `.confirm-overlay` `openDialog` pattern. - **New hub event**: typed `Notify*` wrapper on Notifier + hub allowlist entry (cross-repo). - **New app integration**: `integrations.Manager.RegisterHandler` with `IntegrationKey(provider, target)`. - **New startup self-check**: append check fn in `selftest.Run` (controller/internal/selftest/selftest.go).