fix(v0.4.0): state schemaVersion + Docker HEALTHCHECK / multi-arch / SHA-pin#62
Merged
Conversation
Closes audit findings HIGH H5/H6/H7/H8 + medium Dockerfile SHA-pin and gosu binary verification. Fourth of ~5 PRs gating v0.4.0. State schema versioning (H8) - JobState gains an int schemaVersion component (last position to keep the diff small at the 9 construction sites). CURRENT_SCHEMA_VERSION = 1. Existing v0.3.x JSON files have no field — Jackson defaults to 0, treated as schema 1 on read. - SidecarMeta gains the same. The MetaJson DTO it serializes through defaults old files to schema 1 on toMeta() and refuses any future schemaVersion > CURRENT_SCHEMA_VERSION (rather than silently misinterpreting newer-format files). Same on JsonJobStore.load / loadFile — refused entries are skipped, never destroyed. - Pre-v0.4.0 the on-disk JSON formats had no schemaVersion field, so a forward-incompatible change later would have been impossible to detect. Now: bumping the constant in either record signals "this version refuses to read older NetCopy's downgrade attempts" — a precondition for the v1.0.0 compatibility story. Docker HEALTHCHECK (H5) - HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 CMD curl -fsS http://127.0.0.1:7777/api/health - UBI 10 minimal doesn't ship curl; we install curl-minimal (~6 MiB layer) before the COPY of the gosu binary. Compose `depends_on: condition: service_healthy` and similar orchestrator primitives now work. Multi-arch image (H7) - release.yml: docker/build-push-action `platforms: linux/amd64,linux/arm64`. The Dockerfile already SHA-pins the per-arch gosu binary, so the cross-build is straightforward. ARM users (RPi 4+, Apple Silicon via Docker Desktop, AWS Graviton) finally get a working pull. `:latest` only for non-0.x (H6) - release.yml docker_tags: while VERSION matches `^0.`, push only ghcr.io/.../netcopy:<version> — NOT :latest. Matches the README claim ("`latest` — Highest tagged stable release once 1.x ships") and the `make_latest` flag on the GitHub Release. Pre-v0.4.0 every 0.x tag silently overwrote :latest, contradicting the docs. Dockerfile base-image SHA pin - alpine:3.20 → @sha256:d9e853e87e... (digest-pinned) - eclipse-temurin:25-jre-ubi10-minimal → @sha256:c897ce903faf... - Decouples our build from any upstream re-tag of those names. Bump deliberately on each NetCopy release. gosu SHA-256 verification - per-arch SHA from the upstream SHA256SUMS file is now baked into the Dockerfile and verified after curl. Closes the "compromised GitHub release / MITM" supply-chain hole noted in the audit. Local mvn test: schema-related suites (JsonJobStoreTest, FileSidecarStoreTest, ChunkBitmapTest, ArchitectureTest) all green individually. The 56 errors in the full mvn test run are the existing Windows-env Jetty-loopback issue, unchanged from main. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes audit findings HIGH H5/H6/H7/H8 + medium Docker SHA-pin and gosu-binary verification. Fourth of ~5 PRs gating v0.4.0.
Changes
State schemaVersion (H8)
Pre-v0.4.0 the on-disk JSON formats had no version field — a future format change would silently misinterpret older files (or vice-versa).
JobState: newint schemaVersion(last component to keep the diff small at the 9 construction sites).CURRENT_SCHEMA_VERSION = 1.SidecarMeta: same.JsonJobStore.loadFile/load,FileSidecarStoreMetaJson) refuse files whose schemaVersion exceeds the supported version — log + skip, never destroy.Bumping the constant in either record now signals an intentional break, the precondition for the v1.0.0 compatibility story.
Docker HEALTHCHECK (H5)
UBI 10 minimal doesn't ship curl; the Dockerfile installs
curl-minimal(~6 MiB) right before the gosu COPY. Composedepends_on: condition: service_healthyand similar primitives now work.Multi-arch image (H7)
release.ymldocker/build-push-action:platforms: linux/amd64,linux/arm64. The Dockerfile already SHA-pins the per-arch gosu binary, so cross-build is straightforward. ARM users (RPi 4+, Apple Silicon, AWS Graviton) get a workingdocker pull.:latestonly for non-0.x (H6)release.yml: while VERSION matches^0., push only:<version>, NOT:latest. Matches the README claim andmake_latestflag on the GitHub Release. Pre-v0.4.0 every 0.x tag silently overwrote:latest.SHA-pinned base images + gosu binary
alpine:3.20→@sha256:d9e853e87e...eclipse-temurin:25-jre-ubi10-minimal→@sha256:c897ce903faf...gosu-amd64/gosu-arm64SHA-256 from upstreamSHA256SUMSis verified aftercurlviasha256sum -c. Closes the "compromised GitHub release / MITM" supply-chain hole.Test plan
mvn test -Dtest=JsonJobStoreTest→ 10 tests pass.mvn test -Dtest=FileSidecarStoreTest→ 12 tests pass.mvn test -Dtest=ChunkBitmapTest→ 11 tests pass.mvn test -Dtest=ArchitectureTest→ 8 tests pass.docker build -t test .succeeds on amd64 Linux;docker buildx build --platform linux/arm64 -t test .also succeeds (gosu SHA verification passes for both arches).🤖 Generated with Claude Code