Commit Graph

70 Commits

Author SHA1 Message Date
admin 783830a9d4 fix: add HasVolumeData to AppBackupRow for template rendering
The backups page template references .HasVolumeData on the status table
rows but the AppBackupRow struct was missing this field, causing a
template error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 21:48:22 +01:00
admin c929948f27 feat: Docker volume backup, Tier 2 restore, restore dropdown fixes (v0.33.0)
- Add Docker named volume backup to Tier 1 (dump to tar, include in restic)
  and Tier 2 (copy tars to rsync mirror _volumes/ dir)
- Fix volume name resolution: use project-prefixed names (mealie_mealie_data)
- Fix double Tier 1 in restore dropdown: filter snapshots by app's home drive
- Add Tier 2 restore: RestoreAppFromTier2() restores from rsync mirror
- Show Tier 2 entry in restore dropdown when cross-drive backup succeeded
- Add .fab import link in restore section
- Volume-aware restore type banners and backup content labels

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 21:43:02 +01:00
admin 54390c456c move optional config from app info page to deploy/settings page
Users couldn't find metadata provider fields (IGDB, ScreenScraper, etc.)
on the app info page. Move them to the deploy page where all other
settings (integrations, geo-restriction) already live.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 20:04:28 +01:00
admin 36afd828a1 fix: FileBrowser reads stale config on fresh deployments
The gtstef/filebrowser image bakes FILEBROWSER_CONFIG=/home/filebrowser/data/config.yaml,
but controller mounts config at /home/filebrowser/config.yaml. Override the env var in both
generateFileBrowserCompose() and docker-setup.sh so FileBrowser reads the controller-managed
config with proper sources and database path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 18:51:59 +01:00
admin 9b13c0e21c feat: Tier2 backup pauses when destination drive is inactive (Inaktív)
Deactivated drives (Schedulable=false) now treated like disconnected for
Tier2 backups. New IsStoragePathSchedulable() checks active+connected+not
decommissioned. UI shows yellow "Cél meghajtó inaktív" badge, scheduler
skips silently with WARN log.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 10:59:56 +01:00
admin 4fd907a09e fix: Tier2 backup status now detects drives removed from storage (not just disconnected)
Previously, removing a storage drive from the controller only marked it as
disconnected if the StoragePath entry still existed with Disconnected:true.
Drives removed entirely from storage_paths were invisible to the check,
causing Tier2 backup UI to show green "Sikeres" and scheduler to attempt
backups to a no-longer-managed destination.

New IsStoragePathKnown() method covers both cases. UI shows yellow
"Cél meghajtó leválasztva" and scheduler skips silently.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 10:48:00 +01:00
admin f19c6fb0c9 fix: USB badge detection for bind-mounted drives + graceful Tier2 backup on disconnected destinations
- IsUSBDevice/diskModel: strip findmnt bind-mount suffix [/subdir] before
  parsing device path (fixes USB badge not showing for attach-wizard drives)
- crossdrive.go: skip disconnected src/dest drives with WARN log instead of
  returning error (prevents noisy error status in settings.json)
- handlers.go: detect Tier2 destination disconnection, set yellow status dot
  instead of red, skip ValidateDestination for disconnected paths
