test(maven): hermetic end-to-end proxy harness (S14 plan: 18/19)
Summary
Step 18 of the Maven remote plan: the hermetic end-to-end proxy harness (the plan's Type: test step), satisfying the CLAUDE.md "run conformance tests before marking format work complete" guardrail for a proxy path. TestRemoteProxy_MavenResolverConformanceSequence drives a realistic Maven Resolver sequence through one kind=2 repository against an in-process fake upstream (httptest): package-level metadata to discover versions, the .pom then the .jar for each coordinate, every artifact's .sha1 verified against the bytes the same pass served, a snapshot version resolved through its relayed version-level metadata to a dated artifact, and a full repeat pass served from cache with the header set the cold fill deliberately omitted.
Deterministic and network-free — no live upstream, no new CI job (the maven package is already in the test:integration allowlist). The harness reuses the artifact and sidecar suites' shared plumbing (newRemoteFillDispatcher, fillUpstream, seedMavenRemoteRepo, newRemoteSeed, blobRowPersister, sidecarSHA1Body, assertNoUpstreamSidecarPath, remotetest.CaptureLogs) and adds only its staged mini-repository and its own response-shape pins. It pins all three freshness knobs (both 24-hour validity windows and the snapshot opt-in), verifies the complete hit-path header set on every repeat-pass path including each .sha1, guards the capture-logger wiring the log-hygiene assertion leans on, and asserts no error-level records across the serve / fill / sidecar arms.
Test-first provisional readings, resolved before opening and recorded for the reviewer:
- Artifact proxy AC 4 / Sidecar-synthesis header contract ("MD5 in proxy mode only, FIPS rules honored") — the repeat-pass hit assertion gates
X-Checksum-Md5oncrypto/fips140.Enabled()at runtime and asserts the header is empty under FIPS-on, matching the fill suites' posture pattern. - Step 18 acceptance "exactly one upstream GET per distinct file path" — asserted as the exact ordered list of upstream paths, because the sequence is serial and deterministic; ordering also catches unexpected extra fetches with a precise diff.
Governing ADRs
- ADR-005 — the repeat pass drives S06's proxy-mode serve and pins its full header set (
Accept-Ranges, contentETag, SHA-1 always, MD5 proxy-mode/FIPS-gated); the fixture uses an in-process BlobStore, so no redirect-vs-proxy selection is exercised — a fixture limitation, not a deviation. - ADR-008 — serve and sidecar expectations are digest-keyed;
requireDistinctConformanceDigestskeeps every staged document SHA-256-distinct so a cross-wired serve fails at the fixture. - ADR-009 — uniform
/{slug}/maven/{repo}/{path}client URLs across kinds; read-only MR, no route or payload change. - ADR-010 — the fixture pins both 24-hour validity windows and the snapshot always-revalidate opt-in so the repeat pass is cache-fresh; retention behavior itself is not exercised.
- ADR-023 — flat
internal/format/mavenpackage,remote_-prefixed file, format → datastore/remote/storage import direction only; no depguard change. - Checked and not engaged: ADR-001, 002, 007, 012, 022.
Per Mirror freshness and internal ADRs, the local mirror is not the authority; no deviation is introduced here.
Testing
The harness is the test: TestRemoteProxy_MavenResolverConformanceSequence in internal/format/maven/remote_conformance_integration_test.go (//go:build integration), staged on the existing test:integration anchor (internal/format/maven/**/* in .gitlab-ci.yml) — no new CI job. The MR also records the landed-size correction in the plan's Step 18 table row.
Spec coverage
Spec: docs/specs/S14-maven-remote.md
Plan acceptance (Step 18)
| # | Acceptance | Evidence |
|---|---|---|
| S18-1 | First pass: exactly one upstream GET per distinct file path, none for any sidecar path |
ordered wire assertion (require.Len + per-call GET/path pin) + assertNoUpstreamSidecarPath (remote_conformance_integration_test.go:611-621) |
| S18-2 | Every synthesized .sha1 matches the bytes the same pass served |
requireSidecarSHA1 / requirePrimaryAndSHA1 on all six primaries plus the repeat-pass sidecar (:424-437, :483-493) |
| S18-3 | Snapshot flow resolves the dated artifact from the relayed version-level metadata | resolveDatedSnapshotJAR parses the served bytes and derives the dated name — "not hardcoded" (:521-550, :589-597) |
| S18-4 | Repeat pass: zero upstream requests, identical bytes, full hit header set vs the cold fill's deliberate omission | requireHitBlob header set + callsSnapshot equality (:447-477, :639-640); cold omission pinned by requireColdBlob (:405-419) |
Spec criteria this harness pins (proxy path)
| # | Criterion | Evidence |
|---|---|---|
| AP-1 | Cache miss, fill: stream + one-transaction commit | harness: exactly one upstream GET per path + countRemoteFillRows == 8 (:624-626) |
| AP-2 | Identity representation | Accept-Encoding: identity on every upstream call (:618); forwarded Content-Length (:414) |
| AP-3 | Cold-fill header subset | requireColdBlob on all 8 primary paths (:405-419) |
| AP-4 | Fresh hit | repeat-pass hits with full header set (:447-477) |
| MP-1 | Verbatim relay | three metadata documents relayed byte-verbatim (:565, :578, :590) |
| MP-2 | Metadata freshness window | repeat-pass metadata GETs issue zero upstream (:639-640); window pins at :155-157 |
| MP-3 | Snapshot metadata default window + dated artifact | cross-path resolution half (:521-550, :589-597) |
| MP-5 | Metadata sidecar cache-generation consistency | version-level metadata .sha1 matches the served document (:590) |
| SS-3 | No upstream sidecar fetch | zero sidecar-path upstream requests across both passes (:618, :639-640) |
| SS-10 | Sidecar cache-generation consistency | every .sha1 equals the SHA-1 of the bytes the same pass served (:424-437) |
Criteria not driven by the harness remain pinned by the earlier merged steps (Steps 11/12/14/15/16 suites: stale revalidation arms, single-flight, Range/HEAD, all four sidecar extensions, FIPS, mid-fill coalescing, cold-parent fill, conditional requests, error mapping) — no criterion is covered by neither.
docs/testing/ (Guardrail 12)
No e2e scenario is added or affected: the Maven e2e catalog (docs/testing/e2e/maven.md) covers hosted local repositories only, and this MR is an in-package hermetic suite, not a catalog scenario.
Diff footprint (Guardrail 18)
+649 −1 total; the plan carries this work as one step (Step 18). The diff is a single integration-test file (648 lines) plus the plan's Status and landing rows. The file exceeds the 500-LOC reviewable ceiling, so per development-model.md the size is justified here: it is 100% test surface with no production code — the staged upstream mini-repository (~115 lines of fixture bytes and ETags), the response-shape pin helpers (requireColdBlob / requireHitBlob / requireSidecarSHA1 / requirePrimaryAndSHA1), and the two-pass orchestration with its wire-order and call-snapshot assertions.
Related to #286 (closed)