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.9 KiB
JSON
15 lines
4.9 KiB
JSON
{
|
|
"assetKey": "a14-f014-advanced",
|
|
"kind": "terminal",
|
|
"command": "set -e\nset -o pipefail\nW=adapter/inbound/web/src/main/java/dev/caskeleton/adapter/inbound/web\necho \"# 열거형이 세운 규칙과 상수\"\nsed -n '5,15p' $W/advanced/WebAdvancedFeature.java\necho -n \" 선언된 상수 수 : \"\n{ grep -cE '^ [A-Z][A-Z0-9_]*[,;]$' $W/advanced/WebAdvancedFeature.java; }\ngrep -nE '^ [A-Z][A-Z0-9_]*[,;]$' $W/advanced/WebAdvancedFeature.java | sed 's#^# #'\necho \" 각 상수가 발행하는 속성 이름 :\"\nsed -n '59,63p' $W/advanced/WebAdvancedFeature.java\necho\necho \"# main 에 그 접두사가 나오는 자리 전부. 만드는 쪽과 읽는 쪽이 섞여 있다\"\ngrep -rn 'backend\\.web\\.advanced' --include=*.java --include=*.yml --include=*.yaml --include=*.properties . \\\n | grep '/src/main/' | sed -E 's#^\\./[^:]*/([^:/]+):([0-9]+):# \\1:\\2 #'\necho \" 그중 게이트나 바인딩인 셋 :\"\ngrep -n 'ConfigurationProperties(prefix = \"backend.web.advanced' $W/advanced/mvc/VirtualThreadSettings.java\ngrep -n -A3 'prefix = \"backend.web.advanced.mvc-virtual-threads\"' $W/advanced/mvc/VirtualThreadMvcConfiguration.java\ngrep -n -A3 'prefix = \"backend.web.advanced.ndjson\"' $W/advanced/mvc/MvcStreamingExecutorConfiguration.java\necho \" 이름을 만들기만 하는 둘 :\"\nsed -n '60,61p' $W/advanced/WebAdvancedFeature.java\nsed -n '74,77p' $W/advanced/virtualthread/VirtualThreadProfile.java\necho\necho \"# 두 스위치를 켜면 각각 무엇이 생기는가\"\nsed -n '60,66p' $W/advanced/mvc/VirtualThreadMvcConfiguration.java\necho \" 그런데 그 이름을 출하 조립 경로가 이미 쥐고 있다 :\"\ngrep -n 'EXECUTOR_BEAN_NAME\\|@Primary\\|^@Configuration\\|ThreadPoolTaskExecutor applicationTaskExecutor' \\\n app-bootstrap/src/main/java/dev/caskeleton/bootstrap/async/AsyncExecutorConfig.java\necho -n \" 컴포넌트 스캔 제외 정규식에 bootstrap.async 가 있는가 : \"\n{ sed -n '100,114p' app-bootstrap/src/main/java/dev/caskeleton/bootstrap/CaSkeletonApplication.java | grep -c 'async' || true; }\nsed -n '34,40p' $W/advanced/mvc/MvcStreamingExecutorConfiguration.java\ngrep -n 'StreamFraming.NDJSON\\|StreamFraming.JSON_SEQUENCE' $W/advanced/mvc/MvcStreamingExecutorConfiguration.java\necho -n \" 그 두 미디어 타입을 내는 main 라우트 : \"\ngrep -rn 'produces' --include=*.java . | grep '/src/main/' | grep -c 'x-ndjson\\|json-seq' || true\necho -n \" MvcStreamWriter 를 advanced 밖에서 부르는 main 코드 : \"\ngrep -rln 'MvcStreamWriter' --include=*.java . | grep '/src/main/' | grep -cv '/advanced/' || true\necho\necho \"# 레인이 무엇을 고르고 그 안에서 무엇을 단언하는가\"\nsed -n '205,213p' adapter/inbound/web/build.gradle\necho -n \" 그 태그를 단 시험 클래스 수 : \"\ngrep -rln '@Tag(\"web-advanced\")' --include=*.java . | wc -l\necho \" 그 파일에서 속성을 참으로 두는 자리. 셋은 만들어지는 빈을, 둘은 기동 실패를 단언한다 :\"\ngrep -n 'enabled=true' adapter/inbound/web/src/test/java/dev/caskeleton/adapter/inbound/web/advanced/mvc/MvcAdvancedConfigurationTest.java\necho \" 그중 켠 뒤 빈을 확인하는 자리 :\"\nsed -n '72,82p' adapter/inbound/web/src/test/java/dev/caskeleton/adapter/inbound/web/advanced/mvc/MvcAdvancedConfigurationTest.java\necho\necho \"# 롤백 시험 일곱이 무엇을 단언하는가\"\nT=adapter/inbound/web/src/test/java/dev/caskeleton/adapter/inbound/web/advanced/release/WebAdvancedRollbackIT.java\ngrep -n ' void ' $T\necho \" 속성 상태를 다루는 둘 — 하나는 값을 두지 않고, 하나는 거짓으로 둔다 :\"\nsed -n '49,52p;71,74p' $T\necho \" 플래그 값을 쓰는 유일한 시험 전문 :\"\nsed -n '86,100p' $T\ngrep -n -A2 'public boolean stableBehaviourPreserved' $W/advanced/WebAdvancedFeatureFlags.java\necho\necho \"# 롤백 검증이 대상으로 삼는 값\"\ngrep -n 'public static WebAdvancedFeatureFlags' $W/advanced/WebAdvancedFeatureFlags.java\necho \" 그 타입을 부르는 자리 전부 :\"\ngrep -rn 'WebAdvancedFeatureFlags\\.' --include=*.java . \\\n | grep -v '/WebAdvancedFeatureFlags.java' \\\n | sed -E 's#^\\./[^:]*/src/([a-zA-Z]+)/[^:]*/([^:/]+):([0-9]+):# \\1 · \\2:\\3#' | sort -u\necho\necho \"# 그 값을 돌리는 레인과, 속성 이름을 단언하는 시험\"\ngit -C .. grep -n 'webAdvancedTest' -- '.github/workflows/*' | sed 's#^# #'\ngrep -rn 'propertyName()' --include=*.java . \\\n | sed -E 's#^\\./[^:]*/src/([a-zA-Z]+)/[^:]*/([^:/]+):([0-9]+):# \\1 · \\2:\\3 #'\n",
|
|
"cwd": "/shared/codebase/clean-architecture-backend-template/src",
|
|
"exitCode": 0,
|
|
"executedAt": "2026-09-03T03:58:29+00:00",
|
|
"sourceRevision": "21234e38cdb9a926cbc92bb97a2aee2e4a7d2916",
|
|
"raw": "evidence/raw/a14-f014-advanced.txt",
|
|
"svg": "evidence/rendered/a14-f014-advanced.svg",
|
|
"rawSha256": "3708987e33c1b749d36446e2caac23c4acf3ecf04f99a10e3fa67379ed3d48d7",
|
|
"lines": 172,
|
|
"redaction": "롤백 시험 블록 라벨을 실제 호출에 맞춤"
|
|
}
|