Skip to content

Commit 1267fe9

Browse files
chore(deps): align Java dependencies for the 1.0 baseline
1 parent 8f787c6 commit 1267fe9

20 files changed

Lines changed: 131 additions & 99 deletions

.changeset/new-apes-make.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
---
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.12/apache-maven-3.9.12-bin.zip
1+
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.16/apache-maven-3.9.16-bin.zip
22
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

server/application/pom.xml

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,23 +43,23 @@
4343
<skipCoverage>true</skipCoverage>
4444
<postgres.port>5432</postgres.port>
4545
<resilience4j.version>2.4.0</resilience4j.version>
46-
<okhttp.version>5.3.2</okhttp.version>
46+
<okhttp.version>5.5.0</okhttp.version>
4747
<docker-java.version>3.7.1</docker-java.version>
48-
<archunit.version>1.4.2</archunit.version>
49-
<spring-modulith.version>2.0.0</spring-modulith.version>
50-
<liquibase-hibernate7.version>5.0.3</liquibase-hibernate7.version>
51-
<springdoc.version>3.0.3</springdoc.version>
48+
<archunit.version>1.5.0</archunit.version>
49+
<spring-modulith.version>2.1.1</spring-modulith.version>
50+
<liquibase.version>5.0.4</liquibase.version>
51+
<liquibase-hibernate7.version>5.0.4</liquibase-hibernate7.version>
52+
<springdoc.version>3.1.0</springdoc.version>
5253
<springdoc-maven-plugin.version>1.5</springdoc-maven-plugin.version>
53-
<sentry.version>8.41.0</sentry.version>
54-
<slack-bolt.version>1.48.1</slack-bolt.version>
55-
<jnats.version>2.25.2</jnats.version>
56-
<jgit.version>7.6.0.202603022253-r</jgit.version>
57-
<java-jwt.version>4.5.2</java-jwt.version>
58-
<postgresql.version>42.7.12</postgresql.version>
54+
<sentry.version>8.53.0</sentry.version>
55+
<slack-bolt.version>1.50.0</slack-bolt.version>
56+
<jnats.version>2.26.2</jnats.version>
57+
<jgit.version>7.7.1.202607240634-r</jgit.version>
58+
<java-jwt.version>4.6.0</java-jwt.version>
5959
<therapi.version>0.15.0</therapi.version>
6060
<error-prone.version>2.50.0</error-prone.version>
6161
<nullaway.version>0.14.0</nullaway.version>
62-
<shedlock.version>5.16.0</shedlock.version>
62+
<shedlock.version>7.9.0</shedlock.version>
6363
<bucket4j.version>8.19.0</bucket4j.version>
6464
<maven.build.cache.skipCache>true</maven.build.cache.skipCache>
6565
<maven.build.cache.skipSave>true</maven.build.cache.skipSave>
@@ -190,8 +190,6 @@
190190
<artifactId>lombok</artifactId>
191191
<optional>true</optional>
192192
</dependency>
193-
<!-- Spring Modulith 2.0: declares module boundaries via @ApplicationModule,
194-
verified by ModulithVerificationTest in the architecture surefire group. -->
195193
<dependency>
196194
<groupId>org.springframework.modulith</groupId>
197195
<artifactId>spring-modulith-starter-core</artifactId>
@@ -375,6 +373,11 @@
375373
</dependencies>
376374
<dependencyManagement>
377375
<dependencies>
376+
<dependency>
377+
<groupId>com.tngtech.archunit</groupId>
378+
<artifactId>archunit</artifactId>
379+
<version>${archunit.version}</version>
380+
</dependency>
378381
<dependency>
379382
<groupId>com.squareup.okhttp3</groupId>
380383
<artifactId>okhttp-bom</artifactId>
@@ -454,7 +457,7 @@
454457
<plugin>
455458
<groupId>org.jacoco</groupId>
456459
<artifactId>jacoco-maven-plugin</artifactId>
457-
<version>0.8.14</version>
460+
<version>0.8.15</version>
458461
<executions>
459462
<execution>
460463
<id>default-prepare-agent</id>

