Files
llm-wiki/raw/branch-notes/feature-mongo-runtime-baseline-contract.md

103 KiB

title, source_type, status, branch, parent_branch, related_projects, governing_docs, tags, created, target_merge, status_label, id, kind, project, work_item, inherits, refines, overrides, depends_on, imports, delegates, accepts_delegations, contract_packet
title source_type status branch parent_branch related_projects governing_docs tags created target_merge status_label id kind project work_item inherits refines overrides depends_on imports delegates accepts_delegations contract_packet
branch / feature-mongo-runtime-baseline-contract branch-note raw feature-mongo-runtime-baseline-contract
ca-skeleton
raw/project-notes/ca-skeleton-operational-contract
branch
ca-skeleton
mongodb
persistence
change-stream
index-manifest
2026-07-28 in-progress BR-CA-SKELETON-OPERATIONAL-CONTRACT-065 project-work-item ca-skeleton-operational-contract WI-CA-SKELETON-OPERATIONAL-CONTRACT-065
DEC-CA-SKELETON-OPERATIONAL-CONTRACT-MONGO-BASELINE-001@1
DEC-CA-SKELETON-OPERATIONAL-CONTRACT-STACK-OPTIONAL-ADAPTER-001@1
WI-CA-SKELETON-OPERATIONAL-CONTRACT-060
1

branch: feature-mongo-runtime-baseline-contract

Layer: raw/branch-notes/ — 단일 브랜치의 TODO·결정·진행 기록. 머지/종료 후 verified 결과는 /ingestwiki/projects/에 추출. 원본은 raw에 영구 보관. status_label: in-progress | review | merged | abandoned 2026-07-28 /branch-spec 완료 — D1~D18(+D9-a) + §구현 가이드 10절 + §Audit 6건 작성. 근거는 공식 벤더 문서 13건(verbatim + self-grep 검증)과 ca-tmpl internal-code-fact. 착수 시점 readiness 는 R0 Contract(project note §36.1).

부모 (필수)

분해 근거: docs/superpowers/specs/2026-07-28-ca-skeleton-production-capability-feature-decomposition-design.md §4.2 — 기술 런타임 (Tier T). 본 branch 는 project §8.0 WI-CA-SKELETON-OPERATIONAL-CONTRACT-065 의 실행 단위다.

형제 branch (같은 부모의 다른 자식 — 인접 영역):

브랜치 계약 패킷

project Work Item 에서 내려온 실행 계약의 snapshot. 여기에는 pinned pointer + 1줄 요약 + branch 적용점만 쓰고 상세를 복제하지 않는다.

  • 생성 시 프로젝트 개정: 1
  • 패킷 스키마: contract_packet: 1
  • 완료 조건: concern·index manifest·replica-set 트랜잭션·change stream checkpoint test 가 통과한다

상속한 프로젝트 결정

Decision Ref Project Summary Branch Application Source
DEC-CA-SKELETON-OPERATIONAL-CONTRACT-MONGO-BASELINE-001@1 MongoDB는 read preference·read concern·write concern을 명시하고 트랜잭션과 change stream은 replica-set 요건 검증을 통과할 때만 활성화한다 concern 3축은 D5·D6·D7 이 명시 규칙으로, replica-set 요건 검증은 D8(transaction)·D11(change stream)과 §구현 가이드 4 의 공통 게이트로 구체화 raw/project-notes/ca-skeleton-operational-contract
DEC-CA-SKELETON-OPERATIONAL-CONTRACT-STACK-OPTIONAL-ADAPTER-001@1 optional adapter stack은 축마다 구현체 하나를 고정하고 core stack과 분리된 matrix로 관리한다 D1 이 Mongo 축을 boolean leaf 하나로 고정(provider 축 미승격). index 도구 축도 하나로 고정 — D13 이 자체 러너를 택하고 Mongock·Liquibase 를 명시적으로 기각 raw/project-notes/ca-skeleton-operational-contract

브랜치 지역 결정

상세 근거와 선택 조건은 아래 §결정-근거 매핑의 동일 D-row 가 소유한다. 여기에는 요약과 관계만 둔다.

Decision ID Decision Relation Supporting Claims Status
D1 활성화 축은 boolean leaf 유지 (persistence-mongo.enabled), provider 축으로 승격하지 않음 refines DEC-CA-SKELETON-OPERATIONAL-CONTRACT-STACK-OPTIONAL-ADAPTER-001@1 internal-code-fact + sibling raw/branch-notes/feature-capability-provider-selection-contract D2 proposed
D2 연결 URI 는 Spring 표준 키가 소유하되, 활성인데 URI 미설정이면 startup 거부 local internal-code-fact + MONGO-CONNSTR-C7 proposed
D3 timeout 3종·pool 2종을 드라이버 기본값에 맡기지 않고 명시 local MONGO-CONNSTR-C1~C5 proposed
D4 tls 를 연결 문자열 형식의 기본값에 맡기지 않고 명시 local MONGO-CONNSTR-C7 proposed
D5 read concern 을 연산 단위로 명시, 기본 majority · available 금지 refines DEC-CA-SKELETON-OPERATIONAL-CONTRACT-MONGO-BASELINE-001@1 MONGO-READCONCERN-C1~C12 proposed
D6 write concern 을 명시하고 wtimeout 초과를 "write 취소"로 해석하지 않음 refines DEC-CA-SKELETON-OPERATIONAL-CONTRACT-MONGO-BASELINE-001@1 MONGO-WRITECONCERN-C2~C8 proposed
D7 read preference 기본 primary, secondary 는 stale 허용 선언 경로만 refines DEC-CA-SKELETON-OPERATIONAL-CONTRACT-MONGO-BASELINE-001@1 MONGO-READPREF-C1,C3,C4,C5 proposed
D8 transaction 은 토폴로지·FCV·storage engine 검증 통과 시에만 활성화 refines DEC-CA-SKELETON-OPERATIONAL-CONTRACT-MONGO-BASELINE-001@1 MONGO-TXN-C2~C4 · MONGO-TXN-PROD-C1 proposed
D9 transaction 의 시간·크기 한계를 계약에 명시하고 무제한 사용을 전제하지 않음 local MONGO-TXN-PROD-C2~C5 proposed
D10 드라이버 retryable writes 1회 재시도 위에 애플리케이션 재시도를 중첩하지 않음 local MONGO-RETRYWRITE-C3,C5,C6 proposed
D11 change stream 은 토폴로지 검증 통과 시에만 활성화하고 resume token 을 영속화 refines DEC-CA-SKELETON-OPERATIONAL-CONTRACT-MONGO-BASELINE-001@1 MONGO-CHANGESTREAM-C1,C2,C4~C8 proposed
D12 oplog window 를 감시해 resume token 무효화 전에 경보 local MONGO-CHANGESTREAM-C7 proposed
D13 index 는 auto-index-creation 금지 + 선언적 manifest + drift 감지, 구현은 자체 IndexOperations 러너 local SD-MONGO-INDEX-C1~C3,C5 · MONGOCK-C2 · LIQUIBASE-MONGO-PRO-C1 proposed
D14 index migration runner 는 단일 실행을 보장하는 lock 을 갖는다 local MONGOCK-C3 + project note §25 Multi-Instance Guardrail proposed
D15 Mongo 실패 분류는 기존 Category enum 재사용, error code 는 신규 제안 local internal-code-fact proposed
D16 mongo 모듈에 JPA/Hibernate/Flyway/PostgreSQL 의존 금지 ArchUnit rule 신설 local internal-code-fact (CleanArchitectureTest.java:823-828) proposed
D17 same-store Mongo outbox/inbox 는 가능 조건만 소유하고 행 모델·프로토콜은 위임 local internal-code-fact + sibling 위임 proposed
D18 Mongo 쿼리 filter·document 값이 로그로 새지 않게 driver logger 를 값 미노출 레벨로 고정 local MONGO-JAVA-LOG-C1,C3~C6 proposed

선언한 예외

Override ID Overrides Reason Approval Status

가져온 프로젝트 계약

Ref Owner 요약 Branch 적용

목표

  • WI-CA-SKELETON-OPERATIONAL-CONTRACT-065 의 완료 조건을 구현한다: concern·index manifest·replica-set 트랜잭션·change stream checkpoint test 가 통과한다

  • 이슈:

  • PR:

범위

포함 범위

  • URI·topology·TLS·credential·timeout·pool 설정
  • read preference / read concern / write concern 명시 규칙
  • 트랜잭션·change stream 의 replica-set 요건 검증
  • index manifest·unique/TTL index·drift 감지·migration runner
  • change stream resume token·checkpoint 저장소와 oplog window 감시
  • same-store Mongo outbox/inbox 옵션

제외 범위

의도적으로 제외한 것. 면접 등에서 "이건 범위에 없었습니다"라고 답할 근거.

근거 (필수, 최소 1개+)

2026-07-28 수집 완료 — 13건 전부 wiki-source-summarizer 가 verbatim 인용 + self-grep 검증을 마친 official-doc 이다. 각 자료의 Usage Boundaries이 자료가 증명하지 않는 것을 명시하며, 그 gap 은 §검증해야 할 주장으로 승계했다.