- backups.html: new template branch showing "Cél meghajtó leválasztva" badge
  with grayed-out info and hidden "Futtatás most" button

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 09:59:29 +01:00
admin af1dd14933 fix: standardize log prefixes, remove duplicates, add missing module tags
Second-pass logging cleanup: consistent [LEVEL] [module] format across
all 41 files. Remove stale prefixes ([CF], [SYNC], [SCHED], [API],
[STORAGE], [HEALTH], [ROLLBACK]). Remove 5 duplicate log lines. Gate
ungated DEBUG lines. Fix wrong log levels (restore start WARN→INFO).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 21:20:09 +01:00
admin 8e61cd7ec4 feat: comprehensive INFO/WARN/ERROR logging across all controller modules
Add structured operational logging at INFO, WARN, and ERROR levels to
every controller module. Standardize custom prefixes ([GEO], [SCHED],
[SYNC]) to use [INFO/WARN/ERROR] [module] format. Fix misleveled logs
(WARN->ERROR for data loss scenarios, WARN->INFO for routine operations).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 19:58:27 +01:00
admin 95c821deb2 feat: comprehensive debug logging across all controller modules
Add detailed [DEBUG] logging to every controller module when
logging.level is set to "debug". Each module with stateful debug
uses SetDebug(bool) wired from main.go. Covers stacks, backup,
cloudflare, integrations, system, monitor, settings, scheduler,
web handlers, storage, metrics, API, selfupdate, and assets.

Also includes the app export/import (.fab bundles) feature from
v0.32.0 and its debug page integration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 18:14:43 +01:00
admin f6caea8067 fix: scope FileBrowser DB reset to restore-only path
Normal storage add/remove no longer nukes the FileBrowser database volume.
A .fb-reset flag file is written during restore and consumed on next startup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 15:35:22 +01:00
admin 1e9300e5a0 fix: reset FileBrowser database when sources change
FileBrowser Quantum caches user source preferences in its SQLite
database. After a restore, the config.yaml gets correct sources but
the database still references the old "srv" source from docker-setup.sh
initial install. Now SyncFileBrowserMounts() detects when sources
changed and runs docker compose down -v to reset the database before
recreating.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 15:26:38 +01:00
admin e7f8dad5b4 Fix FB integration not picked up + OO mixed content behind HTTPS proxy
- SyncFileBrowserMounts: use --force-recreate so FB always picks up
  config.yaml changes (bind mount not detected by docker compose up)
- OnlyOffice compose template: add Traefik middleware to forward
  X-Forwarded-Proto=https (fixes mixed content errors in browser)
- Nextcloud handler: add StorageUrl=http://nextcloud for internal
  file download callbacks from OO Document Server

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:04:18 +01:00
admin 65c0da4a2b Fix FileBrowser integration config lost after SyncFileBrowserMounts
SyncFileBrowserMounts regenerates config.yaml from scratch, overwriting
any integration config. The old approach used an async OnStackStart hook
after container restart, which failed due to timing issues (stack state
not yet refreshed).

New approach: ReapplyConfigForTarget() writes integration config
synchronously after config generation but before container restart,
with a no-op RestartStack since the caller handles restart.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 20:54:03 +01:00
admin 4ee8ba6851 Move integration + geo-restriction UI to deploy/settings page
User feedback: these settings belong on the Beállítások (settings) page,
not the app description/details page. Moves both sections from app_info.html
to deploy.html and rewires data in deployHandler instead of appDetailHandler.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 20:37:05 +01:00
admin 0a5840a255 feat: app-to-app integration framework + OnlyOffice handlers
Generic integration system for connecting deployed apps via toggle UI.
First handlers: OnlyOffice→FileBrowser (config.yaml patch) and
OnlyOffice→Nextcloud (occ CLI). Lifecycle hooks auto-suspend on
stop and re-apply on start.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 20:06:20 +01:00
admin db83db383c fix: deep bug hunt II — concurrency, security & optimization (25 files)
Critical: watchdog mutex panic safety, SetGeoAppOverride nil guard,
SSD-only app DB restore fallback.

High: double deploy race (atomic Deploying flag), delete/remove during
deploy guard, ScanStacks overwrite protection, FileBrowser mount mutex,
PushEvent history, PushOnce error handling, DB dump sync+close before
rename, restic retry fresh context, encrypt failure logging, cross-backup
path traversal validation, deepCopyStack completeness.

Security: constant-time API key comparison, login rate limiting (5/min),
git credential masking in logs, storage path prefix traversal fix.

