Files
document-haness/docs/clean-architecture-backend-template/final/evidence/meta/a19-f014-kafka-msg.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.9 KiB
JSON

{
"assetKey": "a19-f014-kafka-msg",
"kind": "terminal",
"command": "set -e\nset -o pipefail\nB=src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap\nA=src/messaging/messaging-spring-boot-starter/src/main/java/dev/caskeleton/messaging/autoconfigure\nstrip() { sed -E 's#^src/[^:]*/src/(main|test)/java/dev/caskeleton/([^:]*)/([^:/]+):([0-9]+):# \\1 · \\2/\\3:\\4 #'; }\ncut_range() { awk -v f=\"$2\" -v a=\"$3\" -v b=\"$4\" 'NR>=a && NR<=b {printf \" %s:%d %s\\n\", f, NR, $0}' \"$1\"; }\n\necho \"# 가족 문서가 이 항목을 어떻게 들고 있는가\"\ngrep -n 'MSG-015' src/messaging/CLAUDE.md | cut -c1-150 | sed 's#^# messaging/CLAUDE.md:#'\n\necho\necho \"# 두 스택의 설정 클래스와 생산자 빈\"\ncut_range $B/messaging/KafkaSenderConfig.java bootstrap/messaging/KafkaSenderConfig.java 37 39\ncut_range $B/messaging/KafkaSenderConfig.java bootstrap/messaging/KafkaSenderConfig.java 61 63\nawk 'NR>=126 && NR<=131 {printf \" autoconfigure/KafkaMessagingAutoConfiguration.java:%d %s\\n\", NR, $0}' $A/KafkaMessagingAutoConfiguration.java\n\necho\necho \"# 플랫폼 쪽이 켜지는 사슬\"\ngit grep -n 'prefix = MessagingSettings.PREFIX, name = \"enabled\"' -- 'src/**/*.java' | strip\ngit grep -n '\"kafka\", KafkaMessagingAutoConfiguration.class' -- 'src/**/*.java' | strip\n\necho\necho \"# broker 만 준 시험이 통과하는 이유 — 게이트 뒤 설정을 손으로 등록한다\"\ngit grep -n 'withUserConfiguration(KafkaAdapterConfig' -- 'src/**/*.java' | strip\nO=src/app-bootstrap/src/test/java/dev/caskeleton/adapter/outbound/OptionalAdapterBeanGatingTest.java\nawk 'NR>=59 && NR<=70 {printf \" test · OptionalAdapterBeanGatingTest.java:%d %s\\n\", NR, $0}' $O\necho \" 두 시험이 컴포지션 루트를 쓰는가 :\"\nfor f in src/adapter/outbound/messaging/src/test/java/dev/caskeleton/adapter/outbound/messaging/MessagingConfigTest.java $O; do\n n=$(grep -c 'CaSkeletonApplication' \"$f\" || true)\n printf \" %-40s CaSkeletonApplication 언급 %s 건\\n\" \"$(basename $f)\" \"${n:-0}\"\ndone\necho \" KafkaSenderConfig 가 그 슬라이스에 등록되는가 :\"\nfor f in src/adapter/outbound/messaging/src/test/java/dev/caskeleton/adapter/outbound/messaging/MessagingConfigTest.java $O; do\n n=$(grep -c 'KafkaSenderConfig' \"$f\" || true)\n printf \" %-40s KafkaSenderConfig 언급 %s 건\\n\" \"$(basename $f)\" \"${n:-0}\"\ndone\n\necho\necho \"# 이 조합을 거르는 검증기가 있는가\"\nV=$(find src -name CapabilityDependencyValidator.java -path '*/main/*')\nawk 'NR>=64 && NR<=80 {printf \" CapabilityDependencyValidator.java:%d %s\\n\", NR, $0}' $V\n\necho\necho \"# 운영 문서가 이 키를 무엇이라고 설명하는가\"\nawk 'NR>=26 && NR<=32 {printf \" docs/runbooks/outbox-publish-failed.md:%d %s\\n\", NR, $0}' docs/runbooks/outbox-publish-failed.md\n\necho\necho \"# 출하 설정이 두 키를 어떻게 주는가\"\ngrep -n 'APP_MESSAGING_ENABLED\\|APP_MESSAGING_BROKER' src/config/runtime/compose-profile-contracts.json | head -8 | sed 's#^# compose-profile-contracts.json:#'\nfor f in src/.env src/.env.example src/.env.local.example; do\n [ -f \"$f\" ] && grep -n 'APP_MESSAGING_BROKER\\|APP_MESSAGING_ENABLED' \"$f\" | sed \"s#^# $(basename $f):#\"\ndone\n\necho\necho \"# KafkaSenderConfig 가 조건에서 물러나는가\"\nawk 'NR>=60 && NR<=65 {printf \" KafkaSenderConfig.java:%d %s\\n\", NR, $0}' $B/messaging/KafkaSenderConfig.java\n\necho\necho \"# 이음매 설정 클래스 자신은 스캔 대상인가\"\nhead -1 $B/messaging/KafkaSenderConfig.java | sed 's#^# KafkaSenderConfig.java:1 #'\nn=$(grep -c 'bootstrap\\\\.messaging' $B/CaSkeletonApplication.java || true)\necho \" AUTO_CONFIGURED_PACKAGES 가 bootstrap.messaging 을 제외하는가 : ${n:-0} 건\"\n\necho\necho \"# 이음매 쪽 생산자가 요구하는 설정 빈은 어디서 오는가\"\ngit grep -n 'EnableConfigurationProperties(KafkaAdapterSettings.class)' -- 'src/**/*.java' | strip\ngit grep -n 'Import({MessagingConfig.class, KafkaAdapterConfig.class})\\|prefix = \"app.messaging\", name = \"enabled\"' -- 'src/**/*.java' | strip\n\necho\necho \"# 그 설정 클래스가 컴포넌트 스캔으로 들어올 수 있는가\"\nawk 'NR>=41 && NR<=57 {printf \" CaSkeletonApplication.java:%d %s\\n\", NR, $0}' $B/CaSkeletonApplication.java\nawk 'NR>=100 && NR<=101 {printf \" CaSkeletonApplication.java:%d %s\\n\", NR, $0}' $B/CaSkeletonApplication.java\ngrep -n 'adapter\\\\\\\\.outbound\\\\\\\\.messaging' $B/CaSkeletonApplication.java | sed -E 's#^([0-9]+): *# CaSkeletonApplication.java:\\1 #'\necho \" ConfigurationPropertiesScan 목록에 adapter.outbound.messaging 이 있는가 :\"\nn=$(awk 'NR>=58 && NR<=82' $B/CaSkeletonApplication.java | grep -c 'adapter.outbound.messaging' || true)\necho \" $n 건\"\n\necho\necho \"# broker=kafka 를 쓰는 시험마다 같은 파일이 enabled 를 주는가\"\nfor f in $(git grep -l 'app.messaging.broker=kafka' -- 'src/**/*.java' | grep '/test/'); do\n b=$(grep -c 'app.messaging.broker=kafka' \"$f\" || true)\n e=$(grep -c 'app.messaging.enabled=' \"$f\" || true)\n printf \" %-46s broker=kafka %s 줄 · enabled= %s 줄\\n\" \"$(basename $f)\" \"$b\" \"$e\"\ndone\necho \" enabled 를 한 줄도 주지 않는 파일의 시험 이름 :\"\nfor f in $(git grep -l 'app.messaging.broker=kafka' -- 'src/**/*.java' | grep '/test/'); do\n e=$(grep -c 'app.messaging.enabled=' \"$f\" || true)\n if [ \"$e\" = \"0\" ]; then grep -n 'void .*(' \"$f\" | sed -E \"s#^([0-9]+): *# $(basename $f):\\1 #\"; fi\ndone\n",
"cwd": "/shared/codebase/clean-architecture-backend-template",
"exitCode": 0,
"executedAt": "2026-09-04T01:37:31+00:00",
"sourceRevision": "21234e38cdb9a926cbc92bb97a2aee2e4a7d2916",
"raw": "evidence/raw/a19-f014-kafka-msg.txt",
"svg": "evidence/rendered/a19-f014-kafka-msg.svg",
"rawSha256": "fdb9acc28d9e2de8a714af9359e84d2bf8690abcf165381dafe4d25b658688c8",
"lines": 140,
"redaction": "비밀값 없음"
}