mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-11 14:00:29 +00:00
883e951023
/download/pulse-agent served whatever agent artifact sat on disk with no relation to the running build. Local agent binaries are build outputs that nothing refreshes on their own, so they go stale silently: a dev backend was found serving a four-week-old v6.0.5 agent while reporting 6.2.0-rc.8. Staleness is not cosmetic. The installer renders its service wrapper from the server's current template, so an agent predating a flag that template now passes exits immediately with "flag provided but not defined" and crash-loops under its watchdog. That is how a real host lost its agent: the version mismatch was reported only as an installer warning, after download, easy to read as noise. Validation already scanned the binary for its report-contract endpoints, so the version check joins that same single pass and rejects a binary that does not carry this server's agent version. Refusal is loud where the old warning was quiet: a dev server answers 404 naming the stale path and the build command, and a published release falls through to the existing release-asset proxy and fetches the matching version, which makes production self-healing rather than silently downgraded. The expected version resolves through updates.GetCurrentVersion rather than the compiled-in serverVersion. The first cut of this guard used serverVersion and was inert on exactly the builds that need it: the enterprise binary compiles in "dev-pro", no version parser accepts it, and the check disabled itself. It passed its unit tests and still served the stale binary; only replaying the real v6.0.5 artifact through the running server exposed it. "dev-pro" is now pinned in the version table with that reasoning attached. The shared download-test fixture built a binary carrying the report endpoint but no version string, which a real agent always has, so it now stamps the expected version. Verified non-vacuous in both directions: those tests fail with the guard active and the thin fixture, and pass with a faithful one. Contract-Neutral: storage-recovery is pulled in only by the broad internal/api/ Extension Points prefix and this change does not move that boundary: it constrains which agent binary /download/pulse-agent serves, touching no storage provider, backup target, recovery repository or protected-workload evidence. The agent-lifecycle, deployment-installability and api-contracts deltas staged here cover every boundary the change actually moves.