feat(maven): set the upstream request User-Agent (S14 plan: 19/20)
Summary
Maven remote upstream requests currently carry no User-Agent, so Go's transport sends Go-http-client/1.1 — and Maven Central answers 429 to that exact string, making a remote pointed at Central unusable. This MR sets the header in UpstreamRequestBuilder.BuildRequest, pins it with a regression test, and records the requirement in the specs and the S14 plan.
What's in this MR
internal/format/maven/remote_upstream.go—User-Agentset on every composed upstream request (gitlab-artifact-registry/0.1.0; the exact value is a spec decision, see the amended spec paragraph).internal/format/maven/remote_upstream_test.go— regression pinning the outgoing header on the composed request: both credential states and the HEAD-probe shape, exactly one header value.docs/specs/S14-maven-remote.md— the Maven remote operations paragraph requiring the header, and the new "Upstream request identity" acceptance criterion under Credentials and health.docs/specs/S13-virtual-remote-foundation.md— corrects the claim that the S13 client "accepts arbitrary header maps"; names the format's request builder as the single outbound header-composition site.docs/plans/2026-07-27-maven-remote.md— Step 19 ("upstream request User-Agent") and its Status row.
Evidence
429toGo-http-client/1.1on both Central hosts (repeatedly verified);200to Maven-shaped and custom values includinggitlab-artifact-registry/*.- End-to-end verification with the header set: cold
mvn dependency:getthrough the registry made exactly 2 upstream requests torepo1.maven.org, both200, zero429s; a cold 6.7 MB artifact completed through the registry in 4.9 s.
Deviation from repo guardrails (operator-approved)
Guardrails 3 ("do not write code until the plan MR is merged") and 4 ("step MRs do not edit the plan file") are overridden for this change: spec addenda, plan amendment, and code ship in one MR per explicit operator request. The plan's approval-signal role is carried by this MR's review instead of a separately merged plan MR, and the plan edit rides this branch as a single-writer exception.
No e2e scenario added
The change is one outbound header; no proxy behavior changes. The composed-request header is pinned by the unit test, and the live-Central behavior is documented on the linked issue. No docs/testing/ update is needed.
Spec-review note
The spec additions normally land via a spec MR with status Approved; in this combined MR they are reviewed inline as part of the change.
Related to #813 (closed)