docs(clean-architecture-backend-template): 제1부가 채택한 것만 글감으로 남기고 다시 고른다

글감 1,001개 중 제1부(§3~§11) 앵커를 하나라도 가진 것은 112개뿐이었다. 나머지 889개는
제2부 모듈 분석 65편의 절 제목에서 나온 것이고, 그것이 재판정이 필요했던 이유다.

  주제      44 → 16   (43개가 독자 질문 없이 있었다. 지금은 전부 있다)
  글감   1,001 → 123  (제1부 앵커 112 + 제1부가 채택했는데 비어 있던 자리 11)
  후보      965 → 1,088 · PENDING 905 → 0
  error   3,042 → 0

내려온 889개는 후보 대장에 KEEP_IN_SSOT 로 남는다 — 버린 것이 아니라 분석에 남기고 독립
기록으로 만들지 않기로 한 것이다. 그 글감을 받치던 기록 파일 828개는 지웠다. 계약이 정본이고,
파일이 남아 있다는 이유로 계약에서 뺀 주제가 되살아나면 안 된다. 이력에는 그대로 있다 —
git checkout a0ca2bb -- <경로>.

제1부가 채택했는데 글감이 없던 자리 열하나를 채웠다: mongo high-water mark 가 재전달 이벤트를
삼킨 P1, admin plane 이 가드만 켜고 서비스는 켜지 않은 것과 그 짝인 결정, 실패 어휘 세 층과
SQLState 매트릭스 병합 규칙, 부하 아래에서만 새는 admission 경계, 발행 증거와 완료 판정의
분리, keyset·JSONB 결정 둘.