Concurrency: MigrateEncryption lock ordering, SubdomainInUse I/O outside
lock, scheduler late-registered jobs, SQLite WAL verification, metrics
shutdown context, telemetry scan error logging, asset sync lock scope.

Optimization: streaming file copy for DB dumps, restic stats dedup,
atomic infra config copy.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 14:21:09 +01:00
admin 8b8c04a487 fix: P0+P1 critical bug fixes across controller (24 files)
Concurrency fixes:
- Deep-copy stacks in GetStack/GetStacks to prevent shared state mutation (C04)
- Add per-state mutex to watchdog pathProbeState (C05)
- Guard MetricsCollector.Start() with sync.Once against double-start (C06)
- Hold diskJobMu across entire raw mount operation (C07)
- Add mutex to SetEncryptionKey (C08), MigrateEncryption write lock (H03)
- Use sync.Once for sync.Stop() channel close (H08)
- Set syncing=true before releasing lock in TriggerSync (H09)
- Deep-copy lastDBDump/lastBackup in GetFullStatus (H11)
- Add WaitGroup for stderr goroutine in MigrateDrive (H19)
- Add mutex to SetBackupRunningCheck (M18)

Security fixes:
- Validate Bearer token against Hub API key in CSRF middleware (H16)
- Validate backup paths start with expected prefix in RemoveStack (M12)
- Guard uuid[:8] slice with length check (H20)
- Parse fstab fields exactly for mount target matching (H21)

Bug fixes:
- Use decrypted env vars for compose deploy (C01)
- Log decrypt failures in DecryptMap instead of swallowing (C02)
- Move Deployed=false inside lock in runComposeDeploy (C03)
- Fix activeDrives() to skip disconnected drives (H02)
- Fix Snapshot() stderr extraction from exec.ExitError (H01)
- Check unlockCmd.Run() error in restic (H01)
- Buffer template rendering via bytes.Buffer (H07)
- Thread context.Context through cloudflare client (H10)
- Fix leaf-name collision detection in cross-drive backup (H15)
- Add nil check for crossDriveRunner (H17)
- Use strings.TrimSpace instead of slice on command output (H18)
- Make SaveAppConfig atomic with write-to-tmp+rename (H04)
- Pass encKey on deploy failure SaveAppConfig (H05)
- Fix IPv6 address format in TCP health probe

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 13:39:45 +01:00
admin e1fb85240b feat: geo-restriction via Cloudflare WAF custom rules
Add country-based access control managed through the Settings page.
Global allow-list with per-app overrides, searchable country selector,
automatic sync to Cloudflare WAF on settings change / deploy / remove,
plus periodic 6-hour verification.

