feat(agent): report running semver on the control channel (VA-94) #94

Merged
David merged 1 commit from feat/VA-94-report-running-semver into main 2026-06-30 23:13:56 +02:00
Owner

What

Reports the agent's running release version (semver) on the mTLS control channel so the server can detect agents behind the configured release channel (VA-94). The existing server-pushed chunked update (verify + swap) is unchanged and confirmed end to end.

Why

The only version on the wire was the hardcoded numeric DEFAULT_AGENT_VERSION (194) in the AuthInfo handshake. That is a constant unrelated to the release, so the server cannot compare it to a channel's latest SemVer. The real version::VERSION (e.g. 0.1.0-3-g1b66909, baked in by build.rs) was never put on the wire.

Changes

  • DispatchContext carries agent_semver, defaulted to version::VERSION in from_host, so both production from_host call sites in net.rs get it automatically (AC1).
  • coreinfo reply gains a semver field; the numeric agentversion is retained for back-compat (AC2).
  • On registration the agent proactively sends an unsolicited coreinfo report (action coreinfo, carrying semver + commitdate) right after AuthInfo, over the JSON channel, so the server records the version without polling. New dispatch::coreinfo_report reuses the exact coreinfo payload shape (no responseid). The packed AuthInfo struct is unchanged - it mirrors the upstream C wire layout, so the semver rides an additive JSON frame (AC3).

Trust model (unchanged, matches VA-87)

The chunked push verifies streamed bytes only against the SHA-384 the authenticated server declares in the AgentUpdate End frame; the agent trusts the mTLS-authenticated server to have verified the minisign signature server-side (VS-20). No second signature check is added on this path. The oobupdate URL path keeps its signature check.

Tests / checks

  • New update::chunked_push_verifies_and_swaps_against_temp_exe: drives AgentUpdate Begin / AgentUpdateBlock chunks / AgentUpdate End against a temp exe_path through the same handle_update_frame / handle_block path net.rs uses, asserts EndOutcome::Verified and that swap_in_place replaces the target. The production apply (execv / Windows spawn_updater) is never hit, gated by the exe_path override (AC4).
  • New dispatch::coreinfo_report_carries_semver_without_responseid; updated coreinfo_includes_host_metadata to assert semver.
  • just check (fmt, clippy --deny warnings, test) passes; the authoritative oci-build/check.Dockerfile build passes (also runs as the pre-commit hook on commit), including the Windows cross-check and swtpm TPM test (AC5).

Acceptance criteria

  • DispatchContext carries agent_semver (from version::VERSION), set at both production from_host sites.
  • coreinfo reply includes a semver field; numeric agentversion retained.
  • On registration the agent proactively reports its semver (and commitdate); the packed AuthInfo struct is unchanged.
  • An integration test drives the chunked AgentUpdate / AgentUpdateBlock push against a temp exe_path and asserts verify + swap; the production apply path is unchanged.
  • just check passes.
