diff --git a/docker-compose.yaml b/docker-compose.yaml
index 4fded43d2facbb9b24fbe28b0a1903643777f9e1..42036f8a174a80f41673f72a30446e231712d259 100644
--- a/docker-compose.yaml
+++ b/docker-compose.yaml
@@ -23,7 +23,7 @@ services:
     depends_on:
       - foundationdb
   foundationdb:
-    image: eclipsefdn/foundationdb-api:production-a25f588-21
+    image: eclipsefdn/foundationdb-api:production-529fdf7-37
     ports:
       - '10112:8095'
     environment:
diff --git a/pom.xml b/pom.xml
index 00798ef87940ea5710667b9c2e1b4652155934f2..1cec70ce33faaf91925f0eb260796eb25b0db237 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,6 +7,7 @@
   <groupId>org.eclipsefoundation</groupId>
   <artifactId>eclipse-openvsx-api</artifactId>
   <version>1.0.0-SNAPSHOT</version>
+
   <properties>
     <compiler-plugin.version>3.11.0</compiler-plugin.version>
     <maven.compiler.source>17</maven.compiler.source>
@@ -15,11 +16,11 @@
     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
     <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
     <quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
-    <quarkus.platform.version>3.2.11.Final</quarkus.platform.version>
+    <quarkus.platform.version>3.8.3</quarkus.platform.version>
     <surefire-plugin.version>3.1.2</surefire-plugin.version>
     <auto-value.version>1.10.4</auto-value.version>
     <hibernate.version>5.5.6.Final</hibernate.version>
-    <eclipse-api-version>0.9.5</eclipse-api-version>
+    <eclipse-api-version>1.0.0</eclipse-api-version>
     <org.mapstruct.version>1.5.5.Final</org.mapstruct.version>
     <fdndb-api-version>1.0.6</fdndb-api-version>
     <sonar.sources>src/main</sonar.sources>
@@ -34,6 +35,7 @@
     <sonar.projectKey>eclipse-openvsx-api</sonar.projectKey>
     <sonar.projectName>Open VSX API</sonar.projectName>
   </properties>
+
   <repositories>
     <repository>
       <id>eclipsefdn</id>
@@ -46,6 +48,7 @@
       </snapshots>
     </repository>
   </repositories>
+
   <dependencyManagement>
     <dependencies>
       <dependency>
@@ -57,8 +60,8 @@
       </dependency>
     </dependencies>
   </dependencyManagement>
-  <dependencies>
 
+  <dependencies>
     <dependency>
       <groupId>org.eclipsefoundation</groupId>
       <artifactId>quarkus-core</artifactId>
@@ -87,13 +90,6 @@
       <artifactId>quarkus-oidc-client</artifactId>
     </dependency>
 
-    <!-- Annotation preprocessors - reduce all of the boiler plate -->
-    <dependency>
-      <groupId>com.google.auto.value</groupId>
-      <artifactId>auto-value-annotations</artifactId>
-      <version>${auto-value.version}</version>
-    </dependency>
-
     <!-- Testing dependencies only -->
     <dependency>
       <groupId>org.eclipsefoundation</groupId>
@@ -111,8 +107,8 @@
       <artifactId>quarkus-jacoco</artifactId>
       <scope>test</scope>
     </dependency>
-
   </dependencies>
+
   <build>
     <plugins>
       <plugin>
@@ -130,20 +126,7 @@
           </execution>
         </executions>
       </plugin>
-      <plugin>
-        <artifactId>maven-compiler-plugin</artifactId>
-        <version>${compiler-plugin.version}</version>
-        <configuration>
-          <annotationProcessorPaths>
-            <path>
-              <groupId>
-                com.google.auto.value</groupId>
-              <artifactId>auto-value</artifactId>
-              <version>${auto-value.version}</version>
-            </path>
-          </annotationProcessorPaths>
-        </configuration>
-      </plugin>
+
       <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
         <version>${surefire-plugin.version}</version>
@@ -159,6 +142,7 @@
       </plugin>
     </plugins>
   </build>
+  
   <profiles>
     <profile>
       <id>native</id>
diff --git a/spec/openapi.yaml b/spec/openapi.yaml
index 0e85889261ed914a66842be7a71e4a735109a0a4..02e49cd5a7931404b4fa8b8fc50c58127d746b47 100644
--- a/spec/openapi.yaml
+++ b/spec/openapi.yaml
@@ -202,6 +202,42 @@ components:
       type: array
       items:
         $ref: "#/components/schemas/EfUser"
+      example:
+        - uid: "606609"
+          name: zacharysabourin
+          mail: zachary.sabourin@eclipse-foundation.org
+          picture: https://secure.gravatar.com/avatar/fbbbb03860062596a5cf11105dcc7d47.jpg?d=mm&s=185&r=G
+          eca:
+            signed: true
+            can_contribute_spec_project: true
+          is_committer: true
+          first_name: Zachary
+          last_name: Sabourin
+          github_handle: zacharysabourin
+          twitter_handle: sometwitteruser
+          publisher_agreements:
+            "open-vsx":
+              version: "1"
+          org: Eclipse Foundation
+          org_id: null
+          job_title: Web Developer
+          website: https://google.com
+          country:
+            code: CA
+            name: Canada
+          bio: This is my bio. Hello!
+          interests:
+            - MTG
+            - Warhammer
+            - Bass guitar
+          working_groups_interests:
+            - adoptium
+            - oniro
+          eca_url: https://api.eclipse.org/account/profile/zacharysabourin/eca
+          projects_url: https://api.eclipse.org/account/profile/zacharysabourin/projects
+          gerrit_url: https://api.eclipse.org/account/profile/zacharysabourin/gerrit
+          mailinglist_url: https://api.eclipse.org/account/profile/zacharysabourin/mailing-list
+          mpc_favorites_url: https://api.eclipse.org/marketplace/favorites?name=zacharysabourin
 
     EfUser:
       type: object
@@ -346,10 +382,10 @@ components:
         working_groups_interests:
           - adoptium
           - oniro
-        eca_url: https://api.eclipse.org/sandbox/account/profile/zacharysabourin/eca
-        projects_url: https://api.eclipse.org/sandbox/account/profile/zacharysabourin/projects
-        gerrit_url: https://api.eclipse.org/sandbox/account/profile/zacharysabourin/gerrit
-        mailinglist_url: https://api.eclipse.org/sandbox/account/profile/zacharysabourin/mailing-list
+        eca_url: https://api.eclipse.org/account/profile/zacharysabourin/eca
+        projects_url: https://api.eclipse.org/account/profile/zacharysabourin/projects
+        gerrit_url: https://api.eclipse.org/account/profile/zacharysabourin/gerrit
+        mailinglist_url: https://api.eclipse.org/account/profile/zacharysabourin/mailing-list
         mpc_favorites_url: https://api.eclipse.org/marketplace/favorites?name=zacharysabourin
 
     Eca:
diff --git a/src/main/java/org/eclipsefoundation/openvsx/api/PeopleAPI.java b/src/main/java/org/eclipsefoundation/openvsx/api/PeopleAPI.java
index 702708438b0c0031686fcc60063c2e8574714535..a505cc9668c0bce8bc7b958a7ccf41a19b39f479 100644
--- a/src/main/java/org/eclipsefoundation/openvsx/api/PeopleAPI.java
+++ b/src/main/java/org/eclipsefoundation/openvsx/api/PeopleAPI.java
@@ -13,6 +13,12 @@ package org.eclipsefoundation.openvsx.api;
 
 import java.util.List;
 
+import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
+import org.eclipsefoundation.foundationdb.client.model.PeopleData;
+import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData;
+import org.eclipsefoundation.openvsx.api.models.ModLogHeaders;
+
+import io.quarkus.oidc.client.filter.OidcClientFilter;
 import jakarta.annotation.security.RolesAllowed;
 import jakarta.enterprise.context.ApplicationScoped;
 import jakarta.ws.rs.BeanParam;
@@ -25,13 +31,6 @@ import jakarta.ws.rs.QueryParam;
 import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.core.Response;
 
-import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
-import org.eclipsefoundation.foundationdb.client.model.PeopleData;
-import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData;
-import org.eclipsefoundation.openvsx.api.models.ModLogHeaders;
-
-import io.quarkus.oidc.client.filter.OidcClientFilter;
-
 /**
  * Fdndb-api binding for People resources.
  */
@@ -43,8 +42,7 @@ import io.quarkus.oidc.client.filter.OidcClientFilter;
 public interface PeopleAPI {
 
     /**
-     * Create a person record into foundationDB. Only status code is used to
-     * validate success of the operation.
+     * Create a person record into foundationDB. Only status code is used to validate success of the operation.
      * 
      * @param src The person to create
      * @return A Response containing the persisted person.
@@ -65,32 +63,30 @@ public interface PeopleAPI {
     PeopleData getPerson(@PathParam("personID") String personId);
 
     /**
-     * Fetches a list of all PeopleDocument entities tied to a given user filtered
-     * by documentID.
+     * Fetches a list of all PeopleDocument entities tied to a given user filtered by documentID.
      * 
-     * @param personId   The given ef username
+     * @param personId The given ef username
      * @param documentId The desired document id
      * @return A List of PeopleDocumentData entities if they exist
      */
     @GET
     @Path("{personID}/documents")
     @RolesAllowed("fdb_read_people_documents")
-    List<PeopleDocumentData> getPeopleDocument(@PathParam("personID") String personId,
-            @QueryParam("documentID") String documentId);
+    List<PeopleDocumentData> getPeopleDocument(@PathParam("personID") String personId, @QueryParam("documentID") String documentId,
+            @QueryParam("include_bytes") boolean includeBytes);
 
     /**
-     * Persists a PeopleDocumentData entity in foundationDb. Can be used to create
-     * new documents or update existing ones. Passes the required ModLog headers to
-     * allow automatic ModLogEvent tracking.
+     * Persists a PeopleDocumentData entity in foundationDb. Can be used to create new documents or update existing ones. Passes the
+     * required ModLog headers to allow automatic ModLogEvent tracking.
      * 
-     * @param modLog   The required ModLog headers
+     * @param modLog The required ModLog headers
      * @param personId The person signing the document
-     * @param src      The signed document(s).
+     * @param src The signed document(s).
      * @return A List of PeopleDocumentData entites if the operation was successful
      */
     @PUT
     @Path("{personID}/documents")
     @RolesAllowed("fdb_write_people_documents")
-    List<PeopleDocumentData> persistPeopleDocument(@BeanParam ModLogHeaders modLog,
-            @PathParam("personID") String personId, PeopleDocumentData src);
+    List<PeopleDocumentData> persistPeopleDocument(@BeanParam ModLogHeaders modLog, @PathParam("personID") String personId,
+            PeopleDocumentData src);
 }
diff --git a/src/main/java/org/eclipsefoundation/openvsx/api/SysAPI.java b/src/main/java/org/eclipsefoundation/openvsx/api/SysAPI.java
index 090432160c22da46ae7fd7b51a7b89361848c40b..3565cbb32c4cc193a7a5e443515700c9e7c15869 100644
--- a/src/main/java/org/eclipsefoundation/openvsx/api/SysAPI.java
+++ b/src/main/java/org/eclipsefoundation/openvsx/api/SysAPI.java
@@ -13,6 +13,10 @@ package org.eclipsefoundation.openvsx.api;
 
 import java.util.List;
 
+import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
+import org.eclipsefoundation.foundationdb.client.model.SysModLogData;
+
+import io.quarkus.oidc.client.filter.OidcClientFilter;
 import jakarta.annotation.security.RolesAllowed;
 import jakarta.enterprise.context.ApplicationScoped;
 import jakarta.ws.rs.PUT;
