Files
document-haness/docs/clean-architecture-backend-template/tech-log-studio/delivery-and-settlement-models/concept/concept-shared-contract-c01.md
T
DongHyeonkaandClaude Fable 5.1 b25357c48a docs(clean-architecture-backend-template): fold analysis into final and re-select one topic
- analysis/·source-index·state.json 을 final/document.md 제2부·제3부로 접었다. SSOT 는 하나다
- 파일럿 — commit-ambiguity-as-a-result 를 새 기준으로 재선별. 후보 14 → 글감 5
  (PROMOTE 5 · MERGE_INTO 3 · KEEP_IN_SSOT 4 · 보류 2). 기록 5건을 다시 썼고 그림 1개를
  techviz 로 만들었다
- 재선별이 잡은 것: 제1부 §6.2·§11.1 이 자기 §13.2 와 어긋나 있었다(레인을 안 돌렸다 vs
  돌렸다) — 정정. 이미 답이 나와 있던 Question 을 HEAD 재실행 질문으로 다시 세웠다.
  Concept 이 인용한 코드가 SSOT 에 없어 뺐다
- candidateScope·sourceRepository 기록. 나머지 43개 주제는 재선별 대기(PENDING 905)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-07 12:39:20 +09:00

4.0 KiB
Raw Blame History

kind, slug, title, topic, project, status, sourceRevision, rootTreeNode, evidenceCapturedOn, assets, evidence, source, module
kind slug title topic project status sourceRevision rootTreeNode evidenceCapturedOn assets evidence source module
CONCEPT shared-contract-c01 factory는 검증하고 raw 생성자는 검증하지 않는다 delivery-and-settlement-models clean-architecture-backend-template 게시 전 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 concept:shared-contract-c01 2026-09-01
key file
shared-contract-c01 ../../../final/evidence/rendered/shared-contract-c01.svg
key file
shared-contract-c01-diagram ../../../final/assets/diagrams/shared-contract-c01.svg
../../../final/evidence/raw/shared-contract-c01.txt
원본 분석 절은 final/document.md#a02#L51 이다.
shared-contract

factory는 검증하고 raw 생성자는 검증하지 않는다

ApiErrorCode는 code/category/httpStatus/retryable의 최소 표면을 제공하고 OperationalError가 registry mirror 역할을 한다. Category는 VALIDATION, AUTH, AUTHZ, NOT_FOUND, CONFLICT, RATE_LIMIT, TRANSIENT_DEPENDENCY, PERMANENT_DEPENDENCY, DATA_INTEGRITY, INTERNAL의 10개 값으로 고정되어 있으며 테스트가 정확한 vocabulary를 pin 한다.

본문

ApiErrorCode는 code/category/httpStatus/retryable의 최소 표면을 제공하고 OperationalError가 registry mirror 역할을 한다. Category는 VALIDATION, AUTH, AUTHZ, NOT_FOUND, CONFLICT, RATE_LIMIT, TRANSIENT_DEPENDENCY, PERMANENT_DEPENDENCY, DATA_INTEGRITY, INTERNAL의 10개 값으로 고정되어 있으며 테스트가 정확한 vocabulary를 pin 한다.

ApiErrorCode 참조 위치

:::evidence key="shared-contract-c01" alt="코드베이스에서 ApiErrorCode 를 검색한 출력 16줄. 이 기록이 세는 참조가 그 출력에 그대로 보인다." caption="ApiErrorCode 코드베이스 검색 — 16줄 · exit 0" zoom="true" :::

retryable 이 category 에서 자동으로 나오지 않는다

OperationalErrorTest는 단순 enum 존재보다 category × retryable 의미를 강하게 검증한다. deterministic VALIDATION/AUTHZ/NOT_FOUND는 retryable=false이고, transient INTERNAL은 기본적으로 retryable=true이되 deploy-time/configuration/terminal 상태인 일부 code는 명시적 예외로 false다. AUTH_KID_UNKNOWN은 key rotation 중 JWKS refresh 가능성을 이유로 AUTH 중 유일한 retryable case로 pin 되어 있다. upstream 4xx 전체를 permanent/non-retryable로 분류하면서 408/429의 의미 차이가 남는다는 점은 source comment와 README가 이미 known edge로 기록한다.

어떤 예외가 코드를 나르는가

DependencyFailureExceptionPersistenceFailureExceptionApiErrorCarrier를 통해 transport adapter에 stable error code를 전달하면서 raw cause/diagnostic message를 server-side 정보로 남긴다. AdapterDisabledException은 carrier를 구현하지 않고 별도 mapping 대상이다.

검증이 걸리는 자리

:::evidence key="shared-contract-c01-diagram" alt="factory 경로에 배타성 검증과 문서의 정상 shape 가 놓이고 raw 생성자에 배타성 미검증과 invalid shape 가능이 빗금으로 놓인다" caption="검증이 걸리는 자리" zoom="false" :::

Envelope, BulkEnvelope, ResponseMeta, PageMeta, Operation은 framework-neutral record/factory로 API shape를 전달한다. Envelope.ok/failure, BulkEnvelope.allOk/partial, Operation.pending/succeeded/failed factory는 문서의 정상 shape를 생성하고 테스트도 이 factory path를 검증한다. 그러나 canonical record constructor 자체는 success/data/error의 배타성, operation status와 result/error의 조합, pagination 범위 등을 검증하지 않는다.

그래서 이 규칙의 성격이 다르다

rate-limit value object처럼 intrinsic constructor invariant가 아니라 factory/adapter usage contract다. 현재 source와 test가 일치하므로 즉시 결함으로 분류하지 않지만, raw constructor가 외부 module에 public인 만큼 invalid shape 생성 가능성은 P1 hardening 후보로 남는다.