server/application/src/main/java/de/tum/cit/aet/hephaestus/agent/runtime/worker/WorkerDrainCoordinator.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@
1414
import org.slf4j.LoggerFactory;
1515
import org.springframework.boot.availability.AvailabilityChangeEvent;
1616
import org.springframework.boot.availability.ReadinessState;
17-
import org.springframework.boot.web.server.context.WebServerGracefulShutdownLifecycle;
17+
import org.springframework.boot.web.server.context.WebServerApplicationContext;
1818
import org.springframework.context.ApplicationEventPublisher;
1919
import org.springframework.context.SmartLifecycle;
2020

2121
/**
22-
* SIGTERM-driven graceful shutdown for the worker. Runs at
23-
* {@link WebServerGracefulShutdownLifecycle#SMART_LIFECYCLE_PHASE} {@code - 1024} (after HTTP
22+
* Graceful shutdown for the worker. Runs at
23+
* {@link WebServerApplicationContext#GRACEFUL_SHUTDOWN_PHASE} {@code - 1024} (after HTTP
2424
* server stop, before executor teardown). Liveness stays {@code CORRECT} — kubelet must
2525
* not kill the pod early; only readiness flips to {@code REFUSING_TRAFFIC}.
2626
*
@@ -32,7 +32,7 @@ public class WorkerDrainCoordinator implements SmartLifecycle {
3232

3333
private static final Logger log = LoggerFactory.getLogger(WorkerDrainCoordinator.class);
3434

35-
static final int PHASE = WebServerGracefulShutdownLifecycle.SMART_LIFECYCLE_PHASE - 1024;
35+
static final int PHASE = WebServerApplicationContext.GRACEFUL_SHUTDOWN_PHASE - 1024;
3636

3737
private final WorkerControlClient client;
3838
private final WorkerCapacityState state;

server/application/src/main/java/de/tum/cit/aet/hephaestus/core/auth/jwt/CookieBearerTokenResolver.java

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,13 @@
44
import de.tum.cit.aet.hephaestus.core.security.StaleAuthCookieFilter;
55
import jakarta.servlet.http.Cookie;
66
import jakarta.servlet.http.HttpServletRequest;
7+
import org.jspecify.annotations.Nullable;
78
import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver;
89
import org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver;
910

1011
/**
11-
* Resolves the resource-server bearer token from the SPA's {@code __Host-HEPHAESTUS_AT} cookie
12-
* (name from {@link AuthProperties#cookieName()}), falling back to the standard
13-
* {@code Authorization: Bearer} header (ADR 0017).
14-
*
15-
* <p>The SPA authenticates by an HttpOnly access-token cookie set on the OAuth success path
16-
* ({@code HephaestusAuthSuccessHandler}) and sent automatically with {@code credentials:"include"};
17-
* it never sends an {@code Authorization} header. The framework default
18-
* ({@link DefaultBearerTokenResolver}) only reads the header, so without this resolver every
19-
* browser request is 401. Worker / API / bearer-token integration clients still authenticate via
20-
* the header fallback.
21-
*
22-
* <p>Order is cookie-first: a browser request carries only the cookie, while a non-browser client
23-
* carries only the header, so they never collide in practice. CSRF (double-submit) covers the
24-
* cookie-authenticated, state-changing browser path — see {@code SecurityConfig#requiresCsrf}.
12+
* Resolves the configured access-token cookie before falling back to a standard bearer header.
13+
* Rejected stale cookies are ignored. See ADR 0017 for the cookie-first security policy.
2514
*/
2615
public class CookieBearerTokenResolver implements BearerTokenResolver {
2716

@@ -33,10 +22,8 @@ public CookieBearerTokenResolver(AuthProperties properties) {
3322
}
3423

3524
@Override
36-
public String resolve(HttpServletRequest request) {
37-
// A stale cookie already rejected by StaleAuthCookieFilter: ignore it so this request stays
38-
// anonymous (a permitAll endpoint serves instead of 401ing on the dead token). The header
39-
// fallback below still applies for worker/API/bearer clients.
25+
public @Nullable String resolve(HttpServletRequest request) {
26+
// A rejected stale cookie must not authenticate this request.
4027
if (Boolean.TRUE.equals(request.getAttribute(StaleAuthCookieFilter.COOKIE_INVALID_ATTRIBUTE))) {
4128
return headerResolver.resolve(request);
4229
}
@@ -51,7 +38,6 @@ public String resolve(HttpServletRequest request) {
5138
}
5239
}
5340
}
54-
// No cookie token → fall back to the standard Authorization: Bearer header (worker/API/tests).
5541
return headerResolver.resolve(request);
5642
}
5743
}

