Files
document-haness/docs/clean-architecture-backend-template/final/evidence/meta/a11-f002-pool-route-exceeds-total-shape.json
T
DongHyeonkaandClaude Opus 5 b2963105a8 docs(keycloak-session-store): import the session-storage lab as a new project
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>
2026-09-04 22:51:59 +09:00

15 lines
5.1 KiB
JSON

{
"assetKey": "a11-f002-pool-route-exceeds-total-shape",
"kind": "terminal",
"command": "set -e\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/PoolViolationProbe.java\" <<'JAVA'\nimport dev.caskeleton.adapter.outbound.httpclient.profile.ClientProfile;\nimport dev.caskeleton.adapter.outbound.httpclient.profile.ClientProfileValidator;\nimport dev.caskeleton.adapter.outbound.httpclient.profile.ClientProfileViolation;\nimport dev.caskeleton.adapter.outbound.httpclient.profile.HttpProtocol;\nimport dev.caskeleton.adapter.outbound.httpclient.profile.PoolSettings;\nimport dev.caskeleton.adapter.outbound.httpclient.profile.RuntimeEnvironment;\nimport dev.caskeleton.adapter.outbound.httpclient.profile.TransportType;\nimport dev.caskeleton.adapter.outbound.httpclient.testkit.ClientProfiles;\nimport java.time.Duration;\nimport java.util.List;\n\npublic final class PoolViolationProbe {\n\n private static PoolSettings routePool(int total, int perRoute) {\n return new PoolSettings(\n total, perRoute, 16,\n Duration.ofSeconds(2), Duration.ofSeconds(30), Duration.ofMinutes(5),\n Duration.ofSeconds(5), Duration.ofSeconds(15), Duration.ofSeconds(5),\n true, false);\n }\n\n private static PoolSettings pool(int total, int perRoute) {\n return new PoolSettings(\n total,\n perRoute,\n 16,\n Duration.ofSeconds(2),\n Duration.ofSeconds(30),\n Duration.ofMinutes(5),\n Duration.ofSeconds(5),\n Duration.ofSeconds(15),\n Duration.ofSeconds(5),\n false,\n false);\n }\n\n private static void report(String label, ClientProfile profile) {\n List<ClientProfileViolation> found =\n new ClientProfileValidator().validate(profile, RuntimeEnvironment.PRODUCTION);\n System.out.println(\" \" + label);\n if (found.isEmpty()) {\n System.out.println(\" 위반 없음\");\n return;\n }\n for (ClientProfileViolation violation : found) {\n System.out.println(\" \" + violation);\n }\n }\n\n public static void main(String[] args) {\n System.out.println(\"[검증기가 내는 형태] 프로덕션 판정, 정렬된 위반 목록\");\n report(\"전체 20 / 경로당 5\", ClientProfiles.builder(\"payment\").pool(pool(20, 5)).build());\n report(\"전체 20 / 경로당 20 (같음)\", ClientProfiles.builder(\"payment\").pool(pool(20, 20)).build());\n report(\n \"전송만 SIMPLE 로 바꾼 프로파일\",\n ClientProfiles.builder(\"payment\").transport(TransportType.SIMPLE).build());\n report(\n \"전송 JDK + 경로 풀 요구 + HTTP/3 미승인\",\n ClientProfiles.builder(\"payment\")\n .transport(TransportType.JDK)\n .pool(routePool(20, 5))\n .protocols(java.util.Set.of(HttpProtocol.HTTP_1_1, HttpProtocol.HTTP_3))\n .build());\n System.out.println();\n\n System.out.println(\"[POOL_ROUTE_EXCEEDS_TOTAL 조건을 만들려면]\");\n try {\n PoolSettings unusable = pool(10, 20);\n System.out.println(\" 전체 10 / 경로당 20 -> 만들어짐 \" + unusable.maxConnectionsPerRoute());\n } catch (IllegalArgumentException rejected) {\n System.out.println(\n \" 전체 10 / 경로당 20 -> \" + rejected.getClass().getSimpleName() + \": \" + rejected.getMessage());\n }\n System.out.println(\" 프로파일은 이미 만들어진 PoolSettings 를 들고 있으므로,\");\n System.out.println(\" 검증기에 넘길 프로파일 자체를 만들 수 없다.\");\n System.out.println();\n\n System.out.println(\"[DUPLICATE_CLIENT_NAME 조건을 만들려면]\");\n ClientProfile one = ClientProfiles.builder(\"payment\").build();\n java.util.Map<dev.caskeleton.adapter.outbound.httpclient.api.ClientProfileName, ClientProfile>\n profiles = new java.util.HashMap<>();\n profiles.put(one.name(), one);\n profiles.put(one.name(), ClientProfiles.builder(\"payment\").build());\n System.out.println(\" 같은 이름을 두 번 넣은 맵의 크기 : \" + profiles.size());\n System.out.println(\" 검증기가 이름 중복을 세는 자리는 이 맵을 순회한다.\");\n }\n}\nJAVA\njavac -encoding UTF-8 -cp \"$JAR:$D\" -d \"$D\" \"$D/PoolViolationProbe.java\"\njava -Dstdout.encoding=UTF-8 -cp \"$JAR:$D\" PoolViolationProbe\n",
"cwd": "/shared/codebase/clean-architecture-backend-template",
"exitCode": 0,
"executedAt": "2026-09-02T13:26:24+00:00",
"sourceRevision": "21234e38cdb9a926cbc92bb97a2aee2e4a7d2916",
"raw": "evidence/raw/a11-f002-pool-route-exceeds-total-shape.txt",
"svg": "evidence/rendered/a11-f002-pool-route-exceeds-total-shape.svg",
"rawSha256": "82912731dfe4a778b1cea2559a5c6fd712a2ac943815a024d00c7716f0034296",
"lines": 20,
"redaction": "none — 밀폐 탐침 실행 출력, 자격증명 없음"
}