@@ -20,11 +24,6 @@ import jakarta.ws.rs.Path;
 import jakarta.ws.rs.Produces;
 import jakarta.ws.rs.core.MediaType;
 
-import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
-import org.eclipsefoundation.foundationdb.client.model.SysModLogData;
-
-import io.quarkus.oidc.client.filter.OidcClientFilter;
-
 /**
  * Fdndb-api binding for System resources.
  */
@@ -36,8 +35,7 @@ import io.quarkus.oidc.client.filter.OidcClientFilter;
 public interface SysAPI {
 
     /**
-     * Persists SysModLogData entities in foundationDB. Returns a list of
-     * created/updated results if the operation was successful.
+     * Persists SysModLogData entities in foundationDB. Returns a list of created/updated results if the operation was successful.
      * 
      * @param src The new/updated ModLog
      * @return A List or new/updated SysModLogData entities on success.
diff --git a/src/main/java/org/eclipsefoundation/openvsx/api/models/ModLogHeaders.java b/src/main/java/org/eclipsefoundation/openvsx/api/models/ModLogHeaders.java
index 842651ea83e5b648b8c11f28eacec0dd7753874c..fa833365f60cbd58b1c4e89d4e63898d54b832a6 100644
--- a/src/main/java/org/eclipsefoundation/openvsx/api/models/ModLogHeaders.java
+++ b/src/main/java/org/eclipsefoundation/openvsx/api/models/ModLogHeaders.java
@@ -11,60 +11,88 @@
 **********************************************************************/
 package org.eclipsefoundation.openvsx.api.models;
 
-import jakarta.annotation.Nullable;
 import jakarta.ws.rs.HeaderParam;
 
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
-import com.google.auto.value.AutoValue;
-
-@AutoValue
-@JsonDeserialize(builder = AutoValue_ModLogHeaders.Builder.class)
-public abstract class ModLogHeaders {
-
+/**
+ * Model used to capture X-ModLog-* header params.
+ */
+public class ModLogHeaders {
     @HeaderParam("X-ModLog-Key-1")
-    public abstract String getModLogKey1();
-
-    @Nullable
+    private String key1;
     @HeaderParam("X-ModLog-Key-2")
-    public abstract String getModLogKey2();
-
+    private String key2;
     @HeaderParam("X-ModLog-table")
-    public abstract String getModLogTable();
-
+    private String table;
     @HeaderParam("X-ModLog-Person")
-    public abstract String getModLogPerson();
-
-    @Nullable
+    private String person;
     @HeaderParam("X-ModLog-Action")
-    public abstract String getModLogAction();
-
-    @Nullable
+    private String action;
     @HeaderParam("X-ModLog-Time")
-    public abstract String getModLogTime();
+    private String time;
+
+    public ModLogHeaders() {
+        this.key1 = "api.eclipse.org";
+        this.table = "openvsx/publisher_agreement";
+    }
+
+    public ModLogHeaders(String key2, String person, String action) {
+        this("api.eclipse.org", key2, "openvsx/publisher_agreement", person, action, null);
+    }
+
+    public ModLogHeaders(String key1, String key2, String table, String person, String action, String time) {
+        this.key1 = key1;
+        this.key2 = key2;
+        this.table = table;
+        this.person = person;
+        this.action = action;
+        this.time = time;
+    }
 
-    public static Builder builder() {
-        return new AutoValue_ModLogHeaders.Builder()
-                .setModLogTable("openvsx/publisher_agreement")
-                .setModLogKey1("api.eclipse.org");
+    public String getKey1() {
+        return key1;
     }
 
-    @AutoValue.Builder
-    @JsonPOJOBuilder(withPrefix = "set")
-    public abstract static class Builder {
+    public void setKey1(String key1) {
+        this.key1 = key1;
+    }
 
-        public abstract Builder setModLogKey1(String key);
+    public String getKey2() {
+        return key2;
+    }
 
-        public abstract Builder setModLogKey2(String key);
+    public void setKey2(String key2) {
+        this.key2 = key2;
+    }
 
-        public abstract Builder setModLogTable(String table);
+    public String getTable() {
+        return table;
+    }
 
-        public abstract Builder setModLogPerson(String person);
+    public void setTable(String table) {
+        this.table = table;
+    }
 
-        public abstract Builder setModLogAction(String action);
+    public String getPerson() {
+        return person;
+    }
 
-        public abstract Builder setModLogTime(String time);
+    public void setPerson(String person) {
+        this.person = person;
+    }
+
+    public String getAction() {
+        return action;
+    }
+
+    public void setAction(String action) {
+        this.action = action;
+    }
+
+    public String getTime() {
+        return time;
+    }
 
-        public abstract ModLogHeaders build();
+    public void setTime(String time) {
+        this.time = time;
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/eclipsefoundation/openvsx/config/PublisherAgreementConfig.java b/src/main/java/org/eclipsefoundation/openvsx/config/PublisherAgreementConfig.java
index 09ed5c520981dc4dab01ddf48bb02306b371632e..bccc72851f49eeb19e4e7313d7e5fcad02058124 100644
--- a/src/main/java/org/eclipsefoundation/openvsx/config/PublisherAgreementConfig.java
+++ b/src/main/java/org/eclipsefoundation/openvsx/config/PublisherAgreementConfig.java
@@ -21,7 +21,7 @@ import io.smallrye.config.WithDefault;
  */
 @ConfigMapping(prefix = "eclipse.openvsx.publisher-agreement")
 public interface PublisherAgreementConfig {
-    
+
     String docId();
 
     @WithDefault("1")
diff --git a/src/main/java/org/eclipsefoundation/openvsx/models/AgreementSigningRequest.java b/src/main/java/org/eclipsefoundation/openvsx/models/AgreementSigningRequest.java
index b4297f833cd5bb311261740deed2118b78f11e9f..2e095a11a682b6e4aacca09f8da73c08970950ce 100644
--- a/src/main/java/org/eclipsefoundation/openvsx/models/AgreementSigningRequest.java
+++ b/src/main/java/org/eclipsefoundation/openvsx/models/AgreementSigningRequest.java
@@ -11,30 +11,9 @@
 **********************************************************************/
 package org.eclipsefoundation.openvsx.models;
 
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
-import com.google.auto.value.AutoValue;
+/**
+ * Model used to capture incoming publisher agreement signing requests.
+ */
+public record AgreementSigningRequest(String version, String githubHandle) {
 
-@AutoValue
-@JsonDeserialize(builder = AutoValue_AgreementSigningRequest.Builder.class)
-public abstract class AgreementSigningRequest {
-
-    public abstract String getVersion();
-
-    public abstract String getGithubHandle();
-
-    public static Builder builder() {
-        return new AutoValue_AgreementSigningRequest.Builder();
-    }
-
-    @AutoValue.Builder
-    @JsonPOJOBuilder(withPrefix = "set")
-    public abstract static class Builder {
-
-        public abstract Builder setVersion(String version);
-
-        public abstract Builder setGithubHandle(String handle);
-
-        public abstract AgreementSigningRequest build();
-    }
 }
diff --git a/src/main/java/org/eclipsefoundation/openvsx/models/DocumentBody.java b/src/main/java/org/eclipsefoundation/openvsx/models/DocumentBody.java
index 9ddc259031444371bc4c0cfb43e73837a1c85ab7..9b2dbc7264786ff06513a4768e1959851dcf7a63 100644
--- a/src/main/java/org/eclipsefoundation/openvsx/models/DocumentBody.java
+++ b/src/main/java/org/eclipsefoundation/openvsx/models/DocumentBody.java
@@ -11,49 +11,19 @@
 **********************************************************************/
 package org.eclipsefoundation.openvsx.models;
 
-import jakarta.annotation.Nullable;
-
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
-import com.google.auto.value.AutoValue;
-
-@AutoValue
-@JsonDeserialize(builder = AutoValue_DocumentBody.Builder.class)
-public abstract class DocumentBody {
-
-    public abstract String getVersion();
-
-    public abstract String getGithubHandle();
-
-    public abstract String getUsername();
-
-    public abstract String getFirstName();
-
-    public abstract String getLastName();
-
-    @Nullable
-    public abstract String getMail();
-
-    public static Builder builder() {
-        return new AutoValue_DocumentBody.Builder();
-    }
-
-    @AutoValue.Builder
-    @JsonPOJOBuilder(withPrefix = "set")
-    public abstract static class Builder {
-
-        public abstract Builder setVersion(String version);
-
-        public abstract Builder setGithubHandle(String handle);
-
-        public abstract Builder setUsername(String name);
-
-        public abstract Builder setFirstName(String name);
-
-        public abstract Builder setLastName(String name);
-
-        public abstract Builder setMail(String mail);
-
-        public abstract DocumentBody build();
+import java.util.Objects;
+
+/**
+ * Model used to represent the publisher agreement document. Gets serialized to a String then inserted into the DB as a Blob.
+ * Every field except mail is required to be non-null.
+ */
+public record DocumentBody(String version, String githubHandle, String username, String firstName, String lastName, String mail) {
+
+    public DocumentBody {
+        Objects.requireNonNull(version);
+        Objects.requireNonNull(githubHandle);
+        Objects.requireNonNull(username);
+        Objects.requireNonNull(firstName);
+        Objects.requireNonNull(lastName);
     }
 }
diff --git a/src/main/java/org/eclipsefoundation/openvsx/models/PublisherAgreementData.java b/src/main/java/org/eclipsefoundation/openvsx/models/PublisherAgreementData.java
index ced2569177e7b566c1c9dc086ed970e311bdbbdb..9b91aec0d26d4b8b9f9b65357bc60fdefd68a1f7 100644
--- a/src/main/java/org/eclipsefoundation/openvsx/models/PublisherAgreementData.java
+++ b/src/main/java/org/eclipsefoundation/openvsx/models/PublisherAgreementData.java
@@ -11,73 +11,35 @@
 **********************************************************************/
 package org.eclipsefoundation.openvsx.models;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
-import com.google.auto.value.AutoValue;
-
-@AutoValue
-@JsonDeserialize(builder = AutoValue_PublisherAgreementData.Builder.class)
-public abstract class PublisherAgreementData {
-
-    @JsonProperty("PersonID")
-    public abstract String getPersonID();
-
-    @JsonProperty("DocumentID")
-    public abstract String getDocumentID();
-
-    @JsonProperty("Version")
-    public abstract String getVersion();
-
-    @JsonProperty("EffectiveDate")
-    public abstract String getEffectiveDate();
-
-    @JsonProperty("ReceivedDate")
-    public abstract String getReceivedDate();
+import java.util.Objects;
 
-    @JsonProperty("ScannedDocumentBLOB")
-    public abstract String getScannedDocumentBlob();
-
-    @JsonProperty("ScannedDocumentMime")
-    public abstract String getScannedDocumentMime();
-
-    @JsonProperty("ScannedDocumentBytes")
-    public abstract String getScannedDocumentBytes();
-
-    @JsonProperty("ScannedDocumentFileName")
-    public abstract String getScannedDocumentFileName();
-
-    @JsonProperty("Comments")
-    public abstract String getComments();
-
-    public static Builder builder() {
-        return new AutoValue_PublisherAgreementData.Builder();
-    }
-
-    @AutoValue.Builder
-    @JsonPOJOBuilder(withPrefix = "set")
-    public abstract static class Builder {
-
-        public abstract Builder setPersonID(String id);
-
-        public abstract Builder setDocumentID(String id);
-
-        public abstract Builder setVersion(String version);
-
-        public abstract Builder setEffectiveDate(String date);
-
-        public abstract Builder setReceivedDate(String date);
-
-        public abstract Builder setScannedDocumentBlob(String blob);
-
-        public abstract Builder setScannedDocumentMime(String mime);
-
-        public abstract Builder setScannedDocumentBytes(String bytes);
-
-        public abstract Builder setScannedDocumentFileName(String name);
-
-        public abstract Builder setComments(String commetns);
+import com.fasterxml.jackson.annotation.JsonProperty;
 
-        public abstract PublisherAgreementData build();
+/**
+ * Model used to capture outbound PA data for a user. All fields are required to be non-null.
+ */
+public record PublisherAgreementData(
+    @JsonProperty("PersonID") String personId, 
+    @JsonProperty("DocumentID") String documentId,
+    @JsonProperty("Version") String version, 
+    @JsonProperty("EffectiveDate") String effectiveDate,
+    @JsonProperty("ReceivedDate") String receivedDate, 
+    @JsonProperty("ScannedDocumentBLOB") String scannedDocumentBlob,
+    @JsonProperty("ScannedDocumentMime") String scannedDocumentMime, 
+    @JsonProperty("ScannedDocumentBytes") String scannedDocumentBytes,
+    @JsonProperty("ScannedDocumentFileName") String scannedDocumentFiledName, 
+    @JsonProperty("Comments") String comments) {
+
+    public PublisherAgreementData {
+        Objects.requireNonNull(personId);
+        Objects.requireNonNull(documentId);
+        Objects.requireNonNull(version);
+        Objects.requireNonNull(effectiveDate);
+        Objects.requireNonNull(receivedDate);
+        Objects.requireNonNull(scannedDocumentBlob);
+        Objects.requireNonNull(scannedDocumentMime);
+        Objects.requireNonNull(scannedDocumentBytes);
+        Objects.requireNonNull(scannedDocumentFiledName);
+        Objects.requireNonNull(comments);
     }
 }
diff --git a/src/main/java/org/eclipsefoundation/openvsx/models/RequestUserProfileWrapper.java b/src/main/java/org/eclipsefoundation/openvsx/models/RequestUserProfileWrapper.java
index 1352857acf16386acd1e65d3206cb7f4779a61c2..9bdce63e47964c574c9fc2d072e06018b47c6ba9 100644
--- a/src/main/java/org/eclipsefoundation/openvsx/models/RequestUserProfileWrapper.java
+++ b/src/main/java/org/eclipsefoundation/openvsx/models/RequestUserProfileWrapper.java
@@ -11,19 +11,17 @@
 **********************************************************************/
 package org.eclipsefoundation.openvsx.models;
 
+import org.eclipsefoundation.efservices.api.models.EfUser;
+import org.eclipsefoundation.utils.exception.FinalForbiddenException;
+
 import jakarta.enterprise.context.RequestScoped;
 import jakarta.servlet.http.HttpServletRequest;
 
-import org.eclipsefoundation.core.exception.FinalForbiddenException;
-import org.eclipsefoundation.efservices.api.models.EfUser;
-
 /**
- * A RequestScoped bean that wraps the EfUser value set in the request
- * chain. This bean is used to access profile information about the
- * user associated with the current token. To set this data, a user search must
- * be performed using the 'uid' from the current oauth token info. To access
- * this data, a EfUser object must be set as the 'current_profile' property in
- * the HttpServletRequest bound to the current request chain.
+ * A RequestScoped bean that wraps the EfUser value set in the request chain. This bean is used to access profile information about the user
+ * associated with the current token. To set this data, a user search must be performed using the 'uid' from the current oauth token info.
+ * To access this data, a EfUser object must be set as the 'current_profile' property in the HttpServletRequest bound to the current request
+ * chain.
  */
 @RequestScoped
 public class RequestUserProfileWrapper {
diff --git a/src/main/java/org/eclipsefoundation/openvsx/request/OAuthFilter.java b/src/main/java/org/eclipsefoundation/openvsx/request/OAuthFilter.java
index 0bc6c6801e2272d6cf88987b47e3b3b2efa2d01e..325d3d6611867e148e3d5f22edc2a38e2e1349ed 100644
--- a/src/main/java/org/eclipsefoundation/openvsx/request/OAuthFilter.java
+++ b/src/main/java/org/eclipsefoundation/openvsx/request/OAuthFilter.java
@@ -14,25 +14,25 @@ package org.eclipsefoundation.openvsx.request;
 import java.io.IOException;
 import java.util.Optional;
 
-import jakarta.enterprise.inject.Instance;
-import jakarta.inject.Inject;
-import jakarta.ws.rs.container.ContainerRequestContext;
-import jakarta.ws.rs.container.ContainerRequestFilter;
-import jakarta.ws.rs.ext.Provider;
-
-import org.eclipsefoundation.core.config.OAuth2SecurityConfig;
-import org.eclipsefoundation.core.exception.FinalForbiddenException;
 import org.eclipsefoundation.efservices.api.models.DrupalOAuthData;
 import org.eclipsefoundation.efservices.api.models.EfUser;
 import org.eclipsefoundation.efservices.api.models.UserSearchParams;
 import org.eclipsefoundation.efservices.helpers.DrupalAuthHelper;
-import org.eclipsefoundation.efservices.services.AccountService;
 import org.eclipsefoundation.efservices.services.DrupalOAuthService;
+import org.eclipsefoundation.efservices.services.ProfileService;
+import org.eclipsefoundation.http.config.OAuth2SecurityConfig;
 import org.eclipsefoundation.openvsx.models.RequestUserProfileWrapper;
+import org.eclipsefoundation.utils.exception.FinalForbiddenException;
 import org.jboss.resteasy.util.HttpHeaderNames;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import jakarta.enterprise.inject.Instance;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerRequestFilter;
+import jakarta.ws.rs.ext.Provider;
+
 @Provider
 public class OAuthFilter implements ContainerRequestFilter {
     private static final Logger LOGGER = LoggerFactory.getLogger(OAuthFilter.class);
@@ -43,19 +43,17 @@ public class OAuthFilter implements ContainerRequestFilter {
     @Inject
     DrupalOAuthService oauthService;
     @Inject
-    AccountService accountService;
+    ProfileService profileService;
 
     @Override
     public void filter(ContainerRequestContext requestContext) throws IOException {
         if (Boolean.TRUE.equals(config.get().filter().enabled())) {
 
             // Strip token from Auth header
-            String token = DrupalAuthHelper
-                    .stripBearerToken(requestContext.getHeaderString(HttpHeaderNames.AUTHORIZATION));
+            String token = DrupalAuthHelper.stripBearerToken(requestContext.getHeaderString(HttpHeaderNames.AUTHORIZATION));
 
             DrupalOAuthData tokenStatus = oauthService
-                    .validateTokenStatus(token, config.get().filter().validScopes(),
-                            config.get().filter().validClientIds());
+                    .validateTokenStatus(token, config.get().filter().validScopes(), config.get().filter().validClientIds());
 
             // The incoming token must have a user associated with it.
             if (tokenStatus == null || tokenStatus.getUserId() == null) {
@@ -63,12 +61,11 @@ public class OAuthFilter implements ContainerRequestFilter {
             }
 
             // There is no openid scope incoming. User search needed for user data
-            Optional<EfUser> currentUserProfile = accountService
+            Optional<EfUser> currentUserProfile = profileService
                     .performUserSearch(UserSearchParams.builder().setUid(tokenStatus.getUserId()).build());
             if (currentUserProfile.isEmpty()) {
                 LOGGER.warn("Cannot find profile for user {}", tokenStatus.getUserId());
-                throw new FinalForbiddenException(
-                        String.format("Cannot find profile for user %s", tokenStatus.getUserId()));
+                throw new FinalForbiddenException(String.format("Cannot find profile for user %s", tokenStatus.getUserId()));
             }
 
             // Set profile data into context
diff --git a/src/main/java/org/eclipsefoundation/openvsx/resources/ProfileResource.java b/src/main/java/org/eclipsefoundation/openvsx/resources/ProfileResource.java
index 7b6582292a88a40b3a49e8ed4b2045285d0690c4..8f56a6424604248495f82e4523b3b760ed28b1ba 100644
--- a/src/main/java/org/eclipsefoundation/openvsx/resources/ProfileResource.java
+++ b/src/main/java/org/eclipsefoundation/openvsx/resources/ProfileResource.java
@@ -13,13 +13,13 @@ package org.eclipsefoundation.openvsx.resources;
 
 import java.util.Arrays;
 
+import org.eclipsefoundation.openvsx.models.RequestUserProfileWrapper;
+
 import jakarta.inject.Inject;
 import jakarta.ws.rs.GET;
 import jakarta.ws.rs.Path;
 import jakarta.ws.rs.core.Response;
 
-import org.eclipsefoundation.openvsx.models.RequestUserProfileWrapper;
-
 @Path("profile")
 public class ProfileResource {
 
diff --git a/src/main/java/org/eclipsefoundation/openvsx/resources/PublisherAgreementResource.java b/src/main/java/org/eclipsefoundation/openvsx/resources/PublisherAgreementResource.java
index ada7ea9c53bf100ba20093f49cbde1fb97086a93..8cf7d10cc70339977f4ee38252b6e716fec63f87 100644
--- a/src/main/java/org/eclipsefoundation/openvsx/resources/PublisherAgreementResource.java
+++ b/src/main/java/org/eclipsefoundation/openvsx/resources/PublisherAgreementResource.java
@@ -13,6 +13,18 @@ package org.eclipsefoundation.openvsx.resources;
 
 import java.util.Optional;
 
+import org.apache.commons.lang3.StringUtils;
+import org.eclipsefoundation.efservices.api.models.EfUser;
+import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData;
+import org.eclipsefoundation.http.model.WebError;
+import org.eclipsefoundation.openvsx.config.PublisherAgreementConfig;
+import org.eclipsefoundation.openvsx.models.AgreementSigningRequest;
+import org.eclipsefoundation.openvsx.models.PublisherAgreementData;
+import org.eclipsefoundation.openvsx.models.RequestUserProfileWrapper;
+import org.eclipsefoundation.openvsx.services.FoundationOperationService;
+import org.eclipsefoundation.openvsx.services.PublisherAgreementService;
+import org.eclipsefoundation.utils.exception.FinalForbiddenException;
+
 import jakarta.inject.Inject;
 import jakarta.ws.rs.BadRequestException;
 import jakarta.ws.rs.DELETE;
@@ -25,18 +37,6 @@ import jakarta.ws.rs.ServerErrorException;
 import jakarta.ws.rs.core.Response;
 import jakarta.ws.rs.core.Response.Status;
 
-import org.apache.commons.lang3.StringUtils;
-import org.eclipsefoundation.core.exception.FinalForbiddenException;
-import org.eclipsefoundation.core.model.Error;
-import org.eclipsefoundation.efservices.api.models.EfUser;
-import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData;
-import org.eclipsefoundation.openvsx.config.PublisherAgreementConfig;
-import org.eclipsefoundation.openvsx.models.AgreementSigningRequest;
-import org.eclipsefoundation.openvsx.models.PublisherAgreementData;
-import org.eclipsefoundation.openvsx.models.RequestUserProfileWrapper;
-import org.eclipsefoundation.openvsx.services.FoundationOperationService;
-import org.eclipsefoundation.openvsx.services.PublisherAgreementService;
-
 @Path("publisher_agreement")
 public class PublisherAgreementResource {
 
@@ -80,14 +80,13 @@ public class PublisherAgreementResource {
 
         // Conflict if already signed agreement that isn't expired
         if (agreementService.getPublisherAgreementByUsername(user.getName()).isPresent()) {
-            return new Error(Status.CONFLICT,
-                    "The request could not be completed due to a conflict with the current state of the resource.")
-                    .asResponse();
+            return new WebError(Status.CONFLICT,
+                    "The request could not be completed due to a conflict with the current state of the resource.").asResponse();
         }
 
         // Create user in fdndb if they don't exist
         if (!foundationService.createDbUserIfNotFound(user)) {
-            throw new ServerErrorException("Internal Server Error", 500);
+            throw new ServerErrorException("Internal Server Error", Status.INTERNAL_SERVER_ERROR);
         }
 
         // Attempt to persist the agreement data. Returning the result
@@ -127,43 +126,38 @@ public class PublisherAgreementResource {
 
         String currentUser = userProfile.getCurrentUserProfile().getName();
 
-        Optional<PeopleDocumentData> updateResult = agreementService.revokePublisherAgreement(fetchResult.get(),
-                currentUser);
+        Optional<PeopleDocumentData> updateResult = agreementService.revokePublisherAgreement(fetchResult.get(), currentUser);
         if (updateResult.isEmpty()) {
-            throw new ServerErrorException("Internal Server Error", 500);
+            throw new ServerErrorException("Internal Server Error", Status.INTERNAL_SERVER_ERROR);
         }
 
         return Response.noContent().build();
     }
 
     /**
-     * Validates the incoming signing request by ensuring the fields are in valid
-     * states, and that the user in the URL is the same as the one bound to the
-     * token.
+     * Validates the incoming signing request by ensuring the fields are in valid states, and that the user in the URL is the same as the
+     * one bound to the token.
      * 
      * @param request The incoming singing request
      */
     private void validateSigningRequest(AgreementSigningRequest request) {
-        if (!StringUtils.isNumeric(request.getVersion())
-                || Double.parseDouble(request.getVersion()) != config.docVersion()) {
+        if (!StringUtils.isNumeric(request.version()) || Double.parseDouble(request.version()) != config.docVersion()) {
             throw new BadRequestException("The version of the agreement is missing or invalid");
         }
 
-        if (StringUtils.isBlank(request.getGithubHandle())) {
+        if (StringUtils.isBlank(request.githubHandle())) {
             throw new BadRequestException("The github_handle is missing or invalid");
         }
 
         // Ensure GH handle from current user same as in request body.
-        if (!StringUtils.equalsIgnoreCase(userProfile.getCurrentUserProfile().getGithubHandle(),
-                request.getGithubHandle())) {
+        if (!StringUtils.equalsIgnoreCase(userProfile.getCurrentUserProfile().getGithubHandle(), request.githubHandle())) {
             throw new BadRequestException("The github_handle does not match our records.");
         }
     }
 
     /**
-     * Checks whether the token user is in the listed allowed users or if the token
-     * user is the same as the user in the request URL. Throws a
-     * FinalForbiddenException if the user can't access this resource
+     * Checks whether the token user is in the listed allowed users or if the token user is the same as the user in the request URL. Throws
+     * a FinalForbiddenException if the user can't access this resource
      * 
      * @param urlUsername The username in the request URL
      * @return True if current user can access endpoint
@@ -171,8 +165,7 @@ public class PublisherAgreementResource {
     void checkIfAdminOrSelf(String urlUsername) {
         // Reject request if current user is not in URL and they aren't an admin
         if (!urlUsername.equalsIgnoreCase(userProfile.getCurrentUserProfile().getName())
-                && config.adminUsers().stream().noneMatch(
-                        email -> email.equalsIgnoreCase(userProfile.getCurrentUserProfile().getMail()))) {
+                && config.adminUsers().stream().noneMatch(email -> email.equalsIgnoreCase(userProfile.getCurrentUserProfile().getMail()))) {
             throw new FinalForbiddenException(String.format("Access denied to resources for: %s", urlUsername));
         }
     }
diff --git a/src/main/java/org/eclipsefoundation/openvsx/services/FoundationOperationService.java b/src/main/java/org/eclipsefoundation/openvsx/services/FoundationOperationService.java
index 328ddb7b96f0534f003236b9eca5c575b6d28c9a..a897823b852ec6ab8d3a123a1f6c6ae0cd0cb3ab 100644
--- a/src/main/java/org/eclipsefoundation/openvsx/services/FoundationOperationService.java
+++ b/src/main/java/org/eclipsefoundation/openvsx/services/FoundationOperationService.java
@@ -19,14 +19,12 @@ import org.eclipsefoundation.foundationdb.client.model.SysModLogData;
 import org.eclipsefoundation.openvsx.api.models.ModLogHeaders;
 
 /**
- * Defines the service for performing specific CRUD operations on
- * FoundationDb-API.
+ * Defines the service for performing specific CRUD operations on FoundationDb-API.
  */
 public interface FoundationOperationService {
 
     /**
-     * Given the username, retrieves the most recent openvsx publisher
-     * agreement for the given user.
+     * Given the username, retrieves the most recent openvsx publisher agreement for the given user.
      * 
      * @param username The desired user's EF username.
      * @return An Optional containing a PeopleDocumentData entity if it exists.
@@ -34,32 +32,29 @@ public interface FoundationOperationService {
     Optional<PeopleDocumentData> fetchMostRecentDocument(String username);
 
     /**
-     * Sends a PeopleDocumentData object to the fdndb-api to be created/updated.
-     * Sets a set of ModLog headers to enable auto-event logging at request-time.
+     * Sends a PeopleDocumentData object to the fdndb-api to be created/updated. Sets a set of ModLog headers to enable auto-event logging
+     * at request-time.
      * 
-     * @param headers  The request ModLog headers
+     * @param headers The request ModLog headers
      * @param toInsert the document to insert
      * @return An Optional containing the updated document if it exists.
      */
     Optional<PeopleDocumentData> persistDocumentWithModLog(ModLogHeaders headers, PeopleDocumentData toInsert);
 
     /**
-     * Creates a SysModLogData entity using the desired values and sends it to
-     * fdndb-api.
+     * Creates a SysModLogData entity using the desired values and sends it to fdndb-api.
      * 
-     * @param pk1      The given pk1
+     * @param pk1 The given pk1
      * @param personId The person logging the event
      * @return An optional containing a SysModLogData entity if it exists
      */
     Optional<SysModLogData> insertErrorSysModLog(String pk1, String personId);
 
     /**
-     * Checks if the given user exists in fdndb. Creates a new record if they can't
-     * be found.
+     * Checks if the given user exists in fdndb. Creates a new record if they can't be found.
      * 
      * @param user The current user to add.
-     * @return True if success. False if there was an error performing the
-     *         operation.
+     * @return True if success. False if there was an error performing the operation.
      */
     boolean createDbUserIfNotFound(EfUser user);
 }
diff --git a/src/main/java/org/eclipsefoundation/openvsx/services/PublisherAgreementService.java b/src/main/java/org/eclipsefoundation/openvsx/services/PublisherAgreementService.java
index 20f0f7565b56d1ee75e365eaaca47afc66c4636c..cd61f7e067afb39e0cb5cc5f80516e3141b435bd 100644
--- a/src/main/java/org/eclipsefoundation/openvsx/services/PublisherAgreementService.java
+++ b/src/main/java/org/eclipsefoundation/openvsx/services/PublisherAgreementService.java
@@ -18,14 +18,12 @@ import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData;
 import org.eclipsefoundation.openvsx.models.PublisherAgreementData;
 
 /**
- * Defines the service for fetching, creating and revoking openvsx publisher
- * agreements.
+ * Defines the service for fetching, creating and revoking openvsx publisher agreements.
  */
 public interface PublisherAgreementService {
 
     /**
-     * Given the username, retrieves the most recent valid openvsx publisher
-     * agreement for the given user.
+     * Given the username, retrieves the most recent valid openvsx publisher agreement for the given user.
      * 
      * @param username The desired user's EF username.
      * @return An Optional containing a PublisherAgreementData entity if it exists.
@@ -33,22 +31,19 @@ public interface PublisherAgreementService {
     public Optional<PublisherAgreementData> getPublisherAgreementByUsername(String username);
 
     /**
-     * Creates a publisher agreement for the given user using the request
-     * body containing the user GH handle and document version. Inserts a modLog
-     * event on fail or pass. Returns an empty Optional if it encounters an error.
+     * Creates a publisher agreement for the given user using the request body containing the user GH handle and document version. Inserts a
+     * modLog event on fail or pass. Returns an empty Optional if it encounters an error.
      * 
      * @param user The current logged in user
-     * @return An Optional containing the created PublisherAgreementData entity if
-     *         it exists
+     * @return An Optional containing the created PublisherAgreementData entity if it exists
      */
     public Optional<PublisherAgreementData> createPublisherAgreement(EfUser user);
 
     /**
-     * Expires a Publisher agreement and updates it in the foundationdb. Inserts a
-     * modLog event on fail or pass. Returns an empty Optional if it encounters an
-     * error.
+     * Expires a Publisher agreement and updates it in the foundationdb. Inserts a modLog event on fail or pass. Returns an empty Optional
+     * if it encounters an error.
      * 
-     * @param document    The current signed publisher agreement
+     * @param document The current signed publisher agreement
      * @param currentUser The user bound to the token
      * @return An Optional containing the updated PeopleDocumentData if it exists
      */
diff --git a/src/main/java/org/eclipsefoundation/openvsx/services/impl/DefaultFoundationOperationService.java b/src/main/java/org/eclipsefoundation/openvsx/services/impl/DefaultFoundationOperationService.java
index b9c0a5e532ce61fce9237c3cb94b4d6e2d63d389..03e403f1a86ce2400b09fa64b85cf7d3c086883d 100644
--- a/src/main/java/org/eclipsefoundation/openvsx/services/impl/DefaultFoundationOperationService.java
+++ b/src/main/java/org/eclipsefoundation/openvsx/services/impl/DefaultFoundationOperationService.java
@@ -15,17 +15,13 @@ import java.time.ZonedDateTime;
 import java.util.List;
 import java.util.Optional;
 
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.inject.Inject;
-
-import org.apache.commons.lang3.StringUtils;
 import org.eclipse.microprofile.rest.client.inject.RestClient;
-import org.eclipsefoundation.core.model.RequestWrapper;
-import org.eclipsefoundation.core.service.CachingService;
+import org.eclipsefoundation.caching.service.CachingService;
 import org.eclipsefoundation.efservices.api.models.EfUser;
 import org.eclipsefoundation.foundationdb.client.model.PeopleData;
 import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData;
 import org.eclipsefoundation.foundationdb.client.model.SysModLogData;
+import org.eclipsefoundation.http.helper.IPParser;
 import org.eclipsefoundation.openvsx.api.PeopleAPI;
 import org.eclipsefoundation.openvsx.api.SysAPI;
 import org.eclipsefoundation.openvsx.api.models.ModLogHeaders;
@@ -36,6 +32,10 @@ import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.core.Response.Status;
+
 @ApplicationScoped
 public class DefaultFoundationOperationService implements FoundationOperationService {
     private static final Logger LOGGER = LoggerFactory.getLogger(DefaultFoundationOperationService.class);
@@ -43,34 +43,29 @@ public class DefaultFoundationOperationService implements FoundationOperationSer
     @Inject
     PublisherAgreementConfig config;
 
-    @Inject
     @RestClient
     PeopleAPI peopleAPI;
-    @Inject
     @RestClient
     SysAPI sysAPI;
 
     @Inject
     CachingService cache;
     @Inject
-    RequestWrapper wrap;
+    IPParser ipParser;
 
     @Override
     public Optional<PeopleDocumentData> fetchMostRecentDocument(String username) {
         try {
             LOGGER.debug("Fetching most recent publisher agreement for user: {}", username);
 
-            List<PeopleDocumentData> results = peopleAPI.getPeopleDocument(username, config.docId());
+            List<PeopleDocumentData> results = peopleAPI.getPeopleDocument(username, config.docId(), true);
             if (results == null || results.isEmpty()) {
                 LOGGER.warn("Unable to find agreement for user with name: {}", username);
                 return Optional.empty();
             }
 
             // Sort by date. Most recent first
-            return results
-                    .stream()
-                    .sorted((pDoc1, pDoc2) -> pDoc2.getEffectiveDate().compareTo(pDoc1.getEffectiveDate()))
-                    .findFirst();
+            return results.stream().sorted((pDoc1, pDoc2) -> pDoc2.getEffectiveDate().compareTo(pDoc1.getEffectiveDate())).findFirst();
 
         } catch (Exception e) {
             LOGGER.error("Error while fetching publisher agreement for user: {}", username, e);
@@ -99,7 +94,7 @@ public class DefaultFoundationOperationService implements FoundationOperationSer
                     .builder()
                     .setLogTable("openvsx/publisher_agreement")
                     .setPK1(pk1)
-                    .setPK2(getBestMatchingIP())
+                    .setPK2(ipParser.getBestMatchingIP())
                     .setLogAction(OpenvsxModLogActions.SQL_ERROR)
                     .setPersonId(personId)
                     .setModDateTime(ZonedDateTime.now())
@@ -144,7 +139,7 @@ public class DefaultFoundationOperationService implements FoundationOperationSer
                     .build();
 
             // Insert new person record
-            return peopleAPI.persistPersonEntity(person).getStatus() == 200;
+            return peopleAPI.persistPersonEntity(person).getStatus() == Status.OK.getStatusCode();
 
         } catch (Exception e) {
             LOGGER.error("Error inserting user: {}", user.getName(), e);
@@ -162,37 +157,11 @@ public class DefaultFoundationOperationService implements FoundationOperationSer
     private Optional<PeopleData> fetchFoundationUser(String personId) {
         try {
             LOGGER.debug("Fetching user: {}", personId);
-            return cache
-                    .get(personId, new MultivaluedMapImpl<>(), PeopleData.class, () -> peopleAPI.getPerson(personId))
-                    .getData();
+            return cache.get(personId, new MultivaluedMapImpl<>(), PeopleData.class, () -> peopleAPI.getPerson(personId)).getData();
         } catch (Exception e) {
             LOGGER.error("Error searching for user: {}", personId, e);
             insertErrorSysModLog("fetchFoundationUser", personId);
             return Optional.empty();
         }
     }
-
-    /**
-     * Retrieves the best IP for the current request, using the x-real-ip and x-forwarded-for headers to pull the
-     * information from the current request.
-     * 
-     * @return the best matching IP for current request, or localhost if none can be found
-     */
-    private String getBestMatchingIP() {
-        LOGGER.debug("Looking up best IP address");
-        // use real IP, followed by forwarded for to get the requests IP
-        String initialIp = wrap.getHeader("X-Real-Ip");
-        if (StringUtils.isBlank(initialIp)) {
-            String[] forwardedIps = StringUtils.split(wrap.getHeader("X-Forwarded-For"), ",\\s*");
-            if (forwardedIps != null && forwardedIps.length > 1) {
-                initialIp = forwardedIps[1];
-            }
-        }
-        // default to localhost if we can't find request information
-        if (StringUtils.isBlank(initialIp)) {
-            initialIp = "0.0.0.0";
-        }
-        return initialIp;
-    }
-
 }
diff --git a/src/main/java/org/eclipsefoundation/openvsx/services/impl/DefaultPublisherAgreementService.java b/src/main/java/org/eclipsefoundation/openvsx/services/impl/DefaultPublisherAgreementService.java
index a528f11e12b13ba7625230c10f02da06ef236b3f..ff64538aca93707b4ff1850b0f406bb6e5538017 100644
--- a/src/main/java/org/eclipsefoundation/openvsx/services/impl/DefaultPublisherAgreementService.java
+++ b/src/main/java/org/eclipsefoundation/openvsx/services/impl/DefaultPublisherAgreementService.java
@@ -19,11 +19,7 @@ import java.util.Date;
 import java.util.List;
 import java.util.Optional;
 
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.inject.Inject;
-
 import org.apache.commons.lang3.ArrayUtils;
-import org.eclipsefoundation.core.helper.DateTimeHelper;
 import org.eclipsefoundation.efservices.api.models.EfUser;
 import org.eclipsefoundation.foundationdb.client.model.PeopleDocumentData;
 import org.eclipsefoundation.openvsx.api.models.ModLogHeaders;
@@ -33,11 +29,15 @@ import org.eclipsefoundation.openvsx.models.PublisherAgreementData;
 import org.eclipsefoundation.openvsx.namespace.OpenvsxModLogActions;
 import org.eclipsefoundation.openvsx.services.FoundationOperationService;
 import org.eclipsefoundation.openvsx.services.PublisherAgreementService;
+import org.eclipsefoundation.utils.helper.DateTimeHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+
 @ApplicationScoped
 public class DefaultPublisherAgreementService implements PublisherAgreementService {
     private static final Logger LOGGER = LoggerFactory.getLogger(DefaultPublisherAgreementService.class);
@@ -63,29 +63,20 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
         try {
             LOGGER.debug("Creating publisher agreement for user: {}", user.getName());
 
-            ModLogHeaders headers = ModLogHeaders.builder()
-                    .setModLogKey2(user.getName())
-                    .setModLogAction(OpenvsxModLogActions.AGREEMENT_SIGNED)
-                    .setModLogPerson(user.getName()).build();
+            ModLogHeaders headers = new ModLogHeaders(user.getName(), user.getName(), OpenvsxModLogActions.AGREEMENT_SIGNED);
 
             LOGGER.debug("Encoding publisher agreement document for user: {}", user.getName());
 
             // Create document from user data + request info. Then encode it
-            String jsonDoc = objectMapper.writeValueAsString(DocumentBody.builder()
-                    .setVersion(String.valueOf(config.docVersion()))
-                    .setGithubHandle(user.getGithubHandle())
-                    .setUsername(user.getName())
-                    .setFirstName(user.getFirstName())
-                    .setLastName(user.getLastName())
-                    .setMail(user.getMail())
-                    .build());
-
-            Optional<PeopleDocumentData> creationResult = foundationService.persistDocumentWithModLog(headers,
-                    createDocumentSigningRequest(jsonDoc, user.getName()));
+            String jsonDoc = objectMapper
+                    .writeValueAsString(new DocumentBody(String.valueOf(config.docVersion()), user.getGithubHandle(), user.getName(),
+                            user.getFirstName(), user.getLastName(), user.getMail()));
+
+            Optional<PeopleDocumentData> creationResult = foundationService
+                    .persistDocumentWithModLog(headers, createDocumentSigningRequest(jsonDoc, user.getName()));
 
             // Convert to PublisherAgreementData if persistence successful
-            return creationResult.isEmpty() ? Optional.empty()
-                    : Optional.of(buildPublisherAgreement(creationResult.get(), false));
+            return creationResult.isEmpty() ? Optional.empty() : Optional.of(buildPublisherAgreement(creationResult.get(), false));
 
         } catch (Exception e) {
             LOGGER.error("Error while creating publisher agreement", e);
@@ -100,7 +91,8 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
             LOGGER.debug("{} is revoking publisher agreement for user: {}", currentUser, document.getPersonID());
 
             // Update the doc with an expiry date
-            PeopleDocumentData updated = PeopleDocumentData.builder()
+            PeopleDocumentData updated = PeopleDocumentData
+                    .builder()
                     .setPersonID(document.getPersonID())
                     .setDocumentID(document.getDocumentID())
                     .setVersion(document.getVersion())
@@ -114,10 +106,7 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
                     .setExpirationDate(new Date())
                     .build();
 
-            ModLogHeaders headers = ModLogHeaders.builder()
-                    .setModLogKey2(document.getPersonID())
-                    .setModLogAction(OpenvsxModLogActions.AGREEMENT_REVOKED)
-                    .setModLogPerson(currentUser).build();
+            ModLogHeaders headers = new ModLogHeaders(document.getPersonID(), currentUser, OpenvsxModLogActions.AGREEMENT_REVOKED);
 
             return foundationService.persistDocumentWithModLog(headers, updated);
 
@@ -135,8 +124,7 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
      * @return True if expired/invalid, false otherwise
      */
     private boolean isdocumentExpired(PeopleDocumentData document) {
-        boolean isExpired = document.getExpirationDate() != null
-                && document.getExpirationDate().before(Date.from(Instant.now()));
+        boolean isExpired = document.getExpirationDate() != null && document.getExpirationDate().before(Date.from(Instant.now()));
         if (isExpired) {
             LOGGER.warn("Most recent document is expired");
         }
@@ -144,11 +132,10 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
     }
 
     /**
-     * Creates an OpenVSX publisher agreement document signing request using the
-     * given user. Builds and encodes the current Publisher Agreement from the
-     * necessary fields.
+     * Creates an OpenVSX publisher agreement document signing request using the given user. Builds and encodes the current Publisher
+     * Agreement from the necessary fields.
      * 
-     * @param jsonDoc  The encoded Document as a Json String
+     * @param jsonDoc The encoded Document as a Json String
      * @param username The user signing the agreement
      * @return The constructed PeopleDocumentData object.
      */
@@ -160,7 +147,8 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
         // Set date to UTC timezone when creating
         Date now = Date.from(DateTimeHelper.now().toInstant());
 
-        return PeopleDocumentData.builder()
+        return PeopleDocumentData
+                .builder()
                 .setPersonID(username)
                 .setDocumentID(config.docId())
                 .setVersion(config.docVersion())
@@ -175,11 +163,10 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
     }
 
     /**
-     * Builds a PublisherAgreementData object using the given PeopleDocumentData
-     * entity. Has a flag to offset the received date by one day to compensate for
-     * the modification made by fdndb-api.
+     * Builds a PublisherAgreementData object using the given PeopleDocumentData entity. Has a flag to offset the received date by one day
+     * to compensate for the modification made by fdndb-api.
      * 
-     * @param document   The given PeopleDocumentData entity
+     * @param document The given PeopleDocumentData entity
      * @param adjustTime A Flag to increment the received date by a day
      * @return A populated PublisherAgreementData object
      */
@@ -187,8 +174,7 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
 
         // Conversion of List<Byte> to byte[] to allow conversion to string
         byte[] blob = document.getScannedDocumentBLOB() == null ? new byte[0]
-                : ArrayUtils.toPrimitive(
-                        document.getScannedDocumentBLOB().toArray(new Byte[document.getScannedDocumentBLOB().size()]));
+                : ArrayUtils.toPrimitive(document.getScannedDocumentBLOB().toArray(new Byte[document.getScannedDocumentBLOB().size()]));
 
         SimpleDateFormat effectiveDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
         SimpleDateFormat receivedDateFormat = new SimpleDateFormat("yyyy-MM-dd");
@@ -198,24 +184,14 @@ public class DefaultPublisherAgreementService implements PublisherAgreementServi
         // The 'received_date' column is only a 'date' type and gets rewinded a day when
         // adjusted for UTC time by fdndb-api. Flag should onlybe set on fetch requests
         if (adjustTime) {
-            ZonedDateTime adjustedTime = ZonedDateTime.parse(DateTimeHelper.toRFC3339(document.getReceivedDate()))
-                    .plusDays(1);
+            ZonedDateTime adjustedTime = ZonedDateTime.parse(DateTimeHelper.toRFC3339(document.getReceivedDate())).plusDays(1);
             receivedDate = receivedDateFormat.format(Date.from(adjustedTime.toInstant()));
         } else {
             receivedDate = receivedDateFormat.format(document.getReceivedDate());
         }
 
-        return PublisherAgreementData.builder()
-                .setPersonID(document.getPersonID())
-                .setDocumentID(document.getDocumentID())
-                .setVersion(Integer.toString((int) document.getVersion()))
-                .setEffectiveDate(effectiveDateFormat.format(document.getEffectiveDate()))
-                .setReceivedDate(receivedDate)
-                .setScannedDocumentBlob(new String(blob))
-                .setScannedDocumentMime(document.getScannedDocumentMime())
-                .setScannedDocumentBytes(Integer.toString(blob.length))
-                .setScannedDocumentFileName(document.getScannedDocumentFileName())
-                .setComments(document.getComments())
-                .build();
+        return new PublisherAgreementData(document.getPersonID(), document.getDocumentID(), Integer.toString((int) document.getVersion()),
+                effectiveDateFormat.format(document.getEffectiveDate()), receivedDate, new String(blob), document.getScannedDocumentMime(),
+                Integer.toString(blob.length), document.getScannedDocumentFileName(), document.getComments());
     }
 }
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 201f9db8c7a79459a91315661d6acfaa7f2f5190..dc480aaa55ac8ba25101f613c831b4757cd8990d 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -7,3 +7,7 @@ fdndb-api/mp-rest/url=http://foundationdb:8095
 %dev.fdndb-api/mp-rest/url=http://localhost:10112
 
 eclipse.security.oauth2.filter.enabled=true
+
+quarkus.log.file.enable=false
+
+quarkus.micrometer.enabled=true
\ No newline at end of file
diff --git a/src/test/java/org/eclipsefoundation/openvsx/resources/ProfileResourceTest.java b/src/test/java/org/eclipsefoundation/openvsx/resources/ProfileResourceTest.java
index b264da020268b68e946b0ba3473f1cab37a5b4d6..6124c935d96146947d4259b49d3fe327cac067d3 100644
--- a/src/test/java/org/eclipsefoundation/openvsx/resources/ProfileResourceTest.java
+++ b/src/test/java/org/eclipsefoundation/openvsx/resources/ProfileResourceTest.java
@@ -28,11 +28,9 @@ class ProfileResourceTest {
 
     public static final Optional<Map<String, Object>> userCreds = Optional.of(Map.of("Authorization", "Bearer token2"));
 
-    public static final Optional<Map<String, Object>> noUserCreds = Optional
-            .of(Map.of("Authorization", "Bearer token6"));
+    public static final Optional<Map<String, Object>> noUserCreds = Optional.of(Map.of("Authorization", "Bearer token6"));
 
-    public static final Optional<Map<String, Object>> invalidCreds = Optional
-            .of(Map.of("Authorization", "Bearer token1"));
+    public static final Optional<Map<String, Object>> invalidCreds = Optional.of(Map.of("Authorization", "Bearer token1"));
 
     public static final EndpointTestCase GET_CURRENT_SUCCESS = TestCaseHelper
             .prepareTestCase(BASE_URL, new String[] {}, SchemaNamespaceHelper.EF_USERS_SCHEMA_PATH)
diff --git a/src/test/java/org/eclipsefoundation/openvsx/resources/PublisherAgreementResourceTest.java b/src/test/java/org/eclipsefoundation/openvsx/resources/PublisherAgreementResourceTest.java
index 8d83417c891bab5d1aa4d8893933645a0bacc6bd..3bac45244a864ca9d7b7fd438008108ab0e1e60d 100644
--- a/src/test/java/org/eclipsefoundation/openvsx/resources/PublisherAgreementResourceTest.java
+++ b/src/test/java/org/eclipsefoundation/openvsx/resources/PublisherAgreementResourceTest.java
@@ -14,8 +14,6 @@ package org.eclipsefoundation.openvsx.resources;
 import java.util.Map;
 import java.util.Optional;
 
-import jakarta.inject.Inject;
-
 import org.eclipsefoundation.openvsx.models.AgreementSigningRequest;
 import org.eclipsefoundation.openvsx.test.helpers.SchemaNamespaceHelper;
 import org.eclipsefoundation.testing.helpers.TestCaseHelper;
@@ -28,6 +26,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 
 import io.quarkus.test.junit.QuarkusTest;
 import io.restassured.http.ContentType;
+import jakarta.inject.Inject;
 
 @QuarkusTest
 class PublisherAgreementResourceTest {
@@ -36,14 +35,11 @@ class PublisherAgreementResourceTest {
 
     public static final Optional<Map<String, Object>> userCreds = Optional.of(Map.of("Authorization", "Bearer token2"));
 
-    public static final Optional<Map<String, Object>> userNoDocCreds = Optional
-            .of(Map.of("Authorization", "Bearer token5"));
+    public static final Optional<Map<String, Object>> userNoDocCreds = Optional.of(Map.of("Authorization", "Bearer token5"));
 
-    public static final Optional<Map<String, Object>> invalidCreds = Optional
-            .of(Map.of("Authorization", "Bearer token1"));
+    public static final Optional<Map<String, Object>> invalidCreds = Optional.of(Map.of("Authorization", "Bearer token1"));
 
-    public static final Optional<Map<String, Object>> docCreateCreds = Optional
-            .of(Map.of("Authorization", "Bearer token7"));
+    public static final Optional<Map<String, Object>> docCreateCreds = Optional.of(Map.of("Authorization", "Bearer token7"));
 
     public static final EndpointTestCase GET_CURRENT_SUCCESS = TestCaseHelper
             .prepareTestCase(BASE_URL, new String[] {}, SchemaNamespaceHelper.PUBLISHER_AGREEMENT_SCHEMA_PATH)
@@ -75,8 +71,7 @@ class PublisherAgreementResourceTest {
             .build();
 
     public static final EndpointTestCase GET_USER_SUCCESS = TestCaseHelper
-            .prepareTestCase(USER_URL, new String[] { "fakeuser" },
-                    SchemaNamespaceHelper.PUBLISHER_AGREEMENT_SCHEMA_PATH)
+            .prepareTestCase(USER_URL, new String[] { "fakeuser" }, SchemaNamespaceHelper.PUBLISHER_AGREEMENT_SCHEMA_PATH)
             .setHeaderParams(userCreds)
             .build();
 
@@ -87,15 +82,13 @@ class PublisherAgreementResourceTest {
             .build();
 
     public static final EndpointTestCase FOR_USER_BAD_CREDS = TestCaseHelper
-            .prepareTestCase(USER_URL, new String[] { "fakeuser" },
-                    SchemaNamespaceHelper.PUBLISHER_AGREEMENT_SCHEMA_PATH)
+            .prepareTestCase(USER_URL, new String[] { "fakeuser" }, SchemaNamespaceHelper.PUBLISHER_AGREEMENT_SCHEMA_PATH)
             .setStatusCode(403)
             .setHeaderParams(invalidCreds)
             .build();
 
     public static final EndpointTestCase REVOKE_SUCCESS = TestCaseHelper
-            .prepareTestCase(USER_URL, new String[] { "fakeuser" },
-                    SchemaNamespaceHelper.PUBLISHER_AGREEMENT_SCHEMA_PATH)
+            .prepareTestCase(USER_URL, new String[] { "fakeuser" }, SchemaNamespaceHelper.PUBLISHER_AGREEMENT_SCHEMA_PATH)
             .setHeaderParams(userCreds)
             .setStatusCode(204)
             .build();
@@ -161,8 +154,7 @@ class PublisherAgreementResourceTest {
     void testPost_currentUser_success() {
         EndpointTestBuilder
                 .from(TestCaseHelper
-                        .prepareTestCase(BASE_URL, new String[] {},
-                                SchemaNamespaceHelper.PUBLISHER_AGREEMENT_SCHEMA_PATH)
+                        .prepareTestCase(BASE_URL, new String[] {}, SchemaNamespaceHelper.PUBLISHER_AGREEMENT_SCHEMA_PATH)
                         .setHeaderParams(docCreateCreds)
                         .build())
                 .doPost(generateSigningSample("nodoc"))
@@ -176,20 +168,12 @@ class PublisherAgreementResourceTest {
 
     @Test
     void testPost_currentUser_conflict_validateResponseFormat() {
-        EndpointTestBuilder
-                .from(POST_CURRENT_CONFLICT)
-                .doPost(generateSigningSample("fakeuser"))
-                .andCheckFormat()
-                .run();
+        EndpointTestBuilder.from(POST_CURRENT_CONFLICT).doPost(generateSigningSample("fakeuser")).andCheckFormat().run();
     }
 
     @Test
     void testPost_currentUser_conflict_validateSchema() {
-        EndpointTestBuilder
-                .from(POST_CURRENT_CONFLICT)
-                .doPost(generateSigningSample("fakeuser"))
-                .andCheckFormat()
-                .run();
+        EndpointTestBuilder.from(POST_CURRENT_CONFLICT).doPost(generateSigningSample("fakeuser")).andCheckFormat().run();
     }
 
     @Test
@@ -199,11 +183,7 @@ class PublisherAgreementResourceTest {
 
     @Test
     void testPost_currentUser_failure_invalidHandle_validateFormat() {
-        EndpointTestBuilder
-                .from(POST_CURRENT_INVALID_HANDLE)
-                .doPost(generateSigningSample("otheruser"))
-                .andCheckFormat()
-                .run();
+        EndpointTestBuilder.from(POST_CURRENT_INVALID_HANDLE).doPost(generateSigningSample("otheruser")).andCheckFormat().run();
     }
 
     @Test
@@ -279,9 +259,7 @@ class PublisherAgreementResourceTest {
 
     private String generateSigningSample(String ghHandle) {
         try {
-            return mapper
-                    .writeValueAsString(
-                            AgreementSigningRequest.builder().setVersion("1").setGithubHandle(ghHandle).build());
+            return mapper.writeValueAsString(new AgreementSigningRequest("1", ghHandle));
         } catch (JsonProcessingException e) {
             throw new RuntimeException(e);
         }
diff --git a/src/test/java/org/eclipsefoundation/openvsx/test/api/MockDrupalOAuthAPI.java b/src/test/java/org/eclipsefoundation/openvsx/test/api/MockDrupalOAuthAPI.java
index 6d0f62811f1287e35886d8c07350000573b5e7e7..fa454cb1e2f4a390b91be59675a0afd92ee33290 100644
--- a/src/test/java/org/eclipsefoundation/openvsx/test/api/MockDrupalOAuthAPI.java
+++ b/src/test/java/org/eclipsefoundation/openvsx/test/api/MockDrupalOAuthAPI.java
@@ -16,16 +16,15 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-import jakarta.enterprise.context.ApplicationScoped;
-
 import org.eclipse.microprofile.rest.client.inject.RestClient;
-import org.eclipsefoundation.core.exception.FinalForbiddenException;
 import org.eclipsefoundation.efservices.api.DrupalOAuthAPI;
 import org.eclipsefoundation.efservices.api.models.DrupalOAuthData;
 import org.eclipsefoundation.efservices.api.models.DrupalUserInfo;
 import org.eclipsefoundation.efservices.helpers.DrupalAuthHelper;
+import org.eclipsefoundation.utils.exception.FinalForbiddenException;
 
 import io.quarkus.test.Mock;
+import jakarta.enterprise.context.ApplicationScoped;
 
 @Mock
 @RestClient
@@ -37,70 +36,67 @@ public class MockDrupalOAuthAPI implements DrupalOAuthAPI {
 
     public MockDrupalOAuthAPI() {
         tokens = new ArrayList<>();
-        tokens.addAll(Arrays.asList(
-                DrupalOAuthData.builder()
-                        .setAccessToken("token1")
-                        .setClientId("client-id")
-                        .setExpires(1674111182)
-                        .setScope("read write")
-                        .build(),
-                DrupalOAuthData.builder()
-                        .setAccessToken("token2")
-                        .setClientId("test-id")
-                        .setUserId("42")
-                        .setExpires(Instant.now().getEpochSecond() + 20000)
-                        .setScope("read write admin")
-                        .build(),
-                DrupalOAuthData.builder()
-                        .setAccessToken("token3")
-                        .setClientId("test-id")
-                        .setExpires(1234567890)
-                        .setScope("read admin")
-                        .build(),
-                DrupalOAuthData.builder()
-                        .setAccessToken("token4")
-                        .setClientId("client-id")
-                        .setExpires(Instant.now().getEpochSecond() + 20000)
-                        .setScope("read write")
-                        .build(),
-                DrupalOAuthData.builder()
-                        .setAccessToken("token5")
-                        .setClientId("test-id")
-                        .setUserId("333")
-                        .setExpires(Instant.now().getEpochSecond() + 20000)
-                        .setScope("read write admin")
-                        .build(),
-                DrupalOAuthData.builder()
-                        .setAccessToken("token6")
-                        .setClientId("test-id")
-                        .setExpires(Instant.now().getEpochSecond() + 20000)
-                        .setScope("read write admin")
-                        .build(),
-                DrupalOAuthData.builder()
-                        .setAccessToken("token7")
-                        .setClientId("test-id")
-                        .setUserId("444")
-                        .setExpires(Instant.now().getEpochSecond() + 20000)
-                        .setScope("read write admin")
-                        .build()));
+        tokens
+                .addAll(Arrays
+                        .asList(DrupalOAuthData
+                                .builder()
+                                .setAccessToken("token1")
+                                .setClientId("client-id")
+                                .setExpires(1674111182)
+                                .setScope("read write")
+                                .build(),
+                                DrupalOAuthData
+                                        .builder()
+                                        .setAccessToken("token2")
+                                        .setClientId("test-id")
+                                        .setUserId("42")
+                                        .setExpires(Instant.now().getEpochSecond() + 20000)
+                                        .setScope("read write admin")
+                                        .build(),
+                                DrupalOAuthData
+                                        .builder()
+                                        .setAccessToken("token3")
+                                        .setClientId("test-id")
+                                        .setExpires(1234567890)
+                                        .setScope("read admin")
+                                        .build(),
+                                DrupalOAuthData
+                                        .builder()
+                                        .setAccessToken("token4")
+                                        .setClientId("client-id")
+                                        .setExpires(Instant.now().getEpochSecond() + 20000)
+                                        .setScope("read write")
+                                        .build(),
+                                DrupalOAuthData
+                                        .builder()
+                                        .setAccessToken("token5")
+                                        .setClientId("test-id")
+                                        .setUserId("333")
+                                        .setExpires(Instant.now().getEpochSecond() + 20000)
+                                        .setScope("read write admin")
+                                        .build(),
+                                DrupalOAuthData
+                                        .builder()
+                                        .setAccessToken("token6")
+                                        .setClientId("test-id")
+                                        .setExpires(Instant.now().getEpochSecond() + 20000)
+                                        .setScope("read write admin")
+                                        .build(),
+                                DrupalOAuthData
+                                        .builder()
+                                        .setAccessToken("token7")
+                                        .setClientId("test-id")
+                                        .setUserId("444")
+                                        .setExpires(Instant.now().getEpochSecond() + 20000)
+                                        .setScope("read write admin")
+                                        .build()));
 
         users = new ArrayList<>();
-        users.addAll(Arrays.asList(
-                DrupalUserInfo.builder()
-                        .setSub("42")
-                        .setName("fakeuser")
-                        .setGithubHandle("fakeuser")
-                        .build(),
-                DrupalUserInfo.builder()
-                        .setSub("333")
-                        .setName("otheruser")
-                        .setGithubHandle("other")
-                        .build(),
-                DrupalUserInfo.builder()
-                        .setSub("444")
-                        .setName("nodoc")
-                        .setGithubHandle("nodoc")
-                        .build()));
+        users
+                .addAll(Arrays
+                        .asList(DrupalUserInfo.builder().setSub("42").setName("fakeuser").setGithubHandle("fakeuser").build(),
+                                DrupalUserInfo.builder().setSub("333").setName("otheruser").setGithubHandle("other").build(),
+                                DrupalUserInfo.builder().setSub("444").setName("nodoc").setGithubHandle("nodoc").build()));
     }
 
     @Override
@@ -112,11 +108,9 @@ public class MockDrupalOAuthAPI implements DrupalOAuthAPI {
     public DrupalUserInfo getUserInfoFromToken(String token) {
         DrupalOAuthData tokenInfo = getTokenInfo(DrupalAuthHelper.stripBearerToken(token));
         if (tokenInfo == null || tokenInfo.getUserId() == null) {
-            throw new FinalForbiddenException(
-                    "The access token " + DrupalAuthHelper.stripBearerToken(token) + " provided is invalid");
+            throw new FinalForbiddenException("The access token " + DrupalAuthHelper.stripBearerToken(token) + " provided is invalid");
         }
 
-        return users.stream().filter(u -> u.getSub().equalsIgnoreCase(tokenInfo.getUserId())).findFirst()
-                .orElse(null);
+        return users.stream().filter(u -> u.getSub().equalsIgnoreCase(tokenInfo.getUserId())).findFirst().orElse(null);
     }
 }
\ No newline at end of file
diff --git a/src/test/java/org/eclipsefoundation/openvsx/test/api/MockPeopleAPI.java b/src/test/java/org/eclipsefoundation/openvsx/test/api/MockPeopleAPI.java
index db30b0c9fa5fd397dd45beef8b29cd9f76d73ff8..e4c0941aad4393ab0ee04d25ff510caebef44da3 100644
--- a/src/test/java/org/eclipsefoundation/openvsx/test/api/MockPeopleAPI.java
+++ b/src/test/java/org/eclipsefoundation/openvsx/test/api/MockPeopleAPI.java
@@ -20,10 +20,6 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.ws.rs.core.MultivaluedMap;
-import jakarta.ws.rs.core.Response;
-
 import org.apache.commons.lang3.ArrayUtils;
 import org.eclipse.microprofile.rest.client.inject.RestClient;
 import org.eclipsefoundation.foundationdb.client.model.PeopleData;
@@ -33,6 +29,9 @@ import org.eclipsefoundation.openvsx.api.models.ModLogHeaders;
 import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
 
 import io.quarkus.test.Mock;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.Response;
 
 @Mock
 @RestClient
@@ -68,24 +67,25 @@ public class MockPeopleAPI implements PeopleAPI {
     }
 
     @Override
-    public List<PeopleDocumentData> getPeopleDocument(String personId, String documentId) {
+    public List<PeopleDocumentData> getPeopleDocument(String personId, String documentId, boolean includeBytes) {
         return peopleDocs.get(personId).isEmpty() ? Collections.emptyList()
-                : peopleDocs.get(personId)
+                : peopleDocs
+                        .get(personId)
                         .stream()
                         .filter(pd -> pd.getDocumentID().equalsIgnoreCase(documentId))
                         .collect(Collectors.toList());
     }
 
     @Override
-    public List<PeopleDocumentData> persistPeopleDocument(ModLogHeaders modLog, String personId,
-            PeopleDocumentData src) {
+    public List<PeopleDocumentData> persistPeopleDocument(ModLogHeaders modLog, String personId, PeopleDocumentData src) {
 
         if (peopleDocs.get(personId) != null && !peopleDocs.get(personId).isEmpty()) {
 
             // Remove if exists. Then add it
-            Optional<PeopleDocumentData> existingDoc = peopleDocs.get(personId).stream()
-                    .filter(d -> d.getPersonID().equalsIgnoreCase(personId)
-                            && d.getDocumentID().equalsIgnoreCase(src.getDocumentID())
+            Optional<PeopleDocumentData> existingDoc = peopleDocs
+                    .get(personId)
+                    .stream()
+                    .filter(d -> d.getPersonID().equalsIgnoreCase(personId) && d.getDocumentID().equalsIgnoreCase(src.getDocumentID())
                             && d.getEffectiveDate().compareTo(src.getEffectiveDate()) == 0)
                     .findFirst();
             if (existingDoc.isPresent()) {
@@ -99,7 +99,8 @@ public class MockPeopleAPI implements PeopleAPI {
     }
 
     private PeopleData buildPeople(String personId) {
-        return PeopleData.builder()
+        return PeopleData
+                .builder()
                 .setPersonID(personId)
                 .setFname("test")
                 .setLname("entity")
@@ -112,7 +113,8 @@ public class MockPeopleAPI implements PeopleAPI {
     }
 
     private PeopleDocumentData buildPeopleDocument(String personId, String docId) {
-        return PeopleDocumentData.builder()
+        return PeopleDocumentData
+                .builder()
                 .setPersonID(personId)
                 .setDocumentID(docId)
                 .setVersion(1)
diff --git a/src/test/java/org/eclipsefoundation/openvsx/test/api/MockProfileAPI.java b/src/test/java/org/eclipsefoundation/openvsx/test/api/MockProfileAPI.java
index b168df2ff37ca27df059659e189b58d38ac67dee..7652803e6a37065e258bac6fa45efbe901f3c115 100644
--- a/src/test/java/org/eclipsefoundation/openvsx/test/api/MockProfileAPI.java
+++ b/src/test/java/org/eclipsefoundation/openvsx/test/api/MockProfileAPI.java
@@ -18,9 +18,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.stream.Collectors;
 
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.ws.rs.NotFoundException;
-
 import org.apache.commons.lang3.StringUtils;
 import org.eclipse.microprofile.rest.client.inject.RestClient;
 import org.eclipsefoundation.efservices.api.ProfileAPI;
@@ -29,6 +26,8 @@ import org.eclipsefoundation.efservices.api.models.EfUser.Country;
 import org.eclipsefoundation.efservices.api.models.UserSearchParams;
 
 import io.quarkus.test.Mock;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.ws.rs.NotFoundException;
 
 @Mock
 @RestClient
@@ -39,92 +38,98 @@ public class MockProfileAPI implements ProfileAPI {
 
     public MockProfileAPI() {
         this.users = new ArrayList<>();
-        this.users.addAll(Arrays.asList(
-                EfUser.builder()
-                        .setUid("666")
-                        .setName("firstlast")
-                        .setFullName("sample")
-                        .setGithubHandle("handle")
-                        .setMail("firstlast@test.com")
-                        .setPicture("pic url")
-                        .setFirstName("first")
-                        .setLastName("last")
-                        .setPublisherAgreements(new HashMap<>())
-                        .setTwitterHandle("")
-                        .setOrg("null")
-                        .setJobTitle("employee")
-                        .setWebsite("site url")
-                        .setCountry(Country.builder().build())
-                        .setInterests(Arrays.asList())
-                        .build(),
-                EfUser.builder()
-                        .setUid("42")
-                        .setName("fakeuser")
-                        .setFullName("sample")
-                        .setPicture("pic url")
-                        .setFirstName("fake")
-                        .setLastName("user")
-                        .setMail("fakeuser@test.com")
-                        .setPublisherAgreements(new HashMap<>())
-                        .setGithubHandle("fakeuser")
-                        .setTwitterHandle("")
-                        .setOrg("null")
-                        .setJobTitle("employee")
-                        .setWebsite("site url")
-                        .setCountry(Country.builder().build())
-                        .setInterests(Arrays.asList())
-                        .build(),
-                EfUser.builder()
-                        .setUid("333")
-                        .setName("otheruser")
-                        .setFullName("sample")
-                        .setGithubHandle("other")
-                        .setMail("admin@email.com")
-                        .setPicture("pic url")
-                        .setFirstName("other")
-                        .setLastName("user")
-                        .setPublisherAgreements(new HashMap<>())
-                        .setTwitterHandle("")
-                        .setOrg("null")
-                        .setJobTitle("employee")
-                        .setWebsite("site url")
-                        .setCountry(Country.builder().build())
-                        .setInterests(Arrays.asList())
-                        .build(),
-                EfUser.builder()
-                        .setUid("222")
-                        .setName("name")
-                        .setFullName("sample")
-                        .setGithubHandle("name")
-                        .setMail("Mail@test.com")
-                        .setPicture("pic url")
-                        .setFirstName("fake")
-                        .setLastName("user")
-                        .setPublisherAgreements(new HashMap<>())
-                        .setTwitterHandle("")
-                        .setOrg("null")
-                        .setJobTitle("employee")
-                        .setWebsite("site url")
-                        .setCountry(Country.builder().build())
-                        .setInterests(Arrays.asList())
-                        .build(),
-                EfUser.builder()
-                        .setUid("444")
-                        .setName("nodoc")
-                        .setFullName("sample")
-                        .setGithubHandle("nodoc")
-                        .setMail("nodoc@test.com")
-                        .setPicture("pic url")
-                        .setFirstName("no")
-                        .setLastName("doc")
-                        .setPublisherAgreements(new HashMap<>())
-                        .setTwitterHandle("")
-                        .setOrg("null")
-                        .setJobTitle("employee")
-                        .setWebsite("site url")
-                        .setCountry(Country.builder().build())
-                        .setInterests(Arrays.asList())
-                        .build()));
+        this.users
+                .addAll(Arrays
+                        .asList(EfUser
+                                .builder()
+                                .setUid("666")
+                                .setName("firstlast")
+                                .setFullName("sample")
+                                .setGithubHandle("handle")
+                                .setMail("firstlast@test.com")
+                                .setPicture("pic url")
+                                .setFirstName("first")
+                                .setLastName("last")
+                                .setPublisherAgreements(new HashMap<>())
+                                .setTwitterHandle("")
+                                .setOrg("null")
+                                .setJobTitle("employee")
+                                .setWebsite("site url")
+                                .setCountry(Country.builder().build())
+                                .setInterests(Arrays.asList())
+                                .build(),
+                                EfUser
+                                        .builder()
+                                        .setUid("42")
+                                        .setName("fakeuser")
+                                        .setFullName("sample")
+                                        .setPicture("pic url")
+                                        .setFirstName("fake")
+                                        .setLastName("user")
+                                        .setMail("fakeuser@test.com")
+                                        .setPublisherAgreements(new HashMap<>())
+                                        .setGithubHandle("fakeuser")
+                                        .setTwitterHandle("")
+                                        .setOrg("null")
+                                        .setJobTitle("employee")
+                                        .setWebsite("site url")
+                                        .setCountry(Country.builder().build())
+                                        .setInterests(Arrays.asList())
+                                        .build(),
+                                EfUser
+                                        .builder()
+                                        .setUid("333")
+                                        .setName("otheruser")
+                                        .setFullName("sample")
+                                        .setGithubHandle("other")
+                                        .setMail("admin@email.com")
+                                        .setPicture("pic url")
+                                        .setFirstName("other")
+                                        .setLastName("user")
+                                        .setPublisherAgreements(new HashMap<>())
+                                        .setTwitterHandle("")
+                                        .setOrg("null")
+                                        .setJobTitle("employee")
+                                        .setWebsite("site url")
+                                        .setCountry(Country.builder().build())
+                                        .setInterests(Arrays.asList())
+                                        .build(),
+                                EfUser
+                                        .builder()
+                                        .setUid("222")
+                                        .setName("name")
+                                        .setFullName("sample")
+                                        .setGithubHandle("name")
+                                        .setMail("Mail@test.com")
+                                        .setPicture("pic url")
+                                        .setFirstName("fake")
+                                        .setLastName("user")
+                                        .setPublisherAgreements(new HashMap<>())
+                                        .setTwitterHandle("")
+                                        .setOrg("null")
+                                        .setJobTitle("employee")
+                                        .setWebsite("site url")
+                                        .setCountry(Country.builder().build())
+                                        .setInterests(Arrays.asList())
+                                        .build(),
+                                EfUser
+                                        .builder()
+                                        .setUid("444")
+                                        .setName("nodoc")
+                                        .setFullName("sample")
+                                        .setGithubHandle("nodoc")
+                                        .setMail("nodoc@test.com")
+                                        .setPicture("pic url")
+                                        .setFirstName("no")
+                                        .setLastName("doc")
+                                        .setPublisherAgreements(new HashMap<>())
+                                        .setTwitterHandle("")
+                                        .setOrg("null")
+                                        .setJobTitle("employee")
+                                        .setWebsite("site url")
+                                        .setCountry(Country.builder().build())
+                                        .setInterests(Arrays.asList())
+                                        .build()));
     }
 
     @Override
@@ -137,16 +142,13 @@ public class MockProfileAPI implements ProfileAPI {
 
         // Only filter via additional fields if it can't find with previous ones
         if (params.getUid() != null) {
-            results = users.stream().filter(u -> u.getUid().compareTo(params.getUid()) == 0)
-                    .collect(Collectors.toList());
+            results = users.stream().filter(u -> u.getUid().compareTo(params.getUid()) == 0).collect(Collectors.toList());
         }
         if (StringUtils.isNotBlank(params.getName()) && results.isEmpty()) {
-            results = users.stream().filter(u -> u.getName().equalsIgnoreCase(params.getName()))
-                    .collect(Collectors.toList());
+            results = users.stream().filter(u -> u.getName().equalsIgnoreCase(params.getName())).collect(Collectors.toList());
         }
         if (StringUtils.isNotBlank(params.getMail()) && results.isEmpty()) {
-            results = users.stream().filter(u -> u.getMail().equalsIgnoreCase(params.getMail()))
-                    .collect(Collectors.toList());
+            results = users.stream().filter(u -> u.getMail().equalsIgnoreCase(params.getMail())).collect(Collectors.toList());
         }
 
         return results;
@@ -154,13 +156,19 @@ public class MockProfileAPI implements ProfileAPI {
 
     @Override
     public EfUser getUserByEfUsername(String token, String username) {
-        return users.stream().filter(u -> u.getName().equalsIgnoreCase(username)).findFirst()
+        return users
+                .stream()
+                .filter(u -> u.getName().equalsIgnoreCase(username))
+                .findFirst()
                 .orElseThrow(() -> new NotFoundException(String.format("User '%s' not found", username)));
     }
 
     @Override
     public EfUser getUserByGithubHandle(String token, String handle) {
-        return users.stream().filter(u -> u.getGithubHandle().equalsIgnoreCase(handle)).findFirst()
+        return users
+                .stream()
+                .filter(u -> u.getGithubHandle().equalsIgnoreCase(handle))
+                .findFirst()
                 .orElseThrow(() -> new NotFoundException(String.format("User '%s' not found", handle)));
     }
 }
diff --git a/src/test/java/org/eclipsefoundation/openvsx/test/api/MockSysAPI.java b/src/test/java/org/eclipsefoundation/openvsx/test/api/MockSysAPI.java
index 2897b79ebadc0e2201a30442bc1bf8d2b54a6b39..517df61e806951497f9d4620fc327119411f29f2 100644
--- a/src/test/java/org/eclipsefoundation/openvsx/test/api/MockSysAPI.java
+++ b/src/test/java/org/eclipsefoundation/openvsx/test/api/MockSysAPI.java
@@ -15,13 +15,12 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-import jakarta.enterprise.context.ApplicationScoped;
-
 import org.eclipse.microprofile.rest.client.inject.RestClient;
 import org.eclipsefoundation.foundationdb.client.model.SysModLogData;
 import org.eclipsefoundation.openvsx.api.SysAPI;
 
 import io.quarkus.test.Mock;
+import jakarta.enterprise.context.ApplicationScoped;
 
 @Mock
 @RestClient
diff --git a/src/test/java/org/eclipsefoundation/openvsx/test/helpers/SchemaNamespaceHelper.java b/src/test/java/org/eclipsefoundation/openvsx/test/helpers/SchemaNamespaceHelper.java
index 029f54ab561f01f42237d022311e4d6b64a97007..9907e222a166bcaa1339bf6e36e75410e2d201b6 100644
--- a/src/test/java/org/eclipsefoundation/openvsx/test/helpers/SchemaNamespaceHelper.java
+++ b/src/test/java/org/eclipsefoundation/openvsx/test/helpers/SchemaNamespaceHelper.java
@@ -15,10 +15,8 @@ public class SchemaNamespaceHelper {
     public static final String BASE_SCHEMA_PATH = "schemas/";
     public static final String BASE_SCHEMA_PATH_SUFFIX = "-schema.json";
 
-    public static final String SIGNING_REQUEST_SCHEMA_PATH = BASE_SCHEMA_PATH + "agreement-signing-request"
-            + BASE_SCHEMA_PATH_SUFFIX;
-    public static final String PUBLISHER_AGREEMENT_SCHEMA_PATH = BASE_SCHEMA_PATH + "publisher-agreement"
-            + BASE_SCHEMA_PATH_SUFFIX;
+    public static final String SIGNING_REQUEST_SCHEMA_PATH = BASE_SCHEMA_PATH + "agreement-signing-request" + BASE_SCHEMA_PATH_SUFFIX;
+    public static final String PUBLISHER_AGREEMENT_SCHEMA_PATH = BASE_SCHEMA_PATH + "publisher-agreement" + BASE_SCHEMA_PATH_SUFFIX;
     public static final String EF_USER_SCHEMA_PATH = BASE_SCHEMA_PATH + "ef-user" + BASE_SCHEMA_PATH_SUFFIX;
     public static final String EF_USERS_SCHEMA_PATH = BASE_SCHEMA_PATH + "ef-users" + BASE_SCHEMA_PATH_SUFFIX;
     public static final String ERROR_SCHEMA_PATH = BASE_SCHEMA_PATH + "error" + BASE_SCHEMA_PATH_SUFFIX;
diff --git a/src/test/java/org/eclipsefoundation/openvsx/test/services/impl/MockDrupalTokenService.java b/src/test/java/org/eclipsefoundation/openvsx/test/services/impl/MockDrupalTokenService.java
index 2f2da19ad0622aa30ee0ab517be691eae1a2867e..a8b26d1240fa9295afa9832b8c5744c107ab50ae 100644
--- a/src/test/java/org/eclipsefoundation/openvsx/test/services/impl/MockDrupalTokenService.java
+++ b/src/test/java/org/eclipsefoundation/openvsx/test/services/impl/MockDrupalTokenService.java
@@ -11,11 +11,10 @@
 **********************************************************************/
 package org.eclipsefoundation.openvsx.test.services.impl;
 
-import jakarta.enterprise.context.ApplicationScoped;
-
 import org.eclipsefoundation.efservices.services.DrupalTokenService;
 
 import io.quarkus.test.Mock;
+import jakarta.enterprise.context.ApplicationScoped;
 
 @Mock
 @ApplicationScoped