Commit Graph

674 Commits

Author SHA1 Message Date
admin 8967ba7cb4 C6B-F1 cause 2: .fab export mount discovery resolves the userdata convention
exportAdapter.GetStackHDDMounts now returns stacks.ExportDataMounts — the
${HDD_PATH} binds UNIONed with the ${USERDATA_PATH} ROOT (captured at the
root, not per-bind, so the manifest's basename keying round-trips through the
existing import mapping without touching restore). Containment-aware dedupe
both directions. The backup-side stackAdapter is intentionally unchanged.
Red-proof: pre-fix behavior fails TestExportDataMounts_UserdataConvention/
MixedBindsUnion/LiteralUserdataBindDeduped (run->fail->revert recorded).
2026-07-14 15:10:45 +02:00
admin eb3bf4a391 @
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
@
2026-07-14 09:55:53 +02:00
admin 7465713a2f @
v0.129.0: CAMPAIGN-4 fixes — rate-limiter key (F-B) + volume-blind estimate (F-A) + no-op claim status (F-C)

F-B (MED, security): shared clientIP(r) helper (XFF first-hop, else SplitHostPort
host, else raw) replaces requestIP + the duplicated inline derivation in handleLogin,
so login AND escrow re-auth key on the port-stripped host IP — distinct direct
connections no longer evade the failed-attempt counter. XFF-trust out of scope (commented).

F-A (MED, honesty): volumeSizer seam reads volume size from a container view
(docker run --rm -v vol:/vol:ro alpine du -sb /vol), replacing the host-path du that
returned 0 inside the containerized controller. Failed read -> size_unknown +
fits_on_dest forced false (never "fits"). Export pre-flight hard-aborts only on a
KNOWN doesn.t-fit. HDD branch unchanged.

F-C (LOW-MED): escrowClaimAPIHandler relays agent 404 -> clean 404 and 409 -> 409;
410 and genuine-unreachable 502 unchanged (was: 404 fell through to 502).

Tests + red-proofs: ratelimit_ip_test.go (F-B x6), estimate_volsize_test.go (F-A x3),
TestEscrowClaim_ProxySemantics +3 (F-C). Alpine busybox du -sb verified prod-valid.

