Fix and harden Windows tentacle upgrade download path
Summary
Make the Windows tentacle self-upgrade work, and work reliably across Windows versions and environments.
Correctness fix (the field report: upgrade to 1.8.13 failed with "End of central directory record could not be found", exit 14):
-
Invoke-WebRequest -OutFilecorrupted the large binary download on PS 5.1 → extraction failed. Switch toSystem.Net.WebClient.DownloadFile+ forced TLS 1.2. - The
.sha256companion (served by GitHub asapplication/octet-stream) was fetched withInvoke-WebRequest, which returns.Contentas abyte[]for octet-stream → the hex split failed → SHA verification was silently skipped, letting the corrupt download through. Switch toWebClient.DownloadString(always a string) + log an ASCII snippet of any malformed companion. - Extract via
[System.IO.Compression.ZipFile]::ExtractToDirectoryinstead ofExpand-Archive. - Script is now pure ASCII so PS 5.1 + the web log don't mojibake under non-Latin OEM codepages.
Reliability hardening (raise success rate toward 100%):
- Retry the download with backoff (3 attempts, env-tunable
SQUID_UPGRADE_DOWNLOAD_RETRIES) — survives transient TCP reset / CDN 503 / proxy blips. - Route through the configured proxy with default credentials — authenticated corporate proxies (407) no longer block it.
- Reject a 0-byte / truncated download with a clear message instead of an opaque extraction error.
- Retry extraction + binary swap — Defender briefly locking a freshly-written file no longer fails the upgrade.
Same fix + hardening applied to install-tentacle.ps1.
Test plan
-
705 upgrade unit tests + resource/strategy/parity drift detectors green (macOS) -
Cross-platform drift detectors: WebClient+TLS12 download, ZipFile extraction, pure-ASCII script, retry/proxy/size hardening -
Octet-stream SHA regression test — reproduces the real cause; fails the old Invoke-WebRequestcode -
Behavioural download-retry E2E — LocalReleaseMirror.FailNextArchiveRequests(1)injects a 503; the real.ps1retries and the upgrade still succeeds -
Windows E2E green on a real Windows runner (run 26962192825, 10m): production .ps1end-to-end — WebClient download → SHA → ZipFile extract → swap → restart →last-upgrade.json -
Windows E2E matrix (windows-2019 + windows-2022) — re-dispatched on this branch with the hardening + retry test -
Manual confirmation on the reporting operator's box (already verified WebClient returns the byte-exact archive: size + SHA match)