R-108: network storage may not host an app's data namespace (v0.187.0)
This is D5's precondition and it is now met. An app's namespace root IS its backup root: namespaceRoot returns a non-system drive path as-is, so the recovery unit lands at <HDD_PATH>/backups/primary/<stack>/. On a NAS that sits inside the share, which FileBrowser binds WHOLE — share root, :rslave, download:true. The bind was NOT narrowed, and establishing why inverted the fix. The share-root :rslave bind is load-bearing (a 2026-07-22 probe proved an in-container access through it wakes the idle automount trigger), and scoping is undefinable anyway: apps on a share store at <share>/<app>, there is no userdata/ layer, and creating one would write Felhom convention onto a customer's own NAS, which R-67 forbids. So the browsing surface cannot be narrowed and the backup tree must never be placed under it. Operator ruling: refuse the placement, keep the browse bind. Tier 2 already refuses network targets for this reason (F-6C-1). Nothing stranded: zero apps on network storage across all six hub customers including Peti. R-67's browse capability is byte-identical. FIVE surfaces, not the four the register named — settings.RefuseAsAppNamespace is the single predicate. The deploy POST is the real boundary (it accepts any caller-supplied HDD_PATH; DeployStack validates only os.Stat). Surface 4, handleStorageDecommission mode=migrate, guarded only its SOURCE, so a whole namespace could be decommissioned ONTO a NAS — that one is not in the register. Fails closed: /mnt/felhom-drives holds both kinds, Kind exists only on a registered path, so an unregistered path under that root refuses. Supersedes README's "NAS backup locality — decision A" (v0.118.0). 9 tests, all non-effect (nil stackMgr, so a guard that misses panics rather than passing). 4 red-proofs, each mutation asserted to have landed. Suite rc=0, 27 packages, 0 FAIL. vet rc=0. Template + emoji gates OK.
This commit is contained in:
+18
-6
@@ -744,12 +744,24 @@ The nightly backup has two phases that run sequentially. All paths are **per-dri
|
||||
> drive. Guarded: only for a DEPLOYED app whose CURRENT drive differs from the dir's drive; never the
|
||||
> current-drive dir (the live restore point) or an undeployed app's dir; strictly under `backups/primary/`.
|
||||
|
||||
> **NAS backup locality (v0.118.0, CAMPAIGN-3 Part 4 — decision A).** A NAS-resident app's tier-1
|
||||
> artifacts live **on the NAS itself** (`nas-media/backups/primary/<app>`), beside the data. During a
|
||||
> NAS outage both the app data AND its freshest tier-1 dump are on the dead device — the **tier-2**
|
||||
> cross-drive copy to a local drive is the off-NAS leg that saves them (and only after it has run).
|
||||
> This locality is deliberate (kept in the fork over retargeting tier-1 to a local drive); the tier-2
|
||||
> copy is the mitigation. Stated here so the outage window is never a surprise.
|
||||
> **~~NAS backup locality (v0.118.0, CAMPAIGN-3 Part 4 — decision A)~~ — SUPERSEDED by R-108
|
||||
> (v0.187.0, 2026-07-30).** Decision A said a NAS-resident app's tier-1 artifacts live **on the NAS
|
||||
> itself** (`nas-media/backups/primary/<app>`), beside the data, with the tier-2 cross-drive copy as the
|
||||
> off-NAS mitigation. That locality is exactly what made a `backups/` tree reachable through
|
||||
> FileBrowser's share-ROOT bind (`download: true`), and it is why architectural target **D5** — app
|
||||
> secrets in the local recovery unit — could not be adopted.
|
||||
>
|
||||
> **An app's data namespace may no longer live on network storage at all** (operator ruling
|
||||
> 2026-07-30), so the case decision A described can no longer arise: no app on a NAS ⇒ no
|
||||
> `backups/primary/` on a NAS. `settings.RefuseAsAppNamespace` is the single predicate; every
|
||||
> placement surface consults it (deploy POST, per-app migrate, decommission-with-migrate). The NAS
|
||||
> keeps its **browse** capability unchanged — the share-root `:rslave` bind is load-bearing for
|
||||
> automount wake (R-67) and was deliberately NOT narrowed; scoping it is undefinable anyway, since
|
||||
> apps on a share store at `<share>/<app>` and creating a `userdata/` layer would write Felhom
|
||||
> convention onto a customer's own NAS.
|
||||
>
|
||||
> The NAS-outage window decision A warned about is therefore also gone: an app's tier-1 artifacts are
|
||||
> always on a local drive now, because the app itself always is.
|
||||
|
||||
**Drive layout (v0.26.0):**
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user