docs: R-203 contract + report (controller v0.197.0, proven live)
gates / gates (push) Successful in 10s

This commit is contained in:
2026-08-04 18:53:47 +02:00
parent 58c703bd44
commit f4796e0d00
2 changed files with 73 additions and 30 deletions
+29
View File
@@ -1672,6 +1672,35 @@ Last updated: 2026-06-13 (v0.60.0 backlog-Medium cleanup)
---
## R-203 (v0.197.0) — the namespace-root contract, and what `ok` now means
**The contract, in one line:** `appbackup`'s path helpers (`UserdataDir`, `PrimaryBackupPath`,
`RecoveryUnitPath`, `AppDataDir`) take a **NAMESPACE ROOT**. Anything that came out of `HDD_PATH` or a
`StoragePath` is a **DRIVE path** — put it through `appbackup.NamespaceRootFor(drive, systemDataPath)`
first. `UserdataDir(bareDrivePath)` still compiles and is still wrong; five callers proved it.
**The rule now has ONE expression.** `NamespaceRootFor` / `IsEnrolledDrive` in `appbackup`;
`backup.Manager.namespaceRoot` and `stacks.Manager.inGuest` delegate. There were two copies before and
**they differed** — one compared without `filepath.Clean`, the other with it.
**Why it was invisible:** on an enrolled drive the namespace root IS the drive path. The two diverge
only on the system-data fallback, which `paths.go:26` names as a supported arrangement.
**`last_status` gains `incomplete`.** A run that could not capture a directory an app declares
MANDATORY is not a successful run. **Not `error`** — the rest of the run worked, so `SnapshotCount`
and `LastSuccess` still record what WAS captured. It reaches the operator via the existing
`backup_run_failures` digest (a new event type is a two-repo change; the hub drops unlisted types).
The Hungarian customer warning is unchanged; the page renders `! Hiányos`.
**Still open, and NOT fixed here:** `resolveAbs` resolves `RootHDD` and `RootUserdata` against the same
root. Both callers now pass the namespace root so the export and the backup agree with each other, but
whether `${HDD_PATH}` should mean the namespace root on the system drive touches every deployed app's
binds and needs a decision, not a patch.
**Blast radius, measured before changing anything:** exactly one app in the fleet had
`HDD_PATH == system_data_path` (`calibre-web` on demo-hp, the R-201 drill fixture). Its data was
migrated and its sentinel re-verified byte-identical.
## R-203 (2026-08-04) — a MANDATORY userdata directory can be absent from the off-site snapshot while the run says `ok`
Found live on demo-hp while staging the R-201 drill, and it **halted that drill**.