chore: 이전 세션이 남긴 변경을 커밋한다

이번 파이프라인 작업과 무관하게 작업 트리에 남아 있던 것을 그대로 올린다.
사용자가 「전부 커밋」으로 정했고, 이번 작업과 섞이지 않게 커밋만 나눴다.

대부분은 clean-architecture-backend-template 의 그림 정본 재배치다 —
final/assets/diagrams/<이름>/ 에 있던 것이 CLAUDE.md 가 적은 배치인
final/assets/<이름>/ 로 옮겨졌고 .techviz/<이름>/ 이 함께 들어왔다.
삽입 줄의 대부분(3.15M)이 그 .techviz context.json 이다.

그 밖에 ca-tmpl·document-haness 의 정리, .claude/agents/ 열한 개,
writing-practitioner-guides 스킬, .playwright-mcp 세션 산출물,
scripts/check-ssot-facts.py 와 그 시험이 들어 있다.

이 커밋의 내용은 내가 만든 것이 아니라 이전 세션이 남긴 것이고 검증하지 않았다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
DongHyeonka
2026-09-17 11:02:02 +09:00
co-authored by Claude Opus 5
parent 2109f726fe
commit ab59130196
1524 changed files with 3160026 additions and 8369 deletions
@@ -33,18 +33,18 @@ source:
## 결론
간헐적으로 보인 것은 두 가지 결정적 어긋남이었고, 사용자는 둘 다 만났다.
간헐적으로 보였을 뿐 실제로는 두 가지로 어긋났고, 사용자는 둘 다 만났다.
인증 : 남는 글자가 없어 빈 문자열 → 폼이 요청 전에 거절
Redis 캐시 와 Redis 클러스터 : 둘 다 redis → 두 번째가 충돌
> 규칙은 간헐적이었던 적이 없다. **보이지 않았을 뿐이다** — slug 생성이 [a-z0-9] 만 남기고 나머지를 버려서, 한글 이름은 아무것도 기여하지 못했다.
`5cffe30` 이 그것을 이렇게 적었다. 규칙은 간헐적이었던 적이 없다. 보이지 않았을 뿐이다 — slug 생성이 [a-z0-9] 만 남기고 나머지를 버려서, 한글 이름은 아무것도 기여하지 못했다.
한글을 버리지 않고 로마자로 옮긴다. 음절을 초성·중성·종성으로 산술 분해하므로 표가 필요 없고 결정적이다.
백엔드 아키텍처 → baekendeu-akitekcheo
국어의 로마자 표기법의 자모 대응만 적용하고 음운 변화 규칙은 일부러 뺐다. slug 는 읽는 것이지 발음하는 것이 아니고, 그 규칙을 넣으면 같은 이름이 문맥에 따라 다른 slug 가 된다.
국어의 로마자 표기법의 자모 대응만 적용하고 음운 변화 규칙은 일부러 뺐다. 함수의 javadoc 이 그 이유를 적는다. slug 는 읽는 것이지 발음하는 것이 아니고, 그 규칙을 넣으면 같은 이름이 문맥에 따라 다른 slug 가 된다.
## 검증 환경
@@ -35,9 +35,9 @@ source:
편집기가 질문과 결정 목록을 못 읽으면 빈 배열로 삼키고 있었다. 서버는 404 를 주고 있었다 — 그 두 연산에 컨트롤러가 없었다.
작성자에게는 「아직 안 쓴 것」으로 읽힌다.
작성자에게는 「아직 안 쓴 것」으로 읽힌다. 그래서 화면이 지킬 규칙을 하나 정했다.
> 거짓말을 하느니 못 읽었다고 말한다.
거짓말을 하느니 못 읽었다고 말한다.
못 읽었을 때 못 읽었다고 적게 고쳤다. 같은 판단을 주제 탭에도 적용했다.
@@ -79,6 +79,8 @@ tech-log-backend : 911e8ba — 없던 두 컨트롤러를 구현
대신 저장할 때 그 대상이 실제로 있는지 확인한다. 확인하지 않으면 없는 id 가 그대로 저장되고, 공개 화면은 조용히 빈 focus 를 그린다 — 저장은 성공했는데 화면에는 아무것도 안 나오는, 이유를 알 수 없는 실패가 된다.
확인하는 것은 있는지까지다. 그 대상이 공개인지는 저장할 때 보지 않는다. 아직 게시하지 않은 프로젝트를 미리 지목해 두고 게시와 동시에 홈에 뜨게 하는 것이 정상적인 순서이고, 공개 여부는 공개 조회 쪽이 매번 다시 판단한다.
같은 화면의 두 자리가 반대로 처리돼 있었다. 저장 쪽은 없는 대상을 막고, 목록을 못 읽은 쪽은 없는 것으로 그렸다.
## 못 읽었다고 적는다
@@ -33,13 +33,13 @@ source:
## 결론
두 요청을 하나로 묶어 기다리면 한쪽 실패 전체 실패로 만든다. 둘을 따로 읽도록 갈랐다.
두 요청을 하나로 묶어 기다리면 한쪽 실패해도 전체 실패다. 둘을 따로 읽도록 갈랐다.
더 미묘한 변종이 하나 더 있었다.
더 미묘한 변종이 하나 더 있었고, `fd73bc8` 이 그것을 적어 두었다.
> Promise.all([gateway.foo()]) 은 foo 가 **거절하는 것만** 잡는다. 호출이 **동기적으로 던지면** 배열을 만드는 중에 터져 rejection handler 를 지나지 못하고, 그러면 홈 focus 한 칸 때문에 대시보드 전체가 빈 화면이 된다.
Promise.all([gateway.foo()]) 은 foo 가 거절하는 것만 잡는다. 호출이 동기적으로 던지면 배열을 만드는 중에 터져 rejection handler 를 지나지 못하고, 그러면 홈 focus 한 칸 때문에 대시보드 전체가 빈 화면이 된다.
같은 판단을 주제 탭에도 적용했다.
같은 판단을 나중에 주제 탭에도 적용했다.
## 검증 환경
@@ -27,9 +27,9 @@ source:
## 목적
매번 우는 검사가 읽히지 않게 되는 것을 막는다.
검사 결과를 사람이 계속 읽게 하려고 정한 기준이다.
> 매번 늑대를 외치는 검사는 읽히지 않게 되고, 진짜 실패가 그 옆에 눈에 띄지 않은 채 앉아 있게 된다.
매번 늑대를 외치는 검사는 읽히지 않게 되고, 진짜 실패가 그 옆에 눈에 띄지 않은 채 앉아 있게 된다.
## 규칙
@@ -34,11 +34,11 @@ SPA 안에서 이동하면 화면이 열린다. 주소창에 그 주소를 직
## 결론
서빙 계약 절반은 라우트 레지스트리에서 유도하고 있었고 나머지 절반은 손으로 유지하는 배열이었다.
서빙 계약 절반씩 다른 방식으로 만들어지고 있었다. 그것을 고친 `ab8c6c1` 이 원인을 이렇게 짚었다.
> 서빙 계약의 공개 절반은 라우트 레지스트리에서 패턴을 유도한다. **Studio 절반은 손으로 유지하는 배열이었고, 손으로 유지하는 배열이 실패하는 방식 그대로 실패했다** — ^/studio/assets$ 위의 주석이 바로 그 버그를 한 번 고친 기록이고, 라우트를 더하니 즉시 반복됐다.
서빙 계약의 공개 절반은 라우트 레지스트리에서 패턴을 유도한다. Studio 절반은 손으로 유지하는 배열이었고, 손으로 유지하는 배열이 실패하는 방식 그대로 실패했다 — ^/studio/assets$ 위의 주석이 바로 그 버그를 한 번 고친 기록이고, 라우트를 더하니 즉시 반복됐다.
공개 절반도 유도라고 하기 어려웠다. 번들된 픽스처에 우연히 들어 있던 공개 경로를 전부 열거하고, 생성된 nginx 가 정확히 그것들을 location = 블록으로 게시했다. 빌드 이후에 게시된 기록은 SPA 에 묻기도 전에 엣지에서 404 였다. 경로 27개가 얼어 있었고 28번째는 무엇이든 닿을 수 없었다.
공개 절반도 유도라고 하기 어려웠다. 서빙 계약이 번들된 픽스처에 우연히 들어 있던 공개 경로를 전부 열거하고, 생성된 nginx 가 정확히 그것들을 location = 블록으로 게시했다. 빌드 이후에 게시된 기록은 SPA 에 묻기도 전에 엣지에서 404 였다. 경로 27개가 얼어 있었고 28번째는 무엇이든 닿을 수 없었다.
지금은 라우트 계약에서 등록된 Public 라우트마다 정규식 하나를 만든다. 파라미터는 한 세그먼트만 잡고 슬래시는 잡지 않으므로 /cases/a/b 는 404 로 남는다.
@@ -30,20 +30,16 @@ source:
홈 화면 하나에 종류 이름이 아홉 개 있었다.
text
최근 기록 목록: CASE · CONCEPT · OPEN QUESTION · REFERENCE
바로 아래 「종류별로 읽기」: 검증 기록 · 동작 원리 · 적용 기준 · 열린 질문
두 목록이 같은 다섯 종류를 가리키는데 이름이 겹치지 않는다. 독자는 그 둘이 같은 것이라는 단서를 받지 못한다.
## 결론
> 표가 화면마다 복사되어 **여섯 벌**이었고 그래서 갈라졌다: 같은 QUESTION 이 공개 화면에서 "Open Question", 작업본 목록과 게시 기록에서 "Question", 편집기 상태 줄에서 "QUESTION" 이었다. **쓰는 사람은 같은 문서를 화면마다 다른 이름으로 만난다.**
종류 이름을 한 곳에 모은 `ca1fc92` 가 원인을 짚었다. 표가 화면마다 복사되어 여섯 벌이었고 그래서 갈라졌다: 같은 QUESTION 이 공개 화면에서 "Open Question", 작업본 목록과 게시 기록에서 "Question", 편집기 상태 줄에서 "QUESTION" 이었다. 쓰는 사람은 같은 문서를 화면마다 다른 이름으로 만난다.
종류에서 이름으로 가는 표 하나로 모다.
편집기 칸 이름도 공개 화면과 맞췄다.
종류에서 이름으로 가는 표 하나로 모으고, 편집기 칸 이름도 공개 화면과 맞췄다.
## 검증 환경
@@ -69,7 +65,7 @@ tech-log-frontend : dc2fda7 · ca1fc92 · 82e992d
두 목록이 세로로 붙어 있다. 위는 계약의 enum 이름을, 아래는 사람이 붙인 이름을 쓴다. 독자는 둘이 같은 것이라는 단서를 어디서도 받지 못했다.
이름을 바꾸기 전에는 양쪽이 다 enum 이름이었으므로 적어도 같아 보였다. 이 화면은 이름을 바꾸면서 나빠졌다.
이름을 바꾸기 전에는 양쪽이 다 enum 이름이었으므로 적어도 같아 보였다. 이름을 바꿔서 나빠졌다고 짚은 화면은 홈 하나다. 두 이름이 같이 뜨는 다른 화면을 전수로 세지는 않았다.
## 표가 여섯 벌이었다
@@ -35,7 +35,7 @@ source:
컬럼 이름 하나가 틀렸고, 그 쿼리가 한 번도 실행된 적이 없었다.
> 그 쿼리의 여섯 컬럼 중 다섯은 마이그레이션과 대조했다. 이 하나만 가정했고, 그것이 틀렸다.
그 쿼리의 여섯 컬럼 중 다섯은 마이그레이션과 대조했다. 이 하나만 가정했고, 그것이 틀렸다.
표준 check 는 Testcontainers 를 띄우지 않는다. persistence SQL 은 한 번도 실행되지 않은 채 빌드가 통과하고, 컴파일도 단위 테스트도 컬럼 이름을 검증하지 못한다.
@@ -101,7 +101,7 @@ DB : 실제 PostgreSQL (Testcontainers)
삭제 경로 전용 통합 테스트 태스크를 만들고, 실패했던 그 쿼리를 포함해 여덟 시나리오를 실제 PostgreSQL 에서 돌린다.
전용 태스크로 뺀 이유는 컨테이너를 띄우는 데 시간이 들어 표준 검사에 넣으면 모든 빌드가 느려지기 때문이다. 대신 그 태스크를 돌리는 것은 사람이 기억해야 한다.
표준 check 에 들어가지 않으므로 그 태스크를 돌리는 것은 사람이 기억해야 한다.
## 확인하지 못한 것
@@ -42,7 +42,7 @@ CI 게이트도 마찬가지였다. 라우트를 더하면서 기준값을 함
첫 번째 : 화면 테스트를 별도 명령이 돌리는데 그것을 안 돌려 23건이 빨간 채로 여러 커밋을 지나갔다
두 번째 : 주제 화면 셋을 더하면서 게이트 기준값을 빠뜨려 게이트가 빨간 채로 여러 커밋을 지나갔다
> **가드는 CI 에 묶여야 의미가 있습니다.** 사람이 기억해서 돌리는 가드는 절반만 존재합니다.
가드는 CI 에 묶여야 의미가 있습니다. 사람이 기억해서 돌리는 가드는 절반만 존재합니다.
## 검증 환경
@@ -70,7 +70,7 @@ tech-log-frontend : fd73bc8 · fe6b56a
## 게이트 기준값을 빠뜨렸다
주제 화면 셋을 더할 때 CI 게이트가 요구하는 기준값 셋을 함께 올리지 않았다. 게이트는 라우트 집합과 증거 집합이 정확히 일치하기를 요구하므로 그 상태를 정확히 거절한다.
주제 화면 셋을 더할 때 CI 게이트가 요구하는 기준값 셋을 또 빠뜨렸다 — 라우트를 더하면서 거기 딸린 손 목록을 빠뜨린 것이 처음이 아니었다. 게이트는 라우트 집합과 증거 집합이 정확히 일치하기를 요구하므로 그 상태를 정확히 거절한다.
게이트가 빨간 채로 여러 커밋을 지나갔고, 결정 링크 404 를 고치던 커밋에서야 함께 맞췄다.
+2 -1
View File
@@ -73,7 +73,8 @@
],
"reference": [],
"question": [],
"decision": []
"decision": [],
"setup": []
}
}
},
@@ -1,106 +0,0 @@
{
"version": "1.1",
"id": "production-vs-optin",
"title": "app-bootstrap의 main 클래스패스에는 어댑터 11개가 포함되고 참조 어댑터 3개는 의존 목록 밖에 있다",
"question": "app-bootstrap의 main 프로젝트 의존에 포함된 어댑터와 의존 목록 밖의 opt-in 참조 어댑터는 어떻게 구분되는가?",
"type": "concept",
"direction": "LR",
"audience": [
"멀티모듈 Spring Boot 애플리케이션 설계자",
"클린 아키텍처 구현 독자"
],
"summary": "main 프로젝트 의존은 어댑터 11개를 클래스패스에 올리고, grpc·graphql·websocket 세 참조 어댑터는 의존성을 선언하지 않는 방식으로 opt-in한다.",
"alt": "왼쪽의 app-bootstrap main 의존 포함 어댑터 11개와 오른쪽의 main 의존 목록 밖 grpc·graphql·websocket 세 개를 비교한 그림. 클래스패스 구성 비교이며 활성 빈 수를 뜻하지 않는다.",
"long_description": "왼쪽 비교 항목은 app-bootstrap의 main 프로젝트 의존에 포함되어 main 클래스패스에 들어오는 어댑터 11개를 나타낸다. 클래스패스 포함과 실제 빈 활성화는 별개이며 런타임 조건이 활성화를 추가로 결정한다. 오른쪽 비교 항목은 현재 main 의존 목록에 없는 grpc, graphql, websocket 세 참조 어댑터를 나타낸다. 이 셋은 클래스패스에 등록되면 기본 활성화되므로 의존성 선언을 하지 않는 것이 opt-in 수단이다. 두 수치는 main 의존 선언을 비교한 것이며 실행 시 활성 빈 전체를 측정한 값이 아니다.",
"source_context": {
"document": "/home/donghyeon/workspace/ai-tool/topic-arrange/executable-clean-architecture/claridoc-rewrite/document.md",
"document_sha256": "81fb5cb8cd16eaae6916a0d0f2b3cddfabc39e58a87559466b52f922ca95a95b",
"anchor": {
"kind": "marker",
"value": "production-vs-optin",
"line": 502
}
},
"composition": {
"profile": "comparison",
"diagram_only": true,
"reference_ids": [
"contract-comparison"
],
"rationale": "본문이 main 프로젝트 의존에 포함된 집합과 의존 목록 밖의 opt-in 집합을 명시적으로 비교하므로, 호출 관계나 시간 순서를 만들지 않고 같은 필드로 두 집합을 정렬하는 비교 문법이 독자의 질문에 가장 직접적으로 답한다."
},
"groups": [],
"nodes": [
{
"id": "main-classpath-adapters",
"label": "main 의존 포함 · 11",
"kind": "concept",
"role": "option",
"description": "app-bootstrap의 main 프로젝트 의존에 포함되어 main 클래스패스에 들어오는 어댑터 집합",
"details": [
"수량: 11개",
"프로젝트 의존: 선언됨",
"클래스패스: 포함",
"어댑터: 포함 대상 11개",
"활성화: 클래스패스와 별도",
"측정 범위: main 의존 선언"
],
"emphasis": "primary",
"evidence": [
{
"start_line": 449,
"end_line": 456
},
{
"start_line": 476,
"end_line": 480
},
{
"start_line": 500,
"end_line": 501
},
{
"start_line": 517,
"end_line": 517
}
],
"assumption": false
},
{
"id": "omitted-optin-adapters",
"label": "main 의존 목록 밖 · 3",
"kind": "concept",
"role": "option",
"description": "저장소에는 있지만 app-bootstrap의 main 프로젝트 의존에는 선언되지 않은 참조 어댑터 집합",
"details": [
"수량: 3개",
"프로젝트 의존: 선언하지 않음",
"클래스패스: 제외",
"어댑터: grpc · graphql · websocket",
"활성화: 등록하면 기본 활성",
"측정 범위: main 의존 선언"
],
"emphasis": "warning",
"evidence": [
{
"start_line": 481,
"end_line": 489
},
{
"start_line": 500,
"end_line": 501
},
{
"start_line": 517,
"end_line": 517
}
],
"assumption": false
}
],
"edges": [],
"legend": [],
"metadata": {
"rationale": "14개 어댑터를 각각 카드로 반복하면 비교 필드가 흐려지고 밀도 예산을 넘으므로, 두 집합을 수량·의존 상태·클래스패스 상태·활성화 의미·측정 범위로 정렬했다."
}
}
@@ -1,51 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="610" viewBox="0 0 1280 610" role="img" aria-labelledby="title desc">
<title id="title">Layered architecture boundary problem</title>
<desc id="desc">Four technical layers depend downward; the business layer is consequently tied to database technology.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1280" height="610" fill="#FFFFFF"/>
<rect x="300" y="55" width="600" height="82" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="600" y="90" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">Presentation</text>
<text x="600" y="115" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">Controller · View</text>
<rect x="300" y="175" width="600" height="82" fill="#EAF3FF" stroke="#0B5CC4" stroke-width="2" rx="8" />
<text x="600" y="210" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">Business Logic</text>
<text x="600" y="235" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">Service · 도메인 규칙</text>
<rect x="300" y="295" width="600" height="82" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="600" y="330" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">Data Access</text>
<text x="600" y="355" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">Repository · DAO</text>
<rect x="470" y="435" width="260" height="85" fill="#F6F7F9" />
<ellipse cx="600" cy="435" rx="130" ry="10" fill="#F6F7F9" stroke="#59616B" stroke-width="1.6" />
<path d="M 470 435 L 470 520" fill="none" stroke="#59616B" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" />
<path d="M 730 435 L 730 520" fill="none" stroke="#59616B" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" />
<path d="M 470 520 C 522 532, 678 532, 730 520" fill="none" stroke="#59616B" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" />
<text x="600" y="479.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="15" font-weight="700" fill="#25282D" text-anchor="middle">Database</text>
<text x="600" y="500.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="450" fill="#667085" text-anchor="middle">기술 저장소</text>
<path d="M 600 137 L 600 175" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-ink)" />
<rect x="636.6" y="146" width="76.7" height="20" fill="#FFFFFF" rx="2" />
<text x="675" y="162" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">depends on</text>
<path d="M 600 257 L 600 295" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-ink)" />
<rect x="636.6" y="266" width="76.7" height="20" fill="#FFFFFF" rx="2" />
<text x="675" y="282" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">depends on</text>
<path d="M 600 377 L 600 425" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-ink)" />
<rect x="636.6" y="391" width="76.7" height="20" fill="#FFFFFF" rx="2" />
<text x="675" y="407" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">depends on</text>
<rect x="975" y="182" width="250" height="150" fill="#FDEDEF" stroke="#D64550" stroke-width="1.6" rx="10" />
<text x="1100" y="222" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="800" fill="#D64550" text-anchor="middle">문제</text>
<text x="1100" y="255" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="15" font-weight="650" fill="#25282D" text-anchor="middle">
<tspan x="1100" dy="0">도메인이 기술에 묶인다</tspan>
<tspan x="1100" dy="21">경계가 컴파일러에</tspan>
<tspan x="1100" dy="21">보이지 않는다</tspan>
</text>
<path d="M 900 216 L 975 216" fill="none" stroke="#D64550" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-red)" />
<rect x="888.6" y="183" width="98.8" height="20" fill="#FFFFFF" rx="2" />
<text x="938" y="199" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#D64550" text-anchor="middle">DB·기술에 종속</text>
</svg>

Before

Width:  |  Height:  |  Size: 6.6 KiB

@@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="650" viewBox="0 0 1440 650" role="img" aria-labelledby="title desc">
<title id="title">Three architecture lenses</title>
<desc id="desc">Layered, Hexagonal, and Clean are shown as three distinct views of the same inward dependency rule.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1440" height="650" fill="#FFFFFF"/>
<rect x="40" y="45" width="420" height="455" fill="#FFFFFF" stroke="#8A919A" stroke-width="1.4" rx="10" />
<text x="250" y="88" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="19" font-weight="750" fill="#25282D" text-anchor="middle">Layered</text>
<text x="250" y="116" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="500" fill="#667085" text-anchor="middle">기술 책임을 층으로</text>
<rect x="500" y="45" width="420" height="455" fill="#FFFFFF" stroke="#8A919A" stroke-width="1.4" rx="10" />
<text x="710" y="88" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="19" font-weight="750" fill="#25282D" text-anchor="middle">Hexagonal</text>
<text x="710" y="116" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="500" fill="#667085" text-anchor="middle">상호작용 경계를 포트로</text>
<rect x="960" y="45" width="420" height="455" fill="#FFFFFF" stroke="#8A919A" stroke-width="1.4" rx="10" />
<text x="1170" y="88" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="19" font-weight="750" fill="#25282D" text-anchor="middle">Clean</text>
<text x="1170" y="116" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="500" fill="#667085" text-anchor="middle">정책 수준을 동심원으로</text>
<rect x="105" y="160" width="290" height="60" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="250" y="195" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">Presentation</text>
<path d="M 250 220 L 250 252" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="105" y="252" width="290" height="60" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="250" y="287" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">Application</text>
<path d="M 250 312 L 250 344" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="105" y="344" width="290" height="60" fill="#EAF7F1" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="250" y="379" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">Domain</text>
<polygon points="630,165 830,165 890,300 830,435 630,435 570,300" fill="#EAF3FF" stroke="#1677FF" stroke-width="2" />
<text x="730" y="292" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="18" font-weight="750" fill="#0B5CC4" text-anchor="middle">Core</text>
<circle cx="580" cy="300" r="8" fill="#FFFFFF" stroke="#1677FF" stroke-width="2" />
<circle cx="880" cy="300" r="8" fill="#FFFFFF" stroke="#1677FF" stroke-width="2" />
<path d="M 525 300 L 570 300" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<path d="M 890 300 L 935 300" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<text x="730" y="390" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="650" fill="#667085" text-anchor="middle">ports</text>
<circle cx="1170" cy="300" r="150" fill="#F6F7F9" stroke="#858B94" stroke-width="1.6" />
<circle cx="1170" cy="300" r="105" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.8" />
<circle cx="1170" cy="300" r="55" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.8" />
<text x="1170" y="305" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="750" fill="#168A5B" text-anchor="middle">Policy</text>
<text x="1170" y="235" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="650" fill="#0B5CC4" text-anchor="middle">Use cases</text>
<text x="1170" y="175" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="650" fill="#667085" text-anchor="middle">Frameworks</text>
<path d="M 1310 300 L 1230 300" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="410" y="545" width="620" height="60" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.6" rx="30" />
<text x="720" y="582" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="18" font-weight="750" fill="#0B5CC4" text-anchor="middle">한 규칙 · 의존은 안쪽으로만</text>
</svg>

Before

Width:  |  Height:  |  Size: 6.8 KiB