Claude-Session: https://claude.ai/code/session_01LbMm4T7Ayzs1unB9pN6Uqd
@
2026-07-14 09:52:11 +02:00
admin 3c9de42c20 docs: REPORT + CONTEXT cover v0.128.1 + demo legacy dir-storage retirement (gates G1-G3, 4/4 verifications) 2026-07-13 21:51:06 +02:00
admin d752f159b9 v0.128.1: suppress the class hint on USB drives (ruling F5)
Only Observe-sourced drives ever carried class, so legacy PVE dir:-backed USB
drives showed 'lassú' while registry-sourced ones never did. The card already
carries the USB type tag. Hub-report ClassHint UNCHANGED (UI-only). Pinned by
TestStorageTemplate_USBClassBadgeSuppressed (red-proof run).
2026-07-13 21:40:37 +02:00
admin 61c1391ff6 docs: REPORT covers v0.128.0 (probe numbers, A-F results, red-proofs, both guests live) 2026-07-13 21:14:18 +02:00
admin db16371f47 v0.128.0: chunked browser .fab upload on /import (tunnel-proof)
Cloudflare edge caps request bodies (~100 MB, probed live: 120 MiB -> edge 413,
80 MiB -> origin), so the client slices the file into 64 MiB strictly-sequential
chunks; the server streams each to a .part file in the default drive's exports
dir and finalize renames atomically. Scan/validate/import pipeline untouched.
upload/{init,chunk,finalize,abort} inside ServeExportAPI (inherits auth+CSRF);
single-flight; offset==received or 409+echo; free-space gate; collision ->
lowest-free "name (N).fab"; startup GC of *.part-*; 15-min idle abort.
appexport.DiskFree exported (seam web.uploadDiskFree). Scenarios A-F tested,
red-proofs run (traversal / out-of-order / overwrite).
2026-07-13 21:09:20 +02:00
admin 59e4ca70de docs: REPORT covers v0.127.1-.3 (live-code reveal copy; both guests on 0.127.3, healthy) 2026-07-13 20:46:56 +02:00
admin 8eed73b38a v0.127.3: reveal copy states the shown code is already the LIVE one (supersede happens at upload, before display); render test pins the pre-generation Mégsem 2026-07-13 20:45:11 +02:00
admin 900adf733c docs: REPORT covers v0.127.1+v0.127.2 (manual-only hide toggle per Viktor's live finding; both guests on 0.127.2, healthy) 2026-07-13 20:28:49 +02:00
admin 788f8e65fa v0.127.2: wizard code hide is manual-only — drop the v0.127.1 auto-blur-on-focus (customers type the verification words from the screen); Elrejtés/Megjelenítés toggle shown from reveal, never automatic 2026-07-13 20:26:40 +02:00
admin 6f72e5e0c2 docs: v0.127.1 REPORT (polish deployed both guests, healthy; §10 red-proofs N/A — presentation-only; visual leg awaits Viktor) 2026-07-13 20:20:16 +02:00
admin 156e7d5565 v0.127.1: escrow wizard polish — escrowed-card CTA as btn-outline, Hungarian preflight detail map (raw agent English only as muted failure diagnostic), typed-back word highlight (span-per-word, textContent-only), blur-on-verify toggle 2026-07-13 20:17:36 +02:00
admin a5041dac80 docs: v0.127.0 REPORT (Scenario F LIVE both boxes: stale warn fired at first ACK, drill blob repaired + flag cleared on the 17:23Z ACK, state never flipped; red-proofs 4/5; NOT-live-validated: full browser wizard leg — customer-owned password) + CONTEXT 2026-07-13 19:24:18 +02:00
admin 08a966b92f v0.127.0: customer-facing escrow ceremony wizard (/backup/escrow) + Scenario-F stale-blob re-check — one-shot R reveal (no-store, typed-back), re-stage-first start order, agent version gate (MinAgent 0.88.0), escrowed-state hash re-check with card warning (never flips, never blocks); manual-confirm button removed (endpoint stays deprecated) 2026-07-13 19:01:31 +02:00
admin 51c871ad9b docs: scrub the real hub bearer key from controller.yaml.example (hub v0.53.0 bearer de-git; placeholder only - real boxes use hub-issued per-customer keys) 2026-07-13 14:56:30 +02:00
admin c739003379 v0.126.4: edge-safe error statuses + native-alert ban — writeDiskJSON maps 502/504→500 (CF swallows those bodies; the M1 refusal reached the operator as a JSON SyntaxError popup), M1 refusal = typed errLastUsableDrive → 409; all 29 native alert() swept to showAlert + native_confirm_gate now bans alert( (F-11 class complete) 2026-07-13 14:13:05 +02:00
admin 6136461de6 docs: REPORT — v0.126.3 wizard-CSRF section (root cause, latency-via-claim-arc, red-proof, deploy) 2026-07-13 13:53:09 +02:00
admin f8df1e9f16 v0.126.3: storage wizard CSRF on claimed boxes — wizard pages rendered via raw render() shipped an EMPTY csrf-meta token, every /api/storage/init|attach POST died with 'token mismatch'; latent until the claim arc (unclaimed boxes skip CsrfProtect); fix = executeTemplate injection + session-backed regression test (red-proven) 2026-07-13 13:51:19 +02:00
admin 93c95f0fb5 docs: v0.126.x REPORT overwrite (parts, 4 red-proofs, gate outputs, drill live-QA evidence incl. reversible gate-lift + restore, open demo human steps) + CONTEXT 2026-07-13 12:07:09 +02:00
admin 21d0f66c15 v0.126.2: stylesheet cache-bust ?v={{.Version}} — CF edge caches /static/style.css 4h, every release served the previous CSS until TTL (hub v0.47.0 gotcha class, controller instance) 2026-07-13 12:00:35 +02:00
admin 41c8fc23cf v0.126.1: .form-input/.form-row finally have CSS — the classes were used across backups/import/offbox templates with NO backing rule (root cause of the unstyled .fab password field seen in 0.126.0 live QA); same visual spec as the .form-control twin 2026-07-13 11:57:08 +02:00
admin 912e6a62b6 docs: v0.126.0 UI uniformity bundle — CHANGELOG (parts A-E + gate housekeeping), REUSE (app_list_row canonical row + gate list), README (shared-row pattern, infra identity, Part E display pick), CONTEXT 2026-07-13 11:41:11 +02:00
admin 02c84e1ce2 Part E: the stale zero-toggle line tells the truth (v0.126.0)
- offboxWarningDisplay(lastWarning, toggledCount) — pure DISPLAY pick, no state mutation:
  a persisted 'nincs mentésre jelölt alkalmazás' run-result is replaced by
  'A kijelölés módosult az utolsó futás óta — a következő távoli mentés már tartalmazza.'
  once ≥1 app is toggled; 0 toggled keeps the v0.123.0 honesty verbatim; every other
  warning (quota, partial) passes through untouched
- replacement renders NEUTRAL (exception-color principle: reassurance, not deviation);
  the untouched original keeps the warn color
- unit + render tests; red-proven (pick removed → 1-enabled case fails at both levels)
2026-07-13 11:37:47 +02:00
admin 458cf4a4c2 Part D: mojibake_gate.py — double-encoded UTF-8 can never enter the source again (v0.126.0)
- scans all templates + Go sources (291 files) for the double-encoding signature chars
  (Ã Â Ă ă ˘ ˇ) + strict-UTF-8 decode; allowlist ZERO by design; Python per the
  multibyte rule (this task exists partly because of a bash-era mojibake sweep)
- byte-level sweep result: the committed source contains NO mojibake — the 'Tárhely'-class
  text on the live import page is the felhom-usb DRIVE-LABEL DATA (settings.json on the
  demo box; default-label pattern settings.go GenerateLabel), repaired via the label-edit
  UI in the live-validation step, not by code
- red-proven: reintroduced 'Tárhely' into app_import.html → exit 1 naming file:line; reverted → 0
2026-07-13 11:35:04 +02:00
admin 67494f9890 Part C: restore-form polish — the .fab encryption field is a standard form field (v0.126.0)
- backups_restore: placeholder 'Opcionális jelszó' + helper under the field
  ('Üresen hagyva a csomag titkosítás nélkül készül.') — the long clipped placeholder is gone
- app_import: the bundle-password input picks up the standard .form-input class
  (was a bare browser-default input)
2026-07-13 11:32:41 +02:00
admin 4f06149abc Part B: infra stacks carry identity — curated Hungarian metadata for cloudflared/traefik/filebrowser (v0.126.0)
- inframeta.go: static display-only map (name/description/Linked) + infraMeta template func;
  filebrowser is the ONLY Linked stack (files.<domain> Megnyitás on the dashboard row;
  the stacks card already links via Subdomains)
- generic infra icon: embedded /static/infra-logo.svg (Lucide-style server, monochrome)
  wired through the app-row FallbackIcon slot + the stacks-card onerror chain
- dashboard rows + app cards: infra name + description + existing Védett chip
- guarded WRONG outcome: no customer link for cloudflared/traefik — render tests count
  exactly ONE https:// link; red-proven (Linked:true on cloudflared → test FAILS)
2026-07-13 11:31:38 +02:00
admin 3eacb6c326 Part A: shared app_list_row partial — ONE row grammar on four surfaces (v0.126.0)
- templates/app_row.html: app_list_row/app_list_row_end (layout_start/_end idiom) — icon+name
  (+optional secondary) left, caller action block right; compact 44px row; logoURL→PNG→
  optional FallbackIcon→hidden onerror chain
- applied: Távoli mentés toggle list, Visszaállítás restore-to-verify + .fab lists, dashboard
  Telepített alkalmazások (state edge + data-href preserved); Alkalmazások collapsed headers
  ALIGNED (icon+name left, status dot moved right before chevron; expander untouched)
- funcmap: dict + appHref; OffboxAppRow/AppBackupRow gain Slug
- style.css: .app-row family; stack-card/stack-info/stack-logo/stack-name/stack-desc/
  stack-actions rules retired (dashboard rows now shared); .app-backup-row-header matched
  to the shared row height
- scripts/app_row_dedup_gate.py: row markup single-sourced (red-proven: pasted old
  storage-path-item block → exit 1); render tests per surface (app_row_test.go)
- NO behavior change: toggle/download/expander actions byte-identical
2026-07-13 11:26:48 +02:00
admin 7b3e7f2e71 chore: retire backups_split_move_check.py — the one-shot v0.124.0 migration gate served its purpose (v0.126.0 legitimately rewrites the moved blocks onto the shared row partial); doc refs updated (README page-map note, REUSE builder row) 2026-07-13 11:15:12 +02:00
admin e0618af438 docs: v0.125.0 path-strand fix — CHANGELOG + REPORT (probe transcript, red-proofs, round-trip evidence, Tier-1/2 mechanism) + CONTEXT + REUSE + README flows; hollow-bundle asymmetry recorded (containerized ≤0.124.0 exports suspect — re-export); floor note for the next train
Claude-Session: https://claude.ai/code/session_01GzammAMzsJTgpQHqxwM2bC
2026-07-13 10:58:19 +02:00
admin 466f42708e controller: .fab volume legs stream via docker cp (fixes the containerized path-strand data loss, IA finding 1 HIGH) — zero shared paths both deployment shapes; export fails LOUD on any missing/empty claimed tar (no hollow bundles); import validates BEFORE it destroys (hollow bundle → app untouched); docker_run_volume_path_gate.py extinguishes the class (Tier-1/2 mounts documented host-visible)
Claude-Session: https://claude.ai/code/session_01GzammAMzsJTgpQHqxwM2bC
2026-07-13 10:42:02 +02:00
admin 811a0ef7a7 docs: v0.124.0 backups IA restructure — CHANGELOG + REPORT + CONTEXT (decisions 1-3) + README page map + REUSE; records the HIGH containerized-.fab volume-strand finding and the agent SystemDisks legacy-boot finding
Claude-Session: https://claude.ai/code/session_01GzammAMzsJTgpQHqxwM2bC
2026-07-13 10:17:58 +02:00
admin 753cd83456 controller: .fab browser download — the existing export pipeline staged under the data dir + a guarded streaming exit (estimate-first, io.Copy, post-stream cleanup, 1h TTL sweep); portability framing (decision 3); traversal guard red-proven, export→import round-trip + corrupt-bundle refusal unit-proven
Claude-Session: https://claude.ai/code/session_01GzammAMzsJTgpQHqxwM2bC
2026-07-13 09:47:10 +02:00
admin aa967fbf69 controller: Felhom-offsite status card — three honest states from local data (opt-in pitch / Aktív-nincs-kijelölt / the regular status block); display-only by design (decision 2: never a state change), state-tested incl. the no-form/no-button invariant
Claude-Session: https://claude.ai/code/session_01GzammAMzsJTgpQHqxwM2bC
2026-07-13 09:37:05 +02:00
admin 0ece2ba85c controller: backups IA split — four sub-pages (Áttekintés /backups, Távoli mentés /backups/remote, Alkalmazások /backups/apps, Visszaállítás /backups/restore); sections MOVED verbatim (backups_split_move_check.py enforces vs df7ad37); shared data builder extracted; offbox restore-to-verify relocated to the restore page; flash redirects + tier-3 anchors + tier2 back-link retargeted
Claude-Session: https://claude.ai/code/session_01GzammAMzsJTgpQHqxwM2bC
2026-07-13 09:35:01 +02:00
admin df7ad378f4 docs: v0.123.0 polish batch — CHANGELOG + REPORT + CONTEXT + REUSE (felhomConfirm pattern, new gates)
Claude-Session: https://claude.ai/code/session_01GzammAMzsJTgpQHqxwM2bC
2026-07-13 08:47:58 +02:00
admin b482860c03 controller: zero-toggle honesty — a configured+escrowed offbox with no app selected shows 'Nincs távoli mentésre jelölt alkalmazás…' on the toggle list, and a zero-toggle run reports 'Sikeres — nincs mentésre jelölt alkalmazás' instead of bare success
Claude-Session: https://claude.ai/code/session_01GzammAMzsJTgpQHqxwM2bC
2026-07-13 08:27:52 +02:00
admin a00afcc79d controller: Tier-3 rename — customer-facing 'NAS-mentés' branding becomes 'Távoli mentés' (backups page, offbox flashes, quota copy); manual-target form generalized to any SFTP target; offbox_rename_gate.py enforces zero regressions
Claude-Session: https://claude.ai/code/session_01GzammAMzsJTgpQHqxwM2bC
2026-07-13 08:23:43 +02:00
admin 8987ce0f67 controller: drill F-11 — inline two-step confirm (felhomConfirm + data-confirm) replaces every native confirm(); native_confirm_gate.py enforces zero; stale-data delete keeps its double acknowledgement inline
Claude-Session: https://claude.ai/code/session_01GzammAMzsJTgpQHqxwM2bC
2026-07-13 08:19:39 +02:00
admin 40b53047f1 controller: atomicPromoteTar syncs via an O_RDWR handle — read-only fsync is refused on Windows, which kept the dev-box green gate permanently red (Linux behavior unchanged)
Claude-Session: https://claude.ai/code/session_01GzammAMzsJTgpQHqxwM2bC
2026-07-13 08:19:39 +02:00
admin b4e0a197f9 controller: F-15 instant reset codes — reset-request response hash applied via the ACK's generation-guarded ClaimSync (emailed code works immediately; old-hub bare response = no-op)
Claude-Session: https://claude.ai/code/session_01GzammAMzsJTgpQHqxwM2bC
2026-07-13 08:05:07 +02:00
admin d4641c221d docs: v0.122.0 customer-claim gate — REPORT + CONTEXT 2026-07-12 18:56:29 +02:00
admin 3cf49c7fd5 controller: customer-claim password gate v0.122.0 (closes DRILL-day0-vm F-4/F-5)
The customer sets + owns the dashboard password via a hub-emailed one-time
claim code. An unclaimed box (code hash present, no password) serves ONLY the
claim page — every other route → claim page (302) or 401, so a Day-0 box is
never open on the internet. A set password disables the gate (auth wins).
Reset rides the same code engine (login "Elfelejtett jelszó"). Legacy-open
(no password, no hash) shows a red transition banner until the hub delivers a
hash. Report ACK caches the code state idempotently by generation; report
carries claimed (set-only). --print-reset-code root escape hatch. Requires
hub v0.50.0. Gate-coverage signature test + 4 red-proofs proven.
2026-07-12 18:42:39 +02:00
admin dec6fef20d REPORT: v0.121.0 live-validation results (9201, claude-in-chrome a–g green) 2026-07-12 12:33:39 +02:00
admin 9d05fa5c35 controller v0.121.0: backups page truth pass — remove dead Részletek card, real Tier-3 off-box state, SQLite-honest DB messaging
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.
2026-07-12 12:26:30 +02:00
admin 92d670e8a6 controller v0.120.0: dead-app alerting (fix-3) + ring revision (fix-6) — CLOSES CAMPAIGN-3 (docs+CHANGELOG+REPORT+CONTEXT)
fix-3: deadapp-check job -> self-clearing WARN banner + one app_start_failed hub
event per running->down transition. fix-6: ring 1000->5000, periodic spam->TRACE
(ring-dropped), atomic SSD spill/load across restart. Live-validated on 9201+hub 0.48.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017CDMFpFx84pfviCTVuGGhf
2026-07-12 10:31:12 +02:00
admin 40498254c6 fix-6: raise ring display cap to 5000 (viewer + Entries clamp); viewer default limit 1000
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017CDMFpFx84pfviCTVuGGhf
2026-07-12 10:21:34 +02:00
admin e030b8d9a9 test: clean message in fix-6 spill tests 2026-07-12 10:09:22 +02:00
admin 6ab8f943af test: io.Discard logger in fix-3 tests 2026-07-12 10:08:39 +02:00
admin d8f6069b46 controller: fix-3 dead-app alerting + fix-6 ring cap/spill/spam (WIP, pre-build)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017CDMFpFx84pfviCTVuGGhf
2026-07-12 10:07:47 +02:00