feat(shares): R-7b Parts 4-6 — shares restore, samba liveness, UI truth-up

Part 4 — restore: RestoreSharesScratch + PlaceSharesRestore as SIBLINGS of the
per-app scratch/place pair. Files merged missing-only (never overwriting), each
destination PREFIX-ASSERTED against registered LIVE storage roots; definitions
merged with existing-wins; ReconcileSamba via a seam (backup must not import
stacks); credential restored best-effort into the samba named volume.
New routes POST /backup/shares/{restore,place} + a restore-page entry that renders
'Megosztasok', never the raw reserved key.
Also adds scratchJoin: reconstructing an absolute captured path under a scratch
must strip the volume name rather than rely on filepath.Join.

Part 5 — liveness: EffectiveProtected gains a settings-backed dynamic extra so the
samba CONTAINER (not the stack name — they differ) is watched exactly while sharing
is on. FINDING: the issue -> health 'fail' -> existing health_critical event ->
alert -> Hungarian degradation e-mail path needs NO further change, and introduces
no new event type, so the allowlist gotcha does not apply.

Part 6 — UI: per-tier backup status lines on the Megosztas page (amber only on
deviation). Verified the two warning-prose sites (offbox_capture/tier2_capture)
only ever receive per-app stack names, so no mapping is needed there.

RED-PROOFS RUN AND REVERTED (both fired):
  4. prefix-assert removed        -> place-guard traversal test FAILS
  5. dynamic samba extra removed  -> Scenario E enabled-case FAILS
This commit is contained in:
2026-07-18 13:02:41 +02:00
parent 85b76e0fc3
commit 900c870212
14 changed files with 822 additions and 18 deletions
+6
View File
@@ -101,6 +101,12 @@ type Manager struct {
// samba named volume (`docker exec -i … tar xf -`). Nil → the real defaultSharesPassdbRestore.
sharesPassdbRestore func(tar []byte) error
// sharesReconcile (R-7b), if set, re-renders and applies the samba stack after a shares restore
// re-adds definitions to the registry (wired in main.go to stacks.Manager.ReconcileSamba). It is a
// SEAM rather than a direct call because the backup package must not depend on the stacks package.
// Nil → the registry is updated and a WARN says smb.conf will catch up on the next health tick.
sharesReconcile func() error
// tier2SSDFits (3b) — the SSD-headroom predicate seam, overridable in tests (system.GetDiskUsage is
// Linux-only → nil on the Windows test host, which would always refuse the SSD branch). Nil → the
// real tier2FitsSystemDrive.