diff --git a/Dockerfile b/Dockerfile
index bafdeebb5..1c7a4e14b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,28 +1,20 @@
-FROM eclipse-temurin:21 AS builder
-
-ARG MAVEN_VERSION=3.9.6
-ARG USER_HOME_DIR="/root"
-ARG SHA=706f01b20dec0305a822ab614d51f32b07ee11d0218175e55450242e49d2156386483b506b3a4e8a03ac8611bae96395fd5eec15f50d3013d5deed6d1ee18224
-ARG BASE_URL=https://archive.apache.org/dist/maven/maven-3/${MAVEN_VERSION}/binaries
-
-RUN mkdir -p /usr/share/maven /usr/share/maven/ref \
- && for i in 1 2 3; do \
- echo "Attempt $i to download Maven..." && \
- curl -fsSL --connect-timeout 300 --max-time 600 -o /tmp/apache-maven.tar.gz ${BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz && break || \
- (echo "Download failed, attempt $i of 3" && sleep 10); \
- done \
- && echo "${SHA} /tmp/apache-maven.tar.gz" | sha512sum -c - \
- && tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1 \
- && rm -f /tmp/apache-maven.tar.gz \
- && ln -s /usr/share/maven/bin/mvn /usr/bin/mvn
-
-ENV MAVEN_HOME /usr/share/maven
-ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2"
-
-COPY mvn-entrypoint.sh /usr/local/bin/mvn-entrypoint.sh
-COPY settings-docker.xml /usr/share/maven/ref/
-
-# Copy src files needed for build
+# -----------------------------
+# Builder stage
+# -----------------------------
+# Uses the official Maven image with Eclipse Temurin Java 21 on Alpine.
+# This stage is only used to compile/package the application.
+# Maven and build tools stay in this stage and are not included in the final runtime image.
+FROM maven:3.9.15-eclipse-temurin-21-alpine AS builder
+
+# Set the application source directory inside the container.
+WORKDIR /usr/src/app
+
+# Copy custom Maven settings.
+# This is useful if the build depends on internal repositories, mirrors, credentials, or proxy config.
+COPY settings-docker.xml /usr/share/maven/ref/settings-docker.xml
+
+# Copy only the source files/modules needed for the Maven build.
+# Keeping this explicit avoids copying unnecessary files into the build context.
COPY pom.xml /usr/src/app/
COPY commons/ /usr/src/app/commons/
COPY test-commons/ /usr/src/app/test-commons/
@@ -32,18 +24,54 @@ COPY rest-api/ /usr/src/app/rest-api/
COPY generate/ /usr/src/app/generate/
COPY test-coverage/ /usr/src/app/test-coverage/
COPY tools/docker/docker-artifacts/ /usr/src/app/tools/docker/docker-artifacts/
-WORKDIR /usr/src/app/
-RUN /usr/local/bin/mvn-entrypoint.sh mvn install -Dmaven.test.skip -Djacoco.skip=true -Dskip.generate=true > /dev/null
+# Build the application.
+# -B runs Maven in batch mode for CI/CD.
+# -ntp disables Maven transfer progress logs.
+# -s uses the custom Maven settings file copied above.
+# Tests, JaCoCo, and generate steps are skipped because this Docker build only packages the runtime artifact.
+RUN mvn -B -ntp \
+ -s /usr/share/maven/ref/settings-docker.xml \
+ clean install \
+ -Dmaven.test.skip=true \
+ -Djacoco.skip=true \
+ -Dskip.generate=true > /dev/null
-# Final stage
-FROM eclipse-temurin:21-jre
-RUN mkdir -p /usr/src/run/
-COPY --from=builder /usr/src/app/tools/docker/docker-artifacts /usr/src/run/
-COPY --from=builder /usr/src/app/rest-api/target/rest-api.jar /usr/src/run/
+# -----------------------------
+# Final runtime stage
+# -----------------------------
+# Uses a pinned Alpine-based Java 21 JRE image.
+# This avoids the Ubuntu-based OS package vulnerabilities reported by Snyk
+# while keeping the runtime image smaller and more reproducible.
+FROM eclipse-temurin:21.0.10_7-jre-alpine-3.23
+# Set the directory where the application will run.
WORKDIR /usr/src/run/
+# Copy only the runtime artifacts from the builder stage.
+# This keeps Maven, source code, and build dependencies out of the final image.
+COPY --from=builder /usr/src/app/tools/docker/docker-artifacts /usr/src/run/
+COPY --from=builder /usr/src/app/rest-api/target/rest-api.jar /usr/src/run/rest-api.jar
+
+# Prepare the startup script for the Alpine runtime.
+# 1. Remove Windows CRLF line endings if present.
+# 2. Replace a bash shebang with sh because Alpine includes /bin/sh by default,
+# but does not include /bin/bash unless bash is installed separately.
+# 3. Make the script executable.
+# 4. Validate that the required runtime files exist during image build.
+#
+# We intentionally do not run "apk upgrade" here.
+# The runtime image is pinned, so OS package versions come from the selected base image.
+# This keeps builds more reproducible and avoids transient failures from Alpine package repos.
+RUN sed -i 's/\r$//' /usr/src/run/qppConverter.sh \
+ && sed -i '1s|^#!/bin/bash|#!/bin/sh|' /usr/src/run/qppConverter.sh \
+ && chmod +x /usr/src/run/qppConverter.sh \
+ && test -f /usr/src/run/rest-api.jar \
+ && test -f /usr/src/run/qppConverter.sh
+
+# Application listens on 8443.
EXPOSE 8443
-CMD ["/usr/src/run/qppConverter.sh"]
+
+# Start the application using the existing startup script.
+CMD ["/usr/src/run/qppConverter.sh"]
\ No newline at end of file
diff --git a/DockerfileTest b/DockerfileTest
index 9f11d33bc..28b446748 100644
--- a/DockerfileTest
+++ b/DockerfileTest
@@ -1,21 +1,56 @@
-FROM maven:3.9.6-eclipse-temurin-21 AS builder
+# -----------------------------
+# Builder stage
+# -----------------------------
+# Uses Maven with Eclipse Temurin Java 21 on Alpine.
+# This stage builds the application jar only.
+FROM maven:3.9.15-eclipse-temurin-21-alpine AS builder
+# Copy the full project into the build container.
COPY ./ /usr/src/app/
-WORKDIR /usr/src/app/
-RUN mvn install -Dmaven.test.skip -Djacoco.skip=true > /dev/null
+# Set project directory.
+WORKDIR /usr/src/app/
-# Final stage
-FROM eclipse-temurin:21-jre
+# Build the project and create the application jar.
+# -B = batch mode, useful for CI
+# -ntp = no transfer progress, cleaner logs
+# Tests and JaCoCo are skipped because this image only needs the built runtime jar.
+RUN mvn -B -ntp install \
+ -Dmaven.test.skip=true \
+ -Djacoco.skip=true \
+ -Dskip.generate=true > /dev/null
-RUN apt-get update && apt-get install -y dos2unix && rm -rf /var/lib/apt/lists/*
-RUN mkdir -p /usr/src/run/
-COPY --from=builder /usr/src/app/rest-api/target/rest-api.jar /usr/src/run/
-COPY --from=builder /usr/src/app/tools/docker/docker-test-artifacts/* /usr/src/run/
-RUN dos2unix /usr/src/run/qppConverterTest.sh
+# -----------------------------
+# Final runtime stage
+# -----------------------------
+# Uses a smaller Alpine-based Eclipse Temurin Java 21 JRE image.
+# This avoids the Ubuntu-based OS package vulnerabilities reported by Snyk.
+FROM eclipse-temurin:21.0.10_7-jre-alpine-3.23
+# Set the runtime directory.
WORKDIR /usr/src/run/
+# Copy only the built jar from the builder stage.
+# This keeps Maven, source code, and build dependencies out of the final image.
+COPY --from=builder /usr/src/app/rest-api/target/rest-api.jar /usr/src/run/rest-api.jar
+
+# Copy test runtime artifacts, including qppConverterTest.sh.
+COPY --from=builder /usr/src/app/tools/docker/docker-test-artifacts/ /usr/src/run/
+
+# Fix the startup script for Alpine runtime:
+# 1. Remove Windows CRLF line endings if present.
+# 2. Replace #!/bin/bash with #!/bin/sh because Alpine does not include bash by default.
+# 3. Make the script executable.
+# 4. Validate that the jar and startup script exist during image build.
+RUN sed -i 's/\r$//' /usr/src/run/qppConverterTest.sh \
+ && sed -i '1s|^#!/bin/bash|#!/bin/sh|' /usr/src/run/qppConverterTest.sh \
+ && chmod +x /usr/src/run/qppConverterTest.sh \
+ && test -f /usr/src/run/rest-api.jar \
+ && test -f /usr/src/run/qppConverterTest.sh
+
+# Application test container listens on 8080.
EXPOSE 8080
-ENTRYPOINT ["/usr/src/run/qppConverterTest.sh"]
+
+# Start the test application using the startup script.
+ENTRYPOINT ["/usr/src/run/qppConverterTest.sh"]
\ No newline at end of file
diff --git a/acceptance-tests/pom.xml b/acceptance-tests/pom.xml
index 954308451..f3891dbf6 100644
--- a/acceptance-tests/pom.xml
+++ b/acceptance-tests/pom.xml
@@ -3,7 +3,7 @@
4.0.0
acceptance-tests
gov.cms.qpp.conversion
- 2026.03.31.01-RELEASE
+ 2026.05.01.01-RELEASE
conversion-tests
jar
@@ -13,6 +13,12 @@
+
+ com.fasterxml.jackson.core
+ jackson-core
+ 2.21.2
+
+
io.cucumber
cucumber-java
@@ -30,7 +36,7 @@
org.seleniumhq.selenium
selenium-java
- 4.14.0
+ 4.14.1
@@ -43,7 +49,7 @@
org.springframework
spring-web
- 6.1.21
+ 6.2.18
diff --git a/commandline/pom.xml b/commandline/pom.xml
index c2bd030b2..bec511301 100644
--- a/commandline/pom.xml
+++ b/commandline/pom.xml
@@ -6,7 +6,7 @@
gov.cms.qpp.conversion
qpp-conversion-tool-parent
- 2026.03.31.01-RELEASE
+ 2026.05.01.01-RELEASE
../pom.xml
@@ -68,6 +68,12 @@
+
+ com.fasterxml.jackson.core
+ jackson-core
+ 2.21.2
+
+
ch.qos.logback
logback-classic
diff --git a/commons/pom.xml b/commons/pom.xml
index 2c4a758b0..846d1b263 100644
--- a/commons/pom.xml
+++ b/commons/pom.xml
@@ -6,7 +6,7 @@
gov.cms.qpp.conversion
qpp-conversion-tool-parent
- 2026.03.31.01-RELEASE
+ 2026.05.01.01-RELEASE
../pom.xml
diff --git a/converter/pom.xml b/converter/pom.xml
index f77422b48..be87ebdc4 100644
--- a/converter/pom.xml
+++ b/converter/pom.xml
@@ -6,7 +6,7 @@
gov.cms.qpp.conversion
qpp-conversion-tool-parent
- 2026.03.31.01-RELEASE
+ 2026.05.01.01-RELEASE
../pom.xml
@@ -69,6 +69,12 @@
+
+ com.fasterxml.jackson.core
+ jackson-core
+ 2.21.2
+
+
com.google.code.findbugs
annotations
diff --git a/converter/src/test/java/gov/cms/qpp/conversion/encode/QualityMeasureIdEncoderTest.java b/converter/src/test/java/gov/cms/qpp/conversion/encode/QualityMeasureIdEncoderTest.java
index eb74b5a6c..9e6242940 100644
--- a/converter/src/test/java/gov/cms/qpp/conversion/encode/QualityMeasureIdEncoderTest.java
+++ b/converter/src/test/java/gov/cms/qpp/conversion/encode/QualityMeasureIdEncoderTest.java
@@ -3,6 +3,7 @@
import static com.google.common.truth.Truth.assertThat;
import com.jayway.jsonpath.TypeRef;
+import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -69,6 +70,11 @@ void setUp() {
MeasureConfigs.initMeasureConfigs(MeasureConfigs.TEST_MEASURE_DATA);
}
+ @AfterEach
+ void tearDown() {
+ MeasureConfigs.initMeasureConfigs(MeasureConfigs.DEFAULT_MEASURE_DATA_FILE_NAME);
+ }
+
@Test
void testMeasureIdIsEncoded() {
executeInternalEncode();
diff --git a/generate-race-cpcplus/pom.xml b/generate-race-cpcplus/pom.xml
index cebc0a23b..c3788db96 100644
--- a/generate-race-cpcplus/pom.xml
+++ b/generate-race-cpcplus/pom.xml
@@ -6,7 +6,7 @@
gov.cms.qpp.conversion
generateRaceCpcPlus
- 2026.03.31.01-RELEASE
+ 2026.05.01.01-RELEASE
generate-race-cpcplus
jar
@@ -56,6 +56,11 @@
+
+ com.fasterxml.jackson.core
+ jackson-core
+ 2.21.2
+
org.jdom
jdom2
diff --git a/generate/pom.xml b/generate/pom.xml
index 1f960c91c..60779bd5d 100644
--- a/generate/pom.xml
+++ b/generate/pom.xml
@@ -5,7 +5,7 @@
qpp-conversion-tool-parent
gov.cms.qpp.conversion
- 2026.03.31.01-RELEASE
+ 2026.05.01.01-RELEASE
../pom.xml
4.0.0
@@ -57,6 +57,12 @@
+
+ com.fasterxml.jackson.core
+ jackson-core
+ 2.21.2
+
+
com.github.spullara.mustache.java
diff --git a/pom.xml b/pom.xml
index 48b8fc136..68476a7bf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
gov.cms.qpp.conversion
qpp-conversion-tool-parent
pom
- 2026.03.31.01-RELEASE
+ 2026.05.01.01-RELEASE
QPP Conversion Tool
@@ -237,25 +237,25 @@
com.fasterxml.jackson.core
jackson-core
- 2.18.6
+ 2.21.2
com.fasterxml.jackson.core
jackson-annotations
- 2.18.6
+ 2.21
com.fasterxml.jackson.core
jackson-databind
- 2.18.6
+ 2.21.2
com.fasterxml.jackson.dataformat
jackson-dataformat-xml
- 2.18.6
+ 2.21.2
@@ -517,19 +517,19 @@
org.springframework
spring-webmvc
- 6.2.17
+ 6.2.18
org.springframework
spring-web
- 6.2.17
+ 6.2.18
org.springframework
spring-framework-bom
- 6.2.17
+ 6.2.18
pom
import
@@ -537,13 +537,13 @@
org.bouncycastle
bcprov-jdk18on
- 1.83
+ 1.84
com.fasterxml.jackson.module
jackson-module-jaxb-annotations
- 2.18.6
+ 2.21.2
@@ -555,17 +555,17 @@
org.apache.tomcat.embed
tomcat-embed-core
- 10.1.52
+ 10.1.54
org.apache.tomcat.embed
tomcat-embed-el
- 10.1.52
+ 10.1.54
org.apache.tomcat.embed
tomcat-embed-websocket
- 10.1.52
+ 10.1.54
diff --git a/qrda3-update-measures/pom.xml b/qrda3-update-measures/pom.xml
index 25631f9fd..090a0bd6e 100644
--- a/qrda3-update-measures/pom.xml
+++ b/qrda3-update-measures/pom.xml
@@ -4,7 +4,7 @@
gov.cms.qpp.conversion
qpp-update-measures
- 2026.03.31.01-RELEASE
+ 2026.05.01.01-RELEASE
qrda3-update-measures
jar
@@ -37,6 +37,11 @@
+
+ com.fasterxml.jackson.core
+ jackson-core
+ 2.21.2
+
org.jdom
jdom2
diff --git a/rest-api/pom.xml b/rest-api/pom.xml
index 73a72ae90..4bd2226f2 100644
--- a/rest-api/pom.xml
+++ b/rest-api/pom.xml
@@ -19,7 +19,7 @@
gov.cms.qpp.conversion
qpp-conversion-tool-parent
- 2026.03.31.01-RELEASE
+ 2026.05.01.01-RELEASE
../pom.xml
@@ -32,8 +32,9 @@
0.90
- 6.2.17
- 10.1.52
+ 6.2.18
+
+ managed-by-boot-bom
5.11.4
1.11.4
@@ -44,7 +45,7 @@
6.1.0
- 6.5.9
+ 6.5.10
@@ -58,7 +59,7 @@
org.springframework.boot
spring-boot-maven-plugin
- 3.4.8
+ 3.5.13
repackage
@@ -186,7 +187,7 @@
org.springframework.boot
spring-boot-dependencies
- 3.4.11
+ 3.5.14
pom
import
@@ -196,39 +197,28 @@
org.springframework
spring-webmvc
- 6.2.17
+ 6.2.18
org.springframework
spring-beans
- 6.2.17
+ 6.2.18
-
+
org.springframework
spring-framework-bom
- 6.2.17
+ 6.2.18
pom
import
-
-
- org.apache.tomcat.embed
- tomcat-embed-core
- 10.1.52
-
-
- org.apache.tomcat.embed
- tomcat-embed-el
- 10.1.52
-
-
- org.apache.tomcat.embed
- tomcat-embed-websocket
- 10.1.52
-
+
org.springframework.security
diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/HealthCheckController.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/HealthCheckController.java
index 109d1482f..abefcb0ba 100644
--- a/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/HealthCheckController.java
+++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/controllers/HealthCheckController.java
@@ -39,8 +39,6 @@ public HealthCheckController(VersionService version) {
HealthCheck healthCheck = new HealthCheck();
healthCheck.setImplementationVersion(version.getImplementationVersion());
healthCheck.setValidationUrl(System.getenv("VALIDATION_URL"));
- healthCheck.setPcfClose(System.getenv("CPC_END_DATE") + " EST");
- healthCheck.setValidationFile(System.getenv("CPC_PLUS_VALIDATION_FILE"));
healthCheck.setJavaVersion(System.getProperty("java.version"));
healthCheck.setStatus(HttpStatus.OK);
diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/model/HealthCheck.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/model/HealthCheck.java
index 760930bb4..988436f65 100644
--- a/rest-api/src/main/java/gov/cms/qpp/conversion/api/model/HealthCheck.java
+++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/model/HealthCheck.java
@@ -11,9 +11,7 @@ public class HealthCheck {
private String implementationVersion;
private HttpStatus status;
private String javaVersion;
- private String pcfClose;
private String validationUrl;
- private String validationFile;
public String getImplementationVersion() {
return implementationVersion;
@@ -33,16 +31,6 @@ public void setValidationUrl(String validationUrl) {
this.validationUrl = validationUrl;
}
- public String getValidationFile() { return validationFile; }
- public void setValidationFile(String validationFile) {
- this.validationFile = validationFile;
- }
-
- public String getPcfClose() { return pcfClose; }
- public void setPcfClose(String pcfClose) {
- this.pcfClose = pcfClose;
- }
-
public HttpStatus getStatus() { return status; }
public void setStatus(HttpStatus status) {
this.status = status;
@@ -63,15 +51,13 @@ public boolean equals(Object o) {
boolean equals = Objects.equals(implementationVersion, that.implementationVersion);
equals &= Objects.equals(status, that.status);
equals &= Objects.equals(javaVersion, that.javaVersion);
- equals &= Objects.equals(pcfClose, that.pcfClose);
equals &= Objects.equals(validationUrl, that.validationUrl);
- equals &= Objects.equals(validationFile, that.validationFile);
return equals;
}
@Override
public int hashCode() {
- return Objects.hash(implementationVersion, status, javaVersion, pcfClose, validationUrl, validationFile);
+ return Objects.hash(implementationVersion, status, javaVersion, validationUrl);
}
}
diff --git a/test-commons/pom.xml b/test-commons/pom.xml
index 721766610..5b0f622b4 100644
--- a/test-commons/pom.xml
+++ b/test-commons/pom.xml
@@ -6,7 +6,7 @@
gov.cms.qpp.conversion
qpp-conversion-tool-parent
- 2026.03.31.01-RELEASE
+ 2026.05.01.01-RELEASE
../pom.xml
@@ -40,6 +40,12 @@
+
+ com.fasterxml.jackson.core
+ jackson-core
+ 2.21.2
+
+
com.jayway.jsonpath
json-path
diff --git a/test-coverage/pom.xml b/test-coverage/pom.xml
index 05d3db351..676e17f67 100644
--- a/test-coverage/pom.xml
+++ b/test-coverage/pom.xml
@@ -6,7 +6,7 @@
gov.cms.qpp.conversion
qpp-conversion-tool-parent
- 2026.03.31.01-RELEASE
+ 2026.05.01.01-RELEASE
../pom.xml
@@ -19,6 +19,12 @@
+
+ com.fasterxml.jackson.core
+ jackson-core
+ 2.21.2
+
+
gov.cms.qpp.conversion
converter