New package: internal/cloudflare/ (client, zone, waf, countries, geosync)
New API: /api/geo/* (6 endpoints) + /api/stacks/{name}/geo/override

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 11:58:22 +01:00
admin 44f7fd2f19 feat: encrypt sensitive values in app.yaml with AES-256-GCM
Passwords and secrets from deploy fields (type: password/secret) are now
encrypted at rest in app.yaml using a per-node 32-byte key. Values stored
as ENC:base64(nonce+ciphertext), decrypted transparently for docker-compose
and web UI. Key included in infra backup bundle for disaster recovery.
Existing plaintext values migrated automatically on startup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 19:12:24 +01:00
admin 46c220fd8f fix: show filebrowser subdomain link on stacks page
Protected stacks like filebrowser have no .felhom.yml or app.yaml,
so the subdomain lookup found nothing. Added well-known subdomain
fallback map for programmatically managed protected stacks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 15:53:20 +01:00
admin df165f7ef0 feat: catch-all page for stopped apps, deploy controls, dashboard open button
Stopped/undeployed app subdomains now show a branded page instead of
Traefik 404. Deploy settings page gains start/stop/restart controls.
Dashboard shows "Megnyitás" button for running apps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 13:38:53 +01:00
admin ad4c005e01 v0.27.3: Use real system memory everywhere, add monitoring memory bar
Deploy page, pre-start check, and deploy validation now use actual
/proc/meminfo usage instead of declared mem_request sums. New
GetMemoryMB() helper for lightweight real-time memory reads. Monitoring
page gains a stacked memory distribution bar showing per-container
usage, OS overhead, and free memory.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 10:06:03 +01:00
admin b8ab9264f4 fix: SyncFileBrowserMounts reads domain from controller config instead of missing .env
The filebrowser stack has no .env file — domain is baked into compose labels
by docker-setup.sh. The sync always bailed with a WARN and storage paths
were never applied to FileBrowser's config.yaml or docker-compose.yml.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 18:01:43 +01:00
admin 66817709ad v0.27.0 — user-configurable app subdomains
Users can now customize the subdomain for each app during deployment
instead of using a fixed value. The deploy page shows an editable text
input with the default pre-filled and the base domain as a suffix.

New "subdomain" deploy field type with DNS-safe format validation,
reserved name blocklist, and uniqueness check across deployed stacks.
Locked after deploy — changing requires Remove + Redeploy.

Backward compatible: InjectMissingFields() auto-fills SUBDOMAIN from
.felhom.yml defaults for existing deployed apps on next sync/restart.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 15:06:22 +01:00
admin f7556b0dad v0.26.2 — show full app URL on deploy page
Domain field now displays subdomain.base_domain (e.g. wiki.demo-felhom.eu)
instead of just the base domain, matching the app card display.
Applies to both pre-deploy and post-deploy settings pages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 13:51:39 +01:00
admin f95f570670 v0.26.1 — show auto-generated values on deploy page
- Pre-generate domain + secret field values when deploy page loads,
  so user sees actual domain and masked passwords (with reveal button)
  before deploying. Same values submitted as hidden inputs → saved to app.yaml.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 13:42:15 +01:00
admin 7abd1c5954 v0.26.0: Storage namespace felhom-data/ + test node wipe script
All felhom-managed data on external drives now lives under felhom-data/
subdirectory, cleanly separating controller data from user files.

- backup/paths.go: add FelhomDataDir constant, update 8 path helpers
- stacks/delete.go: add local felhomDataDir constant (circular import
  boundary), update ProtectedHDDPaths + GetStackBackupData
- storage/migrate_drive.go: import backup pkg, fix conflict check, verify,
  rsync excludes (felhom-data/backups/*/restic/), size estimation
- storage/migrate.go: import backup pkg, fix DB dump paths
- web/handlers.go: fix legacy 'storage' path -> backup.AppDataDir()
- storage/format_linux.go: create felhom-data/ instead of storage/
- storage/attach_linux.go: create felhom-data/ instead of storage/
- scripts/felhom-wipe.sh: new multi-level test node wipe script
  (soft/controller/full/nuclear)
- CHANGELOG.md, controller/README.md, scripts/README.md: updated docs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 10:10:51 +01:00
admin 7f48786312 v0.25.0 — Debug page: operator testing & diagnostics dashboard
Debug-mode-only dashboard (/debug) with 8 collapsible sections:
system diagnostics, notification testing, backup triggers, storage
simulation, hub & connectivity, self-update dry-run, DR/setup wizard,
and in-memory log viewer. Migrates debug dump from API router to web
server. Adds ring buffer log capture, storage disconnect simulation,
event history tracking, and cross-drive/self-update test methods.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 20:18:57 +01:00
admin 51617f55d0 Fix build: rename _ to r in handler signatures for executeTemplate
dashboardHandler, stacksHandler, monitoringHandler used blank identifier
for the request param but now call executeTemplate(w, r, ...).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-21 16:40:40 +01:00
admin 02650e3202 v0.23.0 — CSRF protection on all browser-facing POST endpoints
Controller:
- internal/web/csrf.go (new): CsrfProtect middleware, csrfToken/csrfField helpers
- auth.go: per-session CSRF token (csrfToken field, csrfTokenForSession method)
- server.go: executeTemplate wrapper auto-injects CSRFField+CSRFToken
- main.go: wire CsrfProtect on all routes; bump to v0.23.0
- handlers.go, storage_handlers.go, handler_restore.go: executeTemplate
- All templates: CSRFField in forms, meta csrf-token, csrfHeaders() JS helper,
  fetch calls updated; sendBeacon→fetch+keepalive in storage_attach.html

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-21 16:38:56 +01:00
admin 6eb75204b6 v0.22.0: First-run setup wizard, local infra backup, hub verification
New controller features:
- Web-based setup wizard replaces docker-setup.sh interactive config
  - Dual listener: :8080 (Traefik) + :8081 (direct HTTP for LAN)
  - Drive scanner finds .felhom-infra-backup/ on all block devices
  - Hub recovery pull (GET /api/v1/recovery/{id}) with retrieval password
  - Fresh install: Hub config download or manual wizard
  - CSRF protection, state persistence, Hungarian UI
