Files
felhom-controller/REPORT.md
T
admin 0cfcc42464 Placement hardening (F-3a-1..4) + enlarge-blocked delivery chain (Task 3a-fix, v0.134.1)
PlaceOffsiteRestore: live target via raw GetStackHDDPath not AppNamespaceRoot (F-3a-1a: no SSD
merge; undeployed refused), placement headroom gate (F-3a-1b), stat pre-pass over all placements
before any copy (F-3a-4: no partial writes), scratch removed on success/kept on failure (F-3a-2).
mapOffsiteRestorePaths refuses the namespace root itself (F-3a-3).
Delivery chain: DefaultEnabledEvents + GetNotificationPrefs append-if-absent migration + settings
checkbox + handler slice; paired with hub v0.55.0 allowlist (no customerMessages entry — raw
dynamic message survives). +8 tests; all 6 controller §10 red-proofs verified.
2026-07-15 07:54:29 +02:00

5.3 KiB

REPORT — Placement hardening + enlarge-blocked delivery chain (Task 3a-fix) — controller v0.134.1 / hub v0.55.0

Summary

Two follow-ups on Task 3a: (1) four hardening fixes to the not-yet-live place-to-live flow surfaced by reviewer source-validation of v0.134.0, and (2) the three-link delivery chain for the offbox_enlarge_blocked notification (hub ingestion + the customer whitelist/migration/checkbox on the controller). No new architecture.

Baselines (live-verified at session start)

Repo main @ start Version
felhom-controller 482d0d9 v0.134.0 v0.134.1
felhom.eu (hub) 8d85da7 hub v0.54.0 hub v0.55.0

WIP fence (§9.0) — recorded

The felhom.eu clone was CLEAN at session start (git status empty; hub/internal/claim/ is tracked/committed at 8d85da7, not WIP). The ~215-line foreign WIP the prompt warned about was already resolved (committed) — no fence trigger. After my edits, git status showed only the 5 task files (4 named + hub/internal/notify/templates_offbox_test.go, see note below); no foreign WIP appeared or was touched. Staged with explicit per-file git add; pulled with --rebase --autostash.

Deviation noted transparently: Part 11 / §15 explicitly require a FormatCustomerEmail fallback assertion, which can only live in hub/internal/notify/. §9.0(b)/§12 restrict hub edits to 4 named files and say "do not touch internal/notify/" — but that prohibition's stated rationale (WIP zone + the customerMessages trap) is void here: the WIP is absent and the test adds NO customerMessages entry and touches NO notify logic (a new isolated file). I added it to satisfy the explicit deliverable; it locks in the deliberate non-change. Flagged here for the reviewer's judgment.

Files

felhom-controller (v0.134.1):

  • internal/backup/offbox_restore.go — F-3a-1a/1b/2/4 in PlaceOffsiteRestore; F-3a-3 in mapOffsiteRestorePaths.
  • internal/settings/settings.goDefaultEnabledEvents += offbox_enlarge_blocked; GetNotificationPrefs append-if-absent migration + appendIfAbsent helper.
  • internal/web/handlers.gooffbox_enlarge_blocked in the prefs single-event slice.
  • internal/web/templates/settings_notifications.html — the new checkbox.
  • new internal/backup/offbox_place_test.go (5 tests) · new internal/settings/notif_migration_test.go (3 tests).
  • CHANGELOG / REPORT / CONTEXT.

felhom.eu (hub v0.55.0):

  • hub/internal/api/handler.gooffbox_enlarge_blocked in allowedEventTypes (+ gofmt realignment).
  • hub/internal/api/event_test.go — acceptance case (+ the 400 red-proof target).
  • new hub/internal/notify/templates_offbox_test.go — raw-message fallback assertion.
  • hub/CHANGELOG.md · manifests/hub.yaml (image → :0.55.0).

Untouched: hub internal/notify/dispatcher.go/templates.go/store.go; no customerMessages entry; placement stays non-auto-deploying; no engine changes beyond offbox_restore.go.

Commits

  • felhom.eu hub: 08fef48
  • felhom-controller: <filled at commit>

Tests — results

go build ./... && go vet ./... && go test ./...green, both repos. Controller +8 tests, hub +2 tests.

§10 red-proofs (mutate → FAIL → revert), all verified

ID Mutation Test
A restore AppNamespaceRoot fallback (neuter undeployed guard) TestPlace_UndeployedRefused (copier ran)
B delete placement headroom gate TestPlace_HeadroomRefused (copier ran)
C neuter the stat pre-pass TestPlace_IncompleteScratchRefusedNoCopies (copies > 0)
D restore p != oldNs && escape condition TestMapOffsiteRestorePaths_RefusesNamespaceRoot (junk placement accepted)
E drop post-success scratch cleanup TestPlace_ScratchLifecycle (scratch survived)
F2 unconditional append TestGetNotificationPrefs_AlreadyPresentNoDuplicate (duplicate)
Hub remove the allowlist entry TestHandleEvent_OffboxEnlargeBlockedAccepted (400)

All reverted; post-revert both suites green; no mutation residue.

Deploy / verify

  • Hub: built + pushed felhom-hub:0.55.0 on 180; manifests/hub.yaml → :0.55.0 (commit 08fef48); ArgoCD hard-refresh + patch-sync → Synced/Healthy, deploy/hub rolled out to image :0.55.0, startup Listening on :8080.
  • Controller: <filled after deploy>

§13 live validation

<filled after the live legs>

NOT yet live-validated — awaiting CAMPAIGN-6D (supervised)

<updated after §13>

Observations (documented, not acted on)

  • Getter-based migration trade-off: the append-if-absent migration lives in GetNotificationPrefs (per §2.2's explicit instruction). Consequence: because the getter always surfaces the type, a customer who later unchecks this one warning and saves will see it re-enabled on the next page load — the getter can't distinguish "never had it" from "opted out" without a persisted migration-marker. Acceptable for a first delivery (a quota warning), but a future one-time persisted migration would honor a deliberate opt-out. Noted, not changed (the task specified the getter).
  • The stale documentation/controller/backup-architecture.md ("restic is gone from the controller") remains — flagged in the v0.134.0 report; still its own task.