Skip to content

Commit 7b59f01

Browse files
wolpertclaude
andcommitted
build(spring-boot): upgrade to Spring Boot 4.0.6 / Spring Security 7.0.5
Spring Boot 4 standardized on Jackson 3 (tools.jackson.*) — the same namespace pk-auth-core uses (ADR 0009) — so the Jackson 2 bridge module is gone. The core's PkAuthObjectMappers.pkAuthModule() is now registered directly as a Spring bean, and Spring picks it up automatically. - gradle/libs.versions.toml: spring-boot 4.0.6, spring-security 7.0.5; add spring-boot-webmvc-test for the AutoConfigureMockMvc artifact carved out of spring-boot-test-autoconfigure in Spring Boot 4. - pk-auth-core: make PkAuthObjectMappers.pkAuthModule() public so adapter modules can register it on host-framework ObjectMappers. - pk-auth-spring-boot-starter: delete PkAuthJacksonModule (Jackson 2 bridge); PkAuthWebAutoConfiguration registers the core's module directly. Tests migrated to tools.jackson.databind.ObjectMapper. - examples/spring-boot-demo: AutoConfigureMockMvc import moved to org.springframework.boot.webmvc.test.autoconfigure. - .github/dependabot.yml: drop the Spring Boot 4 / Spring Security 7 ignore rules now that the upgrade has landed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b6bb69c commit 7b59f01

10 files changed

Lines changed: 32 additions & 120 deletions

File tree

.github/dependabot.yml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,6 @@ updates:
2424
# the implementation artifact id, so this is the right Dependabot dependency-name.
2525
- dependency-name: "com.diffplug.spotless:com.diffplug.spotless.gradle.plugin"
2626
versions: [">=8"]
27-
# Spring Boot 4.x dropped Jackson 2 in favor of Jackson 3 (`tools.jackson.*`). Our Phase 8
28-
# adapter's `PkAuthJacksonModule` bridges Jackson 2 ↔ pk-auth's Jackson 3 wire types;
29-
# moving to Spring Boot 4 requires rewriting that bridge. Brief §6.10 also pins 3.5.x.
30-
- dependency-name: "org.springframework.boot:*"
31-
update-types: ["version-update:semver-major"]
32-
# Spring Security 7 is tied to Spring Framework 7 / Spring Boot 4. Stay on the 6.x line
33-
# until the Spring Boot 4 migration is planned.
34-
- dependency-name: "org.springframework.security:*"
35-
update-types: ["version-update:semver-major"]
3627
# Dropwizard 5 changes the bundle and configuration surface in ways the Phase 9 adapter
3728
# doesn't yet accommodate. Brief §6.11 also pins 4.x.
3829
- dependency-name: "io.dropwizard:*"

examples/spring-boot-demo/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ dependencies {
3434

3535
testImplementation(project(":pk-auth-testkit"))
3636
testImplementation(libs.spring.boot.starter.test)
37+
testImplementation(libs.spring.boot.webmvc.test)
3738
testImplementation(libs.spring.security.test)
3839
}
3940

examples/spring-boot-demo/src/test/java/com/codeheadsystems/pkauth/examples/spring/SpringBootDemoApplicationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
import org.junit.jupiter.api.Test;
1111
import org.springframework.beans.factory.annotation.Autowired;
12-
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
1312
import org.springframework.boot.test.context.SpringBootTest;
13+
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
1414
import org.springframework.http.MediaType;
1515
import org.springframework.test.web.servlet.MockMvc;
1616

gradle/libs.versions.toml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,13 @@ hikaricp = "7.0.2"
3939
aws-sdk = "2.44.6"
4040
testcontainers = "1.21.4"
4141

