E-2 complete: wrapper, installer Case A/B, offer flow, degraded banner
Live: hub 0.81.0, agent 0.113.0, controller 0.185.1 on both demo boxes; host-install 1.22.0 (script; no reinstall performed). E-2a wrapper proven live as root on demo-hp: F-1 subdirectory refused, F-2 unmounted path refused, root device refused, idempotent re-apply is a no-op, repointing refused -- 0 stray storages. The agent PVE role was NOT widened. Scenario E proven live on BOTH boxes: healthy renders nothing, no message key. Records three defects I introduced and caught: unreachable routes (mounted outside /api/storage/, caught by the first live call), a hollow test exposed by its own red-proof, and another gofmt-realignment no-op. Not live-proven: the degraded banner and offer acceptance (both boxes healthy), backup_target_absent end-to-end, Case A/B on a real install, drive-loss recovery.
This commit is contained in:
@@ -109,3 +109,75 @@ mock, because the failure class is "nothing arrives".
|
||||
two identically-exposed boxes, so demo-felhom was rolled to the same proven artifacts.
|
||||
- `StorageTarget.Role` carries a documented vocabulary including `vzdump-target` and is always `""`.
|
||||
Checked — it is a deliberate unpopulated field ("hub-owned, slice 10"), **not** a sixth dead seam.
|
||||
|
||||
---
|
||||
|
||||
# E-2 increment 2 (same day): the wrapper, the installer, the offer and the banner
|
||||
|
||||
**Live fleet:** hub **0.81.0**, agent **0.113.0**, controller **0.185.1**, host-install **1.22.0**
|
||||
(script; no reinstall performed). Both demo boxes. `peti-felhom` untouched.
|
||||
|
||||
## E-2a — the guarded wrapper
|
||||
|
||||
`configs/felhom-backup-target-apply` behind a literal `FELHOM_BACKUPTARGET` sudoers alias. **The
|
||||
agent's PVE role was not widened** — it still holds neither `Datastore.Allocate` at `/storage` nor
|
||||
`Permissions.Modify`.
|
||||
|
||||
All five laws proven live as root on demo-hp, with **0 stray storages created**:
|
||||
|
||||
| Probe | Result |
|
||||
|---|---|
|
||||
| F-1 subdirectory (`/mnt/nvme-1tb/dump`) | REFUSED — "must be the drive's OWN mountpoint" |
|
||||
| F-2 unmounted path | REFUSED — "would silently retarget onto the system drive" |
|
||||
| root device (`/`) | REFUSED |
|
||||
| idempotent re-apply on the real target | no-op, exit 0 |
|
||||
| repointing an existing id | REFUSED |
|
||||
|
||||
`POST /backup/target` drives it **create → grant → config**, and deliberately does **not** restart the
|
||||
agent: it returns `restart_required` so the restart happens behind the caller's own immediate
|
||||
in-flight check. That is E-1's spurious-tier-failure mistake encoded as a contract, and a test asserts
|
||||
the handler never restarts.
|
||||
|
||||
## Part 2 — the installer (v1.22.0)
|
||||
|
||||
Case A creates the target through the same wrapper; Case B records DEGRADED in two warning lines and
|
||||
**still succeeds** — a single-drive appliance is valid. Scenario F returns early with **0 wrapper
|
||||
calls**; the red-proof (guard removed) shows **2**, i.e. it would have "corrected" a correct box.
|
||||
|
||||
**Installer-logic-tested, NOT install-tested** — the harness runs the extracted functions with
|
||||
stubbed `pvesm`/wrapper. No reinstall was performed.
|
||||
|
||||
## Parts 3+4 — the offer and the banner
|
||||
|
||||
`POST /api/storage/backup-target/assign` is the **only** writer of the role. `GET
|
||||
/api/storage/backup-target` drives the banner. Hungarian copy is FACT → CONSEQUENCE → REMEDY.
|
||||
|
||||
**Scenario E proven live on both boxes** — healthy renders nothing:
|
||||
|
||||
```
|
||||
demo-hp {"degraded":false,"known":true,"label":"NVME 1TB","target":"felhom-backup"}
|
||||
demo-felhom {"degraded":false,"known":true,"label":"USB HDD 1TB","target":"felhom-backup"}
|
||||
```
|
||||
|
||||
No `message` key at all. Red-proofed: adding a reassurance to the healthy branch fails Scenario E.
|
||||
|
||||
## Three defects I introduced and caught
|
||||
|
||||
1. **The offer endpoints were unreachable.** Registered as `/api/backup-target` inside
|
||||
`ServeStorageAPI`, which `main.go` mounts only at `/api/storage/`. Every unit test passed because
|
||||
they called the handlers directly; the **first live call** returned `endpoint not found`. Fixed in
|
||||
v0.185.1 with a test that asserts the dispatcher's own source contains both routes.
|
||||
2. **A hollow test.** `TestUnknownStateRendersNothing` used `{Known:false}` with `Degraded` left
|
||||
false, so it passed even with the `!Known` guard deleted. Its own red-proof exposed it; the
|
||||
fixture is now `{Known:false, Degraded:true}`.
|
||||
3. **A gofmt-realignment no-op** (again): a `sed`-style replace silently matched nothing because the
|
||||
formatter had changed the spacing. Every mutation is now verified to have landed before its result
|
||||
is trusted.
|
||||
|
||||
## Still not live-proven
|
||||
|
||||
- The **DEGRADED banner** and the **offer acceptance** — both boxes are healthy, so neither state
|
||||
occurs naturally. Unit- and red-proofed only.
|
||||
- **`backup_target_absent` end-to-end** — needs a live enrolled drive to go absent.
|
||||
- **Case A/B on a real install** — installer-logic-tested only.
|
||||
- **Full drive-loss recovery** — physical access.
|
||||
|
||||
Reference in New Issue
Block a user