- Local infra backup written to all connected drives after each backup cycle
  - .felhom-infra-backup/backup.json + metadata.json with SHA256 checksum
- Hub verification: parse customer_blocked from report push response
  - Limited mode after 7 days without verification
- Recovery info page on Settings + recovery-info.txt file generation
- Pending events queue: DR events sent to Hub on next report push
- docker-setup.sh v6.0.0: removed interactive wizard, minimal controller.yaml only

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 12:33:17 +01:00
admin 8aebbb8902 feat: Hub monitoring takeover — event push system + config cleanup (v0.21.0)
Replace external Healthchecks.io with Hub-native event system. Controller
now pushes structured events via POST /api/v1/event with typed detail
structs. Hub handles dead man's switch, notification dispatch, and cooldowns.

Phase 5: PushEvent() core method, 21 event types, expanded notification
settings (11 toggles), Hub connection monitoring on dashboard, alerts.
Phase 6: Deprecation log for ping UUIDs, pinger kept for transition.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 18:53:21 +01:00
admin 99bf3ca7a8 feat: drive migration & Tier 2 restic deprecation (v0.18.0)
Phase 1: Deprecate restic as Tier 2 method (rsync only), auto-migrate on startup
Phase 2: Enhanced per-app migration with backup awareness, DB dump copy, auto-cleanup
Phase 3: Full drive migration with decommissioned state, rollback support, wizard UI
Phase 4: Hub report includes decommissioned drive state

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 21:49:14 +01:00
admin bdbe170a54 feat: storage watchdog — USB disconnect detection, auto-stop, safe eject, auto-reconnect (v0.17.0)
New storage watchdog monitors registered storage paths every 5s. On disconnect
(3 consecutive probe failures), auto-stops affected apps, lazy-unmounts stale
VFS entries, fires alerts/notifications/hub report. On reconnect (UUID detected),
auto-remounts via fstab, cleans stale restic locks, offers app restart.

Safe disconnect UI for USB drives: confirmation dialog, stop apps, sync, unmount.
Disconnected state visible across all pages (dashboard, settings, backups, monitoring)
with hatched red bars and badges. Backup guards skip disconnected drives.

22 files changed (1 new: monitor/watchdog.go), ~1500 lines added.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 19:42:26 +01:00
admin c9a88afcef feat: add controller self-update mechanism (v0.16.0)
New selfupdate package: version parsing, audit state file, updater with
Gitea registry V2 check, docker pull + compose rewrite + compose up flow.