42-
# Spring Boot adapter (Phase 8). Brief §6.10 mandates Spring Boot 3.5.x / Spring Security 6.5.x.
43-
# Spring Boot 4.0 dropped Jackson 2 in favor of Jackson 3 (`tools.jackson.*`), which breaks our
44-
# Phase 8 Jackson 2 bridge (`PkAuthJacksonModule`). Stay on 3.5.x until we revisit the
45-
# Jackson-bridge strategy in a future phase. Dependabot ignore in .github/dependabot.yml keeps
46-
# this from getting bumped back automatically.
47-
spring-boot = "3.5.5"
48-
spring-security = "6.5.3"
42+
# Spring Boot adapter (Phase 8). Spring Boot 4 / Spring Security 7. Spring Boot 4 standardized
43+
# on Jackson 3 (`tools.jackson.*`), the same namespace pk-auth-core uses (ADR 0009) — so the
44+
# previous Jackson 2 bridge module is gone, replaced by direct registration of the core's
45+
# `PkAuthObjectMappers.pkAuthModule()` as a Spring bean. Brief §6.10 originally specified
46+
# 3.5.x / 6.5.x; the upgrade landed as a deliberate framework refresh.
47+
spring-boot = "4.0.6"
48+
spring-security = "7.0.5"
4949
# H2 in the demo so reviewers can run the spring-boot-demo without an external Postgres.
5050
# Confined to the demo's runtime; the starter does not pull it in.
5151
h2 = "2.4.240"
@@ -143,6 +143,9 @@ spring-boot-starter = { module = "org.springframework.boot:spring-boot-starter",
143143
spring-boot-starter-web = { module = "org.springframework.boot:spring-boot-starter-web", version.ref = "spring-boot" }
144144
spring-boot-starter-security = { module = "org.springframework.boot:spring-boot-starter-security", version.ref = "spring-boot" }
145145
spring-boot-starter-test = { module = "org.springframework.boot:spring-boot-starter-test", version.ref = "spring-boot" }
146+
# Spring Boot 4 carved AutoConfigureMockMvc / the MockMvc test slice out of
147+
# spring-boot-test-autoconfigure into a dedicated spring-boot-webmvc-test artifact.
148+
spring-boot-webmvc-test = { module = "org.springframework.boot:spring-boot-webmvc-test", version.ref = "spring-boot" }
146149
spring-boot-configuration-processor = { module = "org.springframework.boot:spring-boot-configuration-processor", version.ref = "spring-boot" }
147150
spring-security-test = { module = "org.springframework.security:spring-security-test", version.ref = "spring-security" }
148151
h2 = { module = "com.h2database:h2", version.ref = "h2" }

pk-auth-core/src/main/java/com/codeheadsystems/pkauth/json/PkAuthObjectMappers.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,13 @@ public static JsonMapper.Builder builder() {
5353
value -> value.withValueInclusion(JsonInclude.Include.NON_NULL));
5454
}
5555

