Capture-set computation (INERT; Task 3-core, v0.133.0)
Pure appbackup.ComputeCaptureSet(binds, hasClassification, tier, hddPath) → CaptureSet
{HasClassification, Paths, Skipped}: legacy short-circuit → tier filter (§2) → structural
guards → equal-Abs collapse (mandatory>optional) → containment dedup → sort. Slash algebra,
no filepath/FS/log. Structural guards (traversal / bare HDD drive-root / reserved backups/)
are load-bearing (the compose parser does not reject ..). Pure CrossAppOverlaps advisory
(WARN wiring deferred to 3a/3b). INERT — no engine consumes it yet.
Tests: Groups A-F (appbackup) + F-S3 no-seam wiring (stacks); all 6 §10 red-proofs verified.
Docs: architecture §3 aligned (felhom.eu 8d85da7).
This commit is contained in:
@@ -1,5 +1,45 @@
|
||||
## Changelog
|
||||
|
||||
### v0.133.0 — Capture-set computation (INERT; Task 3-core) (2026-07-14)
|
||||
|
||||
Task 3-core of the backup-classification-redesign arc
|
||||
(`felhom.eu/documentation/architecture/07-backup-architecture.md` §3; matrix §2; SP-1/2/3 spike
|
||||
verdicts landed in `SPIKE-restic-snapshot-shape-2026-07-14.md`). Ships the **pure capture-set
|
||||
computation** in the `appbackup` leaf package — **deliberately INERT**: NO backup tier changes
|
||||
behavior. 3a (offsite policy engine) and 3b (tier-2 rework) are the consumers.
|
||||
|
||||
- **`ComputeCaptureSet(binds, hasClassification, tier, hddPath) CaptureSet`
|
||||
(`internal/appbackup/captureset.go`, new):** turns an app's `ClassifiedBinds` into a tier-filtered,
|
||||
structurally-guarded, containment-deduped absolute path set. Fixed pipeline (§8): legacy
|
||||
short-circuit → tier filter → structural guards → equal-Abs collapse (mandatory > optional) →
|
||||
containment dedup (keep ancestor) → sort by Abs. `CaptureSet{HasClassification, Paths []CapturePath,
|
||||
Skipped []SkippedPath}`; each `CapturePath` carries `{Abs, Root, RelPath, Class}`.
|
||||
- **Tier columns (§2):** `TierOffsite` = mandatory only (optional never ships offsite); `TierSecondary`
|
||||
= mandatory + optional; **excluded** is silently dropped at every tier (never in Paths, never in
|
||||
Skipped). A **legacy** app (`hasClassification=false`) resolves NOTHING — `{HasClassification:false}`,
|
||||
nil Paths/Skipped — so the engines' no-block branch stays byte-identical (the SQ5 cost-regression
|
||||
guard: an unmigrated app never resolves a bind into an automatic tier).
|
||||
- **Structural guards (security-shaped, load-bearing):** the compose parser path.Cleans but does NOT
|
||||
reject `..`, and `ValidateBackupSpec` vets only *spec* entries, so an unlisted writable
|
||||
`${HDD_PATH}/../x` bind arrives classed **mandatory**. Guards (run after the tier filter) move
|
||||
traversal (`..` segment / absolute), bare **HDD** drive-root (`""` — would nest `<hddPath>/backups`),
|
||||
and reserved `backups/` zone captures into `Skipped` with distinct English reasons (a skipped
|
||||
mandatory = a capture GAP the engines log loudly). Bare **userdata** root is allowed
|
||||
(`<hddPath>/userdata`). Segment-wise `..` detection (a legit `a..b` dir passes).
|
||||
- **`CrossAppOverlaps(map[app]CaptureSet) []Overlap`:** pure §4.2 advisory — same absolute path in ≥2
|
||||
apps' Paths (exact-Abs only; cross-app *containment* is legitimate and does NOT report). WARN wiring
|
||||
is deferred to 3a/3b by design — no log call sites here.
|
||||
- **Purity:** no `os`/`exec`/`filepath`/logging; **slash algebra** (`path.Join`/`path.Clean`)
|
||||
throughout — resolved paths are in-container Linux paths, and `filepath` on the Windows test host
|
||||
would flip separators and break containment prefix checks.
|
||||
- **Docs alignment:** architecture §3 sketch updated to the as-built API (`UnitOnly` → `HasClassification`,
|
||||
`Skipped` added), felhom.eu commit `8d85da7`.
|
||||
- **Tests (all green):** `internal/appbackup/captureset_test.go` (Groups A–F: per-tier split, legacy
|
||||
inertness, excluded-invisible, structural guards + legit `a..b`, containment/collapse/determinism,
|
||||
cross-app overlap) + the F-S3 no-seam wiring test `internal/stacks/captureset_wiring_test.go`
|
||||
(Group G, real Manager → ClassifiedBinds → ComputeCaptureSet end-to-end). All 6 §10 red-proofs
|
||||
verified (mutation → fail → revert). **No behavior change; no UI; no engine edits.**
|
||||
|
||||
### v0.132.0 — Backup classification: schema + parser + pure classifier (INERT; Task 2) (2026-07-14)
|
||||
|
||||
Task 2 of the backup-classification-redesign arc
|
||||
|
||||
Reference in New Issue
Block a user