From 72ab145b419b91be7635dc42a8000b819df3e369 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Wed, 25 Feb 2026 13:48:47 +0100 Subject: [PATCH] docs: add v0.30.3 changelog entry for comprehensive bug hunt fixes Co-Authored-By: Claude Opus 4.6 --- CHANGELOG.md | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e4ea6b..26a5489 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,69 @@ ## Changelog +### v0.30.3 — Comprehensive Bug Hunt Fixes (2026-02-25) + +#### Fixed (Critical — P0) +- **Encrypted env vars** — `UpdateStackConfig` now uses decrypted values when building compose env, preventing `ENC:...` literals in containers (C01) +- **Silent decrypt failures** — `DecryptMap` now logs warnings on decrypt failure instead of silently returning empty values (C02) +- **Deploy race condition** — `Deployed = false` flag now set inside the mutex lock in `runComposeDeploy` (C03) +- **Shared state mutation** — `GetStack`/`GetStacks` now return deep copies preventing callers from mutating cached state (C04) +- **Watchdog races** — Added per-state mutex to `pathProbeState` for thread-safe probe state access (C05) +- **Metrics double-start** — `MetricsCollector.Start()` guarded with `sync.Once` (C06) +- **Raw mount race** — `diskJobMu` now held across entire cleanup+mount+set operation (C07) +- **Encryption key race** — Added mutex to `SetEncryptionKey` (C08) + +#### Fixed (High — P1) +- **Restic lock detection** — `Snapshot()` now extracts stderr from `*exec.ExitError` and checks `unlockCmd.Run()` error (H01) +- **Disconnected drives in backup** — `activeDrives()` now skips disconnected/decommissioned drives (H02) +- **Template rendering** — Buffered via `bytes.Buffer` to prevent partial HTML on error (H07) +- **Sync stop panic** — `Stop()` uses `sync.Once` for safe channel close (H08) +- **Sync race** — `syncing = true` set before releasing lock in `TriggerSync` (H09) +- **Cloudflare context** — Threaded `context.Context` through all Cloudflare API calls for cancellation support (H10) +- **Cross-drive collision** — Replaced flawed leaf-name dedup with proper `seen` map (H15) +- **CSRF bypass** — Bearer token now validated against Hub API key before skipping CSRF (H16) +- **Nil pointer** — Added nil check for `crossDriveRunner` in handlers (H17) +- **Selftest panic** — Replaced `out[:len(out)-1]` with `strings.TrimSpace` (H18) +- **Stderr goroutine** — Added `sync.WaitGroup` in `MigrateDrive` (H19) +- **UUID slice** — Guarded `uuid[:8]` with length check (H20) +- **Fstab matching** — Parse fields exactly instead of loose `strings.Contains` (H21) +- **Atomic save** — `SaveAppConfig` writes to `.tmp` then renames (H04) +- **Deploy failure** — `SaveAppConfig` on failure now includes `encKey` (H05) +- **Encryption migration** — Uses write lock instead of read lock (H03) +- **Deep copy** — `GetFullStatus` deep-copies `lastDBDump`/`lastBackup` (H11) +- **IPv6** — TCP health probe uses `net.JoinHostPort` for IPv6 compatibility +- **Backup path validation** — `RemoveStack` validates paths under expected directory (M12) +- **Updater race** — `SetBackupRunningCheck` protected by mutex (M18) + +#### Fixed (Medium — P2) +- **Config env overrides** — `LoadFromBytes` now calls `applyEnvOverrides` (M05) +- **Selfupdate state** — Compose-up failure now sets `state.Status = "failed"` (M16) +- **Memory check** — `usableMB` clamped to min 0 (M22) +- **Cross-backup trigger** — Removed invalid "manual" schedule from `triggerAllCrossBackups` (M23) +- **mmcblk support** — Partition path and `stripPartition` now handle mmcblk devices (M21, L25) +- **Scheduler** — `Start()` guarded against double-start, `Stop()` acquires mutex (M14, L24) +- **Pending events** — Events restored on save failure in `DrainPendingEvents` (M03) +- **Duplicate storage** — `AddStoragePath` rejects already-registered paths (M04) +- **Setup scan** — `CleanupTempMounts` called after drive scan (H13) +- **Setup state** — `SetStep` now logs save errors (M25) + +#### Fixed (Low — P3) +- **UTF-8 truncation** — `TruncateStr` now operates on runes and handles negative maxLen (L05/L06) +- **AllDone** — Returns false for empty restore plans (L14) +- **PushOnce** — Returns actual errors instead of swallowing them (L39) +- **CSRF token** — Panics on `crypto/rand.Read` failure instead of using static fallback (L40) +- **Logout** — Requires POST method (L32) +- **Server.Close** — Uses `sync.Once` to prevent double-close panic (L49) +- **Log cap** — `lines` query parameter capped at 10000 (L31) +- **Hash function** — Replaced custom `simpleHash` with `crc32.ChecksumIEEE` (L48) +- **hasPrefix** — Replaced custom implementation with `strings.HasPrefix` (L13) +- **DefaultEnabledEvents** — Copied in `GetNotificationPrefs` early return (L09) +- **Variable shadowing** — Renamed `copy` to `cp` in `SetNotificationPrefs` (L07) + +#### Removed +- Dead `imageName` function in selfupdate (L02) +- Dead `detectHostIPViaRoute` function in setup (L03) +- Custom `hasPrefix` function in restore_scan (L13) + ### v0.30.2 — Report geo-restriction + logo/favicon update (2026-02-25) #### Added