Placement hardening (F-3a-1..4) + enlarge-blocked delivery chain (Task 3a-fix, v0.134.1)
PlaceOffsiteRestore: live target via raw GetStackHDDPath not AppNamespaceRoot (F-3a-1a: no SSD merge; undeployed refused), placement headroom gate (F-3a-1b), stat pre-pass over all placements before any copy (F-3a-4: no partial writes), scratch removed on success/kept on failure (F-3a-2). mapOffsiteRestorePaths refuses the namespace root itself (F-3a-3). Delivery chain: DefaultEnabledEvents + GetNotificationPrefs append-if-absent migration + settings checkbox + handler slice; paired with hub v0.55.0 allowlist (no customerMessages entry — raw dynamic message survives). +8 tests; all 6 controller §10 red-proofs verified.
This commit is contained in:
@@ -1,5 +1,35 @@
|
||||
## Changelog
|
||||
|
||||
### v0.134.1 — Placement hardening (F-3a-1..4) + enlarge-blocked notification delivery chain (Task 3a-fix) (2026-07-15)
|
||||
|
||||
Follow-up hardening of the (not-yet-live) place-to-live flow from v0.134.0, plus the controller side
|
||||
of the `offbox_enlarge_blocked` notification delivery chain (paired with hub v0.55.0). No new
|
||||
architecture.
|
||||
|
||||
- **F-3a-1a (`offbox_restore.go` `PlaceOffsiteRestore`):** the live target now resolves via the RAW
|
||||
`GetStackHDDPath` (mirrors `offboxCaptureSet`), NOT `AppNamespaceRoot` whose `systemDataPath`
|
||||
fallback would have merged userdata onto the SSD system namespace. Empty HDD ⇒ undeployed ⇒ refuse
|
||||
(`"a(z) %s nincs telepítve — előbb állítsd helyre az alkalmazást, utána az adatokat"`).
|
||||
- **F-3a-1b:** placement headroom gate — refuse before any copy if `offboxFree(liveNs) <
|
||||
offboxSize(scratch)` (a missing-only merge copies at most the scratch size).
|
||||
- **F-3a-4:** the src-existence check is now a `os.Stat` PRE-PASS over EVERY placement before the
|
||||
first copy — an incomplete scratch (e.g. a unit-only restore) refuses with ZERO copies, making the
|
||||
"no partial writes" guarantee true (was interleaved: the unit could be placed before the refusal).
|
||||
- **F-3a-3 (`mapOffsiteRestorePaths`):** the escape check tightened to `!HasPrefix(p, oldNs+"/")` so
|
||||
the namespace root itself (`p == oldNs`) is refused instead of mapping to a junk placement.
|
||||
- **F-3a-2:** on FULL success the scratch is removed best-effort (logged); `OffboxFullScratchReady`
|
||||
then turns false so the place button disappears. A FAILED placement keeps the scratch for a retry.
|
||||
- **Delivery chain (controller side):** `settings.DefaultEnabledEvents` gains
|
||||
`offbox_enlarge_blocked`; `GetNotificationPrefs` append-if-absent migration surfaces it enabled for
|
||||
existing customers (idempotent — a customer couldn't have disabled a type that didn't exist), which
|
||||
the startup prefs sync (`main.go:782`) carries to the hub; the settings-page checkbox
|
||||
(`"Távoli mentés — tárhelykeret-figyelmeztetés"`) + the handler's single-event slice both gain it
|
||||
(missing either half re-opens the checkbox-drop trap). Hub v0.55.0 allowlists the event; NO
|
||||
`customerMessages` entry (the raw dynamic two-number message must survive — `templates.go:129`).
|
||||
- **Tests:** +5 placement (`offbox_place_test.go`: undeployed/headroom/incomplete-pre-pass/lifecycle
|
||||
+ mapping namespace-root) + 3 settings (`notif_migration_test.go`: default-contains, migration
|
||||
idempotency, no-duplicate). All 6 controller §10 red-proofs verified (mutate → fail → revert).
|
||||
|
||||
### v0.134.0 — Offsite tier policy engine: mandatory userdata, raw-data quota, restore rework (Task 3a) (2026-07-14)
|
||||
|
||||
Task 3a of the backup-classification-redesign arc — the FIRST behavior-changing task
|
||||
|
||||
Reference in New Issue
Block a user