- API: /api/selfupdate/{status,check,update} with session+bearer auth
- UI: Settings "Verzió és frissítés" card with check/install buttons + JS polling
- Scheduler: periodic check (6h default) + optional daily auto-update
- Notifications: success/failure on post-update startup verification
- Alert: info banner when update available
- docker-compose.yml: add directory bind mount for compose file access

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 17:33:40 +01:00
admin 4923afa6a7 v0.15.7: Fix backup page storage display & rename system drive label
- Add StorageBars to backupsHandler so all registered storage paths appear
- Update backups.html to use StorageBars loop (replacing single HDDConfigured block)
- Rename "SSD (/)" → "Rendszer (/)" on backup, monitoring, and dashboard pages

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 16:04:36 +01:00
admin 215ba8a83d v0.15.3: Show all storage paths on dashboard/monitoring + fix hub report 2026-02-19 09:06:59 +01:00
admin 2befa6877b v0.15.1: Backup page Részletek overhaul with per-drive tier sections
Replace Tároló section with collapsible Részletek containing 3 tiers:
- Tier 1: per-drive restic repo stats with storage labels
- Tier 2: cross-drive items grouped by destination, split by method
- Tier 3: remote backup placeholder
Restore UI now shows tier + drive labels in snapshot dropdown.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 08:23:33 +01:00
admin debab0f38b fix: mount config.yaml at correct path for FileBrowser Quantum
FileBrowser reads config.yaml from its working directory
(/home/filebrowser/), not from the data subdirectory.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 22:21:48 +01:00
admin b06e9bb368 fix: persist FileBrowser database + sync on manual storage add
- Add server.database to generated config.yaml pointing to the
  persistent data volume. Previously the database was at
  /home/filebrowser/database.db (outside the volume) and was lost
  on every container recreation.
- Call syncFileBrowserMounts after manual storage path add, so newly
  registered drives (like sys_drive) also appear in FileBrowser.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 22:19:26 +01:00
admin b88c9c76e6 feat: auto-configure FileBrowser sidebar with per-drive sources
Generate config.yaml with a separate source per registered storage path.
Each source uses the drive's label as its display name, making it appear
automatically in FileBrowser's sidebar. The config.yaml is bind-mounted
into the container (read-only) alongside the data volume.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 21:53:30 +01:00
admin 563c9515d9 v0.14.0: Per-drive backup architecture + storage path overhaul
Major refactor of backup and storage paths:

- Per-drive restic repos at <drive>/backups/primary/restic/
- Per-app DB dumps at <drive>/backups/primary/<app>/db-dumps/
- Remove global BackupDir, DBDumpDir, ResticRepo config fields
- Add SystemDataPath config (fallback for apps without HDD)
- New backup/paths.go with pure path computation helpers
- Add GetStackHDDPath to StackDataProvider interface
- Restic methods now accept repoPath as parameter
- Cross-drive backup uses new secondary path structure
- Rename storage/ to appdata/ in scripts and compose templates
- Update protected HDD paths (storage → appdata + backups)
- Simplify backup UI (remove global path displays)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 18:47:39 +01:00
admin 05f6095e6b v0.13.1: UI polish fixes round 2 (4 fixes)
- Fix 1: deploy-cross-drive card uses correct CSS vars (--bg-secondary, --border-color)
- Fix 2: Auto-generated env values — badge inline with label, remove copy buttons, muted readonly inputs
- Fix 3: Snapshot table shows 0 instead of n/a; remove unused .col-na CSS
- Fix 4: Disk warnings moved inline under storage bars (Inline alert field, GetInlineAlerts, inline-warning CSS)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 16:09:56 +01:00
admin 90826dec7a v0.13.0: UI polish fixes (8 improvements)
- Fix 1: Dashboard backup card border (verified already correct)
- Fix 2: Show auto-generated env values on deploy page with copy/reveal
- Fix 3: Temperature value pill for better visibility on dashboard
- Fix 4: Rework dashboard backup section (remove manual trigger, add Tier 2 summary)
- Fix 5: Scope HDD warning banner to dashboard and monitoring pages only
- Fix 6: Move Tárhely section up in monitoring page
- Fix 7: Snapshot table clarity (HOZZÁADOTT header, n/a instead of -)
- Fix 8: Restructure Tároló section into tiered storage view

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 13:30:21 +01:00
admin 3f2557fe26 v0.12.9: Tier 2 for all apps + status dot update
- Tier 2 cross-drive backup now configurable for all apps (not just HDD apps)
- Non-HDD apps (Mealie, Gokapi) can back up config + DB to secondary drive
- Status dot: removed "auto" gray — all apps start yellow, green = 2+ tiers OK
- Backup page: Tier 2 row always shown, Tier 3 placeholder added
- Deploy page: cross-drive config visible for all deployed apps
- Meta badges: non-HDD apps show "Konfig" or "Konfig + DB" instead of "Auto"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 12:11:27 +01:00
admin 4a9aea647b v0.12.8: complete cross-drive backup + per-tier UI
- Cross-drive now copies DB dumps (_db/) and config (_config/) alongside user data
- restic cross-drive includes config dir + full DB dump dir
- UI: per-tier rows (1. mentés / 2. mentés) instead of per-layer (DB/Konfig/Data)
- UI: BackupContents label shows what each tier protects (DB + Konfig + Adatok)
- UI: rsync backups show browsable indicator (📁)
- Cleanup: removed unused filterSnapshotsByPaths + pathCovers from router.go

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 11:37:48 +01:00
admin e4433f07b4 Post-deploy fixes (v0.12.7a) 2026-02-18 11:03:56 +01:00
admin d160c6c06d v0.12.4 — 15 bug fixes (CRITICAL/HIGH/MEDIUM)
CRITICAL:
- C1: SetAppBackupBulk data loss + nil map panic (settings.go)
- C2: UpdateStackConfig nil Env map panic (deploy.go)
- C3: ValidateDump missing scanner.Err() check (dbdump.go)

