chore: record pre-existing uncommitted repository state

Snapshot of the in-flight state that already existed, identically, in both
this worktree and the main checkout before this session began: the initial
HTTP Client platform implementation (previously untracked), the redis-lab
removal, and the JPA / object-storage / notification integration work.

Kept separate from this session's HTTP Client review response, which lands
in the following commit, so the two bodies of work stay reviewable apart.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
DongHyeonka
2026-08-11 16:48:43 +09:00
co-authored by Claude Opus 5
parent 1a3b560678
commit 5f10b791d3
1857 changed files with 130925 additions and 72491 deletions
@@ -91,7 +91,7 @@ org.junit.platform:junit-platform-engine:6.0.1=testRuntimeClasspath
org.junit.platform:junit-platform-launcher:6.0.1=testRuntimeClasspath
org.junit:junit-bom:6.0.1=testCompileClasspath,testRuntimeClasspath
org.junit:junit-bom:6.1.0=spotbugs
org.mockito:mockito-core:5.20.0=testCompileClasspath,testRuntimeClasspath
org.mockito:mockito-core:5.20.0=mockitoAgent,testCompileClasspath,testRuntimeClasspath
org.mockito:mockito-junit-jupiter:5.20.0=testCompileClasspath,testRuntimeClasspath
org.objenesis:objenesis:3.3=testRuntimeClasspath
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
@@ -9,6 +9,8 @@ import java.util.HexFormat;
/** Fail-closed error for an invalid checked-in notification catalog. */
public final class NotificationCatalogException extends RuntimeException {
private static final long serialVersionUID = 1L;
public NotificationCatalogException(String message) {
super(message);
}
@@ -8,6 +8,7 @@ import java.util.Collection;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
/**
@@ -81,7 +82,7 @@ public final class RoutingNotifier implements NotificationPort {
if (!channelRegistry.containsKey(providerId)) {
throw new IllegalStateException(
"app.notification.routes."
+ channel.name().toLowerCase()
+ channel.name().toLowerCase(Locale.ROOT)
+ "."
+ route
+ " references providerId '"
@@ -131,7 +132,7 @@ public final class RoutingNotifier implements NotificationPort {
+ " route='"
+ route
+ "' — set app.notification.routes."
+ channel.name().toLowerCase()
+ channel.name().toLowerCase(Locale.ROOT)
+ "."
+ route
+ "=<providerId>[,<providerId>] and enable that provider"
@@ -95,6 +95,7 @@ public interface NotificationProviderAttemptClient {
/** Explicit provider-proven invalid recipient/content detected before wire I/O. */
final class PreWireDeliveryRejectedException extends RuntimeException {
private static final long serialVersionUID = 1L;
public PreWireDeliveryRejectedException() {
super("provider rejected the prepared delivery before wire I/O");
@@ -3,6 +3,8 @@ package dev.caskeleton.adapter.outbound.notification.template;
/** Redacted fail-closed template loading or rendering error. */
public final class TemplateRenderingException extends RuntimeException {
private static final long serialVersionUID = 1L;
public TemplateRenderingException(String safeMessage) {
super(safeMessage);
}
@@ -14,6 +14,7 @@ import dev.caskeleton.application.notification.Notification;
import dev.caskeleton.shared.error.AdapterDisabledException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.AfterEach;
@@ -287,6 +288,21 @@ class RoutingNotifierTest {
.hasMessageContaining("google-email");
}
@Test
void unknownProviderRouteKeyUsesLocaleIndependentLowercase() {
Locale originalDefault = Locale.getDefault();
Locale.setDefault(Locale.forLanguageTag("tr-TR"));
try {
Map<Channel, Map<String, List<String>>> routes =
Map.of(Channel.EMAIL, Map.of("default", List.of("google-email")));
assertThatThrownBy(() -> new RoutingNotifier(List.of(), routes))
.hasMessageContaining("app.notification.routes.email.default");
} finally {
Locale.setDefault(originalDefault);
}
}
@Test
void zeroProvidersAndRoutesConstructsCleanly() {
// L262: optional module must not block startup when unconfigured.