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:
co-authored by
Claude Opus 5
parent
2109f726fe
commit
ab59130196
+15316
File diff suppressed because one or more lines are too long
+169
@@ -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": {}
|
||||
}
|
||||
+15277
File diff suppressed because one or more lines are too long
+141
@@ -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": {}
|
||||
}
|
||||
+18755
File diff suppressed because one or more lines are too long
+137
@@ -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": {}
|
||||
}
|
||||
+15354
File diff suppressed because one or more lines are too long
+108
@@ -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": {}
|
||||
}
|
||||
+15175
File diff suppressed because one or more lines are too long
+109
@@ -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": {}
|
||||
}
|
||||
+15173
File diff suppressed because it is too large
Load Diff
+136
@@ -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": {}
|
||||
}
|
||||
+15143
File diff suppressed because it is too large
Load Diff
+135
@@ -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": {}
|
||||
}
|
||||
+15266
File diff suppressed because one or more lines are too long
+142
@@ -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": {}
|
||||
}
|
||||
+16142
File diff suppressed because one or more lines are too long
+108
@@ -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": {}
|
||||
}
|
||||
+15156
File diff suppressed because one or more lines are too long
+108
@@ -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": {}
|
||||
}
|
||||
+15132
File diff suppressed because it is too large
Load Diff
+108
@@ -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": {}
|
||||
}
|
||||
+15164
File diff suppressed because one or more lines are too long
+111
@@ -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": {}
|
||||
}
|
||||
+16462
File diff suppressed because one or more lines are too long
+174
@@ -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": {}
|
||||
}
|
||||
+15751
File diff suppressed because one or more lines are too long
+132
@@ -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": {}
|
||||
}
|
||||
+15146
File diff suppressed because one or more lines are too long
+116
@@ -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": {}
|
||||
}
|
||||
+15151
File diff suppressed because it is too large
Load Diff
+115
@@ -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": {}
|
||||
}
|
||||
+15119
File diff suppressed because it is too large
Load Diff
+163
@@ -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": {}
|
||||
}
|
||||
+15147
File diff suppressed because it is too large
Load Diff
+135
@@ -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": {}
|
||||
}
|
||||
+15255
File diff suppressed because one or more lines are too long
+135
@@ -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": {}
|
||||
}
|
||||
+201116
File diff suppressed because one or more lines are too long
+135
@@ -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": {}
|
||||
}
|
||||
+15263
File diff suppressed because it is too large
Load Diff
+171
@@ -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": {}
|
||||
}
|
||||
+15194
File diff suppressed because one or more lines are too long
+126
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
+15156
File diff suppressed because it is too large
Load Diff
+126
@@ -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": {}
|
||||
}
|
||||
+16462
File diff suppressed because one or more lines are too long
+162
@@ -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": {}
|
||||
}
|
||||
+15162
File diff suppressed because it is too large
Load Diff
+113
@@ -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": {}
|
||||
}
|
||||
+15163
File diff suppressed because it is too large
Load Diff
+145
@@ -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": {}
|
||||
}
|
||||
+15249
File diff suppressed because it is too large
Load Diff
+129
@@ -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": {}
|
||||
}
|
||||
+15485
File diff suppressed because one or more lines are too long
+166
@@ -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": {}
|
||||
}
|
||||
+15334
File diff suppressed because it is too large
Load Diff
+110
@@ -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": {}
|
||||
}
|
||||
+15311
File diff suppressed because it is too large
Load Diff
+148
@@ -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": {}
|
||||
}
|
||||
+15166
File diff suppressed because it is too large
Load Diff
+135
@@ -0,0 +1,135 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "adapter-outbound-persistence-jpa-c26",
|
||||
"audience": [
|
||||
"플랫폼 어댑터를 읽는 사람"
|
||||
],
|
||||
"source_context": {
|
||||
"document": "docs/clean-architecture-backend-template/final/document.md",
|
||||
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
|
||||
"anchor": {
|
||||
"kind": "line",
|
||||
"value": 5598,
|
||||
"line": 5598
|
||||
}
|
||||
},
|
||||
"groups": [],
|
||||
"legend": [],
|
||||
"metadata": {},
|
||||
"title": "쓰기 경로마다 다른 소유 모델",
|
||||
"question": "세 쓰기 경로는 트랜잭션 소유를 어떻게 다르게 다루는가?",
|
||||
"type": "dependency",
|
||||
"direction": "LR",
|
||||
"summary": "같은 저장소 호출처럼 보여도 세 경로가 트랜잭션 경계와 엔티티 수명주기를 다르게 다룬다.",
|
||||
"alt": "쓰기 경로에서 일반 repository adapter 와 bulk DML 과 StatelessSession runner 로 갈라진다.",
|
||||
"long_description": "SSOT §40 은 Hibernate bulk DML 과 StatelessSession 이 각각 엔티티 수명주기를 우회하고 트랜잭션 경계를 스스로 소유한다고 적는다. 세 경로는 같은 저장소 호출처럼 보이지만 감사와 수명주기 보장이 같지 않다.",
|
||||
"composition": {
|
||||
"profile": "component-flow",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"rationale": "한 쓰기 요청이 어느 경로로 가느냐에 따라 소유 모델이 갈리는 방향이 논지다.",
|
||||
"focus_node": "write"
|
||||
},
|
||||
"nodes": [
|
||||
{
|
||||
"id": "write",
|
||||
"label": "쓰기 경로",
|
||||
"kind": "service",
|
||||
"role": "source",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5598,
|
||||
"end_line": 5612
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "repo",
|
||||
"label": "일반 repository adapter",
|
||||
"kind": "service",
|
||||
"role": "sink",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5598,
|
||||
"end_line": 5600
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "bulk",
|
||||
"label": "bulk DML",
|
||||
"kind": "service",
|
||||
"role": "sink",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5598,
|
||||
"end_line": 5612
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "stateless",
|
||||
"label": "StatelessSession runner",
|
||||
"kind": "service",
|
||||
"role": "sink",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5613,
|
||||
"end_line": 5620
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "a",
|
||||
"from": "write",
|
||||
"to": "repo",
|
||||
"label": "경계에 참여",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5598,
|
||||
"end_line": 5600
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "b",
|
||||
"from": "write",
|
||||
"to": "bulk",
|
||||
"label": "엔티티 수명주기 우회",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5598,
|
||||
"end_line": 5612
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "c",
|
||||
"from": "write",
|
||||
"to": "stateless",
|
||||
"label": "경계 자체 소유",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 5613,
|
||||
"end_line": 5620
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
}
|
||||
]
|
||||
}
|
||||
+16462
File diff suppressed because one or more lines are too long
+163
@@ -0,0 +1,163 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "adapter-outbound-persistence-jpa-c36",
|
||||
"title": "같은 row 를 읽는 두 경로",
|
||||
"question": "만료된 COMPLETED row 를 두 진입점이 같게 읽는가?",
|
||||
"type": "dependency",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"이 저장소의 구조를 읽는 사람"
|
||||
],
|
||||
"summary": "만료된 COMPLETED row 를 inspect 는 재생하라고 읽고 claim 은 인수 가능으로 읽는다.",
|
||||
"alt": "같은 row 가 inspect 로 가면 COMPLETED_REPLAY 가 되고 claim 으로 가면 TakenOverClaimed 가 된다.",
|
||||
"long_description": "SSOT 는 만료된 COMPLETED row 를 두 진입점이 서로 다르게 해석한다고 적는다. 한쪽은 이전 응답을 재생하라 하고 다른 쪽은 새 실행을 소유하라 한다.",
|
||||
"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": "row"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "row",
|
||||
"label": "만료된 COMPLETED row",
|
||||
"kind": "service",
|
||||
"role": "source",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 46523,
|
||||
"end_line": 46700
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "inspect",
|
||||
"label": "inspect",
|
||||
"kind": "service",
|
||||
"role": "service",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 46523,
|
||||
"end_line": 46700
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "claim",
|
||||
"label": "claim",
|
||||
"kind": "service",
|
||||
"role": "service",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 46523,
|
||||
"end_line": 46796
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "replay",
|
||||
"label": "COMPLETED_REPLAY",
|
||||
"kind": "service",
|
||||
"role": "sink",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 46523,
|
||||
"end_line": 46700
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "taken",
|
||||
"label": "TakenOverClaimed",
|
||||
"kind": "service",
|
||||
"role": "sink",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 46523,
|
||||
"end_line": 46796
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "a",
|
||||
"from": "row",
|
||||
"to": "inspect",
|
||||
"label": "같은 row",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 46523,
|
||||
"end_line": 46700
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "b",
|
||||
"from": "row",
|
||||
"to": "claim",
|
||||
"label": "같은 row",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 46523,
|
||||
"end_line": 46796
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "c",
|
||||
"from": "inspect",
|
||||
"to": "replay",
|
||||
"label": "재생하라",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 46523,
|
||||
"end_line": 46700
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "d",
|
||||
"from": "claim",
|
||||
"to": "taken",
|
||||
"label": "소유하라",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 46523,
|
||||
"end_line": 46796
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary",
|
||||
"style": "dashed"
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {}
|
||||
}
|
||||
+15577
File diff suppressed because one or more lines are too long
+130
@@ -0,0 +1,130 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "adapter-outbound-persistence-jpa-c42",
|
||||
"title": "narrow scan 이 닿는 범위",
|
||||
"question": "스캔 목록은 어떤 컴포넌트를 만들어 내는가?",
|
||||
"type": "sequence",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"이 저장소의 구조를 읽는 사람"
|
||||
],
|
||||
"summary": "스캔 목록에 적힌 여섯 패키지만 컴포넌트가 되고 같은 리프 안에 있어도 목록 밖이면 만들어지지 않는다.",
|
||||
"alt": "스캔 목록이 컴포넌트 스캔에 전달되고 컨테이너에 여섯 패키지 컴포넌트가 만들어진다. 목록 밖 어댑터는 만들어지지 않는다.",
|
||||
"long_description": "SSOT §14 는 SpringTransactionPort 와 그 조립을 다룬다. JpaAdapterComponentsConfig 가 어댑터 전체를 넓게 스캔하지 않고 여섯 패키지만 명시적으로 스캔하므로, 같은 리프 안에 있어도 그 목록 밖이면 도달하지 않는다.",
|
||||
"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": 4565,
|
||||
"line": 4565
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "sequence",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-approval-sequence"
|
||||
],
|
||||
"rationale": "목록을 받아 무엇을 만들고 무엇을 안 만드는지가 순서로 드러난다.",
|
||||
"focus_node": "scan"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "spec",
|
||||
"label": "스캔 목록",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 4565,
|
||||
"end_line": 4600
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"details": [
|
||||
"audit · failure · idempotency",
|
||||
"lock · outbox · transaction"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "scan",
|
||||
"label": "컴포넌트 스캔",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 4565,
|
||||
"end_line": 4600
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "ctx",
|
||||
"label": "컨테이너",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 4565,
|
||||
"end_line": 4608
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "m1",
|
||||
"from": "spec",
|
||||
"to": "scan",
|
||||
"label": "여섯 패키지 전달",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 4565,
|
||||
"end_line": 4600
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 1
|
||||
},
|
||||
{
|
||||
"id": "m2",
|
||||
"from": "scan",
|
||||
"to": "ctx",
|
||||
"label": "컴포넌트 생성",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 4565,
|
||||
"end_line": 4600
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 2,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "m3",
|
||||
"from": "scan",
|
||||
"to": "ctx",
|
||||
"label": "목록 밖 생성 없음",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 4565,
|
||||
"end_line": 4608
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 3,
|
||||
"style": "dashed"
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {}
|
||||
}
|
||||
+15283
File diff suppressed because one or more lines are too long
+117
@@ -0,0 +1,117 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "adapter-outbound-persistence-jpa-c51",
|
||||
"title": "Stable 스캔 목록에 들어 있는 것",
|
||||
"question": "Stable 스캔 목록에 무엇이 들어 있는가?",
|
||||
"type": "sequence",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"이 저장소의 구조를 읽는 사람"
|
||||
],
|
||||
"summary": "Stable persistence unit 의 스캔 문자열 목록에 조건 없는 experimental package 가 이미 들어 있다.",
|
||||
"alt": "Stable EntityScan 목록이 조건 있는 stable package 목록과 조건 없는 experimental package 를 함께 담는다.",
|
||||
"long_description": "SSOT 는 Stable persistence unit 의 스캔 문자열 목록에 experimental package 가 이미 들어 있다고 적는다.",
|
||||
"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": 7518,
|
||||
"line": 7518
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "sequence",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-approval-sequence"
|
||||
],
|
||||
"rationale": "같은 목록이 조건 있는 항목과 없는 항목을 함께 담는다는 것이 순서로 드러난다.",
|
||||
"focus_node": "scan"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "scan",
|
||||
"label": "Stable @EntityScan 목록",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 7518,
|
||||
"end_line": 7540
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "stable",
|
||||
"label": "stable package 목록",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 7518,
|
||||
"end_line": 7540
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"details": [
|
||||
"조건 있음"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "exp",
|
||||
"label": "experimental package",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 7518,
|
||||
"end_line": 7546
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"details": [
|
||||
"조건 없음"
|
||||
]
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "m1",
|
||||
"from": "scan",
|
||||
"to": "stable",
|
||||
"label": "목록 포함",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 7518,
|
||||
"end_line": 7540
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 1
|
||||
},
|
||||
{
|
||||
"id": "m2",
|
||||
"from": "scan",
|
||||
"to": "exp",
|
||||
"label": "목록 포함",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 7518,
|
||||
"end_line": 7546
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 2,
|
||||
"style": "dashed",
|
||||
"emphasis": "primary"
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {}
|
||||
}
|
||||
+15388
File diff suppressed because one or more lines are too long
+170
@@ -0,0 +1,170 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "adapter-outbound-persistence-jpa-c56",
|
||||
"title": "두 스캔을 가르는 선",
|
||||
"question": "항상 설치되는 스캔과 옵트인 스캔은 무엇이 다른가?",
|
||||
"type": "architecture",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"이 저장소의 구조를 읽는 사람"
|
||||
],
|
||||
"summary": "항상 설치되는 스캔은 스무 개 패키지를 열거하고 옵트인 둘은 각자의 조건부 설정이 자기 패키지만 스캔한다.",
|
||||
"alt": "스캔 계약에서 PersistenceJpaConfig 가 스무 개 패키지를 열거하고 notification 과 fileserver 는 각자 옵트인으로 붙는다.",
|
||||
"long_description": "SSOT §117 은 always-install scan 과 opt-in scan 의 경계를 적는다. 항상 설치되는 쪽은 package 를 열거하고 옵트인 두 개는 각자의 조건부 Configuration 이 자기 package 만 스캔한다.",
|
||||
"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": 7920,
|
||||
"line": 7920
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "ports-adapters",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"order-ports-adapters"
|
||||
],
|
||||
"rationale": "스캔이 항상 붙는 쪽과 조건부로 붙는 쪽으로 갈리는 것이 논지다.",
|
||||
"focus_node": "always"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "ctx",
|
||||
"label": "컨테이너",
|
||||
"kind": "adapter",
|
||||
"role": "inbound-adapter",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 7920,
|
||||
"end_line": 7927
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "scan",
|
||||
"label": "스캔 계약",
|
||||
"kind": "interface",
|
||||
"role": "port",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 7920,
|
||||
"end_line": 7927
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "always",
|
||||
"label": "PersistenceJpaConfig",
|
||||
"kind": "domain",
|
||||
"role": "core",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 7920,
|
||||
"end_line": 7927
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary",
|
||||
"details": [
|
||||
"열거된 스무 개 package"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "optin",
|
||||
"label": "옵트인 스캔 계약",
|
||||
"kind": "interface",
|
||||
"role": "port",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 7920,
|
||||
"end_line": 7929
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "leaves",
|
||||
"label": "notification · fileserver",
|
||||
"kind": "adapter",
|
||||
"role": "outbound-adapter",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 7920,
|
||||
"end_line": 7929
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"details": [
|
||||
"조건부 Configuration",
|
||||
"자기 package 만"
|
||||
]
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "a",
|
||||
"from": "ctx",
|
||||
"to": "scan",
|
||||
"label": "스캔 요청",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 7920,
|
||||
"end_line": 7927
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "b",
|
||||
"from": "scan",
|
||||
"to": "always",
|
||||
"label": "항상 설치",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 7920,
|
||||
"end_line": 7927
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "c",
|
||||
"from": "always",
|
||||
"to": "optin",
|
||||
"label": "옵트인 위임",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 7920,
|
||||
"end_line": 7929
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "d",
|
||||
"from": "leaves",
|
||||
"to": "optin",
|
||||
"label": "조건 충족 시",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 7920,
|
||||
"end_line": 7929
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"style": "dashed"
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {}
|
||||
}
|
||||
+15230
File diff suppressed because one or more lines are too long
+116
@@ -0,0 +1,116 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "adapter-outbound-persistence-mongo-c01",
|
||||
"title": "옵트인을 이루는 네 겹",
|
||||
"question": "같은 스위치를 몇 겹이 읽는가?",
|
||||
"type": "sequence",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"이 저장소의 구조를 읽는 사람"
|
||||
],
|
||||
"summary": "네 겹이 같은 스위치를 읽지만 각각 다른 실패를 막고 첫 겹은 Boot 의 후보군에서 나머지는 자기 bean 그래프에서 막는다.",
|
||||
"alt": "같은 스위치를 임포트 필터와 루트 자동설정과 퍼시스턴스 설정과 플랫폼 자동설정이 차례로 읽는 순서.",
|
||||
"long_description": "SSOT 는 네 겹이 같은 스위치를 읽지만 각각 다른 실패를 막는다고 적는다. 첫 겹은 Boot 의 후보군에서, 나머지는 자기 bean 그래프에서 막는다.",
|
||||
"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": 9029,
|
||||
"line": 9029
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "sequence",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-approval-sequence"
|
||||
],
|
||||
"rationale": "같은 스위치가 네 겹에서 차례로 읽히는 순서가 논지다.",
|
||||
"focus_node": "filter"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "sw",
|
||||
"label": "같은 스위치",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 9029,
|
||||
"end_line": 9040
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "filter",
|
||||
"label": "MongoOptInAutoConfigurationImportFilter",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 9029,
|
||||
"end_line": 9040
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary",
|
||||
"details": [
|
||||
"Boot 후보군 제외"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "rest",
|
||||
"label": "루트 · 퍼시스턴스 · 플랫폼 자동설정",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 9029,
|
||||
"end_line": 9043
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"details": [
|
||||
"자기 bean 그래프 제외"
|
||||
]
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "m1",
|
||||
"from": "sw",
|
||||
"to": "filter",
|
||||
"label": "첫 겹 판정",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 9029,
|
||||
"end_line": 9040
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 1
|
||||
},
|
||||
{
|
||||
"id": "m2",
|
||||
"from": "sw",
|
||||
"to": "rest",
|
||||
"label": "나머지 세 겹 판정",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 9029,
|
||||
"end_line": 9043
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 2,
|
||||
"emphasis": "primary"
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {}
|
||||
}
|
||||
+15228
File diff suppressed because one or more lines are too long
+144
@@ -0,0 +1,144 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "adapter-outbound-persistence-mongo-c03",
|
||||
"title": "실행 scope 의 고정된 순서",
|
||||
"question": "실행 범위는 어떤 순서로 세워지는가?",
|
||||
"type": "dependency",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"이 저장소의 구조를 읽는 사람"
|
||||
],
|
||||
"summary": "프로파일 해석과 관측 개시와 일관성 바인딩을 거친 뒤에 콜백이 실행되어 아직 쓰이지 않은 연산에도 같은 불변식이 성립한다.",
|
||||
"alt": "profile 해석에서 observation 개시로 그리고 consistency 바인딩과 callback 실행으로 이어지는 순서.",
|
||||
"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": 9517,
|
||||
"line": 9517
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "component-flow",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"rationale": "한 곳에 고정된 순서가 아직 없는 연산에도 적용된다는 것이 논지다.",
|
||||
"focus_node": "profile"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "profile",
|
||||
"label": "profile 해석",
|
||||
"kind": "service",
|
||||
"role": "source",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 9517,
|
||||
"end_line": 9527
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary",
|
||||
"details": [
|
||||
"물리 이름"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "obs",
|
||||
"label": "observation 개시",
|
||||
"kind": "service",
|
||||
"role": "service",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 9517,
|
||||
"end_line": 9527
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"details": [
|
||||
"관측 범위"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cons",
|
||||
"label": "consistency 바인딩",
|
||||
"kind": "service",
|
||||
"role": "service",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 9517,
|
||||
"end_line": 9530
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"details": [
|
||||
"파생 template"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cb",
|
||||
"label": "callback 실행",
|
||||
"kind": "service",
|
||||
"role": "sink",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 9517,
|
||||
"end_line": 9530
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "a",
|
||||
"from": "profile",
|
||||
"to": "obs",
|
||||
"label": "고정 순서",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 9517,
|
||||
"end_line": 9527
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "b",
|
||||
"from": "obs",
|
||||
"to": "cons",
|
||||
"label": "고정 순서",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 9517,
|
||||
"end_line": 9527
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "c",
|
||||
"from": "cons",
|
||||
"to": "cb",
|
||||
"label": "고정 순서",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 9517,
|
||||
"end_line": 9530
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {}
|
||||
}
|
||||
+15286
File diff suppressed because one or more lines are too long
+125
@@ -0,0 +1,125 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "adapter-outbound-persistence-mongo-c04",
|
||||
"title": "반응형 경로가 직접 배치한 것",
|
||||
"question": "블로킹 경로가 공짜로 얻는 것을 반응형은 어디서 얻는가?",
|
||||
"type": "sequence",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"이 저장소의 구조를 읽는 사람"
|
||||
],
|
||||
"summary": "취소와 마감과 컨텍스트 전파를 반응형 실행기가 직접 배치한다.",
|
||||
"alt": "반응형 실행기가 관측 범위를 열고 조립 후 timeout 을 붙이고 Reactor Context 를 옮기는 순서.",
|
||||
"long_description": "SSOT §17 은 반응형 경로가 블로킹 경로에서 공짜로 얻는 것을 직접 배치해야 한다고 적는다. 취소·마감·컨텍스트 전파 셋이 그 자리다.",
|
||||
"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": 9278,
|
||||
"line": 9278
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "sequence",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-approval-sequence"
|
||||
],
|
||||
"rationale": "반응형 경로가 세 가지를 차례로 직접 붙이는 순서가 논지다.",
|
||||
"focus_node": "exec"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "exec",
|
||||
"label": "DefaultReactiveMongoExecutor",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 9278,
|
||||
"end_line": 9291
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "scope",
|
||||
"label": "Mono.using 관측 범위",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 9278,
|
||||
"end_line": 9291
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "ctx",
|
||||
"label": "Reactor Context",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 9278,
|
||||
"end_line": 9293
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "m1",
|
||||
"from": "exec",
|
||||
"to": "scope",
|
||||
"label": "범위 열기",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 9278,
|
||||
"end_line": 9291
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 1
|
||||
},
|
||||
{
|
||||
"id": "m2",
|
||||
"from": "exec",
|
||||
"to": "scope",
|
||||
"label": "조립 후 timeout",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 9278,
|
||||
"end_line": 9291
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 2,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "m3",
|
||||
"from": "exec",
|
||||
"to": "ctx",
|
||||
"label": "컨텍스트 이동",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 9278,
|
||||
"end_line": 9293
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 3
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {}
|
||||
}
|
||||
+15622
File diff suppressed because one or more lines are too long
+167
@@ -0,0 +1,167 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "adapter-outbound-support-c01",
|
||||
"title": "이 리프의 프로덕션 표면",
|
||||
"question": "공유 보조 seam 은 무엇을 내놓는가?",
|
||||
"type": "architecture",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"이 저장소의 구조를 읽는 사람"
|
||||
],
|
||||
"summary": "공유 보조 seam 하나에 타입이 셋뿐이고 설정이 조건 없이 기본 bean 을 준다.",
|
||||
"alt": "어댑터 호출자에서 공유 보조 seam 으로 가고, OutboundSupportConfig 가 기본 bean 계약을 채우며 두 타입이 그 계약을 구현한다.",
|
||||
"long_description": "SSOT §6 은 OutboundSupportConfig 가 조건 없는 공유 bean seam 이라고 적는다. 이 리프의 프로덕션 표면은 상관 식별자 조회(OutboundCorrelation)와 fail-open 관측 기록(FailOpenDependencyLogger), 그리고 그 기본 bean 을 주는 설정 셋이다.",
|
||||
"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": 3385,
|
||||
"line": 3385
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "ports-adapters",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"order-ports-adapters"
|
||||
],
|
||||
"rationale": "설정이 무엇을 만들고 그것이 어느 계약을 채우는지가 논지다.",
|
||||
"focus_node": "config"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "caller",
|
||||
"label": "어댑터 호출자",
|
||||
"kind": "adapter",
|
||||
"role": "inbound-adapter",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3385,
|
||||
"end_line": 3420
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "port",
|
||||
"label": "공유 보조 seam",
|
||||
"kind": "interface",
|
||||
"role": "port",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3385,
|
||||
"end_line": 3420
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "config",
|
||||
"label": "OutboundSupportConfig",
|
||||
"kind": "domain",
|
||||
"role": "core",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3385,
|
||||
"end_line": 3420
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "outport",
|
||||
"label": "기본 bean 계약",
|
||||
"kind": "interface",
|
||||
"role": "port",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3385,
|
||||
"end_line": 3420
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "types",
|
||||
"label": "프로덕션 타입 둘",
|
||||
"kind": "adapter",
|
||||
"role": "outbound-adapter",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3385,
|
||||
"end_line": 3420
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"details": [
|
||||
"OutboundCorrelation",
|
||||
"FailOpenDependencyLogger"
|
||||
]
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "a",
|
||||
"from": "caller",
|
||||
"to": "port",
|
||||
"label": "seam 사용",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3385,
|
||||
"end_line": 3420
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "b",
|
||||
"from": "port",
|
||||
"to": "config",
|
||||
"label": "bean 요청",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3385,
|
||||
"end_line": 3420
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "c",
|
||||
"from": "config",
|
||||
"to": "outport",
|
||||
"label": "기본 bean 제공",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3385,
|
||||
"end_line": 3420
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "d",
|
||||
"from": "types",
|
||||
"to": "outport",
|
||||
"label": "계약 구현",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3385,
|
||||
"end_line": 3420
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"style": "dashed"
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {}
|
||||
}
|
||||
+15580
File diff suppressed because one or more lines are too long
+15832
File diff suppressed because one or more lines are too long
+136
@@ -0,0 +1,136 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "adapter-outbound-support-c02",
|
||||
"title": "판정과 기록의 갈림",
|
||||
"question": "fail-open 실패를 누가 정하고 로거는 무엇을 하는가?",
|
||||
"type": "data-flow",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"플랫폼 어댑터를 읽는 사람"
|
||||
],
|
||||
"summary": "fail-open 여부는 호출 지점이 정하고 로거는 이미 정해진 결과를 관측만 한다.",
|
||||
"alt": "호출 지점에서 fail-open outcome 으로 판정이 가고, outcome 에서 호출자로 결과가, 로거로 관측이 간다. 로거에서 나가는 화살표는 없다.",
|
||||
"long_description": "SSOT §3 은 FailOpenDependencyLogger 가 retry·recovery·fallback 을 수행하지 않고 이미 결정된 fail-open outcome 을 관측하는 기술 seam 이라고 적는다(3205). WARN 을 고른 이유도 core use case 자체는 성공했기 때문이다(3203). 그래서 로거에서 업무 경로로 되돌아오는 화살표가 없다.",
|
||||
"source_context": {
|
||||
"document": "docs/clean-architecture-backend-template/final/document.md",
|
||||
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
|
||||
"anchor": {
|
||||
"kind": "line",
|
||||
"value": 3186,
|
||||
"line": 3186
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "component-flow",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"rationale": "결과가 호출 지점에서 호출자와 로거로 흐르는 방향이 논지다. 로거가 끝점이라는 것이 그림의 주장이다.",
|
||||
"focus_node": "outcome"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "call-site",
|
||||
"label": "호출 지점",
|
||||
"kind": "service",
|
||||
"role": "source",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3209,
|
||||
"end_line": 3219
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "outcome",
|
||||
"label": "fail-open outcome",
|
||||
"kind": "service",
|
||||
"role": "service",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3203,
|
||||
"end_line": 3205
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "caller",
|
||||
"label": "호출자",
|
||||
"kind": "service",
|
||||
"role": "sink",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3203,
|
||||
"end_line": 3203
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "logger",
|
||||
"label": "FailOpenDependencyLogger",
|
||||
"kind": "observability",
|
||||
"role": "sink",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3205,
|
||||
"end_line": 3205
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "decide",
|
||||
"from": "call-site",
|
||||
"to": "outcome",
|
||||
"label": "fail-open 판정",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3205,
|
||||
"end_line": 3205
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "result",
|
||||
"from": "outcome",
|
||||
"to": "caller",
|
||||
"label": "결과 반환",
|
||||
"kind": "response",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3203,
|
||||
"end_line": 3203
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "observe",
|
||||
"from": "outcome",
|
||||
"to": "logger",
|
||||
"label": "관측",
|
||||
"kind": "data",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3205,
|
||||
"end_line": 3205
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"style": "dashed"
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {}
|
||||
}
|
||||
+15136
File diff suppressed because it is too large
Load Diff
+164
@@ -0,0 +1,164 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "application-core-c01",
|
||||
"title": "의존이 흐르는 한 방향",
|
||||
"question": "의존은 어느 쪽으로 흐르는가?",
|
||||
"type": "architecture",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"이 저장소의 구조를 읽는 사람"
|
||||
],
|
||||
"summary": "어댑터가 application-core 의 포트를 구현하고 application-core 는 shared-contract 하나에만 의존한다.",
|
||||
"alt": "어댑터가 포트를 구현하고 application-core 가 그 포트를 선언하며 shared-contract 로만 의존이 나간다.",
|
||||
"long_description": "SSOT 는 어댑터가 application-core 의 포트를 구현하고 application-core 가 shared-contract 하나에만 의존한다고 적는다.",
|
||||
"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": 2390,
|
||||
"line": 2390
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "ports-adapters",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"order-ports-adapters"
|
||||
],
|
||||
"rationale": "의존 화살표가 한 방향으로만 흐른다는 것이 논지다.",
|
||||
"focus_node": "core"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "adapter",
|
||||
"label": "어댑터",
|
||||
"kind": "adapter",
|
||||
"role": "inbound-adapter",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2390,
|
||||
"end_line": 2396
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "port",
|
||||
"label": "port 선언",
|
||||
"kind": "interface",
|
||||
"role": "port",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2390,
|
||||
"end_line": 2396
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "core",
|
||||
"label": "application-core",
|
||||
"kind": "domain",
|
||||
"role": "core",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2390,
|
||||
"end_line": 2396
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "sc",
|
||||
"label": "shared-contract 계약",
|
||||
"kind": "interface",
|
||||
"role": "port",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2390,
|
||||
"end_line": 2398
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "shared",
|
||||
"label": "shared-contract",
|
||||
"kind": "adapter",
|
||||
"role": "outbound-adapter",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2390,
|
||||
"end_line": 2398
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "a",
|
||||
"from": "adapter",
|
||||
"to": "port",
|
||||
"label": "port 구현",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2390,
|
||||
"end_line": 2396
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"style": "dashed"
|
||||
},
|
||||
{
|
||||
"id": "b",
|
||||
"from": "port",
|
||||
"to": "core",
|
||||
"label": "계약 소유",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2390,
|
||||
"end_line": 2396
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "c",
|
||||
"from": "core",
|
||||
"to": "sc",
|
||||
"label": "유일한 의존",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2390,
|
||||
"end_line": 2398
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "d",
|
||||
"from": "shared",
|
||||
"to": "sc",
|
||||
"label": "계약 제공",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2390,
|
||||
"end_line": 2398
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"style": "dashed"
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {}
|
||||
}
|
||||
+15252
File diff suppressed because one or more lines are too long
+114
@@ -0,0 +1,114 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "application-core-c02",
|
||||
"title": "두 판정이 갈리는 자리",
|
||||
"question": "권한 판정과 객체 판정은 어디서 나뉘는가?",
|
||||
"type": "dependency",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"이 저장소의 구조를 읽는 사람"
|
||||
],
|
||||
"summary": "같은 요청에 대해 작업 종류를 묻는 판정과 개별 객체 접근을 묻는 판정이 서로 다른 포트로 나뉜다.",
|
||||
"alt": "요청이 AuthorizationPort 로 작업 종류를 묻고 ObjectAccessPolicy 로 개별 객체를 묻는다.",
|
||||
"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": 2613,
|
||||
"line": 2613
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "component-flow",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"rationale": "한 요청이 두 판정으로 갈리는 것이 논지다.",
|
||||
"focus_node": "req"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "req",
|
||||
"label": "요청",
|
||||
"kind": "service",
|
||||
"role": "source",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2613,
|
||||
"end_line": 2620
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "authz",
|
||||
"label": "AuthorizationPort",
|
||||
"kind": "service",
|
||||
"role": "sink",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2613,
|
||||
"end_line": 2620
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"details": [
|
||||
"작업 종류"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "obj",
|
||||
"label": "ObjectAccessPolicy",
|
||||
"kind": "service",
|
||||
"role": "sink",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2613,
|
||||
"end_line": 2622
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"details": [
|
||||
"개별 객체"
|
||||
]
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "a",
|
||||
"from": "req",
|
||||
"to": "authz",
|
||||
"label": "작업 종류 판정",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2613,
|
||||
"end_line": 2620
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "b",
|
||||
"from": "req",
|
||||
"to": "obj",
|
||||
"label": "개별 객체 판정",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2613,
|
||||
"end_line": 2622
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {}
|
||||
}
|
||||
+15280
File diff suppressed because one or more lines are too long
+166
@@ -0,0 +1,166 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "application-core-c03",
|
||||
"title": "노출하는 어휘와 감추는 어휘",
|
||||
"question": "응용 계층은 트랜잭션을 어떤 어휘로 말하는가?",
|
||||
"type": "dependency",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"이 저장소의 구조를 읽는 사람"
|
||||
],
|
||||
"summary": "정책 식별자와 결과 대수가 응용 계층의 어휘로 노출되고 프레임워크의 전파 숫자는 경계 밖에 남는다.",
|
||||
"alt": "호출자에서 application-core 어휘로 가고 거기서 TransactionPolicyId 와 TransactionResult 가 나온다. Spring 전파 숫자로는 점선이 간다.",
|
||||
"long_description": "SSOT 는 TransactionPolicyId 가 Spring propagation 숫자가 아니라 COMMAND_DEFAULT · QUERY_PRIMARY 같은 application semantic ID 를 노출한다고 적는다.",
|
||||
"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": 2627,
|
||||
"line": 2627
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "component-flow",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"rationale": "같은 개념이 어느 어휘로 넘어오고 어느 어휘가 경계에서 멈추는지가 논지다.",
|
||||
"focus_node": "vocab"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "caller",
|
||||
"label": "응용 호출자",
|
||||
"kind": "service",
|
||||
"role": "source",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2627,
|
||||
"end_line": 2650
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "vocab",
|
||||
"label": "application-core 어휘",
|
||||
"kind": "service",
|
||||
"role": "service",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2627,
|
||||
"end_line": 2650
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "policy",
|
||||
"label": "TransactionPolicyId",
|
||||
"kind": "service",
|
||||
"role": "sink",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2627,
|
||||
"end_line": 2650
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "result",
|
||||
"label": "TransactionResult",
|
||||
"kind": "service",
|
||||
"role": "sink",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2627,
|
||||
"end_line": 2650
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "spring",
|
||||
"label": "Spring 전파 숫자",
|
||||
"kind": "service",
|
||||
"role": "sink",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2627,
|
||||
"end_line": 2652
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"details": [
|
||||
"경계 밖"
|
||||
]
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "a",
|
||||
"from": "caller",
|
||||
"to": "vocab",
|
||||
"label": "정책 요청",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2627,
|
||||
"end_line": 2650
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "b",
|
||||
"from": "vocab",
|
||||
"to": "policy",
|
||||
"label": "식별자 노출",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2627,
|
||||
"end_line": 2650
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "c",
|
||||
"from": "vocab",
|
||||
"to": "result",
|
||||
"label": "결과 노출",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2627,
|
||||
"end_line": 2650
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "d",
|
||||
"from": "vocab",
|
||||
"to": "spring",
|
||||
"label": "미노출",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2627,
|
||||
"end_line": 2652
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"style": "dashed"
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {}
|
||||
}
|
||||
+15438
File diff suppressed because one or more lines are too long
+134
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "application-core-c04",
|
||||
"audience": [
|
||||
"플랫폼 어댑터를 읽는 사람"
|
||||
],
|
||||
"source_context": {
|
||||
"document": "docs/clean-architecture-backend-template/final/document.md",
|
||||
"document_sha256": "8071fe71b3359d9cf60b95909c26c7b50653ce2f22bbc5fcf6988719bb91236d",
|
||||
"anchor": {
|
||||
"kind": "line",
|
||||
"value": 22371,
|
||||
"line": 22371
|
||||
}
|
||||
},
|
||||
"groups": [],
|
||||
"legend": [],
|
||||
"metadata": {},
|
||||
"title": "응답을 잃은 구간을 맡는 세 장치",
|
||||
"question": "효과는 일어났는데 응답만 잃은 구간을 무엇이 맡는가?",
|
||||
"type": "dependency",
|
||||
"direction": "LR",
|
||||
"summary": "응답 유실 구간을 멱등성·inbox·outbox 셋이 나눠 맡고 어느 쪽도 불확실을 성공이나 실패로 접지 않는다.",
|
||||
"alt": "응답 유실 구간에서 idempotency V2 와 inbox 와 outbox 로 갈라진다.",
|
||||
"long_description": "SSOT §7.1 은 outbox·inbox 체인이 만족되지 않는 조건 뒤에 있다고 적는다. 세 장치는 효과가 이미 일어났을 수 있는데 응답만 잃은 구간을 나눠 맡고, 어느 쪽도 불확실을 성공이나 실패로 접지 않는다.",
|
||||
"composition": {
|
||||
"profile": "component-flow",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"rationale": "한 구간이 세 장치로 나뉘는 분담 방향이 논지다.",
|
||||
"focus_node": "gap"
|
||||
},
|
||||
"nodes": [
|
||||
{
|
||||
"id": "gap",
|
||||
"label": "응답 유실 구간",
|
||||
"kind": "service",
|
||||
"role": "source",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 22371,
|
||||
"end_line": 22380
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "idem",
|
||||
"label": "idempotency V2",
|
||||
"kind": "service",
|
||||
"role": "sink",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 22371,
|
||||
"end_line": 22390
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "inbox",
|
||||
"label": "inbox",
|
||||
"kind": "service",
|
||||
"role": "sink",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 22371,
|
||||
"end_line": 22390
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "outbox",
|
||||
"label": "outbox",
|
||||
"kind": "service",
|
||||
"role": "sink",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 22371,
|
||||
"end_line": 22390
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "a",
|
||||
"from": "gap",
|
||||
"to": "idem",
|
||||
"label": "owner-safe CAS",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 22371,
|
||||
"end_line": 22390
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "b",
|
||||
"from": "gap",
|
||||
"to": "inbox",
|
||||
"label": "owner-safe 수신 상태",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 22371,
|
||||
"end_line": 22390
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "c",
|
||||
"from": "gap",
|
||||
"to": "outbox",
|
||||
"label": "at-least-once 발행",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 22371,
|
||||
"end_line": 22390
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
]
|
||||
}
|
||||
+15095
File diff suppressed because it is too large
Load Diff
+130
@@ -0,0 +1,130 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "application-core-c10",
|
||||
"title": "공개 계약과 비밀이 나뉘는 자리",
|
||||
"question": "공개 알림 계약은 무엇을 받고 무엇을 막는가?",
|
||||
"type": "sequence",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"이 저장소의 구조를 읽는 사람"
|
||||
],
|
||||
"summary": "sealed 변수 대수와 고정된 템플릿 판본과 유계 수신자 수만 공개 계약에 들어오고 임의 Object 변수와 연락처 원문은 막힌다.",
|
||||
"alt": "호출자가 공개 알림 계약에 sealed 변수를 넘기면 받아들여지고 임의 Object 변수는 거절되는 순서.",
|
||||
"long_description": "SSOT 는 public contract 가 arbitrary Object 나 Map<String,Object> 를 허용하지 않고 sealed NotificationVariable algebra 를 쓴다고 적는다. 과거 mutable/arbitrary variable 때문에 serialization·fingerprint drift 와 toString 충돌이 가능했던 것이 변경 근거다.",
|
||||
"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": 2767,
|
||||
"line": 2767
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "sequence",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-approval-sequence"
|
||||
],
|
||||
"rationale": "받아들이는 입력과 거절하는 입력이 순서 위에서 갈린다.",
|
||||
"focus_node": "contract"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "caller",
|
||||
"label": "알림 호출자",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2765,
|
||||
"end_line": 2770
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "contract",
|
||||
"label": "공개 알림 계약",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2765,
|
||||
"end_line": 2770
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary",
|
||||
"details": [
|
||||
"고정된 템플릿 판본",
|
||||
"유계 수신자 수"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "guard",
|
||||
"label": "구조 테스트",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2765,
|
||||
"end_line": 2772
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "m1",
|
||||
"from": "caller",
|
||||
"to": "contract",
|
||||
"label": "sealed 변수 대수",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2765,
|
||||
"end_line": 2770
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 1
|
||||
},
|
||||
{
|
||||
"id": "m2",
|
||||
"from": "caller",
|
||||
"to": "contract",
|
||||
"label": "임의 Object 변수",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2765,
|
||||
"end_line": 2770
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 2,
|
||||
"style": "dashed"
|
||||
},
|
||||
{
|
||||
"id": "m3",
|
||||
"from": "contract",
|
||||
"to": "guard",
|
||||
"label": "공개 API 검사",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 2765,
|
||||
"end_line": 2772
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 3,
|
||||
"emphasis": "primary"
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {}
|
||||
}
|
||||
+15042
File diff suppressed because it is too large
Load Diff
+108
@@ -0,0 +1,108 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "approval-verification-execution",
|
||||
"title": "승인이 실행에 닿기까지",
|
||||
"question": "승인은 어떤 단계를 지나 실행에 닿는가?",
|
||||
"type": "dependency",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"이 저장소의 구조를 읽는 사람"
|
||||
],
|
||||
"summary": "승인 문서가 가드 검증을 지나 VerifiedApproval 이 되어야 파괴적 실행에 닿는다.",
|
||||
"alt": "승인 발급에서 가드 검증으로 승인 문서가 건너가고 가드 검증에서 파괴적 실행으로 VerifiedApproval 이 건너간다.",
|
||||
"long_description": "SSOT 는 승인 사슬 전체가 검증자 없이는 시작될 수 없다고 적는다. 승인 문서가 가드 검증을 지나 VerifiedApproval 이 되어야 파괴적 실행에 닿는다.",
|
||||
"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": 25110,
|
||||
"line": 25110
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "component-flow",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"rationale": "승인이 검증을 반드시 지나야 실행에 닿는다는 순서가 논지다.",
|
||||
"focus_node": "guard"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "issue",
|
||||
"label": "승인 발급",
|
||||
"kind": "service",
|
||||
"role": "source",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 25110,
|
||||
"end_line": 25113
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "guard",
|
||||
"label": "가드 검증",
|
||||
"kind": "service",
|
||||
"role": "service",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 25110,
|
||||
"end_line": 25113
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "exec",
|
||||
"label": "파괴적 실행",
|
||||
"kind": "service",
|
||||
"role": "sink",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 25110,
|
||||
"end_line": 25115
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "a",
|
||||
"from": "issue",
|
||||
"to": "guard",
|
||||
"label": "승인 문서",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 25110,
|
||||
"end_line": 25113
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "b",
|
||||
"from": "guard",
|
||||
"to": "exec",
|
||||
"label": "VerifiedApproval",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 25110,
|
||||
"end_line": 25115
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {}
|
||||
}
|
||||
+15136
File diff suppressed because it is too large
Load Diff
+128
@@ -0,0 +1,128 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "bounded-and-unbounded-side-by-side",
|
||||
"title": "두 오버로드를 가르는 표시",
|
||||
"question": "두 purge 오버로드는 무엇으로 구분되는가?",
|
||||
"type": "sequence",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"이 저장소의 구조를 읽는 사람"
|
||||
],
|
||||
"summary": "배치 제한 오버로드에는 javadoc 근거가 있고 무제한 오버로드에는 그것을 가르는 표시가 없다.",
|
||||
"alt": "호출자가 무제한 오버로드와 배치 제한 오버로드를 차례로 부르고 한쪽에만 근거가 붙는 순서.",
|
||||
"long_description": "SSOT 는 포트가 bounded/unbounded purge 두 오버로드를 나란히 두고 무제한 쪽을 가르는 표시가 없다고 적는다.",
|
||||
"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": 34553,
|
||||
"line": 34553
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "sequence",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-approval-sequence"
|
||||
],
|
||||
"rationale": "같은 이름의 두 오버로드에서 한쪽에만 근거가 붙는다는 것이 순서로 드러난다.",
|
||||
"focus_node": "port"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "caller",
|
||||
"label": "호출자",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 34553,
|
||||
"end_line": 34558
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "port",
|
||||
"label": "purge 포트",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 34553,
|
||||
"end_line": 34560
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "m1",
|
||||
"from": "caller",
|
||||
"to": "port",
|
||||
"label": "purgeBefore Instant",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 34553,
|
||||
"end_line": 34558
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 1
|
||||
},
|
||||
{
|
||||
"id": "m2",
|
||||
"from": "port",
|
||||
"to": "caller",
|
||||
"label": "가르는 표시 없음",
|
||||
"kind": "response",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 34553,
|
||||
"end_line": 34558
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 2,
|
||||
"style": "dashed",
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "m3",
|
||||
"from": "caller",
|
||||
"to": "port",
|
||||
"label": "purgeBefore Instant int",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 34553,
|
||||
"end_line": 34560
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 3
|
||||
},
|
||||
{
|
||||
"id": "m4",
|
||||
"from": "port",
|
||||
"to": "caller",
|
||||
"label": "javadoc 이 적은 근거",
|
||||
"kind": "response",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 34553,
|
||||
"end_line": 34560
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 4
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {}
|
||||
}
|
||||
+15682
File diff suppressed because one or more lines are too long
+111
@@ -0,0 +1,111 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "capability-schema-registry",
|
||||
"title": "적용과 사용 승인이 갈리는 자리",
|
||||
"question": "스키마 적용과 사용 승인은 어떻게 나뉘는가?",
|
||||
"type": "dependency",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"이 저장소의 구조를 읽는 사람"
|
||||
],
|
||||
"summary": "선행조건 검사를 지나 테이블을 만들고 자기를 INSTALLED_INACTIVE 로 등록하므로 적용과 사용 승인이 갈린다.",
|
||||
"alt": "선행조건 검사에서 테이블 생성으로 core epoch 확인이 건너가고 테이블 생성에서 레지스트리 등록으로 INSTALLED_INACTIVE 가 건너간다.",
|
||||
"long_description": "SSOT 는 각 capability 스트림의 V1 이 선행조건 검사와 테이블 생성과 자기 등록 세 단계를 밟는다고 적는다. 그래서 스키마가 적용됐다와 capability 를 써도 된다가 분리된다.",
|
||||
"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": 541,
|
||||
"line": 541
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "component-flow",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"rationale": "적용이 끝나도 사용 승인이 따로 남는다는 순서가 논지다.",
|
||||
"focus_node": "table"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "pre",
|
||||
"label": "선행조건 검사",
|
||||
"kind": "service",
|
||||
"role": "source",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 541,
|
||||
"end_line": 600
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "table",
|
||||
"label": "테이블 생성",
|
||||
"kind": "service",
|
||||
"role": "service",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 541,
|
||||
"end_line": 600
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
},
|
||||
{
|
||||
"id": "reg",
|
||||
"label": "레지스트리 등록",
|
||||
"kind": "service",
|
||||
"role": "sink",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 541,
|
||||
"end_line": 653
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"details": [
|
||||
"INSTALLED_INACTIVE"
|
||||
]
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "a",
|
||||
"from": "pre",
|
||||
"to": "table",
|
||||
"label": "core epoch 확인",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 541,
|
||||
"end_line": 600
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "b",
|
||||
"from": "table",
|
||||
"to": "reg",
|
||||
"label": "자기 등록",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 541,
|
||||
"end_line": 653
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary"
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {}
|
||||
}
|
||||
+15473
File diff suppressed because one or more lines are too long
+131
@@ -0,0 +1,131 @@
|
||||
{
|
||||
"version": "1.1",
|
||||
"id": "cardinality-bounds-as-types",
|
||||
"title": "값 타입 생성자가 막는 것",
|
||||
"question": "이름 자리에 무엇이 들어올 수 있는가?",
|
||||
"type": "sequence",
|
||||
"direction": "LR",
|
||||
"audience": [
|
||||
"이 저장소의 구조를 읽는 사람"
|
||||
],
|
||||
"summary": "등록된 이름과 정규식을 통과한 값만 값 타입이 되고 엔티티 id 와 SQL 조각은 생성자가 거부한다.",
|
||||
"alt": "호출자가 형식을 맞춘 문자열을 넘기면 등록된 이름을 받고 엔티티 id 나 SQL 조각을 넘기면 거부되는 순서.",
|
||||
"long_description": "SSOT §2.3 은 PersistenceOperationName 이 [a-z][a-z0-9.-]{2,95} 형식만 허용한다고 적는다. 자유 문자열 대신 등록 가능한 identity 를 타입으로 만들어 엔티티 id·tenant id·SQL 조각·요청 값이 그 자리에 올 수 없게 한다.",
|
||||
"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": 3879,
|
||||
"line": 3879
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"profile": "sequence",
|
||||
"diagram_only": true,
|
||||
"reference_ids": [
|
||||
"payment-approval-sequence"
|
||||
],
|
||||
"rationale": "같은 자리에 무엇을 넣었을 때 통과하고 무엇을 넣었을 때 거부되는지가 순서로 드러난다.",
|
||||
"focus_node": "ctor"
|
||||
},
|
||||
"groups": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "caller",
|
||||
"label": "호출자",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3879,
|
||||
"end_line": 3900
|
||||
}
|
||||
],
|
||||
"assumption": false
|
||||
},
|
||||
{
|
||||
"id": "ctor",
|
||||
"label": "값 타입 생성자",
|
||||
"kind": "service",
|
||||
"role": "participant",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3879,
|
||||
"end_line": 3900
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"emphasis": "primary",
|
||||
"details": [
|
||||
"정규식 통과 값"
|
||||
]
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "m1",
|
||||
"from": "caller",
|
||||
"to": "ctor",
|
||||
"label": "형식 맞는 문자열",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3879,
|
||||
"end_line": 3900
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 1
|
||||
},
|
||||
{
|
||||
"id": "m2",
|
||||
"from": "ctor",
|
||||
"to": "caller",
|
||||
"label": "등록된 이름",
|
||||
"kind": "response",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3879,
|
||||
"end_line": 3900
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 2,
|
||||
"style": "dashed"
|
||||
},
|
||||
{
|
||||
"id": "m3",
|
||||
"from": "caller",
|
||||
"to": "ctor",
|
||||
"label": "엔티티 id · SQL 조각",
|
||||
"kind": "request",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3879,
|
||||
"end_line": 3902
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 3
|
||||
},
|
||||
{
|
||||
"id": "m4",
|
||||
"from": "ctor",
|
||||
"to": "caller",
|
||||
"label": "거부",
|
||||
"kind": "response",
|
||||
"evidence": [
|
||||
{
|
||||
"start_line": 3879,
|
||||
"end_line": 3902
|
||||
}
|
||||
],
|
||||
"assumption": false,
|
||||
"order": 4,
|
||||
"emphasis": "primary"
|
||||
}
|
||||
],
|
||||
"legend": [],
|
||||
"metadata": {}
|
||||
}
|
||||
+15682
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user