D49 = A follow-ups: (A) the undo copy is released only after a stable start — 3 min of running, healthy, no restart, one rule for the first verdict and the late-start watch; a watch ends only for a restore begun after it; (B, R-1279) the .fab import downloads first with the restores' D48 helper, before it removes anything. Red-proved. Commit only.
gates / gates (push) Successful in 1m26s

This commit is contained in:
2026-10-25 12:45:33 +01:00
parent e8d2151a77
commit 7720439440
16 changed files with 549 additions and 27 deletions
+24
View File
@@ -22,6 +22,30 @@ brief 2026-10-24, Part 4 (commit only; the release rides the next normal train).
`…OnlyWhenTheAgentWaitsAndAnAppRuns`, `…QBLimitRuleSkipsAHeldLimit`, `…TheTwoAppsReadAndWriteTheirLimit`,
`TestLineTestRunOutlastsTheClientTimeout`, `TestStartUpwatchRecoversTheHoldFirst`, `TestUpwatchHoldGetsBothAgentCalls`.
### The undo copy goes only after a stable start; the `.fab` import downloads first (R-1270 follow-up, R-1279) — 2026-10-26, attended
Operator ruling D49 = A (2026-10-25 11:44): a restore whose app does not start keeps the restored data and the undo copy,
says „not started yet", alarms the operator; a late start is a success; never a put-back by itself.
- **Fix A (`backup/restore_verdict.go`):** before, the late-start watcher released the undo copy at the FIRST sample
that read „running", and a restore whose 90 s health wait passed dropped it at once — an app crashing and restarting
reads „running" between crashes. Now ONE rule (`waitStableStart`) for both: for 3 minutes every sample (each 10 s) has
the stack running, every healthcheck `healthy`, the same containers and no RestartCount grown (`ContainerSamples`, a
read-only `docker inspect` in the stack adapter). The page's first verdict is unchanged; the copy is released after
the window (`releaseAfterStableStart`), or stays for support with one operator line if no stable window comes in 30
minutes. A NEW restore of the app (one begun after the watch started) ends the watch untouched — found while
testing: the watch starts inside its own restore, before the page's record ends, so „a restore of the app runs"
alone ended every watch at once and would have kept every copy (`TestFixA_AStableAppReleasesTheCopyAfterTheWindow`
in the production order, seen failing with the plain check). Each watch reads its timing once, at its start.
- **Fix B (R-1279, `appexport/restore.go`):** the import asks the restores' own D48 helper (`PrepareRestoreImages`,
passed in by main.go — the package may not import `backup`) about the bundle's definition BEFORE step 1 removes the
running app's volumes; a version that cannot be downloaded refuses with the two D48 sentences and nothing changed.
- Tests (each seen failing first — felhom.eu `audits/release-2026-10-26/redproof/`): `TestFixA_AFlappingAppKeepsTheCopy`,
`…AHealthcheckStillStartingKeepsTheCopy`, `…ANewRestoreDuringTheWatchLeavesTheCopy`,
`…TheLateStartWatcherNeedsAStableStart`, control `…AStableAppReleasesTheCopyAfterTheWindow`;
`TestR1279_AnUnpullableImageRefusesTheImportBeforeAnythingIsRemoved`, `…APullableImageIsAskedFirstAndTheImportGoesOn`;
`TestR1279_MainWiresTheImportsDownloadFirst`; `TestR488_HealthWaitDefaultsAreProduction` now pins 3 min / 10 s / 30 min.
### „Use my kept data" never takes a copy dated in the future (R-1271, P2) — 2026-10-25, commit only
- **The cause, read from the code:** the catalog sweep's Tester4 off-site store held the 2026-10-20 rehearsal box's