From f75b3aa778e8de954072fd2f39230ec2755d3de0 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Fri, 16 Oct 2026 22:46:00 +0200 Subject: [PATCH] v0.324.0: the database password comes back with the data (R-1106, R-127b, R-926); restic 0.19.1 (R-1107); R-1108, R-1065, R-1017; dashboard hardening (R-983, R-976) --- CHANGELOG.md | 34 ++ REUSE.md | 4 +- controller/Dockerfile | 6 +- controller/cmd/controller/main.go | 6 + controller/internal/appbackup/dbservices.go | 119 +++++ controller/internal/appbackup/paths.go | 2 +- .../userdata_bare_drive_guard_test.go | 254 ++++++++++ controller/internal/backup/offbox_capture.go | 10 +- .../internal/backup/offbox_reconstitute.go | 37 +- .../backup/r1105_restic_versions_test.go | 72 +-- .../backup/r1106_db_credentials_test.go | 301 ++++++++++++ controller/internal/backup/restore_dbcreds.go | 194 ++++++++ controller/internal/backup/restore_unit.go | 34 +- .../restic/0.14.0/backup-status.jsonl | 2 +- .../testdata/restic/0.14.0/check-damaged.txt | 8 +- .../testdata/restic/0.14.0/check-ok.txt | 2 +- .../testdata/restic/0.14.0/forget-dryrun.json | 2 +- .../restic/0.14.0/locked-exclusive.txt | 6 +- .../testdata/restic/0.14.0/locked-shared.txt | 6 +- .../restic/0.14.0/snapshots-latest-tag.json | 2 +- .../testdata/restic/0.14.0/snapshots.json | 2 +- .../testdata/restic/0.14.0/stats-raw.json | 2 +- .../restic/0.18.1/backup-status.jsonl | 4 +- .../testdata/restic/0.18.1/check-damaged.txt | 10 +- .../testdata/restic/0.18.1/check-ok.txt | 2 +- .../testdata/restic/0.18.1/forget-dryrun.json | 2 +- .../restic/0.18.1/locked-exclusive.txt | 6 +- .../testdata/restic/0.18.1/locked-shared.txt | 6 +- .../restic/0.18.1/snapshots-latest-tag.json | 2 +- .../testdata/restic/0.18.1/snapshots.json | 2 +- .../testdata/restic/0.18.1/stats-raw.json | 2 +- .../restic/0.19.1/backup-status.jsonl | 1 + .../testdata/restic/0.19.1/check-damaged.txt | 19 + .../testdata/restic/0.19.1/check-ok.txt | 7 + .../testdata/restic/0.19.1/forget-dryrun.json | 1 + .../testdata/restic/0.19.1/init-exists.txt | 1 + .../restic/0.19.1/locked-exclusive.txt | 5 + .../testdata/restic/0.19.1/locked-shared.txt | 5 + .../backup/testdata/restic/0.19.1/no-repo.txt | 3 + .../restic/0.19.1/rclone-dead-ssh.txt | 2 + .../restic/0.19.1/sftp-refused-key.txt | 2 + .../restic/0.19.1/sftp-refused-port.txt | 2 + .../restic/0.19.1/sftp-unreachable.txt | 2 + .../restic/0.19.1/snapshots-latest-tag.json | 1 + .../testdata/restic/0.19.1/snapshots.json | 1 + .../testdata/restic/0.19.1/stats-id.json | 1 + .../testdata/restic/0.19.1/stats-raw.json | 1 + .../testdata/restic/0.19.1/wrong-password.txt | 1 + controller/internal/family/family.go | 49 +- controller/internal/i18n/locales/en.json | 5 +- controller/internal/i18n/locales/hu.json | 5 +- controller/internal/stacks/delete.go | 8 +- .../internal/stacks/delete_r442_test.go | 25 + controller/internal/stacks/deploy.go | 49 ++ .../stacks/r1106_set_secret_values_test.go | 51 ++ controller/internal/stacks/samba.go | 14 +- controller/internal/stacks/samba_test.go | 89 ++++ controller/internal/web/auth.go | 102 +++- controller/internal/web/claim.go | 53 +- controller/internal/web/family_gate.go | 105 ++-- controller/internal/web/family_gate_test.go | 4 +- controller/internal/web/handlers.go | 12 +- controller/internal/web/i18n_cases_a_test.go | 1 + controller/internal/web/i18n_cases_c_test.go | 3 +- controller/internal/web/media_events.go | 11 +- controller/internal/web/plex_claim_test.go | 44 ++ .../internal/web/r255_secret_sweep_test.go | 4 +- controller/internal/web/r983_r976_test.go | 452 ++++++++++++++++++ controller/internal/web/server.go | 21 +- controller/internal/web/session_store_test.go | 2 + controller/internal/web/setup_gate.go | 41 +- .../internal/web/templates/familygate.html | 1 + controller/internal/web/templates/layout.html | 2 +- .../web/templates/settings_security.html | 6 +- controller/internal/web/templates/style.css | 3 +- .../i18n_parity/app_data_deployed.html | 2 +- .../testdata/i18n_parity/app_data_export.html | 2 +- .../i18n_parity/app_data_files_media.html | 2 +- .../i18n_parity/app_data_not_hdd.html | 2 +- .../i18n_parity/app_data_not_hdd_absent.html | 2 +- .../app_data_not_hdd_protected.html | 2 +- .../app_data_not_hdd_same_disk.html | 2 +- .../app_data_notarget_disabled.html | 2 +- .../i18n_parity/app_data_target_auto.html | 2 +- .../i18n_parity/app_data_target_ssd.html | 2 +- .../i18n_parity/app_guide_available.html | 2 +- .../testdata/i18n_parity/app_guide_full.html | 2 +- .../app_guide_infra_filebrowser.html | 2 +- .../i18n_parity/app_guide_installable.html | 2 +- .../i18n_parity/app_guide_no_guide.html | 2 +- .../i18n_parity/app_import_bundles.html | 4 +- .../i18n_parity/app_import_empty.html | 4 +- .../web/testdata/i18n_parity/app_logs.html | 2 +- .../i18n_parity/app_settings_after_start.html | 2 +- .../app_settings_close_signup.html | 2 +- .../app_settings_close_signup_native.html | 2 +- .../i18n_parity/app_settings_deployed.html | 2 +- .../i18n_parity/app_settings_hold_log.html | 2 +- .../app_settings_infra_filebrowser.html | 2 +- .../app_settings_infra_filebrowser_stale.html | 2 +- .../app_settings_install_hold.html | 2 +- .../app_settings_known_login_changed.html | 2 +- .../app_settings_ladder_steps.html | 2 +- .../i18n_parity/app_settings_login_email.html | 2 +- .../app_settings_login_family.html | 2 +- .../i18n_parity/app_settings_login_none.html | 2 +- .../app_settings_login_not_stored.html | 2 +- .../app_settings_login_text_name.html | 2 +- .../i18n_parity/app_settings_lost_files.html | 2 +- .../i18n_parity/app_settings_not_checked.html | 2 +- .../app_settings_operator_creds.html | 2 +- .../app_settings_restored_login.html | 2 +- .../i18n_parity/app_settings_running.html | 2 +- .../app_settings_setup_gate_button.html | 2 +- .../app_settings_setup_gate_native.html | 2 +- .../app_settings_setup_gate_probe.html | 2 +- .../app_settings_signup_closed.html | 2 +- .../app_settings_signup_native.html | 2 +- ...pp_settings_signup_native_open_failed.html | 2 +- .../app_settings_signup_window.html | 2 +- .../i18n_parity/app_settings_stopped.html | 2 +- .../i18n_parity/app_settings_updating.html | 2 +- .../i18n_parity/backups_apps_empty.html | 4 +- .../i18n_parity/backups_apps_error.html | 4 +- .../backups_apps_interrupted_run.html | 4 +- .../backups_apps_offsite_offer.html | 4 +- .../testdata/i18n_parity/backups_apps_ok.html | 4 +- .../i18n_parity/backups_apps_other.html | 4 +- .../i18n_parity/backups_apps_running.html | 4 +- .../i18n_parity/backups_apps_stale_copy.html | 4 +- .../i18n_parity/backups_degraded.html | 4 +- .../testdata/i18n_parity/backups_empty.html | 4 +- .../testdata/i18n_parity/backups_full.html | 4 +- .../i18n_parity/backups_interrupted_run.html | 4 +- .../i18n_parity/backups_nobackup_yet.html | 4 +- .../backups_remote_abandon_overdue.html | 4 +- .../i18n_parity/backups_remote_empty.html | 4 +- .../i18n_parity/backups_remote_error.html | 4 +- .../i18n_parity/backups_remote_escrowed.html | 4 +- .../i18n_parity/backups_remote_full.html | 4 +- .../backups_remote_incomplete.html | 4 +- .../i18n_parity/backups_remote_notconf.html | 4 +- .../backups_remote_notconf_hub.html | 4 +- .../backups_remote_offsite_offer_fit.html | 4 +- .../backups_remote_pending_agent.html | 4 +- .../backups_remote_pending_old.html | 4 +- .../i18n_parity/backups_remote_running.html | 4 +- .../i18n_parity/backups_remote_stale.html | 4 +- .../i18n_parity/backups_remote_stale_old.html | 4 +- .../i18n_parity/backups_restore_empty.html | 4 +- .../i18n_parity/backups_restore_full.html | 4 +- .../backups_restore_known_empty.html | 4 +- .../i18n_parity/backups_restore_notarget.html | 4 +- .../i18n_parity/backups_tier_due.html | 4 +- .../i18n_parity/dashboard_diskcrit.html | 4 +- .../testdata/i18n_parity/dashboard_full.html | 4 +- .../i18n_parity/dashboard_nobackup.html | 4 +- .../i18n_parity/dashboard_sparse.html | 4 +- .../i18n_parity/dashboard_tunnel_offline.html | 4 +- .../web/testdata/i18n_parity/debug.html | 4 +- .../web/testdata/i18n_parity/deploy_new.html | 2 +- .../i18n_parity/deploy_new_blocked.html | 2 +- .../deploy_new_memory_blocked.html | 2 +- .../i18n_parity/escrow_agent_old.html | 4 +- .../testdata/i18n_parity/escrow_first.html | 4 +- .../i18n_parity/escrow_not_ready.html | 4 +- .../i18n_parity/escrow_receremony.html | 4 +- .../i18n_parity/familygate_signed_in.html | 3 +- .../testdata/i18n_parity/kept_data_empty.html | 4 +- .../testdata/i18n_parity/kept_data_full.html | 4 +- .../i18n_parity/launcher_abandon_overdue.html | 4 +- .../launcher_abandon_overdue_offered.html | 4 +- .../testdata/i18n_parity/launcher_empty.html | 4 +- .../testdata/i18n_parity/launcher_full.html | 4 +- .../i18n_parity/launcher_missed_backup.html | 4 +- .../i18n_parity/launcher_nopassword.html | 4 +- .../i18n_parity/launcher_reminder_tier0.html | 4 +- .../i18n_parity/launcher_reminder_tiers.html | 4 +- .../i18n_parity/monitoring_hub_down.html | 4 +- .../i18n_parity/monitoring_hub_off.html | 4 +- .../i18n_parity/monitoring_hub_ok.html | 4 +- .../i18n_parity/restore_wizard_blocked.html | 4 +- .../i18n_parity/restore_wizard_exec.html | 4 +- .../restore_wizard_nodumptime.html | 4 +- .../restore_wizard_prepare_confirm.html | 4 +- .../i18n_parity/restore_wizard_ready.html | 4 +- .../settings_notifications_clear_confirm.html | 4 +- .../settings_notifications_groups_custom.html | 4 +- .../settings_notifications_hub.html | 4 +- .../settings_notifications_nohub.html | 4 +- .../i18n_parity/settings_security_full.html | 10 +- .../i18n_parity/settings_system_failed.html | 4 +- .../i18n_parity/settings_system_full.html | 4 +- .../i18n_parity/settings_system_nomemory.html | 4 +- .../i18n_parity/settings_system_pending.html | 4 +- .../i18n_parity/sharing_error_skipped.html | 4 +- .../testdata/i18n_parity/sharing_full.html | 4 +- .../i18n_parity/sharing_no_offsite_yet.html | 4 +- .../i18n_parity/sharing_notarget_blocked.html | 4 +- .../web/testdata/i18n_parity/sharing_off.html | 4 +- .../i18n_parity/sharing_other_none.html | 4 +- .../web/testdata/i18n_parity/stacks_full.html | 4 +- .../stacks_install_interrupted.html | 4 +- .../i18n_parity/stacks_unhealthy_stop.html | 4 +- .../testdata/i18n_parity/storage_attach.html | 4 +- .../testdata/i18n_parity/storage_empty.html | 4 +- .../testdata/i18n_parity/storage_full.html | 4 +- .../testdata/i18n_parity/storage_init.html | 4 +- .../i18n_parity/storage_network_full.html | 4 +- .../storage_network_nosupport.html | 4 +- controller/scripts/i18n_go_keys.json | 3 +- controller/scripts/secret_in_markup_gate.py | 2 + 212 files changed, 2414 insertions(+), 398 deletions(-) create mode 100644 controller/internal/appbackup/userdata_bare_drive_guard_test.go create mode 100644 controller/internal/backup/r1106_db_credentials_test.go create mode 100644 controller/internal/backup/restore_dbcreds.go create mode 100644 controller/internal/backup/testdata/restic/0.19.1/backup-status.jsonl create mode 100644 controller/internal/backup/testdata/restic/0.19.1/check-damaged.txt create mode 100644 controller/internal/backup/testdata/restic/0.19.1/check-ok.txt create mode 100644 controller/internal/backup/testdata/restic/0.19.1/forget-dryrun.json create mode 100644 controller/internal/backup/testdata/restic/0.19.1/init-exists.txt create mode 100644 controller/internal/backup/testdata/restic/0.19.1/locked-exclusive.txt create mode 100644 controller/internal/backup/testdata/restic/0.19.1/locked-shared.txt create mode 100644 controller/internal/backup/testdata/restic/0.19.1/no-repo.txt create mode 100644 controller/internal/backup/testdata/restic/0.19.1/rclone-dead-ssh.txt create mode 100644 controller/internal/backup/testdata/restic/0.19.1/sftp-refused-key.txt create mode 100644 controller/internal/backup/testdata/restic/0.19.1/sftp-refused-port.txt create mode 100644 controller/internal/backup/testdata/restic/0.19.1/sftp-unreachable.txt create mode 100644 controller/internal/backup/testdata/restic/0.19.1/snapshots-latest-tag.json create mode 100644 controller/internal/backup/testdata/restic/0.19.1/snapshots.json create mode 100644 controller/internal/backup/testdata/restic/0.19.1/stats-id.json create mode 100644 controller/internal/backup/testdata/restic/0.19.1/stats-raw.json create mode 100644 controller/internal/backup/testdata/restic/0.19.1/wrong-password.txt create mode 100644 controller/internal/stacks/r1106_set_secret_values_test.go create mode 100644 controller/internal/web/r983_r976_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index d1c4bd7..edb0914 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,37 @@ +## v0.324.0 — a restore brings the database password back with the data; restic 0.19.1; dashboard hardening; three small fixes (2026-10-17) + +**MinAgent: 0.158.1** — the floor's, carried. Nothing here calls the agent. No golden (`09` §3 decision 250). Task: +night brief 2026-10-16 → 17 (felhom.eu `REPORT-night-2026-10-17.md`). + +- **R-1106 + R-127 (b) — operator decision 1A: on a restore, the backup's database password wins.** New + `appbackup.DBCredentialVars` finds the app.yaml variables that feed a database service's `*_PASSWORD` (17 catalog + apps, 20 fields); `DBDataVolumes` the database's named volumes. The off-site full restore that keeps the app's + definition now writes the snapshot's password into the app's settings (`stacks.SetStackSecretValues`, load-then-save) + before the database starts — but only when the snapshot replays the database's data volume. The shared unit-restore + env (on-box restore, update rollback, „use kept data", off-site at the snapshot's version) keeps unit-wins and now + REFUSES, before any change, when neither the unit carries the password nor the current install is older than the + data; O4 never generates a database password again. Refusal sentence `err.backup.restore_no_db_password` (HU/EN). + R-926 on this path: the reinstall's `type: password` logins are recorded as restored-login fields (the page says to + use the old password). Tests `TestR1106_*` (backup, stacks), red-proved by six mutations. Catalog gate + `db-credentials` (app-catalog `af75dc0`). +- **R-1107 — restic 0.19.1** (official binary, signed `SHA256SUMS`, both sums pinned). Fixtures for 0.14.0, 0.18.1 and + 0.19.1 recaptured from one shared store; `TestR1105_*` runs every version against 0.14.0. One change read from its + notes and measured: a missing top-level backup path now exits 3 (was 0) — the capture's stat-filter keeps such paths + out of argv, so only a race reaches it, and that race now reads as a failure instead of a silent partial copy. +- **R-1108** — `SetSMBPassword` applies changed files when the stack is running (a share added before the first + password is exported). `TestSambaPassword_ShareAddedBeforePasswordIsApplied` (+ companion). +- **R-1065** — a successful Plex claim schedules the media wiring (`RunMediaWiringSoon`). `TestPlexClaim_TriggersMediaWiring`. +- **R-1017** — the guard the `paths.go` comment named now exists: `TestNoBareDrivePathToUserdataDir`. It found one more + bare drive path: the remove dialog's „kept folders" list was empty on the system-drive fallback (`delete.go` + `userdataKept`) — fixed, `TestRemoveStack_R800_UserdataKeptOnSystemDrive`. +- **R-983 (six items)** — sign-in `next` stays on the box (`safeBackPath`); `X-Frame-Options: DENY` + CSP + `frame-ancestors 'none'`; a sign-in try is counted before the password check (dashboard and family gate); the settings + password minimum is the claim's (12); reset-code requests limited (1 per visitor per minute, 3 per box per 15 min); + logout is a POST with CSRF (dashboard and family gate — the dashboard's sign-out link had done nothing since + 2026-02-25). **R-976** — a password change or reset ends every dashboard, family and setup-gate session (the gate key + is rotated and saved); a family app cookie carries a per-app token, never the session. Tests `TestR983_*`, + `TestR976_*`, each red-proved. 135 i18n parity fixtures re-captured (the sign-out control; one minlength), 22 unchanged. + ## v0.323.0 — Debian 13 with restic pinned outside the OS, re-proven; felhom-samba 1.2.0 on Alpine 3.24.2 (2026-10-16) **MinAgent: 0.158.1** — the floor's, carried. Nothing here calls the agent. No golden (`09` §3 decision 250). Task: diff --git a/REUSE.md b/REUSE.md index dcb1a7d..b62f5db 100644 --- a/REUSE.md +++ b/REUSE.md @@ -28,7 +28,7 @@ | `stacks.RunAfterInstall` / `expandAfterInstall` / `web.defaultLoginInEffect` (v0.279.0, decision 45) | controller/internal/stacks/after_install.go · controller/internal/web/known_login.go | `(name, wait)` / `(cmd, allowed, env)` / `(meta, cfg, installed)` | A fresh install replaces a known default login; the page says when a default is still in effect | **Only from the deploy-done hook** — never after a restore/kept load (R-694). A `success:` marker is required (exit 0 lies). Never log the expanded command | | `stacks.OpenSetupGate` / `SetupGateTick` / `SetupGateHost` · `web.ServeGateAuth` / `ServeGateStart` (v0.280.0, decision 46) | controller/internal/stacks/setup_gate.go · controller/internal/web/setup_gate.go | `(name, by)` / `()` / `(host)` · handlers | The setup gate: a `setup_gate: true` install is closed to everyone but the household until its probe or the household's press opens it | **Write the gate BEFORE the first start** (spike F2). Open = record first, then remove the file. Never widen the dashboard cookie — the handshake mints a host-bound one-use token | | `stacks.OpenSignupWindow` / `SignupBlocked` / `SetupGateProbe` · `web.ServeSignupClosed` (v0.281.0, decision 47) | controller/internal/stacks/signup_block.go · controller/internal/web/setup_gate.go | `(name)` | Sign-up closed at the app's own address once the gate opens; the household's 15-minute window; the press asks the probe | **The block goes up BEFORE the gate comes down** (a failed write keeps the gate closed). Never on an app this box did not gate | -| `family.Store` · `stacks.FamilyGateHost` / `familyGateTick` / `FamilyExceptRegexp` · `web.ServeFamilyGateAuth` / `ServeFamilyStart` / `ServeFamilyLogin` / `ServeFamilyLogout` (v0.287.0, decisions 63/64) | controller/internal/family/family.go · controller/internal/stacks/family_gate.go · controller/internal/web/family_gate.go | store `Add/Reset/Remove/Verify/NewSession/Valid/EndSession` · `(host)` / `()` / `(prefix)` · handlers | The PERMANENT family gate: family members with their own logins in front of a `family_gate: true` app | **A family cookie never opens the dashboard** (RequireAuth reads only `felhom_session`); the app cookie names a STORE session, so the store is asked on every request (reset/remove/logout end access at once); **every exception goes through `FamilyExceptRegexp`** (anchored — never a hand-written PathPrefix); door written before the first start, like the setup gate. `familyStoreOverride` is the test seam. Fifth atomic-write helper (family.json, fsync) — see §6 | +| `family.Store` · `stacks.FamilyGateHost` / `familyGateTick` / `FamilyExceptRegexp` · `web.ServeFamilyGateAuth` / `ServeFamilyStart` / `ServeFamilyLogin` / `ServeFamilyLogout` (v0.287.0, decisions 63/64) | controller/internal/family/family.go · controller/internal/stacks/family_gate.go · controller/internal/web/family_gate.go | store `Add/Reset/Remove/Verify/NewSession/Valid/EndSession/Find/EndAll` · `(host)` / `()` / `(prefix)` · handlers | The PERMANENT family gate: family members with their own logins in front of a `family_gate: true` app | **A family cookie never opens the dashboard** (RequireAuth reads only `felhom_session`); the app cookie carries a token DERIVED per app host from a STORE session (`familyAppToken`, R-976 — never the session id itself), so the store is asked on every request (reset/remove/logout end access at once); **every exception goes through `FamilyExceptRegexp`** (anchored — never a hand-written PathPrefix); door written before the first start, like the setup gate. `familyStoreOverride` is the test seam. Fifth atomic-write helper (family.json, fsync) — see §6 | | `stacks.OpenInstallHold` / `installHoldTick` (v0.284.0, R-741) | controller/internal/stacks/install_hold.go | `(name, by)` / `()` | An `after_install` app held behind the setup gate's door until its known login is replaced | **Written before the first start**, like the gate; opens on `after_install` success or the household's "I changed it"; the door (`SetupGateHost`) reads holds first | | `stacks.RetainImagesAfterUpdate` / `RetainImagesAfterRemove` / `RunImageRetentionOnce` (→ `(deleted, done)` since v0.294.0) / `RunImageRetentionOnceUntilDone` · seam `imageDocker` (v0.284.0, decision 53) | controller/internal/stacks/image_retention.go | `(name, previous)` / `(name, repos)` / `()` | Deletes an app's images older than its running + previous one | **The keep set is box-wide and read at delete time** (containers, installed composes, installed/previous records); exact id, never forced or pruned; skipped while any update runs AND while any image-pulling compose command runs (R-863, `dockerexec.TryImageCleanup`); the one-time pass writes its marker only after a pass that RAN; tests use the `imageDocker` seam, never Docker | | `dockerexec.BeginImageWork(args)` / `TryImageCleanup()` / `ImagePulling(args)` (v0.294.0, R-863) | controller/internal/dockerexec/imagework.go | `defer dockerexec.BeginImageWork(args)()` | **Every NEW place that runs `compose up/pull/create/run` must hold it** (the stacks compose helpers, appexport's restore and the FileBrowser sync already do) | An image pulled by compose is named by no container until compose creates one; a clean-up pass in that window deleted it (measured, R-863). The pass takes the lock exclusively without waiting; pulling commands wait for a running pass (seconds) | @@ -284,6 +284,8 @@ | `Scheduler.RunNow` / `scheduler.OnDemand` | controller/internal/scheduler/scheduler.go | `RunNow(name) error`; `OnDemand(ctx) bool` | Run a registered job once now (operator action `run_job`, decision 185) | Refuses unknown and already-running jobs; a job that checks due-ness reads `OnDemand(ctx)` to skip that check on demand | | `report.OperatorActions` | controller/internal/report/opactions.go | `Reconcile(reply)` → results in the next report | Hub-requested actions in the report reply — the `selftail.go` pattern plus results | The action table is CLOSED and pinned by `TestOpActions_ClosedList`; once per id in memory; every entry must be safe to repeat | | `web.sessionFingerprint` / `loadSessions` / `saveSessionsLocked` / `saveSessionsRevokingLocked` | controller/internal/web/session_store.go | dashboard sessions on disk (R-35) | Any session lookup | The map is keyed by sha256(cookie), NEVER the cookie — hash with `sessionFingerprint` first; a path that ENDS sessions uses the revoking save | +| `web.endEverySession` / `rotateGateKey` (R-976, v0.324.0) | controller/internal/web/auth.go · controller/internal/web/setup_gate.go | `(why string)` / `()` | A dashboard password change or claim/reset — ANY act that must end every way in | Ends the dashboard sessions, every family session (`family.Store.EndAll`) AND every setup-gate pass / family app cookie (the gate key is replaced; a failed save REMOVES the old key file so a restart cannot bring old passes back). Call this, never `invalidateAllSessions` alone — that ends only the dashboard's. Pinned by `TestR976_PasswordChangeEndsFamilyAndGateSessions` / `TestR976_ClaimResetEndsFamilyAndGateSessions` | +| `web.reserveLoginAttempt` / `familyReserve` / `allowResetRequest` (R-983, v0.324.0) | controller/internal/web/auth.go · family_gate.go · claim.go | `(key) → may go ahead` | Any limiter in front of a slow check (bcrypt, a hub call) | **Check and count in ONE locked step, BEFORE the slow work** — a count taken after the compare lets N parallel tries all pass the check (the shape R-983 removed from the dashboard and family sign-ins). A success clears the count afterwards. `shareRateLimited` and `escrowRateLimited` still have the old check-then-count shape | | `Scheduler.Every` / `Daily` | controller/internal/scheduler/scheduler.go | `(name, interval/"HH:MM", fn)` | ALL background jobs | Daily is Europe/Budapest, DST-safe (`nextDailyRun` avoids Add(24h)); register in main.go block (§5) | | `Scheduler.UpdateDaily` | controller/internal/scheduler/scheduler.go | `(name, "HH:MM") bool` | Retime a daily job at runtime (no restart) | Per-job buffered `resched` chan + select case in `runDailyJob`; false (WARN) on invalid time / unknown-or-non-daily name; read `Schedule` under the mutex in the loop | | `backupwindow.*` (LegTimes / GateWindow / EffectiveWindow / ParseHHMM / FmtHHMM / Valid) | controller/internal/backupwindow/backupwindow.go | pure `string`↔`int` | Backup-window arithmetic (v0.168.0) | Offsets (W+60m/W+105m, gate W+2h..W+6h) are CONSTANTS — derived, never stored; wrap-safe modulo 1440; `EffectiveWindow(settings, yaml)` = settings>yaml>"02:30" | diff --git a/controller/Dockerfile b/controller/Dockerfile index 3cd1836..855cc9e 100644 --- a/controller/Dockerfile +++ b/controller/Dockerfile @@ -49,9 +49,9 @@ RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build \ # cannot swap the binary. Pinned by TestR1105_ResticIsPinnedOutsideTheOS. FROM debian:13.7-slim@sha256:a29215f6a35e51e22adffa17f89e9d2ef06214e64a2bad10d765c46aea49f11f AS restic ARG TARGETARCH -ARG RESTIC_VERSION=0.18.1 -ARG RESTIC_SHA256_AMD64=680838f19d67151adba227e1570cdd8af12c19cf1735783ed1ba928bc41f363d -ARG RESTIC_SHA256_ARM64=87f53fddde38764095e9c058a3b31834052c37e5826d2acf34e18923c006bd45 +ARG RESTIC_VERSION=0.19.1 +ARG RESTIC_SHA256_AMD64=f415415624dcc452f2a02b8c33641791a8c6d6d3b65bbb3543fcf9a25151585c +ARG RESTIC_SHA256_ARM64=a5f64aaab53d51e311fa3829124c5b703f2d14cf187d8640b6be3b2b49376465 COPY third_party/restic/restic-release-key.asc /tmp/restic-release-key.asc RUN set -eu; \ apt-get update && apt-get install -y --no-install-recommends ca-certificates curl gnupg gpgv bzip2; \ diff --git a/controller/cmd/controller/main.go b/controller/cmd/controller/main.go index 5dd97dd..2602b52 100644 --- a/controller/cmd/controller/main.go +++ b/controller/cmd/controller/main.go @@ -3262,6 +3262,12 @@ func (a *stackAdapter) RecreateStackDefinitionFromUnit(name, composeSrcDir strin return nil } +// SetStackSecretValues writes the named values into the app's app.yaml (R-1106: the off-site restore's database +// password). The optional backup.secretValueSetter. +func (a *stackAdapter) SetStackSecretValues(name string, values map[string]string) error { + return a.mgr.SetStackSecretValues(name, values) +} + // StartStackServices brings up only the named compose services (the DB-only replay window, R-47). func (a *stackAdapter) StartStackServices(name string, services []string) error { return a.mgr.StartStackServices(name, services) diff --git a/controller/internal/appbackup/dbservices.go b/controller/internal/appbackup/dbservices.go index b4f5b41..585d937 100644 --- a/controller/internal/appbackup/dbservices.go +++ b/controller/internal/appbackup/dbservices.go @@ -3,6 +3,7 @@ package appbackup import ( "fmt" "os" + "regexp" "sort" "strings" @@ -80,3 +81,121 @@ func DBServiceNames(composePath string) ([]string, error) { sort.Strings(names) return names, nil } + +// dbCredentialKeyRe matches a database service's credential variable (POSTGRES_PASSWORD, MARIADB_ROOT_PASSWORD, +// MYSQL_PASSWORD, …): the engine images read these ONLY when they initialise an empty data directory, so once a +// restore puts a data directory back, the value that matches it is the one it was created with (R-1106). +var dbCredentialKeyRe = regexp.MustCompile(`^(POSTGRES|PG|MARIADB|MYSQL)_[A-Z_]*PASSWORD$`) + +// interpRefRe pulls the variable names out of a compose value: ${NAME}, ${NAME:-x}, ${NAME-x}, $NAME. +var interpRefRe = regexp.MustCompile(`\$\{([A-Za-z_][A-Za-z0-9_]*)(?:[:]?[-?+][^}]*)?\}|\$([A-Za-z_][A-Za-z0-9_]*)`) + +type composeDBEnvDoc struct { + Services map[string]struct { + Image string `yaml:"image"` + Environment yaml.Node `yaml:"environment"` + } `yaml:"services"` +} + +// DBCredentialVars (R-1106, `07` §7.4 — operator decision 1A, 2026-10-16) returns the sorted, unique app.yaml +// variable names that feed a database service's credential variables in composePath — e.g. rallly's +// `POSTGRES_PASSWORD=${DB_PASSWORD}` → DB_PASSWORD. These are the values a restore must put back WITH the data it puts +// back: a fresh install's generated value does not open a restored data directory. A literal credential (no +// variable) yields nothing — there is nothing to carry. Same parse and same DB predicate as DBServiceNames, so the +// two cannot disagree about which services hold a database. Pinned by TestR1106_DBCredentialVars*. +func DBCredentialVars(composePath string) ([]string, error) { + data, err := os.ReadFile(composePath) + if err != nil { + return nil, fmt.Errorf("reading compose file: %w", err) + } + var doc composeDBEnvDoc + if err := yaml.Unmarshal(data, &doc); err != nil { + return nil, fmt.Errorf("parsing compose file %s: %w", composePath, err) + } + seen := map[string]bool{} + add := func(key, val string) { + if !dbCredentialKeyRe.MatchString(key) { + return + } + for _, m := range interpRefRe.FindAllStringSubmatch(val, -1) { + n := m[1] + if n == "" { + n = m[2] + } + seen[n] = true + } + } + for _, svc := range doc.Services { + if _, ok := dbTypeForImage(svc.Image); !ok { + continue + } + env := svc.Environment + switch env.Kind { + case yaml.SequenceNode: // - KEY=value + for _, it := range env.Content { + if k, v, ok := strings.Cut(it.Value, "="); ok { + add(strings.TrimSpace(k), v) + } + } + case yaml.MappingNode: // KEY: value + for i := 0; i+1 < len(env.Content); i += 2 { + add(env.Content[i].Value, env.Content[i+1].Value) + } + } + } + out := make([]string, 0, len(seen)) + for n := range seen { + out = append(out, n) + } + sort.Strings(out) + return out, nil +} + +type composeDBVolDoc struct { + Services map[string]struct { + Image string `yaml:"image"` + Volumes []interface{} `yaml:"volumes"` + } `yaml:"services"` +} + +// DBDataVolumes (R-1106) returns the sorted NAMED volumes (not binds) that a database service in composePath mounts — +// its data directory. A restore that replays one of these puts back a data directory that only its own password +// opens; a restore that replays only a logical dump does not, and the current password stays right. +func DBDataVolumes(composePath string) ([]string, error) { + data, err := os.ReadFile(composePath) + if err != nil { + return nil, fmt.Errorf("reading compose file: %w", err) + } + var doc composeDBVolDoc + if err := yaml.Unmarshal(data, &doc); err != nil { + return nil, fmt.Errorf("parsing compose file %s: %w", composePath, err) + } + seen := map[string]bool{} + for _, svc := range doc.Services { + if _, ok := dbTypeForImage(svc.Image); !ok { + continue + } + for _, v := range svc.Volumes { + var src string + switch t := v.(type) { + case string: + src, _, _ = strings.Cut(t, ":") + case map[string]interface{}: + if typ, _ := t["type"].(string); typ != "" && typ != "volume" { + continue + } + src, _ = t["source"].(string) + } + if src == "" || strings.ContainsAny(src, "/.$~") { + continue // a bind or an interpolated path — not a named volume + } + seen[src] = true + } + } + out := make([]string, 0, len(seen)) + for n := range seen { + out = append(out, n) + } + sort.Strings(out) + return out, nil +} diff --git a/controller/internal/appbackup/paths.go b/controller/internal/appbackup/paths.go index 28c64f3..740fd08 100644 --- a/controller/internal/appbackup/paths.go +++ b/controller/internal/appbackup/paths.go @@ -56,7 +56,7 @@ func IsEnrolledDrive(drivePath, systemDataPath string) bool { // PrimaryBackupPath, RecoveryUnitPath and AppDataDir all take a NAMESPACE ROOT. If you are holding // something that came out of HDD_PATH or a StoragePath, it is a DRIVE path — put it through here // first. `UserdataDir(bareDrivePath)` still compiles and is still wrong; TestNoBareDrivePathToUserdataDir -// is the guard that keeps the count from growing. +// (userdata_bare_drive_guard_test.go, R-1017) is the guard that keeps the count from growing. func NamespaceRootFor(drivePath, systemDataPath string) string { return NamespaceRoot(drivePath, IsEnrolledDrive(drivePath, systemDataPath)) } diff --git a/controller/internal/appbackup/userdata_bare_drive_guard_test.go b/controller/internal/appbackup/userdata_bare_drive_guard_test.go new file mode 100644 index 0000000..c82df59 --- /dev/null +++ b/controller/internal/appbackup/userdata_bare_drive_guard_test.go @@ -0,0 +1,254 @@ +package appbackup + +import ( + "go/ast" + "go/parser" + "go/token" + "io/fs" + "os" + "path/filepath" + "sort" + "strconv" + "strings" + "testing" +) + +// TestNoBareDrivePathToUserdataDir is the guard the NamespaceRootFor doc comment (paths.go) names (R-1017). +// +// THE COUNT: UserdataDir takes a felhom-data NAMESPACE ROOT. R-203 found five callers passing a bare DRIVE path +// (HDD_PATH, a StoragePath) instead — identical on an enrolled drive, one `felhom-data` segment short on the +// system-data fallback, so the app and its backup looked in different directories while the run said ok. This +// test reads every non-test Go file of the module and checks the argument of EVERY UserdataDir call. An argument +// is accepted only when its shape says "namespace root" by construction: +// +// - a call to the resolver: NamespaceRootFor / NamespaceRoot, or a provider method documented as returning +// the namespace root (GetStackNamespaceRoot, StackNamespaceRoot, namespaceRoot); +// - filepath.Clean of an accepted argument; +// - an identifier named nsRoot — the contract's own parameter name. LIMIT, stated: a variable named nsRoot +// that holds a drive path passes; the name is the declaration the reviewer reads, and a lie there is a +// louder one than a bare `hddPath`. +// +// Anything else is a bare drive path until shown otherwise (fail-safe: ambiguity refuses). A reference to +// UserdataDir that is not a direct call (a func value) cannot be checked and is refused too. Known exceptions +// live in bareDriveAllowed with their reason; the test fails if one disappears too, so the list stays exact. +// +// COMPANION RED-PROOFS (R-1017): (1) a temporary `appbackup.UserdataDir(hddPath)` added to stacks/deploy.go → FAIL, +// naming the file and function; (2) userdataKept (stacks/delete.go) reverted to the bare hddPath → FAIL. +func TestNoBareDrivePathToUserdataDir(t *testing.T) { + root := moduleRoot(t) + calls, violations := scanUserdataDirCalls(t, root) + + // Positive control (rule 3: an absent finding is not evidence): the scan MUST reach the known callers, + // or a scope bug (wrong root, one-level walk) would turn this test green on an empty census. + for _, want := range []string{ + "internal/stacks/deploy.go:withPathVars", + "internal/appexport/export.go", + "internal/web/handlers.go", + "internal/appbackup/userdata.go", + } { + found := false + for _, c := range calls { + if strings.HasPrefix(c, want) { + found = true + break + } + } + if !found { + t.Errorf("the census did not reach %s — the scan is blind (calls seen: %v)", want, calls) + } + } + + got := map[string]bool{} + for _, v := range violations { + key := v.file + ":" + v.fn + if _, ok := bareDriveAllowed[key]; ok { + got[key] = true + continue + } + t.Errorf("%s:%d (%s): UserdataDir(%s) — the argument is not a namespace root by construction. "+ + "Put a drive path through appbackup.NamespaceRootFor(drive, systemDataPath) first (R-203).", + v.file, v.line, v.fn, v.arg) + } + for key, why := range bareDriveAllowed { + if !got[key] { + t.Errorf("allowed exception %s no longer passes a bare path — remove it from bareDriveAllowed (the count shrank; was: %s)", key, why) + } + } +} + +// bareDriveAllowed is the count. Keyed "relative/file.go:Function" (not a line number, which drifts). +var bareDriveAllowed = map[string]string{ + "internal/stacks/media_library.go:mediaBindSource": "drive comes from GetStoragePaths (MediaDrives); the system " + + "drive is never a registered StoragePath (R-203 changelog), so every such drive is an enrolled in-guest " + + "mount and IS its namespace root. Latent, not live — routing it needs the system-data path here.", +} + +type bareCall struct { + file, fn, arg string + line int +} + +const appbackupImport = "gitea.dooplex.hu/admin/felhom-controller/internal/appbackup" + +func moduleRoot(t *testing.T) string { + t.Helper() + dir, err := filepath.Abs(".") + if err != nil { + t.Fatal(err) + } + for { + if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { + return dir + } + parent := filepath.Dir(dir) + if parent == dir { + t.Fatal("go.mod not found above the test directory") + } + dir = parent + } +} + +// scanUserdataDirCalls returns every UserdataDir call site ("file:Func") and those whose argument is not a +// namespace root by construction. Recursive walk (os.walk, not one level — the R-421 scope trap). +func scanUserdataDirCalls(t *testing.T, root string) (calls []string, bad []bareCall) { + t.Helper() + fset := token.NewFileSet() + err := filepath.WalkDir(root, func(p string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if d.IsDir() { + n := d.Name() + if p != root && (n == "vendor" || n == "testdata" || n == "node_modules" || strings.HasPrefix(n, ".")) { + return filepath.SkipDir + } + return nil + } + if !strings.HasSuffix(p, ".go") || strings.HasSuffix(p, "_test.go") { + return nil + } + f, perr := parser.ParseFile(fset, p, nil, 0) + if perr != nil { + return perr + } + rel, _ := filepath.Rel(root, p) + rel = filepath.ToSlash(rel) + c, b := scanFile(fset, f, rel) + calls = append(calls, c...) + bad = append(bad, b...) + return nil + }) + if err != nil { + t.Fatalf("walking %s: %v", root, err) + } + sort.Strings(calls) + return calls, bad +} + +// scanFile finds the UserdataDir references of one file. Inside package appbackup the call is unqualified; +// elsewhere it is .UserdataDir for the appbackup import (alias honoured). +func scanFile(fset *token.FileSet, f *ast.File, rel string) (calls []string, bad []bareCall) { + inPkg := f.Name.Name == "appbackup" + alias := "" + for _, imp := range f.Imports { + if path, _ := strconv.Unquote(imp.Path.Value); path == appbackupImport { + alias = "appbackup" + if imp.Name != nil { + alias = imp.Name.Name + } + } + } + if !inPkg && alias == "" { + return nil, nil + } + isUserdataDir := func(e ast.Expr) bool { + switch x := e.(type) { + case *ast.Ident: + return inPkg && x.Name == "UserdataDir" + case *ast.SelectorExpr: + id, ok := x.X.(*ast.Ident) + return ok && alias != "" && id.Name == alias && x.Sel.Name == "UserdataDir" + } + return false + } + isResolver := func(fun ast.Expr) bool { + switch x := fun.(type) { + case *ast.Ident: + return inPkg && (x.Name == "NamespaceRootFor" || x.Name == "NamespaceRoot") + case *ast.SelectorExpr: + if id, ok := x.X.(*ast.Ident); ok && alias != "" && id.Name == alias { + return x.Sel.Name == "NamespaceRootFor" || x.Sel.Name == "NamespaceRoot" + } + switch x.Sel.Name { + case "GetStackNamespaceRoot", "StackNamespaceRoot", "namespaceRoot": + return true + } + } + return false + } + var nsRootArg func(e ast.Expr) bool + nsRootArg = func(e ast.Expr) bool { + switch x := e.(type) { + case *ast.ParenExpr: + return nsRootArg(x.X) + case *ast.Ident: + return x.Name == "nsRoot" + case *ast.CallExpr: + if sel, ok := x.Fun.(*ast.SelectorExpr); ok { + if id, ok := sel.X.(*ast.Ident); ok && id.Name == "filepath" && sel.Sel.Name == "Clean" && len(x.Args) == 1 { + return nsRootArg(x.Args[0]) + } + } + return isResolver(x.Fun) + } + return false + } + + visit := func(fn string, body ast.Node) { + called := map[ast.Expr]bool{} + ast.Inspect(body, func(n ast.Node) bool { + call, ok := n.(*ast.CallExpr) + if !ok || !isUserdataDir(call.Fun) { + return true + } + called[call.Fun] = true + calls = append(calls, rel+":"+fn) + if len(call.Args) != 1 || !nsRootArg(call.Args[0]) { + arg := "?" + if len(call.Args) == 1 { + arg = exprString(fset, call.Args[0]) + } + bad = append(bad, bareCall{file: rel, fn: fn, arg: arg, line: fset.Position(call.Pos()).Line}) + } + return true + }) + // A func-value reference (f := appbackup.UserdataDir) escapes the argument check — refuse it. + ast.Inspect(body, func(n ast.Node) bool { + e, ok := n.(ast.Expr) + if ok && isUserdataDir(e) && !called[e] { + bad = append(bad, bareCall{file: rel, fn: fn, arg: "", line: fset.Position(e.Pos()).Line}) + } + return true + }) + } + for _, decl := range f.Decls { + switch d := decl.(type) { + case *ast.FuncDecl: + if d.Body != nil { + visit(d.Name.Name, d.Body) + } + case *ast.GenDecl: + visit("", d) + } + } + return calls, bad +} + +func exprString(fset *token.FileSet, e ast.Expr) string { + start, end := fset.Position(e.Pos()), fset.Position(e.End()) + b, err := os.ReadFile(start.Filename) + if err != nil || end.Offset > len(b) { + return "?" + } + return string(b[start.Offset:end.Offset]) +} diff --git a/controller/internal/backup/offbox_capture.go b/controller/internal/backup/offbox_capture.go index f7535bf..fc7e49a 100644 --- a/controller/internal/backup/offbox_capture.go +++ b/controller/internal/backup/offbox_capture.go @@ -12,10 +12,12 @@ import ( // TierOffsite capture set (recovery unit + MANDATORY userdata only) into the extra absolute paths // appended to the app's restic snapshot, plus the Hungarian customer warnings for LOUD capture gaps. // -// SP-3.4 is law here: restic does NOT error on a missing source path — it skips with a warning, exits 0, -// and silently writes a partial snapshot (0.14.0, and re-measured on 0.18.1 for R-1105, 2026-10-16). So a skipped/missing MANDATORY path is detected in -// THIS function (the structural-guard Skipped list + an os.Stat filter) and surfaced in BOTH the -// English log and the Hungarian LastWarning. A restic exit code proves nothing about a missing path. +// SP-3.4 is law here: restic skips a missing source path with a warning and still writes a partial snapshot. +// 0.14.0 and 0.18.1 then exit 0; 0.19.x exits 3 (restic #4467 — measured 2026-10-16, R-1107), which the run reads +// as that app's failure. Either way the filter below keeps a declared-but-absent path out of argv, so only a path +// that vanishes between the stat and restic reaches it — and on 0.19 that race is now loud instead of silent. +// So a skipped/missing MANDATORY path is detected in THIS function (the structural-guard Skipped list + an os.Stat +// filter) and surfaced in BOTH the English log and the Hungarian LastWarning — never left to restic's exit code. // offboxBlocked records an app whose enlarged (userdata-carrying) push was refused by the pre-push // quota gate. The unit-only push still proceeds (never a protection regression). estBytes is the diff --git a/controller/internal/backup/offbox_reconstitute.go b/controller/internal/backup/offbox_reconstitute.go index b7c1c00..2866c72 100644 --- a/controller/internal/backup/offbox_reconstitute.go +++ b/controller/internal/backup/offbox_reconstitute.go @@ -828,12 +828,31 @@ func (m *Manager) ReconstituteFromOffsite(ctx context.Context, stack string, ack } } + // --- THE DATABASE PASSWORD COMES BACK WITH THE DATA (R-1106, `07` §7.4, decision 1A) --------- + // When the app keeps its own definition (same version), its app.yaml still holds the CURRENT install's database + // password — after a remove + reinstall, a freshly generated one that cannot open the data directory this restore + // is about to put back (measured 2026-10-16: Rallly crash-looped on auth, Grimmory was held). So when the snapshot + // replays a database service's data VOLUME, the snapshot's password is written into the app's settings before + // anything starts. A snapshot that replays only a logical dump leaves the current password alone — the dump goes + // into the current data directory, which the current password opens. Decided before the first mutation; a + // refusal touches nothing. (The other branch already gets this through unitRestoreEnv.) + var credOverlay map[string]string + if !defineFromSnapshot { + ov, oErr := m.offsiteCredentialOverlay(stack, scratchUnit, scratchCompose, man) + if oErr != nil { + return res, oErr + } + credOverlay = ov + } + definitionMoved := defineFromSnapshot || len(credOverlay) > 0 + // --- THE LIVE DEFINITION, KEPT FOR A FAILED REPLAY (R-893, `09` §3 decision 192) ------------- // When the snapshot's definition is about to be written, keep the LIVE one first, so a failed // replay below can write it back before the app is held. Taken before the first mutation; a // failure here refuses with nothing touched — without it the failure branch could not be undone. + // R-1106: the same when only the database password is about to move. var liveDef *liveDefinition - if defineFromSnapshot { + if definitionMoved { ld, ldErr := m.captureLiveDefinition(stack) if ldErr != nil { m.logger.Printf("[ERROR] [offbox] Restore REFUSED for %s: could not keep the live definition: %v — nothing was touched", stack, ldErr) @@ -919,6 +938,14 @@ func (m *Manager) ReconstituteFromOffsite(ctx context.Context, stack string, ack } return res, fmt.Errorf("restoring %s: writing the snapshot's definition failed: %w", stack, err) } + } else if len(credOverlay) > 0 { + if err := m.stackProvider.(secretValueSetter).SetStackSecretValues(stack, credOverlay); err != nil { + if sErr := restartStack(); sErr != nil { + m.logger.Printf("[WARN] [offbox] %s: restart after a failed password write also failed: %v", stack, sErr) + } + return res, fmt.Errorf("restoring %s: writing the backup's database password failed: %w", stack, err) + } + m.logger.Printf("[INFO] [offbox] %s: the backup's database password(s) %v written into the app's settings before the data (R-1106)", stack, credNames(credOverlay)) } copier := m.fullPlaceCopier() for _, pl := range placements { @@ -943,7 +970,7 @@ func (m *Manager) ReconstituteFromOffsite(ctx context.Context, stack string, ack if cErr != nil { // R-893 option C (security review 2026-10-08): once the snapshot's (possibly older) definition // is written, a start would run that version on the live data — HOLD the app instead. - if defineFromSnapshot { + if definitionMoved { m.holdAppAfterMixedRestore(stack, cErr, liveDef) return res, util.MsgError("err.backup.restore_failed_held_mixed", stack) } @@ -977,7 +1004,7 @@ func (m *Manager) ReconstituteFromOffsite(ctx context.Context, stack string, ack // already be the snapshot's — HOLD the app rather than start it on a mix. // R-893 option C (security review 2026-10-08): a volume already replaced, or the snapshot's // definition written → HOLD (the volume detail reaches the operator through the hold notice). - if defineFromSnapshot || nVols > 0 { + if definitionMoved || nVols > 0 { m.holdAppAfterMixedRestore(stack, vErr, liveDef) return res, util.MsgError("err.backup.restore_failed_held_mixed", stack) } @@ -997,7 +1024,7 @@ func (m *Manager) ReconstituteFromOffsite(ctx context.Context, stack string, ack if hasDB { if err := m.stackProvider.StartStackServices(stack, dbServices); err != nil { // R-893 option C (security review 2026-10-08): volumes or the definition already moved → HOLD. - if defineFromSnapshot || res.VolumesReplayed > 0 { + if definitionMoved || res.VolumesReplayed > 0 { m.holdAppAfterMixedRestore(stack, err, liveDef) return res, util.MsgError("err.backup.restore_failed_held_mixed", stack) } @@ -1044,7 +1071,7 @@ func (m *Manager) ReconstituteFromOffsite(ctx context.Context, stack string, ack // Pinned by r893_mixed_restore_test.go; the plain case keeps TestR379_ScenarioA. // Placed FILES alone do not hold (option C as ruled): that mix is what „put back exactly as it // was" (option A, the next slice) removes. - if defineFromSnapshot || res.VolumesReplayed > 0 { + if definitionMoved || res.VolumesReplayed > 0 { m.holdAppAfterMixedRestore(stack, iErr, liveDef) return res, util.MsgError("err.backup.db_restore_failed_held_mixed", stack) } diff --git a/controller/internal/backup/r1105_restic_versions_test.go b/controller/internal/backup/r1105_restic_versions_test.go index c8acc42..4b53870 100644 --- a/controller/internal/backup/r1105_restic_versions_test.go +++ b/controller/internal/backup/r1105_restic_versions_test.go @@ -12,13 +12,13 @@ import ( "time" ) -// R-1105: the off-site code was measured against restic 0.14.0; v0.323.0 ships 0.18.1. The fixtures in +// R-1105: the off-site code was measured against restic 0.14.0; v0.323.0 shipped 0.18.1, v0.324.0 ships 0.19.1 (R-1107). The fixtures in // testdata/restic// are REAL outputs of both official binaries, captured 2026-10-16 on one shared scratch -// repository (made by 0.14.0, so both versions read the same snapshot set; paths rewritten to /data/x). Each +// repository (made by 0.14.0, so every version reads the same snapshot set — recaptured for all three on 2026-10-16 20:10 UTC; paths rewritten to /data/x). Each // assumption the code makes about restic's output is asserted for BOTH versions through the code's own functions — // so a future restic that rewords one of them fails here, by name, instead of moving a failure to `unknown` on a // customer's box (07-backup-architecture.md §6.7, §6.8). -var r1105Versions = []string{"0.14.0", "0.18.1"} +var r1105Versions = []string{"0.14.0", "0.18.1", "0.19.1"} // [0] is the measured baseline; v0.324.0 ships the last func r1105Fixture(t *testing.T, version, name string) []byte { t.Helper() @@ -162,7 +162,7 @@ func TestR1105_TheJSONTheCodeReadsStillParses(t *testing.T) { t.Errorf("restic %s: no status line carried the totals the progress bar shows", v) } } - if counts["0.14.0"] != counts["0.18.1"] { + if counts["0.14.0"] != counts["0.18.1"] || counts["0.14.0"] != counts["0.19.1"] { t.Errorf("the two versions list a different number of snapshots of ONE repository: %v", counts) } } @@ -213,40 +213,42 @@ func TestR1105_TheForgetPlanOnlyEverKeepsMore(t *testing.T) { t.Errorf("restic %s: the guard refuses the honest plan: %s", v, refuse) } } - for id := range plans["0.18.1"] { - if !plans["0.14.0"][id] { - t.Errorf("0.18.1 removes snapshot %s, which 0.14.0 keeps — the new restic removes MORE", id) + for _, v := range r1105Versions[1:] { // every newer version against 0.14.0, the measured baseline + for id := range plans[v] { + if !plans["0.14.0"][id] { + t.Errorf("%s removes snapshot %s, which 0.14.0 keeps — the new restic removes MORE", v, id) + } } - } - // Every snapshot only 0.14.0 removes is one 0.18.1 keeps as the „oldest" of a window with unused slots. - var groups []struct { - Reasons []struct { - Snapshot struct { - ID string `json:"id"` - } `json:"snapshot"` - Matches []string `json:"matches"` - } `json:"reasons"` - } - if err := json.Unmarshal(r1105Fixture(t, "0.18.1", "forget-dryrun.json"), &groups); err != nil { - t.Fatal(err) - } - why := map[string]string{} - for _, g := range groups { - for _, r := range g.Reasons { - why[r.Snapshot.ID] = strings.Join(r.Matches, ",") + // Every snapshot only 0.14.0 removes is one the newer version keeps as the „oldest" of a window with unused slots. + var groups []struct { + Reasons []struct { + Snapshot struct { + ID string `json:"id"` + } `json:"snapshot"` + Matches []string `json:"matches"` + } `json:"reasons"` } - } - extra := 0 - for id := range plans["0.14.0"] { - if plans["0.18.1"][id] { - continue + if err := json.Unmarshal(r1105Fixture(t, v, "forget-dryrun.json"), &groups); err != nil { + t.Fatal(err) } - extra++ - if !strings.Contains(why[id], "oldest") { - t.Errorf("0.18.1 keeps snapshot %s that 0.14.0 removes, for a reason other than “oldest”: %q", id, why[id]) + why := map[string]string{} + for _, g := range groups { + for _, r := range g.Reasons { + why[r.Snapshot.ID] = strings.Join(r.Matches, ",") + } + } + extra := 0 + for id := range plans["0.14.0"] { + if plans[v][id] { + continue + } + extra++ + if !strings.Contains(why[id], "oldest") { + t.Errorf("%s keeps snapshot %s that 0.14.0 removes, for a reason other than “oldest”: %q", v, id, why[id]) + } + } + if extra == 0 { + t.Errorf("%s: the fixture no longer shows the 0.17+ “oldest” keep — it no longer tests the difference it documents", v) } - } - if extra == 0 { - t.Error("the fixture no longer shows the 0.17+ “oldest” keep — it no longer tests the difference it documents") } } diff --git a/controller/internal/backup/r1106_db_credentials_test.go b/controller/internal/backup/r1106_db_credentials_test.go new file mode 100644 index 0000000..cecff1f --- /dev/null +++ b/controller/internal/backup/r1106_db_credentials_test.go @@ -0,0 +1,301 @@ +package backup + +import ( + "context" + "io" + "log" + "os" + "path/filepath" + "reflect" + "strings" + "testing" + "time" +) + +// R-1106 (`07` §7.4, operator decision 1A): a restored database comes back with the password it was saved with. + +const r1106Compose = `services: + app: + image: ghcr.io/x/app:1 + environment: + - DATABASE_URL=postgresql://app:${DB_PASSWORD}@app-db:5432/app + app-db: + image: postgres:18-alpine + environment: + - POSTGRES_USER=app + - POSTGRES_PASSWORD=${DB_PASSWORD} + volumes: + - app_db_data:/var/lib/postgresql + - ./init:/docker-entrypoint-initdb.d + maria: + image: mariadb:11.4 + environment: + MARIADB_ROOT_PASSWORD: "${DB_ROOT_PASSWORD:-x}" + MARIADB_PASSWORD: literal-not-a-variable + MARIADB_DATABASE: app + volumes: + - type: volume + source: maria_data + target: /var/lib/mysql + cache: + image: redis:7-alpine + environment: + - REDIS_PASSWORD=${CACHE_PASSWORD} +` + +// r1106OneDB is one Postgres fed by DB_PASSWORD — the Rallly shape. +const r1106OneDB = `services: + app: + image: ghcr.io/x/app:1 + app-db: + image: postgres:18-alpine + environment: + - POSTGRES_PASSWORD=${DB_PASSWORD} + volumes: + - app_db_data:/var/lib/postgresql +` + +func TestR1106_DBCredentialVarsAndVolumes(t *testing.T) { + p := filepath.Join(t.TempDir(), "docker-compose.yml") + mustWrite(t, p, r1106Compose) + vars, err := DBCredentialVars(p) + if err != nil { + t.Fatal(err) + } + // list form, map form with a default; the literal yields nothing; redis is not a database. + if want := []string{"DB_PASSWORD", "DB_ROOT_PASSWORD"}; !reflect.DeepEqual(vars, want) { + t.Errorf("DBCredentialVars = %v, want %v", vars, want) + } + vols, err := DBDataVolumesFor(p) + if err != nil { + t.Fatal(err) + } + if want := []string{"app_db_data", "maria_data"}; !reflect.DeepEqual(vols, want) { + t.Errorf("DBDataVolumes = %v, want %v (binds are not volumes)", vols, want) + } +} + +func TestR1106_PlanDBCredentials(t *testing.T) { + data := time.Date(2026, 10, 16, 18, 0, 0, 0, time.UTC) + before, after := data.Add(-24*time.Hour), data.Add(time.Hour) + names := []string{"DB_PASSWORD"} + cases := []struct { + name string + unit map[string]string + live map[string]string + installed time.Time + dataAt time.Time + wantErr bool + wantUnit string + }{ + {"the unit's value wins over a reinstall's", map[string]string{"DB_PASSWORD": "old"}, map[string]string{"DB_PASSWORD": "new"}, after, data, false, "old"}, + {"unit lacks it, install OLDER than the data → kept", nil, map[string]string{"DB_PASSWORD": "same"}, before, data, false, ""}, + {"unit lacks it, install NEWER than the data → refused", nil, map[string]string{"DB_PASSWORD": "new"}, after, data, true, ""}, + {"unit lacks it, install time unknown → refused", nil, map[string]string{"DB_PASSWORD": "new"}, time.Time{}, data, true, ""}, + {"unit lacks it, data time unknown → refused", nil, map[string]string{"DB_PASSWORD": "new"}, before, time.Time{}, true, ""}, + {"nowhere at all → refused", nil, nil, before, data, true, ""}, + } + for _, c := range cases { + p, err := planDBCredentials(names, c.unit, c.live, c.installed, c.dataAt) + if (err != nil) != c.wantErr { + t.Errorf("%s: err = %v, wantErr %v", c.name, err, c.wantErr) + continue + } + if p.FromUnit["DB_PASSWORD"] != c.wantUnit { + t.Errorf("%s: FromUnit = %q, want %q", c.name, p.FromUnit["DB_PASSWORD"], c.wantUnit) + } + } +} + +// r1106UnitRestoreFixture: a unit whose compose has a database fed by DB_PASSWORD, a live install deployed AFTER the +// unit's data. unitPW "" = the unit carries no DB_PASSWORD. +func r1106UnitRestoreFixture(t *testing.T, unitPW string, guest map[string]string) (*Manager, *fakeRecoveryProvider, *[]string) { + t.Helper() + tmp := t.TempDir() + drive := filepath.Join(tmp, "drive") + composeDir := RecoveryUnitComposePath(drive, "app") + mustWrite(t, filepath.Join(composeDir, "docker-compose.yml"), r1106OneDB) + env := "deployed: true\nenv:\n SUBDOMAIN: trips\n" + portable := []string{} + if unitPW != "" { + env += " DB_PASSWORD: " + unitPW + "\n" + portable = []string{"DB_PASSWORD"} + } + mustWrite(t, filepath.Join(composeDir, "app.yaml"), env) + man := &RecoveryManifest{SchemaVersion: 2, AppName: "app", ControllerVer: "v", + SecretEnvVars: []string{"DB_PASSWORD"}, PortableSecretEnvVars: portable, + CreatedAt: "2026-10-16T18:00:00Z", DumpsAt: "2026-10-16T18:00:00Z"} + if err := writeManifest(RecoveryUnitManifestPath(drive, "app"), man); err != nil { + t.Fatal(err) + } + live := filepath.Join(tmp, "live") + mustWrite(t, filepath.Join(live, "docker-compose.yml"), r1106OneDB) + mustWrite(t, filepath.Join(live, "app.yaml"), "deployed: true\ndeployed_at: \"2026-10-16T19:00:00Z\"\nenv: {}\n") + fake := &fakeRecoveryProvider{hdd: drive, running: true, secrets: guest, info: RecoveryInfo{StackDir: live}} + m := &Manager{logger: log.New(io.Discard, "", 0), systemDataPath: filepath.Join(drive, "..", "sys"), stackProvider: fake} + var gen []string + m.generateSecret = func(_, envVar string) (string, bool) { gen = append(gen, envVar); return "GENERATED", true } + return m, fake, &gen +} + +// The on-box restore after a reinstall: the backup's password is the one the app gets. +func TestR1106_UnitRestoreUsesTheBackupsDBPassword(t *testing.T) { + m, fake, gen := r1106UnitRestoreFixture(t, "old-pw", map[string]string{"DB_PASSWORD": "new-pw-from-reinstall"}) + if _, err := m.RestoreFromRecoveryUnit("app"); err != nil { + t.Fatalf("restore: %v", err) + } + if fake.gotEnv["DB_PASSWORD"] != "old-pw" { + t.Errorf("DB_PASSWORD = %q, want the backup's value", fake.gotEnv["DB_PASSWORD"]) + } + if len(*gen) != 0 { + t.Errorf("a database password was generated: %v", *gen) + } +} + +// A unit without the database password, restored over a NEWER install: refused before anything changes, and never +// a generated password (O4 used to make one — the R-127 (b) trap). +func TestR1106_UnitRestoreNeverGeneratesADBPassword(t *testing.T) { + for name, guest := range map[string]map[string]string{ + "no value anywhere": nil, + "only the reinstall's new value": {"DB_PASSWORD": "new-pw-from-reinstall"}, + } { + m, fake, gen := r1106UnitRestoreFixture(t, "", guest) + _, err := m.RestoreFromRecoveryUnit("app") + if err == nil || !strings.Contains(err.Error(), "adatbázis jelszavát") { + t.Errorf("%s: want the refusal sentence, got %v", name, err) + } + if fake.gotEnv != nil || fake.stopped { + t.Errorf("%s: the current install was touched (recreate %v, stopped %v)", name, fake.gotEnv != nil, fake.stopped) + } + if len(*gen) != 0 { + t.Errorf("%s: a database password was generated: %v", name, *gen) + } + } +} + +// credProvider wraps the reconstitute fixture's provider with the live install's secrets, its app.yaml (for the +// install time) and the narrow writer, recording WHEN the writer ran relative to the other calls. +type credProvider struct { + *recordingProvider + live map[string]string + stackDir string + written map[string]string +} + +func (p *credProvider) RecoverStackSecrets(_ string, names []string) map[string]string { + out := map[string]string{} + for _, n := range names { + if v, ok := p.live[n]; ok { + out[n] = v + } + } + return out +} +func (p *credProvider) GetStackRecoveryInfo(string) (RecoveryInfo, bool) { + return RecoveryInfo{StackDir: p.stackDir}, true +} +func (p *credProvider) SetStackSecretValues(_ string, values map[string]string) error { + p.written = values + p.calls = append(p.calls, "setsecrets") + return nil +} + +// r1106ReconFixture: the reconstitute fixture with a database fed by DB_PASSWORD, a reinstall NEWER than the +// snapshot, the snapshot's unit carrying unitPW (or not), and the DB volume archive in the snapshot when withVolume. +func r1106ReconFixture(t *testing.T, unitPW string, withVolume bool) (*Manager, *credProvider) { + t.Helper() + m, prov, _ := reconFixture(t, "20261016T180000Z", "2026-10-16T18:00:00Z", pgDump(1)) + compose := `services: + immich-server: + image: ghcr.io/immich-app/immich-server:v3.0.3 + immich-postgres: + image: ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0 + environment: + - POSTGRES_PASSWORD=${DB_PASSWORD} + volumes: + - immich_postgres_data:/var/lib/postgresql/data +` + mustWrite(t, prov.composePath, compose) + stackDir := filepath.Dir(prov.composePath) + mustWrite(t, filepath.Join(stackDir, "app.yaml"), "deployed: true\ndeployed_at: \"2026-10-16T19:00:00Z\"\nenv: {}\n") + cp := &credProvider{recordingProvider: prov, live: map[string]string{"DB_PASSWORD": "new-pw-from-reinstall"}, stackDir: stackDir} + m.SetStackProvider(cp) + + scratch, _, err := m.offboxRestoreScratchDir("immich") + if err != nil { + t.Fatal(err) + } + unit := findScratchUnitDir(scratch, "immich") + env := "deployed: true\nenv:\n SUBDOMAIN: photos\n" + portable := []string{} + if unitPW != "" { + env += " DB_PASSWORD: " + unitPW + "\n" + portable = []string{"DB_PASSWORD"} + } + mustWrite(t, filepath.Join(UnitComposeDir(unit), "app.yaml"), env) + man := &RecoveryManifest{SchemaVersion: 2, AppName: "immich", OffsiteRunID: "20261016T180000Z", DumpsAt: "2026-10-16T18:00:00Z", + SecretEnvVars: []string{"DB_PASSWORD"}, PortableSecretEnvVars: portable} + if err := writeManifest(filepath.Join(unit, "manifest.json"), man); err != nil { + t.Fatal(err) + } + if withVolume { + seedScratchVolumes(t, m, "immich", "immich_immich_postgres_data.tar") + } + m.volumeReplayFrom = func(_, dir string) (int, error) { + cp.calls = append(cp.calls, "volumes") + entries, _ := os.ReadDir(dir) + return len(entries), nil + } + return m, cp +} + +// The drill's shape (Rallly, Grimmory, 2026-10-16): reinstall, then an off-site full restore that replays the DB +// volume. The backup's password must be in the app's settings BEFORE the database starts. +func TestR1106_OffsiteRestoreWritesTheBackupsDBPasswordBeforeTheDBStarts(t *testing.T) { + m, cp := r1106ReconFixture(t, "old-pw", true) + if _, err := m.ReconstituteFromOffsite(context.Background(), "immich", false); err != nil { + t.Fatalf("ReconstituteFromOffsite: %v", err) + } + if cp.written["DB_PASSWORD"] != "old-pw" { + t.Fatalf("the backup's password was not written (got %v)", cp.written) + } + set, db := -1, -1 + for i, c := range cp.calls { + if c == "setsecrets" && set < 0 { + set = i + } + if strings.HasPrefix(c, "startsvc:") && db < 0 { + db = i + } + } + if set < 0 || db < 0 || set > db { + t.Errorf("the password must be written before the database service starts; calls = %v", cp.calls) + } +} + +// The unit carries no password and the install is newer than the snapshot: refused, nothing stopped or written. +func TestR1106_OffsiteRestoreRefusesWithoutTheDBPassword(t *testing.T) { + m, cp := r1106ReconFixture(t, "", true) + _, err := m.ReconstituteFromOffsite(context.Background(), "immich", false) + if err == nil || !strings.Contains(err.Error(), "adatbázis jelszavát") { + t.Fatalf("want the refusal sentence, got %v", err) + } + for _, c := range cp.calls { + if c == "stop" || c == "setsecrets" || c == "volumes" { + t.Errorf("the current install was touched: calls = %v", cp.calls) + break + } + } +} + +// A snapshot that replays only a logical dump (no DB volume) must leave the current password alone: the dump goes +// into the current data directory, which only the current password opens. +func TestR1106_DumpOnlySnapshotKeepsTheCurrentPassword(t *testing.T) { + m, cp := r1106ReconFixture(t, "old-pw", false) + if _, err := m.ReconstituteFromOffsite(context.Background(), "immich", false); err != nil { + t.Fatalf("ReconstituteFromOffsite: %v", err) + } + if cp.written != nil { + t.Errorf("a dump-only restore rewrote the password: %v", cp.written) + } +} diff --git a/controller/internal/backup/restore_dbcreds.go b/controller/internal/backup/restore_dbcreds.go new file mode 100644 index 0000000..1a244a3 --- /dev/null +++ b/controller/internal/backup/restore_dbcreds.go @@ -0,0 +1,194 @@ +package backup + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "sort" + "time" + + "gitea.dooplex.hu/admin/felhom-controller/internal/appbackup" + "gitea.dooplex.hu/admin/felhom-controller/internal/stacks" + "gitea.dooplex.hu/admin/felhom-controller/internal/util" +) + +// R-1106 — A RESTORED DATABASE COMES BACK WITH THE PASSWORD IT WAS SAVED WITH (`07` §7.4, operator decision 1A, +// 2026-10-16). +// +// A database engine reads its credential variables (POSTGRES_PASSWORD, MARIADB_ROOT_PASSWORD, …) only when it +// initialises an EMPTY data directory. Once a restore has put a data directory back, the only password that opens it +// is the one it was created with. Measured 2026-10-16 on demo-hp (the drill in `audits/debian13-restic-2026-10-16/` +// part2): Rallly and Grimmory removed, reinstalled (the reinstall generated new passwords), restored from the +// off-site copy — the data came back and neither app could open it: Rallly crash-looped `P1000`, Grimmory's replay +// and its rollback failed `ERROR 1045` and it was held. +// +// The rule: for every app.yaml variable that feeds a database service's credential (appbackup.DBCredentialVars), the +// value the backup unit carries (D5 — every `type: secret` travels) WINS over the current install's. When the unit +// carries none, the current install's value is used only when that install is OLDER than the data being restored +// (so it is the value the data was written with); otherwise the restore is REFUSED before anything changes. A +// database credential is never generated for restored data (O4 no longer reaches these names). + +// errRestoreNoDBCredential is the refusal; the sentence is the bundle key's (HU + EN). +var errRestoreNoDBCredential = errors.New("restore refused: the backup does not carry the database password") + +// dbCredPlan is the decision for one restore: the credential values to put into the app's settings (unit values +// that differ from — or are absent in — the current install), and every credential name considered. +type dbCredPlan struct { + Names []string // every variable that feeds a DB credential in the compose that will run + FromUnit map[string]string // name → the unit's value, for every name the unit carries + KeptLocal []string // names the unit lacks whose CURRENT value predates the data (kept) +} + +// planDBCredentials decides, as a PURE function, which credential each DB variable gets. installedAt is when the +// current install was deployed (zero = unknown); dataAt is when the data being restored was captured (zero = +// unknown). An unknown time on either side never licenses the current value: unknown is not "older". +func planDBCredentials(names []string, unitSecrets, liveSecrets map[string]string, installedAt, dataAt time.Time) (dbCredPlan, error) { + p := dbCredPlan{Names: append([]string(nil), names...), FromUnit: map[string]string{}} + sort.Strings(p.Names) + var missing []string + for _, n := range p.Names { + if v := unitSecrets[n]; v != "" { + p.FromUnit[n] = v + continue + } + live := liveSecrets[n] + if live != "" && !installedAt.IsZero() && !dataAt.IsZero() && installedAt.Before(dataAt) { + p.KeptLocal = append(p.KeptLocal, n) + continue + } + missing = append(missing, n) + } + if len(missing) > 0 { + return p, fmt.Errorf("%w: %v (the current install is not older than the data, or no value at all)", errRestoreNoDBCredential, missing) + } + return p, nil +} + +// installedAt reads when the app's CURRENT install was deployed (app.yaml `deployed_at`). Zero when unknown. +func (m *Manager) installedAt(stack string) time.Time { + info, ok := m.stackProvider.GetStackRecoveryInfo(stack) + if !ok || info.StackDir == "" { + return time.Time{} + } + cfg := stacks.LoadAppConfig(info.StackDir) + if cfg == nil || cfg.DeployedAt == "" { + return time.Time{} + } + t, err := time.Parse(time.RFC3339, cfg.DeployedAt) + if err != nil { + return time.Time{} + } + return t +} + +// dbCredentialPlanFor reads the compose that will RUN (composePath), the unit's carried secrets and the live ones, +// and returns the plan — or the refusal, as the household's sentence, with the underlying reason logged. Nothing is +// written here. +func (m *Manager) dbCredentialPlanFor(stack, composePath string, unitSecrets map[string]string, dataAt time.Time) (dbCredPlan, error) { + if !fileExists(composePath) { + // A unit without its compose (never written by a current capture; old fixtures and hand-made units): read + // the LIVE definition instead — the variable NAMES do not change between installs of one template. + live, ok := m.stackProvider.GetStackComposePath(stack) + if !ok || live == "" || !fileExists(live) { + m.logger.Printf("[WARN] [backup] Restore %s: no compose to read the database password variables from — none checked", stack) + return dbCredPlan{FromUnit: map[string]string{}}, nil + } + composePath = live + } + names, err := DBCredentialVars(composePath) + if err != nil { + // "cannot tell" is not "no database password": refuse rather than restore blind. + m.logger.Printf("[ERROR] [backup] Restore REFUSED for %s: cannot read which variables hold the database password (%s): %v", stack, filepath.Base(composePath), err) + return dbCredPlan{}, util.MsgError("err.backup.restore_no_db_password") + } + if len(names) == 0 { + return dbCredPlan{FromUnit: map[string]string{}}, nil + } + live := m.stackProvider.RecoverStackSecrets(stack, names) + plan, perr := planDBCredentials(names, unitSecrets, live, m.installedAt(stack), dataAt) + if perr != nil { + m.logger.Printf("[ERROR] [backup] Restore REFUSED for %s before any change: %v (R-1106)", stack, perr) + return plan, util.MsgError("err.backup.restore_no_db_password") + } + m.logger.Printf("[INFO] [backup] Restore %s: database password(s) %v come from the backup, %v stay as installed (older than the data) — values not logged (R-1106)", + stack, credNames(plan.FromUnit), plan.KeptLocal) + return plan, nil +} + +func credNames(mp map[string]string) []string { + out := make([]string, 0, len(mp)) + for k := range mp { + out = append(out, k) + } + sort.Strings(out) + return out +} + +// secretValueSetter is the narrow write the off-site restore needs when the app keeps its own definition: put the +// named values into the app's settings (load-then-save, encrypted at rest) and nothing else. An optional interface +// so the many test fakes of StackProvider need no stub; a provider without it makes the restore REFUSE when a change +// is needed (fail-closed), never proceed with the wrong password. +type secretValueSetter interface { + SetStackSecretValues(name string, values map[string]string) error +} + +// DBCredentialVars forwards appbackup.DBCredentialVars. +func DBCredentialVars(composePath string) ([]string, error) { + return appbackup.DBCredentialVars(composePath) +} + +// offsiteCredentialOverlay (R-1106) decides, for an off-site restore that keeps the app's own definition, which +// database passwords to write into the app's settings: the snapshot's, for every DB credential whose value differs +// from the current install's — but ONLY when the snapshot replays a database service's data VOLUME (that data +// directory opens with its own password only). A dump-only snapshot changes nothing. Empty map = nothing to write. +func (m *Manager) offsiteCredentialOverlay(stack, scratchUnit, scratchCompose string, man *RecoveryManifest) (map[string]string, error) { + composeRun, ok := m.stackProvider.GetStackComposePath(stack) + if !ok || composeRun == "" { + return nil, nil // no live definition to read — the existing gates below decide (R-47's fail-closed refusal) + } + vols, err := DBDataVolumesFor(composeRun) + if err != nil { + m.logger.Printf("[ERROR] [offbox] Restore REFUSED for %s: cannot read the database volumes of the live definition: %v", stack, err) + return nil, util.MsgError("err.backup.restore_no_db_password") + } + replaysDBVolume := false + for _, v := range vols { + if fileExists(filepath.Join(scratchUnit, "volume-dumps", stack+"_"+v+".tar")) { + replaysDBVolume = true + break + } + } + if !replaysDBVolume { + return nil, nil + } + _, unitSecrets := readUnitEnv(filepath.Join(scratchCompose, "app.yaml"), man.PortableSecretEnvVars) + plan, err := m.dbCredentialPlanFor(stack, composeRun, unitSecrets, manifestDataTime(man)) + if err != nil { + return nil, err + } + live := m.stackProvider.RecoverStackSecrets(stack, plan.Names) + ov := map[string]string{} + for n, v := range plan.FromUnit { + if live[n] != v { + ov[n] = v + } + } + if len(ov) > 0 { + if _, ok := m.stackProvider.(secretValueSetter); !ok { + m.logger.Printf("[ERROR] [offbox] Restore REFUSED for %s: the database password must change and this provider cannot write it", stack) + return nil, fmt.Errorf("restoring %s: the backup's database password cannot be written", stack) + } + } + return ov, nil +} + +func fileExists(p string) bool { + st, err := os.Stat(p) + return err == nil && !st.IsDir() +} + +// DBDataVolumesFor forwards appbackup.DBDataVolumes. +func DBDataVolumesFor(composePath string) ([]string, error) { + return appbackup.DBDataVolumes(composePath) +} diff --git a/controller/internal/backup/restore_unit.go b/controller/internal/backup/restore_unit.go index 8c20fec..17189e4 100644 --- a/controller/internal/backup/restore_unit.go +++ b/controller/internal/backup/restore_unit.go @@ -511,6 +511,19 @@ func (m *Manager) unitRestoreEnv(stackName, composeDir string, manifest *Recover m.logger.Printf("[ERROR] [backup] Restore REFUSED for %s: %v", stackName, err) return nil, missing, err } + // R-1106 (`07` §7.4, decision 1A): the database password comes back WITH the data — the unit's value, or the + // current install's only when that install is older than the data; otherwise refused here, before any change. + dbPlan, perr := m.dbCredentialPlanFor(stackName, filepath.Join(composeDir, "docker-compose.yml"), unitSecrets, manifestDataTime(manifest)) + if perr != nil { + return nil, missing, perr + } + for n, v := range dbPlan.FromUnit { + fullEnv[n] = v + } + dbCredSet := make(map[string]bool, len(dbPlan.Names)) + for _, n := range dbPlan.Names { + dbCredSet[n] = true + } // O4: a missing RESETTABLE secret used to redeploy blank (compose "Defaulting to a blank // string" → exit 1). Generate a replacement via the deploy flow's generator instead — // RecreateStackFromUnit persists fullEnv through SaveAppConfig, so the new value lands @@ -534,7 +547,9 @@ func (m *Manager) unitRestoreEnv(stackName, composeDir string, manifest *Recover } var generated, unresolved []string for _, name := range missing { - if !dataKeySet[name] && m.generateSecret != nil { + // R-1106: never a database password — a generated one cannot open the restored data directory. + // (dbCredentialPlanFor refused already if one was unrecoverable; this is the second line.) + if !dataKeySet[name] && !dbCredSet[name] && m.generateSecret != nil { if v, ok := m.generateSecret(stackName, name); ok && v != "" { fullEnv[name] = v generated = append(generated, name) @@ -554,3 +569,20 @@ func (m *Manager) unitRestoreEnv(stackName, composeDir string, manifest *Recover } return fullEnv, missing, nil } + +// manifestDataTime is when the unit's DATA was captured: the data stamp (v0.275.0+), else the dump leg's end, else the +// unit's own creation time. Zero when none parses — and zero never licenses keeping the current install's password. +func manifestDataTime(man *RecoveryManifest) time.Time { + if man == nil { + return time.Time{} + } + if t, ok := man.Data.DataTime(); ok { + return t + } + for _, s := range []string{man.DumpsAt, man.CreatedAt} { + if t, err := time.Parse(time.RFC3339, s); err == nil { + return t + } + } + return time.Time{} +} diff --git a/controller/internal/backup/testdata/restic/0.14.0/backup-status.jsonl b/controller/internal/backup/testdata/restic/0.14.0/backup-status.jsonl index 909f57d..29d826c 100644 --- a/controller/internal/backup/testdata/restic/0.14.0/backup-status.jsonl +++ b/controller/internal/backup/testdata/restic/0.14.0/backup-status.jsonl @@ -1,2 +1,2 @@ {"message_type":"status","percent_done":0,"total_files":1,"total_bytes":41943040} -{"message_type":"status","percent_done":0.6679942601232657,"total_files":3,"files_done":2,"total_bytes":41943061,"bytes_done":28017724,"current_files":["/data/x/u/a/big.tar"]} +{"message_type":"status","percent_done":0.7110543744053397,"total_files":3,"files_done":2,"total_bytes":41943061,"bytes_done":29823797,"current_files":["/data/x/u/a/big.tar"]} diff --git a/controller/internal/backup/testdata/restic/0.14.0/check-damaged.txt b/controller/internal/backup/testdata/restic/0.14.0/check-damaged.txt index b55ae81..93e8fb1 100644 --- a/controller/internal/backup/testdata/restic/0.14.0/check-damaged.txt +++ b/controller/internal/backup/testdata/restic/0.14.0/check-damaged.txt @@ -1,14 +1,14 @@ -using temporary cache in /data/x/cache/restic-check-cache-279810929 +using temporary cache in /data/x/cache/restic-check-cache-1162611374 create exclusive lock for repository load indexes check all packs check snapshots, trees and blobs -error for tree 49327794: - decrypting blob 49327794eaad1ff31fb67ceb6bad31d812456993a7543d5fdf7ec8dad187e156 failed: ciphertext verification failed +error for tree 2dd49e74: + decrypting blob 2dd49e743c4d0b61ec5cfa2dc99f5446d5e7482635df00484aaa6a193aba98b8 failed: ciphertext verification failed [0:00] 100.00% 82 / 82 snapshots read all data -Pack ID does not match, want fc6016f0ad5e780ab7d800bd3012c8a602eb1dc9e291dedd61ea3d027befae72, got 39ddedb2fc2555d1e386d3eb7c440142ec3d7c02484f3d10db46105343393948 +Pack ID does not match, want fd6de2a5f8204c762b7a38c35a81a60785d6a542d3506a63dadad936b0aeb160, got d22a000a356e727dc3afaeef9408a189de77107618df88519e050153a5a653a8 [0:00] 100.00% 123 / 123 packs Fatal: repository contains errors diff --git a/controller/internal/backup/testdata/restic/0.14.0/check-ok.txt b/controller/internal/backup/testdata/restic/0.14.0/check-ok.txt index 925fc88..c74c0da 100644 --- a/controller/internal/backup/testdata/restic/0.14.0/check-ok.txt +++ b/controller/internal/backup/testdata/restic/0.14.0/check-ok.txt @@ -1,4 +1,4 @@ -using temporary cache in /data/x/cache/restic-check-cache-1995998052 +using temporary cache in /data/x/cache/restic-check-cache-2557640014 create exclusive lock for repository load indexes check all packs diff --git a/controller/internal/backup/testdata/restic/0.14.0/forget-dryrun.json b/controller/internal/backup/testdata/restic/0.14.0/forget-dryrun.json index 518bd37..1e619d8 100644 --- a/controller/internal/backup/testdata/restic/0.14.0/forget-dryrun.json +++ b/controller/internal/backup/testdata/restic/0.14.0/forget-dryrun.json @@ -1 +1 @@ -[{"tags":["a","felhom-offbox"],"host":"box","paths":null,"keep":[{"time":"2026-10-16T02:30:00Z","parent":"16f5cbf1aab3d6aaf201e9cf15f90b780e5db3854751f745883a6bd6e707d2dd","tree":"286f8da9b1b553de264161006b6f14be594a3eef691d3980954808cf02387f21","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"3e5346879326eed55c3c0ab2abcce53b9207c9f1da1a4f3ad1ee0ab831063651","short_id":"3e534687"},{"time":"2026-10-15T02:30:00Z","parent":"c980586cfb31f9bf16ec3a509de8d37160ea05102ffa4cfb12f3a834eb8317b3","tree":"cfc9e89d510b4d7500f66c7774f8fa1d26035be91e2de72bb5b35b5ff1565597","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"16f5cbf1aab3d6aaf201e9cf15f90b780e5db3854751f745883a6bd6e707d2dd","short_id":"16f5cbf1"},{"time":"2026-10-14T02:30:00Z","parent":"b6280f340819d34bf80b0a8edf7c9b378d04363483abd74b1a8a61dc921499e7","tree":"795573bb56c71a53b79b999ee8bf8abbdddd04e223191fa07976d2384c24370f","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"c980586cfb31f9bf16ec3a509de8d37160ea05102ffa4cfb12f3a834eb8317b3","short_id":"c980586c"},{"time":"2026-10-13T02:30:00Z","parent":"d85b77be2724c4e449fa4d5a51ade77b83f83d3fba834e322ff2a07575c413fa","tree":"13ab80d5668ef726b7c82ba2f73366f1fa9f2d25511d7cb3fe798582ec2d189d","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"b6280f340819d34bf80b0a8edf7c9b378d04363483abd74b1a8a61dc921499e7","short_id":"b6280f34"},{"time":"2026-10-12T02:30:00Z","parent":"3f14d64b4c7715903cff2a628a00a6e4c774e242a42400ef3fd24d3e3a1fee1a","tree":"1c1df704c5d5d3ac06dfc4a2d43ad706d692dbd78f3b5a6b983c2623d005cf2a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"d85b77be2724c4e449fa4d5a51ade77b83f83d3fba834e322ff2a07575c413fa","short_id":"d85b77be"},{"time":"2026-10-11T02:30:00Z","parent":"6d15ebd146b4ddf76a0f5501fe68a228a37afb00ff05d9e17fb0dd99934f3455","tree":"3ebf8ab552c78434bfdb5465cfb48338a3fa83744c2c41e79af0899cd5cef03c","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"3f14d64b4c7715903cff2a628a00a6e4c774e242a42400ef3fd24d3e3a1fee1a","short_id":"3f14d64b"},{"time":"2026-10-10T02:30:00Z","parent":"a25b1537a1ffedceb22b885753385f07e7435ff086258ea3ac14ed4446a4187d","tree":"bb0cd1b8820b86ccd427ce6049c08ea8e06b8719f000596f0835f6c9e001392b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"6d15ebd146b4ddf76a0f5501fe68a228a37afb00ff05d9e17fb0dd99934f3455","short_id":"6d15ebd1"},{"time":"2026-10-04T02:30:00Z","parent":"fab7e5d7ba440392bc8ee00c0c0fefb071168f03e3b58e3934aad0ff91560489","tree":"788dc5f69207e6351f2511edeb04473000634a2b3840570676f1f33ad7760bf4","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"039063a1d376f4c47fba5862f1314a29adefc05a23897519d30d86df701fd453","short_id":"039063a1"},{"time":"2026-09-30T02:30:00Z","parent":"78546e509597b716e8748b001bbf274e2068a0eaf74f7a5d888e65bc0dc5c5e3","tree":"66891382721b1b41319f9dc30cccd92e81e3d3794e2795c4d99da13a48a87ea9","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"67eb5eff9d3ce202877e027ce212fc1b914febce0d86455ed7a804053d402806","short_id":"67eb5eff"},{"time":"2026-09-27T02:30:00Z","parent":"9d3dd3268ab916288fab00729df16d85878fa9292576176e7d7e05b41babfa97","tree":"87434cf19bafe37d88781b28071ab4887feb96b0ded0b37bc27ac7bbd7e33e2e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"e5f43196aec8f410ffd7b2caf0d076ed0e7ebd92d5f04619c415b16ae56b7d1f","short_id":"e5f43196"}],"remove":[{"time":"2026-10-09T02:30:00Z","parent":"59960090510b6ead422be13c69e3bf87e2e53f0fe3246c460da3bac22e6d29a7","tree":"1aa9645c6d95bbe1fc5c0f81ea48122b346635fad67504ca44d4dc765ca7504e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"a25b1537a1ffedceb22b885753385f07e7435ff086258ea3ac14ed4446a4187d","short_id":"a25b1537"},{"time":"2026-10-08T02:30:00Z","parent":"f97353dadd1c5a066f26376a1e4de94e2e2924c30fc8336bce7226b17e8b47a4","tree":"9020a0778ef202f0dd278394e8c6e6f29ab5cb96190f80f1860b57a3ab8905ea","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"59960090510b6ead422be13c69e3bf87e2e53f0fe3246c460da3bac22e6d29a7","short_id":"59960090"},{"time":"2026-10-07T02:30:00Z","parent":"a34683b0a3bdf8f344804b0a8353d39663ed79484c336bcb3649178c18c62bef","tree":"59c955a77ad371adcd241705a113b07cf021164c7fea59eb8c305255924594d3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"f97353dadd1c5a066f26376a1e4de94e2e2924c30fc8336bce7226b17e8b47a4","short_id":"f97353da"},{"time":"2026-10-06T02:30:00Z","parent":"4c4f771ef180a648b16060f2d2b56f1c934f78bb2bb19ea71856b1ff3491f41c","tree":"a1eb787269c933c2cf52b73ac6953bc88cde2f53e69e75a868789e2469e59b2e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"a34683b0a3bdf8f344804b0a8353d39663ed79484c336bcb3649178c18c62bef","short_id":"a34683b0"},{"time":"2026-10-05T02:30:00Z","parent":"039063a1d376f4c47fba5862f1314a29adefc05a23897519d30d86df701fd453","tree":"d7f57de522610361b8f6e1ae3e1c8f0af6fff45b9caba60e79dbea09bad3e8bb","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"4c4f771ef180a648b16060f2d2b56f1c934f78bb2bb19ea71856b1ff3491f41c","short_id":"4c4f771e"},{"time":"2026-10-03T02:30:00Z","parent":"7afa8edcb7f984756564e202d29cdca8400309603590be914b3b7ee84934d4cf","tree":"e0fc2c64b57d15c40924e54e45e4f3f5cf6c88549d4ee60911c2a8069cb55c05","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"fab7e5d7ba440392bc8ee00c0c0fefb071168f03e3b58e3934aad0ff91560489","short_id":"fab7e5d7"},{"time":"2026-10-02T02:30:00Z","parent":"d808dbb1ec076b1e43762a470336464f7310a7e1a1ccad5d4f6aa049b492bb2d","tree":"461258fdd0946cb26ee3ec87c2b35db08921b497d9567e0cb921fa7953e1d724","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"7afa8edcb7f984756564e202d29cdca8400309603590be914b3b7ee84934d4cf","short_id":"7afa8edc"},{"time":"2026-10-01T02:30:00Z","parent":"67eb5eff9d3ce202877e027ce212fc1b914febce0d86455ed7a804053d402806","tree":"83aafad6973ac879054f312c0b7b9711f05e61144e67145c44763fedbc8da0f3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"d808dbb1ec076b1e43762a470336464f7310a7e1a1ccad5d4f6aa049b492bb2d","short_id":"d808dbb1"},{"time":"2026-09-29T02:30:00Z","parent":"ef9f435cf9a21c296e8cddbd73ae58e8c5c15e121c3b2a0d2773d371d365fa92","tree":"57ad9030700fd2929ef4d4325fb23070983ee4b909df35f62ecd60ca2dca7b6a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"78546e509597b716e8748b001bbf274e2068a0eaf74f7a5d888e65bc0dc5c5e3","short_id":"78546e50"},{"time":"2026-09-28T02:30:00Z","parent":"e5f43196aec8f410ffd7b2caf0d076ed0e7ebd92d5f04619c415b16ae56b7d1f","tree":"aebc8687a066367c7b527d14d7567d54bbe8c5803658ebf254a144c82670c5a2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"ef9f435cf9a21c296e8cddbd73ae58e8c5c15e121c3b2a0d2773d371d365fa92","short_id":"ef9f435c"},{"time":"2026-09-26T02:30:00Z","parent":"d9368785703ec3905bc9f6f716b4ebfbd0b2bb0692ddb704e4bf977e8aff1ff3","tree":"63233ccb5f095ca40bc126b605c297e3844685293c629d5d656da1a4c826a921","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"9d3dd3268ab916288fab00729df16d85878fa9292576176e7d7e05b41babfa97","short_id":"9d3dd326"},{"time":"2026-09-25T02:30:00Z","parent":"bb943a0960b2c03215e6b0462256450d9e67cc5214acd354db1a0cb0705a1696","tree":"9fea50e970c47996bcc1610eba645ae379ac87f0515b284df2985f536bf26d24","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"d9368785703ec3905bc9f6f716b4ebfbd0b2bb0692ddb704e4bf977e8aff1ff3","short_id":"d9368785"},{"time":"2026-09-24T02:30:00Z","parent":"5a13db8c85c9de7bd9957f4c382c557c6986eb4fa052fa773d3d6c056b522698","tree":"12224495435b7d8df970beab00e5efd0ba6c3d4d53aaf607a72816d861554e6b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"bb943a0960b2c03215e6b0462256450d9e67cc5214acd354db1a0cb0705a1696","short_id":"bb943a09"},{"time":"2026-09-23T02:30:00Z","parent":"c2d8f4210e52cdadd1327dab71f6c967affc51a7d0944027ece5e8654000d377","tree":"eb49dad786fdf2ab9c00b0633c34cf58de5224d70e74a3a9a31237d0c56b52fd","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"5a13db8c85c9de7bd9957f4c382c557c6986eb4fa052fa773d3d6c056b522698","short_id":"5a13db8c"},{"time":"2026-09-22T02:30:00Z","parent":"ed5a6be0ed1510c644e6ca1ce28d812099582240fafd4c475758a59dae75f268","tree":"373424cff38c1c809bf3c45e6b25d64d5ee96e16890350bb9ccd8f1807a36ca1","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"c2d8f4210e52cdadd1327dab71f6c967affc51a7d0944027ece5e8654000d377","short_id":"c2d8f421"},{"time":"2026-09-21T02:30:00Z","parent":"9fc7b97f4fea54dccefe6f9643c809c6221efc59c0efcab7aa34d459686cde0d","tree":"f18e6b1e580681cd98c27e89a258c39223b793385ea5f14cb4da8522501d1768","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"ed5a6be0ed1510c644e6ca1ce28d812099582240fafd4c475758a59dae75f268","short_id":"ed5a6be0"},{"time":"2026-09-20T02:30:00Z","parent":"3084ed321a45d2c70cd05dcda31fe2c324849add619a27229fb307a9e455f7a1","tree":"7a6b05c4b9ab4b817be0765cfd1c35ec846ef6da798bfd0ef34153fda3b3823f","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"9fc7b97f4fea54dccefe6f9643c809c6221efc59c0efcab7aa34d459686cde0d","short_id":"9fc7b97f"},{"time":"2026-09-19T02:30:00Z","parent":"a5fff383e0c4b921e8359bccf05d6f7bd2747fd481ef721a224118b88ff82ace","tree":"43b99b529fbfe9175e37b9739ddb72769d0877fbb543b65256da164e05008aff","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"3084ed321a45d2c70cd05dcda31fe2c324849add619a27229fb307a9e455f7a1","short_id":"3084ed32"},{"time":"2026-09-18T02:30:00Z","parent":"efcf3fcd77e50fc6dda0747daf9181f75f9663ed4505f8988f74b6433777be7f","tree":"178b66f451efe2d51b864e749502d8183db3d19faf346db7025fcc95035a6fd2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"a5fff383e0c4b921e8359bccf05d6f7bd2747fd481ef721a224118b88ff82ace","short_id":"a5fff383"},{"time":"2026-09-17T02:30:00Z","parent":"1e006efa46517bffcd436c66f28590127db1b083901aa86bb346846766b69f22","tree":"27b98f1320cc2b68ae8be3c27fb259471de7467083c444e465272564383aa374","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"efcf3fcd77e50fc6dda0747daf9181f75f9663ed4505f8988f74b6433777be7f","short_id":"efcf3fcd"},{"time":"2026-09-16T02:30:00Z","parent":"62717aad9a003d7fa57b87a2ea93d7d8954ab400b4ff0da966a9c04223fb1846","tree":"40e0a017a084528d33a98f78b4ad74cad1a33fc2f36cfaa9169635117b1618f9","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"1e006efa46517bffcd436c66f28590127db1b083901aa86bb346846766b69f22","short_id":"1e006efa"},{"time":"2026-09-15T02:30:00Z","parent":"4553f115de0d3983fa65b64b44be8ff1f82e40af54bb915b0fd3ab25d05f4d69","tree":"a7c63419c0fa17e1d62bdc3d9174e533754939eb4b02600662a0631b4561a83e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"62717aad9a003d7fa57b87a2ea93d7d8954ab400b4ff0da966a9c04223fb1846","short_id":"62717aad"},{"time":"2026-09-14T02:30:00Z","parent":"86ab152afd9baafe145fe9d1bd55af12a7ee4f44f61d899f998836e87d2b466d","tree":"422635882ea83f0e6e759795a1124db6cd51b6db0a04fda920296421d93ce92f","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"4553f115de0d3983fa65b64b44be8ff1f82e40af54bb915b0fd3ab25d05f4d69","short_id":"4553f115"},{"time":"2026-09-13T02:30:00Z","parent":"9afa939a8fc9758c4547b61dc77c51fb7f6ee563a4e33b2db6655358bb79b7e2","tree":"3b7db2503aaa703f480a67329b650f87bfd0e8561f611ad68d18a4e712d2a226","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"86ab152afd9baafe145fe9d1bd55af12a7ee4f44f61d899f998836e87d2b466d","short_id":"86ab152a"},{"time":"2026-09-12T02:30:00Z","parent":"6b9b78390e84353c864415e80862da09efb3948c726f9ea58d70957916ba5373","tree":"801be774e3bd1f6a006ddab0eba439a02ed0cb4865bd11722c0d54c33617d877","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"9afa939a8fc9758c4547b61dc77c51fb7f6ee563a4e33b2db6655358bb79b7e2","short_id":"9afa939a"},{"time":"2026-09-11T02:30:00Z","parent":"86e446b059058f35daf0e1f2255f8faa52a6f8fe582a0f9b5c2f2532c28548c4","tree":"daa8d607c445235bb4a6fe5169e1ee0d66fc0df2c40eee57e34c621d6f0c3747","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"6b9b78390e84353c864415e80862da09efb3948c726f9ea58d70957916ba5373","short_id":"6b9b7839"},{"time":"2026-09-10T02:30:00Z","parent":"0c3db5b724f38baaad8d504678a69c80ae77f66f14e517b10ffa7e88efbf678a","tree":"5b3d8750af755b0e38a9a63bc013bb83c8cd397094827edde8a0394009d49743","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"86e446b059058f35daf0e1f2255f8faa52a6f8fe582a0f9b5c2f2532c28548c4","short_id":"86e446b0"},{"time":"2026-09-09T02:30:00Z","parent":"46671301ce8fa7f064566a4caf267ea149c9099bb6e5d7f668f3ac6679bb42fb","tree":"b5d5c1b06b526a0472dd900185abb9b4f7bbd863df944aeb933e3f20b6dca653","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"0c3db5b724f38baaad8d504678a69c80ae77f66f14e517b10ffa7e88efbf678a","short_id":"0c3db5b7"},{"time":"2026-09-08T02:30:00Z","parent":"d7736f8cf82ac8c9e6d485943fa598a447ee094f3640de9b977eeca8298bdc05","tree":"b53736d4f878d0075076993c7edd16d73aca6a97ace6fd8639b43b1abbe78e56","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"46671301ce8fa7f064566a4caf267ea149c9099bb6e5d7f668f3ac6679bb42fb","short_id":"46671301"},{"time":"2026-09-07T02:30:00Z","parent":"e1d954f907f00b8337729a49bc71c9f4e7dc14dcb3f4547cc631a9d0ed34dedc","tree":"884bae5ecb7c125b0247b040e7dd662d29edb3adc027478bdfe82669511532e0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"d7736f8cf82ac8c9e6d485943fa598a447ee094f3640de9b977eeca8298bdc05","short_id":"d7736f8c"},{"time":"2026-09-06T02:30:00Z","tree":"d8d1be9062564caa6509955aefd722f7037d8fd270e339fe818dabd9bdbe5f10","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"e1d954f907f00b8337729a49bc71c9f4e7dc14dcb3f4547cc631a9d0ed34dedc","short_id":"e1d954f9"}],"reasons":[{"snapshot":{"time":"2026-10-16T02:30:00Z","parent":"16f5cbf1aab3d6aaf201e9cf15f90b780e5db3854751f745883a6bd6e707d2dd","tree":"286f8da9b1b553de264161006b6f14be594a3eef691d3980954808cf02387f21","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["daily snapshot","weekly snapshot","monthly snapshot"],"counters":{"daily":6,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-15T02:30:00Z","parent":"c980586cfb31f9bf16ec3a509de8d37160ea05102ffa4cfb12f3a834eb8317b3","tree":"cfc9e89d510b4d7500f66c7774f8fa1d26035be91e2de72bb5b35b5ff1565597","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"daily":5,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-14T02:30:00Z","parent":"b6280f340819d34bf80b0a8edf7c9b378d04363483abd74b1a8a61dc921499e7","tree":"795573bb56c71a53b79b999ee8bf8abbdddd04e223191fa07976d2384c24370f","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"daily":4,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-13T02:30:00Z","parent":"d85b77be2724c4e449fa4d5a51ade77b83f83d3fba834e322ff2a07575c413fa","tree":"13ab80d5668ef726b7c82ba2f73366f1fa9f2d25511d7cb3fe798582ec2d189d","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"daily":3,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-12T02:30:00Z","parent":"3f14d64b4c7715903cff2a628a00a6e4c774e242a42400ef3fd24d3e3a1fee1a","tree":"1c1df704c5d5d3ac06dfc4a2d43ad706d692dbd78f3b5a6b983c2623d005cf2a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"daily":2,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-11T02:30:00Z","parent":"6d15ebd146b4ddf76a0f5501fe68a228a37afb00ff05d9e17fb0dd99934f3455","tree":"3ebf8ab552c78434bfdb5465cfb48338a3fa83744c2c41e79af0899cd5cef03c","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["daily snapshot","weekly snapshot"],"counters":{"daily":1,"weekly":2,"monthly":5}},{"snapshot":{"time":"2026-10-10T02:30:00Z","parent":"a25b1537a1ffedceb22b885753385f07e7435ff086258ea3ac14ed4446a4187d","tree":"bb0cd1b8820b86ccd427ce6049c08ea8e06b8719f000596f0835f6c9e001392b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"weekly":2,"monthly":5}},{"snapshot":{"time":"2026-10-04T02:30:00Z","parent":"fab7e5d7ba440392bc8ee00c0c0fefb071168f03e3b58e3934aad0ff91560489","tree":"788dc5f69207e6351f2511edeb04473000634a2b3840570676f1f33ad7760bf4","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["weekly snapshot"],"counters":{"weekly":1,"monthly":5}},{"snapshot":{"time":"2026-09-30T02:30:00Z","parent":"78546e509597b716e8748b001bbf274e2068a0eaf74f7a5d888e65bc0dc5c5e3","tree":"66891382721b1b41319f9dc30cccd92e81e3d3794e2795c4d99da13a48a87ea9","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["monthly snapshot"],"counters":{"weekly":1,"monthly":4}},{"snapshot":{"time":"2026-09-27T02:30:00Z","parent":"9d3dd3268ab916288fab00729df16d85878fa9292576176e7d7e05b41babfa97","tree":"87434cf19bafe37d88781b28071ab4887feb96b0ded0b37bc27ac7bbd7e33e2e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["weekly snapshot"],"counters":{"monthly":4}}]},{"tags":["b","felhom-offbox"],"host":"box","paths":null,"keep":[{"time":"2026-10-16T02:30:00Z","parent":"331513b5478c67fd17b601f4e86536be66fdebac42db635d2b44073c418c9044","tree":"2479779a0246aded8ea88b1b43549f333df32233150ead772301d4060d9834b6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"1bb3e0b01ad4e9ef4092c0f4f38d003d026d3e62bd4ec32ad84d2ae50b1fc26b","short_id":"1bb3e0b0"},{"time":"2026-10-15T02:30:00Z","parent":"8d4189078ef8c5de57f8e0a58d646229c6ea05a584a223b13d6d52ee9b2a499a","tree":"c81de4fd5684584aecccba2848d623d9b46d27aaa7a8fda0cf7a4a56faa19f12","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"331513b5478c67fd17b601f4e86536be66fdebac42db635d2b44073c418c9044","short_id":"331513b5"},{"time":"2026-10-14T02:30:00Z","parent":"4a74cebcf061b3f721ce35f1dae2fe644c3dcb77620042d6a9e9a1f69ffa5908","tree":"22deec6d4575076f3b5b9228249ef0935883841659af9e60c2e471f903d301cf","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8d4189078ef8c5de57f8e0a58d646229c6ea05a584a223b13d6d52ee9b2a499a","short_id":"8d418907"},{"time":"2026-10-13T02:30:00Z","parent":"44f0faa89145f8dd68e06437323d677fae465f54c4f6aa95f938234ba0112f57","tree":"2f79914cd5a90ceb735c3dd272c22db5a67f5f1c6a35f48af320f7b218959177","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"4a74cebcf061b3f721ce35f1dae2fe644c3dcb77620042d6a9e9a1f69ffa5908","short_id":"4a74cebc"},{"time":"2026-10-12T02:30:00Z","parent":"9dcb3fa42c8d5b880c7e407ea15e134d540bab3fb250a63854c14dddb1748b79","tree":"7945e1927ec6444933dbe89befa7f342ffd218ab2a96d824a3e3cd9a25f11286","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"44f0faa89145f8dd68e06437323d677fae465f54c4f6aa95f938234ba0112f57","short_id":"44f0faa8"},{"time":"2026-10-11T02:30:00Z","parent":"b82290210fdaab03ba7fa7066ab61e31c5a3545d80a5dec4533fe21ded17dc95","tree":"41316836995752c254b9adce2243f694fab0421b8359109df23ea1fb996ce0fb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"9dcb3fa42c8d5b880c7e407ea15e134d540bab3fb250a63854c14dddb1748b79","short_id":"9dcb3fa4"},{"time":"2026-10-10T02:30:00Z","parent":"dd010c8b70468216b74dc107c0125f008c1e8a0d889481e481e40f8f82994764","tree":"f1ca437cda2b7f0db26af3d9b7509db45f238cd346a1f62bf801252daca93420","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"b82290210fdaab03ba7fa7066ab61e31c5a3545d80a5dec4533fe21ded17dc95","short_id":"b8229021"},{"time":"2026-10-04T02:30:00Z","parent":"eabaa0652f6549580fa3b1125f842209428a1b425016621190a4764bed2afb08","tree":"468d616ac9063de9f2829a1fd9d3d362af359c6ce79403d9bdb41f56707f7570","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"3a916d89540e17509b7c6ac5dc43d5842d268970dcb2470737a635e9ef343734","short_id":"3a916d89"},{"time":"2026-09-30T02:30:00Z","parent":"2ef32e3aec2169bfd005c607d23fa8caefd3597d5933a2ee6ef0992954439e11","tree":"a37fa979d19d953863ad8b8cb276382dcee1e0f2cfe1c87d91908d1a6a9a95e0","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"1b5e6b74f1abaf4d4f390be385bf34650eebe21aa034aeaba3e29150193532c2","short_id":"1b5e6b74"},{"time":"2026-09-27T02:30:00Z","parent":"b6c3ff0ed8c270eed4c0d1c691ad5fca3b4957f13d1bde79f29094150536529c","tree":"f06890a88f7ac258af5adf77d52b9f7b9fef3414ac7effce40eb52ebbab0fe29","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"88ce7523616beee04180afa0d25c2048c41d4431391e0c0c5c6e923921a9268e","short_id":"88ce7523"}],"remove":[{"time":"2026-10-09T02:30:00Z","parent":"0095d1024e633c17869e063c307b6e7ef74dd54a0e8c406c91bf38ca7ad16f1b","tree":"c14587a70d549b4cf45f6091ba985e7c57911d9ce65aa0ae6fcbb54cd2798320","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"dd010c8b70468216b74dc107c0125f008c1e8a0d889481e481e40f8f82994764","short_id":"dd010c8b"},{"time":"2026-10-08T02:30:00Z","parent":"20cccbaa5b814f5a1a1816d1c49af6f4703dd33e7c62faf4a2152d15161c45f0","tree":"58a11c46cd107e285a02424d5fedf8c6c3831ec57d5231dca34a77221478230f","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"0095d1024e633c17869e063c307b6e7ef74dd54a0e8c406c91bf38ca7ad16f1b","short_id":"0095d102"},{"time":"2026-10-07T02:30:00Z","parent":"4600ed1a4a0a08348ad95e38368431242b4eeb9be82ca860c7dcd626833d38fb","tree":"e89d06f95e23814a4c5b36b1a61d51b59b621b0a1c0750ef93f71e2beff2e17b","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"20cccbaa5b814f5a1a1816d1c49af6f4703dd33e7c62faf4a2152d15161c45f0","short_id":"20cccbaa"},{"time":"2026-10-06T02:30:00Z","parent":"c86697c291b279d448ba785b6e600794a811980413d3119cc1e7dd4c07b15124","tree":"3b18bc51857c3b43ef3b7f7251a747a4aa1d860336c3276c1e895b8ed89c990e","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"4600ed1a4a0a08348ad95e38368431242b4eeb9be82ca860c7dcd626833d38fb","short_id":"4600ed1a"},{"time":"2026-10-05T02:30:00Z","parent":"3a916d89540e17509b7c6ac5dc43d5842d268970dcb2470737a635e9ef343734","tree":"353fcfbdbb2b33da457308307d2aca87f18cf9e45a4e3c8f56e1ee4060dc555f","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"c86697c291b279d448ba785b6e600794a811980413d3119cc1e7dd4c07b15124","short_id":"c86697c2"},{"time":"2026-10-03T02:30:00Z","parent":"3869db68bb5543ab788ddca26d61583a6137ff71d6be864be83762359192c232","tree":"2fcca788daf43bbcea34d3e41650cb2f94549620a997511365e9018d667db0d0","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"eabaa0652f6549580fa3b1125f842209428a1b425016621190a4764bed2afb08","short_id":"eabaa065"},{"time":"2026-10-02T02:30:00Z","parent":"6d39107b801aff3b7d929393c3070ccfee278387276db8aacf1b46b8a5da1e1c","tree":"ee800f29da370e89ef260c6be721d6dfb691c85b9ca2b35ff2bd2340c4fc737a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"3869db68bb5543ab788ddca26d61583a6137ff71d6be864be83762359192c232","short_id":"3869db68"},{"time":"2026-10-01T02:30:00Z","parent":"1b5e6b74f1abaf4d4f390be385bf34650eebe21aa034aeaba3e29150193532c2","tree":"aad23ab1f6a4a59f8e09fca43fa8927321a5cfa6707310a9a66ed4738ffd6c4d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"6d39107b801aff3b7d929393c3070ccfee278387276db8aacf1b46b8a5da1e1c","short_id":"6d39107b"},{"time":"2026-09-29T02:30:00Z","parent":"999889b6f8de7d3eafeaa86ad705420affcfdf646e10a0c366ee82f3bfa5a758","tree":"8636f52172dd153181a2eeeacadaf422a0ab9230d3a9eb300a323d9ecf6d2bda","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"2ef32e3aec2169bfd005c607d23fa8caefd3597d5933a2ee6ef0992954439e11","short_id":"2ef32e3a"},{"time":"2026-09-28T02:30:00Z","parent":"88ce7523616beee04180afa0d25c2048c41d4431391e0c0c5c6e923921a9268e","tree":"c7dada1e21510896f6475d62d0f2f88454c7719b0a74c79ce3593bc14f4d19ff","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"999889b6f8de7d3eafeaa86ad705420affcfdf646e10a0c366ee82f3bfa5a758","short_id":"999889b6"},{"time":"2026-09-26T02:30:00Z","parent":"738389466ef5b3f129a2392fb14371e16604c6a3071ad89b1cc97154539df00b","tree":"7a29695c4ffb7201fe199173c93083bf98a3eb6083d4171e819b25c385ee3292","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"b6c3ff0ed8c270eed4c0d1c691ad5fca3b4957f13d1bde79f29094150536529c","short_id":"b6c3ff0e"},{"time":"2026-09-25T02:30:00Z","parent":"3c149e5a2092648bbdf09398f04ee351b8eb3e43f5d9e5f92a216328fe2192a8","tree":"f766854d8b67adac39aa2971fe1eeda94a4adbde52cc473929e03cbc97f15929","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"738389466ef5b3f129a2392fb14371e16604c6a3071ad89b1cc97154539df00b","short_id":"73838946"},{"time":"2026-09-24T02:30:00Z","parent":"148fb7b1b6e4cc4ebb5ca99ea00cd92703065c4879c5edcf88890d082dd6f31c","tree":"f90e90886d9e47a708c439f90ab0b811e00372c122928d4db0b3a679643e7377","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"3c149e5a2092648bbdf09398f04ee351b8eb3e43f5d9e5f92a216328fe2192a8","short_id":"3c149e5a"},{"time":"2026-09-23T02:30:00Z","parent":"d27d1ae70c280fdb945c0366ba17c654d3b5be2516d8e4e6ae862a3be0cbac54","tree":"5ff035bfe269e00cbdca9b6c966b822a578ae26742a29938a89ac1ff92dd5fed","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"148fb7b1b6e4cc4ebb5ca99ea00cd92703065c4879c5edcf88890d082dd6f31c","short_id":"148fb7b1"},{"time":"2026-09-22T02:30:00Z","parent":"79792a9b1e5603f08b6228fae860d8c974313bccc6ff2dde76270f3cc521d5c7","tree":"76e67a0fd8eb8215e67487127e1823ec76db61eafde6f9519ffbc5388fd1de9f","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"d27d1ae70c280fdb945c0366ba17c654d3b5be2516d8e4e6ae862a3be0cbac54","short_id":"d27d1ae7"},{"time":"2026-09-21T02:30:00Z","parent":"e62e8764fadbcb8dd8b59fd2c861603fb48891e451a50c1f8d8fa84effe6c693","tree":"2fcc4e0dd7db7447990b38ec9c93ad2c83297ea1e9ab17b1b50c3c0f24637579","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"79792a9b1e5603f08b6228fae860d8c974313bccc6ff2dde76270f3cc521d5c7","short_id":"79792a9b"},{"time":"2026-09-20T02:30:00Z","parent":"57880fadf8682a92a4992909de29de94d2fff6f45689e2e82277b5cf8911f13f","tree":"6d32c2444b76fb0eb422b1290fb41309ba642c2c8389519a6ee286e5726594f1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"e62e8764fadbcb8dd8b59fd2c861603fb48891e451a50c1f8d8fa84effe6c693","short_id":"e62e8764"},{"time":"2026-09-19T02:30:00Z","parent":"9a5d9b218160f2a99d228dfbe7d5c94c425a55d34c931b958a5094981337efe3","tree":"e9c735d5260376c08bf4ba6ff9ca2c11325e9013a15509b4559c94c4170a6ae4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"57880fadf8682a92a4992909de29de94d2fff6f45689e2e82277b5cf8911f13f","short_id":"57880fad"},{"time":"2026-09-18T02:30:00Z","parent":"3610529c13a4b87deea7309dc9e352c96e79cd8c465d79590643c3192d3383ef","tree":"6a7b9de7f8a847690487acab15e9808a7c485a77da3202aa7394dfdb048ac828","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"9a5d9b218160f2a99d228dfbe7d5c94c425a55d34c931b958a5094981337efe3","short_id":"9a5d9b21"},{"time":"2026-09-17T02:30:00Z","parent":"0e064dcba9e15e96b4a5066b1847d550163d9943314615e34e7f4927c1ffe20a","tree":"1a527598187b2c775100f690c73af64d8cc662c84935eaf2256fee9730bb0766","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"3610529c13a4b87deea7309dc9e352c96e79cd8c465d79590643c3192d3383ef","short_id":"3610529c"},{"time":"2026-09-16T02:30:00Z","parent":"8905c672851940782321709d03e4d976cc8975aeb63c9ef50a7713ad2e257d75","tree":"3ca35c35a404dcd752bb371217365049d27737d3604af69924d070b520dd9ae2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"0e064dcba9e15e96b4a5066b1847d550163d9943314615e34e7f4927c1ffe20a","short_id":"0e064dcb"},{"time":"2026-09-15T02:30:00Z","parent":"7ca16908b1c9ba4e9c9719bed7e0ec0f3987e155bafaf5bab4bb0a903067ae07","tree":"489bf44b49d5679494a5d660eea153236adc9af8a6f768cee85b40c9444395fb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8905c672851940782321709d03e4d976cc8975aeb63c9ef50a7713ad2e257d75","short_id":"8905c672"},{"time":"2026-09-14T02:30:00Z","parent":"dd8abd92e055c916448d058660cc0b4ed63cb99a418b1941119c33bbb30f2e37","tree":"e0c2d3e7cdf6db59ffafe688a844e75c62211868b38efcdc6025cd497312f03d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"7ca16908b1c9ba4e9c9719bed7e0ec0f3987e155bafaf5bab4bb0a903067ae07","short_id":"7ca16908"},{"time":"2026-09-13T02:30:00Z","parent":"4facc0c230bf587cde80d5a3d3cbb62e938150316545d2f91f883a8f0f23560b","tree":"6f7f51fbf57abeb9fc1af9689e59212344b12e833a926b9ba1ada7dfb926bccc","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"dd8abd92e055c916448d058660cc0b4ed63cb99a418b1941119c33bbb30f2e37","short_id":"dd8abd92"},{"time":"2026-09-12T02:30:00Z","parent":"9a9b7aee5b1b8801a89190f64cd0a25cdc0de5dc90bf507727de8ee76b70d59d","tree":"56ea6daeaf9b8c6e55fe21d488e0c7b90d926290fc98da3de942ca4aa7b57ce1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"4facc0c230bf587cde80d5a3d3cbb62e938150316545d2f91f883a8f0f23560b","short_id":"4facc0c2"},{"time":"2026-09-11T02:30:00Z","parent":"24331fad4982bf1e6e5be6f899580e71f69a7a3dc29785b40ec595b16f9ede7b","tree":"b13daaa02a014a7f2811f6cd845bc427883833ac6e578677fffb9756cb08855d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"9a9b7aee5b1b8801a89190f64cd0a25cdc0de5dc90bf507727de8ee76b70d59d","short_id":"9a9b7aee"},{"time":"2026-09-10T02:30:00Z","parent":"c2dd9de7fe5ce5e76bf986b99c0115da212f8b07277da5c236092dc4144d8af3","tree":"09722b272016f5585fe991a8b5cd5a9451cbf778cb64d9d65ca1cde792e9ace7","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"24331fad4982bf1e6e5be6f899580e71f69a7a3dc29785b40ec595b16f9ede7b","short_id":"24331fad"},{"time":"2026-09-09T02:30:00Z","parent":"b56d7267f0f3775d7d75c1ec209267404aba5d08db7f6c6f31ea171efe8343b7","tree":"b0d2594624bb645cd6ef4be633d745c5ff09190768fb0188bdd8fedff6c785bd","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"c2dd9de7fe5ce5e76bf986b99c0115da212f8b07277da5c236092dc4144d8af3","short_id":"c2dd9de7"},{"time":"2026-09-08T02:30:00Z","parent":"b4b6cf86aa3c85ea88d095bac696ec1566e6095ad19ca7af9c1ff1814ab6380f","tree":"64c83bfdc2ae9e0a9e2ff79c96ea517b75e7af4c7162291cf9672aa9976e05c8","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"b56d7267f0f3775d7d75c1ec209267404aba5d08db7f6c6f31ea171efe8343b7","short_id":"b56d7267"},{"time":"2026-09-07T02:30:00Z","parent":"a4391a2d1fa176171693df8ccda6c8c334cf0736e64a36af579d5f7d8c23b20b","tree":"32e15b2de82fccb7de96c01942bf7f1045e338f18b24c86c200f37959831aa1e","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"b4b6cf86aa3c85ea88d095bac696ec1566e6095ad19ca7af9c1ff1814ab6380f","short_id":"b4b6cf86"},{"time":"2026-09-06T02:30:00Z","tree":"4ad0876539f4a3e21e3a3970e2acc6b054f595a2cf08a99fdcb5bb330bd24d49","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"a4391a2d1fa176171693df8ccda6c8c334cf0736e64a36af579d5f7d8c23b20b","short_id":"a4391a2d"}],"reasons":[{"snapshot":{"time":"2026-10-16T02:30:00Z","parent":"331513b5478c67fd17b601f4e86536be66fdebac42db635d2b44073c418c9044","tree":"2479779a0246aded8ea88b1b43549f333df32233150ead772301d4060d9834b6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["daily snapshot","weekly snapshot","monthly snapshot"],"counters":{"daily":6,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-15T02:30:00Z","parent":"8d4189078ef8c5de57f8e0a58d646229c6ea05a584a223b13d6d52ee9b2a499a","tree":"c81de4fd5684584aecccba2848d623d9b46d27aaa7a8fda0cf7a4a56faa19f12","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"daily":5,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-14T02:30:00Z","parent":"4a74cebcf061b3f721ce35f1dae2fe644c3dcb77620042d6a9e9a1f69ffa5908","tree":"22deec6d4575076f3b5b9228249ef0935883841659af9e60c2e471f903d301cf","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"daily":4,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-13T02:30:00Z","parent":"44f0faa89145f8dd68e06437323d677fae465f54c4f6aa95f938234ba0112f57","tree":"2f79914cd5a90ceb735c3dd272c22db5a67f5f1c6a35f48af320f7b218959177","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"daily":3,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-12T02:30:00Z","parent":"9dcb3fa42c8d5b880c7e407ea15e134d540bab3fb250a63854c14dddb1748b79","tree":"7945e1927ec6444933dbe89befa7f342ffd218ab2a96d824a3e3cd9a25f11286","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"daily":2,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-11T02:30:00Z","parent":"b82290210fdaab03ba7fa7066ab61e31c5a3545d80a5dec4533fe21ded17dc95","tree":"41316836995752c254b9adce2243f694fab0421b8359109df23ea1fb996ce0fb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["daily snapshot","weekly snapshot"],"counters":{"daily":1,"weekly":2,"monthly":5}},{"snapshot":{"time":"2026-10-10T02:30:00Z","parent":"dd010c8b70468216b74dc107c0125f008c1e8a0d889481e481e40f8f82994764","tree":"f1ca437cda2b7f0db26af3d9b7509db45f238cd346a1f62bf801252daca93420","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"weekly":2,"monthly":5}},{"snapshot":{"time":"2026-10-04T02:30:00Z","parent":"eabaa0652f6549580fa3b1125f842209428a1b425016621190a4764bed2afb08","tree":"468d616ac9063de9f2829a1fd9d3d362af359c6ce79403d9bdb41f56707f7570","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["weekly snapshot"],"counters":{"weekly":1,"monthly":5}},{"snapshot":{"time":"2026-09-30T02:30:00Z","parent":"2ef32e3aec2169bfd005c607d23fa8caefd3597d5933a2ee6ef0992954439e11","tree":"a37fa979d19d953863ad8b8cb276382dcee1e0f2cfe1c87d91908d1a6a9a95e0","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["monthly snapshot"],"counters":{"weekly":1,"monthly":4}},{"snapshot":{"time":"2026-09-27T02:30:00Z","parent":"b6c3ff0ed8c270eed4c0d1c691ad5fca3b4957f13d1bde79f29094150536529c","tree":"f06890a88f7ac258af5adf77d52b9f7b9fef3414ac7effce40eb52ebbab0fe29","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["weekly snapshot"],"counters":{"monthly":4}}]}] +[{"tags":["a","felhom-offbox"],"host":"box","paths":null,"keep":[{"time":"2026-10-16T02:30:00Z","parent":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","tree":"b830b8165dc45c4b23086a81004548a5a52a00060028f0d274d8098dcc168b49","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"94fc37b9bfe97271d4a0b0feda4443a5e2934a3557108dd521d0bfb2f49423c8","short_id":"94fc37b9"},{"time":"2026-10-15T02:30:00Z","parent":"47bbaa059c6e306c801b5f793e5f3500d1a0c258c3075855aa160276b4a0c704","tree":"a0dd167d57e68ce11fde606350779191cdc8c4413875240091be5880fb91c66e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","short_id":"27898187"},{"time":"2026-10-14T02:30:00Z","parent":"5339cf6d7ec710b3998e7bf52a09a17cbb5907d2c09ccf18ace19f525b812ae8","tree":"57ab0a0f2ea360c1fbdfbc3b700e0225fb347eb8e715750283bb4b46e1133bf3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"47bbaa059c6e306c801b5f793e5f3500d1a0c258c3075855aa160276b4a0c704","short_id":"47bbaa05"},{"time":"2026-10-13T02:30:00Z","parent":"26da1569ccbbd96c81a266beef45c84e5a4b6dc870f44a41a89c437ebb09c09f","tree":"3c0228aa205d8a36c5b4fe501ba5e50d638e219cf2cd4aef45f77e0ba9fc5bb0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"5339cf6d7ec710b3998e7bf52a09a17cbb5907d2c09ccf18ace19f525b812ae8","short_id":"5339cf6d"},{"time":"2026-10-12T02:30:00Z","parent":"23ae66812d30a5ba39d9ec618c3e3dd453a2883da4d07e7c39438168388069d9","tree":"b721e2ac4dcc985dd24b608acb6b5243dad979038229a6a5b8e501cc2d7bad8e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"26da1569ccbbd96c81a266beef45c84e5a4b6dc870f44a41a89c437ebb09c09f","short_id":"26da1569"},{"time":"2026-10-11T02:30:00Z","parent":"cd0707729940a95ae60e9297780e370798d6ed750dc711dc6c34c80c82a6f105","tree":"e408a9e30f5cb44933c7faaec25373d0874bc7e9447bf28ceda6fff612611d92","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"23ae66812d30a5ba39d9ec618c3e3dd453a2883da4d07e7c39438168388069d9","short_id":"23ae6681"},{"time":"2026-10-10T02:30:00Z","parent":"13ecd2eeb9d433ae4be796a9dd9e289b7f12aa55b807cbca1ac6d88b6033accd","tree":"0ad2f65dd3de6f7fe4f32210cc07fae810683c769591e3122e9c12acd64a4281","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"cd0707729940a95ae60e9297780e370798d6ed750dc711dc6c34c80c82a6f105","short_id":"cd070772"},{"time":"2026-10-04T02:30:00Z","parent":"0e6cad1bee36f6ce4c5d28d756f256bb692a1419cf91e29cc1a856c22d5975e7","tree":"4709d5189f78175060c473debd32bbc95e655c0a6e5ca9792c34b3fd0415de69","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"960d1e720e43e9cb467f170f45277f133494374baa337f93a8af1b973e4b84b3","short_id":"960d1e72"},{"time":"2026-09-30T02:30:00Z","parent":"35e79f2b266136d2be26273e4eabb20005fd5158e59539cd492b0c8e4bbfb2d3","tree":"56b96a8e688ab8190bddb0868d331ece565f8856aef3cdcfef32fc1518e6baf2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"5ae64e02898e62676cdb3ba4689ed25eb83588a65127d244e69417846e495d78","short_id":"5ae64e02"},{"time":"2026-09-27T02:30:00Z","parent":"e974e4a5987c5d524f227b4b091811a0488e5fed27cb736d511f009b13b13b1d","tree":"c5cb9ce2ff06516329a42aec557f7223e1a3c3801c502f7a53f0ab6414cedf15","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"7e67848219703f577e06ce2750b104a8c8f956978b05aafa4a205a3d258eb376","short_id":"7e678482"}],"remove":[{"time":"2026-10-09T02:30:00Z","parent":"c27b0d1dabe2d975d297daad5b01ad678fb4c88e2d1e6e6ed5f2cf4aa21c5410","tree":"0ffe8da4512fd658f56dc4ee240488b5d63ae4c07f742810846df3044a365f5a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"13ecd2eeb9d433ae4be796a9dd9e289b7f12aa55b807cbca1ac6d88b6033accd","short_id":"13ecd2ee"},{"time":"2026-10-08T02:30:00Z","parent":"2d383c39077530c4a9f98ba8dc20f014e210854d2c4f32f79b335a19388b1e89","tree":"f44bda5e625b1e7636d14efb44c79f9451ef71475b38751bd2c962d04f86ebd4","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"c27b0d1dabe2d975d297daad5b01ad678fb4c88e2d1e6e6ed5f2cf4aa21c5410","short_id":"c27b0d1d"},{"time":"2026-10-07T02:30:00Z","parent":"c7aee7b89b42a2539a75e863e0083ae8761ee7ed8826b5a6c3d49820c0e6ba26","tree":"87bbe7cfd2c5e04fffb43951ae72dbcdc26c2e4eac1be4fa384c26238139d7f3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"2d383c39077530c4a9f98ba8dc20f014e210854d2c4f32f79b335a19388b1e89","short_id":"2d383c39"},{"time":"2026-10-06T02:30:00Z","parent":"d1a3dffd18e46a92ee75c698f7c716727a942ace2efba7ccc2935b6087992908","tree":"978e63c6278adf45029b4c51f773aac5252d334e4d2782f2fac88174fedbb1ff","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"c7aee7b89b42a2539a75e863e0083ae8761ee7ed8826b5a6c3d49820c0e6ba26","short_id":"c7aee7b8"},{"time":"2026-10-05T02:30:00Z","parent":"960d1e720e43e9cb467f170f45277f133494374baa337f93a8af1b973e4b84b3","tree":"8bffed4ff0074c8dbc58f616ddfea18aae6a4bbafb6f3ead72cc2d6fdc7bb7d7","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"d1a3dffd18e46a92ee75c698f7c716727a942ace2efba7ccc2935b6087992908","short_id":"d1a3dffd"},{"time":"2026-10-03T02:30:00Z","parent":"cee066c08d1f2f222dd490fa86e4a7931be865004d0aaf50e63f8536d0e232ec","tree":"2fdf5cb4f765aeda71371e854f2b73e96ed86e5deb4b54faf6d45ad76756cfb5","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"0e6cad1bee36f6ce4c5d28d756f256bb692a1419cf91e29cc1a856c22d5975e7","short_id":"0e6cad1b"},{"time":"2026-10-02T02:30:00Z","parent":"bfaf7ca84276c21938171a2d38258647686386fc83df7f24a1b7d67de552202a","tree":"0fd6c21124d32f9e6a9ee6c3d3a740143c7d90683391082c42bd6cd3bfd0f530","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"cee066c08d1f2f222dd490fa86e4a7931be865004d0aaf50e63f8536d0e232ec","short_id":"cee066c0"},{"time":"2026-10-01T02:30:00Z","parent":"5ae64e02898e62676cdb3ba4689ed25eb83588a65127d244e69417846e495d78","tree":"b4403fd15f29eced5de4749e59d5b9fe2022030132fe5e9e4d6bb64f83a1cf92","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"bfaf7ca84276c21938171a2d38258647686386fc83df7f24a1b7d67de552202a","short_id":"bfaf7ca8"},{"time":"2026-09-29T02:30:00Z","parent":"a695cd17a42947d6a5f1d74db5dc14f508cffbd7f98582124a25c53d47defd21","tree":"07492d5c8986dadc99631897cd7c4acfe18ec97dd70898d09899d5cd87b9539e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"35e79f2b266136d2be26273e4eabb20005fd5158e59539cd492b0c8e4bbfb2d3","short_id":"35e79f2b"},{"time":"2026-09-28T02:30:00Z","parent":"7e67848219703f577e06ce2750b104a8c8f956978b05aafa4a205a3d258eb376","tree":"e03a49f45c2db8d9342d90626025311ca3592d7d78c6dd6eeb8ffed0848c7ae0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"a695cd17a42947d6a5f1d74db5dc14f508cffbd7f98582124a25c53d47defd21","short_id":"a695cd17"},{"time":"2026-09-26T02:30:00Z","parent":"ce4afadd45ee5a17b6e8f276704f99478bf5e82cc0870a5b4e6db3e07d64ace8","tree":"8f40b7ed62ec04ce4dd10a648fd97db920711a6f387503bb2a75f535de395656","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"e974e4a5987c5d524f227b4b091811a0488e5fed27cb736d511f009b13b13b1d","short_id":"e974e4a5"},{"time":"2026-09-25T02:30:00Z","parent":"264cbd7c1e22696db518c2b8aba55d9755e2799bab72d54d48f8521ae1740e84","tree":"0b332b3757a2111c5c5e1adcb59f011b4ce4716c350fbb289496525a612b27eb","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"ce4afadd45ee5a17b6e8f276704f99478bf5e82cc0870a5b4e6db3e07d64ace8","short_id":"ce4afadd"},{"time":"2026-09-24T02:30:00Z","parent":"6398aadc912ab1364b0c83f3e3ce51c3099bf74e018ac25107f51dbeed6b3c47","tree":"29e68a845705a5490fc07891a54fa6ff4d674183f4314f23361fb3d5c43b5057","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"264cbd7c1e22696db518c2b8aba55d9755e2799bab72d54d48f8521ae1740e84","short_id":"264cbd7c"},{"time":"2026-09-23T02:30:00Z","parent":"7b37aba5b0971c1f41c15269fe2157e320b4f6428920d743302e4a904e053f63","tree":"eac20fb1f7f17be350f01322cc58152ec05c680ba60706fa5f25db89bab1d264","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"6398aadc912ab1364b0c83f3e3ce51c3099bf74e018ac25107f51dbeed6b3c47","short_id":"6398aadc"},{"time":"2026-09-22T02:30:00Z","parent":"ab24192f7a961b8103bdf4c5a3ab7d2a13b949b6accb9d52d1411f49d9d0deea","tree":"1e0e3145356cbc6b68674824bdb7b2bc5524ab3fc8cbcb27368f9efb819c0124","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"7b37aba5b0971c1f41c15269fe2157e320b4f6428920d743302e4a904e053f63","short_id":"7b37aba5"},{"time":"2026-09-21T02:30:00Z","parent":"43902ad8c4d345ac41a98af33afc74fd36d2f6896fb45e94fe553ba3f2b51d0f","tree":"f10d8afc6c36f40a793446537a09092aab457abaddd2f5dd884273014ffd986b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"ab24192f7a961b8103bdf4c5a3ab7d2a13b949b6accb9d52d1411f49d9d0deea","short_id":"ab24192f"},{"time":"2026-09-20T02:30:00Z","parent":"c2e659092443ccc73500e061690d9f99b0a653e8dcc002f441cd359385045e0e","tree":"4ad27f2ca164c7d23866d5c06e75aa70ad20d8f86229816534ce7adcffb652a7","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"43902ad8c4d345ac41a98af33afc74fd36d2f6896fb45e94fe553ba3f2b51d0f","short_id":"43902ad8"},{"time":"2026-09-19T02:30:00Z","parent":"177c6f12c40c9f355adc60d0a875830e78353038462fe15beeb00f3afef04efe","tree":"a97bea5453e2a1a8913ee3965b4fec1632d677dfe0ecf74213efee6f43568e20","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"c2e659092443ccc73500e061690d9f99b0a653e8dcc002f441cd359385045e0e","short_id":"c2e65909"},{"time":"2026-09-18T02:30:00Z","parent":"a2be8e6be366d62cca9bc6d4e12b1c97a310051e2fa8a077dff1fb07e904000a","tree":"251699699303a792c841f497662af163952386fd70b2d6dcfa435bd0d902ace2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"177c6f12c40c9f355adc60d0a875830e78353038462fe15beeb00f3afef04efe","short_id":"177c6f12"},{"time":"2026-09-17T02:30:00Z","parent":"e0ec672a95aacf51c562acf57701aba0e725a1d811ce3a6f5c2ebad549a8c016","tree":"a037a5eb6e669bc15c6705f0c4eb665c729eefa37af2a196086ce1701230988e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"a2be8e6be366d62cca9bc6d4e12b1c97a310051e2fa8a077dff1fb07e904000a","short_id":"a2be8e6b"},{"time":"2026-09-16T02:30:00Z","parent":"0c24dfcc62048ac0b64dd13aad000479b47ceddfd2963119e631c488714f8cc3","tree":"39e7b89853eb47ec19c07a060be51173dd800a2d46417ae0201fefa3af33d90a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"e0ec672a95aacf51c562acf57701aba0e725a1d811ce3a6f5c2ebad549a8c016","short_id":"e0ec672a"},{"time":"2026-09-15T02:30:00Z","parent":"a74319ea5b78b3276b0aa7407b39f95e44c0676915ce815a979383d2afbc6e23","tree":"be3be59ec618cf36d26d6d3e8368b560ce88c60b6eda56e861c6f5146f667be2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"0c24dfcc62048ac0b64dd13aad000479b47ceddfd2963119e631c488714f8cc3","short_id":"0c24dfcc"},{"time":"2026-09-14T02:30:00Z","parent":"d6678aa268695bc4387fe3a857f3304013c2bd672dc1234cf2161343bf18efdc","tree":"fdc02ae7cab64e7ab641be509365b4b8201eaf3c6dddf7191ba01bbcd750d3ea","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"a74319ea5b78b3276b0aa7407b39f95e44c0676915ce815a979383d2afbc6e23","short_id":"a74319ea"},{"time":"2026-09-13T02:30:00Z","parent":"9224b1af26c1c1fe31395055f22158bf09cc541f4b59a59caf91b71f92bc63f1","tree":"a5b546be122e577d101aaa067994bae404a881925573c09a2576431b51bb3e82","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"d6678aa268695bc4387fe3a857f3304013c2bd672dc1234cf2161343bf18efdc","short_id":"d6678aa2"},{"time":"2026-09-12T02:30:00Z","parent":"8c127f74318a1ff657ebc803b1fda7fae31ff1e2e3e145c9bd137d04f9de9d92","tree":"57c13238258e80cccb13e8d4dac05a82f9c3da4ac3dc6a26e9b8f4736e478af1","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"9224b1af26c1c1fe31395055f22158bf09cc541f4b59a59caf91b71f92bc63f1","short_id":"9224b1af"},{"time":"2026-09-11T02:30:00Z","parent":"e4b8322da1d838315d2dd62509678d7b419924a0d7c4723062aa31140a417ac0","tree":"9b79e87705df56afe04f10b8a5e15cb8cc4abed0585815e54282b77cacd3eae6","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"8c127f74318a1ff657ebc803b1fda7fae31ff1e2e3e145c9bd137d04f9de9d92","short_id":"8c127f74"},{"time":"2026-09-10T02:30:00Z","parent":"d1c1d0c71c88d2f829b267adfdafbc1b19fdf184de6cdf1de28703cf46b40d65","tree":"ed7361b730a863510df1e3b9f7d25b810902e8e86e0e230632250186cc558b21","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"e4b8322da1d838315d2dd62509678d7b419924a0d7c4723062aa31140a417ac0","short_id":"e4b8322d"},{"time":"2026-09-09T02:30:00Z","parent":"1242b68c1b172bc4ae762fe874cd6dd8863ce3ae03961f5175c35fa26475d385","tree":"2bfaf9b4b8dabb68a2824ce5f48d27fda4ea94c2a960718bd84cabd59be13acf","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"d1c1d0c71c88d2f829b267adfdafbc1b19fdf184de6cdf1de28703cf46b40d65","short_id":"d1c1d0c7"},{"time":"2026-09-08T02:30:00Z","parent":"820d553d84f1c920803a156ffea356c7aacf469e7555f07ea8b9408d2021f254","tree":"f725d2ffc7382c23554b85a5381905f02a11b09d307c24cd20980bcb30dce47b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"1242b68c1b172bc4ae762fe874cd6dd8863ce3ae03961f5175c35fa26475d385","short_id":"1242b68c"},{"time":"2026-09-07T02:30:00Z","parent":"2a76397eb8a43be8c70dd687ab03fcd939f2f058f815804b9fa2e0f5d9d32376","tree":"70b21a93a7e8af3804e813d7d47cb5d936ebfff4ebf1b8b80a9834382142aee5","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"820d553d84f1c920803a156ffea356c7aacf469e7555f07ea8b9408d2021f254","short_id":"820d553d"},{"time":"2026-09-06T02:30:00Z","tree":"f685956bf88ee15d577e60f77a8ce561abdb2dd56eb1d00b26d5c59276add7a6","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"2a76397eb8a43be8c70dd687ab03fcd939f2f058f815804b9fa2e0f5d9d32376","short_id":"2a76397e"}],"reasons":[{"snapshot":{"time":"2026-10-16T02:30:00Z","parent":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","tree":"b830b8165dc45c4b23086a81004548a5a52a00060028f0d274d8098dcc168b49","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["daily snapshot","weekly snapshot","monthly snapshot"],"counters":{"daily":6,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-15T02:30:00Z","parent":"47bbaa059c6e306c801b5f793e5f3500d1a0c258c3075855aa160276b4a0c704","tree":"a0dd167d57e68ce11fde606350779191cdc8c4413875240091be5880fb91c66e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"daily":5,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-14T02:30:00Z","parent":"5339cf6d7ec710b3998e7bf52a09a17cbb5907d2c09ccf18ace19f525b812ae8","tree":"57ab0a0f2ea360c1fbdfbc3b700e0225fb347eb8e715750283bb4b46e1133bf3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"daily":4,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-13T02:30:00Z","parent":"26da1569ccbbd96c81a266beef45c84e5a4b6dc870f44a41a89c437ebb09c09f","tree":"3c0228aa205d8a36c5b4fe501ba5e50d638e219cf2cd4aef45f77e0ba9fc5bb0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"daily":3,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-12T02:30:00Z","parent":"23ae66812d30a5ba39d9ec618c3e3dd453a2883da4d07e7c39438168388069d9","tree":"b721e2ac4dcc985dd24b608acb6b5243dad979038229a6a5b8e501cc2d7bad8e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"daily":2,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-11T02:30:00Z","parent":"cd0707729940a95ae60e9297780e370798d6ed750dc711dc6c34c80c82a6f105","tree":"e408a9e30f5cb44933c7faaec25373d0874bc7e9447bf28ceda6fff612611d92","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["daily snapshot","weekly snapshot"],"counters":{"daily":1,"weekly":2,"monthly":5}},{"snapshot":{"time":"2026-10-10T02:30:00Z","parent":"13ecd2eeb9d433ae4be796a9dd9e289b7f12aa55b807cbca1ac6d88b6033accd","tree":"0ad2f65dd3de6f7fe4f32210cc07fae810683c769591e3122e9c12acd64a4281","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"weekly":2,"monthly":5}},{"snapshot":{"time":"2026-10-04T02:30:00Z","parent":"0e6cad1bee36f6ce4c5d28d756f256bb692a1419cf91e29cc1a856c22d5975e7","tree":"4709d5189f78175060c473debd32bbc95e655c0a6e5ca9792c34b3fd0415de69","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["weekly snapshot"],"counters":{"weekly":1,"monthly":5}},{"snapshot":{"time":"2026-09-30T02:30:00Z","parent":"35e79f2b266136d2be26273e4eabb20005fd5158e59539cd492b0c8e4bbfb2d3","tree":"56b96a8e688ab8190bddb0868d331ece565f8856aef3cdcfef32fc1518e6baf2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["monthly snapshot"],"counters":{"weekly":1,"monthly":4}},{"snapshot":{"time":"2026-09-27T02:30:00Z","parent":"e974e4a5987c5d524f227b4b091811a0488e5fed27cb736d511f009b13b13b1d","tree":"c5cb9ce2ff06516329a42aec557f7223e1a3c3801c502f7a53f0ab6414cedf15","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"]},"matches":["weekly snapshot"],"counters":{"monthly":4}}]},{"tags":["b","felhom-offbox"],"host":"box","paths":null,"keep":[{"time":"2026-10-16T02:30:00Z","parent":"ee8432e0cd7bb4113731adc2e76d492238b539c3d6ce24a408670fee40579e57","tree":"024c36c1f532ac9150f9768ed57bb27cb284f8949f51958804dfd0f11ee70b65","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"315ff629674caa42ace8498b9d4bb82e5a77cb2284e628560444e12d9072ec8f","short_id":"315ff629"},{"time":"2026-10-15T02:30:00Z","parent":"2b09f89771cf2744dde14e804ed9e7342871c8a6c1cb4849b8128f5d2571342f","tree":"8f361f971daac52f40180aa7fd3e4638e4ef90903699241b16954ee17fa304e6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"ee8432e0cd7bb4113731adc2e76d492238b539c3d6ce24a408670fee40579e57","short_id":"ee8432e0"},{"time":"2026-10-14T02:30:00Z","parent":"e3fc65e0827c6939f7d86880e75facf36c2692f9cd259fe880232ee7de2a5391","tree":"377caf3fbe1e17b4af93cc053064cde6b40976809805fcdebb0645e41b649ffb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"2b09f89771cf2744dde14e804ed9e7342871c8a6c1cb4849b8128f5d2571342f","short_id":"2b09f897"},{"time":"2026-10-13T02:30:00Z","parent":"4a611990c2123e859808a8546af22c372308a27a87b335aeeb89276e97049165","tree":"279178ad0293ba5157fdd209ec244a1d4899b58e1b9459c11ecac057cac60ff4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"e3fc65e0827c6939f7d86880e75facf36c2692f9cd259fe880232ee7de2a5391","short_id":"e3fc65e0"},{"time":"2026-10-12T02:30:00Z","parent":"8ff9e57a4c7e509cd5e49202f3617630771e0d839ad04911b8106b8b7c4207af","tree":"879f6a9563bba4bcdebbea7f32c27b9e452615464c6dc3111c2df59cd661a8a1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"4a611990c2123e859808a8546af22c372308a27a87b335aeeb89276e97049165","short_id":"4a611990"},{"time":"2026-10-11T02:30:00Z","parent":"5e76f560c4d54a477fce35b1a96ce61374291dc8fa52b6dfb76fde6d91f25bdb","tree":"afe3b0d5eaf569af22f299df9b77ccd8166b7c654c0e886b7452bb10512d0706","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8ff9e57a4c7e509cd5e49202f3617630771e0d839ad04911b8106b8b7c4207af","short_id":"8ff9e57a"},{"time":"2026-10-10T02:30:00Z","parent":"29607a0ab3c4afc1d63525a96605bb44e0b5f4de690d1ed44bfd3bbc27025fa2","tree":"357713e3a55168ec6bea559274dc7552b4fbd64381ce4bde9022e242ec328ad1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"5e76f560c4d54a477fce35b1a96ce61374291dc8fa52b6dfb76fde6d91f25bdb","short_id":"5e76f560"},{"time":"2026-10-04T02:30:00Z","parent":"7c1f837ad939b4f4c376a0ff177862f08d87e4616cbe8e54a60d4a666b804ce7","tree":"a5e934915e68d97267ee3b108c7ee16ea0867e651b9232443fe919d83fa3a4c2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"fa1d764f43f6190cf22b9a763d8cc972d7dc3bb01aaf4f1074e56dbfc350c5e8","short_id":"fa1d764f"},{"time":"2026-09-30T02:30:00Z","parent":"cb87227f0c1c6acf4999c4b2024b589203cb184ce089a01a2db472ddbb560380","tree":"b778b7edf7fa14307405e72c16f20050fc813cf944bda6b445d209db77e4bc00","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8e604e28a0930828c9080477856be09c1475c467ac41f6ded7e2da5bdb3571ac","short_id":"8e604e28"},{"time":"2026-09-27T02:30:00Z","parent":"b26700ff3e9871ac081886d146fc30b9d8e7bd4572cea0b62f8f0261ea1a4f9d","tree":"21aa00a24cb6990028d074e46a5af0457b5bc87da6867d0857663f776247b8cc","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"e24109dd53394e0bd7278f7b5e3fffa90f685bfdcd0a93952cff5638967a13fe","short_id":"e24109dd"}],"remove":[{"time":"2026-10-09T02:30:00Z","parent":"ec2a30d9ff60c7473067c0f6b620948f728174c7a5bb8eddfa238f0d8af5066f","tree":"2e07df0532a24fe466f5fe8415b3c4e7a208d130974b1543591f7d5e42be04ba","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"29607a0ab3c4afc1d63525a96605bb44e0b5f4de690d1ed44bfd3bbc27025fa2","short_id":"29607a0a"},{"time":"2026-10-08T02:30:00Z","parent":"a818ad6aa46ec61c586a0ffb38e63148a69c7bbc08fd0a09acb6734278fbd63b","tree":"4caaed0b8ce301dc03a64b5fe8e441a3bf6cb9297bf96ad72d62c3b45525ef01","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"ec2a30d9ff60c7473067c0f6b620948f728174c7a5bb8eddfa238f0d8af5066f","short_id":"ec2a30d9"},{"time":"2026-10-07T02:30:00Z","parent":"a0ad00ea114be1368fbce2b72ca2f638b904795e73124adb8bd25ae30458933e","tree":"a360e27e1aef84a6eacdf3dba92ab0a46a3628869c2af12d3c1b412863b0535d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"a818ad6aa46ec61c586a0ffb38e63148a69c7bbc08fd0a09acb6734278fbd63b","short_id":"a818ad6a"},{"time":"2026-10-06T02:30:00Z","parent":"2a9ca46af4806ddc2989b343739647e93f622ce863a6610d58e3e5b5f1bae413","tree":"1782fe2e236f85c58cf9b786a7737b5e7974ad71b960bfeaf4240bc528fec665","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"a0ad00ea114be1368fbce2b72ca2f638b904795e73124adb8bd25ae30458933e","short_id":"a0ad00ea"},{"time":"2026-10-05T02:30:00Z","parent":"fa1d764f43f6190cf22b9a763d8cc972d7dc3bb01aaf4f1074e56dbfc350c5e8","tree":"d74e551770184290eb6224af4d48c4008a5b3b7e7cb8204eb3c85c14354d19df","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"2a9ca46af4806ddc2989b343739647e93f622ce863a6610d58e3e5b5f1bae413","short_id":"2a9ca46a"},{"time":"2026-10-03T02:30:00Z","parent":"bd15d29185bb8d6e805451f5e17315396cf315d27c4ca53b9d31d0798ce9d182","tree":"f1dad16a3035d09aac43fe50021f0d0c50ff022c54b28b5c499cf572c95b5746","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"7c1f837ad939b4f4c376a0ff177862f08d87e4616cbe8e54a60d4a666b804ce7","short_id":"7c1f837a"},{"time":"2026-10-02T02:30:00Z","parent":"23ab590268b600c179d6636df65055810c0def0e99a571cdcb7890c556446cc2","tree":"65f5c632a0d2b90ad809a363562f24e3f66d1c52483a9defd47b266da1af4199","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"bd15d29185bb8d6e805451f5e17315396cf315d27c4ca53b9d31d0798ce9d182","short_id":"bd15d291"},{"time":"2026-10-01T02:30:00Z","parent":"8e604e28a0930828c9080477856be09c1475c467ac41f6ded7e2da5bdb3571ac","tree":"bcd5f11e44998ee9e52c5b89ea0a4867e06475bc90b5cb4267364ab6146c9d01","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"23ab590268b600c179d6636df65055810c0def0e99a571cdcb7890c556446cc2","short_id":"23ab5902"},{"time":"2026-09-29T02:30:00Z","parent":"f062f3c51cde5c848398daa1b47cd122d76a0639c76f9436983ae2657895f352","tree":"b99010471bc3056f04c0a8dd25fa412b4834f977d1a7600c03b03b1bb8a9d8fe","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"cb87227f0c1c6acf4999c4b2024b589203cb184ce089a01a2db472ddbb560380","short_id":"cb87227f"},{"time":"2026-09-28T02:30:00Z","parent":"e24109dd53394e0bd7278f7b5e3fffa90f685bfdcd0a93952cff5638967a13fe","tree":"7c0a07c56348b0fa19b9507bf17dada815bdf81517a714408db21e288fc554b3","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"f062f3c51cde5c848398daa1b47cd122d76a0639c76f9436983ae2657895f352","short_id":"f062f3c5"},{"time":"2026-09-26T02:30:00Z","parent":"d4562f249a7d2962d749dbaf843d8ac71b9c8ebb0c0b7cec09afcd8711529eea","tree":"36c5d5c1356cef66b9017f1411f798274554b52a7b01a8b4127ef1c30c6a02f6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"b26700ff3e9871ac081886d146fc30b9d8e7bd4572cea0b62f8f0261ea1a4f9d","short_id":"b26700ff"},{"time":"2026-09-25T02:30:00Z","parent":"0b0bc0701cee5d7533d4a97f4c9ef7f5a401eb552d2ca3536a1ed5cebeb83f97","tree":"c6508fdf7a64e55c2058145ba81f1b27e8687b8b2b2a4bd7324a157ef31ad12a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"d4562f249a7d2962d749dbaf843d8ac71b9c8ebb0c0b7cec09afcd8711529eea","short_id":"d4562f24"},{"time":"2026-09-24T02:30:00Z","parent":"0c73460e3fa99b3c38ef31c378515f2424f18877bd354994d053576aa58ec214","tree":"530b2ba5c60bab9cc6f56148cf6388dff62236a252592031c10df1e2dd2607d6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"0b0bc0701cee5d7533d4a97f4c9ef7f5a401eb552d2ca3536a1ed5cebeb83f97","short_id":"0b0bc070"},{"time":"2026-09-23T02:30:00Z","parent":"5e41a7b17484c04288c67cce0dbf9cb3046325a9617b27f33d128ea5e906eebe","tree":"1092cccb0c44787eb64ea2ea143189a5bf5d093ebfa0427d0cb07ac47543bcf4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"0c73460e3fa99b3c38ef31c378515f2424f18877bd354994d053576aa58ec214","short_id":"0c73460e"},{"time":"2026-09-22T02:30:00Z","parent":"8f870fe269857d1d611fff5e03d2b22533bce7dc5aad4340de6cdf434b5aa0ae","tree":"31fbee51dde5e56f1d5940902bf8428ee4a1a2825a6081dea2b3ffb60a66ca26","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"5e41a7b17484c04288c67cce0dbf9cb3046325a9617b27f33d128ea5e906eebe","short_id":"5e41a7b1"},{"time":"2026-09-21T02:30:00Z","parent":"ec0f30baecf767c3a02ec631814236071014258f0287f3044b591a34d5a99d73","tree":"c1ddfe015a6300456c24a6561c1a1f247f255254834aac61435ceef06456e806","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8f870fe269857d1d611fff5e03d2b22533bce7dc5aad4340de6cdf434b5aa0ae","short_id":"8f870fe2"},{"time":"2026-09-20T02:30:00Z","parent":"0c97b2f8a266b152761dd1769c0898bc78a367c859ca8013edec68bfc61aa0d4","tree":"f61ebed68d2e86ca59dc4e4223535a3aa8198562b2cecb812b52d3ba9e5411e7","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"ec0f30baecf767c3a02ec631814236071014258f0287f3044b591a34d5a99d73","short_id":"ec0f30ba"},{"time":"2026-09-19T02:30:00Z","parent":"dc383edfe97cc655252f1ad872386b2fefeecc0b3e170e7a04d8683225214951","tree":"2ca8aade0fdfc72248d246771ee003972eaad397aa613f78dea4b2ba6d1a0287","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"0c97b2f8a266b152761dd1769c0898bc78a367c859ca8013edec68bfc61aa0d4","short_id":"0c97b2f8"},{"time":"2026-09-18T02:30:00Z","parent":"ee89b04f40a213571e3a100a01c666b02566dde4ea56e902b11df9a2c3f13a09","tree":"862bd61ed170b4a5e0ec0fa971bf16a2fd295b5b0ca5ca8b5573d5d96bf46d0b","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"dc383edfe97cc655252f1ad872386b2fefeecc0b3e170e7a04d8683225214951","short_id":"dc383edf"},{"time":"2026-09-17T02:30:00Z","parent":"f0a0d4eb6dda96f6db6099dff7156458aed506eeadca78859ad9657068e44501","tree":"92ac0d05e95224172f35772f54eb47981154feb9e6e58a4f03c3b273eea3dd1d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"ee89b04f40a213571e3a100a01c666b02566dde4ea56e902b11df9a2c3f13a09","short_id":"ee89b04f"},{"time":"2026-09-16T02:30:00Z","parent":"bf5abbdc483043f91fefdde6e97249ee81610adca5195440770fea3ec9c014f1","tree":"55007688ced33784bc5785e3dc9546f472cbeda9d545f9327aca913631586c3a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"f0a0d4eb6dda96f6db6099dff7156458aed506eeadca78859ad9657068e44501","short_id":"f0a0d4eb"},{"time":"2026-09-15T02:30:00Z","parent":"2f18a0cd5a226f2d04d075853265761756f6228499c1d8d6d08694c49bb3c2b7","tree":"1352369b945c41e97bbd11d3ca0f0ed4885046ce3e51e3762b4986b0c9b04ca0","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"bf5abbdc483043f91fefdde6e97249ee81610adca5195440770fea3ec9c014f1","short_id":"bf5abbdc"},{"time":"2026-09-14T02:30:00Z","parent":"8a336152be88a2f4123b281a9fd1da34c195eb44363f08e988cf2f35645a2b66","tree":"56004cc3737e424b403621b63b8cbc4e71c0ae86a326c30fe3a627a1c572d963","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"2f18a0cd5a226f2d04d075853265761756f6228499c1d8d6d08694c49bb3c2b7","short_id":"2f18a0cd"},{"time":"2026-09-13T02:30:00Z","parent":"670ca41966dd9493c733a7160c867d8c5024128d6d3f804142ce873089d56d1c","tree":"ee30f31481f47e63795e88c27f2cc603d60ea9ad9dd53fb60417ca48b93c48c8","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8a336152be88a2f4123b281a9fd1da34c195eb44363f08e988cf2f35645a2b66","short_id":"8a336152"},{"time":"2026-09-12T02:30:00Z","parent":"f22a8b07c06ae226ae53db79d52c977c9f01b5708cc2d24a47e1171ce05f34a7","tree":"422cd3972d9092ce5082e72b49d1df597a80f88de2085e6ae6a40b676bb97601","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"670ca41966dd9493c733a7160c867d8c5024128d6d3f804142ce873089d56d1c","short_id":"670ca419"},{"time":"2026-09-11T02:30:00Z","parent":"7b08e08836fa06d1a6cf125cf8e7f5f5bca1358421ff7386a9d1a3b204e0aeb6","tree":"45dace70a50297723fc9ab12d5215e2892adb5e15338f093495913aa9c674a45","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"f22a8b07c06ae226ae53db79d52c977c9f01b5708cc2d24a47e1171ce05f34a7","short_id":"f22a8b07"},{"time":"2026-09-10T02:30:00Z","parent":"c25662ce1a2597f3468e93251a04d35419b912c26907724b89c197edb79b69c9","tree":"3e9374ab1878e6aad827032c581f50b02296f436c71afc9db1080bc28c53db1a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"7b08e08836fa06d1a6cf125cf8e7f5f5bca1358421ff7386a9d1a3b204e0aeb6","short_id":"7b08e088"},{"time":"2026-09-09T02:30:00Z","parent":"3f9ff630cd8c4830ccd24976f24065aa17e84e24a04876cda02310a9d845a554","tree":"fb772e958ecbf3b778ef2b838a4937dab663d80ae6ffa571453dcf0d375d70b7","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"c25662ce1a2597f3468e93251a04d35419b912c26907724b89c197edb79b69c9","short_id":"c25662ce"},{"time":"2026-09-08T02:30:00Z","parent":"96824fce2d56c812475efc60585f0a3fe7988874ec48ecf7a55946feb3e14c0d","tree":"dd6a4ba2b1bd03d58f08b20df5ce546db43a0bdc69c88430c4f835773f75645d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"3f9ff630cd8c4830ccd24976f24065aa17e84e24a04876cda02310a9d845a554","short_id":"3f9ff630"},{"time":"2026-09-07T02:30:00Z","parent":"b49faa0a4d3e92a36922c154ede633f1ff9080fea23770cfe9547316803701e3","tree":"46653667b9ba1ba3646c2af1471791b09b03a936d8a8a8f247f09a8731db42d2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"96824fce2d56c812475efc60585f0a3fe7988874ec48ecf7a55946feb3e14c0d","short_id":"96824fce"},{"time":"2026-09-06T02:30:00Z","tree":"ce672340389400ef8f5094e689dff293adf1f0d532d6e9f811b693a112a01933","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"b49faa0a4d3e92a36922c154ede633f1ff9080fea23770cfe9547316803701e3","short_id":"b49faa0a"}],"reasons":[{"snapshot":{"time":"2026-10-16T02:30:00Z","parent":"ee8432e0cd7bb4113731adc2e76d492238b539c3d6ce24a408670fee40579e57","tree":"024c36c1f532ac9150f9768ed57bb27cb284f8949f51958804dfd0f11ee70b65","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["daily snapshot","weekly snapshot","monthly snapshot"],"counters":{"daily":6,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-15T02:30:00Z","parent":"2b09f89771cf2744dde14e804ed9e7342871c8a6c1cb4849b8128f5d2571342f","tree":"8f361f971daac52f40180aa7fd3e4638e4ef90903699241b16954ee17fa304e6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"daily":5,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-14T02:30:00Z","parent":"e3fc65e0827c6939f7d86880e75facf36c2692f9cd259fe880232ee7de2a5391","tree":"377caf3fbe1e17b4af93cc053064cde6b40976809805fcdebb0645e41b649ffb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"daily":4,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-13T02:30:00Z","parent":"4a611990c2123e859808a8546af22c372308a27a87b335aeeb89276e97049165","tree":"279178ad0293ba5157fdd209ec244a1d4899b58e1b9459c11ecac057cac60ff4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"daily":3,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-12T02:30:00Z","parent":"8ff9e57a4c7e509cd5e49202f3617630771e0d839ad04911b8106b8b7c4207af","tree":"879f6a9563bba4bcdebbea7f32c27b9e452615464c6dc3111c2df59cd661a8a1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"daily":2,"weekly":3,"monthly":5}},{"snapshot":{"time":"2026-10-11T02:30:00Z","parent":"5e76f560c4d54a477fce35b1a96ce61374291dc8fa52b6dfb76fde6d91f25bdb","tree":"afe3b0d5eaf569af22f299df9b77ccd8166b7c654c0e886b7452bb10512d0706","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["daily snapshot","weekly snapshot"],"counters":{"daily":1,"weekly":2,"monthly":5}},{"snapshot":{"time":"2026-10-10T02:30:00Z","parent":"29607a0ab3c4afc1d63525a96605bb44e0b5f4de690d1ed44bfd3bbc27025fa2","tree":"357713e3a55168ec6bea559274dc7552b4fbd64381ce4bde9022e242ec328ad1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["daily snapshot"],"counters":{"weekly":2,"monthly":5}},{"snapshot":{"time":"2026-10-04T02:30:00Z","parent":"7c1f837ad939b4f4c376a0ff177862f08d87e4616cbe8e54a60d4a666b804ce7","tree":"a5e934915e68d97267ee3b108c7ee16ea0867e651b9232443fe919d83fa3a4c2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["weekly snapshot"],"counters":{"weekly":1,"monthly":5}},{"snapshot":{"time":"2026-09-30T02:30:00Z","parent":"cb87227f0c1c6acf4999c4b2024b589203cb184ce089a01a2db472ddbb560380","tree":"b778b7edf7fa14307405e72c16f20050fc813cf944bda6b445d209db77e4bc00","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["monthly snapshot"],"counters":{"weekly":1,"monthly":4}},{"snapshot":{"time":"2026-09-27T02:30:00Z","parent":"b26700ff3e9871ac081886d146fc30b9d8e7bd4572cea0b62f8f0261ea1a4f9d","tree":"21aa00a24cb6990028d074e46a5af0457b5bc87da6867d0857663f776247b8cc","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"]},"matches":["weekly snapshot"],"counters":{"monthly":4}}]}] diff --git a/controller/internal/backup/testdata/restic/0.14.0/locked-exclusive.txt b/controller/internal/backup/testdata/restic/0.14.0/locked-exclusive.txt index 3d277ca..b798f30 100644 --- a/controller/internal/backup/testdata/restic/0.14.0/locked-exclusive.txt +++ b/controller/internal/backup/testdata/restic/0.14.0/locked-exclusive.txt @@ -1,4 +1,4 @@ -unable to create lock in backend: repository is already locked exclusively by PID 2773051 on other-box by root (UID 0, GID 0) -lock was created at 2026-10-16 18:20:13 (1.310283004s ago) -storage ID 8cbd92f5 +unable to create lock in backend: repository is already locked exclusively by PID 3688286 on other-box by root (UID 0, GID 0) +lock was created at 2026-10-16 20:02:53 (1.105027717s ago) +storage ID e0199133 the `unlock` command can be used to remove stale locks diff --git a/controller/internal/backup/testdata/restic/0.14.0/locked-shared.txt b/controller/internal/backup/testdata/restic/0.14.0/locked-shared.txt index ac39a3c..4c0d7ad 100644 --- a/controller/internal/backup/testdata/restic/0.14.0/locked-shared.txt +++ b/controller/internal/backup/testdata/restic/0.14.0/locked-shared.txt @@ -1,4 +1,4 @@ -unable to create lock in backend: repository is already locked by PID 2772696 on other-box by root (UID 0, GID 0) -lock was created at 2026-10-16 18:20:11 (1.294783283s ago) -storage ID a2cb4ce8 +unable to create lock in backend: repository is already locked by PID 3687988 on other-box by root (UID 0, GID 0) +lock was created at 2026-10-16 20:02:52 (1.102036609s ago) +storage ID fd3abc66 the `unlock` command can be used to remove stale locks diff --git a/controller/internal/backup/testdata/restic/0.14.0/snapshots-latest-tag.json b/controller/internal/backup/testdata/restic/0.14.0/snapshots-latest-tag.json index 00ca62e..e4e32d2 100644 --- a/controller/internal/backup/testdata/restic/0.14.0/snapshots-latest-tag.json +++ b/controller/internal/backup/testdata/restic/0.14.0/snapshots-latest-tag.json @@ -1 +1 @@ -[{"time":"2026-10-16T02:30:00Z","parent":"16f5cbf1aab3d6aaf201e9cf15f90b780e5db3854751f745883a6bd6e707d2dd","tree":"286f8da9b1b553de264161006b6f14be594a3eef691d3980954808cf02387f21","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"3e5346879326eed55c3c0ab2abcce53b9207c9f1da1a4f3ad1ee0ab831063651","short_id":"3e534687"}] +[{"time":"2026-10-16T02:30:00Z","parent":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","tree":"b830b8165dc45c4b23086a81004548a5a52a00060028f0d274d8098dcc168b49","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"94fc37b9bfe97271d4a0b0feda4443a5e2934a3557108dd521d0bfb2f49423c8","short_id":"94fc37b9"}] diff --git a/controller/internal/backup/testdata/restic/0.14.0/snapshots.json b/controller/internal/backup/testdata/restic/0.14.0/snapshots.json index 5d25127..db05159 100644 --- a/controller/internal/backup/testdata/restic/0.14.0/snapshots.json +++ b/controller/internal/backup/testdata/restic/0.14.0/snapshots.json @@ -1 +1 @@ -[{"time":"2026-09-06T02:30:00Z","tree":"d8d1be9062564caa6509955aefd722f7037d8fd270e339fe818dabd9bdbe5f10","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"e1d954f907f00b8337729a49bc71c9f4e7dc14dcb3f4547cc631a9d0ed34dedc","short_id":"e1d954f9"},{"time":"2026-09-06T02:30:00Z","tree":"4ad0876539f4a3e21e3a3970e2acc6b054f595a2cf08a99fdcb5bb330bd24d49","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"a4391a2d1fa176171693df8ccda6c8c334cf0736e64a36af579d5f7d8c23b20b","short_id":"a4391a2d"},{"time":"2026-09-07T02:30:00Z","parent":"e1d954f907f00b8337729a49bc71c9f4e7dc14dcb3f4547cc631a9d0ed34dedc","tree":"884bae5ecb7c125b0247b040e7dd662d29edb3adc027478bdfe82669511532e0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"d7736f8cf82ac8c9e6d485943fa598a447ee094f3640de9b977eeca8298bdc05","short_id":"d7736f8c"},{"time":"2026-09-07T02:30:00Z","parent":"a4391a2d1fa176171693df8ccda6c8c334cf0736e64a36af579d5f7d8c23b20b","tree":"32e15b2de82fccb7de96c01942bf7f1045e338f18b24c86c200f37959831aa1e","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"b4b6cf86aa3c85ea88d095bac696ec1566e6095ad19ca7af9c1ff1814ab6380f","short_id":"b4b6cf86"},{"time":"2026-09-08T02:30:00Z","parent":"b4b6cf86aa3c85ea88d095bac696ec1566e6095ad19ca7af9c1ff1814ab6380f","tree":"64c83bfdc2ae9e0a9e2ff79c96ea517b75e7af4c7162291cf9672aa9976e05c8","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"b56d7267f0f3775d7d75c1ec209267404aba5d08db7f6c6f31ea171efe8343b7","short_id":"b56d7267"},{"time":"2026-09-08T02:30:00Z","parent":"d7736f8cf82ac8c9e6d485943fa598a447ee094f3640de9b977eeca8298bdc05","tree":"b53736d4f878d0075076993c7edd16d73aca6a97ace6fd8639b43b1abbe78e56","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"46671301ce8fa7f064566a4caf267ea149c9099bb6e5d7f668f3ac6679bb42fb","short_id":"46671301"},{"time":"2026-09-09T02:30:00Z","parent":"b56d7267f0f3775d7d75c1ec209267404aba5d08db7f6c6f31ea171efe8343b7","tree":"b0d2594624bb645cd6ef4be633d745c5ff09190768fb0188bdd8fedff6c785bd","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"c2dd9de7fe5ce5e76bf986b99c0115da212f8b07277da5c236092dc4144d8af3","short_id":"c2dd9de7"},{"time":"2026-09-09T02:30:00Z","parent":"46671301ce8fa7f064566a4caf267ea149c9099bb6e5d7f668f3ac6679bb42fb","tree":"b5d5c1b06b526a0472dd900185abb9b4f7bbd863df944aeb933e3f20b6dca653","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"0c3db5b724f38baaad8d504678a69c80ae77f66f14e517b10ffa7e88efbf678a","short_id":"0c3db5b7"},{"time":"2026-09-10T02:30:00Z","parent":"0c3db5b724f38baaad8d504678a69c80ae77f66f14e517b10ffa7e88efbf678a","tree":"5b3d8750af755b0e38a9a63bc013bb83c8cd397094827edde8a0394009d49743","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"86e446b059058f35daf0e1f2255f8faa52a6f8fe582a0f9b5c2f2532c28548c4","short_id":"86e446b0"},{"time":"2026-09-10T02:30:00Z","parent":"c2dd9de7fe5ce5e76bf986b99c0115da212f8b07277da5c236092dc4144d8af3","tree":"09722b272016f5585fe991a8b5cd5a9451cbf778cb64d9d65ca1cde792e9ace7","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"24331fad4982bf1e6e5be6f899580e71f69a7a3dc29785b40ec595b16f9ede7b","short_id":"24331fad"},{"time":"2026-09-11T02:30:00Z","parent":"86e446b059058f35daf0e1f2255f8faa52a6f8fe582a0f9b5c2f2532c28548c4","tree":"daa8d607c445235bb4a6fe5169e1ee0d66fc0df2c40eee57e34c621d6f0c3747","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"6b9b78390e84353c864415e80862da09efb3948c726f9ea58d70957916ba5373","short_id":"6b9b7839"},{"time":"2026-09-11T02:30:00Z","parent":"24331fad4982bf1e6e5be6f899580e71f69a7a3dc29785b40ec595b16f9ede7b","tree":"b13daaa02a014a7f2811f6cd845bc427883833ac6e578677fffb9756cb08855d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"9a9b7aee5b1b8801a89190f64cd0a25cdc0de5dc90bf507727de8ee76b70d59d","short_id":"9a9b7aee"},{"time":"2026-09-12T02:30:00Z","parent":"6b9b78390e84353c864415e80862da09efb3948c726f9ea58d70957916ba5373","tree":"801be774e3bd1f6a006ddab0eba439a02ed0cb4865bd11722c0d54c33617d877","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"9afa939a8fc9758c4547b61dc77c51fb7f6ee563a4e33b2db6655358bb79b7e2","short_id":"9afa939a"},{"time":"2026-09-12T02:30:00Z","parent":"9a9b7aee5b1b8801a89190f64cd0a25cdc0de5dc90bf507727de8ee76b70d59d","tree":"56ea6daeaf9b8c6e55fe21d488e0c7b90d926290fc98da3de942ca4aa7b57ce1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"4facc0c230bf587cde80d5a3d3cbb62e938150316545d2f91f883a8f0f23560b","short_id":"4facc0c2"},{"time":"2026-09-13T02:30:00Z","parent":"9afa939a8fc9758c4547b61dc77c51fb7f6ee563a4e33b2db6655358bb79b7e2","tree":"3b7db2503aaa703f480a67329b650f87bfd0e8561f611ad68d18a4e712d2a226","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"86ab152afd9baafe145fe9d1bd55af12a7ee4f44f61d899f998836e87d2b466d","short_id":"86ab152a"},{"time":"2026-09-13T02:30:00Z","parent":"4facc0c230bf587cde80d5a3d3cbb62e938150316545d2f91f883a8f0f23560b","tree":"6f7f51fbf57abeb9fc1af9689e59212344b12e833a926b9ba1ada7dfb926bccc","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"dd8abd92e055c916448d058660cc0b4ed63cb99a418b1941119c33bbb30f2e37","short_id":"dd8abd92"},{"time":"2026-09-14T02:30:00Z","parent":"dd8abd92e055c916448d058660cc0b4ed63cb99a418b1941119c33bbb30f2e37","tree":"e0c2d3e7cdf6db59ffafe688a844e75c62211868b38efcdc6025cd497312f03d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"7ca16908b1c9ba4e9c9719bed7e0ec0f3987e155bafaf5bab4bb0a903067ae07","short_id":"7ca16908"},{"time":"2026-09-14T02:30:00Z","parent":"86ab152afd9baafe145fe9d1bd55af12a7ee4f44f61d899f998836e87d2b466d","tree":"422635882ea83f0e6e759795a1124db6cd51b6db0a04fda920296421d93ce92f","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"4553f115de0d3983fa65b64b44be8ff1f82e40af54bb915b0fd3ab25d05f4d69","short_id":"4553f115"},{"time":"2026-09-15T02:30:00Z","parent":"7ca16908b1c9ba4e9c9719bed7e0ec0f3987e155bafaf5bab4bb0a903067ae07","tree":"489bf44b49d5679494a5d660eea153236adc9af8a6f768cee85b40c9444395fb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"8905c672851940782321709d03e4d976cc8975aeb63c9ef50a7713ad2e257d75","short_id":"8905c672"},{"time":"2026-09-15T02:30:00Z","parent":"4553f115de0d3983fa65b64b44be8ff1f82e40af54bb915b0fd3ab25d05f4d69","tree":"a7c63419c0fa17e1d62bdc3d9174e533754939eb4b02600662a0631b4561a83e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"62717aad9a003d7fa57b87a2ea93d7d8954ab400b4ff0da966a9c04223fb1846","short_id":"62717aad"},{"time":"2026-09-16T02:30:00Z","parent":"62717aad9a003d7fa57b87a2ea93d7d8954ab400b4ff0da966a9c04223fb1846","tree":"40e0a017a084528d33a98f78b4ad74cad1a33fc2f36cfaa9169635117b1618f9","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"1e006efa46517bffcd436c66f28590127db1b083901aa86bb346846766b69f22","short_id":"1e006efa"},{"time":"2026-09-16T02:30:00Z","parent":"8905c672851940782321709d03e4d976cc8975aeb63c9ef50a7713ad2e257d75","tree":"3ca35c35a404dcd752bb371217365049d27737d3604af69924d070b520dd9ae2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"0e064dcba9e15e96b4a5066b1847d550163d9943314615e34e7f4927c1ffe20a","short_id":"0e064dcb"},{"time":"2026-09-17T02:30:00Z","parent":"1e006efa46517bffcd436c66f28590127db1b083901aa86bb346846766b69f22","tree":"27b98f1320cc2b68ae8be3c27fb259471de7467083c444e465272564383aa374","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"efcf3fcd77e50fc6dda0747daf9181f75f9663ed4505f8988f74b6433777be7f","short_id":"efcf3fcd"},{"time":"2026-09-17T02:30:00Z","parent":"0e064dcba9e15e96b4a5066b1847d550163d9943314615e34e7f4927c1ffe20a","tree":"1a527598187b2c775100f690c73af64d8cc662c84935eaf2256fee9730bb0766","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"3610529c13a4b87deea7309dc9e352c96e79cd8c465d79590643c3192d3383ef","short_id":"3610529c"},{"time":"2026-09-18T02:30:00Z","parent":"efcf3fcd77e50fc6dda0747daf9181f75f9663ed4505f8988f74b6433777be7f","tree":"178b66f451efe2d51b864e749502d8183db3d19faf346db7025fcc95035a6fd2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"a5fff383e0c4b921e8359bccf05d6f7bd2747fd481ef721a224118b88ff82ace","short_id":"a5fff383"},{"time":"2026-09-18T02:30:00Z","parent":"3610529c13a4b87deea7309dc9e352c96e79cd8c465d79590643c3192d3383ef","tree":"6a7b9de7f8a847690487acab15e9808a7c485a77da3202aa7394dfdb048ac828","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"9a5d9b218160f2a99d228dfbe7d5c94c425a55d34c931b958a5094981337efe3","short_id":"9a5d9b21"},{"time":"2026-09-19T02:30:00Z","parent":"9a5d9b218160f2a99d228dfbe7d5c94c425a55d34c931b958a5094981337efe3","tree":"e9c735d5260376c08bf4ba6ff9ca2c11325e9013a15509b4559c94c4170a6ae4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"57880fadf8682a92a4992909de29de94d2fff6f45689e2e82277b5cf8911f13f","short_id":"57880fad"},{"time":"2026-09-19T02:30:00Z","parent":"a5fff383e0c4b921e8359bccf05d6f7bd2747fd481ef721a224118b88ff82ace","tree":"43b99b529fbfe9175e37b9739ddb72769d0877fbb543b65256da164e05008aff","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"3084ed321a45d2c70cd05dcda31fe2c324849add619a27229fb307a9e455f7a1","short_id":"3084ed32"},{"time":"2026-09-20T02:30:00Z","parent":"3084ed321a45d2c70cd05dcda31fe2c324849add619a27229fb307a9e455f7a1","tree":"7a6b05c4b9ab4b817be0765cfd1c35ec846ef6da798bfd0ef34153fda3b3823f","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"9fc7b97f4fea54dccefe6f9643c809c6221efc59c0efcab7aa34d459686cde0d","short_id":"9fc7b97f"},{"time":"2026-09-20T02:30:00Z","parent":"57880fadf8682a92a4992909de29de94d2fff6f45689e2e82277b5cf8911f13f","tree":"6d32c2444b76fb0eb422b1290fb41309ba642c2c8389519a6ee286e5726594f1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"e62e8764fadbcb8dd8b59fd2c861603fb48891e451a50c1f8d8fa84effe6c693","short_id":"e62e8764"},{"time":"2026-09-21T02:30:00Z","parent":"9fc7b97f4fea54dccefe6f9643c809c6221efc59c0efcab7aa34d459686cde0d","tree":"f18e6b1e580681cd98c27e89a258c39223b793385ea5f14cb4da8522501d1768","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"ed5a6be0ed1510c644e6ca1ce28d812099582240fafd4c475758a59dae75f268","short_id":"ed5a6be0"},{"time":"2026-09-21T02:30:00Z","parent":"e62e8764fadbcb8dd8b59fd2c861603fb48891e451a50c1f8d8fa84effe6c693","tree":"2fcc4e0dd7db7447990b38ec9c93ad2c83297ea1e9ab17b1b50c3c0f24637579","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"79792a9b1e5603f08b6228fae860d8c974313bccc6ff2dde76270f3cc521d5c7","short_id":"79792a9b"},{"time":"2026-09-22T02:30:00Z","parent":"ed5a6be0ed1510c644e6ca1ce28d812099582240fafd4c475758a59dae75f268","tree":"373424cff38c1c809bf3c45e6b25d64d5ee96e16890350bb9ccd8f1807a36ca1","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"c2d8f4210e52cdadd1327dab71f6c967affc51a7d0944027ece5e8654000d377","short_id":"c2d8f421"},{"time":"2026-09-22T02:30:00Z","parent":"79792a9b1e5603f08b6228fae860d8c974313bccc6ff2dde76270f3cc521d5c7","tree":"76e67a0fd8eb8215e67487127e1823ec76db61eafde6f9519ffbc5388fd1de9f","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"d27d1ae70c280fdb945c0366ba17c654d3b5be2516d8e4e6ae862a3be0cbac54","short_id":"d27d1ae7"},{"time":"2026-09-23T02:30:00Z","parent":"c2d8f4210e52cdadd1327dab71f6c967affc51a7d0944027ece5e8654000d377","tree":"eb49dad786fdf2ab9c00b0633c34cf58de5224d70e74a3a9a31237d0c56b52fd","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"5a13db8c85c9de7bd9957f4c382c557c6986eb4fa052fa773d3d6c056b522698","short_id":"5a13db8c"},{"time":"2026-09-23T02:30:00Z","parent":"d27d1ae70c280fdb945c0366ba17c654d3b5be2516d8e4e6ae862a3be0cbac54","tree":"5ff035bfe269e00cbdca9b6c966b822a578ae26742a29938a89ac1ff92dd5fed","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"148fb7b1b6e4cc4ebb5ca99ea00cd92703065c4879c5edcf88890d082dd6f31c","short_id":"148fb7b1"},{"time":"2026-09-24T02:30:00Z","parent":"5a13db8c85c9de7bd9957f4c382c557c6986eb4fa052fa773d3d6c056b522698","tree":"12224495435b7d8df970beab00e5efd0ba6c3d4d53aaf607a72816d861554e6b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"bb943a0960b2c03215e6b0462256450d9e67cc5214acd354db1a0cb0705a1696","short_id":"bb943a09"},{"time":"2026-09-24T02:30:00Z","parent":"148fb7b1b6e4cc4ebb5ca99ea00cd92703065c4879c5edcf88890d082dd6f31c","tree":"f90e90886d9e47a708c439f90ab0b811e00372c122928d4db0b3a679643e7377","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"3c149e5a2092648bbdf09398f04ee351b8eb3e43f5d9e5f92a216328fe2192a8","short_id":"3c149e5a"},{"time":"2026-09-25T02:30:00Z","parent":"3c149e5a2092648bbdf09398f04ee351b8eb3e43f5d9e5f92a216328fe2192a8","tree":"f766854d8b67adac39aa2971fe1eeda94a4adbde52cc473929e03cbc97f15929","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"738389466ef5b3f129a2392fb14371e16604c6a3071ad89b1cc97154539df00b","short_id":"73838946"},{"time":"2026-09-25T02:30:00Z","parent":"bb943a0960b2c03215e6b0462256450d9e67cc5214acd354db1a0cb0705a1696","tree":"9fea50e970c47996bcc1610eba645ae379ac87f0515b284df2985f536bf26d24","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"d9368785703ec3905bc9f6f716b4ebfbd0b2bb0692ddb704e4bf977e8aff1ff3","short_id":"d9368785"},{"time":"2026-09-26T02:30:00Z","parent":"d9368785703ec3905bc9f6f716b4ebfbd0b2bb0692ddb704e4bf977e8aff1ff3","tree":"63233ccb5f095ca40bc126b605c297e3844685293c629d5d656da1a4c826a921","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"9d3dd3268ab916288fab00729df16d85878fa9292576176e7d7e05b41babfa97","short_id":"9d3dd326"},{"time":"2026-09-26T02:30:00Z","parent":"738389466ef5b3f129a2392fb14371e16604c6a3071ad89b1cc97154539df00b","tree":"7a29695c4ffb7201fe199173c93083bf98a3eb6083d4171e819b25c385ee3292","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"b6c3ff0ed8c270eed4c0d1c691ad5fca3b4957f13d1bde79f29094150536529c","short_id":"b6c3ff0e"},{"time":"2026-09-27T02:30:00Z","parent":"9d3dd3268ab916288fab00729df16d85878fa9292576176e7d7e05b41babfa97","tree":"87434cf19bafe37d88781b28071ab4887feb96b0ded0b37bc27ac7bbd7e33e2e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"e5f43196aec8f410ffd7b2caf0d076ed0e7ebd92d5f04619c415b16ae56b7d1f","short_id":"e5f43196"},{"time":"2026-09-27T02:30:00Z","parent":"b6c3ff0ed8c270eed4c0d1c691ad5fca3b4957f13d1bde79f29094150536529c","tree":"f06890a88f7ac258af5adf77d52b9f7b9fef3414ac7effce40eb52ebbab0fe29","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"88ce7523616beee04180afa0d25c2048c41d4431391e0c0c5c6e923921a9268e","short_id":"88ce7523"},{"time":"2026-09-28T02:30:00Z","parent":"e5f43196aec8f410ffd7b2caf0d076ed0e7ebd92d5f04619c415b16ae56b7d1f","tree":"aebc8687a066367c7b527d14d7567d54bbe8c5803658ebf254a144c82670c5a2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"ef9f435cf9a21c296e8cddbd73ae58e8c5c15e121c3b2a0d2773d371d365fa92","short_id":"ef9f435c"},{"time":"2026-09-28T02:30:00Z","parent":"88ce7523616beee04180afa0d25c2048c41d4431391e0c0c5c6e923921a9268e","tree":"c7dada1e21510896f6475d62d0f2f88454c7719b0a74c79ce3593bc14f4d19ff","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"999889b6f8de7d3eafeaa86ad705420affcfdf646e10a0c366ee82f3bfa5a758","short_id":"999889b6"},{"time":"2026-09-29T02:30:00Z","parent":"999889b6f8de7d3eafeaa86ad705420affcfdf646e10a0c366ee82f3bfa5a758","tree":"8636f52172dd153181a2eeeacadaf422a0ab9230d3a9eb300a323d9ecf6d2bda","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"2ef32e3aec2169bfd005c607d23fa8caefd3597d5933a2ee6ef0992954439e11","short_id":"2ef32e3a"},{"time":"2026-09-29T02:30:00Z","parent":"ef9f435cf9a21c296e8cddbd73ae58e8c5c15e121c3b2a0d2773d371d365fa92","tree":"57ad9030700fd2929ef4d4325fb23070983ee4b909df35f62ecd60ca2dca7b6a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"78546e509597b716e8748b001bbf274e2068a0eaf74f7a5d888e65bc0dc5c5e3","short_id":"78546e50"},{"time":"2026-09-30T02:30:00Z","parent":"78546e509597b716e8748b001bbf274e2068a0eaf74f7a5d888e65bc0dc5c5e3","tree":"66891382721b1b41319f9dc30cccd92e81e3d3794e2795c4d99da13a48a87ea9","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"67eb5eff9d3ce202877e027ce212fc1b914febce0d86455ed7a804053d402806","short_id":"67eb5eff"},{"time":"2026-09-30T02:30:00Z","parent":"2ef32e3aec2169bfd005c607d23fa8caefd3597d5933a2ee6ef0992954439e11","tree":"a37fa979d19d953863ad8b8cb276382dcee1e0f2cfe1c87d91908d1a6a9a95e0","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"1b5e6b74f1abaf4d4f390be385bf34650eebe21aa034aeaba3e29150193532c2","short_id":"1b5e6b74"},{"time":"2026-10-01T02:30:00Z","parent":"67eb5eff9d3ce202877e027ce212fc1b914febce0d86455ed7a804053d402806","tree":"83aafad6973ac879054f312c0b7b9711f05e61144e67145c44763fedbc8da0f3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"d808dbb1ec076b1e43762a470336464f7310a7e1a1ccad5d4f6aa049b492bb2d","short_id":"d808dbb1"},{"time":"2026-10-01T02:30:00Z","parent":"1b5e6b74f1abaf4d4f390be385bf34650eebe21aa034aeaba3e29150193532c2","tree":"aad23ab1f6a4a59f8e09fca43fa8927321a5cfa6707310a9a66ed4738ffd6c4d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"6d39107b801aff3b7d929393c3070ccfee278387276db8aacf1b46b8a5da1e1c","short_id":"6d39107b"},{"time":"2026-10-02T02:30:00Z","parent":"d808dbb1ec076b1e43762a470336464f7310a7e1a1ccad5d4f6aa049b492bb2d","tree":"461258fdd0946cb26ee3ec87c2b35db08921b497d9567e0cb921fa7953e1d724","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"7afa8edcb7f984756564e202d29cdca8400309603590be914b3b7ee84934d4cf","short_id":"7afa8edc"},{"time":"2026-10-02T02:30:00Z","parent":"6d39107b801aff3b7d929393c3070ccfee278387276db8aacf1b46b8a5da1e1c","tree":"ee800f29da370e89ef260c6be721d6dfb691c85b9ca2b35ff2bd2340c4fc737a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"3869db68bb5543ab788ddca26d61583a6137ff71d6be864be83762359192c232","short_id":"3869db68"},{"time":"2026-10-03T02:30:00Z","parent":"7afa8edcb7f984756564e202d29cdca8400309603590be914b3b7ee84934d4cf","tree":"e0fc2c64b57d15c40924e54e45e4f3f5cf6c88549d4ee60911c2a8069cb55c05","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"fab7e5d7ba440392bc8ee00c0c0fefb071168f03e3b58e3934aad0ff91560489","short_id":"fab7e5d7"},{"time":"2026-10-03T02:30:00Z","parent":"3869db68bb5543ab788ddca26d61583a6137ff71d6be864be83762359192c232","tree":"2fcca788daf43bbcea34d3e41650cb2f94549620a997511365e9018d667db0d0","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"eabaa0652f6549580fa3b1125f842209428a1b425016621190a4764bed2afb08","short_id":"eabaa065"},{"time":"2026-10-04T02:30:00Z","parent":"eabaa0652f6549580fa3b1125f842209428a1b425016621190a4764bed2afb08","tree":"468d616ac9063de9f2829a1fd9d3d362af359c6ce79403d9bdb41f56707f7570","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"3a916d89540e17509b7c6ac5dc43d5842d268970dcb2470737a635e9ef343734","short_id":"3a916d89"},{"time":"2026-10-04T02:30:00Z","parent":"fab7e5d7ba440392bc8ee00c0c0fefb071168f03e3b58e3934aad0ff91560489","tree":"788dc5f69207e6351f2511edeb04473000634a2b3840570676f1f33ad7760bf4","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"039063a1d376f4c47fba5862f1314a29adefc05a23897519d30d86df701fd453","short_id":"039063a1"},{"time":"2026-10-05T02:30:00Z","parent":"3a916d89540e17509b7c6ac5dc43d5842d268970dcb2470737a635e9ef343734","tree":"353fcfbdbb2b33da457308307d2aca87f18cf9e45a4e3c8f56e1ee4060dc555f","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"c86697c291b279d448ba785b6e600794a811980413d3119cc1e7dd4c07b15124","short_id":"c86697c2"},{"time":"2026-10-05T02:30:00Z","parent":"039063a1d376f4c47fba5862f1314a29adefc05a23897519d30d86df701fd453","tree":"d7f57de522610361b8f6e1ae3e1c8f0af6fff45b9caba60e79dbea09bad3e8bb","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"4c4f771ef180a648b16060f2d2b56f1c934f78bb2bb19ea71856b1ff3491f41c","short_id":"4c4f771e"},{"time":"2026-10-06T02:30:00Z","parent":"4c4f771ef180a648b16060f2d2b56f1c934f78bb2bb19ea71856b1ff3491f41c","tree":"a1eb787269c933c2cf52b73ac6953bc88cde2f53e69e75a868789e2469e59b2e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"a34683b0a3bdf8f344804b0a8353d39663ed79484c336bcb3649178c18c62bef","short_id":"a34683b0"},{"time":"2026-10-06T02:30:00Z","parent":"c86697c291b279d448ba785b6e600794a811980413d3119cc1e7dd4c07b15124","tree":"3b18bc51857c3b43ef3b7f7251a747a4aa1d860336c3276c1e895b8ed89c990e","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"4600ed1a4a0a08348ad95e38368431242b4eeb9be82ca860c7dcd626833d38fb","short_id":"4600ed1a"},{"time":"2026-10-07T02:30:00Z","parent":"a34683b0a3bdf8f344804b0a8353d39663ed79484c336bcb3649178c18c62bef","tree":"59c955a77ad371adcd241705a113b07cf021164c7fea59eb8c305255924594d3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"f97353dadd1c5a066f26376a1e4de94e2e2924c30fc8336bce7226b17e8b47a4","short_id":"f97353da"},{"time":"2026-10-07T02:30:00Z","parent":"4600ed1a4a0a08348ad95e38368431242b4eeb9be82ca860c7dcd626833d38fb","tree":"e89d06f95e23814a4c5b36b1a61d51b59b621b0a1c0750ef93f71e2beff2e17b","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"20cccbaa5b814f5a1a1816d1c49af6f4703dd33e7c62faf4a2152d15161c45f0","short_id":"20cccbaa"},{"time":"2026-10-08T02:30:00Z","parent":"f97353dadd1c5a066f26376a1e4de94e2e2924c30fc8336bce7226b17e8b47a4","tree":"9020a0778ef202f0dd278394e8c6e6f29ab5cb96190f80f1860b57a3ab8905ea","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"59960090510b6ead422be13c69e3bf87e2e53f0fe3246c460da3bac22e6d29a7","short_id":"59960090"},{"time":"2026-10-08T02:30:00Z","parent":"20cccbaa5b814f5a1a1816d1c49af6f4703dd33e7c62faf4a2152d15161c45f0","tree":"58a11c46cd107e285a02424d5fedf8c6c3831ec57d5231dca34a77221478230f","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"0095d1024e633c17869e063c307b6e7ef74dd54a0e8c406c91bf38ca7ad16f1b","short_id":"0095d102"},{"time":"2026-10-09T02:30:00Z","parent":"59960090510b6ead422be13c69e3bf87e2e53f0fe3246c460da3bac22e6d29a7","tree":"1aa9645c6d95bbe1fc5c0f81ea48122b346635fad67504ca44d4dc765ca7504e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"a25b1537a1ffedceb22b885753385f07e7435ff086258ea3ac14ed4446a4187d","short_id":"a25b1537"},{"time":"2026-10-09T02:30:00Z","parent":"0095d1024e633c17869e063c307b6e7ef74dd54a0e8c406c91bf38ca7ad16f1b","tree":"c14587a70d549b4cf45f6091ba985e7c57911d9ce65aa0ae6fcbb54cd2798320","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"dd010c8b70468216b74dc107c0125f008c1e8a0d889481e481e40f8f82994764","short_id":"dd010c8b"},{"time":"2026-10-10T02:30:00Z","parent":"dd010c8b70468216b74dc107c0125f008c1e8a0d889481e481e40f8f82994764","tree":"f1ca437cda2b7f0db26af3d9b7509db45f238cd346a1f62bf801252daca93420","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"b82290210fdaab03ba7fa7066ab61e31c5a3545d80a5dec4533fe21ded17dc95","short_id":"b8229021"},{"time":"2026-10-10T02:30:00Z","parent":"a25b1537a1ffedceb22b885753385f07e7435ff086258ea3ac14ed4446a4187d","tree":"bb0cd1b8820b86ccd427ce6049c08ea8e06b8719f000596f0835f6c9e001392b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"6d15ebd146b4ddf76a0f5501fe68a228a37afb00ff05d9e17fb0dd99934f3455","short_id":"6d15ebd1"},{"time":"2026-10-11T02:30:00Z","parent":"6d15ebd146b4ddf76a0f5501fe68a228a37afb00ff05d9e17fb0dd99934f3455","tree":"3ebf8ab552c78434bfdb5465cfb48338a3fa83744c2c41e79af0899cd5cef03c","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"3f14d64b4c7715903cff2a628a00a6e4c774e242a42400ef3fd24d3e3a1fee1a","short_id":"3f14d64b"},{"time":"2026-10-11T02:30:00Z","parent":"b82290210fdaab03ba7fa7066ab61e31c5a3545d80a5dec4533fe21ded17dc95","tree":"41316836995752c254b9adce2243f694fab0421b8359109df23ea1fb996ce0fb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"9dcb3fa42c8d5b880c7e407ea15e134d540bab3fb250a63854c14dddb1748b79","short_id":"9dcb3fa4"},{"time":"2026-10-12T02:30:00Z","parent":"9dcb3fa42c8d5b880c7e407ea15e134d540bab3fb250a63854c14dddb1748b79","tree":"7945e1927ec6444933dbe89befa7f342ffd218ab2a96d824a3e3cd9a25f11286","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"44f0faa89145f8dd68e06437323d677fae465f54c4f6aa95f938234ba0112f57","short_id":"44f0faa8"},{"time":"2026-10-12T02:30:00Z","parent":"3f14d64b4c7715903cff2a628a00a6e4c774e242a42400ef3fd24d3e3a1fee1a","tree":"1c1df704c5d5d3ac06dfc4a2d43ad706d692dbd78f3b5a6b983c2623d005cf2a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"d85b77be2724c4e449fa4d5a51ade77b83f83d3fba834e322ff2a07575c413fa","short_id":"d85b77be"},{"time":"2026-10-13T02:30:00Z","parent":"d85b77be2724c4e449fa4d5a51ade77b83f83d3fba834e322ff2a07575c413fa","tree":"13ab80d5668ef726b7c82ba2f73366f1fa9f2d25511d7cb3fe798582ec2d189d","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"b6280f340819d34bf80b0a8edf7c9b378d04363483abd74b1a8a61dc921499e7","short_id":"b6280f34"},{"time":"2026-10-13T02:30:00Z","parent":"44f0faa89145f8dd68e06437323d677fae465f54c4f6aa95f938234ba0112f57","tree":"2f79914cd5a90ceb735c3dd272c22db5a67f5f1c6a35f48af320f7b218959177","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"4a74cebcf061b3f721ce35f1dae2fe644c3dcb77620042d6a9e9a1f69ffa5908","short_id":"4a74cebc"},{"time":"2026-10-14T02:30:00Z","parent":"b6280f340819d34bf80b0a8edf7c9b378d04363483abd74b1a8a61dc921499e7","tree":"795573bb56c71a53b79b999ee8bf8abbdddd04e223191fa07976d2384c24370f","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"c980586cfb31f9bf16ec3a509de8d37160ea05102ffa4cfb12f3a834eb8317b3","short_id":"c980586c"},{"time":"2026-10-14T02:30:00Z","parent":"4a74cebcf061b3f721ce35f1dae2fe644c3dcb77620042d6a9e9a1f69ffa5908","tree":"22deec6d4575076f3b5b9228249ef0935883841659af9e60c2e471f903d301cf","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"8d4189078ef8c5de57f8e0a58d646229c6ea05a584a223b13d6d52ee9b2a499a","short_id":"8d418907"},{"time":"2026-10-15T02:30:00Z","parent":"c980586cfb31f9bf16ec3a509de8d37160ea05102ffa4cfb12f3a834eb8317b3","tree":"cfc9e89d510b4d7500f66c7774f8fa1d26035be91e2de72bb5b35b5ff1565597","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"16f5cbf1aab3d6aaf201e9cf15f90b780e5db3854751f745883a6bd6e707d2dd","short_id":"16f5cbf1"},{"time":"2026-10-15T02:30:00Z","parent":"8d4189078ef8c5de57f8e0a58d646229c6ea05a584a223b13d6d52ee9b2a499a","tree":"c81de4fd5684584aecccba2848d623d9b46d27aaa7a8fda0cf7a4a56faa19f12","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"331513b5478c67fd17b601f4e86536be66fdebac42db635d2b44073c418c9044","short_id":"331513b5"},{"time":"2026-10-16T02:30:00Z","parent":"16f5cbf1aab3d6aaf201e9cf15f90b780e5db3854751f745883a6bd6e707d2dd","tree":"286f8da9b1b553de264161006b6f14be594a3eef691d3980954808cf02387f21","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"3e5346879326eed55c3c0ab2abcce53b9207c9f1da1a4f3ad1ee0ab831063651","short_id":"3e534687"},{"time":"2026-10-16T02:30:00Z","parent":"331513b5478c67fd17b601f4e86536be66fdebac42db635d2b44073c418c9044","tree":"2479779a0246aded8ea88b1b43549f333df32233150ead772301d4060d9834b6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"1bb3e0b01ad4e9ef4092c0f4f38d003d026d3e62bd4ec32ad84d2ae50b1fc26b","short_id":"1bb3e0b0"}] +[{"time":"2026-09-06T02:30:00Z","tree":"f685956bf88ee15d577e60f77a8ce561abdb2dd56eb1d00b26d5c59276add7a6","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"2a76397eb8a43be8c70dd687ab03fcd939f2f058f815804b9fa2e0f5d9d32376","short_id":"2a76397e"},{"time":"2026-09-06T02:30:00Z","tree":"ce672340389400ef8f5094e689dff293adf1f0d532d6e9f811b693a112a01933","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"b49faa0a4d3e92a36922c154ede633f1ff9080fea23770cfe9547316803701e3","short_id":"b49faa0a"},{"time":"2026-09-07T02:30:00Z","parent":"2a76397eb8a43be8c70dd687ab03fcd939f2f058f815804b9fa2e0f5d9d32376","tree":"70b21a93a7e8af3804e813d7d47cb5d936ebfff4ebf1b8b80a9834382142aee5","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"820d553d84f1c920803a156ffea356c7aacf469e7555f07ea8b9408d2021f254","short_id":"820d553d"},{"time":"2026-09-07T02:30:00Z","parent":"b49faa0a4d3e92a36922c154ede633f1ff9080fea23770cfe9547316803701e3","tree":"46653667b9ba1ba3646c2af1471791b09b03a936d8a8a8f247f09a8731db42d2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"96824fce2d56c812475efc60585f0a3fe7988874ec48ecf7a55946feb3e14c0d","short_id":"96824fce"},{"time":"2026-09-08T02:30:00Z","parent":"96824fce2d56c812475efc60585f0a3fe7988874ec48ecf7a55946feb3e14c0d","tree":"dd6a4ba2b1bd03d58f08b20df5ce546db43a0bdc69c88430c4f835773f75645d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"3f9ff630cd8c4830ccd24976f24065aa17e84e24a04876cda02310a9d845a554","short_id":"3f9ff630"},{"time":"2026-09-08T02:30:00Z","parent":"820d553d84f1c920803a156ffea356c7aacf469e7555f07ea8b9408d2021f254","tree":"f725d2ffc7382c23554b85a5381905f02a11b09d307c24cd20980bcb30dce47b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"1242b68c1b172bc4ae762fe874cd6dd8863ce3ae03961f5175c35fa26475d385","short_id":"1242b68c"},{"time":"2026-09-09T02:30:00Z","parent":"3f9ff630cd8c4830ccd24976f24065aa17e84e24a04876cda02310a9d845a554","tree":"fb772e958ecbf3b778ef2b838a4937dab663d80ae6ffa571453dcf0d375d70b7","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"c25662ce1a2597f3468e93251a04d35419b912c26907724b89c197edb79b69c9","short_id":"c25662ce"},{"time":"2026-09-09T02:30:00Z","parent":"1242b68c1b172bc4ae762fe874cd6dd8863ce3ae03961f5175c35fa26475d385","tree":"2bfaf9b4b8dabb68a2824ce5f48d27fda4ea94c2a960718bd84cabd59be13acf","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"d1c1d0c71c88d2f829b267adfdafbc1b19fdf184de6cdf1de28703cf46b40d65","short_id":"d1c1d0c7"},{"time":"2026-09-10T02:30:00Z","parent":"d1c1d0c71c88d2f829b267adfdafbc1b19fdf184de6cdf1de28703cf46b40d65","tree":"ed7361b730a863510df1e3b9f7d25b810902e8e86e0e230632250186cc558b21","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"e4b8322da1d838315d2dd62509678d7b419924a0d7c4723062aa31140a417ac0","short_id":"e4b8322d"},{"time":"2026-09-10T02:30:00Z","parent":"c25662ce1a2597f3468e93251a04d35419b912c26907724b89c197edb79b69c9","tree":"3e9374ab1878e6aad827032c581f50b02296f436c71afc9db1080bc28c53db1a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"7b08e08836fa06d1a6cf125cf8e7f5f5bca1358421ff7386a9d1a3b204e0aeb6","short_id":"7b08e088"},{"time":"2026-09-11T02:30:00Z","parent":"e4b8322da1d838315d2dd62509678d7b419924a0d7c4723062aa31140a417ac0","tree":"9b79e87705df56afe04f10b8a5e15cb8cc4abed0585815e54282b77cacd3eae6","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"8c127f74318a1ff657ebc803b1fda7fae31ff1e2e3e145c9bd137d04f9de9d92","short_id":"8c127f74"},{"time":"2026-09-11T02:30:00Z","parent":"7b08e08836fa06d1a6cf125cf8e7f5f5bca1358421ff7386a9d1a3b204e0aeb6","tree":"45dace70a50297723fc9ab12d5215e2892adb5e15338f093495913aa9c674a45","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"f22a8b07c06ae226ae53db79d52c977c9f01b5708cc2d24a47e1171ce05f34a7","short_id":"f22a8b07"},{"time":"2026-09-12T02:30:00Z","parent":"8c127f74318a1ff657ebc803b1fda7fae31ff1e2e3e145c9bd137d04f9de9d92","tree":"57c13238258e80cccb13e8d4dac05a82f9c3da4ac3dc6a26e9b8f4736e478af1","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"9224b1af26c1c1fe31395055f22158bf09cc541f4b59a59caf91b71f92bc63f1","short_id":"9224b1af"},{"time":"2026-09-12T02:30:00Z","parent":"f22a8b07c06ae226ae53db79d52c977c9f01b5708cc2d24a47e1171ce05f34a7","tree":"422cd3972d9092ce5082e72b49d1df597a80f88de2085e6ae6a40b676bb97601","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"670ca41966dd9493c733a7160c867d8c5024128d6d3f804142ce873089d56d1c","short_id":"670ca419"},{"time":"2026-09-13T02:30:00Z","parent":"9224b1af26c1c1fe31395055f22158bf09cc541f4b59a59caf91b71f92bc63f1","tree":"a5b546be122e577d101aaa067994bae404a881925573c09a2576431b51bb3e82","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"d6678aa268695bc4387fe3a857f3304013c2bd672dc1234cf2161343bf18efdc","short_id":"d6678aa2"},{"time":"2026-09-13T02:30:00Z","parent":"670ca41966dd9493c733a7160c867d8c5024128d6d3f804142ce873089d56d1c","tree":"ee30f31481f47e63795e88c27f2cc603d60ea9ad9dd53fb60417ca48b93c48c8","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"8a336152be88a2f4123b281a9fd1da34c195eb44363f08e988cf2f35645a2b66","short_id":"8a336152"},{"time":"2026-09-14T02:30:00Z","parent":"8a336152be88a2f4123b281a9fd1da34c195eb44363f08e988cf2f35645a2b66","tree":"56004cc3737e424b403621b63b8cbc4e71c0ae86a326c30fe3a627a1c572d963","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"2f18a0cd5a226f2d04d075853265761756f6228499c1d8d6d08694c49bb3c2b7","short_id":"2f18a0cd"},{"time":"2026-09-14T02:30:00Z","parent":"d6678aa268695bc4387fe3a857f3304013c2bd672dc1234cf2161343bf18efdc","tree":"fdc02ae7cab64e7ab641be509365b4b8201eaf3c6dddf7191ba01bbcd750d3ea","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"a74319ea5b78b3276b0aa7407b39f95e44c0676915ce815a979383d2afbc6e23","short_id":"a74319ea"},{"time":"2026-09-15T02:30:00Z","parent":"2f18a0cd5a226f2d04d075853265761756f6228499c1d8d6d08694c49bb3c2b7","tree":"1352369b945c41e97bbd11d3ca0f0ed4885046ce3e51e3762b4986b0c9b04ca0","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"bf5abbdc483043f91fefdde6e97249ee81610adca5195440770fea3ec9c014f1","short_id":"bf5abbdc"},{"time":"2026-09-15T02:30:00Z","parent":"a74319ea5b78b3276b0aa7407b39f95e44c0676915ce815a979383d2afbc6e23","tree":"be3be59ec618cf36d26d6d3e8368b560ce88c60b6eda56e861c6f5146f667be2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"0c24dfcc62048ac0b64dd13aad000479b47ceddfd2963119e631c488714f8cc3","short_id":"0c24dfcc"},{"time":"2026-09-16T02:30:00Z","parent":"0c24dfcc62048ac0b64dd13aad000479b47ceddfd2963119e631c488714f8cc3","tree":"39e7b89853eb47ec19c07a060be51173dd800a2d46417ae0201fefa3af33d90a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"e0ec672a95aacf51c562acf57701aba0e725a1d811ce3a6f5c2ebad549a8c016","short_id":"e0ec672a"},{"time":"2026-09-16T02:30:00Z","parent":"bf5abbdc483043f91fefdde6e97249ee81610adca5195440770fea3ec9c014f1","tree":"55007688ced33784bc5785e3dc9546f472cbeda9d545f9327aca913631586c3a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"f0a0d4eb6dda96f6db6099dff7156458aed506eeadca78859ad9657068e44501","short_id":"f0a0d4eb"},{"time":"2026-09-17T02:30:00Z","parent":"e0ec672a95aacf51c562acf57701aba0e725a1d811ce3a6f5c2ebad549a8c016","tree":"a037a5eb6e669bc15c6705f0c4eb665c729eefa37af2a196086ce1701230988e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"a2be8e6be366d62cca9bc6d4e12b1c97a310051e2fa8a077dff1fb07e904000a","short_id":"a2be8e6b"},{"time":"2026-09-17T02:30:00Z","parent":"f0a0d4eb6dda96f6db6099dff7156458aed506eeadca78859ad9657068e44501","tree":"92ac0d05e95224172f35772f54eb47981154feb9e6e58a4f03c3b273eea3dd1d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"ee89b04f40a213571e3a100a01c666b02566dde4ea56e902b11df9a2c3f13a09","short_id":"ee89b04f"},{"time":"2026-09-18T02:30:00Z","parent":"a2be8e6be366d62cca9bc6d4e12b1c97a310051e2fa8a077dff1fb07e904000a","tree":"251699699303a792c841f497662af163952386fd70b2d6dcfa435bd0d902ace2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"177c6f12c40c9f355adc60d0a875830e78353038462fe15beeb00f3afef04efe","short_id":"177c6f12"},{"time":"2026-09-18T02:30:00Z","parent":"ee89b04f40a213571e3a100a01c666b02566dde4ea56e902b11df9a2c3f13a09","tree":"862bd61ed170b4a5e0ec0fa971bf16a2fd295b5b0ca5ca8b5573d5d96bf46d0b","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"dc383edfe97cc655252f1ad872386b2fefeecc0b3e170e7a04d8683225214951","short_id":"dc383edf"},{"time":"2026-09-19T02:30:00Z","parent":"dc383edfe97cc655252f1ad872386b2fefeecc0b3e170e7a04d8683225214951","tree":"2ca8aade0fdfc72248d246771ee003972eaad397aa613f78dea4b2ba6d1a0287","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"0c97b2f8a266b152761dd1769c0898bc78a367c859ca8013edec68bfc61aa0d4","short_id":"0c97b2f8"},{"time":"2026-09-19T02:30:00Z","parent":"177c6f12c40c9f355adc60d0a875830e78353038462fe15beeb00f3afef04efe","tree":"a97bea5453e2a1a8913ee3965b4fec1632d677dfe0ecf74213efee6f43568e20","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"c2e659092443ccc73500e061690d9f99b0a653e8dcc002f441cd359385045e0e","short_id":"c2e65909"},{"time":"2026-09-20T02:30:00Z","parent":"c2e659092443ccc73500e061690d9f99b0a653e8dcc002f441cd359385045e0e","tree":"4ad27f2ca164c7d23866d5c06e75aa70ad20d8f86229816534ce7adcffb652a7","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"43902ad8c4d345ac41a98af33afc74fd36d2f6896fb45e94fe553ba3f2b51d0f","short_id":"43902ad8"},{"time":"2026-09-20T02:30:00Z","parent":"0c97b2f8a266b152761dd1769c0898bc78a367c859ca8013edec68bfc61aa0d4","tree":"f61ebed68d2e86ca59dc4e4223535a3aa8198562b2cecb812b52d3ba9e5411e7","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"ec0f30baecf767c3a02ec631814236071014258f0287f3044b591a34d5a99d73","short_id":"ec0f30ba"},{"time":"2026-09-21T02:30:00Z","parent":"43902ad8c4d345ac41a98af33afc74fd36d2f6896fb45e94fe553ba3f2b51d0f","tree":"f10d8afc6c36f40a793446537a09092aab457abaddd2f5dd884273014ffd986b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"ab24192f7a961b8103bdf4c5a3ab7d2a13b949b6accb9d52d1411f49d9d0deea","short_id":"ab24192f"},{"time":"2026-09-21T02:30:00Z","parent":"ec0f30baecf767c3a02ec631814236071014258f0287f3044b591a34d5a99d73","tree":"c1ddfe015a6300456c24a6561c1a1f247f255254834aac61435ceef06456e806","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"8f870fe269857d1d611fff5e03d2b22533bce7dc5aad4340de6cdf434b5aa0ae","short_id":"8f870fe2"},{"time":"2026-09-22T02:30:00Z","parent":"ab24192f7a961b8103bdf4c5a3ab7d2a13b949b6accb9d52d1411f49d9d0deea","tree":"1e0e3145356cbc6b68674824bdb7b2bc5524ab3fc8cbcb27368f9efb819c0124","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"7b37aba5b0971c1f41c15269fe2157e320b4f6428920d743302e4a904e053f63","short_id":"7b37aba5"},{"time":"2026-09-22T02:30:00Z","parent":"8f870fe269857d1d611fff5e03d2b22533bce7dc5aad4340de6cdf434b5aa0ae","tree":"31fbee51dde5e56f1d5940902bf8428ee4a1a2825a6081dea2b3ffb60a66ca26","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"5e41a7b17484c04288c67cce0dbf9cb3046325a9617b27f33d128ea5e906eebe","short_id":"5e41a7b1"},{"time":"2026-09-23T02:30:00Z","parent":"7b37aba5b0971c1f41c15269fe2157e320b4f6428920d743302e4a904e053f63","tree":"eac20fb1f7f17be350f01322cc58152ec05c680ba60706fa5f25db89bab1d264","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"6398aadc912ab1364b0c83f3e3ce51c3099bf74e018ac25107f51dbeed6b3c47","short_id":"6398aadc"},{"time":"2026-09-23T02:30:00Z","parent":"5e41a7b17484c04288c67cce0dbf9cb3046325a9617b27f33d128ea5e906eebe","tree":"1092cccb0c44787eb64ea2ea143189a5bf5d093ebfa0427d0cb07ac47543bcf4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"0c73460e3fa99b3c38ef31c378515f2424f18877bd354994d053576aa58ec214","short_id":"0c73460e"},{"time":"2026-09-24T02:30:00Z","parent":"6398aadc912ab1364b0c83f3e3ce51c3099bf74e018ac25107f51dbeed6b3c47","tree":"29e68a845705a5490fc07891a54fa6ff4d674183f4314f23361fb3d5c43b5057","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"264cbd7c1e22696db518c2b8aba55d9755e2799bab72d54d48f8521ae1740e84","short_id":"264cbd7c"},{"time":"2026-09-24T02:30:00Z","parent":"0c73460e3fa99b3c38ef31c378515f2424f18877bd354994d053576aa58ec214","tree":"530b2ba5c60bab9cc6f56148cf6388dff62236a252592031c10df1e2dd2607d6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"0b0bc0701cee5d7533d4a97f4c9ef7f5a401eb552d2ca3536a1ed5cebeb83f97","short_id":"0b0bc070"},{"time":"2026-09-25T02:30:00Z","parent":"0b0bc0701cee5d7533d4a97f4c9ef7f5a401eb552d2ca3536a1ed5cebeb83f97","tree":"c6508fdf7a64e55c2058145ba81f1b27e8687b8b2b2a4bd7324a157ef31ad12a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"d4562f249a7d2962d749dbaf843d8ac71b9c8ebb0c0b7cec09afcd8711529eea","short_id":"d4562f24"},{"time":"2026-09-25T02:30:00Z","parent":"264cbd7c1e22696db518c2b8aba55d9755e2799bab72d54d48f8521ae1740e84","tree":"0b332b3757a2111c5c5e1adcb59f011b4ce4716c350fbb289496525a612b27eb","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"ce4afadd45ee5a17b6e8f276704f99478bf5e82cc0870a5b4e6db3e07d64ace8","short_id":"ce4afadd"},{"time":"2026-09-26T02:30:00Z","parent":"ce4afadd45ee5a17b6e8f276704f99478bf5e82cc0870a5b4e6db3e07d64ace8","tree":"8f40b7ed62ec04ce4dd10a648fd97db920711a6f387503bb2a75f535de395656","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"e974e4a5987c5d524f227b4b091811a0488e5fed27cb736d511f009b13b13b1d","short_id":"e974e4a5"},{"time":"2026-09-26T02:30:00Z","parent":"d4562f249a7d2962d749dbaf843d8ac71b9c8ebb0c0b7cec09afcd8711529eea","tree":"36c5d5c1356cef66b9017f1411f798274554b52a7b01a8b4127ef1c30c6a02f6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"b26700ff3e9871ac081886d146fc30b9d8e7bd4572cea0b62f8f0261ea1a4f9d","short_id":"b26700ff"},{"time":"2026-09-27T02:30:00Z","parent":"e974e4a5987c5d524f227b4b091811a0488e5fed27cb736d511f009b13b13b1d","tree":"c5cb9ce2ff06516329a42aec557f7223e1a3c3801c502f7a53f0ab6414cedf15","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"7e67848219703f577e06ce2750b104a8c8f956978b05aafa4a205a3d258eb376","short_id":"7e678482"},{"time":"2026-09-27T02:30:00Z","parent":"b26700ff3e9871ac081886d146fc30b9d8e7bd4572cea0b62f8f0261ea1a4f9d","tree":"21aa00a24cb6990028d074e46a5af0457b5bc87da6867d0857663f776247b8cc","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"e24109dd53394e0bd7278f7b5e3fffa90f685bfdcd0a93952cff5638967a13fe","short_id":"e24109dd"},{"time":"2026-09-28T02:30:00Z","parent":"7e67848219703f577e06ce2750b104a8c8f956978b05aafa4a205a3d258eb376","tree":"e03a49f45c2db8d9342d90626025311ca3592d7d78c6dd6eeb8ffed0848c7ae0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"a695cd17a42947d6a5f1d74db5dc14f508cffbd7f98582124a25c53d47defd21","short_id":"a695cd17"},{"time":"2026-09-28T02:30:00Z","parent":"e24109dd53394e0bd7278f7b5e3fffa90f685bfdcd0a93952cff5638967a13fe","tree":"7c0a07c56348b0fa19b9507bf17dada815bdf81517a714408db21e288fc554b3","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"f062f3c51cde5c848398daa1b47cd122d76a0639c76f9436983ae2657895f352","short_id":"f062f3c5"},{"time":"2026-09-29T02:30:00Z","parent":"f062f3c51cde5c848398daa1b47cd122d76a0639c76f9436983ae2657895f352","tree":"b99010471bc3056f04c0a8dd25fa412b4834f977d1a7600c03b03b1bb8a9d8fe","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"cb87227f0c1c6acf4999c4b2024b589203cb184ce089a01a2db472ddbb560380","short_id":"cb87227f"},{"time":"2026-09-29T02:30:00Z","parent":"a695cd17a42947d6a5f1d74db5dc14f508cffbd7f98582124a25c53d47defd21","tree":"07492d5c8986dadc99631897cd7c4acfe18ec97dd70898d09899d5cd87b9539e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"35e79f2b266136d2be26273e4eabb20005fd5158e59539cd492b0c8e4bbfb2d3","short_id":"35e79f2b"},{"time":"2026-09-30T02:30:00Z","parent":"35e79f2b266136d2be26273e4eabb20005fd5158e59539cd492b0c8e4bbfb2d3","tree":"56b96a8e688ab8190bddb0868d331ece565f8856aef3cdcfef32fc1518e6baf2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"5ae64e02898e62676cdb3ba4689ed25eb83588a65127d244e69417846e495d78","short_id":"5ae64e02"},{"time":"2026-09-30T02:30:00Z","parent":"cb87227f0c1c6acf4999c4b2024b589203cb184ce089a01a2db472ddbb560380","tree":"b778b7edf7fa14307405e72c16f20050fc813cf944bda6b445d209db77e4bc00","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"8e604e28a0930828c9080477856be09c1475c467ac41f6ded7e2da5bdb3571ac","short_id":"8e604e28"},{"time":"2026-10-01T02:30:00Z","parent":"5ae64e02898e62676cdb3ba4689ed25eb83588a65127d244e69417846e495d78","tree":"b4403fd15f29eced5de4749e59d5b9fe2022030132fe5e9e4d6bb64f83a1cf92","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"bfaf7ca84276c21938171a2d38258647686386fc83df7f24a1b7d67de552202a","short_id":"bfaf7ca8"},{"time":"2026-10-01T02:30:00Z","parent":"8e604e28a0930828c9080477856be09c1475c467ac41f6ded7e2da5bdb3571ac","tree":"bcd5f11e44998ee9e52c5b89ea0a4867e06475bc90b5cb4267364ab6146c9d01","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"23ab590268b600c179d6636df65055810c0def0e99a571cdcb7890c556446cc2","short_id":"23ab5902"},{"time":"2026-10-02T02:30:00Z","parent":"bfaf7ca84276c21938171a2d38258647686386fc83df7f24a1b7d67de552202a","tree":"0fd6c21124d32f9e6a9ee6c3d3a740143c7d90683391082c42bd6cd3bfd0f530","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"cee066c08d1f2f222dd490fa86e4a7931be865004d0aaf50e63f8536d0e232ec","short_id":"cee066c0"},{"time":"2026-10-02T02:30:00Z","parent":"23ab590268b600c179d6636df65055810c0def0e99a571cdcb7890c556446cc2","tree":"65f5c632a0d2b90ad809a363562f24e3f66d1c52483a9defd47b266da1af4199","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"bd15d29185bb8d6e805451f5e17315396cf315d27c4ca53b9d31d0798ce9d182","short_id":"bd15d291"},{"time":"2026-10-03T02:30:00Z","parent":"cee066c08d1f2f222dd490fa86e4a7931be865004d0aaf50e63f8536d0e232ec","tree":"2fdf5cb4f765aeda71371e854f2b73e96ed86e5deb4b54faf6d45ad76756cfb5","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"0e6cad1bee36f6ce4c5d28d756f256bb692a1419cf91e29cc1a856c22d5975e7","short_id":"0e6cad1b"},{"time":"2026-10-03T02:30:00Z","parent":"bd15d29185bb8d6e805451f5e17315396cf315d27c4ca53b9d31d0798ce9d182","tree":"f1dad16a3035d09aac43fe50021f0d0c50ff022c54b28b5c499cf572c95b5746","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"7c1f837ad939b4f4c376a0ff177862f08d87e4616cbe8e54a60d4a666b804ce7","short_id":"7c1f837a"},{"time":"2026-10-04T02:30:00Z","parent":"0e6cad1bee36f6ce4c5d28d756f256bb692a1419cf91e29cc1a856c22d5975e7","tree":"4709d5189f78175060c473debd32bbc95e655c0a6e5ca9792c34b3fd0415de69","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"960d1e720e43e9cb467f170f45277f133494374baa337f93a8af1b973e4b84b3","short_id":"960d1e72"},{"time":"2026-10-04T02:30:00Z","parent":"7c1f837ad939b4f4c376a0ff177862f08d87e4616cbe8e54a60d4a666b804ce7","tree":"a5e934915e68d97267ee3b108c7ee16ea0867e651b9232443fe919d83fa3a4c2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"fa1d764f43f6190cf22b9a763d8cc972d7dc3bb01aaf4f1074e56dbfc350c5e8","short_id":"fa1d764f"},{"time":"2026-10-05T02:30:00Z","parent":"fa1d764f43f6190cf22b9a763d8cc972d7dc3bb01aaf4f1074e56dbfc350c5e8","tree":"d74e551770184290eb6224af4d48c4008a5b3b7e7cb8204eb3c85c14354d19df","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"2a9ca46af4806ddc2989b343739647e93f622ce863a6610d58e3e5b5f1bae413","short_id":"2a9ca46a"},{"time":"2026-10-05T02:30:00Z","parent":"960d1e720e43e9cb467f170f45277f133494374baa337f93a8af1b973e4b84b3","tree":"8bffed4ff0074c8dbc58f616ddfea18aae6a4bbafb6f3ead72cc2d6fdc7bb7d7","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"d1a3dffd18e46a92ee75c698f7c716727a942ace2efba7ccc2935b6087992908","short_id":"d1a3dffd"},{"time":"2026-10-06T02:30:00Z","parent":"d1a3dffd18e46a92ee75c698f7c716727a942ace2efba7ccc2935b6087992908","tree":"978e63c6278adf45029b4c51f773aac5252d334e4d2782f2fac88174fedbb1ff","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"c7aee7b89b42a2539a75e863e0083ae8761ee7ed8826b5a6c3d49820c0e6ba26","short_id":"c7aee7b8"},{"time":"2026-10-06T02:30:00Z","parent":"2a9ca46af4806ddc2989b343739647e93f622ce863a6610d58e3e5b5f1bae413","tree":"1782fe2e236f85c58cf9b786a7737b5e7974ad71b960bfeaf4240bc528fec665","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"a0ad00ea114be1368fbce2b72ca2f638b904795e73124adb8bd25ae30458933e","short_id":"a0ad00ea"},{"time":"2026-10-07T02:30:00Z","parent":"c7aee7b89b42a2539a75e863e0083ae8761ee7ed8826b5a6c3d49820c0e6ba26","tree":"87bbe7cfd2c5e04fffb43951ae72dbcdc26c2e4eac1be4fa384c26238139d7f3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"2d383c39077530c4a9f98ba8dc20f014e210854d2c4f32f79b335a19388b1e89","short_id":"2d383c39"},{"time":"2026-10-07T02:30:00Z","parent":"a0ad00ea114be1368fbce2b72ca2f638b904795e73124adb8bd25ae30458933e","tree":"a360e27e1aef84a6eacdf3dba92ab0a46a3628869c2af12d3c1b412863b0535d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"a818ad6aa46ec61c586a0ffb38e63148a69c7bbc08fd0a09acb6734278fbd63b","short_id":"a818ad6a"},{"time":"2026-10-08T02:30:00Z","parent":"2d383c39077530c4a9f98ba8dc20f014e210854d2c4f32f79b335a19388b1e89","tree":"f44bda5e625b1e7636d14efb44c79f9451ef71475b38751bd2c962d04f86ebd4","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"c27b0d1dabe2d975d297daad5b01ad678fb4c88e2d1e6e6ed5f2cf4aa21c5410","short_id":"c27b0d1d"},{"time":"2026-10-08T02:30:00Z","parent":"a818ad6aa46ec61c586a0ffb38e63148a69c7bbc08fd0a09acb6734278fbd63b","tree":"4caaed0b8ce301dc03a64b5fe8e441a3bf6cb9297bf96ad72d62c3b45525ef01","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"ec2a30d9ff60c7473067c0f6b620948f728174c7a5bb8eddfa238f0d8af5066f","short_id":"ec2a30d9"},{"time":"2026-10-09T02:30:00Z","parent":"c27b0d1dabe2d975d297daad5b01ad678fb4c88e2d1e6e6ed5f2cf4aa21c5410","tree":"0ffe8da4512fd658f56dc4ee240488b5d63ae4c07f742810846df3044a365f5a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"13ecd2eeb9d433ae4be796a9dd9e289b7f12aa55b807cbca1ac6d88b6033accd","short_id":"13ecd2ee"},{"time":"2026-10-09T02:30:00Z","parent":"ec2a30d9ff60c7473067c0f6b620948f728174c7a5bb8eddfa238f0d8af5066f","tree":"2e07df0532a24fe466f5fe8415b3c4e7a208d130974b1543591f7d5e42be04ba","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"29607a0ab3c4afc1d63525a96605bb44e0b5f4de690d1ed44bfd3bbc27025fa2","short_id":"29607a0a"},{"time":"2026-10-10T02:30:00Z","parent":"29607a0ab3c4afc1d63525a96605bb44e0b5f4de690d1ed44bfd3bbc27025fa2","tree":"357713e3a55168ec6bea559274dc7552b4fbd64381ce4bde9022e242ec328ad1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"5e76f560c4d54a477fce35b1a96ce61374291dc8fa52b6dfb76fde6d91f25bdb","short_id":"5e76f560"},{"time":"2026-10-10T02:30:00Z","parent":"13ecd2eeb9d433ae4be796a9dd9e289b7f12aa55b807cbca1ac6d88b6033accd","tree":"0ad2f65dd3de6f7fe4f32210cc07fae810683c769591e3122e9c12acd64a4281","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"cd0707729940a95ae60e9297780e370798d6ed750dc711dc6c34c80c82a6f105","short_id":"cd070772"},{"time":"2026-10-11T02:30:00Z","parent":"cd0707729940a95ae60e9297780e370798d6ed750dc711dc6c34c80c82a6f105","tree":"e408a9e30f5cb44933c7faaec25373d0874bc7e9447bf28ceda6fff612611d92","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"23ae66812d30a5ba39d9ec618c3e3dd453a2883da4d07e7c39438168388069d9","short_id":"23ae6681"},{"time":"2026-10-11T02:30:00Z","parent":"5e76f560c4d54a477fce35b1a96ce61374291dc8fa52b6dfb76fde6d91f25bdb","tree":"afe3b0d5eaf569af22f299df9b77ccd8166b7c654c0e886b7452bb10512d0706","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"8ff9e57a4c7e509cd5e49202f3617630771e0d839ad04911b8106b8b7c4207af","short_id":"8ff9e57a"},{"time":"2026-10-12T02:30:00Z","parent":"23ae66812d30a5ba39d9ec618c3e3dd453a2883da4d07e7c39438168388069d9","tree":"b721e2ac4dcc985dd24b608acb6b5243dad979038229a6a5b8e501cc2d7bad8e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"26da1569ccbbd96c81a266beef45c84e5a4b6dc870f44a41a89c437ebb09c09f","short_id":"26da1569"},{"time":"2026-10-12T02:30:00Z","parent":"8ff9e57a4c7e509cd5e49202f3617630771e0d839ad04911b8106b8b7c4207af","tree":"879f6a9563bba4bcdebbea7f32c27b9e452615464c6dc3111c2df59cd661a8a1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"4a611990c2123e859808a8546af22c372308a27a87b335aeeb89276e97049165","short_id":"4a611990"},{"time":"2026-10-13T02:30:00Z","parent":"26da1569ccbbd96c81a266beef45c84e5a4b6dc870f44a41a89c437ebb09c09f","tree":"3c0228aa205d8a36c5b4fe501ba5e50d638e219cf2cd4aef45f77e0ba9fc5bb0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"5339cf6d7ec710b3998e7bf52a09a17cbb5907d2c09ccf18ace19f525b812ae8","short_id":"5339cf6d"},{"time":"2026-10-13T02:30:00Z","parent":"4a611990c2123e859808a8546af22c372308a27a87b335aeeb89276e97049165","tree":"279178ad0293ba5157fdd209ec244a1d4899b58e1b9459c11ecac057cac60ff4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"e3fc65e0827c6939f7d86880e75facf36c2692f9cd259fe880232ee7de2a5391","short_id":"e3fc65e0"},{"time":"2026-10-14T02:30:00Z","parent":"5339cf6d7ec710b3998e7bf52a09a17cbb5907d2c09ccf18ace19f525b812ae8","tree":"57ab0a0f2ea360c1fbdfbc3b700e0225fb347eb8e715750283bb4b46e1133bf3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"47bbaa059c6e306c801b5f793e5f3500d1a0c258c3075855aa160276b4a0c704","short_id":"47bbaa05"},{"time":"2026-10-14T02:30:00Z","parent":"e3fc65e0827c6939f7d86880e75facf36c2692f9cd259fe880232ee7de2a5391","tree":"377caf3fbe1e17b4af93cc053064cde6b40976809805fcdebb0645e41b649ffb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"2b09f89771cf2744dde14e804ed9e7342871c8a6c1cb4849b8128f5d2571342f","short_id":"2b09f897"},{"time":"2026-10-15T02:30:00Z","parent":"47bbaa059c6e306c801b5f793e5f3500d1a0c258c3075855aa160276b4a0c704","tree":"a0dd167d57e68ce11fde606350779191cdc8c4413875240091be5880fb91c66e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","short_id":"27898187"},{"time":"2026-10-15T02:30:00Z","parent":"2b09f89771cf2744dde14e804ed9e7342871c8a6c1cb4849b8128f5d2571342f","tree":"8f361f971daac52f40180aa7fd3e4638e4ef90903699241b16954ee17fa304e6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"ee8432e0cd7bb4113731adc2e76d492238b539c3d6ce24a408670fee40579e57","short_id":"ee8432e0"},{"time":"2026-10-16T02:30:00Z","parent":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","tree":"b830b8165dc45c4b23086a81004548a5a52a00060028f0d274d8098dcc168b49","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"94fc37b9bfe97271d4a0b0feda4443a5e2934a3557108dd521d0bfb2f49423c8","short_id":"94fc37b9"},{"time":"2026-10-16T02:30:00Z","parent":"ee8432e0cd7bb4113731adc2e76d492238b539c3d6ce24a408670fee40579e57","tree":"024c36c1f532ac9150f9768ed57bb27cb284f8949f51958804dfd0f11ee70b65","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"315ff629674caa42ace8498b9d4bb82e5a77cb2284e628560444e12d9072ec8f","short_id":"315ff629"}] diff --git a/controller/internal/backup/testdata/restic/0.14.0/stats-raw.json b/controller/internal/backup/testdata/restic/0.14.0/stats-raw.json index 18f114d..847e91e 100644 --- a/controller/internal/backup/testdata/restic/0.14.0/stats-raw.json +++ b/controller/internal/backup/testdata/restic/0.14.0/stats-raw.json @@ -1 +1 @@ -{"total_size":217738,"total_file_count":0,"total_blob_count":863,"snapshots_count":82} +{"total_size":217458,"total_file_count":0,"total_blob_count":863,"snapshots_count":82} diff --git a/controller/internal/backup/testdata/restic/0.18.1/backup-status.jsonl b/controller/internal/backup/testdata/restic/0.18.1/backup-status.jsonl index 3ca7e7e..424671e 100644 --- a/controller/internal/backup/testdata/restic/0.18.1/backup-status.jsonl +++ b/controller/internal/backup/testdata/restic/0.18.1/backup-status.jsonl @@ -1,4 +1,4 @@ -{"message_type":"status","percent_done":0.056467624048707366,"total_files":3,"files_done":2,"total_bytes":41943061,"bytes_done":2368425,"current_files":["/data/x/u/a/big.tar"]} -{"message_type":"status","percent_done":0.5571281981541595,"total_files":3,"files_done":2,"total_bytes":41943061,"bytes_done":23367662,"current_files":["/data/x/u/a/big.tar"]} +{"message_type":"status","percent_done":5.006787654339296e-7,"total_files":3,"files_done":2,"total_bytes":41943061,"bytes_done":21,"current_files":["/data/x/u/a/big.tar"]} +{"message_type":"status","percent_done":0.5636983671744893,"total_files":3,"files_done":2,"total_bytes":41943061,"bytes_done":23643235,"current_files":["/data/x/u/a/big.tar"]} {"message_type":"status","percent_done":1,"total_files":3,"files_done":2,"total_bytes":41943061,"bytes_done":41943061} {"message_type":"status","percent_done":1,"total_files":3,"files_done":3,"total_bytes":41943061,"bytes_done":41943061} diff --git a/controller/internal/backup/testdata/restic/0.18.1/check-damaged.txt b/controller/internal/backup/testdata/restic/0.18.1/check-damaged.txt index 7c73d03..c847f5f 100644 --- a/controller/internal/backup/testdata/restic/0.18.1/check-damaged.txt +++ b/controller/internal/backup/testdata/restic/0.18.1/check-damaged.txt @@ -1,18 +1,18 @@ -using temporary cache in /data/x/cache/restic-check-cache-3291579747 +using temporary cache in /data/x/cache/restic-check-cache-1056767702 create exclusive lock for repository load indexes check all packs check snapshots, trees and blobs -error for tree 49327794: - decrypting blob from fc6016f0 failed: ciphertext verification failed +error for tree 2dd49e74: + decrypting blob from fd6de2a5 failed: ciphertext verification failed [0:00] 100.00% 82 / 82 snapshots read all data -pack fc6016f0ad5e780ab7d800bd3012c8a602eb1dc9e291dedd61ea3d027befae72 contains 2 errors: [blob 49327794eaad1ff31fb67ceb6bad31d812456993a7543d5fdf7ec8dad187e156: decrypting blob from fc6016f0 failed: ciphertext verification failed unexpected pack id 39ddedb2fc2555d1e386d3eb7c440142ec3d7c02484f3d10db46105343393948] +pack fd6de2a5f8204c762b7a38c35a81a60785d6a542d3506a63dadad936b0aeb160 contains 2 errors: [blob 2dd49e743c4d0b61ec5cfa2dc99f5446d5e7482635df00484aaa6a193aba98b8: decrypting blob from fd6de2a5 failed: ciphertext verification failed unexpected pack id d22a000a356e727dc3afaeef9408a189de77107618df88519e050153a5a653a8] [0:00] 100.00% 123 / 123 packs The repository contains damaged pack files. These damaged files must be removed to repair the repository. This can be done using the following commands. Please read the troubleshooting guide at https://restic.readthedocs.io/en/stable/077_troubleshooting.html first. -restic repair packs fc6016f0ad5e780ab7d800bd3012c8a602eb1dc9e291dedd61ea3d027befae72 +restic repair packs fd6de2a5f8204c762b7a38c35a81a60785d6a542d3506a63dadad936b0aeb160 restic repair snapshots --forget Damaged pack files can be caused by backend problems, hardware problems or bugs in restic. Please open an issue at https://github.com/restic/restic/issues/new/choose for further troubleshooting! diff --git a/controller/internal/backup/testdata/restic/0.18.1/check-ok.txt b/controller/internal/backup/testdata/restic/0.18.1/check-ok.txt index e17bf2d..c72ddc3 100644 --- a/controller/internal/backup/testdata/restic/0.18.1/check-ok.txt +++ b/controller/internal/backup/testdata/restic/0.18.1/check-ok.txt @@ -1,4 +1,4 @@ -using temporary cache in /data/x/cache/restic-check-cache-4211187088 +using temporary cache in /data/x/cache/restic-check-cache-2213934293 create exclusive lock for repository load indexes check all packs diff --git a/controller/internal/backup/testdata/restic/0.18.1/forget-dryrun.json b/controller/internal/backup/testdata/restic/0.18.1/forget-dryrun.json index e379a44..511664b 100644 --- a/controller/internal/backup/testdata/restic/0.18.1/forget-dryrun.json +++ b/controller/internal/backup/testdata/restic/0.18.1/forget-dryrun.json @@ -1 +1 @@ -[{"tags":["b","felhom-offbox"],"host":"box","paths":null,"keep":[{"time":"2026-10-16T02:30:00Z","parent":"331513b5478c67fd17b601f4e86536be66fdebac42db635d2b44073c418c9044","tree":"2479779a0246aded8ea88b1b43549f333df32233150ead772301d4060d9834b6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"1bb3e0b01ad4e9ef4092c0f4f38d003d026d3e62bd4ec32ad84d2ae50b1fc26b","short_id":"1bb3e0b0"},{"time":"2026-10-15T02:30:00Z","parent":"8d4189078ef8c5de57f8e0a58d646229c6ea05a584a223b13d6d52ee9b2a499a","tree":"c81de4fd5684584aecccba2848d623d9b46d27aaa7a8fda0cf7a4a56faa19f12","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"331513b5478c67fd17b601f4e86536be66fdebac42db635d2b44073c418c9044","short_id":"331513b5"},{"time":"2026-10-14T02:30:00Z","parent":"4a74cebcf061b3f721ce35f1dae2fe644c3dcb77620042d6a9e9a1f69ffa5908","tree":"22deec6d4575076f3b5b9228249ef0935883841659af9e60c2e471f903d301cf","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8d4189078ef8c5de57f8e0a58d646229c6ea05a584a223b13d6d52ee9b2a499a","short_id":"8d418907"},{"time":"2026-10-13T02:30:00Z","parent":"44f0faa89145f8dd68e06437323d677fae465f54c4f6aa95f938234ba0112f57","tree":"2f79914cd5a90ceb735c3dd272c22db5a67f5f1c6a35f48af320f7b218959177","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"4a74cebcf061b3f721ce35f1dae2fe644c3dcb77620042d6a9e9a1f69ffa5908","short_id":"4a74cebc"},{"time":"2026-10-12T02:30:00Z","parent":"9dcb3fa42c8d5b880c7e407ea15e134d540bab3fb250a63854c14dddb1748b79","tree":"7945e1927ec6444933dbe89befa7f342ffd218ab2a96d824a3e3cd9a25f11286","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"44f0faa89145f8dd68e06437323d677fae465f54c4f6aa95f938234ba0112f57","short_id":"44f0faa8"},{"time":"2026-10-11T02:30:00Z","parent":"b82290210fdaab03ba7fa7066ab61e31c5a3545d80a5dec4533fe21ded17dc95","tree":"41316836995752c254b9adce2243f694fab0421b8359109df23ea1fb996ce0fb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"9dcb3fa42c8d5b880c7e407ea15e134d540bab3fb250a63854c14dddb1748b79","short_id":"9dcb3fa4"},{"time":"2026-10-10T02:30:00Z","parent":"dd010c8b70468216b74dc107c0125f008c1e8a0d889481e481e40f8f82994764","tree":"f1ca437cda2b7f0db26af3d9b7509db45f238cd346a1f62bf801252daca93420","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"b82290210fdaab03ba7fa7066ab61e31c5a3545d80a5dec4533fe21ded17dc95","short_id":"b8229021"},{"time":"2026-10-04T02:30:00Z","parent":"eabaa0652f6549580fa3b1125f842209428a1b425016621190a4764bed2afb08","tree":"468d616ac9063de9f2829a1fd9d3d362af359c6ce79403d9bdb41f56707f7570","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"3a916d89540e17509b7c6ac5dc43d5842d268970dcb2470737a635e9ef343734","short_id":"3a916d89"},{"time":"2026-09-30T02:30:00Z","parent":"2ef32e3aec2169bfd005c607d23fa8caefd3597d5933a2ee6ef0992954439e11","tree":"a37fa979d19d953863ad8b8cb276382dcee1e0f2cfe1c87d91908d1a6a9a95e0","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"1b5e6b74f1abaf4d4f390be385bf34650eebe21aa034aeaba3e29150193532c2","short_id":"1b5e6b74"},{"time":"2026-09-27T02:30:00Z","parent":"b6c3ff0ed8c270eed4c0d1c691ad5fca3b4957f13d1bde79f29094150536529c","tree":"f06890a88f7ac258af5adf77d52b9f7b9fef3414ac7effce40eb52ebbab0fe29","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"88ce7523616beee04180afa0d25c2048c41d4431391e0c0c5c6e923921a9268e","short_id":"88ce7523"},{"time":"2026-09-06T02:30:00Z","tree":"4ad0876539f4a3e21e3a3970e2acc6b054f595a2cf08a99fdcb5bb330bd24d49","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"a4391a2d1fa176171693df8ccda6c8c334cf0736e64a36af579d5f7d8c23b20b","short_id":"a4391a2d"}],"remove":[{"time":"2026-10-09T02:30:00Z","parent":"0095d1024e633c17869e063c307b6e7ef74dd54a0e8c406c91bf38ca7ad16f1b","tree":"c14587a70d549b4cf45f6091ba985e7c57911d9ce65aa0ae6fcbb54cd2798320","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"dd010c8b70468216b74dc107c0125f008c1e8a0d889481e481e40f8f82994764","short_id":"dd010c8b"},{"time":"2026-10-08T02:30:00Z","parent":"20cccbaa5b814f5a1a1816d1c49af6f4703dd33e7c62faf4a2152d15161c45f0","tree":"58a11c46cd107e285a02424d5fedf8c6c3831ec57d5231dca34a77221478230f","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"0095d1024e633c17869e063c307b6e7ef74dd54a0e8c406c91bf38ca7ad16f1b","short_id":"0095d102"},{"time":"2026-10-07T02:30:00Z","parent":"4600ed1a4a0a08348ad95e38368431242b4eeb9be82ca860c7dcd626833d38fb","tree":"e89d06f95e23814a4c5b36b1a61d51b59b621b0a1c0750ef93f71e2beff2e17b","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"20cccbaa5b814f5a1a1816d1c49af6f4703dd33e7c62faf4a2152d15161c45f0","short_id":"20cccbaa"},{"time":"2026-10-06T02:30:00Z","parent":"c86697c291b279d448ba785b6e600794a811980413d3119cc1e7dd4c07b15124","tree":"3b18bc51857c3b43ef3b7f7251a747a4aa1d860336c3276c1e895b8ed89c990e","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"4600ed1a4a0a08348ad95e38368431242b4eeb9be82ca860c7dcd626833d38fb","short_id":"4600ed1a"},{"time":"2026-10-05T02:30:00Z","parent":"3a916d89540e17509b7c6ac5dc43d5842d268970dcb2470737a635e9ef343734","tree":"353fcfbdbb2b33da457308307d2aca87f18cf9e45a4e3c8f56e1ee4060dc555f","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"c86697c291b279d448ba785b6e600794a811980413d3119cc1e7dd4c07b15124","short_id":"c86697c2"},{"time":"2026-10-03T02:30:00Z","parent":"3869db68bb5543ab788ddca26d61583a6137ff71d6be864be83762359192c232","tree":"2fcca788daf43bbcea34d3e41650cb2f94549620a997511365e9018d667db0d0","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"eabaa0652f6549580fa3b1125f842209428a1b425016621190a4764bed2afb08","short_id":"eabaa065"},{"time":"2026-10-02T02:30:00Z","parent":"6d39107b801aff3b7d929393c3070ccfee278387276db8aacf1b46b8a5da1e1c","tree":"ee800f29da370e89ef260c6be721d6dfb691c85b9ca2b35ff2bd2340c4fc737a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"3869db68bb5543ab788ddca26d61583a6137ff71d6be864be83762359192c232","short_id":"3869db68"},{"time":"2026-10-01T02:30:00Z","parent":"1b5e6b74f1abaf4d4f390be385bf34650eebe21aa034aeaba3e29150193532c2","tree":"aad23ab1f6a4a59f8e09fca43fa8927321a5cfa6707310a9a66ed4738ffd6c4d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"6d39107b801aff3b7d929393c3070ccfee278387276db8aacf1b46b8a5da1e1c","short_id":"6d39107b"},{"time":"2026-09-29T02:30:00Z","parent":"999889b6f8de7d3eafeaa86ad705420affcfdf646e10a0c366ee82f3bfa5a758","tree":"8636f52172dd153181a2eeeacadaf422a0ab9230d3a9eb300a323d9ecf6d2bda","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"2ef32e3aec2169bfd005c607d23fa8caefd3597d5933a2ee6ef0992954439e11","short_id":"2ef32e3a"},{"time":"2026-09-28T02:30:00Z","parent":"88ce7523616beee04180afa0d25c2048c41d4431391e0c0c5c6e923921a9268e","tree":"c7dada1e21510896f6475d62d0f2f88454c7719b0a74c79ce3593bc14f4d19ff","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"999889b6f8de7d3eafeaa86ad705420affcfdf646e10a0c366ee82f3bfa5a758","short_id":"999889b6"},{"time":"2026-09-26T02:30:00Z","parent":"738389466ef5b3f129a2392fb14371e16604c6a3071ad89b1cc97154539df00b","tree":"7a29695c4ffb7201fe199173c93083bf98a3eb6083d4171e819b25c385ee3292","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"b6c3ff0ed8c270eed4c0d1c691ad5fca3b4957f13d1bde79f29094150536529c","short_id":"b6c3ff0e"},{"time":"2026-09-25T02:30:00Z","parent":"3c149e5a2092648bbdf09398f04ee351b8eb3e43f5d9e5f92a216328fe2192a8","tree":"f766854d8b67adac39aa2971fe1eeda94a4adbde52cc473929e03cbc97f15929","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"738389466ef5b3f129a2392fb14371e16604c6a3071ad89b1cc97154539df00b","short_id":"73838946"},{"time":"2026-09-24T02:30:00Z","parent":"148fb7b1b6e4cc4ebb5ca99ea00cd92703065c4879c5edcf88890d082dd6f31c","tree":"f90e90886d9e47a708c439f90ab0b811e00372c122928d4db0b3a679643e7377","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"3c149e5a2092648bbdf09398f04ee351b8eb3e43f5d9e5f92a216328fe2192a8","short_id":"3c149e5a"},{"time":"2026-09-23T02:30:00Z","parent":"d27d1ae70c280fdb945c0366ba17c654d3b5be2516d8e4e6ae862a3be0cbac54","tree":"5ff035bfe269e00cbdca9b6c966b822a578ae26742a29938a89ac1ff92dd5fed","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"148fb7b1b6e4cc4ebb5ca99ea00cd92703065c4879c5edcf88890d082dd6f31c","short_id":"148fb7b1"},{"time":"2026-09-22T02:30:00Z","parent":"79792a9b1e5603f08b6228fae860d8c974313bccc6ff2dde76270f3cc521d5c7","tree":"76e67a0fd8eb8215e67487127e1823ec76db61eafde6f9519ffbc5388fd1de9f","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"d27d1ae70c280fdb945c0366ba17c654d3b5be2516d8e4e6ae862a3be0cbac54","short_id":"d27d1ae7"},{"time":"2026-09-21T02:30:00Z","parent":"e62e8764fadbcb8dd8b59fd2c861603fb48891e451a50c1f8d8fa84effe6c693","tree":"2fcc4e0dd7db7447990b38ec9c93ad2c83297ea1e9ab17b1b50c3c0f24637579","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"79792a9b1e5603f08b6228fae860d8c974313bccc6ff2dde76270f3cc521d5c7","short_id":"79792a9b"},{"time":"2026-09-20T02:30:00Z","parent":"57880fadf8682a92a4992909de29de94d2fff6f45689e2e82277b5cf8911f13f","tree":"6d32c2444b76fb0eb422b1290fb41309ba642c2c8389519a6ee286e5726594f1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"e62e8764fadbcb8dd8b59fd2c861603fb48891e451a50c1f8d8fa84effe6c693","short_id":"e62e8764"},{"time":"2026-09-19T02:30:00Z","parent":"9a5d9b218160f2a99d228dfbe7d5c94c425a55d34c931b958a5094981337efe3","tree":"e9c735d5260376c08bf4ba6ff9ca2c11325e9013a15509b4559c94c4170a6ae4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"57880fadf8682a92a4992909de29de94d2fff6f45689e2e82277b5cf8911f13f","short_id":"57880fad"},{"time":"2026-09-18T02:30:00Z","parent":"3610529c13a4b87deea7309dc9e352c96e79cd8c465d79590643c3192d3383ef","tree":"6a7b9de7f8a847690487acab15e9808a7c485a77da3202aa7394dfdb048ac828","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"9a5d9b218160f2a99d228dfbe7d5c94c425a55d34c931b958a5094981337efe3","short_id":"9a5d9b21"},{"time":"2026-09-17T02:30:00Z","parent":"0e064dcba9e15e96b4a5066b1847d550163d9943314615e34e7f4927c1ffe20a","tree":"1a527598187b2c775100f690c73af64d8cc662c84935eaf2256fee9730bb0766","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"3610529c13a4b87deea7309dc9e352c96e79cd8c465d79590643c3192d3383ef","short_id":"3610529c"},{"time":"2026-09-16T02:30:00Z","parent":"8905c672851940782321709d03e4d976cc8975aeb63c9ef50a7713ad2e257d75","tree":"3ca35c35a404dcd752bb371217365049d27737d3604af69924d070b520dd9ae2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"0e064dcba9e15e96b4a5066b1847d550163d9943314615e34e7f4927c1ffe20a","short_id":"0e064dcb"},{"time":"2026-09-15T02:30:00Z","parent":"7ca16908b1c9ba4e9c9719bed7e0ec0f3987e155bafaf5bab4bb0a903067ae07","tree":"489bf44b49d5679494a5d660eea153236adc9af8a6f768cee85b40c9444395fb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8905c672851940782321709d03e4d976cc8975aeb63c9ef50a7713ad2e257d75","short_id":"8905c672"},{"time":"2026-09-14T02:30:00Z","parent":"dd8abd92e055c916448d058660cc0b4ed63cb99a418b1941119c33bbb30f2e37","tree":"e0c2d3e7cdf6db59ffafe688a844e75c62211868b38efcdc6025cd497312f03d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"7ca16908b1c9ba4e9c9719bed7e0ec0f3987e155bafaf5bab4bb0a903067ae07","short_id":"7ca16908"},{"time":"2026-09-13T02:30:00Z","parent":"4facc0c230bf587cde80d5a3d3cbb62e938150316545d2f91f883a8f0f23560b","tree":"6f7f51fbf57abeb9fc1af9689e59212344b12e833a926b9ba1ada7dfb926bccc","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"dd8abd92e055c916448d058660cc0b4ed63cb99a418b1941119c33bbb30f2e37","short_id":"dd8abd92"},{"time":"2026-09-12T02:30:00Z","parent":"9a9b7aee5b1b8801a89190f64cd0a25cdc0de5dc90bf507727de8ee76b70d59d","tree":"56ea6daeaf9b8c6e55fe21d488e0c7b90d926290fc98da3de942ca4aa7b57ce1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"4facc0c230bf587cde80d5a3d3cbb62e938150316545d2f91f883a8f0f23560b","short_id":"4facc0c2"},{"time":"2026-09-11T02:30:00Z","parent":"24331fad4982bf1e6e5be6f899580e71f69a7a3dc29785b40ec595b16f9ede7b","tree":"b13daaa02a014a7f2811f6cd845bc427883833ac6e578677fffb9756cb08855d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"9a9b7aee5b1b8801a89190f64cd0a25cdc0de5dc90bf507727de8ee76b70d59d","short_id":"9a9b7aee"},{"time":"2026-09-10T02:30:00Z","parent":"c2dd9de7fe5ce5e76bf986b99c0115da212f8b07277da5c236092dc4144d8af3","tree":"09722b272016f5585fe991a8b5cd5a9451cbf778cb64d9d65ca1cde792e9ace7","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"24331fad4982bf1e6e5be6f899580e71f69a7a3dc29785b40ec595b16f9ede7b","short_id":"24331fad"},{"time":"2026-09-09T02:30:00Z","parent":"b56d7267f0f3775d7d75c1ec209267404aba5d08db7f6c6f31ea171efe8343b7","tree":"b0d2594624bb645cd6ef4be633d745c5ff09190768fb0188bdd8fedff6c785bd","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"c2dd9de7fe5ce5e76bf986b99c0115da212f8b07277da5c236092dc4144d8af3","short_id":"c2dd9de7"},{"time":"2026-09-08T02:30:00Z","parent":"b4b6cf86aa3c85ea88d095bac696ec1566e6095ad19ca7af9c1ff1814ab6380f","tree":"64c83bfdc2ae9e0a9e2ff79c96ea517b75e7af4c7162291cf9672aa9976e05c8","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"b56d7267f0f3775d7d75c1ec209267404aba5d08db7f6c6f31ea171efe8343b7","short_id":"b56d7267"},{"time":"2026-09-07T02:30:00Z","parent":"a4391a2d1fa176171693df8ccda6c8c334cf0736e64a36af579d5f7d8c23b20b","tree":"32e15b2de82fccb7de96c01942bf7f1045e338f18b24c86c200f37959831aa1e","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"b4b6cf86aa3c85ea88d095bac696ec1566e6095ad19ca7af9c1ff1814ab6380f","short_id":"b4b6cf86"}],"reasons":[{"snapshot":{"time":"2026-10-16T02:30:00Z","parent":"331513b5478c67fd17b601f4e86536be66fdebac42db635d2b44073c418c9044","tree":"2479779a0246aded8ea88b1b43549f333df32233150ead772301d4060d9834b6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"1bb3e0b01ad4e9ef4092c0f4f38d003d026d3e62bd4ec32ad84d2ae50b1fc26b","short_id":"1bb3e0b0"},"matches":["daily snapshot","weekly snapshot","monthly snapshot"]},{"snapshot":{"time":"2026-10-15T02:30:00Z","parent":"8d4189078ef8c5de57f8e0a58d646229c6ea05a584a223b13d6d52ee9b2a499a","tree":"c81de4fd5684584aecccba2848d623d9b46d27aaa7a8fda0cf7a4a56faa19f12","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"331513b5478c67fd17b601f4e86536be66fdebac42db635d2b44073c418c9044","short_id":"331513b5"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-14T02:30:00Z","parent":"4a74cebcf061b3f721ce35f1dae2fe644c3dcb77620042d6a9e9a1f69ffa5908","tree":"22deec6d4575076f3b5b9228249ef0935883841659af9e60c2e471f903d301cf","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8d4189078ef8c5de57f8e0a58d646229c6ea05a584a223b13d6d52ee9b2a499a","short_id":"8d418907"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-13T02:30:00Z","parent":"44f0faa89145f8dd68e06437323d677fae465f54c4f6aa95f938234ba0112f57","tree":"2f79914cd5a90ceb735c3dd272c22db5a67f5f1c6a35f48af320f7b218959177","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"4a74cebcf061b3f721ce35f1dae2fe644c3dcb77620042d6a9e9a1f69ffa5908","short_id":"4a74cebc"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-12T02:30:00Z","parent":"9dcb3fa42c8d5b880c7e407ea15e134d540bab3fb250a63854c14dddb1748b79","tree":"7945e1927ec6444933dbe89befa7f342ffd218ab2a96d824a3e3cd9a25f11286","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"44f0faa89145f8dd68e06437323d677fae465f54c4f6aa95f938234ba0112f57","short_id":"44f0faa8"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-11T02:30:00Z","parent":"b82290210fdaab03ba7fa7066ab61e31c5a3545d80a5dec4533fe21ded17dc95","tree":"41316836995752c254b9adce2243f694fab0421b8359109df23ea1fb996ce0fb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"9dcb3fa42c8d5b880c7e407ea15e134d540bab3fb250a63854c14dddb1748b79","short_id":"9dcb3fa4"},"matches":["daily snapshot","weekly snapshot"]},{"snapshot":{"time":"2026-10-10T02:30:00Z","parent":"dd010c8b70468216b74dc107c0125f008c1e8a0d889481e481e40f8f82994764","tree":"f1ca437cda2b7f0db26af3d9b7509db45f238cd346a1f62bf801252daca93420","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"b82290210fdaab03ba7fa7066ab61e31c5a3545d80a5dec4533fe21ded17dc95","short_id":"b8229021"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-04T02:30:00Z","parent":"eabaa0652f6549580fa3b1125f842209428a1b425016621190a4764bed2afb08","tree":"468d616ac9063de9f2829a1fd9d3d362af359c6ce79403d9bdb41f56707f7570","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"3a916d89540e17509b7c6ac5dc43d5842d268970dcb2470737a635e9ef343734","short_id":"3a916d89"},"matches":["weekly snapshot"]},{"snapshot":{"time":"2026-09-30T02:30:00Z","parent":"2ef32e3aec2169bfd005c607d23fa8caefd3597d5933a2ee6ef0992954439e11","tree":"a37fa979d19d953863ad8b8cb276382dcee1e0f2cfe1c87d91908d1a6a9a95e0","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"1b5e6b74f1abaf4d4f390be385bf34650eebe21aa034aeaba3e29150193532c2","short_id":"1b5e6b74"},"matches":["monthly snapshot"]},{"snapshot":{"time":"2026-09-27T02:30:00Z","parent":"b6c3ff0ed8c270eed4c0d1c691ad5fca3b4957f13d1bde79f29094150536529c","tree":"f06890a88f7ac258af5adf77d52b9f7b9fef3414ac7effce40eb52ebbab0fe29","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"88ce7523616beee04180afa0d25c2048c41d4431391e0c0c5c6e923921a9268e","short_id":"88ce7523"},"matches":["weekly snapshot"]},{"snapshot":{"time":"2026-09-06T02:30:00Z","tree":"4ad0876539f4a3e21e3a3970e2acc6b054f595a2cf08a99fdcb5bb330bd24d49","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"a4391a2d1fa176171693df8ccda6c8c334cf0736e64a36af579d5f7d8c23b20b","short_id":"a4391a2d"},"matches":["oldest monthly snapshot"]}]},{"tags":["a","felhom-offbox"],"host":"box","paths":null,"keep":[{"time":"2026-10-16T02:30:00Z","parent":"16f5cbf1aab3d6aaf201e9cf15f90b780e5db3854751f745883a6bd6e707d2dd","tree":"286f8da9b1b553de264161006b6f14be594a3eef691d3980954808cf02387f21","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"3e5346879326eed55c3c0ab2abcce53b9207c9f1da1a4f3ad1ee0ab831063651","short_id":"3e534687"},{"time":"2026-10-15T02:30:00Z","parent":"c980586cfb31f9bf16ec3a509de8d37160ea05102ffa4cfb12f3a834eb8317b3","tree":"cfc9e89d510b4d7500f66c7774f8fa1d26035be91e2de72bb5b35b5ff1565597","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"16f5cbf1aab3d6aaf201e9cf15f90b780e5db3854751f745883a6bd6e707d2dd","short_id":"16f5cbf1"},{"time":"2026-10-14T02:30:00Z","parent":"b6280f340819d34bf80b0a8edf7c9b378d04363483abd74b1a8a61dc921499e7","tree":"795573bb56c71a53b79b999ee8bf8abbdddd04e223191fa07976d2384c24370f","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"c980586cfb31f9bf16ec3a509de8d37160ea05102ffa4cfb12f3a834eb8317b3","short_id":"c980586c"},{"time":"2026-10-13T02:30:00Z","parent":"d85b77be2724c4e449fa4d5a51ade77b83f83d3fba834e322ff2a07575c413fa","tree":"13ab80d5668ef726b7c82ba2f73366f1fa9f2d25511d7cb3fe798582ec2d189d","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"b6280f340819d34bf80b0a8edf7c9b378d04363483abd74b1a8a61dc921499e7","short_id":"b6280f34"},{"time":"2026-10-12T02:30:00Z","parent":"3f14d64b4c7715903cff2a628a00a6e4c774e242a42400ef3fd24d3e3a1fee1a","tree":"1c1df704c5d5d3ac06dfc4a2d43ad706d692dbd78f3b5a6b983c2623d005cf2a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"d85b77be2724c4e449fa4d5a51ade77b83f83d3fba834e322ff2a07575c413fa","short_id":"d85b77be"},{"time":"2026-10-11T02:30:00Z","parent":"6d15ebd146b4ddf76a0f5501fe68a228a37afb00ff05d9e17fb0dd99934f3455","tree":"3ebf8ab552c78434bfdb5465cfb48338a3fa83744c2c41e79af0899cd5cef03c","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"3f14d64b4c7715903cff2a628a00a6e4c774e242a42400ef3fd24d3e3a1fee1a","short_id":"3f14d64b"},{"time":"2026-10-10T02:30:00Z","parent":"a25b1537a1ffedceb22b885753385f07e7435ff086258ea3ac14ed4446a4187d","tree":"bb0cd1b8820b86ccd427ce6049c08ea8e06b8719f000596f0835f6c9e001392b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"6d15ebd146b4ddf76a0f5501fe68a228a37afb00ff05d9e17fb0dd99934f3455","short_id":"6d15ebd1"},{"time":"2026-10-04T02:30:00Z","parent":"fab7e5d7ba440392bc8ee00c0c0fefb071168f03e3b58e3934aad0ff91560489","tree":"788dc5f69207e6351f2511edeb04473000634a2b3840570676f1f33ad7760bf4","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"039063a1d376f4c47fba5862f1314a29adefc05a23897519d30d86df701fd453","short_id":"039063a1"},{"time":"2026-09-30T02:30:00Z","parent":"78546e509597b716e8748b001bbf274e2068a0eaf74f7a5d888e65bc0dc5c5e3","tree":"66891382721b1b41319f9dc30cccd92e81e3d3794e2795c4d99da13a48a87ea9","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"67eb5eff9d3ce202877e027ce212fc1b914febce0d86455ed7a804053d402806","short_id":"67eb5eff"},{"time":"2026-09-27T02:30:00Z","parent":"9d3dd3268ab916288fab00729df16d85878fa9292576176e7d7e05b41babfa97","tree":"87434cf19bafe37d88781b28071ab4887feb96b0ded0b37bc27ac7bbd7e33e2e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"e5f43196aec8f410ffd7b2caf0d076ed0e7ebd92d5f04619c415b16ae56b7d1f","short_id":"e5f43196"},{"time":"2026-09-06T02:30:00Z","tree":"d8d1be9062564caa6509955aefd722f7037d8fd270e339fe818dabd9bdbe5f10","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"e1d954f907f00b8337729a49bc71c9f4e7dc14dcb3f4547cc631a9d0ed34dedc","short_id":"e1d954f9"}],"remove":[{"time":"2026-10-09T02:30:00Z","parent":"59960090510b6ead422be13c69e3bf87e2e53f0fe3246c460da3bac22e6d29a7","tree":"1aa9645c6d95bbe1fc5c0f81ea48122b346635fad67504ca44d4dc765ca7504e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"a25b1537a1ffedceb22b885753385f07e7435ff086258ea3ac14ed4446a4187d","short_id":"a25b1537"},{"time":"2026-10-08T02:30:00Z","parent":"f97353dadd1c5a066f26376a1e4de94e2e2924c30fc8336bce7226b17e8b47a4","tree":"9020a0778ef202f0dd278394e8c6e6f29ab5cb96190f80f1860b57a3ab8905ea","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"59960090510b6ead422be13c69e3bf87e2e53f0fe3246c460da3bac22e6d29a7","short_id":"59960090"},{"time":"2026-10-07T02:30:00Z","parent":"a34683b0a3bdf8f344804b0a8353d39663ed79484c336bcb3649178c18c62bef","tree":"59c955a77ad371adcd241705a113b07cf021164c7fea59eb8c305255924594d3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"f97353dadd1c5a066f26376a1e4de94e2e2924c30fc8336bce7226b17e8b47a4","short_id":"f97353da"},{"time":"2026-10-06T02:30:00Z","parent":"4c4f771ef180a648b16060f2d2b56f1c934f78bb2bb19ea71856b1ff3491f41c","tree":"a1eb787269c933c2cf52b73ac6953bc88cde2f53e69e75a868789e2469e59b2e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"a34683b0a3bdf8f344804b0a8353d39663ed79484c336bcb3649178c18c62bef","short_id":"a34683b0"},{"time":"2026-10-05T02:30:00Z","parent":"039063a1d376f4c47fba5862f1314a29adefc05a23897519d30d86df701fd453","tree":"d7f57de522610361b8f6e1ae3e1c8f0af6fff45b9caba60e79dbea09bad3e8bb","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"4c4f771ef180a648b16060f2d2b56f1c934f78bb2bb19ea71856b1ff3491f41c","short_id":"4c4f771e"},{"time":"2026-10-03T02:30:00Z","parent":"7afa8edcb7f984756564e202d29cdca8400309603590be914b3b7ee84934d4cf","tree":"e0fc2c64b57d15c40924e54e45e4f3f5cf6c88549d4ee60911c2a8069cb55c05","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"fab7e5d7ba440392bc8ee00c0c0fefb071168f03e3b58e3934aad0ff91560489","short_id":"fab7e5d7"},{"time":"2026-10-02T02:30:00Z","parent":"d808dbb1ec076b1e43762a470336464f7310a7e1a1ccad5d4f6aa049b492bb2d","tree":"461258fdd0946cb26ee3ec87c2b35db08921b497d9567e0cb921fa7953e1d724","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"7afa8edcb7f984756564e202d29cdca8400309603590be914b3b7ee84934d4cf","short_id":"7afa8edc"},{"time":"2026-10-01T02:30:00Z","parent":"67eb5eff9d3ce202877e027ce212fc1b914febce0d86455ed7a804053d402806","tree":"83aafad6973ac879054f312c0b7b9711f05e61144e67145c44763fedbc8da0f3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"d808dbb1ec076b1e43762a470336464f7310a7e1a1ccad5d4f6aa049b492bb2d","short_id":"d808dbb1"},{"time":"2026-09-29T02:30:00Z","parent":"ef9f435cf9a21c296e8cddbd73ae58e8c5c15e121c3b2a0d2773d371d365fa92","tree":"57ad9030700fd2929ef4d4325fb23070983ee4b909df35f62ecd60ca2dca7b6a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"78546e509597b716e8748b001bbf274e2068a0eaf74f7a5d888e65bc0dc5c5e3","short_id":"78546e50"},{"time":"2026-09-28T02:30:00Z","parent":"e5f43196aec8f410ffd7b2caf0d076ed0e7ebd92d5f04619c415b16ae56b7d1f","tree":"aebc8687a066367c7b527d14d7567d54bbe8c5803658ebf254a144c82670c5a2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"ef9f435cf9a21c296e8cddbd73ae58e8c5c15e121c3b2a0d2773d371d365fa92","short_id":"ef9f435c"},{"time":"2026-09-26T02:30:00Z","parent":"d9368785703ec3905bc9f6f716b4ebfbd0b2bb0692ddb704e4bf977e8aff1ff3","tree":"63233ccb5f095ca40bc126b605c297e3844685293c629d5d656da1a4c826a921","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"9d3dd3268ab916288fab00729df16d85878fa9292576176e7d7e05b41babfa97","short_id":"9d3dd326"},{"time":"2026-09-25T02:30:00Z","parent":"bb943a0960b2c03215e6b0462256450d9e67cc5214acd354db1a0cb0705a1696","tree":"9fea50e970c47996bcc1610eba645ae379ac87f0515b284df2985f536bf26d24","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"d9368785703ec3905bc9f6f716b4ebfbd0b2bb0692ddb704e4bf977e8aff1ff3","short_id":"d9368785"},{"time":"2026-09-24T02:30:00Z","parent":"5a13db8c85c9de7bd9957f4c382c557c6986eb4fa052fa773d3d6c056b522698","tree":"12224495435b7d8df970beab00e5efd0ba6c3d4d53aaf607a72816d861554e6b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"bb943a0960b2c03215e6b0462256450d9e67cc5214acd354db1a0cb0705a1696","short_id":"bb943a09"},{"time":"2026-09-23T02:30:00Z","parent":"c2d8f4210e52cdadd1327dab71f6c967affc51a7d0944027ece5e8654000d377","tree":"eb49dad786fdf2ab9c00b0633c34cf58de5224d70e74a3a9a31237d0c56b52fd","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"5a13db8c85c9de7bd9957f4c382c557c6986eb4fa052fa773d3d6c056b522698","short_id":"5a13db8c"},{"time":"2026-09-22T02:30:00Z","parent":"ed5a6be0ed1510c644e6ca1ce28d812099582240fafd4c475758a59dae75f268","tree":"373424cff38c1c809bf3c45e6b25d64d5ee96e16890350bb9ccd8f1807a36ca1","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"c2d8f4210e52cdadd1327dab71f6c967affc51a7d0944027ece5e8654000d377","short_id":"c2d8f421"},{"time":"2026-09-21T02:30:00Z","parent":"9fc7b97f4fea54dccefe6f9643c809c6221efc59c0efcab7aa34d459686cde0d","tree":"f18e6b1e580681cd98c27e89a258c39223b793385ea5f14cb4da8522501d1768","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"ed5a6be0ed1510c644e6ca1ce28d812099582240fafd4c475758a59dae75f268","short_id":"ed5a6be0"},{"time":"2026-09-20T02:30:00Z","parent":"3084ed321a45d2c70cd05dcda31fe2c324849add619a27229fb307a9e455f7a1","tree":"7a6b05c4b9ab4b817be0765cfd1c35ec846ef6da798bfd0ef34153fda3b3823f","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"9fc7b97f4fea54dccefe6f9643c809c6221efc59c0efcab7aa34d459686cde0d","short_id":"9fc7b97f"},{"time":"2026-09-19T02:30:00Z","parent":"a5fff383e0c4b921e8359bccf05d6f7bd2747fd481ef721a224118b88ff82ace","tree":"43b99b529fbfe9175e37b9739ddb72769d0877fbb543b65256da164e05008aff","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"3084ed321a45d2c70cd05dcda31fe2c324849add619a27229fb307a9e455f7a1","short_id":"3084ed32"},{"time":"2026-09-18T02:30:00Z","parent":"efcf3fcd77e50fc6dda0747daf9181f75f9663ed4505f8988f74b6433777be7f","tree":"178b66f451efe2d51b864e749502d8183db3d19faf346db7025fcc95035a6fd2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"a5fff383e0c4b921e8359bccf05d6f7bd2747fd481ef721a224118b88ff82ace","short_id":"a5fff383"},{"time":"2026-09-17T02:30:00Z","parent":"1e006efa46517bffcd436c66f28590127db1b083901aa86bb346846766b69f22","tree":"27b98f1320cc2b68ae8be3c27fb259471de7467083c444e465272564383aa374","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"efcf3fcd77e50fc6dda0747daf9181f75f9663ed4505f8988f74b6433777be7f","short_id":"efcf3fcd"},{"time":"2026-09-16T02:30:00Z","parent":"62717aad9a003d7fa57b87a2ea93d7d8954ab400b4ff0da966a9c04223fb1846","tree":"40e0a017a084528d33a98f78b4ad74cad1a33fc2f36cfaa9169635117b1618f9","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"1e006efa46517bffcd436c66f28590127db1b083901aa86bb346846766b69f22","short_id":"1e006efa"},{"time":"2026-09-15T02:30:00Z","parent":"4553f115de0d3983fa65b64b44be8ff1f82e40af54bb915b0fd3ab25d05f4d69","tree":"a7c63419c0fa17e1d62bdc3d9174e533754939eb4b02600662a0631b4561a83e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"62717aad9a003d7fa57b87a2ea93d7d8954ab400b4ff0da966a9c04223fb1846","short_id":"62717aad"},{"time":"2026-09-14T02:30:00Z","parent":"86ab152afd9baafe145fe9d1bd55af12a7ee4f44f61d899f998836e87d2b466d","tree":"422635882ea83f0e6e759795a1124db6cd51b6db0a04fda920296421d93ce92f","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"4553f115de0d3983fa65b64b44be8ff1f82e40af54bb915b0fd3ab25d05f4d69","short_id":"4553f115"},{"time":"2026-09-13T02:30:00Z","parent":"9afa939a8fc9758c4547b61dc77c51fb7f6ee563a4e33b2db6655358bb79b7e2","tree":"3b7db2503aaa703f480a67329b650f87bfd0e8561f611ad68d18a4e712d2a226","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"86ab152afd9baafe145fe9d1bd55af12a7ee4f44f61d899f998836e87d2b466d","short_id":"86ab152a"},{"time":"2026-09-12T02:30:00Z","parent":"6b9b78390e84353c864415e80862da09efb3948c726f9ea58d70957916ba5373","tree":"801be774e3bd1f6a006ddab0eba439a02ed0cb4865bd11722c0d54c33617d877","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"9afa939a8fc9758c4547b61dc77c51fb7f6ee563a4e33b2db6655358bb79b7e2","short_id":"9afa939a"},{"time":"2026-09-11T02:30:00Z","parent":"86e446b059058f35daf0e1f2255f8faa52a6f8fe582a0f9b5c2f2532c28548c4","tree":"daa8d607c445235bb4a6fe5169e1ee0d66fc0df2c40eee57e34c621d6f0c3747","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"6b9b78390e84353c864415e80862da09efb3948c726f9ea58d70957916ba5373","short_id":"6b9b7839"},{"time":"2026-09-10T02:30:00Z","parent":"0c3db5b724f38baaad8d504678a69c80ae77f66f14e517b10ffa7e88efbf678a","tree":"5b3d8750af755b0e38a9a63bc013bb83c8cd397094827edde8a0394009d49743","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"86e446b059058f35daf0e1f2255f8faa52a6f8fe582a0f9b5c2f2532c28548c4","short_id":"86e446b0"},{"time":"2026-09-09T02:30:00Z","parent":"46671301ce8fa7f064566a4caf267ea149c9099bb6e5d7f668f3ac6679bb42fb","tree":"b5d5c1b06b526a0472dd900185abb9b4f7bbd863df944aeb933e3f20b6dca653","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"0c3db5b724f38baaad8d504678a69c80ae77f66f14e517b10ffa7e88efbf678a","short_id":"0c3db5b7"},{"time":"2026-09-08T02:30:00Z","parent":"d7736f8cf82ac8c9e6d485943fa598a447ee094f3640de9b977eeca8298bdc05","tree":"b53736d4f878d0075076993c7edd16d73aca6a97ace6fd8639b43b1abbe78e56","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"46671301ce8fa7f064566a4caf267ea149c9099bb6e5d7f668f3ac6679bb42fb","short_id":"46671301"},{"time":"2026-09-07T02:30:00Z","parent":"e1d954f907f00b8337729a49bc71c9f4e7dc14dcb3f4547cc631a9d0ed34dedc","tree":"884bae5ecb7c125b0247b040e7dd662d29edb3adc027478bdfe82669511532e0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"d7736f8cf82ac8c9e6d485943fa598a447ee094f3640de9b977eeca8298bdc05","short_id":"d7736f8c"}],"reasons":[{"snapshot":{"time":"2026-10-16T02:30:00Z","parent":"16f5cbf1aab3d6aaf201e9cf15f90b780e5db3854751f745883a6bd6e707d2dd","tree":"286f8da9b1b553de264161006b6f14be594a3eef691d3980954808cf02387f21","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"3e5346879326eed55c3c0ab2abcce53b9207c9f1da1a4f3ad1ee0ab831063651","short_id":"3e534687"},"matches":["daily snapshot","weekly snapshot","monthly snapshot"]},{"snapshot":{"time":"2026-10-15T02:30:00Z","parent":"c980586cfb31f9bf16ec3a509de8d37160ea05102ffa4cfb12f3a834eb8317b3","tree":"cfc9e89d510b4d7500f66c7774f8fa1d26035be91e2de72bb5b35b5ff1565597","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"16f5cbf1aab3d6aaf201e9cf15f90b780e5db3854751f745883a6bd6e707d2dd","short_id":"16f5cbf1"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-14T02:30:00Z","parent":"b6280f340819d34bf80b0a8edf7c9b378d04363483abd74b1a8a61dc921499e7","tree":"795573bb56c71a53b79b999ee8bf8abbdddd04e223191fa07976d2384c24370f","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"c980586cfb31f9bf16ec3a509de8d37160ea05102ffa4cfb12f3a834eb8317b3","short_id":"c980586c"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-13T02:30:00Z","parent":"d85b77be2724c4e449fa4d5a51ade77b83f83d3fba834e322ff2a07575c413fa","tree":"13ab80d5668ef726b7c82ba2f73366f1fa9f2d25511d7cb3fe798582ec2d189d","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"b6280f340819d34bf80b0a8edf7c9b378d04363483abd74b1a8a61dc921499e7","short_id":"b6280f34"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-12T02:30:00Z","parent":"3f14d64b4c7715903cff2a628a00a6e4c774e242a42400ef3fd24d3e3a1fee1a","tree":"1c1df704c5d5d3ac06dfc4a2d43ad706d692dbd78f3b5a6b983c2623d005cf2a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"d85b77be2724c4e449fa4d5a51ade77b83f83d3fba834e322ff2a07575c413fa","short_id":"d85b77be"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-11T02:30:00Z","parent":"6d15ebd146b4ddf76a0f5501fe68a228a37afb00ff05d9e17fb0dd99934f3455","tree":"3ebf8ab552c78434bfdb5465cfb48338a3fa83744c2c41e79af0899cd5cef03c","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"3f14d64b4c7715903cff2a628a00a6e4c774e242a42400ef3fd24d3e3a1fee1a","short_id":"3f14d64b"},"matches":["daily snapshot","weekly snapshot"]},{"snapshot":{"time":"2026-10-10T02:30:00Z","parent":"a25b1537a1ffedceb22b885753385f07e7435ff086258ea3ac14ed4446a4187d","tree":"bb0cd1b8820b86ccd427ce6049c08ea8e06b8719f000596f0835f6c9e001392b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"6d15ebd146b4ddf76a0f5501fe68a228a37afb00ff05d9e17fb0dd99934f3455","short_id":"6d15ebd1"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-04T02:30:00Z","parent":"fab7e5d7ba440392bc8ee00c0c0fefb071168f03e3b58e3934aad0ff91560489","tree":"788dc5f69207e6351f2511edeb04473000634a2b3840570676f1f33ad7760bf4","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"039063a1d376f4c47fba5862f1314a29adefc05a23897519d30d86df701fd453","short_id":"039063a1"},"matches":["weekly snapshot"]},{"snapshot":{"time":"2026-09-30T02:30:00Z","parent":"78546e509597b716e8748b001bbf274e2068a0eaf74f7a5d888e65bc0dc5c5e3","tree":"66891382721b1b41319f9dc30cccd92e81e3d3794e2795c4d99da13a48a87ea9","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"67eb5eff9d3ce202877e027ce212fc1b914febce0d86455ed7a804053d402806","short_id":"67eb5eff"},"matches":["monthly snapshot"]},{"snapshot":{"time":"2026-09-27T02:30:00Z","parent":"9d3dd3268ab916288fab00729df16d85878fa9292576176e7d7e05b41babfa97","tree":"87434cf19bafe37d88781b28071ab4887feb96b0ded0b37bc27ac7bbd7e33e2e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"e5f43196aec8f410ffd7b2caf0d076ed0e7ebd92d5f04619c415b16ae56b7d1f","short_id":"e5f43196"},"matches":["weekly snapshot"]},{"snapshot":{"time":"2026-09-06T02:30:00Z","tree":"d8d1be9062564caa6509955aefd722f7037d8fd270e339fe818dabd9bdbe5f10","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"e1d954f907f00b8337729a49bc71c9f4e7dc14dcb3f4547cc631a9d0ed34dedc","short_id":"e1d954f9"},"matches":["oldest monthly snapshot"]}]}] +[{"tags":["b","felhom-offbox"],"host":"box","paths":null,"keep":[{"time":"2026-10-16T02:30:00Z","parent":"ee8432e0cd7bb4113731adc2e76d492238b539c3d6ce24a408670fee40579e57","tree":"024c36c1f532ac9150f9768ed57bb27cb284f8949f51958804dfd0f11ee70b65","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"315ff629674caa42ace8498b9d4bb82e5a77cb2284e628560444e12d9072ec8f","short_id":"315ff629"},{"time":"2026-10-15T02:30:00Z","parent":"2b09f89771cf2744dde14e804ed9e7342871c8a6c1cb4849b8128f5d2571342f","tree":"8f361f971daac52f40180aa7fd3e4638e4ef90903699241b16954ee17fa304e6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"ee8432e0cd7bb4113731adc2e76d492238b539c3d6ce24a408670fee40579e57","short_id":"ee8432e0"},{"time":"2026-10-14T02:30:00Z","parent":"e3fc65e0827c6939f7d86880e75facf36c2692f9cd259fe880232ee7de2a5391","tree":"377caf3fbe1e17b4af93cc053064cde6b40976809805fcdebb0645e41b649ffb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"2b09f89771cf2744dde14e804ed9e7342871c8a6c1cb4849b8128f5d2571342f","short_id":"2b09f897"},{"time":"2026-10-13T02:30:00Z","parent":"4a611990c2123e859808a8546af22c372308a27a87b335aeeb89276e97049165","tree":"279178ad0293ba5157fdd209ec244a1d4899b58e1b9459c11ecac057cac60ff4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"e3fc65e0827c6939f7d86880e75facf36c2692f9cd259fe880232ee7de2a5391","short_id":"e3fc65e0"},{"time":"2026-10-12T02:30:00Z","parent":"8ff9e57a4c7e509cd5e49202f3617630771e0d839ad04911b8106b8b7c4207af","tree":"879f6a9563bba4bcdebbea7f32c27b9e452615464c6dc3111c2df59cd661a8a1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"4a611990c2123e859808a8546af22c372308a27a87b335aeeb89276e97049165","short_id":"4a611990"},{"time":"2026-10-11T02:30:00Z","parent":"5e76f560c4d54a477fce35b1a96ce61374291dc8fa52b6dfb76fde6d91f25bdb","tree":"afe3b0d5eaf569af22f299df9b77ccd8166b7c654c0e886b7452bb10512d0706","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8ff9e57a4c7e509cd5e49202f3617630771e0d839ad04911b8106b8b7c4207af","short_id":"8ff9e57a"},{"time":"2026-10-10T02:30:00Z","parent":"29607a0ab3c4afc1d63525a96605bb44e0b5f4de690d1ed44bfd3bbc27025fa2","tree":"357713e3a55168ec6bea559274dc7552b4fbd64381ce4bde9022e242ec328ad1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"5e76f560c4d54a477fce35b1a96ce61374291dc8fa52b6dfb76fde6d91f25bdb","short_id":"5e76f560"},{"time":"2026-10-04T02:30:00Z","parent":"7c1f837ad939b4f4c376a0ff177862f08d87e4616cbe8e54a60d4a666b804ce7","tree":"a5e934915e68d97267ee3b108c7ee16ea0867e651b9232443fe919d83fa3a4c2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"fa1d764f43f6190cf22b9a763d8cc972d7dc3bb01aaf4f1074e56dbfc350c5e8","short_id":"fa1d764f"},{"time":"2026-09-30T02:30:00Z","parent":"cb87227f0c1c6acf4999c4b2024b589203cb184ce089a01a2db472ddbb560380","tree":"b778b7edf7fa14307405e72c16f20050fc813cf944bda6b445d209db77e4bc00","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8e604e28a0930828c9080477856be09c1475c467ac41f6ded7e2da5bdb3571ac","short_id":"8e604e28"},{"time":"2026-09-27T02:30:00Z","parent":"b26700ff3e9871ac081886d146fc30b9d8e7bd4572cea0b62f8f0261ea1a4f9d","tree":"21aa00a24cb6990028d074e46a5af0457b5bc87da6867d0857663f776247b8cc","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"e24109dd53394e0bd7278f7b5e3fffa90f685bfdcd0a93952cff5638967a13fe","short_id":"e24109dd"},{"time":"2026-09-06T02:30:00Z","tree":"ce672340389400ef8f5094e689dff293adf1f0d532d6e9f811b693a112a01933","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"b49faa0a4d3e92a36922c154ede633f1ff9080fea23770cfe9547316803701e3","short_id":"b49faa0a"}],"remove":[{"time":"2026-10-09T02:30:00Z","parent":"ec2a30d9ff60c7473067c0f6b620948f728174c7a5bb8eddfa238f0d8af5066f","tree":"2e07df0532a24fe466f5fe8415b3c4e7a208d130974b1543591f7d5e42be04ba","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"29607a0ab3c4afc1d63525a96605bb44e0b5f4de690d1ed44bfd3bbc27025fa2","short_id":"29607a0a"},{"time":"2026-10-08T02:30:00Z","parent":"a818ad6aa46ec61c586a0ffb38e63148a69c7bbc08fd0a09acb6734278fbd63b","tree":"4caaed0b8ce301dc03a64b5fe8e441a3bf6cb9297bf96ad72d62c3b45525ef01","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"ec2a30d9ff60c7473067c0f6b620948f728174c7a5bb8eddfa238f0d8af5066f","short_id":"ec2a30d9"},{"time":"2026-10-07T02:30:00Z","parent":"a0ad00ea114be1368fbce2b72ca2f638b904795e73124adb8bd25ae30458933e","tree":"a360e27e1aef84a6eacdf3dba92ab0a46a3628869c2af12d3c1b412863b0535d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"a818ad6aa46ec61c586a0ffb38e63148a69c7bbc08fd0a09acb6734278fbd63b","short_id":"a818ad6a"},{"time":"2026-10-06T02:30:00Z","parent":"2a9ca46af4806ddc2989b343739647e93f622ce863a6610d58e3e5b5f1bae413","tree":"1782fe2e236f85c58cf9b786a7737b5e7974ad71b960bfeaf4240bc528fec665","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"a0ad00ea114be1368fbce2b72ca2f638b904795e73124adb8bd25ae30458933e","short_id":"a0ad00ea"},{"time":"2026-10-05T02:30:00Z","parent":"fa1d764f43f6190cf22b9a763d8cc972d7dc3bb01aaf4f1074e56dbfc350c5e8","tree":"d74e551770184290eb6224af4d48c4008a5b3b7e7cb8204eb3c85c14354d19df","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"2a9ca46af4806ddc2989b343739647e93f622ce863a6610d58e3e5b5f1bae413","short_id":"2a9ca46a"},{"time":"2026-10-03T02:30:00Z","parent":"bd15d29185bb8d6e805451f5e17315396cf315d27c4ca53b9d31d0798ce9d182","tree":"f1dad16a3035d09aac43fe50021f0d0c50ff022c54b28b5c499cf572c95b5746","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"7c1f837ad939b4f4c376a0ff177862f08d87e4616cbe8e54a60d4a666b804ce7","short_id":"7c1f837a"},{"time":"2026-10-02T02:30:00Z","parent":"23ab590268b600c179d6636df65055810c0def0e99a571cdcb7890c556446cc2","tree":"65f5c632a0d2b90ad809a363562f24e3f66d1c52483a9defd47b266da1af4199","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"bd15d29185bb8d6e805451f5e17315396cf315d27c4ca53b9d31d0798ce9d182","short_id":"bd15d291"},{"time":"2026-10-01T02:30:00Z","parent":"8e604e28a0930828c9080477856be09c1475c467ac41f6ded7e2da5bdb3571ac","tree":"bcd5f11e44998ee9e52c5b89ea0a4867e06475bc90b5cb4267364ab6146c9d01","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"23ab590268b600c179d6636df65055810c0def0e99a571cdcb7890c556446cc2","short_id":"23ab5902"},{"time":"2026-09-29T02:30:00Z","parent":"f062f3c51cde5c848398daa1b47cd122d76a0639c76f9436983ae2657895f352","tree":"b99010471bc3056f04c0a8dd25fa412b4834f977d1a7600c03b03b1bb8a9d8fe","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"cb87227f0c1c6acf4999c4b2024b589203cb184ce089a01a2db472ddbb560380","short_id":"cb87227f"},{"time":"2026-09-28T02:30:00Z","parent":"e24109dd53394e0bd7278f7b5e3fffa90f685bfdcd0a93952cff5638967a13fe","tree":"7c0a07c56348b0fa19b9507bf17dada815bdf81517a714408db21e288fc554b3","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"f062f3c51cde5c848398daa1b47cd122d76a0639c76f9436983ae2657895f352","short_id":"f062f3c5"},{"time":"2026-09-26T02:30:00Z","parent":"d4562f249a7d2962d749dbaf843d8ac71b9c8ebb0c0b7cec09afcd8711529eea","tree":"36c5d5c1356cef66b9017f1411f798274554b52a7b01a8b4127ef1c30c6a02f6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"b26700ff3e9871ac081886d146fc30b9d8e7bd4572cea0b62f8f0261ea1a4f9d","short_id":"b26700ff"},{"time":"2026-09-25T02:30:00Z","parent":"0b0bc0701cee5d7533d4a97f4c9ef7f5a401eb552d2ca3536a1ed5cebeb83f97","tree":"c6508fdf7a64e55c2058145ba81f1b27e8687b8b2b2a4bd7324a157ef31ad12a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"d4562f249a7d2962d749dbaf843d8ac71b9c8ebb0c0b7cec09afcd8711529eea","short_id":"d4562f24"},{"time":"2026-09-24T02:30:00Z","parent":"0c73460e3fa99b3c38ef31c378515f2424f18877bd354994d053576aa58ec214","tree":"530b2ba5c60bab9cc6f56148cf6388dff62236a252592031c10df1e2dd2607d6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"0b0bc0701cee5d7533d4a97f4c9ef7f5a401eb552d2ca3536a1ed5cebeb83f97","short_id":"0b0bc070"},{"time":"2026-09-23T02:30:00Z","parent":"5e41a7b17484c04288c67cce0dbf9cb3046325a9617b27f33d128ea5e906eebe","tree":"1092cccb0c44787eb64ea2ea143189a5bf5d093ebfa0427d0cb07ac47543bcf4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"0c73460e3fa99b3c38ef31c378515f2424f18877bd354994d053576aa58ec214","short_id":"0c73460e"},{"time":"2026-09-22T02:30:00Z","parent":"8f870fe269857d1d611fff5e03d2b22533bce7dc5aad4340de6cdf434b5aa0ae","tree":"31fbee51dde5e56f1d5940902bf8428ee4a1a2825a6081dea2b3ffb60a66ca26","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"5e41a7b17484c04288c67cce0dbf9cb3046325a9617b27f33d128ea5e906eebe","short_id":"5e41a7b1"},{"time":"2026-09-21T02:30:00Z","parent":"ec0f30baecf767c3a02ec631814236071014258f0287f3044b591a34d5a99d73","tree":"c1ddfe015a6300456c24a6561c1a1f247f255254834aac61435ceef06456e806","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8f870fe269857d1d611fff5e03d2b22533bce7dc5aad4340de6cdf434b5aa0ae","short_id":"8f870fe2"},{"time":"2026-09-20T02:30:00Z","parent":"0c97b2f8a266b152761dd1769c0898bc78a367c859ca8013edec68bfc61aa0d4","tree":"f61ebed68d2e86ca59dc4e4223535a3aa8198562b2cecb812b52d3ba9e5411e7","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"ec0f30baecf767c3a02ec631814236071014258f0287f3044b591a34d5a99d73","short_id":"ec0f30ba"},{"time":"2026-09-19T02:30:00Z","parent":"dc383edfe97cc655252f1ad872386b2fefeecc0b3e170e7a04d8683225214951","tree":"2ca8aade0fdfc72248d246771ee003972eaad397aa613f78dea4b2ba6d1a0287","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"0c97b2f8a266b152761dd1769c0898bc78a367c859ca8013edec68bfc61aa0d4","short_id":"0c97b2f8"},{"time":"2026-09-18T02:30:00Z","parent":"ee89b04f40a213571e3a100a01c666b02566dde4ea56e902b11df9a2c3f13a09","tree":"862bd61ed170b4a5e0ec0fa971bf16a2fd295b5b0ca5ca8b5573d5d96bf46d0b","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"dc383edfe97cc655252f1ad872386b2fefeecc0b3e170e7a04d8683225214951","short_id":"dc383edf"},{"time":"2026-09-17T02:30:00Z","parent":"f0a0d4eb6dda96f6db6099dff7156458aed506eeadca78859ad9657068e44501","tree":"92ac0d05e95224172f35772f54eb47981154feb9e6e58a4f03c3b273eea3dd1d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"ee89b04f40a213571e3a100a01c666b02566dde4ea56e902b11df9a2c3f13a09","short_id":"ee89b04f"},{"time":"2026-09-16T02:30:00Z","parent":"bf5abbdc483043f91fefdde6e97249ee81610adca5195440770fea3ec9c014f1","tree":"55007688ced33784bc5785e3dc9546f472cbeda9d545f9327aca913631586c3a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"f0a0d4eb6dda96f6db6099dff7156458aed506eeadca78859ad9657068e44501","short_id":"f0a0d4eb"},{"time":"2026-09-15T02:30:00Z","parent":"2f18a0cd5a226f2d04d075853265761756f6228499c1d8d6d08694c49bb3c2b7","tree":"1352369b945c41e97bbd11d3ca0f0ed4885046ce3e51e3762b4986b0c9b04ca0","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"bf5abbdc483043f91fefdde6e97249ee81610adca5195440770fea3ec9c014f1","short_id":"bf5abbdc"},{"time":"2026-09-14T02:30:00Z","parent":"8a336152be88a2f4123b281a9fd1da34c195eb44363f08e988cf2f35645a2b66","tree":"56004cc3737e424b403621b63b8cbc4e71c0ae86a326c30fe3a627a1c572d963","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"2f18a0cd5a226f2d04d075853265761756f6228499c1d8d6d08694c49bb3c2b7","short_id":"2f18a0cd"},{"time":"2026-09-13T02:30:00Z","parent":"670ca41966dd9493c733a7160c867d8c5024128d6d3f804142ce873089d56d1c","tree":"ee30f31481f47e63795e88c27f2cc603d60ea9ad9dd53fb60417ca48b93c48c8","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8a336152be88a2f4123b281a9fd1da34c195eb44363f08e988cf2f35645a2b66","short_id":"8a336152"},{"time":"2026-09-12T02:30:00Z","parent":"f22a8b07c06ae226ae53db79d52c977c9f01b5708cc2d24a47e1171ce05f34a7","tree":"422cd3972d9092ce5082e72b49d1df597a80f88de2085e6ae6a40b676bb97601","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"670ca41966dd9493c733a7160c867d8c5024128d6d3f804142ce873089d56d1c","short_id":"670ca419"},{"time":"2026-09-11T02:30:00Z","parent":"7b08e08836fa06d1a6cf125cf8e7f5f5bca1358421ff7386a9d1a3b204e0aeb6","tree":"45dace70a50297723fc9ab12d5215e2892adb5e15338f093495913aa9c674a45","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"f22a8b07c06ae226ae53db79d52c977c9f01b5708cc2d24a47e1171ce05f34a7","short_id":"f22a8b07"},{"time":"2026-09-10T02:30:00Z","parent":"c25662ce1a2597f3468e93251a04d35419b912c26907724b89c197edb79b69c9","tree":"3e9374ab1878e6aad827032c581f50b02296f436c71afc9db1080bc28c53db1a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"7b08e08836fa06d1a6cf125cf8e7f5f5bca1358421ff7386a9d1a3b204e0aeb6","short_id":"7b08e088"},{"time":"2026-09-09T02:30:00Z","parent":"3f9ff630cd8c4830ccd24976f24065aa17e84e24a04876cda02310a9d845a554","tree":"fb772e958ecbf3b778ef2b838a4937dab663d80ae6ffa571453dcf0d375d70b7","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"c25662ce1a2597f3468e93251a04d35419b912c26907724b89c197edb79b69c9","short_id":"c25662ce"},{"time":"2026-09-08T02:30:00Z","parent":"96824fce2d56c812475efc60585f0a3fe7988874ec48ecf7a55946feb3e14c0d","tree":"dd6a4ba2b1bd03d58f08b20df5ce546db43a0bdc69c88430c4f835773f75645d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"3f9ff630cd8c4830ccd24976f24065aa17e84e24a04876cda02310a9d845a554","short_id":"3f9ff630"},{"time":"2026-09-07T02:30:00Z","parent":"b49faa0a4d3e92a36922c154ede633f1ff9080fea23770cfe9547316803701e3","tree":"46653667b9ba1ba3646c2af1471791b09b03a936d8a8a8f247f09a8731db42d2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"96824fce2d56c812475efc60585f0a3fe7988874ec48ecf7a55946feb3e14c0d","short_id":"96824fce"}],"reasons":[{"snapshot":{"time":"2026-10-16T02:30:00Z","parent":"ee8432e0cd7bb4113731adc2e76d492238b539c3d6ce24a408670fee40579e57","tree":"024c36c1f532ac9150f9768ed57bb27cb284f8949f51958804dfd0f11ee70b65","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"315ff629674caa42ace8498b9d4bb82e5a77cb2284e628560444e12d9072ec8f","short_id":"315ff629"},"matches":["daily snapshot","weekly snapshot","monthly snapshot"]},{"snapshot":{"time":"2026-10-15T02:30:00Z","parent":"2b09f89771cf2744dde14e804ed9e7342871c8a6c1cb4849b8128f5d2571342f","tree":"8f361f971daac52f40180aa7fd3e4638e4ef90903699241b16954ee17fa304e6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"ee8432e0cd7bb4113731adc2e76d492238b539c3d6ce24a408670fee40579e57","short_id":"ee8432e0"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-14T02:30:00Z","parent":"e3fc65e0827c6939f7d86880e75facf36c2692f9cd259fe880232ee7de2a5391","tree":"377caf3fbe1e17b4af93cc053064cde6b40976809805fcdebb0645e41b649ffb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"2b09f89771cf2744dde14e804ed9e7342871c8a6c1cb4849b8128f5d2571342f","short_id":"2b09f897"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-13T02:30:00Z","parent":"4a611990c2123e859808a8546af22c372308a27a87b335aeeb89276e97049165","tree":"279178ad0293ba5157fdd209ec244a1d4899b58e1b9459c11ecac057cac60ff4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"e3fc65e0827c6939f7d86880e75facf36c2692f9cd259fe880232ee7de2a5391","short_id":"e3fc65e0"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-12T02:30:00Z","parent":"8ff9e57a4c7e509cd5e49202f3617630771e0d839ad04911b8106b8b7c4207af","tree":"879f6a9563bba4bcdebbea7f32c27b9e452615464c6dc3111c2df59cd661a8a1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"4a611990c2123e859808a8546af22c372308a27a87b335aeeb89276e97049165","short_id":"4a611990"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-11T02:30:00Z","parent":"5e76f560c4d54a477fce35b1a96ce61374291dc8fa52b6dfb76fde6d91f25bdb","tree":"afe3b0d5eaf569af22f299df9b77ccd8166b7c654c0e886b7452bb10512d0706","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8ff9e57a4c7e509cd5e49202f3617630771e0d839ad04911b8106b8b7c4207af","short_id":"8ff9e57a"},"matches":["daily snapshot","weekly snapshot"]},{"snapshot":{"time":"2026-10-10T02:30:00Z","parent":"29607a0ab3c4afc1d63525a96605bb44e0b5f4de690d1ed44bfd3bbc27025fa2","tree":"357713e3a55168ec6bea559274dc7552b4fbd64381ce4bde9022e242ec328ad1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"5e76f560c4d54a477fce35b1a96ce61374291dc8fa52b6dfb76fde6d91f25bdb","short_id":"5e76f560"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-04T02:30:00Z","parent":"7c1f837ad939b4f4c376a0ff177862f08d87e4616cbe8e54a60d4a666b804ce7","tree":"a5e934915e68d97267ee3b108c7ee16ea0867e651b9232443fe919d83fa3a4c2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"fa1d764f43f6190cf22b9a763d8cc972d7dc3bb01aaf4f1074e56dbfc350c5e8","short_id":"fa1d764f"},"matches":["weekly snapshot"]},{"snapshot":{"time":"2026-09-30T02:30:00Z","parent":"cb87227f0c1c6acf4999c4b2024b589203cb184ce089a01a2db472ddbb560380","tree":"b778b7edf7fa14307405e72c16f20050fc813cf944bda6b445d209db77e4bc00","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8e604e28a0930828c9080477856be09c1475c467ac41f6ded7e2da5bdb3571ac","short_id":"8e604e28"},"matches":["monthly snapshot"]},{"snapshot":{"time":"2026-09-27T02:30:00Z","parent":"b26700ff3e9871ac081886d146fc30b9d8e7bd4572cea0b62f8f0261ea1a4f9d","tree":"21aa00a24cb6990028d074e46a5af0457b5bc87da6867d0857663f776247b8cc","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"e24109dd53394e0bd7278f7b5e3fffa90f685bfdcd0a93952cff5638967a13fe","short_id":"e24109dd"},"matches":["weekly snapshot"]},{"snapshot":{"time":"2026-09-06T02:30:00Z","tree":"ce672340389400ef8f5094e689dff293adf1f0d532d6e9f811b693a112a01933","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"b49faa0a4d3e92a36922c154ede633f1ff9080fea23770cfe9547316803701e3","short_id":"b49faa0a"},"matches":["oldest monthly snapshot"]}]},{"tags":["a","felhom-offbox"],"host":"box","paths":null,"keep":[{"time":"2026-10-16T02:30:00Z","parent":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","tree":"b830b8165dc45c4b23086a81004548a5a52a00060028f0d274d8098dcc168b49","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"94fc37b9bfe97271d4a0b0feda4443a5e2934a3557108dd521d0bfb2f49423c8","short_id":"94fc37b9"},{"time":"2026-10-15T02:30:00Z","parent":"47bbaa059c6e306c801b5f793e5f3500d1a0c258c3075855aa160276b4a0c704","tree":"a0dd167d57e68ce11fde606350779191cdc8c4413875240091be5880fb91c66e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","short_id":"27898187"},{"time":"2026-10-14T02:30:00Z","parent":"5339cf6d7ec710b3998e7bf52a09a17cbb5907d2c09ccf18ace19f525b812ae8","tree":"57ab0a0f2ea360c1fbdfbc3b700e0225fb347eb8e715750283bb4b46e1133bf3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"47bbaa059c6e306c801b5f793e5f3500d1a0c258c3075855aa160276b4a0c704","short_id":"47bbaa05"},{"time":"2026-10-13T02:30:00Z","parent":"26da1569ccbbd96c81a266beef45c84e5a4b6dc870f44a41a89c437ebb09c09f","tree":"3c0228aa205d8a36c5b4fe501ba5e50d638e219cf2cd4aef45f77e0ba9fc5bb0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"5339cf6d7ec710b3998e7bf52a09a17cbb5907d2c09ccf18ace19f525b812ae8","short_id":"5339cf6d"},{"time":"2026-10-12T02:30:00Z","parent":"23ae66812d30a5ba39d9ec618c3e3dd453a2883da4d07e7c39438168388069d9","tree":"b721e2ac4dcc985dd24b608acb6b5243dad979038229a6a5b8e501cc2d7bad8e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"26da1569ccbbd96c81a266beef45c84e5a4b6dc870f44a41a89c437ebb09c09f","short_id":"26da1569"},{"time":"2026-10-11T02:30:00Z","parent":"cd0707729940a95ae60e9297780e370798d6ed750dc711dc6c34c80c82a6f105","tree":"e408a9e30f5cb44933c7faaec25373d0874bc7e9447bf28ceda6fff612611d92","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"23ae66812d30a5ba39d9ec618c3e3dd453a2883da4d07e7c39438168388069d9","short_id":"23ae6681"},{"time":"2026-10-10T02:30:00Z","parent":"13ecd2eeb9d433ae4be796a9dd9e289b7f12aa55b807cbca1ac6d88b6033accd","tree":"0ad2f65dd3de6f7fe4f32210cc07fae810683c769591e3122e9c12acd64a4281","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"cd0707729940a95ae60e9297780e370798d6ed750dc711dc6c34c80c82a6f105","short_id":"cd070772"},{"time":"2026-10-04T02:30:00Z","parent":"0e6cad1bee36f6ce4c5d28d756f256bb692a1419cf91e29cc1a856c22d5975e7","tree":"4709d5189f78175060c473debd32bbc95e655c0a6e5ca9792c34b3fd0415de69","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"960d1e720e43e9cb467f170f45277f133494374baa337f93a8af1b973e4b84b3","short_id":"960d1e72"},{"time":"2026-09-30T02:30:00Z","parent":"35e79f2b266136d2be26273e4eabb20005fd5158e59539cd492b0c8e4bbfb2d3","tree":"56b96a8e688ab8190bddb0868d331ece565f8856aef3cdcfef32fc1518e6baf2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"5ae64e02898e62676cdb3ba4689ed25eb83588a65127d244e69417846e495d78","short_id":"5ae64e02"},{"time":"2026-09-27T02:30:00Z","parent":"e974e4a5987c5d524f227b4b091811a0488e5fed27cb736d511f009b13b13b1d","tree":"c5cb9ce2ff06516329a42aec557f7223e1a3c3801c502f7a53f0ab6414cedf15","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"7e67848219703f577e06ce2750b104a8c8f956978b05aafa4a205a3d258eb376","short_id":"7e678482"},{"time":"2026-09-06T02:30:00Z","tree":"f685956bf88ee15d577e60f77a8ce561abdb2dd56eb1d00b26d5c59276add7a6","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"2a76397eb8a43be8c70dd687ab03fcd939f2f058f815804b9fa2e0f5d9d32376","short_id":"2a76397e"}],"remove":[{"time":"2026-10-09T02:30:00Z","parent":"c27b0d1dabe2d975d297daad5b01ad678fb4c88e2d1e6e6ed5f2cf4aa21c5410","tree":"0ffe8da4512fd658f56dc4ee240488b5d63ae4c07f742810846df3044a365f5a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"13ecd2eeb9d433ae4be796a9dd9e289b7f12aa55b807cbca1ac6d88b6033accd","short_id":"13ecd2ee"},{"time":"2026-10-08T02:30:00Z","parent":"2d383c39077530c4a9f98ba8dc20f014e210854d2c4f32f79b335a19388b1e89","tree":"f44bda5e625b1e7636d14efb44c79f9451ef71475b38751bd2c962d04f86ebd4","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"c27b0d1dabe2d975d297daad5b01ad678fb4c88e2d1e6e6ed5f2cf4aa21c5410","short_id":"c27b0d1d"},{"time":"2026-10-07T02:30:00Z","parent":"c7aee7b89b42a2539a75e863e0083ae8761ee7ed8826b5a6c3d49820c0e6ba26","tree":"87bbe7cfd2c5e04fffb43951ae72dbcdc26c2e4eac1be4fa384c26238139d7f3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"2d383c39077530c4a9f98ba8dc20f014e210854d2c4f32f79b335a19388b1e89","short_id":"2d383c39"},{"time":"2026-10-06T02:30:00Z","parent":"d1a3dffd18e46a92ee75c698f7c716727a942ace2efba7ccc2935b6087992908","tree":"978e63c6278adf45029b4c51f773aac5252d334e4d2782f2fac88174fedbb1ff","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"c7aee7b89b42a2539a75e863e0083ae8761ee7ed8826b5a6c3d49820c0e6ba26","short_id":"c7aee7b8"},{"time":"2026-10-05T02:30:00Z","parent":"960d1e720e43e9cb467f170f45277f133494374baa337f93a8af1b973e4b84b3","tree":"8bffed4ff0074c8dbc58f616ddfea18aae6a4bbafb6f3ead72cc2d6fdc7bb7d7","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"d1a3dffd18e46a92ee75c698f7c716727a942ace2efba7ccc2935b6087992908","short_id":"d1a3dffd"},{"time":"2026-10-03T02:30:00Z","parent":"cee066c08d1f2f222dd490fa86e4a7931be865004d0aaf50e63f8536d0e232ec","tree":"2fdf5cb4f765aeda71371e854f2b73e96ed86e5deb4b54faf6d45ad76756cfb5","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"0e6cad1bee36f6ce4c5d28d756f256bb692a1419cf91e29cc1a856c22d5975e7","short_id":"0e6cad1b"},{"time":"2026-10-02T02:30:00Z","parent":"bfaf7ca84276c21938171a2d38258647686386fc83df7f24a1b7d67de552202a","tree":"0fd6c21124d32f9e6a9ee6c3d3a740143c7d90683391082c42bd6cd3bfd0f530","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"cee066c08d1f2f222dd490fa86e4a7931be865004d0aaf50e63f8536d0e232ec","short_id":"cee066c0"},{"time":"2026-10-01T02:30:00Z","parent":"5ae64e02898e62676cdb3ba4689ed25eb83588a65127d244e69417846e495d78","tree":"b4403fd15f29eced5de4749e59d5b9fe2022030132fe5e9e4d6bb64f83a1cf92","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"bfaf7ca84276c21938171a2d38258647686386fc83df7f24a1b7d67de552202a","short_id":"bfaf7ca8"},{"time":"2026-09-29T02:30:00Z","parent":"a695cd17a42947d6a5f1d74db5dc14f508cffbd7f98582124a25c53d47defd21","tree":"07492d5c8986dadc99631897cd7c4acfe18ec97dd70898d09899d5cd87b9539e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"35e79f2b266136d2be26273e4eabb20005fd5158e59539cd492b0c8e4bbfb2d3","short_id":"35e79f2b"},{"time":"2026-09-28T02:30:00Z","parent":"7e67848219703f577e06ce2750b104a8c8f956978b05aafa4a205a3d258eb376","tree":"e03a49f45c2db8d9342d90626025311ca3592d7d78c6dd6eeb8ffed0848c7ae0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"a695cd17a42947d6a5f1d74db5dc14f508cffbd7f98582124a25c53d47defd21","short_id":"a695cd17"},{"time":"2026-09-26T02:30:00Z","parent":"ce4afadd45ee5a17b6e8f276704f99478bf5e82cc0870a5b4e6db3e07d64ace8","tree":"8f40b7ed62ec04ce4dd10a648fd97db920711a6f387503bb2a75f535de395656","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"e974e4a5987c5d524f227b4b091811a0488e5fed27cb736d511f009b13b13b1d","short_id":"e974e4a5"},{"time":"2026-09-25T02:30:00Z","parent":"264cbd7c1e22696db518c2b8aba55d9755e2799bab72d54d48f8521ae1740e84","tree":"0b332b3757a2111c5c5e1adcb59f011b4ce4716c350fbb289496525a612b27eb","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"ce4afadd45ee5a17b6e8f276704f99478bf5e82cc0870a5b4e6db3e07d64ace8","short_id":"ce4afadd"},{"time":"2026-09-24T02:30:00Z","parent":"6398aadc912ab1364b0c83f3e3ce51c3099bf74e018ac25107f51dbeed6b3c47","tree":"29e68a845705a5490fc07891a54fa6ff4d674183f4314f23361fb3d5c43b5057","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"264cbd7c1e22696db518c2b8aba55d9755e2799bab72d54d48f8521ae1740e84","short_id":"264cbd7c"},{"time":"2026-09-23T02:30:00Z","parent":"7b37aba5b0971c1f41c15269fe2157e320b4f6428920d743302e4a904e053f63","tree":"eac20fb1f7f17be350f01322cc58152ec05c680ba60706fa5f25db89bab1d264","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"6398aadc912ab1364b0c83f3e3ce51c3099bf74e018ac25107f51dbeed6b3c47","short_id":"6398aadc"},{"time":"2026-09-22T02:30:00Z","parent":"ab24192f7a961b8103bdf4c5a3ab7d2a13b949b6accb9d52d1411f49d9d0deea","tree":"1e0e3145356cbc6b68674824bdb7b2bc5524ab3fc8cbcb27368f9efb819c0124","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"7b37aba5b0971c1f41c15269fe2157e320b4f6428920d743302e4a904e053f63","short_id":"7b37aba5"},{"time":"2026-09-21T02:30:00Z","parent":"43902ad8c4d345ac41a98af33afc74fd36d2f6896fb45e94fe553ba3f2b51d0f","tree":"f10d8afc6c36f40a793446537a09092aab457abaddd2f5dd884273014ffd986b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"ab24192f7a961b8103bdf4c5a3ab7d2a13b949b6accb9d52d1411f49d9d0deea","short_id":"ab24192f"},{"time":"2026-09-20T02:30:00Z","parent":"c2e659092443ccc73500e061690d9f99b0a653e8dcc002f441cd359385045e0e","tree":"4ad27f2ca164c7d23866d5c06e75aa70ad20d8f86229816534ce7adcffb652a7","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"43902ad8c4d345ac41a98af33afc74fd36d2f6896fb45e94fe553ba3f2b51d0f","short_id":"43902ad8"},{"time":"2026-09-19T02:30:00Z","parent":"177c6f12c40c9f355adc60d0a875830e78353038462fe15beeb00f3afef04efe","tree":"a97bea5453e2a1a8913ee3965b4fec1632d677dfe0ecf74213efee6f43568e20","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"c2e659092443ccc73500e061690d9f99b0a653e8dcc002f441cd359385045e0e","short_id":"c2e65909"},{"time":"2026-09-18T02:30:00Z","parent":"a2be8e6be366d62cca9bc6d4e12b1c97a310051e2fa8a077dff1fb07e904000a","tree":"251699699303a792c841f497662af163952386fd70b2d6dcfa435bd0d902ace2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"177c6f12c40c9f355adc60d0a875830e78353038462fe15beeb00f3afef04efe","short_id":"177c6f12"},{"time":"2026-09-17T02:30:00Z","parent":"e0ec672a95aacf51c562acf57701aba0e725a1d811ce3a6f5c2ebad549a8c016","tree":"a037a5eb6e669bc15c6705f0c4eb665c729eefa37af2a196086ce1701230988e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"a2be8e6be366d62cca9bc6d4e12b1c97a310051e2fa8a077dff1fb07e904000a","short_id":"a2be8e6b"},{"time":"2026-09-16T02:30:00Z","parent":"0c24dfcc62048ac0b64dd13aad000479b47ceddfd2963119e631c488714f8cc3","tree":"39e7b89853eb47ec19c07a060be51173dd800a2d46417ae0201fefa3af33d90a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"e0ec672a95aacf51c562acf57701aba0e725a1d811ce3a6f5c2ebad549a8c016","short_id":"e0ec672a"},{"time":"2026-09-15T02:30:00Z","parent":"a74319ea5b78b3276b0aa7407b39f95e44c0676915ce815a979383d2afbc6e23","tree":"be3be59ec618cf36d26d6d3e8368b560ce88c60b6eda56e861c6f5146f667be2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"0c24dfcc62048ac0b64dd13aad000479b47ceddfd2963119e631c488714f8cc3","short_id":"0c24dfcc"},{"time":"2026-09-14T02:30:00Z","parent":"d6678aa268695bc4387fe3a857f3304013c2bd672dc1234cf2161343bf18efdc","tree":"fdc02ae7cab64e7ab641be509365b4b8201eaf3c6dddf7191ba01bbcd750d3ea","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"a74319ea5b78b3276b0aa7407b39f95e44c0676915ce815a979383d2afbc6e23","short_id":"a74319ea"},{"time":"2026-09-13T02:30:00Z","parent":"9224b1af26c1c1fe31395055f22158bf09cc541f4b59a59caf91b71f92bc63f1","tree":"a5b546be122e577d101aaa067994bae404a881925573c09a2576431b51bb3e82","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"d6678aa268695bc4387fe3a857f3304013c2bd672dc1234cf2161343bf18efdc","short_id":"d6678aa2"},{"time":"2026-09-12T02:30:00Z","parent":"8c127f74318a1ff657ebc803b1fda7fae31ff1e2e3e145c9bd137d04f9de9d92","tree":"57c13238258e80cccb13e8d4dac05a82f9c3da4ac3dc6a26e9b8f4736e478af1","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"9224b1af26c1c1fe31395055f22158bf09cc541f4b59a59caf91b71f92bc63f1","short_id":"9224b1af"},{"time":"2026-09-11T02:30:00Z","parent":"e4b8322da1d838315d2dd62509678d7b419924a0d7c4723062aa31140a417ac0","tree":"9b79e87705df56afe04f10b8a5e15cb8cc4abed0585815e54282b77cacd3eae6","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"8c127f74318a1ff657ebc803b1fda7fae31ff1e2e3e145c9bd137d04f9de9d92","short_id":"8c127f74"},{"time":"2026-09-10T02:30:00Z","parent":"d1c1d0c71c88d2f829b267adfdafbc1b19fdf184de6cdf1de28703cf46b40d65","tree":"ed7361b730a863510df1e3b9f7d25b810902e8e86e0e230632250186cc558b21","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"e4b8322da1d838315d2dd62509678d7b419924a0d7c4723062aa31140a417ac0","short_id":"e4b8322d"},{"time":"2026-09-09T02:30:00Z","parent":"1242b68c1b172bc4ae762fe874cd6dd8863ce3ae03961f5175c35fa26475d385","tree":"2bfaf9b4b8dabb68a2824ce5f48d27fda4ea94c2a960718bd84cabd59be13acf","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"d1c1d0c71c88d2f829b267adfdafbc1b19fdf184de6cdf1de28703cf46b40d65","short_id":"d1c1d0c7"},{"time":"2026-09-08T02:30:00Z","parent":"820d553d84f1c920803a156ffea356c7aacf469e7555f07ea8b9408d2021f254","tree":"f725d2ffc7382c23554b85a5381905f02a11b09d307c24cd20980bcb30dce47b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"1242b68c1b172bc4ae762fe874cd6dd8863ce3ae03961f5175c35fa26475d385","short_id":"1242b68c"},{"time":"2026-09-07T02:30:00Z","parent":"2a76397eb8a43be8c70dd687ab03fcd939f2f058f815804b9fa2e0f5d9d32376","tree":"70b21a93a7e8af3804e813d7d47cb5d936ebfff4ebf1b8b80a9834382142aee5","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"820d553d84f1c920803a156ffea356c7aacf469e7555f07ea8b9408d2021f254","short_id":"820d553d"}],"reasons":[{"snapshot":{"time":"2026-10-16T02:30:00Z","parent":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","tree":"b830b8165dc45c4b23086a81004548a5a52a00060028f0d274d8098dcc168b49","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"94fc37b9bfe97271d4a0b0feda4443a5e2934a3557108dd521d0bfb2f49423c8","short_id":"94fc37b9"},"matches":["daily snapshot","weekly snapshot","monthly snapshot"]},{"snapshot":{"time":"2026-10-15T02:30:00Z","parent":"47bbaa059c6e306c801b5f793e5f3500d1a0c258c3075855aa160276b4a0c704","tree":"a0dd167d57e68ce11fde606350779191cdc8c4413875240091be5880fb91c66e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","short_id":"27898187"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-14T02:30:00Z","parent":"5339cf6d7ec710b3998e7bf52a09a17cbb5907d2c09ccf18ace19f525b812ae8","tree":"57ab0a0f2ea360c1fbdfbc3b700e0225fb347eb8e715750283bb4b46e1133bf3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"47bbaa059c6e306c801b5f793e5f3500d1a0c258c3075855aa160276b4a0c704","short_id":"47bbaa05"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-13T02:30:00Z","parent":"26da1569ccbbd96c81a266beef45c84e5a4b6dc870f44a41a89c437ebb09c09f","tree":"3c0228aa205d8a36c5b4fe501ba5e50d638e219cf2cd4aef45f77e0ba9fc5bb0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"5339cf6d7ec710b3998e7bf52a09a17cbb5907d2c09ccf18ace19f525b812ae8","short_id":"5339cf6d"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-12T02:30:00Z","parent":"23ae66812d30a5ba39d9ec618c3e3dd453a2883da4d07e7c39438168388069d9","tree":"b721e2ac4dcc985dd24b608acb6b5243dad979038229a6a5b8e501cc2d7bad8e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"26da1569ccbbd96c81a266beef45c84e5a4b6dc870f44a41a89c437ebb09c09f","short_id":"26da1569"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-11T02:30:00Z","parent":"cd0707729940a95ae60e9297780e370798d6ed750dc711dc6c34c80c82a6f105","tree":"e408a9e30f5cb44933c7faaec25373d0874bc7e9447bf28ceda6fff612611d92","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"23ae66812d30a5ba39d9ec618c3e3dd453a2883da4d07e7c39438168388069d9","short_id":"23ae6681"},"matches":["daily snapshot","weekly snapshot"]},{"snapshot":{"time":"2026-10-10T02:30:00Z","parent":"13ecd2eeb9d433ae4be796a9dd9e289b7f12aa55b807cbca1ac6d88b6033accd","tree":"0ad2f65dd3de6f7fe4f32210cc07fae810683c769591e3122e9c12acd64a4281","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"cd0707729940a95ae60e9297780e370798d6ed750dc711dc6c34c80c82a6f105","short_id":"cd070772"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-04T02:30:00Z","parent":"0e6cad1bee36f6ce4c5d28d756f256bb692a1419cf91e29cc1a856c22d5975e7","tree":"4709d5189f78175060c473debd32bbc95e655c0a6e5ca9792c34b3fd0415de69","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"960d1e720e43e9cb467f170f45277f133494374baa337f93a8af1b973e4b84b3","short_id":"960d1e72"},"matches":["weekly snapshot"]},{"snapshot":{"time":"2026-09-30T02:30:00Z","parent":"35e79f2b266136d2be26273e4eabb20005fd5158e59539cd492b0c8e4bbfb2d3","tree":"56b96a8e688ab8190bddb0868d331ece565f8856aef3cdcfef32fc1518e6baf2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"5ae64e02898e62676cdb3ba4689ed25eb83588a65127d244e69417846e495d78","short_id":"5ae64e02"},"matches":["monthly snapshot"]},{"snapshot":{"time":"2026-09-27T02:30:00Z","parent":"e974e4a5987c5d524f227b4b091811a0488e5fed27cb736d511f009b13b13b1d","tree":"c5cb9ce2ff06516329a42aec557f7223e1a3c3801c502f7a53f0ab6414cedf15","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"7e67848219703f577e06ce2750b104a8c8f956978b05aafa4a205a3d258eb376","short_id":"7e678482"},"matches":["weekly snapshot"]},{"snapshot":{"time":"2026-09-06T02:30:00Z","tree":"f685956bf88ee15d577e60f77a8ce561abdb2dd56eb1d00b26d5c59276add7a6","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"2a76397eb8a43be8c70dd687ab03fcd939f2f058f815804b9fa2e0f5d9d32376","short_id":"2a76397e"},"matches":["oldest monthly snapshot"]}]}] diff --git a/controller/internal/backup/testdata/restic/0.18.1/locked-exclusive.txt b/controller/internal/backup/testdata/restic/0.18.1/locked-exclusive.txt index 90e6152..49898a0 100644 --- a/controller/internal/backup/testdata/restic/0.18.1/locked-exclusive.txt +++ b/controller/internal/backup/testdata/restic/0.18.1/locked-exclusive.txt @@ -1,5 +1,5 @@ repo already locked, waiting up to 0s for the lock -unable to create lock in backend: repository is already locked exclusively by PID 2775667 on other-box by root (UID 0, GID 0) -lock was created at 2026-10-16 18:20:26 (1.312752495s ago) -storage ID be8a3f47 +unable to create lock in backend: repository is already locked exclusively by PID 3690145 on other-box by root (UID 0, GID 0) +lock was created at 2026-10-16 20:03:03 (1.111629809s ago) +storage ID 3cf3b3cf the `unlock` command can be used to remove stale locks diff --git a/controller/internal/backup/testdata/restic/0.18.1/locked-shared.txt b/controller/internal/backup/testdata/restic/0.18.1/locked-shared.txt index 98f7192..449b57b 100644 --- a/controller/internal/backup/testdata/restic/0.18.1/locked-shared.txt +++ b/controller/internal/backup/testdata/restic/0.18.1/locked-shared.txt @@ -1,5 +1,5 @@ repo already locked, waiting up to 0s for the lock -unable to create lock in backend: repository is already locked by PID 2775299 on other-box by root (UID 0, GID 0) -lock was created at 2026-10-16 18:20:25 (1.301138628s ago) -storage ID b41afa86 +unable to create lock in backend: repository is already locked by PID 3689928 on other-box by root (UID 0, GID 0) +lock was created at 2026-10-16 20:03:02 (1.097394824s ago) +storage ID 74d5af8c the `unlock` command can be used to remove stale locks diff --git a/controller/internal/backup/testdata/restic/0.18.1/snapshots-latest-tag.json b/controller/internal/backup/testdata/restic/0.18.1/snapshots-latest-tag.json index 00ca62e..e4e32d2 100644 --- a/controller/internal/backup/testdata/restic/0.18.1/snapshots-latest-tag.json +++ b/controller/internal/backup/testdata/restic/0.18.1/snapshots-latest-tag.json @@ -1 +1 @@ -[{"time":"2026-10-16T02:30:00Z","parent":"16f5cbf1aab3d6aaf201e9cf15f90b780e5db3854751f745883a6bd6e707d2dd","tree":"286f8da9b1b553de264161006b6f14be594a3eef691d3980954808cf02387f21","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"3e5346879326eed55c3c0ab2abcce53b9207c9f1da1a4f3ad1ee0ab831063651","short_id":"3e534687"}] +[{"time":"2026-10-16T02:30:00Z","parent":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","tree":"b830b8165dc45c4b23086a81004548a5a52a00060028f0d274d8098dcc168b49","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"94fc37b9bfe97271d4a0b0feda4443a5e2934a3557108dd521d0bfb2f49423c8","short_id":"94fc37b9"}] diff --git a/controller/internal/backup/testdata/restic/0.18.1/snapshots.json b/controller/internal/backup/testdata/restic/0.18.1/snapshots.json index fbc93ab..db05159 100644 --- a/controller/internal/backup/testdata/restic/0.18.1/snapshots.json +++ b/controller/internal/backup/testdata/restic/0.18.1/snapshots.json @@ -1 +1 @@ -[{"time":"2026-09-06T02:30:00Z","tree":"d8d1be9062564caa6509955aefd722f7037d8fd270e339fe818dabd9bdbe5f10","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"e1d954f907f00b8337729a49bc71c9f4e7dc14dcb3f4547cc631a9d0ed34dedc","short_id":"e1d954f9"},{"time":"2026-09-06T02:30:00Z","tree":"4ad0876539f4a3e21e3a3970e2acc6b054f595a2cf08a99fdcb5bb330bd24d49","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"a4391a2d1fa176171693df8ccda6c8c334cf0736e64a36af579d5f7d8c23b20b","short_id":"a4391a2d"},{"time":"2026-09-07T02:30:00Z","parent":"e1d954f907f00b8337729a49bc71c9f4e7dc14dcb3f4547cc631a9d0ed34dedc","tree":"884bae5ecb7c125b0247b040e7dd662d29edb3adc027478bdfe82669511532e0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"d7736f8cf82ac8c9e6d485943fa598a447ee094f3640de9b977eeca8298bdc05","short_id":"d7736f8c"},{"time":"2026-09-07T02:30:00Z","parent":"a4391a2d1fa176171693df8ccda6c8c334cf0736e64a36af579d5f7d8c23b20b","tree":"32e15b2de82fccb7de96c01942bf7f1045e338f18b24c86c200f37959831aa1e","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"b4b6cf86aa3c85ea88d095bac696ec1566e6095ad19ca7af9c1ff1814ab6380f","short_id":"b4b6cf86"},{"time":"2026-09-08T02:30:00Z","parent":"b4b6cf86aa3c85ea88d095bac696ec1566e6095ad19ca7af9c1ff1814ab6380f","tree":"64c83bfdc2ae9e0a9e2ff79c96ea517b75e7af4c7162291cf9672aa9976e05c8","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"b56d7267f0f3775d7d75c1ec209267404aba5d08db7f6c6f31ea171efe8343b7","short_id":"b56d7267"},{"time":"2026-09-08T02:30:00Z","parent":"d7736f8cf82ac8c9e6d485943fa598a447ee094f3640de9b977eeca8298bdc05","tree":"b53736d4f878d0075076993c7edd16d73aca6a97ace6fd8639b43b1abbe78e56","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"46671301ce8fa7f064566a4caf267ea149c9099bb6e5d7f668f3ac6679bb42fb","short_id":"46671301"},{"time":"2026-09-09T02:30:00Z","parent":"b56d7267f0f3775d7d75c1ec209267404aba5d08db7f6c6f31ea171efe8343b7","tree":"b0d2594624bb645cd6ef4be633d745c5ff09190768fb0188bdd8fedff6c785bd","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"c2dd9de7fe5ce5e76bf986b99c0115da212f8b07277da5c236092dc4144d8af3","short_id":"c2dd9de7"},{"time":"2026-09-09T02:30:00Z","parent":"46671301ce8fa7f064566a4caf267ea149c9099bb6e5d7f668f3ac6679bb42fb","tree":"b5d5c1b06b526a0472dd900185abb9b4f7bbd863df944aeb933e3f20b6dca653","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"0c3db5b724f38baaad8d504678a69c80ae77f66f14e517b10ffa7e88efbf678a","short_id":"0c3db5b7"},{"time":"2026-09-10T02:30:00Z","parent":"c2dd9de7fe5ce5e76bf986b99c0115da212f8b07277da5c236092dc4144d8af3","tree":"09722b272016f5585fe991a8b5cd5a9451cbf778cb64d9d65ca1cde792e9ace7","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"24331fad4982bf1e6e5be6f899580e71f69a7a3dc29785b40ec595b16f9ede7b","short_id":"24331fad"},{"time":"2026-09-10T02:30:00Z","parent":"0c3db5b724f38baaad8d504678a69c80ae77f66f14e517b10ffa7e88efbf678a","tree":"5b3d8750af755b0e38a9a63bc013bb83c8cd397094827edde8a0394009d49743","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"86e446b059058f35daf0e1f2255f8faa52a6f8fe582a0f9b5c2f2532c28548c4","short_id":"86e446b0"},{"time":"2026-09-11T02:30:00Z","parent":"24331fad4982bf1e6e5be6f899580e71f69a7a3dc29785b40ec595b16f9ede7b","tree":"b13daaa02a014a7f2811f6cd845bc427883833ac6e578677fffb9756cb08855d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"9a9b7aee5b1b8801a89190f64cd0a25cdc0de5dc90bf507727de8ee76b70d59d","short_id":"9a9b7aee"},{"time":"2026-09-11T02:30:00Z","parent":"86e446b059058f35daf0e1f2255f8faa52a6f8fe582a0f9b5c2f2532c28548c4","tree":"daa8d607c445235bb4a6fe5169e1ee0d66fc0df2c40eee57e34c621d6f0c3747","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"6b9b78390e84353c864415e80862da09efb3948c726f9ea58d70957916ba5373","short_id":"6b9b7839"},{"time":"2026-09-12T02:30:00Z","parent":"6b9b78390e84353c864415e80862da09efb3948c726f9ea58d70957916ba5373","tree":"801be774e3bd1f6a006ddab0eba439a02ed0cb4865bd11722c0d54c33617d877","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"9afa939a8fc9758c4547b61dc77c51fb7f6ee563a4e33b2db6655358bb79b7e2","short_id":"9afa939a"},{"time":"2026-09-12T02:30:00Z","parent":"9a9b7aee5b1b8801a89190f64cd0a25cdc0de5dc90bf507727de8ee76b70d59d","tree":"56ea6daeaf9b8c6e55fe21d488e0c7b90d926290fc98da3de942ca4aa7b57ce1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"4facc0c230bf587cde80d5a3d3cbb62e938150316545d2f91f883a8f0f23560b","short_id":"4facc0c2"},{"time":"2026-09-13T02:30:00Z","parent":"9afa939a8fc9758c4547b61dc77c51fb7f6ee563a4e33b2db6655358bb79b7e2","tree":"3b7db2503aaa703f480a67329b650f87bfd0e8561f611ad68d18a4e712d2a226","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"86ab152afd9baafe145fe9d1bd55af12a7ee4f44f61d899f998836e87d2b466d","short_id":"86ab152a"},{"time":"2026-09-13T02:30:00Z","parent":"4facc0c230bf587cde80d5a3d3cbb62e938150316545d2f91f883a8f0f23560b","tree":"6f7f51fbf57abeb9fc1af9689e59212344b12e833a926b9ba1ada7dfb926bccc","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"dd8abd92e055c916448d058660cc0b4ed63cb99a418b1941119c33bbb30f2e37","short_id":"dd8abd92"},{"time":"2026-09-14T02:30:00Z","parent":"dd8abd92e055c916448d058660cc0b4ed63cb99a418b1941119c33bbb30f2e37","tree":"e0c2d3e7cdf6db59ffafe688a844e75c62211868b38efcdc6025cd497312f03d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"7ca16908b1c9ba4e9c9719bed7e0ec0f3987e155bafaf5bab4bb0a903067ae07","short_id":"7ca16908"},{"time":"2026-09-14T02:30:00Z","parent":"86ab152afd9baafe145fe9d1bd55af12a7ee4f44f61d899f998836e87d2b466d","tree":"422635882ea83f0e6e759795a1124db6cd51b6db0a04fda920296421d93ce92f","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"4553f115de0d3983fa65b64b44be8ff1f82e40af54bb915b0fd3ab25d05f4d69","short_id":"4553f115"},{"time":"2026-09-15T02:30:00Z","parent":"7ca16908b1c9ba4e9c9719bed7e0ec0f3987e155bafaf5bab4bb0a903067ae07","tree":"489bf44b49d5679494a5d660eea153236adc9af8a6f768cee85b40c9444395fb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"8905c672851940782321709d03e4d976cc8975aeb63c9ef50a7713ad2e257d75","short_id":"8905c672"},{"time":"2026-09-15T02:30:00Z","parent":"4553f115de0d3983fa65b64b44be8ff1f82e40af54bb915b0fd3ab25d05f4d69","tree":"a7c63419c0fa17e1d62bdc3d9174e533754939eb4b02600662a0631b4561a83e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"62717aad9a003d7fa57b87a2ea93d7d8954ab400b4ff0da966a9c04223fb1846","short_id":"62717aad"},{"time":"2026-09-16T02:30:00Z","parent":"62717aad9a003d7fa57b87a2ea93d7d8954ab400b4ff0da966a9c04223fb1846","tree":"40e0a017a084528d33a98f78b4ad74cad1a33fc2f36cfaa9169635117b1618f9","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"1e006efa46517bffcd436c66f28590127db1b083901aa86bb346846766b69f22","short_id":"1e006efa"},{"time":"2026-09-16T02:30:00Z","parent":"8905c672851940782321709d03e4d976cc8975aeb63c9ef50a7713ad2e257d75","tree":"3ca35c35a404dcd752bb371217365049d27737d3604af69924d070b520dd9ae2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"0e064dcba9e15e96b4a5066b1847d550163d9943314615e34e7f4927c1ffe20a","short_id":"0e064dcb"},{"time":"2026-09-17T02:30:00Z","parent":"0e064dcba9e15e96b4a5066b1847d550163d9943314615e34e7f4927c1ffe20a","tree":"1a527598187b2c775100f690c73af64d8cc662c84935eaf2256fee9730bb0766","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"3610529c13a4b87deea7309dc9e352c96e79cd8c465d79590643c3192d3383ef","short_id":"3610529c"},{"time":"2026-09-17T02:30:00Z","parent":"1e006efa46517bffcd436c66f28590127db1b083901aa86bb346846766b69f22","tree":"27b98f1320cc2b68ae8be3c27fb259471de7467083c444e465272564383aa374","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"efcf3fcd77e50fc6dda0747daf9181f75f9663ed4505f8988f74b6433777be7f","short_id":"efcf3fcd"},{"time":"2026-09-18T02:30:00Z","parent":"efcf3fcd77e50fc6dda0747daf9181f75f9663ed4505f8988f74b6433777be7f","tree":"178b66f451efe2d51b864e749502d8183db3d19faf346db7025fcc95035a6fd2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"a5fff383e0c4b921e8359bccf05d6f7bd2747fd481ef721a224118b88ff82ace","short_id":"a5fff383"},{"time":"2026-09-18T02:30:00Z","parent":"3610529c13a4b87deea7309dc9e352c96e79cd8c465d79590643c3192d3383ef","tree":"6a7b9de7f8a847690487acab15e9808a7c485a77da3202aa7394dfdb048ac828","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"9a5d9b218160f2a99d228dfbe7d5c94c425a55d34c931b958a5094981337efe3","short_id":"9a5d9b21"},{"time":"2026-09-19T02:30:00Z","parent":"9a5d9b218160f2a99d228dfbe7d5c94c425a55d34c931b958a5094981337efe3","tree":"e9c735d5260376c08bf4ba6ff9ca2c11325e9013a15509b4559c94c4170a6ae4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"57880fadf8682a92a4992909de29de94d2fff6f45689e2e82277b5cf8911f13f","short_id":"57880fad"},{"time":"2026-09-19T02:30:00Z","parent":"a5fff383e0c4b921e8359bccf05d6f7bd2747fd481ef721a224118b88ff82ace","tree":"43b99b529fbfe9175e37b9739ddb72769d0877fbb543b65256da164e05008aff","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"3084ed321a45d2c70cd05dcda31fe2c324849add619a27229fb307a9e455f7a1","short_id":"3084ed32"},{"time":"2026-09-20T02:30:00Z","parent":"57880fadf8682a92a4992909de29de94d2fff6f45689e2e82277b5cf8911f13f","tree":"6d32c2444b76fb0eb422b1290fb41309ba642c2c8389519a6ee286e5726594f1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"e62e8764fadbcb8dd8b59fd2c861603fb48891e451a50c1f8d8fa84effe6c693","short_id":"e62e8764"},{"time":"2026-09-20T02:30:00Z","parent":"3084ed321a45d2c70cd05dcda31fe2c324849add619a27229fb307a9e455f7a1","tree":"7a6b05c4b9ab4b817be0765cfd1c35ec846ef6da798bfd0ef34153fda3b3823f","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"9fc7b97f4fea54dccefe6f9643c809c6221efc59c0efcab7aa34d459686cde0d","short_id":"9fc7b97f"},{"time":"2026-09-21T02:30:00Z","parent":"e62e8764fadbcb8dd8b59fd2c861603fb48891e451a50c1f8d8fa84effe6c693","tree":"2fcc4e0dd7db7447990b38ec9c93ad2c83297ea1e9ab17b1b50c3c0f24637579","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"79792a9b1e5603f08b6228fae860d8c974313bccc6ff2dde76270f3cc521d5c7","short_id":"79792a9b"},{"time":"2026-09-21T02:30:00Z","parent":"9fc7b97f4fea54dccefe6f9643c809c6221efc59c0efcab7aa34d459686cde0d","tree":"f18e6b1e580681cd98c27e89a258c39223b793385ea5f14cb4da8522501d1768","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"ed5a6be0ed1510c644e6ca1ce28d812099582240fafd4c475758a59dae75f268","short_id":"ed5a6be0"},{"time":"2026-09-22T02:30:00Z","parent":"ed5a6be0ed1510c644e6ca1ce28d812099582240fafd4c475758a59dae75f268","tree":"373424cff38c1c809bf3c45e6b25d64d5ee96e16890350bb9ccd8f1807a36ca1","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"c2d8f4210e52cdadd1327dab71f6c967affc51a7d0944027ece5e8654000d377","short_id":"c2d8f421"},{"time":"2026-09-22T02:30:00Z","parent":"79792a9b1e5603f08b6228fae860d8c974313bccc6ff2dde76270f3cc521d5c7","tree":"76e67a0fd8eb8215e67487127e1823ec76db61eafde6f9519ffbc5388fd1de9f","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"d27d1ae70c280fdb945c0366ba17c654d3b5be2516d8e4e6ae862a3be0cbac54","short_id":"d27d1ae7"},{"time":"2026-09-23T02:30:00Z","parent":"c2d8f4210e52cdadd1327dab71f6c967affc51a7d0944027ece5e8654000d377","tree":"eb49dad786fdf2ab9c00b0633c34cf58de5224d70e74a3a9a31237d0c56b52fd","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"5a13db8c85c9de7bd9957f4c382c557c6986eb4fa052fa773d3d6c056b522698","short_id":"5a13db8c"},{"time":"2026-09-23T02:30:00Z","parent":"d27d1ae70c280fdb945c0366ba17c654d3b5be2516d8e4e6ae862a3be0cbac54","tree":"5ff035bfe269e00cbdca9b6c966b822a578ae26742a29938a89ac1ff92dd5fed","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"148fb7b1b6e4cc4ebb5ca99ea00cd92703065c4879c5edcf88890d082dd6f31c","short_id":"148fb7b1"},{"time":"2026-09-24T02:30:00Z","parent":"5a13db8c85c9de7bd9957f4c382c557c6986eb4fa052fa773d3d6c056b522698","tree":"12224495435b7d8df970beab00e5efd0ba6c3d4d53aaf607a72816d861554e6b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"bb943a0960b2c03215e6b0462256450d9e67cc5214acd354db1a0cb0705a1696","short_id":"bb943a09"},{"time":"2026-09-24T02:30:00Z","parent":"148fb7b1b6e4cc4ebb5ca99ea00cd92703065c4879c5edcf88890d082dd6f31c","tree":"f90e90886d9e47a708c439f90ab0b811e00372c122928d4db0b3a679643e7377","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"3c149e5a2092648bbdf09398f04ee351b8eb3e43f5d9e5f92a216328fe2192a8","short_id":"3c149e5a"},{"time":"2026-09-25T02:30:00Z","parent":"3c149e5a2092648bbdf09398f04ee351b8eb3e43f5d9e5f92a216328fe2192a8","tree":"f766854d8b67adac39aa2971fe1eeda94a4adbde52cc473929e03cbc97f15929","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"738389466ef5b3f129a2392fb14371e16604c6a3071ad89b1cc97154539df00b","short_id":"73838946"},{"time":"2026-09-25T02:30:00Z","parent":"bb943a0960b2c03215e6b0462256450d9e67cc5214acd354db1a0cb0705a1696","tree":"9fea50e970c47996bcc1610eba645ae379ac87f0515b284df2985f536bf26d24","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"d9368785703ec3905bc9f6f716b4ebfbd0b2bb0692ddb704e4bf977e8aff1ff3","short_id":"d9368785"},{"time":"2026-09-26T02:30:00Z","parent":"d9368785703ec3905bc9f6f716b4ebfbd0b2bb0692ddb704e4bf977e8aff1ff3","tree":"63233ccb5f095ca40bc126b605c297e3844685293c629d5d656da1a4c826a921","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"9d3dd3268ab916288fab00729df16d85878fa9292576176e7d7e05b41babfa97","short_id":"9d3dd326"},{"time":"2026-09-26T02:30:00Z","parent":"738389466ef5b3f129a2392fb14371e16604c6a3071ad89b1cc97154539df00b","tree":"7a29695c4ffb7201fe199173c93083bf98a3eb6083d4171e819b25c385ee3292","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"b6c3ff0ed8c270eed4c0d1c691ad5fca3b4957f13d1bde79f29094150536529c","short_id":"b6c3ff0e"},{"time":"2026-09-27T02:30:00Z","parent":"9d3dd3268ab916288fab00729df16d85878fa9292576176e7d7e05b41babfa97","tree":"87434cf19bafe37d88781b28071ab4887feb96b0ded0b37bc27ac7bbd7e33e2e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"e5f43196aec8f410ffd7b2caf0d076ed0e7ebd92d5f04619c415b16ae56b7d1f","short_id":"e5f43196"},{"time":"2026-09-27T02:30:00Z","parent":"b6c3ff0ed8c270eed4c0d1c691ad5fca3b4957f13d1bde79f29094150536529c","tree":"f06890a88f7ac258af5adf77d52b9f7b9fef3414ac7effce40eb52ebbab0fe29","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"88ce7523616beee04180afa0d25c2048c41d4431391e0c0c5c6e923921a9268e","short_id":"88ce7523"},{"time":"2026-09-28T02:30:00Z","parent":"e5f43196aec8f410ffd7b2caf0d076ed0e7ebd92d5f04619c415b16ae56b7d1f","tree":"aebc8687a066367c7b527d14d7567d54bbe8c5803658ebf254a144c82670c5a2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"ef9f435cf9a21c296e8cddbd73ae58e8c5c15e121c3b2a0d2773d371d365fa92","short_id":"ef9f435c"},{"time":"2026-09-28T02:30:00Z","parent":"88ce7523616beee04180afa0d25c2048c41d4431391e0c0c5c6e923921a9268e","tree":"c7dada1e21510896f6475d62d0f2f88454c7719b0a74c79ce3593bc14f4d19ff","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"999889b6f8de7d3eafeaa86ad705420affcfdf646e10a0c366ee82f3bfa5a758","short_id":"999889b6"},{"time":"2026-09-29T02:30:00Z","parent":"999889b6f8de7d3eafeaa86ad705420affcfdf646e10a0c366ee82f3bfa5a758","tree":"8636f52172dd153181a2eeeacadaf422a0ab9230d3a9eb300a323d9ecf6d2bda","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"2ef32e3aec2169bfd005c607d23fa8caefd3597d5933a2ee6ef0992954439e11","short_id":"2ef32e3a"},{"time":"2026-09-29T02:30:00Z","parent":"ef9f435cf9a21c296e8cddbd73ae58e8c5c15e121c3b2a0d2773d371d365fa92","tree":"57ad9030700fd2929ef4d4325fb23070983ee4b909df35f62ecd60ca2dca7b6a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"78546e509597b716e8748b001bbf274e2068a0eaf74f7a5d888e65bc0dc5c5e3","short_id":"78546e50"},{"time":"2026-09-30T02:30:00Z","parent":"78546e509597b716e8748b001bbf274e2068a0eaf74f7a5d888e65bc0dc5c5e3","tree":"66891382721b1b41319f9dc30cccd92e81e3d3794e2795c4d99da13a48a87ea9","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"67eb5eff9d3ce202877e027ce212fc1b914febce0d86455ed7a804053d402806","short_id":"67eb5eff"},{"time":"2026-09-30T02:30:00Z","parent":"2ef32e3aec2169bfd005c607d23fa8caefd3597d5933a2ee6ef0992954439e11","tree":"a37fa979d19d953863ad8b8cb276382dcee1e0f2cfe1c87d91908d1a6a9a95e0","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"1b5e6b74f1abaf4d4f390be385bf34650eebe21aa034aeaba3e29150193532c2","short_id":"1b5e6b74"},{"time":"2026-10-01T02:30:00Z","parent":"67eb5eff9d3ce202877e027ce212fc1b914febce0d86455ed7a804053d402806","tree":"83aafad6973ac879054f312c0b7b9711f05e61144e67145c44763fedbc8da0f3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"d808dbb1ec076b1e43762a470336464f7310a7e1a1ccad5d4f6aa049b492bb2d","short_id":"d808dbb1"},{"time":"2026-10-01T02:30:00Z","parent":"1b5e6b74f1abaf4d4f390be385bf34650eebe21aa034aeaba3e29150193532c2","tree":"aad23ab1f6a4a59f8e09fca43fa8927321a5cfa6707310a9a66ed4738ffd6c4d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"6d39107b801aff3b7d929393c3070ccfee278387276db8aacf1b46b8a5da1e1c","short_id":"6d39107b"},{"time":"2026-10-02T02:30:00Z","parent":"d808dbb1ec076b1e43762a470336464f7310a7e1a1ccad5d4f6aa049b492bb2d","tree":"461258fdd0946cb26ee3ec87c2b35db08921b497d9567e0cb921fa7953e1d724","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"7afa8edcb7f984756564e202d29cdca8400309603590be914b3b7ee84934d4cf","short_id":"7afa8edc"},{"time":"2026-10-02T02:30:00Z","parent":"6d39107b801aff3b7d929393c3070ccfee278387276db8aacf1b46b8a5da1e1c","tree":"ee800f29da370e89ef260c6be721d6dfb691c85b9ca2b35ff2bd2340c4fc737a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"3869db68bb5543ab788ddca26d61583a6137ff71d6be864be83762359192c232","short_id":"3869db68"},{"time":"2026-10-03T02:30:00Z","parent":"7afa8edcb7f984756564e202d29cdca8400309603590be914b3b7ee84934d4cf","tree":"e0fc2c64b57d15c40924e54e45e4f3f5cf6c88549d4ee60911c2a8069cb55c05","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"fab7e5d7ba440392bc8ee00c0c0fefb071168f03e3b58e3934aad0ff91560489","short_id":"fab7e5d7"},{"time":"2026-10-03T02:30:00Z","parent":"3869db68bb5543ab788ddca26d61583a6137ff71d6be864be83762359192c232","tree":"2fcca788daf43bbcea34d3e41650cb2f94549620a997511365e9018d667db0d0","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"eabaa0652f6549580fa3b1125f842209428a1b425016621190a4764bed2afb08","short_id":"eabaa065"},{"time":"2026-10-04T02:30:00Z","parent":"eabaa0652f6549580fa3b1125f842209428a1b425016621190a4764bed2afb08","tree":"468d616ac9063de9f2829a1fd9d3d362af359c6ce79403d9bdb41f56707f7570","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"3a916d89540e17509b7c6ac5dc43d5842d268970dcb2470737a635e9ef343734","short_id":"3a916d89"},{"time":"2026-10-04T02:30:00Z","parent":"fab7e5d7ba440392bc8ee00c0c0fefb071168f03e3b58e3934aad0ff91560489","tree":"788dc5f69207e6351f2511edeb04473000634a2b3840570676f1f33ad7760bf4","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"039063a1d376f4c47fba5862f1314a29adefc05a23897519d30d86df701fd453","short_id":"039063a1"},{"time":"2026-10-05T02:30:00Z","parent":"3a916d89540e17509b7c6ac5dc43d5842d268970dcb2470737a635e9ef343734","tree":"353fcfbdbb2b33da457308307d2aca87f18cf9e45a4e3c8f56e1ee4060dc555f","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"c86697c291b279d448ba785b6e600794a811980413d3119cc1e7dd4c07b15124","short_id":"c86697c2"},{"time":"2026-10-05T02:30:00Z","parent":"039063a1d376f4c47fba5862f1314a29adefc05a23897519d30d86df701fd453","tree":"d7f57de522610361b8f6e1ae3e1c8f0af6fff45b9caba60e79dbea09bad3e8bb","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"4c4f771ef180a648b16060f2d2b56f1c934f78bb2bb19ea71856b1ff3491f41c","short_id":"4c4f771e"},{"time":"2026-10-06T02:30:00Z","parent":"4c4f771ef180a648b16060f2d2b56f1c934f78bb2bb19ea71856b1ff3491f41c","tree":"a1eb787269c933c2cf52b73ac6953bc88cde2f53e69e75a868789e2469e59b2e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"a34683b0a3bdf8f344804b0a8353d39663ed79484c336bcb3649178c18c62bef","short_id":"a34683b0"},{"time":"2026-10-06T02:30:00Z","parent":"c86697c291b279d448ba785b6e600794a811980413d3119cc1e7dd4c07b15124","tree":"3b18bc51857c3b43ef3b7f7251a747a4aa1d860336c3276c1e895b8ed89c990e","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"4600ed1a4a0a08348ad95e38368431242b4eeb9be82ca860c7dcd626833d38fb","short_id":"4600ed1a"},{"time":"2026-10-07T02:30:00Z","parent":"4600ed1a4a0a08348ad95e38368431242b4eeb9be82ca860c7dcd626833d38fb","tree":"e89d06f95e23814a4c5b36b1a61d51b59b621b0a1c0750ef93f71e2beff2e17b","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"20cccbaa5b814f5a1a1816d1c49af6f4703dd33e7c62faf4a2152d15161c45f0","short_id":"20cccbaa"},{"time":"2026-10-07T02:30:00Z","parent":"a34683b0a3bdf8f344804b0a8353d39663ed79484c336bcb3649178c18c62bef","tree":"59c955a77ad371adcd241705a113b07cf021164c7fea59eb8c305255924594d3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"f97353dadd1c5a066f26376a1e4de94e2e2924c30fc8336bce7226b17e8b47a4","short_id":"f97353da"},{"time":"2026-10-08T02:30:00Z","parent":"20cccbaa5b814f5a1a1816d1c49af6f4703dd33e7c62faf4a2152d15161c45f0","tree":"58a11c46cd107e285a02424d5fedf8c6c3831ec57d5231dca34a77221478230f","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"0095d1024e633c17869e063c307b6e7ef74dd54a0e8c406c91bf38ca7ad16f1b","short_id":"0095d102"},{"time":"2026-10-08T02:30:00Z","parent":"f97353dadd1c5a066f26376a1e4de94e2e2924c30fc8336bce7226b17e8b47a4","tree":"9020a0778ef202f0dd278394e8c6e6f29ab5cb96190f80f1860b57a3ab8905ea","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"59960090510b6ead422be13c69e3bf87e2e53f0fe3246c460da3bac22e6d29a7","short_id":"59960090"},{"time":"2026-10-09T02:30:00Z","parent":"0095d1024e633c17869e063c307b6e7ef74dd54a0e8c406c91bf38ca7ad16f1b","tree":"c14587a70d549b4cf45f6091ba985e7c57911d9ce65aa0ae6fcbb54cd2798320","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"dd010c8b70468216b74dc107c0125f008c1e8a0d889481e481e40f8f82994764","short_id":"dd010c8b"},{"time":"2026-10-09T02:30:00Z","parent":"59960090510b6ead422be13c69e3bf87e2e53f0fe3246c460da3bac22e6d29a7","tree":"1aa9645c6d95bbe1fc5c0f81ea48122b346635fad67504ca44d4dc765ca7504e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"a25b1537a1ffedceb22b885753385f07e7435ff086258ea3ac14ed4446a4187d","short_id":"a25b1537"},{"time":"2026-10-10T02:30:00Z","parent":"a25b1537a1ffedceb22b885753385f07e7435ff086258ea3ac14ed4446a4187d","tree":"bb0cd1b8820b86ccd427ce6049c08ea8e06b8719f000596f0835f6c9e001392b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"6d15ebd146b4ddf76a0f5501fe68a228a37afb00ff05d9e17fb0dd99934f3455","short_id":"6d15ebd1"},{"time":"2026-10-10T02:30:00Z","parent":"dd010c8b70468216b74dc107c0125f008c1e8a0d889481e481e40f8f82994764","tree":"f1ca437cda2b7f0db26af3d9b7509db45f238cd346a1f62bf801252daca93420","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"b82290210fdaab03ba7fa7066ab61e31c5a3545d80a5dec4533fe21ded17dc95","short_id":"b8229021"},{"time":"2026-10-11T02:30:00Z","parent":"b82290210fdaab03ba7fa7066ab61e31c5a3545d80a5dec4533fe21ded17dc95","tree":"41316836995752c254b9adce2243f694fab0421b8359109df23ea1fb996ce0fb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"9dcb3fa42c8d5b880c7e407ea15e134d540bab3fb250a63854c14dddb1748b79","short_id":"9dcb3fa4"},{"time":"2026-10-11T02:30:00Z","parent":"6d15ebd146b4ddf76a0f5501fe68a228a37afb00ff05d9e17fb0dd99934f3455","tree":"3ebf8ab552c78434bfdb5465cfb48338a3fa83744c2c41e79af0899cd5cef03c","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"3f14d64b4c7715903cff2a628a00a6e4c774e242a42400ef3fd24d3e3a1fee1a","short_id":"3f14d64b"},{"time":"2026-10-12T02:30:00Z","parent":"3f14d64b4c7715903cff2a628a00a6e4c774e242a42400ef3fd24d3e3a1fee1a","tree":"1c1df704c5d5d3ac06dfc4a2d43ad706d692dbd78f3b5a6b983c2623d005cf2a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"d85b77be2724c4e449fa4d5a51ade77b83f83d3fba834e322ff2a07575c413fa","short_id":"d85b77be"},{"time":"2026-10-12T02:30:00Z","parent":"9dcb3fa42c8d5b880c7e407ea15e134d540bab3fb250a63854c14dddb1748b79","tree":"7945e1927ec6444933dbe89befa7f342ffd218ab2a96d824a3e3cd9a25f11286","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"44f0faa89145f8dd68e06437323d677fae465f54c4f6aa95f938234ba0112f57","short_id":"44f0faa8"},{"time":"2026-10-13T02:30:00Z","parent":"d85b77be2724c4e449fa4d5a51ade77b83f83d3fba834e322ff2a07575c413fa","tree":"13ab80d5668ef726b7c82ba2f73366f1fa9f2d25511d7cb3fe798582ec2d189d","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"b6280f340819d34bf80b0a8edf7c9b378d04363483abd74b1a8a61dc921499e7","short_id":"b6280f34"},{"time":"2026-10-13T02:30:00Z","parent":"44f0faa89145f8dd68e06437323d677fae465f54c4f6aa95f938234ba0112f57","tree":"2f79914cd5a90ceb735c3dd272c22db5a67f5f1c6a35f48af320f7b218959177","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"4a74cebcf061b3f721ce35f1dae2fe644c3dcb77620042d6a9e9a1f69ffa5908","short_id":"4a74cebc"},{"time":"2026-10-14T02:30:00Z","parent":"b6280f340819d34bf80b0a8edf7c9b378d04363483abd74b1a8a61dc921499e7","tree":"795573bb56c71a53b79b999ee8bf8abbdddd04e223191fa07976d2384c24370f","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"c980586cfb31f9bf16ec3a509de8d37160ea05102ffa4cfb12f3a834eb8317b3","short_id":"c980586c"},{"time":"2026-10-14T02:30:00Z","parent":"4a74cebcf061b3f721ce35f1dae2fe644c3dcb77620042d6a9e9a1f69ffa5908","tree":"22deec6d4575076f3b5b9228249ef0935883841659af9e60c2e471f903d301cf","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"8d4189078ef8c5de57f8e0a58d646229c6ea05a584a223b13d6d52ee9b2a499a","short_id":"8d418907"},{"time":"2026-10-15T02:30:00Z","parent":"8d4189078ef8c5de57f8e0a58d646229c6ea05a584a223b13d6d52ee9b2a499a","tree":"c81de4fd5684584aecccba2848d623d9b46d27aaa7a8fda0cf7a4a56faa19f12","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"331513b5478c67fd17b601f4e86536be66fdebac42db635d2b44073c418c9044","short_id":"331513b5"},{"time":"2026-10-15T02:30:00Z","parent":"c980586cfb31f9bf16ec3a509de8d37160ea05102ffa4cfb12f3a834eb8317b3","tree":"cfc9e89d510b4d7500f66c7774f8fa1d26035be91e2de72bb5b35b5ff1565597","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"16f5cbf1aab3d6aaf201e9cf15f90b780e5db3854751f745883a6bd6e707d2dd","short_id":"16f5cbf1"},{"time":"2026-10-16T02:30:00Z","parent":"331513b5478c67fd17b601f4e86536be66fdebac42db635d2b44073c418c9044","tree":"2479779a0246aded8ea88b1b43549f333df32233150ead772301d4060d9834b6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"1bb3e0b01ad4e9ef4092c0f4f38d003d026d3e62bd4ec32ad84d2ae50b1fc26b","short_id":"1bb3e0b0"},{"time":"2026-10-16T02:30:00Z","parent":"16f5cbf1aab3d6aaf201e9cf15f90b780e5db3854751f745883a6bd6e707d2dd","tree":"286f8da9b1b553de264161006b6f14be594a3eef691d3980954808cf02387f21","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"3e5346879326eed55c3c0ab2abcce53b9207c9f1da1a4f3ad1ee0ab831063651","short_id":"3e534687"}] +[{"time":"2026-09-06T02:30:00Z","tree":"f685956bf88ee15d577e60f77a8ce561abdb2dd56eb1d00b26d5c59276add7a6","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"2a76397eb8a43be8c70dd687ab03fcd939f2f058f815804b9fa2e0f5d9d32376","short_id":"2a76397e"},{"time":"2026-09-06T02:30:00Z","tree":"ce672340389400ef8f5094e689dff293adf1f0d532d6e9f811b693a112a01933","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"b49faa0a4d3e92a36922c154ede633f1ff9080fea23770cfe9547316803701e3","short_id":"b49faa0a"},{"time":"2026-09-07T02:30:00Z","parent":"2a76397eb8a43be8c70dd687ab03fcd939f2f058f815804b9fa2e0f5d9d32376","tree":"70b21a93a7e8af3804e813d7d47cb5d936ebfff4ebf1b8b80a9834382142aee5","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"820d553d84f1c920803a156ffea356c7aacf469e7555f07ea8b9408d2021f254","short_id":"820d553d"},{"time":"2026-09-07T02:30:00Z","parent":"b49faa0a4d3e92a36922c154ede633f1ff9080fea23770cfe9547316803701e3","tree":"46653667b9ba1ba3646c2af1471791b09b03a936d8a8a8f247f09a8731db42d2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"96824fce2d56c812475efc60585f0a3fe7988874ec48ecf7a55946feb3e14c0d","short_id":"96824fce"},{"time":"2026-09-08T02:30:00Z","parent":"96824fce2d56c812475efc60585f0a3fe7988874ec48ecf7a55946feb3e14c0d","tree":"dd6a4ba2b1bd03d58f08b20df5ce546db43a0bdc69c88430c4f835773f75645d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"3f9ff630cd8c4830ccd24976f24065aa17e84e24a04876cda02310a9d845a554","short_id":"3f9ff630"},{"time":"2026-09-08T02:30:00Z","parent":"820d553d84f1c920803a156ffea356c7aacf469e7555f07ea8b9408d2021f254","tree":"f725d2ffc7382c23554b85a5381905f02a11b09d307c24cd20980bcb30dce47b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"1242b68c1b172bc4ae762fe874cd6dd8863ce3ae03961f5175c35fa26475d385","short_id":"1242b68c"},{"time":"2026-09-09T02:30:00Z","parent":"3f9ff630cd8c4830ccd24976f24065aa17e84e24a04876cda02310a9d845a554","tree":"fb772e958ecbf3b778ef2b838a4937dab663d80ae6ffa571453dcf0d375d70b7","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"c25662ce1a2597f3468e93251a04d35419b912c26907724b89c197edb79b69c9","short_id":"c25662ce"},{"time":"2026-09-09T02:30:00Z","parent":"1242b68c1b172bc4ae762fe874cd6dd8863ce3ae03961f5175c35fa26475d385","tree":"2bfaf9b4b8dabb68a2824ce5f48d27fda4ea94c2a960718bd84cabd59be13acf","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"d1c1d0c71c88d2f829b267adfdafbc1b19fdf184de6cdf1de28703cf46b40d65","short_id":"d1c1d0c7"},{"time":"2026-09-10T02:30:00Z","parent":"d1c1d0c71c88d2f829b267adfdafbc1b19fdf184de6cdf1de28703cf46b40d65","tree":"ed7361b730a863510df1e3b9f7d25b810902e8e86e0e230632250186cc558b21","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"e4b8322da1d838315d2dd62509678d7b419924a0d7c4723062aa31140a417ac0","short_id":"e4b8322d"},{"time":"2026-09-10T02:30:00Z","parent":"c25662ce1a2597f3468e93251a04d35419b912c26907724b89c197edb79b69c9","tree":"3e9374ab1878e6aad827032c581f50b02296f436c71afc9db1080bc28c53db1a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"7b08e08836fa06d1a6cf125cf8e7f5f5bca1358421ff7386a9d1a3b204e0aeb6","short_id":"7b08e088"},{"time":"2026-09-11T02:30:00Z","parent":"e4b8322da1d838315d2dd62509678d7b419924a0d7c4723062aa31140a417ac0","tree":"9b79e87705df56afe04f10b8a5e15cb8cc4abed0585815e54282b77cacd3eae6","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"8c127f74318a1ff657ebc803b1fda7fae31ff1e2e3e145c9bd137d04f9de9d92","short_id":"8c127f74"},{"time":"2026-09-11T02:30:00Z","parent":"7b08e08836fa06d1a6cf125cf8e7f5f5bca1358421ff7386a9d1a3b204e0aeb6","tree":"45dace70a50297723fc9ab12d5215e2892adb5e15338f093495913aa9c674a45","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"f22a8b07c06ae226ae53db79d52c977c9f01b5708cc2d24a47e1171ce05f34a7","short_id":"f22a8b07"},{"time":"2026-09-12T02:30:00Z","parent":"8c127f74318a1ff657ebc803b1fda7fae31ff1e2e3e145c9bd137d04f9de9d92","tree":"57c13238258e80cccb13e8d4dac05a82f9c3da4ac3dc6a26e9b8f4736e478af1","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"9224b1af26c1c1fe31395055f22158bf09cc541f4b59a59caf91b71f92bc63f1","short_id":"9224b1af"},{"time":"2026-09-12T02:30:00Z","parent":"f22a8b07c06ae226ae53db79d52c977c9f01b5708cc2d24a47e1171ce05f34a7","tree":"422cd3972d9092ce5082e72b49d1df597a80f88de2085e6ae6a40b676bb97601","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"670ca41966dd9493c733a7160c867d8c5024128d6d3f804142ce873089d56d1c","short_id":"670ca419"},{"time":"2026-09-13T02:30:00Z","parent":"9224b1af26c1c1fe31395055f22158bf09cc541f4b59a59caf91b71f92bc63f1","tree":"a5b546be122e577d101aaa067994bae404a881925573c09a2576431b51bb3e82","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"d6678aa268695bc4387fe3a857f3304013c2bd672dc1234cf2161343bf18efdc","short_id":"d6678aa2"},{"time":"2026-09-13T02:30:00Z","parent":"670ca41966dd9493c733a7160c867d8c5024128d6d3f804142ce873089d56d1c","tree":"ee30f31481f47e63795e88c27f2cc603d60ea9ad9dd53fb60417ca48b93c48c8","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"8a336152be88a2f4123b281a9fd1da34c195eb44363f08e988cf2f35645a2b66","short_id":"8a336152"},{"time":"2026-09-14T02:30:00Z","parent":"8a336152be88a2f4123b281a9fd1da34c195eb44363f08e988cf2f35645a2b66","tree":"56004cc3737e424b403621b63b8cbc4e71c0ae86a326c30fe3a627a1c572d963","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"2f18a0cd5a226f2d04d075853265761756f6228499c1d8d6d08694c49bb3c2b7","short_id":"2f18a0cd"},{"time":"2026-09-14T02:30:00Z","parent":"d6678aa268695bc4387fe3a857f3304013c2bd672dc1234cf2161343bf18efdc","tree":"fdc02ae7cab64e7ab641be509365b4b8201eaf3c6dddf7191ba01bbcd750d3ea","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"a74319ea5b78b3276b0aa7407b39f95e44c0676915ce815a979383d2afbc6e23","short_id":"a74319ea"},{"time":"2026-09-15T02:30:00Z","parent":"2f18a0cd5a226f2d04d075853265761756f6228499c1d8d6d08694c49bb3c2b7","tree":"1352369b945c41e97bbd11d3ca0f0ed4885046ce3e51e3762b4986b0c9b04ca0","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"bf5abbdc483043f91fefdde6e97249ee81610adca5195440770fea3ec9c014f1","short_id":"bf5abbdc"},{"time":"2026-09-15T02:30:00Z","parent":"a74319ea5b78b3276b0aa7407b39f95e44c0676915ce815a979383d2afbc6e23","tree":"be3be59ec618cf36d26d6d3e8368b560ce88c60b6eda56e861c6f5146f667be2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"0c24dfcc62048ac0b64dd13aad000479b47ceddfd2963119e631c488714f8cc3","short_id":"0c24dfcc"},{"time":"2026-09-16T02:30:00Z","parent":"0c24dfcc62048ac0b64dd13aad000479b47ceddfd2963119e631c488714f8cc3","tree":"39e7b89853eb47ec19c07a060be51173dd800a2d46417ae0201fefa3af33d90a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"e0ec672a95aacf51c562acf57701aba0e725a1d811ce3a6f5c2ebad549a8c016","short_id":"e0ec672a"},{"time":"2026-09-16T02:30:00Z","parent":"bf5abbdc483043f91fefdde6e97249ee81610adca5195440770fea3ec9c014f1","tree":"55007688ced33784bc5785e3dc9546f472cbeda9d545f9327aca913631586c3a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"f0a0d4eb6dda96f6db6099dff7156458aed506eeadca78859ad9657068e44501","short_id":"f0a0d4eb"},{"time":"2026-09-17T02:30:00Z","parent":"e0ec672a95aacf51c562acf57701aba0e725a1d811ce3a6f5c2ebad549a8c016","tree":"a037a5eb6e669bc15c6705f0c4eb665c729eefa37af2a196086ce1701230988e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"a2be8e6be366d62cca9bc6d4e12b1c97a310051e2fa8a077dff1fb07e904000a","short_id":"a2be8e6b"},{"time":"2026-09-17T02:30:00Z","parent":"f0a0d4eb6dda96f6db6099dff7156458aed506eeadca78859ad9657068e44501","tree":"92ac0d05e95224172f35772f54eb47981154feb9e6e58a4f03c3b273eea3dd1d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"ee89b04f40a213571e3a100a01c666b02566dde4ea56e902b11df9a2c3f13a09","short_id":"ee89b04f"},{"time":"2026-09-18T02:30:00Z","parent":"a2be8e6be366d62cca9bc6d4e12b1c97a310051e2fa8a077dff1fb07e904000a","tree":"251699699303a792c841f497662af163952386fd70b2d6dcfa435bd0d902ace2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"177c6f12c40c9f355adc60d0a875830e78353038462fe15beeb00f3afef04efe","short_id":"177c6f12"},{"time":"2026-09-18T02:30:00Z","parent":"ee89b04f40a213571e3a100a01c666b02566dde4ea56e902b11df9a2c3f13a09","tree":"862bd61ed170b4a5e0ec0fa971bf16a2fd295b5b0ca5ca8b5573d5d96bf46d0b","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"dc383edfe97cc655252f1ad872386b2fefeecc0b3e170e7a04d8683225214951","short_id":"dc383edf"},{"time":"2026-09-19T02:30:00Z","parent":"dc383edfe97cc655252f1ad872386b2fefeecc0b3e170e7a04d8683225214951","tree":"2ca8aade0fdfc72248d246771ee003972eaad397aa613f78dea4b2ba6d1a0287","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"0c97b2f8a266b152761dd1769c0898bc78a367c859ca8013edec68bfc61aa0d4","short_id":"0c97b2f8"},{"time":"2026-09-19T02:30:00Z","parent":"177c6f12c40c9f355adc60d0a875830e78353038462fe15beeb00f3afef04efe","tree":"a97bea5453e2a1a8913ee3965b4fec1632d677dfe0ecf74213efee6f43568e20","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"c2e659092443ccc73500e061690d9f99b0a653e8dcc002f441cd359385045e0e","short_id":"c2e65909"},{"time":"2026-09-20T02:30:00Z","parent":"c2e659092443ccc73500e061690d9f99b0a653e8dcc002f441cd359385045e0e","tree":"4ad27f2ca164c7d23866d5c06e75aa70ad20d8f86229816534ce7adcffb652a7","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"43902ad8c4d345ac41a98af33afc74fd36d2f6896fb45e94fe553ba3f2b51d0f","short_id":"43902ad8"},{"time":"2026-09-20T02:30:00Z","parent":"0c97b2f8a266b152761dd1769c0898bc78a367c859ca8013edec68bfc61aa0d4","tree":"f61ebed68d2e86ca59dc4e4223535a3aa8198562b2cecb812b52d3ba9e5411e7","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"ec0f30baecf767c3a02ec631814236071014258f0287f3044b591a34d5a99d73","short_id":"ec0f30ba"},{"time":"2026-09-21T02:30:00Z","parent":"43902ad8c4d345ac41a98af33afc74fd36d2f6896fb45e94fe553ba3f2b51d0f","tree":"f10d8afc6c36f40a793446537a09092aab457abaddd2f5dd884273014ffd986b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"ab24192f7a961b8103bdf4c5a3ab7d2a13b949b6accb9d52d1411f49d9d0deea","short_id":"ab24192f"},{"time":"2026-09-21T02:30:00Z","parent":"ec0f30baecf767c3a02ec631814236071014258f0287f3044b591a34d5a99d73","tree":"c1ddfe015a6300456c24a6561c1a1f247f255254834aac61435ceef06456e806","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"8f870fe269857d1d611fff5e03d2b22533bce7dc5aad4340de6cdf434b5aa0ae","short_id":"8f870fe2"},{"time":"2026-09-22T02:30:00Z","parent":"ab24192f7a961b8103bdf4c5a3ab7d2a13b949b6accb9d52d1411f49d9d0deea","tree":"1e0e3145356cbc6b68674824bdb7b2bc5524ab3fc8cbcb27368f9efb819c0124","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"7b37aba5b0971c1f41c15269fe2157e320b4f6428920d743302e4a904e053f63","short_id":"7b37aba5"},{"time":"2026-09-22T02:30:00Z","parent":"8f870fe269857d1d611fff5e03d2b22533bce7dc5aad4340de6cdf434b5aa0ae","tree":"31fbee51dde5e56f1d5940902bf8428ee4a1a2825a6081dea2b3ffb60a66ca26","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"5e41a7b17484c04288c67cce0dbf9cb3046325a9617b27f33d128ea5e906eebe","short_id":"5e41a7b1"},{"time":"2026-09-23T02:30:00Z","parent":"7b37aba5b0971c1f41c15269fe2157e320b4f6428920d743302e4a904e053f63","tree":"eac20fb1f7f17be350f01322cc58152ec05c680ba60706fa5f25db89bab1d264","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"6398aadc912ab1364b0c83f3e3ce51c3099bf74e018ac25107f51dbeed6b3c47","short_id":"6398aadc"},{"time":"2026-09-23T02:30:00Z","parent":"5e41a7b17484c04288c67cce0dbf9cb3046325a9617b27f33d128ea5e906eebe","tree":"1092cccb0c44787eb64ea2ea143189a5bf5d093ebfa0427d0cb07ac47543bcf4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"0c73460e3fa99b3c38ef31c378515f2424f18877bd354994d053576aa58ec214","short_id":"0c73460e"},{"time":"2026-09-24T02:30:00Z","parent":"6398aadc912ab1364b0c83f3e3ce51c3099bf74e018ac25107f51dbeed6b3c47","tree":"29e68a845705a5490fc07891a54fa6ff4d674183f4314f23361fb3d5c43b5057","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"264cbd7c1e22696db518c2b8aba55d9755e2799bab72d54d48f8521ae1740e84","short_id":"264cbd7c"},{"time":"2026-09-24T02:30:00Z","parent":"0c73460e3fa99b3c38ef31c378515f2424f18877bd354994d053576aa58ec214","tree":"530b2ba5c60bab9cc6f56148cf6388dff62236a252592031c10df1e2dd2607d6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"0b0bc0701cee5d7533d4a97f4c9ef7f5a401eb552d2ca3536a1ed5cebeb83f97","short_id":"0b0bc070"},{"time":"2026-09-25T02:30:00Z","parent":"0b0bc0701cee5d7533d4a97f4c9ef7f5a401eb552d2ca3536a1ed5cebeb83f97","tree":"c6508fdf7a64e55c2058145ba81f1b27e8687b8b2b2a4bd7324a157ef31ad12a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"d4562f249a7d2962d749dbaf843d8ac71b9c8ebb0c0b7cec09afcd8711529eea","short_id":"d4562f24"},{"time":"2026-09-25T02:30:00Z","parent":"264cbd7c1e22696db518c2b8aba55d9755e2799bab72d54d48f8521ae1740e84","tree":"0b332b3757a2111c5c5e1adcb59f011b4ce4716c350fbb289496525a612b27eb","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"ce4afadd45ee5a17b6e8f276704f99478bf5e82cc0870a5b4e6db3e07d64ace8","short_id":"ce4afadd"},{"time":"2026-09-26T02:30:00Z","parent":"ce4afadd45ee5a17b6e8f276704f99478bf5e82cc0870a5b4e6db3e07d64ace8","tree":"8f40b7ed62ec04ce4dd10a648fd97db920711a6f387503bb2a75f535de395656","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"e974e4a5987c5d524f227b4b091811a0488e5fed27cb736d511f009b13b13b1d","short_id":"e974e4a5"},{"time":"2026-09-26T02:30:00Z","parent":"d4562f249a7d2962d749dbaf843d8ac71b9c8ebb0c0b7cec09afcd8711529eea","tree":"36c5d5c1356cef66b9017f1411f798274554b52a7b01a8b4127ef1c30c6a02f6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"b26700ff3e9871ac081886d146fc30b9d8e7bd4572cea0b62f8f0261ea1a4f9d","short_id":"b26700ff"},{"time":"2026-09-27T02:30:00Z","parent":"e974e4a5987c5d524f227b4b091811a0488e5fed27cb736d511f009b13b13b1d","tree":"c5cb9ce2ff06516329a42aec557f7223e1a3c3801c502f7a53f0ab6414cedf15","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"7e67848219703f577e06ce2750b104a8c8f956978b05aafa4a205a3d258eb376","short_id":"7e678482"},{"time":"2026-09-27T02:30:00Z","parent":"b26700ff3e9871ac081886d146fc30b9d8e7bd4572cea0b62f8f0261ea1a4f9d","tree":"21aa00a24cb6990028d074e46a5af0457b5bc87da6867d0857663f776247b8cc","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"e24109dd53394e0bd7278f7b5e3fffa90f685bfdcd0a93952cff5638967a13fe","short_id":"e24109dd"},{"time":"2026-09-28T02:30:00Z","parent":"7e67848219703f577e06ce2750b104a8c8f956978b05aafa4a205a3d258eb376","tree":"e03a49f45c2db8d9342d90626025311ca3592d7d78c6dd6eeb8ffed0848c7ae0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"a695cd17a42947d6a5f1d74db5dc14f508cffbd7f98582124a25c53d47defd21","short_id":"a695cd17"},{"time":"2026-09-28T02:30:00Z","parent":"e24109dd53394e0bd7278f7b5e3fffa90f685bfdcd0a93952cff5638967a13fe","tree":"7c0a07c56348b0fa19b9507bf17dada815bdf81517a714408db21e288fc554b3","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"f062f3c51cde5c848398daa1b47cd122d76a0639c76f9436983ae2657895f352","short_id":"f062f3c5"},{"time":"2026-09-29T02:30:00Z","parent":"f062f3c51cde5c848398daa1b47cd122d76a0639c76f9436983ae2657895f352","tree":"b99010471bc3056f04c0a8dd25fa412b4834f977d1a7600c03b03b1bb8a9d8fe","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"cb87227f0c1c6acf4999c4b2024b589203cb184ce089a01a2db472ddbb560380","short_id":"cb87227f"},{"time":"2026-09-29T02:30:00Z","parent":"a695cd17a42947d6a5f1d74db5dc14f508cffbd7f98582124a25c53d47defd21","tree":"07492d5c8986dadc99631897cd7c4acfe18ec97dd70898d09899d5cd87b9539e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"35e79f2b266136d2be26273e4eabb20005fd5158e59539cd492b0c8e4bbfb2d3","short_id":"35e79f2b"},{"time":"2026-09-30T02:30:00Z","parent":"35e79f2b266136d2be26273e4eabb20005fd5158e59539cd492b0c8e4bbfb2d3","tree":"56b96a8e688ab8190bddb0868d331ece565f8856aef3cdcfef32fc1518e6baf2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"5ae64e02898e62676cdb3ba4689ed25eb83588a65127d244e69417846e495d78","short_id":"5ae64e02"},{"time":"2026-09-30T02:30:00Z","parent":"cb87227f0c1c6acf4999c4b2024b589203cb184ce089a01a2db472ddbb560380","tree":"b778b7edf7fa14307405e72c16f20050fc813cf944bda6b445d209db77e4bc00","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"8e604e28a0930828c9080477856be09c1475c467ac41f6ded7e2da5bdb3571ac","short_id":"8e604e28"},{"time":"2026-10-01T02:30:00Z","parent":"5ae64e02898e62676cdb3ba4689ed25eb83588a65127d244e69417846e495d78","tree":"b4403fd15f29eced5de4749e59d5b9fe2022030132fe5e9e4d6bb64f83a1cf92","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"bfaf7ca84276c21938171a2d38258647686386fc83df7f24a1b7d67de552202a","short_id":"bfaf7ca8"},{"time":"2026-10-01T02:30:00Z","parent":"8e604e28a0930828c9080477856be09c1475c467ac41f6ded7e2da5bdb3571ac","tree":"bcd5f11e44998ee9e52c5b89ea0a4867e06475bc90b5cb4267364ab6146c9d01","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"23ab590268b600c179d6636df65055810c0def0e99a571cdcb7890c556446cc2","short_id":"23ab5902"},{"time":"2026-10-02T02:30:00Z","parent":"bfaf7ca84276c21938171a2d38258647686386fc83df7f24a1b7d67de552202a","tree":"0fd6c21124d32f9e6a9ee6c3d3a740143c7d90683391082c42bd6cd3bfd0f530","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"cee066c08d1f2f222dd490fa86e4a7931be865004d0aaf50e63f8536d0e232ec","short_id":"cee066c0"},{"time":"2026-10-02T02:30:00Z","parent":"23ab590268b600c179d6636df65055810c0def0e99a571cdcb7890c556446cc2","tree":"65f5c632a0d2b90ad809a363562f24e3f66d1c52483a9defd47b266da1af4199","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"bd15d29185bb8d6e805451f5e17315396cf315d27c4ca53b9d31d0798ce9d182","short_id":"bd15d291"},{"time":"2026-10-03T02:30:00Z","parent":"cee066c08d1f2f222dd490fa86e4a7931be865004d0aaf50e63f8536d0e232ec","tree":"2fdf5cb4f765aeda71371e854f2b73e96ed86e5deb4b54faf6d45ad76756cfb5","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"0e6cad1bee36f6ce4c5d28d756f256bb692a1419cf91e29cc1a856c22d5975e7","short_id":"0e6cad1b"},{"time":"2026-10-03T02:30:00Z","parent":"bd15d29185bb8d6e805451f5e17315396cf315d27c4ca53b9d31d0798ce9d182","tree":"f1dad16a3035d09aac43fe50021f0d0c50ff022c54b28b5c499cf572c95b5746","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"7c1f837ad939b4f4c376a0ff177862f08d87e4616cbe8e54a60d4a666b804ce7","short_id":"7c1f837a"},{"time":"2026-10-04T02:30:00Z","parent":"0e6cad1bee36f6ce4c5d28d756f256bb692a1419cf91e29cc1a856c22d5975e7","tree":"4709d5189f78175060c473debd32bbc95e655c0a6e5ca9792c34b3fd0415de69","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"960d1e720e43e9cb467f170f45277f133494374baa337f93a8af1b973e4b84b3","short_id":"960d1e72"},{"time":"2026-10-04T02:30:00Z","parent":"7c1f837ad939b4f4c376a0ff177862f08d87e4616cbe8e54a60d4a666b804ce7","tree":"a5e934915e68d97267ee3b108c7ee16ea0867e651b9232443fe919d83fa3a4c2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"fa1d764f43f6190cf22b9a763d8cc972d7dc3bb01aaf4f1074e56dbfc350c5e8","short_id":"fa1d764f"},{"time":"2026-10-05T02:30:00Z","parent":"fa1d764f43f6190cf22b9a763d8cc972d7dc3bb01aaf4f1074e56dbfc350c5e8","tree":"d74e551770184290eb6224af4d48c4008a5b3b7e7cb8204eb3c85c14354d19df","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"2a9ca46af4806ddc2989b343739647e93f622ce863a6610d58e3e5b5f1bae413","short_id":"2a9ca46a"},{"time":"2026-10-05T02:30:00Z","parent":"960d1e720e43e9cb467f170f45277f133494374baa337f93a8af1b973e4b84b3","tree":"8bffed4ff0074c8dbc58f616ddfea18aae6a4bbafb6f3ead72cc2d6fdc7bb7d7","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"d1a3dffd18e46a92ee75c698f7c716727a942ace2efba7ccc2935b6087992908","short_id":"d1a3dffd"},{"time":"2026-10-06T02:30:00Z","parent":"d1a3dffd18e46a92ee75c698f7c716727a942ace2efba7ccc2935b6087992908","tree":"978e63c6278adf45029b4c51f773aac5252d334e4d2782f2fac88174fedbb1ff","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"c7aee7b89b42a2539a75e863e0083ae8761ee7ed8826b5a6c3d49820c0e6ba26","short_id":"c7aee7b8"},{"time":"2026-10-06T02:30:00Z","parent":"2a9ca46af4806ddc2989b343739647e93f622ce863a6610d58e3e5b5f1bae413","tree":"1782fe2e236f85c58cf9b786a7737b5e7974ad71b960bfeaf4240bc528fec665","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"a0ad00ea114be1368fbce2b72ca2f638b904795e73124adb8bd25ae30458933e","short_id":"a0ad00ea"},{"time":"2026-10-07T02:30:00Z","parent":"c7aee7b89b42a2539a75e863e0083ae8761ee7ed8826b5a6c3d49820c0e6ba26","tree":"87bbe7cfd2c5e04fffb43951ae72dbcdc26c2e4eac1be4fa384c26238139d7f3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"2d383c39077530c4a9f98ba8dc20f014e210854d2c4f32f79b335a19388b1e89","short_id":"2d383c39"},{"time":"2026-10-07T02:30:00Z","parent":"a0ad00ea114be1368fbce2b72ca2f638b904795e73124adb8bd25ae30458933e","tree":"a360e27e1aef84a6eacdf3dba92ab0a46a3628869c2af12d3c1b412863b0535d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"a818ad6aa46ec61c586a0ffb38e63148a69c7bbc08fd0a09acb6734278fbd63b","short_id":"a818ad6a"},{"time":"2026-10-08T02:30:00Z","parent":"2d383c39077530c4a9f98ba8dc20f014e210854d2c4f32f79b335a19388b1e89","tree":"f44bda5e625b1e7636d14efb44c79f9451ef71475b38751bd2c962d04f86ebd4","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"c27b0d1dabe2d975d297daad5b01ad678fb4c88e2d1e6e6ed5f2cf4aa21c5410","short_id":"c27b0d1d"},{"time":"2026-10-08T02:30:00Z","parent":"a818ad6aa46ec61c586a0ffb38e63148a69c7bbc08fd0a09acb6734278fbd63b","tree":"4caaed0b8ce301dc03a64b5fe8e441a3bf6cb9297bf96ad72d62c3b45525ef01","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"ec2a30d9ff60c7473067c0f6b620948f728174c7a5bb8eddfa238f0d8af5066f","short_id":"ec2a30d9"},{"time":"2026-10-09T02:30:00Z","parent":"c27b0d1dabe2d975d297daad5b01ad678fb4c88e2d1e6e6ed5f2cf4aa21c5410","tree":"0ffe8da4512fd658f56dc4ee240488b5d63ae4c07f742810846df3044a365f5a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"13ecd2eeb9d433ae4be796a9dd9e289b7f12aa55b807cbca1ac6d88b6033accd","short_id":"13ecd2ee"},{"time":"2026-10-09T02:30:00Z","parent":"ec2a30d9ff60c7473067c0f6b620948f728174c7a5bb8eddfa238f0d8af5066f","tree":"2e07df0532a24fe466f5fe8415b3c4e7a208d130974b1543591f7d5e42be04ba","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"29607a0ab3c4afc1d63525a96605bb44e0b5f4de690d1ed44bfd3bbc27025fa2","short_id":"29607a0a"},{"time":"2026-10-10T02:30:00Z","parent":"29607a0ab3c4afc1d63525a96605bb44e0b5f4de690d1ed44bfd3bbc27025fa2","tree":"357713e3a55168ec6bea559274dc7552b4fbd64381ce4bde9022e242ec328ad1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"5e76f560c4d54a477fce35b1a96ce61374291dc8fa52b6dfb76fde6d91f25bdb","short_id":"5e76f560"},{"time":"2026-10-10T02:30:00Z","parent":"13ecd2eeb9d433ae4be796a9dd9e289b7f12aa55b807cbca1ac6d88b6033accd","tree":"0ad2f65dd3de6f7fe4f32210cc07fae810683c769591e3122e9c12acd64a4281","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"cd0707729940a95ae60e9297780e370798d6ed750dc711dc6c34c80c82a6f105","short_id":"cd070772"},{"time":"2026-10-11T02:30:00Z","parent":"cd0707729940a95ae60e9297780e370798d6ed750dc711dc6c34c80c82a6f105","tree":"e408a9e30f5cb44933c7faaec25373d0874bc7e9447bf28ceda6fff612611d92","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"23ae66812d30a5ba39d9ec618c3e3dd453a2883da4d07e7c39438168388069d9","short_id":"23ae6681"},{"time":"2026-10-11T02:30:00Z","parent":"5e76f560c4d54a477fce35b1a96ce61374291dc8fa52b6dfb76fde6d91f25bdb","tree":"afe3b0d5eaf569af22f299df9b77ccd8166b7c654c0e886b7452bb10512d0706","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"8ff9e57a4c7e509cd5e49202f3617630771e0d839ad04911b8106b8b7c4207af","short_id":"8ff9e57a"},{"time":"2026-10-12T02:30:00Z","parent":"23ae66812d30a5ba39d9ec618c3e3dd453a2883da4d07e7c39438168388069d9","tree":"b721e2ac4dcc985dd24b608acb6b5243dad979038229a6a5b8e501cc2d7bad8e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"26da1569ccbbd96c81a266beef45c84e5a4b6dc870f44a41a89c437ebb09c09f","short_id":"26da1569"},{"time":"2026-10-12T02:30:00Z","parent":"8ff9e57a4c7e509cd5e49202f3617630771e0d839ad04911b8106b8b7c4207af","tree":"879f6a9563bba4bcdebbea7f32c27b9e452615464c6dc3111c2df59cd661a8a1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"4a611990c2123e859808a8546af22c372308a27a87b335aeeb89276e97049165","short_id":"4a611990"},{"time":"2026-10-13T02:30:00Z","parent":"26da1569ccbbd96c81a266beef45c84e5a4b6dc870f44a41a89c437ebb09c09f","tree":"3c0228aa205d8a36c5b4fe501ba5e50d638e219cf2cd4aef45f77e0ba9fc5bb0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"5339cf6d7ec710b3998e7bf52a09a17cbb5907d2c09ccf18ace19f525b812ae8","short_id":"5339cf6d"},{"time":"2026-10-13T02:30:00Z","parent":"4a611990c2123e859808a8546af22c372308a27a87b335aeeb89276e97049165","tree":"279178ad0293ba5157fdd209ec244a1d4899b58e1b9459c11ecac057cac60ff4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"e3fc65e0827c6939f7d86880e75facf36c2692f9cd259fe880232ee7de2a5391","short_id":"e3fc65e0"},{"time":"2026-10-14T02:30:00Z","parent":"5339cf6d7ec710b3998e7bf52a09a17cbb5907d2c09ccf18ace19f525b812ae8","tree":"57ab0a0f2ea360c1fbdfbc3b700e0225fb347eb8e715750283bb4b46e1133bf3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"47bbaa059c6e306c801b5f793e5f3500d1a0c258c3075855aa160276b4a0c704","short_id":"47bbaa05"},{"time":"2026-10-14T02:30:00Z","parent":"e3fc65e0827c6939f7d86880e75facf36c2692f9cd259fe880232ee7de2a5391","tree":"377caf3fbe1e17b4af93cc053064cde6b40976809805fcdebb0645e41b649ffb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"2b09f89771cf2744dde14e804ed9e7342871c8a6c1cb4849b8128f5d2571342f","short_id":"2b09f897"},{"time":"2026-10-15T02:30:00Z","parent":"47bbaa059c6e306c801b5f793e5f3500d1a0c258c3075855aa160276b4a0c704","tree":"a0dd167d57e68ce11fde606350779191cdc8c4413875240091be5880fb91c66e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","short_id":"27898187"},{"time":"2026-10-15T02:30:00Z","parent":"2b09f89771cf2744dde14e804ed9e7342871c8a6c1cb4849b8128f5d2571342f","tree":"8f361f971daac52f40180aa7fd3e4638e4ef90903699241b16954ee17fa304e6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"ee8432e0cd7bb4113731adc2e76d492238b539c3d6ce24a408670fee40579e57","short_id":"ee8432e0"},{"time":"2026-10-16T02:30:00Z","parent":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","tree":"b830b8165dc45c4b23086a81004548a5a52a00060028f0d274d8098dcc168b49","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"94fc37b9bfe97271d4a0b0feda4443a5e2934a3557108dd521d0bfb2f49423c8","short_id":"94fc37b9"},{"time":"2026-10-16T02:30:00Z","parent":"ee8432e0cd7bb4113731adc2e76d492238b539c3d6ce24a408670fee40579e57","tree":"024c36c1f532ac9150f9768ed57bb27cb284f8949f51958804dfd0f11ee70b65","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"315ff629674caa42ace8498b9d4bb82e5a77cb2284e628560444e12d9072ec8f","short_id":"315ff629"}] diff --git a/controller/internal/backup/testdata/restic/0.18.1/stats-raw.json b/controller/internal/backup/testdata/restic/0.18.1/stats-raw.json index 24bbff1..7e869f8 100644 --- a/controller/internal/backup/testdata/restic/0.18.1/stats-raw.json +++ b/controller/internal/backup/testdata/restic/0.18.1/stats-raw.json @@ -1 +1 @@ -{"total_size":217738,"total_uncompressed_size":345762,"compression_ratio":1.587972701136228,"compression_progress":100,"compression_space_saving":37.02662525089513,"total_blob_count":863,"snapshots_count":82} +{"total_size":217458,"total_uncompressed_size":345270,"compression_ratio":1.5877548768037966,"compression_progress":100,"compression_space_saving":37.017985924059424,"total_blob_count":863,"snapshots_count":82} diff --git a/controller/internal/backup/testdata/restic/0.19.1/backup-status.jsonl b/controller/internal/backup/testdata/restic/0.19.1/backup-status.jsonl new file mode 100644 index 0000000..5e362e7 --- /dev/null +++ b/controller/internal/backup/testdata/restic/0.19.1/backup-status.jsonl @@ -0,0 +1 @@ +{"message_type":"status","percent_done":0.3130332809996867,"total_files":3,"files_done":2,"total_bytes":41943061,"bytes_done":13129574,"current_files":["/data/x/u/a/big.tar"]} diff --git a/controller/internal/backup/testdata/restic/0.19.1/check-damaged.txt b/controller/internal/backup/testdata/restic/0.19.1/check-damaged.txt new file mode 100644 index 0000000..a78b899 --- /dev/null +++ b/controller/internal/backup/testdata/restic/0.19.1/check-damaged.txt @@ -0,0 +1,19 @@ +using temporary cache in /data/x/cache/restic-check-cache-237814189 +create exclusive lock for repository +load indexes +check all packs +check snapshots, trees and blobs +error for tree 2dd49e74: + decrypting blob from pack fd6de2a5f8204c762b7a38c35a81a60785d6a542d3506a63dadad936b0aeb160 failed: ciphertext verification failed +[0:00] 100.00% 82 / 82 snapshots +read all data +pack fd6de2a5f8204c762b7a38c35a81a60785d6a542d3506a63dadad936b0aeb160 contains 2 errors: [blob 2dd49e743c4d0b61ec5cfa2dc99f5446d5e7482635df00484aaa6a193aba98b8: decrypting blob from pack fd6de2a5f8204c762b7a38c35a81a60785d6a542d3506a63dadad936b0aeb160 failed: ciphertext verification failed unexpected pack id d22a000a356e727dc3afaeef9408a189de77107618df88519e050153a5a653a8] +[0:00] 100.00% 123 / 123 packs + +The repository contains damaged pack files. These damaged files must be removed to repair the repository. This can be done using the following commands. Please read the troubleshooting guide at https://restic.readthedocs.io/en/stable/077_troubleshooting.html first. + +restic repair packs fd6de2a5f8204c762b7a38c35a81a60785d6a542d3506a63dadad936b0aeb160 +restic repair snapshots --forget + +Damaged pack files can be caused by backend problems, hardware problems or bugs in restic. Please open an issue at https://github.com/restic/restic/issues/new/choose for further troubleshooting! +Fatal: repository contains errors diff --git a/controller/internal/backup/testdata/restic/0.19.1/check-ok.txt b/controller/internal/backup/testdata/restic/0.19.1/check-ok.txt new file mode 100644 index 0000000..167731c --- /dev/null +++ b/controller/internal/backup/testdata/restic/0.19.1/check-ok.txt @@ -0,0 +1,7 @@ +using temporary cache in /data/x/cache/restic-check-cache-2363455331 +create exclusive lock for repository +load indexes +check all packs +check snapshots, trees and blobs +[0:00] 100.00% 82 / 82 snapshots +no errors were found diff --git a/controller/internal/backup/testdata/restic/0.19.1/forget-dryrun.json b/controller/internal/backup/testdata/restic/0.19.1/forget-dryrun.json new file mode 100644 index 0000000..ecac55a --- /dev/null +++ b/controller/internal/backup/testdata/restic/0.19.1/forget-dryrun.json @@ -0,0 +1 @@ +[{"tags":["a","felhom-offbox"],"host":"box","paths":null,"keep":[{"time":"2026-10-16T02:30:00Z","parent":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","tree":"b830b8165dc45c4b23086a81004548a5a52a00060028f0d274d8098dcc168b49","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"94fc37b9bfe97271d4a0b0feda4443a5e2934a3557108dd521d0bfb2f49423c8","short_id":"94fc37b9"},{"time":"2026-10-15T02:30:00Z","parent":"47bbaa059c6e306c801b5f793e5f3500d1a0c258c3075855aa160276b4a0c704","tree":"a0dd167d57e68ce11fde606350779191cdc8c4413875240091be5880fb91c66e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","short_id":"27898187"},{"time":"2026-10-14T02:30:00Z","parent":"5339cf6d7ec710b3998e7bf52a09a17cbb5907d2c09ccf18ace19f525b812ae8","tree":"57ab0a0f2ea360c1fbdfbc3b700e0225fb347eb8e715750283bb4b46e1133bf3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"47bbaa059c6e306c801b5f793e5f3500d1a0c258c3075855aa160276b4a0c704","short_id":"47bbaa05"},{"time":"2026-10-13T02:30:00Z","parent":"26da1569ccbbd96c81a266beef45c84e5a4b6dc870f44a41a89c437ebb09c09f","tree":"3c0228aa205d8a36c5b4fe501ba5e50d638e219cf2cd4aef45f77e0ba9fc5bb0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"5339cf6d7ec710b3998e7bf52a09a17cbb5907d2c09ccf18ace19f525b812ae8","short_id":"5339cf6d"},{"time":"2026-10-12T02:30:00Z","parent":"23ae66812d30a5ba39d9ec618c3e3dd453a2883da4d07e7c39438168388069d9","tree":"b721e2ac4dcc985dd24b608acb6b5243dad979038229a6a5b8e501cc2d7bad8e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"26da1569ccbbd96c81a266beef45c84e5a4b6dc870f44a41a89c437ebb09c09f","short_id":"26da1569"},{"time":"2026-10-11T02:30:00Z","parent":"cd0707729940a95ae60e9297780e370798d6ed750dc711dc6c34c80c82a6f105","tree":"e408a9e30f5cb44933c7faaec25373d0874bc7e9447bf28ceda6fff612611d92","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"23ae66812d30a5ba39d9ec618c3e3dd453a2883da4d07e7c39438168388069d9","short_id":"23ae6681"},{"time":"2026-10-10T02:30:00Z","parent":"13ecd2eeb9d433ae4be796a9dd9e289b7f12aa55b807cbca1ac6d88b6033accd","tree":"0ad2f65dd3de6f7fe4f32210cc07fae810683c769591e3122e9c12acd64a4281","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"cd0707729940a95ae60e9297780e370798d6ed750dc711dc6c34c80c82a6f105","short_id":"cd070772"},{"time":"2026-10-04T02:30:00Z","parent":"0e6cad1bee36f6ce4c5d28d756f256bb692a1419cf91e29cc1a856c22d5975e7","tree":"4709d5189f78175060c473debd32bbc95e655c0a6e5ca9792c34b3fd0415de69","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"960d1e720e43e9cb467f170f45277f133494374baa337f93a8af1b973e4b84b3","short_id":"960d1e72"},{"time":"2026-09-30T02:30:00Z","parent":"35e79f2b266136d2be26273e4eabb20005fd5158e59539cd492b0c8e4bbfb2d3","tree":"56b96a8e688ab8190bddb0868d331ece565f8856aef3cdcfef32fc1518e6baf2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"5ae64e02898e62676cdb3ba4689ed25eb83588a65127d244e69417846e495d78","short_id":"5ae64e02"},{"time":"2026-09-27T02:30:00Z","parent":"e974e4a5987c5d524f227b4b091811a0488e5fed27cb736d511f009b13b13b1d","tree":"c5cb9ce2ff06516329a42aec557f7223e1a3c3801c502f7a53f0ab6414cedf15","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"7e67848219703f577e06ce2750b104a8c8f956978b05aafa4a205a3d258eb376","short_id":"7e678482"},{"time":"2026-09-06T02:30:00Z","tree":"f685956bf88ee15d577e60f77a8ce561abdb2dd56eb1d00b26d5c59276add7a6","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"2a76397eb8a43be8c70dd687ab03fcd939f2f058f815804b9fa2e0f5d9d32376","short_id":"2a76397e"}],"remove":[{"time":"2026-10-09T02:30:00Z","parent":"c27b0d1dabe2d975d297daad5b01ad678fb4c88e2d1e6e6ed5f2cf4aa21c5410","tree":"0ffe8da4512fd658f56dc4ee240488b5d63ae4c07f742810846df3044a365f5a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"13ecd2eeb9d433ae4be796a9dd9e289b7f12aa55b807cbca1ac6d88b6033accd","short_id":"13ecd2ee"},{"time":"2026-10-08T02:30:00Z","parent":"2d383c39077530c4a9f98ba8dc20f014e210854d2c4f32f79b335a19388b1e89","tree":"f44bda5e625b1e7636d14efb44c79f9451ef71475b38751bd2c962d04f86ebd4","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"c27b0d1dabe2d975d297daad5b01ad678fb4c88e2d1e6e6ed5f2cf4aa21c5410","short_id":"c27b0d1d"},{"time":"2026-10-07T02:30:00Z","parent":"c7aee7b89b42a2539a75e863e0083ae8761ee7ed8826b5a6c3d49820c0e6ba26","tree":"87bbe7cfd2c5e04fffb43951ae72dbcdc26c2e4eac1be4fa384c26238139d7f3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"2d383c39077530c4a9f98ba8dc20f014e210854d2c4f32f79b335a19388b1e89","short_id":"2d383c39"},{"time":"2026-10-06T02:30:00Z","parent":"d1a3dffd18e46a92ee75c698f7c716727a942ace2efba7ccc2935b6087992908","tree":"978e63c6278adf45029b4c51f773aac5252d334e4d2782f2fac88174fedbb1ff","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"c7aee7b89b42a2539a75e863e0083ae8761ee7ed8826b5a6c3d49820c0e6ba26","short_id":"c7aee7b8"},{"time":"2026-10-05T02:30:00Z","parent":"960d1e720e43e9cb467f170f45277f133494374baa337f93a8af1b973e4b84b3","tree":"8bffed4ff0074c8dbc58f616ddfea18aae6a4bbafb6f3ead72cc2d6fdc7bb7d7","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"d1a3dffd18e46a92ee75c698f7c716727a942ace2efba7ccc2935b6087992908","short_id":"d1a3dffd"},{"time":"2026-10-03T02:30:00Z","parent":"cee066c08d1f2f222dd490fa86e4a7931be865004d0aaf50e63f8536d0e232ec","tree":"2fdf5cb4f765aeda71371e854f2b73e96ed86e5deb4b54faf6d45ad76756cfb5","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"0e6cad1bee36f6ce4c5d28d756f256bb692a1419cf91e29cc1a856c22d5975e7","short_id":"0e6cad1b"},{"time":"2026-10-02T02:30:00Z","parent":"bfaf7ca84276c21938171a2d38258647686386fc83df7f24a1b7d67de552202a","tree":"0fd6c21124d32f9e6a9ee6c3d3a740143c7d90683391082c42bd6cd3bfd0f530","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"cee066c08d1f2f222dd490fa86e4a7931be865004d0aaf50e63f8536d0e232ec","short_id":"cee066c0"},{"time":"2026-10-01T02:30:00Z","parent":"5ae64e02898e62676cdb3ba4689ed25eb83588a65127d244e69417846e495d78","tree":"b4403fd15f29eced5de4749e59d5b9fe2022030132fe5e9e4d6bb64f83a1cf92","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"bfaf7ca84276c21938171a2d38258647686386fc83df7f24a1b7d67de552202a","short_id":"bfaf7ca8"},{"time":"2026-09-29T02:30:00Z","parent":"a695cd17a42947d6a5f1d74db5dc14f508cffbd7f98582124a25c53d47defd21","tree":"07492d5c8986dadc99631897cd7c4acfe18ec97dd70898d09899d5cd87b9539e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"35e79f2b266136d2be26273e4eabb20005fd5158e59539cd492b0c8e4bbfb2d3","short_id":"35e79f2b"},{"time":"2026-09-28T02:30:00Z","parent":"7e67848219703f577e06ce2750b104a8c8f956978b05aafa4a205a3d258eb376","tree":"e03a49f45c2db8d9342d90626025311ca3592d7d78c6dd6eeb8ffed0848c7ae0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"a695cd17a42947d6a5f1d74db5dc14f508cffbd7f98582124a25c53d47defd21","short_id":"a695cd17"},{"time":"2026-09-26T02:30:00Z","parent":"ce4afadd45ee5a17b6e8f276704f99478bf5e82cc0870a5b4e6db3e07d64ace8","tree":"8f40b7ed62ec04ce4dd10a648fd97db920711a6f387503bb2a75f535de395656","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"e974e4a5987c5d524f227b4b091811a0488e5fed27cb736d511f009b13b13b1d","short_id":"e974e4a5"},{"time":"2026-09-25T02:30:00Z","parent":"264cbd7c1e22696db518c2b8aba55d9755e2799bab72d54d48f8521ae1740e84","tree":"0b332b3757a2111c5c5e1adcb59f011b4ce4716c350fbb289496525a612b27eb","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"ce4afadd45ee5a17b6e8f276704f99478bf5e82cc0870a5b4e6db3e07d64ace8","short_id":"ce4afadd"},{"time":"2026-09-24T02:30:00Z","parent":"6398aadc912ab1364b0c83f3e3ce51c3099bf74e018ac25107f51dbeed6b3c47","tree":"29e68a845705a5490fc07891a54fa6ff4d674183f4314f23361fb3d5c43b5057","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"264cbd7c1e22696db518c2b8aba55d9755e2799bab72d54d48f8521ae1740e84","short_id":"264cbd7c"},{"time":"2026-09-23T02:30:00Z","parent":"7b37aba5b0971c1f41c15269fe2157e320b4f6428920d743302e4a904e053f63","tree":"eac20fb1f7f17be350f01322cc58152ec05c680ba60706fa5f25db89bab1d264","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"6398aadc912ab1364b0c83f3e3ce51c3099bf74e018ac25107f51dbeed6b3c47","short_id":"6398aadc"},{"time":"2026-09-22T02:30:00Z","parent":"ab24192f7a961b8103bdf4c5a3ab7d2a13b949b6accb9d52d1411f49d9d0deea","tree":"1e0e3145356cbc6b68674824bdb7b2bc5524ab3fc8cbcb27368f9efb819c0124","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"7b37aba5b0971c1f41c15269fe2157e320b4f6428920d743302e4a904e053f63","short_id":"7b37aba5"},{"time":"2026-09-21T02:30:00Z","parent":"43902ad8c4d345ac41a98af33afc74fd36d2f6896fb45e94fe553ba3f2b51d0f","tree":"f10d8afc6c36f40a793446537a09092aab457abaddd2f5dd884273014ffd986b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"ab24192f7a961b8103bdf4c5a3ab7d2a13b949b6accb9d52d1411f49d9d0deea","short_id":"ab24192f"},{"time":"2026-09-20T02:30:00Z","parent":"c2e659092443ccc73500e061690d9f99b0a653e8dcc002f441cd359385045e0e","tree":"4ad27f2ca164c7d23866d5c06e75aa70ad20d8f86229816534ce7adcffb652a7","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"43902ad8c4d345ac41a98af33afc74fd36d2f6896fb45e94fe553ba3f2b51d0f","short_id":"43902ad8"},{"time":"2026-09-19T02:30:00Z","parent":"177c6f12c40c9f355adc60d0a875830e78353038462fe15beeb00f3afef04efe","tree":"a97bea5453e2a1a8913ee3965b4fec1632d677dfe0ecf74213efee6f43568e20","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"c2e659092443ccc73500e061690d9f99b0a653e8dcc002f441cd359385045e0e","short_id":"c2e65909"},{"time":"2026-09-18T02:30:00Z","parent":"a2be8e6be366d62cca9bc6d4e12b1c97a310051e2fa8a077dff1fb07e904000a","tree":"251699699303a792c841f497662af163952386fd70b2d6dcfa435bd0d902ace2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"177c6f12c40c9f355adc60d0a875830e78353038462fe15beeb00f3afef04efe","short_id":"177c6f12"},{"time":"2026-09-17T02:30:00Z","parent":"e0ec672a95aacf51c562acf57701aba0e725a1d811ce3a6f5c2ebad549a8c016","tree":"a037a5eb6e669bc15c6705f0c4eb665c729eefa37af2a196086ce1701230988e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"a2be8e6be366d62cca9bc6d4e12b1c97a310051e2fa8a077dff1fb07e904000a","short_id":"a2be8e6b"},{"time":"2026-09-16T02:30:00Z","parent":"0c24dfcc62048ac0b64dd13aad000479b47ceddfd2963119e631c488714f8cc3","tree":"39e7b89853eb47ec19c07a060be51173dd800a2d46417ae0201fefa3af33d90a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"e0ec672a95aacf51c562acf57701aba0e725a1d811ce3a6f5c2ebad549a8c016","short_id":"e0ec672a"},{"time":"2026-09-15T02:30:00Z","parent":"a74319ea5b78b3276b0aa7407b39f95e44c0676915ce815a979383d2afbc6e23","tree":"be3be59ec618cf36d26d6d3e8368b560ce88c60b6eda56e861c6f5146f667be2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"0c24dfcc62048ac0b64dd13aad000479b47ceddfd2963119e631c488714f8cc3","short_id":"0c24dfcc"},{"time":"2026-09-14T02:30:00Z","parent":"d6678aa268695bc4387fe3a857f3304013c2bd672dc1234cf2161343bf18efdc","tree":"fdc02ae7cab64e7ab641be509365b4b8201eaf3c6dddf7191ba01bbcd750d3ea","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"a74319ea5b78b3276b0aa7407b39f95e44c0676915ce815a979383d2afbc6e23","short_id":"a74319ea"},{"time":"2026-09-13T02:30:00Z","parent":"9224b1af26c1c1fe31395055f22158bf09cc541f4b59a59caf91b71f92bc63f1","tree":"a5b546be122e577d101aaa067994bae404a881925573c09a2576431b51bb3e82","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"d6678aa268695bc4387fe3a857f3304013c2bd672dc1234cf2161343bf18efdc","short_id":"d6678aa2"},{"time":"2026-09-12T02:30:00Z","parent":"8c127f74318a1ff657ebc803b1fda7fae31ff1e2e3e145c9bd137d04f9de9d92","tree":"57c13238258e80cccb13e8d4dac05a82f9c3da4ac3dc6a26e9b8f4736e478af1","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"9224b1af26c1c1fe31395055f22158bf09cc541f4b59a59caf91b71f92bc63f1","short_id":"9224b1af"},{"time":"2026-09-11T02:30:00Z","parent":"e4b8322da1d838315d2dd62509678d7b419924a0d7c4723062aa31140a417ac0","tree":"9b79e87705df56afe04f10b8a5e15cb8cc4abed0585815e54282b77cacd3eae6","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"8c127f74318a1ff657ebc803b1fda7fae31ff1e2e3e145c9bd137d04f9de9d92","short_id":"8c127f74"},{"time":"2026-09-10T02:30:00Z","parent":"d1c1d0c71c88d2f829b267adfdafbc1b19fdf184de6cdf1de28703cf46b40d65","tree":"ed7361b730a863510df1e3b9f7d25b810902e8e86e0e230632250186cc558b21","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"e4b8322da1d838315d2dd62509678d7b419924a0d7c4723062aa31140a417ac0","short_id":"e4b8322d"},{"time":"2026-09-09T02:30:00Z","parent":"1242b68c1b172bc4ae762fe874cd6dd8863ce3ae03961f5175c35fa26475d385","tree":"2bfaf9b4b8dabb68a2824ce5f48d27fda4ea94c2a960718bd84cabd59be13acf","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"d1c1d0c71c88d2f829b267adfdafbc1b19fdf184de6cdf1de28703cf46b40d65","short_id":"d1c1d0c7"},{"time":"2026-09-08T02:30:00Z","parent":"820d553d84f1c920803a156ffea356c7aacf469e7555f07ea8b9408d2021f254","tree":"f725d2ffc7382c23554b85a5381905f02a11b09d307c24cd20980bcb30dce47b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"1242b68c1b172bc4ae762fe874cd6dd8863ce3ae03961f5175c35fa26475d385","short_id":"1242b68c"},{"time":"2026-09-07T02:30:00Z","parent":"2a76397eb8a43be8c70dd687ab03fcd939f2f058f815804b9fa2e0f5d9d32376","tree":"70b21a93a7e8af3804e813d7d47cb5d936ebfff4ebf1b8b80a9834382142aee5","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"820d553d84f1c920803a156ffea356c7aacf469e7555f07ea8b9408d2021f254","short_id":"820d553d"}],"reasons":[{"snapshot":{"time":"2026-10-16T02:30:00Z","parent":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","tree":"b830b8165dc45c4b23086a81004548a5a52a00060028f0d274d8098dcc168b49","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"94fc37b9bfe97271d4a0b0feda4443a5e2934a3557108dd521d0bfb2f49423c8","short_id":"94fc37b9"},"matches":["daily snapshot","weekly snapshot","monthly snapshot"]},{"snapshot":{"time":"2026-10-15T02:30:00Z","parent":"47bbaa059c6e306c801b5f793e5f3500d1a0c258c3075855aa160276b4a0c704","tree":"a0dd167d57e68ce11fde606350779191cdc8c4413875240091be5880fb91c66e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","short_id":"27898187"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-14T02:30:00Z","parent":"5339cf6d7ec710b3998e7bf52a09a17cbb5907d2c09ccf18ace19f525b812ae8","tree":"57ab0a0f2ea360c1fbdfbc3b700e0225fb347eb8e715750283bb4b46e1133bf3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"47bbaa059c6e306c801b5f793e5f3500d1a0c258c3075855aa160276b4a0c704","short_id":"47bbaa05"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-13T02:30:00Z","parent":"26da1569ccbbd96c81a266beef45c84e5a4b6dc870f44a41a89c437ebb09c09f","tree":"3c0228aa205d8a36c5b4fe501ba5e50d638e219cf2cd4aef45f77e0ba9fc5bb0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"5339cf6d7ec710b3998e7bf52a09a17cbb5907d2c09ccf18ace19f525b812ae8","short_id":"5339cf6d"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-12T02:30:00Z","parent":"23ae66812d30a5ba39d9ec618c3e3dd453a2883da4d07e7c39438168388069d9","tree":"b721e2ac4dcc985dd24b608acb6b5243dad979038229a6a5b8e501cc2d7bad8e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"26da1569ccbbd96c81a266beef45c84e5a4b6dc870f44a41a89c437ebb09c09f","short_id":"26da1569"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-11T02:30:00Z","parent":"cd0707729940a95ae60e9297780e370798d6ed750dc711dc6c34c80c82a6f105","tree":"e408a9e30f5cb44933c7faaec25373d0874bc7e9447bf28ceda6fff612611d92","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"23ae66812d30a5ba39d9ec618c3e3dd453a2883da4d07e7c39438168388069d9","short_id":"23ae6681"},"matches":["daily snapshot","weekly snapshot"]},{"snapshot":{"time":"2026-10-10T02:30:00Z","parent":"13ecd2eeb9d433ae4be796a9dd9e289b7f12aa55b807cbca1ac6d88b6033accd","tree":"0ad2f65dd3de6f7fe4f32210cc07fae810683c769591e3122e9c12acd64a4281","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"cd0707729940a95ae60e9297780e370798d6ed750dc711dc6c34c80c82a6f105","short_id":"cd070772"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-04T02:30:00Z","parent":"0e6cad1bee36f6ce4c5d28d756f256bb692a1419cf91e29cc1a856c22d5975e7","tree":"4709d5189f78175060c473debd32bbc95e655c0a6e5ca9792c34b3fd0415de69","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"960d1e720e43e9cb467f170f45277f133494374baa337f93a8af1b973e4b84b3","short_id":"960d1e72"},"matches":["weekly snapshot"]},{"snapshot":{"time":"2026-09-30T02:30:00Z","parent":"35e79f2b266136d2be26273e4eabb20005fd5158e59539cd492b0c8e4bbfb2d3","tree":"56b96a8e688ab8190bddb0868d331ece565f8856aef3cdcfef32fc1518e6baf2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"5ae64e02898e62676cdb3ba4689ed25eb83588a65127d244e69417846e495d78","short_id":"5ae64e02"},"matches":["monthly snapshot"]},{"snapshot":{"time":"2026-09-27T02:30:00Z","parent":"e974e4a5987c5d524f227b4b091811a0488e5fed27cb736d511f009b13b13b1d","tree":"c5cb9ce2ff06516329a42aec557f7223e1a3c3801c502f7a53f0ab6414cedf15","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"7e67848219703f577e06ce2750b104a8c8f956978b05aafa4a205a3d258eb376","short_id":"7e678482"},"matches":["weekly snapshot"]},{"snapshot":{"time":"2026-09-06T02:30:00Z","tree":"f685956bf88ee15d577e60f77a8ce561abdb2dd56eb1d00b26d5c59276add7a6","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["a","felhom-offbox"],"id":"2a76397eb8a43be8c70dd687ab03fcd939f2f058f815804b9fa2e0f5d9d32376","short_id":"2a76397e"},"matches":["oldest monthly snapshot"]}]},{"tags":["b","felhom-offbox"],"host":"box","paths":null,"keep":[{"time":"2026-10-16T02:30:00Z","parent":"ee8432e0cd7bb4113731adc2e76d492238b539c3d6ce24a408670fee40579e57","tree":"024c36c1f532ac9150f9768ed57bb27cb284f8949f51958804dfd0f11ee70b65","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"315ff629674caa42ace8498b9d4bb82e5a77cb2284e628560444e12d9072ec8f","short_id":"315ff629"},{"time":"2026-10-15T02:30:00Z","parent":"2b09f89771cf2744dde14e804ed9e7342871c8a6c1cb4849b8128f5d2571342f","tree":"8f361f971daac52f40180aa7fd3e4638e4ef90903699241b16954ee17fa304e6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"ee8432e0cd7bb4113731adc2e76d492238b539c3d6ce24a408670fee40579e57","short_id":"ee8432e0"},{"time":"2026-10-14T02:30:00Z","parent":"e3fc65e0827c6939f7d86880e75facf36c2692f9cd259fe880232ee7de2a5391","tree":"377caf3fbe1e17b4af93cc053064cde6b40976809805fcdebb0645e41b649ffb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"2b09f89771cf2744dde14e804ed9e7342871c8a6c1cb4849b8128f5d2571342f","short_id":"2b09f897"},{"time":"2026-10-13T02:30:00Z","parent":"4a611990c2123e859808a8546af22c372308a27a87b335aeeb89276e97049165","tree":"279178ad0293ba5157fdd209ec244a1d4899b58e1b9459c11ecac057cac60ff4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"e3fc65e0827c6939f7d86880e75facf36c2692f9cd259fe880232ee7de2a5391","short_id":"e3fc65e0"},{"time":"2026-10-12T02:30:00Z","parent":"8ff9e57a4c7e509cd5e49202f3617630771e0d839ad04911b8106b8b7c4207af","tree":"879f6a9563bba4bcdebbea7f32c27b9e452615464c6dc3111c2df59cd661a8a1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"4a611990c2123e859808a8546af22c372308a27a87b335aeeb89276e97049165","short_id":"4a611990"},{"time":"2026-10-11T02:30:00Z","parent":"5e76f560c4d54a477fce35b1a96ce61374291dc8fa52b6dfb76fde6d91f25bdb","tree":"afe3b0d5eaf569af22f299df9b77ccd8166b7c654c0e886b7452bb10512d0706","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8ff9e57a4c7e509cd5e49202f3617630771e0d839ad04911b8106b8b7c4207af","short_id":"8ff9e57a"},{"time":"2026-10-10T02:30:00Z","parent":"29607a0ab3c4afc1d63525a96605bb44e0b5f4de690d1ed44bfd3bbc27025fa2","tree":"357713e3a55168ec6bea559274dc7552b4fbd64381ce4bde9022e242ec328ad1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"5e76f560c4d54a477fce35b1a96ce61374291dc8fa52b6dfb76fde6d91f25bdb","short_id":"5e76f560"},{"time":"2026-10-04T02:30:00Z","parent":"7c1f837ad939b4f4c376a0ff177862f08d87e4616cbe8e54a60d4a666b804ce7","tree":"a5e934915e68d97267ee3b108c7ee16ea0867e651b9232443fe919d83fa3a4c2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"fa1d764f43f6190cf22b9a763d8cc972d7dc3bb01aaf4f1074e56dbfc350c5e8","short_id":"fa1d764f"},{"time":"2026-09-30T02:30:00Z","parent":"cb87227f0c1c6acf4999c4b2024b589203cb184ce089a01a2db472ddbb560380","tree":"b778b7edf7fa14307405e72c16f20050fc813cf944bda6b445d209db77e4bc00","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8e604e28a0930828c9080477856be09c1475c467ac41f6ded7e2da5bdb3571ac","short_id":"8e604e28"},{"time":"2026-09-27T02:30:00Z","parent":"b26700ff3e9871ac081886d146fc30b9d8e7bd4572cea0b62f8f0261ea1a4f9d","tree":"21aa00a24cb6990028d074e46a5af0457b5bc87da6867d0857663f776247b8cc","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"e24109dd53394e0bd7278f7b5e3fffa90f685bfdcd0a93952cff5638967a13fe","short_id":"e24109dd"},{"time":"2026-09-06T02:30:00Z","tree":"ce672340389400ef8f5094e689dff293adf1f0d532d6e9f811b693a112a01933","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"b49faa0a4d3e92a36922c154ede633f1ff9080fea23770cfe9547316803701e3","short_id":"b49faa0a"}],"remove":[{"time":"2026-10-09T02:30:00Z","parent":"ec2a30d9ff60c7473067c0f6b620948f728174c7a5bb8eddfa238f0d8af5066f","tree":"2e07df0532a24fe466f5fe8415b3c4e7a208d130974b1543591f7d5e42be04ba","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"29607a0ab3c4afc1d63525a96605bb44e0b5f4de690d1ed44bfd3bbc27025fa2","short_id":"29607a0a"},{"time":"2026-10-08T02:30:00Z","parent":"a818ad6aa46ec61c586a0ffb38e63148a69c7bbc08fd0a09acb6734278fbd63b","tree":"4caaed0b8ce301dc03a64b5fe8e441a3bf6cb9297bf96ad72d62c3b45525ef01","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"ec2a30d9ff60c7473067c0f6b620948f728174c7a5bb8eddfa238f0d8af5066f","short_id":"ec2a30d9"},{"time":"2026-10-07T02:30:00Z","parent":"a0ad00ea114be1368fbce2b72ca2f638b904795e73124adb8bd25ae30458933e","tree":"a360e27e1aef84a6eacdf3dba92ab0a46a3628869c2af12d3c1b412863b0535d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"a818ad6aa46ec61c586a0ffb38e63148a69c7bbc08fd0a09acb6734278fbd63b","short_id":"a818ad6a"},{"time":"2026-10-06T02:30:00Z","parent":"2a9ca46af4806ddc2989b343739647e93f622ce863a6610d58e3e5b5f1bae413","tree":"1782fe2e236f85c58cf9b786a7737b5e7974ad71b960bfeaf4240bc528fec665","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"a0ad00ea114be1368fbce2b72ca2f638b904795e73124adb8bd25ae30458933e","short_id":"a0ad00ea"},{"time":"2026-10-05T02:30:00Z","parent":"fa1d764f43f6190cf22b9a763d8cc972d7dc3bb01aaf4f1074e56dbfc350c5e8","tree":"d74e551770184290eb6224af4d48c4008a5b3b7e7cb8204eb3c85c14354d19df","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"2a9ca46af4806ddc2989b343739647e93f622ce863a6610d58e3e5b5f1bae413","short_id":"2a9ca46a"},{"time":"2026-10-03T02:30:00Z","parent":"bd15d29185bb8d6e805451f5e17315396cf315d27c4ca53b9d31d0798ce9d182","tree":"f1dad16a3035d09aac43fe50021f0d0c50ff022c54b28b5c499cf572c95b5746","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"7c1f837ad939b4f4c376a0ff177862f08d87e4616cbe8e54a60d4a666b804ce7","short_id":"7c1f837a"},{"time":"2026-10-02T02:30:00Z","parent":"23ab590268b600c179d6636df65055810c0def0e99a571cdcb7890c556446cc2","tree":"65f5c632a0d2b90ad809a363562f24e3f66d1c52483a9defd47b266da1af4199","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"bd15d29185bb8d6e805451f5e17315396cf315d27c4ca53b9d31d0798ce9d182","short_id":"bd15d291"},{"time":"2026-10-01T02:30:00Z","parent":"8e604e28a0930828c9080477856be09c1475c467ac41f6ded7e2da5bdb3571ac","tree":"bcd5f11e44998ee9e52c5b89ea0a4867e06475bc90b5cb4267364ab6146c9d01","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"23ab590268b600c179d6636df65055810c0def0e99a571cdcb7890c556446cc2","short_id":"23ab5902"},{"time":"2026-09-29T02:30:00Z","parent":"f062f3c51cde5c848398daa1b47cd122d76a0639c76f9436983ae2657895f352","tree":"b99010471bc3056f04c0a8dd25fa412b4834f977d1a7600c03b03b1bb8a9d8fe","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"cb87227f0c1c6acf4999c4b2024b589203cb184ce089a01a2db472ddbb560380","short_id":"cb87227f"},{"time":"2026-09-28T02:30:00Z","parent":"e24109dd53394e0bd7278f7b5e3fffa90f685bfdcd0a93952cff5638967a13fe","tree":"7c0a07c56348b0fa19b9507bf17dada815bdf81517a714408db21e288fc554b3","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"f062f3c51cde5c848398daa1b47cd122d76a0639c76f9436983ae2657895f352","short_id":"f062f3c5"},{"time":"2026-09-26T02:30:00Z","parent":"d4562f249a7d2962d749dbaf843d8ac71b9c8ebb0c0b7cec09afcd8711529eea","tree":"36c5d5c1356cef66b9017f1411f798274554b52a7b01a8b4127ef1c30c6a02f6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"b26700ff3e9871ac081886d146fc30b9d8e7bd4572cea0b62f8f0261ea1a4f9d","short_id":"b26700ff"},{"time":"2026-09-25T02:30:00Z","parent":"0b0bc0701cee5d7533d4a97f4c9ef7f5a401eb552d2ca3536a1ed5cebeb83f97","tree":"c6508fdf7a64e55c2058145ba81f1b27e8687b8b2b2a4bd7324a157ef31ad12a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"d4562f249a7d2962d749dbaf843d8ac71b9c8ebb0c0b7cec09afcd8711529eea","short_id":"d4562f24"},{"time":"2026-09-24T02:30:00Z","parent":"0c73460e3fa99b3c38ef31c378515f2424f18877bd354994d053576aa58ec214","tree":"530b2ba5c60bab9cc6f56148cf6388dff62236a252592031c10df1e2dd2607d6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"0b0bc0701cee5d7533d4a97f4c9ef7f5a401eb552d2ca3536a1ed5cebeb83f97","short_id":"0b0bc070"},{"time":"2026-09-23T02:30:00Z","parent":"5e41a7b17484c04288c67cce0dbf9cb3046325a9617b27f33d128ea5e906eebe","tree":"1092cccb0c44787eb64ea2ea143189a5bf5d093ebfa0427d0cb07ac47543bcf4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"0c73460e3fa99b3c38ef31c378515f2424f18877bd354994d053576aa58ec214","short_id":"0c73460e"},{"time":"2026-09-22T02:30:00Z","parent":"8f870fe269857d1d611fff5e03d2b22533bce7dc5aad4340de6cdf434b5aa0ae","tree":"31fbee51dde5e56f1d5940902bf8428ee4a1a2825a6081dea2b3ffb60a66ca26","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"5e41a7b17484c04288c67cce0dbf9cb3046325a9617b27f33d128ea5e906eebe","short_id":"5e41a7b1"},{"time":"2026-09-21T02:30:00Z","parent":"ec0f30baecf767c3a02ec631814236071014258f0287f3044b591a34d5a99d73","tree":"c1ddfe015a6300456c24a6561c1a1f247f255254834aac61435ceef06456e806","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8f870fe269857d1d611fff5e03d2b22533bce7dc5aad4340de6cdf434b5aa0ae","short_id":"8f870fe2"},{"time":"2026-09-20T02:30:00Z","parent":"0c97b2f8a266b152761dd1769c0898bc78a367c859ca8013edec68bfc61aa0d4","tree":"f61ebed68d2e86ca59dc4e4223535a3aa8198562b2cecb812b52d3ba9e5411e7","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"ec0f30baecf767c3a02ec631814236071014258f0287f3044b591a34d5a99d73","short_id":"ec0f30ba"},{"time":"2026-09-19T02:30:00Z","parent":"dc383edfe97cc655252f1ad872386b2fefeecc0b3e170e7a04d8683225214951","tree":"2ca8aade0fdfc72248d246771ee003972eaad397aa613f78dea4b2ba6d1a0287","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"0c97b2f8a266b152761dd1769c0898bc78a367c859ca8013edec68bfc61aa0d4","short_id":"0c97b2f8"},{"time":"2026-09-18T02:30:00Z","parent":"ee89b04f40a213571e3a100a01c666b02566dde4ea56e902b11df9a2c3f13a09","tree":"862bd61ed170b4a5e0ec0fa971bf16a2fd295b5b0ca5ca8b5573d5d96bf46d0b","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"dc383edfe97cc655252f1ad872386b2fefeecc0b3e170e7a04d8683225214951","short_id":"dc383edf"},{"time":"2026-09-17T02:30:00Z","parent":"f0a0d4eb6dda96f6db6099dff7156458aed506eeadca78859ad9657068e44501","tree":"92ac0d05e95224172f35772f54eb47981154feb9e6e58a4f03c3b273eea3dd1d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"ee89b04f40a213571e3a100a01c666b02566dde4ea56e902b11df9a2c3f13a09","short_id":"ee89b04f"},{"time":"2026-09-16T02:30:00Z","parent":"bf5abbdc483043f91fefdde6e97249ee81610adca5195440770fea3ec9c014f1","tree":"55007688ced33784bc5785e3dc9546f472cbeda9d545f9327aca913631586c3a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"f0a0d4eb6dda96f6db6099dff7156458aed506eeadca78859ad9657068e44501","short_id":"f0a0d4eb"},{"time":"2026-09-15T02:30:00Z","parent":"2f18a0cd5a226f2d04d075853265761756f6228499c1d8d6d08694c49bb3c2b7","tree":"1352369b945c41e97bbd11d3ca0f0ed4885046ce3e51e3762b4986b0c9b04ca0","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"bf5abbdc483043f91fefdde6e97249ee81610adca5195440770fea3ec9c014f1","short_id":"bf5abbdc"},{"time":"2026-09-14T02:30:00Z","parent":"8a336152be88a2f4123b281a9fd1da34c195eb44363f08e988cf2f35645a2b66","tree":"56004cc3737e424b403621b63b8cbc4e71c0ae86a326c30fe3a627a1c572d963","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"2f18a0cd5a226f2d04d075853265761756f6228499c1d8d6d08694c49bb3c2b7","short_id":"2f18a0cd"},{"time":"2026-09-13T02:30:00Z","parent":"670ca41966dd9493c733a7160c867d8c5024128d6d3f804142ce873089d56d1c","tree":"ee30f31481f47e63795e88c27f2cc603d60ea9ad9dd53fb60417ca48b93c48c8","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8a336152be88a2f4123b281a9fd1da34c195eb44363f08e988cf2f35645a2b66","short_id":"8a336152"},{"time":"2026-09-12T02:30:00Z","parent":"f22a8b07c06ae226ae53db79d52c977c9f01b5708cc2d24a47e1171ce05f34a7","tree":"422cd3972d9092ce5082e72b49d1df597a80f88de2085e6ae6a40b676bb97601","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"670ca41966dd9493c733a7160c867d8c5024128d6d3f804142ce873089d56d1c","short_id":"670ca419"},{"time":"2026-09-11T02:30:00Z","parent":"7b08e08836fa06d1a6cf125cf8e7f5f5bca1358421ff7386a9d1a3b204e0aeb6","tree":"45dace70a50297723fc9ab12d5215e2892adb5e15338f093495913aa9c674a45","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"f22a8b07c06ae226ae53db79d52c977c9f01b5708cc2d24a47e1171ce05f34a7","short_id":"f22a8b07"},{"time":"2026-09-10T02:30:00Z","parent":"c25662ce1a2597f3468e93251a04d35419b912c26907724b89c197edb79b69c9","tree":"3e9374ab1878e6aad827032c581f50b02296f436c71afc9db1080bc28c53db1a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"7b08e08836fa06d1a6cf125cf8e7f5f5bca1358421ff7386a9d1a3b204e0aeb6","short_id":"7b08e088"},{"time":"2026-09-09T02:30:00Z","parent":"3f9ff630cd8c4830ccd24976f24065aa17e84e24a04876cda02310a9d845a554","tree":"fb772e958ecbf3b778ef2b838a4937dab663d80ae6ffa571453dcf0d375d70b7","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"c25662ce1a2597f3468e93251a04d35419b912c26907724b89c197edb79b69c9","short_id":"c25662ce"},{"time":"2026-09-08T02:30:00Z","parent":"96824fce2d56c812475efc60585f0a3fe7988874ec48ecf7a55946feb3e14c0d","tree":"dd6a4ba2b1bd03d58f08b20df5ce546db43a0bdc69c88430c4f835773f75645d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"3f9ff630cd8c4830ccd24976f24065aa17e84e24a04876cda02310a9d845a554","short_id":"3f9ff630"},{"time":"2026-09-07T02:30:00Z","parent":"b49faa0a4d3e92a36922c154ede633f1ff9080fea23770cfe9547316803701e3","tree":"46653667b9ba1ba3646c2af1471791b09b03a936d8a8a8f247f09a8731db42d2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"96824fce2d56c812475efc60585f0a3fe7988874ec48ecf7a55946feb3e14c0d","short_id":"96824fce"}],"reasons":[{"snapshot":{"time":"2026-10-16T02:30:00Z","parent":"ee8432e0cd7bb4113731adc2e76d492238b539c3d6ce24a408670fee40579e57","tree":"024c36c1f532ac9150f9768ed57bb27cb284f8949f51958804dfd0f11ee70b65","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"315ff629674caa42ace8498b9d4bb82e5a77cb2284e628560444e12d9072ec8f","short_id":"315ff629"},"matches":["daily snapshot","weekly snapshot","monthly snapshot"]},{"snapshot":{"time":"2026-10-15T02:30:00Z","parent":"2b09f89771cf2744dde14e804ed9e7342871c8a6c1cb4849b8128f5d2571342f","tree":"8f361f971daac52f40180aa7fd3e4638e4ef90903699241b16954ee17fa304e6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"ee8432e0cd7bb4113731adc2e76d492238b539c3d6ce24a408670fee40579e57","short_id":"ee8432e0"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-14T02:30:00Z","parent":"e3fc65e0827c6939f7d86880e75facf36c2692f9cd259fe880232ee7de2a5391","tree":"377caf3fbe1e17b4af93cc053064cde6b40976809805fcdebb0645e41b649ffb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"2b09f89771cf2744dde14e804ed9e7342871c8a6c1cb4849b8128f5d2571342f","short_id":"2b09f897"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-13T02:30:00Z","parent":"4a611990c2123e859808a8546af22c372308a27a87b335aeeb89276e97049165","tree":"279178ad0293ba5157fdd209ec244a1d4899b58e1b9459c11ecac057cac60ff4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"e3fc65e0827c6939f7d86880e75facf36c2692f9cd259fe880232ee7de2a5391","short_id":"e3fc65e0"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-12T02:30:00Z","parent":"8ff9e57a4c7e509cd5e49202f3617630771e0d839ad04911b8106b8b7c4207af","tree":"879f6a9563bba4bcdebbea7f32c27b9e452615464c6dc3111c2df59cd661a8a1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"4a611990c2123e859808a8546af22c372308a27a87b335aeeb89276e97049165","short_id":"4a611990"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-11T02:30:00Z","parent":"5e76f560c4d54a477fce35b1a96ce61374291dc8fa52b6dfb76fde6d91f25bdb","tree":"afe3b0d5eaf569af22f299df9b77ccd8166b7c654c0e886b7452bb10512d0706","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8ff9e57a4c7e509cd5e49202f3617630771e0d839ad04911b8106b8b7c4207af","short_id":"8ff9e57a"},"matches":["daily snapshot","weekly snapshot"]},{"snapshot":{"time":"2026-10-10T02:30:00Z","parent":"29607a0ab3c4afc1d63525a96605bb44e0b5f4de690d1ed44bfd3bbc27025fa2","tree":"357713e3a55168ec6bea559274dc7552b4fbd64381ce4bde9022e242ec328ad1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"5e76f560c4d54a477fce35b1a96ce61374291dc8fa52b6dfb76fde6d91f25bdb","short_id":"5e76f560"},"matches":["daily snapshot"]},{"snapshot":{"time":"2026-10-04T02:30:00Z","parent":"7c1f837ad939b4f4c376a0ff177862f08d87e4616cbe8e54a60d4a666b804ce7","tree":"a5e934915e68d97267ee3b108c7ee16ea0867e651b9232443fe919d83fa3a4c2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"fa1d764f43f6190cf22b9a763d8cc972d7dc3bb01aaf4f1074e56dbfc350c5e8","short_id":"fa1d764f"},"matches":["weekly snapshot"]},{"snapshot":{"time":"2026-09-30T02:30:00Z","parent":"cb87227f0c1c6acf4999c4b2024b589203cb184ce089a01a2db472ddbb560380","tree":"b778b7edf7fa14307405e72c16f20050fc813cf944bda6b445d209db77e4bc00","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"8e604e28a0930828c9080477856be09c1475c467ac41f6ded7e2da5bdb3571ac","short_id":"8e604e28"},"matches":["monthly snapshot"]},{"snapshot":{"time":"2026-09-27T02:30:00Z","parent":"b26700ff3e9871ac081886d146fc30b9d8e7bd4572cea0b62f8f0261ea1a4f9d","tree":"21aa00a24cb6990028d074e46a5af0457b5bc87da6867d0857663f776247b8cc","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"e24109dd53394e0bd7278f7b5e3fffa90f685bfdcd0a93952cff5638967a13fe","short_id":"e24109dd"},"matches":["weekly snapshot"]},{"snapshot":{"time":"2026-09-06T02:30:00Z","tree":"ce672340389400ef8f5094e689dff293adf1f0d532d6e9f811b693a112a01933","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["b","felhom-offbox"],"id":"b49faa0a4d3e92a36922c154ede633f1ff9080fea23770cfe9547316803701e3","short_id":"b49faa0a"},"matches":["oldest monthly snapshot"]}]}] diff --git a/controller/internal/backup/testdata/restic/0.19.1/init-exists.txt b/controller/internal/backup/testdata/restic/0.19.1/init-exists.txt new file mode 100644 index 0000000..a354d2f --- /dev/null +++ b/controller/internal/backup/testdata/restic/0.19.1/init-exists.txt @@ -0,0 +1 @@ +Fatal: Fatal: create repository at /data/x/repo failed: config file already exists diff --git a/controller/internal/backup/testdata/restic/0.19.1/locked-exclusive.txt b/controller/internal/backup/testdata/restic/0.19.1/locked-exclusive.txt new file mode 100644 index 0000000..947fe21 --- /dev/null +++ b/controller/internal/backup/testdata/restic/0.19.1/locked-exclusive.txt @@ -0,0 +1,5 @@ +repo already locked, waiting up to 0s for the lock +unable to create lock in backend: repository is already locked exclusively by PID 3694515 on other-box by root (UID 0, GID 0) +lock was created at 2026-10-16 20:03:13 (1.104257918s ago) +storage ID 781ffba8 +the `unlock` command can be used to remove stale locks diff --git a/controller/internal/backup/testdata/restic/0.19.1/locked-shared.txt b/controller/internal/backup/testdata/restic/0.19.1/locked-shared.txt new file mode 100644 index 0000000..8a4bd21 --- /dev/null +++ b/controller/internal/backup/testdata/restic/0.19.1/locked-shared.txt @@ -0,0 +1,5 @@ +repo already locked, waiting up to 0s for the lock +unable to create lock in backend: repository is already locked by PID 3693859 on other-box by root (UID 0, GID 0) +lock was created at 2026-10-16 20:03:12 (1.095585673s ago) +storage ID 03a00a80 +the `unlock` command can be used to remove stale locks diff --git a/controller/internal/backup/testdata/restic/0.19.1/no-repo.txt b/controller/internal/backup/testdata/restic/0.19.1/no-repo.txt new file mode 100644 index 0000000..04e9b52 --- /dev/null +++ b/controller/internal/backup/testdata/restic/0.19.1/no-repo.txt @@ -0,0 +1,3 @@ +Fatal: repository does not exist: unable to open config file: stat /data/x/nothing-here/config: no such file or directory +Is there a repository at the following location? +/data/x/nothing-here diff --git a/controller/internal/backup/testdata/restic/0.19.1/rclone-dead-ssh.txt b/controller/internal/backup/testdata/restic/0.19.1/rclone-dead-ssh.txt new file mode 100644 index 0000000..c54d213 --- /dev/null +++ b/controller/internal/backup/testdata/restic/0.19.1/rclone-dead-ssh.txt @@ -0,0 +1,2 @@ +rclone: ssh: connect to host 127.0.0.1 port 1: Connection refused +Fatal: unable to open repository at rclone:x: error talking HTTP to rclone: exit status 255 diff --git a/controller/internal/backup/testdata/restic/0.19.1/sftp-refused-key.txt b/controller/internal/backup/testdata/restic/0.19.1/sftp-refused-key.txt new file mode 100644 index 0000000..af0b1fa --- /dev/null +++ b/controller/internal/backup/testdata/restic/0.19.1/sftp-refused-key.txt @@ -0,0 +1,2 @@ +subprocess ssh: u@127.0.0.1: Permission denied (publickey,password). +Fatal: unable to open repository at sftp:u@127.0.0.1:/x: unable to start the sftp session, error: error receiving version packet from server: server unexpectedly closed connection: unexpected EOF diff --git a/controller/internal/backup/testdata/restic/0.19.1/sftp-refused-port.txt b/controller/internal/backup/testdata/restic/0.19.1/sftp-refused-port.txt new file mode 100644 index 0000000..639a9dc --- /dev/null +++ b/controller/internal/backup/testdata/restic/0.19.1/sftp-refused-port.txt @@ -0,0 +1,2 @@ +subprocess ssh: ssh: connect to host 127.0.0.1 port 1: Connection refused +Fatal: unable to open repository at sftp:u@127.0.0.1:/x: unable to start the sftp session, error: error receiving version packet from server: server unexpectedly closed connection: unexpected EOF diff --git a/controller/internal/backup/testdata/restic/0.19.1/sftp-unreachable.txt b/controller/internal/backup/testdata/restic/0.19.1/sftp-unreachable.txt new file mode 100644 index 0000000..7c35a6c --- /dev/null +++ b/controller/internal/backup/testdata/restic/0.19.1/sftp-unreachable.txt @@ -0,0 +1,2 @@ +subprocess ssh: ssh: connect to host 10.255.255.1 port 22: Connection timed out +Fatal: unable to open repository at sftp:u@10.255.255.1:/x: unable to start the sftp session, error: error receiving version packet from server: server unexpectedly closed connection: unexpected EOF diff --git a/controller/internal/backup/testdata/restic/0.19.1/snapshots-latest-tag.json b/controller/internal/backup/testdata/restic/0.19.1/snapshots-latest-tag.json new file mode 100644 index 0000000..e4e32d2 --- /dev/null +++ b/controller/internal/backup/testdata/restic/0.19.1/snapshots-latest-tag.json @@ -0,0 +1 @@ +[{"time":"2026-10-16T02:30:00Z","parent":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","tree":"b830b8165dc45c4b23086a81004548a5a52a00060028f0d274d8098dcc168b49","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"94fc37b9bfe97271d4a0b0feda4443a5e2934a3557108dd521d0bfb2f49423c8","short_id":"94fc37b9"}] diff --git a/controller/internal/backup/testdata/restic/0.19.1/snapshots.json b/controller/internal/backup/testdata/restic/0.19.1/snapshots.json new file mode 100644 index 0000000..a262f4d --- /dev/null +++ b/controller/internal/backup/testdata/restic/0.19.1/snapshots.json @@ -0,0 +1 @@ +[{"time":"2026-09-06T02:30:00Z","tree":"ce672340389400ef8f5094e689dff293adf1f0d532d6e9f811b693a112a01933","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"b49faa0a4d3e92a36922c154ede633f1ff9080fea23770cfe9547316803701e3","short_id":"b49faa0a"},{"time":"2026-09-06T02:30:00Z","tree":"f685956bf88ee15d577e60f77a8ce561abdb2dd56eb1d00b26d5c59276add7a6","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"2a76397eb8a43be8c70dd687ab03fcd939f2f058f815804b9fa2e0f5d9d32376","short_id":"2a76397e"},{"time":"2026-09-07T02:30:00Z","parent":"2a76397eb8a43be8c70dd687ab03fcd939f2f058f815804b9fa2e0f5d9d32376","tree":"70b21a93a7e8af3804e813d7d47cb5d936ebfff4ebf1b8b80a9834382142aee5","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"820d553d84f1c920803a156ffea356c7aacf469e7555f07ea8b9408d2021f254","short_id":"820d553d"},{"time":"2026-09-07T02:30:00Z","parent":"b49faa0a4d3e92a36922c154ede633f1ff9080fea23770cfe9547316803701e3","tree":"46653667b9ba1ba3646c2af1471791b09b03a936d8a8a8f247f09a8731db42d2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"96824fce2d56c812475efc60585f0a3fe7988874ec48ecf7a55946feb3e14c0d","short_id":"96824fce"},{"time":"2026-09-08T02:30:00Z","parent":"96824fce2d56c812475efc60585f0a3fe7988874ec48ecf7a55946feb3e14c0d","tree":"dd6a4ba2b1bd03d58f08b20df5ce546db43a0bdc69c88430c4f835773f75645d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"3f9ff630cd8c4830ccd24976f24065aa17e84e24a04876cda02310a9d845a554","short_id":"3f9ff630"},{"time":"2026-09-08T02:30:00Z","parent":"820d553d84f1c920803a156ffea356c7aacf469e7555f07ea8b9408d2021f254","tree":"f725d2ffc7382c23554b85a5381905f02a11b09d307c24cd20980bcb30dce47b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"1242b68c1b172bc4ae762fe874cd6dd8863ce3ae03961f5175c35fa26475d385","short_id":"1242b68c"},{"time":"2026-09-09T02:30:00Z","parent":"3f9ff630cd8c4830ccd24976f24065aa17e84e24a04876cda02310a9d845a554","tree":"fb772e958ecbf3b778ef2b838a4937dab663d80ae6ffa571453dcf0d375d70b7","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"c25662ce1a2597f3468e93251a04d35419b912c26907724b89c197edb79b69c9","short_id":"c25662ce"},{"time":"2026-09-09T02:30:00Z","parent":"1242b68c1b172bc4ae762fe874cd6dd8863ce3ae03961f5175c35fa26475d385","tree":"2bfaf9b4b8dabb68a2824ce5f48d27fda4ea94c2a960718bd84cabd59be13acf","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"d1c1d0c71c88d2f829b267adfdafbc1b19fdf184de6cdf1de28703cf46b40d65","short_id":"d1c1d0c7"},{"time":"2026-09-10T02:30:00Z","parent":"c25662ce1a2597f3468e93251a04d35419b912c26907724b89c197edb79b69c9","tree":"3e9374ab1878e6aad827032c581f50b02296f436c71afc9db1080bc28c53db1a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"7b08e08836fa06d1a6cf125cf8e7f5f5bca1358421ff7386a9d1a3b204e0aeb6","short_id":"7b08e088"},{"time":"2026-09-10T02:30:00Z","parent":"d1c1d0c71c88d2f829b267adfdafbc1b19fdf184de6cdf1de28703cf46b40d65","tree":"ed7361b730a863510df1e3b9f7d25b810902e8e86e0e230632250186cc558b21","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"e4b8322da1d838315d2dd62509678d7b419924a0d7c4723062aa31140a417ac0","short_id":"e4b8322d"},{"time":"2026-09-11T02:30:00Z","parent":"e4b8322da1d838315d2dd62509678d7b419924a0d7c4723062aa31140a417ac0","tree":"9b79e87705df56afe04f10b8a5e15cb8cc4abed0585815e54282b77cacd3eae6","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"8c127f74318a1ff657ebc803b1fda7fae31ff1e2e3e145c9bd137d04f9de9d92","short_id":"8c127f74"},{"time":"2026-09-11T02:30:00Z","parent":"7b08e08836fa06d1a6cf125cf8e7f5f5bca1358421ff7386a9d1a3b204e0aeb6","tree":"45dace70a50297723fc9ab12d5215e2892adb5e15338f093495913aa9c674a45","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"f22a8b07c06ae226ae53db79d52c977c9f01b5708cc2d24a47e1171ce05f34a7","short_id":"f22a8b07"},{"time":"2026-09-12T02:30:00Z","parent":"8c127f74318a1ff657ebc803b1fda7fae31ff1e2e3e145c9bd137d04f9de9d92","tree":"57c13238258e80cccb13e8d4dac05a82f9c3da4ac3dc6a26e9b8f4736e478af1","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"9224b1af26c1c1fe31395055f22158bf09cc541f4b59a59caf91b71f92bc63f1","short_id":"9224b1af"},{"time":"2026-09-12T02:30:00Z","parent":"f22a8b07c06ae226ae53db79d52c977c9f01b5708cc2d24a47e1171ce05f34a7","tree":"422cd3972d9092ce5082e72b49d1df597a80f88de2085e6ae6a40b676bb97601","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"670ca41966dd9493c733a7160c867d8c5024128d6d3f804142ce873089d56d1c","short_id":"670ca419"},{"time":"2026-09-13T02:30:00Z","parent":"9224b1af26c1c1fe31395055f22158bf09cc541f4b59a59caf91b71f92bc63f1","tree":"a5b546be122e577d101aaa067994bae404a881925573c09a2576431b51bb3e82","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"d6678aa268695bc4387fe3a857f3304013c2bd672dc1234cf2161343bf18efdc","short_id":"d6678aa2"},{"time":"2026-09-13T02:30:00Z","parent":"670ca41966dd9493c733a7160c867d8c5024128d6d3f804142ce873089d56d1c","tree":"ee30f31481f47e63795e88c27f2cc603d60ea9ad9dd53fb60417ca48b93c48c8","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"8a336152be88a2f4123b281a9fd1da34c195eb44363f08e988cf2f35645a2b66","short_id":"8a336152"},{"time":"2026-09-14T02:30:00Z","parent":"d6678aa268695bc4387fe3a857f3304013c2bd672dc1234cf2161343bf18efdc","tree":"fdc02ae7cab64e7ab641be509365b4b8201eaf3c6dddf7191ba01bbcd750d3ea","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"a74319ea5b78b3276b0aa7407b39f95e44c0676915ce815a979383d2afbc6e23","short_id":"a74319ea"},{"time":"2026-09-14T02:30:00Z","parent":"8a336152be88a2f4123b281a9fd1da34c195eb44363f08e988cf2f35645a2b66","tree":"56004cc3737e424b403621b63b8cbc4e71c0ae86a326c30fe3a627a1c572d963","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"2f18a0cd5a226f2d04d075853265761756f6228499c1d8d6d08694c49bb3c2b7","short_id":"2f18a0cd"},{"time":"2026-09-15T02:30:00Z","parent":"2f18a0cd5a226f2d04d075853265761756f6228499c1d8d6d08694c49bb3c2b7","tree":"1352369b945c41e97bbd11d3ca0f0ed4885046ce3e51e3762b4986b0c9b04ca0","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"bf5abbdc483043f91fefdde6e97249ee81610adca5195440770fea3ec9c014f1","short_id":"bf5abbdc"},{"time":"2026-09-15T02:30:00Z","parent":"a74319ea5b78b3276b0aa7407b39f95e44c0676915ce815a979383d2afbc6e23","tree":"be3be59ec618cf36d26d6d3e8368b560ce88c60b6eda56e861c6f5146f667be2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"0c24dfcc62048ac0b64dd13aad000479b47ceddfd2963119e631c488714f8cc3","short_id":"0c24dfcc"},{"time":"2026-09-16T02:30:00Z","parent":"0c24dfcc62048ac0b64dd13aad000479b47ceddfd2963119e631c488714f8cc3","tree":"39e7b89853eb47ec19c07a060be51173dd800a2d46417ae0201fefa3af33d90a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"e0ec672a95aacf51c562acf57701aba0e725a1d811ce3a6f5c2ebad549a8c016","short_id":"e0ec672a"},{"time":"2026-09-16T02:30:00Z","parent":"bf5abbdc483043f91fefdde6e97249ee81610adca5195440770fea3ec9c014f1","tree":"55007688ced33784bc5785e3dc9546f472cbeda9d545f9327aca913631586c3a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"f0a0d4eb6dda96f6db6099dff7156458aed506eeadca78859ad9657068e44501","short_id":"f0a0d4eb"},{"time":"2026-09-17T02:30:00Z","parent":"f0a0d4eb6dda96f6db6099dff7156458aed506eeadca78859ad9657068e44501","tree":"92ac0d05e95224172f35772f54eb47981154feb9e6e58a4f03c3b273eea3dd1d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"ee89b04f40a213571e3a100a01c666b02566dde4ea56e902b11df9a2c3f13a09","short_id":"ee89b04f"},{"time":"2026-09-17T02:30:00Z","parent":"e0ec672a95aacf51c562acf57701aba0e725a1d811ce3a6f5c2ebad549a8c016","tree":"a037a5eb6e669bc15c6705f0c4eb665c729eefa37af2a196086ce1701230988e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"a2be8e6be366d62cca9bc6d4e12b1c97a310051e2fa8a077dff1fb07e904000a","short_id":"a2be8e6b"},{"time":"2026-09-18T02:30:00Z","parent":"a2be8e6be366d62cca9bc6d4e12b1c97a310051e2fa8a077dff1fb07e904000a","tree":"251699699303a792c841f497662af163952386fd70b2d6dcfa435bd0d902ace2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"177c6f12c40c9f355adc60d0a875830e78353038462fe15beeb00f3afef04efe","short_id":"177c6f12"},{"time":"2026-09-18T02:30:00Z","parent":"ee89b04f40a213571e3a100a01c666b02566dde4ea56e902b11df9a2c3f13a09","tree":"862bd61ed170b4a5e0ec0fa971bf16a2fd295b5b0ca5ca8b5573d5d96bf46d0b","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"dc383edfe97cc655252f1ad872386b2fefeecc0b3e170e7a04d8683225214951","short_id":"dc383edf"},{"time":"2026-09-19T02:30:00Z","parent":"dc383edfe97cc655252f1ad872386b2fefeecc0b3e170e7a04d8683225214951","tree":"2ca8aade0fdfc72248d246771ee003972eaad397aa613f78dea4b2ba6d1a0287","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"0c97b2f8a266b152761dd1769c0898bc78a367c859ca8013edec68bfc61aa0d4","short_id":"0c97b2f8"},{"time":"2026-09-19T02:30:00Z","parent":"177c6f12c40c9f355adc60d0a875830e78353038462fe15beeb00f3afef04efe","tree":"a97bea5453e2a1a8913ee3965b4fec1632d677dfe0ecf74213efee6f43568e20","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"c2e659092443ccc73500e061690d9f99b0a653e8dcc002f441cd359385045e0e","short_id":"c2e65909"},{"time":"2026-09-20T02:30:00Z","parent":"c2e659092443ccc73500e061690d9f99b0a653e8dcc002f441cd359385045e0e","tree":"4ad27f2ca164c7d23866d5c06e75aa70ad20d8f86229816534ce7adcffb652a7","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"43902ad8c4d345ac41a98af33afc74fd36d2f6896fb45e94fe553ba3f2b51d0f","short_id":"43902ad8"},{"time":"2026-09-20T02:30:00Z","parent":"0c97b2f8a266b152761dd1769c0898bc78a367c859ca8013edec68bfc61aa0d4","tree":"f61ebed68d2e86ca59dc4e4223535a3aa8198562b2cecb812b52d3ba9e5411e7","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"ec0f30baecf767c3a02ec631814236071014258f0287f3044b591a34d5a99d73","short_id":"ec0f30ba"},{"time":"2026-09-21T02:30:00Z","parent":"43902ad8c4d345ac41a98af33afc74fd36d2f6896fb45e94fe553ba3f2b51d0f","tree":"f10d8afc6c36f40a793446537a09092aab457abaddd2f5dd884273014ffd986b","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"ab24192f7a961b8103bdf4c5a3ab7d2a13b949b6accb9d52d1411f49d9d0deea","short_id":"ab24192f"},{"time":"2026-09-21T02:30:00Z","parent":"ec0f30baecf767c3a02ec631814236071014258f0287f3044b591a34d5a99d73","tree":"c1ddfe015a6300456c24a6561c1a1f247f255254834aac61435ceef06456e806","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"8f870fe269857d1d611fff5e03d2b22533bce7dc5aad4340de6cdf434b5aa0ae","short_id":"8f870fe2"},{"time":"2026-09-22T02:30:00Z","parent":"8f870fe269857d1d611fff5e03d2b22533bce7dc5aad4340de6cdf434b5aa0ae","tree":"31fbee51dde5e56f1d5940902bf8428ee4a1a2825a6081dea2b3ffb60a66ca26","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"5e41a7b17484c04288c67cce0dbf9cb3046325a9617b27f33d128ea5e906eebe","short_id":"5e41a7b1"},{"time":"2026-09-22T02:30:00Z","parent":"ab24192f7a961b8103bdf4c5a3ab7d2a13b949b6accb9d52d1411f49d9d0deea","tree":"1e0e3145356cbc6b68674824bdb7b2bc5524ab3fc8cbcb27368f9efb819c0124","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"7b37aba5b0971c1f41c15269fe2157e320b4f6428920d743302e4a904e053f63","short_id":"7b37aba5"},{"time":"2026-09-23T02:30:00Z","parent":"7b37aba5b0971c1f41c15269fe2157e320b4f6428920d743302e4a904e053f63","tree":"eac20fb1f7f17be350f01322cc58152ec05c680ba60706fa5f25db89bab1d264","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"6398aadc912ab1364b0c83f3e3ce51c3099bf74e018ac25107f51dbeed6b3c47","short_id":"6398aadc"},{"time":"2026-09-23T02:30:00Z","parent":"5e41a7b17484c04288c67cce0dbf9cb3046325a9617b27f33d128ea5e906eebe","tree":"1092cccb0c44787eb64ea2ea143189a5bf5d093ebfa0427d0cb07ac47543bcf4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"0c73460e3fa99b3c38ef31c378515f2424f18877bd354994d053576aa58ec214","short_id":"0c73460e"},{"time":"2026-09-24T02:30:00Z","parent":"6398aadc912ab1364b0c83f3e3ce51c3099bf74e018ac25107f51dbeed6b3c47","tree":"29e68a845705a5490fc07891a54fa6ff4d674183f4314f23361fb3d5c43b5057","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"264cbd7c1e22696db518c2b8aba55d9755e2799bab72d54d48f8521ae1740e84","short_id":"264cbd7c"},{"time":"2026-09-24T02:30:00Z","parent":"0c73460e3fa99b3c38ef31c378515f2424f18877bd354994d053576aa58ec214","tree":"530b2ba5c60bab9cc6f56148cf6388dff62236a252592031c10df1e2dd2607d6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"0b0bc0701cee5d7533d4a97f4c9ef7f5a401eb552d2ca3536a1ed5cebeb83f97","short_id":"0b0bc070"},{"time":"2026-09-25T02:30:00Z","parent":"0b0bc0701cee5d7533d4a97f4c9ef7f5a401eb552d2ca3536a1ed5cebeb83f97","tree":"c6508fdf7a64e55c2058145ba81f1b27e8687b8b2b2a4bd7324a157ef31ad12a","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"d4562f249a7d2962d749dbaf843d8ac71b9c8ebb0c0b7cec09afcd8711529eea","short_id":"d4562f24"},{"time":"2026-09-25T02:30:00Z","parent":"264cbd7c1e22696db518c2b8aba55d9755e2799bab72d54d48f8521ae1740e84","tree":"0b332b3757a2111c5c5e1adcb59f011b4ce4716c350fbb289496525a612b27eb","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"ce4afadd45ee5a17b6e8f276704f99478bf5e82cc0870a5b4e6db3e07d64ace8","short_id":"ce4afadd"},{"time":"2026-09-26T02:30:00Z","parent":"ce4afadd45ee5a17b6e8f276704f99478bf5e82cc0870a5b4e6db3e07d64ace8","tree":"8f40b7ed62ec04ce4dd10a648fd97db920711a6f387503bb2a75f535de395656","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"e974e4a5987c5d524f227b4b091811a0488e5fed27cb736d511f009b13b13b1d","short_id":"e974e4a5"},{"time":"2026-09-26T02:30:00Z","parent":"d4562f249a7d2962d749dbaf843d8ac71b9c8ebb0c0b7cec09afcd8711529eea","tree":"36c5d5c1356cef66b9017f1411f798274554b52a7b01a8b4127ef1c30c6a02f6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"b26700ff3e9871ac081886d146fc30b9d8e7bd4572cea0b62f8f0261ea1a4f9d","short_id":"b26700ff"},{"time":"2026-09-27T02:30:00Z","parent":"e974e4a5987c5d524f227b4b091811a0488e5fed27cb736d511f009b13b13b1d","tree":"c5cb9ce2ff06516329a42aec557f7223e1a3c3801c502f7a53f0ab6414cedf15","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"7e67848219703f577e06ce2750b104a8c8f956978b05aafa4a205a3d258eb376","short_id":"7e678482"},{"time":"2026-09-27T02:30:00Z","parent":"b26700ff3e9871ac081886d146fc30b9d8e7bd4572cea0b62f8f0261ea1a4f9d","tree":"21aa00a24cb6990028d074e46a5af0457b5bc87da6867d0857663f776247b8cc","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"e24109dd53394e0bd7278f7b5e3fffa90f685bfdcd0a93952cff5638967a13fe","short_id":"e24109dd"},{"time":"2026-09-28T02:30:00Z","parent":"7e67848219703f577e06ce2750b104a8c8f956978b05aafa4a205a3d258eb376","tree":"e03a49f45c2db8d9342d90626025311ca3592d7d78c6dd6eeb8ffed0848c7ae0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"a695cd17a42947d6a5f1d74db5dc14f508cffbd7f98582124a25c53d47defd21","short_id":"a695cd17"},{"time":"2026-09-28T02:30:00Z","parent":"e24109dd53394e0bd7278f7b5e3fffa90f685bfdcd0a93952cff5638967a13fe","tree":"7c0a07c56348b0fa19b9507bf17dada815bdf81517a714408db21e288fc554b3","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"f062f3c51cde5c848398daa1b47cd122d76a0639c76f9436983ae2657895f352","short_id":"f062f3c5"},{"time":"2026-09-29T02:30:00Z","parent":"f062f3c51cde5c848398daa1b47cd122d76a0639c76f9436983ae2657895f352","tree":"b99010471bc3056f04c0a8dd25fa412b4834f977d1a7600c03b03b1bb8a9d8fe","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"cb87227f0c1c6acf4999c4b2024b589203cb184ce089a01a2db472ddbb560380","short_id":"cb87227f"},{"time":"2026-09-29T02:30:00Z","parent":"a695cd17a42947d6a5f1d74db5dc14f508cffbd7f98582124a25c53d47defd21","tree":"07492d5c8986dadc99631897cd7c4acfe18ec97dd70898d09899d5cd87b9539e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"35e79f2b266136d2be26273e4eabb20005fd5158e59539cd492b0c8e4bbfb2d3","short_id":"35e79f2b"},{"time":"2026-09-30T02:30:00Z","parent":"35e79f2b266136d2be26273e4eabb20005fd5158e59539cd492b0c8e4bbfb2d3","tree":"56b96a8e688ab8190bddb0868d331ece565f8856aef3cdcfef32fc1518e6baf2","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"5ae64e02898e62676cdb3ba4689ed25eb83588a65127d244e69417846e495d78","short_id":"5ae64e02"},{"time":"2026-09-30T02:30:00Z","parent":"cb87227f0c1c6acf4999c4b2024b589203cb184ce089a01a2db472ddbb560380","tree":"b778b7edf7fa14307405e72c16f20050fc813cf944bda6b445d209db77e4bc00","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"8e604e28a0930828c9080477856be09c1475c467ac41f6ded7e2da5bdb3571ac","short_id":"8e604e28"},{"time":"2026-10-01T02:30:00Z","parent":"5ae64e02898e62676cdb3ba4689ed25eb83588a65127d244e69417846e495d78","tree":"b4403fd15f29eced5de4749e59d5b9fe2022030132fe5e9e4d6bb64f83a1cf92","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"bfaf7ca84276c21938171a2d38258647686386fc83df7f24a1b7d67de552202a","short_id":"bfaf7ca8"},{"time":"2026-10-01T02:30:00Z","parent":"8e604e28a0930828c9080477856be09c1475c467ac41f6ded7e2da5bdb3571ac","tree":"bcd5f11e44998ee9e52c5b89ea0a4867e06475bc90b5cb4267364ab6146c9d01","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"23ab590268b600c179d6636df65055810c0def0e99a571cdcb7890c556446cc2","short_id":"23ab5902"},{"time":"2026-10-02T02:30:00Z","parent":"bfaf7ca84276c21938171a2d38258647686386fc83df7f24a1b7d67de552202a","tree":"0fd6c21124d32f9e6a9ee6c3d3a740143c7d90683391082c42bd6cd3bfd0f530","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"cee066c08d1f2f222dd490fa86e4a7931be865004d0aaf50e63f8536d0e232ec","short_id":"cee066c0"},{"time":"2026-10-02T02:30:00Z","parent":"23ab590268b600c179d6636df65055810c0def0e99a571cdcb7890c556446cc2","tree":"65f5c632a0d2b90ad809a363562f24e3f66d1c52483a9defd47b266da1af4199","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"bd15d29185bb8d6e805451f5e17315396cf315d27c4ca53b9d31d0798ce9d182","short_id":"bd15d291"},{"time":"2026-10-03T02:30:00Z","parent":"cee066c08d1f2f222dd490fa86e4a7931be865004d0aaf50e63f8536d0e232ec","tree":"2fdf5cb4f765aeda71371e854f2b73e96ed86e5deb4b54faf6d45ad76756cfb5","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"0e6cad1bee36f6ce4c5d28d756f256bb692a1419cf91e29cc1a856c22d5975e7","short_id":"0e6cad1b"},{"time":"2026-10-03T02:30:00Z","parent":"bd15d29185bb8d6e805451f5e17315396cf315d27c4ca53b9d31d0798ce9d182","tree":"f1dad16a3035d09aac43fe50021f0d0c50ff022c54b28b5c499cf572c95b5746","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"7c1f837ad939b4f4c376a0ff177862f08d87e4616cbe8e54a60d4a666b804ce7","short_id":"7c1f837a"},{"time":"2026-10-04T02:30:00Z","parent":"0e6cad1bee36f6ce4c5d28d756f256bb692a1419cf91e29cc1a856c22d5975e7","tree":"4709d5189f78175060c473debd32bbc95e655c0a6e5ca9792c34b3fd0415de69","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"960d1e720e43e9cb467f170f45277f133494374baa337f93a8af1b973e4b84b3","short_id":"960d1e72"},{"time":"2026-10-04T02:30:00Z","parent":"7c1f837ad939b4f4c376a0ff177862f08d87e4616cbe8e54a60d4a666b804ce7","tree":"a5e934915e68d97267ee3b108c7ee16ea0867e651b9232443fe919d83fa3a4c2","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"fa1d764f43f6190cf22b9a763d8cc972d7dc3bb01aaf4f1074e56dbfc350c5e8","short_id":"fa1d764f"},{"time":"2026-10-05T02:30:00Z","parent":"fa1d764f43f6190cf22b9a763d8cc972d7dc3bb01aaf4f1074e56dbfc350c5e8","tree":"d74e551770184290eb6224af4d48c4008a5b3b7e7cb8204eb3c85c14354d19df","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"2a9ca46af4806ddc2989b343739647e93f622ce863a6610d58e3e5b5f1bae413","short_id":"2a9ca46a"},{"time":"2026-10-05T02:30:00Z","parent":"960d1e720e43e9cb467f170f45277f133494374baa337f93a8af1b973e4b84b3","tree":"8bffed4ff0074c8dbc58f616ddfea18aae6a4bbafb6f3ead72cc2d6fdc7bb7d7","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"d1a3dffd18e46a92ee75c698f7c716727a942ace2efba7ccc2935b6087992908","short_id":"d1a3dffd"},{"time":"2026-10-06T02:30:00Z","parent":"2a9ca46af4806ddc2989b343739647e93f622ce863a6610d58e3e5b5f1bae413","tree":"1782fe2e236f85c58cf9b786a7737b5e7974ad71b960bfeaf4240bc528fec665","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"a0ad00ea114be1368fbce2b72ca2f638b904795e73124adb8bd25ae30458933e","short_id":"a0ad00ea"},{"time":"2026-10-06T02:30:00Z","parent":"d1a3dffd18e46a92ee75c698f7c716727a942ace2efba7ccc2935b6087992908","tree":"978e63c6278adf45029b4c51f773aac5252d334e4d2782f2fac88174fedbb1ff","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"c7aee7b89b42a2539a75e863e0083ae8761ee7ed8826b5a6c3d49820c0e6ba26","short_id":"c7aee7b8"},{"time":"2026-10-07T02:30:00Z","parent":"c7aee7b89b42a2539a75e863e0083ae8761ee7ed8826b5a6c3d49820c0e6ba26","tree":"87bbe7cfd2c5e04fffb43951ae72dbcdc26c2e4eac1be4fa384c26238139d7f3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"2d383c39077530c4a9f98ba8dc20f014e210854d2c4f32f79b335a19388b1e89","short_id":"2d383c39"},{"time":"2026-10-07T02:30:00Z","parent":"a0ad00ea114be1368fbce2b72ca2f638b904795e73124adb8bd25ae30458933e","tree":"a360e27e1aef84a6eacdf3dba92ab0a46a3628869c2af12d3c1b412863b0535d","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"a818ad6aa46ec61c586a0ffb38e63148a69c7bbc08fd0a09acb6734278fbd63b","short_id":"a818ad6a"},{"time":"2026-10-08T02:30:00Z","parent":"2d383c39077530c4a9f98ba8dc20f014e210854d2c4f32f79b335a19388b1e89","tree":"f44bda5e625b1e7636d14efb44c79f9451ef71475b38751bd2c962d04f86ebd4","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"c27b0d1dabe2d975d297daad5b01ad678fb4c88e2d1e6e6ed5f2cf4aa21c5410","short_id":"c27b0d1d"},{"time":"2026-10-08T02:30:00Z","parent":"a818ad6aa46ec61c586a0ffb38e63148a69c7bbc08fd0a09acb6734278fbd63b","tree":"4caaed0b8ce301dc03a64b5fe8e441a3bf6cb9297bf96ad72d62c3b45525ef01","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"ec2a30d9ff60c7473067c0f6b620948f728174c7a5bb8eddfa238f0d8af5066f","short_id":"ec2a30d9"},{"time":"2026-10-09T02:30:00Z","parent":"c27b0d1dabe2d975d297daad5b01ad678fb4c88e2d1e6e6ed5f2cf4aa21c5410","tree":"0ffe8da4512fd658f56dc4ee240488b5d63ae4c07f742810846df3044a365f5a","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"13ecd2eeb9d433ae4be796a9dd9e289b7f12aa55b807cbca1ac6d88b6033accd","short_id":"13ecd2ee"},{"time":"2026-10-09T02:30:00Z","parent":"ec2a30d9ff60c7473067c0f6b620948f728174c7a5bb8eddfa238f0d8af5066f","tree":"2e07df0532a24fe466f5fe8415b3c4e7a208d130974b1543591f7d5e42be04ba","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"29607a0ab3c4afc1d63525a96605bb44e0b5f4de690d1ed44bfd3bbc27025fa2","short_id":"29607a0a"},{"time":"2026-10-10T02:30:00Z","parent":"29607a0ab3c4afc1d63525a96605bb44e0b5f4de690d1ed44bfd3bbc27025fa2","tree":"357713e3a55168ec6bea559274dc7552b4fbd64381ce4bde9022e242ec328ad1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"5e76f560c4d54a477fce35b1a96ce61374291dc8fa52b6dfb76fde6d91f25bdb","short_id":"5e76f560"},{"time":"2026-10-10T02:30:00Z","parent":"13ecd2eeb9d433ae4be796a9dd9e289b7f12aa55b807cbca1ac6d88b6033accd","tree":"0ad2f65dd3de6f7fe4f32210cc07fae810683c769591e3122e9c12acd64a4281","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"cd0707729940a95ae60e9297780e370798d6ed750dc711dc6c34c80c82a6f105","short_id":"cd070772"},{"time":"2026-10-11T02:30:00Z","parent":"cd0707729940a95ae60e9297780e370798d6ed750dc711dc6c34c80c82a6f105","tree":"e408a9e30f5cb44933c7faaec25373d0874bc7e9447bf28ceda6fff612611d92","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"23ae66812d30a5ba39d9ec618c3e3dd453a2883da4d07e7c39438168388069d9","short_id":"23ae6681"},{"time":"2026-10-11T02:30:00Z","parent":"5e76f560c4d54a477fce35b1a96ce61374291dc8fa52b6dfb76fde6d91f25bdb","tree":"afe3b0d5eaf569af22f299df9b77ccd8166b7c654c0e886b7452bb10512d0706","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"8ff9e57a4c7e509cd5e49202f3617630771e0d839ad04911b8106b8b7c4207af","short_id":"8ff9e57a"},{"time":"2026-10-12T02:30:00Z","parent":"8ff9e57a4c7e509cd5e49202f3617630771e0d839ad04911b8106b8b7c4207af","tree":"879f6a9563bba4bcdebbea7f32c27b9e452615464c6dc3111c2df59cd661a8a1","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"4a611990c2123e859808a8546af22c372308a27a87b335aeeb89276e97049165","short_id":"4a611990"},{"time":"2026-10-12T02:30:00Z","parent":"23ae66812d30a5ba39d9ec618c3e3dd453a2883da4d07e7c39438168388069d9","tree":"b721e2ac4dcc985dd24b608acb6b5243dad979038229a6a5b8e501cc2d7bad8e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"26da1569ccbbd96c81a266beef45c84e5a4b6dc870f44a41a89c437ebb09c09f","short_id":"26da1569"},{"time":"2026-10-13T02:30:00Z","parent":"26da1569ccbbd96c81a266beef45c84e5a4b6dc870f44a41a89c437ebb09c09f","tree":"3c0228aa205d8a36c5b4fe501ba5e50d638e219cf2cd4aef45f77e0ba9fc5bb0","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"5339cf6d7ec710b3998e7bf52a09a17cbb5907d2c09ccf18ace19f525b812ae8","short_id":"5339cf6d"},{"time":"2026-10-13T02:30:00Z","parent":"4a611990c2123e859808a8546af22c372308a27a87b335aeeb89276e97049165","tree":"279178ad0293ba5157fdd209ec244a1d4899b58e1b9459c11ecac057cac60ff4","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"e3fc65e0827c6939f7d86880e75facf36c2692f9cd259fe880232ee7de2a5391","short_id":"e3fc65e0"},{"time":"2026-10-14T02:30:00Z","parent":"5339cf6d7ec710b3998e7bf52a09a17cbb5907d2c09ccf18ace19f525b812ae8","tree":"57ab0a0f2ea360c1fbdfbc3b700e0225fb347eb8e715750283bb4b46e1133bf3","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"47bbaa059c6e306c801b5f793e5f3500d1a0c258c3075855aa160276b4a0c704","short_id":"47bbaa05"},{"time":"2026-10-14T02:30:00Z","parent":"e3fc65e0827c6939f7d86880e75facf36c2692f9cd259fe880232ee7de2a5391","tree":"377caf3fbe1e17b4af93cc053064cde6b40976809805fcdebb0645e41b649ffb","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"2b09f89771cf2744dde14e804ed9e7342871c8a6c1cb4849b8128f5d2571342f","short_id":"2b09f897"},{"time":"2026-10-15T02:30:00Z","parent":"47bbaa059c6e306c801b5f793e5f3500d1a0c258c3075855aa160276b4a0c704","tree":"a0dd167d57e68ce11fde606350779191cdc8c4413875240091be5880fb91c66e","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","short_id":"27898187"},{"time":"2026-10-15T02:30:00Z","parent":"2b09f89771cf2744dde14e804ed9e7342871c8a6c1cb4849b8128f5d2571342f","tree":"8f361f971daac52f40180aa7fd3e4638e4ef90903699241b16954ee17fa304e6","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"ee8432e0cd7bb4113731adc2e76d492238b539c3d6ce24a408670fee40579e57","short_id":"ee8432e0"},{"time":"2026-10-16T02:30:00Z","parent":"27898187d9337190afb6154237f44817ccf2070d6be912c86af3c1ef55ed8e3d","tree":"b830b8165dc45c4b23086a81004548a5a52a00060028f0d274d8098dcc168b49","paths":["/data/x/u/a"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","a"],"id":"94fc37b9bfe97271d4a0b0feda4443a5e2934a3557108dd521d0bfb2f49423c8","short_id":"94fc37b9"},{"time":"2026-10-16T02:30:00Z","parent":"ee8432e0cd7bb4113731adc2e76d492238b539c3d6ce24a408670fee40579e57","tree":"024c36c1f532ac9150f9768ed57bb27cb284f8949f51958804dfd0f11ee70b65","paths":["/data/x/u/b"],"hostname":"box","username":"root","uid":1000,"gid":1000,"tags":["felhom-offbox","b"],"id":"315ff629674caa42ace8498b9d4bb82e5a77cb2284e628560444e12d9072ec8f","short_id":"315ff629"}] diff --git a/controller/internal/backup/testdata/restic/0.19.1/stats-id.json b/controller/internal/backup/testdata/restic/0.19.1/stats-id.json new file mode 100644 index 0000000..13e23bb --- /dev/null +++ b/controller/internal/backup/testdata/restic/0.19.1/stats-id.json @@ -0,0 +1 @@ +{"total_size":21,"total_file_count":12,"snapshots_count":1} diff --git a/controller/internal/backup/testdata/restic/0.19.1/stats-raw.json b/controller/internal/backup/testdata/restic/0.19.1/stats-raw.json new file mode 100644 index 0000000..7e869f8 --- /dev/null +++ b/controller/internal/backup/testdata/restic/0.19.1/stats-raw.json @@ -0,0 +1 @@ +{"total_size":217458,"total_uncompressed_size":345270,"compression_ratio":1.5877548768037966,"compression_progress":100,"compression_space_saving":37.017985924059424,"total_blob_count":863,"snapshots_count":82} diff --git a/controller/internal/backup/testdata/restic/0.19.1/wrong-password.txt b/controller/internal/backup/testdata/restic/0.19.1/wrong-password.txt new file mode 100644 index 0000000..16c9fcd --- /dev/null +++ b/controller/internal/backup/testdata/restic/0.19.1/wrong-password.txt @@ -0,0 +1 @@ +Fatal: wrong password or no key found diff --git a/controller/internal/family/family.go b/controller/internal/family/family.go index 31e482b..4556049 100644 --- a/controller/internal/family/family.go +++ b/controller/internal/family/family.go @@ -1,8 +1,9 @@ // Package family is the household's family list for the permanent family gate (`09` §3 decisions 63, 64; R-780). // // Each family member has their OWN name and password (never the dashboard's); the household's dashboard admin adds, -// resets and removes them. A member who signs in gets a SESSION (30 days). Every app cookie the gate mints names the -// session, so the gate asks this store on every request: a removed member, a reset password (the member's generation +// resets and removes them. A member who signs in gets a SESSION (30 days). Every app cookie the gate mints carries a +// token derived from the session for that app (never the session id itself, R-976), so the gate asks this store on +// every request (Find): a removed member, a reset password (the member's generation // moves on) or a logout (the session is deleted) ends every app's access at the next request. // // A session with Member "" is the HOUSEHOLD's: minted when the dashboard's own session vouched for the browser (the @@ -312,6 +313,50 @@ func (s *Store) Valid(id string) (Session, bool) { return se, true } +// Find returns the first session that match accepts and that still holds (the same test as Valid). It lets a caller +// look a session up by something DERIVED from its id — the per-app token the family gate puts in an app's cookie +// (R-976) — without that id ever leaving the dashboard host. +func (s *Store) Find(match func(id string) bool) (Session, bool) { + if s == nil || match == nil { + return Session{}, false + } + s.mu.Lock() + var found string + for id := range s.sessions { + if match(id) { + found = id + break + } + } + s.mu.Unlock() + if found == "" { + return Session{}, false + } + return s.Valid(found) +} + +// EndAll deletes every session — every member's and the household's — and keeps the members (R-976: a dashboard +// password change or reset ends every way into the family apps; members sign in again with their own passwords). +// It returns how many sessions it ended. +func (s *Store) EndAll() (int, error) { + if s == nil { + return 0, nil + } + s.mu.Lock() + defer s.mu.Unlock() + n := len(s.sessions) + if n == 0 { + return 0, nil + } + // Ended in memory even when the save fails: an ending is never undone because a disk write failed (the caller + // logs the error; the sessions stay ended until a restart would read the old file back). + s.sessions = map[string]Session{} + if err := s.saveLocked(); err != nil { + return n, err + } + return n, nil +} + // EndSession deletes a session (logout). Unknown ids are not an error. func (s *Store) EndSession(id string) error { if s == nil { diff --git a/controller/internal/i18n/locales/en.json b/controller/internal/i18n/locales/en.json index 027dd59..e7967cf 100644 --- a/controller/internal/i18n/locales/en.json +++ b/controller/internal/i18n/locales/en.json @@ -1287,6 +1287,7 @@ "err.backup.adatbazis_felderites_sikertelen": "finding the databases failed: %s", "err.backup.adatbazis_masolat_csonka_nem_indult": "The database copy of %s is cut off: it does not end the way a complete copy does. The restore did not start, for safety — the app and its data are untouched.", "err.backup.adatbazis_masolat_csonka_nem_toltve": "The database copy of %s is cut off: it does not end the way a complete copy does. That copy was not loaded — the database was not restored from it.", + "err.backup.restore_no_db_password": "This backup cannot be restored: it does not contain the database password, and without it the app could not start. The current install was left as it was.", "err.backup.adatbazis_mentes_sikertelen": "the database backup failed (%s): %s", "err.backup.az_adatbazis_szolgaltatas_nem_azonosithato_a": "The database service cannot be identified in %s — the restore did not start, for safety.", "err.backup.az_alkalmazas_meghajtoja_le_van_szerelve": "the app’s drive is decommissioned", @@ -1978,7 +1979,7 @@ "settings.notify_saved_sync_failed": "Notification settings saved on this machine. Syncing them to the central service failed: %v", "settings.pw_mismatch": "The two passwords do not match", "settings.pw_save_error": "Something went wrong while saving the password", - "settings.pw_too_short": "The password must be at least 8 characters long", + "settings.pw_too_short": "The password must be at least %d characters long", "settings.pw_wrong_current": "That is not your current password", "settings.test_email_failed": "The test email could not be sent: %v", "settings.test_email_sent": "The test email is sent.", @@ -2055,7 +2056,7 @@ "settings_security.jelszo_modositasa": "Change password", "settings_security.kesz": "Done", "settings_security.kezi_szinkronizalas": "Sync by hand", - "settings_security.legalabb_8_karakter": "At least 8 characters", + "settings_security.legalabb_karakter": "At least {{.MinPassword}} characters", "settings_security.magyarorszag_eltavolitasa_nem_ajanlott_f": "Removing Hungary is not recommended. Continue?", "settings_security.megerosites": "Confirm", "settings_security.megjelenit": "Show", diff --git a/controller/internal/i18n/locales/hu.json b/controller/internal/i18n/locales/hu.json index 155d939..195a368 100644 --- a/controller/internal/i18n/locales/hu.json +++ b/controller/internal/i18n/locales/hu.json @@ -1282,6 +1282,7 @@ "err.backup.adatbazis_felderites_sikertelen": "adatbázis-felderítés sikertelen: %s", "err.backup.adatbazis_masolat_csonka_nem_indult": "A(z) %s adatbázis-másolata csonka: nem ér véget, ahogy egy teljes másolat. A visszaállítás biztonsági okból nem indult el — az alkalmazás és az adatai érintetlenek.", "err.backup.adatbazis_masolat_csonka_nem_toltve": "A(z) %s adatbázis-másolata csonka: nem ér véget, ahogy egy teljes másolat. Ezt a másolatot nem töltöttük vissza — az adatbázis nem ebből a másolatból állt vissza.", + "err.backup.restore_no_db_password": "Ezt a mentést nem lehet visszaállítani: nem tartalmazza az adatbázis jelszavát, és nélküle az alkalmazás nem tudna elindulni. A mostani telepítés érintetlen maradt.", "err.backup.adatbazis_mentes_sikertelen": "adatbázis-mentés sikertelen (%s): %s", "err.backup.az_adatbazis_szolgaltatas_nem_azonosithato_a": "Az adatbázis-szolgáltatás nem azonosítható a(z) %s alkalmazásban — a visszaállítás biztonsági okból nem indult el.", "err.backup.az_alkalmazas_meghajtoja_le_van_szerelve": "az alkalmazás meghajtója le van szerelve", @@ -1966,7 +1967,7 @@ "settings.notify_saved_sync_failed": "Értesítési beállítások mentve (helyi). A központi szinkronizálás sikertelen: %v", "settings.pw_mismatch": "A két jelszó nem egyezik", "settings.pw_save_error": "Belső hiba a jelszó mentésekor", - "settings.pw_too_short": "A jelszónak legalább 8 karakter hosszúnak kell lennie", + "settings.pw_too_short": "A jelszónak legalább %d karakter hosszúnak kell lennie", "settings.pw_wrong_current": "Hibás jelenlegi jelszó", "settings.test_email_failed": "Teszt email küldése sikertelen: %v", "settings.test_email_sent": "Teszt email elküldve.", @@ -2043,7 +2044,7 @@ "settings_security.jelszo_modositasa": "Jelszó módosítása", "settings_security.kesz": "Kész", "settings_security.kezi_szinkronizalas": "Kézi szinkronizálás", - "settings_security.legalabb_8_karakter": "Legalább 8 karakter", + "settings_security.legalabb_karakter": "Legalább {{.MinPassword}} karakter", "settings_security.magyarorszag_eltavolitasa_nem_ajanlott_f": "Magyarország eltávolítása nem ajánlott. Folytatod?", "settings_security.megerosites": "Megerősítés", "settings_security.megjelenit": "Megjelenít", diff --git a/controller/internal/stacks/delete.go b/controller/internal/stacks/delete.go index a0f32ce..048d3d4 100644 --- a/controller/internal/stacks/delete.go +++ b/controller/internal/stacks/delete.go @@ -171,15 +171,17 @@ func hddNoteFor(removeHDDData bool, mounts, missing, userdataKept []string) stri // userdataKept lists the folders the app binds through ${USERDATA_PATH} that exist on its drive — the household's own // files (books, videos, photos it sees in the file browser). No remove deletes them (`09` §3 decision 67, R-800): the // removal reads ${HDD_PATH} binds only, and ProtectedHDDPaths guards the roots. This list exists so the dialog and the -// result can SAY so, by name. USERDATA_PATH is /userdata (withUserdataPath at deploy). Pinned by -// TestRemoveStack_R800_UserdataKeptIsNamed. +// result can SAY so, by name. USERDATA_PATH is /userdata (withPathVars at deploy) — on +// the system-data fallback that root is /felhom-data, so the bare HDD_PATH is never passed to UserdataDir +// (R-203 shape, found by the R-1017 guard). Pinned by TestRemoveStack_R800_UserdataKeptIsNamed and +// TestRemoveStack_R800_UserdataKeptOnSystemDrive. func (m *Manager) userdataKept(name, composePath string) []HDDPath { out := []HDDPath{} hddPath, declared := m.appHDDPath(name) if !declared { return out } - for _, p := range ParseComposeUserdataMounts(composePath, appbackup.UserdataDir(hddPath)) { + for _, p := range ParseComposeUserdataMounts(composePath, appbackup.UserdataDir(appbackup.NamespaceRootFor(hddPath, m.sysDataPath))) { clean := filepath.Clean(p) info, err := os.Stat(clean) if err != nil || !info.IsDir() { diff --git a/controller/internal/stacks/delete_r442_test.go b/controller/internal/stacks/delete_r442_test.go index 9ce5e28..e6d7584 100644 --- a/controller/internal/stacks/delete_r442_test.go +++ b/controller/internal/stacks/delete_r442_test.go @@ -456,6 +456,31 @@ func TestRemoveStack_R800_UserdataKeptIsNamed(t *testing.T) { } } +// R-1017 / R-203 shape: an app on the SYSTEM-DATA fallback has USERDATA_PATH = /felhom-data/userdata (the +// deploy's withPathVars), so its kept folders live there — not under /userdata. The dialog must name them. +// COMPANION RED-PROOF: pass the bare hddPath to UserdataDir in userdataKept again → userdata_kept is empty. +func TestRemoveStack_R800_UserdataKeptOnSystemDrive(t *testing.T) { + sys := t.TempDir() + compose := "services:\n" + + " app:\n" + + " image: nginx:1.27\n" + + " volumes:\n" + + " - ${USERDATA_PATH}/media/app:/downloads\n" + m, _, _ := newR442Manager(t, "app", compose, driveAppYAML(sys), sys) + m.sysDataPath = sys + m.cfg.Paths.SystemDataPath = sys + kept := filepath.Join(sys, "felhom-data", "userdata", "media", "app") + plantFile(t, filepath.Join(kept, "clip.mp4")) + + hd, err := m.GetStackHDDData("app") + if err != nil { + t.Fatal(err) + } + if len(hd.UserdataKept) != 1 || hd.UserdataKept[0].Path != kept { + t.Fatalf("hdd-data userdata_kept = %+v, want [%s] — on the system drive the household's folder sits under felhom-data", hd.UserdataKept, kept) + } +} + // An SSD app: userdata_kept serialises as [] (never null), the "no drive data" note is unchanged. func TestRemoveStack_R800_SSDAppUserdataKeptEmpty(t *testing.T) { m, _, _ := newR442Manager(t, "app", ssdCompose, "deployed: true\nenv: {}\n", "") diff --git a/controller/internal/stacks/deploy.go b/controller/internal/stacks/deploy.go index 51339c4..ffdb057 100644 --- a/controller/internal/stacks/deploy.go +++ b/controller/internal/stacks/deploy.go @@ -10,6 +10,7 @@ import ( "os" "path/filepath" "regexp" + "sort" "strings" "time" @@ -1590,3 +1591,51 @@ func restoredLoginFields(app string, meta Metadata, prior *AppConfig, env map[st } return out } + +// SetStackSecretValues (R-1106) writes the named values into an installed app's app.yaml and NOTHING else: load the +// file as it is (records, pin, gates, locked fields all kept — the R-697 lesson: a non-install writer loads, then +// saves), replace the named env values, save with the sensitive fields encrypted. Used by the off-site restore to put +// back the database password a restored data directory was created with. Values are never logged. The in-memory app +// config is refreshed so the next start renders the new value. +func (m *Manager) SetStackSecretValues(name string, values map[string]string) error { + stack, ok := m.GetStack(name) + if !ok { + return fmt.Errorf("stack %q not found", name) + } + stackDir := filepath.Dir(stack.ComposePath) + meta := LoadMetadata(stackDir) + cfg := LoadAppConfig(stackDir) + if cfg == nil { + return fmt.Errorf("app.yaml of %s not readable", name) + } + if cfg.Env == nil { + cfg.Env = map[string]string{} + } + names := make([]string, 0, len(values)) + for k, v := range values { + cfg.Env[k] = v // plaintext here; SaveAppConfig encrypts every sensitive field + names = append(names, k) + } + sort.Strings(names) + // R-926 / R-694 on this path: the only caller writes these values because the install is NOT the one the restored + // data belongs to (a reinstall). Its `type: password` admin logins were generated for the fresh, empty app; the + // restored data carries the household's own login. So they are recorded as restored-login fields — the page then + // never shows them as the app's login and says to use the old password, exactly as after a unit restore that had + // to generate one. A login the app applies at every start (loginAppliedEveryStart) stays a real login. + for _, f := range meta.DeployFields { + if f.Type != "password" || cfg.Env[f.EnvVar] == "" || loginAppliedEveryStart[name][f.EnvVar] || containsStr(cfg.RestoredLogins, f.EnvVar) { + continue + } + cfg.RestoredLogins = append(cfg.RestoredLogins, f.EnvVar) + } + if err := SaveAppConfig(stackDir, cfg, m.encKey, SensitiveEnvVars(&meta)); err != nil { + return fmt.Errorf("saving app config: %w", err) + } + m.mu.Lock() + if s, ok := m.stacks[name]; ok { + s.AppConfig = LoadAppConfig(stackDir) + } + m.mu.Unlock() + m.logger.Printf("[INFO] [stacks] %s: secret value(s) %v replaced in app.yaml (values not logged)", name, names) + return nil +} diff --git a/controller/internal/stacks/r1106_set_secret_values_test.go b/controller/internal/stacks/r1106_set_secret_values_test.go new file mode 100644 index 0000000..7026d6b --- /dev/null +++ b/controller/internal/stacks/r1106_set_secret_values_test.go @@ -0,0 +1,51 @@ +package stacks + +import ( + "io" + "log" + "os" + "path/filepath" + "strings" + "testing" + + "gitea.dooplex.hu/admin/felhom-controller/internal/config" +) + +// R-1106 / R-926: the off-site restore over a REINSTALL writes the backup's database password and nothing else of the +// app's settings, and records the reinstall's generated admin login as NOT the app's login (the restored data carries +// the household's own). Through the production writer. +func TestR1106_SetStackSecretValues(t *testing.T) { + dir := t.TempDir() + cfg := &config.Config{} + cfg.Paths.StacksDir = filepath.Join(dir, "stacks") + cfg.Stacks.ComposeCommand = "docker compose" + app := filepath.Join(cfg.Paths.StacksDir, "bookstack") + must(t, os.MkdirAll(app, 0o755)) + must(t, os.WriteFile(filepath.Join(app, "docker-compose.yml"), []byte("services:\n web:\n image: x/y:1\n"), 0o644)) + must(t, os.WriteFile(filepath.Join(app, ".felhom.yml"), []byte("display_name: X\ndeploy_fields:\n"+ + " - env_var: DB_PASSWORD\n label: DB\n type: secret\n"+ + " - env_var: ADMIN_PASSWORD\n label: Admin\n type: password\n"), 0o644)) + must(t, os.WriteFile(filepath.Join(app, "app.yaml"), []byte("deployed: true\ndeployed_at: \"2026-10-16T19:00:00Z\"\n"+ + "pinned_images:\n web: x/y:1\nenv:\n DB_PASSWORD: reinstall-db\n ADMIN_PASSWORD: reinstall-admin\n SUBDOMAIN: books\n"), 0o600)) + m, err := NewManager(cfg, log.New(io.Discard, "", 0)) + must(t, err) + must(t, m.ScanStacks()) + must(t, m.SetStackSecretValues("bookstack", map[string]string{"DB_PASSWORD": "backup-db"})) + + got := LoadAppConfig(app) + if got == nil { + t.Fatal("app.yaml unreadable") + } + if got.Env["DB_PASSWORD"] != "backup-db" { + t.Errorf("DB_PASSWORD = %q, want the backup's", got.Env["DB_PASSWORD"]) + } + if got.Env["SUBDOMAIN"] != "books" || got.Env["ADMIN_PASSWORD"] != "reinstall-admin" || got.DeployedAt != "2026-10-16T19:00:00Z" { + t.Errorf("other settings changed: %+v", got) + } + if len(got.PinnedImages) == 0 { + t.Error("the pin was dropped — a non-install writer must load, then save (R-697)") + } + if strings.Join(got.RestoredLogins, ",") != "ADMIN_PASSWORD" { + t.Errorf("restored_logins = %v, want the reinstall's admin login recorded as not the app's (R-926)", got.RestoredLogins) + } +} diff --git a/controller/internal/stacks/samba.go b/controller/internal/stacks/samba.go index a8abedd..3507111 100644 --- a/controller/internal/stacks/samba.go +++ b/controller/internal/stacks/samba.go @@ -258,12 +258,22 @@ func (m *Manager) SetSMBPassword(password string) error { } dir := m.sambaDir() data := m.sambaRenderData(smb) - if _, err := m.writeSambaFiles(dir, data); err != nil { + changed, err := m.writeSambaFiles(dir, data) + if err != nil { return err } // The container must be running to accept smbpasswd. Bringing it up before a password exists is // safe: `security = user` + `map to guest = never` means nothing is reachable until this lands. - if !m.sambaIsRunning() { + // + // R-1108: an ALREADY-running container must also be re-applied when the files changed. A share + // added while the password was unset was skipped by reconcileSambaAt (UserSet=false) and lands on + // disk only here; smb.conf is a bind-mounted FILE replaced by atomic rename, so the running + // container still holds the old inode — only `compose up -d` (which recreates, the share binds + // having changed the compose file) applies it. The next reconcile sees "unchanged + running" and + // would never do it. Pinned by TestSambaPassword_ShareAddedBeforePasswordIsApplied. + running := m.sambaIsRunning() + if !running || changed { + m.logger.Printf("[INFO] [samba] applying samba stack before password set: shares=%d config_changed=%v was_running=%v", len(data.Shares), changed, running) if err := m.sambaUp(dir); err != nil { return util.MsgError("err.stacks.a_megosztas_szolgaltatas_inditasa_sikertelen", err) } diff --git a/controller/internal/stacks/samba_test.go b/controller/internal/stacks/samba_test.go index 2cecd72..f710b16 100644 --- a/controller/internal/stacks/samba_test.go +++ b/controller/internal/stacks/samba_test.go @@ -296,3 +296,92 @@ func TestSambaPasswordRefusedWhenDisabled(t *testing.T) { t.Errorf("no compose call may happen while disabled, got %d", *upCalls) } } + +// R-1108: a share added while sharing is on but the household password is NOT yet set must be +// exported once the password is set, even though the samba container is ALREADY running. Before the +// fix SetSMBPassword rewrote smb.conf + compose but called compose up only when the container was +// down, and the next reconcile saw "unchanged + running" and did nothing — the share never appeared. +// The consequence asserted: the new config is on disk AND a compose up ran after it was written. +func TestSambaPassword_ShareAddedBeforePasswordIsApplied(t *testing.T) { + m, sett, root, upCalls := newSambaManager(t) + if err := sett.SetSMBEnabled(true); err != nil { + t.Fatal(err) + } + // First password attempt: the container is brought up, then smbpasswd fails — the box is left + // with sharing on, UserSet=false and a RUNNING container holding a share-less config. + m.sambaPasswdFn = func(string) error { return os.ErrDeadlineExceeded } + if err := m.SetSMBPassword("elso"); err == nil { + t.Fatal("setup: the first password apply was meant to fail") + } + if *upCalls != 1 { + t.Fatalf("setup: expected the container brought up once, got %d", *upCalls) + } + if sett.GetSMBSettings().UserSet { + t.Fatal("setup: UserSet must stay false after a failed smbpasswd") + } + m.sambaRunFn = func() bool { return true } + + // A share is added now; its reconcile is skipped because no password is set yet. + shareDir := seedShare(t, sett, root, "dokumentumok") + if err := sett.AddSMBShare(settings.SMBShare{Name: "dokumentumok", Path: shareDir}); err != nil { + t.Fatal(err) + } + if err := m.ReconcileSamba(); err != nil { + t.Fatal(err) + } + if *upCalls != 1 { + t.Fatalf("setup: reconcile without a password must not deploy, got %d up calls", *upCalls) + } + + // The password is set: the share must be written AND applied to the running container. + var upAfterWrite bool + m.sambaUpFn = func(dir string) error { + *upCalls++ + conf, err := os.ReadFile(filepath.Join(dir, "smb.conf")) + upAfterWrite = err == nil && strings.Contains(string(conf), "[dokumentumok]") + return nil + } + m.sambaPasswdFn = func(string) error { return nil } + if err := m.SetSMBPassword("masodik"); err != nil { + t.Fatalf("SetSMBPassword: %v", err) + } + conf, err := os.ReadFile(filepath.Join(m.sambaDir(), "smb.conf")) + if err != nil || !strings.Contains(string(conf), "[dokumentumok]") { + t.Fatalf("share missing from smb.conf after the password set: err=%v\n%s", err, conf) + } + if *upCalls != 2 || !upAfterWrite { + t.Errorf("the running container must be re-applied with the new share: up calls=%d (want 2), up saw the share=%v", *upCalls, upAfterWrite) + } + + // And the follow-up reconcile is a clean no-op (nothing pending was left behind). + before := *upCalls + if err := m.ReconcileSamba(); err != nil { + t.Fatal(err) + } + if *upCalls != before { + t.Errorf("reconcile after the password set must be a no-op: up calls %d → %d", before, *upCalls) + } +} + +// R-1108 companion: setting (or changing) the password on a running container whose config did NOT +// change performs no compose call — the fix must not turn every password change into a recreate. +func TestSambaPassword_RunningUnchangedNoComposeCall(t *testing.T) { + m, sett, root, upCalls := newSambaManager(t) + shareDir := seedShare(t, sett, root, "dokumentumok") + enableSMB(t, sett) + if err := sett.AddSMBShare(settings.SMBShare{Name: "dokumentumok", Path: shareDir}); err != nil { + t.Fatal(err) + } + if err := m.ReconcileSamba(); err != nil { + t.Fatal(err) + } + m.sambaRunFn = func() bool { return true } + m.sambaPasswdFn = func(string) error { return nil } + before := *upCalls + if err := m.SetSMBPassword("uj"); err != nil { + t.Fatalf("SetSMBPassword: %v", err) + } + if *upCalls != before { + t.Errorf("an unchanged config on a running container needs no compose call: %d → %d", before, *upCalls) + } +} diff --git a/controller/internal/web/auth.go b/controller/internal/web/auth.go index 69721c0..6f99d6f 100644 --- a/controller/internal/web/auth.go +++ b/controller/internal/web/auth.go @@ -2,6 +2,7 @@ package web import ( "crypto/rand" + "crypto/subtle" "encoding/hex" "fmt" "net/http" @@ -164,31 +165,19 @@ func (s *Server) handleLogin(w http.ResponseWriter, r *http.Request) { return } - s.loginAttemptMu.Lock() - attempt := s.loginAttempts[ip] - if attempt != nil && time.Since(attempt.lastFail) > loginWindowDuration { - // Window expired — reset - attempt = nil - delete(s.loginAttempts, ip) - } - if attempt != nil && attempt.count >= loginMaxAttempts { - s.loginAttemptMu.Unlock() - s.logger.Printf("[WARN] [web] Login rate limited for %s (%d attempts)", ip, attempt.count) + // R-983 (v0.324.0): the try is RESERVED before the password is compared, under the one lock — check and count + // are a single step. Before, the count was taken only after the slow compare, so N parallel tries all passed the + // check and the 5-per-minute limit became "as many as arrive at once". A right password clears the counter below, + // so the household loses nothing by its own try being counted first. Pinned by TestR983_ParallelLoginsHitTheLimit. + if n, ok := s.reserveLoginAttempt(ip); !ok { + s.logger.Printf("[WARN] [web] Login rate limited for %s (%d attempts)", ip, n) s.renderLogin(w, r, s.msg(r, "login.msg.rate_limited"), "") return } - s.loginAttemptMu.Unlock() effectiveHash := s.effectivePasswordHash() - if err := bcrypt.CompareHashAndPassword([]byte(effectiveHash), []byte(password)); err != nil { + if err := s.comparePassword([]byte(effectiveHash), []byte(password)); err != nil { s.logger.Printf("[WARN] [web] Failed login from %s", ip) - s.loginAttemptMu.Lock() - if s.loginAttempts[ip] == nil { - s.loginAttempts[ip] = &loginAttempt{} - } - s.loginAttempts[ip].count++ - s.loginAttempts[ip].lastFail = time.Now() - s.loginAttemptMu.Unlock() s.renderLogin(w, r, s.msg(r, "login.msg.wrong_password"), "") return } @@ -221,14 +210,50 @@ func (s *Server) handleLogin(w http.ResponseWriter, r *http.Request) { s.logger.Printf("[INFO] [web] Login from %s", ip) - // Redirect to ?next= target if provided, otherwise to dashboard - redirectTo := "/" - if nextURL != "" && strings.HasPrefix(nextURL, "/") { - redirectTo = nextURL - } - http.Redirect(w, r, redirectTo, http.StatusFound) + // Redirect to ?next= target if provided, otherwise to dashboard. R-983 (v0.324.0): through safeBackPath, the one + // guard for a destination taken from a request — a bare HasPrefix("/") let "//host" and "/\host" send a browser + // that had just signed in to another site. Pinned by TestR983_LoginNextStaysOnTheBox. + http.Redirect(w, r, safeBackPath(nextURL), http.StatusFound) } +// reserveLoginAttempt counts one sign-in try for this visitor BEFORE the password is compared and reports whether it +// may go ahead (and the count it found). Check and count happen under one lock, so parallel tries cannot all pass a +// check that none of them has counted yet. A window that has passed starts clean. +func (s *Server) reserveLoginAttempt(ip string) (int, bool) { + s.loginAttemptMu.Lock() + defer s.loginAttemptMu.Unlock() + if s.loginAttempts == nil { + s.loginAttempts = map[string]*loginAttempt{} + } + a := s.loginAttempts[ip] + if a != nil && time.Since(a.lastFail) > loginWindowDuration { + a = nil + } + if a == nil { + a = &loginAttempt{} + s.loginAttempts[ip] = a + } + if a.count >= loginMaxAttempts { + return a.count, false + } + a.count++ + a.lastFail = time.Now() + return a.count, true +} + +// comparePassword is bcrypt's compare; passwordCompare replaces it in tests (a slow compare makes a race measurable). +func (s *Server) comparePassword(hash, pw []byte) error { + if s.passwordCompare != nil { + return s.passwordCompare(hash, pw) + } + return bcrypt.CompareHashAndPassword(hash, pw) +} + +// handleLogout ends the presented dashboard session. It runs inside RequireAuth, BEFORE CsrfProtect, so it checks the +// session's CSRF token itself (R-983, v0.324.0): without it any page — another site, or an app on a sibling +// subdomain, which is same-site and so gets the Lax cookie — could sign the household out. A GET changes nothing and +// goes to the dashboard; the dashboard's own sign-out control is a POST form carrying the token (layout.html). +// A POST with no valid session has nothing to end and only clears the cookie. Pinned by TestR983_LogoutNeedsCSRF. func (s *Server) handleLogout(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Redirect(w, r, "/", http.StatusFound) @@ -238,6 +263,16 @@ func (s *Server) handleLogout(w http.ResponseWriter, r *http.Request) { s.logger.Printf("[DEBUG] [web] logout from %s", r.RemoteAddr) } if cookie, err := r.Cookie(sessionCookieName); err == nil { + if expected := s.csrfTokenForSession(cookie.Value); expected != "" { + submitted := r.FormValue(csrfFormField) + if submitted == "" { + submitted = r.Header.Get(csrfHeaderName) + } + if submitted == "" || subtle.ConstantTimeCompare([]byte(submitted), []byte(expected)) != 1 { + s.csrfReject(w, r, "logout without the session's token") + return + } + } s.sessionsMu.Lock() delete(s.sessions, sessionFingerprint(cookie.Value)) s.saveSessionsRevokingLocked() // R-35: a signed-out cookie stays signed out across a restart @@ -304,6 +339,23 @@ func (s *Server) invalidateAllSessions() { s.logger.Printf("[INFO] [web] All sessions invalidated (cleared %d)", count) } +// endEverySession is what a dashboard password change and a claim/reset do (R-976, v0.324.0): every dashboard session +// ends (invalidateAllSessions), every family session — each member's and the household's — ends, and the gate key is +// replaced, so every setup-gate pass and every family app cookie stops opening its app at the next request. Before, +// only the dashboard sessions ended, so a session copied out of a family app kept working for up to 30 days after the +// household had changed its password. Family members keep their own passwords and sign in again; the household's +// browser passes again through its new dashboard session. Pinned by TestR976_PasswordChangeEndsFamilyAndGateSessions +// and TestR976_ClaimResetEndsFamilyAndGateSessions. +func (s *Server) endEverySession(why string) { + s.invalidateAllSessions() + n, err := s.familyStore().EndAll() + if err != nil { + s.logger.Printf("[ERROR] [web] %s: the family sessions were ended but the family list could not be saved: %v", why, err) + } + s.rotateGateKey() + s.logger.Printf("[INFO] [web] %s: every dashboard session, %d family session(s) and every app gate pass ended", why, n) +} + func (s *Server) cleanupSessions() { ticker := time.NewTicker(15 * time.Minute) defer ticker.Stop() diff --git a/controller/internal/web/claim.go b/controller/internal/web/claim.go index 9115972..5020c52 100644 --- a/controller/internal/web/claim.go +++ b/controller/internal/web/claim.go @@ -397,7 +397,7 @@ func (s *Server) handleClaimSubmit(w http.ResponseWriter, r *http.Request) { } } - s.invalidateAllSessions() // reset: kill old sessions; first-claim: none exist + s.endEverySession("claim/reset") // reset: kill old sessions — dashboard, family, gate passes (R-976); first-claim: none exist action := "claimed" if wasReset { @@ -428,10 +428,59 @@ func (s *Server) handleClaimRequestNewCode(w http.ResponseWriter, r *http.Reques s.handleClaimPage(w, r, s.msg(r, "claim.msg.invalid_form"), "") return } - go s.requestHubResetCode() // fire-and-forget; the neutral response never reveals the outcome + // R-983 (v0.324.0): a request reaches the hub only inside the box's own limit. Each call mints a fresh code that + // replaces the one the household may be typing, and mails the household — so without a limit a stranger could do + // both at will. The answer stays the same neutral page either way (it never revealed the outcome). + if ok, why := s.allowResetRequest(rateKey(r)); !ok { + s.logger.Printf("[WARN] [web] claim: a reset-code request was not passed to the hub (%s) — visitor %s", why, rateKey(r)) + } else if s.resetRequestFn != nil { + s.resetRequestFn() + } else { + go s.requestHubResetCode() // fire-and-forget; the neutral response never reveals the outcome + } s.handleClaimPage(w, r, "", s.msg(r, "claim.msg.code_sent")) } +// The reset-code request's limit (R-983): one hub call per visitor per resetReqVisitorEvery, and at most +// resetReqGlobalMax for the whole box in any resetReqGlobalWindow. The worst a stranger can do is hold the box's +// budget for one window — the household's code already sent stays valid meanwhile, because nothing replaces it. +const ( + resetReqVisitorEvery = time.Minute + resetReqGlobalMax = 3 + resetReqGlobalWindow = 15 * time.Minute +) + +// allowResetRequest decides and counts in one step (under claimMu), so parallel requests cannot all pass. +func (s *Server) allowResetRequest(visitor string) (bool, string) { + s.claimMu.Lock() + defer s.claimMu.Unlock() + now := s.claimNow() + if s.resetReqVisitor == nil { + s.resetReqVisitor = map[string]time.Time{} + } + for k, at := range s.resetReqVisitor { + if now.Sub(at) >= resetReqVisitorEvery { + delete(s.resetReqVisitor, k) + } + } + keep := s.resetReqGlobal[:0] + for _, at := range s.resetReqGlobal { + if now.Sub(at) < resetReqGlobalWindow { + keep = append(keep, at) + } + } + s.resetReqGlobal = keep + if _, seen := s.resetReqVisitor[visitor]; seen { + return false, "this visitor asked less than a minute ago" + } + if len(s.resetReqGlobal) >= resetReqGlobalMax { + return false, "the box's limit for this quarter hour is used" + } + s.resetReqVisitor[visitor] = now + s.resetReqGlobal = append(s.resetReqGlobal, now) + return true, "" +} + // requestHubResetCode calls POST /api/v1/claim/reset-request with the box's own report key. // v0.123.0 (take-two F-15): a hub ≥0.52.0 returns the freshly rotated code state in the response; // it is applied through the SAME generation-guarded consumer as the report ACK (ClaimSync), so the diff --git a/controller/internal/web/family_gate.go b/controller/internal/web/family_gate.go index 238087b..f80a05e 100644 --- a/controller/internal/web/family_gate.go +++ b/controller/internal/web/family_gate.go @@ -39,8 +39,10 @@ import ( // every request). // // THE RULE: a family cookie never opens the dashboard. RequireAuth reads only `felhom_session`; nothing here ever sets -// it. An app cookie names a store session, so a removed member, a reset password or a logout ends access at the next -// request on every app. Pinned by internal/web/family_gate_test.go. +// it. An app cookie carries a token derived from a store session for that one app host (familyAppToken, R-976), so a +// removed member, a reset password, a logout or a dashboard password change ends access at the next request on every +// app, and what an app's backend sees cannot be turned into a pass for another app. Pinned by +// internal/web/family_gate_test.go and r983_r976_test.go. const ( familySessionCookie = "felhom_family" @@ -91,8 +93,10 @@ func (s *Server) familyStore() *family.Store { return s.fam.store } -// familyLocked reports whether this visitor or this name is out of tries. Windows slide; a success clears both. -func (s *Server) familyLocked(visitor, name string) bool { +// familyReserve checks whether this visitor or this name is out of tries and, when neither is, counts this try +// against both — one step under one lock (R-983, v0.324.0), so parallel tries cannot all pass a check that none of +// them has counted yet. Windows slide; a success clears both (familyCleared). It reports whether the try may go ahead. +func (s *Server) familyReserve(visitor, name string) bool { s.familyStore() now := s.gateNow() s.fam.mu.Lock() @@ -116,17 +120,14 @@ func (s *Server) familyLocked(visitor, name string) bool { if name != "" { n = prune(s.fam.name, name, familyNameWindow) } - return v >= familyVisitorMax || n >= familyNameMax -} - -func (s *Server) familyFailed(visitor, name string) { - now := s.gateNow() - s.fam.mu.Lock() - defer s.fam.mu.Unlock() + if v >= familyVisitorMax || n >= familyNameMax { + return false + } s.fam.visitor[visitor] = append(s.fam.visitor[visitor], now) if name != "" { s.fam.name[name] = append(s.fam.name[name], now) } + return true } func (s *Server) familyCleared(visitor, name string) { @@ -152,9 +153,28 @@ func (s *Server) familyRDHost(rd string) (string, bool) { return host, true } +// familyAppToken is what an app host ever sees of a family session (R-976, v0.324.0): a token DERIVED from the +// session for that one host, never the session itself. Before, the app cookie carried the session id in clear; every +// family-gated app's backend receives its cookies, and a session id lifted from one app, set as the family session +// cookie on the dashboard host, minted passes into EVERY family app for 30 days. A derived token cannot be turned back +// into the session, and it opens only its own host. Pinned by TestR976_AnAppCookieCannotBeLiftedIntoAnotherApp. +func (s *Server) familyAppToken(host, sid string) string { + return s.gateMAC("famapp", host, sid) +} + +// familySessionForAppToken finds the session an app token was derived from (still valid, as Store.Valid judges it). +func (s *Server) familySessionForAppToken(host, at string) (family.Session, bool) { + if at == "" { + return family.Session{}, false + } + return s.familyStore().Find(func(id string) bool { + return hmac.Equal([]byte(s.familyAppToken(host, id)), []byte(at)) + }) +} + type familyToken struct { Host string `json:"h"` - Sid string `json:"s"` + App string `json:"a"` // the per-app token (familyAppToken), never the session id Exp int64 `json:"e"` Nonce string `json:"n"` RD string `json:"r"` @@ -164,14 +184,14 @@ type familyToken struct { func (s *Server) mintFamilyToken(host, sid, rd string) string { nb := make([]byte, 12) _, _ = rand.Read(nb) - t := familyToken{Host: host, Sid: sid, Exp: s.gateNow().Add(gateTokenLife).Unix(), Nonce: hex.EncodeToString(nb), RD: rd} - t.MAC = s.gateMAC("ftoken", t.Host, t.Sid, strconv.FormatInt(t.Exp, 10), t.Nonce, t.RD) + t := familyToken{Host: host, App: s.familyAppToken(host, sid), Exp: s.gateNow().Add(gateTokenLife).Unix(), Nonce: hex.EncodeToString(nb), RD: rd} + t.MAC = s.gateMAC("ftoken", t.Host, t.App, strconv.FormatInt(t.Exp, 10), t.Nonce, t.RD) b, _ := json.Marshal(t) return base64.RawURLEncoding.EncodeToString(b) } -// takeFamilyToken checks a token for host, uses it up, and returns the session and where the browser was going. -func (s *Server) takeFamilyToken(raw, host string) (sid, rd string, err error) { +// takeFamilyToken checks a token for host, uses it up, and returns the per-app token and where the browser was going. +func (s *Server) takeFamilyToken(raw, host string) (at, rd string, err error) { b, err := base64.RawURLEncoding.DecodeString(raw) if err != nil { return "", "", errors.New("malformed") @@ -180,7 +200,7 @@ func (s *Server) takeFamilyToken(raw, host string) (sid, rd string, err error) { if json.Unmarshal(b, &t) != nil { return "", "", errors.New("malformed") } - if !hmac.Equal([]byte(t.MAC), []byte(s.gateMAC("ftoken", t.Host, t.Sid, strconv.FormatInt(t.Exp, 10), t.Nonce, t.RD))) { + if !hmac.Equal([]byte(t.MAC), []byte(s.gateMAC("ftoken", t.Host, t.App, strconv.FormatInt(t.Exp, 10), t.Nonce, t.RD))) { return "", "", errors.New("bad signature") } if t.Host != host { @@ -202,11 +222,13 @@ func (s *Server) takeFamilyToken(raw, host string) (sid, rd string, err error) { return "", "", errors.New("already used") } s.gate.used["f:"+t.Nonce] = time.Unix(t.Exp, 0).Add(time.Second) - return t.Sid, t.RD, nil + return t.App, t.RD, nil } -// familyAppCookieSession: ".." → the session, if the cookie is genuine for -// this host, unexpired, and the store still holds the session (a removed member / reset / logout fails here). +// familyAppCookieSession: ".." → the session, if the cookie is +// genuine for this host, unexpired, and the store still holds the session the token was derived from (a removed +// member / reset / logout / dashboard password change fails here). A cookie of the old ".…" shape is +// refused: the browser goes through the sign-in start once more and gets the new shape. func (s *Server) familyAppCookieSession(r *http.Request, host string) (family.Session, bool) { c, err := r.Cookie(familyAppCookie) if err != nil { @@ -223,7 +245,7 @@ func (s *Server) familyAppCookieSession(r *http.Request, host string) (family.Se if !hmac.Equal([]byte(parts[2]), []byte(s.gateMAC("famcookie", host, parts[0], parts[1]))) { return family.Session{}, false } - return s.familyStore().Valid(parts[0]) + return s.familySessionForAppToken(host, parts[0]) } func familyRefuse(w http.ResponseWriter, code int) { @@ -256,9 +278,9 @@ func (s *Server) ServeFamilyGateAuth(w http.ResponseWriter, r *http.Request) { return } if u, err := url.Parse(uri); err == nil && u.Path == familyCallbackURI { - sid, rd, err := s.takeFamilyToken(u.Query().Get("t"), host) + at, rd, err := s.takeFamilyToken(u.Query().Get("t"), host) if err == nil { - if _, ok := s.familyStore().Valid(sid); !ok { + if _, ok := s.familySessionForAppToken(host, at); !ok { err = errors.New("the session ended") } } @@ -269,7 +291,7 @@ func (s *Server) ServeFamilyGateAuth(w http.ResponseWriter, r *http.Request) { } exp := strconv.FormatInt(s.gateNow().Add(family.SessionLife).Unix(), 10) http.SetCookie(w, &http.Cookie{ - Name: familyAppCookie, Value: sid + "." + exp + "." + s.gateMAC("famcookie", host, sid, exp), Path: "/", + Name: familyAppCookie, Value: at + "." + exp + "." + s.gateMAC("famcookie", host, at, exp), Path: "/", MaxAge: int(family.SessionLife.Seconds()), HttpOnly: true, Secure: true, SameSite: http.SameSiteLaxMode, }) s.logger.Printf("[INFO] [web] family gate %s: a signed-in browser passed — visitor %s", app, clientIP(r)) @@ -356,14 +378,16 @@ func (s *Server) ServeFamilyLogin(w http.ResponseWriter, r *http.Request) { } name := strings.ToLower(strings.TrimSpace(r.FormValue("name"))) visitor := rateKey(r) - if s.familyLocked(visitor, name) { + // R-983 (v0.324.0): the try is counted BEFORE the password is checked, in the same step as the lock check, so + // parallel tries cannot all pass a check none of them has counted yet. A right password clears both counts. + // Pinned by TestR983_ParallelFamilySignInsHitTheLimit. + if !s.familyReserve(visitor, name) { s.logger.Printf("[WARN] [web] family sign-in: too many wrong tries — visitor %s, name %q", visitor, name) s.renderFamilyPage(w, r, rd, s.msg(r, "family_gate.msg.locked"), http.StatusTooManyRequests) return } st := s.familyStore() if st == nil || !st.Verify(name, r.FormValue("password")) { - s.familyFailed(visitor, name) s.logger.Printf("[WARN] [web] family sign-in failed — visitor %s", visitor) s.renderFamilyPage(w, r, rd, s.msg(r, "family_gate.msg.wrong"), http.StatusUnauthorized) return @@ -385,12 +409,30 @@ func (s *Server) ServeFamilyLogin(w http.ResponseWriter, r *http.Request) { s.renderFamilyPage(w, r, "", s.msg(r, "family_gate.msg.signed_in"), http.StatusOK) } +// familyLogoutToken is the sign-out form's token, bound to the family session it ends (R-983, v0.324.0). The sign-in +// form's token (familyFormToken) is the same for every visitor, so a stranger could fetch one and use it; this one +// names the session, which another page never sees. +func (s *Server) familyLogoutToken(sid string) string { + return s.gateMAC("famlogout", sid) +} + // ServeFamilyLogout is /__family/logout: the family session ends, and every app cookie minted from it with it. +// R-983 (v0.324.0): only a POST from the sign-out form (familygate.html), carrying familyLogoutToken. Anything else — +// a GET, or a form another page built — changes nothing and shows the family page. Pinned by +// TestR983_FamilyLogoutNeedsItsToken. func (s *Server) ServeFamilyLogout(w http.ResponseWriter, r *http.Request) { - if c, err := r.Cookie(familySessionCookie); err == nil { - if err := s.familyStore().EndSession(c.Value); err != nil { - s.logger.Printf("[ERROR] [web] family sign-out: %v", err) - } + c, err := r.Cookie(familySessionCookie) + if r.Method != http.MethodPost || err != nil { + s.renderFamilyPage(w, r, "", "", http.StatusOK) + return + } + if !hmac.Equal([]byte(r.FormValue("_ft")), []byte(s.familyLogoutToken(c.Value))) { + s.logger.Printf("[WARN] [web] family sign-out refused: the form's token does not match the session — visitor %s", clientIP(r)) + s.renderFamilyPage(w, r, "", s.msg(r, "family_gate.msg.form_expired"), http.StatusForbidden) + return + } + if err := s.familyStore().EndSession(c.Value); err != nil { + s.logger.Printf("[ERROR] [web] family sign-out: %v", err) } http.SetCookie(w, &http.Cookie{Name: familySessionCookie, Value: "", Path: familyCookiePath, MaxAge: -1, HttpOnly: true, Secure: true}) s.renderFamilyPage(w, r, "", s.msg(r, "family_gate.msg.signed_out"), http.StatusOK) @@ -406,8 +448,9 @@ func (s *Server) renderFamilyPage(w http.ResponseWriter, r *http.Request, rd, no } } } - if _, ok := s.familySessionFromCookie(r); ok { + if se, ok := s.familySessionFromCookie(r); ok { data["SignedIn"] = true + data["LogoutToken"] = s.familyLogoutToken(se.ID) } w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Header().Set("Cache-Control", "no-store") diff --git a/controller/internal/web/family_gate_test.go b/controller/internal/web/family_gate_test.go index 9648f48..369ec83 100644 --- a/controller/internal/web/family_gate_test.go +++ b/controller/internal/web/family_gate_test.go @@ -213,7 +213,9 @@ func TestFamilyGate_ResetRemoveLogoutEndAccessAtOnce(t *testing.T) { } sess = login() app = famPass(t, s, sess) - r := httptest.NewRequest(http.MethodPost, "https://felhom.example.hu"+familyLogoutPath, nil) + r := httptest.NewRequest(http.MethodPost, "https://felhom.example.hu"+familyLogoutPath, + strings.NewReader(url.Values{"_ft": {s.familyLogoutToken(sess.Value)}}.Encode())) + r.Header.Set("Content-Type", "application/x-www-form-urlencoded") r.AddCookie(sess) s.ServeFamilyLogout(httptest.NewRecorder(), r) if ok(app) { diff --git a/controller/internal/web/handlers.go b/controller/internal/web/handlers.go index 0b4336b..b26c6bf 100644 --- a/controller/internal/web/handlers.go +++ b/controller/internal/web/handlers.go @@ -2507,6 +2507,7 @@ func (s *Server) securityPageData() map[string]interface{} { // EXISTS, and the value comes from POST /settings/retrieval-password/reveal, which is an // explicit authenticated act and is logged as one. data["HasRetrievalPassword"] = strings.TrimSpace(s.settings.GetRetrievalPassword()) != "" + data["MinPassword"] = claimMinPassword // R-983: the password form's minimum is the claim's data["HubURL"] = s.cfg.Hub.URL data["SupportEmail"] = "support@felhom.eu" data["SupportURL"] = "https://felhom.eu/kapcsolat" @@ -2848,9 +2849,10 @@ func (s *Server) settingsPasswordHandler(w http.ResponseWriter, r *http.Request) return } - // Validate new password length - if len(newPassword) < 8 { - data["PasswordError"] = s.msg(r, "settings.pw_too_short") + // Validate new password length. R-983 (v0.324.0): the claim's minimum (claim.go claimMinPassword), not 8 — one + // dashboard password, one rule, wherever it is set. Pinned by TestR983_SettingsPasswordMinimumIsTheClaims. + if len(newPassword) < claimMinPassword { + data["PasswordError"] = s.msg(r, "settings.pw_too_short", claimMinPassword) s.executeTemplate(w, r, "settings_security", data) return } @@ -2881,8 +2883,8 @@ func (s *Server) settingsPasswordHandler(w http.ResponseWriter, r *http.Request) s.logger.Printf("[INFO] [web] Password changed via settings page from %s", r.RemoteAddr) - // Invalidate all sessions (force re-login) - s.invalidateAllSessions() + // Invalidate all sessions (force re-login) — the dashboard's, the family gate's and every app gate pass (R-976). + s.endEverySession("password change") // Redirect to login with flash message http.Redirect(w, r, "/login?"+flashQuery("flash", "flash.login.password_changed"), http.StatusFound) diff --git a/controller/internal/web/i18n_cases_a_test.go b/controller/internal/web/i18n_cases_a_test.go index 8627c04..0dc7623 100644 --- a/controller/internal/web/i18n_cases_a_test.go +++ b/controller/internal/web/i18n_cases_a_test.go @@ -276,6 +276,7 @@ func i18nCasesA() []i18nCase { d["HasRetrievalPassword"] = true d["CustomerID"], d["HubURL"] = "test-customer", "https://hub.example" d["SupportEmail"], d["SupportURL"] = "support@example.hu", "https://example.hu/kapcsolat" + d["MinPassword"] = claimMinPassword // R-983 (v0.324.0): the claim's minimum, as securityPageData sets it return d }}, {"settings_security_noauth", "settings_security", func() map[string]interface{} { diff --git a/controller/internal/web/i18n_cases_c_test.go b/controller/internal/web/i18n_cases_c_test.go index e47f542..4393580 100644 --- a/controller/internal/web/i18n_cases_c_test.go +++ b/controller/internal/web/i18n_cases_c_test.go @@ -166,7 +166,8 @@ func i18nCasesC() []i18nCase { return m{"AppName": "Grimmory", "Host": "books.example.hu", "RD": "https://books.example.hu/", "FormToken": "FT"} }}, {"familygate_signed_in", "familygate", func() map[string]interface{} { - return m{"SignedIn": true, "Notice": "Beléptél. Nyisd meg újra az alkalmazást."} + // R-983 (v0.324.0): the sign-out form carries its session-bound token — re-captured for that line. + return m{"SignedIn": true, "Notice": "Beléptél. Nyisd meg újra az alkalmazást.", "LogoutToken": "LOGOUT-TOKEN"} }}, {"catchall_unknown", "catchall", func() map[string]interface{} { return m{"ControllerURL": "https://felhom.example.hu", "Status": "unknown", "StatusText": "Ez a cím nem tartozik alkalmazáshoz", "Host": "x.example.hu"} diff --git a/controller/internal/web/media_events.go b/controller/internal/web/media_events.go index da07fab..bc26d90 100644 --- a/controller/internal/web/media_events.go +++ b/controller/internal/web/media_events.go @@ -411,13 +411,22 @@ func (s *Server) applyPlexClaim(code string) error { s.logger.Printf("[WARN] [web] plex: claimed, but opening the setup gate failed: %v", oerr) } s.logger.Printf("[INFO] [web] plex: claimed — the setup gate is open (R-1028)") + // R-1065: the libraries are set by the media wiring, which needs the server's own token and so could + // not run while Plex was unclaimed. Trigger it now (debounced, with its retry) instead of leaving the + // household's libraries empty until the next drive event or restart. Pinned by + // TestPlexClaim_TriggersMediaWiring. + s.logger.Printf("[INFO] [web] plex: claimed — media wiring scheduled to set the libraries (R-1065)") + s.RunMediaWiringSoon("plex") return nil } - time.Sleep(time.Second) + time.Sleep(plexClaimPoll) } return &afterStartError{Status: http.StatusConflict, MsgKey: "err.plex_claim.not_claimed"} } +// plexClaimPoll is the wait between the „is it claimed yet" probes after a claim (a seam: tests poll without the wait). +var plexClaimPoll = time.Second + // plexHTTP is the client for the box's own calls to Plex (a seam: tests dial a fake that refuses the name „plex"). var plexHTTP = &http.Client{Timeout: 30 * time.Second} diff --git a/controller/internal/web/plex_claim_test.go b/controller/internal/web/plex_claim_test.go index 20d2fe2..51cb1f5 100644 --- a/controller/internal/web/plex_claim_test.go +++ b/controller/internal/web/plex_claim_test.go @@ -81,3 +81,47 @@ func TestPlexDonePress_RefusedWhileUnclaimed(t *testing.T) { t.Fatalf("„Kész” on a claimed Plex: HTTP %d, want 200", c) } } + +// R-1065: a claim that Plex confirms schedules the media wiring (which sets the libraries — it could +// not while Plex was unclaimed); a claim Plex refuses, or one Plex never reports as claimed, does not. +// The consequence asserted is the armed wiring timer — the same one a media app coming up arms. +// COMPANION RED-PROOF: drop the RunMediaWiringSoon call in applyPlexClaim → the claimed case fails. +func TestPlexClaim_TriggersMediaWiring(t *testing.T) { + oldClaim, oldClaimed, oldPoll := plexClaim, plexClaimed, plexClaimPoll + t.Cleanup(func() { plexClaim, plexClaimed, plexClaimPoll = oldClaim, oldClaimed, oldPoll }) + plexClaimPoll = 0 + for _, c := range []struct { + name string + status int + claimed bool + wantErr bool + wantWiring bool + }{ + {"claimed", http.StatusOK, true, false, true}, + {"plex refused the code", http.StatusUnauthorized, true, true, false}, + {"plex never says claimed", http.StatusOK, false, true, false}, + } { + t.Run(c.name, func(t *testing.T) { + s := gateHarness(t) + t.Cleanup(func() { + s.mediaMu.Lock() + if s.mediaSoonTmr != nil { + s.mediaSoonTmr.Stop() + } + s.mediaMu.Unlock() + }) + plexClaim = func(string) (int, error) { return c.status, nil } + plexClaimed = func() bool { return c.claimed } + err := s.applyPlexClaim("claim-AbCdEf123456789xyz") + if (err != nil) != c.wantErr { + t.Fatalf("applyPlexClaim err=%v, want error=%v", err, c.wantErr) + } + s.mediaMu.Lock() + armed := s.mediaSoonTmr != nil + s.mediaMu.Unlock() + if armed != c.wantWiring { + t.Errorf("media wiring scheduled=%v, want %v", armed, c.wantWiring) + } + }) + } +} diff --git a/controller/internal/web/r255_secret_sweep_test.go b/controller/internal/web/r255_secret_sweep_test.go index 243c68e..087b4b5 100644 --- a/controller/internal/web/r255_secret_sweep_test.go +++ b/controller/internal/web/r255_secret_sweep_test.go @@ -48,9 +48,11 @@ import ( var secretNameRe = regexp.MustCompile(`(?i)(pass(word|phrase)|secret|token|api_?key|private_?key|recovery_?code|credential|_key$)`) // notSecretNames are names the pattern matches that carry no secret: the CSRF tokens a form must carry -// (session-bound, useless without the session) and a password-change ERROR MESSAGE. +// (session-bound, useless without the session) and a password-change ERROR MESSAGE. LogoutToken (R-983, v0.324.0) is +// the family sign-out form's CSRF token: an HMAC naming the family session, useless without that session's cookie. var notSecretNames = map[string]bool{ "CSRFToken": true, "CSRFField": true, "FormToken": true, "LangCSRF": true, "PasswordError": true, + "LogoutToken": true, } const plantedPrefix = "PLANTEDSECRET" diff --git a/controller/internal/web/r983_r976_test.go b/controller/internal/web/r983_r976_test.go new file mode 100644 index 0000000..a166193 --- /dev/null +++ b/controller/internal/web/r983_r976_test.go @@ -0,0 +1,452 @@ +package web + +import ( + "encoding/base64" + "errors" + "fmt" + "html" + "net/http" + "net/http/httptest" + "net/url" + "regexp" + "strconv" + "strings" + "sync" + "sync/atomic" + "testing" + "time" + + "golang.org/x/crypto/bcrypt" +) + +// R-983 (security review 2026-10-12, six remaining items) and R-976 (family and gate sessions), v0.324.0. Each test +// drives the handler the browser or traefik reaches. Red-proofs are recorded in the REPORT of the release. + +// ── R-983 item 1: after sign-in the browser stays on the box ───────────────────────────────────────────────── + +func TestR983_LoginNextStaysOnTheBox(t *testing.T) { + s := rateLimitTestServer(t) + login := func(next string) string { + form := url.Values{"password": {"correct-pass"}, "next": {next}} + r := httptest.NewRequest(http.MethodPost, "/login", strings.NewReader(form.Encode())) + r.Header.Set("Content-Type", "application/x-www-form-urlencoded") + r.RemoteAddr = "203.0.113.7:4000" + w := httptest.NewRecorder() + s.handleLogin(w, r) + if w.Code != http.StatusFound { + t.Fatalf("next=%q: sign-in answered %d, want 302", next, w.Code) + } + return w.Header().Get("Location") + } + for _, evil := range []string{"//evil.example/x", "/\\evil.example", "https://evil.example/", "/\\/evil.example"} { + if got := login(evil); got != "/" { + t.Errorf("next=%q sent the signed-in browser to %q — want /", evil, got) + } + } + if got := login("/stacks?tab=1"); got != "/stacks?tab=1" { + t.Errorf("a page on the box must still be the destination: got %q", got) + } +} + +// ── R-983 item 2: no page of the dashboard may be framed ───────────────────────────────────────────────────── + +func TestR983_DashboardRefusesFraming(t *testing.T) { + s, _ := familyHarness(t) + reached := false + h := s.CatchAllMiddleware(s.RequireAuth(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + reached = true + w.WriteHeader(http.StatusOK) + }))) + sess := &http.Cookie{Name: sessionCookieName, Value: newTestSession(s)} + for _, p := range []string{"/launcher", "/login", familyLoginPath, "/settings/security"} { + r := httptest.NewRequest(http.MethodGet, "https://felhom.example.hu"+p, nil) + r.AddCookie(sess) + w := httptest.NewRecorder() + h.ServeHTTP(w, r) + if got := w.Header().Get("X-Frame-Options"); got != "DENY" { + t.Errorf("%s: X-Frame-Options %q, want DENY", p, got) + } + if got := w.Header().Get("Content-Security-Policy"); got != "frame-ancestors 'none'" { + t.Errorf("%s: Content-Security-Policy %q, want frame-ancestors 'none'", p, got) + } + } + if !reached { + t.Fatal("the signed-in page was never reached — the test proved nothing about a real page") + } + // traefik's forwardAuth answers stay as they were: their headers must not ride onto an app's responses. + r := httptest.NewRequest(http.MethodGet, "http://felhom-controller:8080"+familyAuthPath, nil) + r.Header.Set("X-Forwarded-Host", "fapp.example.hu") + w := httptest.NewRecorder() + h.ServeHTTP(w, r) + if w.Header().Get("X-Frame-Options") != "" || w.Header().Get("Content-Security-Policy") != "" { + t.Error("the forwardAuth answer must carry no framing header") + } +} + +// ── R-983 item 3: parallel sign-in tries are counted ───────────────────────────────────────────────────────── + +// The compare is a seam that waits until every try has arrived (or a short deadline): with check-then-count all 20 +// tries reach it; with the try reserved first only loginMaxAttempts do. +func TestR983_ParallelLoginsHitTheLimit(t *testing.T) { + s := rateLimitTestServer(t) + const tries = 20 + var calls int32 + all := make(chan struct{}) + var once sync.Once + s.passwordCompare = func(hash, pw []byte) error { + if atomic.AddInt32(&calls, 1) == tries { + once.Do(func() { close(all) }) + } + select { + case <-all: + case <-time.After(400 * time.Millisecond): + } + return errors.New("mismatch") + } + var wg sync.WaitGroup + start := make(chan struct{}) + for i := 0; i < tries; i++ { + wg.Add(1) + go func(i int) { + defer wg.Done() + <-start + doLogin(s, fmt.Sprintf("198.51.100.9:%d", 6000+i), "", "wrong") + }(i) + } + close(start) + wg.Wait() + if got := atomic.LoadInt32(&calls); got > loginMaxAttempts { + t.Fatalf("%d parallel wrong tries reached the password compare — the limit is %d per visitor", got, loginMaxAttempts) + } + // and the household's right password is still refused only for this visitor, not for everyone + s.passwordCompare = nil + if body := doLogin(s, "203.0.113.50:7000", "", "correct-pass"); body.Code != http.StatusFound { + t.Fatalf("another visitor with the right password must get in: %d", body.Code) + } +} + +func TestR983_ParallelFamilySignInsHitTheLimit(t *testing.T) { + s, st := familyHarness(t) + st.SetCost(10) // a real compare takes tens of milliseconds, so the tries overlap + if _, err := st.Add("anna"); err != nil { + t.Fatal(err) + } + const tries = 20 + var wrong, locked int32 + var wg sync.WaitGroup + start := make(chan struct{}) + for i := 0; i < tries; i++ { + wg.Add(1) + go func() { + defer wg.Done() + <-start + switch famLogin(s, "198.51.100.66", "anna", "wrong", "").Code { + case http.StatusUnauthorized: + atomic.AddInt32(&wrong, 1) + case http.StatusTooManyRequests: + atomic.AddInt32(&locked, 1) + } + }() + } + close(start) + wg.Wait() + if wrong > familyVisitorMax { + t.Fatalf("%d parallel tries had their password checked — the limit is %d per visitor (locked: %d)", wrong, familyVisitorMax, locked) + } + if wrong+locked != tries { + t.Fatalf("every try must be answered as wrong or locked: %d + %d of %d", wrong, locked, tries) + } +} + +// ── R-983 item 4: the settings page's minimum is the claim's ───────────────────────────────────────────────── + +func TestR983_SettingsPasswordMinimumIsTheClaims(t *testing.T) { + if claimMinPassword != 12 { + t.Fatalf("the claim's minimum moved to %d — this test's literals assume 12", claimMinPassword) + } + s, _ := familyHarness(t) + tok := newTestSession(s) + change := func(pw string) *httptest.ResponseRecorder { + form := url.Values{"current_password": {"dashboard-pass"}, "new_password": {pw}, "confirm_password": {pw}} + r := httptest.NewRequest(http.MethodPost, "https://felhom.example.hu/settings/password", strings.NewReader(form.Encode())) + r.Header.Set("Content-Type", "application/x-www-form-urlencoded") + r.AddCookie(&http.Cookie{Name: sessionCookieName, Value: tok}) + w := httptest.NewRecorder() + s.settingsPasswordHandler(w, r) + return w + } + w := change("eleven-char") + if w.Code == http.StatusFound { + t.Fatal("an 11-character password was accepted — the claim requires 12") + } + if !strings.Contains(w.Body.String(), "legalább 12 karakter") { + t.Errorf("the refusal must name the claim's minimum (Hungarian)") + } + if bcrypt.CompareHashAndPassword([]byte(s.effectivePasswordHash()), []byte("dashboard-pass")) != nil { + t.Fatal("the refused change altered the password") + } + // the page's own form says the same minimum (both languages render it from one value) + page := w.Body.String() + if !strings.Contains(page, `minlength="12"`) || strings.Contains(page, `minlength="8"`) { + t.Errorf("the password form must ask for at least 12 characters") + } + if got := s.msgLang("en", "settings.pw_too_short", claimMinPassword); !strings.Contains(got, "at least 12 characters") { + t.Errorf("English refusal %q must name 12", got) + } + if w := change("twelve-chars"); w.Code != http.StatusFound { + t.Fatalf("a 12-character password must be accepted: %d", w.Code) + } +} + +// ── R-983 item 5: reset-code requests are limited on the box ───────────────────────────────────────────────── + +func TestR983_ResetCodeRequestsAreLimited(t *testing.T) { + s, _, _ := claimTestServer(t) + now := time.Date(2026, 10, 16, 2, 0, 0, 0, time.UTC) + s.claimClock = func() time.Time { return now } + var calls int + s.resetRequestFn = func() { calls++ } + ask := func(visitor string) { + form := url.Values{"_csrf": {s.claimCSRFToken()}} + r := httptest.NewRequest(http.MethodPost, "/claim/request-new-code", strings.NewReader(form.Encode())) + r.Header.Set("Content-Type", "application/x-www-form-urlencoded") + r.AddCookie(&http.Cookie{Name: claimCSRFCookie, Value: s.claimCSRFToken()}) + r.RemoteAddr = visitor + ":5000" + w := httptest.NewRecorder() + s.handleClaimRequestNewCode(w, r) + if w.Code != http.StatusOK { + t.Fatalf("the answer must stay the neutral page: %d", w.Code) + } + } + for i := 0; i < 3; i++ { + ask("198.51.100.1") + } + if calls != 1 { + t.Fatalf("3 requests in one minute from one visitor reached the hub %d times — want 1", calls) + } + now = now.Add(resetReqVisitorEvery + time.Second) + ask("198.51.100.1") + if calls != 2 { + t.Fatalf("after a minute the same visitor must reach the hub again: %d calls", calls) + } + ask("198.51.100.2") + ask("198.51.100.3") // the box's budget for the quarter hour is used here + if calls != resetReqGlobalMax { + t.Fatalf("calls %d, want %d", calls, resetReqGlobalMax) + } + ask("198.51.100.4") + if calls != resetReqGlobalMax { + t.Fatalf("a fourth visitor in the same quarter hour reached the hub: %d calls", calls) + } + now = now.Add(resetReqGlobalWindow) + ask("198.51.100.4") + if calls != resetReqGlobalMax+1 { + t.Fatalf("after the window a request must reach the hub again (the household is not locked out for long): %d", calls) + } +} + +// ── R-983 item 6: logout cannot be triggered from another page ─────────────────────────────────────────────── + +func TestR983_LogoutNeedsCSRF(t *testing.T) { + s, _ := familyHarness(t) + tok := newTestSession(s) + h := s.RequireAuth(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(299) })) + out := func(method, csrf string) *httptest.ResponseRecorder { + var body *strings.Reader + if csrf != "" { + body = strings.NewReader(url.Values{csrfFormField: {csrf}}.Encode()) + } else { + body = strings.NewReader("") + } + r := httptest.NewRequest(method, "https://felhom.example.hu/logout", body) + r.Header.Set("Content-Type", "application/x-www-form-urlencoded") + r.AddCookie(&http.Cookie{Name: sessionCookieName, Value: tok}) + w := httptest.NewRecorder() + h.ServeHTTP(w, r) + return w + } + if w := out(http.MethodPost, ""); w.Code != http.StatusForbidden || !s.isValidSession(tok) { + t.Fatalf("a POST without the token: %d, session valid %v — want 403 and the session kept", w.Code, s.isValidSession(tok)) + } + if w := out(http.MethodPost, "not-the-token"); w.Code != http.StatusForbidden || !s.isValidSession(tok) { + t.Fatalf("a POST with a wrong token: %d — want 403 and the session kept", w.Code) + } + if w := out(http.MethodGet, ""); w.Code != http.StatusFound || w.Header().Get("Location") != "/" || !s.isValidSession(tok) { + t.Fatalf("a GET must change nothing: %d %q", w.Code, w.Header().Get("Location")) + } + // The dashboard's own control: a POST form carrying the session's token. + r := httptest.NewRequest(http.MethodGet, "https://felhom.example.hu/settings/security", nil) + r.AddCookie(&http.Cookie{Name: sessionCookieName, Value: tok}) + pw := httptest.NewRecorder() + s.settingsSecurityPageHandler(pw, r) + m := regexp.MustCompile(`
`).FindStringSubmatch(pw.Body.String()) + if m == nil { + t.Fatal("the dashboard's sign-out control must be a POST form carrying the session's token") + } + if w := out(http.MethodPost, m[1]); w.Code != http.StatusFound || w.Header().Get("Location") != "/login" || s.isValidSession(tok) { + t.Fatalf("the dashboard's own sign-out: %d %q, session valid %v — want 302 /login and the session ended", w.Code, w.Header().Get("Location"), s.isValidSession(tok)) + } +} + +func TestR983_FamilyLogoutNeedsItsToken(t *testing.T) { + s, st := familyHarness(t) + pw, _ := st.Add("anna") + sess := famCookie(famLogin(s, "203.0.113.10", "anna", pw, ""), familySessionCookie) + app := famPass(t, s, sess) + ok := func() bool { + return famAsk(s, "fapp.example.hu", "GET", "/", "application/json", app).Code == http.StatusOK + } + out := func(method, ft string) *httptest.ResponseRecorder { + r := httptest.NewRequest(method, "https://felhom.example.hu"+familyLogoutPath, strings.NewReader(url.Values{"_ft": {ft}}.Encode())) + r.Header.Set("Content-Type", "application/x-www-form-urlencoded") + r.AddCookie(sess) + w := httptest.NewRecorder() + s.ServeFamilyLogout(w, r) + return w + } + out(http.MethodGet, "") + out(http.MethodPost, "") + out(http.MethodPost, s.familyFormToken()) // the sign-in form's token: anyone can fetch one + if !ok() { + t.Fatal("a GET, a tokenless POST or a POST with the sign-in form's token ended the family session") + } + // the page's own sign-out form carries the session's token, and that ends it + r := httptest.NewRequest(http.MethodGet, "https://felhom.example.hu"+familyLoginPath, nil) + r.AddCookie(sess) + pg := httptest.NewRecorder() + s.ServeFamilyLogin(pg, r) + m := regexp.MustCompile(`action="/__family/logout">\s*`).FindStringSubmatch(pg.Body.String()) + if m == nil { + t.Fatal("the family page's sign-out form must carry its token") + } + if w := out(http.MethodPost, html.UnescapeString(m[1])); w.Code != http.StatusOK { + t.Fatalf("the page's own sign-out: %d", w.Code) + } + if ok() { + t.Fatal("the family page's own sign-out must end the session") + } +} + +// ── R-976 (b): a family app cookie cannot be lifted into another app ───────────────────────────────────────── + +func TestR976_AnAppCookieCannotBeLiftedIntoAnotherApp(t *testing.T) { + s, st := familyHarness(t) + pw, _ := st.Add("anna") + sess := famCookie(famLogin(s, "203.0.113.10", "anna", pw, ""), familySessionCookie) + app := famPass(t, s, sess) + if strings.Contains(app.Value, sess.Value) { + t.Fatal("the app cookie carries the family session itself — an app's backend could lift it") + } + // what an app backend sees, set as the family session on the dashboard host, must mint nothing + lifted := strings.SplitN(app.Value, ".", 2)[0] + rd := "https://fapp.example.hu/" + r := httptest.NewRequest(http.MethodGet, "https://felhom.example.hu"+familyStartPath+"?"+url.Values{"rd": {rd}}.Encode(), nil) + r.AddCookie(&http.Cookie{Name: familySessionCookie, Value: lifted}) + w := httptest.NewRecorder() + s.ServeFamilyStart(w, r) + if loc := w.Header().Get("Location"); strings.Contains(loc, familyCallbackURI) { + t.Fatalf("a value lifted from an app cookie minted a pass: %q", loc) + } + // the sign-in token in flight carries no session either + tok := s.mintFamilyToken("fapp.example.hu", sess.Value, rd) + if dec, _ := base64.RawURLEncoding.DecodeString(tok); strings.Contains(string(dec), sess.Value) { + t.Fatal("the sign-in token carries the family session id") + } + // a cookie of the old shape (the session id itself, correctly signed) is refused + exp := strconv.FormatInt(time.Now().Add(time.Hour).Unix(), 10) + old := &http.Cookie{Name: familyAppCookie, Value: sess.Value + "." + exp + "." + s.gateMAC("famcookie", "fapp.example.hu", sess.Value, exp)} + if w := famAsk(s, "fapp.example.hu", "GET", "/", "application/json", old); w.Code == http.StatusOK { + t.Fatal("an app cookie carrying the session id must not pass any more") + } + // the genuine cookie still passes its own app + if w := famAsk(s, "fapp.example.hu", "GET", "/", "application/json", app); w.Code != http.StatusOK { + t.Fatalf("the member's own app cookie must pass: %d", w.Code) + } +} + +// ── R-976 (a): a password change or reset ends every family and gate session ───────────────────────────────── + +// r976World signs anna in (family session + app cookie) and walks the household through the setup gate (gate pass). +func r976World(t *testing.T, s *Server) (famSess, famApp, gatePass *http.Cookie) { + t.Helper() + pw, err := s.familyStore().Add("anna") + if err != nil { + t.Fatal(err) + } + famSess = famCookie(famLogin(s, "203.0.113.10", "anna", pw, ""), familySessionCookie) + famApp = famPass(t, s, famSess) + dash := &http.Cookie{Name: sessionCookieName, Value: newTestSession(s)} + w := gateStart(s, "https://gapp.example.hu/", dash) + cb, _ := url.Parse(w.Header().Get("Location")) + w = gateAsk(s, "gapp.example.hu", "GET", cb.RequestURI(), "text/html") + for _, c := range w.Result().Cookies() { + if c.Name == gateCookieName { + gatePass = c + } + } + if gatePass == nil { + t.Fatal("setup: no gate pass") + } + r976AllOpen(t, s, famSess, famApp, gatePass, true) + return famSess, famApp, gatePass +} + +func r976AllOpen(t *testing.T, s *Server, famSess, famApp, gatePass *http.Cookie, want bool) { + t.Helper() + appOK := famAsk(s, "fapp.example.hu", "GET", "/", "application/json", famApp).Code == http.StatusOK + gateOK := gateAsk(s, "gapp.example.hu", "GET", "/", "application/json", gatePass).Code == http.StatusOK + r := httptest.NewRequest(http.MethodGet, "https://felhom.example.hu"+familyStartPath+"?"+url.Values{"rd": {"https://fapp.example.hu/"}}.Encode(), nil) + r.AddCookie(famSess) + w := httptest.NewRecorder() + s.ServeFamilyStart(w, r) + sessOK := strings.Contains(w.Header().Get("Location"), familyCallbackURI) + if appOK != want || gateOK != want || sessOK != want { + t.Fatalf("family app cookie passes %v, setup gate pass passes %v, family session mints %v — want all %v", appOK, gateOK, sessOK, want) + } +} + +func TestR976_PasswordChangeEndsFamilyAndGateSessions(t *testing.T) { + s, st := familyHarness(t) + famSess, famApp, gatePass := r976World(t, s) + form := url.Values{"current_password": {"dashboard-pass"}, "new_password": {"a-new-password-12"}, "confirm_password": {"a-new-password-12"}} + r := httptest.NewRequest(http.MethodPost, "https://felhom.example.hu/settings/password", strings.NewReader(form.Encode())) + r.Header.Set("Content-Type", "application/x-www-form-urlencoded") + w := httptest.NewRecorder() + s.settingsPasswordHandler(w, r) + if w.Code != http.StatusFound { + t.Fatalf("the password change: %d", w.Code) + } + r976AllOpen(t, s, famSess, famApp, gatePass, false) + // the members stay; anna signs in again with her own password + if names := st.Names(); len(names) != 1 || names[0] != "anna" { + t.Fatalf("the family list must be kept: %v", names) + } +} + +func TestR976_ClaimResetEndsFamilyAndGateSessions(t *testing.T) { + s, _ := familyHarness(t) + s.cfg.Web.SessionSecret = "test-session-secret-abcdef" + code := "alma-korte-szilva" + hash, _ := bcrypt.GenerateFromPassword([]byte(code), bcrypt.MinCost) + if err := s.settings.SetClaimCode(string(hash), 1, time.Now().UTC().Format(time.RFC3339)); err != nil { + t.Fatal(err) + } + famSess, famApp, gatePass := r976World(t, s) + form := url.Values{"_csrf": {s.claimCSRFToken()}, "code": {code}, "new_password": {"a-new-password-12"}, "confirm_password": {"a-new-password-12"}} + r := httptest.NewRequest(http.MethodPost, "/claim", strings.NewReader(form.Encode())) + r.Header.Set("Content-Type", "application/x-www-form-urlencoded") + r.AddCookie(&http.Cookie{Name: claimCSRFCookie, Value: s.claimCSRFToken()}) + w := httptest.NewRecorder() + s.handleClaimSubmit(w, r) + if w.Code != http.StatusFound || w.Header().Get("Location") != "/" { + t.Fatalf("the reset: %d %q", w.Code, w.Header().Get("Location")) + } + r976AllOpen(t, s, famSess, famApp, gatePass, false) + // a restart must not bring the old passes back: the rotated key is what is on disk + s2 := &Server{cfg: s.cfg, settings: s.settings, stackMgr: s.stackMgr, logger: s.logger, version: "test", + sessions: map[string]*session{}, familyStoreOverride: s.familyStoreOverride} + s2.loadTemplates() + if w := gateAsk(s2, "gapp.example.hu", "GET", "/", "application/json", gatePass); w.Code == http.StatusOK { + t.Fatal("after a restart the old gate pass opened the app again") + } +} diff --git a/controller/internal/web/server.go b/controller/internal/web/server.go index c59a4f0..143b2b6 100644 --- a/controller/internal/web/server.go +++ b/controller/internal/web/server.go @@ -74,8 +74,11 @@ type Server struct { sessionsMu sync.RWMutex loginAttempts map[string]*loginAttempt loginAttemptMu sync.Mutex - done chan struct{} - closeOnce sync.Once + // passwordCompare replaces bcrypt's compare at the dashboard sign-in in tests (R-983: a slow compare makes the + // parallel-try race measurable). nil → bcrypt. + passwordCompare func(hash, pw []byte) error + done chan struct{} + closeOnce sync.Once // Guest launcher share (v0.165.0): its OWN per-IP brute-force limiter for the optional share // password gate — deliberately separate from loginAttempts (the admin login), so a guest and the @@ -89,6 +92,11 @@ type Server struct { claimAttempts map[string]*claimAttempt claimGlobal claimAttempt claimClock func() time.Time + // R-983 (v0.324.0): the reset-code request's own limit, under claimMu and claimClock — when each visitor last + // reached the hub, and when the box last did (a sliding window). resetRequestFn replaces the hub call in tests. + resetReqVisitor map[string]time.Time + resetReqGlobal []time.Time + resetRequestFn func() // Guard for FileBrowser sync — prevents concurrent file writes (H5 fix) fileBrowserMu sync.Mutex @@ -975,6 +983,15 @@ func (s *Server) CatchAllMiddleware(next http.Handler) http.Handler { s.ServeFamilyGateAuth(w, r) return } + // R-983 (v0.324.0): no page of ours may be shown inside another page's frame. Every app on *. is + // SAME-SITE with the dashboard, so the Lax session cookie goes along into a frame an app page draws — a page + // on any app host could lay the signed-in dashboard under its own buttons. Nothing frames the dashboard + // legitimately (no iframe in the controller, the catalog, the hub or the website, checked 2026-10-16), so + // DENY rather than SAMEORIGIN. The two forwardAuth answers above are left exactly as they were: traefik + // reads them, and their headers must not leak onto an app's own responses. Pinned by + // TestR983_DashboardRefusesFraming. + w.Header().Set("X-Frame-Options", "DENY") + w.Header().Set("Content-Security-Policy", "frame-ancestors 'none'") if strings.EqualFold(host, controllerHost) { switch r.URL.Path { // v0.287.0: the family sign-in pages, outside the dashboard's own auth on purpose case familyStartPath: diff --git a/controller/internal/web/session_store_test.go b/controller/internal/web/session_store_test.go index a2c8c8f..ffb84d8 100644 --- a/controller/internal/web/session_store_test.go +++ b/controller/internal/web/session_store_test.go @@ -125,6 +125,7 @@ func TestR35_LogoutEndsSessionAcrossRestart(t *testing.T) { t.Fatal("setup: the session must survive one restart first") } req := httptest.NewRequest(http.MethodPost, "/logout", nil) + req.Header.Set(csrfHeaderName, s2.csrfTokenForSession(tok)) // R-983: the sign-out carries the session's token req.AddCookie(&http.Cookie{Name: sessionCookieName, Value: tok}) s2.handleLogout(httptest.NewRecorder(), req) if s2.isValidSession(tok) { @@ -235,6 +236,7 @@ func TestR35_FailedLogoutSaveRemovesFile(t *testing.T) { t.Fatal(err) } req := httptest.NewRequest(http.MethodPost, "/logout", nil) + req.Header.Set(csrfHeaderName, s2.csrfTokenForSession(tok)) // R-983: the sign-out carries the session's token req.AddCookie(&http.Cookie{Name: sessionCookieName, Value: tok}) s2.handleLogout(httptest.NewRecorder(), req) s2.Close() diff --git a/controller/internal/web/setup_gate.go b/controller/internal/web/setup_gate.go index 1b682d6..92cabb7 100644 --- a/controller/internal/web/setup_gate.go +++ b/controller/internal/web/setup_gate.go @@ -53,10 +53,11 @@ const ( ) type gateState struct { - once sync.Once - key []byte - mu sync.Mutex - used map[string]time.Time // token nonces already swapped, until they expire + once sync.Once + keyMu sync.RWMutex // guards key: rotateGateKey replaces it while requests read it + key []byte + mu sync.Mutex + used map[string]time.Time // token nonces already swapped, until they expire } // gateKey loads the gate's HMAC key from the data dir, or makes one. No data dir → a key for this run only. @@ -82,9 +83,41 @@ func (s *Server) gateKey() []byte { } } }) + s.gate.keyMu.RLock() + defer s.gate.keyMu.RUnlock() return s.gate.key } +// rotateGateKey replaces the gate's key (R-976, v0.324.0). Every cookie and token the key signed stops opening +// anything at once: each setup-gate pass, each family app cookie, each sign-in token in flight. The household's +// browser passes again through its dashboard session. The new key is saved tmp+rename; when that fails the old file +// is REMOVED, so a restart makes a fresh key rather than bringing the old one — and every cookie it signed — back. +func (s *Server) rotateGateKey() { + s.gateKey() + k := make([]byte, 32) + _, _ = rand.Read(k) + s.gate.keyMu.Lock() + s.gate.key = k + s.gate.keyMu.Unlock() + if s.cfg == nil || s.cfg.Paths.DataDir == "" { + return + } + p := filepath.Join(s.cfg.Paths.DataDir, "setup-gate.key") + tmp := p + ".tmp" + err := os.WriteFile(tmp, []byte(hex.EncodeToString(k)), 0o600) + if err == nil { + err = os.Rename(tmp, p) + } + if err != nil { + _ = os.Remove(tmp) + if rerr := os.Remove(p); rerr != nil && !os.IsNotExist(rerr) { + s.logger.Printf("[ERROR] [web] gate key: the new key could not be saved (%v) and the old one could not be removed (%v) — a restart would accept passes signed before the password change", err, rerr) + return + } + s.logger.Printf("[WARN] [web] gate key: the new key could not be saved (%v) — the old one was removed, so a restart makes a fresh key", err) + } +} + func (s *Server) gateMAC(parts ...string) string { m := hmac.New(sha256.New, s.gateKey()) m.Write([]byte(strings.Join(parts, "\x00"))) diff --git a/controller/internal/web/templates/familygate.html b/controller/internal/web/templates/familygate.html index 8b6342f..2a9a5c1 100644 --- a/controller/internal/web/templates/familygate.html +++ b/controller/internal/web/templates/familygate.html @@ -20,6 +20,7 @@ {{- if .SignedIn}}

{{T "family_gate.signed_in_note"}}

+ {{- else}} diff --git a/controller/internal/web/templates/layout.html b/controller/internal/web/templates/layout.html index bbf972c..5848ced 100644 --- a/controller/internal/web/templates/layout.html +++ b/controller/internal/web/templates/layout.html @@ -125,7 +125,7 @@ diff --git a/controller/internal/web/templates/settings_security.html b/controller/internal/web/templates/settings_security.html index 772a35f..9a6d050 100644 --- a/controller/internal/web/templates/settings_security.html +++ b/controller/internal/web/templates/settings_security.html @@ -19,12 +19,12 @@
- +
-
diff --git a/controller/internal/web/templates/style.css b/controller/internal/web/templates/style.css index d5c7220..c937033 100644 --- a/controller/internal/web/templates/style.css +++ b/controller/internal/web/templates/style.css @@ -150,7 +150,8 @@ body { .lang-globe-item:hover { color: var(--blue-bright); } .lang-globe-item.current { color: var(--text-1); font-weight: 600; } .lang-globe-item.current::after { content: " \2713"; } -.logout-link { color: var(--text-3); text-decoration: none; transition: color 0.2s ease; } +.logout-form { display: inline; margin: 0; } +.logout-link { color: var(--text-3); text-decoration: none; transition: color 0.2s ease; background: none; border: 0; padding: 0; font: inherit; cursor: pointer; } .logout-link:hover { color: var(--blue-bright); } /* Mobile chrome (v0.166.0) — hidden by default so desktop (>768px) stays pixel-identical; the ≤768px block below turns the top bar on and converts the sidebar into an off-canvas drawer. */ diff --git a/controller/internal/web/testdata/i18n_parity/app_data_deployed.html b/controller/internal/web/testdata/i18n_parity/app_data_deployed.html index 26083b7..66bb828 100644 --- a/controller/internal/web/testdata/i18n_parity/app_data_deployed.html +++ b/controller/internal/web/testdata/i18n_parity/app_data_deployed.html @@ -159,7 +159,7 @@
  • - Kijelentkezés ↗ +
    diff --git a/controller/internal/web/testdata/i18n_parity/app_data_export.html b/controller/internal/web/testdata/i18n_parity/app_data_export.html index 620fdd1..1a3f9d4 100644 --- a/controller/internal/web/testdata/i18n_parity/app_data_export.html +++ b/controller/internal/web/testdata/i18n_parity/app_data_export.html @@ -159,7 +159,7 @@
  • - Kijelentkezés ↗ +
    diff --git a/controller/internal/web/testdata/i18n_parity/app_data_files_media.html b/controller/internal/web/testdata/i18n_parity/app_data_files_media.html index 494072a..967a87b 100644 --- a/controller/internal/web/testdata/i18n_parity/app_data_files_media.html +++ b/controller/internal/web/testdata/i18n_parity/app_data_files_media.html @@ -159,7 +159,7 @@
  • - Kijelentkezés ↗ +
    diff --git a/controller/internal/web/testdata/i18n_parity/app_data_not_hdd.html b/controller/internal/web/testdata/i18n_parity/app_data_not_hdd.html index 595ff1f..dd31322 100644 --- a/controller/internal/web/testdata/i18n_parity/app_data_not_hdd.html +++ b/controller/internal/web/testdata/i18n_parity/app_data_not_hdd.html @@ -159,7 +159,7 @@
  • - Kijelentkezés ↗ +
    diff --git a/controller/internal/web/testdata/i18n_parity/app_data_not_hdd_absent.html b/controller/internal/web/testdata/i18n_parity/app_data_not_hdd_absent.html index cf590f0..9faec1e 100644 --- a/controller/internal/web/testdata/i18n_parity/app_data_not_hdd_absent.html +++ b/controller/internal/web/testdata/i18n_parity/app_data_not_hdd_absent.html @@ -159,7 +159,7 @@
  • - Kijelentkezés ↗ +
    diff --git a/controller/internal/web/testdata/i18n_parity/app_data_not_hdd_protected.html b/controller/internal/web/testdata/i18n_parity/app_data_not_hdd_protected.html index 48f18a4..dac6110 100644 --- a/controller/internal/web/testdata/i18n_parity/app_data_not_hdd_protected.html +++ b/controller/internal/web/testdata/i18n_parity/app_data_not_hdd_protected.html @@ -159,7 +159,7 @@
  • - Kijelentkezés ↗ +
    diff --git a/controller/internal/web/testdata/i18n_parity/app_data_not_hdd_same_disk.html b/controller/internal/web/testdata/i18n_parity/app_data_not_hdd_same_disk.html index 51fc026..7a59ca8 100644 --- a/controller/internal/web/testdata/i18n_parity/app_data_not_hdd_same_disk.html +++ b/controller/internal/web/testdata/i18n_parity/app_data_not_hdd_same_disk.html @@ -159,7 +159,7 @@
  • - Kijelentkezés ↗ +
    diff --git a/controller/internal/web/testdata/i18n_parity/app_data_notarget_disabled.html b/controller/internal/web/testdata/i18n_parity/app_data_notarget_disabled.html index 61de671..d0abdff 100644 --- a/controller/internal/web/testdata/i18n_parity/app_data_notarget_disabled.html +++ b/controller/internal/web/testdata/i18n_parity/app_data_notarget_disabled.html @@ -159,7 +159,7 @@
  • - Kijelentkezés ↗ +
    diff --git a/controller/internal/web/testdata/i18n_parity/app_data_target_auto.html b/controller/internal/web/testdata/i18n_parity/app_data_target_auto.html index 0aeab1b..4f96610 100644 --- a/controller/internal/web/testdata/i18n_parity/app_data_target_auto.html +++ b/controller/internal/web/testdata/i18n_parity/app_data_target_auto.html @@ -159,7 +159,7 @@
  • - Kijelentkezés ↗ +
    diff --git a/controller/internal/web/testdata/i18n_parity/app_data_target_ssd.html b/controller/internal/web/testdata/i18n_parity/app_data_target_ssd.html index 4a90fe6..6e3d42e 100644 --- a/controller/internal/web/testdata/i18n_parity/app_data_target_ssd.html +++ b/controller/internal/web/testdata/i18n_parity/app_data_target_ssd.html @@ -159,7 +159,7 @@
  • - Kijelentkezés ↗ +
    diff --git a/controller/internal/web/testdata/i18n_parity/app_guide_available.html b/controller/internal/web/testdata/i18n_parity/app_guide_available.html index e69fe1a..dafeaf9 100644 --- a/controller/internal/web/testdata/i18n_parity/app_guide_available.html +++ b/controller/internal/web/testdata/i18n_parity/app_guide_available.html @@ -159,7 +159,7 @@
  • - Kijelentkezés ↗ +
    diff --git a/controller/internal/web/testdata/i18n_parity/app_guide_full.html b/controller/internal/web/testdata/i18n_parity/app_guide_full.html index a0d7479..5e6395c 100644 --- a/controller/internal/web/testdata/i18n_parity/app_guide_full.html +++ b/controller/internal/web/testdata/i18n_parity/app_guide_full.html @@ -159,7 +159,7 @@
  • - Kijelentkezés ↗ +
    diff --git a/controller/internal/web/testdata/i18n_parity/app_guide_infra_filebrowser.html b/controller/internal/web/testdata/i18n_parity/app_guide_infra_filebrowser.html index 7b142a4..8e05e2c 100644 --- a/controller/internal/web/testdata/i18n_parity/app_guide_infra_filebrowser.html +++ b/controller/internal/web/testdata/i18n_parity/app_guide_infra_filebrowser.html @@ -159,7 +159,7 @@
  • - Kijelentkezés ↗ +
    diff --git a/controller/internal/web/testdata/i18n_parity/app_guide_installable.html b/controller/internal/web/testdata/i18n_parity/app_guide_installable.html index 85386f9..84affa6 100644 --- a/controller/internal/web/testdata/i18n_parity/app_guide_installable.html +++ b/controller/internal/web/testdata/i18n_parity/app_guide_installable.html @@ -159,7 +159,7 @@
  • - Kijelentkezés ↗ +
    diff --git a/controller/internal/web/testdata/i18n_parity/app_guide_no_guide.html b/controller/internal/web/testdata/i18n_parity/app_guide_no_guide.html index cb28124..f705dd2 100644 --- a/controller/internal/web/testdata/i18n_parity/app_guide_no_guide.html +++ b/controller/internal/web/testdata/i18n_parity/app_guide_no_guide.html @@ -159,7 +159,7 @@
  • - Kijelentkezés ↗ +
    diff --git a/controller/internal/web/testdata/i18n_parity/app_import_bundles.html b/controller/internal/web/testdata/i18n_parity/app_import_bundles.html index 9ad2f62..739765a 100644 --- a/controller/internal/web/testdata/i18n_parity/app_import_bundles.html +++ b/controller/internal/web/testdata/i18n_parity/app_import_bundles.html @@ -8,7 +8,7 @@ Alkalmazás importálása — Felhom.eu - +