The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.
Follows the import procedure in README.md.
source/ the originating repository verbatim — 78 documents, 28 SVGs,
8 manifests, plus .source-revision recording the commit
final/ the SSOT
document.md 729 lines written from the 29 experiment documents, not
concatenated: what was predicted, what was measured, and
where the measurement itself was wrong
evidence/raw 125 outputs, flattened to <experiment>__<file> because
the originals collided (01-baseline.txt appeared three
times) and the audit only globs the top level
evidence/meta one per raw file; command and exitCode are null and the
README says why rather than inventing them
evidence/browser 22 captures
assets/ three diagrams through techviz
.techviz/ their VizSpecs
A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.
Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.
verify-pipeline.py passes. audit-records.py reports no issues.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
122 lines
11 KiB
Plaintext
122 lines
11 KiB
Plaintext
Sub-scope 03 (outbound-messaging) contract/** + destination/** + qualification test — manifest and probes
|
|
revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5
|
|
generatedAt=2026-08-30T06:29:35+00:00
|
|
|
|
=== OWNED FILES ===
|
|
a4b9608deef1faa6107fea013e269595e0e999e0 main/java/dev/caskeleton/adapter/outbound/messaging/contract/CompiledIntegrationEventContract.java 263
|
|
66d6ab3cea648b0a8e5a3eb12596bd5a9256e161 main/java/dev/caskeleton/adapter/outbound/messaging/contract/ContractCatalogCompiler.java 274
|
|
57cf07bc4dfbe53912395e57536dda74735359d5 main/java/dev/caskeleton/adapter/outbound/messaging/contract/ContractCatalogDigest.java 91
|
|
43cdeb88515f9174b1326b8cfb682d9255f7885f main/java/dev/caskeleton/adapter/outbound/messaging/destination/CompiledPublicationBinding.java 105
|
|
9759d0fb0d0942faf22420620b04ebc6efae0bac main/java/dev/caskeleton/adapter/outbound/messaging/destination/DestinationBindingCompiler.java 248
|
|
8fb7ffb59ef243ed8ed423bb7981d8cb0b48865a main/java/dev/caskeleton/adapter/outbound/messaging/destination/DestinationBindingSettings.java 238
|
|
a6c74dbdbb5bb02572303c4b8a3450740b301f49 main/java/dev/caskeleton/adapter/outbound/messaging/destination/PartitionKeyV1.java 132
|
|
9d9274390e5314887d03334e370f1bda95989421 test/java/dev/caskeleton/adapter/outbound/messaging/contract/ContractCatalogCompilerTest.java 566
|
|
1f541d4d217a8af44deb2bd67d7901fe40766305 test/java/dev/caskeleton/adapter/outbound/messaging/contract/ContractCatalogDigestTest.java 112
|
|
500efc002b2ccb3fe73506a8bf1a0a513f1eb5a0 test/java/dev/caskeleton/adapter/outbound/messaging/destination/DestinationBindingCompilerTest.java 648
|
|
b9c9d3d7df0962f27718e717b6a9ad79d644160b test/java/dev/caskeleton/adapter/outbound/messaging/destination/PartitionKeyV1Test.java 104
|
|
1a3fc898cab1fa38bd66707af0c39d9a53651d17 test/java/dev/caskeleton/adapter/outbound/messaging/qualification/MessagingEvidenceManifestSchemaValidator.java 68
|
|
2c0967e3c4d2e4ea81b035b9c649bfcb02e9b1f4 test/java/dev/caskeleton/adapter/outbound/messaging/qualification/MessagingEvidenceManifestSchemaValidatorTest.java 81
|
|
|
|
main: 7 test: 6
|
|
=== 8.1 도메인 분리 상수 전수 ===
|
|
$ git grep -rn 'ca-skeleton.messaging' -- adapter/outbound/messaging/src/main | sed 's|.*/messaging/||'
|
|
contract/ContractCatalogDigest.java:16: "ca-skeleton.messaging.contract-catalog-digest.v1".getBytes(StandardCharsets.UTF_8);
|
|
destination/DestinationBindingCompiler.java:95: MessageDigest digest = digest("ca-skeleton.messaging.destination-settings-digest.v1");
|
|
destination/DestinationBindingCompiler.java:121: MessageDigest digest = digest("ca-skeleton.messaging.schema-set-digest.v1");
|
|
destination/PartitionKeyV1.java:22: "ca-skeleton.messaging.partition-key.v1".getBytes(StandardCharsets.UTF_8);
|
|
envelope/EnvelopeHashV1.java:13: "ca-skeleton.messaging.envelope.v1".getBytes(StandardCharsets.UTF_8);
|
|
envelope/JsonSchemaIntegrationEventEncoder.java:25: "ca-skeleton.messaging.schema-set.v1".getBytes(StandardCharsets.UTF_8);
|
|
envelope/LocalJsonSchemaRegistry.java:64: "ca-skeleton.messaging.draft-2020-12-authority.v1".getBytes(StandardCharsets.UTF_8);
|
|
exit=0
|
|
|
|
=== 8.2 길이 프레이밍 다이제스트 일관성 ===
|
|
$ git grep -n 'unsignedLength\|rawField\|digest.update' -- adapter/outbound/messaging/src/main/java/dev/caskeleton/adapter/outbound/messaging/contract/ContractCatalogDigest.java adapter/outbound/messaging/src/main/java/dev/caskeleton/adapter/outbound/messaging/destination/PartitionKeyV1.java | head -20
|
|
adapter/outbound/messaging/src/main/java/dev/caskeleton/adapter/outbound/messaging/contract/ContractCatalogDigest.java:25: digest.update(DOMAIN);
|
|
adapter/outbound/messaging/src/main/java/dev/caskeleton/adapter/outbound/messaging/contract/ContractCatalogDigest.java:26: digest.update((byte) 0);
|
|
adapter/outbound/messaging/src/main/java/dev/caskeleton/adapter/outbound/messaging/contract/ContractCatalogDigest.java:48: rawField(digest, "schemaHash", contract.payloadSchemaHash().bytes());
|
|
adapter/outbound/messaging/src/main/java/dev/caskeleton/adapter/outbound/messaging/contract/ContractCatalogDigest.java:69: rawField(digest, tag, value.getBytes(StandardCharsets.UTF_8));
|
|
adapter/outbound/messaging/src/main/java/dev/caskeleton/adapter/outbound/messaging/contract/ContractCatalogDigest.java:72: private static void rawField(MessageDigest digest, String tag, byte[] value) {
|
|
adapter/outbound/messaging/src/main/java/dev/caskeleton/adapter/outbound/messaging/contract/ContractCatalogDigest.java:74: digest.update(unsignedLength(tagBytes.length));
|
|
adapter/outbound/messaging/src/main/java/dev/caskeleton/adapter/outbound/messaging/contract/ContractCatalogDigest.java:75: digest.update(tagBytes);
|
|
adapter/outbound/messaging/src/main/java/dev/caskeleton/adapter/outbound/messaging/contract/ContractCatalogDigest.java:76: digest.update(unsignedLength(value.length));
|
|
adapter/outbound/messaging/src/main/java/dev/caskeleton/adapter/outbound/messaging/contract/ContractCatalogDigest.java:77: digest.update(value);
|
|
adapter/outbound/messaging/src/main/java/dev/caskeleton/adapter/outbound/messaging/contract/ContractCatalogDigest.java:80: private static byte[] unsignedLength(int length) {
|
|
adapter/outbound/messaging/src/main/java/dev/caskeleton/adapter/outbound/messaging/destination/PartitionKeyV1.java:55: digest.update(DOMAIN);
|
|
adapter/outbound/messaging/src/main/java/dev/caskeleton/adapter/outbound/messaging/destination/PartitionKeyV1.java:56: digest.update((byte) 0);
|
|
adapter/outbound/messaging/src/main/java/dev/caskeleton/adapter/outbound/messaging/destination/PartitionKeyV1.java:66: digest.update(ByteBuffer.allocate(Integer.BYTES).putInt(bytes.length).array());
|
|
adapter/outbound/messaging/src/main/java/dev/caskeleton/adapter/outbound/messaging/destination/PartitionKeyV1.java:67: digest.update(bytes);
|
|
exit=0
|
|
|
|
=== 8.3 교차 언어 벡터 test ===
|
|
$ git grep -n 'vector\|Vector\|golden\|Golden' -- adapter/outbound/messaging/src/test/java/dev/caskeleton/adapter/outbound/messaging | head -20
|
|
adapter/outbound/messaging/src/test/java/dev/caskeleton/adapter/outbound/messaging/destination/PartitionKeyV1Test.java:17: void freezesTenantScopedGoldenVectorAsLowercaseHexAndExactAsciiBytes() {
|
|
adapter/outbound/messaging/src/test/java/dev/caskeleton/adapter/outbound/messaging/destination/PartitionKeyV1Test.java:54: void nonAsciiAggregateIdGoldenVectorUsesUtf8ByteLengthNotCharacterCount() {
|
|
adapter/outbound/messaging/src/test/java/dev/caskeleton/adapter/outbound/messaging/envelope/JsonSchemaIntegrationEventEncoderTest.java:161: void exactEnvelopeHashHasDomainSeparatedGoldenVectorAndDefensiveShaValue() {
|
|
adapter/outbound/messaging/src/test/java/dev/caskeleton/adapter/outbound/messaging/envelope/LocalJsonSchemaRegistryTest.java:27: void precompilesOnlyCheckedDraft202012ResourcesAndValidatesGoldenVectors() {
|
|
exit=0
|
|
|
|
=== 8.4 qualification test 클래스가 build.gradle 필수 목록과 일치하는가 ===
|
|
$ sed -n '69,104p' adapter/outbound/messaging/build.gradle | grep -oE "'dev\.caskeleton[^']*'" | tr -d \"'\"
|
|
main: eval: line 8: unexpected EOF while looking for matching `''
|
|
exit=2
|
|
|
|
$ git ls-files 'adapter/outbound/messaging/src/test/java/dev/caskeleton/adapter/outbound/messaging' | grep '\.java$' | sed 's|.*/java/||;s|/|.|g;s|\.java$||'
|
|
dev.caskeleton.adapter.outbound.messaging.MessagingConfigTest
|
|
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.core.OutboundMessagePublisherTest
|
|
dev.caskeleton.adapter.outbound.messaging.destination.DestinationBindingCompilerTest
|
|
dev.caskeleton.adapter.outbound.messaging.destination.PartitionKeyV1Test
|
|
dev.caskeleton.adapter.outbound.messaging.envelope.EnvelopeAdversarialCorpusTest
|
|
dev.caskeleton.adapter.outbound.messaging.envelope.JsonSchemaIntegrationEventEncoderTest
|
|
dev.caskeleton.adapter.outbound.messaging.envelope.LocalJsonSchemaRegistryTest
|
|
dev.caskeleton.adapter.outbound.messaging.kafka.BrokerAddressTest
|
|
dev.caskeleton.adapter.outbound.messaging.kafka.KafkaAdapterSettingsTest
|
|
dev.caskeleton.adapter.outbound.messaging.outbox.OutboxMessagePublishAdapterTest
|
|
dev.caskeleton.adapter.outbound.messaging.outbox.Slf4jOutboxRelayFailureReportAdapterTest
|
|
dev.caskeleton.adapter.outbound.messaging.qualification.MessagingEvidenceManifestSchemaValidator
|
|
dev.caskeleton.adapter.outbound.messaging.qualification.MessagingEvidenceManifestSchemaValidatorTest
|
|
exit=0
|
|
|
|
=== 8.5 test 이름 ===
|
|
$ grep -h 'void [a-z]' adapter/outbound/messaging/src/test/java/dev/caskeleton/adapter/outbound/messaging/contract/*.java adapter/outbound/messaging/src/test/java/dev/caskeleton/adapter/outbound/messaging/destination/*.java adapter/outbound/messaging/src/test/java/dev/caskeleton/adapter/outbound/messaging/qualification/*.java | sed 's/^ *//'
|
|
void compilesAnImmutableClosedCatalogFromExactRecordTypeTokens() {
|
|
void rejectsNullInputsDuplicateStableSchemaAndExactPayloadIdentities() {
|
|
void rejectsNonPositiveVersionAndInvalidExactPayloadKinds() {
|
|
void rejectsNullBlankDuplicateAndReflectionMismatchedComponentOrders() {
|
|
void rejectsMissingDescriptorsAndLogicalDestinationDriftAcrossPayloadVersions() {
|
|
void compiledContractCannotBeConstructedWithAnInvalidExactTypeOrComponentOrder() {
|
|
void compiledContractUsesOnlyAStaticPublicCompositionBridgeWithoutReflectionLeak()
|
|
void snapshotsEveryContributionAccessorExactlyOnceIncludingAStatefulSchemaHash() {
|
|
void statefulDescriptorCannotBypassCrossVersionLogicalDestinationDrift() {
|
|
void recursivelyFreezesOnlyTheClosedDeclaredGenericPayloadGraph() {
|
|
void rejectsOpenRawWildcardMapJsonTreeInterfaceAndGenericRecordGraphs() {
|
|
private static void assertInvalidOrder(List<String> order) {
|
|
private static void assertUnsupportedGraph(
|
|
void digestIsDeterministicForEmptyAndInputOrderIndependentForNonEmptyCatalogs() {
|
|
void digestChangesForSchemaHashDescriptorAndCanonicalComponentOrderSemantics() {
|
|
void compilesExactContractBindingWithCodeDeploymentByteIntersectionAndStableDigests() {
|
|
void deploymentMaximumBelowCodeMaximumWinsAndMustRemainPositive() {
|
|
void settingsRejectDuplicateLogicalDestinationsInvalidPortsAndSecretShapedLegacyAliases() {
|
|
void settingsRejectNullDestinationAndDuplicatePhysicalTopicAcrossLogicalDestinations() {
|
|
void rejectsMissingDuplicateExtraAndContractDestinationMismatchedBindings() {
|
|
void rejectsUnknownCardsRoleMismatchLegacyConflictAndRelaxedRequirements() {
|
|
void disabledEmptyCatalogIsZeroResourceWhileActiveRequiresExactCatalogAndBindings() {
|
|
void compiledArtifactsExposeOnlyNarrowStaticImmutableCompositionBridges()
|
|
private static void assertPackagePrivateInstanceMethod(
|
|
private static void assertPublicStaticMethod(
|
|
private static void assertRejected(
|
|
void freezesTenantScopedGoldenVectorAsLowercaseHexAndExactAsciiBytes() {
|
|
void tenantDisabledCallerMustSupplyTheCanonicalNonNullSystemScope() {
|
|
void nonAsciiAggregateIdGoldenVectorUsesUtf8ByteLengthNotCharacterCount() {
|
|
void malformedUtf8SurrogatesAreRejectedInsteadOfCollidingWithLiteralQuestionMark() {
|
|
void canonicalComponentsApplyTask3BoundsBeforeEncoding() {
|
|
public static void main(String[] arguments) {
|
|
static void validate(byte[] exactSchemaBytes, byte[] exactManifestBytes) {
|
|
void validatesAConformingManifestAgainstTheExactCommonSchema() throws IOException {
|
|
void rejectsManifestDriftThatTheCommonSchemaForbids() throws IOException {
|
|
void rejectsCommonSchemaDriftThatFailsDraft202012MetaValidation() throws IOException {
|
|
exit=0
|
|
|