-75
View File
@@ -1,75 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1480" height="760" viewBox="0 0 1480 760" role="img" aria-labelledby="title desc">
<title id="title">Executable clean architecture module picture</title>
<desc id="desc">Inbound and outbound adapters point to application-core, which depends independently on domain-core and shared-contract; app-bootstrap wires the application.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1480" height="760" fill="#FFFFFF"/>
<polygon points="535,190 895,190 975,365 895,540 535,540 455,365" fill="#EAF3FF" stroke="#1677FF" stroke-width="2.2" />
<text x="715" y="265" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="22" font-weight="750" fill="#0B5CC4" text-anchor="middle">application-core</text>
<text x="715" y="296" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="500" fill="#667085" text-anchor="middle">use cases · ports</text>
<rect x="555" y="355" width="235" height="82" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.5" rx="8" />
<text x="672.5" y="390" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">domain-core</text>
<text x="672.5" y="415" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">main 의존 0</text>
<rect x="805" y="355" width="235" height="82" fill="#FFFFFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="922.5" y="390" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">shared-contract</text>
<text x="922.5" y="415" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">main 의존 0</text>
<text x="797" y="477" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="600" fill="#667085" text-anchor="middle">서로 직접 의존하지 않음</text>
<rect x="35" y="215" width="330" height="330" fill="#FBFCFE" stroke="#AEB5BF" stroke-width="1.3" rx="10" />
<rect x="44" y="204" width="120.7" height="20" fill="#FFFFFF" rx="2" />
<text x="51" y="220" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#667085" text-anchor="start">Inbound 어댑터 ×4</text>
<rect x="75" y="270" width="250" height="44" fill="#FFFFFF" stroke="#69717B" stroke-width="1.5" rx="8" />
<text x="200" y="297" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">web</text>
<rect x="75" y="332" width="250" height="44" fill="#FFFFFF" stroke="#69717B" stroke-width="1.5" rx="8" />
<text x="200" y="359" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">batch</text>
<rect x="75" y="394" width="250" height="44" fill="#FFFFFF" stroke="#69717B" stroke-width="1.5" rx="8" />
<text x="200" y="421" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">messaging-in</text>
<rect x="75" y="456" width="250" height="44" fill="#FFFFFF" stroke="#69717B" stroke-width="1.5" rx="8" />
<text x="200" y="483" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">scheduler</text>
<rect x="1115" y="100" width="330" height="500" fill="#FBFCFE" stroke="#AEB5BF" stroke-width="1.3" rx="10" />
<rect x="1124" y="89" width="133.2" height="20" fill="#FFFFFF" rx="2" />
<text x="1131" y="105" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#667085" text-anchor="start">Outbound 어댑터 ×10</text>
<rect x="1155" y="155" width="250" height="46" fill="#FFFFFF" stroke="#69717B" stroke-width="1.5" rx="8" />
<text x="1280" y="183" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">persistence</text>
<rect x="1155" y="221" width="250" height="46" fill="#FFFFFF" stroke="#69717B" stroke-width="1.5" rx="8" />
<text x="1280" y="249" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">object storage</text>
<rect x="1155" y="287" width="250" height="46" fill="#FFFFFF" stroke="#69717B" stroke-width="1.5" rx="8" />
<text x="1280" y="315" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">notification</text>
<rect x="1155" y="353" width="250" height="46" fill="#FFFFFF" stroke="#69717B" stroke-width="1.5" rx="8" />
<text x="1280" y="381" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">cache</text>
<rect x="1155" y="419" width="250" height="46" fill="#FFFFFF" stroke="#69717B" stroke-width="1.5" rx="8" />
<text x="1280" y="447" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">messaging</text>
<rect x="1155" y="485" width="250" height="46" fill="#FFFFFF" stroke="#69717B" stroke-width="1.5" rx="8" />
<text x="1280" y="513" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">http client</text>
<path d="M 365 365 L 455 365" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="371.6" y="340" width="76.7" height="20" fill="#FFFFFF" rx="2" />
<text x="410" y="356" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Depends on</text>
<path d="M 1115 365 L 975 365" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="1006.6" y="340" width="76.7" height="20" fill="#FFFFFF" rx="2" />
<text x="1045" y="356" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Depends on</text>
<path d="M 715 330 L 672 355" fill="none" stroke="#168A5B" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-green)" />
<rect x="599.6" y="318" width="76.7" height="20" fill="#FFFFFF" rx="2" />
<text x="638" y="334" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#168A5B" text-anchor="middle">Depends on</text>
<path d="M 780 330 L 855 355" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-purple)" />
<rect x="845.6" y="318" width="76.7" height="20" fill="#FFFFFF" rx="2" />
<text x="884" y="334" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">Depends on</text>
<rect x="630" y="35" width="290" height="105" fill="#FFFFFF" stroke="#59616B" stroke-width="1.6" rx="3" />
<path d="M 630 70 L 920 70" fill="none" stroke="#59616B" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" />
<path d="M 630 105 L 920 105" fill="none" stroke="#59616B" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" />
<circle cx="648" cy="52.5" r="4" fill="#1677FF" />
<circle cx="648" cy="87.5" r="4" fill="#1677FF" />
<circle cx="648" cy="122.5" r="4" fill="#1677FF" />
<text x="775" y="92.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="15" font-weight="700" fill="#25282D" text-anchor="middle">app-bootstrap</text>
<text x="775" y="166" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="600" fill="#667085" text-anchor="middle">조립 루트</text>
<path d="M 775 140 L 775 190" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-ink)" />
<rect x="827.3" y="169" width="45.3" height="20" fill="#FFFFFF" rx="2" />
<text x="850" y="185" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">Wires</text>
</svg>

Before

Width:  |  Height:  |  Size: 10 KiB

@@ -1,58 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1380" height="700" viewBox="0 0 1380 700" role="img" aria-labelledby="title desc">
<title id="title">Boundary enforcement comparison</title>
<desc id="desc">A two-by-two parallel comparison of four structures and their available boundary enforcement mechanisms; it is not a progression.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1380" height="700" fill="#FFFFFF"/>
<rect x="520" y="28" width="239.3" height="30" fill="#F6F7F9" stroke="#AEB5BF" stroke-width="1.2" rx="15" />
<text x="639.6" y="48" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#667085" text-anchor="middle">2×2 병렬 비교 · 진행 단계 아님</text>
<rect x="50" y="95" width="620" height="245" fill="#FFFFFF" stroke="#757C85" stroke-width="1.4" rx="10" />
<rect x="50" y="95" width="9" height="245" fill="#D64550" rx="4" />
<text x="84" y="138" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="19" font-weight="750" fill="#25282D" text-anchor="start">단일모듈 Layered</text>
<text x="84" y="165" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="550" fill="#667085" text-anchor="start">설명용 검출 예시</text>
<text x="105" y="213" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="500" fill="#25282D" text-anchor="start">
<tspan x="105" dy="0">• 도메인 → JPA 타입</tspan>
<tspan x="105" dy="21.7">• 공유 클래스패스</tspan>
</text>
<rect x="400" y="265" width="116.8" height="30" fill="#F6F7F9" stroke="#D64550" stroke-width="1.2" rx="15" />
<text x="458.4" y="285" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#D64550" text-anchor="middle">경계 장치 없음</text>
<rect x="710" y="95" width="620" height="245" fill="#FFFFFF" stroke="#757C85" stroke-width="1.4" rx="10" />
<rect x="710" y="95" width="9" height="245" fill="#B7791F" rx="4" />
<text x="744" y="138" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="19" font-weight="750" fill="#25282D" text-anchor="start">단일모듈 Clean</text>
<text x="744" y="165" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="550" fill="#667085" text-anchor="start">별도 규칙 필요</text>
<text x="765" y="213" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="500" fill="#25282D" text-anchor="start">
<tspan x="765" dy="0">• 패키지 경계</tspan>
<tspan x="765" dy="21.7">• 위반 타입은 여전히 보임</tspan>
</text>
<rect x="1060" y="265" width="116.7" height="30" fill="#FFFFFF" stroke="#B7791F" stroke-width="1.2" rx="15" />
<text x="1118.3" y="285" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#B7791F" text-anchor="middle">ArchUnit 필요</text>
<rect x="50" y="385" width="620" height="245" fill="#FFFFFF" stroke="#757C85" stroke-width="1.4" rx="10" />
<rect x="50" y="385" width="9" height="245" fill="#1677FF" rx="4" />
<text x="84" y="428" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="19" font-weight="750" fill="#25282D" text-anchor="start">멀티모듈 Clean</text>
<text x="84" y="455" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="550" fill="#667085" text-anchor="start">클래스패스 격리 가능</text>
<text x="105" y="503" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="500" fill="#25282D" text-anchor="start">
<tspan x="105" dy="0">• 모듈별 classpath</tspan>
<tspan x="105" dy="21.7">• 금지 타입 자체가 없음</tspan>
</text>
<rect x="400" y="555" width="94.5" height="30" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.2" rx="15" />
<text x="447.2" y="575" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#1677FF" text-anchor="middle">javac 차단</text>
<rect x="710" y="385" width="620" height="245" fill="#FFFFFF" stroke="#757C85" stroke-width="1.4" rx="10" />
<rect x="710" y="385" width="9" height="245" fill="#168A5B" rx="4" />
<text x="744" y="428" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="19" font-weight="750" fill="#25282D" text-anchor="start">정책·테스트 설치 Clean</text>
<text x="744" y="455" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="550" fill="#667085" text-anchor="start">명시 규칙 강제</text>
<text x="765" y="503" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="500" fill="#25282D" text-anchor="start">
<tspan x="765" dy="0">• Gradle 의존 정책</tspan>
<tspan x="765" dy="21.7">• ArchUnit · test-the-test</tspan>
</text>
<rect x="1060" y="555" width="96.4" height="30" fill="#FFFFFF" stroke="#168A5B" stroke-width="1.2" rx="15" />
<text x="1108.2" y="575" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#168A5B" text-anchor="middle">복수 게이트</text>
</svg>

Before

Width:  |  Height:  |  Size: 6.9 KiB

@@ -1,90 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1460" height="760" viewBox="0 0 1460 760" role="img" aria-labelledby="title desc">
<title id="title">System boundary integrations and seams</title>
<desc id="desc">Four implemented or configured external paths use solid arrows; three project-supplied extension seams use dashed arrows.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1460" height="760" fill="#FFFFFF"/>
<rect x="35" y="45" width="1390" height="670" fill="#FBFCFE" stroke="#AEB5BF" stroke-width="1.3" rx="10" />
<rect x="44" y="34" width="219.7" height="20" fill="#FFFFFF" rx="2" />
<text x="51" y="50" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#667085" text-anchor="start">시스템 경계 · 구현 경로와 확장 seam</text>
<rect x="90" y="82" width="313.6" height="30" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.2" rx="15" />
<text x="246.8" y="102" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#0B5CC4" text-anchor="middle">실선 = 구현·설정 경로 존재 · 활성 런타임 아님</text>
<rect x="780" y="82" width="236.4" height="30" fill="#FFFFFF" stroke="#7556D8" stroke-width="1.2" rx="15" />
<text x="898.2" y="102" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#7556D8" text-anchor="middle">점선 = 프로젝트가 공급할 확장 seam</text>
<rect x="95" y="170" width="250" height="72" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="220" y="211" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">persistence-jpa</text>
<rect x="515" y="178" width="220" height="58" fill="#EAF3FF" />
<ellipse cx="625" cy="178" rx="110" ry="10" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.6" />
<path d="M 515 178 L 515 236" fill="none" stroke="#1677FF" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" />
<path d="M 735 178 L 735 236" fill="none" stroke="#1677FF" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" />
<path d="M 515 236 C 559 248, 691 248, 735 236" fill="none" stroke="#1677FF" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" />
<text x="625" y="209" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="15" font-weight="700" fill="#25282D" text-anchor="middle">PostgreSQL</text>
<text x="625" y="230" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="450" fill="#667085" text-anchor="middle">드라이버 · dialect</text>
<path d="M 345 206 L 515 206" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="395.5" y="181" width="69" height="20" fill="#FFFFFF" rx="2" />
<text x="430" y="197" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">구현·설정</text>
<rect x="95" y="295" width="250" height="72" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="220" y="336" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">persistence-mongo</text>
<rect x="515" y="303" width="220" height="58" fill="#EAF3FF" />
<ellipse cx="625" cy="303" rx="110" ry="10" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.6" />
<path d="M 515 303 L 515 361" fill="none" stroke="#1677FF" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" />
<path d="M 735 303 L 735 361" fill="none" stroke="#1677FF" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" />
<path d="M 515 361 C 559 373, 691 373, 735 361" fill="none" stroke="#1677FF" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" />
<text x="625" y="334" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="15" font-weight="700" fill="#25282D" text-anchor="middle">MongoDB</text>
<text x="625" y="355" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="450" fill="#667085" text-anchor="middle">opt-in 스캐폴드</text>
<path d="M 345 331 L 515 331" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="395.5" y="306" width="69" height="20" fill="#FFFFFF" rx="2" />
<text x="430" y="322" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">구현·설정</text>
<rect x="95" y="420" width="250" height="72" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="220" y="461" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">objectstorage</text>
<rect x="515" y="420" width="220" height="72" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="625" y="450" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">S3 / MinIO</text>
<text x="625" y="475" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">선택형 백엔드</text>
<path d="M 345 456 L 515 456" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="395.5" y="431" width="69" height="20" fill="#FFFFFF" rx="2" />
<text x="430" y="447" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">구현·설정</text>
<rect x="95" y="545" width="250" height="72" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="220" y="586" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">fileserver</text>
<polygon points="535,533 679,533 715,569 715,625 535,625" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.7" />
<path d="M 679 533 L 679 569 L 715 569" fill="none" stroke="#1677FF" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" />
<text x="553" y="569" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="15" font-weight="700" fill="#25282D" text-anchor="start">파일시스템</text>
<text x="553" y="598" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="500" fill="#667085" text-anchor="start">
<tspan x="553" dy="0">구현 경로</tspan>
</text>
<path d="M 345 581 L 515 581" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="395.5" y="556" width="69" height="20" fill="#FFFFFF" rx="2" />
<text x="430" y="572" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">구현·설정</text>
<rect x="820" y="220" width="235" height="75" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="937.5" y="262.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">notification</text>
<circle cx="1180" cy="257" r="10" fill="#FFFFFF" stroke="#7556D8" stroke-width="2" />
<rect x="1210" y="220" width="170" height="75" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="1295" y="262.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">SlackClient seam</text>
<path d="M 1055 257 L 1170 257" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="7 5" marker-end="url(#arrow-purple)" />
<rect x="1093.0" y="232" width="39.1" height="20" fill="#FFFFFF" rx="2" />
<text x="1112.5" y="248" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">seam</text>
<rect x="820" y="370" width="235" height="75" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="937.5" y="412.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">cache-redis</text>
<circle cx="1180" cy="407" r="10" fill="#FFFFFF" stroke="#7556D8" stroke-width="2" />
<rect x="1210" y="370" width="170" height="75" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="1295" y="412.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">RedisClient seam</text>
<path d="M 1055 407 L 1170 407" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="7 5" marker-end="url(#arrow-purple)" />
<rect x="1093.0" y="382" width="39.1" height="20" fill="#FFFFFF" rx="2" />
<text x="1112.5" y="398" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">seam</text>
<rect x="820" y="520" width="235" height="75" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="937.5" y="562.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">messaging</text>
<circle cx="1180" cy="557" r="10" fill="#FFFFFF" stroke="#7556D8" stroke-width="2" />
<rect x="1210" y="520" width="170" height="75" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="1295" y="562.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">KafkaSender seam</text>
<path d="M 1055 557 L 1170 557" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="7 5" marker-end="url(#arrow-purple)" />
<rect x="1093.0" y="532" width="39.1" height="20" fill="#FFFFFF" rx="2" />
<text x="1112.5" y="548" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">seam</text>
</svg>

Before

Width:  |  Height:  |  Size: 12 KiB

@@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="530" viewBox="0 0 1440 530" role="img" aria-labelledby="title desc">
<title id="title">Package organization spectrum</title>
<desc id="desc">A single axis places layer-first and feature-first at its ends and marks ca-tmpl as a hybrid supported by both feature and technical package evidence.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1440" height="530" fill="#FFFFFF"/>
<path d="M 100 255 L 1340 255" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-ink)" />
<circle cx="120" cy="255" r="9" fill="#FFFFFF" stroke="#667085" stroke-width="2" />
<path d="M 120 180 L 120 330" fill="none" stroke="#667085" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<text x="120" y="160" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="750" fill="#667085" text-anchor="middle">layer-first</text>
<text x="120" y="358" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="550" fill="#667085" text-anchor="middle">기술 책임 중심</text>
<circle cx="480" cy="255" r="9" fill="#FFFFFF" stroke="#25282D" stroke-width="2" />
<path d="M 480 180 L 480 330" fill="none" stroke="#25282D" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<text x="480" y="160" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="750" fill="#25282D" text-anchor="middle">계층 소유 코어·어댑터</text>
<text x="480" y="358" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="550" fill="#667085" text-anchor="middle">구조 경계</text>
<circle cx="860" cy="255" r="13" fill="#1677FF" stroke="#1677FF" stroke-width="2" />
<path d="M 860 180 L 860 330" fill="none" stroke="#1677FF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
<text x="860" y="160" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="15" font-weight="750" fill="#1677FF" text-anchor="middle">ca-tmpl · hybrid</text>
<text x="860" y="358" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="550" fill="#667085" text-anchor="middle">현재 저장소 배치</text>
<circle cx="1320" cy="255" r="9" fill="#FFFFFF" stroke="#667085" stroke-width="2" />
<path d="M 1320 180 L 1320 330" fill="none" stroke="#667085" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<text x="1320" y="160" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="750" fill="#667085" text-anchor="middle">feature-first</text>
<text x="1320" y="358" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="550" fill="#667085" text-anchor="middle">기능 응집 중심</text>
<rect x="590" y="380" width="250" height="70" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.5" rx="8" />
<text x="715" y="409" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">application.worklog</text>
<text x="715" y="434" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">기능 패키지</text>
<rect x="880" y="380" width="250" height="70" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="1005" y="409" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">web.controller</text>
<text x="1005" y="434" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">기술 패키지</text>
<path d="M 715 380 L 820 280" fill="none" stroke="#168A5B" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-green)" />
<rect x="666.0" y="299" width="108.0" height="20" fill="#FFFFFF" rx="2" />
<text x="720" y="315" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#168A5B" text-anchor="middle">supports hybrid</text>
<path d="M 1005 380 L 900 280" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-purple)" />
<rect x="956.0" y="299" width="108.0" height="20" fill="#FFFFFF" rx="2" />
<text x="1010" y="315" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">supports hybrid</text>
</svg>

Before

Width:  |  Height:  |  Size: 6.3 KiB

@@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1420" height="560" viewBox="0 0 1420 560" role="img" aria-labelledby="title desc">
<title id="title">Spring Modulith evidence and decision boundary</title>
<desc id="desc">A fixed Gradle-script search establishes zero Spring Modulith dependency declarations; adoption remains a separate conditional evaluation.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1420" height="560" fill="#FFFFFF"/>
<rect x="45" y="65" width="800" height="420" fill="#FBFCFE" stroke="#1677FF" stroke-width="1.3" rx="10" />
<rect x="54" y="54" width="142.8" height="20" fill="#FFFFFF" rx="2" />
<text x="61" y="70" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#0B5CC4" text-anchor="start">확정 가능한 저장소 사실</text>
<polygon points="95,155 344,155 380,191 380,345 95,345" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.7" />
<path d="M 344 155 L 344 191 L 380 191" fill="none" stroke="#1677FF" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" />
<text x="113" y="191" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="15" font-weight="700" fill="#0B5CC4" text-anchor="start">검색 범위</text>
<text x="113" y="220" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="500" fill="#667085" text-anchor="start">
<tspan x="113" dy="0">고정된 Gradle</tspan>
<tspan x="113" dy="17.4">빌드 스크립트 전체</tspan>
</text>
<circle cx="605" cy="250" r="92" fill="#EAF3FF" stroke="#1677FF" stroke-width="2" />
<text x="605" y="240" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="32" font-weight="800" fill="#0B5CC4" text-anchor="middle">0건</text>
<text x="605" y="275" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#0B5CC4" text-anchor="middle">Spring Modulith</text>
<text x="605" y="300" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="600" fill="#667085" text-anchor="middle">의존 선언</text>
<path d="M 380 250 L 513 250" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="414.4" y="225" width="64.3" height="20" fill="#FFFFFF" rx="2" />
<text x="446.5" y="241" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">전체 검색</text>
<path d="M 915 75 L 915 485" fill="none" stroke="#AEB5BF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="7 6" />
<rect x="880.6" y="88" width="68.8" height="21" fill="#FFFFFF" rx="2" />
<text x="915" y="105" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="650" fill="#667085" text-anchor="middle">판단 경계</text>
<rect x="985" y="115" width="390" height="320" fill="#FBFCFE" stroke="#7556D8" stroke-width="1.3" rx="10" stroke-dasharray="7 6" />
<rect x="994" y="104" width="64.3" height="20" fill="#FFFFFF" rx="2" />
<text x="1001" y="120" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="start">별도 평가</text>
<rect x="1040" y="205" width="280" height="100" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="1180" y="249" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">채택 여부</text>
<text x="1180" y="273" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">
<tspan x="1180" dy="0">별도 근거로</tspan>
<tspan x="1180" dy="16.2">조건부 평가</tspan>
</text>
<path d="M 697 250 L 870 250 L 870 365 L 1040 365" fill="none" stroke="#7556D8" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="7 5" />
<path d="M 901 351 L 929 379" fill="none" stroke="#7556D8" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
<path d="M 929 351 L 901 379" fill="none" stroke="#7556D8" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
<text x="1180" y="375" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="650" fill="#667085" text-anchor="middle">0건만으로 채택 결론을 내리지 않음</text>
</svg>

Before

Width:  |  Height:  |  Size: 6.1 KiB

@@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1500" height="780" viewBox="0 0 1500 780" role="img" aria-labelledby="title desc">
<title id="title">Complementary enforcement scopes</title>
<desc id="desc">Five partially overlapping enforcement scopes surround boundary violations without implying a fixed order or speed ranking.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1500" height="780" fill="#FFFFFF"/>
<rect x="545" y="25" width="276.5" height="30" fill="#F6F7F9" stroke="#AEB5BF" stroke-width="1.2" rx="15" />
<text x="683.2" y="45" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#667085" text-anchor="middle">독립·보완 범위 · 고정 실행 순서 없음</text>
<circle cx="750" cy="420" r="105" fill="#FDEDEF" stroke="#D64550" stroke-width="1.8" />
<text x="750" y="410" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="20" font-weight="800" fill="#D64550" text-anchor="middle">경계 위반</text>
<text x="750" y="440" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="600" fill="#667085" text-anchor="middle">종류별 검출 표면</text>
<ellipse cx="470" cy="275" rx="255" ry="150" fill="none" stroke="#1677FF" stroke-width="1.8" />
<rect x="443.1" y="131" width="53.9" height="23" fill="#FFFFFF" stroke="#1677FF" stroke-width="1" rx="2" />
<text x="470" y="150" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="650" fill="#1677FF" text-anchor="middle">javac</text>
<text x="470" y="178" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="600" fill="#667085" text-anchor="middle">클래스패스 범위</text>
<ellipse cx="745" cy="225" rx="285" ry="135" fill="none" stroke="#1677FF" stroke-width="1.8" />
<rect x="714.1" y="96" width="61.9" height="23" fill="#FFFFFF" stroke="#1677FF" stroke-width="1" rx="2" />
<text x="745" y="115" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="650" fill="#1677FF" text-anchor="middle">Gradle</text>
<text x="745" y="143" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="600" fill="#667085" text-anchor="middle">project dependency 범위</text>
<ellipse cx="950" cy="415" rx="285" ry="145" fill="none" stroke="#1677FF" stroke-width="1.8" />
<rect x="1011.1" y="281" width="77.8" height="23" fill="#FFFFFF" stroke="#1677FF" stroke-width="1" rx="2" />
<text x="1050" y="300" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="650" fill="#1677FF" text-anchor="middle">ArchUnit</text>
<text x="1050" y="328" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="600" fill="#667085" text-anchor="middle">구조 규칙 범위</text>
<ellipse cx="730" cy="590" rx="300" ry="120" fill="none" stroke="#1677FF" stroke-width="1.8" />
<rect x="671.1" y="671" width="117.7" height="23" fill="#FFFFFF" stroke="#1677FF" stroke-width="1" rx="2" />
<text x="730" y="690" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="650" fill="#1677FF" text-anchor="middle">test-the-test</text>
<text x="730" y="718" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="600" fill="#667085" text-anchor="middle">비공허성 범위</text>
<ellipse cx="320" cy="485" rx="310" ry="145" fill="none" stroke="#7556D8" stroke-width="1.8" />
<rect x="193.0" y="351" width="114.0" height="23" fill="#FFFFFF" stroke="#7556D8" stroke-width="1" rx="2" />
<text x="250" y="370" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="650" fill="#7556D8" text-anchor="middle">리뷰 · 런타임</text>
<text x="250" y="398" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="600" fill="#667085" text-anchor="middle">정적 규칙 밖 범위</text>
</svg>

Before

Width:  |  Height:  |  Size: 5.6 KiB

@@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="620" viewBox="0 0 1440 620" role="img" aria-labelledby="title desc">
<title id="title">Feed query ports and adapters</title>
<desc id="desc">FeedController calls the concrete GetFeedUseCase; the application core owns FeedQueryPort, implemented by FeedQueryAdapter.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1440" height="620" fill="#FFFFFF"/>
<polygon points="490,75 880,75 980,310 880,545 490,545 390,310" fill="#EAF3FF" stroke="#1677FF" stroke-width="2.3" />
<text x="685" y="125" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#0B5CC4" text-anchor="middle" letter-spacing="0.8">application-core</text>
<rect x="540" y="205" width="290" height="120" fill="#FFFFFF" stroke="#0B5CC4" stroke-width="1.8" rx="8" />
<text x="685" y="259" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">GetFeedUseCase</text>
<text x="685" y="283" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">
<tspan x="685" dy="0">concrete service</tspan>
<tspan x="685" dy="16.2">implements QueryUseCase&lt;Q,R&gt;</tspan>
</text>
<circle cx="400" cy="310" r="10" fill="#FFFFFF" stroke="#1677FF" stroke-width="2" />
<circle cx="970" cy="310" r="10" fill="#FFFFFF" stroke="#1677FF" stroke-width="2" />
<text x="410" y="285" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#0B5CC4" text-anchor="start">input boundary</text>
<text x="960" y="285" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#0B5CC4" text-anchor="end">FeedQueryPort</text>
<rect x="55" y="245" width="280" height="105" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="195" y="291.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">FeedController</text>
<text x="195" y="316.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">driving adapter</text>
<rect x="1060" y="245" width="300" height="105" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="1210" y="291.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">FeedQueryAdapter</text>
<text x="1210" y="316.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">driven adapter · implements port</text>
<path d="M 335 298 L 390 310" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="309.1" y="264" width="101.8" height="20" fill="#FFFFFF" rx="2" />
<text x="360" y="280" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Calls concrete</text>
<path d="M 830 265 L 925 265 L 925 310 L 960 310" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="839.7" y="232" width="120.6" height="20" fill="#FFFFFF" rx="2" />
<text x="900" y="248" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Calls output port</text>
<path d="M 1060 298 L 980 310" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="7 5" marker-end="url(#arrow-purple)" />
<rect x="986.6" y="264" width="76.7" height="20" fill="#FFFFFF" rx="2" />
<text x="1025" y="280" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">Implements</text>
<rect x="570" y="385" width="318.5" height="30" fill="#FFFFFF" stroke="#A8BCE0" stroke-width="1.2" rx="15" />
<text x="729.2" y="405" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#667085" text-anchor="middle">QueryUseCase&lt;Q,R&gt;는 별도 객체가 아닌 구현 계약</text>
</svg>

