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>
15 lines
4.1 KiB
JSON
15 lines
4.1 KiB
JSON
{
|
|
"assetKey": "a11-f007-dns-overloads",
|
|
"kind": "terminal",
|
|
"command": "set -e\nset -o pipefail\nD=$(mktemp -d); trap 'rm -rf \"$D\"' EXIT\nH=/shared/codebase/clean-architecture-backend-template/src/adapter/outbound/httpclient\nJAR=$H/build/libs/httpclient-0.0.1+21234e38cdb9.jar\njava -version 2>&1 | head -1\njavac -encoding UTF-8 -cp \"$JAR\" -d \"$D\" \\\n \"$H/src/testkit/java/dev/caskeleton/adapter/outbound/httpclient/testkit/ClientProfiles.java\"\ncat > \"$D/DnsPinProbe.java\" <<'JAVA'\nimport dev.caskeleton.adapter.outbound.httpclient.profile.ClientMode;\nimport dev.caskeleton.adapter.outbound.httpclient.profile.ClientProfile;\nimport dev.caskeleton.adapter.outbound.httpclient.profile.HttpProtocol;\nimport dev.caskeleton.adapter.outbound.httpclient.testkit.ClientProfiles;\nimport dev.caskeleton.adapter.outbound.httpclient.transport.BlockingTransportCapabilities;\nimport dev.caskeleton.adapter.outbound.httpclient.transport.ReactiveTransportCapabilities;\nimport dev.caskeleton.adapter.outbound.httpclient.transport.TransportCapabilityValidator;\nimport java.util.Set;\n\npublic final class DnsPinProbe {\n\n private static final TransportCapabilityValidator VALIDATOR = new TransportCapabilityValidator();\n private static final Set<HttpProtocol> BOTH = Set.of(HttpProtocol.HTTP_1_1, HttpProtocol.HTTP_2);\n\n private static BlockingTransportCapabilities blocking(boolean pinning, boolean stable) {\n return new BlockingTransportCapabilities(BOTH, true, true, true, true, pinning, stable);\n }\n\n private static ReactiveTransportCapabilities reactive(boolean pinning, boolean stable) {\n return new ReactiveTransportCapabilities(\n BOTH, true, true, true, true, pinning, stable, true, true);\n }\n\n private static String verdict(Runnable call) {\n try {\n call.run();\n return \"통과\";\n } catch (RuntimeException rejected) {\n String message = rejected.getMessage();\n int at = message.indexOf(\"requires: \");\n return \"거부 — \" + (at < 0 ? message : message.substring(at + \"requires: \".length()));\n }\n }\n\n public static void main(String[] args) {\n ClientProfile dynamic =\n ClientProfiles.builder(\"lookup\").mode(ClientMode.DYNAMIC).protocols(BOTH).build();\n\n System.out.println(\"동적 대상 프로파일 하나에 두 플래그 조합 넷을 넣는다\");\n System.out.println();\n System.out.println(\"-\".repeat(96));\n boolean[][] combinations = {{true, true}, {false, false}, {true, false}, {false, true}};\n for (boolean[] flags : combinations) {\n String label =\n String.format(\"pinning=%-5s stable=%-5s\", flags[0], flags[1]);\n System.out.println(label);\n System.out.println(\" 블로킹 : \" + verdict(() -> VALIDATOR.validate(dynamic, blocking(flags[0], flags[1]))));\n System.out.println(\" 반응형 : \" + verdict(() -> VALIDATOR.validate(dynamic, reactive(flags[0], flags[1]))));\n }\n System.out.println();\n System.out.println(\"출하된 반응형 전송 둘의 두 플래그\");\n ReactiveTransportCapabilities netty = ReactiveTransportCapabilities.reactorNetty();\n ReactiveTransportCapabilities jetty = ReactiveTransportCapabilities.jettyHttp3Experimental();\n System.out.printf(\" reactorNetty pinning=%-5s stable=%s%n\",\n netty.validatedDnsPinning(), netty.dynamicTargetStable());\n System.out.printf(\" jettyHttp3Experimental pinning=%-5s stable=%s%n\",\n jetty.validatedDnsPinning(), jetty.dynamicTargetStable());\n }\n}\nJAVA\njavac -encoding UTF-8 -cp \"$JAR:$D\" -d \"$D\" \"$D/DnsPinProbe.java\"\njava -Dstdout.encoding=UTF-8 -cp \"$JAR:$D\" DnsPinProbe\n",
|
|
"cwd": "/shared/codebase/clean-architecture-backend-template",
|
|
"exitCode": 0,
|
|
"executedAt": "2026-09-02T14:06:51+00:00",
|
|
"sourceRevision": "21234e38cdb9a926cbc92bb97a2aee2e4a7d2916",
|
|
"raw": "evidence/raw/a11-f007-dns-overloads.txt",
|
|
"svg": "evidence/rendered/a11-f007-dns-overloads.svg",
|
|
"rawSha256": "803c82c0e50fb5bfb9a29aaf093934bd27b352c34e3ff3f7ee97723a4c5e2bfa",
|
|
"lines": 20,
|
|
"redaction": "none — 밀폐 탐침 실행 출력, 자격증명 없음"
|
|
}
|