Files
document-haness/docs/clean-architecture-backend-template/final/evidence/meta/a20-f010-grpcoutcomereplay.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
4.9 KiB
JSON

{
"assetKey": "a20-f010-grpcoutcomereplay",
"kind": "terminal",
"command": "#!/bin/bash\nset -euo pipefail\ncd /shared/codebase/clean-architecture-backend-template\nR=src/grpc/grpc-policy/src/main/java/dev/caskeleton/grpc/idempotency/GrpcOutcomeReplay.java\nD=src/grpc-advanced/grpc-advanced-streaming/src/main/java/dev/caskeleton/grpc/advanced/streaming/GrpcClientMessageDeduplicator.java\ntest -f \"$R\"; test -f \"$D\"\nCPP=$(cat /tmp/cp-grpc-policy.txt)\n\n# 검색이 헛돌면 0 을 제조하지 않고 죽는다. rc 0=매치, 1=매치없음, 그 밖=오류.\nrefs() {\n local name=$1 self=$2 out rc\n out=$(git grep -l \"$name\" -- 'src/**/*.java'); rc=$?\n [ $rc -le 1 ] || { echo \"SEARCH FAILED rc=$rc for $name\" >&2; exit 2; }\n printf '%s\\n' \"$out\" | { grep '/main/' || true; } | { grep -v \"/$self\" || true; } | grep -c . || true\n}\n\necho \"# 저장소 전체 ($(wc -l < $R) 줄)\"\nawk '{printf \" GrpcOutcomeReplay.java:%d %s\\n\", NR, $0}' $R\n\necho\necho \"# 그 맵에 가해지는 연산 전부\"\ngrep -n 'storedOutcomes' $R | sed -E 's#^([0-9]+): *# GrpcOutcomeReplay.java:\\1 #'\necho \" 클래스와 필드의 접근 한정 :\"\ngrep -nE 'public final class|private final ConcurrentMap' $R | sed -E 's#^([0-9]+): *# GrpcOutcomeReplay.java:\\1 #'\nN='\\.remove|\\.clear|removeIf|computeIfPresent|\\.merge|entrySet|keySet|evict|expire|TTL|Duration|Instant|maximumSize|Caffeine|LinkedHashMap|WeakReference|SoftReference|Cleaner'\necho \" 줄이는 연산 이름 열여덟을 통틀어 : $({ grep -cE \"$N\" $R || true; }) 건\"\necho \" 같은 검색을 대조 파일에 걸면 : $({ grep -cE \"$N\" $D || true; }) 건 (검색이 헛돌지 않음을 보인다)\"\n\necho\necho \"# 크기 상한이 실제로 거부하는가\"\ncd /tmp/probe5\njavac -nowarn -encoding UTF-8 -cp \"$CPP\" -d . OutcomeReplayProbe.java\njava -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -cp \".:$CPP\" OutcomeReplayProbe\ncd /shared/codebase/clean-architecture-backend-template\n\necho\necho \"# 이 타입이 나오는 파일 전부 — 경로 제한 없이, 절단 없이\"\ngit grep -l 'GrpcOutcomeReplay' | sed 's/^/ /'\necho \" 자기 파일 밖 main 참조 : $(refs GrpcOutcomeReplay GrpcOutcomeReplay.java) 개\"\necho \" [대조] 같은 패키지의 GrpcIdempotencyDecision : $(refs GrpcIdempotencyDecision GrpcIdempotencyDecision.java) 개 (0 이 아니어야 정상)\"\necho \" git 이 추적하지 않는 변경 : $(git status --porcelain | grep -c . || true) 건\"\necho \" .java 밖에서 이 이름을 쓰는 파일 : $({ git grep -l 'GrpcOutcomeReplay' -- ':!*.java' || true; } | grep -c . || true) 개\"\n\necho\necho \"# 같은 패키지의 인터셉터는 재생을 어떻게 판정하는가\"\nI=src/grpc/grpc-policy/src/main/java/dev/caskeleton/grpc/idempotency/GrpcIdempotencyInterceptor.java\nawk 'NR>=95 && NR<=110 {printf \" GrpcIdempotencyInterceptor.java:%d %s\\n\", NR, $0}' $I\necho \" 그 파일이 GrpcOutcomeReplay 를 부르는가 : $({ grep -c 'GrpcOutcomeReplay' $I || true; }) 건\"\n\necho\necho \"# 자바독이 이 타입을 무엇이라고 적는가\"\nawk 'NR>=7 && NR<=16 {printf \" GrpcOutcomeReplay.java:%d %s\\n\", NR, $0}' $R\n\necho\necho \"# 대조 클래스에 같은 잣대를 댄다 ($(wc -l < $D) 줄)\"\necho \" 이 파일 : $R\"\necho \" 대조 파일 : $D\"\nawk 'NR>=11 && NR<=14 {printf \" GrpcClientMessageDeduplicator.java:%d %s\\n\", NR, $0}' $D\nawk 'NR>=16 && NR<=23 {printf \" GrpcClientMessageDeduplicator.java:%d %s\\n\", NR, $0}' $D\necho \" 적용된 메시지마다 무엇을 넣는가 :\"\nawk 'NR>=70 && NR<=77 {printf \" GrpcClientMessageDeduplicator.java:%d %s\\n\", NR, $0}' $D\necho \" 정리 경로와 그 호출자 :\"\ngit grep -n 'endSession' -- 'src/**/*.java' \\\n | sed -E 's#^src/[^:]*/src/(main|test)/java/dev/caskeleton/[^:]*/([^:/]+):([0-9]+):# \\1 · \\2:\\3 #'\necho \" 그 대조 클래스의 자기 파일 밖 main 참조 : $(refs GrpcClientMessageDeduplicator GrpcClientMessageDeduplicator.java) 개\"\n\necho\necho \"# 두 클래스가 같은 family 인가\"\necho \" modules.json 의 family 키 : $({ grep -c 'family' src/config/architecture/modules.json || true; }) 건\"\nawk 'NR>=1 && NR<=3 {printf \" src/grpc/CLAUDE.md:%d %s\\n\", NR, $0}' src/grpc/CLAUDE.md\nawk 'NR>=3 && NR<=9 {printf \" src/grpc-advanced/CLAUDE.md:%d %s\\n\", NR, $0}' src/grpc-advanced/CLAUDE.md\ngrep -nE 'grpc:\\*.*→|Stable leaf' src/grpc-advanced/CLAUDE.md \\\n | sed -E 's#^([0-9]+): *# src/grpc-advanced/CLAUDE.md:\\1 #'\n",
"cwd": "/shared/codebase/clean-architecture-backend-template",
"exitCode": 0,
"executedAt": "2026-09-04T03:20:56+00:00",
"sourceRevision": "21234e38cdb9a926cbc92bb97a2aee2e4a7d2916",
"raw": "evidence/raw/a20-f010-grpcoutcomereplay.txt",
"svg": "evidence/rendered/a20-f010-grpcoutcomereplay.svg",
"rawSha256": "52cd9945d3ab8ade10258912cd363ab0900d3439f939546eb4db6cd958465118",
"lines": 166,
"redaction": "비밀값 없음"
}