Before

Width:  |  Height:  |  Size: 6.0 KiB

@@ -1,144 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1640" height="1060" viewBox="0 0 1640 1060" role="img" aria-labelledby="title desc">
<title id="title">Idempotency execution branches</title>
<desc id="desc">One deadline feeds two waiting entry points and four normal decisions; a separate claimed-execution lane shows RuntimeException cleanup outcomes.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1640" height="1060" fill="#FFFFFF"/>
<rect x="25" y="35" width="1590" height="625" fill="#FBFCFE" stroke="#AEB5BF" stroke-width="1.3" rx="10" />
<rect x="34" y="24" width="299.7" height="20" fill="#FFFFFF" rx="2" />
<text x="41" y="40" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#667085" text-anchor="start">정상 결정 · 두 대기 진입점과 단일 200ms deadline</text>
<rect x="55" y="95" width="260" height="72" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="185" y="136" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">execute(context, action, codec)</text>
<rect x="360" y="115" width="178.0" height="30" fill="#FFF7E5" stroke="#B7791F" stroke-width="1.2" rx="15" />
<text x="449.0" y="135" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#B7791F" text-anchor="middle">deadline = 시작 + 200ms</text>
<rect x="625" y="95" width="210" height="72" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="730" y="136" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">store.find(scope, now)</text>
<path d="M 315 131 L 360 131" fill="none" stroke="#B7791F" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-amber)" />
<rect x="302.2" y="106" width="70.5" height="20" fill="#FFFFFF" rx="2" />
<text x="337.5" y="122" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#B7791F" text-anchor="middle">초기화 1회</text>
<path d="M 560 131 L 625 131" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-ink)" />
<rect x="566.7" y="106" width="51.6" height="20" fill="#FFFFFF" rx="2" />
<text x="592.5" y="122" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">lookup</text>
<polygon points="930,85 1015,131 930,177 845,131" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.6" />
<text x="930" y="124.4" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">
<tspan x="930" dy="0">record</tspan>
<tspan x="930" dy="15">존재?</tspan>
</text>
<path d="M 835 131 L 845 131" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<polygon points="1170,160 1260,210 1170,260 1080,210" fill="#FFFFFF" stroke="#7556D8" stroke-width="1.6" />
<text x="1170" y="203.4" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">
<tspan x="1170" dy="0">fingerprint</tspan>
<tspan x="1170" dy="15">일치?</tspan>
</text>
<polygon points="930,270 1020,320 930,370 840,320" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.6" />
<text x="930" y="313.4" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">
<tspan x="930" dy="0">tryBegin</tspan>
<tspan x="930" dy="15">성공?</tspan>
</text>
<path d="M 1015 145 L 1100 190" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-purple)" />
<rect x="1028.6" y="142.5" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="1057.5" y="158.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">Present</text>
<path d="M 930 177 L 930 270" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="904.2" y="198.5" width="51.6" height="20" fill="#FFFFFF" rx="2" />
<text x="930" y="214.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Absent</text>
<rect x="1375" y="120" width="205" height="70" fill="#FDEDEF" stroke="#D64550" stroke-width="1.5" rx="8" />
<text x="1477.5" y="149" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">fingerprint-mismatch</text>
<text x="1477.5" y="174" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">422</text>
<path d="M 1260 190 L 1375 155" fill="none" stroke="#D64550" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-red)" />
<rect x="1285.4" y="147.5" width="64.2" height="20" fill="#FFFFFF" rx="2" />
<text x="1317.5" y="163.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#D64550" text-anchor="middle">Mismatch</text>
<polygon points="1170,304 1255,350 1170,396 1085,350" fill="#FFFFFF" stroke="#7556D8" stroke-width="1.6" />
<text x="1170" y="343.4" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">
<tspan x="1170" dy="0">record</tspan>
<tspan x="1170" dy="15">status</tspan>
</text>
<path d="M 1170 260 L 1170 304" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-purple)" />
<rect x="1147.3" y="257" width="45.3" height="20" fill="#FFFFFF" rx="2" />
<text x="1170" y="273" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">Match</text>
<rect x="1375" y="300" width="205" height="70" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.5" rx="8" />
<text x="1477.5" y="329" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">replay-hit</text>
<text x="1477.5" y="354" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">action 0회</text>
<path d="M 1255 335 L 1375 335" fill="none" stroke="#168A5B" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-green)" />
<rect x="1279.8" y="310" width="70.4" height="20" fill="#FFFFFF" rx="2" />
<text x="1315" y="326" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#168A5B" text-anchor="middle">COMPLETED</text>
<polygon points="1170,452 1257.5,500 1170,548 1082.5,500" fill="#FFF7E5" stroke="#B7791F" stroke-width="1.6" />
<text x="1170" y="493.4" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#B7791F" text-anchor="middle">
<tspan x="1170" dy="0">now &lt;</tspan>
<tspan x="1170" dy="15">deadline?</tspan>
</text>
<path d="M 1170 396 L 1170 452" fill="none" stroke="#B7791F" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-amber)" />
<rect x="1134.8" y="399" width="70.4" height="20" fill="#FFFFFF" rx="2" />
<text x="1170" y="415" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#B7791F" text-anchor="middle">IN_FLIGHT</text>
<path d="M 1020 320 L 1082 480" fill="none" stroke="#B7791F" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-amber)" />
<rect x="1012.6" y="375" width="76.7" height="20" fill="#FFFFFF" rx="2" />
<text x="1051" y="391" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#B7791F" text-anchor="middle">Claim lost</text>
<rect x="1375" y="465" width="205" height="70" fill="#FDEDEF" stroke="#D64550" stroke-width="1.5" rx="8" />
<text x="1477.5" y="494" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">in-flight</text>
<text x="1477.5" y="519" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">409</text>
<path d="M 1258 500 L 1375 500" fill="none" stroke="#D64550" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-red)" />
<rect x="1259.3" y="475" width="114.3" height="20" fill="#FFFFFF" rx="2" />
<text x="1316.5" y="491" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#D64550" text-anchor="middle">Deadline reached</text>
<rect x="1010" y="565" width="210" height="56" fill="#FFF7E5" stroke="#B7791F" stroke-width="1.5" rx="8" />
<text x="1115" y="598" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">20ms 대기 후 재조회</text>
<path d="M 1170 548 L 1115 565" fill="none" stroke="#B7791F" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-amber)" />
<rect x="1088.5" y="531.5" width="108.0" height="20" fill="#FFFFFF" rx="2" />
<text x="1142.5" y="547.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#B7791F" text-anchor="middle">Before deadline</text>
<path d="M 1010 593 L 740 593 L 740 167" fill="none" stroke="#B7791F" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="7 5" marker-end="url(#arrow-ink)" />
<rect x="805.4" y="567" width="89.2" height="20" fill="#FBFCFE" rx="2" />
<text x="850" y="583" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#B7791F" text-anchor="middle">Retry lookup</text>
<rect x="25" y="715" width="1590" height="300" fill="#FBFCFE" stroke="#1677FF" stroke-width="1.3" rx="10" />
<rect x="34" y="704" width="305.8" height="20" fill="#FFFFFF" rx="2" />
<text x="41" y="720" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#0B5CC4" text-anchor="start">클레임 후 실행 · RuntimeException과 discard 결과</text>
<rect x="70" y="795" width="220" height="76" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="180" y="838" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">action.get()</text>
<rect x="330" y="795" width="220" height="76" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="440" y="838" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">codec.serialize(result)</text>
<rect x="630" y="795" width="220" height="76" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="740" y="838" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">store.complete(...)</text>
<rect x="925" y="795" width="220" height="76" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.5" rx="8" />
<text x="1035" y="827" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">new · action 1회</text>
<text x="1035" y="852" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">응답 저장</text>
<path d="M 290 833 L 330 833" fill="none" stroke="#168A5B" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-green)" />
<rect x="281.1" y="808" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="310" y="824" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#168A5B" text-anchor="middle">Success</text>
<path d="M 550 833 L 630 833" fill="none" stroke="#168A5B" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-green)" />
<rect x="561.1" y="808" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="590" y="824" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#168A5B" text-anchor="middle">Success</text>
<path d="M 850 833 L 925 833" fill="none" stroke="#168A5B" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-green)" />
<rect x="858.6" y="808" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="887.5" y="824" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#168A5B" text-anchor="middle">Success</text>
<path d="M 930 370 L 930 700 L 180 700 L 180 795" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="504.8" y="674" width="70.4" height="20" fill="#FFFFFF" rx="2" />
<text x="540" y="690" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Claim won</text>
<rect x="1210" y="760" width="180" height="70" fill="#FDEDEF" stroke="#D64550" stroke-width="1.5" rx="8" />
<text x="1300" y="800" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">RuntimeException</text>
<rect x="1210" y="900" width="180" height="70" fill="#FFFFFF" stroke="#D64550" stroke-width="1.5" rx="8" />
<text x="1300" y="940" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">store.discard(scope)</text>
<path d="M 180 871 L 180 935 L 1190 935 L 1190 795 L 1210 795" fill="none" stroke="#D64550" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" />
<path d="M 440 871 L 440 935 L 1190 935 L 1190 795 L 1210 795" fill="none" stroke="#D64550" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" />
<path d="M 740 871 L 740 935 L 1190 935 L 1190 795 L 1210 795" fill="none" stroke="#D64550" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" />
<path d="M 1300 830 L 1300 900" fill="none" stroke="#D64550" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-red)" />
<rect x="1271.1" y="840" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="1300" y="856" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#D64550" text-anchor="middle">cleanup</text>
<rect x="1430" y="835" width="170" height="65" fill="#FFFFFF" stroke="#D64550" stroke-width="1.5" rx="8" />
<text x="1515" y="861.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">원래 예외 재전파</text>
<text x="1515" y="886.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">discard 성공</text>
<rect x="1430" y="930" width="170" height="65" fill="#FDEDEF" stroke="#D64550" stroke-width="1.5" rx="8" />
<text x="1515" y="956.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="700" fill="#25282D" text-anchor="middle">discard 예외 대체 가능</text>
<text x="1515" y="981.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">정리 불확실</text>
<path d="M 1390 930 L 1430 867" fill="none" stroke="#D64550" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-red)" />
<rect x="1381.1" y="873.5" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="1410" y="889.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#D64550" text-anchor="middle">returns</text>
<path d="M 1390 950 L 1430 962" fill="none" stroke="#D64550" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-red)" />
<rect x="1384.2" y="931" width="51.6" height="20" fill="#FFFFFF" rx="2" />
<text x="1410" y="947" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#D64550" text-anchor="middle">throws</text>
</svg>

Before

Width:  |  Height:  |  Size: 19 KiB

