feat(maven): remote cache store Lookup + freshness (S14 Step 8, part 2/2)

What

Adds the Maven remote cache store wrapper — Step 8, part 2/2 of the S14 Maven remote vertical slice. Stacked on the part 1/2 MR (the datastore backing store; this branch's target is its branch): the internal/format/maven files land on top of internal/datastore/maven_remote_cache.go.

internal/format/maven/remote_store.go — the remote.CacheStore wrapper: parses the inbound path at the seam, selects the freshness window through the pure SelectFreshness, delegates row resolution to the backing store, and sets remote.LookupResult.Fresh via remote.IsFresh against a per-request reference time (construct one per request; a shared instance would freeze every freshness verdict). Carries the compile-time var _ remote.CacheStore anchor. Two return shapes: the interface Lookup returns the format-agnostic remote.LookupResult; the Maven-typed LookupRow beside it returns the full row for the serve and sidecar paths.

internal/format/maven/remote_freshness.go — the pure class-to-column selection: artifacts select cache_validity_hours (0 pins the row fresh), maven-metadata.xml selects metadata_cache_validity_hours, and snapshot_metadata_always_revalidate forces version-level (snapshot) metadata stale regardless of age while package-level metadata in the same repository stays inside its window.

The seam's BlobRef is the stored blob_sha256 content address carried verbatim (sha256:<hex>), per the spec's cache-hit contract — re-hashing the stored bytes would address a blob that never existed.

Coverage

  • internal/format/maven/remote_freshness_test.go (unit) — the three-way selection and the snapshot override.
  • internal/format/maven/remote_store_test.go (unit) — the constructor's nil-backing guard.
  • internal/format/maven/remote_store_integration_test.go (integration) — the wrapper's parse → select → delegate → IsFresh pipeline: hits, clean misses, both freshness windows, the snapshot opt-in, cross-repository isolation, parse rejection as a wrapped error, and the verbatim BlobRef (asserted against an independently-built expectation).

Size note

Part 2/2 is ~1,205 Go LOC, roughly half of the original single MR; the overage against the plan's ~400 estimate (per the plan's Step 8 size row) is the wrapper integration suite's seed/assert boilerplate and the pure selection's unit coverage. The operator accepted the size rather than splitting further.

Review note

The snapshot_metadata_always_revalidate column consumed by SelectFreshness is a spec-sanctioned divergence from ADR-007 as published, pending an ADR-007 amendment via the handbook repo (the repo guardrail forbids editing docs/adr/ in-tree; the amendment patch is staged out-of-tree). The divergence is recorded in S14's "Data model" section.

Validation

Re-ran the step-8 validation after addressing every finding of the first pass; all five categories passed. This MR carries the format half of those fixes: spec PASS (BlobRef now the stored content address, pinned by an independent test expectation), acceptance PASS, dev guidelines PASS (constructor panics name the constructor, process-state citations scrubbed, anonymous table struct, tt subtests). The plan-amendment and size-record edits ride on the part 1/2 MR.

Related to #286 (closed)

Merge request reports

Loading
Loading