server/application/src/main/java/de/tum/cit/aet/hephaestus/core/auth/oauth/CookieOAuth2AuthorizationRequestRepository.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.util.Base64;
1111
import java.util.LinkedHashMap;
1212
import java.util.Map;
13+
import java.util.Objects;
1314
import java.util.Set;
1415
import javax.crypto.Cipher;
1516
import javax.crypto.spec.GCMParameterSpec;
@@ -25,8 +26,7 @@
2526
* rather than the HTTP session. Required because every existing Hephaestus filter chain
2627
* is {@code STATELESS} — the Spring default
2728
* {@code HttpSessionOAuth2AuthorizationRequestRepository} would silently create a session
28-
* that the callback request cannot see on the next pod (the failure mode Wave-2 PE flagged
29-
* as the most likely "doesn't work on multi-pod" bug).
29+
* that the callback request cannot see on another pod.
3030
*
3131
* <h2>Cookie</h2>
3232
* Name {@value #COOKIE_NAME}; {@code HttpOnly}, {@code Secure}, {@code SameSite=Lax}
@@ -45,10 +45,7 @@
4545
* {@code "oauth2-state"} — distinct from any tenant or system AAD so a confused-deputy
4646
* substitution between domains is rejected.
4747
*
48-
* <h2>Multi-flight</h2>
49-
* v1 supports a single in-flight authorization request per browser. Opening a second
50-
* login tab while the first is mid-flight will invalidate the first. Acceptable for
51-
* launch UX; LRU multi-flight cookie can be added if real users hit issues.
48+
* <p>One authorization request is stored per browser; starting another replaces it.
5249
*/
5350
public class CookieOAuth2AuthorizationRequestRepository
5451
implements AuthorizationRequestRepository<OAuth2AuthorizationRequest> {
@@ -202,9 +199,9 @@ private static byte[] serialize(OAuth2AuthorizationRequest req) {
202199
StoredAuthorizationRequest stored = new StoredAuthorizationRequest(
203200
req.getAuthorizationUri(),
204201
req.getClientId(),
205-
req.getRedirectUri(),
202+
Objects.requireNonNull(req.getRedirectUri(), "OAuth redirect URI must be configured"),
206203
req.getScopes(),
207-
req.getState(),
204+
Objects.requireNonNull(req.getState(), "OAuth state must be generated before serialization"),
208205
req.getAuthorizationRequestUri(),
209206
stringifyValues(req.getAttributes()),
210207
stringifyValues(req.getAdditionalParameters()));

server/application/src/main/java/de/tum/cit/aet/hephaestus/core/auth/oauth/GitHubEmailOAuth2UserService.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.util.HashMap;
44
import java.util.List;
55
import java.util.Map;
6+
import java.util.Objects;
67
import java.util.Optional;
78
import org.slf4j.Logger;
89
import org.slf4j.LoggerFactory;
@@ -42,11 +43,13 @@ public class GitHubEmailOAuth2UserService implements OAuth2UserService<OAuth2Use
4243
@Override
4344
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
4445
OAuth2User user = delegate.loadUser(userRequest);
45-
String nameAttrKey = userRequest
46-
.getClientRegistration()
47-
.getProviderDetails()
48-
.getUserInfoEndpoint()
49-
.getUserNameAttributeName(); // "id"
46+
String nameAttrKey = Objects.requireNonNull(
47+
userRequest
48+
.getClientRegistration()
49+
.getProviderDetails()
50+
.getUserInfoEndpoint()
51+
.getUserNameAttributeName(),
52+
"GitHub user-name attribute must be configured");
5053

5154
Map<String, Object> attrs = new HashMap<>(user.getAttributes());
5255
fetchPrimaryVerifiedEmail(userRequest).ifPresent(email -> {

server/application/src/main/java/de/tum/cit/aet/hephaestus/core/auth/oauth/OutlineAuthInfoUserService.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.time.Duration;
55
import java.util.LinkedHashMap;
66
import java.util.Map;
7+
import java.util.Objects;
78
import java.util.Set;
89
import org.jspecify.annotations.Nullable;
910
import org.springframework.core.ParameterizedTypeReference;
@@ -61,11 +62,13 @@ public OutlineAuthInfoUserService() {
6162

6263
@Override
6364
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
64-
String authInfoUri = userRequest
65-
.getClientRegistration()
66-
.getProviderDetails()
67-
.getUserInfoEndpoint()
68-
.getUri();
65+
String authInfoUri = Objects.requireNonNull(
66+
userRequest
67+
.getClientRegistration()
68+
.getProviderDetails()
69+
.getUserInfoEndpoint()
70+
.getUri(),
71+
"Outline auth.info URI must be configured");
6972
Map<String, Object> body;
7073
try {
7174
body = webClient

server/application/src/main/java/de/tum/cit/aet/hephaestus/core/runtime/hub/WorkerSessionRegistry.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import java.util.concurrent.atomic.AtomicReference;
1212
import org.slf4j.Logger;
1313
import org.slf4j.LoggerFactory;
14-
import org.springframework.boot.web.server.context.WebServerGracefulShutdownLifecycle;
14+
import org.springframework.boot.web.server.context.WebServerApplicationContext;
1515
import org.springframework.context.ApplicationEventPublisher;
1616
import org.springframework.context.SmartLifecycle;
1717
import org.springframework.web.socket.CloseStatus;
@@ -118,8 +118,8 @@ public void stop() {
118118
@Override
119119
public int getPhase() {
120120
// SmartLifecycle stops in DESCENDING phase order — higher phase stops first. A phase
121-
// greater than WebServerGracefulShutdownLifecycle.SMART_LIFECYCLE_PHASE makes the WS
121+
// greater than WebServerApplicationContext.GRACEFUL_SHUTDOWN_PHASE makes the WS
122122
// registry drain BEFORE the embedded server stops accepting traffic.
123-
return WebServerGracefulShutdownLifecycle.SMART_LIFECYCLE_PHASE + 1;
123+
return WebServerApplicationContext.GRACEFUL_SHUTDOWN_PHASE + 1;
124124
}
125125
}

server/application/src/main/java/de/tum/cit/aet/hephaestus/integration/core/webhook/WebhookGracefulShutdown.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,24 @@
55
import java.util.concurrent.atomic.AtomicBoolean;
66
import org.slf4j.Logger;
77
import org.slf4j.LoggerFactory;
8-
import org.springframework.boot.web.server.context.WebServerGracefulShutdownLifecycle;
8+
import org.springframework.boot.web.server.context.WebServerApplicationContext;
99
import org.springframework.context.SmartLifecycle;
1010

1111
/**
12-
* Drains in-flight webhook publishes during graceful shutdown, AFTER the HTTP server has stopped
13-
* accepting new requests but BEFORE the NATS connection closes.
12+
* Drains in-flight webhook publishes after the HTTP server stops accepting requests and before the
13+
* NATS connection closes.
1414
*
15-
* <p>{@link SmartLifecycle} semantics: HIGHER phase stops FIRST. Sitting at a phase lower than
16-
* {@link WebServerGracefulShutdownLifecycle#SMART_LIFECYCLE_PHASE} means we stop after Spring's
15+
* <p>{@link SmartLifecycle} stops higher phases first. Sitting at a phase lower than
16+
* {@link WebServerApplicationContext#GRACEFUL_SHUTDOWN_PHASE} means we stop after Spring's
1717
* web server — no new requests can arrive while we drain.
1818
*
19-
* <p>The drain budget comes from {@code hephaestus.webhook.shutdown.drain-timeout}. Docker's
20-
* {@code stop_grace_period} (40s in compose) must cover Spring's HTTP drain plus this budget.
19+
* <p>The drain budget comes from {@code hephaestus.webhook.shutdown.drain-timeout}.
2120
*/
2221
public class WebhookGracefulShutdown implements SmartLifecycle {
2322

2423
private static final Logger log = LoggerFactory.getLogger(WebhookGracefulShutdown.class);
2524

26-
private static final int PHASE = WebServerGracefulShutdownLifecycle.SMART_LIFECYCLE_PHASE - 1024;
25+
private static final int PHASE = WebServerApplicationContext.GRACEFUL_SHUTDOWN_PHASE - 1024;
2726

2827
private final JetStreamPublisher publisher;
2928
private final Duration drainTimeout;

0 commit comments

Comments
 (0)