56-
/** Module registering byte[] / UserHandle / ChallengeId (de)serializers. */
57-
static SimpleModule pkAuthModule() {
56+
/**
57+
* Returns a fresh {@link SimpleModule} registering the byte[] / {@link UserHandle} / {@link
58+
* ChallengeId} (de)serializers used by pk-auth's wire contract. Adapter modules that drive a
59+
* host-framework {@link ObjectMapper} (Spring Boot 4 / Micronaut on Jackson 3, etc.) register
60+
* this module so their mapper produces the same wire shape the core's mapper does.
61+
*/
62+
public static SimpleModule pkAuthModule() {
5863
SimpleModule module = new SimpleModule("pk-auth");
5964
module.addSerializer(byte[].class, new Base64UrlBytesSerializer());
6065
module.addDeserializer(byte[].class, new Base64UrlBytesDeserializer());

pk-auth-spring-boot-starter/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ dependencies {
6565
testImplementation(project(":pk-auth-persistence-jdbi"))
6666
testImplementation(project(":pk-auth-persistence-dynamodb"))
6767
testImplementation(libs.spring.boot.starter.test)
68+
testImplementation(libs.spring.boot.webmvc.test)
6869
testImplementation(libs.spring.security.test)
6970
testImplementation(libs.h2)
7071
testRuntimeOnly(libs.logback.classic)

pk-auth-spring-boot-starter/src/main/java/com/codeheadsystems/pkauth/spring/autoconfigure/PkAuthWebAutoConfiguration.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
package com.codeheadsystems.pkauth.spring.autoconfigure;
33

44
import com.codeheadsystems.pkauth.ceremony.PasskeyAuthenticationService;
5+
import com.codeheadsystems.pkauth.json.PkAuthObjectMappers;
56
import com.codeheadsystems.pkauth.jwt.PkAuthJwtIssuer;
67
import com.codeheadsystems.pkauth.jwt.PkAuthJwtValidator;
78
import com.codeheadsystems.pkauth.spi.CredentialRepository;
89
import com.codeheadsystems.pkauth.spring.security.PkAuthAuthenticationProvider;
910
import com.codeheadsystems.pkauth.spring.security.PkAuthJwtAuthenticationFilter;
1011
import com.codeheadsystems.pkauth.spring.web.PkAuthCeremonyController;
11-
import com.codeheadsystems.pkauth.spring.web.PkAuthJacksonModule;
1212
import org.slf4j.Logger;
1313
import org.slf4j.LoggerFactory;
1414
import org.springframework.boot.autoconfigure.AutoConfiguration;
@@ -24,6 +24,7 @@
2424
import org.springframework.security.web.SecurityFilterChain;
2525
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
2626
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
27+
import tools.jackson.databind.module.SimpleModule;
2728

2829
/**
2930
* Wires the HTTP-facing portion of the starter: the ceremony controller, the JWT validation filter,
@@ -50,14 +51,16 @@ public class PkAuthWebAutoConfiguration {
5051
private static final Logger LOG = LoggerFactory.getLogger(PkAuthWebAutoConfiguration.class);
5152

5253
/**
53-
* Register the pk-auth Jackson 2 module on every Spring Jackson {@code ObjectMapper} so the
54-
* starter's controllers produce the same base64url-no-padding wire format the testkit and
55-
* Jackson-3 core mapper use. Spring's autoconfigured {@code ObjectMapper} picks up every {@link
56-
* com.fasterxml.jackson.databind.Module} bean automatically.
54+
* Register the pk-auth Jackson 3 module on Spring's autoconfigured {@code ObjectMapper}. Spring
55+
* Boot 4 standardized on Jackson 3 ({@code tools.jackson.*}), the same namespace pk-auth-core's
56+
* ObjectMapper uses (ADR 0009); the core's {@link PkAuthObjectMappers#pkAuthModule()} supplies
57+
* the byte[] / UserHandle / ChallengeId (de)serializers, so Spring's mapper produces the same
58+
* base64url-no-padding wire format the testkit and core mapper use. Spring picks up every {@code
59+
* tools.jackson.databind.module.JacksonModule} bean automatically.
5760
*/
5861
@Bean
59-
public PkAuthJacksonModule pkAuthJacksonModule() {
60-
return new PkAuthJacksonModule();
62+
public SimpleModule pkAuthJacksonModule() {
63+
return PkAuthObjectMappers.pkAuthModule();
6164
}
6265

6366
@Bean

pk-auth-spring-boot-starter/src/main/java/com/codeheadsystems/pkauth/spring/web/PkAuthJacksonModule.java

Lines changed: 0 additions & 92 deletions
This file was deleted.

pk-auth-spring-boot-starter/src/test/java/com/codeheadsystems/pkauth/spring/PkAuthAdminIntegrationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import com.codeheadsystems.pkauth.config.RelyingPartyConfig;
2121
import com.codeheadsystems.pkauth.spi.UserLookup;
2222
import com.codeheadsystems.pkauth.testkit.FakeAuthenticator;
23-
import com.fasterxml.jackson.databind.ObjectMapper;
2423
import com.webauthn4j.converter.util.ObjectConverter;
2524
import org.junit.jupiter.api.BeforeEach;
2625
import org.junit.jupiter.api.Test;
@@ -32,6 +31,7 @@
3231
import org.springframework.test.web.servlet.MvcResult;
3332
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
3433
import org.springframework.web.context.WebApplicationContext;
34+
import tools.jackson.databind.ObjectMapper;
3535

3636
/** Exercises a couple of admin endpoints behind the JWT filter using a real JWT. */
3737
@SpringBootTest(classes = PkAuthTestApplication.class)

pk-auth-spring-boot-starter/src/test/java/com/codeheadsystems/pkauth/spring/PkAuthCeremonyIntegrationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import com.codeheadsystems.pkauth.jwt.PkAuthJwtValidator;
2121
import com.codeheadsystems.pkauth.spi.UserLookup;
2222
import com.codeheadsystems.pkauth.testkit.FakeAuthenticator;
23-
import com.fasterxml.jackson.databind.ObjectMapper;
2423
import com.webauthn4j.converter.util.ObjectConverter;
2524
import org.junit.jupiter.api.BeforeEach;
2625
import org.junit.jupiter.api.Test;
@@ -31,6 +30,7 @@
3130
import org.springframework.test.web.servlet.MvcResult;
3231
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
3332
import org.springframework.web.context.WebApplicationContext;
33+
import tools.jackson.databind.ObjectMapper;
3434

3535
/**
3636
* End-to-end ceremony test: register a passkey via {@code /auth/passkeys/registration/*}, assert

0 commit comments

Comments
 (0)