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
@@ -1,3 +1,5 @@
apply from: "${rootProject.projectDir}/gradle/strict-qualification-test.gradle"
dependencies {
implementation project(':application-core')
implementation project(':shared-contract')
@@ -64,3 +66,40 @@ tasks.register('verifyJsonSchemaRuntimeGraph') {
tasks.named('check') {
dependsOn tasks.named('verifyJsonSchemaRuntimeGraph')
}
def messagingCompiledContractsQualification = registerStrictQualificationTest(
name: 'messagingCompiledContractsQualificationTest',
sourceSet: sourceSets.test,
requiredClasses: [
'dev.caskeleton.adapter.outbound.messaging.config.MessagingCapabilityCardRegistryTest',
'dev.caskeleton.adapter.outbound.messaging.contract.ContractCatalogCompilerTest',
'dev.caskeleton.adapter.outbound.messaging.contract.ContractCatalogDigestTest',
'dev.caskeleton.adapter.outbound.messaging.destination.DestinationBindingCompilerTest',
'dev.caskeleton.adapter.outbound.messaging.destination.PartitionKeyV1Test'
],
junitXmlOutput: rootProject.layout.buildDirectory.dir(
'test-results/messaging-evidence/compiled'),
binaryResultsOutput: rootProject.layout.buildDirectory.dir(
'test-results/messaging-evidence-binary/compiled'),
description: 'Runs exact Messaging compiled-contract qualification tests.')
messagingCompiledContractsQualification.configure {
dependsOn ':prepareMessagingContractEvidence'
}
def messagingJsonSchemaV1Qualification = registerStrictQualificationTest(
name: 'messagingJsonSchemaV1QualificationTest',
sourceSet: sourceSets.test,
requiredClasses: [
'dev.caskeleton.adapter.outbound.messaging.envelope.LocalJsonSchemaRegistryTest',
'dev.caskeleton.adapter.outbound.messaging.envelope.JsonSchemaIntegrationEventEncoderTest',
'dev.caskeleton.adapter.outbound.messaging.envelope.EnvelopeAdversarialCorpusTest',
'dev.caskeleton.adapter.outbound.messaging.qualification.MessagingEvidenceManifestSchemaValidatorTest'
],
junitXmlOutput: rootProject.layout.buildDirectory.dir(
'test-results/messaging-evidence/json-schema'),
binaryResultsOutput: rootProject.layout.buildDirectory.dir(
'test-results/messaging-evidence-binary/json-schema'),
description: 'Runs exact Messaging JSON Schema v1 qualification tests.')
messagingJsonSchemaV1Qualification.configure {
dependsOn ':prepareMessagingContractEvidence'
}
@@ -93,7 +93,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
@@ -17,7 +17,9 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import tools.jackson.core.JsonEncoding;
import tools.jackson.core.JsonGenerator;
import tools.jackson.core.ObjectWriteContext;
import tools.jackson.core.StreamWriteConstraints;
import tools.jackson.core.json.JsonFactory;
@@ -347,7 +349,8 @@ final class DeterministicEnvelopeWriter {
private byte[] generate(int maximumBytes, GeneratorAction action) {
ByteArrayOutputStream output = new BoundedByteArrayOutputStream(maximumBytes);
try (JsonGenerator generator = jsonFactory.createGenerator(output)) {
try (JsonGenerator generator =
jsonFactory.createGenerator(ObjectWriteContext.empty(), output, JsonEncoding.UTF8)) {
action.write(generator);
}
byte[] result = output.toByteArray();
@@ -249,14 +249,14 @@ public final class LocalJsonSchemaRegistry {
throw new IllegalArgumentException("schema root must be an object");
}
JsonNode dialect = root.get("$schema");
if (dialect == null || !dialect.isTextual() || !DRAFT_2020_12.equals(dialect.textValue())) {
if (dialect == null || !dialect.isString() || !DRAFT_2020_12.equals(dialect.stringValue())) {
throw new IllegalArgumentException("schema dialect must explicitly be Draft 2020-12");
}
JsonNode identifier = root.get("$id");
if (identifier == null || !identifier.isTextual()) {
if (identifier == null || !identifier.isString()) {
throw new IllegalArgumentException("schema requires an explicit absolute immutable $id");
}
String schemaId = requireAbsoluteImmutableId(identifier.textValue());
String schemaId = requireAbsoluteImmutableId(identifier.stringValue());
rejectUnsupportedSchemaLocations(root, true);
validateVocabulary(root.get("$vocabulary"));
return new ParsedSource(source.resourcePath(), schemaId, source.exactBytes(), actual, root);
@@ -353,10 +353,10 @@ public final class LocalJsonSchemaRegistry {
if (node.isObject()) {
JsonNode ref = node.get("$ref");
if (ref != null) {
if (!ref.isTextual()) {
if (!ref.isString()) {
throw new IllegalArgumentException("$ref must be a string");
}
result.add(parseReference(ownerId, ref.textValue()));
result.add(parseReference(ownerId, ref.stringValue()));
}
node.properties().forEach(entry -> collectReferences(ownerId, entry.getValue(), result));
} else if (node.isArray()) {
@@ -494,7 +494,7 @@ public final class LocalJsonSchemaRegistry {
}
String expectedId = PINNED_META_IDS.get(path);
JsonNode id = node.get("$id");
if (id == null || !id.isTextual() || !expectedId.equals(id.textValue())) {
if (id == null || !id.isString() || !expectedId.equals(id.stringValue())) {
throw new IllegalArgumentException(
"pinned Draft 2020-12 authority has an unexpected $id for " + path);
}
@@ -558,9 +558,9 @@ public final class LocalJsonSchemaRegistry {
throw new IllegalArgumentException("JSON array exceeds items admission limit");
}
node.forEach(child -> enforceInstanceLimits(child, depth + 1));
} else if (node.isTextual()) {
enforceString(node.textValue());
if (node.textValue().codePointCount(0, node.textValue().length())
} else if (node.isString()) {
enforceString(node.stringValue());
if (node.stringValue().codePointCount(0, node.stringValue().length())
> limits.maximumRegexInputCharacters()) {
throw new IllegalArgumentException("JSON string exceeds regex input admission limit");
}
@@ -10,11 +10,13 @@ import dev.caskeleton.application.messaging.contract.IntegrationPayload;
import dev.caskeleton.application.messaging.contract.LogicalDestinationId;
import dev.caskeleton.application.messaging.contract.SchemaResourceId;
import dev.caskeleton.application.messaging.contract.Sha256;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HexFormat;
import java.util.List;
import java.util.Map;
@@ -248,9 +250,9 @@ class ContractCatalogCompilerTest {
assertThat(Modifier.isStatic(modifiers)).isTrue();
});
assertThat(
java.util.Arrays.stream(CompiledIntegrationEventContract.class.getMethods())
.map(java.lang.reflect.Method::getReturnType))
.doesNotContain(java.lang.reflect.Method.class);
Arrays.stream(CompiledIntegrationEventContract.class.getMethods())
.<Class<?>>map(Method::getReturnType))
.doesNotContain(Method.class);
}
@Test
@@ -54,7 +54,7 @@ class JsonSchemaIntegrationEventEncoderTest {
{"envelopeVersion":1,"eventId":"event-1","contractId":"test.event","payloadVersion":1,"logicalDestination":"test-events","aggregate":{"type":"worklog","id":"W-1","sequence":3,"eventIndex":0},"occurredAt":"2026-07-29T01:02:03.123Z","correlationId":"corr-1","contentType":"application/json","payload":{"name":"정확한-UTF8","count":7,"enabled":true,"amount":12.5,"status":"READY","note":null,"tags":["alpha","β"],"nested":{"code":"N1"}}}\
""";
assertThat(first.envelopeBytes()).isEqualTo(expected.getBytes(StandardCharsets.UTF_8));
assertThat(first.envelopeBytes()).containsExactly(expected.getBytes(StandardCharsets.UTF_8));
assertThat(second).isEqualTo(first);
assertThat(first.partitionKeyText()).matches("[0-9a-f]{64}");
assertThat(first.schemaSetHash().toString()).matches("[0-9a-f]{64}");
@@ -152,6 +152,21 @@ class LocalJsonSchemaRegistryTest {
"vocabulary");
}
@Test
void rejectsNonStringRootDialectAndIdentifierNodes() {
assertRejectedSchema(
"""
{"$schema":false,"$id":"urn:test:non-string-dialect","type":"object"}
""",
"dialect");
assertRejectedSchema(
"""
{"$schema":"https://json-schema.org/draft/2020-12/schema",
"$id":false,"type":"object"}
""",
"$id");
}
@Test
void rejectsInvalidSchemaRemoteReferenceAndReferenceGraphBeyondConfiguredDepth() {
assertRejectedSchema(