Concept 17개에 basis-version 을 채우고, 계약 제목과 기록 제목이 갈라져 있던 23건을 기록 쪽에
맞췄다. candidateScope 에 excludedAnchorPattern 을 적어 제2부 앵커만 가진 글감이 다시 올라올
수 없게 한다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
DongHyeonka
2026-09-07 15:02:25 +09:00
co-authored by Claude Opus 5
parent a0ca2bb72a
commit 1f04117bbf
851 changed files with 5498 additions and 90638 deletions
@@ -1,7 +1,7 @@
---
kind: CASE
slug: a-build-gate-that-is-not-in-the-build
title: '"build gate"라 불리는 catalog drift 검사가 어디에서도 실행되지 않는다'
title: "build gate"라 불리는 catalog drift 검사가 어디에서도 실행되지 않는다
topic: redis-command-admission
project: clean-architecture-backend-template
status: 게시 전
@@ -1,60 +0,0 @@
---
kind: PROJECT_DECISION
slug: unclassified-commands-are-refused
title: 분류되지 않은 명령은 fail-closed로 거부한다
topic: redis-command-admission
project: clean-architecture-backend-template
status: 게시 전
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
rootTreeNode: decision:unclassified-commands-are-refused
decisionStatus: ADOPTED
decidedOn: 2026-08-30
source:
- src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandCatalog.java
- src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/CommandPolicyGuard.java
- final/document.md#a10
---
# 분류되지 않은 명령은 fail-closed로 거부한다
## 결정문
명령 카탈로그가 분류하지 못하는 명령은 통과시키지 않고 거부한다.
## 판단 이유
승인 아홉 단계는 명령이 무엇인지 아는 것을 전제한다. 위험 등급도 키 스펙도 슬롯 계산도 카탈로그의 정의에서 나온다.
분류되지 않은 명령을 통과시키면 그 단계들이 적용되지 않은 채 실행된다. 위험 등급을 모르므로 허가 요구도 걸 수 없고, 키 스펙을 모르므로 네임스페이스 검사도 슬롯 계산도 할 수 없다.
즉 통과는 검사를 건너뛰는 것과 같다. 그리고 그 사실이 호출자에게 보이지 않는다.
거부는 시끄럽다. 새 명령을 쓰려면 카탈로그에 먼저 넣어야 한다. 그 마찰이 이 결정의 목적이다.
카탈로그의 정의가 서버 메타데이터에서 온다는 것과 함께 보면 구조가 완성된다. 서버가 아는 명령만 카탈로그에 있고, 카탈로그에 있는 명령만 실행된다.
## 영향
감수하는 것
새 Redis 명령을 쓰려면 카탈로그 갱신이 선행되어야 한다. 서버가 지원해도 바로 쓸 수 없다.
카탈로그가 뒤처지면 정상적인 명령이 거부된다. 그래서 드리프트 검사가 필요하고, 그 검사가 현재 빌드에 없다.
우회 경로가 있으면 이 결정이 그 경로에 적용되지 않는다. 다섯 어댑터가 게이트웨이를 직접 부르는 경로가 그렇다.
얻는 것
정책이 적용되지 않은 명령이 실행되지 않는다.
새 명령의 도입이 명시적 행위가 된다.
## 근거
- **서버 메타데이터가 명령의 정의이고 정책 파일은 허용 범위다**
이 결정이 기대는 관계다.
- **명령 카탈로그와 admission 아홉 단계**
카탈로그가 없으면 적용될 수 없는 단계들이다.
- **의미 어댑터 다섯이 gateway를 직접 불러 admission 아홉 단계를 건너뛴다**
이 결정이 적용되지 않는 경로다.
@@ -1,60 +0,0 @@
---
kind: REFERENCE
slug: a-single-admission-point-must-count-its-bypasses
title: 단일 admission point는 우회 경로를 세어야 성립한다
topic: redis-command-admission
project: clean-architecture-backend-template
status: 게시 전
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
rootTreeNode: reference:a-single-admission-point-must-count-its-bypasses
verifiedOn: # 이 기록은 이번 회차에 실행 확인을 하지 않았다
---
# 단일 admission point는 우회 경로를 세어야 성립한다
## 목적
단일 승인 지점이라는 선언을 그 지점이 실제로 유일하다는 증거로 읽는 것을 막는다.
## 규칙
1. 선언은 두 가지를 함께 주장한다
지나는 것이 전부 검사된다는 것과 모든 것이 지난다는 것이다. 코드가 보장하는 것은 대개 첫 번째뿐이다.
2. 하위 계층 타입을 직접 참조하는 곳을 센다
승인 지점이 감싸고 있는 타입을 상위 코드가 직접 부르면 그것이 우회다.
3. 임포트 목록이 빠른 지표다
어떤 패키지에서 무엇을 가져오는지 집계하면 우회 여부가 드러난다.
4. 우회가 있으면 선언을 좁히거나 경로를 막는다
둘 중 하나를 하지 않으면 다음 사람이 같은 오해를 한다.
5. 컴파일 시점에 막을 수 있으면 그렇게 한다
하위 타입을 패키지 밖에서 볼 수 없게 하면 우회 경로가 생기지 않는다.
## 적용 조건
단일 진입점이나 단일 승인 지점을 표방하는 모든 계층
정책과 실행이 분리된 구조
## 예외
성능이나 특수 목적으로 의도적으로 우회를 허용하는 경로가 있을 수 있다. 그 경우 어떤 검사가 생략되는지가 그 자리에 적혀 있어야 한다.
## 예시
명령 정책 가드가 자기를 모든 명령이 지나는 단일 승인 지점이라고 적는다. 의미 어댑터 다섯이 가드도 실행기도 타입 API 도 참조하지 않고 게이트웨이를 30 회 직접 부른다.
허가 출처 확인이 그 우회로 함께 건너뛰어진다. 가드는 애플리케이션이 허가 인터페이스를 직접 구현하는 경우까지 막도록 설계되어 있다.
## 관계
- **의미 어댑터 다섯이 gateway를 직접 불러 admission 아홉 단계를 건너뛴다**
이 규칙을 만든 사례다.
- **명령 카탈로그와 admission 아홉 단계**
우회되는 대상이다.
- **중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다**
같은 계열의 확인 규칙이다.
@@ -1,58 +0,0 @@
---
kind: REFERENCE
slug: server-metadata-defines-the-command
title: 서버 메타데이터가 명령의 정의이고 정책 파일은 허용 범위다
topic: redis-command-admission
project: clean-architecture-backend-template
status: 게시 전
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
rootTreeNode: reference:server-metadata-defines-the-command
verifiedOn: # 이 기록은 이번 회차에 실행 확인을 하지 않았다
---
# 서버 메타데이터가 명령의 정의이고 정책 파일은 허용 범위다
## 목적
정책 파일이 명령의 정의 노릇을 해서, 서버가 실제로 하는 일과 어긋난 채 허용 판정이 내려지는 것을 막는다.
## 규칙
1. 정의는 서버에서 온다
명령의 키 스펙과 플래그와 인자 구조는 서버 메타데이터가 정본이다.
2. 정책 파일은 그 위에서 범위만 정한다
무엇이 허용되고 무엇이 위험한지를 적는다. 명령이 무엇인지를 다시 적지 않는다.
3. 두 쪽의 드리프트를 검사한다
서버 버전이 올라가면 정의가 바뀔 수 있다. 정책 파일이 옛 정의 위에 서 있는지 확인하는 검사가 필요하다.
4. 그 검사를 실제로 돌린다
게이트라고 부르는 것과 빌드에 있는 것은 다르다.
5. 분류되지 않은 명령은 거부한다
카탈로그가 답하지 못하는 명령을 통과시키면 정책이 적용되지 않은 명령이 실행된다.
## 적용 조건
명령 단위로 허용 여부를 판정하는 모든 데이터 저장소 클라이언트
서버 버전에 따라 명령 정의가 달라지는 환경
## 예외
서버 메타데이터를 조회할 수 없는 구성에서는 정의를 고정할 수밖에 없다. 그 경우 고정한 버전을 명시하고, 다른 버전에 붙었을 때의 동작을 정해 둔다.
## 예시
명령 메타데이터 드리프트를 검사하는 코드가 있고 정책 파일 머리 주석이 그것을 빌드 게이트라고 부르지만, 그 검사를 실행하는 태스크도 CI 단계도 없다.
## 관계
- **명령 카탈로그와 admission 아홉 단계**
카탈로그가 승인에서 하는 역할이다.
- **build gate라 불리는 catalog drift 검사가 어디에서도 실행되지 않는다**
네 번째 규칙이 필요한 사례다.
- **분류되지 않은 명령은 fail-closed로 거부한다**
다섯 번째 규칙을 채택한 결정이다.