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>
This commit is contained in:
DongHyeonka
2026-09-04 22:51:59 +09:00
co-authored by Claude Opus 5
parent 43bccd08a8
commit b2963105a8
5017 changed files with 372751 additions and 4943 deletions
@@ -0,0 +1,19 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="366" viewBox="0 0 880 366" role="img">
<title>요청 예산에서 파생되는 계층</title>
<desc>배선된 요청 데드라인 상자에서 나가는 화살표가 없다. 네 파생 계층은 메서드로만 존재하고 프로덕션 호출자가 0 이라, 파생 전이 자체가 일어나지 않는다.</desc>
<rect x="0" y="0" width="880" height="366" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">요청 예산에서 파생되는 계층</text>
<rect x="28" y="181.0" width="262" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="159.0" y="215.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">요청 데드라인 — 배선됨</text>
<rect x="458" y="76" width="394" height="268" rx="14" fill="none" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="474" y="100" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">파생 없음 — 프로덕션 호출자 0</text>
<rect x="474" y="114" width="362" height="50" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="655.0" y="144.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">리졸버 예산</text>
<rect x="474" y="172" width="362" height="50" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="655.0" y="202.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">DataLoader 배치 타임아웃</text>
<rect x="474" y="230" width="362" height="50" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="655.0" y="260.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">다운스트림 데드라인</text>
<rect x="474" y="288" width="362" height="50" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="655.0" y="318.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">구독 데드라인</text>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>응답을 실제로 만드는 쪽</title>
<desc>상태 코드와 미디어 타입 규칙을 담은 http 패키지가 조립되지 않고, 실제 응답은 프레임워크가 만든다. 노출이 아니라 통제권의 문제다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">응답을 실제로 만드는 쪽</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">Spring GraphQL</text>
<rect x="44.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="171.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">상태 코드 규칙</text>
<rect x="317.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="444.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">미디어 타입 협상</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">http 패키지 — 미배선</text>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="394" viewBox="0 0 880 394" role="img">
<title>패키지별 도달 경로</title>
<desc>자동설정과 배치 로더 등록기에서 나가는 경로는 dataloader 에만 닿는다. fetch·pagination·mutation 으로는 화살표가 없다 — 어떤 배선 경로에도 놓여 있지 않기 때문이다.</desc>
<rect x="0" y="0" width="880" height="394" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">패키지별 도달 경로</text>
<rect x="28" y="74.0" width="262" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="159.0" y="108.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">자동설정 · 배치 로더 등록기</text>
<rect x="474" y="76" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="108.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">dataloader</text>
<line x1="296" y1="103.0" x2="468" y2="103.0" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="95.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">registrar 경유</text>
<rect x="458" y="162" width="394" height="210" rx="14" fill="none" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="474" y="186" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">배선 경로 없음 — 화살표 없음</text>
<rect x="474" y="200" width="362" height="50" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="655.0" y="230.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">fetch</text>
<rect x="474" y="258" width="362" height="50" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="655.0" y="288.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">pagination</text>
<rect x="474" y="316" width="362" height="50" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="655.0" y="346.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">mutation</text>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="366" viewBox="0 0 880 366" role="img">
<title>인터셉터 순서</title>
<desc>인증과 예외 처리의 순서가 곧 계약이다. 예외 처리가 인증보다 앞서면 인증 실패가 업무 오류로 보고된다.</desc>
<rect x="0" y="0" width="880" height="366" fill="#ffffff"/>
<text x="28" y="42" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">인터셉터 순서</text>
<defs><marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="h" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<rect x="28" y="74" width="824" height="64" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440" y="111" text-anchor="middle" font-family="system-ui,sans-serif" font-size="15" fill="#111827">인증</text>
<rect x="28" y="164" width="824" height="64" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440" y="201" text-anchor="middle" font-family="system-ui,sans-serif" font-size="15" fill="#111827">업무 처리</text>
<rect x="28" y="254" width="824" height="64" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440" y="291" text-anchor="middle" font-family="system-ui,sans-serif" font-size="15" fill="#111827">예외 변환</text>
<line x1="440" y1="140" x2="440" y2="162" stroke="#374151" stroke-width="1.6" marker-end="url(#a)"/>
<line x1="440" y1="230" x2="440" y2="252" stroke="#374151" stroke-width="1.6" marker-end="url(#a)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="248" viewBox="0 0 880 248" role="img">
<title>타입이 고르는 자동설정</title>
<desc>두 자동설정은 모두 기본 켜짐이지만 활성화를 가르는 것은 프로퍼티가 아니라 애플리케이션 타입이다. 두 아티팩트가 클래스패스에 함께 있어도 한쪽만 활성화된다.</desc>
<rect x="0" y="0" width="880" height="248" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">타입이 고르는 자동설정</text>
<rect x="28" y="109" width="262" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="159.0" y="143.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">웹 애플리케이션 타입</text>
<rect x="474" y="76" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="108.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">MVC 자동설정</text>
<line x1="296" y1="138" x2="468" y2="103" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="70" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">SERVLET</text>
<rect x="474" y="142" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="174.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">WebFlux 자동설정</text>
<line x1="296" y1="138" x2="468" y2="169" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="162" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">REACTIVE</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>신원 모델이 닿는 범위</title>
<desc>security 패키지의 타입들은 서로를 부르지만 패키지 바깥에서 들어오는 프로덕션 호출자가 없다. 교차 테넌트 가드도 그 안에만 있다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">신원 모델이 닿는 범위</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">security 패키지</text>
<rect x="44.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="126.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">WebSecurityContextBridge</text>
<rect x="226.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">AuthenticationView</text>
<rect x="408.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="490.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">rejectTenantInput</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">바깥 프로덕션 호출자 없음</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>매처가 등록되는 순서</title>
<desc>Spring Security 는 먼저 일치한 매처가 이긴다. 공개 경로가 먼저 등록되므로 제한 경로 규칙보다 앞선다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">매처가 등록되는 순서</text>
<rect x="28.0" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="140.7" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">publicPaths permitAll</text>
<rect x="327.3" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">RestrictedPathRule</text>
<rect x="626.7" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="739.3" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">anyRequest authenticated</text>
<line x1="259.3" y1="133" x2="321.3" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="290.3" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">먼저 등록</text>
<line x1="558.7" y1="133" x2="620.7" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="589.7" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">다음 등록</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="344" viewBox="0 0 880 344" role="img">
<title>설정 접두사와 소비자</title>
<desc>두 접두사에서 그것을 읽는 Configuration 으로 화살표가 간다. 세 번째 접두사에는 화살표가 없다 — 그것을 읽어 조립하는 Configuration 이 저장소에 없기 때문이다.</desc>
<rect x="0" y="0" width="880" height="344" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">설정 접두사와 소비자</text>
<rect x="28" y="107.0" width="262" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="159.0" y="141.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">설정 접두사</text>
<rect x="474" y="76" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="108.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">WebSocketConfig</text>
<line x1="296" y1="136.0" x2="468" y2="103.0" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="95.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">ca-skeleton.websocket</text>
<rect x="474" y="142" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="174.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">SockJs · Stomp</text>
<line x1="296" y1="136.0" x2="468" y2="169.0" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="161.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">app.websocket-platform.advanced</text>
<rect x="458" y="228" width="394" height="94" rx="14" fill="none" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="474" y="252" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">읽는 Configuration 없음</text>
<rect x="474" y="266" width="362" height="50" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="655.0" y="296.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">backend.websocket</text>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>조립이 고정된 순서</title>
<desc>설정을 묶고 교차 필드 규칙을 돌린 뒤에야 클라이언트와 연결이 만들어진다. 검증이 bean factory 메서드 안에 있어서 검증되지 않은 설정을 쓰는 bean 이 생기지 않는다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">조립이 고정된 순서</text>
<rect x="28.0" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="140.7" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">설정 바인딩</text>
<rect x="327.3" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">교차 필드 검증</text>
<rect x="626.7" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="739.3" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">클라이언트 · 연결 생성</text>
<line x1="259.3" y1="133" x2="321.3" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="290.3" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">bound settings</text>
<line x1="558.7" y1="133" x2="620.7" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="589.7" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">검증 통과</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="276" viewBox="0 0 880 276" role="img">
<title>부재를 지키는 세 자리</title>
<desc>없는 명령이라는 선언이 API 문서에만 있지 않다. 구현 계층과 명령 정책 파일이 같은 부재를 각각 다시 막는다.</desc>
<rect x="0" y="0" width="880" height="276" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">부재를 지키는 세 자리</text>
<rect x="28" y="70" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="99.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">sdk/api 선언</text>
<rect x="28" y="130" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="159.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">Lettuce 구현 계층</text>
<rect x="28" y="190" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="219.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">redis-command-policy.yml</text>
<line x1="796" y1="118" x2="796" y2="202" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="796" y="62" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">강제 방향</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="276" viewBox="0 0 880 276" role="img">
<title>검사기에 대한 메타 검사</title>
<desc>두 진입점의 대칭을 반사 검사가 강제하고, 그 검사기가 고장 나 항상 통과하는 상태를 잡는 메타 테스트가 위에 하나 더 있다.</desc>
<rect x="0" y="0" width="880" height="276" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">검사기에 대한 메타 검사</text>
<rect x="28" y="70" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="99.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">두 진입점 인터페이스</text>
<rect x="28" y="130" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="159.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">ApiParityTest</text>
<rect x="28" y="190" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="219.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">검사기에 대한 메타 테스트</text>
<line x1="796" y1="118" x2="796" y2="202" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="796" y="62" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">검사 방향</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="248" viewBox="0 0 880 248" role="img">
<title>두 모델이 공유하는 빌더</title>
<desc>동기 표면과 반응형 표면이 같은 request builder 를 만들어 쓴다. 그래서 permit·예산·인코딩·명령 선택의 변경이 한쪽에만 적용될 수 없다.</desc>
<rect x="0" y="0" width="880" height="248" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">두 모델이 공유하는 빌더</text>
<rect x="28" y="109" width="262" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="159.0" y="143.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">ValueOperationRequests</text>
<rect x="474" y="76" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="108.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">동기 표면</text>
<line x1="296" y1="138" x2="468" y2="103" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="70" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">같은 요청 객체</text>
<rect x="474" y="142" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="174.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">반응형 표면</text>
<line x1="296" y1="138" x2="468" y2="169" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="162" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">같은 요청 객체</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,25 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>고정된 검증 순서</title>
<desc>뒤 단계일수록 비싸므로 명백히 부적격한 명령은 인코딩도 전송도 하기 전에 거절된다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">고정된 검증 순서</text>
<rect x="28.0" y="104" width="105.6" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="80.8" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">capability</text>
<rect x="207.6" y="104" width="105.6" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="260.4" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">risk · permit</text>
<rect x="387.2" y="104" width="105.6" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440.0" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">namespace</text>
<rect x="566.8" y="104" width="105.6" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="619.6" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">slot</text>
<rect x="746.4" y="104" width="105.6" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="799.2" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">request budget</text>
<line x1="139.6" y1="133" x2="201.6" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="170.6" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">버전 대조</text>
<line x1="319.2" y1="133" x2="381.2" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="350.2" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">위험 등급</text>
<line x1="498.8" y1="133" x2="560.8" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="529.8" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">키 소유</text>
<line x1="678.4" y1="133" x2="740.4" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="709.4" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">단일 슬롯</text>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>원시 명령이 지나야 하는 두 문</title>
<desc>조직이 정한 카탈로그 분류와 배포가 등록한 승인 둘 다를 통과해야 한다. 어느 쪽도 요청 시점에 결정되지 않는다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">원시 명령이 지나야 하는 두 문</text>
<rect x="28.0" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="140.7" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">정책 카탈로그 RAW_ONLY</text>
<rect x="327.3" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">ApprovedRawCommand 등록</text>
<rect x="626.7" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="739.3" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">RedisRawGateway</text>
<line x1="259.3" y1="133" x2="321.3" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="290.3" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">조직의 결정</text>
<line x1="558.7" y1="133" x2="620.7" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="589.7" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">배포의 결정</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>등록과 실행의 분리</title>
<desc>등록되지 않은 스크립트는 digest 가 없어서 서버에 닿을 방법이 없다. 그래서 검토된 것만 실행된다는 성질이 관례가 아니라 구조가 된다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">등록과 실행의 분리</text>
<rect x="28.0" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="140.7" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">배포 시 스크립트 등록</text>
<rect x="327.3" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">digest 대조</text>
<rect x="626.7" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="739.3" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">EVALSHA 실행</text>
<line x1="259.3" y1="133" x2="321.3" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="290.3" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">등록본 저장</text>
<line x1="558.7" y1="133" x2="620.7" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="589.7" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">본문 일치</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="244" viewBox="0 0 880 244" role="img">
<title>두 종착 상태</title>
<desc>비terminal 상태에서는 정상 종료로 가거나 격리로 이탈할 수 있고, 두 종착 상태에서 나가는 전이는 없다.</desc>
<rect x="0" y="0" width="880" height="244" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">두 종착 상태</text>
<rect x="28.0" y="120" width="210.7" height="56" rx="26" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="133.3" y="153.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">비terminal 상태</text>
<rect x="334.7" y="120" width="210.7" height="56" rx="26" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440" y="153.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">PUBLISHED</text>
<rect x="641.3" y="120" width="210.7" height="56" rx="26" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="746.7" y="153.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">QUARANTINED</text>
<line x1="244.7" y1="148" x2="328.7" y2="148" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="286.7" y="138" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">정상 종료</text>
<path d="M133.3,178 C133.3,232 746.7,232 746.7,178" fill="none" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4" marker-end="url(#ar)"/>
<text x="440.0" y="228" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">격리로 이탈</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>선언된 것과 선언되지 않은 것</title>
<desc>이 계층은 자기가 막는 것과 막지 못하는 것을 함께 적는다. 잔여 경로 연산은 문서에 선언되고 identity 검사로 감싸인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">선언된 것과 선언되지 않은 것</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">LocalPersistentPayloadOperations</text>
<rect x="44.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="126.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">fileKey 재확인</text>
<rect x="226.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">소유자 · 권한 재확인</text>
<rect x="408.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="490.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">FileStore 재확인</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">서술자 상대 대응물 없음</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>재시도 결정의 순서</title>
<desc>싼 절대 차단이 먼저 오고 그다음 모호성, 그다음 상태별 규칙이 온다. 뒤 규칙이 앞 규칙이 금지한 것을 다시 허용할 수 없다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">재시도 결정의 순서</text>
<rect x="28.0" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="103.2" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">절대 차단 여섯</text>
<rect x="252.5" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="327.8" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">영구 실패 범주</text>
<rect x="477.0" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="552.2" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">증거</text>
<rect x="701.5" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="776.8" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">상태 · 실패별 규칙</text>
<line x1="184.5" y1="133" x2="246.5" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="215.5" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">통과</text>
<line x1="409.0" y1="133" x2="471.0" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="440.0" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">통과</text>
<line x1="633.5" y1="133" x2="695.5" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="664.5" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">통과</text>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>시도마다 지나는 가드 순서</title>
<desc>열린 회로가 요금 토큰이나 벌크헤드 permit 을 쓰기 전에 먼저 거절한다. 해제는 역순이다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">시도마다 지나는 가드 순서</text>
<rect x="28.0" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="103.2" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">Circuit Breaker</text>
<rect x="252.5" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="327.8" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">Rate Limiter</text>
<rect x="477.0" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="552.2" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">Bulkhead</text>
<rect x="701.5" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="776.8" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">HTTP 호출</text>
<line x1="184.5" y1="133" x2="246.5" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="215.5" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">허가</text>
<line x1="409.0" y1="133" x2="471.0" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="440.0" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">토큰</text>
<line x1="633.5" y1="133" x2="695.5" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="664.5" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">permit</text>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="336" viewBox="0 0 880 336" role="img">
<title>응답 크기 예산이 강제되는 자리</title>
<desc>와이어 바이트 예산, 읽는 도중의 상한 강제, 디코드 바이트 예산, 오류 본문 제한 읽기가 읽는 순서대로 쌓여 있고 오른쪽에 읽는 방향 화살표가 있다.</desc>
<rect x="0" y="0" width="880" height="336" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">응답 크기 예산이 강제되는 자리</text>
<rect x="28" y="70" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="99.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">와이어 바이트 예산</text>
<rect x="28" y="130" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="159.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">읽는 도중 상한 강제</text>
<rect x="28" y="190" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="219.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">디코드 바이트 예산</text>
<rect x="28" y="250" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="279.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">오류 본문 제한 읽기</text>
<line x1="796" y1="118" x2="796" y2="262" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="796" y="62" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">읽는 순서</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,19 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>레지스트리가 닫힌 방식</title>
<desc>LocalJsonSchemaRegistry 안에 넘겨받은 바이트, 동봉된 메타스키마, 허용 어휘가 놓이고 바깥에 원격 참조 로더와 동적 키워드가 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">레지스트리가 닫힌 방식</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">LocalJsonSchemaRegistry</text>
<rect x="44.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="126.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">넘겨받은 바이트</text>
<rect x="226.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">동봉된 메타스키마</text>
<rect x="408.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="490.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">허용 어휘</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">원격 참조 로더</text>
<rect x="624" y="166" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="198.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">동적 · 앵커 키워드</text>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="302" viewBox="0 0 880 302" role="img">
<title>이름 없던 상태에 이름 붙이기</title>
<desc>세 자리에서 이전에는 구분되지 않던 두 상황이 각각 이름을 얻었다. 왼쪽은 이름이 없던 상태이고 오른쪽은 지금의 표현이다.</desc>
<rect x="0" y="0" width="880" height="302" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">이름 없던 상태에 이름 붙이기</text>
<text x="28" y="82" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">이전</text>
<text x="468" y="82" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">지금</text>
<rect x="28" y="96" width="380" height="50" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="218.0" y="126.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">공급자 0인 플랫폼</text>
<rect x="468" y="96" width="384" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="660.0" y="126.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">INGEST_ONLY 명시 선택</text>
<rect x="28" y="158" width="380" height="50" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="218.0" y="188.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">자유 문자열 타입</text>
<rect x="468" y="158" width="384" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="660.0" y="188.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">닫힌 ProviderType enum</text>
<rect x="28" y="220" width="380" height="50" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="218.0" y="250.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">여덟 키를 항상 요구</text>
<rect x="468" y="220" width="384" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="660.0" y="250.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">네 키 + 능력별 키</text>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>컴파일과 생성의 순서</title>
<desc>설정 컴파일이 전부 끝난 뒤에야 provider 가 디렉터리·클라이언트·스레드·스케줄러·자격 조회를 만든다. 생성 도중 실패하면 이미 만든 것을 역순으로 닫는다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">컴파일과 생성의 순서</text>
<rect x="28.0" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="140.7" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">compiler.compile(settings)</text>
<rect x="327.3" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">contribution.create(provider)</text>
<rect x="626.7" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="739.3" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">AssembledCapability</text>
<line x1="259.3" y1="133" x2="321.3" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="290.3" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">검증된 바인딩</text>
<line x1="558.7" y1="133" x2="620.7" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="589.7" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">수명주기 소유권</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,22 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="380" viewBox="0 0 880 380" role="img">
<title>어디서든 들어가고 나올 수 없는 분기</title>
<desc>정상 사슬의 어느 단계에서도 분기 전이로 빠질 수 있고, 그 네 상태에서 나오는 전이는 없다.</desc>
<rect x="0" y="0" width="880" height="380" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">어디서든 들어가고 나올 수 없는 분기</text>
<rect x="28" y="175" width="262" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="159.0" y="209.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">정상 사슬의 어느 단계</text>
<rect x="474" y="76" width="378" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="663.0" y="108.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">EXPIRED</text>
<line x1="296" y1="204" x2="468" y2="103" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="70" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">분기 전이</text>
<rect x="474" y="142" width="378" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="663.0" y="174.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">ABORTED</text>
<line x1="296" y1="204" x2="468" y2="169" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<rect x="474" y="208" width="378" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="663.0" y="240.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">FAILED</text>
<line x1="296" y1="204" x2="468" y2="235" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<rect x="474" y="274" width="378" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="663.0" y="306.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">CORRUPT</text>
<line x1="296" y1="204" x2="468" y2="301" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="276" viewBox="0 0 880 276" role="img">
<title>보고 가능한 계약이 만들어지는 층</title>
<desc>능력 이름은 어휘일 뿐이고 지원 등급은 별도 타입이 붙이며 실제 보고는 조립이 구성한다. 코드가 classpath 에 있다는 것과 기본 지원한다는 것을 같은 말로 두지 않는다.</desc>
<rect x="0" y="0" width="880" height="276" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">보고 가능한 계약이 만들어지는 층</text>
<rect x="28" y="70" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="99.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">JpaCapability — 어휘</text>
<rect x="28" y="130" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="159.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">CapabilitySupport — 등급 결합</text>
<rect x="28" y="190" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="219.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">app-bootstrap composition — 실제 보고</text>
<line x1="796" y1="118" x2="796" y2="202" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="796" y="62" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">보고 구성</text>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -0,0 +1,19 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>질의 API가 표현하지 않는 것</title>
<desc>keyset 질의 API 안에 정렬 키와 size 더하기 1과 서명된 커서가 놓이고 바깥에 offset과 total count 질의가 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">질의 API가 표현하지 않는 것</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">keyset 질의 API</text>
<rect x="44.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="126.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">KeysetTerm 정렬 키</text>
<rect x="226.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">요청 size + 1</text>
<rect x="408.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="490.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">서명된 nextCursor</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">offset · page number</text>
<rect x="624" y="166" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="198.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">total count 질의</text>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

@@ -0,0 +1,19 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="210" viewBox="0 0 880 210" role="img">
<title>encode와 decode의 허용 범위</title>
<desc>상한 크기의 payload가 base64url 인코드를 지나 크기 사전 추정 단계에서 decode 쪽 거부로 이어지는 경로.</desc>
<rect x="0" y="0" width="880" height="210" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">encode와 decode의 허용 범위</text>
<rect x="28.0" y="96" width="162.5" height="58" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6"/>
<text x="109.2" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">상한 크기의 payload</text>
<rect x="248.5" y="96" width="162.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="329.8" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">base64url 인코드</text>
<line x1="196.5" y1="125" x2="242.5" y2="125" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<rect x="469.0" y="96" width="162.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="550.2" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">크기 사전 추정</text>
<line x1="417.0" y1="125" x2="463.0" y2="125" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<rect x="689.5" y="96" width="162.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="770.8" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">decode 쪽 거부</text>
<line x1="637.5" y1="125" x2="683.5" y2="125" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="440.0" y="186" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">padding 가정</text>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>allowlist 에 들어갈 수 있는 범주</title>
<desc>설정으로 재시도 가능하게 만들 수 있는 범주가 타입에서 좁혀져 있다. 완료 불명은 생성자가 거부한다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">allowlist 에 들어갈 수 있는 범주</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">RetryProfile 의 retryable allowlist</text>
<rect x="44.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="126.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">serialization failure</text>
<rect x="226.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">optimistic conflict</text>
<rect x="408.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="490.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">lock not available</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">COMPLETION_UNKNOWN</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="276" viewBox="0 0 880 276" role="img">
<title>질의 계층의 세 단계</title>
<desc>응용 계층이 소유한 질의 계약이 아래로 위임되고, 각 단계가 서로 다른 정책을 맡는다. 범용 CRUD 저장소를 대체하는 층이 아니다.</desc>
<rect x="0" y="0" width="880" height="276" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">질의 계층의 세 단계</text>
<rect x="28" y="70" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="99.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">application-owned query contract</text>
<rect x="28" y="130" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="159.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">springdata/**</text>
<rect x="28" y="190" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="219.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">hibernate/**</text>
<line x1="796" y1="118" x2="796" y2="202" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="796" y="62" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">위임 방향</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="240" viewBox="0 0 880 240" role="img">
<title>선언 기준과 런타임 판본의 분리</title>
<desc>왼쪽에 정책 상수 baseline과 문서가 선언한 판본이, 오른쪽에 org.hibernate.Version 조회와 BOM이 해석한 판본이 같은 축에 놓인다.</desc>
<rect x="0" y="0" width="880" height="240" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">선언 기준과 런타임 판본의 분리</text>
<text x="28" y="82" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">선언 기준</text>
<text x="468" y="82" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">실제 런타임</text>
<rect x="28" y="96" width="380" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="218.0" y="126.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">정책 상수 baseline</text>
<rect x="468" y="96" width="384" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="660.0" y="126.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">org.hibernate.Version</text>
<rect x="28" y="158" width="380" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="218.0" y="188.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">문서가 선언한 판본</text>
<rect x="468" y="158" width="384" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="660.0" y="188.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">BOM이 해석한 판본</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="314" viewBox="0 0 880 314" role="img">
<title>쓰기 경로마다 다른 소유 모델</title>
<desc>세 경로가 트랜잭션 소유와 엔티티 수명주기를 서로 다르게 다룬다. 같은 저장소 호출처럼 보여도 감사와 수명주기 보장이 같지 않다.</desc>
<rect x="0" y="0" width="880" height="314" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">쓰기 경로마다 다른 소유 모델</text>
<rect x="28" y="142" width="262" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="159.0" y="176.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">쓰기 경로</text>
<rect x="474" y="76" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="108.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">일반 repository adapter</text>
<line x1="296" y1="171" x2="468" y2="103" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="70" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">경계에 참여</text>
<rect x="474" y="142" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="174.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">bulk DML</text>
<line x1="296" y1="171" x2="468" y2="169" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="162" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">엔티티 수명주기 우회</text>
<rect x="474" y="208" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="240.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">StatelessSession runner</text>
<line x1="296" y1="171" x2="468" y2="235" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="228" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">경계를 스스로 소유</text>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="248" viewBox="0 0 880 248" role="img">
<title>같은 row 를 읽는 두 경로</title>
<desc>만료된 COMPLETED row 를 두 진입점이 서로 다르게 해석한다. 한쪽은 이전 응답을 재생하라 하고 다른 쪽은 새 실행을 소유할 수 있다고 답한다.</desc>
<rect x="0" y="0" width="880" height="248" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">같은 row 를 읽는 두 경로</text>
<rect x="28" y="109" width="262" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="159.0" y="143.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">만료된 COMPLETED row</text>
<rect x="474" y="76" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="108.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">inspect</text>
<line x1="296" y1="138" x2="468" y2="103" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="70" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">COMPLETED_REPLAY</text>
<rect x="474" y="142" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="174.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">claim</text>
<line x1="296" y1="138" x2="468" y2="169" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="162" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">TakenOverClaimed</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>narrow scan 이 닿는 범위</title>
<desc>어댑터 전체를 넓게 스캔하지 않고 여섯 package 만 명시적으로 스캔한다. 같은 리프 안에 있어도 스캔 밖이면 도달하지 않는다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">narrow scan 이 닿는 범위</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">JpaAdapterComponentsConfig</text>
<rect x="44.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="171.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">audit · failure · idempotency</text>
<rect x="317.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="444.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">lock · outbox · transaction</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">DurableOperationStoreAdapter</text>
<rect x="624" y="166" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="198.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">JpaLiveEventReplayAdapter</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="248" viewBox="0 0 880 248" role="img">
<title>Stable 스캔 목록에 들어 있는 것</title>
<desc>Stable persistence unit 의 스캔 문자열 목록에 experimental package 가 이미 들어 있다. 지금은 걸릴 타입이 없지만 별도 조건이 붙어 있지도 않다.</desc>
<rect x="0" y="0" width="880" height="248" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">Stable 스캔 목록에 들어 있는 것</text>
<rect x="28" y="109" width="262" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="159.0" y="143.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">Stable @EntityScan 목록</text>
<rect x="474" y="76" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="108.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">stable package 목록</text>
<line x1="296" y1="138" x2="468" y2="103" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="70" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">조건 있음</text>
<rect x="474" y="142" width="378" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="663.0" y="174.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">experimental package</text>
<line x1="296" y1="138" x2="468" y2="169" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="162" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">조건 없음</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>두 스캔을 가르는 선</title>
<desc>항상 설치되는 스캔은 package 를 열거하고, 옵트인 두 개는 각자의 조건부 Configuration 이 자기 package 만 스캔한다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">두 스캔을 가르는 선</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">PersistenceJpaConfig</text>
<rect x="44.0" y="100" width="528.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">열거된 스무 개 package</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">notification — 옵트인</text>
<rect x="624" y="166" width="228" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="198.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">fileserver — 옵트인</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="336" viewBox="0 0 880 336" role="img">
<title>옵트인을 이루는 네 겹</title>
<desc>네 겹이 같은 스위치를 읽지만 각각 다른 실패를 막는다. 첫 겹은 Boot 의 후보군에서, 나머지는 자기 bean 그래프에서 막는다.</desc>
<rect x="0" y="0" width="880" height="336" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">옵트인을 이루는 네 겹</text>
<rect x="28" y="70" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="99.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">MongoOptInAutoConfigurationImportFilter</text>
<rect x="28" y="130" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="159.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">MongoRootAutoConfiguration</text>
<rect x="28" y="190" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="219.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">MongoPersistenceConfig</text>
<rect x="28" y="250" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="279.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">MongoPlatformAutoConfiguration</text>
<line x1="796" y1="118" x2="796" y2="262" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="796" y="62" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">같은 스위치</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>실행 scope 의 고정된 순서</title>
<desc>이 순서를 한 곳에 고정했기 때문에 아직 쓰이지 않은 연산에도 같은 불변식이 성립한다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">실행 scope 의 고정된 순서</text>
<rect x="28.0" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="103.2" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">profile 해석</text>
<rect x="252.5" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="327.8" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">observation 개시</text>
<rect x="477.0" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="552.2" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">consistency 바인딩</text>
<rect x="701.5" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="776.8" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">callback 실행</text>
<line x1="184.5" y1="133" x2="246.5" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="215.5" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">물리 이름</text>
<line x1="409.0" y1="133" x2="471.0" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="440.0" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">관측 범위</text>
<line x1="633.5" y1="133" x2="695.5" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="664.5" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">파생 template</text>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>반응형 경로가 직접 배치한 것</title>
<desc>블로킹 경로가 공짜로 얻는 것을 반응형 경로에서는 직접 배치해야 한다. 취소·마감·컨텍스트 전파 셋이 그 자리다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">반응형 경로가 직접 배치한 것</text>
<rect x="28" y="66" width="824" height="100" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">DefaultReactiveMongoExecutor</text>
<rect x="44.0" y="100" width="252.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="170.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">Mono.using 관측 범위</text>
<rect x="314.0" y="100" width="252.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">조립 후 timeout</text>
<rect x="584.0" y="100" width="252.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="710.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">Reactor Context 이동</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>이 리프의 프로덕션 표면</title>
<desc>공유 보조 seam 하나에 타입이 셋뿐이다. 상관 식별자 조회와 fail-open 관측 기록, 그리고 그 기본 bean 을 주는 설정이다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">이 리프의 프로덕션 표면</text>
<rect x="28" y="66" width="824" height="100" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">adapter-outbound-support</text>
<rect x="44.0" y="100" width="252.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="170.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">OutboundCorrelation</text>
<rect x="314.0" y="100" width="252.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">FailOpenDependencyLogger</text>
<rect x="584.0" y="100" width="252.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="710.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">OutboundSupportConfig</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="248" viewBox="0 0 880 248" role="img">
<title>판정과 기록의 갈림</title>
<desc>fail-open 여부를 정하는 것은 호출 지점이고 로거는 이미 정해진 결과를 관측만 한다. 로거에서 업무 경로로 되돌아오는 화살표가 없다.</desc>
<rect x="0" y="0" width="880" height="248" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">판정과 기록의 갈림</text>
<rect x="28" y="109" width="262" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="159.0" y="143.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">fail-open 판정</text>
<rect x="474" y="76" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="108.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">use case 결과</text>
<line x1="296" y1="138" x2="468" y2="103" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="70" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">호출자에게 반환</text>
<rect x="474" y="142" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="174.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">FailOpenDependencyLogger</text>
<line x1="296" y1="138" x2="468" y2="169" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="162" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">관측만</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="276" viewBox="0 0 880 276" role="img">
<title>의존이 흐르는 한 방향</title>
<desc>어댑터가 application-core 의 포트를 구현하고 application-core 는 shared-contract 하나만 의존한다. 반대 방향 의존이 없다.</desc>
<rect x="0" y="0" width="880" height="276" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">의존이 흐르는 한 방향</text>
<rect x="28" y="70" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="99.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">adapter — port 구현</text>
<rect x="28" y="130" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="159.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">application-core — port 선언</text>
<rect x="28" y="190" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="219.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">:shared-contract</text>
<line x1="796" y1="118" x2="796" y2="202" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="796" y="62" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">의존 방향</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="248" viewBox="0 0 880 248" role="img">
<title>두 판정이 갈리는 자리</title>
<desc>같은 요청에 대해 작업 종류를 묻는 판정과 개별 객체 접근을 묻는 판정이 서로 다른 포트로 나뉜다. 권한이 같아도 객체 판정 결과는 달라질 수 있다.</desc>
<rect x="0" y="0" width="880" height="248" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">두 판정이 갈리는 자리</text>
<rect x="28" y="109" width="262" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="159.0" y="143.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">요청</text>
<rect x="474" y="76" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="108.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">AuthorizationPort</text>
<line x1="296" y1="138" x2="468" y2="103" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="70" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">작업 종류</text>
<rect x="474" y="142" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="174.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">ObjectAccessPolicy</text>
<line x1="296" y1="138" x2="468" y2="169" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="162" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">개별 객체</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>노출하는 어휘와 감추는 어휘</title>
<desc>정책 식별자와 결과 대수가 응용 계층의 어휘로 노출되고 프레임워크의 전파 숫자는 경계 밖에 남는다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">노출하는 어휘와 감추는 어휘</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">application-core</text>
<rect x="44.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="171.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">TransactionPolicyId</text>
<rect x="317.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="444.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">TransactionResult</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">Spring propagation 숫자</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="314" viewBox="0 0 880 314" role="img">
<title>응답을 잃은 구간을 맡는 세 장치</title>
<desc>효과가 이미 일어났을 수 있는데 응답만 잃은 구간을 셋이 나눠 맡는다. 어느 쪽도 불확실을 성공이나 실패로 접지 않는다.</desc>
<rect x="0" y="0" width="880" height="314" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">응답을 잃은 구간을 맡는 세 장치</text>
<rect x="28" y="142" width="262" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="159.0" y="176.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">응답을 잃은 구간</text>
<rect x="474" y="76" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="108.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">idempotency V2</text>
<line x1="296" y1="171" x2="468" y2="103" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="70" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">owner-safe CAS</text>
<rect x="474" y="142" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="174.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">inbox</text>
<line x1="296" y1="171" x2="468" y2="169" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="162" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">owner-safe 수신 상태</text>
<rect x="474" y="208" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="240.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">outbox</text>
<line x1="296" y1="171" x2="468" y2="235" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="228" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">at-least-once 발행</text>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

@@ -0,0 +1,19 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>공개 계약과 비밀이 나뉘는 자리</title>
<desc>공개 알림 계약 안에 sealed 변수 대수와 고정된 템플릿 판본과 유계 수신자 수가 놓이고 바깥에 임의 Object 변수와 연락처 원문이 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">공개 계약과 비밀이 나뉘는 자리</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">공개 알림 계약</text>
<rect x="44.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="126.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">sealed 변수 대수</text>
<rect x="226.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">고정된 템플릿 판본</text>
<rect x="408.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="490.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">유계 수신자 수</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">임의 Object 변수</text>
<rect x="624" y="166" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="198.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">연락처 원문</text>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>승인이 실행에 닿기까지</title>
<desc>승인 발급 상자에서 가드 검증 상자로 승인 문서가 건너가고, 가드 검증에서 실행 상자로 VerifiedApproval 이 건너간다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">승인이 실행에 닿기까지</text>
<rect x="28.0" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="140.7" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">승인 발급</text>
<rect x="327.3" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">가드 검증</text>
<rect x="626.7" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="739.3" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">파괴적 실행</text>
<line x1="259.3" y1="133" x2="321.3" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="290.3" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">승인 문서</text>
<line x1="558.7" y1="133" x2="620.7" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="589.7" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">VerifiedApproval</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="240" viewBox="0 0 880 240" role="img">
<title>두 오버로드를 가르는 표시</title>
<desc>왼쪽에 무제한 오버로드와 그것을 구분하는 표시 없음이, 오른쪽에 배치 제한 오버로드와 javadoc 근거가 같은 축에 놓인다. 왼쪽 아래 칸만 빗금이다.</desc>
<rect x="0" y="0" width="880" height="240" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">두 오버로드를 가르는 표시</text>
<text x="28" y="82" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">무제한 형태</text>
<text x="468" y="82" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">배치 제한 형태</text>
<rect x="28" y="96" width="380" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="218.0" y="126.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">purge*Before(Instant)</text>
<rect x="468" y="96" width="384" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="660.0" y="126.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">purge*Before(Instant, int)</text>
<rect x="28" y="158" width="380" height="50" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="218.0" y="188.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">가르는 표시 없음</text>
<rect x="468" y="158" width="384" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="660.0" y="188.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">javadoc 이 적은 근거</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>적용과 사용 승인이 갈리는 자리</title>
<desc>선행조건 검사 상자에서 테이블 생성 상자로 core epoch 확인이 건너가고, 테이블 생성에서 레지스트리 등록으로 INSTALLED_INACTIVE 가 건너간다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">적용과 사용 승인이 갈리는 자리</text>
<rect x="28.0" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="140.7" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">선행조건 검사</text>
<rect x="327.3" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">테이블 생성</text>
<rect x="626.7" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="739.3" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">레지스트리 등록</text>
<line x1="259.3" y1="133" x2="321.3" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="290.3" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">core epoch 확인</text>
<line x1="558.7" y1="133" x2="620.7" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="589.7" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">INSTALLED_INACTIVE</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>값 타입 생성자가 막는 것</title>
<desc>값 타입 생성자 안에 등록된 이름과 정규식 통과 값이 놓이고 바깥에 엔티티 id 와 SQL 조각이 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">값 타입 생성자가 막는 것</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">값 타입 생성자</text>
<rect x="44.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="171.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">등록된 이름</text>
<rect x="317.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="444.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">정규식 통과 값</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">엔티티 id · tenant id</text>
<rect x="624" y="166" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="198.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">SQL 조각 · 요청 값</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="248" viewBox="0 0 880 248" role="img">
<title>판정이 되는 갱신 행 수</title>
<desc>조건부 UPDATE 상자에서 두 갈래가 나온다. 위쪽은 한 행 갱신이고 아래쪽은 영 행 갱신이다.</desc>
<rect x="0" y="0" width="880" height="248" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">판정이 되는 갱신 행 수</text>
<rect x="28" y="109" width="262" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="159.0" y="143.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">소유권 튜플 조건부 UPDATE</text>
<rect x="474" y="76" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="108.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">여전히 이 owner</text>
<line x1="296" y1="138" x2="468" y2="103" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="70" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">1행</text>
<rect x="474" y="142" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="174.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">다른 소유자로 이동</text>
<line x1="296" y1="138" x2="468" y2="169" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="162" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">0행</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@@ -0,0 +1,18 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="314" viewBox="0 0 880 314" role="img">
<title>같은 문제의 세 형태</title>
<desc>같은 갱신 문제 상자에서 세 갈래가 나온다. 비교 후 교체 루프와 synchronized 는 실선이고 검사 후 실행만 빗금이다.</desc>
<rect x="0" y="0" width="880" height="314" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">같은 문제의 세 형태</text>
<rect x="28" y="142" width="262" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="159.0" y="176.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">같은 갱신 문제</text>
<rect x="474" y="76" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="108.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">비교 후 교체 루프</text>
<line x1="296" y1="171" x2="468" y2="103" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<rect x="474" y="142" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="174.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">synchronized</text>
<line x1="296" y1="171" x2="468" y2="169" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<rect x="474" y="208" width="378" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="663.0" y="240.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">검사 후 실행</text>
<line x1="296" y1="171" x2="468" y2="235" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="314" viewBox="0 0 880 314" role="img">
<title>COMMITTING 에서만 갈리는 세 결과</title>
<desc>COMMITTING 상자에서 세 갈래가 나온다. 커밋 확인과 롤백 확인과 응답 없음이다.</desc>
<rect x="0" y="0" width="880" height="314" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">COMMITTING 에서만 갈리는 세 결과</text>
<rect x="28" y="142" width="262" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="159.0" y="176.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">COMMITTING</text>
<rect x="474" y="76" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="108.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">COMMITTED</text>
<line x1="296" y1="171" x2="468" y2="103" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="70" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">커밋 확인</text>
<rect x="474" y="142" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="174.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">ROLLED_BACK</text>
<line x1="296" y1="171" x2="468" y2="169" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="162" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">롤백 확인</text>
<rect x="474" y="208" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="240.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">UNKNOWN</text>
<line x1="296" y1="171" x2="468" y2="235" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="228" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">응답 없음</text>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="276" viewBox="0 0 880 276" role="img">
<title>마감이 좁혀지는 세 단계</title>
<desc>호출 예산과 트랜잭션 마감과 데이터베이스 로컬 타임아웃이 위에서 아래로 쌓여 있고 오른쪽에 좁아지는 방향 화살표가 있다.</desc>
<rect x="0" y="0" width="880" height="276" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">마감이 좁혀지는 세 단계</text>
<rect x="28" y="70" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="99.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">호출 예산</text>
<rect x="28" y="130" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="159.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">트랜잭션 마감</text>
<rect x="28" y="190" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="219.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">DB 로컬 타임아웃</text>
<line x1="796" y1="118" x2="796" y2="202" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="796" y="62" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">좁아짐</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>이 모듈이 실제로 소유한 것</title>
<desc>재사용 가능한 도메인 내용이 아니라 도메인 모델링 계약을 소유한다. 실제 샘플 aggregate 는 다른 모듈에 있다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">이 모듈이 실제로 소유한 것</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">domain-core</text>
<rect x="44.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="171.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">ResourceId · IdFactory</text>
<rect x="317.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="444.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">모델링 표식 애너테이션</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">sample-portfolio 의 aggregate</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="240" viewBox="0 0 880 240" role="img">
<title>R1과 R2를 가르는 것</title>
<desc>왼쪽에 내용 검증 통과와 보존된 readinessBlockers 가, 오른쪽에 clean revision 과 prerequisite DAG 가 같은 축에 놓인다. 왼쪽 아래 칸만 빗금이다.</desc>
<rect x="0" y="0" width="880" height="240" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">R1과 R2를 가르는 것</text>
<text x="28" y="82" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">R1</text>
<text x="468" y="82" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">R2</text>
<rect x="28" y="96" width="380" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="218.0" y="126.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">내용 검증 통과</text>
<rect x="468" y="96" width="384" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="660.0" y="126.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">clean revision · CI provenance</text>
<rect x="28" y="158" width="380" height="50" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="218.0" y="188.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">readinessBlockers 보존</text>
<rect x="468" y="158" width="384" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="660.0" y="188.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">prerequisite DAG</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>공개 읽기가 가능한 상태</title>
<desc>공개 읽기 가능 경계 안에 READY 한 상태만 놓이고 바깥에 업로드 중과 검증 중, 실패와 삭제 대기가 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">공개 읽기가 가능한 상태</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">관계형 레코드의 판정</text>
<rect x="44.0" y="100" width="528.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">READY</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">업로드 중 · 검증 중</text>
<rect x="624" y="166" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="198.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">실패 · 삭제 대기</text>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="336" viewBox="0 0 880 336" role="img">
<title>공시 등급의 네 단계</title>
<desc>modelled 와 wired 와 integration-verified 와 production-verified 가 위에서 아래로 쌓여 있고 오른쪽에 등급 상승 방향 화살표가 있다.</desc>
<rect x="0" y="0" width="880" height="336" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">공시 등급의 네 단계</text>
<rect x="28" y="70" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="99.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">modelled</text>
<rect x="28" y="130" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="159.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">wired</text>
<rect x="28" y="190" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="219.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">integration-verified</text>
<rect x="28" y="250" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="279.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">production-verified</text>
<line x1="796" y1="118" x2="796" y2="262" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="796" y="62" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">등급 상승</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="336" viewBox="0 0 880 336" role="img">
<title>격리 경계가 놓이는 층</title>
<desc>database-per-tenant 와 schema-per-tenant 와 RLS 행 수준과 discriminator column 이 위에서 아래로 쌓여 있고 오른쪽에 격리가 얕아지는 방향 화살표가 있다.</desc>
<rect x="0" y="0" width="880" height="336" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">격리 경계가 놓이는 층</text>
<rect x="28" y="70" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="99.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">database-per-tenant</text>
<rect x="28" y="130" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="159.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">schema-per-tenant</text>
<rect x="28" y="190" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="219.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">RLS · 행 수준</text>
<rect x="28" y="250" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="279.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">discriminator column</text>
<line x1="796" y1="118" x2="796" y2="262" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="796" y="62" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">격리 얕아짐</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="336" viewBox="0 0 880 336" role="img">
<title>전역 상태 판정 우선순위</title>
<desc>임계 의존 불건강과 하나라도 NOT_SERVING 과 하나라도 SERVING 과 그 밖이 위에서 아래로 쌓여 있고 오른쪽에 판정 순서 화살표가 있다.</desc>
<rect x="0" y="0" width="880" height="336" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">전역 상태 판정 우선순위</text>
<rect x="28" y="70" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="99.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">임계 의존 불건강 → NOT_SERVING</text>
<rect x="28" y="130" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="159.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">하나라도 NOT_SERVING</text>
<rect x="28" y="190" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="219.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">하나라도 SERVING</text>
<rect x="28" y="250" width="700" height="48" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="378.0" y="279.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">그 밖 → UNKNOWN</text>
<line x1="796" y1="118" x2="796" y2="262" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="796" y="62" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">판정 순서</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>승인 제어기에 없는 것</title>
<desc>tryAdmit 과 inFlightAdmitted 가 승인 제어기 공개 표면 안에 놓이고 승인 중단 메서드가 바깥에 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">승인 제어기에 없는 것</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">GrpcAdmissionController 표면</text>
<rect x="44.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="171.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">tryAdmit</text>
<rect x="317.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="444.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">inFlightAdmitted</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">stopAdmitting · refuseNew</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>게이트가 보는 세 조건</title>
<desc>세 조건을 하나의 boolean 으로 접으면 처방이 서로 다른 세 상황이 같은 메시지를 받는다. 그래서 순서대로 따로 본다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">게이트가 보는 세 조건</text>
<rect x="28.0" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="140.7" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">깃발 설정 여부</text>
<rect x="327.3" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">등급의 시작 가능 여부</text>
<rect x="626.7" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="739.3" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">운영 별도 승인</text>
<line x1="259.3" y1="133" x2="321.3" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="290.3" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">설정됨</text>
<line x1="558.7" y1="133" x2="620.7" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="589.7" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">시작 가능</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>이 리프가 담는 것</title>
<desc>진단 표면과 그것을 게시 가능하게 만드는 편집기, 그리고 고급 능력의 검증 대상을 이름 짓는 테스트킷 계약이 한 리프에 있다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">이 리프가 담는 것</text>
<rect x="28" y="66" width="824" height="100" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">grpc-advanced-diagnostics</text>
<rect x="44.0" y="100" width="252.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="170.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">Channelz · CSDS 표면</text>
<rect x="314.0" y="100" width="252.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">진단 편집기</text>
<rect x="584.0" y="100" width="252.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="710.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">테스트킷 계약</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>열람을 여는 조건</title>
<desc>망 게이트와 역할 게이트가 둘 다 있어야 진단 열람이 열린다. CSDS 는 그 위에 xDS 사용 여부라는 조건이 하나 더 붙는다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">열람을 여는 조건</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">GrpcChannelDiagnosticsPolicy</text>
<rect x="44.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="171.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">네트워크 게이트</text>
<rect x="317.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="444.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">역할 게이트</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">CSDS — xDS 사용 시에만</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>마스킹이 아는 형태</title>
<desc>IPv4 점 십진만 마스킹이 아는 형태 안에 놓이고 IPv6 주소와 호스트 이름 및 unix 경로가 바깥에 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">마스킹이 아는 형태</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">마스킹 대상</text>
<rect x="44.0" y="100" width="528.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">IPv4 점 십진</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">IPv6 주소</text>
<rect x="624" y="166" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="198.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">호스트 이름 · unix 경로</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>비교에 필요한 것</title>
<desc>edition 픽스처만 저장소 안에 놓이고 proto3 짝 픽스처와 컴파일 산출물이 바깥에 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">비교에 필요한 것</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">저장소에 있는 것</text>
<rect x="44.0" y="100" width="528.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">edition 픽스처</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">proto3 짝 픽스처</text>
<rect x="624" y="166" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="198.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">protobuf 컴파일 산출물</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>헤지가 허용되는 조건</title>
<desc>헤지는 성공했을지도 모르는 호출에 대해 일어나므로 예산이 없으면 정상 구간에서도 백엔드 부하가 두 배가 된다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">헤지가 허용되는 조건</text>
<rect x="28.0" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="103.2" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">첫 시도</text>
<rect x="252.5" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="327.8" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">예산 확인</text>
<rect x="477.0" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="552.2" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">토큰 소비</text>
<rect x="701.5" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="776.8" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">헤지 시도</text>
<line x1="184.5" y1="133" x2="246.5" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="215.5" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">응답 지연</text>
<line x1="409.0" y1="133" x2="471.0" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="440.0" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">남은 토큰</text>
<line x1="633.5" y1="133" x2="695.5" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="664.5" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">반올림한 몫</text>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

@@ -0,0 +1,18 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="210" viewBox="0 0 880 210" role="img">
<title>가드가 지키지 못하는 구간</title>
<desc>두 스레드의 개정이 같은 applied 읽기와 둘 다 통과를 지나 옛 엔드포인트 회귀로 이어지는 경로.</desc>
<rect x="0" y="0" width="880" height="210" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">가드가 지키지 못하는 구간</text>
<rect x="28.0" y="96" width="162.5" height="58" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6"/>
<text x="109.2" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">두 스레드의 개정</text>
<rect x="248.5" y="96" width="162.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="329.8" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">같은 applied 읽기</text>
<line x1="196.5" y1="125" x2="242.5" y2="125" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<rect x="469.0" y="96" width="162.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="550.2" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">둘 다 통과</text>
<line x1="417.0" y1="125" x2="463.0" y2="125" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<rect x="689.5" y="96" width="162.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="770.8" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">옛 엔드포인트 회귀</text>
<line x1="637.5" y1="125" x2="683.5" y2="125" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,18 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="210" viewBox="0 0 880 210" role="img">
<title>경합이 끼는 자리</title>
<desc>동시 회전 둘이 같은 previous 읽기와 나중 set 이 덮음을 지나 덮인 세대 미등록으로 이어지는 경로.</desc>
<rect x="0" y="0" width="880" height="210" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">경합이 끼는 자리</text>
<rect x="28.0" y="96" width="162.5" height="58" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6"/>
<text x="109.2" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">동시 회전 둘</text>
<rect x="248.5" y="96" width="162.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="329.8" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">같은 previous 읽기</text>
<line x1="196.5" y1="125" x2="242.5" y2="125" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<rect x="469.0" y="96" width="162.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="550.2" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">나중 set 이 덮음</text>
<line x1="417.0" y1="125" x2="463.0" y2="125" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<rect x="689.5" y="96" width="162.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="770.8" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">덮인 세대 미등록</text>
<line x1="637.5" y1="125" x2="683.5" y2="125" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>회수가 막히는 자리</title>
<desc>비원자적 감소에서 계수기 음수로 둘 다 통과가 건너가고, 계수기 음수에서 회수 불가로 조용함 거짓이 건너간다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">회수가 막히는 자리</text>
<rect x="28.0" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="140.7" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">비원자적 감소</text>
<rect x="327.3" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">계수기 음수</text>
<rect x="626.7" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="739.3" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">회수 불가</text>
<line x1="259.3" y1="133" x2="321.3" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="290.3" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">둘 다 통과</text>
<line x1="558.7" y1="133" x2="620.7" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="589.7" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">조용함 거짓</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="314" viewBox="0 0 880 314" role="img">
<title>소비자 소스에서 유도하는 셋</title>
<desc>손으로 적은 요구 목록은 클라이언트가 이미 말하는 것의 사본이고 갱신이 멈추는 쪽은 사본이다. 그래서 소스에서 유도한다.</desc>
<rect x="0" y="0" width="880" height="314" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">소비자 소스에서 유도하는 셋</text>
<rect x="28" y="142" width="262" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="159.0" y="176.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">소비자 자바 소스</text>
<rect x="474" y="76" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="108.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">생성 자바 패키지</text>
<line x1="296" y1="171" x2="468" y2="103" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="70" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">import 접미</text>
<rect x="474" y="142" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="174.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">서비스 경로</text>
<line x1="296" y1="171" x2="468" y2="169" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="162" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">Grpc import</text>
<rect x="474" y="208" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="240.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">메서드 경로</text>
<line x1="296" y1="171" x2="468" y2="235" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="228" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">stub 호출</text>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>생성자가 막는 것과 검증기가 잡는 것</title>
<desc>위험한 조합은 정책이 아니라 생성자가 거부하게 만든다. 그래서 검증기의 규칙은 생성자를 통과한 조합에서만 발화한다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">생성자가 막는 것과 검증기가 잡는 것</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">정규 생성자</text>
<rect x="44.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="126.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">주소 수 · 리졸버 조합</text>
<rect x="226.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">갱신 주기</text>
<rect x="408.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="490.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">스트림 예산</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">검증기가 잡는 조합</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>구별하는 세 층위</title>
<desc>관측을 논리 RPC 와 물리 시도와 스트림 수명주기로 나눈다. 한 층위로 접으면 재시도한 호출의 성공률이 왜곡된다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">구별하는 세 층위</text>
<rect x="28" y="66" width="824" height="100" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">grpc-observability</text>
<rect x="44.0" y="100" width="252.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="170.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">논리 RPC</text>
<rect x="314.0" y="100" width="252.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">물리 시도</text>
<rect x="584.0" y="100" width="252.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="710.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">스트림 수명주기</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="244" viewBox="0 0 880 244" role="img">
<title>원장의 전이</title>
<desc>진행 중 상태에서만 전이할 수 있고 커밋은 결과 참조가 비면 거부된다.</desc>
<rect x="0" y="0" width="880" height="244" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">원장의 전이</text>
<rect x="28.0" y="120" width="210.7" height="56" rx="26" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="133.3" y="153.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">IN_PROGRESS</text>
<rect x="334.7" y="120" width="210.7" height="56" rx="26" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440" y="153.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">COMMITTED</text>
<rect x="641.3" y="120" width="210.7" height="56" rx="26" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="746.7" y="153.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">FAILED</text>
<line x1="244.7" y1="148" x2="328.7" y2="148" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="286.7" y="138" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">결과 참조 필수</text>
<path d="M133.3,178 C133.3,232 746.7,232 746.7,178" fill="none" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4" marker-end="url(#ar)"/>
<text x="440.0" y="228" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">실패 기록</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@@ -0,0 +1,18 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="210" viewBox="0 0 880 210" role="img">
<title>두 값이 함께 커지는 조건</title>
<desc>재접속 폭주가 같은 값 읽고 통과와 계수기 증가를 지나 경계 초과와 맵 증가로 이어지는 경로.</desc>
<rect x="0" y="0" width="880" height="210" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">두 값이 함께 커지는 조건</text>
<rect x="28.0" y="96" width="162.5" height="58" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6"/>
<text x="109.2" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">재접속 폭주</text>
<rect x="248.5" y="96" width="162.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="329.8" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">같은 값 읽고 통과</text>
<line x1="196.5" y1="125" x2="242.5" y2="125" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<rect x="469.0" y="96" width="162.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="550.2" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">계수기 증가</text>
<line x1="417.0" y1="125" x2="463.0" y2="125" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<rect x="689.5" y="96" width="162.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="770.8" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">경계 초과 · 맵 증가</text>
<line x1="637.5" y1="125" x2="683.5" y2="125" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,18 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="210" viewBox="0 0 880 210" role="img">
<title>두 연산이 겹치는 결과</title>
<desc>회전과 배수 완료가 각자 읽은 상태와 조건 없는 set 을 지나 이전 세대가 현재가 되는 결과로 이어진다.</desc>
<rect x="0" y="0" width="880" height="210" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">두 연산이 겹치는 결과</text>
<rect x="28.0" y="96" width="162.5" height="58" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6"/>
<text x="109.2" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">회전과 배수 완료</text>
<rect x="248.5" y="96" width="162.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="329.8" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">각자 읽은 상태</text>
<line x1="196.5" y1="125" x2="242.5" y2="125" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<rect x="469.0" y="96" width="162.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="550.2" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">조건 없는 set</text>
<line x1="417.0" y1="125" x2="463.0" y2="125" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<rect x="689.5" y="96" width="162.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="770.8" y="130.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">이전 세대가 현재</text>
<line x1="637.5" y1="125" x2="683.5" y2="125" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="240" viewBox="0 0 880 240" role="img">
<title>두 자리가 가리키는 대상</title>
<desc>큐에서 빠지는 것 쪽에 가장 오래된 봉투와 그 봉투의 바이트가 놓이고, 차감되는 값 쪽에 새 메시지와 그 바이트가 놓인다. 봉투의 바이트만 빗금이다.</desc>
<rect x="0" y="0" width="880" height="240" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">두 자리가 가리키는 대상</text>
<text x="28" y="82" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">큐에서 빠지는 것</text>
<text x="468" y="82" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">차감되는 값</text>
<rect x="28" y="96" width="380" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="218.0" y="126.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">가장 오래된 봉투</text>
<rect x="468" y="96" width="384" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="660.0" y="126.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">새로 들어온 메시지</text>
<rect x="28" y="158" width="380" height="50" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="218.0" y="188.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">그 봉투의 바이트</text>
<rect x="468" y="158" width="384" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="660.0" y="188.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">새 메시지의 바이트</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>동기화가 걸린 곳과 아닌 곳</title>
<desc>GrpcSerializedStreamWriter 만 동기화 마커 안에 놓이고 완료 조정자의 pending 이 바깥에 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">동기화가 걸린 곳과 아닌 곳</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">동기화 마커</text>
<rect x="44.0" y="100" width="528.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">GrpcSerializedStreamWriter</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">완료 조정자의 pending</text>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>신호가 건너는 경계</title>
<desc>종료 훅 스레드에서 배수 신호 boolean 으로 signalDrain 쓰기가 건너가고, 배수 신호 boolean 에서 스트림 틱 스레드로 terminationDue 읽기가 건너간다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">신호가 건너는 경계</text>
<rect x="28.0" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="140.7" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">종료 훅 스레드</text>
<rect x="327.3" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">배수 신호 boolean</text>
<rect x="626.7" y="104" width="225.3" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="739.3" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">스트림 틱 스레드</text>
<line x1="259.3" y1="133" x2="321.3" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="290.3" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">signalDrain 쓰기</text>
<line x1="558.7" y1="133" x2="620.7" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="589.7" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">terminationDue 읽기</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,25 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>열 단계 중 안쪽 다섯</title>
<desc>승인이 마감보다 먼저이고 멱등이 검증보다 먼저다. 전체 열 단계 중 순서 논증이 걸린 안쪽 다섯만 그린다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">열 단계 중 안쪽 다섯</text>
<rect x="28.0" y="104" width="105.6" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="80.8" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">ADMISSION</text>
<rect x="207.6" y="104" width="105.6" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="260.4" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">DEADLINE_CANCELLATION</text>
<rect x="387.2" y="104" width="105.6" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440.0" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">IDEMPOTENCY</text>
<rect x="566.8" y="104" width="105.6" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="619.6" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">VALIDATION</text>
<rect x="746.4" y="104" width="105.6" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="799.2" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">SERVICE_ADAPTER</text>
<line x1="139.6" y1="133" x2="201.6" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="170.6" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">수용 여부</text>
<line x1="319.2" y1="133" x2="381.2" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="350.2" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">남은 마감</text>
<line x1="498.8" y1="133" x2="560.8" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="529.8" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">저장된 결과</text>
<line x1="678.4" y1="133" x2="740.4" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="709.4" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">검증된 메시지</text>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

@@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>규칙이 닿지 않는 대상</title>
<desc>인라인 소스 문자열만 규칙이 판정하는 입력 안에 놓이고 저장소의 자바 파일이 바깥에 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">규칙이 닿지 않는 대상</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">규칙이 판정하는 입력</text>
<rect x="44.0" y="100" width="528.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">인라인 소스 문자열</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">저장소의 자바 파일</text>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="240" viewBox="0 0 880 240" role="img">
<title>계수기 쌍의 비대칭</title>
<desc>진행 계수기 쪽에 tryAdmit 증가와 release 감소가 놓이고, 큐 계수기 쪽에 tryAdmit 증가와 반납 메서드 없음이 놓인다. 마지막 칸만 빗금이다.</desc>
<rect x="0" y="0" width="880" height="240" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">계수기 쌍의 비대칭</text>
<text x="28" y="82" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">진행 계수기</text>
<text x="468" y="82" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">큐 계수기</text>
<rect x="28" y="96" width="380" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="218.0" y="126.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">tryAdmit 증가</text>
<rect x="468" y="96" width="384" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="660.0" y="126.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">tryAdmit 증가</text>
<rect x="28" y="158" width="380" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="218.0" y="188.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">release 감소</text>
<rect x="468" y="158" width="384" height="50" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="660.0" y="188.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">반납 메서드 없음</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="314" viewBox="0 0 880 314" role="img">
<title>한 규칙을 지키는 세 지점</title>
<desc>Advanced 의존 금지라는 하나의 규칙이 레지스트리와 빌드 검증 태스크와 자바 단언 세 곳에서 각각 강제된다.</desc>
<rect x="0" y="0" width="880" height="314" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">한 규칙을 지키는 세 지점</text>
<rect x="28" y="142" width="262" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="159.0" y="176.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">Advanced 의존 금지</text>
<rect x="474" y="76" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="108.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">registry allowed_dependencies</text>
<line x1="296" y1="171" x2="468" y2="103" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="70" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">선언</text>
<rect x="474" y="142" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="174.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">verifyCleanArchitectureDependencies</text>
<line x1="296" y1="171" x2="468" y2="169" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="162" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">빌드 검증</text>
<rect x="474" y="208" width="378" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="663.0" y="240.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">GrpcPlatformStartupValidatorTest</text>
<line x1="296" y1="171" x2="468" y2="235" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="384" y="228" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">자바 단언</text>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>검증기가 도는 데 빠진 것</title>
<desc>설정 프로퍼티 셋만 검증기 입력 안에 놓이고 모듈 id 집합 생산자와 requireValid 호출 지점이 바깥에 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">검증기가 도는 데 빠진 것</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">검증기가 요구하는 입력</text>
<rect x="44.0" y="100" width="528.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">설정 프로퍼티 셋</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">모듈 id 집합 생산자</text>
<rect x="624" y="166" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="198.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">requireValid 호출 지점</text>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>레인을 부르는 경로</title>
<desc>직접 입력한 명령만 레인을 부르는 경로 안에 놓이고 check 연결과 CI 워크플로가 바깥에 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">레인을 부르는 경로</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">레인을 부르는 경로</text>
<rect x="44.0" y="100" width="528.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">직접 입력한 명령</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">check 연결</text>
<rect x="624" y="166" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="198.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">CI 워크플로</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>증거가 오는 곳</title>
<desc>리터럴로 쓴 값만 증거가 오는 곳 안에 놓이고 실제 소켓 관측이 바깥에 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">증거가 오는 곳</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">증거가 오는 곳</text>
<rect x="44.0" y="100" width="528.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">리터럴로 쓴 값</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">실제 소켓 관측</text>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

@@ -0,0 +1,19 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>이 리프가 소유한 어휘</title>
<desc>계획 타입과 승인 타입과 검증 타입이 messaging-admin-api 안에 놓이고 브로커 접촉과 저장소 스프링이 바깥에 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">이 리프가 소유한 어휘</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">messaging-admin-api</text>
<rect x="44.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="126.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">계획 타입</text>
<rect x="226.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">승인 타입</text>
<rect x="408.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="490.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">검증 타입</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">브로커 접촉</text>
<rect x="624" y="166" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="198.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">저장소 · 스프링</text>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>승인 검증이 도는 순서</title>
<desc>다이제스트 대조에서 윈도우로 일치가 건너가고 윈도우에서 서명 파싱으로 기간 안이 건너가고 서명 파싱에서 HMAC 으로 형식 통과가 건너간다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">승인 검증이 도는 순서</text>
<rect x="28.0" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="103.2" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">다이제스트 대조</text>
<rect x="252.5" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="327.8" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">윈도우</text>
<rect x="477.0" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="552.2" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">서명 파싱</text>
<rect x="701.5" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="776.8" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">HMAC</text>
<line x1="184.5" y1="133" x2="246.5" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="215.5" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">일치</text>
<line x1="409.0" y1="133" x2="471.0" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="440.0" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">기간 안</text>
<line x1="633.5" y1="133" x2="695.5" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="664.5" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">형식 통과</text>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>타입이 지는 것과 구현이 지는 것</title>
<desc>이 리프에 실행 코드가 없으므로 동시성 계약은 인터페이스 문서로 표현되고, 강제는 구현 리프의 몫이다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">타입이 지는 것과 구현이 지는 것</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">messaging-admin-api</text>
<rect x="44.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="171.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">불변 record 와 final 클래스</text>
<rect x="317.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="444.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">펜싱 토큰 하한</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">오래된 토큰 거절 — 구현 의무</text>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="302" viewBox="0 0 880 302" role="img">
<title>목록에서 빠진 검사</title>
<desc>javadoc 이 든 조건 쪽에 승인 존재와 유효 기간과 빠진 둘이 놓이고, 본문이 보는 조건 쪽에 승인 존재와 유효 기간과 작업 종류 및 출처가 놓인다. 빠진 둘만 빗금이다.</desc>
<rect x="0" y="0" width="880" height="302" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">목록에서 빠진 검사</text>
<text x="28" y="82" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">javadoc 이 든 조건</text>
<text x="468" y="82" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">본문이 보는 조건</text>
<rect x="28" y="96" width="380" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="218.0" y="126.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">승인 존재</text>
<rect x="468" y="96" width="384" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="660.0" y="126.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">승인 존재</text>
<rect x="28" y="158" width="380" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="218.0" y="188.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">유효 기간</text>
<rect x="468" y="158" width="384" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="660.0" y="188.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">유효 기간</text>
<rect x="28" y="220" width="380" height="50" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="218.0" y="250.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">빠진 둘</text>
<rect x="468" y="220" width="384" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="660.0" y="250.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">작업 종류 · 출처</text>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -0,0 +1,19 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>실행 계층이 만지는 것</title>
<desc>오케스트레이션과 실행 서비스와 토폴로지 저널이 messaging-admin-runtime 안에 놓이고 브로커 클라이언트와 스프링 배선이 바깥에 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">실행 계층이 만지는 것</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">messaging-admin-runtime</text>
<rect x="44.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="126.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">오케스트레이션</text>
<rect x="226.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">실행 서비스</text>
<rect x="408.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="490.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">토폴로지 · 저널</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">브로커 클라이언트</text>
<rect x="624" y="166" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="198.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">스프링 배선</text>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>재개가 붙는 쪽과 붙지 않는 쪽</title>
<desc>리드라이브는 리스의 재개 지점과 체크포인트 콜백을 실행 측에 넘기지만 리플레이는 넘기지 않는다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">재개가 붙는 쪽과 붙지 않는 쪽</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">리스와 체크포인트를 받는 실행</text>
<rect x="44.0" y="100" width="528.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">리드라이브 — resumeFrom 사용</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">리플레이 — 시그니처에 없음</text>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>펜싱 토큰이 동작하는 세 지점</title>
<desc>토큰이 인수와 쓰기와 clamp 세 지점에서 각각 작동해 낡은 리스가 후임의 기록을 덮지 못하게 한다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">펜싱 토큰이 동작하는 세 지점</text>
<rect x="28" y="66" width="824" height="100" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">InMemoryAdminOperationJournal</text>
<rect x="44.0" y="100" width="252.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="170.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">인수 시 토큰 증가</text>
<rect x="314.0" y="100" width="252.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="440.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">쓰기 시 토큰 대조</text>
<rect x="584.0" y="100" width="252.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="710.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">clamp 로 단조성 유지</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>보호가 적용된 절반</title>
<desc>REPLAY 와 REDRIVE 가 검증된 승인이 덮는 범위 안에 놓이고 PURGE 와 OFFSET_RESET 과 DELETE_DESTINATION 이 바깥에 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">보호가 적용된 절반</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">VerifiedApproval 이 덮는 범위</text>
<rect x="44.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="171.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">REPLAY</text>
<rect x="317.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="444.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">REDRIVE</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">PURGE · OFFSET_RESET</text>
<rect x="624" y="166" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="198.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">DELETE_DESTINATION</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="240" viewBox="0 0 880 240" role="img">
<title>두 스택이 갈리는 지점</title>
<desc>스택 A 쪽에 파티션 스케일업과 ADVISORY 기동 허용이 놓이고 스택 B 쪽에 파티션 스케일업과 차이 기동 거부가 놓인다. 마지막 칸만 빗금이다.</desc>
<rect x="0" y="0" width="880" height="240" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">두 스택이 갈리는 지점</text>
<text x="28" y="82" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">Stack A</text>
<text x="468" y="82" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">Stack B</text>
<rect x="28" y="96" width="380" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="218.0" y="126.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">파티션 스케일업</text>
<rect x="468" y="96" width="384" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="660.0" y="126.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">파티션 스케일업</text>
<rect x="28" y="158" width="380" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="218.0" y="188.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">ADVISORY · 기동 허용</text>
<rect x="468" y="158" width="384" height="50" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="660.0" y="188.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">차이 · 기동 거부</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>실행되지 않는 계층</title>
<desc>SPI 각각의 단위 테스트만 검증된 범위 안에 놓이고 검사 순서와 저널 시퀀스, 실패 재던짐과 코드 정제가 바깥에 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">실행되지 않는 계층</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">검증된 범위</text>
<rect x="44.0" y="100" width="528.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">SPI 각각의 단위 테스트</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">검사 순서 · 저널 시퀀스</text>
<rect x="624" y="166" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="198.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">실패 재던짐 · 코드 정제</text>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="196" viewBox="0 0 880 196" role="img">
<title>payload 가 지나는 경로</title>
<desc>브로커 한계를 넘는 payload 를 객체 저장소에 두고 메시지는 참조만 나른다. 위협은 실패가 아니라 잘못된 성공이다.</desc>
<rect x="0" y="0" width="880" height="196" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">payload 가 지나는 경로</text>
<rect x="28.0" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="103.2" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">payload</text>
<rect x="252.5" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="327.8" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">객체 저장소</text>
<rect x="477.0" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="552.2" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">ClaimCheckReference</text>
<rect x="701.5" y="104" width="150.5" height="58" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="776.8" y="138.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">메시지</text>
<line x1="184.5" y1="133" x2="246.5" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="215.5" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">오프로드</text>
<line x1="409.0" y1="133" x2="471.0" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="440.0" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">저장 키와 다이제스트</text>
<line x1="633.5" y1="133" x2="695.5" y2="133" stroke="#374151" stroke-width="1.6" marker-end="url(#ar)"/>
<text x="664.5" y="92" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">참조만 탑재</text>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>이 리프가 하는 것과 하지 않는 것</title>
<desc>오프로드와 참조 전달과 무결성 검증은 이 리프가 한다. 보존 sweep 은 전제되어 있지만 이 리프에 없다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">이 리프가 하는 것과 하지 않는 것</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">messaging-claim-check</text>
<rect x="44.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="126.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">오프로드</text>
<rect x="226.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">참조 전달</text>
<rect x="408.0" y="100" width="164.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="490.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">무결성 검증</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">보존 sweep</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>안내가 가리키는 빈자리</title>
<desc>설정 표면과 오류 메시지 안내가 운영자가 켤 수 있는 것 안에 놓이고 저장소 구현과 bean 이 바깥에 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">안내가 가리키는 빈자리</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">운영자가 켤 수 있는 것</text>
<rect x="44.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="171.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">설정 표면</text>
<rect x="317.0" y="100" width="255.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="444.5" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">오류 메시지 안내</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">저장소 구현 · bean</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="230" viewBox="0 0 880 230" role="img">
<title>싣기와 쓰기가 갈리는 자리</title>
<desc>messaging-cloudevents 적재만 배포 아티팩트 안에 놓이고 이 리프 타입의 호출자가 바깥에 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="230" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">싣기와 쓰기가 갈리는 자리</text>
<rect x="28" y="66" width="560" height="134" rx="14" fill="none" stroke="#374151" stroke-width="1.6"/>
<text x="44" y="88" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">app-bootstrap 배포 아티팩트</text>
<rect x="44.0" y="100" width="528.0" height="54" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="308.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">messaging-cloudevents 적재</text>
<rect x="624" y="100" width="228" height="54" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="738.0" y="132.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">이 리프 타입의 호출자</text>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="240" viewBox="0 0 880 240" role="img">
<title>봉투가 왕복에서 잃는 것</title>
<desc>왼쪽 원래 봉투에 occurredAt 과 producedAt 이 있고, 오른쪽 왕복 후 봉투에서 producedAt 만 빗금으로 놓인다.</desc>
<rect x="0" y="0" width="880" height="240" fill="#ffffff"/>
<defs><marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#374151"/></marker><pattern id="hx" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#9ca3af" stroke-width="2"/></pattern></defs>
<text x="28" y="40" font-family="system-ui,sans-serif" font-size="19" font-weight="600" fill="#111827">봉투가 왕복에서 잃는 것</text>
<text x="28" y="82" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">원래 봉투</text>
<text x="468" y="82" font-family="system-ui,sans-serif" font-size="13" fill="#6b7280">왕복 후 봉투</text>
<rect x="28" y="96" width="380" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="218.0" y="126.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">occurredAt</text>
<rect x="468" y="96" width="384" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="660.0" y="126.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">occurredAt</text>
<rect x="28" y="158" width="380" height="50" rx="10" fill="#eef2ff" stroke="#374151" stroke-width="1.6"/>
<text x="218.0" y="188.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">producedAt</text>
<rect x="468" y="158" width="384" height="50" rx="10" fill="url(#hx)" stroke="#374151" stroke-width="1.6" stroke-dasharray="6 4"/>
<text x="660.0" y="188.0" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#111827">producedAt</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

Some files were not shown because too many files have changed in this diff Show More