HIGH:
- H1: nextDailyRun DST bug — use time.Date(day+1) not Add(24h)
- H2: Cache Europe/Budapest timezone with sync.Once in scheduler
- H3: settings.save() leaks .tmp file on WriteFile failure
- H4: SetNotificationPrefs nil pointer panic
- H5: appDirSize + getDirSizeBytes ignore Sscanf return value
- H6: getDirSizeBytes has no timeout — add 30s context
- H7: dbdump.go tmpFile not using defer Close
- H8: UpdateCrossDriveStatus misleading comment

MEDIUM:
- M1: Replace custom containsBytes with strings.Contains
- M2: scheduler.Every() validates interval > 0
- M3: executeJob panic recovery now sets LastRun
- M4: logPostStartStatus copies env slice before goroutine
- M5: Cache timezone in web package via getTimezone() sync.Once

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-18 07:50:02 +01:00
admin 93d9b474f1 v0.12.3 — Security & correctness bug fixes (33 bugs)
CRITICAL: 10 data race and security fixes — backup.go mutex coverage
(C1-C4), IsSystemDisk 12-bit major/minor (C5), /dev/ path validation
(C6), extractName traversal (C7), TargetPath/DestinationPath against
registered paths (C8-C9), ParseComposeHDDMounts Clean-before-prefix (C10).

HIGH: 17 logic/resource fixes — ValidateDump bufio.Scanner (H1), single
appDirSize() with 30s timeout (H2/H3), snapshot ID regex (H4), cross-drive
restic prune (H5), temp file order (H6), dirSizeBytes errors (H7), atomic
fstab (H8), IsDeviceMounted suffix check (H9), eMMC partition mapping (H10),
bytesCopied mutex (H11), separator-aware migrate prefix (H13), DeleteStack
error on compose-down (H14), docker 60s timeout (H16), NotificationPrefs
deep-copy (H17), wipefs warning (H18), fstab rollback on mount fail (H19).

MEDIUM: 7 code quality fixes — formatBytes dedup (M1), .tmp filter order
(M2), sizeBytes string type (M3), elapsed in message (M6), LoadLocation
fallback (M7), pathCovers separator (M10), cancelEditLabel textContent (M11).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-17 21:10:55 +01:00