## What Reports the agent's running release version (semver) on the mTLS control channel so the server can detect agents behind the configured release channel (VA-94). The existing server-pushed chunked update (verify + swap) is unchanged and confirmed end to end. ## Why The only version on the wire was the hardcoded numeric `DEFAULT_AGENT_VERSION` (194) in the `AuthInfo` handshake. That is a constant unrelated to the release, so the server cannot compare it to a channel's latest SemVer. The real `version::VERSION` (e.g. `0.1.0-3-g1b66909`, baked in by `build.rs`) was never put on the wire. ## Changes - `DispatchContext` carries `agent_semver`, defaulted to `version::VERSION` in `from_host`, so both production `from_host` call sites in `net.rs` get it automatically (AC1). - `coreinfo` reply gains a `semver` field; the numeric `agentversion` is retained for back-compat (AC2). - On registration the agent proactively sends an unsolicited `coreinfo` report (action `coreinfo`, carrying `semver` + `commitdate`) right after `AuthInfo`, over the JSON channel, so the server records the version without polling. New `dispatch::coreinfo_report` reuses the exact `coreinfo` payload shape (no `responseid`). The packed `AuthInfo` struct is unchanged - it mirrors the upstream C wire layout, so the semver rides an additive JSON frame (AC3). ## Trust model (unchanged, matches VA-87) The chunked push verifies streamed bytes only against the SHA-384 the authenticated server declares in the `AgentUpdate` End frame; the agent trusts the mTLS-authenticated server to have verified the minisign signature server-side (VS-20). No second signature check is added on this path. The `oobupdate` URL path keeps its signature check. ## Tests / checks - New `update::chunked_push_verifies_and_swaps_against_temp_exe`: drives `AgentUpdate` Begin / `AgentUpdateBlock` chunks / `AgentUpdate` End against a temp `exe_path` through the same `handle_update_frame` / `handle_block` path `net.rs` uses, asserts `EndOutcome::Verified` and that `swap_in_place` replaces the target. The production apply (`execv` / Windows `spawn_updater`) is never hit, gated by the `exe_path` override (AC4). - New `dispatch::coreinfo_report_carries_semver_without_responseid`; updated `coreinfo_includes_host_metadata` to assert `semver`. - `just check` (fmt, clippy `--deny warnings`, test) passes; the authoritative `oci-build/check.Dockerfile` build passes (also runs as the pre-commit hook on commit), including the Windows cross-check and swtpm TPM test (AC5). ## Acceptance criteria - [x] `DispatchContext` carries `agent_semver` (from `version::VERSION`), set at both production `from_host` sites. - [x] `coreinfo` reply includes a `semver` field; numeric `agentversion` retained. - [x] On registration the agent proactively reports its semver (and commitdate); the packed `AuthInfo` struct is unchanged. - [x] An integration test drives the chunked `AgentUpdate` / `AgentUpdateBlock` push against a temp `exe_path` and asserts verify + swap; the production apply path is unchanged. - [x] `just check` passes.
feat(agent): report running semver on the control channel
All checks were successful
Check / fmt + clippy + tests (pull_request) Successful in 5m19s
Create release / Create release from merged PR (pull_request) Has been skipped
11cba48fff
Surface the agent's running release version (semver) so the server can detect agents behind the configured release channel. Previously the only version on the wire was the hardcoded numeric DEFAULT_AGENT_VERSION (194) in the AuthInfo handshake, which is a constant and useless for channel comparison; the real version::VERSION (e.g. 0.1.0-3-g1b66909, baked in by build.rs) was never reported.

DispatchContext now carries agent_semver, defaulted to version::VERSION in from_host so both production from_host call sites in net.rs get it. The coreinfo reply gains a semver field (numeric agentversion retained for back-compat). On registration the agent proactively sends an unsolicited coreinfo report (action coreinfo, carrying semver + commitdate) right after AuthInfo via the JSON channel, so the server records the version without polling. The packed AuthInfo struct is unchanged: it mirrors the upstream C wire layout, so the semver rides an additive JSON frame instead.

The chunked server-pushed update path is unchanged and confirmed end to end by a new test that drives AgentUpdate Begin / AgentUpdateBlock chunks / AgentUpdate End against a temp exe_path through the same handle_update_frame / handle_block code net.rs uses, asserts the payload verifies (EndOutcome::Verified) and swap_in_place replaces the target. The production apply (execv / Windows spawn_updater) is never hit in the test, gated by the exe_path override.

just check (fmt, clippy --deny warnings, test) and the oci-build/check.Dockerfile build pass.

#VA-94

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
David scheduled this pull request to auto merge when all checks succeed 2026-06-30 23:13:45 +02:00
David merged commit 7082f4aa99 into main 2026-06-30 23:13:56 +02:00
David deleted branch feat/VA-94-report-running-semver 2026-06-30 23:13:56 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/vervain-agent!94
No description provided.