@@ -1,108 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="978" height="673" viewBox="0 0 978 673" role="img" aria-labelledby="diagram-title diagram-description">
<title id="diagram-title">전송 타입은 inbound adapter에서 Command·Query로 수렴한다</title>
<desc id="diagram-description">왼쪽에서 오른쪽으로 읽는다. web은 HTTP DTO, grpc는 protobuf message, graphql은 GraphQL request, websocket은 WebSocket message를 각 어댑터 경계에서 처리한다. 네 어댑터는 전송 기술 타입을 application-core로 넘기지 않고 Command 또는 Query로 변환한다. 변환된 입력만 Application use case를 호출한다.</desc>
<metadata>{&quot;techviz&quot;:{&quot;spec_version&quot;:&quot;1.1&quot;,&quot;id&quot;:&quot;inbound-transport-boundary&quot;,&quot;profile&quot;:&quot;component-flow&quot;},&quot;source_context&quot;:{&quot;document&quot;:&quot;/home/donghyeon/workspace/ai-tool/topic-arrange/executable-clean-architecture/claridoc-rewrite/document.md&quot;,&quot;document_sha256&quot;:&quot;04fbab095d33d301746c34f7cca305730919bad3c341bcf63b8ad3ee3b396d31&quot;,&quot;anchor&quot;:{&quot;kind&quot;:&quot;marker&quot;,&quot;value&quot;:&quot;inbound-transport-boundary&quot;,&quot;line&quot;:336}},&quot;evidence_policy&quot;:&quot;Each factual element cites source lines or is marked assumption.&quot;,&quot;diagram_only&quot;:true}</metadata>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" />
</marker>
<style>
:root { color-scheme: light; }
text { font-family: Inter, Pretendard, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #111827; }
.canvas { fill: #ffffff; }
.group-box { fill: #ffffff; stroke: #9ca3af; stroke-width: 1.4; stroke-dasharray: 7 5; }
.group-label-bg { fill: #ffffff; }
.group-label { font-size: 13px; font-weight: 650; fill: #374151; }
.edge { fill: none; stroke: #374151; stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; marker-end: url(#arrow); }
.edge.style-dashed, .edge.semantic-dashed, .edge.assumption { stroke-dasharray: 7 5; }
.edge.style-dotted { stroke-dasharray: 2 5; }
.edge.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
.edge.emphasis-muted { stroke: #9ca3af; }
.edge.emphasis-warning, .edge.kind-failure, .edge.kind-error { stroke: #dc2626; stroke-width: 2.2; }
.edge-label-bg { fill: #ffffff; }
.edge-label { font-size: 12px; font-weight: 560; text-anchor: middle; }
.node-shape { fill: #ffffff; stroke: #4b5563; stroke-width: 1.7; }
.node-shape.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
.node-shape.emphasis-muted { stroke: #9ca3af; fill: #f9fafb; }
.node-shape.emphasis-warning { stroke: #d97706; stroke-width: 2; fill: #fffdf5; }
.node-shape.kind-database, .node-shape.kind-datastore, .node-shape.kind-storage { fill: #f8fafc; }
.node-shape.kind-queue, .node-shape.kind-event, .node-shape.kind-topic { fill: #fafafa; }
.node-shape.assumption { stroke-dasharray: 4 4; }
.storage-bottom, .controller-divider { fill: none; stroke: #4b5563; stroke-width: 1.4; }
.controller-led { fill: #4b5563; }
.actor-symbol { fill: none; stroke: #4b5563; stroke-width: 1.8; stroke-linecap: round; }
.actor-symbol.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
.node-label { font-size: 14px; font-weight: 650; text-anchor: middle; }
.node-role { font-size: 10px; letter-spacing: 0.04em; text-anchor: middle; fill: #6b7280; }
.node-detail-divider { stroke: #d1d5db; stroke-width: 1; }
.node-detail { font-size: 11px; fill: #374151; }
.assumption-badge { font-size: 9px; font-weight: 700; fill: #92400e; }
.failure-mark { stroke: #dc2626; stroke-width: 4; stroke-linecap: round; }
.lifeline { stroke: #9ca3af; stroke-width: 1.2; stroke-dasharray: 5 5; }
.timeline-axis { stroke: #374151; stroke-width: 1.8; marker-end: url(#arrow); }
.timeline-stem { stroke: #6b7280; stroke-width: 1.3; }
.timeline-marker { fill: #ffffff; stroke: #374151; stroke-width: 1.7; }
.timeline-marker.primary { fill: #2563eb; stroke: #2563eb; }
.timeline-marker.warning { fill: #dc2626; stroke: #dc2626; }
.timeline-label { font-size: 13px; font-weight: 650; text-anchor: middle; }
.timeline-detail { font-size: 11px; fill: #4b5563; text-anchor: middle; }
</style>
</defs>
<rect class="canvas" width="978" height="673" />
<polyline class="edge kind-request style-solid emphasis-primary" points="599.0,344.0 679.0,344.0 679.0,344.0 759.0,344.0" data-evidence="322-328" />
<rect class="edge-label-bg" x="643.2" y="302.0" width="71.6" height="22" rx="3" />
<text class="edge-label" x="679.0" y="317.0">유스케이스 호출</text>
<polyline class="edge kind-data style-solid emphasis-normal" points="253.0,424.0 349.5,424.0 349.5,351.3 446.0,351.3" data-evidence="322-327" />
<rect class="edge-label-bg" x="341.1" y="373.7" width="64.9" height="22" rx="3" />
<text class="edge-label" x="373.5" y="388.7">GraphQL</text>
<polyline class="edge kind-data style-solid emphasis-normal" points="253.0,264.0 349.5,264.0 349.5,336.7 446.0,336.7" data-evidence="322-327" />
<rect class="edge-label-bg" x="337.7" y="286.3" width="71.6" height="22" rx="3" />
<text class="edge-label" x="373.5" y="301.3">Protobuf</text>
<polyline class="edge kind-data style-solid emphasis-normal" points="286.0,104.0 366.0,104.0 366.0,322.0 446.0,322.0" data-evidence="322-327" />
<rect class="edge-label-bg" x="354.2" y="199.0" width="71.6" height="22" rx="3" />
<text class="edge-label" x="390.0" y="214.0">HTTP DTO</text>
<polyline class="edge kind-data style-solid emphasis-normal" points="254.5,584.0 350.2,584.0 350.2,366.0 446.0,366.0" data-evidence="322-328" />
<rect class="edge-label-bg" x="335.1" y="461.0" width="78.3" height="22" rx="3" />
<text class="edge-label" x="374.2" y="476.0">WebSocket</text>
<g id="node-web">
<rect class="node-shape kind-adapter emphasis-normal role-source" data-evidence="315-317" x="70.0" y="60.0" width="216.0" height="88.0" rx="7" />
<text class="node-label" x="178.0" y="87.0">web</text>
<line class="node-detail-divider" x1="84.0" y1="108.0" x2="272.0" y2="108.0" />
<text class="node-detail" x="86.0" y="125.0">HTTP · JSON DTO</text>
<text class="node-detail" x="86.0" y="141.0">validation · auth · errors</text>
</g>
<g id="node-grpc">
<rect class="node-shape kind-adapter emphasis-normal role-source" data-evidence="315-318" x="103.0" y="220.0" width="150.0" height="88.0" rx="7" />
<text class="node-label" x="178.0" y="247.0">grpc</text>
<line class="node-detail-divider" x1="117.0" y1="268.0" x2="239.0" y2="268.0" />
<text class="node-detail" x="119.0" y="285.0">Protobuf message</text>
<text class="node-detail" x="119.0" y="301.0">server lifecycle</text>
</g>
<g id="node-graphql">
<rect class="node-shape kind-adapter emphasis-normal role-source" data-evidence="315-319" x="103.0" y="380.0" width="150.0" height="88.0" rx="7" />
<text class="node-label" x="178.0" y="407.0">graphql</text>
<line class="node-detail-divider" x1="117.0" y1="428.0" x2="239.0" y2="428.0" />
<text class="node-detail" x="119.0" y="445.0">GraphQL request</text>
<text class="node-detail" x="119.0" y="461.0">query · mutation</text>
</g>
<g id="node-websocket">
<rect class="node-shape kind-adapter emphasis-normal role-source" data-evidence="315-320" x="101.5" y="540.0" width="153.0" height="88.0" rx="7" />
<text class="node-label" x="178.0" y="567.0">websocket</text>
<line class="node-detail-divider" x1="115.5" y1="588.0" x2="240.5" y2="588.0" />
<text class="node-detail" x="117.5" y="605.0">WebSocket message</text>
<text class="node-detail" x="117.5" y="621.0">STOMP · realtime</text>
</g>
<g id="node-command-query">
<rect class="node-shape kind-interface emphasis-primary role-service" data-evidence="322-328" x="446.0" y="308.5" width="153.0" height="71.0" rx="22" />
<text class="node-label" x="522.5" y="335.5">Command / Query</text>
<line class="node-detail-divider" x1="460.0" y1="356.5" x2="585.0" y2="356.5" />
<text class="node-detail" x="462.0" y="373.5">application input</text>
</g>
<g id="node-use-case">
<rect class="node-shape kind-service emphasis-normal role-sink" data-evidence="322-328" x="759.0" y="308.5" width="174.0" height="71.0" rx="7" />
<text class="node-label" x="846.0" y="335.5">Application use case</text>
<line class="node-detail-divider" x1="773.0" y1="356.5" x2="919.0" y2="356.5" />
<text class="node-detail" x="775.0" y="373.5">transport type 없음</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.5 KiB

@@ -1,68 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1480" height="720" viewBox="0 0 1480 720" role="img" aria-labelledby="title desc">
<title id="title">Lock timeout routing gap</title>
<desc id="desc">The adapter contract declares a lock timeout and a classifier maps its code to HTTP 409, but zero production callers and zero dedicated web handlers leave that route disconnected.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1480" height="720" fill="#FFFFFF"/>
<rect x="40" y="45" width="930" height="300" fill="#FBFCFE" stroke="#AEB5BF" stroke-width="1.3" rx="10" />
<rect x="49" y="34" width="131.8" height="20" fill="#FFFFFF" rx="2" />
<text x="56" y="50" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#667085" text-anchor="start">계약과 분류 · 존재함</text>
<rect x="80" y="145" width="250" height="90" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="205" y="184" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">DistributedLockPort</text>
<text x="205" y="209" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">adapter 계약</text>
<rect x="385" y="145" width="260" height="90" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="515" y="195" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">LockAcquisitionTimeoutException</text>
<rect x="700" y="145" width="230" height="90" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="815" y="195" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">CONCURRENCY_LOCK_TIMEOUT</text>
<path d="M 330 190 L 385 190" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-ink)" />
<rect x="300.3" y="165" width="114.3" height="20" fill="#FFFFFF" rx="2" />
<text x="357.5" y="181" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">Adapter contract</text>
<path d="M 645 190 L 700 190" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="640.4" y="165" width="64.2" height="20" fill="#FFFFFF" rx="2" />
<text x="672.5" y="181" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Declares</text>
<rect x="1015" y="45" width="420" height="300" fill="#FBFCFE" stroke="#AEB5BF" stroke-width="1.3" rx="10" />
<rect x="1024" y="34" width="67.3" height="20" fill="#FFFFFF" rx="2" />
<text x="1031" y="50" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#667085" text-anchor="start">HTTP 분류</text>
<rect x="1060" y="145" width="330" height="90" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="1225" y="184" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">LOCK_TIMEOUT → HTTP 409</text>
<text x="1225" y="209" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">분류 계약</text>
<path d="M 930 190 L 1060 190" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="956.6" y="165" width="76.7" height="20" fill="#FFFFFF" rx="2" />
<text x="995" y="181" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Classifies</text>
<rect x="110" y="430" width="320" height="100" fill="#FDEDEF" stroke="#D64550" stroke-width="1.5" rx="8" />
<text x="270" y="474" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">프로덕션 애플리케이션/유스케이스</text>
<text x="270" y="499" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">호출자 0</text>
<rect x="560" y="430" width="270" height="100" fill="#FDEDEF" stroke="#D64550" stroke-width="1.5" rx="8" />
<text x="695" y="474" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">전용 웹 핸들러</text>
<text x="695" y="499" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">0</text>
<rect x="1040" y="430" width="340" height="100" fill="#FDEDEF" stroke="#D64550" stroke-width="1.5" rx="8" />
<text x="1210" y="474" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">현재 HTTP 409</text>
<text x="1210" y="499" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">보장 없음</text>
<path d="M 430 480 L 500 480 L 500 275 L 515 275 L 515 235" fill="none" stroke="#D64550" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="7 5" />
<path d="M 482 337 L 518 373" fill="none" stroke="#D64550" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M 518 337 L 482 373" fill="none" stroke="#D64550" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" />
<rect x="450.2" y="308" width="99.7" height="21" fill="#FFFFFF" rx="2" />
<text x="500" y="325" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="650" fill="#D64550" text-anchor="middle">현재 연결 없음</text>
<path d="M 830 480 L 940 480 L 940 275 L 1225 275 L 1225 235" fill="none" stroke="#D64550" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="7 5" />
<path d="M 922 387 L 958 423" fill="none" stroke="#D64550" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M 958 387 L 922 423" fill="none" stroke="#D64550" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" />
<rect x="898.8" y="358" width="82.4" height="21" fill="#FFFFFF" rx="2" />
<text x="940" y="375" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="650" fill="#D64550" text-anchor="middle">Not routed</text>
<rect x="560" y="600" width="360" height="70" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="740" y="629" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">GlobalExceptionHandler</text>
<text x="740" y="654" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">Exception fallback</text>
<path d="M 920 635 L 1040 500" fill="none" stroke="#667085" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-muted)" />
<rect x="949.7" y="574" width="120.6" height="20" fill="#FFFFFF" rx="2" />
<text x="1010" y="590" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#667085" text-anchor="middle">Fallback response</text>
<path d="M 972 462 L 1008 498" fill="none" stroke="#D64550" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M 1008 462 L 972 498" fill="none" stroke="#D64550" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" />
</svg>

Before

Width:  |  Height:  |  Size: 9.6 KiB

@@ -1,64 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="760" viewBox="0 0 1440 760" role="img" aria-labelledby="title desc">
<title id="title">Logical ownership rings</title>
<desc id="desc">Project modules depend inward while adapter-owned framework surfaces and bootstrap-owned composition surfaces remain distinct.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1440" height="760" fill="#FFFFFF"/>
<rect x="70" y="55" width="1300" height="640" fill="#FBFCFE" stroke="#7E8792" stroke-width="1.5" rx="18" />
<rect x="98" y="45" width="123.7" height="21" fill="#FFFFFF" rx="2" />
<text x="105" y="62" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="650" fill="#667085" text-anchor="start">프로젝트 소유 표면</text>
<rect x="265" y="145" width="910" height="475" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.8" rx="18" />
<rect x="293" y="135" width="99.7" height="21" fill="#FFFFFF" rx="2" />
<text x="300" y="152" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="650" fill="#0B5CC4" text-anchor="start">안쪽 모듈 경계</text>
<rect x="460" y="250" width="520" height="270" fill="#EAF3FF" stroke="#0B5CC4" stroke-width="2" rx="18" />
<rect x="565" y="300" width="310" height="82" fill="#FFFFFF" stroke="#0B5CC4" stroke-width="1.5" rx="8" />
<text x="720" y="335" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">application-core</text>
<text x="720" y="360" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">Spring DI · SLF4J</text>
<rect x="565" y="420" width="310" height="68" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.5" rx="8" />
<text x="720" y="448" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">domain-core</text>
<text x="720" y="473" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">main 외부 의존 0</text>
<rect x="95" y="210" width="280" height="105" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="235" y="256.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">web adapter</text>
<text x="235" y="280.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">
<tspan x="235" dy="0">MVC · Security</tspan>
<tspan x="235" dy="16.2">Validation</tspan>
</text>
<rect x="95" y="410" width="280" height="105" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="235" y="456.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">persistence adapter</text>
<text x="235" y="480.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">
<tspan x="235" dy="0">JPA · PostgreSQL</tspan>
<tspan x="235" dy="16.2">DB 구체 의존</tspan>
</text>
<rect x="1065" y="280" width="250" height="150" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="1190" y="349" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">app-bootstrap</text>
<text x="1190" y="373" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">
<tspan x="1190" dy="0">Boot · Flyway · 관측</tspan>
<tspan x="1190" dy="16.2">Security 조립</tspan>
</text>
<path d="M 375 262 L 480 262 L 480 325 L 565 325" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="406.6" y="234" width="126.9" height="20" fill="#FFFFFF" rx="2" />
<text x="470" y="250" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Project dependency</text>
<path d="M 375 462 L 500 462 L 500 360 L 565 360" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="414.6" y="434" width="126.9" height="20" fill="#FFFFFF" rx="2" />
<text x="478" y="450" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Project dependency</text>
<path d="M 1065 355 L 950 355 L 950 340 L 875 340" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="906.6" y="314" width="126.9" height="20" fill="#FFFFFF" rx="2" />
<text x="970" y="330" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Project dependency</text>
<path d="M 720 382 L 720 420" fill="none" stroke="#168A5B" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-green)" />
<rect x="656.6" y="376" width="126.9" height="20" fill="#FFFFFF" rx="2" />
<text x="720" y="392" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#168A5B" text-anchor="middle">Project dependency</text>
<rect x="590" y="555" width="127.7" height="30" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.2" rx="15" />
<text x="653.9" y="575" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#168A5B" text-anchor="middle">DOMAIN_IS_PURE</text>
<path d="M 720 555 L 720 488" fill="none" stroke="#168A5B" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" marker-end="url(#arrow-green)" />
<rect x="751.0" y="521" width="108.0" height="20" fill="#FFFFFF" rx="2" />
<text x="805" y="537" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#168A5B" text-anchor="middle">Enforces purity</text>
</svg>

Before

Width:  |  Height:  |  Size: 7.9 KiB

@@ -1,121 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="960" viewBox="0 0 1600 960" role="img" aria-labelledby="title desc">
<title id="title">MDC request and asynchronous lifecycle</title>
<desc id="desc">The primary request lifecycle, configured task decorator propagation, cleanup failure window, and unsupported executor path are separated.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1600" height="960" fill="#FFFFFF"/>
<rect x="35" y="40" width="1530" height="320" fill="#FBFCFE" stroke="#AEB5BF" stroke-width="1.3" rx="10" />
<rect x="44" y="29" width="149.1" height="20" fill="#FFFFFF" rx="2" />
<text x="51" y="45" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#667085" text-anchor="start">요청 스레드 · 정리 전제</text>
<rect x="70" y="145" width="185" height="78" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="162.5" y="178" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">요청 헤더</text>
<text x="162.5" y="203" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">traceparent</text>
<rect x="300" y="145" width="185" height="78" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="392.5" y="189" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">살균·채택·생성</text>
<rect x="540" y="145" width="185" height="78" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="632.5" y="178" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">요청 MDC</text>
<text x="632.5" y="203" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">5키 put</text>
<rect x="780" y="145" width="185" height="78" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="872.5" y="189" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">요청 처리</text>
<rect x="1020" y="145" width="185" height="78" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="1112.5" y="178" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">사용자 가명화</text>
<text x="1112.5" y="203" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">MDC에는 가명만</text>
<rect x="1260" y="145" width="185" height="78" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="1352.5" y="189" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">http_request log</text>
<rect x="1460" y="145" width="120" height="78" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="1520" y="178" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">5키 remove</text>
<text x="1520" y="203" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">앞 단계 완료 시</text>
<path d="M 255 184 L 300 184" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<path d="M 485 184 L 540 184" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<path d="M 725 184 L 780 184" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<path d="M 965 184 L 1020 184" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<path d="M 1205 184 L 1260 184" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<path d="M 1445 184 L 1460 184" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="179.8" y="154" width="70.4" height="20" fill="#FBFCFE" rx="2" />
<text x="215" y="170" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#0B5CC4" text-anchor="middle">Normalize</text>
<rect x="488.6" y="154" width="32.8" height="20" fill="#FBFCFE" rx="2" />
<text x="505" y="170" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#0B5CC4" text-anchor="middle">Put</text>
<rect x="901.1" y="154" width="57.9" height="20" fill="#FBFCFE" rx="2" />
<text x="930" y="170" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#0B5CC4" text-anchor="middle">finally</text>
<rect x="545" y="265" width="250" height="58" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="670" y="299" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">응답 헤더 · Envelope meta</text>
<rect x="830" y="265" width="250" height="58" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="955" y="288" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">OutboundCorrelation</text>
<text x="955" y="313" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">같은 스레드에서 read</text>
<rect x="1110" y="279" width="130.1" height="30" fill="#FFF7E5" stroke="#B7791F" stroke-width="1.2" rx="15" />
<text x="1175.0" y="299" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#B7791F" text-anchor="middle">MDC 비면 UNKNOWN</text>
<path d="M 632 223 L 670 265" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="596.1" y="238" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="625" y="254" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Project</text>
<path d="M 725 223 L 930 265" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="805.5" y="232" width="39.1" height="20" fill="#FFFFFF" rx="2" />
<text x="825" y="248" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Read</text>
<path d="M 1080 294 L 1110 294" fill="none" stroke="#B7791F" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-amber)" />
<rect x="1062.9" y="269" width="64.2" height="20" fill="#FFFFFF" rx="2" />
<text x="1095" y="285" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#B7791F" text-anchor="middle">Fallback</text>
<rect x="1010" y="385" width="515" height="92" fill="#FDEDEF" stroke="#D64550" stroke-width="1.5" rx="10" />
<text x="1035" y="420" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="800" fill="#D64550" text-anchor="start">정리 실패 창</text>
<text x="1035" y="450" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="650" fill="#25282D" text-anchor="start">가명화 또는 log 실패 시 5키 제거 보장 없음</text>
<path d="M 1110 223 L 1110 385" fill="none" stroke="#D64550" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" />
<path d="M 1340 223 L 1340 385" fill="none" stroke="#D64550" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" />
<rect x="35" y="530" width="1110" height="370" fill="#FBFCFE" stroke="#1677FF" stroke-width="1.3" rx="10" />
<rect x="44" y="519" width="282.3" height="20" fill="#FFFFFF" rx="2" />
<text x="51" y="535" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#0B5CC4" text-anchor="start">구성된 비동기 경계 · applicationTaskExecutor</text>
<rect x="55" y="625" width="230" height="75" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="170" y="656.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">applicationTaskExecutor</text>
<text x="170" y="681.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">configured</text>
<rect x="315" y="625" width="210" height="75" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="420" y="667.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">AsyncContextTaskDecorator</text>
<rect x="580" y="575" width="210" height="75" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="685" y="606.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">caller MDC 캡처</text>
<text x="685" y="631.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">제출 시</text>
<rect x="580" y="705" width="210" height="75" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="685" y="736.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">worker 이전 MDC</text>
<text x="685" y="761.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">보관</text>
<rect x="850" y="625" width="220" height="75" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="960" y="656.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">task 동안 caller MDC</text>
<text x="960" y="681.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">설치</text>
<path d="M 285 662 L 315 662" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-ink)" />
<rect x="246.0" y="634" width="108.0" height="20" fill="#FFFFFF" rx="2" />
<text x="300" y="650" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">Configured with</text>
<path d="M 525 650 L 580 612" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="523.6" y="606" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="552.5" y="622" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Capture</text>
<path d="M 525 675 L 580 742" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="533.0" y="683.5" width="39.1" height="20" fill="#FFFFFF" rx="2" />
<text x="552.5" y="699.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Save</text>
<path d="M 790 612 L 850 650" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="791.1" y="606" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="820" y="622" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Install</text>
<path d="M 790 742 L 850 688" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" marker-end="url(#arrow-blue)" />
<rect x="787.9" y="690" width="64.2" height="20" fill="#FFFFFF" rx="2" />
<text x="820" y="706" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Preserve</text>
<rect x="850" y="790" width="220" height="70" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.5" rx="8" />
<text x="960" y="819" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">이전 worker MDC 복원</text>
<text x="960" y="844" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">finally</text>
<path d="M 960 700 L 960 790" fill="none" stroke="#168A5B" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" marker-end="url(#arrow-green)" />
<rect x="931.1" y="720" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="960" y="736" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#168A5B" text-anchor="middle">Restore</text>
<path d="M 632 223 L 632 500 L 170 500 L 170 625" fill="none" stroke="#1677FF" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" />
<rect x="286.4" y="477" width="227.2" height="20" fill="#FFFFFF" rx="2" />
<text x="400" y="493" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#0B5CC4" text-anchor="middle">Submit through configured executor</text>
<rect x="1190" y="530" width="375" height="370" fill="#FBFCFE" stroke="#D64550" stroke-width="1.3" rx="10" stroke-dasharray="7 6" />
<rect x="1199" y="519" width="120.8" height="20" fill="#FFFFFF" rx="2" />
<text x="1206" y="535" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#D64550" text-anchor="start">구성 밖 비동기 경계</text>
<rect x="1230" y="640" width="295" height="80" fill="#FFFFFF" stroke="#D64550" stroke-width="1.5" rx="8" />
<text x="1377.5" y="685" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">원시 스레드 · 다른 executor</text>
<rect x="1230" y="790" width="295" height="70" fill="#FDEDEF" stroke="#D64550" stroke-width="1.5" rx="8" />
<text x="1377.5" y="830" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">MDC 자동 복사 없음</text>
<path d="M 1377 720 L 1377 790" fill="none" stroke="#D64550" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="7 5" marker-end="url(#arrow-red)" />
<rect x="1313.6" y="730" width="126.9" height="20" fill="#FFFFFF" rx="2" />
<text x="1377" y="746" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#D64550" text-anchor="middle">Does not auto-copy</text>
</svg>

Before

Width:  |  Height:  |  Size: 18 KiB

@@ -1,84 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1480" height="780" viewBox="0 0 1480 780" role="img" aria-labelledby="title desc">
<title id="title">Measured module policy excerpt</title>
<desc id="desc">Five centered source rows point to allowed targets on each side, exposing asymmetric access to domain-core, shared-contract, and support.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1480" height="780" fill="#FFFFFF"/>
<rect x="480" y="25" width="296.9" height="30" fill="#F6F7F9" stroke="#AEB5BF" stroke-width="1.2" rx="15" />
<text x="628.4" y="45" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#667085" text-anchor="middle">정책 비대칭 선택 발췌 · 전체 그래프 아님</text>
<rect x="55" y="120" width="270" height="68" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.5" rx="8" />
<text x="190" y="159" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">domain-core</text>
<rect x="475" y="112" width="530" height="84" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="740" y="148" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">support · 공유 기반</text>
<text x="740" y="173" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">source</text>
<rect x="1155" y="120" width="270" height="68" fill="#FFFFFF" stroke="#68717B" stroke-width="1.5" rx="8" />
<text x="1290" y="159" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">application-core</text>
<path d="M 475 154 L 325 154" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="371.1" y="129" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="400" y="145" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Allowed</text>
<path d="M 1005 154 L 1155 154" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="1051.1" y="129" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="1080" y="145" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Allowed</text>
<rect x="55" y="245" width="270" height="68" fill="#FFFFFF" stroke="#68717B" stroke-width="1.5" rx="8" />
<text x="190" y="284" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">application-core</text>
<rect x="475" y="237" width="530" height="84" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="740" y="273" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">messaging · cache · notification · httpclient</text>
<text x="740" y="298" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">source</text>
<rect x="1155" y="245" width="270" height="68" fill="#FFFFFF" stroke="#68717B" stroke-width="1.5" rx="8" />
<text x="1290" y="284" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">support</text>
<path d="M 475 279 L 325 279" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="371.1" y="254" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="400" y="270" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Allowed</text>
<path d="M 1005 279 L 1155 279" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="1051.1" y="254" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="1080" y="270" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Allowed</text>
<rect x="55" y="370" width="270" height="68" fill="#FFFFFF" stroke="#68717B" stroke-width="1.5" rx="8" />
<text x="190" y="409" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">application-core</text>
<rect x="475" y="362" width="530" height="84" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="740" y="398" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">objectstorage · fileserver · persistence-mongo</text>
<text x="740" y="423" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">source</text>
<rect x="1155" y="370" width="270" height="68" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="1290" y="409" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">shared-contract</text>
<path d="M 475 404 L 325 404" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="371.1" y="379" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="400" y="395" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Allowed</text>
<path d="M 1005 404 L 1155 404" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="1051.1" y="379" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="1080" y="395" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Allowed</text>
<rect x="55" y="495" width="270" height="68" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.5" rx="8" />
<text x="190" y="534" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">domain-core</text>
<rect x="475" y="487" width="530" height="84" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="740" y="523" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">identifier · support 없음</text>
<text x="740" y="548" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">source</text>
<rect x="1155" y="495" width="270" height="68" fill="#FFFFFF" stroke="#68717B" stroke-width="1.5" rx="8" />
<text x="1290" y="534" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">application-core</text>
<path d="M 475 529 L 325 529" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="371.1" y="504" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="400" y="520" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Allowed</text>
<path d="M 1005 529 L 1155 529" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="1051.1" y="504" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="1080" y="520" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Allowed</text>
<rect x="55" y="620" width="270" height="68" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.5" rx="8" />
<text x="190" y="659" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">domain-core</text>
<rect x="475" y="612" width="530" height="84" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="740" y="648" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">application-core</text>
<text x="740" y="673" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">source</text>
<rect x="1155" y="620" width="270" height="68" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="1290" y="659" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">shared-contract</text>
<path d="M 475 654 L 325 654" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="371.1" y="629" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="400" y="645" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Allowed</text>
<path d="M 1005 654 L 1155 654" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="1051.1" y="629" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="1080" y="645" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Allowed</text>
<text x="740" y="755" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="550" fill="#667085" text-anchor="middle">각 행의 가운데 source → 양쪽 allowed target · 간선 교차 없음</text>
</svg>

Before

Width:  |  Height:  |  Size: 12 KiB

@@ -1,52 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1420" height="670" viewBox="0 0 1420 670" role="img" aria-labelledby="title desc">
<title id="title">Multi-module versus single-module enforcement</title>
<desc id="desc">Two parallel panels contrast isolated compile classpaths with one shared classpath and an ArchUnit-only boundary.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1420" height="670" fill="#FFFFFF"/>
<rect x="40" y="55" width="650" height="535" fill="#FBFCFE" stroke="#1677FF" stroke-width="1.3" rx="10" />
<rect x="49" y="44" width="164.8" height="20" fill="#FFFFFF" rx="2" />
<text x="56" y="60" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#0B5CC4" text-anchor="start">멀티모듈 · 분리 클래스패스</text>
<rect x="95" y="135" width="220" height="85" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.5" rx="8" />
<text x="205" y="171.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">domain-core</text>
<text x="205" y="196.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">Spring/JPA 타입 없음</text>
<rect x="410" y="135" width="220" height="85" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="520" y="171.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">adapter</text>
<text x="520" y="196.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">Spring/JPA 소유</text>
<rect x="80" y="285" width="565" height="80" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="362" y="318" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#D64550" text-anchor="middle">금지 import</text>
<text x="362" y="346" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#0B5CC4" text-anchor="middle">타입이 classpath에 없어 javac 실패</text>
<path d="M 315 178 L 410 178" fill="none" stroke="#D64550" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" />
<path d="M 346 162 L 378 194" fill="none" stroke="#D64550" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M 378 162 L 346 194" fill="none" stroke="#D64550" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" />
<rect x="220" y="430" width="96.4" height="30" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.2" rx="15" />
<text x="268.2" y="450" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#168A5B" text-anchor="middle">독립 컴파일</text>
<text x="362" y="505" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="650" fill="#667085" text-anchor="middle">§26 테스트 독립성의 뿌리</text>
<rect x="730" y="55" width="650" height="535" fill="#FBFCFE" stroke="#7556D8" stroke-width="1.3" rx="10" />
<rect x="739" y="44" width="164.8" height="20" fill="#FFFFFF" rx="2" />
<text x="746" y="60" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="start">단일모듈 · 공유 클래스패스</text>
<rect x="780" y="125" width="550" height="170" fill="#FFFFFF" stroke="#737B85" stroke-width="1.5" rx="10" />
<rect x="820" y="175" width="200" height="70" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="920" y="215" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">domain package</text>
<rect x="1090" y="175" width="200" height="70" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="1190" y="215" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">adapter package</text>
<text x="1055" y="150" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#7556D8" text-anchor="middle">하나의 compile classpath</text>
<path d="M 1020 210 L 1090 210" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-purple)" />
<rect x="982.1" y="185" width="145.8" height="20" fill="#FFFFFF" rx="2" />
<text x="1055" y="201" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">Spring import도 컴파일</text>
<rect x="865" y="360" width="380" height="90" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="1055" y="399" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">ArchUnit</text>
<text x="1055" y="424" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">실행 전까지 위반 코드가 존재</text>
<text x="1055" y="520" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="650" fill="#667085" text-anchor="middle">방어선이 테스트 실행 시점으로 늦어짐</text>
<rect x="500" y="615" width="311.9" height="30" fill="#F6F7F9" stroke="#AEB5BF" stroke-width="1.2" rx="15" />
<text x="655.9" y="635" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#667085" text-anchor="middle">두 패널은 진행 단계가 아니라 강제력의 병렬 비교</text>
</svg>

Before

Width:  |  Height:  |  Size: 7.5 KiB

@@ -1,60 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1450" height="730" viewBox="0 0 1450 730" role="img" aria-labelledby="title desc">
<title id="title">Outbox state machine</title>
<desc id="desc">Pending is claimed into in-flight, which can publish, fail for retry, become dead, or be reclaimed after visibility timeout.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1450" height="730" fill="#FFFFFF"/>
<circle cx="55" cy="345" r="10" fill="#25282D" />
<rect x="125" y="300" width="190" height="90" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="220" y="339" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">PENDING</text>
<text x="220" y="364" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">append 결과</text>
<rect x="500" y="290" width="220" height="110" fill="#FFF7E5" stroke="#B7791F" stroke-width="1.5" rx="8" />
<text x="610" y="339" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">IN_FLIGHT</text>
<text x="610" y="364" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">선점됨</text>
<rect x="970" y="95" width="210" height="90" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.5" rx="8" />
<text x="1075" y="134" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">PUBLISHED</text>
<text x="1075" y="159" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">종착 상태</text>
<rect x="970" y="300" width="210" height="90" fill="#FDEDEF" stroke="#D64550" stroke-width="1.5" rx="8" />
<text x="1075" y="339" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">FAILED</text>
<text x="1075" y="364" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">재시도 가능</text>
<rect x="970" y="515" width="210" height="90" fill="#F6F7F9" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="1075" y="554" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">DEAD</text>
<text x="1075" y="579" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">종착 · FIFO 차단</text>
<rect x="1290" y="95" width="120" height="90" fill="#FFFFFF" stroke="#168A5B" stroke-width="1.5" rx="8" />
<text x="1350" y="134" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">삭제</text>
<text x="1350" y="159" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">보존기간 후</text>
<path d="M 65 345 L 125 345" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-ink)" />
<rect x="69.2" y="320" width="51.6" height="20" fill="#FFFFFF" rx="2" />
<text x="95" y="336" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">append</text>
<path d="M 315 345 L 500 345" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="369.1" y="320" width="76.7" height="20" fill="#FFFFFF" rx="2" />
<text x="407.5" y="336" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">claimBatch</text>
<path d="M 720 320 L 850 320 L 850 140 L 970 140" fill="none" stroke="#168A5B" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-green)" />
<rect x="806.9" y="109" width="86.2" height="20" fill="#FFFFFF" rx="2" />
<text x="850" y="125" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#168A5B" text-anchor="middle">publish 성공</text>
<path d="M 720 345 L 970 345" fill="none" stroke="#D64550" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-red)" />
<rect x="765.1" y="320" width="159.9" height="20" fill="#FFFFFF" rx="2" />
<text x="845" y="336" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#D64550" text-anchor="middle">실패 · attemptCount &lt; 3</text>
<path d="M 720 370 L 850 370 L 850 560 L 970 560" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-ink)" />
<rect x="753.6" y="529" width="192.8" height="20" fill="#FFFFFF" rx="2" />
<text x="850" y="545" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">attemptCount ≥ 3 · markDead</text>
<path d="M 1180 140 L 1290 140" fill="none" stroke="#168A5B" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-green)" />
<rect x="1206" y="115" width="58" height="20" fill="#FFFFFF" rx="2" />
<text x="1235" y="131" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#168A5B" text-anchor="middle">보존기간</text>
<path d="M 970 375 L 820 450 L 610 450 L 610 400" fill="none" stroke="#D64550" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-red)" />
<rect x="685.4" y="425" width="209.1" height="21" fill="#FFFFFF" rx="2" />
<text x="790" y="442" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="650" fill="#D64550" text-anchor="middle">next_attempt_at 경과 후 재선점</text>
<path d="M 560 290 C 430 170, 760 140, 680 290" fill="none" stroke="#B7791F" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="7 5" marker-end="url(#arrow-ink)" />
<rect x="523.3" y="158" width="173.4" height="21" fill="#FFFFFF" rx="2" />
<text x="610" y="175" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="650" fill="#B7791F" text-anchor="middle">가시성 제한 시간 후 재선점</text>
<text x="1075" y="650" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="650" fill="#667085" text-anchor="middle">DEAD에는 자동 후속 전이 없음</text>
</svg>

Before

Width:  |  Height:  |  Size: 8.6 KiB

@@ -1,75 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1500" height="810" viewBox="0 0 1500 810" role="img" aria-labelledby="title desc">
<title id="title">Outbox write and relay paths</title>
<desc id="desc">The atomic write path and the post-commit relay path are separated; a configured five-second poll connects the pending row to claimBatch.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1500" height="810" fill="#FFFFFF"/>
<rect x="40" y="45" width="1420" height="260" fill="#FBFCFE" stroke="#1677FF" stroke-width="1.3" rx="10" />
<rect x="49" y="34" width="188.3" height="20" fill="#FFFFFF" rx="2" />
<text x="56" y="50" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#0B5CC4" text-anchor="start">원자적 쓰기 경로 · 트랜잭션 안</text>
<rect x="95" y="125" width="230" height="78" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="210" y="169" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">비즈니스 유스케이스</text>
<rect x="475" y="105" width="340" height="118" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="645" y="158" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">tx.inWrite</text>
<text x="645" y="183" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">도메인 쓰기 + append</text>
<polygon points="1050,95 1284,95 1320,131 1320,235 1050,235" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.7" />
<path d="M 1284 95 L 1284 131 L 1320 131" fill="none" stroke="#1677FF" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" />
<text x="1068" y="131" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="15" font-weight="700" fill="#0B5CC4" text-anchor="start">outbox_event</text>
<text x="1068" y="160" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="500" fill="#667085" text-anchor="start">
<tspan x="1068" dy="0">status: PENDING</tspan>
<tspan x="1068" dy="17.4">같은 write transaction</tspan>
</text>
<path d="M 325 164 L 475 164" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="380.5" y="139" width="39.1" height="20" fill="#FFFFFF" rx="2" />
<text x="400" y="155" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Flow</text>
<path d="M 815 164 L 1050 164" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="891.0" y="139" width="83.0" height="20" fill="#FFFFFF" rx="2" />
<text x="932.5" y="155" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Creates row</text>
<rect x="40" y="400" width="1420" height="355" fill="#FBFCFE" stroke="#7556D8" stroke-width="1.3" rx="10" />
<rect x="49" y="389" width="277.8" height="20" fill="#FFFFFF" rx="2" />
<text x="56" y="405" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="start">커밋 이후 릴레이 경로 · publish는 트랜잭션 밖</text>
<rect x="80" y="500" width="210" height="82" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="185" y="535" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">OutboxRelayScheduler</text>
<text x="185" y="560" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">fixedDelay=PT5S</text>
<rect x="345" y="500" width="210" height="82" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="450" y="546" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">handle()</text>
<rect x="565" y="500" width="210" height="82" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="670" y="535" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">claimBatch</text>
<text x="670" y="560" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">SKIP LOCKED + FIFO</text>
<rect x="825" y="500" width="210" height="82" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="930" y="535" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">occurredAt 재정렬</text>
<text x="930" y="560" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">오름차순</text>
<rect x="1085" y="500" width="210" height="82" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="1190" y="535" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">publish</text>
<text x="1190" y="560" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">트랜잭션 밖</text>
<path d="M 290 541 L 345 541" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-purple)" />
<path d="M 555 541 L 565 541" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-purple)" />
<path d="M 775 541 L 825 541" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-purple)" />
<path d="M 1035 541 L 1085 541" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-purple)" />
<path d="M 1185 582 L 1185 660 L 1010 660" fill="none" stroke="#168A5B" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-green)" />
<rect x="790" y="625" width="220" height="70" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.5" rx="8" />
<text x="900" y="654" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">markPublished</text>
<text x="900" y="679" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">PUBLISHED</text>
<rect x="1061.1" y="634" width="57.9" height="20" fill="#FBFCFE" rx="2" />
<text x="1090" y="650" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#168A5B" text-anchor="middle">Success</text>
<path d="M 1260 582 L 1260 640" fill="none" stroke="#D64550" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-red)" />
<rect x="1220" y="640" width="210" height="70" fill="#FDEDEF" stroke="#D64550" stroke-width="1.5" rx="8" />
<text x="1325" y="669" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">markFailed / markDead</text>
<text x="1325" y="694" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">backoff 또는 종착</text>
<rect x="1291.1" y="604" width="57.9" height="20" fill="#FBFCFE" rx="2" />
<text x="1320" y="620" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#D64550" text-anchor="middle">Failure</text>
<path d="M 1185 235 L 1185 355 L 670 355 L 670 500" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="7 5" marker-end="url(#arrow-purple)" />
<rect x="834.9" y="328" width="190.3" height="21" fill="#FFFFFF" rx="2" />
<text x="930" y="345" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="650" fill="#7556D8" text-anchor="middle">설정된 fixedDelay=PT5S 폴링</text>
<rect x="430" y="700" width="311.6" height="30" fill="#FFF7E5" stroke="#B7791F" stroke-width="1.2" rx="15" />
<text x="585.8" y="720" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#B7791F" text-anchor="middle">IN_FLIGHT stuck → 가시성 제한 시간 후 재선점</text>
</svg>

Before

Width:  |  Height:  |  Size: 11 KiB

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<mxfile host="app.diagrams.net" modified="2026-07-23T00:00:00.000Z" agent="techviz-harness" version="24.7.17" type="device">
<diagram id="production-vs-optin" name="app-bootstrap의 main 클래스패스에는 어댑터 11개가 포함되고 참조 어댑터 3개는 의존 목록 밖에 있다">
<mxGraphModel dx="680" dy="300" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="n_main-classpath-adapters" value="main 의존 포함 · 11&lt;br/&gt;수량: 11개&lt;br/&gt;프로젝트 의존: 선언됨&lt;br/&gt;클래스패스: 포함&lt;br/&gt;어댑터: 포함 대상 11개&lt;br/&gt;활성화: 클래스패스와 별도&lt;br/&gt;측정 범위: main 의존 선언" tooltip="app-bootstrap의 main 프로젝트 의존에 포함되어 main 클래스패스에 들어오는 어댑터 집합 | Evidence: L449-L456, L476-L480, L500-L501, L517-L517" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;strokeColor=#2563eb;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="45.0" y="45.0" width="251.0" height="156.0" as="geometry"/>
</mxCell>
<mxCell id="n_omitted-optin-adapters" value="main 의존 목록 밖 · 3&lt;br/&gt;수량: 3개&lt;br/&gt;프로젝트 의존: 선언하지 않음&lt;br/&gt;클래스패스: 제외&lt;br/&gt;어댑터: grpc · graphql · websocket&lt;br/&gt;활성화: 등록하면 기본 활성&lt;br/&gt;측정 범위: main 의존 선언" tooltip="저장소에는 있지만 app-bootstrap의 main 프로젝트 의존에는 선언되지 않은 참조 어댑터 집합 | Evidence: L481-L489, L500-L501, L517-L517" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;strokeColor=#d97706;fillColor=#fffdf5;" vertex="1" parent="1">
<mxGeometry x="348.0" y="45.0" width="251.0" height="156.0" as="geometry"/>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
@@ -1,59 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1400" height="660" viewBox="0 0 1400 660" role="img" aria-labelledby="title desc">
<title id="title">Runtime call versus source dependency</title>
<desc id="desc">Two lanes separate runtime dispatch from source dependencies and contract ownership.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1400" height="660" fill="#FFFFFF"/>
<rect x="35" y="45" width="1330" height="245" fill="#FBFCFE" stroke="#C5CBD3" stroke-width="1.3" rx="10" />
<rect x="44" y="34" width="233.9" height="20" fill="#FFFFFF" rx="2" />
<text x="51" y="50" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#667085" text-anchor="start">실행 시점 관계 · 실선 = 호출·디스패치</text>
<rect x="100" y="125" width="245" height="90" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="222.5" y="164" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">FeedController</text>
<text x="222.5" y="189" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">driving adapter</text>
<rect x="555" y="105" width="285" height="130" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="697.5" y="164" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">GetFeedUseCase</text>
<text x="697.5" y="189" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">concrete service</text>
<rect x="1060" y="125" width="250" height="90" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="1185" y="164" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">SpringTransactionPort</text>
<text x="1185" y="189" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">runtime implementation</text>
<path d="M 345 170 L 555 170" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-ink)" />
<rect x="405.4" y="145" width="89.2" height="20" fill="#FFFFFF" rx="2" />
<text x="450" y="161" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">Runtime call</text>
<path d="M 840 170 L 1060 170" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-ink)" />
<rect x="892.8" y="145" width="114.3" height="20" fill="#FFFFFF" rx="2" />
<text x="950" y="161" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">Runtime dispatch</text>
<rect x="35" y="350" width="1330" height="255" fill="#FBFCFE" stroke="#C5CBD3" stroke-width="1.3" rx="10" />
<rect x="44" y="339" width="284.2" height="20" fill="#FFFFFF" rx="2" />
<text x="51" y="355" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#667085" text-anchor="start">계약 소유·소스 의존 · 점선 = 타입·계약을 향함</text>
<rect x="95" y="440" width="260" height="85" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="225" y="461" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="600" fill="#667085" text-anchor="middle" letter-spacing="0.8">&lt;&lt;interface&gt;&gt;</text>
<text x="225" y="482.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">QueryUseCase&lt;Q,R&gt;</text>
<text x="225" y="507.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">application-core contract</text>
<rect x="565" y="420" width="270" height="125" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="700" y="476.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">GetFeedUseCase</text>
<text x="700" y="501.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">implements · calls</text>
<rect x="1060" y="440" width="240" height="85" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="1180" y="461" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="600" fill="#667085" text-anchor="middle" letter-spacing="0.8">&lt;&lt;interface&gt;&gt;</text>
<text x="1180" y="482.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">TransactionPort</text>
<text x="1180" y="507.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">application-core contract</text>
<path d="M 565 465 L 355 465" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="7 5" marker-end="url(#arrow-purple)" />
<rect x="421.6" y="440" width="76.7" height="20" fill="#FFFFFF" rx="2" />
<text x="460" y="456" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">Implements</text>
<path d="M 835 465 L 1060 465" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="7 5" marker-end="url(#arrow-purple)" />
<rect x="902.9" y="440" width="89.2" height="20" fill="#FFFFFF" rx="2" />
<text x="947.5" y="456" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">Runtime call</text>
<rect x="1080" y="370" width="200" height="50" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="1180" y="400" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">SpringTransactionPort</text>
<path d="M 1180 420 L 1180 440" fill="none" stroke="#667085" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="7 5" marker-end="url(#arrow-muted)" />
<rect x="1221.7" y="422" width="76.7" height="20" fill="#FFFFFF" rx="2" />
<text x="1260" y="438" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#667085" text-anchor="middle">Implements</text>
</svg>

Before

Width:  |  Height:  |  Size: 8.6 KiB

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1400" height="330" viewBox="0 0 1400 330" role="img" aria-labelledby="title desc">
<title id="title">Runtime call</title>
<desc id="desc">FeedController calls GetFeedUseCase, which dispatches to SpringTransactionPort at runtime.</desc>
<metadata>{&quot;source&quot;:&quot;runtime-call-source-dependency.svg&quot;,&quot;panel&quot;:&quot;upper&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
</defs>
<rect width="1400" height="330" fill="#FFFFFF"/>
<rect x="35" y="45" width="1330" height="245" fill="#FBFCFE" stroke="#C5CBD3" stroke-width="1.3" rx="10"/>
<rect x="44" y="34" width="233.9" height="20" fill="#FFFFFF" rx="2"/>
<text x="51" y="50" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="11" font-weight="650" fill="#667085" text-anchor="start">실행 시점 관계 · 실선 = 호출·디스패치</text>
<rect x="100" y="125" width="245" height="90" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8"/>
<text x="222.5" y="164" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">FeedController</text>
<text x="222.5" y="189" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="12" font-weight="450" fill="#667085" text-anchor="middle">driving adapter</text>
<rect x="555" y="105" width="285" height="130" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8"/>
<text x="697.5" y="164" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">GetFeedUseCase</text>
<text x="697.5" y="189" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="12" font-weight="450" fill="#667085" text-anchor="middle">concrete service</text>
<rect x="1060" y="125" width="250" height="90" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8"/>
<text x="1185" y="164" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">SpringTransactionPort</text>
<text x="1185" y="189" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="12" font-weight="450" fill="#667085" text-anchor="middle">runtime implementation</text>
<path d="M 345 170 L 555 170" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-ink)"/>
<rect x="405.4" y="145" width="89.2" height="20" fill="#FFFFFF" rx="2"/>
<text x="450" y="161" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">Runtime call</text>
<path d="M 840 170 L 1060 170" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-ink)"/>
<rect x="892.8" y="145" width="114.3" height="20" fill="#FFFFFF" rx="2"/>
<text x="950" y="161" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">Runtime dispatch</text>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

@@ -1,78 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1460" height="790" viewBox="0 0 1460 790" role="img" aria-labelledby="title desc">
<title id="title">Feed runtime sequence</title>
<desc id="desc">Eight numbered runtime messages connect four lifelines; FeedQueryPort is shown separately as a compile-time contract rather than a lifeline.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1460" height="790" fill="#FFFFFF"/>
<rect x="20" y="35" width="230" height="70" fill="#F6F7F9" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="135" y="75" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">FeedController</text>
<path d="M 135 105 L 135 685" fill="none" stroke="#B6BDC7" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 6" />
<rect x="360" y="35" width="230" height="70" fill="#F6F7F9" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="475" y="75" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">GetFeedUseCase</text>
<path d="M 475 105 L 475 685" fill="none" stroke="#B6BDC7" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 6" />
<rect x="720" y="35" width="230" height="70" fill="#F6F7F9" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="835" y="64" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">TransactionPort.inRead</text>
<text x="835" y="89" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">경계</text>
<path d="M 835 105 L 835 685" fill="none" stroke="#B6BDC7" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 6" />
<rect x="1075" y="35" width="230" height="70" fill="#F6F7F9" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="1190" y="75" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#25282D" text-anchor="middle">FeedQueryAdapter</text>
<path d="M 1190 105 L 1190 685" fill="none" stroke="#B6BDC7" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 6" />
<rect x="463" y="145" width="24" height="470" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.3" rx="2" />
<rect x="823" y="205" width="24" height="320" fill="#F6F7F9" stroke="#737B85" stroke-width="1.2" rx="2" />
<rect x="1178" y="350" width="24" height="115" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.2" rx="2" />
<path d="M 135 160 L 463 160" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="229.3" y="134" width="139.4" height="20" fill="#FFFFFF" rx="2" />
<text x="299" y="150" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">handle(GetFeedQuery)</text>
<circle cx="28" cy="160" r="14" fill="#1677FF" />
<text x="28" y="165" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="800" fill="#FFFFFF" text-anchor="middle">1</text>
<path d="M 487 220 L 823 220" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-ink)" />
<rect x="597.8" y="194" width="114.3" height="20" fill="#FFFFFF" rx="2" />
<text x="655" y="210" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">inRead(callback)</text>
<circle cx="28" cy="220" r="14" fill="#25282D" />
<text x="28" y="225" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="800" fill="#FFFFFF" text-anchor="middle">2</text>
<path d="M 823 285 L 487 285" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-ink)" />
<rect x="580.6" y="259" width="148.9" height="20" fill="#FFFFFF" rx="2" />
<text x="655" y="275" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">Supplier callback 실행</text>
<circle cx="28" cy="285" r="14" fill="#25282D" />
<text x="28" y="290" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="800" fill="#FFFFFF" text-anchor="middle">3</text>
<path d="M 487 365 L 1178 365" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="728.3" y="339" width="208.5" height="20" fill="#FFFFFF" rx="2" />
<text x="832.5" y="355" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">loadFeed(page,size) · DI 구현체</text>
<circle cx="28" cy="365" r="14" fill="#1677FF" />
<text x="28" y="370" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="800" fill="#FFFFFF" text-anchor="middle">4</text>
<path d="M 1178 445 L 487 445" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" marker-end="url(#arrow-ink)" />
<rect x="772.2" y="419" width="120.6" height="20" fill="#FFFFFF" rx="2" />
<text x="832.5" y="435" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">List&lt;FeedSummary&gt;</text>
<circle cx="28" cy="445" r="14" fill="#25282D" />
<text x="28" y="450" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="800" fill="#FFFFFF" text-anchor="middle">5</text>
<path d="M 487 505 L 823 505" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" marker-end="url(#arrow-ink)" />
<rect x="608.8" y="479" width="92.4" height="20" fill="#FFFFFF" rx="2" />
<text x="655" y="495" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">callback 결과</text>
<circle cx="28" cy="505" r="14" fill="#25282D" />
<text x="28" y="510" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="800" fill="#FFFFFF" text-anchor="middle">6</text>
<path d="M 823 565 L 487 565" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" marker-end="url(#arrow-ink)" />
<rect x="615.1" y="539" width="79.9" height="20" fill="#FFFFFF" rx="2" />
<text x="655" y="555" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">inRead 결과</text>
<circle cx="28" cy="565" r="14" fill="#25282D" />
<text x="28" y="570" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="800" fill="#FFFFFF" text-anchor="middle">7</text>
<path d="M 463 625 L 135 625" fill="none" stroke="#25282D" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" marker-end="url(#arrow-ink)" />
<rect x="259.1" y="599" width="79.9" height="20" fill="#FFFFFF" rx="2" />
<text x="299" y="615" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#25282D" text-anchor="middle">handle 결과</text>
<circle cx="28" cy="625" r="14" fill="#25282D" />
<text x="28" y="630" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="800" fill="#FFFFFF" text-anchor="middle">8</text>
<rect x="1035" y="705" width="350" height="55" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="1210" y="726.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">FeedQueryPort</text>
<text x="1210" y="751.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">컴파일 시점 계약 · lifeline 아님</text>
<path d="M 1190 705 L 1190 685" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" marker-end="url(#arrow-purple)" />
<rect x="1229.1" y="682" width="101.8" height="20" fill="#FFFFFF" rx="2" />
<text x="1280" y="698" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">Implemented by</text>
</svg>

Before

Width:  |  Height:  |  Size: 10 KiB

@@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1400" height="340" viewBox="0 0 1400 340" role="img" aria-labelledby="title desc">
<title id="title">Source dependency and contract ownership</title>
<desc id="desc">GetFeedUseCase depends on application-core contracts, while SpringTransactionPort implements TransactionPort.</desc>
<metadata>{&quot;source&quot;:&quot;runtime-call-source-dependency.svg&quot;,&quot;panel&quot;:&quot;lower&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;}</metadata>
<defs>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
</defs>
<rect width="1400" height="340" fill="#FFFFFF"/>
<rect x="35" y="45" width="1330" height="255" fill="#FBFCFE" stroke="#C5CBD3" stroke-width="1.3" rx="10"/>
<rect x="44" y="34" width="284.2" height="20" fill="#FFFFFF" rx="2"/>
<text x="51" y="50" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="11" font-weight="650" fill="#667085" text-anchor="start">계약 소유·소스 의존 · 점선 = 타입·계약을 향함</text>
<rect x="95" y="135" width="260" height="85" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8"/>
<text x="225" y="156" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="11" font-weight="600" fill="#667085" text-anchor="middle" letter-spacing="0.8">&lt;&lt;interface&gt;&gt;</text>
<text x="225" y="177.5" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">QueryUseCase&lt;Q,R&gt;</text>
<text x="225" y="202.5" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="12" font-weight="450" fill="#667085" text-anchor="middle">application-core contract</text>
<rect x="565" y="115" width="270" height="125" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8"/>
<text x="700" y="171.5" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">GetFeedUseCase</text>
<text x="700" y="196.5" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="12" font-weight="450" fill="#667085" text-anchor="middle">implements · calls</text>
<rect x="1060" y="135" width="240" height="85" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8"/>
<text x="1180" y="156" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="11" font-weight="600" fill="#667085" text-anchor="middle" letter-spacing="0.8">&lt;&lt;interface&gt;&gt;</text>
<text x="1180" y="177.5" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">TransactionPort</text>
<text x="1180" y="202.5" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="12" font-weight="450" fill="#667085" text-anchor="middle">application-core contract</text>
<path d="M 565 160 L 355 160" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="7 5" marker-end="url(#arrow-purple)"/>
<rect x="421.6" y="135" width="76.7" height="20" fill="#FFFFFF" rx="2"/>
<text x="460" y="151" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">Implements</text>
<path d="M 835 160 L 1060 160" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="7 5" marker-end="url(#arrow-purple)"/>
<rect x="902.9" y="135" width="89.2" height="20" fill="#FFFFFF" rx="2"/>
<text x="947.5" y="151" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">Runtime call</text>
<rect x="1080" y="65" width="200" height="50" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8"/>
<text x="1180" y="95" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">SpringTransactionPort</text>
<path d="M 1180 115 L 1180 135" fill="none" stroke="#667085" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="7 5" marker-end="url(#arrow-muted)"/>
<rect x="1221.7" y="117" width="76.7" height="20" fill="#FFFFFF" rx="2"/>
<text x="1260" y="133" font-family="'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif" font-size="11" font-weight="650" fill="#667085" text-anchor="middle">Implements</text>
</svg>

Before

Width:  |  Height:  |  Size: 4.7 KiB

@@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1420" height="720" viewBox="0 0 1420 720" role="img" aria-labelledby="title desc">
<title id="title">Static analysis coverage subset</title>
<desc id="desc">A smaller static-analysis set sits inside the set of all real boundary violations; caught and missed examples occupy their respective regions.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1420" height="720" fill="#FFFFFF"/>
<ellipse cx="710" cy="370" rx="620" ry="290" fill="#FBFCFE" stroke="#68717B" stroke-width="1.8" />
<rect x="599.1" y="75" width="221.8" height="24" fill="#FFFFFF" stroke="#68717B" stroke-width="1" rx="2" />
<text x="710" y="95" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="15" font-weight="650" fill="#25282D" text-anchor="middle">실제 경계 위반 전체 · 현실</text>
<ellipse cx="520" cy="375" rx="330" ry="205" fill="#EAF3FF" stroke="#1677FF" stroke-width="2" />
<rect x="355.2" y="171" width="329.6" height="23" fill="#FFFFFF" stroke="#1677FF" stroke-width="1" rx="2" />
<text x="520" y="190" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="650" fill="#0B5CC4" text-anchor="middle">정적 분석이 보는 영역 · Gradle + ArchUnit</text>
<text x="360" y="300" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="15" font-weight="650" fill="#0B5CC4" text-anchor="start">
<tspan x="360" dy="0">✅ 모듈 의존</tspan>
<tspan x="360" dy="23.2">✅ import · 호출</tspan>
<tspan x="360" dy="23.2">✅ @Transactional</tspan>
<tspan x="360" dy="23.2">✅ JPA · Lombok</tspan>
</text>
<text x="930" y="300" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="15" font-weight="650" fill="#D64550" text-anchor="start">
<tspan x="930" dy="0">❌ 문자열 조회</tspan>
<tspan x="930" dy="24.8">❌ 리플렉션</tspan>
<tspan x="930" dy="24.8">❌ 조건부 런타임 배선</tspan>
</text>
<rect x="555" y="625" width="181.9" height="30" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.2" rx="15" />
<text x="646.0" y="645" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#0B5CC4" text-anchor="middle">정적 분석 ⊂ 실제 위반</text>
</svg>

Before

Width:  |  Height:  |  Size: 3.7 KiB

@@ -1,57 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1420" height="650" viewBox="0 0 1420 650" role="img" aria-labelledby="title desc">
<title id="title">Layered and port-based test contrast</title>
<desc id="desc">An illustrative framework-collaborator replacement is contrasted with the observed anonymous TransactionPort test double pattern.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1420" height="650" fill="#FFFFFF"/>
<rect x="45" y="55" width="635" height="505" fill="#FBFCFE" stroke="#AEB5BF" stroke-width="1.3" rx="10" />
<rect x="54" y="44" width="75.3" height="20" fill="#FFFFFF" rx="2" />
<text x="61" y="60" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#667085" text-anchor="start">설명용 대조</text>
<rect x="100" y="130" width="230" height="85" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="215" y="177.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">Layered service test</text>
<rect x="405" y="110" width="220" height="70" fill="#FDEDEF" stroke="#D64550" stroke-width="1.5" rx="8" />
<text x="515" y="150" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">Spring context</text>
<rect x="405" y="225" width="220" height="70" fill="#FDEDEF" stroke="#D64550" stroke-width="1.5" rx="8" />
<text x="515" y="265" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">Mockito collaborator</text>
<path d="M 330 165 L 405 145" fill="none" stroke="#D64550" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-red)" />
<rect x="335.4" y="130" width="64.3" height="20" fill="#FFFFFF" rx="2" />
<text x="367.5" y="146" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#D64550" text-anchor="middle">직접 대체</text>
<path d="M 330 185 L 405 260" fill="none" stroke="#D64550" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-red)" />
<rect x="335.4" y="197.5" width="64.3" height="20" fill="#FFFFFF" rx="2" />
<text x="367.5" y="213.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#D64550" text-anchor="middle">직접 대체</text>
<text x="362" y="365" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="650" fill="#667085" text-anchor="middle">컨텍스트·Mockito는 결합도 설명용 예시</text>
<rect x="195" y="430" width="195.4" height="30" fill="#F6F7F9" stroke="#AEB5BF" stroke-width="1.2" rx="15" />
<text x="292.7" y="450" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#667085" text-anchor="middle">저장소의 대칭 측정 결과 아님</text>
<rect x="740" y="55" width="635" height="505" fill="#FBFCFE" stroke="#1677FF" stroke-width="1.3" rx="10" />
<rect x="749" y="44" width="136.5" height="20" fill="#FFFFFF" rx="2" />
<text x="756" y="60" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#0B5CC4" text-anchor="start">저장소에서 관찰된 패턴</text>
<rect x="795" y="145" width="245" height="95" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="917.5" y="186.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">포트 유스케이스 테스트</text>
<text x="917.5" y="211.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">core-owned seam</text>
<circle cx="1105" cy="192" r="10" fill="#FFFFFF" stroke="#1677FF" stroke-width="2" />
<text x="1105" y="165" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="700" fill="#0B5CC4" text-anchor="middle">port</text>
<polygon points="1160,125 1296,125 1330,159 1330,260 1160,260" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.7" />
<path d="M 1296 125 L 1296 159 L 1330 159" fill="none" stroke="#1677FF" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" />
<text x="1178" y="161" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="15" font-weight="700" fill="#0B5CC4" text-anchor="start">TransactionPort</text>
<text x="1178" y="190" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="500" fill="#667085" text-anchor="start">
<tspan x="1178" dy="0">익명 테스트 더블</tspan>
</text>
<path d="M 1040 192 L 1095 192" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="1048.0" y="167" width="39.1" height="20" fill="#FFFFFF" rx="2" />
<text x="1067.5" y="183" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">uses</text>
<path d="M 1115 192 L 1160 192" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" marker-end="url(#arrow-purple)" />
<rect x="1099.2" y="167" width="76.7" height="20" fill="#FFFFFF" rx="2" />
<text x="1137.5" y="183" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">implements</text>
<text x="1057" y="365" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="700" fill="#0B5CC4" text-anchor="middle">프레임워크 대신 코어가 소유한 계약을 대체</text>
<rect x="905" y="430" width="152.5" height="30" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.2" rx="15" />
<text x="981.3" y="450" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#168A5B" text-anchor="middle">실제 테스트 더블 패턴</text>
</svg>

Before

Width:  |  Height:  |  Size: 7.8 KiB

@@ -1,57 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1420" height="660" viewBox="0 0 1420 660" role="img" aria-labelledby="title desc">
<title id="title">Observed test inventory and enforced rules</title>
<desc id="desc">Observed sample tests and separately enforced ArchUnit rules are shown as independent evidence scopes, not a complete taxonomy.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1420" height="660" fill="#FFFFFF"/>
<rect x="45" y="70" width="625" height="450" fill="#FBFCFE" stroke="#1677FF" stroke-width="1.3" rx="10" />
<rect x="54" y="59" width="158.4" height="20" fill="#FFFFFF" rx="2" />
<text x="61" y="75" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#0B5CC4" text-anchor="start">관찰된 sample 테스트 표본</text>
<circle cx="175" cy="215" r="78" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.8" />
<text x="175" y="210" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="18" font-weight="800" fill="#0B5CC4" text-anchor="middle">15 classes</text>
<text x="175" y="238" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="14" font-weight="650" fill="#0B5CC4" text-anchor="middle">71 methods</text>
<rect x="330" y="165" width="280" height="100" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="470" y="209" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">domain / application</text>
<text x="470" y="234" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">framework import 0</text>
<path d="M 253 215 L 330 215" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="259.4" y="190" width="64.2" height="20" fill="#FFFFFF" rx="2" />
<text x="291.5" y="206" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Measures</text>
<rect x="115" y="340" width="95.9" height="30" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.2" rx="15" />
<text x="162.9" y="360" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#0B5CC4" text-anchor="middle">domain 표본</text>
<rect x="115" y="388" width="130.1" height="30" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.2" rx="15" />
<text x="180.0" y="408" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#0B5CC4" text-anchor="middle">application 표본</text>
<rect x="115" y="436" width="145.7" height="30" fill="#FFFFFF" stroke="#AEB5BF" stroke-width="1.2" rx="15" />
<text x="187.8" y="456" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#667085" text-anchor="middle">완전한 인벤토리 아님</text>
<rect x="750" y="70" width="625" height="450" fill="#FBFCFE" stroke="#7556D8" stroke-width="1.3" rx="10" />
<rect x="759" y="59" width="149.0" height="20" fill="#FFFFFF" rx="2" />
<text x="766" y="75" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="start">별도 ArchUnit 강제 범위</text>
<rect x="800" y="165" width="220" height="100" fill="#FFFFFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="910" y="209" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="700" fill="#25282D" text-anchor="middle">TestTaxonomyArchitectureTest</text>
<text x="910" y="234" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">ArchUnit rule set</text>
<rect x="1080" y="125" width="245" height="60" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="1202.5" y="160" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">Testcontainers 금지</text>
<path d="M 1020 190 L 1080 155" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-purple)" />
<rect x="1017.9" y="147.5" width="64.2" height="20" fill="#FFFFFF" rx="2" />
<text x="1050" y="163.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">Enforces</text>
<rect x="1080" y="220" width="245" height="60" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="1202.5" y="255" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">slice 혼용 금지</text>
<path d="M 1020 210 L 1080 250" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-purple)" />
<rect x="1017.9" y="205" width="64.2" height="20" fill="#FFFFFF" rx="2" />
<text x="1050" y="221" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">Enforces</text>
<rect x="1080" y="315" width="245" height="60" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="1202.5" y="350" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">fixture 누출 금지</text>
<path d="M 1020 230 L 1080 345" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-purple)" />
<rect x="1017.9" y="262.5" width="64.2" height="20" fill="#FFFFFF" rx="2" />
<text x="1050" y="278.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">Enforces</text>
<rect x="265" y="565" width="890" height="55" fill="#F6F7F9" stroke="#AEB5BF" stroke-width="1.3" rx="27" />
<text x="710" y="599" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="15" font-weight="700" fill="#667085" text-anchor="middle">표본 인벤토리 ≠ 완전한 taxonomy · 두 근거 범위는 독립</text>
</svg>

Before

Width:  |  Height:  |  Size: 8.0 KiB

@@ -1,46 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="660" viewBox="0 0 1440 660" role="img" aria-labelledby="title desc">
<title id="title">Three independent enforcement gates</title>
<desc id="desc">Classpath isolation and Gradle policy are grouped as module-dependent scopes; ArchUnit remains an independent scope, with no implied execution order.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1440" height="660" fill="#FFFFFF"/>
<rect x="530" y="25" width="224.5" height="30" fill="#F6F7F9" stroke="#AEB5BF" stroke-width="1.2" rx="15" />
<text x="642.2" y="45" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#667085" text-anchor="middle">세 범위 · 고정 실행 순서 없음</text>
<rect x="45" y="105" width="880" height="430" fill="#FBFCFE" stroke="#1677FF" stroke-width="1.3" rx="10" />
<rect x="54" y="94" width="142.8" height="20" fill="#FFFFFF" rx="2" />
<text x="61" y="110" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#0B5CC4" text-anchor="start">모듈 분리에 기대는 범위</text>
<rect x="100" y="180" width="340" height="260" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.6" rx="10" />
<text x="270" y="225" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="18" font-weight="750" fill="#0B5CC4" text-anchor="middle">컴파일 클래스패스 격리</text>
<rect x="145" y="275" width="250" height="65" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="270" y="312.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">금지 타입이 없음</text>
<rect x="180" y="370" width="89.0" height="30" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.2" rx="15" />
<text x="224.5" y="390" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#168A5B" text-anchor="middle">javac 차단</text>
<rect x="530" y="180" width="340" height="260" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.6" rx="10" />
<text x="700" y="225" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="18" font-weight="750" fill="#0B5CC4" text-anchor="middle">Gradle 의존 정책</text>
<rect x="575" y="275" width="250" height="65" fill="#EAF3FF" stroke="#1677FF" stroke-width="1.5" rx="8" />
<text x="700" y="312.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">allowedProjectDependencies</text>
<rect x="600" y="370" width="136.9" height="30" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.2" rx="15" />
<text x="668.5" y="390" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#168A5B" text-anchor="middle">project edge 차단</text>
<rect x="990" y="105" width="405" height="430" fill="#FBFCFE" stroke="#7556D8" stroke-width="1.3" rx="10" />
<rect x="999" y="94" width="64.3" height="20" fill="#FFFFFF" rx="2" />
<text x="1006" y="110" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="start">독립 범위</text>
<text x="1192" y="225" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="18" font-weight="750" fill="#7556D8" text-anchor="middle">ArchUnit 구조 규칙</text>
<rect x="1065" y="275" width="255" height="65" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="1192.5" y="312.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">import · annotation · package</text>
<rect x="1100" y="370" width="109.7" height="30" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.2" rx="15" />
<text x="1154.8" y="390" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#168A5B" text-anchor="middle">구조 위반 차단</text>
<path d="M 180 590 L 1260 590" fill="none" stroke="#AEB5BF" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" />
<circle cx="270" cy="590" r="7" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.8" />
<circle cx="700" cy="590" r="7" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.8" />
<circle cx="1192" cy="590" r="7" fill="#FFFFFF" stroke="#7556D8" stroke-width="1.8" />
<text x="720" y="630" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="600" fill="#667085" text-anchor="middle">동일 축의 독립 범위 · 화살표 없음</text>
</svg>

Before

Width:  |  Height:  |  Size: 6.2 KiB

@@ -1,92 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1500" height="850" viewBox="0 0 1500 850" role="img" aria-labelledby="title desc">
<title id="title">Transaction and lock contracts</title>
<desc id="desc">Current transaction and distributed-lock wiring are shown independently; a dashed future-only strip records acquire, commit, release ordering and database constraints.</desc>
<metadata>{&quot;generator&quot;:&quot;_work/regenerate-technical-assets.py&quot;,&quot;canvas_policy&quot;:&quot;diagram-only&quot;,&quot;decorative_effects&quot;:false}</metadata>
<defs>
<marker id="arrow-ink" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#25282D"/></marker>
<marker id="arrow-muted" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#667085"/></marker>
<marker id="arrow-blue" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#1677FF"/></marker>
<marker id="arrow-purple" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#7556D8"/></marker>
<marker id="arrow-green" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#168A5B"/></marker>
<marker id="arrow-red" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#D64550"/></marker>
<marker id="arrow-amber" markerWidth="10" markerHeight="8" refX="9" refY="4" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 4 L 0 8 z" fill="#B7791F"/></marker>
</defs>
<rect width="1500" height="850" fill="#FFFFFF"/>
<rect x="560" y="25" width="352.4" height="30" fill="#F6F7F9" stroke="#AEB5BF" stroke-width="1.2" rx="15" />
<text x="736.2" y="45" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#667085" text-anchor="middle">상단 = 현재 배선 · 하단 점선 = FUTURE 계약 입력</text>
<rect x="40" y="85" width="680" height="430" fill="#FBFCFE" stroke="#1677FF" stroke-width="1.3" rx="10" />
<rect x="49" y="74" width="181.9" height="20" fill="#FFFFFF" rx="2" />
<text x="56" y="90" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#0B5CC4" text-anchor="start">TransactionPort · 현재 배선</text>
<rect x="105" y="155" width="250" height="90" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="230" y="176" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="600" fill="#667085" text-anchor="middle" letter-spacing="0.8">&lt;&lt;interface&gt;&gt;</text>
<text x="230" y="200" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">TransactionPort</text>
<text x="230" y="225" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">application-core contract</text>
<rect x="110" y="315" width="71.9" height="30" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.2" rx="15" />
<text x="145.9" y="335" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#0B5CC4" text-anchor="middle">inWrite</text>
<rect x="280" y="315" width="65.0" height="30" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.2" rx="15" />
<text x="312.5" y="335" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#0B5CC4" text-anchor="middle">inRead</text>
<rect x="450" y="315" width="58.2" height="30" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.2" rx="15" />
<text x="479.1" y="335" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#0B5CC4" text-anchor="middle">inNew</text>
<rect x="430" y="155" width="240" height="90" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="550" y="194" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">SpringTransactionPort</text>
<text x="550" y="219" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">implements</text>
<path d="M 430 200 L 355 200" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" marker-end="url(#arrow-purple)" />
<rect x="354.1" y="175" width="76.7" height="20" fill="#FFFFFF" rx="2" />
<text x="392.5" y="191" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">Implements</text>
<path d="M 230 245 L 230 280" fill="none" stroke="#1677FF" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" />
<circle cx="230" cy="280" r="4" fill="#1677FF" />
<path d="M 230 280 L 145 315" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<path d="M 230 280 L 315 315" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="252.9" y="258" width="64.2" height="20" fill="#FFFFFF" rx="2" />
<text x="285" y="274" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#1677FF" text-anchor="middle">Declares</text>
<path d="M 230 280 L 485 315" fill="none" stroke="#1677FF" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-blue)" />
<rect x="780" y="85" width="680" height="430" fill="#FBFCFE" stroke="#7556D8" stroke-width="1.3" rx="10" />
<rect x="789" y="74" width="206.9" height="20" fill="#FFFFFF" rx="2" />
<text x="796" y="90" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="start">DistributedLockPort · 현재 배선</text>
<rect x="830" y="150" width="245" height="85" fill="#F1EDFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="952.5" y="171" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="600" fill="#667085" text-anchor="middle" letter-spacing="0.8">&lt;&lt;interface&gt;&gt;</text>
<text x="952.5" y="192.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="16" font-weight="700" fill="#25282D" text-anchor="middle">DistributedLockPort</text>
<text x="952.5" y="217.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">application-core contract</text>
<rect x="820" y="310" width="250" height="82" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="945" y="345" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">false · in-process adapter</text>
<text x="945" y="370" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">default</text>
<rect x="1125" y="310" width="245" height="82" fill="#FFFFFF" stroke="#59616B" stroke-width="1.5" rx="8" />
<text x="1247.5" y="345" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">true · JDBC lock adapter</text>
<text x="1247.5" y="370" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">conditional</text>
<path d="M 920 235 L 920 310" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-purple)" />
<rect x="891.1" y="247.5" width="57.9" height="20" fill="#FFFFFF" rx="2" />
<text x="920" y="263.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">Default</text>
<path d="M 1010 235 L 1247 310" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-purple)" />
<rect x="1087.0" y="247.5" width="83.0" height="20" fill="#FFFFFF" rx="2" />
<text x="1128.5" y="263.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">Conditional</text>
<rect x="1125" y="425" width="245" height="58" fill="#FFFFFF" stroke="#7556D8" stroke-width="1.5" rx="8" />
<text x="1247.5" y="459" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#25282D" text-anchor="middle">MeteredDistributedLockPort</text>
<path d="M 1247 392 L 1247 425" fill="none" stroke="#7556D8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" marker-end="url(#arrow-purple)" />
<rect x="1189.8" y="383.5" width="114.3" height="20" fill="#FFFFFF" rx="2" />
<text x="1247" y="399.5" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#7556D8" text-anchor="middle">Conditional wrap</text>
<rect x="835" y="435" width="128.5" height="30" fill="#FDEDEF" stroke="#D64550" stroke-width="1.2" rx="15" />
<text x="899.3" y="455" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#D64550" text-anchor="middle">프로덕션 호출자 0</text>
<path d="M 835 450 L 795 450 L 795 192 L 830 192" fill="none" stroke="#D64550" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" />
<path d="M 799 179 L 825 205" fill="none" stroke="#D64550" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M 825 179 L 799 205" fill="none" stroke="#D64550" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" />
<rect x="120" y="600" width="1260" height="195" fill="#FBFCFE" stroke="#667085" stroke-width="1.3" rx="10" stroke-dasharray="8 6" />
<rect x="129" y="589" width="232.2" height="20" fill="#FFFFFF" rx="2" />
<text x="136" y="605" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#667085" text-anchor="start">FUTURE 계약 · 현재 프로덕션 실행 없음</text>
<rect x="170" y="660" width="71.9" height="30" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.2" rx="15" />
<text x="205.9" y="680" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#0B5CC4" text-anchor="middle">acquire</text>
<path d="M 315 675 L 520 675" fill="none" stroke="#667085" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" marker-end="url(#arrow-muted)" />
<rect x="520" y="660" width="65.0" height="30" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.2" rx="15" />
<text x="552.5" y="680" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#0B5CC4" text-anchor="middle">commit</text>
<path d="M 650 675 L 855 675" fill="none" stroke="#667085" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" marker-end="url(#arrow-muted)" />
<rect x="855" y="660" width="71.9" height="30" fill="#FFFFFF" stroke="#1677FF" stroke-width="1.2" rx="15" />
<text x="890.9" y="680" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="700" fill="#0B5CC4" text-anchor="middle">release</text>
<rect x="1060" y="642" width="270" height="70" fill="#EAF7F1" stroke="#168A5B" stroke-width="1.5" rx="8" />
<text x="1195" y="671" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="13" font-weight="700" fill="#25282D" text-anchor="middle">DB 제약 · 낙관적 동시성</text>
<text x="1195" y="696" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="12" font-weight="450" fill="#667085" text-anchor="middle">최종 정합성 방어선</text>
<path d="M 230 515 L 230 580 L 230 600" fill="none" stroke="#667085" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" />
<path d="M 1000 515 L 1000 580 L 1000 600" fill="none" stroke="#667085" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" />
<path d="M 1060 677 L 980 677" fill="none" stroke="#168A5B" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6 5" marker-end="url(#arrow-green)" />
<rect x="959.7" y="652" width="120.6" height="20" fill="#FFFFFF" rx="2" />
<text x="1020" y="668" font-family='&quot;Noto Sans CJK KR&quot;, &quot;Apple SD Gothic Neo&quot;, sans-serif' font-size="11" font-weight="650" fill="#168A5B" text-anchor="middle">Correctness guard</text>
</svg>

Before

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,169 @@
{
"version": "1.1",
"id": "adapter-inbound-graphql-c04",
"title": "요청 예산에서 파생되는 계층",
"question": "요청 데드라인은 아래 계층으로 내려가는가?",
"type": "dependency",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "요청 데드라인은 배선돼 있지만 네 파생 계층은 메서드로만 있고 프로덕션 호출자가 0이라 파생 전이가 일어나지 않는다.",
"alt": "요청 데드라인에서 네 파생 계층으로 가는 화살표가 모두 점선이다.",
"long_description": "SSOT §10 은 이 리프가 무엇을 하는 코드인지를 센다. 배선된 요청 데드라인에서 나가는 화살표가 없고 리졸버 예산·DataLoader 배치 타임아웃·다운스트림 데드라인·구독 데드라인은 메서드로만 존재한다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 18990,
"line": 18990
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "예산이 아래로 내려가야 할 자리에서 멈춘다는 방향이 논지다.",
"focus_node": "budget"
},
"groups": [],
"nodes": [
{
"id": "budget",
"label": "요청 데드라인",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 18990,
"end_line": 19005
}
],
"assumption": false,
"emphasis": "primary",
"details": [
"배선됨"
]
},
{
"id": "resolver",
"label": "리졸버 예산",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 18990,
"end_line": 19005
}
],
"assumption": false
},
{
"id": "loader",
"label": "DataLoader 배치 타임아웃",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 18990,
"end_line": 19005
}
],
"assumption": false
},
{
"id": "down",
"label": "다운스트림 데드라인",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 18990,
"end_line": 19005
}
],
"assumption": false
},
{
"id": "sub",
"label": "구독 데드라인",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 18990,
"end_line": 19007
}
],
"assumption": false
}
],
"edges": [
{
"id": "a",
"from": "budget",
"to": "resolver",
"label": "파생 없음",
"kind": "request",
"evidence": [
{
"start_line": 18990,
"end_line": 19005
}
],
"assumption": false,
"style": "dashed",
"emphasis": "primary"
},
{
"id": "b",
"from": "budget",
"to": "loader",
"label": "파생 없음",
"kind": "request",
"evidence": [
{
"start_line": 18990,
"end_line": 19005
}
],
"assumption": false,
"style": "dashed"
},
{
"id": "c",
"from": "budget",
"to": "down",
"label": "파생 없음",
"kind": "request",
"evidence": [
{
"start_line": 18990,
"end_line": 19005
}
],
"assumption": false,
"style": "dashed"
},
{
"id": "d",
"from": "budget",
"to": "sub",
"label": "파생 없음",
"kind": "request",
"evidence": [
{
"start_line": 18990,
"end_line": 19007
}
],
"assumption": false,
"style": "dashed"
}
],
"legend": [],
"metadata": {}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,141 @@
{
"version": "1.1",
"id": "adapter-inbound-graphql-c09",
"title": "응답을 실제로 만드는 쪽",
"question": "GraphQL 응답의 상태 코드와 미디어 타입은 누가 정하는가?",
"type": "dependency",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "상태 코드와 미디어 타입 규칙을 담은 http 패키지가 조립되지 않고 실제 응답은 프레임워크가 만든다.",
"alt": "GraphQL 요청에서 Spring GraphQL 로 화살표가 가고 거기서 응답이 나온다. http 패키지로 가는 화살표는 점선이다.",
"long_description": "SSOT §20.1b 는 HTTP 전송 계약 계층이 미배선이고 실제 전송은 프레임워크가 정한다고 적는다. 노출이 아니라 통제권의 문제다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 19344,
"line": 19344
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "응답을 만드는 경로가 프레임워크로 가고 규칙을 담은 패키지로는 가지 않는 방향이 논지다.",
"focus_node": "spring"
},
"groups": [],
"nodes": [
{
"id": "req",
"label": "GraphQL 요청",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 19344,
"end_line": 19350
}
],
"assumption": false
},
{
"id": "spring",
"label": "Spring GraphQL",
"kind": "service",
"role": "service",
"evidence": [
{
"start_line": 19344,
"end_line": 19355
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "resp",
"label": "응답",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 19344,
"end_line": 19355
}
],
"assumption": false
},
{
"id": "http",
"label": "http 패키지",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 19344,
"end_line": 19360
}
],
"assumption": false,
"details": [
"상태 코드 규칙",
"미디어 타입 협상",
"미배선"
]
}
],
"edges": [
{
"id": "a",
"from": "req",
"to": "spring",
"label": "처리",
"kind": "request",
"evidence": [
{
"start_line": 19344,
"end_line": 19350
}
],
"assumption": false
},
{
"id": "b",
"from": "spring",
"to": "resp",
"label": "응답 생성",
"kind": "request",
"evidence": [
{
"start_line": 19344,
"end_line": 19355
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "c",
"from": "spring",
"to": "http",
"label": "미도달",
"kind": "request",
"evidence": [
{
"start_line": 19344,
"end_line": 19360
}
],
"assumption": false,
"style": "dashed"
}
],
"legend": [],
"metadata": {}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,137 @@
{
"version": "1.1",
"id": "adapter-inbound-graphql-c10",
"title": "패키지별 도달 경로",
"question": "자동설정에서 어느 패키지까지 배선이 닿는가?",
"type": "dependency",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "자동설정과 배치 로더 등록기에서 나가는 경로는 dataloader 에만 닿고 fetch·pagination·mutation 으로는 닿지 않는다.",
"alt": "자동설정에서 registrar 를 거쳐 dataloader 로 화살표가 가고 fetch 와 pagination 과 mutation 으로는 점선이 간다.",
"long_description": "SSOT 는 자동설정과 배치 로더 등록기에서 나가는 배선 경로가 dataloader 에만 닿는다고 적는다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 19824,
"line": 19824
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "배선이 어느 패키지까지 가고 어디서 멈추는지가 논지다.",
"focus_node": "auto"
},
"groups": [],
"nodes": [
{
"id": "auto",
"label": "자동설정 · 배치 로더 등록기",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 19824,
"end_line": 20000
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "dl",
"label": "dataloader",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 19824,
"end_line": 20000
}
],
"assumption": false
},
{
"id": "fetch",
"label": "fetch",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 19824,
"end_line": 20024
}
],
"assumption": false
},
{
"id": "page",
"label": "pagination · mutation",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 19824,
"end_line": 20024
}
],
"assumption": false
}
],
"edges": [
{
"id": "a",
"from": "auto",
"to": "dl",
"label": "registrar 경유",
"kind": "request",
"evidence": [
{
"start_line": 19824,
"end_line": 20000
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "b",
"from": "auto",
"to": "fetch",
"label": "배선 없음",
"kind": "request",
"evidence": [
{
"start_line": 19824,
"end_line": 20024
}
],
"assumption": false,
"style": "dashed"
},
{
"id": "c",
"from": "auto",
"to": "page",
"label": "배선 없음",
"kind": "request",
"evidence": [
{
"start_line": 19824,
"end_line": 20024
}
],
"assumption": false,
"style": "dashed"
}
],
"legend": [],
"metadata": {}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,108 @@
{
"version": "1.1",
"id": "adapter-inbound-grpc-c01",
"title": "인터셉터 순서",
"question": "인증과 예외 변환은 어느 순서인가?",
"type": "dependency",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "인증이 업무 처리보다 앞서고 예외 변환이 그 뒤에 와야 인증 실패가 업무 오류로 보고되지 않는다.",
"alt": "요청이 인증과 업무 처리를 지나 예외 변환으로 이어지는 순서.",
"long_description": "SSOT 는 인증과 예외 처리의 순서가 곧 계약이고 예외 처리가 인증보다 앞서면 인증 실패가 업무 오류로 보고된다고 적는다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 504,
"line": 504
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "순서가 뒤집히면 오류 분류가 달라진다는 것이 논지다.",
"focus_node": "auth"
},
"groups": [],
"nodes": [
{
"id": "auth",
"label": "인증",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 494,
"end_line": 512
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "biz",
"label": "업무 처리",
"kind": "service",
"role": "service",
"evidence": [
{
"start_line": 494,
"end_line": 512
}
],
"assumption": false
},
{
"id": "err",
"label": "예외 변환",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 494,
"end_line": 517
}
],
"assumption": false
}
],
"edges": [
{
"id": "a",
"from": "auth",
"to": "biz",
"label": "통과",
"kind": "request",
"evidence": [
{
"start_line": 494,
"end_line": 512
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "b",
"from": "biz",
"to": "err",
"label": "오류 전달",
"kind": "request",
"evidence": [
{
"start_line": 494,
"end_line": 517
}
],
"assumption": false
}
],
"legend": [],
"metadata": {}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,109 @@
{
"version": "1.1",
"id": "adapter-inbound-web-c01",
"title": "타입이 고르는 자동설정",
"question": "두 자동설정 중 무엇이 켜지는가?",
"type": "dependency",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "두 자동설정은 모두 기본 켜짐이지만 활성화를 가르는 것은 프로퍼티가 아니라 웹 애플리케이션 타입이다.",
"alt": "웹 애플리케이션 타입이 SERVLET 이면 MVC 자동설정으로 REACTIVE 면 WebFlux 자동설정으로 간다.",
"long_description": "SSOT 는 두 자동설정이 모두 기본 켜짐이고 활성화를 가르는 것이 프로퍼티가 아니라 애플리케이션 타입이라고 적는다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 17783,
"line": 17783
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "한 값이 두 자동설정 중 하나를 고르는 갈림이 논지다.",
"focus_node": "type"
},
"groups": [],
"nodes": [
{
"id": "type",
"label": "웹 애플리케이션 타입",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 17783,
"end_line": 17815
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "mvc",
"label": "MVC 자동설정",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 17783,
"end_line": 17815
}
],
"assumption": false
},
{
"id": "flux",
"label": "WebFlux 자동설정",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 17783,
"end_line": 17819
}
],
"assumption": false
}
],
"edges": [
{
"id": "a",
"from": "type",
"to": "mvc",
"label": "SERVLET",
"kind": "request",
"evidence": [
{
"start_line": 17783,
"end_line": 17815
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "b",
"from": "type",
"to": "flux",
"label": "REACTIVE",
"kind": "request",
"evidence": [
{
"start_line": 17783,
"end_line": 17819
}
],
"assumption": false,
"style": "dashed"
}
],
"legend": [],
"metadata": {}
}
@@ -0,0 +1,136 @@
{
"version": "1.1",
"id": "adapter-inbound-web-c03",
"title": "신원 모델이 닿는 범위",
"question": "security 패키지의 타입을 누가 부르는가?",
"type": "dependency",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "security 패키지의 타입들은 서로를 부르지만 패키지 바깥에서 들어오는 프로덕션 호출자가 없다.",
"alt": "바깥 프로덕션 호출자에서 security 패키지로 가는 화살표는 점선이고, 패키지 안에서는 브리지와 뷰와 가드가 이어진다.",
"long_description": "SSOT §11.1 은 신원 모델의 프로덕션 참조 수를 센다. 타입들은 서로를 부르지만 패키지 바깥에서 들어오는 프로덕션 호출자가 없고 교차 테넌트 가드도 그 안에만 있다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 16831,
"line": 16831
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "호출이 패키지 안에서만 돌고 바깥에서 들어오지 않는다는 방향이 논지다.",
"focus_node": "bridge"
},
"groups": [],
"nodes": [
{
"id": "outside",
"label": "바깥 프로덕션 호출자",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 16831,
"end_line": 16850
}
],
"assumption": false
},
{
"id": "bridge",
"label": "WebSecurityContextBridge",
"kind": "service",
"role": "service",
"evidence": [
{
"start_line": 16831,
"end_line": 16850
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "view",
"label": "AuthenticationView",
"kind": "service",
"role": "service",
"evidence": [
{
"start_line": 16831,
"end_line": 16850
}
],
"assumption": false
},
{
"id": "guard",
"label": "rejectTenantInput",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 16831,
"end_line": 16850
}
],
"assumption": false
}
],
"edges": [
{
"id": "a",
"from": "outside",
"to": "bridge",
"label": "없음",
"kind": "request",
"evidence": [
{
"start_line": 16831,
"end_line": 16850
}
],
"assumption": false,
"style": "dashed",
"emphasis": "primary"
},
{
"id": "b",
"from": "bridge",
"to": "view",
"label": "신원 노출",
"kind": "request",
"evidence": [
{
"start_line": 16831,
"end_line": 16850
}
],
"assumption": false
},
{
"id": "c",
"from": "view",
"to": "guard",
"label": "교차 테넌트 검사",
"kind": "request",
"evidence": [
{
"start_line": 16831,
"end_line": 16850
}
],
"assumption": false
}
],
"legend": [],
"metadata": {}
}
@@ -0,0 +1,135 @@
{
"version": "1.1",
"id": "adapter-inbound-web-c04",
"title": "매처가 등록되는 순서",
"question": "보안 매처는 어떤 순서로 걸리는가?",
"type": "dependency",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "먼저 일치한 매처가 이기므로 공개 경로가 먼저 등록되어 제한 경로 규칙보다 앞선다.",
"alt": "요청이 publicPaths permitAll 을 먼저 만나고 다음에 RestrictedPathRule 과 anyRequest authenticated 를 만나는 순서.",
"long_description": "SSOT 는 Spring Security 에서 먼저 일치한 매처가 이기고 공개 경로가 먼저 등록되므로 제한 경로 규칙보다 앞선다고 적는다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 16987,
"line": 16987
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "등록 순서가 판정 순서를 정한다는 방향이 논지다.",
"focus_node": "public"
},
"groups": [],
"nodes": [
{
"id": "req",
"label": "요청",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 16987,
"end_line": 16994
}
],
"assumption": false
},
{
"id": "public",
"label": "publicPaths permitAll",
"kind": "service",
"role": "service",
"evidence": [
{
"start_line": 16987,
"end_line": 16994
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "rule",
"label": "RestrictedPathRule",
"kind": "service",
"role": "service",
"evidence": [
{
"start_line": 16987,
"end_line": 16994
}
],
"assumption": false
},
{
"id": "any",
"label": "anyRequest authenticated",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 16987,
"end_line": 16996
}
],
"assumption": false
}
],
"edges": [
{
"id": "a",
"from": "req",
"to": "public",
"label": "먼저 등록",
"kind": "request",
"evidence": [
{
"start_line": 16987,
"end_line": 16994
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "b",
"from": "public",
"to": "rule",
"label": "다음 등록",
"kind": "request",
"evidence": [
{
"start_line": 16987,
"end_line": 16994
}
],
"assumption": false
},
{
"id": "c",
"from": "rule",
"to": "any",
"label": "마지막",
"kind": "request",
"evidence": [
{
"start_line": 16987,
"end_line": 16996
}
],
"assumption": false
}
],
"legend": [],
"metadata": {}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,142 @@
{
"version": "1.1",
"id": "adapter-inbound-websocket-c01",
"title": "설정 접두사와 소비자",
"question": "설정 접두사를 읽는 Configuration 이 있는가?",
"type": "component",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "두 접두사는 그것을 읽는 Configuration 이 있고 세 번째 접두사는 읽어 조립하는 곳이 없다.",
"alt": "WebSocketConfig 가 두 설정 접두사를 읽고 세 번째 접두사는 읽는 곳이 없다.",
"long_description": "SSOT 는 두 접두사에서 그것을 읽는 Configuration 으로 화살표가 가고 세 번째 접두사에는 읽어 조립하는 곳이 없다고 적는다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 20052,
"line": 20052
}
},
"composition": {
"profile": "orchestrator-workers",
"diagram_only": true,
"reference_ids": [
"mission-workers"
],
"rationale": "한 설정 클래스가 어느 접두사를 읽고 어느 것을 읽지 않는지가 논지다.",
"focus_node": "cfg"
},
"groups": [],
"nodes": [
{
"id": "cfg",
"label": "WebSocketConfig",
"kind": "service",
"role": "orchestrator",
"evidence": [
{
"start_line": 20052,
"end_line": 20074
}
],
"assumption": false,
"emphasis": "primary",
"details": [
"SockJs · Stomp"
]
},
{
"id": "skel",
"label": "ca-skeleton.websocket",
"kind": "service",
"role": "worker",
"evidence": [
{
"start_line": 20052,
"end_line": 20074
}
],
"assumption": false
},
{
"id": "adv",
"label": "app.websocket-platform.advanced",
"kind": "service",
"role": "worker",
"evidence": [
{
"start_line": 20052,
"end_line": 20074
}
],
"assumption": false
},
{
"id": "backend",
"label": "backend.websocket",
"kind": "service",
"role": "monitor",
"evidence": [
{
"start_line": 20052,
"end_line": 20078
}
],
"assumption": false,
"details": [
"읽는 Configuration 없음"
]
}
],
"edges": [
{
"id": "a",
"from": "cfg",
"to": "skel",
"label": "읽음",
"kind": "request",
"evidence": [
{
"start_line": 20052,
"end_line": 20074
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "b",
"from": "cfg",
"to": "adv",
"label": "읽음",
"kind": "request",
"evidence": [
{
"start_line": 20052,
"end_line": 20074
}
],
"assumption": false
},
{
"id": "c",
"from": "cfg",
"to": "backend",
"label": "읽지 않음",
"kind": "request",
"evidence": [
{
"start_line": 20052,
"end_line": 20078
}
],
"assumption": false,
"style": "dashed"
}
],
"legend": [],
"metadata": {}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,108 @@
{
"version": "1.1",
"id": "adapter-outbound-cache-redis-c01",
"title": "조립이 고정된 순서",
"question": "클라이언트는 무엇을 지난 뒤에 만들어지는가?",
"type": "dependency",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "설정을 묶고 교차 필드 규칙을 돌린 뒤에야 클라이언트와 연결이 만들어진다.",
"alt": "설정 바인딩에서 교차 필드 검증으로 그리고 클라이언트 생성으로 이어지는 순서.",
"long_description": "SSOT 는 검증이 bean factory 메서드 안에 있어 검증을 지나지 않고는 클라이언트가 만들어질 수 없다고 적는다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 10437,
"line": 10437
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "생성이 검증 뒤에만 일어난다는 고정된 순서가 논지다.",
"focus_node": "check"
},
"groups": [],
"nodes": [
{
"id": "bind",
"label": "설정 바인딩",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 10437,
"end_line": 10442
}
],
"assumption": false
},
{
"id": "check",
"label": "교차 필드 검증",
"kind": "service",
"role": "service",
"evidence": [
{
"start_line": 10437,
"end_line": 10442
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "client",
"label": "클라이언트 · 연결 생성",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 10437,
"end_line": 10444
}
],
"assumption": false
}
],
"edges": [
{
"id": "a",
"from": "bind",
"to": "check",
"label": "bound settings",
"kind": "request",
"evidence": [
{
"start_line": 10437,
"end_line": 10442
}
],
"assumption": false
},
{
"id": "b",
"from": "check",
"to": "client",
"label": "검증 통과",
"kind": "request",
"evidence": [
{
"start_line": 10437,
"end_line": 10444
}
],
"assumption": false,
"emphasis": "primary"
}
],
"legend": [],
"metadata": {}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,108 @@
{
"version": "1.1",
"id": "adapter-outbound-cache-redis-c03",
"title": "부재를 지키는 세 자리",
"question": "없는 명령은 어디서 막히는가?",
"type": "dependency",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "없는 명령이라는 선언이 API 문서와 구현 계층과 명령 정책 파일 세 곳에서 각각 다시 막힌다.",
"alt": "sdk/api 선언에서 Lettuce 구현 계층으로 그리고 redis-command-policy.yml 로 강제가 이어진다.",
"long_description": "SSOT 는 없는 명령이라는 선언이 API 문서에만 있지 않고 구현 계층과 명령 정책 파일이 같은 부재를 각각 다시 막는다고 적는다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 12887,
"line": 12887
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "같은 부재를 세 자리가 겹쳐 막는 방향이 논지다.",
"focus_node": "sdk"
},
"groups": [],
"nodes": [
{
"id": "sdk",
"label": "sdk/api 선언",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 12887,
"end_line": 12894
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "lettuce",
"label": "Lettuce 구현 계층",
"kind": "service",
"role": "service",
"evidence": [
{
"start_line": 12887,
"end_line": 12894
}
],
"assumption": false
},
{
"id": "policy",
"label": "redis-command-policy.yml",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 12887,
"end_line": 12896
}
],
"assumption": false
}
],
"edges": [
{
"id": "a",
"from": "sdk",
"to": "lettuce",
"label": "강제 방향",
"kind": "request",
"evidence": [
{
"start_line": 12887,
"end_line": 12894
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "b",
"from": "lettuce",
"to": "policy",
"label": "강제 방향",
"kind": "request",
"evidence": [
{
"start_line": 12887,
"end_line": 12896
}
],
"assumption": false
}
],
"legend": [],
"metadata": {}
}
@@ -0,0 +1,108 @@
{
"version": "1.1",
"id": "adapter-outbound-cache-redis-c04",
"title": "검사기에 대한 메타 검사",
"question": "검사기가 고장 나면 무엇이 잡는가?",
"type": "dependency",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "두 진입점의 대칭을 반사 검사가 강제하고 그 검사기가 항상 통과하는 상태를 메타 테스트가 잡는다.",
"alt": "두 진입점 인터페이스를 ApiParityTest 가 검사하고 그 검사기를 메타 테스트가 다시 검사한다.",
"long_description": "SSOT 는 두 진입점의 대칭을 반사 검사가 강제하고 그 검사기가 고장 나 항상 통과하는 상태를 잡는 메타 테스트가 위에 하나 더 있다고 적는다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 12903,
"line": 12903
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "검사기 위에 검사기가 한 겹 더 있다는 방향이 논지다.",
"focus_node": "parity"
},
"groups": [],
"nodes": [
{
"id": "api",
"label": "두 진입점 인터페이스",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 12903,
"end_line": 12912
}
],
"assumption": false
},
{
"id": "parity",
"label": "ApiParityTest",
"kind": "service",
"role": "service",
"evidence": [
{
"start_line": 12903,
"end_line": 12912
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "meta",
"label": "검사기에 대한 메타 테스트",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 12903,
"end_line": 12914
}
],
"assumption": false
}
],
"edges": [
{
"id": "a",
"from": "api",
"to": "parity",
"label": "검사 방향",
"kind": "request",
"evidence": [
{
"start_line": 12903,
"end_line": 12912
}
],
"assumption": false
},
{
"id": "b",
"from": "parity",
"to": "meta",
"label": "검사 방향",
"kind": "request",
"evidence": [
{
"start_line": 12903,
"end_line": 12914
}
],
"assumption": false,
"emphasis": "primary"
}
],
"legend": [],
"metadata": {}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,111 @@
{
"version": "1.1",
"id": "adapter-outbound-cache-redis-c08",
"title": "두 모델이 공유하는 빌더",
"question": "동기와 반응형 표면은 무엇을 공유하는가?",
"type": "dependency",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "동기 표면과 반응형 표면이 같은 request builder 로 같은 요청 객체를 만든다.",
"alt": "동기 표면과 반응형 표면이 모두 ValueOperationRequests 로 같은 요청 객체를 만든다.",
"long_description": "SSOT 는 동기 표면과 반응형 표면이 같은 request builder 를 만들어 쓰므로 permit·예산·인코딩·명령 선택의 변경이 양쪽에 함께 적용된다고 적는다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 13108,
"line": 13108
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "두 표면이 한 빌더로 모이는 방향이 논지다.",
"focus_node": "builder"
},
"groups": [],
"nodes": [
{
"id": "sync",
"label": "동기 표면",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 13108,
"end_line": 13113
}
],
"assumption": false
},
{
"id": "reactive",
"label": "반응형 표면",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 13108,
"end_line": 13115
}
],
"assumption": false
},
{
"id": "builder",
"label": "ValueOperationRequests",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 13108,
"end_line": 13113
}
],
"assumption": false,
"emphasis": "primary",
"details": [
"같은 요청 객체"
]
}
],
"edges": [
{
"id": "a",
"from": "sync",
"to": "builder",
"label": "요청 생성",
"kind": "request",
"evidence": [
{
"start_line": 13108,
"end_line": 13113
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "b",
"from": "reactive",
"to": "builder",
"label": "요청 생성",
"kind": "request",
"evidence": [
{
"start_line": 13108,
"end_line": 13115
}
],
"assumption": false
}
],
"legend": [],
"metadata": {}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,174 @@
{
"version": "1.1",
"id": "adapter-outbound-cache-redis-c10",
"title": "고정된 검증 순서",
"question": "명령은 어떤 순서로 검증되는가?",
"type": "dependency",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "뒤 단계일수록 비싸므로 명백히 부적격한 명령은 인코딩도 전송도 하기 전에 거절된다.",
"alt": "명령이 capability 와 risk·permit 과 namespace 와 slot 과 request budget 을 차례로 지나는 순서.",
"long_description": "SSOT 는 명령 하나가 나가기 전에 지나는 단계를 적는다 — 카탈로그 분류, capability 와 최소 버전 확인, permit provenance 검증, 네임스페이스 검사, Cluster 동일 슬롯 검사, 요청 예산이다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 46523,
"line": 46523
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "뒤 단계가 비싸므로 앞에서 거른다는 순서가 논지다.",
"focus_node": "cap"
},
"groups": [],
"nodes": [
{
"id": "cap",
"label": "capability",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 46523,
"end_line": 46700
}
],
"assumption": false,
"emphasis": "primary",
"details": [
"버전 대조"
]
},
{
"id": "risk",
"label": "risk · permit",
"kind": "service",
"role": "service",
"evidence": [
{
"start_line": 46523,
"end_line": 46700
}
],
"assumption": false,
"details": [
"위험 등급"
]
},
{
"id": "ns",
"label": "namespace",
"kind": "service",
"role": "service",
"evidence": [
{
"start_line": 46523,
"end_line": 46700
}
],
"assumption": false,
"details": [
"키 소유"
]
},
{
"id": "slot",
"label": "slot",
"kind": "service",
"role": "service",
"evidence": [
{
"start_line": 46523,
"end_line": 46796
}
],
"assumption": false,
"details": [
"단일 슬롯"
]
},
{
"id": "budget",
"label": "request budget",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 46523,
"end_line": 46796
}
],
"assumption": false
}
],
"edges": [
{
"id": "a",
"from": "cap",
"to": "risk",
"label": "통과",
"kind": "request",
"evidence": [
{
"start_line": 46523,
"end_line": 46700
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "b",
"from": "risk",
"to": "ns",
"label": "통과",
"kind": "request",
"evidence": [
{
"start_line": 46523,
"end_line": 46700
}
],
"assumption": false
},
{
"id": "c",
"from": "ns",
"to": "slot",
"label": "통과",
"kind": "request",
"evidence": [
{
"start_line": 46523,
"end_line": 46796
}
],
"assumption": false
},
{
"id": "d",
"from": "slot",
"to": "budget",
"label": "통과",
"kind": "request",
"evidence": [
{
"start_line": 46523,
"end_line": 46796
}
],
"assumption": false
}
],
"legend": [],
"metadata": {}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,132 @@
{
"version": "1.1",
"id": "adapter-outbound-cache-redis-c12",
"title": "원시 명령이 지나야 하는 두 문",
"question": "원시 명령은 무엇을 통과해야 하는가?",
"type": "sequence",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "조직이 정한 카탈로그 분류와 배포가 등록한 승인 둘 다를 통과해야 하고 어느 쪽도 요청 시점에 결정되지 않는다.",
"alt": "원시 명령이 정책 카탈로그와 승인 등록을 차례로 지나 게이트웨이에 닿는 순서.",
"long_description": "SSOT 는 원시 명령이 조직이 정한 카탈로그 분류(RAW_ONLY)와 배포가 등록한 승인(ApprovedRawCommand) 둘 다를 통과해야 한다고 적는다. 어느 쪽도 요청 시점에 결정되지 않는다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 13603,
"line": 13603
}
},
"composition": {
"profile": "sequence",
"diagram_only": true,
"reference_ids": [
"payment-approval-sequence"
],
"rationale": "요청 전에 정해진 두 문을 차례로 지나야 한다는 순서가 논지다.",
"focus_node": "gateway"
},
"groups": [],
"nodes": [
{
"id": "cmd",
"label": "원시 명령",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 13603,
"end_line": 13740
}
],
"assumption": false
},
{
"id": "catalog",
"label": "정책 카탈로그 RAW_ONLY",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 13603,
"end_line": 13740
}
],
"assumption": false,
"details": [
"조직의 결정"
]
},
{
"id": "gateway",
"label": "RedisRawGateway",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 13603,
"end_line": 13755
}
],
"assumption": false,
"emphasis": "primary",
"details": [
"ApprovedRawCommand 등록",
"배포의 결정"
]
}
],
"edges": [
{
"id": "m1",
"from": "cmd",
"to": "catalog",
"label": "분류 확인",
"kind": "request",
"evidence": [
{
"start_line": 13603,
"end_line": 13740
}
],
"assumption": false,
"order": 1
},
{
"id": "m2",
"from": "catalog",
"to": "gateway",
"label": "RAW_ONLY 통과",
"kind": "request",
"evidence": [
{
"start_line": 13603,
"end_line": 13740
}
],
"assumption": false,
"order": 2
},
{
"id": "m3",
"from": "gateway",
"to": "cmd",
"label": "승인 등록 확인",
"kind": "response",
"evidence": [
{
"start_line": 13603,
"end_line": 13755
}
],
"assumption": false,
"order": 3,
"emphasis": "primary"
}
],
"legend": [],
"metadata": {}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,116 @@
{
"version": "1.1",
"id": "adapter-outbound-cache-redis-c13",
"title": "등록과 실행의 분리",
"question": "스크립트는 어떻게 실행되는가?",
"type": "sequence",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "배포 시 등록된 스크립트만 digest 를 가지므로 검토된 것만 실행된다는 성질이 관례가 아니라 구조가 된다.",
"alt": "배포 시 스크립트를 등록하고 digest 를 대조한 뒤 EVALSHA 로 실행하는 순서.",
"long_description": "SSOT 는 등록되지 않은 스크립트가 digest 가 없어 서버에 닿을 방법이 없다고 적는다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 13245,
"line": 13245
}
},
"composition": {
"profile": "sequence",
"diagram_only": true,
"reference_ids": [
"payment-approval-sequence"
],
"rationale": "등록이 실행의 전제라는 순서가 논지다.",
"focus_node": "digest"
},
"groups": [],
"nodes": [
{
"id": "reg",
"label": "배포 시 스크립트 등록",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 13241,
"end_line": 13251
}
],
"assumption": false,
"details": [
"등록본 저장"
]
},
{
"id": "digest",
"label": "digest 대조",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 13241,
"end_line": 13251
}
],
"assumption": false,
"emphasis": "primary",
"details": [
"본문 일치"
]
},
{
"id": "eval",
"label": "EVALSHA 실행",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 13241,
"end_line": 13254
}
],
"assumption": false
}
],
"edges": [
{
"id": "m1",
"from": "reg",
"to": "digest",
"label": "등록 결과",
"kind": "request",
"evidence": [
{
"start_line": 13241,
"end_line": 13251
}
],
"assumption": false,
"order": 1
},
{
"id": "m2",
"from": "digest",
"to": "eval",
"label": "일치 확인",
"kind": "request",
"evidence": [
{
"start_line": 13241,
"end_line": 13254
}
],
"assumption": false,
"order": 2,
"emphasis": "primary"
}
],
"legend": [],
"metadata": {}
}
@@ -0,0 +1,115 @@
{
"version": "1.1",
"id": "adapter-outbound-fileserver-c03",
"title": "두 종착 상태",
"question": "파일 상태는 어디서 멈추는가?",
"type": "state",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "비terminal 상태에서 정상 종료로 가거나 격리로 이탈할 수 있고 두 종착 상태에서 나가는 전이는 없다.",
"alt": "비terminal 상태에서 PUBLISHED 와 QUARANTINED 로 화살표가 가고 그 둘에서 나가는 화살표는 없다.",
"long_description": "SSOT 는 비terminal 상태에서 정상 종료로 가거나 격리로 이탈할 수 있고 두 종착 상태에서 나가는 전이가 없다고 적는다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 11220,
"line": 11220
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "어느 상태에서 멈추고 그 뒤로는 나가지 않는다는 것이 논지다.",
"focus_node": "mid"
},
"groups": [],
"nodes": [
{
"id": "mid",
"label": "비terminal 상태",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 11220,
"end_line": 11235
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "pub",
"label": "PUBLISHED",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 11220,
"end_line": 11235
}
],
"assumption": false,
"details": [
"종착 상태"
]
},
{
"id": "quar",
"label": "QUARANTINED",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 11220,
"end_line": 11239
}
],
"assumption": false,
"details": [
"종착 상태"
]
}
],
"edges": [
{
"id": "a",
"from": "mid",
"to": "pub",
"label": "정상 종료",
"kind": "request",
"evidence": [
{
"start_line": 11220,
"end_line": 11235
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "b",
"from": "mid",
"to": "quar",
"label": "격리로 이탈",
"kind": "request",
"evidence": [
{
"start_line": 11220,
"end_line": 11239
}
],
"assumption": false,
"style": "dashed"
}
],
"legend": [],
"metadata": {}
}
@@ -0,0 +1,163 @@
{
"version": "1.1",
"id": "adapter-outbound-fileserver-c08",
"title": "선언된 것과 선언되지 않은 것",
"question": "payload 계층은 잔여 위험을 어떻게 다루는가?",
"type": "dependency",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "잔여 경로 연산이 문서에 선언되고 identity 검사로 감싸이지만 서술자에는 상대 대응물이 없다.",
"alt": "잔여 경로 연산에서 세 가지 재확인으로 화살표가 가고 서술자 상대 대응물로는 점선이 간다.",
"long_description": "SSOT §48 은 payload 계층이 자기가 막는 것과 막지 못하는 것을 함께 적는다고 기록한다. 잔여 경로 연산은 문서에 선언되고 identity 검사로 감싸인다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 11508,
"line": 11508
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "한 연산이 세 검사로 감싸이고 한 자리만 비어 있다는 것이 논지다.",
"focus_node": "ops"
},
"groups": [],
"nodes": [
{
"id": "ops",
"label": "LocalPersistentPayloadOperations",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 11508,
"end_line": 11515
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "key",
"label": "fileKey 재확인",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 11508,
"end_line": 11515
}
],
"assumption": false
},
{
"id": "owner",
"label": "소유자 · 권한 재확인",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 11508,
"end_line": 11515
}
],
"assumption": false
},
{
"id": "store",
"label": "FileStore 재확인",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 11508,
"end_line": 11515
}
],
"assumption": false
},
{
"id": "desc",
"label": "서술자 상대 대응물",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 11508,
"end_line": 11517
}
],
"assumption": false
}
],
"edges": [
{
"id": "a",
"from": "ops",
"to": "key",
"label": "검사",
"kind": "request",
"evidence": [
{
"start_line": 11508,
"end_line": 11515
}
],
"assumption": false
},
{
"id": "b",
"from": "ops",
"to": "owner",
"label": "검사",
"kind": "request",
"evidence": [
{
"start_line": 11508,
"end_line": 11515
}
],
"assumption": false
},
{
"id": "c",
"from": "ops",
"to": "store",
"label": "검사",
"kind": "request",
"evidence": [
{
"start_line": 11508,
"end_line": 11515
}
],
"assumption": false
},
{
"id": "d",
"from": "ops",
"to": "desc",
"label": "없음",
"kind": "request",
"evidence": [
{
"start_line": 11508,
"end_line": 11517
}
],
"assumption": false,
"style": "dashed",
"emphasis": "primary"
}
],
"legend": [],
"metadata": {}
}
@@ -0,0 +1,135 @@
{
"version": "1.1",
"id": "adapter-outbound-httpclient-c04",
"title": "재시도 결정의 순서",
"question": "재시도 판정은 어떤 순서로 걸리는가?",
"type": "dependency",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "싼 절대 차단이 먼저 오고 그다음 모호성 그다음 상태별 규칙이 오며 뒤 규칙이 앞 규칙의 금지를 뒤집지 못한다.",
"alt": "절대 차단 여섯을 지나 영구 실패 범주와 증거를 거쳐 상태별 규칙에 닿는 순서.",
"long_description": "SSOT 는 싼 절대 차단이 먼저 오고 그다음 모호성, 그다음 상태별 규칙이 온다고 적는다. 뒤 규칙이 앞 규칙이 금지한 것을 다시 허용할 수 없다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 14084,
"line": 14084
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "판정이 싼 것부터 걸리고 뒤가 앞을 뒤집지 못한다는 순서가 논지다.",
"focus_node": "block"
},
"groups": [],
"nodes": [
{
"id": "block",
"label": "절대 차단 여섯",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 14084,
"end_line": 14098
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "perm",
"label": "영구 실패 범주",
"kind": "service",
"role": "service",
"evidence": [
{
"start_line": 14084,
"end_line": 14098
}
],
"assumption": false
},
{
"id": "evid",
"label": "증거",
"kind": "service",
"role": "service",
"evidence": [
{
"start_line": 14084,
"end_line": 14098
}
],
"assumption": false
},
{
"id": "rule",
"label": "상태 · 실패별 규칙",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 14084,
"end_line": 14101
}
],
"assumption": false
}
],
"edges": [
{
"id": "a",
"from": "block",
"to": "perm",
"label": "통과",
"kind": "request",
"evidence": [
{
"start_line": 14084,
"end_line": 14098
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "b",
"from": "perm",
"to": "evid",
"label": "통과",
"kind": "request",
"evidence": [
{
"start_line": 14084,
"end_line": 14098
}
],
"assumption": false
},
{
"id": "c",
"from": "evid",
"to": "rule",
"label": "통과",
"kind": "request",
"evidence": [
{
"start_line": 14084,
"end_line": 14101
}
],
"assumption": false
}
],
"legend": [],
"metadata": {}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,135 @@
{
"version": "1.1",
"id": "adapter-outbound-httpclient-c05",
"title": "시도마다 지나는 가드 순서",
"question": "가드는 어떤 순서로 걸리고 풀리는가?",
"type": "dependency",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "열린 회로가 요금 토큰이나 벌크헤드 permit 을 쓰기 전에 먼저 거절하고 해제는 역순이다.",
"alt": "시도가 Circuit Breaker 와 Rate Limiter 와 Bulkhead 를 차례로 지나 HTTP 호출에 닿는 순서.",
"long_description": "SSOT 는 열린 회로가 요금 토큰이나 벌크헤드 permit 을 쓰기 전에 먼저 거절하고 해제는 역순이라고 적는다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 14102,
"line": 14102
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "싼 거절이 앞에 오고 비싼 자원이 뒤에 쓰인다는 순서가 논지다.",
"focus_node": "cb"
},
"groups": [],
"nodes": [
{
"id": "cb",
"label": "Circuit Breaker",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 14102,
"end_line": 14112
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "rl",
"label": "Rate Limiter",
"kind": "service",
"role": "service",
"evidence": [
{
"start_line": 14102,
"end_line": 14112
}
],
"assumption": false
},
{
"id": "bh",
"label": "Bulkhead",
"kind": "service",
"role": "service",
"evidence": [
{
"start_line": 14102,
"end_line": 14112
}
],
"assumption": false
},
{
"id": "http",
"label": "HTTP 호출",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 14102,
"end_line": 14114
}
],
"assumption": false
}
],
"edges": [
{
"id": "a",
"from": "cb",
"to": "rl",
"label": "허가",
"kind": "request",
"evidence": [
{
"start_line": 14102,
"end_line": 14112
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "b",
"from": "rl",
"to": "bh",
"label": "토큰",
"kind": "request",
"evidence": [
{
"start_line": 14102,
"end_line": 14112
}
],
"assumption": false
},
{
"id": "c",
"from": "bh",
"to": "http",
"label": "permit",
"kind": "request",
"evidence": [
{
"start_line": 14102,
"end_line": 14114
}
],
"assumption": false
}
],
"legend": [],
"metadata": {}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,135 @@
{
"version": "1.1",
"id": "adapter-outbound-httpclient-c06",
"title": "응답 크기 예산이 강제되는 자리",
"question": "응답 크기는 어디서 몇 번 걸리는가?",
"type": "dependency",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "와이어 바이트 예산과 읽는 도중 상한 강제와 디코드 바이트 예산과 오류 본문 제한 읽기가 읽는 순서대로 쌓여 있다.",
"alt": "응답을 읽는 순서대로 와이어 바이트 예산과 읽는 도중 상한 강제와 디코드 바이트 예산과 오류 본문 제한 읽기가 이어진다.",
"long_description": "SSOT 는 응답 크기 예산이 강제되는 자리가 읽는 순서대로 쌓여 있다고 적는다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 1,
"line": 1
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "같은 예산이 읽는 순서를 따라 네 자리에서 걸린다는 것이 논지다.",
"focus_node": "wire"
},
"groups": [],
"nodes": [
{
"id": "wire",
"label": "와이어 바이트 예산",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 1,
"end_line": 1500
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "during",
"label": "읽는 도중 상한 강제",
"kind": "service",
"role": "service",
"evidence": [
{
"start_line": 1,
"end_line": 1500
}
],
"assumption": false
},
{
"id": "decode",
"label": "디코드 바이트 예산",
"kind": "service",
"role": "service",
"evidence": [
{
"start_line": 1,
"end_line": 1838
}
],
"assumption": false
},
{
"id": "err",
"label": "오류 본문 제한 읽기",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 1,
"end_line": 1838
}
],
"assumption": false
}
],
"edges": [
{
"id": "a",
"from": "wire",
"to": "during",
"label": "읽는 순서",
"kind": "request",
"evidence": [
{
"start_line": 1,
"end_line": 1500
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "b",
"from": "during",
"to": "decode",
"label": "읽는 순서",
"kind": "request",
"evidence": [
{
"start_line": 1,
"end_line": 1838
}
],
"assumption": false
},
{
"id": "c",
"from": "decode",
"to": "err",
"label": "읽는 순서",
"kind": "request",
"evidence": [
{
"start_line": 1,
"end_line": 1838
}
],
"assumption": false
}
],
"legend": [],
"metadata": {}
}
@@ -0,0 +1,171 @@
{
"version": "1.1",
"id": "adapter-outbound-messaging-c01",
"title": "레지스트리가 닫힌 방식",
"question": "스키마 레지스트리는 무엇을 받아들이는가?",
"type": "architecture",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "넘겨받은 바이트와 동봉된 메타스키마와 허용 어휘만 쓰고 원격 참조 로더와 동적 키워드는 쓰지 않는다.",
"alt": "호출자가 레지스트리에 바이트를 넘기고 레지스트리는 동봉된 메타스키마와 허용 어휘만 쓰며 원격 참조 로더로는 나가지 않는다.",
"long_description": "SSOT 는 LocalJsonSchemaRegistry 가 넘겨받은 바이트와 동봉된 메타스키마, 허용 어휘 안에서 닫혀 있고 원격 참조 로더와 동적·앵커 키워드를 쓰지 않는다고 적는다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 14789,
"line": 14789
}
},
"composition": {
"profile": "ports-adapters",
"diagram_only": true,
"reference_ids": [
"order-ports-adapters"
],
"rationale": "레지스트리가 어떤 입력을 계약으로 받고 어떤 바깥 경로를 갖지 않는지가 논지다.",
"focus_node": "registry"
},
"groups": [],
"nodes": [
{
"id": "caller",
"label": "스키마 호출자",
"kind": "adapter",
"role": "inbound-adapter",
"evidence": [
{
"start_line": 14789,
"end_line": 14820
}
],
"assumption": false
},
{
"id": "inport",
"label": "넘겨받은 바이트",
"kind": "interface",
"role": "port",
"evidence": [
{
"start_line": 14789,
"end_line": 14820
}
],
"assumption": false
},
{
"id": "registry",
"label": "LocalJsonSchemaRegistry",
"kind": "domain",
"role": "core",
"evidence": [
{
"start_line": 14789,
"end_line": 14820
}
],
"assumption": false,
"emphasis": "primary",
"details": [
"동봉된 메타스키마",
"허용 어휘"
]
},
{
"id": "outport",
"label": "바깥 해석 경로",
"kind": "interface",
"role": "port",
"evidence": [
{
"start_line": 14789,
"end_line": 14827
}
],
"assumption": false
},
{
"id": "remote",
"label": "원격 참조 로더",
"kind": "adapter",
"role": "outbound-adapter",
"evidence": [
{
"start_line": 14789,
"end_line": 14827
}
],
"assumption": false,
"details": [
"동적 · 앵커 키워드"
]
}
],
"edges": [
{
"id": "a",
"from": "caller",
"to": "inport",
"label": "바이트 전달",
"kind": "request",
"evidence": [
{
"start_line": 14789,
"end_line": 14820
}
],
"assumption": false
},
{
"id": "b",
"from": "inport",
"to": "registry",
"label": "검증 요청",
"kind": "request",
"evidence": [
{
"start_line": 14789,
"end_line": 14820
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "c",
"from": "registry",
"to": "outport",
"label": "요구 없음",
"kind": "request",
"evidence": [
{
"start_line": 14789,
"end_line": 14827
}
],
"assumption": false,
"style": "dashed"
},
{
"id": "d",
"from": "remote",
"to": "outport",
"label": "미사용",
"kind": "request",
"evidence": [
{
"start_line": 14789,
"end_line": 14827
}
],
"assumption": false,
"style": "dashed"
}
],
"legend": [],
"metadata": {}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,126 @@
{
"version": "1.1",
"id": "adapter-outbound-notification-c01",
"audience": [
"메시징 플랫폼을 읽는 사람"
],
"source_context": {
"document": "docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 15305,
"line": 15305
}
},
"groups": [],
"legend": [],
"metadata": {},
"title": "이름 없던 상태에 이름 붙이기",
"question": "공급자 0인 배포는 어떻게 사고와 구분되는가?",
"type": "sequence",
"direction": "LR",
"summary": "공급자 0인 배포를 사고와 구분하려고 INGEST_ONLY 를 명시 선택으로 만들고 조립이 그것을 강제한다.",
"alt": "공급자 0인 플랫폼에서 INGEST_ONLY 명시 선택으로 화살표가 가고, 선택이 없으면 조립 거부로 간다.",
"long_description": "SSOT 는 INGEST_ONLY 를 명시적으로 선택해야 한다고 적는다 — \"A deployment that reaches zero providers by accident is a misconfiguration, and the whole point of this enum is that the two are told apart\". NotificationProviderAssembly:183 이 그것을 강제해, 경로가 비었는데 모드가 INGEST_ONLY 가 아니면 조립을 거부하고 메시지로 그 모드를 안내한다.",
"composition": {
"profile": "sequence",
"diagram_only": true,
"reference_ids": [
"payment-approval-sequence"
],
"rationale": "조립이 경로와 모드를 차례로 보고 두 결과로 갈리는 순서가 논지다.",
"focus_node": "assembly"
},
"nodes": [
{
"id": "config",
"label": "배포 설정",
"kind": "config",
"role": "participant",
"evidence": [
{
"start_line": 15305,
"end_line": 15310
}
],
"assumption": false
},
{
"id": "assembly",
"label": "NotificationProviderAssembly",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 15305,
"end_line": 15310
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "result",
"label": "조립 결과",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 15305,
"end_line": 15310
}
],
"assumption": false
}
],
"edges": [
{
"id": "m1",
"from": "config",
"to": "assembly",
"label": "공급자 0 · 모드 전달",
"kind": "request",
"order": 1,
"evidence": [
{
"start_line": 15305,
"end_line": 15310
}
],
"assumption": false
},
{
"id": "m2",
"from": "assembly",
"to": "result",
"label": "INGEST_ONLY 면 진행",
"kind": "response",
"order": 2,
"evidence": [
{
"start_line": 15305,
"end_line": 15310
}
],
"assumption": false
},
{
"id": "m3",
"from": "assembly",
"to": "result",
"label": "아니면 조립 거부",
"kind": "response",
"order": 3,
"evidence": [
{
"start_line": 15305,
"end_line": 15310
}
],
"assumption": false,
"style": "dashed",
"emphasis": "primary"
}
]
}
@@ -0,0 +1,126 @@
{
"version": "1.1",
"id": "adapter-outbound-objectstorage-c01",
"title": "컴파일과 생성의 순서",
"question": "자원은 언제 만들어지는가?",
"type": "sequence",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "설정 컴파일이 전부 끝난 뒤에야 provider 가 디렉터리와 클라이언트와 스레드와 스케줄러와 자격 조회를 만든다.",
"alt": "compiler.compile 이 검증된 바인딩을 만들고 contribution.create 가 그것으로 AssembledCapability 를 만드는 순서.",
"long_description": "SSOT 는 설정 컴파일이 전부 끝난 뒤에야 provider 가 자원을 만들고 생성 도중 실패하면 수명주기 소유권이 넘어간다고 적는다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 11788,
"line": 11788
}
},
"composition": {
"profile": "sequence",
"diagram_only": true,
"reference_ids": [
"payment-approval-sequence"
],
"rationale": "컴파일이 끝난 뒤에만 생성이 일어난다는 순서가 논지다.",
"focus_node": "create"
},
"groups": [],
"nodes": [
{
"id": "compile",
"label": "compiler.compile settings",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 11788,
"end_line": 11798
}
],
"assumption": false
},
{
"id": "create",
"label": "contribution.create provider",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 11788,
"end_line": 11798
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "cap",
"label": "AssembledCapability",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 11788,
"end_line": 11801
}
],
"assumption": false
}
],
"edges": [
{
"id": "m1",
"from": "compile",
"to": "create",
"label": "검증된 바인딩",
"kind": "request",
"evidence": [
{
"start_line": 11788,
"end_line": 11798
}
],
"assumption": false,
"order": 1
},
{
"id": "m2",
"from": "create",
"to": "cap",
"label": "자원 생성",
"kind": "request",
"evidence": [
{
"start_line": 11788,
"end_line": 11801
}
],
"assumption": false,
"order": 2,
"emphasis": "primary"
},
{
"id": "m3",
"from": "cap",
"to": "create",
"label": "수명주기 소유권",
"kind": "response",
"evidence": [
{
"start_line": 11788,
"end_line": 11801
}
],
"assumption": false,
"order": 3,
"style": "dashed"
}
],
"legend": [],
"metadata": {}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,162 @@
{
"version": "1.1",
"id": "adapter-outbound-objectstorage-c05",
"title": "어디서든 들어가고 나올 수 없는 분기",
"question": "분기 상태에서 돌아올 수 있는가?",
"type": "state",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "정상 사슬의 어느 단계에서도 분기 전이로 빠질 수 있고 그 네 상태에서 나오는 전이는 없다.",
"alt": "정상 사슬의 어느 단계에서 EXPIRED 와 ABORTED 와 FAILED 와 CORRUPT 로 분기 전이가 가고 되돌아오는 화살표는 없다.",
"long_description": "SSOT 는 정상 사슬의 어느 단계에서도 분기 전이로 빠질 수 있고 그 네 상태에서 나오는 전이가 없다고 적는다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 46523,
"line": 46523
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "어느 단계에서든 빠질 수 있고 빠지면 돌아오지 못한다는 것이 논지다.",
"focus_node": "chain"
},
"groups": [],
"nodes": [
{
"id": "chain",
"label": "정상 사슬의 어느 단계",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 46523,
"end_line": 46700
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "expired",
"label": "EXPIRED",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 46523,
"end_line": 46700
}
],
"assumption": false
},
{
"id": "aborted",
"label": "ABORTED",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 46523,
"end_line": 46700
}
],
"assumption": false
},
{
"id": "failed",
"label": "FAILED",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 46523,
"end_line": 46796
}
],
"assumption": false
},
{
"id": "corrupt",
"label": "CORRUPT",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 46523,
"end_line": 46796
}
],
"assumption": false
}
],
"edges": [
{
"id": "a",
"from": "chain",
"to": "expired",
"label": "분기 전이",
"kind": "request",
"evidence": [
{
"start_line": 46523,
"end_line": 46700
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "b",
"from": "chain",
"to": "aborted",
"label": "분기 전이",
"kind": "request",
"evidence": [
{
"start_line": 46523,
"end_line": 46700
}
],
"assumption": false
},
{
"id": "c",
"from": "chain",
"to": "failed",
"label": "분기 전이",
"kind": "request",
"evidence": [
{
"start_line": 46523,
"end_line": 46796
}
],
"assumption": false
},
{
"id": "d",
"from": "chain",
"to": "corrupt",
"label": "분기 전이",
"kind": "request",
"evidence": [
{
"start_line": 46523,
"end_line": 46796
}
],
"assumption": false
}
],
"legend": [],
"metadata": {}
}
@@ -0,0 +1,113 @@
{
"version": "1.1",
"id": "adapter-outbound-persistence-jpa-c02",
"title": "보고 가능한 계약이 만들어지는 층",
"question": "능력 보고는 어느 층에서 완성되는가?",
"type": "sequence",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "능력 이름은 어휘일 뿐이고 지원 등급은 별도 타입이 붙이며 실제 보고는 조립이 구성한다.",
"alt": "JpaCapability 어휘에서 CapabilitySupport 등급 결합으로 그리고 app-bootstrap 조립으로 이어지는 순서.",
"long_description": "SSOT 는 능력 이름이 어휘일 뿐이고 지원 등급을 별도 타입이 붙이며 실제 보고를 조립이 구성한다고 적는다. 코드가 classpath 에 있다는 것과 다르다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 3905,
"line": 3905
}
},
"composition": {
"profile": "sequence",
"diagram_only": true,
"reference_ids": [
"payment-approval-sequence"
],
"rationale": "어휘에서 등급으로 그리고 보고로 올라가는 순서가 논지다.",
"focus_node": "support"
},
"groups": [],
"nodes": [
{
"id": "vocab",
"label": "JpaCapability 어휘",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 3905,
"end_line": 3918
}
],
"assumption": false
},
{
"id": "support",
"label": "CapabilitySupport 등급 결합",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 3905,
"end_line": 3918
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "comp",
"label": "app-bootstrap composition",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 3905,
"end_line": 3922
}
],
"assumption": false,
"details": [
"실제 보고"
]
}
],
"edges": [
{
"id": "m1",
"from": "vocab",
"to": "support",
"label": "이름 전달",
"kind": "request",
"evidence": [
{
"start_line": 3905,
"end_line": 3918
}
],
"assumption": false,
"order": 1
},
{
"id": "m2",
"from": "support",
"to": "comp",
"label": "등급 결합",
"kind": "request",
"evidence": [
{
"start_line": 3905,
"end_line": 3922
}
],
"assumption": false,
"order": 2,
"emphasis": "primary"
}
],
"legend": [],
"metadata": {}
}
@@ -0,0 +1,145 @@
{
"version": "1.1",
"id": "adapter-outbound-persistence-jpa-c04",
"title": "질의 API가 표현하지 않는 것",
"question": "keyset 질의 API 는 무엇을 받고 무엇을 받지 않는가?",
"type": "sequence",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "정렬 키와 size 더하기 1과 서명된 커서로 페이지를 만들고 offset 과 total count 질의는 받지 않는다.",
"alt": "호출자가 keyset 질의 API 에 정렬 키를 주고 서명된 커서를 받으며 offset 과 total count 요청은 받아들여지지 않는 순서.",
"long_description": "SSOT §5.1 은 KeysetPageRequest 에 offset 자체가 없다고 적는다. 정렬 키와 요청 size + 1, 서명된 nextCursor 로 다음 페이지를 만든다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 4081,
"line": 4081
}
},
"composition": {
"profile": "sequence",
"diagram_only": true,
"reference_ids": [
"payment-approval-sequence"
],
"rationale": "받는 입력과 받지 않는 입력이 순서 위에서 갈린다.",
"focus_node": "api"
},
"groups": [],
"nodes": [
{
"id": "caller",
"label": "호출자",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 4081,
"end_line": 4094
}
],
"assumption": false
},
{
"id": "api",
"label": "keyset 질의 API",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 4081,
"end_line": 4094
}
],
"assumption": false,
"emphasis": "primary",
"details": [
"KeysetTerm 정렬 키",
"요청 size + 1"
]
},
{
"id": "db",
"label": "저장소",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 4081,
"end_line": 4096
}
],
"assumption": false
}
],
"edges": [
{
"id": "m1",
"from": "caller",
"to": "api",
"label": "정렬 키 · size",
"kind": "request",
"evidence": [
{
"start_line": 4081,
"end_line": 4094
}
],
"assumption": false,
"order": 1
},
{
"id": "m2",
"from": "api",
"to": "db",
"label": "한 건 더 조회",
"kind": "request",
"evidence": [
{
"start_line": 4081,
"end_line": 4094
}
],
"assumption": false,
"order": 2
},
{
"id": "m3",
"from": "api",
"to": "caller",
"label": "서명된 nextCursor",
"kind": "response",
"evidence": [
{
"start_line": 4081,
"end_line": 4094
}
],
"assumption": false,
"order": 3,
"emphasis": "primary"
},
{
"id": "m4",
"from": "caller",
"to": "api",
"label": "offset · total count 없음",
"kind": "request",
"evidence": [
{
"start_line": 4081,
"end_line": 4096
}
],
"assumption": false,
"order": 4,
"style": "dashed"
}
],
"legend": [],
"metadata": {}
}
@@ -0,0 +1,129 @@
{
"version": "1.1",
"id": "adapter-outbound-persistence-jpa-c05",
"title": "encode와 decode의 허용 범위",
"question": "상한 크기 payload 는 왕복하는가?",
"type": "sequence",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "상한 크기 payload 가 base64url 인코드를 지나면 크기 사전 추정에서 decode 쪽이 거부한다.",
"alt": "상한 크기 payload 가 base64url 인코드와 크기 사전 추정을 지나 decode 쪽 거부로 이어지는 순서.",
"long_description": "SSOT 는 상한 크기의 payload 가 base64url 인코드를 지나 크기 사전 추정 단계에서 decode 쪽 거부로 이어진다고 적는다. padding 가정이 그 원인이다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 4142,
"line": 4142
}
},
"composition": {
"profile": "sequence",
"diagram_only": true,
"reference_ids": [
"payment-approval-sequence"
],
"rationale": "인코드는 통과하는데 디코드에서 막힌다는 순서가 논지다.",
"focus_node": "estimate"
},
"groups": [],
"nodes": [
{
"id": "payload",
"label": "상한 크기의 payload",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 4137,
"end_line": 4152
}
],
"assumption": false
},
{
"id": "enc",
"label": "base64url 인코드",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 4137,
"end_line": 4152
}
],
"assumption": false
},
{
"id": "estimate",
"label": "크기 사전 추정",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 4137,
"end_line": 4158
}
],
"assumption": false,
"emphasis": "primary",
"details": [
"padding 가정"
]
}
],
"edges": [
{
"id": "m1",
"from": "payload",
"to": "enc",
"label": "인코드",
"kind": "request",
"evidence": [
{
"start_line": 4137,
"end_line": 4152
}
],
"assumption": false,
"order": 1
},
{
"id": "m2",
"from": "enc",
"to": "estimate",
"label": "추정 요청",
"kind": "request",
"evidence": [
{
"start_line": 4137,
"end_line": 4152
}
],
"assumption": false,
"order": 2
},
{
"id": "m3",
"from": "estimate",
"to": "payload",
"label": "decode 쪽 거부",
"kind": "response",
"evidence": [
{
"start_line": 4137,
"end_line": 4158
}
],
"assumption": false,
"order": 3,
"style": "dashed",
"emphasis": "primary"
}
],
"legend": [],
"metadata": {}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,166 @@
{
"version": "1.1",
"id": "adapter-outbound-persistence-jpa-c06",
"title": "allowlist 에 들어갈 수 있는 범주",
"question": "설정으로 재시도 가능하게 만들 수 있는 범주는 무엇인가?",
"type": "dependency",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "설정으로 재시도 가능하게 만들 수 있는 범주가 타입에서 좁혀져 있고 완료 불명은 생성자가 거부한다.",
"alt": "RetryProfile allowlist 에서 직렬화 실패와 낙관적 충돌과 락 획득 실패로 화살표가 가고 COMPLETION_UNKNOWN 으로는 거부 화살표가 간다.",
"long_description": "SSOT §58 은 SQLSTATE 분류를 다루고 RetryProfile 이 COMPLETION_UNKNOWN 을 화이트리스트에 넣는 것을 생성자에서 거부한다고 적는다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 6409,
"line": 6409
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "어떤 범주가 allowlist 에 들어가고 어떤 것이 거부되는지가 논지다.",
"focus_node": "allow"
},
"groups": [],
"nodes": [
{
"id": "allow",
"label": "RetryProfile allowlist",
"kind": "service",
"role": "source",
"evidence": [
{
"start_line": 6409,
"end_line": 6440
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "ser",
"label": "직렬화 실패",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 6409,
"end_line": 6440
}
],
"assumption": false
},
{
"id": "opt",
"label": "낙관적 충돌",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 6409,
"end_line": 6440
}
],
"assumption": false
},
{
"id": "lock",
"label": "락 획득 실패",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 6409,
"end_line": 6440
}
],
"assumption": false
},
{
"id": "unk",
"label": "COMPLETION_UNKNOWN",
"kind": "service",
"role": "sink",
"evidence": [
{
"start_line": 6409,
"end_line": 6445
}
],
"assumption": false,
"details": [
"생성자가 거부"
]
}
],
"edges": [
{
"id": "a",
"from": "allow",
"to": "ser",
"label": "허용",
"kind": "request",
"evidence": [
{
"start_line": 6409,
"end_line": 6440
}
],
"assumption": false
},
{
"id": "b",
"from": "allow",
"to": "opt",
"label": "허용",
"kind": "request",
"evidence": [
{
"start_line": 6409,
"end_line": 6440
}
],
"assumption": false
},
{
"id": "c",
"from": "allow",
"to": "lock",
"label": "허용",
"kind": "request",
"evidence": [
{
"start_line": 6409,
"end_line": 6440
}
],
"assumption": false
},
{
"id": "d",
"from": "allow",
"to": "unk",
"label": "거부",
"kind": "request",
"evidence": [
{
"start_line": 6409,
"end_line": 6445
}
],
"assumption": false,
"style": "dashed",
"emphasis": "primary"
}
],
"legend": [],
"metadata": {}
}
@@ -0,0 +1,110 @@
{
"version": "1.1",
"id": "adapter-outbound-persistence-jpa-c24",
"title": "질의 계층의 세 단계",
"question": "질의 계약은 어디로 위임되는가?",
"type": "sequence",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "응용 계층이 소유한 질의 계약이 springdata 를 거쳐 hibernate 로 위임되고 각 단계가 다른 정책을 맡는다.",
"alt": "호출자가 응용 계층 질의 계약을 부르면 springdata 로 그리고 hibernate 로 위임이 이어지는 순서.",
"long_description": "SSOT 는 응용 계층이 소유한 질의 계약이 아래로 위임되고 각 단계가 서로 다른 정책을 맡는다고 적는다. 범용 CRUD 저장소를 대체하는 층이 아니다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 5370,
"line": 5370
}
},
"composition": {
"profile": "sequence",
"diagram_only": true,
"reference_ids": [
"payment-approval-sequence"
],
"rationale": "계약이 위에서 아래로 차례로 위임되는 순서가 논지다.",
"focus_node": "sd"
},
"groups": [],
"nodes": [
{
"id": "contract",
"label": "application-owned query contract",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 5370,
"end_line": 5383
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "sd",
"label": "springdata",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 5370,
"end_line": 5383
}
],
"assumption": false
},
{
"id": "hb",
"label": "hibernate",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 5370,
"end_line": 5386
}
],
"assumption": false
}
],
"edges": [
{
"id": "m1",
"from": "contract",
"to": "sd",
"label": "위임",
"kind": "request",
"evidence": [
{
"start_line": 5370,
"end_line": 5383
}
],
"assumption": false,
"order": 1
},
{
"id": "m2",
"from": "sd",
"to": "hb",
"label": "위임",
"kind": "request",
"evidence": [
{
"start_line": 5370,
"end_line": 5386
}
],
"assumption": false,
"order": 2,
"emphasis": "primary"
}
],
"legend": [],
"metadata": {}
}
@@ -0,0 +1,148 @@
{
"version": "1.1",
"id": "adapter-outbound-persistence-jpa-c25",
"title": "선언 기준과 런타임 판본의 분리",
"question": "Hibernate 판본은 어디서 나오는가?",
"type": "sequence",
"direction": "LR",
"audience": [
"이 저장소의 구조를 읽는 사람"
],
"summary": "정책 상수 baseline 이 선언 기준을 주고 실제 판본은 org.hibernate.Version 조회로 확인한다.",
"alt": "정책 검사가 상수 baseline 을 읽고 런타임에 org.hibernate.Version 을 조회해 둘을 견주는 순서.",
"long_description": "SSOT §35 는 Hibernate provider policy 가 선언된 baseline 을 갖고 실제 판본은 런타임 조회로 확인된다고 적는다. 문서가 선언한 판본과 BOM 이 해석한 판본이 같은 축에 놓인다.",
"source_context": {
"document": "/home/donghyeon/workspace/chat-gpt-container/document-haness/docs/clean-architecture-backend-template/final/document.md",
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
"anchor": {
"kind": "line",
"value": 5420,
"line": 5420
}
},
"composition": {
"profile": "sequence",
"diagram_only": true,
"reference_ids": [
"payment-approval-sequence"
],
"rationale": "선언이 먼저 있고 런타임 조회가 뒤에 오는 순서가 논지다.",
"focus_node": "policy"
},
"groups": [],
"nodes": [
{
"id": "policy",
"label": "provider policy",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 5420,
"end_line": 5436
}
],
"assumption": false,
"emphasis": "primary"
},
{
"id": "const",
"label": "정책 상수 baseline",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 5420,
"end_line": 5436
}
],
"assumption": false,
"details": [
"문서가 선언한 판본"
]
},
{
"id": "runtime",
"label": "org.hibernate.Version",
"kind": "service",
"role": "participant",
"evidence": [
{
"start_line": 5420,
"end_line": 5438
}
],
"assumption": false,
"details": [
"BOM 이 해석한 판본"
]
}
],
"edges": [
{
"id": "m1",
"from": "policy",
"to": "const",
"label": "선언 기준 조회",
"kind": "request",
"evidence": [
{
"start_line": 5420,
"end_line": 5436
}
],
"assumption": false,
"order": 1
},
{
"id": "m2",
"from": "const",
"to": "policy",
"label": "baseline",
"kind": "response",
"evidence": [
{
"start_line": 5420,
"end_line": 5436
}
],
"assumption": false,
"order": 2,
"style": "dashed"
},
{
"id": "m3",
"from": "policy",
"to": "runtime",
"label": "런타임 판본 조회",
"kind": "request",
"evidence": [
{
"start_line": 5420,
"end_line": 5438
}
],
"assumption": false,
"order": 3,
"emphasis": "primary"
},
{
"id": "m4",
"from": "runtime",
"to": "policy",
"label": "실제 판본",
"kind": "response",
"evidence": [
{
"start_line": 5420,
"end_line": 5438
}
],
"assumption": false,
"order": 4,
"style": "dashed"
}
],
"legend": [],
"metadata": {}
}

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