Source 정당화하는 결정
raw/official-docs/mongodb-connection-string-options timeout(serverSelectionTimeoutMS/connectTimeoutMS/socketTimeoutMS)·pool(maxPoolSize/minPoolSize/maxIdleTimeMStls·retryWrites/retryReads 를 드라이버 기본값에 맡기지 않고 명시하고 env registry 로 노출한다
raw/official-docs/read-concern-mongodb-official MongoDB 조회는 read concern 을 명시하고 기본값(local implicit default)에 의존하지 않는다 — local/available/majority/linearizable/snapshot 5개 level 의 보증/비보증 차이, majority 의 replica-set·multi-document transaction 관계(write concern "majority" 커밋 조건부 보장), level별 topology/operation 제약(linearizable primary 전용, snapshot 트랜잭션 밖 find/aggregate/distinct-unsharded-only) 근거(MONGO-READCONCERN-C1~C12)
raw/official-docs/write-concern-mongodb-official MongoDB write 는 write concern 을 명시하고 기본값(w: "majority" 여부)에 의존하지 않는다 + journaling(j) / wtimeout 을 명시한다 — w/j/wtimeout 의미, implicit default, wtimeout 초과 시 write 가 rollback 되지 않는다는 실패 모드 근거
raw/official-docs/spring-data-mongodb-template-config-official D5·D6·D7 이 "concern 을 명시한다"고 결정한 것을 Spring Data MongoTemplate API 어디에 붙이는지(적용 seam) 확인 — WriteConcernResolver 가 연산 단위(remove/update/insert/save) write concern 결정 수단으로 실재함(D6 근거), ReadPreference 는 template 의 설정 가능 property 로 존재함(D7 근거). read concern 설정 수단은 이 문서에 부재(self-grep 0 매치) — D5 의 Spring Data 측 seam 은 이 자료로 닫히지 않으며 UNSUPPORTED_DECISION 후보로 승계
raw/official-docs/spring-data-mongodb-index-management-official automatic index creation 기본값(OFF, 버전 3.0+)과 explicit/programmatic index 생성 권고(IndexResolver+IndexOperations) 확인 — "auto-index-creation 에 맡기지 않는다" 결정의 부분 근거. "manifest"/"migration runner"/"drift 감지" 자체는 이 자료가 증명하지 않음 (해당 raw 문서 Usage Boundaries 참조)
raw/official-docs/read-preference-mongodb-official 조회 replica 라우팅을 read preference mode로 명시하고 secondary 읽기는 stale read 허용 경로에만 쓴다 — mode 5종 정의 + secondary 읽기 stale 경고 + maxStalenessSeconds 메커니즘 + 트랜잭션 내 read preference 제약(primary 고정) 근거. maxStalenessSeconds 의 수치 최소값 제약은 이 자료 범위 밖(별도 페이지 확인 필요, 해당 raw 문서 Usage Boundaries 참조)
raw/official-docs/change-streams-mongodb-official change stream 은 replica set/sharded cluster 요건(WiredTiger, read concern majority 지원 여부 무관)을 검증할 때만 활성화하고, resume token 을 checkpoint 저장소에 영속화하며(resumeAfter/startAfter/startAtOperationTime 3가지 재개 경로), oplog window 부족 시 resume 실패·invalidate event 발생 시 stream 종료를 감지해 startAfter 로 재개하는 계약의 근거
raw/official-docs/retryable-writes-mongodb-official Mongo write 재시도 의미를 명시한다 — 드라이버의 retryable writes 가 무엇을 보장하고 무엇을 보장하지 않는지를 계약에 적고, 애플리케이션 재시도와 겹치지 않게 한다. retryable writes 기본 활성 여부(4.2+ 호환 드라이버) + 재시도 정확히 1회 + 재시도 가능(단일 문서 연산, acknowledged write concern)/불가능(w:0, multi-document update/delete, 트랜잭션 내부 개별 write) 연산 목록 + replica-set/sharded-cluster 배포 요건(standalone 불가) 근거
raw/official-docs/transactions-mongodb-official multi-document transaction 은 replica-set/sharded 요건 검증을 통과할 때만 활성화하고(FCV Replica Set≥4.0/Sharded Cluster≥4.2, primary WiredTiger 요건, writeConcernMajorityJournalDefault:false shard 배제) + transaction 은 시간·크기 한계를 가지므로 무제한 사용을 전제하지 않는다(runtime limit 이 공식 usage consideration 으로 인정됨 — 단 구체 수치는 별도 Production Considerations 페이지, 이 자료 범위 밖) 근거. 부수적으로 transaction 내 read concern(기본 "local")/write concern(기본 w:"majority"/w:1") 결정 체인 근거
raw/official-docs/transactions-production-considerations-mongodb-official (부분) transaction 은 시간·크기 한계를 가지므로 무제한 사용을 전제하지 않고, 한계 초과 시 동작을 계약에 명시한다 — runtime limit 기본값("less than one minute", transactionLifetimeLimitSeconds 초과 시 periodic cleanup 에 의한 abort)과 oplog entry 크기 한계(transaction 전체 아닌 entry 단위 16MB) 근거. TransientTransactionError/UnknownTransactionCommitResult 라벨 기반 재시도 계약은 이 자료로 정당화되지 않음 — 두 라벨 모두 이 URL 에 부재(self-grep 0 매치), 별도 raw 자료 필요(UNSUPPORTED_DECISION 후보)
raw/official-docs/liquibase-mongodb-pro-drift-report-official MongoDB index drift 감지를 Liquibase 로 얻지 않고 자체 러너로 구현한다 — Liquibase 의 MongoDB drift report 접근이 Liquibase MongoDB Pro extension(유료) 기능 목록에 명시된다는 근거(LIQUIBASE-MONGO-PRO-C1, C2). 주의: 무료(OSS) extension 에 drift 가 전혀 없다는 부정 명제는 이 자료가 직접 증명하지 않음(해당 raw 문서 Usage Boundaries 참조) — "무료 티어 미충족"을 최종 결정 근거로 쓰려면 이 gap 을 D-row 에 needs-confirmation 으로 명시할 것
raw/official-docs/mongock-migration-lock-maintenance-official index manifest 적용 + drift 감지를 Mongock 이 아니라 Spring Data IndexOperations 기반 자체 러너로 구현한다 — Mongock 미채택 근거(신규 개발이 후속 프로젝트 Flamingock 으로 이전, critical bug fix/security update 만 지속)와 채택 시 이점(멀티 인스턴스 동시 실행 방지 DB 영속 pessimistic lock 내장)을 모두 인지한 trade-off 근거(MONGOCK-C1~C4)
raw/official-docs/java-driver-logging-mongodb-official MongoDB 쿼리 filter·document 값이 로그로 새지 않게 억제한다(D18 후보, §엣지·실패·의존 표에 이미 전방 참조된 결정) — 어느 logger(org.mongodb.driver.protocol/하위 org.mongodb.driver.protocol.command)가 command 내용을 어느 레벨(DEBUG)로 남기는지, SLF4J 바인딩 설정으로 logger 이름 단위 레벨을 조정하는 방법, maxDocumentLength()(기본 1000자)로 로그 메시지 길이를 제한할 수 있으나 이는 truncation 이지 필드 마스킹이 아니라는 것의 근거(MONGO-JAVA-LOG-C1~C6)

프로젝트 내부 설계 참조 (등급 internal-design-doc — 공식 문서 아님, best practice 로 격상 금지):

  • llm-wiki docs/superpowers/specs/2026-07-28-ca-skeleton-production-capability-feature-decomposition-design.md §4.2 #6
  • ⚠️ ca-tmpl docs/superpowers/specs/2026-07-26-production-capability-platform-design.md (§12.3) — 저장소에 존재하지 않음(§Audit A3). 본 branch 의 D-row 는 이 문서를 인용하지 않으며, 모든 근거는 위 공식 벤더 문서 13건 또는 internal-code-fact 다.

TODO

각 항목 옆에 증거 등급 표기: actually-implemented | locally-verified | prod-verified | documented-only | planned | needs-confirmation

  • /branch-spec 로 D-row(D1~D18)·§구현 가이드 10절·§Audit 6건 작성 — 등급: actually-implemented (문서 작업)

선행 — 자료 수집 5건 (되돌릴 코드를 먼저 쓰지 않기 위해 착수 앞에 둔다):

  • Mongock v5 기능/lock 페이지 + Liquibase 무료 OSS extension 기능 목록 — D13 기각 논리 확정용. D13·D14 코드보다 먼저 — 등급: planned
  • oplog window 측정 수단 공식 자료 — D12 코드보다 먼저 — 등급: planned
  • Spring Data / 드라이버의 read concern 적용 API — §구현 가이드 2-1 의 미확정 seam. D5 코드보다 먼저 — 등급: planned
  • MongoDB Java driver transactions 에러 처리(재시도 라벨) — D9-a 확정용. 대응 구현 TODO 없음 → 순서 제약 없음 — 등급: planned
  • MongoDB TTL index 만료 정밀도 · unique index 기존 데이터 실패 — §구현 가이드 6 의 lock 후보 (a)(unique+TTL 컬렉션)를 채택한다면 D14 코드보다 먼저 (TTL 만료 지연이 lock 안전성의 전제) — 등급: planned

구현:

  • 연결 계약 — URI 필수화 + timeout·pool·tls 명시 (D2·D3·D4) — 등급: planned
  • concern 3종 명시 규칙 (D5·D6·D7 · §구현 가이드 2-1) — 등급: planned
  • 토폴로지 검증 게이트 (D8·D11 · §구현 가이드 4) — 등급: planned
  • 쿼리·document 값 로그 유출 억제 (D18 · §구현 가이드 8) — 등급: planned
  • ArchUnit rule 신설 (D16) — 등급: planned
  • Mongo 실패 매핑 registry 신규 제안 (D15) — 등급: planned
  • change stream checkpoint + oplog window 감시 (D11·D12) — 등급: planned
  • index manifest + migration runner + drift (D13·D14) — 등급: planned
  • 로컬 replica-set 컨테이너 + 통합 test — 완료 조건 검증 — 등급: planned

진행 중 메모

  • 2026-07-28: 이 branch 착수 시점의 ca-tmpl 상태는 R0 Contract 다 — 모듈은 있으나 wiring 뿐이고, 연결 URI 조차 어디에도 설정돼 있지 않다(§Audit A1). "opt-in 설정만 존재" 라는 project note §34 표기는 정확하다.
  • 근거 수집은 MongoDB 공식 9건 + Spring 2건 + 도구 2건(Mongock·Liquibase) = 13건. 전부 verbatim 인용 + self-grep 검증을 거쳤다. (2회차 게이트 반영으로 Spring Data template config · MongoDB Java driver logging 2건 추가.)
  • 수집 과정에서 부재를 부재로 기록한 항목이 여러 개 있다(transactionLifetimeLimitSeconds 정수값, TransientTransactionError 라벨, maxStalenessSeconds 하한). 이 값들을 추측해 채우지 않았고 §검증해야 할 주장으로 승계했다.

결정 사항

Decision Evidence Map / 결정-근거 매핑

Supporting Claimsraw/...#Cn 은 verbatim 인용 + self-grep 검증을 마친 claim. internal-code-fact 는 ca-tmpl 코드를 직접 읽어 확인한 사실(경로·행 명시). 외부 공식 근거가 없는 결정은 UNSUPPORTED_DECISION 으로 라벨한다 — 추측으로 채우지 않는다.

근거의 두 축을 섞지 않는다. MongoDB 공식 문서가 증명하는 것은 메커니즘·기본값(드라이버·서버가 어떻게 동작하는가)이고, 정책(그래서 우리는 무엇을 금지·강제하는가)은 대부분 내부 결정이다. 각 행의 Evidence Strength 가 이 경계를 표시한다.

Decision ID Decision 선택 조건 (언제 이 결정 / 언제 대안) Supporting Claims Evidence Strength Open Risk
D1 Mongo capability 의 활성화 축은 boolean leaf 로 유지한다 — ca-skeleton.persistence-mongo.enabled. provider 축(provider: disabled|<id>)으로 승격하지 않는다 구현체 대안이 없고 켜고 끄는 것 외 선택지가 없음 → boolean (현행 유지). 관리형 Mongo/DocumentDB 등 provider 대안이 2개 이상 생기면 → provider 축으로 이관하고 그때 breaking rename 을 감수. 두 축 동시 보유는 금지 internal-code-fact: adapter/outbound/persistence-mongo/.../MongoPersistenceConfig.java:33-36 (@ConditionalOnProperty(prefix="ca-skeleton.persistence-mongo", name="enabled", havingValue="true"), matchIfMissing 미지정), MongoPersistenceSettings.java:23 (enabled=false), app-bootstrap/.../application.yml:336-338. sibling: raw/branch-notes/feature-capability-provider-selection-contract D2(축 단일화)·D4(matchIfMissing=true 금지 — 본 모듈은 미지정이므로 이미 준수) 정책 internal-policy (sibling 결정 상속) / 현행 internal-code-fact prefix 통일(sibling D3)이 app.* 로 확정되면 ca-skeleton.persistence-mongo.* 는 rename 대상이 된다. 본 branch 는 축만 고정하고 prefix 문자열은 sibling 이 소유 — 두 결정이 다른 PR 로 나뉘면 이행 창에 키가 둘로 갈린다
D2 연결 URI 는 Spring 표준 spring.data.mongodb.uri 가 계속 소유한다(모듈 Settings 로 옮기지 않음). 단 capability 가 활성인데 URI 가 미설정이면 startup 을 거부한다 URI 는 운영자가 이미 아는 표준 키 → Spring 소유 유지. 모듈이 URI 를 자체 property 로 재정의 → 키가 둘이 되어 verifyEnvKeys 3-way drift 검사(sibling env-driven D7)를 통과할 수 없으므로 선택 안 함. 미설정 시 조용한 기본값 사용은 어느 조건에서도 선택하지 않는다 internal-code-fact: MongoPersistenceSettings.java:10-13 이 URI 미모델링을 의도적 결정으로 주석에 명시. 그러나 spring.data.mongodb.*application.yml·src/.env(126행) 어디에도 존재하지 않음(grep 0건). → 플래그를 켰을 때 드라이버/Spring 기본 URI 로 연결을 시도하는지, 아니면 Spring 이 먼저 실패시키는지는 needs-confirmation — 수집한 13건 중 Spring Boot MongoProperties 기본값을 다루는 자료가 없다(§검증해야 할 주장 — 플래그를 켰을 때 기본 URI 로 붙는지). 어느 쪽이든 "설정하지 않은 채 활성화" 가 유효한 상태가 아니라는 점은 같으므로 D2 의 거부 정책은 성립한다. MONGO-CONNSTR-C7: tls 기본값이 연결 문자열 형식마다 다르므로(SRV=true / Standard=false) URI 문자열 자체가 보안 결정을 담는다. 실패 코드는 기존 STARTUP_VALIDATION_FAILED(error-codes.yaml:841, owner feature-migration-startup-contract) 재사용 internal-code-fact + 메커니즘 official-vendor-doc(C7) / 거부 정책 internal-policy 이 gap 은 현재 실재한다 — §Audit A1 참조. env-keys.yaml 에 mongo row 가 0개라 verifyEnvKeys 도 이 부재를 잡지 못한다. registry 등록이 선행돼야 startup 검증이 성립한다
D3 timeout 3종(serverSelectionTimeoutMS·connectTimeoutMS·socketTimeoutMS)과 pool 2종(maxPoolSize·minPoolSize)을 드라이버 기본값에 맡기지 않고 명시한다 운영 환경(dev/staging/prod) → 5개 전부 명시 필수. 로컬 단일 개발자 실행 → 기본값 허용하되 그 사실을 프로파일에 명시. socketTimeoutMS 만은 어느 환경에서도 명시한다 — 기본값이 무제한이라 미명시 = 무한 대기 MONGO-CONNSTR-C3(raw/official-docs/mongodb-connection-string-options.md#MONGO-CONNSTR-C3 — "The time in milliseconds to attempt a send or receive on a socket before the attempt times out. The default is no timeout, though different drivers might vary."), C1(serverSelection 기본 30,000ms), C2(connect 기본 10,000ms, 드라이버별 상이), C4(maxPoolSize 기본 100), C5(minPoolSize 기본 0) 기본값 official-vendor-doc / 명시 정책 internal-policy 값 자체는 본 branch 소유가 아니다 — sibling raw/branch-notes/feature-database-connection-pool-contract 가 Hikari 값을 feature-env-driven-runtime-configuration 에 위임한 선례와 동일하게, 본 branch 는 "명시 대상 키 집합"만 고정하고 수치는 env-driven 이 소유한다. maxIdleTimeMS 는 원문에 숫자 기본값이 없어(C6) 명시 대상에서 제외 — 필요해지면 별도 결정
D4 tls 를 연결 문자열 형식의 암묵적 기본값에 맡기지 않고 항상 명시한다 prod/staging → tls=true 명시. 로컬 docker → tls=false명시(생략 금지). SRV 형식이라 "어차피 true" 라는 이유로 생략하는 것은 선택하지 않는다 MONGO-CONNSTR-C7(#MONGO-CONNSTR-C7tls 기본값이 SRV 형식은 true, Standard 형식은 false). 즉 연결 문자열 형식을 바꾸면 TLS 여부가 조용히 뒤집힌다 메커니즘 official-vendor-doc / 명시 정책 internal-policy URI 는 secret 분류 대상(자격증명 포함)이라 secrets-classification.yaml row 가 필요한데 현재 0건 — owner 는 raw/branch-notes/feature-secrets-config-source-contract. 본 branch 는 신규 제안만 하고 등록은 그 branch 절차를 따른다
D5 조회는 read concern 을 연산 단위로 명시하고 기본은 majority 로 한다. available 은 금지, linearizable·snapshot 은 제약 충족 시에만 정확성이 필요한 업무 조회 → majority. 오래된 데이터를 감수해도 되는 대량 분석/근사 조회 → local명시적 opt-in 으로만. 단일 document 를 고유 식별하는 강한 읽기 → linearizable(primary 전용). 트랜잭션 또는 find/aggregate/distinct(unsharded) 의 시점 고정 조회 → snapshot. sharded collection 조회 → available 금지 MONGO-READCONCERN-C2(raw/official-docs/read-concern-mongodb-official.md#MONGO-READCONCERN-C2local 이 "Default for reads against the primary and secondaries"), C1(local 은 과반수 기록 보장 없음 · "Data may be rolled back"), C4(majority 는 "Returned documents are durable, even if a failure occurs"), C5(majority 는 WiredTiger 요건), C3(available 은 sharded 조회에서 orphaned document 반환), C7/C8(linearizable 은 primary + 단일 document 식별 필터일 때만), C9~C11(snapshot 의 범위·연산 제한), C6(트랜잭션 안의 majority 는 write concern "majority" 커밋일 때만 보장) official-vendor-doc — level 별 보증/제약은 전부 벤더 진술. "기본을 majority 로" 라는 선택 자체는 internal-policy C6/C10 때문에 read concern 단독으로는 트랜잭션 안에서 보증이 성립하지 않는다 — D6 의 write concern 결정과 쌍으로만 유효하다. 두 결정을 따로 적용하면 트랜잭션 경로에서 보증이 조용히 사라진다
D6 write 는 write concern 을 명시하고, wtimeout 초과를 "write 취소"로 해석하지 않는다. 트랜잭션 내부 개별 write 에는 write concern 을 설정하지 않는다 업무 write → w:"majority" 명시. 유실 감수 가능한 보조 write → 낮은 w명시적 opt-in. j 는 배포의 journaling 정책에 따라 선언. wtimeout 은 명시하되 초과 시 재시도는 멱등성이 보장된 연산에만 허용 MONGO-WRITECONCERN-C7(raw/official-docs/write-concern-mongodb-official.md#MONGO-WRITECONCERN-C7 — "When these write operations return, MongoDB does not undo successful data modifications performed before the write concern exceeded the wtimeout time limit"), C6(한계 초과 시 "even if the required write concern will eventually succeed" write concern error 반환), C5(wtimeout 은 primary 성공 전파 시간 제한), C3(majority 의미), C4(j 의미), C8(implicit default 가 {w:"majority"}), MONGO-TXN-C7(트랜잭션 내부 개별 write 에 write concern 설정 시 에러) official-vendor-doc — 특히 C7 은 실패 해석의 핵심 벤더 진술 C8 이 "implicit default 가 이미 majority" 라고 말하므로 명시가 무의미해 보일 수 있으나, 배포가 CWWC(cluster-wide write concern)를 바꾸면 기본값이 달라진다 — 이 branch 가 명시를 요구하는 이유이나 CWWC override 메커니즘 자체는 이번 회차에서 조사하지 않았다(비존재 단정 아님)
D7 조회의 replica 라우팅은 read preference 로 명시하고 기본은 primary, secondary 읽기는 stale 을 허용한다고 선언한 경로에만 허용한다 기본/미지정 조회 → primary. stale 감수를 선언한 조회 → secondaryPreferred + maxStalenessSeconds 명시. read 를 포함한 트랜잭션 → primary 강제(선택지 없음). nearest 는 지연 최적화가 정확성보다 중요한 경로에만 MONGO-READPREF-C1(raw/official-docs/read-preference-mongodb-official.md#MONGO-READPREF-C1 — primary 가 default), C3("All read preference modes except primary may return stale data ... Ensure that your application can tolerate stale data"), C4(maxStalenessSeconds 로 지연 상한 지정), C5("Transactions that contain read operations must use read preference primary"), C2/C6/C7/C8(mode 별 fallback 동작) official-vendor-doc(메커니즘·제약) / "언제 stale 을 허용하는가" 는 internal-policy ReadConsistency 정책 → 라우팅 판정 매핑은 본 branch 소유가 아니다raw/branch-notes/feature-read-consistency-query-contractDEC-…-READ-CONSISTENCY-001@1 의 owner 다. 본 branch 는 Mongo 측 표현 수단(mode·maxStalenessSeconds)만 고정한다. 또한 maxStalenessSeconds수치 하한은 미확보(해당 raw 의 Usage Boundaries — 별도 페이지)
D8 multi-document transaction 은 토폴로지·FCV·storage engine 검증을 통과할 때만 활성화한다. standalone 배포에서는 활성화 자체를 거부한다 여러 document/collection 에 걸친 원자성이 실제로 필요 → transaction 활성화 + 기동 시 요건 검증. 단일 document 로 모델링 가능 → transaction 을 쓰지 않는다(이미 원자적). 요건 미충족 배포 → STARTUP_VALIDATION_FAILED 로 기동 거부(조용한 비활성 아님) MONGO-TXN-PROD-C1(raw/official-docs/transactions-production-considerations-mongodb-official.md#MONGO-TXN-PROD-C1 — "MongoDB standalone deployments do not support transactions. To use transactions, your deployment must be a multiple node replica set."), MONGO-TXN-C2(FCV — Replica Set ≥4.0 / Sharded Cluster ≥4.2), C3(primary WiredTiger, secondary WiredTiger 또는 in-memory), C4(writeConcernMajorityJournalDefault:false shard 가 있는 sharded cluster 에서 실행 불가), C1("In MongoDB, an operation on a single document is atomic" — transaction 이 많은 경우 불필요) official-vendor-doc(요건) / 기동 거부 정책 internal-policy 검증 시점은 sibling raw/branch-notes/feature-capability-provider-selection-contract D6(refresh 완료 , SmartInitializingSingleton)을 상속해야 한다 — 본 branch 가 별도 시점을 정의하면 startup 검증이 두 곳으로 갈린다. FCV·storage engine 을 런타임에 어떤 명령으로 질의할지는 미정 — §구현 가이드 4 의 UNSUPPORTED_IMPL_DECISION
D9 transaction 의 시간·크기 한계를 계약에 명시하고 무제한 사용을 전제하지 않는다 기본 → 1분 미만 runtime 을 전제로 트랜잭션 범위를 설계. 1분을 넘길 수밖에 없는 배치성 작업 → transaction 이 아니라 분할 + 멱등 재시도로 설계(파라미터 상향은 마지막 수단). 대량 write → oplog entry 당 16MB 한계를 설계 제약으로 취급 MONGO-TXN-PROD-C2(#MONGO-TXN-PROD-C2 — "By default, a transaction must have a runtime of less than one minute. You can modify this limit using transactionLifetimeLimitSeconds" + "Transactions that exceeds this limit are considered expired and will be aborted by a periodic cleanup process."), C3(전체 16MB 한계는 제거됐으나 개별 oplog entry 는 여전히 16MB BSON 한계), C4(TransactionTooLargeForCache 에러와 함께 abort), C5("When you encounter an error during individual operation in the transaction, abort and retry the transaction.") official-vendor-doc — 단 정확한 기본 정수 초는 원문에 없음("less than one minute" 서술만). "60초" 라고 적지 않는다 TransientTransactionError / UnknownTransactionCommitResult 라벨 기반 재시도 계약은 근거 미확보 — 두 라벨 모두 해당 URL 에 self-grep 0 매치. 아래 D9-a 로 분리해 UNSUPPORTED_DECISION 라벨 유지
D9-a 트랜잭션 재시도 책임(어떤 에러 라벨에서 트랜잭션 전체를 재시도할 것인가)을 애플리케이션 계약으로 못박는다 (선택 조건 미확정 — 근거 확보 후 작성) 조사 범위 내 미확보MONGO-TXN-PROD-C5 는 "에러 시 abort 후 retry" 라는 사후 대응 권고만 제공하고 라벨 이름을 주지 않는다. TransientTransactionError·UnknownTransactionCommitResult 는 해당 URL 에 부재(grep 0 매치, 비존재 단정 아님 — 드라이버별 에러 처리 페이지 미조사) UNSUPPORTED_DECISION 라벨 없이 재시도 조건을 코드에 박으면 "어떤 에러에서 재시도해야 하는가" 를 구현자가 임의로 정하게 된다. 착수 전 별도 dispatch 1건(MongoDB Java driver transactions 에러 처리 페이지)으로 닫는 것이 권고
D10 드라이버의 retryable writes(기본 1회 재시도) 위에 애플리케이션 재시도를 중첩하지 않는다. 재시도가 필요한 경로는 멱등성을 스스로 보장한다 단일 document write → 드라이버 재시도에 위임(추가 재시도 없음). updateMany/deleteMany 등 multi-document write → 드라이버가 재시도하지 않으므로 멱등 설계 + 명시적 재시도가 필요. w:0 → 재시도 대상이 아니므로 업무 write 에 사용 금지. 트랜잭션 내부 write → 개별 재시도가 없으므로 트랜잭션 전체 재시도(D9-a 소관) MONGO-RETRYWRITE-C3(raw/official-docs/retryable-writes-mongodb-official.md#MONGO-RETRYWRITE-C3 — "By default, MongoDB retries writes once. One retry attempts to address transient network errors and replica set elections, but not persistent network errors."), C5(w:0updateMany/deleteMany 는 재시도 불가), C6(트랜잭션 내부 write 는 개별 재시도 없음, commit/abort 는 retryWrites 와 무관하게 1회 재시도), C4(재시도 대상 = acknowledged write concern + 단일 document 연산), C1(standalone 미지원), C2(4.2+ 드라이버 기본 활성), C7(6.1+ NoWritesPerformed 라벨) official-vendor-doc(재시도 의미) / 중첩 금지 정책 internal-policy 기본이 true(MONGO-CONNSTR-C8)라 아무도 결정하지 않아도 재시도가 이미 일어나고 있다 — 이 사실을 모르는 상태에서 애플리케이션 재시도를 추가하면 실제 시도 횟수가 2배가 된다. D3 의 명시 대상 키에 retryWrites 를 포함할지는 §구현 가이드 2 에서 다룬다
D11 change stream 은 토폴로지 검증을 통과할 때만 활성화하고, resume token 을 checkpoint 저장소에 영속화한다. invalidate 이후 재개는 startAfter 로 한다 replica set / sharded cluster + WiredTiger → 활성화 허용. standalone → 활성화 거부. 정상 재개 → resumeAfter(저장된 token). invalidate 발생 후 재개 → startAfter(resumeAfter 는 invalidate 이후 재개 불가). token 이 없는 최초 기동 → startAtOperationTime MONGO-CHANGESTREAM-C1(raw/official-docs/change-streams-mongodb-official.md#MONGO-CHANGESTREAM-C1 — "Change streams are available for replica sets and sharded clusters"), C2(WiredTiger 요건), C4(resumeAfter), C5("Unlike resumeAfter , startAfter can resume notifications after an invalidate event"), C6(startAtOperationTime 은 oplog 시간 범위 안이어야 함), C8(cursor 종료 4조건 — 명시적 close / invalidate / 연결 종료·timeout / shard 제거), C3(read concern majority 지원 여부와 무관하게 사용 가능) official-vendor-doc checkpoint 저장소 선택(same-store Mongo 컬렉션 vs 별도 store)은 근거 없음 → §구현 가이드 5 의 UNSUPPORTED_IMPL_DECISION. 또한 checkpoint 저장이 이벤트 처리와 원자적이지 않으면 at-least-once 가 되며, 이 보증 등급은 project note §11 의 durable 경로 정책과 정합돼야 한다
D12 oplog window 를 감시해 resume token 이 무효화되기 전에 경보한다 change stream 을 활성화한 배포 → 감시 필수. 비활성 배포 → 해당 없음. 경보 임계는 "남은 oplog 시간 < 소비자 최대 다운타임 허용치" 로 정의 MONGO-CHANGESTREAM-C7(#MONGO-CHANGESTREAM-C7 — "The oplog must have enough history to locate the operation associated with the token or the timestamp, if the timestamp is in the past.") — 즉 oplog 가 롤오버되면 저장해 둔 token 으로 재개할 수 없다 위험 근거 official-vendor-doc / 임계값·metric 이름은 internal-policy metric 이름·임계값은 신규 제안이다 — metrics.yaml 에 mongo row 가 0건이고 registry owner 절차(sibling raw/branch-notes/feature-contract-registry-governance)를 거쳐야 한다. 본 branch 단독으로 확정 불가
D13 index 는 automatic index creation 에 맡기지 않고 선언적 manifest + 적용 러너 + drift 감지로 관리하며, 구현은 자체 IndexOperations 러너로 한다(Mongock·Liquibase 미채택) drift 감지가 1급 요구사항이고 Spring Boot 4 호환 리스크를 없애야 함 → 자체 러너(기본). changelog 이력·rollback 추적이 drift 보다 중요 → Mongock 을 시한부로 채택하되 EOL 을 계약에 명시. 조직이 이미 Liquibase Pro 라이선스 보유 → Liquibase-mongodb Pro SD-MONGO-INDEX-C1(raw/official-docs/spring-data-mongodb-index-management-official.md#SD-MONGO-INDEX-C1 — "Automatic index creation is turned OFF by default as of version 3.0"), C2("index creation must be explicitly enabled since version 3.0 to prevent undesired effects on collection lifecycle and performance"), C3(programmatic 생성이 "(Recommended)" 로 표기, IndexResolver+IndexOperations), C5("Explicit index creation provides better control than automatic creation"). 대안 기각 근거MONGOCK-C2(raw/official-docs/mongock-migration-lock-maintenance-official.md#MONGOCK-C2 — "Mongock will continue receiving critical bug fixes and security updates only. All innovation is happening in Flamingock."), LIQUIBASE-MONGO-PRO-C1(raw/official-docs/liquibase-mongodb-pro-drift-report-official.md#LIQUIBASE-MONGO-PRO-C1 — drift report 접근이 Pro 기능 목록에 포함) 채택 근거 official-vendor-doc / 기각 근거 official-vendor-doc(EOL·Pro gating) + needs-confirmation 기각 논리에 gap 이 있다 — Liquibase 자료는 "Pro 에 drift 가 있다" 를 증명할 뿐 "무료 OSS extension 에 drift 가 없다" 는 부정 명제를 직접 증명하지 않는다(해당 raw 의 Usage Boundaries). Mongock 역시 "drift 기능이 없다" 가 아니라 "이 페이지에서 확인되지 않음" 이다. 따라서 기각은 needs-confirmation 이며 §검증해야 할 주장 2행으로 승계한다. manifest 포맷·diff 알고리즘은 §구현 가이드 6 의 UNSUPPORTED_IMPL_DECISION
D14 index migration runner 는 단일 실행을 보장하는 lock 을 갖는다 multi-instance 배포 → lock 필수. 단일 인스턴스 로컬 → lock 없이 실행 허용하되 그 사실을 명시. lock 획득 실패 → 기동 거부가 아니라 대기 후 실패(다른 인스턴스가 적용 중일 수 있음) MONGOCK-C3(#MONGOCK-C3 — "As more than one instance of the client-service may be running simultaneusly in the environment [...] Mongock uses a pesimistic lock that is persisted in database") — 기성 도구도 이 문제를 DB 영속 lock 으로 푼다는 벤더 확인. project note §25 Multi-Instance Guardrail("migration runner: one app startup runner / multi-instance 활성화 시 migration lock 검증 필요"). sibling: raw/branch-notes/feature-distributed-lock-contract 가 migration runner lock 을 자기 범위 밖으로 선언 → 범용 DistributedLockPort 재사용 아님 문제 실재 official-vendor-doc / lock 메커니즘 선택 internal-policy lock 구현 수단(unique index + TTL 컬렉션)은 근거 없음 → §구현 가이드 6 의 UNSUPPORTED_IMPL_DECISION. 특히 TTL index 의 만료 정밀도가 lock 안전성에 미치는 영향은 미조사 → §검증해야 할 주장 — lock 컬렉션 TTL 만료 정밀도
D15 Mongo 실패 분류는 기존 Category enum 10종을 재사용하고, error code 는 기존 DB_* 를 재사용하지 않고 신규 제안한다 실패가 기존 category 의미에 들어맞음 → 재사용(TRANSIENT_DEPENDENCY/CONFLICT/DATA_INTEGRITY/INTERNAL). code 는 기존 DB_*SQLState 기반이라 Mongo 에 매핑되지 않음 → 신규 code 제안. 기존 code 를 의미 확장해 재사용하는 것은 선택하지 않는다(owner 가 다른 branch) internal-code-fact: shared-contract/.../shared/error/Category.java:11-20(enum 10종), docs/registries/error-codes.yamlDB_UNAVAILABLE(L231)~DB_QUERY_CANCELED(L343) 9종이 전부 owner_branch: feature-persistence-failure-baseline 이고 주석이 SQLState 매트릭스(08*, 40001, 40P01 …) 출처를 명시. mongo grep 0건. 선례: sibling raw/branch-notes/feature-integration-adapter-templatesADAPTER_DISABLED신규 code 로 만든 근거(startup lifecycle ≠ runtime lifecycle 혼동 방지) internal-code-fact 본 branch 는 registry 소비자이자 신규 제안자다. code 이름·retryable·http_status 확정은 feature-contract-registry-governance 의 변경 절차를 거쳐야 하며 여기서 단독 확정할 수 없다 — §구현 가이드 3 은 제안 표로만 둔다
D16 mongo 모듈이 JPA/Hibernate/Flyway/PostgreSQL 타입에 의존하지 못하게 하는 ArchUnit rule 을 신설한다 NoSQL adapter 모듈이 존재하는 한 → rule 필수. 모듈이 제거되면 → rule 도 함께 제거 internal-code-fact: app-bootstrap/src/test/java/.../architecture/CleanArchitectureTest.java:823-828 — "Future NoSQL adapter modules (for example adapter-persistence-mongodb) must be added as sibling modules ... When such a module exists, add an ArchUnit rule forbidding jakarta.persistence.., org.hibernate.., org.springframework.data.jpa.., org.flywaydb.., and dev.caskeleton.adapter.outbound.persistence.postgresql.. dependencies from that module." 그 모듈은 이미 존재하나(modules.yaml:202-212) rule 은 미작성(mongo grep = 이 주석 1건뿐) internal-code-fact — 코드 주석이 조건과 대상 패키지를 명시적으로 지정 rule 이 없는 동안 mongo 모듈이 JPA 타입을 import 해도 빌드가 막지 않는다. 단 src/build.gradleallowedProjectDependencies 가 프로젝트 의존만 통제하므로(modules.yaml:207 = [application-core, shared-contract]) 외부 라이브러리 import 는 현재 무방비다
D17 same-store Mongo outbox/inbox 는 본 branch 가 가능 조건(어떤 요건이 충족돼야 Mongo 에 둘 수 있는가)만 소유하고, 행 모델·상태 머신·프로토콜은 소유하지 않는다 Mongo 가 업무 store 이고 D8 트랜잭션 게이트를 통과 → same-store outbox 가능. 트랜잭션 요건 미충족 → 불가(append 원자성이 성립하지 않음). 행 모델·dispatch 모드 → raw/branch-notes/feature-outbox-dispatch-mode-contract. owner token 프로토콜 → raw/branch-notes/feature-idempotency-ownership-protocol-contract internal-code-fact: 현행 adapter/outbound/persistence-mongo/CLAUDE.md 가 "does not reimplement idempotency / outbox / lock on Mongo (those stay JPA-only)" 로 명시 금지. project note §11 "outbox append → 업무 트랜잭션 롤백"(append 는 업무 write 와 원자) → Mongo same-store 는 D8 게이트에 종속. MONGO-TXN-C1(단일 document 는 이미 원자적) internal-code-fact + internal-policy(project note §11 상속) 현행 모듈 CLAUDE.md 의 금지를 해제하려면 그 파일을 고쳐야 하는데, 이는 ca-tmpl 측 변경이다. 본 branch 는 해제 조건만 정의하고 실제 해제는 outbox branch 착수 시점에 이뤄진다 — 두 문서가 어긋난 채 방치되면 다음 작업자가 "금지인가 허용인가" 를 되묻게 된다
D18 Mongo 쿼리 filter·document 값이 로그로 새지 않게 driver logger 를 값 미노출 레벨로 고정한다 — 관계형 계약의 "SQL/parameter 로그 금지" 에 대응하는 Mongo 측 규칙 운영 프로파일 → org.mongodb.driver.protocol.command 를 DEBUG 미만으로 고정(값 노출 차단). 로컬 디버깅 → DEBUG 허용하되 운영 데이터가 없는 환경에서만. 진단 목적으로 운영에서 DEBUG 가 필요 → LoggerSettings.maxDocumentLength 축소 + 한시적 활성화 + 종료 시각 명시 MONGO-JAVA-LOG-C3(raw/official-docs/java-driver-logging-mongodb-official.md#MONGO-JAVA-LOG-C3org.mongodb.driver.protocol.commandDEBUG 레벨로 command 시작/성공 기록), C4(그 DEBUG 라인의 Command: 필드에 command document 전체가 그대로 남으며 예시에 filter 키 포함), C1(org.mongodb.driver.protocol = "Commands sent to and replies received"), C2(org.mongodb.driver.connection 은 별개 관심사 — 연결/pool 은 값을 담지 않으므로 함께 끄지 않아도 됨), C5(LoggerSettings.maxDocumentLength() 기본 1000자), C6(logger 이름 단위 레벨 조정). governing doc §11 Persistence "SQL/parameter 로그 금지" 의 Mongo 대응 official-vendor-doc(무엇이 어느 레벨에 남는가) / 금지 정책 internal-policy(project note §11 상속) maxDocumentLength 기본값이 1000자라 축소해도 값의 앞부분은 남는다 — 길이 제한은 유출 완화이지 차단이 아니다. 차단은 레벨 고정으로만 성립한다. 또한 raw/branch-notes/feature-log-management-contract D1 의 masking 계층은 구현돼 있으나(internal-code-fact: logback-spring.xml:45-46,:81 + SecretMaskingMessageConverter) LogMaskingPatterns 카탈로그 기반 고정 패턴이라 부분만 덮는다 — 카탈로그 키(password/passwd/pwd/secret/token/api_key/access_token/refresh_token/client_secret + authorization 헤더 + 독립 bearer)에 해당하는 filter 필드 값은 실제로 마스킹되지만, 그 외 임의 업무 필드 값은 덮이지 않는다. 부분 커버리지는 "마스킹되니 안전하다" 는 오해를 만들기 때문에 오히려 위험하다 — 값 차단은 레벨 고정으로만 성립한다. 잔여 미검증 채널은 §구현 가이드 8 의 "덮지 않는 채널" 표 참조

구현 가이드

3-rule meta principle 적용 — R1 각 sub-section 은 Decision ID + Supporting Claim ID reference, R2 근거 없는 detail 은 UNSUPPORTED_IMPL_DECISION + trade-off 한 줄, R3 본 branch 결정 범위 밖은 이관.

코드 위치 표기: ca-tmpl repo 기준 상대 경로. 본 branch 는 계약 SSOT 이고 실제 코드 작성은 ca-tmpl plan 이 소유한다 — 아래 클래스명·경로는 코드로 확인된 것만 actually-implemented 로 표기했고 나머지는 planned 다.

1. 현행 as-built 와 이 branch 가 바꾸는 것

Trace: D1(활성화 축) · D2(URI 소유) · D16(ArchUnit) — 전부 internal-code-fact

항목 현행 상태 등급 본 branch 후
모듈 존재 adapter/outbound/persistence-mongo (소스 2개: MongoPersistenceConfig·MongoPersistenceSettings) actually-implemented 유지
opt-in gate MongoPersistenceConfig.java:33-36matchIfMissing 미지정(프레임워크 기본 false) actually-implemented 유지 (D1)
classpath 무력화 app-bootstrap/.../application.yml:19-21 spring.autoconfigure.exclude 3건 ↔ MongoPersistenceConfig.java:38-42 @ImportAutoConfiguration 3건 actually-implemented 유지 — 두 half 는 함께 바뀌어야 함
repository 스캔 범위 :43 @EnableMongoRepositories(basePackageClasses = MongoPersistenceConfig.class) actually-implemented 유지
연결 URI spring.data.mongodb.* 어디에도 없음 (application.yml·src/.env 126행 grep 0건) D2 로 신설 + 미설정 시 startup 거부
timeout·pool·tls 미설정 (드라이버 기본값) D3·D4 로 명시
concern 3종 미설정 D5·D6·D7 로 명시
transaction TransactionPort 구현체는 persistence-jpa/.../SpringTransactionPort 1개뿐 actually-implemented(JPA만) D8 게이트. Mongo 측 구현 여부는 §7
change stream 없음 D11·D12 로 신설
index manifest 없음 D13·D14 로 신설
ArchUnit rule CleanArchitectureTest.java:823-828TODO 주석만, rule 미작성 documented-only D16 으로 신설
registry row env-keys·metrics·error-codes·secrets-classification 전부 mongo row 0건 D2·D3·D12·D15 가 신규 제안
로컬 실행 자산 docker-compose*.yml 에 Mongo 서비스 없음, Mongo Testcontainers test 없음 R1 승급의 선행 조건(§8)

Readiness 등급 판정 (project note §36.1): 현행은 R0 Contract — 타입·seam·placeholder 만 존재. 근거: 문서/document/repository 0개, 로컬 서비스 없음, 통합 test 없음. R0R2 로 표기하는 것은 §36.1 금지 항목이므로, 본 branch 완료 시점의 목표 등급은 R1 Local(로컬 replica-set 컨테이너 + 집중 통합 test)이며 R2 주장은 실서비스 통합·runbook 확보 후에만 한다.

2. 연결 설정 계약 (명시 대상 키 집합)

Trace: D2(URI) · D3(timeout·pool) · D4(tls) · D10(retryWrites) — MONGO-CONNSTR-C1~C8

드라이버 기본값 (근거) 명시 필수? 이유
serverSelectionTimeoutMS 30,000ms (MONGO-CONNSTR-C1) 운영 필수 30s 는 요청 타임아웃보다 길어 상류에서 먼저 끊긴다
connectTimeoutMS 10,000ms, 드라이버별 상이 (C2) 운영 필수 "드라이버별로 다를 수 있다" 는 원문 단서 자체가 명시 사유
socketTimeoutMS no timeout (C3) 항상 필수 미명시 = 무한 대기. 유일하게 로컬에서도 명시
maxPoolSize 100 (C4) 운영 필수 100 은 대부분 배포에서 과다
minPoolSize 0 (C5) 운영 필수 0 이면 첫 요청이 연결 비용을 부담
maxIdleTimeMS 원문에 숫자 기본값 없음 (C6) 제외 기본값을 모르는 키를 "기본값 대비 명시" 로 규정할 수 없음. 단 이 제외는 문서 부재를 근거로 한 것이고 드라이버의 실제 동작은 미확인
timeoutMS (CSOT 통합 timeout) (미조사) 제외 — 채택 시 D10 재도출 필요 MONGO-RETRYWRITE-C3 의 적용 범위가 "timeoutMS 를 별도 설정하지 않은 기본 동작" 이고, 같은 자료가 "timeoutMS 설정 시 몇 회까지 재시도되는지의 상한은 명시하지 않음" 을 Does-not-prove 로 남긴다. 즉 timeoutMS 를 켜면 D10 의 "정확히 1회 재시도" 전제가 무효가 된다
tls SRV=true / Standard=false (C7) 항상 필수 연결 문자열 형식을 바꾸면 TLS 가 조용히 뒤집힘 (D4)
retryWrites / retryReads 공식 드라이버 true (C8) 명시 권고 기본이 켜져 있다는 사실을 계약에 드러내야 D10 의 "중첩 금지" 가 성립

UNSUPPORTED_IMPL_DECISION: 이 키들을 URI 쿼리스트링에 담을지, Spring spring.data.mongodb.* 개별 property 로 분리할지. trade-off — 쿼리스트링은 드라이버 문서와 1:1 이라 대조가 쉽지만 URI 전체가 secret 분류가 되어 개별 값의 registry 검증(verifyEnvKeys)이 불가능해진다. 개별 property 는 registry 검증이 되지만 Spring 이 노출하는 property 집합이 드라이버 옵션 전체를 덮는지 확인되지 않았다. registry 정합만 보면 개별 property 가 우세하나 결정 근거는 없다.

2-1. concern·read preference 적용 seam (D5·D6·D7 이 어디에 붙는가)

Trace: D5(read concern) · D6(write concern) · D7(read preference) — SD-MONGO-TEMPLATE-C1~C6 · MONGO-READPREF-C5 · MONGO-TXN-C7

D5·D6·D7 은 무엇을 명시할 것인가를 정했다. 본 절은 Spring Data MongoDB 에서 그 값이 붙는 지점을 고정한다 — 이것이 없으면 구현자가 "repository 인가 template 인가 client 설정인가" 를 되묻는다.

적용 seam 근거 상태
write concern (기본값) MongoTemplate 의 기본 WriteConcern 속성. 미설정 시 드라이버(MongoClient)의 DB/Collection 설정으로 폴백 SD-MONGO-TEMPLATE-C3 — "If it has not yet been specified through the driver at a higher level (such as com.mongodb.client.MongoClient), you can set the com.mongodb.WriteConcern property that the MongoTemplate uses ... If the WriteConcern property is not set, it defaults to the one set in the MongoDB driver's DB or Collection setting." 확정
write concern (연산별) WriteConcernResolverMongoTemplate 에 구성 — remove/update/insert/save 별로 다른 값 결정 SD-MONGO-TEMPLATE-C4(per-operation 전략 인터페이스) · C5(WriteConcern resolve(MongoAction action)) · C6(MongoAction 이 collection 명·POJO 클래스·변환된 Document·연산 종류(REMOVE/UPDATE/INSERT/INSERT_LIST/SAVE)를 제공) 확정 — D6 의 "연산별 명시" 를 실현하는 수단
read preference (기본값) MongoTemplate 의 선택적 속성 중 하나. Query 수준 지정이 template 기본값보다 우선 SD-MONGO-TEMPLATE-C1(설정 가능 속성 목록에 ReadPreference 포함) · C2("The default read preference applied to read operations if no other preference was defined via the Query") 확정
read preference (트랜잭션 내) 선택 불가 — primary 강제 MONGO-READPREF-C5 확정
write concern (트랜잭션 내 개별 write) 설정 금지 — 설정 시 에러. transaction/session/client 레벨에서만 지정 MONGO-TXN-C7 확정
read concern 미확정 해당 페이지에 "read concern"/"ReadConcern" 이 0회 등장(self-grep 0 매치) — SD-MONGO-TEMPLATE Does-not-prove UNSUPPORTED_IMPL_DECISION

UNSUPPORTED_IMPL_DECISION — read concern 적용 seam. 수집한 자료 중 Spring Data MongoDB 가 read concern 을 어떤 API 로 노출하는지 다루는 것이 없다(위 페이지는 WriteConcern·ReadPreference 만 다룬다). 후보 — (a) MongoClientSettings 수준에서 전역 설정(연산별 분기 불가), (b) Query/AggregationOptions 수준 옵션이 존재한다면 그것, (c) MongoTemplate 을 감싼 자체 wrapper 에서 명시. trade-off — (a)는 확실히 존재하지만 D5 의 "연산 단위로 명시" 를 충족하지 못한다(정확성 조회와 근사 조회가 같은 값을 쓰게 됨). (b)가 있으면 D5 를 그대로 실현하지만 존재 여부 자체가 미확인이다. (c)는 항상 가능하나 프레임워크가 이미 제공하는 것을 재발명할 위험이 있다. (b)의 존재 확인이 선행돼야 한다 — §검증해야 할 주장 참조.

범위 한정: 위 seam 은 전부 MongoTemplate 경로 기준이다. 모듈 wiring 은 @EnableMongoRepositories(§1)이므로 repository 파생 쿼리에 concern/preference 가 어떻게 붙는지는 본 표가 다루지 않는다. 현재 repository·document 가 0개라 착수를 막지는 않으나, 첫 @Document/MongoRepository 를 추가하는 시점에 재확인해야 한다.

대비: write concern 은 WriteConcernResolver(C4~C6)라는 연산별 결정 수단이 확인된 반면, read concern 은 그 대응물이 확인되지 않았다. 따라서 D5 와 D6 은 같은 문장 구조("연산 단위로 명시")를 갖지만 실현 확실성이 다르다.

3. 실패 분류 — 기존 재사용 vs 신규 제안

Trace: D15 · internal-code-fact(Category.java:11-20, error-codes.yaml)

  • 본 § 는 제안이다. code 확정은 feature-contract-registry-governance 의 registry 변경 절차 소관이며 본 branch 가 단독으로 확정하지 않는다.

기존 재사용 (변경 없음):

대상 재사용 owner
실패 category 어휘 Category enum 10종 (VALIDATION·AUTH·AUTHZ·NOT_FOUND·CONFLICT·RATE_LIMIT·TRANSIENT_DEPENDENCY·PERMANENT_DEPENDENCY·DATA_INTEGRITY·INTERNAL) shared-contract
토폴로지 검증 실패 (D2·D8·D11) STARTUP_VALIDATION_FAILED feature-migration-startup-contract
index migration 실패 (D13·D14) MIGRATION_FAILED feature-migration-startup-contract
비활성 capability 런타임 호출 ADAPTER_DISABLED feature-integration-adapter-templates

신규 제안 (아직 registry 에 없음 — 이름은 확정 아님):

가장 흔한 3종 먼저 — 아래 3행은 정상 운영에서 가장 자주 만나는 실패다. DB_* 가 SQLState 기반이라 재사용할 수 없으므로(D15) Mongo 측 대응이 필요하다:

실패 제안 category 근거 claim
서버 선택 실패 (serverSelectionTimeoutMS 초과 — 서버 미기동·전원 unreachable·replica set 미구성) TRANSIENT_DEPENDENCY MONGO-CONNSTR-C1(기본 30,000ms 후 예외). PostgreSQL 대응은 DB_UNAVAILABLE(503·retryable, owner feature-persistence-failure-baseline)이나 SQLState 기반이라 재사용 불가
인증·권한 실패 (자격증명 오류, 최소권한 계정의 명령 거부) AUTH / INTERNAL / PERMANENT_DEPENDENCY미정 (아래 UNSUPPORTED_IMPL_DECISION 참조) 근거 claim 없음. 기존 AUTH_* 9종은 전부 JWT 사용자 인증용(owner feature-authentication-authorization-contract)이라 서버-대-DB 인증에 의미가 맞지 않는다. §구현 가이드 4 의 최소권한 검증(§검증해야 할 주장 — 토폴로지·FCV 질의를 최소권한 계정이 실행 가능한가)과 쌍
connection pool 고갈 (maxPoolSize 소진 후 대기) TRANSIENT_DEPENDENCY MONGO-CONNSTR-C4(기본 100)·C5(min 0). Hikari 대응(DB_UNAVAILABLE + hikaricp.connections.acquire{outcome=TIMEOUT})은 raw/branch-notes/feature-persistence-failure-baseline·raw/branch-notes/feature-database-connection-pool-contract 소유이며 JDBC 전용

나머지 (드물지만 계약이 필요한 경로):

실패 제안 category 근거 claim
write concern 미달·wtimeout 초과 TRANSIENT_DEPENDENCY MONGO-WRITECONCERN-C6·C7 — write 는 취소되지 않으므로 재시도는 멱등 연산에만
transaction 시간 한계 초과 abort CONFLICT MONGO-TXN-PROD-C2
TransactionTooLargeForCache INTERNAL MONGO-TXN-PROD-C4
change stream resume 불가 (oplog 롤오버) INTERNAL MONGO-CHANGESTREAM-C7
unique index 위반 (duplicate key) CONFLICT 선례 정합internal-code-fact: error-codes.yaml:301-306 DB_UNIQUE_VIOLATION = category CONFLICT · http_status: 409 · retryable: false. Mongo duplicate key 도 같은 의미이므로 category 를 일치시킨다(code 이름만 신규). sibling raw/branch-notes/feature-transaction-concurrency-contract D5 의 "optimistic 충돌 → 409 non-retryable" 계열과도 정합

UNSUPPORTED_IMPL_DECISION — 인증 실패의 category: 위 표의 "인증·권한 실패" 행은 category 자체가 미정이다. 후보 — (a) AUTH, (b) INTERNAL, (c) PERMANENT_DEPENDENCY. trade-off — 기존 AUTH_* 9종은 전부 클라이언트가 제시한 JWT 를 다루므로 (a)를 쓰면 "누구의 인증인가" 가 로그·대시보드에서 뒤섞인다. DB 자격증명 오류는 클라이언트가 고칠 수 없고 배포 설정으로만 고쳐지므로 (b)/(c)가 의미상 가깝다. 어느 쪽도 외부 근거가 없고, 기존 registry 에도 서버-대-의존성 인증 실패 선례가 없다.

UNSUPPORTED_IMPL_DECISION: 위 신규 code 의 이름·retryable·http_status. trade-off — 기존 DB_* 접두사를 이어 쓰면(DB_WRITE_CONCERN_TIMEOUT 등) grep 일관성은 좋지만 그 접두사는 SQLState 매트릭스가 owner 인 feature-persistence-failure-baseline 소유라 의미 확장 = 남의 registry 침범이다. MONGO_* 접두사는 소유가 깨끗하지만 vendor 이름을 error code 에 박는 첫 사례가 된다. 소유 경계만 보면 MONGO_* 가 우세하나 결정 근거는 없다.

4. 토폴로지 검증 게이트 (transaction · change stream 공통)

Trace: D8(transaction) · D11(change stream) · D2(URI) — MONGO-TXN-C2~C4 · MONGO-TXN-PROD-C1 · MONGO-CHANGESTREAM-C1·C2

검증 항목과 대상 기능:

검증 transaction (D8) change stream (D11) 근거
standalone 아님 (replica set / sharded) 필수 필수 MONGO-TXN-PROD-C1 · MONGO-CHANGESTREAM-C1
primary WiredTiger 필수 필수 MONGO-TXN-C3 · MONGO-CHANGESTREAM-C2
FCV ≥ RS 4.0 / SC 4.2 필수 (해당 없음) MONGO-TXN-C2
writeConcernMajorityJournalDefault≠false shard 필수 (sharded) (해당 없음) MONGO-TXN-C4
read concern majority 지원 여부 (해당 없음) 무관 MONGO-CHANGESTREAM-C3
  • 검증 시점은 sibling raw/branch-notes/feature-capability-provider-selection-contract D6 을 상속한다 — context refresh 완료 전(SmartInitializingSingleton), ApplicationRunner 로 옮기지 않는다. 본 branch 는 시점을 재정의하지 않는다.
  • 검증 실패 시 STARTUP_VALIDATION_FAILED 로 기동 거부한다. 조용한 비활성 전환은 하지 않는다 — 활성화를 선언했는데 요건이 없으면 그것은 설정 오류다.

UNSUPPORTED_IMPL_DECISION: 토폴로지·FCV·storage engine 을 어떤 명령으로 질의할지(hello/buildInfo/getParameter 등)와 자격증명이 그 명령을 실행할 권한을 갖는지. trade-off — 관리 명령은 권한이 없으면 실패하므로, 검증이 오히려 최소권한 계정에서 기동을 막을 수 있다. 근거 자료(위 4건) 중 어느 것도 클라이언트가 이 요건을 런타임에 확인하는 방법을 다루지 않는다. 검증 방법이 확정될 때까지 게이트는 "실패 시 거부" 정책만 확정이고 판정 수단은 미정이다.

5. change stream checkpoint 와 재개 경로

Trace: D11 · D12 — MONGO-CHANGESTREAM-C4~C8

재개 경로 결정표:

상황 사용 옵션 근거
저장된 resume token 있음 · invalidate 없었음 resumeAfter C4
invalidate event 이후 재개 startAfter C5resumeAfter 는 invalidate 이후 재개 불가
token 없음 (최초 기동) startAtOperationTime C6 — 과거 시점이면 oplog 시간 범위 안이어야 함
oplog 가 token 을 넘겨 롤오버됨 재개 불가 — 소비를 중단하고 경보. 복구 방법은 아래 참조 C7

OUT_OF_BRANCH_SCOPE — "재개 불가 이후의 복구": 저장된 token 이 무효가 된 뒤 무엇을 해야 소비자가 정합 상태로 돌아오는가(컬렉션 전량 재스캔 / 보상 이벤트 재발행 / 수동 개입)는 소비자가 무엇을 하는 소비자인지에 종속되며 skeleton 범위 밖의 도메인 결정이다. 본 branch 는 여기까지만 소유한다 — (1) 이 상태를 감지하고(C7), (2) 소비를 중단하고, (3) 경보한다. 조용히 최신 시점부터 재개해 이벤트 구간을 건너뛰는 동작은 금지한다(유실을 은폐하므로). 실제 복구 절차의 문서 산출물 owner 는 raw/branch-notes/feature-operational-runbook-contract D9(실 runbook 본문 작성)다. change stream 소비자를 도입하는 branch 가 도메인 절차를 정의하겠지만 그런 branch 는 현재 저장소에 없다(소비자 도입 시 신설) — 지금 시점에 이 절차를 소유한 문서는 없으며, 그 사실 자체를 여기 명시해 다음 작업자가 "이미 있는데 못 찾는 것" 으로 오해하지 않게 한다.

cursor 종료 4조건(C8)은 전부 정상 처리 경로를 가져야 한다: 명시적 close(정상 종료) / invalidate(→ startAfter 재개) / 연결 종료·timeout(→ resumeAfter 재개) / sharded cluster 의 shard 제거(→ resumeAfter 재개 + 경보).

UNSUPPORTED_IMPL_DECISION: checkpoint 저장 위치와 저장 시점. 후보 — (a) 같은 Mongo 의 전용 컬렉션, (b) PostgreSQL(업무 store), (c) 별도 store. trade-off — (a)는 change stream 대상과 저장소가 같아 운영 단순하고 D8 트랜잭션 게이트를 통과하면 처리와 checkpoint 를 한 트랜잭션에 넣을 여지가 있으나, Mongo 가 죽으면 checkpoint 도 함께 잃는다. (b)는 이미 트랜잭션이 검증된 store 지만 두 DB 에 걸친 원자성은 불가능해 at-least-once 가 확정된다. 근거 자료 어느 것도 checkpoint 저장 전략을 다루지 않는다. 저장 시점(처리 전 vs 후)에 따라 at-least-once ↔ at-most-once 가 갈리므로, 이 선택은 project note §11 의 durable 경로 정책과 함께 결정돼야 한다.

6. index manifest · migration runner · drift

Trace: D13(자체 러너) · D14(lock) — SD-MONGO-INDEX-C1~C3,C5 · MONGOCK-C2,C3 · LIQUIBASE-MONGO-PRO-C1

확정된 것:

  • spring.data.mongodb.auto-index-creation 을 켜지 않는다. 근거 SD-MONGO-INDEX-C1(3.0 부터 기본 OFF) + C2("undesired effects on collection lifecycle and performance"). 기본값이 이미 OFF 이므로 "켜지 않는다" 는 별도 조치 없이 성립하며, 계약의 역할은 누군가 켜는 것을 막는 것이다.
  • 적용은 programmatic 경로를 쓴다 — IndexResolver + IndexOperations (C3 가 "(Recommended)" 로 표기, C5 가 "more control than annotations").
  • drift 감지는 실제 인덱스 목록과 manifest 를 대조한다.

대안 기각 (D13 선택 조건의 근거):

대안 기각 사유 근거 확신도
Mongock 신규 개발이 Flamingock 으로 이전, critical fix 만 유지 MONGOCK-C2 확정 (벤더 공지)
Mongock (drift) drift 기능이 이 페이지에서 확인되지 않음 MONGOCK-C4 Does-not-prove needs-confirmation — 부재의 증거 아님
Liquibase-mongodb drift report 가 Pro 기능 LIQUIBASE-MONGO-PRO-C1·C2 확정
Liquibase (무료 티어) 무료 extension 에 drift 가 없다는 부정 명제 (직접 근거 없음) needs-confirmation

착수 순서 제약: 위 표의 needs-confirmation 2행은 본 절(§6)의 코드를 쓰기 전에 닫아야 한다. 자체 러너는 §구현 가이드 최대 분량 절이고 전부 이 기각 논리에 종속되므로, 기각이 뒤집히면 작성한 코드를 되돌리게 된다. §검증해야 할 주장의 Mongock·Liquibase 자료 2건(Mongock v5 기능/lock 페이지 · Liquibase 무료 OSS extension 기능 목록)을 먼저 수집한다. 채택 근거(SD-MONGO-INDEX-C1~C3,C5)는 이미 충분하므로 "auto-index-creation 을 쓰지 않는다" 부분은 지금 착수해도 안전하다 — 되돌릴 위험이 있는 것은 도구 대신 자체 러너를 만든다 는 부분뿐이다.

UNSUPPORTED_IMPL_DECISION 1 — manifest 포맷과 drift 판정 범위. 후보 — (a) @Document 애노테이션을 IndexResolver 로 읽어 manifest 를 코드에서 도출, (b) 별도 YAML manifest 파일, (c) 둘 병행. trade-off — (a)는 SSOT 가 하나지만 "인덱스 목록" 을 코드 밖에서 리뷰할 수 없고, (b)는 리뷰 가능하나 엔티티와 manifest 가 어긋날 수 있다. 또한 drift 를 어디까지 볼 것인가(키 순서만 vs unique/partialFilterExpression/collation/TTL expireAfterSeconds 까지)가 미정이며, SD-MONGO-INDEX-C3 의 Does-not-prove 가 "manifest·migration 이력·drift 비교 로직은 이 문서 범위 밖" 임을 명시한다. 어느 쪽도 외부 근거가 없다.

UNSUPPORTED_IMPL_DECISION 2 — drift 발견 시 동작. 후보 — (a) 기동 거부(MIGRATION_FAILED), (b) 경보만 남기고 기동, (c) 자동 교정. trade-off — (a)는 배포 중단 비용이 크고 운영자가 인덱스를 손으로 추가한 정당한 경우에도 막힌다. (c)는 프로덕션에서 예상치 못한 인덱스 빌드를 유발해 SD-MONGO-INDEX-C2 가 경고한 바로 그 "undesired effects" 를 재현한다. (b)가 가장 보수적이나 결정 근거는 없다.

UNSUPPORTED_IMPL_DECISION 3 — runner lock 메커니즘. D14 는 lock 이 필요하다까지만 근거가 있다(MONGOCK-C3 = 기성 도구도 DB 영속 pessimistic lock 을 씀). 후보 — (a) unique index 를 건 lock 컬렉션 + TTL 로 만료, (b) 배포 파이프라인 단일 Job 으로 분리(앱 밖), (c) 기존 MigrationStartupRunner 와 같은 프로세스에 묶기. trade-off — (a)는 D13 이 어차피 다뤄야 하는 unique/TTL index 를 재료로 쓰므로 신규 개념이 없으나 TTL 만료 정밀도가 lock 안전성에 미치는 영향이 미조사(§검증해야 할 주장 — lock 컬렉션 TTL 만료 정밀도)다. (b)는 sibling feature-migration-startup-contract 가 이미 K8S-JOB-C1/C2 로 근거를 확보한 패턴이지만 앱 readiness 게이트와 분리된다. (a)가 기존 아키텍처와 가장 정합하나 결정 근거는 없다.

6-1. oplog window 측정 (D12)

Trace: D12 — MONGO-CHANGESTREAM-C7

  • UNSUPPORTED_IMPL_DECISION — 측정 수단: C7 은 "oplog 에 충분한 history 가 있어야 resume 이 된다" 는 위험만 증명하고, 남은 window 를 어떻게 재는가는 다루지 않는다. 후보 — (a) replSetGetStatus 의 oplog 타임스탬프 범위, (b) local.oplog.rs 의 first/last entry 타임스탬프 차이, (c) db.getReplicationInfo()timeDiff. trade-off — (a)·(c)는 관리 명령이라 §구현 가이드 4 와 같은 최소권한 문제를 공유하고(§검증해야 할 주장 — 토폴로지·FCV 질의를 최소권한 계정이 실행 가능한가), (b)는 local 데이터베이스 직접 조회라 권한 요구가 다르고 MONGO-READCONCERN-C12(local DB 는 read concern 을 조용히 무시)가 적용되는 특수 영역이다. 어느 쪽도 외부 근거가 없다.
  • UNSUPPORTED_IMPL_DECISION — 경보 임계: D12 는 임계를 "남은 oplog 시간 < 소비자 최대 다운타임 허용치" 로 표현했으나 그 허용치를 정하는 주체가 본 branch 가 아니다. raw/branch-notes/feature-metrics-alerting-contract D3 가 "alert threshold 는 SLO/error budget 또는 documented operational default 에 연결 — 임의 수치 금지" 를 강제하므로, 본 branch 는 수치를 제안하지 않고 임계의 형태(비율 기반 vs 절대 시간)만 남긴다.
항목 본 branch 가 고정하는 것 위임
무엇을 재는가 남은 oplog window(시간) 와 마지막 저장 checkpoint 의 시간 격차
어떻게 재는가 (미정 — 위 후보 3종)
metric 이름 (제안하지 않음) raw/branch-notes/feature-metrics-alerting-contract D2 (Micrometer dot.case + unit suffix)
경보 임계 수치 (제안하지 않음 — 임의 수치 금지) raw/branch-notes/feature-metrics-alerting-contract D3
registry 등록 신규 제안만 raw/branch-notes/feature-contract-registry-governance

7. 위임 — 본 branch 가 정의하지 않는 것

Trace: D7(read preference) · D17(outbox/inbox) — R3 정제 결과

관심사 owner 본 branch 가 남기는 것
ReadConsistency 정책 → replica 라우팅 판정 raw/branch-notes/feature-read-consistency-query-contract (DEC-…-READ-CONSISTENCY-001@1) Mongo 측 표현 수단만 (mode 5종 · maxStalenessSeconds) — D7
outbox 행 모델 · dispatch 모드 · 순서 raw/branch-notes/feature-outbox-dispatch-mode-contract Mongo same-store 가능 조건(D8 게이트 통과)만 — D17
idempotency owner token 프로토콜 raw/branch-notes/feature-idempotency-ownership-protocol-contract 동일 — D17
활성화 property prefix 문자열 · descriptor 스키마 raw/branch-notes/feature-capability-provider-selection-contract (D2·D3·D5·D6) 축이 boolean 이라는 것만 — D1
env key 이름·수치·bounds 등록 raw/branch-notes/feature-env-driven-runtime-configuration (D2·D7) 명시 대상 키 집합만 — D3·D4
secret 분류·회전 정책 raw/branch-notes/feature-secrets-config-source-contract URI 가 secret 이라는 신규 제안만 — D4
운영 runbook 문서 raw/branch-notes/feature-operational-runbook-contract Mongo runbook 부재를 §Audit A4 로 신고만 — 작성은 그 branch 절차
error code 이름 확정 raw/branch-notes/feature-contract-registry-governance category 매핑 제안만 — D15
PostgreSQL/JPA 실패 매핑 · Hikari pool raw/branch-notes/feature-persistence-failure-baseline · raw/branch-notes/feature-database-connection-pool-contract 없음 (본 branch 범위 밖)

TransactionPort 를 Mongo 로 구현할 것인지(현재 구현체는 JPA 1개)는 본 branch 에서 확정하지 않는다 — 두 PlatformTransactionManager 공존은 application-core 의 포트 계약에 영향을 주므로 feature-application-port-usecase-contract 와의 조율이 선행돼야 한다. D8 은 Mongo 트랜잭션을 언제 켜도 되는가만 정의한다.

8. 쿼리·document 값 로그 유출 억제 (D18)

Trace: D18 — MONGO-JAVA-LOG-C1~C6 · governing doc §11 Persistence("SQL/parameter 로그 금지")

관계형 쪽 대응은 raw/branch-notes/feature-persistence-failure-baseline 이 소유하나 그 구현은 Hibernate show-sql(JDBC 전용)에 한정된다. Mongo 는 다른 logger 계층을 쓰므로 같은 금지를 별도로 집행해야 한다.

logger 무엇이 남는가 값 노출? 운영 정책
org.mongodb.driver.protocol.command command 시작/성공 이벤트. Command: 필드에 command document 전체(예시에 filter 포함) 예 — 차단 대상 DEBUG 미만으로 고정
org.mongodb.driver.protocol (상위) "Commands sent to and replies received" 하위와 함께 고정
org.mongodb.driver.connection 연결·connection pool 아니오 (값 미포함) 끄지 않는다 — pool 고갈 진단(§구현 가이드 3)에 필요

규범:

  • 운영 프로파일에서 command logger 를 DEBUG 이상으로 올리는 설정은 금지한다. 이 금지가 없으면 모든 쿼리 filter 값이 평문으로 남는다(C4).
  • LoggerSettings.maxDocumentLength완화 수단이지 차단 수단이 아니다 — 기본 1000자(C5)를 줄여도 값의 앞부분은 남는다. 차단은 레벨로만 한다.
  • connection logger 는 값을 담지 않으므로(C2) 일괄 차단 대상에서 분리한다 — pool 고갈·연결 실패 진단 능력을 잃지 않기 위해.
  • 이 규칙은 Mongo 가 비활성일 때도 설정에 남아 있어야 한다(활성화 시점에 잊지 않도록).

이 규칙이 덮지 않는 채널 (근거 자료가 Does-not-prove 로 명시한 범위 — "레벨만 내리면 다 막힌다" 고 주장하지 않는다):

채널 왜 안 덮이는가
Command Monitoring API logger 와 별개 채널이다. 애플리케이션이 command listener 를 등록하면 로그 레벨과 무관하게 command 내용을 받는다 — 등록 시 그쪽에서 별도 억제 필요
org.mongodb.driver.operation 등 나머지 driver logger 수집 자료가 이름 목록만 제공하고 각각이 값을 담는지 실측을 주지 않는다
protocolprotocol.command 상속 관계 공식 목록에 protocol.commandprotocol 의 자식으로 명시돼 있지 않다(추론일 뿐). 상위만 끄면 하위가 따라 꺼지는지는 미검증 → 두 이름을 모두 명시적으로 고정한다
Spring Data org.springframework.data.mongodb.core logger Spring Data 자체 로깅은 driver logger 와 별개다. 수집 자료가 다루지 않아 취급 미정

UNSUPPORTED_IMPL_DECISION — 집행 수단. 후보 — (a) logback-spring.xml 등 로깅 설정에 logger 레벨을 못박기, (b) 코드에서 LoggerSettings 를 빌드해 주입, (c) 운영 프로파일 startup 검증에서 해당 logger 의 유효 레벨을 확인하고 위반 시 거부. trade-off — (a)는 가장 단순하나 설정 파일을 고치면 조용히 뚫린다. (c)는 D2·D8 의 startup 게이트와 같은 모양이라 정합적이지만 로깅 프레임워크의 유효 레벨을 런타임에 질의하는 방식이 프레임워크마다 다르다. (a)+(c) 조합이 가장 견고하나 결정 근거는 없다. 로깅 설정 파일의 소유자는 raw/branch-notes/feature-log-management-contract 이므로 (a) 채택 시 그 branch 와 조율이 필요하다.

Audit & Findings

/branch-spec 실행 중 ca-tmpl 코드·registry 대조에서 발견한 정합 문제. 본 branch 가 자동 수정하지 않는다 — 사용자·owner branch 의 결정 영역이므로 정합 권고만 남긴다.

ID 유형 발견 근거 권고
A1 MONGO_URI_UNCONFIGURED spring.data.mongodb.*application.ymlsrc/.env(126행) 어디에도 없다(grep 0건). 즉 ca-skeleton.persistence-mongo.enabled=true 로 바꿔도 연결 대상이 정의되지 않은 상태다. (플래그를 켰을 때 기본 URI 로 붙는지 Spring 이 먼저 실패시키는지는 needs-confirmation — §검증해야 할 주장 — 플래그를 켰을 때 기본 URI 로 붙는지) internal-code-fact(부재는 grep 으로 확정) D2 로 해소. env-keys.yaml 등록이 선행돼야 verifyEnvKeys 가 이 부재를 잡는다
A2 ARCHUNIT_RULE_ABSENT CleanArchitectureTest.java:823-828 이 "그런 모듈이 생기면 rule 을 추가하라" 고 적었으나 모듈은 이미 존재(modules.yaml:202-212)하고 rule 은 미작성 internal-code-fact D16 으로 해소
A3 MISSING_INTERNAL_DESIGN_DOC 프로젝트 결정 DEC-…-MONGO-BASELINE-001 의 근거란이 "ca-tmpl platform 설계 §12.3" 을 가리키나, ca-tmpl docs/superpowers/specs/ 에 tracked 된 파일은 2026-07-20-harness-policy-engine-design.md 하나뿐이다. docs/ 는 gitignore 가 아니라 정상 tracked(54 파일)이므로 부재가 확실하다 internal-code-fact (git ls-files docs/superpowers/) 본 branch 는 §12.3 내용을 인용하지 않았다 — 모든 D-row 는 공식 벤더 문서 또는 코드 사실에 근거한다. project note §6.1 의 근거란 정정은 project-note owner 소관
A4 REGISTRY_ROW_ABSENT env-keys·metrics·error-codes·secrets-classification 4개 registry 전부 mongo row 0건. docs/runbooks/ 에도 mongo runbook 없음(db-*.md 5건은 전부 SQL) internal-code-fact D2·D3·D12·D15 가 신규 제안. 등록은 각 owner branch 절차
A5 README_SCOPE_DRIFT ca-tmpl README.md:25adapter:outbound:persistence-* 가 "JPA/PostgreSQL·MongoDB 영속 구현과 매핑·migration" 을 담당한다고 적었으나, mongo 모듈의 CLAUDE.md·README.md 는 wiring-only 이며 migration 을 명시적으로 다루지 않는다 internal-code-fact D13·D14 착수 시 README 문구를 실제 범위에 맞춘다 (낮은 심각도)
A7 OWNER_DOC_STALE raw/branch-notes/feature-log-management-contract 본문이 masking Layer 1 을 미구현으로 서술한다(:190 "Layer 1~3 모두 미구현", :274, :278, :334 "Layer 1 미구현(DRIFT-2)"). 그러나 코드는 구현돼 있고(logback-spring.xml:45-46,:80-81 + SecretMaskingMessageConverter·SecretMaskingJsonGeneratorDecorator·LogMaskingPatterns) 같은 문서의 frontmatter :22 last_pass: 2026-06-14 도 "Phase C2 전면 구현 완료" 로 갱신돼 있다 — 본문과 frontmatter 가 서로 어긋난 상태 internal-code-fact 본 branch 는 고치지 않는다(Single-Owner). owner branch 가 본문을 정정해야 하며 /sync 로 그 branch 의 frontmatter↔본문 drift 를 별도 처리 권고. 본 branch 의 D18·§구현 가이드 8 은 코드 사실을 기준으로 작성했다
A6 MODULE_METADATA_ODD modules.yaml:211 의 mongo 모듈 mutation_importdev.caskeleton.adapter.inbound.web.controller.HealthcheckController — 본 모듈 타입이 아니다. 모듈에 자체 public 타입이 사실상 없어서일 수 있다 internal-code-fact 모듈에 실제 타입이 생기면 재검토 (정보성)

엣지·실패·의존

실패·엣지 경로 (각 경로의 기대 동작):

경로 기대 동작 근거 / 결정
capability 활성인데 URI 미설정 STARTUP_VALIDATION_FAILED 로 기동 거부. 기본 URI 로 조용히 연결하지 않는다 D2 · §Audit A1
standalone 배포에서 transaction/change stream 활성 선언 STARTUP_VALIDATION_FAILED 로 기동 거부. 조용한 비활성 전환 금지 D8 · D11 · MONGO-TXN-PROD-C1 · MONGO-CHANGESTREAM-C1
wtimeout 초과 write concern error 반환. 이미 적용된 write 는 되돌아가지 않는다 → 재시도는 멱등 연산에만 D6 · MONGO-WRITECONCERN-C6·C7
transaction 이 1분 초과 periodic cleanup 이 abort. 배치성 작업은 분할 + 멱등 재시도로 설계 D9 · MONGO-TXN-PROD-C2
transaction 이 WiredTiger cache 초과 TransactionTooLargeForCache 로 abort D9 · MONGO-TXN-PROD-C4
단일 oplog entry 16MB 초과 설계 제약으로 취급 — 트랜잭션 범위를 줄인다 D9 · MONGO-TXN-PROD-C3
일시적 네트워크 오류 · replica set election 드라이버가 1회 재시도. 애플리케이션 재시도를 겹치지 않는다 D10 · MONGO-RETRYWRITE-C3
지속적 네트워크 오류 드라이버 재시도로 해결되지 않음 → 실패로 전파 D10 · MONGO-RETRYWRITE-C3
updateMany/deleteMany 실패 드라이버가 재시도하지 않음 → 멱등 설계 + 명시적 재시도 필요 D10 · MONGO-RETRYWRITE-C5
트랜잭션 내부 개별 write 실패 개별 재시도 없음 → 트랜잭션 전체 재시도 (조건은 D9-a, 미확정) D10 · MONGO-RETRYWRITE-C6
change stream invalidate (collection drop/rename) cursor 종료 → startAfter 로 재개 D11 · MONGO-CHANGESTREAM-C5·C8
change stream 연결 종료·timeout cursor 종료 → 저장된 token 으로 resumeAfter 재개 D11 · MONGO-CHANGESTREAM-C8
sharded cluster 에서 shard 제거 cursor 종료 → resumeAfter 재개 + 경보 D11 · MONGO-CHANGESTREAM-C8
oplog 롤오버로 resume token 무효 재개 불가소비 중단 + 경보. 최신 시점부터 조용히 재개해 구간을 건너뛰는 동작은 금지(유실 은폐). 복구 절차 자체는 §구현 가이드 5 의 OUT_OF_BRANCH_SCOPE. 이 상태에 도달하기 전 경보하는 것이 D12 D11 · D12 · MONGO-CHANGESTREAM-C7
secondary 읽기가 오래된 데이터 반환 정상 동작 — stale 허용을 선언한 경로에서만 발생해야 함 D7 · MONGO-READPREF-C3
sharded collection 을 available 로 조회 orphaned document 반환 → 금지 D5 · MONGO-READCONCERN-C3
local read concern 데이터의 rollback 과반수 미기록 데이터는 롤백될 수 있음 → 정확성 경로에서 local 금지 D5 · MONGO-READCONCERN-C1
기존 데이터가 unique index 제약을 위반 index 생성 실패 → MIGRATION_FAILED. 기존 데이터 정리 전략은 본 branch 범위 밖 D13 · §검증해야 할 주장 — unique index 기존 데이터 정리 전략
Mongo 서버 미기동·unreachable serverSelectionTimeoutMS 초과 후 예외 → TRANSIENT_DEPENDENCY 계열 신규 code. 기동 시점이면 D2 의 startup 거부와 구분한다(런타임 실패 ≠ 설정 오류) §구현 가이드 3 · MONGO-CONNSTR-C1
자격증명 오류 / 최소권한 계정의 명령 거부 실패로 전파. category 미확정(needs-confirmation) — 기존 AUTH_* 는 JWT 사용자 인증용이라 의미가 맞지 않음 §구현 가이드 3 · §검증해야 할 주장 — 토폴로지·FCV 질의를 최소권한 계정이 실행 가능한가
connection pool 고갈 maxPoolSize 소진 → 대기 후 실패, TRANSIENT_DEPENDENCY 계열. Hikari 의 DB_UNAVAILABLE 은 JDBC 전용이라 재사용 불가 §구현 가이드 3 · MONGO-CONNSTR-C4·C5
쿼리 filter·document 값이 로그로 유출 드라이버·template logger 를 값이 새지 않는 레벨로 고정 (D18) D18 · §구현 가이드 8
migration runner 동시 실행 lock 으로 단일 실행 보장. 획득 실패 시 대기 후 실패 D14 · MONGOCK-C3
트랜잭션 안에서 read concern majority/snapshot 을 쓰되 w:"majority" 로 커밋하지 않음 보증이 조용히 사라진다 → D5·D6 을 쌍으로 강제 MONGO-READCONCERN-C6·C10

다른 계약 의존:

  • WI-CA-SKELETON-OPERATIONAL-CONTRACT-060 = raw/branch-notes/feature-capability-provider-selection-contractD2(활성화 축 단일화)·D3(단일 prefix + APP_* env registry)·D6(startup 검증 시점 = refresh 완료 전)·D10(startup 실패는 기존 registry code 재사용)에 의존. 그 branch 가 prefix 를 app.* 로 확정하면 본 branch 의 D1 키(ca-skeleton.persistence-mongo.enabled)가 rename 대상이 된다.
  • raw/branch-notes/feature-env-driven-runtime-configurationD2(APP_ 통일, registry = SSOT)·D7(verifyEnvKeys 3-way drift). 본 branch 의 D2·D3·D4 가 제안하는 키가 이 branch 절차로 등록돼야 검증이 성립한다.
  • raw/branch-notes/feature-migration-startup-contractSTARTUP_VALIDATION_FAILED·MIGRATION_FAILED code 의 owner. 본 branch 는 소비자다.
  • raw/branch-notes/feature-read-consistency-query-contractDEC-…-READ-CONSISTENCY-001@1 owner. D7 이 제공하는 Mongo 표현 수단을 그 branch 의 정책이 소비한다.
  • raw/branch-notes/feature-outbox-dispatch-mode-contract · raw/branch-notes/feature-idempotency-ownership-protocol-contract — D17 이 same-store 가능 조건만 넘기고 행 모델·프로토콜을 위임.
  • raw/branch-notes/feature-contract-registry-governance — D12(metric)·D15(error code) 신규 제안의 등록 절차 owner.
  • raw/branch-notes/feature-application-port-usecase-contractTransactionPort 계약 owner. Mongo 트랜잭션 구현 여부는 이 계약과 조율 후 결정(§구현 가이드 7).
  • raw/branch-notes/feature-migration-startup-contract D6 — "multi-instance 에서는 app startup runner 를 그대로 확장하지 않고 platform one-shot job 또는 migration lock 검증 필요". 본 branch 의 D14 는 이 결정을 상속한다 — Job 이냐 lock 이냐의 선택 자체는 그 branch 소유이고, 본 branch 는 Mongo index manifest 러너에도 같은 규율이 적용된다는 것만 선언한다. §구현 가이드 6 의 lock 메커니즘 후보 (b)(배포 파이프라인 단일 Job)가 그 branch 의 K8S-JOB-C1/C2 근거와 같은 선택지다.
  • raw/branch-notes/feature-background-job-async-contract D3 — "scheduler/outbox publisher 는 single-instance 기본, multi-instance 시 DB advisory lock 또는 ShedLock 필수"(lock 전략 SSOT). D14 가 Mongo 자체 lock 컬렉션을 택하면 이 SSOT 와 다른 메커니즘이 되므로, §구현 가이드 6 의 후보 선택 시 그 정합을 먼저 확인해야 한다.
  • raw/branch-notes/feature-metrics-alerting-contract D2(metric naming = Micrometer dot.case + unit suffix 강제)·D3(alert threshold 는 SLO/error budget 또는 documented operational default 에 연결 — 임의 수치 금지). D12 의 oplog window metric 이름·임계는 이 두 결정을 따라야 한다 — 본 branch 가 임의 수치를 제안할 수 없는 이유다.
  • raw/branch-notes/feature-log-management-contract D1(JSON log 기본 + Logback masking converter = Layer 1 SSOTD4(production logging stdout JSON default). D18 의 집행 수단 후보 (a)(로깅 설정 파일에 logger 레벨 못박기)는 그 branch 소유 파일을 건드린다 — 채택 시 조율 필수. 그 masking 계층은 actually-implemented 다(internal-code-fact: app-bootstrap/.../logging/SecretMaskingMessageConverter.java + SecretMaskingJsonGeneratorDecorator, logback-spring.xml:45-46,:81conversionRule/decorator 등록). 그럼에도 D18 이 필요한 이유: 그 계층은 LogMaskingPatterns 카탈로그 기반 패턴 masking(token/password/bearer 류 고정 패턴)이라 임의 업무 필드 값 — Mongo query filter 의 값 — 은 패턴에 걸리지 않는다. 즉 masking 이 있어도 org.mongodb.driver.protocol.command 의 DEBUG 출력(MONGO-JAVA-LOG-C4)은 그대로 남는다.
  • raw/branch-notes/feature-transaction-concurrency-contract D5(lock 충돌 분류 — optimistic 409 non-retryable / deadlock·serialization retryable-by-policy)·D6("duplicate command → idempotency branch key scope. retryable write without idempotency forbidden"). D10 의 "재시도 경로는 멱등성을 스스로 보장한다" 는 D6 의 재진술이 아니라 그 정책의 Mongo 적용점이다 — 재시도·멱등 정책 자체의 owner 는 그 branch다. D9-a(트랜잭션 재시도 라벨)도 근거 확보 후 그 branch 로 이관하는 것이 정합적일 수 있다.

검증해야 할 주장 / Claims To Verify

공식 문서가 증명한 것은 MongoDB 의 동작이지 우리 배포에서의 동작이 아니다. 아래는 구현 전/중/후에 실제로 확인해야 하는 주장이다.

Claim Why uncertain How to verify Status
본 branch 가 소유할 관심사가 sibling branch 결정과 겹치지 않는다 D-row 17개가 새로 생겼고 D7·D17 은 명시적으로 sibling 에 위임한다 /sync 실행 — owner 중복·재진술 검출 needs-confirmation
Mongock 에 index drift 감지 기능이 없다 근거는 "이 페이지에서 확인되지 않음" 이지 "없다" 가 아니다(MONGOCK-C4 Does-not-prove). D13 의 기각 논리가 여기에 걸려 있다 Mongock v5 문서 트리 전체(특히 lock·기능 목록 페이지) 확인 후 D13 기각 사유 확정 또는 철회 needs-confirmation
Liquibase 무료 OSS MongoDB extension 에 drift 가 없다 확보한 자료는 "Pro 에 drift 가 있다" 만 증명한다. "무료엔 없다" 는 부정 명제는 미증명 무료 liquibase-mongodb extension 기능 목록 페이지를 별도 수집해 대조 needs-confirmation
lock 컬렉션의 TTL 만료 정밀도가 migration runner 의 단일 실행 보장에 충분하다 §구현 가이드 6 의 후보 (a)가 TTL 만료에 의존하는데, MongoDB 의 TTL 백그라운드 스캔 주기를 이번 회차에서 공식 문서로 확인하지 않았다 MongoDB TTL index 공식 문서 수집 → 만료 지연 상한을 확인하고 "이중 실행 윈도우" 허용 여부 판정 planned
기존 데이터가 있는 컬렉션에 unique index 를 걸 때의 실패·정리 전략 실패 경로는 §엣지에 넣었으나 기존 데이터 dedup 전략(자동 정리 vs 수동 vs partial unique index 우회)은 어느 대안을 골라도 필요한 별도 결정이며 이번 조사 범위 밖 MongoDB unique index 공식 문서 수집 후 별도 결정으로 추가 planned
트랜잭션 재시도를 촉발하는 에러 라벨 집합 D9-a 가 UNSUPPORTED_DECISIONTransientTransactionError/UnknownTransactionCommitResult 가 수집한 두 자료 어디에도 없다(self-grep 0 매치) MongoDB Java driver 의 transactions 에러 처리 페이지 1건 수집 → D9-a 확정 planned
transactionLifetimeLimitSeconds 의 정확한 기본 정수값 원문은 "less than one minute" 서술만 제공한다. 60 이라고 단정하지 않았다 MongoDB server parameters 페이지에서 해당 파라미터 기본값 확인 planned
maxStalenessSeconds 의 수치 하한 read preference 자료가 메커니즘만 설명하고 하한을 명시하지 않는다(해당 raw 의 Usage Boundaries) read preference staleness 전용 페이지 수집 planned
Spring Data MongoTemplate/Query 로 read concern 을 연산 단위로 설정하는 API 수단 spring-data-mongodb-template-config-official 문서에 "read concern"/"ReadConcern" 문자열이 0회 등장(self-grep 확인) — WriteConcernResolver 에 대응하는 read concern 결정 수단(예: ReadConcernResolver 류)이 이 페이지에 없다. D5(read concern 연산 단위 명시)의 Spring Data 측 적용 seam 이 미확보 상태 MongoDB Java driver 의 MongoCollection#withReadConcern() 공식 문서 또는 Spring Data MongoDB ClientSession/세션 스코프 문서 1건 추가 수집 UNSUPPORTED_DECISION
Spring 이 노출하는 spring.data.mongodb.* property 가 §구현 가이드 2 의 키 집합을 전부 덮는다 드라이버 옵션과 Spring property 의 대응 범위를 확인하지 않았다. §구현 가이드 2 의 UNSUPPORTED_IMPL_DECISION 이 여기에 걸려 있다 Spring Boot MongoProperties 코드/문서 확인 후 URI-쿼리 vs property 결정 planned
토폴로지·FCV 질의 명령을 최소권한 계정이 실행할 수 있다 §구현 가이드 4 의 게이트가 관리 명령에 의존하는데, 권한 부족 시 게이트 자체가 기동을 막는다 로컬 replica-set 컨테이너에 최소권한 사용자를 만들어 검증 명령 실행 planned
oplog window 를 재는 수단 (replSetGetStatus / local.oplog.rs / db.getReplicationInfo() 중 무엇) §구현 가이드 6-1 의 후보 3종이 전부 무근거다. 수집한 change stream 자료가 "측정·임계는 이 자료 범위 밖" 이라고 스스로 명시한다 change stream Production Recommendations 또는 replSetGetStatus/db.getReplicationInfo 공식 페이지 1건 수집 → §6-1 의 UNSUPPORTED_IMPL_DECISION 확정. D12 코드 작성 전에 닫는다 planned
레벨 고정 후에도 잔여 채널로 쿼리 값이 새지 않는다 §구현 가이드 8 의 "덮지 않는 채널" 4종(Command Monitoring API · 나머지 driver logger · protocolprotocol.command 상속 미확인 · Spring Data 자체 logger)이 미검증이다. "레벨만 내리면 다 막힌다" 는 주장을 하지 않았다 로컬 replica-set 에서 레벨 고정 후 실제 로그를 수집해 filter 값 유출 여부를 확인 (D18 통합 test) planned
Mongo 서버-대-DB 인증 실패의 category §구현 가이드 3 의 후보 3종(AUTH/INTERNAL/PERMANENT_DEPENDENCY)에 근거가 없고 기존 registry 에 서버-대-의존성 인증 실패 선례가 없다 registry owner(raw/branch-notes/feature-contract-registry-governance)와 category 의미 확인 후 확정 needs-confirmation
위 계약이 실제 replica-set 에서 성립한다 현재 docker-compose*.yml 에 Mongo 서비스가 없고 Mongo Testcontainers test 도 없다 — 계약을 실행해 본 적이 없다 replica-set 컨테이너 + 통합 test 추가 (완료 조건의 "concern·index manifest·replica-set 트랜잭션·change stream checkpoint test") planned

관심사 커버리지 (coverage-auditor 자동 생성 — 있을 때)

coverage-auditor 2회차(2026-07-28) 결과. Verdict: Covered — Blocking 0 / Should-fix 0 / Advisory 3. 손으로 유지하지 않는다(매 /coverage 실행 시 재생성).

관심사 상태 owner 심각도 근거
URI·timeout 3종·pool 2종·tls 명시 covered-here D2·D3·D4
read/write concern·read preference 명시 (DEC-…-MONGO-BASELINE-001) covered-here D5·D6·D7 · §구현 가이드 2-1
transaction replica-set/FCV/storage engine 게이트 covered-here D8·D9 · §구현 가이드 4
change stream replica-set 게이트 + resume token 영속화 covered-here D11 · §구현 가이드 5
oplog window 감시 covered-here(측정 수단 UNSUPPORTED_IMPL_DECISION) + delegated(임계) raw/branch-notes/feature-metrics-alerting-contract D2·D3 OK D12 · §구현 가이드 6-1
index manifest·auto-creation 금지·drift·migration runner covered-here D13 · §구현 가이드 6
migration runner 단일 실행 lock (§25 Multi-Instance Guardrail) covered-here(메커니즘 UNSUPPORTED_IMPL_DECISION) D14
retryable writes 위 애플리케이션 재시도 중첩 금지 covered-here D10
트랜잭션 재시도 라벨 covered-here(UNSUPPORTED_DECISION, 후속 dispatch 계획 명시) D9-a · §검증해야 할 주장
Mongo 쿼리·document 값 로그 유출 억제 (§11) covered-here D18 · §구현 가이드 8 (1회차 Blocking 해소)
Data integrity / DB unavailable → 실패 category covered-here(제안) raw/branch-notes/feature-contract-registry-governance OK D15 · §구현 가이드 3
query timeout covered-here(socketTimeoutMS 로 대체) Advisory D3 — per-operation maxTimeMS 는 미언급. 소켓 상한이 무한대기는 막으므로 Blocking 아님
JPA system failure (governing §11 6항목 중 1) out-of-scope raw/branch-notes/feature-persistence-failure-baseline Mongo 모듈은 JPA 미사용 — D16 이 오히려 JPA 의존을 금지
ArchUnit vendor-isolation rule covered-here D16
same-store Mongo outbox/inbox covered-here(가능 조건만) + delegated(행모델·프로토콜) raw/branch-notes/feature-outbox-dispatch-mode-contract · raw/branch-notes/feature-idempotency-ownership-protocol-contract OK D17
ReadConsistency → replica 라우팅 정책 delegated raw/branch-notes/feature-read-consistency-query-contract OK D7 · §구현 가이드 7
env key 등록·수치 delegated raw/branch-notes/feature-env-driven-runtime-configuration OK D3·D4 · §구현 가이드 2
secret 분류(URI) delegated raw/branch-notes/feature-secrets-config-source-contract OK (1회차 Should-fix 해소) D4
운영 runbook delegated(부재 신고만) raw/branch-notes/feature-operational-runbook-contract Advisory §Audit A4 — Mongo runbook 미작성, 위임 경로는 명확
TransactionPort Mongo 구현 여부 out-of-scope(조율 대기) raw/branch-notes/feature-application-port-usecase-contract OK §구현 가이드 7
활성화 축(boolean vs provider) covered-here(refines) D1
§36.2 capability card 전체 미충족(요구되지 않음) Advisory 목표 등급이 R1 Local — §36.2 는 R2 이상 주장 시에만 요구. R2 승급 시 재요구

마주친 문제

아직 없음.

묶음 (이 branch에서 파생된 자료)

관련 일일 노트

해당 없음.

완료 후 정리

  • PR 링크:
  • 리뷰 메모:
  • 머지 결과 / 배포 환경:
  • wiki 추출 대상 (verified만, wiki/projects/로만 추출):
  • 추출하지 않을 항목 (planned / documented-only / abandoned):