Files
document-haness/docs/clean-architecture-backend-template/final/evidence/rendered/a05-f006-stable.svg
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

100 lines
17 KiB
XML

<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="1800" viewBox="0 0 1200 1800" role="img">
<title>terminal evidence</title>
<desc>Terminal-style rendering generated from retained command output. Sensitive-looking values are redacted in the visual asset.</desc>
<rect x="1" y="1" width="1198" height="1798" rx="14" fill="#0d1117" stroke="#30363d"/>
<rect x="1" y="1" width="1198" height="44" rx="14" fill="#161b22"/>
<rect x="1" y="30" width="1198" height="14" fill="#161b22"/>
<circle cx="24" cy="22" r="6" fill="#ff5f57"/>
<circle cx="44" cy="22" r="6" fill="#febc2e"/>
<circle cx="64" cy="22" r="6" fill="#28c840"/>
<text x="92" y="27" fill="#8b949e" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace">terminal evidence</text>
<text x="24" y="68" fill="#c9d1d9" font-size="15" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">$ M=adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/transaction/EvidenceAware</tspan><tspan x="24" dy="22">JpaTransactionManager.java
echo &#x27;# 능력 리포트가 이 능력에 매긴 등급&#x27;
grep -rn &#x27;COMPLETION_EVIDENCE&#x27; --include=*.java -</tspan><tspan x="24" dy="22">-exclude-dir=build . | grep &#x27;/main/&#x27; | sed &#x27;s|.*/||&#x27;
echo
echo &#x27;# 매니저의 javadoc 이 주장하는 것&#x27;
grep -n &#x27;&#x27; &quot;$M&quot; | se</tspan><tspan x="24" dy="22">d -n &#x27;11,23p&#x27;
echo &#x27;# 같은 파일의 코드가 하는 것&#x27;
grep -n &#x27;&#x27; &quot;$M&quot; | sed -n &#x27;49,73p&#x27;
echo
echo &#x27;# 그 매니저를 만드는 코</tspan><tspan x="24" dy="22">&#x27;
grep -rn &#x27;new EvidenceAwareJpaTransactionManager\|EvidenceAwareJpaTransactionManager\.standard&#x27; --include=*.java --e</tspan><tspan x="24" dy="22">xclude-dir=build . | sed &#x27;s|^\./||&#x27;
echo -n &#x27;# 자기 파일과 javadoc 을 뺀 생성 지점: &#x27;
grep -rn &#x27;new EvidenceAwareJpaTr</tspan><tspan x="24" dy="22">ansactionManager\|EvidenceAwareJpaTransactionManager\.standard&#x27; --include=*.java --exclude-dir=build . \
| grep -v &#x27;tr</tspan><tspan x="24" dy="22">ansaction/EvidenceAwareJpaTransactionManager.java&#x27; | grep -vc &#x27; \* &#x27;
echo -n &#x27;# FQCN 이 설정 리소스에 등장하는 곳: &#x27;
g</tspan><tspan x="24" dy="22">rep -rln &#x27;EvidenceAwareJpaTransactionManager&#x27; --exclude-dir=build --include=*.yml --include=*.properties --include=*.imp</tspan><tspan x="24" dy="22">orts --include=spring.factories --include=*.xml --include=*.json . | wc -l
echo -n &#x27;# 그 클래스를 상속하는 코드: &#x27;
gre</tspan><tspan x="24" dy="22">p -rn &#x27;extends EvidenceAwareJpaTransactionManager&#x27; --include=*.java --exclude-dir=build . | wc -l
echo
echo &#x27;# 트랜잭션</tspan><tspan x="24" dy="22"> 매니저 빈을 등록하는 코드 (애너테이션 다음 여섯 줄까지 본다)&#x27;
echo -n &#x27;# main: &#x27;
grep -rn -A6 &#x27;@Bean&#x27; --include=*.jav</tspan><tspan x="24" dy="22">a --exclude-dir=build . | grep &#x27;/main/&#x27; | grep -cE &#x27;TransactionManager +[A-Za-z]+\(&#x27;
echo -n &#x27;# test: &#x27;
grep -rn -A6 &#x27;</tspan><tspan x="24" dy="22">@Bean&#x27; --include=*.java --exclude-dir=build . | grep &#x27;/test/&#x27; | grep -cE &#x27;TransactionManager +[A-Za-z]+\(&#x27;
grep -rn -A6 </tspan><tspan x="24" dy="22">&#x27;@Bean&#x27; --include=*.java --exclude-dir=build . | grep &#x27;/test/&#x27; | grep -E &#x27;TransactionManager +[A-Za-z]+\(&#x27; | sed &#x27;s|.*/|</tspan><tspan x="24" dy="22">|&#x27; </tspan></text>
<text x="24" y="420" fill="#8b949e" font-size="13" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">cwd: /shared/codebase/clean-architecture-backend-template/src</tspan></text>
<text x="24" y="442" fill="#8b949e" font-size="13" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">time: 2026-09-02T03:48:36+00:00 · exit 0</tspan></text>
<line x1="24" y1="456" x2="1176" y2="456" stroke="#30363d"/>
<text x="24" y="496" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 능력 리포트가 이 능력에 매긴 등급</tspan></text>
<text x="24" y="518" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">JpaPlatformAutoConfiguration.java:57: CapabilitySupport.stable(JpaCapability.COMPLETION_EVIDENCE),</tspan></text>
<text x="24" y="540" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">JpaCapability.java:16: COMPLETION_EVIDENCE(&quot;transaction.completion-evidence&quot;),</tspan></text>
<text x="24" y="562" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"></tspan></text>
<text x="24" y="584" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 매니저의 javadoc 이 주장하는 것</tspan></text>
<text x="24" y="606" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">11:/**</tspan></text>
<text x="24" y="628" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">12: * A {@link JpaTransactionManager} that records how far each transaction got, so a commit failure</tspan></text>
<text x="24" y="650" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">13: * can be classified as &quot;rolled back&quot; or &quot;outcome unknown&quot; instead of guessed (design §17.2).</tspan></text>
<text x="24" y="672" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">14: *</tspan></text>
<text x="24" y="694" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">15: * &lt;p&gt;The phase is marked {@link TransactionCompletionEvidence#COMMITTING} immediately before the</tspan></text>
<text x="24" y="716" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">16: * provider commit and never after. That ordering is the whole mechanism: if the JVM, the network,</tspan></text>
<text x="24" y="738" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">17: * or the server dies inside {@code super.doCommit}, the last thing written is &quot;we asked, we do not</tspan></text>
<text x="24" y="760" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">18: * know&quot;, which is exactly the state that must not be mistaken for a rollback.</tspan></text>
<text x="24" y="782" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">19: *</tspan></text>
<text x="24" y="804" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">20: * &lt;p&gt;Evidence is cleared on every path — commit success, commit failure, rollback, and cleanup. A</tspan></text>
<text x="24" y="826" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">21: * frame left behind on a pooled thread would attach this transaction&#x27;s phase to the next unrelated</tspan></text>
<text x="24" y="848" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">22: * unit of work that thread picks up.</tspan></text>
<text x="24" y="870" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">23: */</tspan></text>
<text x="24" y="892" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 같은 파일의 코드가 하는 것</tspan></text>
<text x="24" y="914" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">49: @Override</tspan></text>
<text x="24" y="936" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">50: protected void doCommit(DefaultTransactionStatus status) {</tspan></text>
<text x="24" y="958" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">51: TransactionEvidenceContext.mark(TransactionCompletionEvidence.COMMITTING);</tspan></text>
<text x="24" y="980" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">52: try {</tspan></text>
<text x="24" y="1002" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">53: super.doCommit(status);</tspan></text>
<text x="24" y="1024" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">54: TransactionEvidenceContext.mark(TransactionCompletionEvidence.COMMITTED);</tspan></text>
<text x="24" y="1046" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">55: } catch (RuntimeException failure) {</tspan></text>
<text x="24" y="1068" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">56: TransactionEvidenceContext.mark(TransactionCompletionEvidence.UNKNOWN);</tspan></text>
<text x="24" y="1090" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">57: throw classifier.translateCommitFailure(failure);</tspan></text>
<text x="24" y="1112" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">58: } finally {</tspan></text>
<text x="24" y="1134" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">59: // Deliberately not cleared here. The executor&#x27;s scope owns the frame&#x27;s lifetime; a second</tspan></text>
<text x="24" y="1156" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">60: // owner popping was how an inner REQUIRES_NEW transaction deleted its outer frame.</tspan></text>
<text x="24" y="1178" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">61: }</tspan></text>
<text x="24" y="1200" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">62: }</tspan></text>
<text x="24" y="1222" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">63:</tspan></text>
<text x="24" y="1244" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">64: @Override</tspan></text>
<text x="24" y="1266" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">65: protected void doRollback(DefaultTransactionStatus status) {</tspan></text>
<text x="24" y="1288" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">66: try {</tspan></text>
<text x="24" y="1310" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">67: super.doRollback(status);</tspan></text>
<text x="24" y="1332" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">68: TransactionEvidenceContext.mark(TransactionCompletionEvidence.ROLLED_BACK);</tspan></text>
<text x="24" y="1354" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">69: } finally {</tspan></text>
<text x="24" y="1376" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">70: // Deliberately not cleared here. The executor&#x27;s scope owns the frame&#x27;s lifetime; a second</tspan></text>
<text x="24" y="1398" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">71: // owner popping was how an inner REQUIRES_NEW transaction deleted its outer frame.</tspan></text>
<text x="24" y="1420" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">72: }</tspan></text>
<text x="24" y="1442" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">73: }</tspan></text>
<text x="24" y="1464" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"></tspan></text>
<text x="24" y="1486" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 그 매니저를 만드는 코드</tspan></text>
<text x="24" y="1508" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">app-bootstrap/src/main/java/dev/caskeleton/bootstrap/autoconfigure/jpa/JpaTransactionAutoConfiguration.java:55: * EvidenceAwar</tspan><tspan x="24" dy="22">eJpaTransactionManager.standard(entityManagerFactory, clock)}. The composition root</tspan></text>
<text x="24" y="1552" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/transaction/EvidenceAwareJpaTransacti</tspan><tspan x="24" dy="22">onManager.java:39: return new EvidenceAwareJpaTransactionManager(</tspan></text>
<text x="24" y="1596" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 자기 파일과 javadoc 을 뺀 생성 지점: 0</tspan></text>
<text x="24" y="1618" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># FQCN 이 설정 리소스에 등장하는 곳: 0</tspan></text>
<text x="24" y="1640" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 그 클래스를 상속하는 코드: 0</tspan></text>
<text x="24" y="1662" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"></tspan></text>
<text x="24" y="1684" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 트랜잭션 매니저 빈을 등록하는 코드 (애너테이션 다음 여섯 줄까지 본다)</tspan></text>
<text x="24" y="1706" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># main: 0</tspan></text>
<text x="24" y="1728" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># test: 1</tspan></text>
<text x="24" y="1750" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">JpaPlatformRuntimeAutoConfigurationTest.java-257- PlatformTransactionManager transactionManager() {</tspan></text>
</svg>