Files
document-haness/docs/clean-architecture-backend-template/final/evidence/rendered/a19-f003-messaging-reliability-api.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

198 lines
26 KiB
XML

<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="2702" viewBox="0 0 1200 2702" 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="2700" 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">$ set -e
set -o pipefail
M=src/messaging
echo &quot;# sub-scope 01 네 리프의 소스 세트와 계수&quot;
for m in messaging-core-api m</tspan><tspan x="24" dy="22">essaging-transport-spi messaging-reliability-api messaging-runtime-core; do
d=$M/$m
mf=$(find $d/src/main -name &#x27;*.j</tspan><tspan x="24" dy="22">ava&#x27; 2&gt;/dev/null | wc -l || true)
tf=$(find $d/src/test -name &#x27;*.java&#x27; 2&gt;/dev/null | wc -l || true)
ml=$(find $d/src</tspan><tspan x="24" dy="22">/main -name &#x27;*.java&#x27; 2&gt;/dev/null -exec cat {} + | wc -l || true)
sets=$(ls $d/src | tr &#x27;\n&#x27; &#x27; &#x27;)
printf &quot; %-26s mai</tspan><tspan x="24" dy="22">n=%-3s test=%-3s main줄수=%-5s 소스세트: %s\n&quot; &quot;$m&quot; &quot;$mf&quot; &quot;$tf&quot; &quot;$ml&quot; &quot;$sets&quot;
done
echo
echo &quot;# 그 817 줄의 내역&quot;
pytho</tspan><tspan x="24" dy="22">n3 - &lt;&lt;&#x27;PY&#x27;
import pathlib, re
root = pathlib.Path(&#x27;src/messaging/messaging-reliability-api/src/main&#x27;)
blank = comment =</tspan><tspan x="24" dy="22"> code = 0
for f in sorted(root.rglob(&#x27;*.java&#x27;)):
inblock = False
for line in f.read_text(encoding=&#x27;utf-8&#x27;).split</tspan><tspan x="24" dy="22">lines():
s = line.strip()
if inblock:
comment += 1
if &#x27;*/&#x27; in s: inblock = False</tspan><tspan x="24" dy="22">
elif not s: blank += 1
elif s.startswith(&#x27;//&#x27;): comment += 1
elif s.startswith(&#x27;/*&#x27;):
</tspan><tspan x="24" dy="22"> comment += 1
if &#x27;*/&#x27; not in s: inblock = True
else: code += 1
print(f&quot; 공백 {blank} · 주석 {com</tspan><tspan x="24" dy="22">ment} · 코드 {code} · 합계 {blank+comment+code}&quot;)
PY
echo
echo &quot;# 열세 타입의 선언 형태와 줄 수&quot;
for f in $(find $M/m</tspan><tspan x="24" dy="22">essaging-reliability-api/src/main -name &#x27;*.java&#x27; | sort); do
kind=$(grep -oE &#x27;public (sealed )?(interface|record|enum|</tspan><tspan x="24" dy="22">final class|abstract class|class)&#x27; $f | head -1 || true)
printf &quot; %-34s %-14s %s 줄\n&quot; &quot;$(basename $f)&quot; &quot;${kind#publi</tspan><tspan x="24" dy="22">c }&quot; &quot;$(wc -l &lt; $f)&quot;
done
echo
echo &quot;# 실행 가능한 규칙을 가진 유일한 열거형&quot;
grep -n &#x27;isSafeToSettle\|CLAIMED_ELSEWHER</tspan><tspan x="24" dy="22">E&#x27; $M/messaging-reliability-api/src/main/java/dev/caskeleton/messaging/reliability/InboxResult.java \
| sed -E &#x27;s#^([0</tspan><tspan x="24" dy="22">-9]+): *# InboxResult.java:\1 #&#x27; | head -5
echo &quot; OutboxStatus 와 OutboxTransitionResult 의 메서드 수 :&quot;
for t in Out</tspan><tspan x="24" dy="22">boxStatus OutboxTransitionResult; do
n=$(grep -cE &#x27;^ (public|private|static).*\(&#x27; $M/messaging-reliability-api/src/ma</tspan><tspan x="24" dy="22">in/java/dev/caskeleton/messaging/reliability/$t.java || true)
printf &quot; %-24s %s 개\n&quot; &quot;$t&quot; &quot;$n&quot;
done
echo &quot; 전이 </tspan><tspan x="24" dy="22">규칙이 실제로 선언된 자리 :&quot;
grep -n &#x27;STALE_LEASE\|still owns&#x27; $M/messaging-reliability-api/src/main/java/dev/caskeleton</tspan><tspan x="24" dy="22">/messaging/reliability/OutboxRepository.java \
| head -3 | sed -E &#x27;s#^([0-9]+): *# OutboxRepository.java:\1 #&#x27;
echo</tspan><tspan x="24" dy="22">
echo &quot;# 원문 §3.6 이 지목한 구현 리프 이름과, 같은 문서 §7 이 적은 실제 이름&quot;
A=/shared/document-detail/clean-archite</tspan><tspan x="24" dy="22">cture-backend-template/analysis/19-messaging-platform.md
grep -n &#x27;messaging-outbox-jdbc\b\|messaging-inbox-jdbc\b&#x27; $A | </tspan><tspan x="24" dy="22">head -2 | cut -c1-120 | sed &#x27;s#^# analysis/19:#&#x27;
grep -n &#x27;messaging-outbox-jdbc-postgresql\|messaging-inbox-jdbc-postgr</tspan><tspan x="24" dy="22">esql\|messaging-claim-check&#x27; $A | head -3 | cut -c1-120 | sed &#x27;s#^# analysis/19:#&#x27;
echo &quot; 저장소에 실재하는 이름 :&quot;
fo</tspan><tspan x="24" dy="22">r m in messaging-outbox-jdbc messaging-inbox-jdbc messaging-outbox-jdbc-postgresql messaging-inbox-jdbc-postgresql messa</tspan><tspan x="24" dy="22">ging-claim-check; do
if [ -d &quot;$M/$m/src&quot; ]; then
printf &quot; %-34s main=%-3s test=%s\n&quot; &quot;$m&quot; &quot;$(find $M/$m/src/mai</tspan><tspan x="24" dy="22">n -name &#x27;*.java&#x27; 2&gt;/dev/null | wc -l || true)&quot; &quot;$(find $M/$m/src/test -name &#x27;*.java&#x27; 2&gt;/dev/null | wc -l || true)&quot;
els</tspan><tspan x="24" dy="22">e
printf &quot; %-34s src 디렉터리 없음\n&quot; &quot;$m&quot;
fi
done
echo &quot; messaging-outbox-jpa · messaging-inbox-jpa 가 등록</tspan><tspan x="24" dy="22">돼 있는가 :&quot;
r=$(grep -c &#x27;messaging-outbox-jpa\|messaging-inbox-jpa&#x27; src/config/architecture/modules.json || true)
g=$(g</tspan><tspan x="24" dy="22">it ls-files &quot;$M/messaging-outbox-jpa&quot; &quot;$M/messaging-inbox-jpa&quot; | wc -l || true)
echo &quot; modules.json 등재 $r 건 · git</tspan><tspan x="24" dy="22"> 추적 파일 $g 개&quot;
echo
echo &quot;# 두 열거형을 코드에서 참조하는 test (주석·문자열 제거, 단어 경계)&quot;
python3 - &lt;&lt;&#x27;PY&#x27;
impo</tspan><tspan x="24" dy="22">rt pathlib, re, subprocess
files = subprocess.run([&#x27;git&#x27;,&#x27;grep&#x27;,&#x27;-l&#x27;,&#x27;Outbox&#x27;,&#x27;--&#x27;,&#x27;src/**/*.java&#x27;],
</tspan><tspan x="24" dy="22"> capture_output=True, text=True).stdout.split()
def strip(src):
src = re.sub(r&#x27;/\*.*?\*/&#x27;, &#x27; &#x27;, src, flags=re.S)
</tspan><tspan x="24" dy="22"> src = re.sub(r&#x27;(?m)//.*$&#x27;, &#x27; &#x27;, src)
return re.sub(r&#x27;&quot;(?:[^&quot;\\]|\\.)*&quot;&#x27;, &#x27; &#x27;, src)
for t in (&#x27;OutboxStatus&#x27;, &#x27;Ou</tspan><tspan x="24" dy="22">tboxTransitionResult&#x27;):
hits = []
for p in files:
if &#x27;/test/&#x27; not in p: continue
n = len(re.find</tspan><tspan x="24" dy="22">all(rf&#x27;\b{t}\b&#x27;, strip(pathlib.Path(p).read_text(encoding=&#x27;utf-8&#x27;))))
if n: hits.append((pathlib.Path(p).name, n</tspan><tspan x="24" dy="22">, p.split(&#x27;/src/&#x27;)[0].split(&#x27;/&#x27;)[-1]))
print(f&quot; {t} : {len(hits)} 파일&quot;)
for name, n, leaf in sorted(hits):
</tspan><tspan x="24" dy="22"> print(f&quot; {name:&lt;44} {n:&gt;3} 회 ({leaf})&quot;)
PY
echo
echo &quot;# 열세 타입 중 test 참조가 0 인 것&quot;
python3 - &lt;&lt;&#x27;PY&#x27;
im</tspan><tspan x="24" dy="22">port pathlib, re, subprocess
types = sorted(p.stem for p in pathlib.Path(&#x27;src/messaging/messaging-reliability-api/src/ma</tspan><tspan x="24" dy="22">in&#x27;).rglob(&#x27;*.java&#x27;))
allj = subprocess.run([&#x27;git&#x27;,&#x27;grep&#x27;,&#x27;-l&#x27;,&#x27;&#x27;,&#x27;--&#x27;,&#x27;src/**/*.java&#x27;], capture_output=True, text=True)</tspan><tspan x="24" dy="22">.stdout.split()
def strip(src):
src = re.sub(r&#x27;/\*.*?\*/&#x27;, &#x27; &#x27;, src, flags=re.S)
src = re.sub(r&#x27;(?m)//.*$&#x27;, &#x27; &#x27;,</tspan><tspan x="24" dy="22"> src)
return re.sub(r&#x27;&quot;(?:[^&quot;\\]|\\.)*&quot;&#x27;, &#x27; &#x27;, src)
cache = {p: strip(pathlib.Path(p).read_text(encoding=&#x27;utf-8&#x27;, er</tspan><tspan x="24" dy="22">rors=&#x27;replace&#x27;)) for p in allj}
for t in types:
tn = sum(1 for p, s in cache.items() if &#x27;/test/&#x27; in p and re.search(</tspan><tspan x="24" dy="22">rf&#x27;\b{t}\b&#x27;, s))
mn = sum(1 for p, s in cache.items() if &#x27;/main/&#x27; in p and f&#x27;/{t}.java&#x27; not in p and re.search(rf&#x27;\b</tspan><tspan x="24" dy="22">{t}\b&#x27;, s))
if tn == 0:
print(f&quot; {t:&lt;30} test 0 · 자기 파일 밖 main {mn}&quot;)
PY
</tspan></text>
<text x="24" y="1058" 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</tspan></text>
<text x="24" y="1080" 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-04T00:24:01+00:00 · exit 0</tspan></text>
<line x1="24" y1="1094" x2="1176" y2="1094" stroke="#30363d"/>
<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"># sub-scope 01 네 리프의 소스 세트와 계수</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"> messaging-core-api main=85 test=8 main줄수=3948 소스세트: main test </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"> messaging-transport-spi main=13 test=4 main줄수=776 소스세트: main test </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"> messaging-reliability-api main=13 test=0 main줄수=817 소스세트: main </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"> messaging-runtime-core main=6 test=4 main줄수=787 소스세트: main test </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"></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"># 그 817 줄의 내역</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"> 공백 79 · 주석 415 · 코드 323 · 합계 817</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"></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"># 열세 타입의 선언 형태와 줄 수</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"> ClaimCheckReference.java record 50 줄</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"> IdempotentMessageHandler.java interface 33 줄</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"> InboxRecord.java record 27 줄</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"> InboxRepository.java interface 53 줄</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"> InboxResult.java enum 45 줄</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"> OutboxCanonicalMetadata.java record 158 줄</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"> OutboxLease.java record 42 줄</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"> OutboxRecord.java record 140 줄</tspan></text>
<text x="24" y="1530" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> OutboxRepository.java interface 152 줄</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"> OutboxStatus.java enum 37 줄</tspan></text>
<text x="24" y="1574" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> OutboxTransitionResult.java enum 24 줄</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"> ReliableMessagePublisher.java interface 27 줄</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"> TransactionalMessageAction.java interface 29 줄</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"></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"> InboxResult.java:6 * &lt;p&gt;Three outcomes, not two. Collapsing {@link #ALREADY_APPLIED} and {@link #CLAIMED_ELSEWHERE}</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"> InboxResult.java:29 CLAIMED_ELSEWHERE(false);</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"> InboxResult.java:42 public boolean isSafeToSettle() {</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"> OutboxStatus 와 OutboxTransitionResult 의 메서드 수 :</tspan></text>
<text x="24" y="1772" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> OutboxStatus 0 개</tspan></text>
<text x="24" y="1794" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> OutboxTransitionResult 0 개</tspan></text>
<text x="24" y="1816" 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="1838" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> OutboxRepository.java:70 * Records a confirmed publication, only if this lease still owns the row.</tspan></text>
<text x="24" y="1860" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> OutboxRepository.java:72 * @return {@link OutboxTransitionResult#STALE_LEASE} when another relay has taken it</tspan></text>
<text x="24" y="1882" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> OutboxRepository.java:87 /** Records an ambiguous outcome, only if this lease still owns the row. */</tspan></text>
<text x="24" y="1904" 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="1926" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 원문 §3.6 이 지목한 구현 리프 이름과, 같은 문서 §7 이 적은 실제 이름</tspan></text>
<text x="24" y="1948" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> analysis/19:33:| 7 | `messaging-outbox-jdbc-postgresql` | 28 | 5 | `app-bootstrap` |</tspan></text>
<text x="24" y="1970" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> analysis/19:41:| 15 | `messaging-inbox-jdbc-postgresql` | 13 | 2 | `app-bootstrap` |</tspan></text>
<text x="24" y="1992" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> analysis/19:33:| 7 | `messaging-outbox-jdbc-postgresql` | 28 | 5 | `app-bootstrap` |</tspan></text>
<text x="24" y="2014" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> analysis/19:41:| 15 | `messaging-inbox-jdbc-postgresql` | 13 | 2 | `app-bootstrap` |</tspan></text>
<text x="24" y="2036" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> analysis/19:44:| 18 | `messaging-claim-check` | 11 | 2 | `app-bootstrap` |</tspan></text>
<text x="24" y="2058" 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="2080" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> messaging-outbox-jdbc src 디렉터리 없음</tspan></text>
<text x="24" y="2102" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> messaging-inbox-jdbc src 디렉터리 없음</tspan></text>
<text x="24" y="2124" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> messaging-outbox-jdbc-postgresql main=13 test=8</tspan></text>
<text x="24" y="2146" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> messaging-inbox-jdbc-postgresql main=6 test=4</tspan></text>
<text x="24" y="2168" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> messaging-claim-check main=6 test=3</tspan></text>
<text x="24" y="2190" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> messaging-outbox-jpa · messaging-inbox-jpa 가 등록돼 있는가 :</tspan></text>
<text x="24" y="2212" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> modules.json 등재 0 건 · git 추적 파일 0 개</tspan></text>
<text x="24" y="2234" 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="2256" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 두 열거형을 코드에서 참조하는 test (주석·문자열 제거, 단어 경계)</tspan></text>
<text x="24" y="2278" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> OutboxStatus : 6 파일</tspan></text>
<text x="24" y="2300" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> DebeziumOutboxRecordMapperTest.java 2 회 (messaging-outbox-jdbc-postgresql)</tspan></text>
<text x="24" y="2322" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> JdbcOutboxTransactionRequirementTest.java 2 회 (messaging-outbox-jdbc-postgresql)</tspan></text>
<text x="24" y="2344" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> OutboxEnvelopeFactoryTest.java 2 회 (messaging-outbox-jdbc-postgresql)</tspan></text>
<text x="24" y="2366" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> OutboxPostgresIT.java 8 회 (messaging-outbox-jdbc-postgresql)</tspan></text>
<text x="24" y="2388" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> OutboxRelayTest.java 18 회 (messaging-outbox-jdbc-postgresql)</tspan></text>
<text x="24" y="2410" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> OutboxRelayWorkerTest.java 5 회 (messaging-outbox-jdbc-postgresql)</tspan></text>
<text x="24" y="2432" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> OutboxTransitionResult : 4 파일</tspan></text>
<text x="24" y="2454" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> MessagingOutboxRelayLifecycleTest.java 7 회 (messaging-spring-boot-starter)</tspan></text>
<text x="24" y="2476" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> OutboxOperationsTest.java 11 회 (messaging-outbox-jdbc-postgresql)</tspan></text>
<text x="24" y="2498" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> OutboxPostgresIT.java 4 회 (messaging-outbox-jdbc-postgresql)</tspan></text>
<text x="24" y="2520" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> OutboxRelayTest.java 19 회 (messaging-outbox-jdbc-postgresql)</tspan></text>
<text x="24" y="2542" 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="2564" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 열세 타입 중 test 참조가 0 인 것</tspan></text>
<text x="24" y="2586" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> IdempotentMessageHandler test 0 · 자기 파일 밖 main 1</tspan></text>
<text x="24" y="2608" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> InboxRecord test 0 · 자기 파일 밖 main 0</tspan></text>
<text x="24" y="2630" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> ReliableMessagePublisher test 0 · 자기 파일 밖 main 0</tspan></text>
<text x="24" y="2652" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"> TransactionalMessageAction test 0 · 자기 파일 밖 main 2</tspan></text>
</svg>