{ "schemaVersion": 2, "project": "clean-architecture-backend-template", "ssot": "final/document.md", "ssotSha256": "880d3a4a7dba4f6303ff69be9475190b62f2a9d03b7794482b900457ee045ad6", "generatedAt": "2026-09-04", "note": "글감 목록이다. file 이 있으면 이미 쓴 기록이고, 없으면 아직 쓰지 않은 글감이다. ssotSha256 이 지금 final/document.md 와 다르면 SSOT 가 바뀐 뒤 트리를 다시 보지 않은 것이다.", "readinessValues": [ "READY", "NEEDS_EVIDENCE", "BLOCKED", "REJECTED" ], "topics": { "admission-budget-and-backpressure": { "topic": "admission-budget-and-backpressure", "kinds": { "case": [], "concept": [ { "title": "다섯 예산 계층 중 요청 계층만 배선돼 있다", "slug": "adapter-inbound-graphql-c04", "file": "admission-budget-and-backpressure/concept/concept-adapter-inbound-graphql-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-graphql-c04", "adapter-inbound-graphql-c04-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-graphql-c04.txt" ], "relations": [] }, { "title": "요청 데드라인이 실제로 실행을 끊는 경로가 있다", "slug": "adapter-inbound-graphql-c05", "file": "admission-budget-and-backpressure/concept/concept-adapter-inbound-graphql-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-graphql-c05" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-graphql-c05.txt" ], "relations": [] }, { "title": "예산 게이트 프로퍼티가 자바 한 줄에만 있다", "slug": "adapter-inbound-web-c05", "file": "admission-budget-and-backpressure/concept/concept-adapter-inbound-web-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c05" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c05.txt" ], "relations": [] }, { "title": "forwarded 헤더를 해석하는 쪽은 피어를 검사하지 않는다", "slug": "adapter-inbound-web-c14", "file": "admission-budget-and-backpressure/concept/concept-adapter-inbound-web-c14.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c14" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c14.txt" ], "relations": [] }, { "title": "fileserver 매핑 검증은 회로가 닫혀 있다", "slug": "adapter-inbound-web-c18", "file": "admission-budget-and-backpressure/concept/concept-adapter-inbound-web-c18.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c18" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c18.txt" ], "relations": [] }, { "title": "대칭 검사기 자신을 검사하는 메타 테스트가 있다", "slug": "adapter-outbound-cache-redis-c04", "file": "admission-budget-and-backpressure/concept/concept-adapter-outbound-cache-redis-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-cache-redis-c04", "adapter-outbound-cache-redis-c04-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-cache-redis-c04.txt" ], "relations": [] }, { "title": "렌더된 키 문자열을 받는 API가 없다", "slug": "adapter-outbound-cache-redis-c05", "file": "admission-budget-and-backpressure/concept/concept-adapter-outbound-cache-redis-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-cache-redis-c05" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-cache-redis-c05.txt" ], "relations": [] }, { "title": "탈출구가 두 겹의 사전 승인으로 닫혀 있다", "slug": "adapter-outbound-cache-redis-c12", "file": "admission-budget-and-backpressure/concept/concept-adapter-outbound-cache-redis-c12.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-cache-redis-c12", "adapter-outbound-cache-redis-c12-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-cache-redis-c12.txt" ], "relations": [] }, { "title": "거부 메시지가 역할 모델을 설명하지 않는다", "slug": "adapter-outbound-fileserver-c06", "file": "admission-budget-and-backpressure/concept/concept-adapter-outbound-fileserver-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-fileserver-c06" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-fileserver-c06.txt" ], "relations": [] }, { "title": "닿지 않는 설정을 무시하지 않고 거부한다", "slug": "adapter-outbound-httpclient-c01", "file": "admission-budget-and-backpressure/concept/concept-adapter-outbound-httpclient-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-httpclient-c01" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-httpclient-c01.txt" ], "relations": [] }, { "title": "열린 회로가 토큰과 permit을 쓰기 전에 거절한다", "slug": "adapter-outbound-httpclient-c05", "file": "admission-budget-and-backpressure/concept/concept-adapter-outbound-httpclient-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-httpclient-c05", "adapter-outbound-httpclient-c05-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-httpclient-c05.txt" ], "relations": [] }, { "title": "전송의 선언이 프로파일보다 약하면 startup이 실패한다", "slug": "adapter-outbound-httpclient-c08", "file": "admission-budget-and-backpressure/concept/concept-adapter-outbound-httpclient-c08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-httpclient-c08" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-httpclient-c08.txt" ], "relations": [] }, { "title": "레거시 경로 셋이 서로 다른 스위치로 서로를 배제한다", "slug": "adapter-outbound-objectstorage-c02", "file": "admission-budget-and-backpressure/concept/concept-adapter-outbound-objectstorage-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-objectstorage-c02" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-objectstorage-c02.txt" ], "relations": [] }, { "title": "검증 권한과 삭제 권한을 분리한 staged lifecycle", "slug": "application-core-c08", "file": "admission-budget-and-backpressure/concept/concept-application-core-c08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "application-core-c08" ], "evidence": [ "../../../final/evidence/raw/application-core-c08.txt" ], "relations": [ "legacy storage/notification compatibility surface의 제거 조건 추적" ] }, { "title": "능력을 하나씩 등급 매기는 것이 설계다", "slug": "grpc-advanced-bootstrap-c01", "file": "admission-budget-and-backpressure/concept/concept-grpc-advanced-bootstrap-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-bootstrap-c01" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-bootstrap-c01.txt" ], "relations": [] }, { "title": "상한 없는 request(n)은 단계만 늘린 무제한 버퍼링이다", "slug": "grpc-advanced-streaming-c01", "file": "admission-budget-and-backpressure/concept/concept-grpc-advanced-streaming-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-streaming-c01" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-streaming-c01.txt" ], "relations": [] }, { "title": "실행 경로에서 같은 검사가 세 지점에 겹친다", "slug": "messaging-admin-api-c04", "file": "admission-budget-and-backpressure/concept/concept-messaging-admin-api-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-api-c04" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-api-c04.txt" ], "relations": [ "경로 C — 실행" ] }, { "title": "배치 상한이 개수와 바이트 두 축인 이유", "slug": "messaging-policy-c05", "file": "admission-budget-and-backpressure/concept/concept-messaging-policy-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-policy-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-policy-c05.txt" ], "relations": [ "구성 오류는 한 예외 타입과 안정 코드로 보고한다", "저장소 밖 문서를 절 번호로 인용하지 않는다", "부팅 경로의 알고리즘 복잡도는 문서화한다" ] }, { "title": "바이트 상한이 잘못된 공격에 적용돼 있었다", "slug": "messaging-schema-avro-c07", "file": "admission-budget-and-backpressure/concept/concept-messaging-schema-avro-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-avro-c07" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-avro-c07.txt" ], "relations": [ "모드 enum을 분기 조건으로 쓰면 각 분기에 테스트를 둔다", "컬렉션 순서가 계약이면 양쪽에서 같은 방향으로 적는다", "안정 코드는 판단 단위로 정하고 구현 단위로 정하지 않는다" ] }, { "title": "보장에 의존하는 순간 브리지를 거절한다", "slug": "messaging-spring-cloud-stream-bridge-c03", "file": "admission-budget-and-backpressure/concept/concept-messaging-spring-cloud-stream-bridge-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-spring-cloud-stream-bridge-c03", "messaging-spring-cloud-stream-bridge-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-spring-cloud-stream-bridge-c03.txt" ], "relations": [ "허용 의존 목록은 상한이므로 미사용을 잡지 않는다", "등록을 받는 컴포넌트는 해제도 제공한다", "함께 읽히는 두 맵은 한 값으로 묶는다", "에러 메시지가 지시하는 설정은 그 설정을 읽는 코드와 함께 존재해야 한다", "한 개념의 등록 상태를 두 객체가 나눠 갖지 않는다" ] }, { "title": "Permission의 정규화는 문법 제한이 아니다", "slug": "shared-contract-c02", "file": "admission-budget-and-backpressure/concept/concept-shared-contract-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "shared-contract-c02" ], "evidence": [ "../../../final/evidence/raw/shared-contract-c02.txt" ], "relations": [] } ], "reference": [], "question": [], "decision": [] } }, "assembly-ownership": { "topic": "assembly-ownership", "kinds": { "case": [ { "title": "하위 시스템 전체가 미배선인데 그것을 켜는 플래그는 시작 검사를 수행한다", "slug": "a-flag-that-validates-an-unwired-subsystem", "file": "assembly-ownership/case/case-a-flag-that-validates-an-unwired-subsystem.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-flag-that-validates-an-unwired-subsystem" ], "evidence": [ "../../../final/evidence/raw/a-flag-that-validates-an-unwired-subsystem.txt" ], "relations": [ "@Bean이 있다는 것은 조립 증거가 아니다", "\"꺼짐\"은 조건의 반복이 아니라 구조여야 한다" ] }, { "title": "검증기가 운영에 TLS를 요구하고, 실제로 조립되는 생산자에는 그 설정이 없다", "slug": "a-validator-that-demands-tls-and-an-assembly-that-omits-it", "file": "assembly-ownership/case/case-a-validator-that-demands-tls-and-an-assembly-that-omits-it.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-validator-that-demands-tls-and-an-assembly-that-omits-it", "a-validator-that-demands-tls-and-an-assembly-that-omits-it-run" ], "evidence": [ "../../../final/evidence/raw/a-validator-that-demands-tls-and-an-assembly-that-omits-it.txt", "../../../final/evidence/raw/a-validator-that-demands-tls-and-an-assembly-that-omits-it-run.txt" ], "relations": [ "조립 결함을 판정하려면 조립하는 쪽을 먼저 읽어야 한다", "검증기는 발행이 아니라 주입이 강제다", "\"꺼짐\"은 조건의 반복이 아니라 구조여야 한다" ] }, { "title": "플래그는 고정 거짓이라 능력 검사를 끄지만, 조립 조건이 아니라서 소비자 빈은 그대로 생성된다", "slug": "a06-f018-changestreams-false", "file": "assembly-ownership/case/case-a06-f018-changestreams-false.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a06-f018-changestreams-false", "a06-f018-changestreams-false-wiring" ], "evidence": [ "../../../final/evidence/raw/a06-f018-changestreams-false.txt", "../../../final/evidence/raw/a06-f018-changestreams-false-wiring.txt" ], "relations": [ "거부라고 적힌 처리가 폐기이고, 그 값을 읽는 시작 검사는 켤 방법이 없다", "하위 시스템 전체가 미배선인데 그것을 켜는 플래그는 시작 검사를 수행한다", "@Bean이 있다는 것은 조립 증거가 아니다" ] }, { "title": "이름만 AutoConfiguration이던 세 클래스가 capability 리포트에 Stable로 올라 있었다", "slug": "autoconfiguration-in-name-only", "file": "assembly-ownership/case/case-autoconfiguration-in-name-only.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "autoconfiguration-in-name-only" ], "evidence": [ "../../../final/evidence/raw/autoconfiguration-in-name-only.txt" ], "relations": [ "@Bean이 있다는 것은 조립 증거가 아니다", "조건부 빈의 평가 시점 — 파싱 시점과 등록 시점", "시작 검증기가 도는지는 그 능력에 자동설정 루트가 있는지와 일치한다" ] }, { "title": "'@ConditionalOnBean(DataSource.class)가 클래스 파싱 시점에 평가되어 여덟 빈이 사라졌다'", "slug": "conditionalonbean-evaluated-at-parse-time", "file": "assembly-ownership/case/case-conditionalonbean-evaluated-at-parse-time.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "conditionalonbean-evaluated-at-parse-time" ], "evidence": [ "../../../final/evidence/raw/conditionalonbean-evaluated-at-parse-time.txt" ], "relations": [ "조건부 빈의 평가 시점 — 파싱 시점과 등록 시점", "ConditionalOnBean 사슬의 실제 평가 순서를 확인하지 않았다", "이름만 AutoConfiguration이던 세 클래스가 capability 리포트에 Stable로 올라 있었다" ] }, { "title": "넓은 스캔을 좁히자 여덟 컴포넌트에 아무것도 도달하지 않았다", "slug": "narrowing-the-scan-orphaned-eight-components", "file": "assembly-ownership/case/case-narrowing-the-scan-orphaned-eight-components.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "narrowing-the-scan-orphaned-eight-components" ], "evidence": [ "../../../final/evidence/raw/narrowing-the-scan-orphaned-eight-components.txt" ], "relations": [ "스캔에서 뺀 다섯 패키지의 컴포넌트 여섯을 두 자동설정 어느 쪽도 소유하지 않았다", "꺼짐은 조건의 반복이 아니라 구조여야 한다", "@Bean이 있다는 것은 조립 증거가 아니다" ] }, { "title": "관측을 필수 생성자 인자로 만든 수정을 조립이 6인자 생성자로 되돌렸다", "slug": "observation-downgraded-by-the-composition", "file": "assembly-ownership/case/case-observation-downgraded-by-the-composition.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "observation-downgraded-by-the-composition" ], "evidence": [ "../../../final/evidence/raw/observation-downgraded-by-the-composition.txt", "../../../final/evidence/raw/tl-messaging-observation-noop.txt" ], "relations": [ "@Bean이 있다는 것은 조립 증거가 아니다", "조립 결함을 판정하려면 조립하는 쪽을 먼저 읽어야 한다", "outbox가 둘이고, 출하되는 것은 messaging 플랫폼 쪽이 아니다" ] }, { "title": "outbox 가 둘이고, 출하되는 것은 messaging 플랫폼 쪽이 아니다", "slug": "outbox-chain-behind-an-unsatisfiable-condition", "file": "assembly-ownership/case/case-outbox-chain-behind-an-unsatisfiable-condition.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "outbox-chain-behind-an-unsatisfiable-condition" ], "evidence": [ "../../../final/evidence/raw/outbox-chain-behind-an-unsatisfiable-condition.txt", "../../../final/evidence/raw/tl-outbox-unsatisfiable-condition.txt" ], "relations": [ "@Bean이 있다는 것은 조립 증거가 아니다", "@ConditionalOnBean은 조건이 만족될 수 있는지까지 확인해야 한다", "조립 결함을 판정하려면 조립하는 쪽을 먼저 읽어야 한다", "high-water mark가 본 위치를 뜻해서 재전달된 변경이 영구히 사라졌다" ] }, { "title": "스캔에서 뺀 다섯 패키지의 컴포넌트 여섯을 두 자동설정 어느 쪽도 소유하지 않았다", "slug": "scan-exclusion-without-an-owner", "file": "assembly-ownership/case/case-scan-exclusion-without-an-owner.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "scan-exclusion-without-an-owner" ], "evidence": [ "../../../final/evidence/raw/scan-exclusion-without-an-owner.txt", "../../../final/evidence/raw/tl-web-six-unowned-components.txt" ], "relations": [ "@Bean이 있다는 것은 조립 증거다가 아니다", "Spring 조립의 세 경로와 각각이 결정하는 것", "꺼짐은 조건의 반복이 아니라 구조여야 한다" ] }, { "title": "시작 검증기 13개 규칙이 유일한 조립 지점에서 호출되지 않는다", "slug": "thirteen-startup-rules-never-run", "file": "assembly-ownership/case/case-thirteen-startup-rules-never-run.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "thirteen-startup-rules-never-run" ], "evidence": [ "../../../final/evidence/raw/thirteen-startup-rules-never-run.txt" ], "relations": [ "시작 검증기가 도는지는 그 능력에 자동설정 루트가 있는지와 일치한다", "@Bean이 있다는 것은 조립 증거가 아니다" ] } ], "concept": [ { "title": "Spring 조립의 세 경로와 각각이 결정하는 것", "slug": "three-assembly-paths", "file": "assembly-ownership/concept/concept-three-assembly-paths.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "three-assembly-paths", "three-assembly-paths-diagram" ], "evidence": [ "../../../final/evidence/raw/three-assembly-paths.txt", "../../../final/evidence/raw/tl-web-six-unowned-components.txt" ], "relations": [ "스캔에서 뺀 다섯 패키지의 컴포넌트 여섯을 두 자동설정 어느 쪽도 소유하지 않았다", "넓은 스캔을 좁히자 여덟 컴포넌트에 아무것도 도달하지 않았다", "@Bean이 있다는 것은 조립 증거가 아니다" ] }, { "title": "조건부 빈의 평가 시점 — 파싱 시점과 등록 시점", "slug": "when-conditions-are-evaluated", "file": "assembly-ownership/concept/concept-when-conditions-are-evaluated.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "when-conditions-are-evaluated" ], "evidence": [ "../../../final/evidence/raw/when-conditions-are-evaluated.txt" ], "relations": [ "ConditionalOnBean(DataSource)이 클래스 파싱 시점에 평가되어 여덟 빈이 사라졌다", "ConditionalOnBean은 조건이 만족될 수 있는지까지 확인해야 한다", "ConditionalOnBean 사슬의 실제 평가 순서를 확인하지 않았다" ] } ], "reference": [ { "title": "'@Bean이 있다는 것은 조립 증거가 아니다'", "slug": "a-bean-is-not-composition-evidence", "file": "assembly-ownership/reference/reference-a-bean-is-not-composition-evidence.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "스캔에서 뺀 다섯 패키지의 컴포넌트 여섯을 두 자동설정 어느 쪽도 소유하지 않았다", "outbox가 둘이고, 출하되는 것은 messaging 플랫폼 쪽이 아니다", "Spring 조립의 세 경로와 각각이 결정하는 것" ] }, { "title": "'@ConditionalOnBean은 조건이 만족될 수 있는지까지 확인해야 한다'", "slug": "conditionalonbean-must-be-satisfiable", "file": "assembly-ownership/reference/reference-conditionalonbean-must-be-satisfiable.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "outbox가 둘이고, 출하되는 것은 messaging 플랫폼 쪽이 아니다", "조건부 빈의 평가 시점 — 파싱 시점과 등록 시점" ] }, { "title": "프레임워크가 기여하는 자동설정까지 세지 않으면 스위치가 아니다", "slug": "count-the-frameworks-own-autoconfigurations", "file": "assembly-ownership/reference/reference-count-the-frameworks-own-autoconfigurations.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "풀이 필요한지는 JPA가 켜졌나가 아니라 커넥션이 필요한 capability가 있나로 묻는다", "꺼짐은 조건의 반복이 아니라 구조여야 한다" ] }, { "title": "'\"꺼짐\"은 조건의 반복이 아니라 구조여야 한다'", "slug": "off-must-be-structural", "file": "assembly-ownership/reference/reference-off-must-be-structural.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "마스터 스위치는 루트 하나가 소유하고 자식 설정은 조건을 갖지 않는다", "넓은 스캔을 좁히자 여덟 컴포넌트에 아무것도 도달하지 않았다", "프레임워크가 기여하는 자동설정까지 세지 않으면 스위치가 아니다" ] }, { "title": "조립 결함을 판정하려면 조립하는 쪽을 먼저 읽어야 한다", "slug": "read-the-assembling-side-first", "file": "assembly-ownership/reference/reference-read-the-assembling-side-first.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "outbox가 둘이고, 출하되는 것은 messaging 플랫폼 쪽이 아니다", "관측을 필수 생성자 인자로 만든 수정을 조립이 6인자 생성자로 되돌렸다" ] }, { "title": "시작 검증기가 도는지는 그 능력에 자동설정 루트가 있는지와 일치한다", "slug": "the-startup-validator-follows-the-autoconfiguration-root", "file": "assembly-ownership/reference/reference-the-startup-validator-follows-the-autoconfiguration-root.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "시작 검증기 13개 규칙이 유일한 조립 지점에서 호출되지 않는다", "Bean 애너테이션이 있다는 것은 조립 증거가 아니다" ] } ], "question": [ { "title": "'@ConditionalOnBean 사슬의 실제 평가 순서를 확인하지 않았다'", "slug": "conditional-evaluation-order-unverified", "file": "assembly-ownership/question/openquestion-conditional-evaluation-order-unverified.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "outbox가 둘이고, 출하되는 것은 messaging 플랫폼 쪽이 아니다", "ConditionalOnBean(DataSource)이 클래스 파싱 시점에 평가되어 여덟 빈이 사라졌다", "조건부 빈의 평가 시점 — 파싱 시점과 등록 시점", "부팅 한 번으로 확증 가능한 두 건이 아직 정적 추론으로만 남아 있다" ] }, { "title": "부팅 한 번으로 확증 가능한 두 건이 아직 정적 추론으로만 남아 있다", "slug": "one-boot-would-settle-two-findings", "file": "assembly-ownership/question/openquestion-one-boot-would-settle-two-findings.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "관측을 필수 생성자 인자로 만든 수정을 조립이 6인자 생성자로 되돌렸다", "outbox가 둘이고, 출하되는 것은 messaging 플랫폼 쪽이 아니다" ] } ], "decision": [ { "title": "마스터 스위치는 루트 하나가 소유하고 자식 설정은 조건을 갖지 않는다", "slug": "one-root-owns-the-master-switch", "file": "assembly-ownership/decision/decision-one-root-owns-the-master-switch.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "꺼짐은 조건의 반복이 아니라 구조여야 한다", "프레임워크가 기여하는 자동설정까지 세지 않으면 스위치가 아니다", "스캔에서 뺀 다섯 패키지의 컴포넌트 여섯을 두 자동설정 어느 쪽도 소유하지 않았다" ] }, { "title": "풀이 필요한지는 \"JPA가 켜졌나\"가 아니라 \"커넥션이 필요한 capability가 있나\"로 묻는다", "slug": "pool-need-is-a-capability-question", "file": "assembly-ownership/decision/decision-pool-need-is-a-capability-question.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "프레임워크가 기여하는 자동설정까지 세지 않으면 스위치가 아니다", "꺼짐은 조건의 반복이 아니라 구조여야 한다", "마스터 스위치는 루트 하나가 소유하고 자식 설정은 조건을 갖지 않는다" ] } ] } }, "bounding-by-type": { "topic": "bounding-by-type", "kinds": { "case": [ { "title": "진단 리포트가 살아 있는 리소스를 담지 않도록 값 타입을 좁혔다", "slug": "a-report-that-cannot-carry-a-datasource", "file": "bounding-by-type/case/case-a-report-that-cannot-carry-a-datasource.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-report-that-cannot-carry-a-datasource" ], "evidence": [ "../../../final/evidence/raw/a-report-that-cannot-carry-a-datasource.txt" ], "relations": [ "관측을 위해 수집한 데이터가 관측 대상보다 위험할 수 있다", "시그니처가 payload를 받지 않는데 예외 메시지로 PII가 로그에 남았다", "카디널리티 경계를 타입으로 표현하기" ] }, { "title": "안전하다고 적힌 값이 같은 모듈의 저카디널리티 정의를 통과하지 못한다", "slug": "a05-f004-retrydecision-reason", "file": "bounding-by-type/case/case-a05-f004-retrydecision-reason.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a05-f004-retrydecision-reason", "a05-f004-retrydecision-reason-probe" ], "evidence": [ "../../../final/evidence/raw/a05-f004-retrydecision-reason.txt", "../../../final/evidence/raw/a05-f004-retrydecision-reason-probe.txt" ], "relations": [ "카디널리티 경계를 타입으로 표현하기", "CapabilitySupport.constraints 의 경계가 타입에 없다", "이름은 값이 아니라 registry key다" ] }, { "title": "커서 서명 검증이 길이·상수시간·순서를 전부 지켜야 했던 이유", "slug": "cursor-verification-order", "file": "bounding-by-type/case/case-cursor-verification-order.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "cursor-verification-order" ], "evidence": [ "../../../final/evidence/raw/cursor-verification-order.txt" ], "relations": [ "서명된 커서의 구조와 검증 순서", "커서에 서명하는 이유는 기밀성이 아니라 무결성이다" ] }, { "title": "시그니처가 payload를 받지 않는데 예외 메시지로 PII가 로그에 남았다", "slug": "pii-through-an-exception-message", "file": "bounding-by-type/case/case-pii-through-an-exception-message.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "pii-through-an-exception-message" ], "evidence": [ "../../../final/evidence/raw/pii-through-an-exception-message.txt" ], "relations": [ "관측을 위해 수집한 데이터가 관측 대상보다 위험할 수 있다", "sanitize가 아니라 reject가 기본이다", "카디널리티 경계를 타입으로 표현하기" ] } ], "concept": [ { "title": "카디널리티 경계를 타입으로 표현하기", "slug": "cardinality-bounds-as-types", "file": "bounding-by-type/concept/concept-cardinality-bounds-as-types.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "cardinality-bounds-as-types", "cardinality-bounds-as-types-diagram" ], "evidence": [ "../../../final/evidence/raw/cardinality-bounds-as-types.txt" ], "relations": [ "tenant id는 메트릭 태그가 되지 않는다", "관측을 위해 수집한 데이터가 관측 대상보다 위험할 수 있다", "이름은 값이 아니라 registry key다" ] }, { "title": "서명된 커서의 구조와 검증 순서", "slug": "signed-cursor-structure", "file": "bounding-by-type/concept/concept-signed-cursor-structure.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "signed-cursor-structure", "signed-cursor-structure-diagram" ], "evidence": [ "../../../final/evidence/raw/signed-cursor-structure.txt" ], "relations": [ "커서에 서명하는 이유는 기밀성이 아니라 무결성이다", "커서 서명 검증이 길이·상수시간·순서를 전부 지켜야 했던 이유" ] } ], "reference": [ { "title": "이름은 값이 아니라 registry key다", "slug": "names-are-registry-keys-not-values", "file": "bounding-by-type/reference/reference-names-are-registry-keys-not-values.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "카디널리티 경계를 타입으로 표현하기", "path·identifier는 등록하고 value는 바인딩한다" ] }, { "title": "path·identifier는 등록하고 value는 바인딩한다", "slug": "register-paths-bind-values", "file": "bounding-by-type/reference/reference-register-paths-bind-values.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "이름은 값이 아니라 registry key다", "sanitize가 아니라 reject가 기본이다", "서명된 커서의 구조와 검증 순서" ] }, { "title": "sanitize가 아니라 reject가 기본이다", "slug": "reject-rather-than-sanitize", "file": "bounding-by-type/reference/reference-reject-rather-than-sanitize.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "시그니처가 payload를 받지 않는데 예외 메시지로 PII가 로그에 남았다", "path·identifier는 등록하고 value는 바인딩한다" ] }, { "title": "관측을 위해 수집한 데이터가 관측 대상보다 위험할 수 있다", "slug": "telemetry-can-be-more-dangerous-than-its-subject", "file": "bounding-by-type/reference/reference-telemetry-can-be-more-dangerous-than-its-subject.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "진단 리포트가 살아 있는 리소스를 담지 않도록 값 타입을 좁혔다", "시그니처가 payload를 받지 않는데 예외 메시지로 PII가 로그에 남았다", "tenant id는 메트릭 태그가 되지 않는다" ] } ], "question": [], "decision": [ { "title": "커서에 서명하는 이유는 기밀성이 아니라 무결성이다", "slug": "cursors-are-signed-for-integrity", "file": "bounding-by-type/decision/decision-cursors-are-signed-for-integrity.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "서명된 커서의 구조와 검증 순서", "커서 서명 검증이 길이·상수시간·순서를 전부 지켜야 했던 이유", "path·identifier는 등록하고 value는 바인딩한다" ] }, { "title": "tenant id는 메트릭 태그가 되지 않는다", "slug": "tenant-id-is-never-a-metric-tag", "file": "bounding-by-type/decision/decision-tenant-id-is-never-a-metric-tag.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "카디널리티 경계를 타입으로 표현하기", "관측을 위해 수집한 데이터가 관측 대상보다 위험할 수 있다", "이름은 값이 아니라 registry key다" ] } ] } }, "caching-and-redis": { "topic": "caching-and-redis", "kinds": { "case": [ { "title": "표가 증거로 지목한 시험이 그 표를 반증한다", "slug": "a10-f001-readme", "file": "caching-and-redis/case/case-a10-f001-readme.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a10-f001-readme", "a10-f001-readme-counts" ], "evidence": [ "../../../final/evidence/raw/a10-f001-readme.txt", "../../../final/evidence/raw/a10-f001-readme-counts.txt" ], "relations": [ "문서 계약 테스트의 단언 경계 밖에 발견된 드리프트 세 건이 전부 있었다", "README의 세 가지 사실 오류", "산문이 선언한 게이트는 빌드에 있는 게이트가 아니다" ] }, { "title": "상한을 주입받는 자리는 있고 주입하는 곳은 없다", "slug": "a10-f004-pub-sub", "file": "caching-and-redis/case/case-a10-f004-pub-sub.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a10-f004-pub-sub", "a10-f004-pub-sub-bound" ], "evidence": [ "../../../final/evidence/raw/a10-f004-pub-sub.txt", "../../../final/evidence/raw/a10-f004-pub-sub-bound.txt" ], "relations": [ "채워 넣은 상한은 자기가 잴 요청에서 값을 가져온다", "R1과 R2의 설정 취급이 비대칭이고, 검증된 쪽은 하나뿐이다", "그 속성을 보일 수 없는 대역 위에서 통과한 테스트는 증인이 아니다" ] }, { "title": "채워 넣은 상한은 자기가 잴 요청에서 값을 가져온다", "slug": "a10-f005-hyperloglog-merge", "file": "caching-and-redis/case/case-a10-f005-hyperloglog-merge.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a10-f005-hyperloglog-merge", "a10-f005-hyperloglog-merge-scope", "a10-f005-hyperloglog-merge-budget" ], "evidence": [ "../../../final/evidence/raw/a10-f005-hyperloglog-merge.txt", "../../../final/evidence/raw/a10-f005-hyperloglog-merge-scope.txt", "../../../final/evidence/raw/a10-f005-hyperloglog-merge-budget.txt" ], "relations": [ "상한을 주입받는 자리는 있고 주입하는 곳은 없다", "미배선 인터셉터는 누락이 아니라 중복이다", "타입이 문서화한 불변식은 타입이 강제한다" ] }, { "title": "지워도 test가 초록인 검사가 셋이다", "slug": "a10-f006-requireidentifier", "file": "caching-and-redis/case/case-a10-f006-requireidentifier.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a10-f006-requireidentifier", "a10-f006-requireidentifier-branch" ], "evidence": [ "../../../final/evidence/raw/a10-f006-requireidentifier.txt", "../../../final/evidence/raw/a10-f006-requireidentifier-branch.txt" ], "relations": [ "커버리지 gate 둘이 나란히 있고, 하나는 발화할 수 없다", "그 속성을 보일 수 없는 대역 위에서 통과한 테스트는 증인이 아니다", "상한을 주입받는 자리는 있고 주입하는 곳은 없다" ] }, { "title": "SDK가 선언한 두 진입점에 구현이 없다", "slug": "analysis-finding-a10-f003", "file": "caching-and-redis/case/case-analysis-finding-a10-f003.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a10-f003" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a10-f003.txt" ], "relations": [ "README readiness 표가 있는 것을 없다고 적는다", "미배선 경계가 문서에만 있고 compile 경로에서 닫히지 않는다", "인터페이스끼리 비교하는 test는 구현의 부재를 못 본다" ] }, { "title": "패턴 구독의 R2 승인만 호출자가 아니라 배포에 대해 이루어진다", "slug": "analysis-finding-a10-f007", "file": "caching-and-redis/case/case-analysis-finding-a10-f007.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a10-f007" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a10-f007.txt" ], "relations": [ "같은 위험 등급에 두 승인 모델이 있으면 차이를 문서가 적어야 한다", "permit 정책 이름이 세 곳에 문자열로 존재하고 교차 검사가 없다", "식별자 검증의 다섯 검사 중 둘은 도달할 수 없다" ] }, { "title": "permit 정책 이름이 세 곳에 문자열로 존재하고 교차 검사가 없다", "slug": "analysis-finding-a10-f008", "file": "caching-and-redis/case/case-analysis-finding-a10-f008.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a10-f008" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a10-f008.txt" ], "relations": [ "패턴 구독의 승인만 호출자가 아니라 배포에 대해 이루어진다", "문자열로 이어진 두 세계는 오타에서 조용히 갈라진다", "catalog drift gate는 서버 메타데이터와 대조하지 Java 상수와 대조하지 않는다" ] } ], "concept": [], "reference": [], "question": [], "decision": [] } }, "capability-and-disclosure-models": { "topic": "capability-and-disclosure-models", "kinds": { "case": [], "concept": [ { "title": "상호배타성이 프로퍼티가 아니라 타입에서 온다", "slug": "adapter-inbound-web-c01", "file": "capability-and-disclosure-models/concept/concept-adapter-inbound-web-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c01", "adapter-inbound-web-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c01.txt" ], "relations": [] }, { "title": "ndjson 스위치 하나가 두 능력을 함께 켠다", "slug": "adapter-inbound-web-c17", "file": "capability-and-disclosure-models/concept/concept-adapter-inbound-web-c17.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c17" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c17.txt" ], "relations": [] }, { "title": "컴파일이 전부 끝난 뒤에야 생성이 시작된다", "slug": "adapter-outbound-objectstorage-c01", "file": "capability-and-disclosure-models/concept/concept-adapter-outbound-objectstorage-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-objectstorage-c01", "adapter-outbound-objectstorage-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-objectstorage-c01.txt" ], "relations": [] }, { "title": "레지스트리가 덮는 것은 문서 주장이고 설정 경로가 아니다", "slug": "adapter-outbound-objectstorage-c08", "file": "capability-and-disclosure-models/concept/concept-adapter-outbound-objectstorage-c08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-objectstorage-c08" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-objectstorage-c08.txt" ], "relations": [] }, { "title": "질의 계층은 프레임워크가 아니라 세 단계의 정책층이다", "slug": "adapter-outbound-persistence-jpa-c24", "file": "capability-and-disclosure-models/concept/concept-adapter-outbound-persistence-jpa-c24.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c24", "adapter-outbound-persistence-jpa-c24-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c24.txt" ], "relations": [] }, { "title": "세 환경 검증기의 관심사가 서로 다르다", "slug": "app-bootstrap-c01", "file": "capability-and-disclosure-models/concept/concept-app-bootstrap-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "app-bootstrap-c01" ], "evidence": [ "../../../final/evidence/raw/app-bootstrap-c01.txt" ], "relations": [] }, { "title": "런타임 멤버십이 결정하는 어댑터 활성화 스위치 범위", "slug": "app-bootstrap-c02", "file": "capability-and-disclosure-models/concept/concept-app-bootstrap-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "app-bootstrap-c02" ], "evidence": [ "../../../final/evidence/raw/app-bootstrap-c02.txt" ], "relations": [] }, { "title": ".imports 여섯 줄 중 다섯이 능력 루트다", "slug": "app-bootstrap-c03", "file": "capability-and-disclosure-models/concept/concept-app-bootstrap-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "app-bootstrap-c03" ], "evidence": [ "../../../final/evidence/raw/app-bootstrap-c03.txt" ], "relations": [] }, { "title": "진단 열람은 망 게이트와 역할 게이트를 함께 요구한다", "slug": "grpc-advanced-diagnostics-c02", "file": "capability-and-disclosure-models/concept/concept-grpc-advanced-diagnostics-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-diagnostics-c02", "grpc-advanced-diagnostics-c02-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-diagnostics-c02.txt" ], "relations": [] }, { "title": "이전 결함 대신 막으려는 것 셋을 적는다", "slug": "messaging-kafka-share-experimental-c07", "file": "capability-and-disclosure-models/concept/concept-messaging-kafka-share-experimental-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-kafka-share-experimental-c07" ], "evidence": [ "../../../final/evidence/raw/messaging-kafka-share-experimental-c07.txt" ], "relations": [ "허용 의존 목록은 상한이므로 미사용을 잡지 않는다 — 그것을 잡으려면 별도 검사가 필요하다", "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "에러 메시지가 지시하는 설정은 그 설정을 읽는 코드와 함께 존재해야 한다", "구성 오류는 한 예외 타입과 안정 코드로 보고한다" ] }, { "title": "등급을 판정하는 경로가 증거를 만드는 경로 없이도 돈다", "slug": "messaging-testkit-c05", "file": "capability-and-disclosure-models/concept/concept-messaging-testkit-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-testkit-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-testkit-c05.txt" ], "relations": [] } ], "reference": [], "question": [], "decision": [] } }, "capability-declaration-vs-proof": { "topic": "capability-declaration-vs-proof", "kinds": { "case": [ { "title": "지연 배달을 참으로 선언하는데 그 지연을 제공할 토폴로지가 조립되지 않는다", "slug": "a-delayed-delivery-flag-without-the-topology-that-delivers-it", "file": "capability-declaration-vs-proof/case/case-a-delayed-delivery-flag-without-the-topology-that-delivers-it.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-delayed-delivery-flag-without-the-topology-that-delivers-it" ], "evidence": [ "../../../final/evidence/raw/a-delayed-delivery-flag-without-the-topology-that-delivers-it.txt" ], "relations": [ "능력 선언의 세 출처와 그것이 파생되지 않을 때", "능력 선언은 프로파일에서 파생되어야 하고 상수는 그것을 할 수 없다", "선택할 수 없는 브로커가 지원 매트릭스에 기능 목록과 함께 실려 있다" ] }, { "title": "브로커 트랜잭션을 무조건 참으로 선언하고, 그 조건을 검사하는 검증기는 기동 시 돌지 않는다", "slug": "a-transaction-capability-true-and-its-validator-never-run", "file": "capability-declaration-vs-proof/case/case-a-transaction-capability-true-and-its-validator-never-run.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-transaction-capability-true-and-its-validator-never-run" ], "evidence": [ "../../../final/evidence/raw/a-transaction-capability-true-and-its-validator-never-run.txt" ], "relations": [ "능력 선언의 세 출처와 그것이 파생되지 않을 때", "검증기는 발행이 아니라 주입이 강제다", "능력 선언은 프로파일에서 파생되어야 하고 상수는 그것을 할 수 없다" ] }, { "title": "안정 등급으로 광고한 증거를 만드는 매니저가 어디서도 만들어지지 않는다", "slug": "a05-f006-stable", "file": "capability-declaration-vs-proof/case/case-a05-f006-stable.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a05-f006-stable", "a05-f006-stable-chain" ], "evidence": [ "../../../final/evidence/raw/a05-f006-stable.txt", "../../../final/evidence/raw/a05-f006-stable-chain.txt" ], "relations": [ "커밋 증거 단계 — NOT_STARTED에서 UNKNOWN까지", "@Bean이 있다는 것은 조립 증거가 아니다", "지원 등급은 추론이 아니라 선언이고 증거 없이는 올라가지 않는다" ] }, { "title": "검증기는 도는데 정책을 넘기는 한 번의 호출이 없다", "slug": "a05-f022-stable", "file": "capability-declaration-vs-proof/case/case-a05-f022-stable.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a05-f022-stable" ], "evidence": [ "../../../final/evidence/raw/a05-f022-stable.txt" ], "relations": [ "시작 검증기가 도는지는 그 능력에 자동설정 루트가 있는지와 일치한다", "지원 등급은 추론이 아니라 선언이고 증거 없이는 올라가지 않는다", "RLS가 성립하기 위한 세 전제" ] }, { "title": "운영자용 지원 매트릭스가 런타임 편입을 반대로 적고, 틀린 쪽이 옳은 쪽을 권위로 지목한다", "slug": "the-support-matrix-says-nothing-is-deployed-and-eighteen-are", "file": "capability-declaration-vs-proof/case/case-the-support-matrix-says-nothing-is-deployed-and-eighteen-are.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "the-support-matrix-says-nothing-is-deployed-and-eighteen-are" ], "evidence": [ "../../../final/evidence/raw/the-support-matrix-says-nothing-is-deployed-and-eighteen-are.txt" ], "relations": [ "문서의 수치는 세지 말고 파생하거나 게이트로 붙든다", "과대 진술 문서를 과소보다 먼저 고친다", "다섯 문서가 \"exactly 19 leaf\"라고 적고 레지스트리는 62다" ] }, { "title": "같은 어댑터의 능력을 전송과 검증기가 다르게 답하고, 런타임이 쓰는 쪽이 record 의 의미와 어긋난다", "slug": "the-transport-and-the-validator-answer-differently", "file": "capability-declaration-vs-proof/case/case-the-transport-and-the-validator-answer-differently.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "the-transport-and-the-validator-answer-differently" ], "evidence": [ "../../../final/evidence/raw/the-transport-and-the-validator-answer-differently.txt" ], "relations": [ "능력 선언의 세 출처와 그것이 파생되지 않을 때", "능력 플래그의 무게는 그것을 읽는 코드가 정한다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다" ] } ], "concept": [ { "title": "능력 선언의 세 출처와 그것이 파생되지 않을 때", "slug": "three-sources-of-a-capability-answer", "file": "capability-declaration-vs-proof/concept/concept-three-sources-of-a-capability-answer.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "three-sources-of-a-capability-answer", "three-sources-of-a-capability-answer-diagram" ], "evidence": [ "../../../final/evidence/raw/three-sources-of-a-capability-answer.txt" ], "relations": [ "능력 선언은 프로파일에서 파생되어야 하고 상수는 그것을 할 수 없다", "능력 플래그의 무게는 그것을 읽는 코드가 정한다", "능력 상수가 프로파일 조건보다 오래 살아서 중복 제거 없는 목적지가 가드를 통과한다" ] } ], "reference": [ { "title": "능력 선언은 프로파일에서 파생되어야 하고 상수는 그것을 할 수 없다", "slug": "a-capability-constant-must-derive-from-the-profile", "file": "capability-declaration-vs-proof/reference/reference-a-capability-constant-must-derive-from-the-profile.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "능력 선언의 세 출처와 그것이 파생되지 않을 때", "능력 상수가 프로파일 조건보다 오래 살아서 중복 제거 없는 목적지가 가드를 통과한다", "브로커 트랜잭션을 무조건 참으로 선언하고, 그 조건을 검사하는 검증기는 기동 시 돌지 않는다" ] }, { "title": "능력 플래그의 무게는 그것을 읽는 코드가 정한다", "slug": "the-weight-of-a-flag-is-set-by-the-code-that-reads-it", "file": "capability-declaration-vs-proof/reference/reference-the-weight-of-a-flag-is-set-by-the-code-that-reads-it.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "능력 선언의 세 출처와 그것이 파생되지 않을 때", "같은 어댑터의 능력을 전송과 검증기가 다르게 답하고, 런타임이 쓰는 쪽이 문서화된 의미와 어긋난다", "`runtime_memberships`를 먼저 읽고 심각도를 정한다" ] } ], "question": [], "decision": [] } }, "commit-ambiguity-as-a-result": { "topic": "commit-ambiguity-as-a-result", "kinds": { "case": [ { "title": "pg_terminate_backend가 57P01로 도착하고 커밋 레코드는 이미 WAL에 있었다", "slug": "commit-ambiguity-is-not-only-sqlstate-08", "file": "commit-ambiguity-as-a-result/case/case-commit-ambiguity-is-not-only-sqlstate-08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "commit-ambiguity-is-not-only-sqlstate-08" ], "evidence": [ "../../../final/evidence/raw/commit-ambiguity-is-not-only-sqlstate-08.txt" ], "relations": [ "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다", "커밋 모호성 판정은 넓혀도 좁혀도 해롭다", "completion-unknown은 자동으로도 수동으로도 재시도하지 않는다", "커밋 모호성 계약 레인이 이 리비전에서 통과하는지 실행으로 확인되지 않았다" ] }, { "title": "high-water mark가 \"본 위치\"를 뜻해서 재전달된 변경이 영구히 사라졌다", "slug": "high-water-mark-swallowed-a-redelivered-change", "file": "commit-ambiguity-as-a-result/case/case-high-water-mark-swallowed-a-redelivered-change.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "high-water-mark-swallowed-a-redelivered-change" ], "evidence": [ "../../../final/evidence/raw/high-water-mark-swallowed-a-redelivered-change.txt" ], "relations": [ "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다", "조건이 만족될 수 없는 outbox 사슬" ] }, { "title": "커밋 증거 프레임을 두 주인이 pop해서 바깥 트랜잭션의 실패가 익명이 됐다", "slug": "two-owners-popped-the-evidence-frame", "file": "commit-ambiguity-as-a-result/case/case-two-owners-popped-the-evidence-frame.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "two-owners-popped-the-evidence-frame" ], "evidence": [ "../../../final/evidence/raw/two-owners-popped-the-evidence-frame.txt" ], "relations": [ "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다", "재시도 단위는 statement가 아니라 유스케이스 전체다", "커밋 증거 단계 — NOT_STARTED에서 UNKNOWN까지" ] }, { "title": "번역되지 않은 경합 예외가 재시도 코디네이터의 catch를 통째로 비껴갔다", "slug": "untranslated-contention-bypassed-the-retry-catch", "file": "commit-ambiguity-as-a-result/case/case-untranslated-contention-bypassed-the-retry-catch.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "untranslated-contention-bypassed-the-retry-catch" ], "evidence": [ "../../../final/evidence/raw/untranslated-contention-bypassed-the-retry-catch.txt" ], "relations": [ "실패 번역 사슬의 순서는 계약이다", "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다", "아무도 부르지 않는 재시도 구현" ] } ], "concept": [ { "title": "커밋 증거 단계 — NOT_STARTED에서 UNKNOWN까지", "slug": "commit-evidence-phases", "file": "commit-ambiguity-as-a-result/concept/concept-commit-evidence-phases.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "commit-evidence-phases", "commit-evidence-phases-diagram" ], "evidence": [ "../../../final/evidence/raw/commit-evidence-phases.txt" ], "relations": [ "커밋 증거 프레임을 두 주인이 pop해서 바깥 트랜잭션의 실패가 익명이 됐다", "pg_terminate_backend가 57P01로 도착하고 커밋 레코드는 이미 WAL에 있었다", "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다", "completion-unknown은 자동으로도 수동으로도 재시도하지 않는다" ] }, { "title": "트랜잭션 결과 대수 — 다섯 변형이 각각 답하는 질문", "slug": "transaction-result-algebra", "file": "commit-ambiguity-as-a-result/concept/concept-transaction-result-algebra.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "transaction-result-algebra" ], "evidence": [ "../../../final/evidence/raw/transaction-result-algebra.txt" ], "relations": [ "커밋 증거 단계 — NOT_STARTED에서 UNKNOWN까지", "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다", "위험한 조합은 정책이 아니라 생성자가 거부하게 만든다" ] } ], "reference": [ { "title": "커밋 모호성 판정은 넓혀도 좁혀도 해롭다", "slug": "ambiguity-rule-hurts-both-ways", "file": "commit-ambiguity-as-a-result/reference/reference-ambiguity-rule-hurts-both-ways.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "pg_terminate_backend가 57P01로 도착하고 커밋 레코드는 이미 WAL에 있었다", "completion-unknown은 자동으로도 수동으로도 재시도하지 않는다" ] }, { "title": "위험한 조합은 정책이 아니라 생성자가 거부하게 만든다", "slug": "make-the-unsafe-state-unrepresentable", "file": "commit-ambiguity-as-a-result/reference/reference-make-the-unsafe-state-unrepresentable.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다", "completion-unknown은 자동으로도 수동으로도 재시도하지 않는다", "전송·업무·스트림 증거는 세 축이고 서로를 함의하지 않는다" ] }, { "title": "실패 번역 사슬의 순서는 계약이다", "slug": "translation-chain-order-is-a-contract", "file": "commit-ambiguity-as-a-result/reference/reference-translation-chain-order-is-a-contract.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "번역되지 않은 경합 예외가 재시도 코디네이터의 catch를 통째로 비껴갔다", "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다" ] }, { "title": "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다", "slug": "unknown-is-a-third-result", "file": "commit-ambiguity-as-a-result/reference/reference-unknown-is-a-third-result.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "pg_terminate_backend가 57P01로 도착하고 커밋 레코드는 이미 WAL에 있었다", "high-water mark가 본 위치를 뜻해서 재전달된 변경이 영구히 사라졌다", "completion-unknown은 자동으로도 수동으로도 재시도하지 않는다" ] } ], "question": [ { "title": "커밋 모호성 계약 레인이 이 리비전에서 통과하는지 실행으로 확인되지 않았다", "slug": "commit-ambiguity-lane-not-executed", "file": "commit-ambiguity-as-a-result/question/openquestion-commit-ambiguity-lane-not-executed.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "pg_terminate_backend가 57P01로 도착하고 커밋 레코드는 이미 WAL에 있었다" ] } ], "decision": [ { "title": "completion-unknown은 자동으로도 수동으로도 재시도하지 않는다", "slug": "completion-unknown-is-never-retried", "file": "commit-ambiguity-as-a-result/decision/decision-completion-unknown-is-never-retried.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "pg_terminate_backend가 57P01로 도착하고 커밋 레코드는 이미 WAL에 있었다", "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다", "위험한 조합은 정책이 아니라 생성자가 거부하게 만든다", "커밋 모호성 판정은 넓혀도 좁혀도 해롭다" ] }, { "title": "재시도 단위는 statement가 아니라 유스케이스 전체다", "slug": "retry-unit-is-the-use-case", "file": "commit-ambiguity-as-a-result/decision/decision-retry-unit-is-the-use-case.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "번역되지 않은 경합 예외가 재시도 코디네이터의 catch를 통째로 비껴갔다", "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다" ] }, { "title": "전송·업무·스트림 증거는 세 축이고 서로를 함의하지 않는다", "slug": "three-axes-of-evidence", "file": "commit-ambiguity-as-a-result/decision/decision-three-axes-of-evidence.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다", "위험한 조합은 정책이 아니라 생성자가 거부하게 만든다", "completion-unknown은 자동으로도 수동으로도 재시도하지 않는다" ] } ] } }, "composition-and-lifecycle-models": { "topic": "composition-and-lifecycle-models", "kinds": { "case": [], "concept": [ { "title": "미배선 인터셉터는 누락이 아니라 중복이다", "slug": "adapter-inbound-graphql-c03", "file": "composition-and-lifecycle-models/concept/concept-adapter-inbound-graphql-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-graphql-c03" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-graphql-c03.txt" ], "relations": [] }, { "title": "매니페스트 조회를 설계했는데 단일 빈이 대신 주입된다", "slug": "adapter-inbound-graphql-c06", "file": "composition-and-lifecycle-models/concept/concept-adapter-inbound-graphql-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-graphql-c06" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-graphql-c06.txt" ], "relations": [] }, { "title": "선언한 전송 프로파일과 실제 응답을 만드는 쪽이 다르다", "slug": "adapter-inbound-graphql-c09", "file": "composition-and-lifecycle-models/concept/concept-adapter-inbound-graphql-c09.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-graphql-c09", "adapter-inbound-graphql-c09-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-graphql-c09.txt" ], "relations": [] }, { "title": "실패를 보여 준 적 없는 경계 테스트는 잘못된 디렉터리를 스캔한 것과 구별되지 않는다", "slug": "adapter-inbound-web-c02", "file": "composition-and-lifecycle-models/concept/concept-adapter-inbound-web-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c02" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c02.txt" ], "relations": [] }, { "title": "compileOnly로 막았지만 컨버터를 등록하는 코드도 없다", "slug": "adapter-inbound-web-c12", "file": "composition-and-lifecycle-models/concept/concept-adapter-inbound-web-c12.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c12" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c12.txt" ], "relations": [] }, { "title": "나중에 도는 필터가 클라이언트 값으로 덮어쓴다", "slug": "adapter-inbound-web-c13", "file": "composition-and-lifecycle-models/concept/concept-adapter-inbound-web-c13.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c13" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c13.txt" ], "relations": [] }, { "title": "세 설정 접두사 중 하나에 소비자가 없다", "slug": "adapter-inbound-websocket-c01", "file": "composition-and-lifecycle-models/concept/concept-adapter-inbound-websocket-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-websocket-c01", "adapter-inbound-websocket-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-websocket-c01.txt" ], "relations": [] }, { "title": "꺼져 있을 때 아무것도 기여하지 않는다는 말이 문자 그대로다", "slug": "adapter-outbound-cache-redis-c01", "file": "composition-and-lifecycle-models/concept/concept-adapter-outbound-cache-redis-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-cache-redis-c01", "adapter-outbound-cache-redis-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-cache-redis-c01.txt" ], "relations": [] }, { "title": "기본값이 가리키는 리소스가 없고 그것이 시작 실패로 잡힌다", "slug": "adapter-outbound-cache-redis-c02", "file": "composition-and-lifecycle-models/concept/concept-adapter-outbound-cache-redis-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-cache-redis-c02" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-cache-redis-c02.txt" ], "relations": [] }, { "title": "적재는 import filter가 아니라 명시적 component scan이다", "slug": "adapter-outbound-fileserver-c01", "file": "composition-and-lifecycle-models/concept/concept-adapter-outbound-fileserver-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-fileserver-c01" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-fileserver-c01.txt" ], "relations": [] }, { "title": "이름 없던 상태에 이름을 붙인 세 자리", "slug": "adapter-outbound-notification-c01", "file": "composition-and-lifecycle-models/concept/concept-adapter-outbound-notification-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-notification-c01", "adapter-outbound-notification-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-notification-c01.txt" ], "relations": [] }, { "title": "같은 종료 절차를 쓰지만 대상이 다르다", "slug": "adapter-outbound-notification-c02", "file": "composition-and-lifecycle-models/concept/concept-adapter-outbound-notification-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-notification-c02" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-notification-c02.txt" ], "relations": [] }, { "title": "항상 설치되는 스캔이 opt-in package를 끌고 오지 않는다", "slug": "adapter-outbound-persistence-jpa-c56", "file": "composition-and-lifecycle-models/concept/concept-adapter-outbound-persistence-jpa-c56.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c56", "adapter-outbound-persistence-jpa-c56-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c56.txt" ], "relations": [] }, { "title": "네 겹이 같은 스위치를 읽고 각각 다른 실패를 막는다", "slug": "adapter-outbound-persistence-mongo-c01", "file": "composition-and-lifecycle-models/concept/concept-adapter-outbound-persistence-mongo-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-mongo-c01", "adapter-outbound-persistence-mongo-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-mongo-c01.txt" ], "relations": [] }, { "title": "phase를 code table 위에 두는 순서까지 논증돼 있다", "slug": "adapter-outbound-persistence-mongo-c08", "file": "composition-and-lifecycle-models/concept/concept-adapter-outbound-persistence-mongo-c08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-mongo-c08" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-mongo-c08.txt" ], "relations": [] }, { "title": "허용된 의존과 실제 의존이 다르다", "slug": "adapter-outbound-support-c01", "file": "composition-and-lifecycle-models/concept/concept-adapter-outbound-support-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-support-c01", "adapter-outbound-support-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-support-c01.txt" ], "relations": [] }, { "title": "세 조건을 하나의 boolean으로 접지 않는다", "slug": "grpc-advanced-bootstrap-c02", "file": "composition-and-lifecycle-models/concept/concept-grpc-advanced-bootstrap-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-bootstrap-c02", "grpc-advanced-bootstrap-c02-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-bootstrap-c02.txt" ], "relations": [] }, { "title": "네 타입을 쓰지만 그 관측을 만드는 코드가 없다", "slug": "grpc-observability-c02", "file": "composition-and-lifecycle-models/concept/concept-grpc-observability-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-observability-c02" ], "evidence": [ "../../../final/evidence/raw/grpc-observability-c02.txt" ], "relations": [] }, { "title": "선언한 여섯 의존 중 셋이 import 0건이다", "slug": "messaging-admin-runtime-c02", "file": "composition-and-lifecycle-models/concept/concept-messaging-admin-runtime-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-runtime-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-runtime-c02.txt" ], "relations": [] }, { "title": "이 리프의 실질은 세 가지 거절이다", "slug": "messaging-kafka-share-experimental-c01", "file": "composition-and-lifecycle-models/concept/concept-messaging-kafka-share-experimental-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-kafka-share-experimental-c01", "messaging-kafka-share-experimental-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-kafka-share-experimental-c01.txt" ], "relations": [ "허용 의존 목록은 상한이므로 미사용을 잡지 않는다 — 그것을 잡으려면 별도 검사가 필요하다", "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "에러 메시지가 지시하는 설정은 그 설정을 읽는 코드와 함께 존재해야 한다", "구성 오류는 한 예외 타입과 안정 코드로 보고한다" ] }, { "title": "소비자 없음과 membership 없음과 조립 없음이 서로 맞는다", "slug": "messaging-kafka-share-experimental-c02", "file": "composition-and-lifecycle-models/concept/concept-messaging-kafka-share-experimental-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-kafka-share-experimental-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-kafka-share-experimental-c02.txt" ], "relations": [ "허용 의존 목록은 상한이므로 미사용을 잡지 않는다 — 그것을 잡으려면 별도 검사가 필요하다", "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "에러 메시지가 지시하는 설정은 그 설정을 읽는 코드와 함께 존재해야 한다", "구성 오류는 한 예외 타입과 안정 코드로 보고한다" ] }, { "title": "검증기가 불리지 않는 지금 실제로 도는 게이트는 생성자다", "slug": "messaging-nats-experimental-c02", "file": "composition-and-lifecycle-models/concept/concept-messaging-nats-experimental-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-nats-experimental-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-nats-experimental-c02.txt" ], "relations": [] }, { "title": "이 리프는 통째로 하나의 수정이다", "slug": "messaging-runtime-core-c07", "file": "composition-and-lifecycle-models/concept/concept-messaging-runtime-core-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-runtime-core-c07" ], "evidence": [ "../../../final/evidence/raw/messaging-runtime-core-c07.txt" ], "relations": [ "만들어 두고 흘리지 않는 진단값은 진단이 아니다", "증가한다고 문서화한 값이 리터럴이면 그 사실을 적는다", "안정 코드는 운영자의 행동이 갈리는 지점마다 나눈다", "`CompletionStage`를 반환하는 메서드는 동기적으로 던지지 않는다" ] }, { "title": "이 리프는 messaging family에서 배선이 가장 잘 된 축이다", "slug": "messaging-security-c02", "file": "composition-and-lifecycle-models/concept/concept-messaging-security-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-security-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-security-c02.txt" ], "relations": [ "배선된 게이트는 자기 leaf 레인에서 검증한다", "같은 술어가 두 타입에 있으면 하나가 다른 하나를 부른다", "가변 필드로 상태 전이를 표현하면 가시성을 함께 정한다", "맵 갱신 함수 안에서 I/O를 하면 그 지연이 락 범위가 된다" ] }, { "title": "등록되어 있다는 것과 조립할 수 있다는 것을 분리했다", "slug": "messaging-spring-boot-starter-c01", "file": "composition-and-lifecycle-models/concept/concept-messaging-spring-boot-starter-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-spring-boot-starter-c01", "messaging-spring-boot-starter-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-spring-boot-starter-c01.txt" ], "relations": [ "검증기는 발행이 아니라 주입이 강제다" ] }, { "title": "플랫폼 보장과 헷갈릴 만큼 닮은 것이 이 리프의 위협 모델이다", "slug": "messaging-spring-cloud-stream-bridge-c01", "file": "composition-and-lifecycle-models/concept/concept-messaging-spring-cloud-stream-bridge-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-spring-cloud-stream-bridge-c01" ], "evidence": [ "../../../final/evidence/raw/messaging-spring-cloud-stream-bridge-c01.txt" ], "relations": [ "허용 의존 목록은 상한이므로 미사용을 잡지 않는다", "등록을 받는 컴포넌트는 해제도 제공한다", "함께 읽히는 두 맵은 한 값으로 묶는다", "에러 메시지가 지시하는 설정은 그 설정을 읽는 코드와 함께 존재해야 한다", "한 개념의 등록 상태를 두 객체가 나눠 갖지 않는다" ] } ], "reference": [], "question": [], "decision": [] } }, "composition-root-and-bootstrap": { "topic": "composition-root-and-bootstrap", "kinds": { "case": [ { "title": "출하되는 web 어댑터의 스위치가 활성화 모델 밖에 있다", "slug": "analysis-finding-a18-f001", "file": "composition-root-and-bootstrap/case/case-analysis-finding-a18-f001.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a18-f001" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a18-f001.txt" ], "relations": [ "이 leaf의 리액티브 절반 29개 파일은 어떤 출하 배포에서도 활성화될 수 없다", "능력 프로퍼티 이름을 만드는 코드와 실제 게이트가 다른 접두사를 쓴다", "무엇을 스위치로 부를지 정하기 전에는 활성화 모델에 넣을 수 없다" ] }, { "title": "실패는 환경 원인이며, 그 테스트의 도구 가드가 불완전하다", "slug": "analysis-finding-a18-f002", "file": "composition-root-and-bootstrap/case/case-analysis-finding-a18-f002.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a18-f002" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a18-f002.txt" ], "relations": [ "아무것도 발견하지 못한 레인은 성공이 아니라 실패여야 한다", "초록일 수 없는 게이트는 사람들이 건너뛰는 법을 배우게 만든다", "한 test 안에서 도구별로 갈리지 않는 편이 낫다" ] } ], "concept": [], "reference": [], "question": [], "decision": [] } }, "contract-domain-and-bounds": { "topic": "contract-domain-and-bounds", "kinds": { "case": [ { "title": "실환경 증거\" 가 두 리프에 반씩 있고 서로 만나지 않는다", "slug": "grpc-advanced-diagnostics-f03", "file": "contract-domain-and-bounds/case/case-grpc-advanced-diagnostics-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-diagnostics-f03" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-diagnostics-f03.txt" ], "relations": [] }, { "title": "대체 선택기는 사용자 정의 선택기가 받는 보호를 받지 않는다", "slug": "grpc-advanced-resilience-f02", "file": "contract-domain-and-bounds/case/case-grpc-advanced-resilience-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-resilience-f02" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-resilience-f02.txt" ], "relations": [] }, { "title": "클래스가 비판한 무제한 증가를 형제 맵이 그대로 한다", "slug": "grpc-advanced-streaming-f01", "file": "contract-domain-and-bounds/case/case-grpc-advanced-streaming-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-streaming-f01" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-streaming-f01.txt" ], "relations": [] }, { "title": "클라이언트 스트림 정책의 네 상한 중 둘은 읽는 코드가 없다", "slug": "grpc-advanced-streaming-f02", "file": "contract-domain-and-bounds/case/case-grpc-advanced-streaming-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-streaming-f02" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-streaming-f02.txt" ], "relations": [] }, { "title": "메타데이터 예산의 두 성분 중 하나는 강제되지 않고, 나머지 하나는 바이트가 아니라 문자를 센다", "slug": "grpc-core-api-f05", "file": "contract-domain-and-bounds/case/case-grpc-core-api-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-core-api-f05" ], "evidence": [ "../../../final/evidence/raw/grpc-core-api-f05.txt" ], "relations": [] }, { "title": "프로파일이 스트림 재접속 예산을 선언하는데 그것이 함의하는 DNS 갱신 주기를 정하지 않는다", "slug": "grpc-discovery-f01", "file": "contract-domain-and-bounds/case/case-grpc-discovery-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-discovery-f01" ], "evidence": [ "../../../final/evidence/raw/grpc-discovery-f01.txt" ], "relations": [] }, { "title": "낙관적 잠금 컬럼이 없어 전이 가드가 메모리 안에만 있다", "slug": "grpc-operation-ledger-jpa-f01", "file": "contract-domain-and-bounds/case/case-grpc-operation-ledger-jpa-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-operation-ledger-jpa-f01" ], "evidence": [ "../../../final/evidence/raw/grpc-operation-ledger-jpa-f01.txt" ], "relations": [] }, { "title": "WireSafeText의 규칙이 leaf 경계에서 멈춘다", "slug": "messaging-core-api-f05", "file": "contract-domain-and-bounds/case/case-messaging-core-api-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-core-api-f05" ], "evidence": [ "../../../final/evidence/raw/messaging-core-api-f05.txt" ], "relations": [] }, { "title": "extract가 손상된 추적 헤더에 분류되지 않은 예외를 던진다", "slug": "messaging-observability-f07", "file": "contract-domain-and-bounds/case/case-messaging-observability-f07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-observability-f07" ], "evidence": [ "../../../final/evidence/raw/messaging-observability-f07.txt" ], "relations": [ "타입이 문서화한 불변식은 타입이 강제한다" ] }, { "title": "inbox 보존 규칙이 문서로만 있다", "slug": "messaging-reliability-api-f05", "file": "contract-domain-and-bounds/case/case-messaging-reliability-api-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-reliability-api-f05" ], "evidence": [ "../../../final/evidence/raw/messaging-reliability-api-f05.txt" ], "relations": [ "계약만 담는 leaf도 계약의 거절 조건은 자기 레인에서 검증한다", "record의 `equals`를 좁히면 이유를 적는다", "호출 컨텍스트가 계약이면 그 컨텍스트를 검증할 수단을 함께 정한다" ] }, { "title": "포트가 bounded/unbounded purge 두 오버로드를 나란히 노출하고, 호출자가 무제한 쪽을 고른다", "slug": "messaging-reliability-api-f08", "file": "contract-domain-and-bounds/case/case-messaging-reliability-api-f08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-reliability-api-f08" ], "evidence": [ "../../../final/evidence/raw/messaging-reliability-api-f08.txt" ], "relations": [ "계약만 담는 leaf도 계약의 거절 조건은 자기 레인에서 검증한다", "record의 `equals`를 좁히면 이유를 적는다", "호출 컨텍스트가 계약이면 그 컨텍스트를 검증할 수단을 함께 정한다" ] } ], "concept": [], "reference": [ { "title": "컬럼 폭은 애플리케이션 검증과 짝을 이룬다", "slug": "messaging-inbox-jdbc-postgresql-f05", "file": "contract-domain-and-bounds/reference/reference-messaging-inbox-jdbc-postgresql-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "bounded purge가 구현돼 있고 호출되지 않아, cleanup이 스스로 막겠다고 한 장애를 일으킨다", "속성을 이름으로 주장하는 테스트가 그 속성을 보일 수 없는 fake 위에서 통과한다", "SQL 실패가 재시도 불가로 분류된다" ] }, { "title": "같은 안전 규칙은 한 공식과 한 강제 시점을 갖는다", "slug": "messaging-inbox-jdbc-postgresql-f06", "file": "contract-domain-and-bounds/reference/reference-messaging-inbox-jdbc-postgresql-f06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "bounded purge가 구현돼 있고 호출되지 않아, cleanup이 스스로 막겠다고 한 장애를 일으킨다", "속성을 이름으로 주장하는 테스트가 그 속성을 보일 수 없는 fake 위에서 통과한다", "SQL 실패가 재시도 불가로 분류된다" ] } ], "question": [ { "title": "보존 sweep이 없다", "slug": "messaging-claim-check-f05", "file": "contract-domain-and-bounds/question/openquestion-messaging-claim-check-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "같은 튜닝 값이 두 계층에 있으면 어느 쪽이 이기는지 정한다" ] } ], "decision": [] } }, "cross-leaf-integration-facts": { "topic": "cross-leaf-integration-facts", "kinds": { "case": [ { "title": "claim-check는 starter에 배선 코드가 한 줄도 없다", "slug": "claim-check-has-no-wiring-line-in-the-starter", "file": "cross-leaf-integration-facts/case/case-claim-check-has-no-wiring-line-in-the-starter.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "claim-check-has-no-wiring-line-in-the-starter" ], "evidence": [ "../../../final/evidence/raw/claim-check-has-no-wiring-line-in-the-starter.txt" ], "relations": [] }, { "title": "messaging 마이그레이션 스트림을 적용하는 곳이 없고, 적용하려는 순간 버전이 충돌한다", "slug": "messaging-migration-stream-has-no-applier-and-collides-on-adoption", "file": "cross-leaf-integration-facts/case/case-messaging-migration-stream-has-no-applier-and-collides-on-adoption.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-migration-stream-has-no-applier-and-collides-on-adoption", "messaging-migration-stream-has-no-applier-and-collides-on-adoption-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-migration-stream-has-no-applier-and-collides-on-adoption.txt" ], "relations": [ "messaging 마이그레이션 두 leaf가 같은 디렉터리에서 V2를 둘 만들었다" ] }, { "title": "admin 스위치가 가드를 켜고 서비스는 켜지 않는다", "slug": "the-admin-switch-turns-on-the-guard-and-not-the-service", "file": "cross-leaf-integration-facts/case/case-the-admin-switch-turns-on-the-guard-and-not-the-service.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "the-admin-switch-turns-on-the-guard-and-not-the-service", "the-admin-switch-turns-on-the-guard-and-not-the-service-diagram" ], "evidence": [ "../../../final/evidence/raw/the-admin-switch-turns-on-the-guard-and-not-the-service.txt" ], "relations": [] }, { "title": "MessagingPublicSurfaceContractTest가 가족 밖(app-bootstrap)에 있다", "slug": "the-public-surface-contract-test-lives-outside-the-family", "file": "cross-leaf-integration-facts/case/case-the-public-surface-contract-test-lives-outside-the-family.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "the-public-surface-contract-test-lives-outside-the-family" ], "evidence": [ "../../../final/evidence/raw/the-public-surface-contract-test-lives-outside-the-family.txt" ], "relations": [] }, { "title": "messaging-admin-api는 main 25파일 · 1,613 LOC에 테스트 파일이 1개다", "slug": "twenty-five-main-files-and-one-test-file", "file": "cross-leaf-integration-facts/case/case-twenty-five-main-files-and-one-test-file.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "twenty-five-main-files-and-one-test-file" ], "evidence": [ "../../../final/evidence/raw/twenty-five-main-files-and-one-test-file.txt" ], "relations": [] } ], "concept": [], "reference": [], "question": [], "decision": [] } }, "declaration-and-document-drift": { "topic": "declaration-and-document-drift", "kinds": { "case": [ { "title": "정본이 어디인지 주석에 적어 두고 정의는 다시 타이핑한다", "slug": "a05-f019-ssot", "file": "declaration-and-document-drift/case/case-a05-f019-ssot.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a05-f019-ssot" ], "evidence": [ "../../../final/evidence/raw/a05-f019-ssot.txt" ], "relations": [ "문서의 수치는 세지 말고 파생하거나 게이트로 붙든다", "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "같은 개념의 두 어휘가 공존하면 하나를 죽은 것으로 표시한다" ] }, { "title": "javadoc은 재개 가능한 것만 거부한다고 적는데 검사는 마이그레이션을 보지 않는다", "slug": "a06-f016-flamingock", "file": "declaration-and-document-drift/case/case-a06-f016-flamingock.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a06-f016-flamingock", "a06-f016-flamingock-probe" ], "evidence": [ "../../../final/evidence/raw/a06-f016-flamingock.txt", "../../../final/evidence/raw/a06-f016-flamingock-probe.txt" ], "relations": [ "fenced lease — 만료 시각만으로는 부족한 이유", "recordApplied가 펜스를 비교하지 않아 밀려난 실행자가 원장을 차지한다", "문서가 UUIDv7이라 말하고 생성되는 것은 v4다" ] }, { "title": "승격 게이트가 하향 전이도 승격 규칙으로 판정하고, javadoc 이 약속한 거부는 없다", "slug": "grpc-advanced-bootstrap-f02", "file": "declaration-and-document-drift/case/case-grpc-advanced-bootstrap-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-bootstrap-f02" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-bootstrap-f02.txt" ], "relations": [] }, { "title": "승격 차단 목록에 담금 기간과 실환경 항목이 없다", "slug": "grpc-advanced-edition-f02", "file": "declaration-and-document-drift/case/case-grpc-advanced-edition-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-edition-f02" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-edition-f02.txt" ], "relations": [] }, { "title": "부트스트랩 대조가 문서 어디든의 부분 문자열을 본다", "slug": "grpc-advanced-resilience-f01", "file": "declaration-and-document-drift/case/case-grpc-advanced-resilience-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-resilience-f01" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-resilience-f01.txt" ], "relations": [] }, { "title": "프로파일 검증기가 javadoc 이 든 두 실수 중 하나만 검사한다", "slug": "grpc-client-f04", "file": "declaration-and-document-drift/case/case-grpc-client-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-client-f04" ], "evidence": [ "../../../final/evidence/raw/grpc-client-f04.txt" ], "relations": [] }, { "title": "리졸버 검증기의 규칙이 하나뿐인데 javadoc 은 복수형으로 서술한다", "slug": "grpc-discovery-f02", "file": "declaration-and-document-drift/case/case-grpc-discovery-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-discovery-f02" ], "evidence": [ "../../../final/evidence/raw/grpc-discovery-f02.txt" ], "relations": [] }, { "title": "deadlineRemaining 도 meter 가 없다. javadoc 은 그것이 기록된다고 말한다", "slug": "grpc-observability-f02", "file": "declaration-and-document-drift/case/case-grpc-observability-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-observability-f02" ], "evidence": [ "../../../final/evidence/raw/grpc-observability-f02.txt" ], "relations": [] }, { "title": "오류 노출 거부 목록의 \"호스트와 포트\" 규칙이 IPv4 점표기만 본다", "slug": "grpc-policy-f06", "file": "declaration-and-document-drift/case/case-grpc-policy-f06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-policy-f06" ], "evidence": [ "../../../final/evidence/raw/grpc-policy-f06.txt" ], "relations": [] }, { "title": "반환 목록이 자바독이 약속한 source order 가 아니다", "slug": "grpc-proto-contract-f02", "file": "declaration-and-document-drift/case/case-grpc-proto-contract-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-proto-contract-f02" ], "evidence": [ "../../../final/evidence/raw/grpc-proto-contract-f02.txt" ], "relations": [] }, { "title": "원시 API 규칙이 import 문만 보므로 완전 수식 사용과 와일드카드를 놓친다", "slug": "grpc-server-f02", "file": "declaration-and-document-drift/case/case-grpc-server-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-server-f02" ], "evidence": [ "../../../final/evidence/raw/grpc-server-f02.txt" ], "relations": [] }, { "title": "deduplicatedPublish 를 문서는 지원으로 적고 코드는 거짓으로 둔다", "slug": "messaging-kafka-f01", "file": "declaration-and-document-drift/case/case-messaging-kafka-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-kafka-f01", "messaging-kafka-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-kafka-f01.txt" ], "relations": [] }, { "title": "태그 어휘가 존재하고 유일한 호출부가 우회해, 실패 분류가 기록되지 않는다", "slug": "messaging-observability-f01", "file": "declaration-and-document-drift/case/case-messaging-observability-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-observability-f01", "messaging-observability-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-observability-f01.txt" ], "relations": [ "타입이 문서화한 불변식은 타입이 강제한다" ] }, { "title": "백오프 지터가 인스턴스를 분산시키지 못한다", "slug": "messaging-outbox-jdbc-postgresql-f06", "file": "declaration-and-document-drift/case/case-messaging-outbox-jdbc-postgresql-f06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-outbox-jdbc-postgresql-f06" ], "evidence": [ "../../../final/evidence/raw/messaging-outbox-jdbc-postgresql-f06.txt" ], "relations": [] }, { "title": "커넥션 획득 방식이 리프 안에서 갈린다", "slug": "messaging-outbox-jdbc-postgresql-f07", "file": "declaration-and-document-drift/case/case-messaging-outbox-jdbc-postgresql-f07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-outbox-jdbc-postgresql-f07" ], "evidence": [ "../../../final/evidence/raw/messaging-outbox-jdbc-postgresql-f07.txt" ], "relations": [] }, { "title": "CI에서 돈다고 선언한 게이트를 부르는 CI가 없다", "slug": "messaging-schema-avro-f01", "file": "declaration-and-document-drift/case/case-messaging-schema-avro-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-avro-f01", "messaging-schema-avro-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-avro-f01.txt" ], "relations": [ "모드 enum을 분기 조건으로 쓰면 각 분기에 테스트를 둔다", "컬렉션 순서가 계약이면 양쪽에서 같은 방향으로 적는다", "안정 코드는 판단 단위로 정하고 구현 단위로 정하지 않는다" ] }, { "title": "출고되는 신뢰성 체인 전체가 아무도 공급하지 않는 빈 뒤에 있고, 그 사슬이 자기 클래스 안을 가리킨다", "slug": "messaging-spring-boot-starter-f02", "file": "declaration-and-document-drift/case/case-messaging-spring-boot-starter-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-spring-boot-starter-f02", "messaging-spring-boot-starter-f02-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-spring-boot-starter-f02.txt" ], "relations": [ "검증기는 발행이 아니라 주입이 강제다" ] }, { "title": "설정 경로의 재시도가 예외 분류를 표현할 수 없다", "slug": "messaging-spring-boot-starter-f04", "file": "declaration-and-document-drift/case/case-messaging-spring-boot-starter-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-spring-boot-starter-f04" ], "evidence": [ "../../../final/evidence/raw/messaging-spring-boot-starter-f04.txt" ], "relations": [ "검증기는 발행이 아니라 주입이 강제다" ] }, { "title": "클래스 javadoc 이 강제되지 않는 규칙을 강제된다고 말한다", "slug": "messaging-testkit-f02", "file": "declaration-and-document-drift/case/case-messaging-testkit-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-testkit-f02", "messaging-testkit-f02-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-testkit-f02.txt" ], "relations": [] }, { "title": "gitCommit 은 기록되지만 읽혀 판정되지 않는다", "slug": "messaging-testkit-f08", "file": "declaration-and-document-drift/case/case-messaging-testkit-f08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-testkit-f08" ], "evidence": [ "../../../final/evidence/raw/messaging-testkit-f08.txt" ], "relations": [] } ], "concept": [], "reference": [ { "title": "문서가 범위를 제한하면 그 제한을 누가 강제하는지 같이 적는다", "slug": "messaging-cloudevents-f05", "file": "declaration-and-document-drift/reference/reference-messaging-cloudevents-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "배포 아티팩트가 싣지만 아무도 부르지 않는다", "상호운용을 위한 매퍼가 명세 준수 이벤트를 분류되지 않은 예외로 거절한다" ] }, { "title": "타입이 문서화한 불변식은 타입이 강제한다", "slug": "messaging-observability-f06", "file": "declaration-and-document-drift/reference/reference-messaging-observability-f06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "`extract`가 손상된 추적 헤더에 분류되지 않은 예외를 던진다", "관측 구현이 조립되지 않고, 그 재료 둘만 bean으로 존재한다", "감사 sink 인터페이스가 사용처에서 다시 선언된다", "자격증명 판정이 core-api보다 약하다", "태그 어휘가 존재하고 유일한 호출부가 우회해, 실패 분류가 기록되지 않는다" ] }, { "title": "구성 오류는 한 예외 타입과 안정 코드로 보고한다", "slug": "messaging-policy-f06", "file": "declaration-and-document-drift/reference/reference-messaging-policy-f06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "재시도 엔진과 DLQ 조정자가 bean으로 만들어지고 주입되는 곳이 없다", "재시도와 DLQ 각각에 두 개의 구현이 있고 정본이 표시되지 않았다", "DLQ 메타데이터의 두 시각이 항상 같다" ] }, { "title": "저장소 밖 문서를 절 번호로 인용하지 않는다", "slug": "messaging-policy-f07", "file": "declaration-and-document-drift/reference/reference-messaging-policy-f07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "재시도 엔진과 DLQ 조정자가 bean으로 만들어지고 주입되는 곳이 없다", "재시도와 DLQ 각각에 두 개의 구현이 있고 정본이 표시되지 않았다", "DLQ 메타데이터의 두 시각이 항상 같다" ] }, { "title": "호출 컨텍스트가 계약이면 그 컨텍스트를 검증할 수단을 함께 정한다", "slug": "messaging-reliability-api-f06", "file": "declaration-and-document-drift/reference/reference-messaging-reliability-api-f06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "inbox 보존 규칙이 문서로만 있다", "포트가 bounded/unbounded purge 두 오버로드를 나란히 노출하고, 호출자가 무제한 쪽을 고른다", "fencing token 경로가 실제 데이터베이스에 대해 실행되지 않는다", "한 인터페이스가 같은 전이의 두 세대를 갖고, 안전하지 않은 쪽에 `@Deprecated`가 없다" ] }, { "title": "port 계약은 동시성 요구를 적는다", "slug": "messaging-schema-api-f02", "file": "declaration-and-document-drift/reference/reference-messaging-schema-api-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "포맷 독립 진화 규칙이 호출되지 않고, 그것이 막으려던 중복이 실제로 생겼다" ] }, { "title": "도달성 판정은 단어가 아니라 import로 확인한다", "slug": "messaging-schema-api-f03", "file": "declaration-and-document-drift/reference/reference-messaging-schema-api-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "포맷 독립 진화 규칙이 호출되지 않고, 그것이 막으려던 중복이 실제로 생겼다" ] }, { "title": "한 개념의 등록 상태를 두 객체가 나눠 갖지 않는다", "slug": "messaging-spring-cloud-stream-bridge-f03", "file": "declaration-and-document-drift/reference/reference-messaging-spring-cloud-stream-bridge-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [] } ], "question": [ { "title": "세 갈래 판정이 포트의 boolean에서 두 갈래로 접힌다", "slug": "messaging-inbox-jdbc-postgresql-f04", "file": "declaration-and-document-drift/question/openquestion-messaging-inbox-jdbc-postgresql-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "컬럼 폭은 애플리케이션 검증과 짝을 이룬다", "같은 안전 규칙은 한 공식과 한 강제 시점을 갖는다" ] } ], "decision": [] } }, "declared-contract-without-enforcement": { "topic": "declared-contract-without-enforcement", "kinds": { "case": [ { "title": "순서 계약을 구현하는 것이 없고, 그것을 검증한다는 테스트는 enum 선언 순서만 본다", "slug": "an-order-contract-with-no-implementation", "file": "declared-contract-without-enforcement/case/case-an-order-contract-with-no-implementation.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "an-order-contract-with-no-implementation" ], "evidence": [ "../../../final/evidence/raw/an-order-contract-with-no-implementation.txt" ], "relations": [ "8단계 종료 순서 계약과 실제 종료 경로", "선언 순서를 단언하는 테스트는 그 순서를 읽는 코드가 있을 때만 게이트다", "같은 안전 규칙은 하나의 공식과 하나의 강제 시점을 갖는다", "드레인 마감 30초가 세 곳에서 독립적으로 결정된다" ] } ], "concept": [], "reference": [], "question": [], "decision": [] } }, "delivery-and-settlement-models": { "topic": "delivery-and-settlement-models", "kinds": { "case": [], "concept": [ { "title": "보고되는 프로파일이 규정하는 동작을 수행하는 코드가 없다", "slug": "adapter-inbound-graphql-c08", "file": "delivery-and-settlement-models/concept/concept-adapter-inbound-graphql-c08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-graphql-c08" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-graphql-c08.txt" ], "relations": [] }, { "title": "모호한 실행을 재시도 가능으로 표시할 수 없다", "slug": "adapter-outbound-cache-redis-c06", "file": "delivery-and-settlement-models/concept/concept-adapter-outbound-cache-redis-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-cache-redis-c06" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-cache-redis-c06.txt" ], "relations": [] }, { "title": "길이 프레이밍이 구분자를 없애고, 잘린 토큰의 충돌을 컴파일 시점에 잡는다", "slug": "adapter-outbound-fileserver-c05", "file": "delivery-and-settlement-models/concept/concept-adapter-outbound-fileserver-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-fileserver-c05" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-fileserver-c05.txt" ], "relations": [] }, { "title": "인식하지 못한 실패는 변경 연산이면 ambiguous로 떨어진다", "slug": "adapter-outbound-fileserver-c07", "file": "delivery-and-settlement-models/concept/concept-adapter-outbound-fileserver-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-fileserver-c07" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-fileserver-c07.txt" ], "relations": [] }, { "title": "브로커가 받아들인 발행을 로거 실패가 실패로 만들지 못한다", "slug": "adapter-outbound-messaging-c04", "file": "delivery-and-settlement-models/concept/concept-adapter-outbound-messaging-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-messaging-c04" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-messaging-c04.txt" ], "relations": [] }, { "title": "provider가 요청한 지연은 계산값보다 길 때만 채택되고 max에서 잘린다", "slug": "adapter-outbound-notification-c03", "file": "delivery-and-settlement-models/concept/concept-adapter-outbound-notification-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-notification-c03" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-notification-c03.txt" ], "relations": [] }, { "title": "offset을 표현할 수 없는 타입과 count 질의 없는 hasNext", "slug": "adapter-outbound-persistence-jpa-c04", "file": "delivery-and-settlement-models/concept/concept-adapter-outbound-persistence-jpa-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c04", "adapter-outbound-persistence-jpa-c04-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c04.txt" ], "relations": [] }, { "title": "grep refs=0은 finding의 시작점이지 결론이 아니다", "slug": "adapter-outbound-persistence-jpa-c31", "file": "delivery-and-settlement-models/concept/concept-adapter-outbound-persistence-jpa-c31.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c31" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c31.txt" ], "relations": [] }, { "title": "두 export 목록에 postgresql과 h2만큼의 차이가 있다", "slug": "adapter-outbound-persistence-jpa-c32", "file": "delivery-and-settlement-models/concept/concept-adapter-outbound-persistence-jpa-c32.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c32" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c32.txt" ], "relations": [] }, { "title": "leaf list 자체는 outside consumer를 검사하지 않는다", "slug": "adapter-outbound-persistence-jpa-c33", "file": "delivery-and-settlement-models/concept/concept-adapter-outbound-persistence-jpa-c33.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c33" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c33.txt" ], "relations": [] }, { "title": "투영 먼저 checkpoint 나중, 그리고 3-state claim", "slug": "adapter-outbound-persistence-mongo-c07", "file": "delivery-and-settlement-models/concept/concept-adapter-outbound-persistence-mongo-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-mongo-c07" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-mongo-c07.txt" ], "relations": [] }, { "title": "계약에 Kafka topic도 WebSocket도 나오지 않는다", "slug": "application-core-c06", "file": "delivery-and-settlement-models/concept/concept-application-core-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "application-core-c06" ], "evidence": [ "../../../final/evidence/raw/application-core-c06.txt" ], "relations": [ "legacy storage/notification compatibility surface의 제거 조건 추적" ] }, { "title": "forRemoval이 붙었는데 production consumer가 남아 있다", "slug": "application-core-c07", "file": "delivery-and-settlement-models/concept/concept-application-core-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "application-core-c07" ], "evidence": [ "../../../final/evidence/raw/application-core-c07.txt" ], "relations": [ "legacy storage/notification compatibility surface의 제거 조건 추적" ] }, { "title": "adapter까지 있고 호출자가 없는 교정 경로", "slug": "application-core-c11", "file": "delivery-and-settlement-models/concept/concept-application-core-c11.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "application-core-c11" ], "evidence": [ "../../../final/evidence/raw/application-core-c11.txt" ], "relations": [ "legacy storage/notification compatibility surface의 제거 조건 추적" ] }, { "title": "bean은 없고 컴파일 시점 참조만 있다", "slug": "domain-core-c02", "file": "delivery-and-settlement-models/concept/concept-domain-core-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "domain-core-c02" ], "evidence": [ "../../../final/evidence/raw/domain-core-c02.txt" ], "relations": [] }, { "title": "건강 레지스트리 — 낙관에서 시작하지 않는다", "slug": "grpc-admin-c01", "file": "delivery-and-settlement-models/concept/concept-grpc-admin-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-admin-c01", "grpc-admin-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-admin-c01.txt" ], "relations": [] }, { "title": "배수 순서", "slug": "grpc-admin-c02", "file": "delivery-and-settlement-models/concept/concept-grpc-admin-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-admin-c02" ], "evidence": [ "../../../final/evidence/raw/grpc-admin-c02.txt" ], "relations": [] }, { "title": "xDS 시작 가드", "slug": "grpc-advanced-resilience-c02", "file": "delivery-and-settlement-models/concept/concept-grpc-advanced-resilience-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-resilience-c02" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-resilience-c02.txt" ], "relations": [] }, { "title": "권한을 불리언이 아니라 타입으로 만든다", "slug": "messaging-admin-api-c01", "file": "delivery-and-settlement-models/concept/concept-messaging-admin-api-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-api-c01", "messaging-admin-api-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-api-c01.txt" ], "relations": [] }, { "title": "부품은 정교하고 부품을 잇는 층은 실행된 적이 없다", "slug": "messaging-admin-runtime-c01", "file": "delivery-and-settlement-models/concept/concept-messaging-admin-runtime-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-runtime-c01", "messaging-admin-runtime-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-runtime-c01.txt" ], "relations": [] }, { "title": "파괴적 작업에는 실행 경로가 없다", "slug": "messaging-admin-runtime-c04", "file": "delivery-and-settlement-models/concept/concept-messaging-admin-runtime-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-runtime-c04" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-runtime-c04.txt" ], "relations": [] }, { "title": "왕복 검증이 producedAt 을 비교하지 않는다", "slug": "messaging-cloudevents-c04", "file": "delivery-and-settlement-models/concept/concept-messaging-cloudevents-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-cloudevents-c04", "messaging-cloudevents-c04-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-cloudevents-c04.txt" ], "relations": [ "왕복이라 부르는 테스트는 무엇을 보존하지 않는지도 적는다", "문서가 범위를 제한하면 그 제한을 누가 강제하는지 같이 적는다" ] }, { "title": "거절과 결과 모름을 하나로 합치면 중복 주문이 생긴다", "slug": "messaging-core-api-c04", "file": "delivery-and-settlement-models/concept/concept-messaging-core-api-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-core-api-c04", "messaging-core-api-c04-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-core-api-c04.txt" ], "relations": [] }, { "title": "예외 클래스로 분기하지 않아도 되게 만든 기반 타입", "slug": "messaging-core-api-c06", "file": "delivery-and-settlement-models/concept/concept-messaging-core-api-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-core-api-c06" ], "evidence": [ "../../../final/evidence/raw/messaging-core-api-c06.txt" ], "relations": [] }, { "title": "소비자 런타임 — 스레드 규율이 설계다", "slug": "messaging-kafka-c01", "file": "delivery-and-settlement-models/concept/concept-messaging-kafka-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-kafka-c01", "messaging-kafka-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-kafka-c01.txt" ], "relations": [] }, { "title": "등록이 통과한 뒤에 아무 일도 일어나지 않는다", "slug": "messaging-kafka-share-experimental-c04", "file": "delivery-and-settlement-models/concept/concept-messaging-kafka-share-experimental-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-kafka-share-experimental-c04" ], "evidence": [ "../../../final/evidence/raw/messaging-kafka-share-experimental-c04.txt" ], "relations": [ "허용 의존 목록은 상한이므로 미사용을 잡지 않는다 — 그것을 잡으려면 별도 검사가 필요하다", "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "에러 메시지가 지시하는 설정은 그 설정을 읽는 코드와 함께 존재해야 한다", "구성 오류는 한 예외 타입과 안정 코드로 보고한다" ] }, { "title": "조용히 강등하지 않고 던진다", "slug": "messaging-kafka-share-experimental-c05", "file": "delivery-and-settlement-models/concept/concept-messaging-kafka-share-experimental-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-kafka-share-experimental-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-kafka-share-experimental-c05.txt" ], "relations": [ "허용 의존 목록은 상한이므로 미사용을 잡지 않는다 — 그것을 잡으려면 별도 검사가 필요하다", "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "에러 메시지가 지시하는 설정은 그 설정을 읽는 코드와 함께 존재해야 한다", "구성 오류는 한 예외 타입과 안정 코드로 보고한다" ] }, { "title": "없는 큐를 찾아 나서게 만들지 않는다", "slug": "messaging-nats-experimental-c01", "file": "delivery-and-settlement-models/concept/concept-messaging-nats-experimental-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-nats-experimental-c01" ], "evidence": [ "../../../final/evidence/raw/messaging-nats-experimental-c01.txt" ], "relations": [] }, { "title": "차원이 닫혀 있고, 사전 확인과 커밋 사이에 lock이 없다", "slug": "messaging-observability-c03", "file": "delivery-and-settlement-models/concept/concept-messaging-observability-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-observability-c03", "messaging-observability-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-observability-c03.txt" ], "relations": [ "타입이 문서화한 불변식은 타입이 강제한다" ] }, { "title": "거절된 태그 집합도 세어서 남긴다", "slug": "messaging-observability-c04", "file": "delivery-and-settlement-models/concept/concept-messaging-observability-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-observability-c04" ], "evidence": [ "../../../final/evidence/raw/messaging-observability-c04.txt" ], "relations": [ "타입이 문서화한 불변식은 타입이 강제한다" ] }, { "title": "손상된 traceparent 는 이 leaf 의 실패 어휘 밖에서 터진다", "slug": "messaging-observability-c05", "file": "delivery-and-settlement-models/concept/concept-messaging-observability-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-observability-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-observability-c05.txt" ], "relations": [ "타입이 문서화한 불변식은 타입이 강제한다" ] }, { "title": "확률을 낮추는 것과 데이터 제약으로 만드는 것은 다르다", "slug": "messaging-outbox-jdbc-postgresql-c03", "file": "delivery-and-settlement-models/concept/concept-messaging-outbox-jdbc-postgresql-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-outbox-jdbc-postgresql-c03" ], "evidence": [ "../../../final/evidence/raw/messaging-outbox-jdbc-postgresql-c03.txt" ], "relations": [] }, { "title": "bean 정의는 전부 starter 쪽에 있다", "slug": "messaging-policy-c02", "file": "delivery-and-settlement-models/concept/concept-messaging-policy-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-policy-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-policy-c02.txt" ], "relations": [ "구성 오류는 한 예외 타입과 안정 코드로 보고한다", "저장소 밖 문서를 절 번호로 인용하지 않는다", "부팅 경로의 알고리즘 복잡도는 문서화한다" ] }, { "title": "재시도 판단과 DLQ 경로는 출하 컨텍스트에서 호출되지 않는다", "slug": "messaging-policy-c04", "file": "delivery-and-settlement-models/concept/concept-messaging-policy-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-policy-c04" ], "evidence": [ "../../../final/evidence/raw/messaging-policy-c04.txt" ], "relations": [ "구성 오류는 한 예외 타입과 안정 코드로 보고한다", "저장소 밖 문서를 절 번호로 인용하지 않는다", "부팅 경로의 알고리즘 복잡도는 문서화한다" ] }, { "title": "발행 경로는 프로덕션에서 실제로 조립된다", "slug": "messaging-policy-c07", "file": "delivery-and-settlement-models/concept/concept-messaging-policy-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-policy-c07" ], "evidence": [ "../../../final/evidence/raw/messaging-policy-c07.txt" ], "relations": [ "구성 오류는 한 예외 타입과 안정 코드로 보고한다", "저장소 밖 문서를 절 번호로 인용하지 않는다", "부팅 경로의 알고리즘 복잡도는 문서화한다" ] }, { "title": "RetryDecision 변형에 반응하는 파일 넷 중 셋이 선언과 테스트다", "slug": "messaging-policy-c08", "file": "delivery-and-settlement-models/concept/concept-messaging-policy-c08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-policy-c08" ], "evidence": [ "../../../final/evidence/raw/messaging-policy-c08.txt" ], "relations": [ "구성 오류는 한 예외 타입과 안정 코드로 보고한다", "저장소 밖 문서를 절 번호로 인용하지 않는다", "부팅 경로의 알고리즘 복잡도는 문서화한다" ] }, { "title": "소비·정착·죽은 편지의 세 규율", "slug": "messaging-rabbit-c01", "file": "delivery-and-settlement-models/concept/concept-messaging-rabbit-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-rabbit-c01", "messaging-rabbit-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-rabbit-c01.txt" ], "relations": [] }, { "title": "컨텍스트 테스트를 통과하면서 아무것도 실행하지 않는 조립", "slug": "messaging-runtime-core-c01", "file": "delivery-and-settlement-models/concept/concept-messaging-runtime-core-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-runtime-core-c01" ], "evidence": [ "../../../final/evidence/raw/messaging-runtime-core-c01.txt" ], "relations": [ "만들어 두고 흘리지 않는 진단값은 진단이 아니다", "증가한다고 문서화한 값이 리터럴이면 그 사실을 적는다", "안정 코드는 운영자의 행동이 갈리는 지점마다 나눈다", "`CompletionStage`를 반환하는 메서드는 동기적으로 던지지 않는다" ] }, { "title": "인자가 여섯 개라는 것이 관측 지점이다", "slug": "messaging-runtime-core-c02", "file": "delivery-and-settlement-models/concept/concept-messaging-runtime-core-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-runtime-core-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-runtime-core-c02.txt" ], "relations": [ "만들어 두고 흘리지 않는 진단값은 진단이 아니다", "증가한다고 문서화한 값이 리터럴이면 그 사실을 적는다", "안정 코드는 운영자의 행동이 갈리는 지점마다 나눈다", "`CompletionStage`를 반환하는 메서드는 동기적으로 던지지 않는다" ] }, { "title": "바이트가 프로세스를 떠났는가가 REJECTED와 AMBIGUOUS를 가른다", "slug": "messaging-runtime-core-c03", "file": "delivery-and-settlement-models/concept/concept-messaging-runtime-core-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-runtime-core-c03", "messaging-runtime-core-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-runtime-core-c03.txt" ], "relations": [ "만들어 두고 흘리지 않는 진단값은 진단이 아니다", "증가한다고 문서화한 값이 리터럴이면 그 사실을 적는다", "안정 코드는 운영자의 행동이 갈리는 지점마다 나눈다", "`CompletionStage`를 반환하는 메서드는 동기적으로 던지지 않는다" ] }, { "title": "같은 코드가 두 completion에 쓰인다", "slug": "messaging-runtime-core-c05", "file": "delivery-and-settlement-models/concept/concept-messaging-runtime-core-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-runtime-core-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-runtime-core-c05.txt" ], "relations": [ "만들어 두고 흘리지 않는 진단값은 진단이 아니다", "증가한다고 문서화한 값이 리터럴이면 그 사실을 적는다", "안정 코드는 운영자의 행동이 갈리는 지점마다 나눈다", "`CompletionStage`를 반환하는 메서드는 동기적으로 던지지 않는다" ] }, { "title": "크기 초과를 codec에서 잡으면 버려도 안전한 실패가 된다", "slug": "messaging-schema-json-c01", "file": "delivery-and-settlement-models/concept/concept-messaging-schema-json-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-json-c01", "messaging-schema-json-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-json-c01.txt" ], "relations": [ "실패 코드는 운영자의 다음 행동이 갈리는 지점마다 나눈다" ] }, { "title": "여섯 갈래 원인이 하나의 코드로 접힌다", "slug": "messaging-schema-json-c05", "file": "delivery-and-settlement-models/concept/concept-messaging-schema-json-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-json-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-json-c05.txt" ], "relations": [ "실패 코드는 운영자의 다음 행동이 갈리는 지점마다 나눈다" ] }, { "title": "어긋난 짝을 표현할 수 없게 만든 값 하나", "slug": "messaging-schema-protobuf-c03", "file": "delivery-and-settlement-models/concept/concept-messaging-schema-protobuf-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-protobuf-c03", "messaging-schema-protobuf-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-protobuf-c03.txt" ], "relations": [ "검증되지 않는 스키마 파일은 문서임을 파일 안에 적는다", "신뢰할 수 없는 입력 쪽 경계를 먼저 테스트한다" ] }, { "title": "같은 두 검사를 두 예외 계층이 나눠 갖는다", "slug": "messaging-security-c05", "file": "delivery-and-settlement-models/concept/concept-messaging-security-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-security-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-security-c05.txt" ], "relations": [ "배선된 게이트는 자기 leaf 레인에서 검증한다", "같은 술어가 두 타입에 있으면 하나가 다른 하나를 부른다", "가변 필드로 상태 전이를 표현하면 가시성을 함께 정한다", "맵 갱신 함수 안에서 I/O를 하면 그 지연이 락 범위가 된다" ] }, { "title": "모든 거부가 타입이 아니라 키를 부른다", "slug": "messaging-spring-boot-starter-c02", "file": "delivery-and-settlement-models/concept/concept-messaging-spring-boot-starter-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-spring-boot-starter-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-spring-boot-starter-c02.txt" ], "relations": [ "검증기는 발행이 아니라 주입이 강제다" ] }, { "title": "종료 순서가 두 수명 주기의 phase 로 표현된다", "slug": "messaging-spring-boot-starter-c03", "file": "delivery-and-settlement-models/concept/concept-messaging-spring-boot-starter-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-spring-boot-starter-c03", "messaging-spring-boot-starter-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-spring-boot-starter-c03.txt" ], "relations": [ "검증기는 발행이 아니라 주입이 강제다" ] }, { "title": "Spring Cloud Stream 브리지가 Spring을 import하지 않는다", "slug": "messaging-spring-cloud-stream-bridge-c02", "file": "delivery-and-settlement-models/concept/concept-messaging-spring-cloud-stream-bridge-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-spring-cloud-stream-bridge-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-spring-cloud-stream-bridge-c02.txt" ], "relations": [ "허용 의존 목록은 상한이므로 미사용을 잡지 않는다", "등록을 받는 컴포넌트는 해제도 제공한다", "함께 읽히는 두 맵은 한 값으로 묶는다", "에러 메시지가 지시하는 설정은 그 설정을 읽는 코드와 함께 존재해야 한다", "한 개념의 등록 상태를 두 객체가 나눠 갖지 않는다" ] }, { "title": "send가 true를 반환해도 AMBIGUOUS다", "slug": "messaging-spring-cloud-stream-bridge-c04", "file": "delivery-and-settlement-models/concept/concept-messaging-spring-cloud-stream-bridge-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-spring-cloud-stream-bridge-c04" ], "evidence": [ "../../../final/evidence/raw/messaging-spring-cloud-stream-bridge-c04.txt" ], "relations": [ "허용 의존 목록은 상한이므로 미사용을 잡지 않는다", "등록을 받는 컴포넌트는 해제도 제공한다", "함께 읽히는 두 맵은 한 값으로 묶는다", "에러 메시지가 지시하는 설정은 그 설정을 읽는 코드와 함께 존재해야 한다", "한 개념의 등록 상태를 두 객체가 나눠 갖지 않는다" ] }, { "title": "messaging family에서 예외 어휘가 가장 일관된 leaf", "slug": "messaging-spring-cloud-stream-bridge-c05", "file": "delivery-and-settlement-models/concept/concept-messaging-spring-cloud-stream-bridge-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-spring-cloud-stream-bridge-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-spring-cloud-stream-bridge-c05.txt" ], "relations": [ "허용 의존 목록은 상한이므로 미사용을 잡지 않는다", "등록을 받는 컴포넌트는 해제도 제공한다", "함께 읽히는 두 맵은 한 값으로 묶는다", "에러 메시지가 지시하는 설정은 그 설정을 읽는 코드와 함께 존재해야 한다", "한 개념의 등록 상태를 두 객체가 나눠 갖지 않는다" ] }, { "title": "지원한다는 단어의 정의를 코드로 못 박는 곳", "slug": "messaging-testkit-c01", "file": "delivery-and-settlement-models/concept/concept-messaging-testkit-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-testkit-c01", "messaging-testkit-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-testkit-c01.txt" ], "relations": [] }, { "title": "상속하는 쪽이 컴파일되려면 전부 전이되어야 한다", "slug": "messaging-testkit-c02", "file": "delivery-and-settlement-models/concept/concept-messaging-testkit-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-testkit-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-testkit-c02.txt" ], "relations": [] }, { "title": "세 leaf의 타입이 public 시그니처에 직접 등장한다", "slug": "messaging-transport-spi-c02", "file": "delivery-and-settlement-models/concept/concept-messaging-transport-spi-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-transport-spi-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-transport-spi-c02.txt" ], "relations": [ "멱등 종료를 보장하는 컴포넌트는 종료 이후의 등록도 정의한다", "같은 개념의 sentinel은 계층을 넘어 하나로 정한다" ] }, { "title": "factory는 검증하고 raw 생성자는 검증하지 않는다", "slug": "shared-contract-c01", "file": "delivery-and-settlement-models/concept/concept-shared-contract-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "shared-contract-c01", "shared-contract-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/shared-contract-c01.txt" ], "relations": [] } ], "reference": [], "question": [], "decision": [] } }, "drain-and-shutdown-ordering": { "topic": "drain-and-shutdown-ordering", "kinds": { "case": [ { "title": "새 승인을 거절한다는 메서드가 단계만 기록하고 아무것도 거절하지 않는다", "slug": "reject-new-admission-that-rejects-nothing", "file": "drain-and-shutdown-ordering/case/case-reject-new-admission-that-rejects-nothing.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "reject-new-admission-that-rejects-nothing" ], "evidence": [ "../../../final/evidence/raw/reject-new-admission-that-rejects-nothing.txt" ], "relations": [ "8단계 종료 순서 계약과 실제 종료 경로", "배수를 시작한 뒤에도 한 서비스가 다시 SERVING 이 될 수 있다", "검증기는 발행이 아니라 주입이 강제다" ] }, { "title": "비밀을 힙에서 지우는 마지막 단계가 종료 경로에 연결되지 않았다", "slug": "the-last-step-of-secret-erasure-is-not-wired", "file": "drain-and-shutdown-ordering/case/case-the-last-step-of-secret-erasure-is-not-wired.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "the-last-step-of-secret-erasure-is-not-wired" ], "evidence": [ "../../../final/evidence/raw/the-last-step-of-secret-erasure-is-not-wired.txt" ], "relations": [ "8단계 종료 순서 계약과 실제 종료 경로", "순서 계약을 구현하는 것이 없고, 그것을 검증한다는 테스트는 enum 선언 순서만 본다", "검증기는 발행이 아니라 주입이 강제다" ] } ], "concept": [ { "title": "8단계 종료 순서 계약과 실제 종료 경로", "slug": "the-eight-phase-shutdown-contract", "file": "drain-and-shutdown-ordering/concept/concept-the-eight-phase-shutdown-contract.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "the-eight-phase-shutdown-contract", "the-eight-phase-shutdown-contract-diagram" ], "evidence": [ "../../../final/evidence/raw/the-eight-phase-shutdown-contract.txt" ], "relations": [ "순서 계약을 구현하는 것이 없고, 그것을 검증한다는 테스트는 enum 선언 순서만 본다", "새 승인을 거절한다는 메서드가 단계만 기록하고 아무것도 거절하지 않는다", "비밀을 힙에서 지우는 마지막 단계가 종료 경로에 연결되지 않았다" ] } ], "reference": [ { "title": "선언 순서를 단언하는 테스트는 그 순서를 읽는 코드가 있을 때만 게이트다", "slug": "a-declaration-order-test-is-a-gate-only-if-something-reads-that-order", "file": "drain-and-shutdown-ordering/reference/reference-a-declaration-order-test-is-a-gate-only-if-something-reads-that-order.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "순서 계약을 구현하는 것이 없고, 그것을 검증한다는 테스트는 enum 선언 순서만 본다", "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "이름이 검사한다고 말하는 것을 본문이 검사하지 않는 테스트 다섯" ] } ], "question": [], "decision": [] } }, "drift-direction": { "topic": "drift-direction", "kinds": { "case": [ { "title": "실 브로커로 증명된 어댑터가 선택하면 기동이 실패하는 이름으로 등록돼 있다", "slug": "an-unselectable-broker-listed-with-features", "file": "drift-direction/case/case-an-unselectable-broker-listed-with-features.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "an-unselectable-broker-listed-with-features" ], "evidence": [ "../../../final/evidence/raw/an-unselectable-broker-listed-with-features.txt" ], "relations": [ "과대 진술 문서를 과소보다 먼저 고친다", "같은 개념의 두 어휘가 공존하면 하나를 죽은 것으로 표시한다", "문서 계약 테스트의 단언 경계 밖에 발견된 드리프트 세 건이 전부 있었다" ] }, { "title": "문서가 UUIDv7이라 말하고 생성되는 것은 v4다", "slug": "documented-uuidv7-generates-v4", "file": "drift-direction/case/case-documented-uuidv7-generates-v4.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "documented-uuidv7-generates-v4" ], "evidence": [ "../../../final/evidence/raw/documented-uuidv7-generates-v4.txt" ], "relations": [ "과대 진술 문서를 과소보다 먼저 고친다", "문서와 상수가 서로 일치하는 것으로는 아무것도 증명되지 않는다" ] }, { "title": "다섯 문서가 \"exactly 19 leaf\"라고 적고 레지스트리는 62다", "slug": "five-documents-say-nineteen-leaves", "file": "drift-direction/case/case-five-documents-say-nineteen-leaves.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "five-documents-say-nineteen-leaves" ], "evidence": [ "../../../final/evidence/raw/five-documents-say-nineteen-leaves.txt" ], "relations": [ "문서의 수치는 세지 말고 파생하거나 게이트로 붙든다", "빠뜨림이 통과가 되는 게이트는 게이트가 아니다" ] }, { "title": "출하 default 조합이 첫 write에서 예외를 던진다", "slug": "mongo-default-throws-on-first-write", "file": "drift-direction/case/case-mongo-default-throws-on-first-write.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "mongo-default-throws-on-first-write" ], "evidence": [ "../../../final/evidence/raw/mongo-default-throws-on-first-write.txt" ], "relations": [ "README의 활성화 recipe를 그대로 따르면 애플리케이션이 시작되지 않는다", "Bean 애너테이션이 있다는 것은 조립 증거가 아니다" ] }, { "title": "지원 매트릭스가 코드와 반대를 적었고, 그 오해가 소비자에게 자기 멱등성을 생략하게 한다", "slug": "support-matrix-said-the-opposite-of-the-code", "file": "drift-direction/case/case-support-matrix-said-the-opposite-of-the-code.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "support-matrix-said-the-opposite-of-the-code" ], "evidence": [ "../../../final/evidence/raw/support-matrix-said-the-opposite-of-the-code.txt", "../../../final/evidence/raw/tl-kafka-dedup-drift.txt" ], "relations": [ "과대 진술 문서를 과소보다 먼저 고친다", "문서 계약 테스트의 단언 경계 밖에 발견된 드리프트 세 건이 전부 있었다", "문서와 상수가 서로 일치하는 것으로는 아무것도 증명되지 않는다" ] }, { "title": "README의 활성화 recipe를 그대로 따르면 애플리케이션이 시작되지 않는다", "slug": "the-readme-recipe-does-not-start", "file": "drift-direction/case/case-the-readme-recipe-does-not-start.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "the-readme-recipe-does-not-start" ], "evidence": [ "../../../final/evidence/raw/the-readme-recipe-does-not-start.txt" ], "relations": [ "출하 default 조합이 첫 write에서 예외를 던진다", "과대 진술 문서를 과소보다 먼저 고친다" ] } ], "concept": [], "reference": [ { "title": "과대 진술 문서를 과소보다 먼저 고친다", "slug": "fix-overstatement-before-understatement", "file": "drift-direction/reference/reference-fix-overstatement-before-understatement.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "지원 매트릭스가 코드와 반대를 적었고, 그 오해가 소비자에게 자기 멱등성을 생략하게 한다", "여러 문서가 19개 리프라고 적고 레지스트리는 62다", "문서의 수치는 세지 말고 파생하거나 게이트로 붙든다" ] }, { "title": "문서의 수치는 세지 말고 파생하거나 게이트로 붙든다", "slug": "numbers-in-docs-should-be-derived", "file": "drift-direction/reference/reference-numbers-in-docs-should-be-derived.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "여러 문서가 19개 리프라고 적고 레지스트리는 62다", "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "과대 진술 문서를 과소보다 먼저 고친다" ] } ], "question": [ { "title": "문서 계약 테스트의 단언 범위를 capability 표까지 넓힐 것인가", "slug": "widen-doc-contract-assertions", "file": "drift-direction/question/openquestion-widen-doc-contract-assertions.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "문서 계약 테스트의 단언 경계 밖에 발견된 드리프트 세 건이 전부 있었다", "과대 진술 문서를 과소보다 먼저 고친다" ] } ], "decision": [ { "title": "지원 등급은 추론이 아니라 선언이고 증거 없이는 올라가지 않는다", "slug": "capability-grade-is-declared-not-inferred", "file": "drift-direction/decision/decision-capability-grade-is-declared-not-inferred.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "증거 등급과 provenance — R1과 R2를 가르는 것", "후보 증거는 통과해도 R1에 머무르고 R2는 별도 게이트가 판정한다", "지원 매트릭스가 코드와 반대를 적었고, 그 오해가 소비자에게 자기 멱등성을 생략하게 한다", "진단 리포트가 살아 있는 리소스를 담지 않도록 값 타입을 좁혔다" ] } ] } }, "duplicate-mechanisms": { "topic": "duplicate-mechanisms", "kinds": { "case": [ { "title": "요청 식별자를 클라이언트가 고를 수 없다는 정책이 뒤에 도는 필터에 뒤집혔다", "slug": "a-policy-reversed-by-a-later-filter", "file": "duplicate-mechanisms/case/case-a-policy-reversed-by-a-later-filter.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-policy-reversed-by-a-later-filter" ], "evidence": [ "../../../final/evidence/raw/a-policy-reversed-by-a-later-filter.txt" ], "relations": [ "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "클라이언트가 준 엔드포인트가 SSRF 가드가 아니라 약한 private 사본을 지났다", "sanitize가 아니라 reject가 기본이다" ] }, { "title": "정식 경계라고 적은 클래스가 그것을 구현하지 않는다", "slug": "a-retry-implementation-nobody-calls", "file": "duplicate-mechanisms/case/case-a-retry-implementation-nobody-calls.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-retry-implementation-nobody-calls" ], "evidence": [ "../../../final/evidence/raw/a-retry-implementation-nobody-calls.txt" ], "relations": [ "재시도 단위는 statement가 아니라 유스케이스 전체다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "@Bean이 있다는 것은 조립 증거가 아니다" ] }, { "title": "강한 가드가 웹푸시를 지목하는데 값 타입은 약한 검사를 다시 썼다", "slug": "a-weaker-private-copy-on-the-wired-path", "file": "duplicate-mechanisms/case/case-a-weaker-private-copy-on-the-wired-path.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-weaker-private-copy-on-the-wired-path", "a-weaker-private-copy-on-the-wired-path-probe" ], "evidence": [ "../../../final/evidence/raw/a-weaker-private-copy-on-the-wired-path.txt", "../../../final/evidence/raw/a-weaker-private-copy-on-the-wired-path-probe.txt" ], "relations": [ "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "sanitize가 아니라 reject가 기본이다", "요청 식별자를 클라이언트가 고를 수 없다는 정책이 뒤에 도는 필터에 뒤집혔다" ] }, { "title": "JPA 플랫폼 capability 대부분에 production 소비자가 없다", "slug": "jpa-platform-capabilities-have-no-consumer", "file": "duplicate-mechanisms/case/case-jpa-platform-capabilities-have-no-consumer.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "jpa-platform-capabilities-have-no-consumer" ], "evidence": [ "../../../final/evidence/raw/jpa-platform-capabilities-have-no-consumer.txt" ], "relations": [ "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "Bean 애너테이션이 있다는 것은 조립 증거가 아니다", "재시도 코디네이터는 빈이지만 그것을 어디에도 적용하지 않는다" ] }, { "title": "같은 저장소가 \"결정을 그 결정이 판정한 대상에 묶는 것\"을 한 번은 맞게, 한 번은 틀리게 썼다", "slug": "the-same-repository-bound-a-decision-once-and-not-the-other-time", "file": "duplicate-mechanisms/case/case-the-same-repository-bound-a-decision-once-and-not-the-other-time.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "the-same-repository-bound-a-decision-once-and-not-the-other-time" ], "evidence": [ "../../../final/evidence/raw/the-same-repository-bound-a-decision-once-and-not-the-other-time.txt" ], "relations": [ "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "같은 자격 증명 회전 결함이 한 가족에서 닫히고 다른 가족에서 재현됐다", "검증기는 발행이 아니라 주입이 강제다" ] }, { "title": "forwarded 헤더 신뢰 판정이 Nginx에만 있고 Java 정책 421 LOC은 배선되지 않았다", "slug": "trust-policy-lives-in-nginx-not-in-the-code", "file": "duplicate-mechanisms/case/case-trust-policy-lives-in-nginx-not-in-the-code.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "trust-policy-lives-in-nginx-not-in-the-code" ], "evidence": [ "../../../final/evidence/raw/trust-policy-lives-in-nginx-not-in-the-code.txt" ], "relations": [ "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "요청 식별자를 클라이언트가 고를 수 없다는 정책이 다른 필터에서 뒤집힌다" ] } ], "concept": [], "reference": [ { "title": "Atomic* 타입의 존재는 원자성의 증거가 아니다", "slug": "atomic-type-is-not-atomicity", "file": "duplicate-mechanisms/reference/reference-atomic-type-is-not-atomicity.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "커밋 증거 프레임을 두 주인이 pop해서 바깥 트랜잭션의 실패가 익명이 됐다" ] }, { "title": "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "slug": "check-which-duplicate-is-wired", "file": "duplicate-mechanisms/reference/reference-check-which-duplicate-is-wired.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "재시도 코디네이터는 빈이지만 그것을 어디에도 적용하지 않는다", "클라이언트가 준 엔드포인트가 SSRF 가드가 아니라 약한 private 사본을 지났다", "forwarded 헤더 신뢰 판정이 Nginx에 있고 Java 정책 421 LOC은 대부분 참조되지 않는다", "조립 결함을 판정하려면 조립하는 쪽을 먼저 읽어야 한다" ] }, { "title": "같은 개념의 두 어휘가 공존하면 하나를 죽은 것으로 표시한다", "slug": "two-vocabularies-for-one-concept", "file": "duplicate-mechanisms/reference/reference-two-vocabularies-for-one-concept.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "재시도 코디네이터는 빈이지만 그것을 어디에도 적용하지 않는다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다" ] } ], "question": [], "decision": [ { "title": "감사 메커니즘은 엔티티당 정확히 하나여야 한다", "slug": "one-audit-mechanism-per-entity", "file": "duplicate-mechanisms/decision/decision-one-audit-mechanism-per-entity.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "같은 개념의 두 어휘가 공존하면 하나를 죽은 것으로 표시한다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다" ] } ] } }, "failure-category-across-adapters": { "topic": "failure-category-across-adapters", "kinds": { "case": [ { "title": "종료 중이라는 사정이 업무의 영구 실패로 분류된다", "slug": "a-closing-transport-reported-as-a-permanent-business-failure", "file": "failure-category-across-adapters/case/case-a-closing-transport-reported-as-a-permanent-business-failure.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-closing-transport-reported-as-a-permanent-business-failure" ], "evidence": [ "../../../final/evidence/raw/a-closing-transport-reported-as-a-permanent-business-failure.txt" ], "relations": [ "실패 범주는 재시도·DLQ·대시보드 사이의 계약이다", "이 세대의 사정은 업무의 영구 실패가 아니다", "재시도 가능성은 멱등성과 실패 범주를 함께 봐야 정해진다" ] }, { "title": "브로커가 막으면 AUTHORIZATION, 플랫폼이 막으면 CONFIGURATION 이다", "slug": "an-authorization-denial-recorded-as-a-configuration-error", "file": "failure-category-across-adapters/case/case-an-authorization-denial-recorded-as-a-configuration-error.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "an-authorization-denial-recorded-as-a-configuration-error" ], "evidence": [ "../../../final/evidence/raw/an-authorization-denial-recorded-as-a-configuration-error.txt" ], "relations": [ "실패 범주는 재시도·DLQ·대시보드 사이의 계약이다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "권한 거부가 AUTHORIZATION이 아니라 CONFIGURATION으로 기록된다" ] } ], "concept": [], "reference": [ { "title": "실패 범주는 재시도·DLQ·대시보드 사이의 계약이다", "slug": "a-category-is-a-contract-between-retry-dlq-and-dashboard", "file": "failure-category-across-adapters/reference/reference-a-category-is-a-contract-between-retry-dlq-and-dashboard.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "권한 거부가 보안이 아니라 구성 오류로 기록된다", "종료 중이라는 사정이 업무의 영구 실패로 분류된다", "전송 실패의 단계와 범주 — `AttemptStage`와 `FailureCategory`" ] }, { "title": "이 세대의 사정은 업무의 영구 실패가 아니다", "slug": "this-generations-circumstance-is-not-a-permanent-failure", "file": "failure-category-across-adapters/reference/reference-this-generations-circumstance-is-not-a-permanent-failure.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "종료 중이라는 사정이 업무의 영구 실패로 분류된다", "실패 범주는 재시도·DLQ·대시보드 사이의 계약이다", "전송·업무·스트림 증거는 세 축이고 서로를 함의하지 않는다" ] } ], "question": [], "decision": [] } }, "file-transfer-and-storage": { "topic": "file-transfer-and-storage", "kinds": { "case": [ { "title": "부재로 판정된 결합이 원본 증거의 출력 안에 있다", "slug": "a08-f005-transferbufferpool-maxborrowedbytes", "file": "file-transfer-and-storage/case/case-a08-f005-transferbufferpool-maxborrowedbytes.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a08-f005-transferbufferpool-maxborrowedbytes", "a08-f005-transferbufferpool-maxborrowedbytes-peak" ], "evidence": [ "../../../final/evidence/raw/a08-f005-transferbufferpool-maxborrowedbytes.txt", "../../../final/evidence/raw/a08-f005-transferbufferpool-maxborrowedbytes-peak.txt" ], "relations": [ "소비자가 없는 fixture 셋", "그 속성을 보일 수 없는 대역 위에서 통과한 테스트는 증인이 아니다", "커버리지 gate 둘이 나란히 있고, 하나는 발화할 수 없다" ] }, { "title": "R1과 R2의 설정 취급이 비대칭이고, 검증된 쪽은 하나뿐이다", "slug": "analysis-finding-a08-f002", "file": "file-transfer-and-storage/case/case-analysis-finding-a08-f002.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a08-f002" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a08-f002.txt" ], "relations": [ "설정 오타는 실패해야 하고 무시되면 안 된다", "문서가 지목한 기본값 위치와 test 목록이 실제와 다르다", "빠뜨림이 통과가 되는 게이트는 게이트가 아니다" ] }, { "title": "문서가 지목한 기본값 위치와 test 목록이 실제와 다르다", "slug": "analysis-finding-a08-f003", "file": "file-transfer-and-storage/case/case-analysis-finding-a08-f003.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a08-f003" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a08-f003.txt" ], "relations": [ "두 selector의 설정 취급이 비대칭이고 검증된 쪽은 하나뿐이다", "README의 세 가지 사실 오류", "동작이 옳아도 문서가 가리킨 자리는 틀릴 수 있다" ] }, { "title": "발행 rename만 경로 기반이고, 그것을 지키는 것은 이 모듈이 \"근사에 불과하다\"고 적은 사전검사다", "slug": "analysis-finding-a08-f004", "file": "file-transfer-and-storage/case/case-analysis-finding-a08-f004.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a08-f004" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a08-f004.txt" ], "relations": [ "검사를 더 하는 것은 창을 좁힐 뿐 닫지 않는다", "두 selector의 설정 취급이 비대칭이고 검증된 쪽은 하나뿐이다", "계측 필드가 자기 회귀 test를 지목하는데 그 test가 읽지 않는다" ] }, { "title": "production 판정이 두 개의 리터럴 프로파일 이름에 걸려 있다", "slug": "analysis-finding-a09-f001", "file": "file-transfer-and-storage/case/case-analysis-finding-a09-f001.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a09-f001" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a09-f001.txt" ], "relations": [ "거부 검사의 근거를 허용 목록으로 두면 목록 밖이 통과한다", "사라진 가드가 문서에만 남았고 그 부재는 이미 승인된 결정이다", "발행 rename만 경로 기반이고 그것을 지키는 것은 모듈 자신이 근사에 불과하다고 적은 사전검사다" ] }, { "title": "그러나 R0 경계가 문서에만 있고 compile 경로에서 닫히지 않는다", "slug": "analysis-finding-a09-f004", "file": "file-transfer-and-storage/case/case-analysis-finding-a09-f004.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a09-f004" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a09-f004.txt" ], "relations": [ "두 개의 outbox 중 하나만 조립되어 있다", "production 판정이 두 개의 리터럴 프로파일 이름에 걸려 있다", "문서가 선언한 경계는 코드가 닫아야 경계다" ] }, { "title": "nonce replay 경계가 결과를 읽고 버린다", "slug": "analysis-finding-a09-f006", "file": "file-transfer-and-storage/case/case-analysis-finding-a09-f006.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a09-f006" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a09-f006.txt" ], "relations": [ "검사 결과를 읽고 버리면 검사가 아니다", "미배선 경계가 문서에만 있고 compile 경로에서 닫히지 않는다", "멱등은 결과를 같게 만들지만 경계를 대신하지는 않는다" ] } ], "concept": [], "reference": [], "question": [], "decision": [] } }, "fileserver-state-and-fencing": { "topic": "fileserver-state-and-fencing", "kinds": { "case": [ { "title": "claim이 소유자·토큰·만료를 기록하지 않아 죽은 worker의 항목이 영영 남았다", "slug": "a-cleanup-claim-without-fencing", "file": "fileserver-state-and-fencing/case/case-a-cleanup-claim-without-fencing.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-cleanup-claim-without-fencing" ], "evidence": [ "../../../final/evidence/raw/a-cleanup-claim-without-fencing.txt" ], "relations": [ "fenced lease — 만료 시각만으로는 부족한 이유", "리스가 만료 시각만 기록하고 소유자를 기록하지 않아 최종 상태를 되돌릴 수 있었다", "cleanup이 읽은 lease와 삭제 사이에 writer가 그 lease를 얻을 수 있었다" ] }, { "title": "cleanup이 읽은 lease와 삭제 사이에 writer가 그 lease를 얻을 수 있었다", "slug": "a-read-then-delete-race-on-the-upload-lease", "file": "fileserver-state-and-fencing/case/case-a-read-then-delete-race-on-the-upload-lease.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-read-then-delete-race-on-the-upload-lease" ], "evidence": [ "../../../final/evidence/raw/a-read-then-delete-race-on-the-upload-lease.txt" ], "relations": [ "조건부 update로 행을 claim하고 읽은 값으로 판단하지 않는다", "CAS 튜플을 where 절에 전부 반복하고 update count를 답으로 쓴다", "claim이 소유자·토큰·만료를 기록하지 않아 죽은 worker의 항목이 영영 남았다" ] }, { "title": "README가 \"노출된 setting도 bean도 없다\"고 적은 능력에 production bean 여덟이 있다", "slug": "readme-said-no-beans-there-are-eight", "file": "fileserver-state-and-fencing/case/case-readme-said-no-beans-there-are-eight.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "readme-said-no-beans-there-are-eight" ], "evidence": [ "../../../final/evidence/raw/readme-said-no-beans-there-are-eight.txt" ], "relations": [ "과대 진술 문서를 과소보다 먼저 고친다", "Bean 애너테이션이 있다는 것은 조립 증거가 아니다", "문서의 수치는 세지 말고 파생하거나 게이트로 붙든다" ] }, { "title": "scriptable 콘텐츠 탐지가 BOM·NUL·주석으로 우회된다", "slug": "scriptable-detection-bypassed-by-a-bom", "file": "fileserver-state-and-fencing/case/case-scriptable-detection-bypassed-by-a-bom.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "scriptable-detection-bypassed-by-a-bom" ], "evidence": [ "../../../final/evidence/raw/scriptable-detection-bypassed-by-a-bom.txt" ], "relations": [ "접두사 시작 매칭은 시그니처에는 맞고 스니핑 패턴에는 맞지 않는다", "sanitize가 아니라 reject가 기본이다" ] } ], "concept": [ { "title": "파일 상태 기계와 READY가 뜻하는 것", "slug": "file-state-machine-and-ready", "file": "fileserver-state-and-fencing/concept/concept-file-state-machine-and-ready.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "file-state-machine-and-ready", "file-state-machine-and-ready-diagram" ], "evidence": [ "../../../final/evidence/raw/file-state-machine-and-ready.txt" ], "relations": [ "공개 읽기 가능한 상태는 완전한 identity를 DB 제약으로 요구한다", "물리 경로와 원본 파일명을 저장하지 않는다", "claim이 소유자와 토큰과 만료를 기록하지 않아 죽은 worker의 항목이 영영 남았다" ] } ], "reference": [ { "title": "공개 읽기 가능한 상태는 완전한 identity를 DB 제약으로 요구한다", "slug": "a-publicly-readable-state-must-be-complete-by-constraint", "file": "fileserver-state-and-fencing/reference/reference-a-publicly-readable-state-must-be-complete-by-constraint.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "파일 상태 기계와 READY가 뜻하는 것", "CAS 튜플을 where 절에 전부 반복하고 update count를 답으로 쓴다", "위험한 조합은 정책이 아니라 생성자가 거부하게 만든다" ] }, { "title": "조건부 update로 행을 claim하고 읽은 값으로 판단하지 않는다", "slug": "claim-with-a-conditional-update-not-a-read", "file": "fileserver-state-and-fencing/reference/reference-claim-with-a-conditional-update-not-a-read.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "cleanup이 읽은 lease와 삭제 사이에 writer가 그 lease를 얻을 수 있었다", "CAS 튜플을 where 절에 전부 반복하고 update count를 답으로 쓴다", "시간은 DB에서, 그리고 행을 잠근 다음에 읽는다" ] }, { "title": "접두사 시작 매칭은 시그니처에는 맞고 스니핑 패턴에는 맞지 않는다", "slug": "prefix-matching-fits-signatures-not-sniffing", "file": "fileserver-state-and-fencing/reference/reference-prefix-matching-fits-signatures-not-sniffing.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "scriptable 콘텐츠 탐지가 BOM과 NUL과 주석으로 우회된다", "sanitize가 아니라 reject가 기본이다" ] } ], "question": [], "decision": [ { "title": "물리 경로와 원본 파일명을 저장하지 않는다", "slug": "no-physical-paths-in-metadata", "file": "fileserver-state-and-fencing/decision/decision-no-physical-paths-in-metadata.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "파일 상태 기계와 READY가 뜻하는 것", "sanitize가 아니라 reject가 기본이다", "이름은 값이 아니라 registry key다" ] } ] } }, "graphql-surface": { "topic": "graphql-surface", "kinds": { "case": [ { "title": "플랫폼이 강제한다고 적었지만 그 규칙을 실제로 거는 것은 라이브러리다", "slug": "a16-f002-oneof", "file": "graphql-surface/case/case-a16-f002-oneof.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a16-f002-oneof", "a16-f002-oneof-run" ], "evidence": [ "../../../final/evidence/raw/a16-f002-oneof.txt", "../../../final/evidence/raw/a16-f002-oneof-run.txt" ], "relations": [ "크로스 스택 게이트가 검증하는 조립은 픽스처의 조립이고, 플랫폼의 조립이 아니다", "검증기는 발행이 아니라 주입이 강제다", "설정 바인딩이 마스터 스위치 밖에서 일어난다. 컴포지션 루트의 자기 규칙과 어긋난다" ] }, { "title": "연산 이름 정책의 두 구현 중 하나만 배선되고, 미배선 쪽만 GraphQlOperationNamePolicy를 쓴다", "slug": "a16-f004-graphqloperationnamepolicy", "file": "graphql-surface/case/case-a16-f004-graphqloperationnamepolicy.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a16-f004-graphqloperationnamepolicy", "a16-f004-graphqloperationnamepolicy-run" ], "evidence": [ "../../../final/evidence/raw/a16-f004-graphqloperationnamepolicy.txt", "../../../final/evidence/raw/a16-f004-graphqloperationnamepolicy-run.txt" ], "relations": [ "프로파일별 정책 매니페스트가 미배선이라, 자격에서 해석된 프로파일이 아무 예산도 선택하지 않는다", "플랫폼이 강제한다고 적었지만 그 규칙을 실제로 거는 것은 라이브러리다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다" ] }, { "title": "스키마 조립·계약 정체성·해시 사슬이 통째로 미배선이고, 그것을 발행할 액추에이터 엔드포인트도 등록되지 않는다", "slug": "analysis-finding-a16-f001", "file": "graphql-surface/case/case-analysis-finding-a16-f001.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a16-f001" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a16-f001.txt" ], "relations": [ "시작 검증기가 시작 시 실행되지 않는다", "5계층 예산 모델에서 요청 계층만 강제되고 나머지 파생이 전부 미배선이다", "만들어졌으나 아무도 만들지 않는 타입은 계약이 아니다" ] }, { "title": "5계층 예산 모델에서 요청 계층만 강제되고, 나머지 파생이 전부 미배선이다", "slug": "analysis-finding-a16-f003", "file": "graphql-surface/case/case-analysis-finding-a16-f003.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a16-f003" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a16-f003.txt" ], "relations": [ "스키마 조립과 계약 정체성과 해시 사슬이 통째로 미배선이고 그것을 발행할 엔드포인트도 등록되지 않는다", "용량 보호 계층 전체가 자기 테스트 픽스처 안에서만 실행된다", "계층을 나눈 이유가 코드에 적혀 있어도 파생이 없으면 계층은 하나다" ] }, { "title": "설정으로 정한 파서 한계가 graphql-java에 설치되지 않는다", "slug": "analysis-finding-a16-f005", "file": "graphql-surface/case/case-analysis-finding-a16-f005.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a16-f005" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a16-f005.txt" ], "relations": [ "배열 원소 상한이 선언만 되고 강제되지 않으며 백스톱도 없다", "5계층 예산 모델에서 요청 계층만 강제되고 나머지 파생이 전부 미배선이다", "설정은 받아들여지고 검증되며 효과가 없다" ] }, { "title": "프로파일별 정책 매니페스트가 미배선이라, 자격에서 해석된 프로파일이 아무 예산도 선택하지 않는다", "slug": "analysis-finding-a16-f006", "file": "graphql-surface/case/case-analysis-finding-a16-f006.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a16-f006" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a16-f006.txt" ], "relations": [ "연산 이름 정책의 두 구현 중 하나만 배선되고 미배선 쪽만 정책 객체를 쓴다", "설정으로 정한 파서 한계가 라이브러리에 설치되지 않는다", "값이 정확히 해석되어도 그것을 쓰는 조회가 없으면 효과가 없다" ] }, { "title": "파싱·검증 실패에 플랫폼 매퍼가 없다", "slug": "analysis-finding-a16-f008", "file": "graphql-surface/case/case-analysis-finding-a16-f008.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a16-f008" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a16-f008.txt" ], "relations": [ "설정으로 정한 파서 한계가 라이브러리에 설치되지 않는다", "5계층 예산 모델에서 요청 계층만 강제되고 나머지 파생이 전부 미배선이다", "오류 코드로 분기하는 클라이언트는 형식이 갈리는 지점에서 빗나간다" ] }, { "title": "기계가 읽는 능력 매니페스트와 사람이 읽는 등급표가 커서 서명에 대해 다르게 답한다", "slug": "analysis-finding-a16-f011", "file": "graphql-surface/case/case-analysis-finding-a16-f011.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a16-f011" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a16-f011.txt" ], "relations": [ "기본 비활성은 존재하지 않는 스위치의 기본값을 서술한다", "프로파일별 정책 매니페스트가 미배선이라 자격에서 해석된 프로파일이 아무 예산도 선택하지 않는다", "두 목록이 같은 사실을 말하게 하려면 한 test로 묶는다" ] }, { "title": "'\"기본 비활성\"은 존재하지 않는 스위치의 기본값을 서술한다'", "slug": "analysis-finding-a16-f012", "file": "graphql-surface/case/case-analysis-finding-a16-f012.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a16-f012" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a16-f012.txt" ], "relations": [ "기계가 읽는 능력 매니페스트와 사람이 읽는 등급표가 같은 능력에 대해 다르게 답한다", "선언된 Advanced 능력 11개 중 9개는 켜는 방법이 없다", "등급표가 정확하면 산문만 고치면 된다" ] } ], "concept": [], "reference": [], "question": [], "decision": [] } }, "grpc-and-streaming": { "topic": "grpc-and-streaming", "kinds": { "case": [ { "title": "grpc 레인 시험 25개는 check 로 돌고, 레인만 거는 실행 0 검사는 돌지 않는다", "slug": "a20-f003-claude", "file": "grpc-and-streaming/case/case-a20-f003-claude.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a20-f003-claude" ], "evidence": [ "../../../final/evidence/raw/a20-f003-claude.txt" ], "relations": [ "아무도 돌리지 않는 레인의 게이트는 마지막으로 돌린 사람이 본 것을 보고한다", "네 레인이 check 에 붙지 않고, 이 가족을 이름으로 부르는 워크플로가 없다", "release gate가 실제로 차단하는 것은 hermetic test 3개이고, mongo용 CI workflow는 없다" ] }, { "title": "승격이 상한 필드를 읽지 않고, 세 승인 메서드의 main 호출자가 0 이다", "slug": "a20-f006-grpcadmissioncontroller-tryadmit", "file": "grpc-and-streaming/case/case-a20-f006-grpcadmissioncontroller-tryadmit.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a20-f006-grpcadmissioncontroller-tryadmit" ], "evidence": [ "../../../final/evidence/raw/a20-f006-grpcadmissioncontroller-tryadmit.txt" ], "relations": [ "스트림 승인의 경계가 동시성 아래에서 새고, caller별 맵이 줄지 않는다", "원자 타입 위의 검사 후 실행과 비교 후 교체 루프", "테스트에서는 드물고 부하에서는 일상인 것" ] }, { "title": "GrpcStreamAdmission 의 호출자 맵이 줄지 않고 main 소비자는 0 이다", "slug": "a20-f007-grpcstreamadmission", "file": "grpc-and-streaming/case/case-a20-f007-grpcstreamadmission.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a20-f007-grpcstreamadmission" ], "evidence": [ "../../../final/evidence/raw/a20-f007-grpcstreamadmission.txt" ], "relations": [ "스트림 승인의 경계가 동시성 아래에서 새고, caller별 맵이 줄지 않는다", "queued 를 줄이는 유일한 연산이 상한을 읽지 않는 승격 안에 있다", "카디널리티 경계를 타입으로 표현하기" ] }, { "title": "GrpcSerializedStreamWriter 가 버린 봉투 대신 들어오는 크기를 뺀다", "slug": "a20-f008-grpcserializedstreamwriter-drop-oldest", "file": "grpc-and-streaming/case/case-a20-f008-grpcserializedstreamwriter-drop-oldest.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a20-f008-grpcserializedstreamwriter-drop-oldest" ], "evidence": [ "../../../final/evidence/raw/a20-f008-grpcserializedstreamwriter-drop-oldest.txt" ], "relations": [ "queued 를 줄이는 유일한 연산이 상한을 읽지 않는 승격 안에 있다", "배치 상한이 개수와 바이트 두 축인 이유", "테스트에서는 드물고 부하에서는 일상인 것" ] }, { "title": "GrpcOutcomeReplay 의 맵에 put·get·size 뿐이고 부르는 코드도 없다", "slug": "a20-f010-grpcoutcomereplay", "file": "grpc-and-streaming/case/case-a20-f010-grpcoutcomereplay.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a20-f010-grpcoutcomereplay" ], "evidence": [ "../../../final/evidence/raw/a20-f010-grpcoutcomereplay.txt" ], "relations": [ "GrpcStreamAdmission 의 호출자 맵이 줄지 않고 main 소비자는 0 이다", "체크포인트 전진이 ConcurrentMap 위의 확인 후 쓰기다", "조립 결함을 판정하려면 조립하는 쪽을 먼저 읽어야 한다" ] }, { "title": "GrpcCompletionReconciler 의 pending 만 잠금 없는 ArrayList 다", "slug": "a20-f011-grpccompletionreconciler-arraylist", "file": "grpc-and-streaming/case/case-a20-f011-grpccompletionreconciler-arraylist.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a20-f011-grpccompletionreconciler-arraylist" ], "evidence": [ "../../../final/evidence/raw/a20-f011-grpccompletionreconciler-arraylist.txt" ], "relations": [ "queued 를 줄이는 유일한 연산이 상한을 읽지 않는 승격 안에 있다", "의도적으로 스레드 안전하지 않은 타입이 하나 있다", "실행 코드가 없어서 동시성 계약이 전부 문서다" ] }, { "title": "원인 사슬 순회가 2-순환에서 무한 루프에 빠지고, 저장소는 이미 그 사례를 이름으로 적어 두었다", "slug": "analysis-finding-a15-f001", "file": "grpc-and-streaming/case/case-analysis-finding-a15-f001.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a15-f001" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a15-f001.txt" ], "relations": [ "원인 사슬은 바깥부터 안쪽까지 걸어야 한다", "자기참조 검사는 2-순환을 잡지 못한다", "같은 문제를 다른 모듈에서는 닫았다" ] }, { "title": "설정 바인딩이 마스터 스위치 밖에서 일어난다. 컴포지션 루트의 자기 규칙과 어긋난다", "slug": "analysis-finding-a15-f002", "file": "grpc-and-streaming/case/case-analysis-finding-a15-f002.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a15-f002" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a15-f002.txt" ], "relations": [ "원인 사슬 순회가 2-순환에서 무한 루프에 빠지고 저장소는 이미 그 사례를 이름으로 적어 두었다", "지금 안전한 것은 규칙이 지켜져서가 아니라 기본값이 유효해서다", "문서가 선언한 경계는 코드가 닫아야 경계다" ] }, { "title": "조립 경계가 정책 객체 9개를 만들고 서버를 만들지 않는다", "slug": "analysis-finding-a20-f004", "file": "grpc-and-streaming/case/case-analysis-finding-a20-f004.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a20-f004" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a20-f004.txt" ], "relations": [ "크로스 스택 게이트가 검증하는 조립은 픽스처의 조립이고 플랫폼의 조립이 아니다", "저장소 어디에도 참조가 없는 타입 3개", "손으로 만드는 목록은 적어도 한 번은 거꾸로 만든다" ] }, { "title": "저장소 어디에도 참조가 없는 타입 3개", "slug": "analysis-finding-a20-f005", "file": "grpc-and-streaming/case/case-analysis-finding-a20-f005.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a20-f005" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a20-f005.txt" ], "relations": [ "조립 경계가 정책 객체 9개를 만들고 서버를 만들지 않는다", "소비자가 없는 fixture 셋", "던지는 코드도 잡는 코드도 없으면 분기할 것이 없다" ] } ], "concept": [], "reference": [], "question": [], "decision": [] } }, "http-client-and-resilience": { "topic": "http-client-and-resilience", "kinds": { "case": [ { "title": "누수 하나는 회수되고 하나는 회수되지 않는다", "slug": "a11-f001-close", "file": "http-client-and-resilience/case/case-a11-f001-close.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a11-f001-close", "a11-f001-close-leak" ], "evidence": [ "../../../final/evidence/raw/a11-f001-close.txt", "../../../final/evidence/raw/a11-f001-close-leak.txt" ], "relations": [ "회전이 틈으로 관측되지 않게 만든 순서와 두 누수 이력", "타입이 문서화한 불변식은 타입이 강제한다", "그 속성을 보일 수 없는 대역 위에서 통과한 테스트는 증인이 아니다" ] }, { "title": "설정 참고 문서가 약속한 코드를 운영자는 받지 못한다", "slug": "a11-f002-pool-route-exceeds-total", "file": "http-client-and-resilience/case/case-a11-f002-pool-route-exceeds-total.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a11-f002-pool-route-exceeds-total", "a11-f002-pool-route-exceeds-total-shape" ], "evidence": [ "../../../final/evidence/raw/a11-f002-pool-route-exceeds-total.txt", "../../../final/evidence/raw/a11-f002-pool-route-exceeds-total-shape.txt" ], "relations": [ "지워도 test가 초록인 검사가 셋이다", "위반 코드 34종 중 22종이 어떤 test에서도 이름으로 확인되지 않는다", "문서가 지목하는 조정 레코드를 쓰는 코드가 없다" ] }, { "title": "재생 가능으로 인증된 본문이 다른 바이트를 낸다", "slug": "a11-f004-number", "file": "http-client-and-resilience/case/case-a11-f004-number.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a11-f004-number", "a11-f004-number-bytes" ], "evidence": [ "../../../final/evidence/raw/a11-f004-number.txt", "../../../final/evidence/raw/a11-f004-number-bytes.txt" ], "relations": [ "재시도 안전성은 증거에 기반해 판정한다", "지워도 test가 초록인 검사가 셋이다", "타입이 문서화한 불변식은 타입이 강제한다" ] }, { "title": "부르는 쪽이 이미 걸어 둔 것을 한 번 더 건다", "slug": "a11-f006-boundeddatabufferflux", "file": "http-client-and-resilience/case/case-a11-f006-boundeddatabufferflux.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a11-f006-boundeddatabufferflux", "a11-f006-boundeddatabufferflux-release" ], "evidence": [ "../../../final/evidence/raw/a11-f006-boundeddatabufferflux.txt", "../../../final/evidence/raw/a11-f006-boundeddatabufferflux-release.txt" ], "relations": [ "타입이 문서화한 불변식은 타입이 강제한다", "누수 하나는 회수되고 하나는 회수되지 않는다", "그 속성을 보일 수 없는 대역 위에서 통과한 테스트는 증인이 아니다" ] }, { "title": "혼동이라 적어 둔 이름이 아직 검사 문구에 있다", "slug": "a11-f007-dns", "file": "http-client-and-resilience/case/case-a11-f007-dns.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a11-f007-dns", "a11-f007-dns-overloads" ], "evidence": [ "../../../final/evidence/raw/a11-f007-dns.txt", "../../../final/evidence/raw/a11-f007-dns-overloads.txt" ], "relations": [ "두 오버로드가 있었고 호출되는 쪽이 틀린 쪽이었다", "재생 가능으로 인증된 본문이 다른 바이트를 낸다", "가드의 존재가 곧 테넌트 격리 보장은 아니다" ] }, { "title": "위반 코드 34종 중 22종이 어떤 test에서도 이름으로 확인되지 않는다", "slug": "analysis-finding-a11-f003", "file": "http-client-and-resilience/case/case-analysis-finding-a11-f003.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a11-f003" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a11-f003.txt" ], "relations": [ "풀 상한 위반 코드는 발화할 수 없다", "코드 자체가 옳아도 회귀를 막는 것은 test다", "커버리지 gate 둘이 나란히 있고 하나는 발화할 수 없다" ] } ], "concept": [], "reference": [], "question": [], "decision": [] } }, "http-failure-classification": { "topic": "http-failure-classification", "kinds": { "case": [ { "title": "로컬 거부 경로에서 회로 브레이커 permission이 반환되지 않는다", "slug": "a-circuit-breaker-permit-that-leaks-on-local-rejection", "file": "http-failure-classification/case/case-a-circuit-breaker-permit-that-leaks-on-local-rejection.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-circuit-breaker-permit-that-leaks-on-local-rejection" ], "evidence": [ "../../../final/evidence/raw/a-circuit-breaker-permit-that-leaks-on-local-rejection.txt" ], "relations": [ "전송 실패의 단계와 범주 — AttemptStage와 FailureCategory" ] }, { "title": "붉은 테스트를 제품 결함으로 읽은 오진 — 듀얼스택 localhost가 TLS 실패를 버린다", "slug": "a-red-test-misread-as-a-product-defect", "file": "http-failure-classification/case/case-a-red-test-misread-as-a-product-defect.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-red-test-misread-as-a-product-defect", "a-red-test-misread-as-a-product-defect-host-control" ], "evidence": [ "../../../final/evidence/raw/a-red-test-misread-as-a-product-defect.txt", "../../../final/evidence/raw/a-red-test-misread-as-a-product-defect-host-control.txt" ], "relations": [ "전송 실패의 단계와 범주 — AttemptStage와 FailureCategory", "분류기는 엔진이 남긴 것만 볼 수 있다", "런타임의 모양에 대한 주장은 런타임에서 확인한다", "재시도 안전성은 증거에 기반해 판정한다" ] } ], "concept": [ { "title": "전송 실패의 단계와 범주 — AttemptStage와 FailureCategory", "slug": "transport-failure-stage-and-category", "file": "http-failure-classification/concept/concept-transport-failure-stage-and-category.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "transport-failure-stage-and-category", "transport-failure-stage-and-category-diagram" ], "evidence": [ "../../../final/evidence/raw/transport-failure-stage-and-category.txt" ], "relations": [ "붉은 테스트를 제품 결함으로 읽은 오진", "분류기는 엔진이 남긴 것만 볼 수 있다", "재시도 가능성은 멱등성과 실패 범주를 함께 봐야 정해진다", "재시도 안전성은 증거에 기반해 판정한다" ] } ], "reference": [ { "title": "분류기는 엔진이 남긴 것만 볼 수 있다", "slug": "a-classifier-sees-only-what-the-engine-kept", "file": "http-failure-classification/reference/reference-a-classifier-sees-only-what-the-engine-kept.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "붉은 테스트를 제품 결함으로 읽은 오진", "원인 사슬은 가장 구체적인 분류가 이기도록 순회한다" ] }, { "title": "재시도 가능성은 멱등성과 실패 범주를 함께 봐야 정해진다", "slug": "retryability-needs-both-idempotency-and-category", "file": "http-failure-classification/reference/reference-retryability-needs-both-idempotency-and-category.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "전송 실패를 단계와 범주 두 축으로 모델링한다", "재시도 안전성은 증거에 기반해 판정한다" ] }, { "title": "런타임의 모양에 대한 주장은 런타임에서 확인한다", "slug": "verify-runtime-shape-at-runtime", "file": "http-failure-classification/reference/reference-verify-runtime-shape-at-runtime.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "붉은 테스트를 제품 결함으로 읽은 오진", "분류기는 엔진이 남긴 것만 볼 수 있다" ] }, { "title": "원인 사슬은 가장 구체적인 분류가 이기도록 순회한다", "slug": "walk-the-cause-chain-most-specific-wins", "file": "http-failure-classification/reference/reference-walk-the-cause-chain-most-specific-wins.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "분류기는 엔진이 남긴 것만 볼 수 있다", "붉은 테스트를 제품 결함으로 읽은 오진" ] } ], "question": [], "decision": [ { "title": "재시도 안전성은 증거에 기반해 판정한다", "slug": "retry-safety-is-decided-by-evidence", "file": "http-failure-classification/decision/decision-retry-safety-is-decided-by-evidence.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "전송 실패를 단계와 범주 두 축으로 모델링한다", "재시도 가능성은 멱등성과 실패 범주를 함께 봐야 정해진다", "붉은 테스트를 제품 결함으로 읽은 오진" ] } ] } }, "identity-and-identifier": { "topic": "identity-and-identifier", "kinds": { "case": [ { "title": "UuidCodec 의 메서드를 부르는 줄은 자기 명세 다섯뿐이다", "slug": "a07-f001-uuidcodec", "file": "identity-and-identifier/case/case-a07-f001-uuidcodec.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a07-f001-uuidcodec", "a07-f001-uuidcodec-elsewhere" ], "evidence": [ "../../../final/evidence/raw/a07-f001-uuidcodec.txt", "../../../final/evidence/raw/a07-f001-uuidcodec-elsewhere.txt" ], "relations": [ "@Bean이 있다는 것은 조립 증거가 아니다", "소비자가 없는 fixture 셋", "normalize는 canonical이 아닌 입력을 받아 다른 UUID로 조용히 바꾼다", "문서가 선언됐다는 둘은 없고, 선언된 하나는 그 문장에 없다" ] }, { "title": "정규형에서 한 글자를 지운 입력이 거부되지 않고 정규형으로 채워진다", "slug": "a07-f002-normalize", "file": "identity-and-identifier/case/case-a07-f002-normalize.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a07-f002-normalize", "a07-f002-normalize-probe" ], "evidence": [ "../../../final/evidence/raw/a07-f002-normalize.txt", "../../../final/evidence/raw/a07-f002-normalize-probe.txt" ], "relations": [ "UuidCodec 의 메서드를 부르는 줄은 자기 명세 다섯뿐이다", "sanitize가 아니라 reject가 기본이다", "그 속성을 보일 수 없는 대역 위에서 통과한 테스트는 증인이 아니다" ] }, { "title": "문서가 선언됐다는 둘은 없고, 선언된 하나는 그 문장에 없다", "slug": "a07-f004-claude", "file": "identity-and-identifier/case/case-a07-f004-claude.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a07-f004-claude" ], "evidence": [ "../../../final/evidence/raw/a07-f004-claude.txt" ], "relations": [ "사라진 가드가 문서에만 남았고 그 부재는 이미 승인된 결정이다", "README의 세 가지 사실 오류", "허용 의존 목록은 상한이므로 미사용을 잡지 않는다" ] }, { "title": "사라진 가드가 문서에만 남았고 그 부재는 이미 승인된 결정이다", "slug": "a07-f006-claude", "file": "identity-and-identifier/case/case-a07-f006-claude.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a07-f006-claude" ], "evidence": [ "../../../final/evidence/raw/a07-f006-claude.txt" ], "relations": [ "문서가 선언됐다는 둘은 없고, 선언된 하나는 그 문장에 없다", "산문이 선언한 게이트는 빌드에 있는 게이트가 아니다", "release gate가 실제로 차단하는 것은 hermetic test 3개이고, mongo용 CI workflow는 없다" ] }, { "title": "README의 세 가지 사실 오류", "slug": "analysis-finding-a07-f005", "file": "identity-and-identifier/case/case-analysis-finding-a07-f005.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a07-f005" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a07-f005.txt" ], "relations": [ "문서가 선언됐다는 둘은 없고, 선언된 하나는 그 문장에 없다", "사라진 가드가 문서에만 남았고 그 부재는 이미 승인된 결정이다", "문서가 아니라 빌드 파일이 의존성의 진실이다" ] } ], "concept": [], "reference": [], "question": [], "decision": [] } }, "identity-and-value-contracts": { "topic": "identity-and-value-contracts", "kinds": { "case": [ { "title": "never-before-used 는 시그니처가 줄 수 없는 보장이다", "slug": "a01-f002-idfactory-newid", "file": "identity-and-value-contracts/case/case-a01-f002-idfactory-newid.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a01-f002-idfactory-newid" ], "evidence": [ "../../../final/evidence/raw/a01-f002-idfactory-newid.txt" ], "relations": [ "이름은 값이 아니라 registry key다", "문서가 UUIDv7이라 말하고 생성되는 것은 v4다" ] } ], "concept": [ { "title": "상속으로 강제하는 계약과 태스크 그래프로 강제하는 계약", "slug": "adapter-inbound-web-c19", "file": "identity-and-value-contracts/concept/concept-adapter-inbound-web-c19.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c19" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c19.txt" ], "relations": [] }, { "title": "부재 주장을 지키는 세 자리 — 선언·구현·정책", "slug": "adapter-outbound-cache-redis-c03", "file": "identity-and-value-contracts/concept/concept-adapter-outbound-cache-redis-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-cache-redis-c03", "adapter-outbound-cache-redis-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-cache-redis-c03.txt" ], "relations": [] }, { "title": "SSRF 가드의 호출처 둘과 javadoc이 지목하는 둘이 다르다", "slug": "adapter-outbound-notification-c05", "file": "identity-and-value-contracts/concept/concept-adapter-outbound-notification-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-notification-c05" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-notification-c05.txt" ], "relations": [] }, { "title": "상속을 강제하는 장치가 없어 8종 중 3종만 계약을 탄다", "slug": "adapter-outbound-notification-c06", "file": "identity-and-value-contracts/concept/concept-adapter-outbound-notification-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-notification-c06" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-notification-c06.txt" ], "relations": [] }, { "title": "경로 방어는 세그먼트마다, 발행은 배타적 하드링크로", "slug": "adapter-outbound-objectstorage-c09", "file": "identity-and-value-contracts/concept/concept-adapter-outbound-objectstorage-c09.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-objectstorage-c09" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-objectstorage-c09.txt" ], "relations": [] }, { "title": "자동설정 안의 @ConditionalOnBean은 컴포넌트 스캔과 다르다", "slug": "app-bootstrap-c04", "file": "identity-and-value-contracts/concept/concept-app-bootstrap-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "app-bootstrap-c04" ], "evidence": [ "../../../final/evidence/raw/app-bootstrap-c04.txt" ], "relations": [] }, { "title": "게이트가 인자를 받지 않고 집합을 돌려주는 이유", "slug": "grpc-core-api-c01", "file": "identity-and-value-contracts/concept/concept-grpc-core-api-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-core-api-c01" ], "evidence": [ "../../../final/evidence/raw/grpc-core-api-c01.txt" ], "relations": [] }, { "title": "계약 테스트 일곱 개를 어댑터가 지울 수 없게 만든 방식", "slug": "messaging-testkit-c04", "file": "identity-and-value-contracts/concept/concept-messaging-testkit-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-testkit-c04", "messaging-testkit-c04-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-testkit-c04.txt" ], "relations": [] } ], "reference": [], "question": [], "decision": [] } }, "learning-transfer-between-families": { "topic": "learning-transfer-between-families", "kinds": { "case": [ { "title": "같은 자격 증명 회전 결함이 한 가족에서 닫히고 다른 가족에서 재현됐다", "slug": "the-same-rotation-defect-closed-once-and-reproduced", "file": "learning-transfer-between-families/case/case-the-same-rotation-defect-closed-once-and-reproduced.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "the-same-rotation-defect-closed-once-and-reproduced" ], "evidence": [ "../../../final/evidence/raw/the-same-rotation-defect-closed-once-and-reproduced.txt", "../../../final/evidence/raw/tl-rotation-defect-reproduced.txt" ], "relations": [ "Atomic 타입의 존재는 원자성의 증거가 아니다", "레지스트리로 표현된 규칙은 전이되고 CI로 표현된 규칙은 전이되지 않는다", "두 번째 플랫폼이 첫 번째의 bridge 부재는 막고 게이트 배선은 옮기지 않았다" ] }, { "title": "두 번째 플랫폼이 첫 번째의 bridge 부재는 막고 게이트 배선은 옮기지 않았다", "slug": "the-second-platform-carried-the-design-not-the-wiring", "file": "learning-transfer-between-families/case/case-the-second-platform-carried-the-design-not-the-wiring.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "the-second-platform-carried-the-design-not-the-wiring" ], "evidence": [ "../../../final/evidence/raw/the-second-platform-carried-the-design-not-the-wiring.txt", "../../../final/evidence/raw/tl-platform-suite-results.txt", "../../../final/evidence/raw/tl-grpc-evidence-lanes.txt" ], "relations": [ "레지스트리로 표현된 규칙은 전이되고 CI로 표현된 규칙은 전이되지 않는다", "릴리스 게이트가 읽는 증거를 아무도 생산하지 않는다", "gRPC 플랫폼은 build-only로 두고 애플리케이션 도달 경로를 먼저 정한다", "같은 자격 증명 회전 결함이 한 가족에서 닫히고 다른 가족에서 재현됐다" ] } ], "concept": [], "reference": [ { "title": "레지스트리로 표현된 규칙은 전이되고 CI로 표현된 규칙은 전이되지 않는다", "slug": "registry-rules-transfer-ci-rules-do-not", "file": "learning-transfer-between-families/reference/reference-registry-rules-transfer-ci-rules-do-not.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "두 번째 플랫폼이 첫 번째의 bridge 부재는 막고 게이트 배선은 옮기지 않았다", "같은 자격 증명 회전 결함이 한 가족에서 닫히고 다른 가족에서 재현됐다", "릴리스 게이트가 읽는 증거를 아무도 생산하지 않는다" ] } ], "question": [], "decision": [ { "title": "gRPC 플랫폼은 build-only로 두고 애플리케이션 도달 경로를 먼저 정한다", "slug": "grpc-stays-build-only-until-the-bridge-is-decided", "file": "learning-transfer-between-families/decision/decision-grpc-stays-build-only-until-the-bridge-is-decided.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "두 번째 플랫폼이 첫 번째의 bridge 부재는 막고 게이트 배선은 옮기지 않았다", "레지스트리로 표현된 규칙은 전이되고 CI로 표현된 규칙은 전이되지 않는다", "릴리스 게이트가 읽는 증거를 아무도 생산하지 않는다" ] } ] } }, "messaging-and-outbox": { "topic": "messaging-and-outbox", "kinds": { "case": [ { "title": "매 PR 을 막는 게이트가 초록일 수 없다", "slug": "a12-f001-check-verifyjsonschemaruntimegraph", "file": "messaging-and-outbox/case/case-a12-f001-check-verifyjsonschemaruntimegraph.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a12-f001-check-verifyjsonschemaruntimegraph", "a12-f001-check-verifyjsonschemaruntimegraph-run" ], "evidence": [ "../../../final/evidence/raw/a12-f001-check-verifyjsonschemaruntimegraph.txt", "../../../final/evidence/raw/a12-f001-check-verifyjsonschemaruntimegraph-run.txt" ], "relations": [ "release gate가 실제로 차단하는 것은 hermetic test 3개이고, mongo용 CI workflow는 없다", "durable-operation 게이트는 켤 수 없고 켜면 부팅이 실패한다", "없다고 적은 라이브러리로 옆 파일이 봉투를 만든다" ] }, { "title": "근거를 없앤 커밋이 README 를 열고 그 줄만 두었다", "slug": "a12-f002-jackson-databind", "file": "messaging-and-outbox/case/case-a12-f002-jackson-databind.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a12-f002-jackson-databind", "a12-f002-jackson-databind-history" ], "evidence": [ "../../../final/evidence/raw/a12-f002-jackson-databind.txt", "../../../final/evidence/raw/a12-f002-jackson-databind-history.txt" ], "relations": [ "매 PR 을 막는 게이트가 초록일 수 없다", "README가 \"노출된 setting도 bean도 없다\"고 적은 능력에 production bean 여덟이 있다", "문서가 지목하는 조정 레코드를 쓰는 코드가 없다" ] }, { "title": "messaging-reliability-api는 main 13파일 · 817 LOC에 테스트가 0개다", "slug": "a19-f003-messaging-reliability-api", "file": "messaging-and-outbox/case/case-a19-f003-messaging-reliability-api.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a19-f003-messaging-reliability-api" ], "evidence": [ "../../../final/evidence/raw/a19-f003-messaging-reliability-api.txt" ], "relations": [ "outbox 가 둘이고, 출하되는 것은 messaging 플랫폼 쪽이 아니다", "소비자가 없는 fixture 셋", "계약만 담는 leaf도 계약의 거절 조건은 자기 레인에서 검증한다" ] }, { "title": "messaging-cloudevents는 출하 leaf이고 starter의 의존이며 소비자가 없다", "slug": "a19-f006-messaging-cloudevents", "file": "messaging-and-outbox/case/case-a19-f006-messaging-cloudevents.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a19-f006-messaging-cloudevents" ], "evidence": [ "../../../final/evidence/raw/a19-f006-messaging-cloudevents.txt" ], "relations": [ "outbox 가 둘이고, 출하되는 것은 messaging 플랫폼 쪽이 아니다", "브로커 ACL 매니페스트의 자기 점검이 존재하지 않는다", "runtime_memberships를 먼저 읽고 심각도를 정한다" ] }, { "title": "브로커 ACL 매니페스트의 자기 점검이 존재하지 않는다", "slug": "a19-f008-acl", "file": "messaging-and-outbox/case/case-a19-f008-acl.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a19-f008-acl" ], "evidence": [ "../../../final/evidence/raw/a19-f008-acl.txt" ], "relations": [ "ACL 매니페스트 전체가 쓰이지 않는다", "클래스 javadoc 이 강제되지 않는 규칙을 강제된다고 말한다", "타입이 문서화한 불변식은 타입이 강제한다" ] }, { "title": "Kafka 스택이 둘이고, 브로커 이름만 주면 기동이 실패한다", "slug": "a19-f014-kafka-msg", "file": "messaging-and-outbox/case/case-a19-f014-kafka-msg.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a19-f014-kafka-msg", "a19-f014-kafka-msg-probe" ], "evidence": [ "../../../final/evidence/raw/a19-f014-kafka-msg.txt", "../../../final/evidence/raw/a19-f014-kafka-msg-probe.txt" ], "relations": [ "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "마스터 스위치는 루트 하나가 소유하고 자식 설정은 조건을 갖지 않는다", "조건부 빈의 평가 시점 — 파싱 시점과 등록 시점" ] }, { "title": "CompatibilityMatrix 의 EXTENSION 등급을 쓰는 항목이 없다", "slug": "a19-f015-compatibilitymatrix-extension", "file": "messaging-and-outbox/case/case-a19-f015-compatibilitymatrix-extension.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a19-f015-compatibilitymatrix-extension" ], "evidence": [ "../../../final/evidence/raw/a19-f015-compatibilitymatrix-extension.txt" ], "relations": [ "build-only 등급이 90개 파일의 미조립을 오늘의 사고에서 면제한다", "기계가 읽는 능력 매니페스트와 사람이 읽는 등급표가 커서 서명에 대해 다르게 답한다", "지원 등급은 추론이 아니라 선언이고 증거 없이는 올라가지 않는다" ] }, { "title": "messaging-admin-api 의 시험 한 파일이 아홉을 담고 만료까지 단언한다", "slug": "a19-f020-messaging-admin-api", "file": "messaging-and-outbox/case/case-a19-f020-messaging-admin-api.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a19-f020-messaging-admin-api" ], "evidence": [ "../../../final/evidence/raw/a19-f020-messaging-admin-api.txt" ], "relations": [ "messaging-reliability-api는 main 13파일 · 817 LOC에 테스트가 0개다", "브로커 ACL 매니페스트의 자기 점검이 존재하지 않는다", "admin 스위치가 가드를 켜고 서비스는 켜지 않는다" ] }, { "title": "공개 표면 계약 시험이 가족 밖 app-bootstrap 에 있다", "slug": "a19-f022-messagingpublicsurfacecontracttest", "file": "messaging-and-outbox/case/case-a19-f022-messagingpublicsurfacecontracttest.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a19-f022-messagingpublicsurfacecontracttest" ], "evidence": [ "../../../final/evidence/raw/a19-f022-messagingpublicsurfacecontracttest.txt" ], "relations": [ "아무도 돌리지 않는 레인의 게이트는 마지막으로 돌린 사람이 본 것을 보고한다", "문서 계약 테스트의 단언 경계 밖에 발견된 드리프트 세 건이 전부 있었다" ] }, { "title": "capability 12개 중 main 코드가 읽는 것은 3개, 거부하는 것은 1개", "slug": "analysis-finding-a19-f001", "file": "messaging-and-outbox/case/case-analysis-finding-a19-f001.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a19-f001" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a19-f001.txt" ], "relations": [ "선언된 Advanced 능력 11개 중 9개는 켜는 방법이 없다", "조용히 약해진 보증은 사고 전까지 동작하는 것과 구분되지 않는다", "분기와 거부는 다른 답이다" ] }, { "title": "8개 profile validator 중 조립에서 실행되는 것은 3개", "slug": "analysis-finding-a19-f002", "file": "messaging-and-outbox/case/case-analysis-finding-a19-f002.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a19-f002" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a19-f002.txt" ], "relations": [ "capability 12개 중 main 코드가 읽는 것은 3개이고 거부하는 것은 1개다", "브로커 권한 매니페스트의 자기 점검이 존재하지 않는다", "같은 결함이 이미 한 번 고쳐졌는데 나머지에는 적용되지 않았다" ] }, { "title": "스키마 호환성 검증기는 출하 leaf에 있고, main 코드에서 호출되지 않는다", "slug": "analysis-finding-a19-f004", "file": "messaging-and-outbox/case/case-analysis-finding-a19-f004.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a19-f004" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a19-f004.txt" ], "relations": [ "호환성 게이트를 가진 두 포맷은 build-only이고 출하되는 유일한 코덱에는 게이트가 없다", "8개 profile validator 중 조립에서 실행되는 것은 3개다", "검사하지 않는 모드는 설계 중에는 유용하고 보존 로그가 생긴 뒤에는 위험하다" ] }, { "title": "호환성 게이트를 가진 두 포맷은 build-only이고, 출하되는 유일한 코덱에는 게이트가 없다", "slug": "analysis-finding-a19-f005", "file": "messaging-and-outbox/case/case-analysis-finding-a19-f005.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a19-f005" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a19-f005.txt" ], "relations": [ "스키마 호환성 검증기는 출하 leaf에 있고 main 코드에서 호출되지 않는다", "상호운용 규격 leaf는 출하되고 starter의 의존이며 소비자가 없다", "결함은 미조립 자체가 아니라 출하되는 쪽에 대응하는 게이트가 없다는 비대칭이다" ] }, { "title": "접근 검사가 두 갈래로 존재하고, 조립된 쪽이 진단이 약한 쪽이다 (§8.3)", "slug": "analysis-finding-a19-f009", "file": "messaging-and-outbox/case/case-analysis-finding-a19-f009.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a19-f009" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a19-f009.txt" ], "relations": [ "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "브로커 권한 매니페스트의 자기 점검이 존재하지 않는다", "권한 거부와 설정 실수가 같은 버킷에 들어간다" ] }, { "title": "가족 권위 문서가 이미 정정한 build-only 문장이 지원 매트릭스에 남아 있다", "slug": "analysis-finding-a19-f013", "file": "messaging-and-outbox/case/case-analysis-finding-a19-f013.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a19-f013" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a19-f013.txt" ], "relations": [ "문서 계약 test가 존재하고 그 커버리지 경계가 드리프트 위치를 정확히 예측한다", "README readiness 표가 있는 것을 없다고 적는다", "산문에서 세는 순간 다시 drift한다" ] }, { "title": "claim-check는 starter에 배선 코드가 한 줄도 없다", "slug": "analysis-finding-a19-f018", "file": "messaging-and-outbox/case/case-analysis-finding-a19-f018.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a19-f018" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a19-f018.txt" ], "relations": [ "상호운용 규격 leaf는 출하되고 starter의 의존이며 소비자가 없다", "두 개의 outbox 중 하나만 조립되어 있다", "조용한 잘못된 성공이 아니라 시끄러운 실패다" ] }, { "title": "admin 스위치가 가드를 켜고 서비스는 켜지 않는다", "slug": "analysis-finding-a19-f019", "file": "messaging-and-outbox/case/case-analysis-finding-a19-f019.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a19-f019" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a19-f019.txt" ], "relations": [ "관리 계약 leaf는 main 25파일 1613줄에 테스트 파일이 1개다", "멱등 실행 계층과 durable-operation 표면이 픽스처에서만 조립된다", "켰다고 생각한 기능이 없다는 것을 사고 한가운데에서 발견한다" ] } ], "concept": [], "reference": [], "question": [], "decision": [] } }, "multitenancy-isolation": { "topic": "multitenancy-isolation", "kinds": { "case": [ { "title": "네 답을 주는 claim 이 있는데 서비스는 있음·없음 두 갈래로 판단한다", "slug": "analysis-finding-a03-f001", "file": "multitenancy-isolation/case/case-analysis-finding-a03-f001.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a03-f001" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a03-f001.txt" ], "relations": [ "조건부 update로 행을 claim하고 읽은 값으로 판단하지 않는다", "CAS 튜플을 where 절에 전부 반복하고 update count를 답으로 쓴다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다" ] }, { "title": "메시징만 성공 로그를 try 밖으로 옮기고 알림은 같은 try 에 남겨 두었다", "slug": "analysis-finding-a04-f002", "file": "multitenancy-isolation/case/case-analysis-finding-a04-f002.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a04-f002" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a04-f002.txt" ], "relations": [ "시그니처가 payload를 받지 않는데 예외 메시지로 PII가 로그에 남았다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다" ] }, { "title": "실패 로거가 던지면 그 예외가 제공자 예외를 밀어내고 호출자로 나간다", "slug": "analysis-finding-a04-f004", "file": "multitenancy-isolation/case/case-analysis-finding-a04-f004.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a04-f004" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a04-f004.txt" ], "relations": [ "메시징만 성공 로그를 try 밖으로 옮기고 알림은 같은 try 에 남겨 두었다", "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다" ] }, { "title": "README 의 세 문장 중 둘은 쓰일 때부터 틀렸고 하나만 나중에 어긋났다", "slug": "analysis-finding-a04-f005", "file": "multitenancy-isolation/case/case-analysis-finding-a04-f005.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a04-f005" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a04-f005.txt" ], "relations": [ "문서의 수치는 세지 말고 파생하거나 게이트로 붙든다", "과대 진술 문서를 과소보다 먼저 고친다", "다섯 문서가 \"exactly 19 leaf\"라고 적고 레지스트리는 62다" ] }, { "title": "추정식의 여유분이 상수라서 인코드가 내준 세 크기를 디코드가 거절한다", "slug": "analysis-finding-a05-f001", "file": "multitenancy-isolation/case/case-analysis-finding-a05-f001.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a05-f001" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a05-f001.txt" ], "relations": [ "서명된 커서의 구조와 검증 순서", "이진 승인 코덱은 decode 후 재인코딩이 원본과 같아야 한다", "커서 서명 검증이 길이·상수시간·순서를 전부 지켜야 했던 이유" ] }, { "title": "정본이라던 코디네이터는 그 포트를 구현하지 않고 다른 클래스가 구현한다", "slug": "analysis-finding-a05-f010", "file": "multitenancy-isolation/case/case-analysis-finding-a05-f010.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a05-f010" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a05-f010.txt" ], "relations": [ "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "재시도 코디네이터는 빈이지만 그것을 어디에도 적용하지 않는다", "같은 개념의 두 어휘가 공존하면 하나를 죽은 것으로 표시한다" ] }, { "title": "쿼터 원장은 사용량을 적기만 하고 승인은 그것을 읽지 않는다", "slug": "analysis-finding-a05-f023", "file": "multitenancy-isolation/case/case-analysis-finding-a05-f023.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a05-f023" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a05-f023.txt" ], "relations": [ "선언은 통과하는데 강제하는 주체가 없음 계열", "tenant별 풀이 개별적으로 합리적이고 그 합이 서버 상한을 넘긴다", "회수가 페이지 하나를 다 쓰면 남은 바이트를 들고 그대로 끝난다" ] }, { "title": "회수가 페이지 하나를 다 쓰면 남은 바이트를 들고 그대로 끝난다", "slug": "analysis-finding-a05-f024", "file": "multitenancy-isolation/case/case-analysis-finding-a05-f024.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a05-f024" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a05-f024.txt" ], "relations": [ "쿼터 원장은 사용량을 적기만 하고 승인은 그것을 읽지 않는다", "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다" ] }, { "title": "제공자 제출 뒤의 다섯 쓰기 가운데 결과 기록만 조건이 없다", "slug": "analysis-finding-a05-f028", "file": "multitenancy-isolation/case/case-analysis-finding-a05-f028.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a05-f028" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a05-f028.txt" ], "relations": [ "fenced lease — 만료 시각만으로는 부족한 이유", "native claim이 @Version을 올리지 않아 충돌을 보고하지 않는 낙관적 잠금이 됐다", "조건부 update로 행을 claim하고 읽은 값으로 판단하지 않는다" ] }, { "title": "claim 이 넣은 CLAIMED 행을 완료로 바꾸는 코드가 없다", "slug": "analysis-finding-a05-f030", "file": "multitenancy-isolation/case/case-analysis-finding-a05-f030.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a05-f030" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a05-f030.txt" ], "relations": [ "네 답을 주는 claim 이 있는데 서비스는 있음·없음 두 갈래로 판단한다", "조건부 update로 행을 claim하고 읽은 값으로 판단하지 않는다", "@Bean이 있다는 것은 조립 증거가 아니다" ] }, { "title": "오타 난 벤더는 기동을 멈추지만 그 프로퍼티를 지목하지 못한다", "slug": "analysis-finding-a05-f031", "file": "multitenancy-isolation/case/case-analysis-finding-a05-f031.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a05-f031" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a05-f031.txt" ], "relations": [ "@Bean이 있다는 것은 조립 증거가 아니다", "\"꺼짐\"은 조건의 반복이 아니라 구조여야 한다", "스캔에서 뺀 다섯 패키지의 컴포넌트 여섯을 두 자동설정 어느 쪽도 소유하지 않았다" ] }, { "title": "포화된 풀의 대기 수를 단언하는 시험이 풀 계약 레인에 없다", "slug": "analysis-finding-a05-f032", "file": "multitenancy-isolation/case/case-analysis-finding-a05-f032.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a05-f032" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a05-f032.txt" ], "relations": [ "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "풀 계약 레인이 실행되지 않아 포화 동작이 확인되지 않았다", "REQUIRES_NEW의 커넥션 비용과 풀 사이징 제약" ] }, { "title": "세 카드의 태그를 채우는 시험이 프로덕션 타입을 한 줄도 부르지 않는다", "slug": "analysis-finding-a05-f034", "file": "multitenancy-isolation/case/case-analysis-finding-a05-f034.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a05-f034" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a05-f034.txt" ], "relations": [ "증거 등급과 provenance — R1과 R2를 가르는 것", "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "후보 증거는 통과해도 R1에 머무르고 R2는 별도 게이트가 판정한다" ] }, { "title": "가드가 막겠다는 문장이 실제로 있는 두 파일이 탐색 범위 밖이다", "slug": "analysis-finding-a06-f002", "file": "multitenancy-isolation/case/case-analysis-finding-a06-f002.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a06-f002" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a06-f002.txt" ], "relations": [ "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "문서와 상수가 서로 일치하는 것으로는 아무것도 증명되지 않는다", "과대 진술 문서를 과소보다 먼저 고친다" ] }, { "title": "전용 category 를 붙이는 유일한 분기가 도달할 수 없다", "slug": "analysis-finding-a06-f004", "file": "multitenancy-isolation/case/case-analysis-finding-a06-f004.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a06-f004" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a06-f004.txt" ], "relations": [ "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다", "위험한 조합은 정책이 아니라 생성자가 거부하게 만든다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다" ] }, { "title": "cause 를 받지 않는다는 루트 규칙이 스물둘 중 하나에 대해 거짓이다", "slug": "analysis-finding-a06-f005", "file": "multitenancy-isolation/case/case-analysis-finding-a06-f005.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a06-f005" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a06-f005.txt" ], "relations": [ "관측을 위해 수집한 데이터가 관측 대상보다 위험할 수 있다", "시그니처가 payload를 받지 않는데 예외 메시지로 PII가 로그에 남았다", "문서와 상수가 서로 일치하는 것으로는 아무것도 증명되지 않는다" ] }, { "title": "게이트웨이가 적은 순서의 timeout 단계가 정책에 없다", "slug": "analysis-finding-a06-f007", "file": "multitenancy-isolation/case/case-analysis-finding-a06-f007.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a06-f007" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a06-f007.txt" ], "relations": [ "단일 admission point는 우회 경로를 세어야 성립한다", "문서와 상수가 서로 일치하는 것으로는 아무것도 증명되지 않는다", "명령 카탈로그와 admission 아홉 단계" ] }, { "title": "데드라인을 서버로 보내는 접근자를 부르는 프로덕션 코드가 없다", "slug": "analysis-finding-a06-f008", "file": "multitenancy-isolation/case/case-analysis-finding-a06-f008.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a06-f008" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a06-f008.txt" ], "relations": [ "데드라인은 호출 예산에서 시작해 세 단계로 좁힌다", "쓰기 트랜잭션에는 유한 타임아웃이 필수다", "@Bean이 있다는 것은 조립 증거가 아니다" ] }, { "title": "예산 초과 분기가 한 관측에 success 와 failure 를 차례로 부른다", "slug": "analysis-finding-a06-f009", "file": "multitenancy-isolation/case/case-analysis-finding-a06-f009.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a06-f009" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a06-f009.txt" ], "relations": [ "메시징만 성공 로그를 try 밖으로 옮기고 알림은 같은 try 에 남겨 두었다", "데드라인을 서버로 보내는 접근자를 부르는 프로덕션 코드가 없다", "port 계약은 동시성 요구를 적는다" ] }, { "title": "집계 실행기가 컬렉션 이름을 문자열로 따로 받는다", "slug": "analysis-finding-a06-f010", "file": "multitenancy-isolation/case/case-analysis-finding-a06-f010.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a06-f010" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a06-f010.txt" ], "relations": [ "단일 admission point는 우회 경로를 세어야 성립한다", "path·identifier는 등록하고 value는 바인딩한다", "데드라인을 서버로 보내는 접근자를 부르는 프로덕션 코드가 없다" ] }, { "title": "인덱스 diff 는 열네 요소 중 keySignature 와 unique 만 비교한다", "slug": "analysis-finding-a06-f014", "file": "multitenancy-isolation/case/case-analysis-finding-a06-f014.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a06-f014" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a06-f014.txt" ], "relations": [ "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "문서와 상수가 서로 일치하는 것으로는 아무것도 증명되지 않는다", "TTL 규칙 셋을 가진 타입들을 부르는 프로덕션 코드가 없다" ] }, { "title": "MongoTtlPolicyValidator 를 부르는 프로덕션 코드가 없다", "slug": "analysis-finding-a06-f015", "file": "multitenancy-isolation/case/case-analysis-finding-a06-f015.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a06-f015" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a06-f015.txt" ], "relations": [ "같은 개념의 두 어휘가 공존하면 하나를 죽은 것으로 표시한다", "diff 가 견주는 것은 열넷 중 keySignature 와 unique 둘이다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다" ] }, { "title": "MongoChangeHistoryLostException 을 만드는 코드가 없다", "slug": "analysis-finding-a06-f019", "file": "multitenancy-isolation/case/case-analysis-finding-a06-f019.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a06-f019" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a06-f019.txt" ], "relations": [ "타입이 문서화한 불변식은 타입이 강제한다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "TTL 규칙 셋을 가진 타입들을 부르는 프로덕션 코드가 없다" ] }, { "title": "드라이런만 감사 싱크를 직접 불러 번역을 거치지 않는다", "slug": "analysis-finding-a06-f021", "file": "multitenancy-isolation/case/case-analysis-finding-a06-f021.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a06-f021" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a06-f021.txt" ], "relations": [ "단일 admission point는 우회 경로를 세어야 성립한다", "도달성 판정은 단어가 아니라 import로 확인한다", "실패 번역 사슬의 순서는 계약이다" ] }, { "title": "허용 목록 검사를 부르는 프로덕션 코드가 없다", "slug": "analysis-finding-a06-f022", "file": "multitenancy-isolation/case/case-analysis-finding-a06-f022.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a06-f022" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a06-f022.txt" ], "relations": [ "카디널리티 경계를 타입으로 표현하기", "이름은 값이 아니라 registry key다", "단일 admission point는 우회 경로를 세어야 성립한다" ] }, { "title": "고위험 관리 작업 넷이 승인을 널로 넘기는 오버로드를 부른다", "slug": "analysis-finding-a06-f023", "file": "multitenancy-isolation/case/case-analysis-finding-a06-f023.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a06-f023" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a06-f023.txt" ], "relations": [ "권한이 센 절반이 설정 한 줄로 켜지면 안 된다", "같은 개념의 두 어휘가 공존하면 하나를 죽은 것으로 표시한다", "두 형태를 나란히 내놓는 포트는 이미 안전하지 않은 쪽을 고른 것이다" ] }, { "title": "promotion 증거 어휘가 둘이고, gate는 하나만 검사한다", "slug": "analysis-finding-a06-f024", "file": "multitenancy-isolation/case/case-analysis-finding-a06-f024.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a06-f024" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a06-f024.txt" ], "relations": [ "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "같은 개념의 두 어휘가 공존하면 하나를 죽은 것으로 표시한다", "능력 등급은 코드가 아니라 실행된 증거에서 파생한다" ] }, { "title": "구현 없는 4개의 계약 중 셋은 그 사실을 적고, 하나는 적지 않는다", "slug": "analysis-finding-a06-f025", "file": "multitenancy-isolation/case/case-analysis-finding-a06-f025.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a06-f025" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a06-f025.txt" ], "relations": [ "등급은 네 단계로 나누고 관측보다 높게 적지 않는다", "Bean 애너테이션이 있다는 것은 조립 증거가 아니다", "Hibernate filter는 보안 경계가 아니다" ] }, { "title": "커버리지 gate 둘이 나란히 있고, 하나는 발화할 수 없다", "slug": "analysis-finding-a06-f026", "file": "multitenancy-isolation/case/case-analysis-finding-a06-f026.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a06-f026" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a06-f026.txt" ], "relations": [ "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "아무것도 발견하지 못한 레인은 성공이 아니라 실패여야 한다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다" ] }, { "title": "release gate가 실제로 차단하는 것은 hermetic test 3개이고, mongo용 CI workflow는 없다", "slug": "analysis-finding-a06-f027", "file": "multitenancy-isolation/case/case-analysis-finding-a06-f027.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a06-f027" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a06-f027.txt" ], "relations": [ "아무도 돌리지 않는 레인의 게이트는 마지막으로 돌린 사람이 본 것을 보고한다", "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "인증 레인만 Docker 가드를 달지 않는다" ] }, { "title": "소비자가 없는 fixture 셋", "slug": "analysis-finding-a06-f028", "file": "multitenancy-isolation/case/case-analysis-finding-a06-f028.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a06-f028" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a06-f028.txt" ], "relations": [ "계약 테스트는 어댑터가 실제로 돌리는 statement를 실행해야 한다", "release gate가 실제로 차단하는 것은 hermetic test 3개이고 이 리프용 CI workflow는 없다", "Bean 애너테이션이 있다는 것은 조립 증거가 아니다" ] }, { "title": "search_path가 풀로 돌아간 커넥션에 남아 다음 tenant가 상속한다", "slug": "search-path-survived-the-return-to-the-pool", "file": "multitenancy-isolation/case/case-search-path-survived-the-return-to-the-pool.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "search-path-survived-the-return-to-the-pool" ], "evidence": [ "../../../final/evidence/raw/search-path-survived-the-return-to-the-pool.txt" ], "relations": [ "격리 설정은 트랜잭션 로컬이어야 한다", "세션 스코프 설정은 풀로 돌아간 커넥션에 남는다", "네 가지 멀티테넌시 전략과 각각의 격리 경계" ] }, { "title": "tenant별 풀이 개별적으로 합리적이고 그 합이 서버 상한을 넘긴다", "slug": "tenant-pools-summed-past-the-server-ceiling", "file": "multitenancy-isolation/case/case-tenant-pools-summed-past-the-server-ceiling.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "tenant-pools-summed-past-the-server-ceiling" ], "evidence": [ "../../../final/evidence/raw/tenant-pools-summed-past-the-server-ceiling.txt" ], "relations": [ "REQUIRES_NEW의 커넥션 비용과 풀 사이징 제약", "네 가지 멀티테넌시 전략과 각각의 격리 경계", "데드라인은 호출 예산에서 시작해 세 단계로 좁힌다" ] }, { "title": "RLS가 아무것도 하지 않는 세 가지 방법", "slug": "three-ways-rls-does-nothing", "file": "multitenancy-isolation/case/case-three-ways-rls-does-nothing.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "three-ways-rls-does-nothing" ], "evidence": [ "../../../final/evidence/raw/three-ways-rls-does-nothing.txt" ], "relations": [ "RLS가 성립하기 위한 세 전제", "Hibernate filter는 보안 경계가 아니다", "tenant 컬럼이 있는 테이블의 모든 unique 제약에 그 컬럼이 들어가야 한다" ] } ], "concept": [ { "title": "네 가지 멀티테넌시 전략과 각각의 격리 경계", "slug": "four-multitenancy-strategies", "file": "multitenancy-isolation/concept/concept-four-multitenancy-strategies.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "four-multitenancy-strategies", "four-multitenancy-strategies-diagram" ], "evidence": [ "../../../final/evidence/raw/four-multitenancy-strategies.txt" ], "relations": [ "RLS가 성립하기 위한 세 전제", "tenant별 풀이 개별적으로 합리적이고 그 합이 서버 상한을 넘긴다", "클래스패스에 있는 것은 실행 동의가 아니다" ] }, { "title": "RLS가 성립하기 위한 세 전제", "slug": "rls-three-preconditions", "file": "multitenancy-isolation/concept/concept-rls-three-preconditions.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "rls-three-preconditions", "rls-three-preconditions-diagram" ], "evidence": [ "../../../final/evidence/raw/rls-three-preconditions.txt" ], "relations": [ "RLS가 아무것도 하지 않는 세 가지 방법", "Hibernate filter는 보안 경계가 아니다", "격리 설정은 트랜잭션 로컬이어야 한다" ] } ], "reference": [ { "title": "legacy compatibility surface의 제거 조건을 세 가지로 고정한다", "slug": "analysis-finding-a03-f003", "file": "multitenancy-isolation/reference/reference-analysis-finding-a03-f003.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "notification admin atomic claim contract가 service에서 사용되지 않음", "같은 개념의 두 어휘가 공존하면 하나를 죽은 것으로 표시한다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다" ] }, { "title": "Hibernate filter는 보안 경계가 아니다", "slug": "hibernate-filter-is-not-a-security-boundary", "file": "multitenancy-isolation/reference/reference-hibernate-filter-is-not-a-security-boundary.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "RLS가 성립하기 위한 세 전제", "RLS가 아무것도 하지 않는 세 가지 방법", "tenant 컬럼이 있는 테이블의 모든 unique 제약에 그 컬럼이 들어가야 한다" ] }, { "title": "격리 설정은 트랜잭션 로컬이어야 한다", "slug": "isolation-settings-must-be-transaction-local", "file": "multitenancy-isolation/reference/reference-isolation-settings-must-be-transaction-local.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "search_path가 풀로 돌아간 커넥션에 남아 다음 tenant가 상속한다", "세션 스코프 설정은 풀로 돌아간 커넥션에 남는다", "RLS가 성립하기 위한 세 전제" ] }, { "title": "tenant 컬럼이 있는 테이블의 모든 unique 제약에 그 컬럼이 들어가야 한다", "slug": "tenant-column-belongs-in-every-unique-constraint", "file": "multitenancy-isolation/reference/reference-tenant-column-belongs-in-every-unique-constraint.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "RLS가 아무것도 하지 않는 세 가지 방법", "Hibernate filter는 보안 경계가 아니다", "위험한 조합은 정책이 아니라 생성자가 거부하게 만든다" ] } ], "question": [ { "title": "response/LRO invariant enforcement boundary", "slug": "a02-f001-lro", "file": "multitenancy-isolation/question/openquestion-a02-f001-lro.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "위험한 조합은 정책이 아니라 생성자가 거부하게 만든다", "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다" ] }, { "title": "DomainContextKey same-name different-type collision", "slug": "a02-f002-domaincontextkey", "file": "multitenancy-isolation/question/openquestion-a02-f002-domaincontextkey.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "이름은 값이 아니라 registry key다", "위험한 조합은 정책이 아니라 생성자가 거부하게 만든다" ] }, { "title": "CapabilitySupport.constraints 의 경계가 타입에 없다", "slug": "a05-f003-capabilitysupport-constraints", "file": "multitenancy-isolation/question/openquestion-a05-f003-capabilitysupport-constraints.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "진단 리포트가 살아 있는 리소스를 담지 않도록 값 타입을 좁혔다", "관측을 위해 수집한 데이터가 관측 대상보다 위험할 수 있다", "카디널리티 경계를 타입으로 표현하기" ] }, { "title": "bounded operational record identifiers", "slug": "analysis-finding-a02-f003", "file": "multitenancy-isolation/question/openquestion-analysis-finding-a02-f003.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "카디널리티 경계를 타입으로 표현하기", "위험한 조합은 정책이 아니라 생성자가 거부하게 만든다" ] }, { "title": "permission component grammar", "slug": "analysis-finding-a02-f004", "file": "multitenancy-isolation/question/openquestion-analysis-finding-a02-f004.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "이름은 값이 아니라 registry key다", "문서와 상수가 서로 일치하는 것으로는 아무것도 증명되지 않는다" ] }, { "title": "messaging schema qualification boundary", "slug": "analysis-finding-a02-f005", "file": "multitenancy-isolation/question/openquestion-analysis-finding-a02-f005.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "문서와 상수가 서로 일치하는 것으로는 아무것도 증명되지 않는다", "능력 등급은 코드가 아니라 실행된 증거에서 파생한다" ] }, { "title": "notification derived idempotency key가 32-bit hash", "slug": "analysis-finding-a03-f002", "file": "multitenancy-isolation/question/openquestion-analysis-finding-a03-f002.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "digest는 길이 프레이밍하고 버전을 붙인다", "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다" ] }, { "title": "isolation vocabulary와 legacy routing capability의 시차", "slug": "analysis-finding-a03-f004", "file": "multitenancy-isolation/question/openquestion-analysis-finding-a03-f004.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "트랜잭션 템플릿은 모드별로 미리 만들어 둔다", "Bean 애너테이션이 있다는 것은 조립 증거가 아니다", "등급은 네 단계로 나누고 관측보다 높게 적지 않는다" ] }, { "title": "cache-redis 와 httpclient 의 support 간선이 죽었는지 확정되지 않았다", "slug": "analysis-finding-a04-f006", "file": "multitenancy-isolation/question/openquestion-analysis-finding-a04-f006.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "Bean 애너테이션이 있다는 것은 조립 증거가 아니다", "legacy compatibility surface의 제거 조건을 세 가지로 고정한다" ] }, { "title": "실제 성능·용량 특성을 어떤 모듈에서도 측정하지 않았다", "slug": "performance-and-capacity-unmeasured", "file": "multitenancy-isolation/question/openquestion-performance-and-capacity-unmeasured.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "성능 측정은 릴리스 게이트에 넣지 않는다", "tenant별 풀이 개별적으로 합리적이고 그 합이 서버 상한을 넘긴다", "능력 등급은 코드가 아니라 실행된 증거에서 파생한다" ] } ], "decision": [ { "title": "클래스패스에 있는 것은 실행 동의가 아니다", "slug": "classpath-presence-is-not-consent", "file": "multitenancy-isolation/decision/decision-classpath-presence-is-not-consent.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "네 가지 멀티테넌시 전략과 각각의 격리 경계", "Hibernate filter는 보안 경계가 아니다", "runtime_memberships를 먼저 읽고 심각도를 정한다", "마스터 스위치는 루트 하나가 소유하고 자식 설정은 조건을 갖지 않는다" ] } ] } }, "non-atomic-check-then-act": { "topic": "non-atomic-check-then-act", "kinds": { "case": [ { "title": "회전이 비교 후 교체가 아니라 덮어쓰기이고, 세대 계수기는 음수가 되면 회수되지 않는다", "slug": "a-rotation-that-overwrites-and-a-generation-that-cannot-be-reclaimed", "file": "non-atomic-check-then-act/case/case-a-rotation-that-overwrites-and-a-generation-that-cannot-be-reclaimed.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-rotation-that-overwrites-and-a-generation-that-cannot-be-reclaimed" ], "evidence": [ "../../../final/evidence/raw/a-rotation-that-overwrites-and-a-generation-that-cannot-be-reclaimed.txt" ], "relations": [ "원자 타입 위의 검사 후 실행과 비교 후 교체 루프", "같은 자격 증명 회전 결함이 한 가족에서 닫히고 다른 가족에서 재현됐다", "배수 완료가 자기가 읽은 값으로 상태를 다시 써서 진행 중인 자격증명 회전을 되돌린다" ] }, { "title": "upsert 라고 적힌 연산이 갱신하고 안 되면 삽입한다", "slug": "a05-f026-enqueue", "file": "non-atomic-check-then-act/case/case-a05-f026-enqueue.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a05-f026-enqueue", "a05-f026-enqueue-race" ], "evidence": [ "../../../final/evidence/raw/a05-f026-enqueue.txt", "../../../final/evidence/raw/a05-f026-enqueue-race.txt" ], "relations": [ "CAS 튜플을 where 절에 전부 반복하고 update count를 답으로 쓴다", "조건부 update로 행을 claim하고 읽은 값으로 판단하지 않는다", "Atomic* 타입의 존재는 원자성의 증거가 아니다" ] }, { "title": "queued 를 줄이는 유일한 연산이 상한을 읽지 않는 승격 안에 있다", "slug": "an-admission-boundary-that-leaks-and-a-counter-that-cannot-return", "file": "non-atomic-check-then-act/case/case-an-admission-boundary-that-leaks-and-a-counter-that-cannot-return.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "an-admission-boundary-that-leaks-and-a-counter-that-cannot-return" ], "evidence": [ "../../../final/evidence/raw/an-admission-boundary-that-leaks-and-a-counter-that-cannot-return.txt" ], "relations": [ "원자 타입 위의 검사 후 실행과 비교 후 교체 루프", "Atomic* 타입의 존재는 원자성의 증거가 아니다", "승격이 상한 필드를 읽지 않고, 세 승인 메서드의 main 호출자가 0 이다" ] }, { "title": "배수를 시작한 뒤에도 한 서비스가 다시 SERVING 이 될 수 있다", "slug": "draining-began-and-a-service-came-back-serving", "file": "non-atomic-check-then-act/case/case-draining-began-and-a-service-came-back-serving.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "draining-began-and-a-service-came-back-serving" ], "evidence": [ "../../../final/evidence/raw/draining-began-and-a-service-came-back-serving.txt" ], "relations": [ "원자 타입 위의 검사 후 실행과 비교 후 교체 루프", "전이를 시작하는 쓰기와 그 전이가 덮는 집합은 한 연산이어야 한다", "새 승인을 거절한다는 메서드가 단계만 기록하고 아무것도 거절하지 않는다" ] } ], "concept": [ { "title": "원자 타입 위의 검사 후 실행과 비교 후 교체 루프", "slug": "check-then-act-on-atomic-types", "file": "non-atomic-check-then-act/concept/concept-check-then-act-on-atomic-types.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "check-then-act-on-atomic-types", "check-then-act-on-atomic-types-diagram" ], "evidence": [ "../../../final/evidence/raw/check-then-act-on-atomic-types.txt" ], "relations": [ "`Atomic*` 타입의 존재는 원자성의 증거가 아니다", "전이를 시작하는 쓰기와 그 전이가 덮는 집합은 한 연산이어야 한다", "같은 자격 증명 회전 결함이 한 가족에서 닫히고 다른 가족에서 재현됐다" ] } ], "reference": [ { "title": "전이를 시작하는 쓰기와 그 전이가 덮는 집합은 한 연산이어야 한다", "slug": "beginning-a-transition-and-the-set-it-covers-are-one-operation", "file": "non-atomic-check-then-act/reference/reference-beginning-a-transition-and-the-set-it-covers-are-one-operation.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "원자 타입 위의 검사 후 실행과 비교 후 교체 루프", "배수를 시작한 뒤에도 한 서비스가 다시 SERVING 이 될 수 있다", "배수 완료가 자기가 읽은 값으로 상태를 다시 써서 진행 중인 자격증명 회전을 되돌린다" ] } ], "question": [], "decision": [] } }, "notification-and-delivery": { "topic": "notification-and-delivery", "kinds": { "case": [ { "title": "두 호출이 상태와 함께 경보를 끈다", "slug": "a13-f002-authentication-failed-resumehealthy", "file": "notification-and-delivery/case/case-a13-f002-authentication-failed-resumehealthy.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a13-f002-authentication-failed-resumehealthy", "a13-f002-authentication-failed-resumehealthy-sequence" ], "evidence": [ "../../../final/evidence/raw/a13-f002-authentication-failed-resumehealthy.txt", "../../../final/evidence/raw/a13-f002-authentication-failed-resumehealthy-sequence.txt" ], "relations": [ "nonce replay 경계가 결과를 읽고 버린다", "그 속성을 보일 수 없는 대역 위에서 통과한 테스트는 증인이 아니다", "아직 쓰이지 않은 연산에도 같은 불변식이 성립하게 만든 순서" ] }, { "title": "정책을 담은 필드가 참이 된 적도 읽힌 적도 없다", "slug": "a13-f003-accesscontext", "file": "notification-and-delivery/case/case-a13-f003-accesscontext.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a13-f003-accesscontext", "a13-f003-accesscontext-reveal" ], "evidence": [ "../../../final/evidence/raw/a13-f003-accesscontext.txt", "../../../final/evidence/raw/a13-f003-accesscontext-reveal.txt" ], "relations": [ "소비자가 없는 fixture 셋", "타입이 문서화한 불변식은 타입이 강제한다", "실패 사유가 저널에도 감사 이벤트에도 남지 않는다" ] }, { "title": "Thymeleaf 메시지 삭제 가드가 프로덕션 경로에 없고, 있어도 값은 로그에 남는다", "slug": "a13-f004-thymeleaf", "file": "notification-and-delivery/case/case-a13-f004-thymeleaf.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a13-f004-thymeleaf", "a13-f004-thymeleaf-messages" ], "evidence": [ "../../../final/evidence/raw/a13-f004-thymeleaf.txt", "../../../final/evidence/raw/a13-f004-thymeleaf-messages.txt" ], "relations": [ "정리 작업이 무제한 DELETE 를 쏘고, 그것을 막는 오버로드는 호출되지 않는다", "정책을 담은 필드가 참이 된 적도 읽힌 적도 없다", "두 오버로드가 있었고 호출되는 쪽이 틀린 쪽이었다" ] }, { "title": "음수 Retry-After 를 거르지 않는 파서 셋이 조립되지 않아 결함이 잠재로 남는다", "slug": "a13-f005-retry-after-illegalargumentexception", "file": "notification-and-delivery/case/case-a13-f005-retry-after-illegalargumentexception.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a13-f005-retry-after-illegalargumentexception", "a13-f005-retry-after-illegalargumentexception-negative", "a13-f005-retry-after-illegalargumentexception-unassembled", "a13-f005-retry-after-illegalargumentexception-ambiguous" ], "evidence": [ "../../../final/evidence/raw/a13-f005-retry-after-illegalargumentexception.txt", "../../../final/evidence/raw/a13-f005-retry-after-illegalargumentexception-negative.txt", "../../../final/evidence/raw/a13-f005-retry-after-illegalargumentexception-unassembled.txt", "../../../final/evidence/raw/a13-f005-retry-after-illegalargumentexception-ambiguous.txt" ], "relations": [ "검증기가 불리지 않는 지금 실제로 도는 게이트는 생성자다", "\"상한을 두고 읽는다\"는 본문 핸들러가 전부 읽은 뒤에 자른다", "바이트가 프로세스를 떠났는가가 REJECTED와 AMBIGUOUS를 가른다" ] }, { "title": "포트를 뺀 호스트를 서명하는 자리가 둘이고, 같은 저장소의 네 자리는 그 포트를 지킨다", "slug": "a13-f008-host", "file": "notification-and-delivery/case/case-a13-f008-host.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a13-f008-host", "a13-f008-host-wire" ], "evidence": [ "../../../final/evidence/raw/a13-f008-host.txt", "../../../final/evidence/raw/a13-f008-host-wire.txt" ], "relations": [ "지운다고 약속한 사본은 아무도 받지 않고, 서명 자리가 받는 사본은 지울 수 없다", "로컬이 다른 DB면 로컬 테스트는 다른 시스템에 대한 진술이다", "음수 Retry-After 를 거르지 않는 파서 셋이 조립되지 않아 결함이 잠재로 남는다" ] }, { "title": "지운다고 약속한 사본은 아무도 받지 않고, 서명 자리가 받는 사본은 지울 수 없다", "slug": "a13-f009-sigv4-string", "file": "notification-and-delivery/case/case-a13-f009-sigv4-string.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a13-f009-sigv4-string", "a13-f009-sigv4-string-heap" ], "evidence": [ "../../../final/evidence/raw/a13-f009-sigv4-string.txt", "../../../final/evidence/raw/a13-f009-sigv4-string-heap.txt" ], "relations": [ "포트를 뺀 호스트를 서명하는 자리가 둘이고, 같은 저장소의 네 자리는 그 포트를 지킨다", "비밀을 힙에서 지우는 마지막 단계가 종료 경로에 연결되지 않았다", "정책을 담은 필드가 참이 된 적도 읽힌 적도 없다" ] }, { "title": "'\"상한을 두고 읽는다\"는 본문 핸들러가 전부 읽은 뒤에 자른다'", "slug": "analysis-finding-a13-f007", "file": "notification-and-delivery/case/case-analysis-finding-a13-f007.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a13-f007" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a13-f007.txt" ], "relations": [ "음수 Retry-After 가 확정 거절을 영구 중지되는 모호한 제출로 바꾼다", "이름이 상한을 말한다고 상한이 걸리는 것은 아니다", "두 연산자가 이름만 있고 아무것도 하지 않는다" ] }, { "title": "FCM만 \"커밋 후 응답 손실 = ambiguous\" 규칙 밖에 있고, 그 FCM이 두 계약 집합 어디에도 없다", "slug": "analysis-finding-a13-f010", "file": "notification-and-delivery/case/case-analysis-finding-a13-f010.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a13-f010" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a13-f010.txt" ], "relations": [ "재시도 안전은 증거로 결정된다", "상한을 두고 읽는다는 본문 handler가 전부 읽은 뒤에 자른다", "모든 어댑터가 지난다고 적힌 통로에 예외가 있으면 규칙은 한 번 쓰인 것이 아니다" ] }, { "title": "공유 provider 계약이 8종 중 3종에서만 상속되고, 강제 장치가 없다", "slug": "analysis-finding-a13-f011", "file": "notification-and-delivery/case/case-analysis-finding-a13-f011.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a13-f011" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a13-f011.txt" ], "relations": [ "한 제공자만 커밋 후 응답 손실은 모호하다 규칙 밖에 있고 그 제공자가 두 계약 집합 어디에도 없다", "문서가 선언한 경계는 코드가 닫아야 경계다", "위반 코드 34종 중 22종이 어떤 test에서도 이름으로 확인되지 않는다" ] } ], "concept": [], "reference": [], "question": [], "decision": [] } }, "objectstorage-staged-lifecycle": { "topic": "objectstorage-staged-lifecycle", "kinds": { "case": [ { "title": "APPLY를 켜는 설정은 있고 승인을 검증하는 bean은 없다", "slug": "apply-is-a-setting-approval-is-not", "file": "objectstorage-staged-lifecycle/case/case-apply-is-a-setting-approval-is-not.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "apply-is-a-setting-approval-is-not" ], "evidence": [ "../../../final/evidence/raw/apply-is-a-setting-approval-is-not.txt" ], "relations": [ "권한이 센 절반이 설정 한 줄로 켜지면 안 된다", "legacy 채택은 서로 다른 두 승인자의 서명을 요구한다", "Bean 애너테이션이 있다는 것은 조립 증거가 아니다" ] }, { "title": "서명된 grant의 endpoint 검증이 upload 경로에만 있다", "slug": "endpoint-check-only-on-upload", "file": "objectstorage-staged-lifecycle/case/case-endpoint-check-only-on-upload.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "endpoint-check-only-on-upload" ], "evidence": [ "../../../final/evidence/raw/endpoint-check-only-on-upload.txt" ], "relations": [ "staged lifecycle과 서명된 grant", "단일 admission point는 우회 경로를 세어야 성립한다", "직접 multipart의 마지막 part는 grant를 받을 수 없다" ] }, { "title": "직접 multipart의 마지막 part는 grant를 받을 수 없다", "slug": "the-last-part-cannot-get-a-grant", "file": "objectstorage-staged-lifecycle/case/case-the-last-part-cannot-get-a-grant.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "the-last-part-cannot-get-a-grant" ], "evidence": [ "../../../final/evidence/raw/the-last-part-cannot-get-a-grant.txt" ], "relations": [ "staged lifecycle과 서명된 grant", "서명된 grant의 endpoint 검증이 upload 경로에만 있다" ] } ], "concept": [ { "title": "staged lifecycle과 서명된 grant", "slug": "staged-lifecycle-and-signed-grants", "file": "objectstorage-staged-lifecycle/concept/concept-staged-lifecycle-and-signed-grants.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "staged-lifecycle-and-signed-grants", "staged-lifecycle-and-signed-grants-diagram" ], "evidence": [ "../../../final/evidence/raw/staged-lifecycle-and-signed-grants.txt" ], "relations": [ "APPLY를 켜는 설정은 있고 승인을 검증하는 bean은 없다", "직접 multipart의 마지막 part는 grant를 받을 수 없다", "서명된 grant의 endpoint 검증이 upload 경로에만 있다", "커서에 서명하는 이유는 기밀성이 아니라 무결성이다" ] } ], "reference": [ { "title": "이진 승인 코덱은 decode 후 재인코딩이 원본과 같아야 한다", "slug": "a-binary-approval-codec-must-round-trip", "file": "objectstorage-staged-lifecycle/reference/reference-a-binary-approval-codec-must-round-trip.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "서명된 커서의 구조와 검증 순서", "digest는 길이 프레이밍하고 버전을 붙인다", "APPLY를 켜는 설정은 있고 승인을 검증하는 bean은 없다" ] }, { "title": "권한이 센 절반이 설정 한 줄로 켜지면 안 된다", "slug": "the-powerful-half-must-not-be-one-setting-away", "file": "objectstorage-staged-lifecycle/reference/reference-the-powerful-half-must-not-be-one-setting-away.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "APPLY를 켜는 설정은 있고 승인을 검증하는 bean은 없다", "legacy 채택은 서로 다른 두 승인자의 서명을 요구한다", "Bean 애너테이션이 있다는 것은 조립 증거가 아니다" ] } ], "question": [], "decision": [ { "title": "legacy 채택은 서로 다른 두 승인자의 서명을 요구한다", "slug": "legacy-adoption-requires-two-approvers", "file": "objectstorage-staged-lifecycle/decision/decision-legacy-adoption-requires-two-approvers.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "APPLY를 켜는 설정은 있고 승인을 검증하는 bean은 없다", "권한이 센 절반이 설정 한 줄로 켜지면 안 된다", "이진 승인 코덱은 decode 후 재인코딩이 원본과 같아야 한다" ] } ] } }, "observability-models": { "topic": "observability-models", "kinds": { "case": [], "concept": [ { "title": "상관 식별자를 만드는 필터가 세 벌이다", "slug": "adapter-inbound-web-c15", "file": "observability-models/concept/concept-adapter-inbound-web-c15.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c15" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c15.txt" ], "relations": [] }, { "title": "manual audit 경로만 조립되고 Spring Data auditing은 dormant다", "slug": "adapter-outbound-persistence-jpa-c44", "file": "observability-models/concept/concept-adapter-outbound-persistence-jpa-c44.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c44" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c44.txt" ], "relations": [] }, { "title": "FailOpenDependencyLogger는 실패 정책을 정하지 않는다", "slug": "adapter-outbound-support-c02", "file": "observability-models/concept/concept-adapter-outbound-support-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-support-c02", "adapter-outbound-support-c02-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-support-c02.txt" ], "relations": [] }, { "title": "두 게이트가 증명하는 것과 증명하지 않는 것", "slug": "adapter-outbound-support-c06", "file": "observability-models/concept/concept-adapter-outbound-support-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-support-c06" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-support-c06.txt" ], "relations": [] }, { "title": "allowlist가 기본 거절이고 거절 목록은 메시지를 위한 것이다", "slug": "grpc-observability-c03", "file": "observability-models/concept/concept-grpc-observability-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-observability-c03" ], "evidence": [ "../../../final/evidence/raw/grpc-observability-c03.txt" ], "relations": [] }, { "title": "실패 사유가 저널에도 감사 이벤트에도 남지 않는다", "slug": "messaging-admin-runtime-c05", "file": "observability-models/concept/concept-messaging-admin-runtime-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-runtime-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-runtime-c05.txt" ], "relations": [] }, { "title": "재료 둘만 bean으로 있고 그것을 조립하는 것이 없다", "slug": "messaging-observability-c02", "file": "observability-models/concept/concept-messaging-observability-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-observability-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-observability-c02.txt" ], "relations": [ "타입이 문서화한 불변식은 타입이 강제한다" ] } ], "reference": [], "question": [], "decision": [] } }, "operator-approval-and-destructive-operations": { "topic": "operator-approval-and-destructive-operations", "kinds": { "case": [ { "title": "재개된 리드라이브가 옮기지 못한 메시지를 건너뛰고 성공으로 닫힌다", "slug": "a-resumed-redrive-skips-what-it-could-not-move", "file": "operator-approval-and-destructive-operations/case/case-a-resumed-redrive-skips-what-it-could-not-move.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-resumed-redrive-skips-what-it-could-not-move" ], "evidence": [ "../../../final/evidence/raw/a-resumed-redrive-skips-what-it-could-not-move.txt" ], "relations": [ "승인·검증·실행의 분리와 그것을 타입으로 표현하기", "재개는 인덱스가 아니라 신원으로 한다", "그 속성을 보일 수 없는 대역 위에서 통과한 테스트는 증인이 아니다", "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다" ] }, { "title": "BLOCKING 이면 기동이 실패한다는 보장이 어떤 배선에서도 실행되지 않는다", "slug": "blocking-means-startup-fails-and-nothing-runs-it", "file": "operator-approval-and-destructive-operations/case/case-blocking-means-startup-fails-and-nothing-runs-it.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "blocking-means-startup-fails-and-nothing-runs-it" ], "evidence": [ "../../../final/evidence/raw/blocking-means-startup-fails-and-nothing-runs-it.txt" ], "relations": [ "승인·검증·실행의 분리와 그것을 타입으로 표현하기", "검증기는 발행이 아니라 주입이 강제다", "시작 검증기가 도는지는 그 능력에 자동설정 루트가 있는지와 일치한다", "시작 검증기 13개 규칙이 유일한 조립 지점에서 호출되지 않는다" ] }, { "title": "위조 가능한 승인이 하필 되돌릴 수 없는 작업 쪽에만 남았다", "slug": "the-forgeable-approval-survived-on-the-irreversible-half", "file": "operator-approval-and-destructive-operations/case/case-the-forgeable-approval-survived-on-the-irreversible-half.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "the-forgeable-approval-survived-on-the-irreversible-half" ], "evidence": [ "../../../final/evidence/raw/the-forgeable-approval-survived-on-the-irreversible-half.txt" ], "relations": [ "승인·검증·실행의 분리와 그것을 타입으로 표현하기", "권한이 센 절반이 설정 한 줄로 켜지면 안 된다", "서명 능력과 검증 능력은 같은 객체에 두지 않는다", "APPLY를 켜는 설정은 있고 승인을 검증하는 bean은 없다" ] } ], "concept": [ { "title": "승인·검증·실행의 분리와 그것을 타입으로 표현하기", "slug": "approval-verification-execution", "file": "operator-approval-and-destructive-operations/concept/concept-approval-verification-execution.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "approval-verification-execution", "approval-verification-execution-diagram" ], "evidence": [ "../../../final/evidence/raw/approval-verification-execution.txt" ], "relations": [ "위조 가능한 승인이 하필 되돌릴 수 없는 작업 쪽에만 남았다", "서명 능력과 검증 능력은 같은 객체에 두지 않는다", "권한이 센 절반이 설정 한 줄로 켜지면 안 된다" ] } ], "reference": [ { "title": "재개는 인덱스가 아니라 신원으로 한다", "slug": "resume-by-identity-not-by-index", "file": "operator-approval-and-destructive-operations/reference/reference-resume-by-identity-not-by-index.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "재개된 리드라이브가 옮기지 못한 메시지를 건너뛰고 성공으로 닫힌다", "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다", "그 속성을 보일 수 없는 대역 위에서 통과한 테스트는 증인이 아니다" ] }, { "title": "서명 능력과 검증 능력은 같은 객체에 두지 않는다", "slug": "signing-and-verifying-do-not-share-an-object", "file": "operator-approval-and-destructive-operations/reference/reference-signing-and-verifying-do-not-share-an-object.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "승인·검증·실행의 분리와 그것을 타입으로 표현하기", "위조 가능한 승인이 하필 되돌릴 수 없는 작업 쪽에만 남았다", "legacy 채택은 서로 다른 두 승인자의 서명을 요구한다" ] } ], "question": [], "decision": [] } }, "owner-safe-state-machines": { "topic": "owner-safe-state-machines", "kinds": { "case": [ { "title": "transition digest가 \"누가·언제\"만 덮고 \"무엇\"을 덮지 않아 다른 전이를 같다고 보고했다", "slug": "a-digest-that-covered-who-but-not-what", "file": "owner-safe-state-machines/case/case-a-digest-that-covered-who-but-not-what.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-digest-that-covered-who-but-not-what" ], "evidence": [ "../../../final/evidence/raw/a-digest-that-covered-who-but-not-what.txt" ], "relations": [ "digest는 길이 프레이밍하고 버전을 붙인다", "CAS 튜플을 where 절에 전부 반복하고 update count를 답으로 쓴다", "complete()의 replay 판정이 replayTtl 변경을 무시한다" ] }, { "title": "리스가 만료 시각만 기록하고 소유자를 기록하지 않아 최종 상태를 되돌릴 수 있었다", "slug": "a-lease-without-an-owner", "file": "owner-safe-state-machines/case/case-a-lease-without-an-owner.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-lease-without-an-owner" ], "evidence": [ "../../../final/evidence/raw/a-lease-without-an-owner.txt" ], "relations": [ "fenced lease — 만료 시각만으로는 부족한 이유", "CAS 튜플을 where 절에 전부 반복하고 update count를 답으로 쓴다", "만료된 claim과 만료된 실행은 다르게 다뤄야 한다" ] }, { "title": "활성 트랜잭션 검사가 data source를 묻지 않아 남의 트랜잭션이 통과했다", "slug": "an-active-transaction-check-that-asked-the-wrong-question", "file": "owner-safe-state-machines/case/case-an-active-transaction-check-that-asked-the-wrong-question.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "an-active-transaction-check-that-asked-the-wrong-question" ], "evidence": [ "../../../final/evidence/raw/an-active-transaction-check-that-asked-the-wrong-question.txt" ], "relations": [ "CAS 튜플과 update count가 답이 되는 구조", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "두 오버로드가 있었고 호출되는 쪽이 틀린 쪽이었다" ] }, { "title": "만료된 CLAIMED는 takeover하고 만료된 EXECUTING은 조정을 요구하도록 갈랐다", "slug": "expired-claim-versus-expired-execution", "file": "owner-safe-state-machines/case/case-expired-claim-versus-expired-execution.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "expired-claim-versus-expired-execution" ], "evidence": [ "../../../final/evidence/raw/expired-claim-versus-expired-execution.txt" ], "relations": [ "만료된 claim과 만료된 실행은 다르게 다뤄야 한다", "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다", "fenced lease — 만료 시각만으로는 부족한 이유" ] }, { "title": "native claim이 @Version을 올리지 않아 충돌을 보고하지 않는 낙관적 잠금이 됐다", "slug": "native-claim-did-not-bump-the-version", "file": "owner-safe-state-machines/case/case-native-claim-did-not-bump-the-version.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "native-claim-did-not-bump-the-version" ], "evidence": [ "../../../final/evidence/raw/native-claim-did-not-bump-the-version.txt" ], "relations": [ "CAS 튜플과 update count가 답이 되는 구조", "Atomic 타입의 존재는 원자성의 증거가 아니다" ] } ], "concept": [ { "title": "capability_schema_registry — 스키마 적용과 사용 승인의 분리", "slug": "capability-schema-registry", "file": "owner-safe-state-machines/concept/concept-capability-schema-registry.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "capability-schema-registry", "capability-schema-registry-diagram" ], "evidence": [ "../../../final/evidence/raw/capability-schema-registry.txt" ], "relations": [ "capability는 스키마 적용과 사용 승인을 분리한다", "지원 등급은 추론이 아니라 선언이고 증거 없이는 올라가지 않는다" ] }, { "title": "CAS 튜플과 update count가 답이 되는 구조", "slug": "cas-tuple-and-update-count", "file": "owner-safe-state-machines/concept/concept-cas-tuple-and-update-count.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "cas-tuple-and-update-count", "cas-tuple-and-update-count-diagram" ], "evidence": [ "../../../final/evidence/raw/cas-tuple-and-update-count.txt" ], "relations": [ "fenced lease — 만료 시각만으로는 부족한 이유", "CAS 튜플을 where 절에 전부 반복하고 update count를 답으로 쓴다", "native claim이 Version을 올리지 않아 충돌을 보고하지 않는 낙관적 잠금이 됐다" ] }, { "title": "fenced lease — 만료 시각만으로는 부족한 이유", "slug": "fenced-lease", "file": "owner-safe-state-machines/concept/concept-fenced-lease.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "fenced-lease" ], "evidence": [ "../../../final/evidence/raw/fenced-lease.txt" ], "relations": [ "lease가 만료 시각만 기록하고 소유자를 기록하지 않아 terminal state가 되돌려졌다", "CAS 튜플을 where 절에 전부 반복하고 update count를 답으로 쓴다", "만료된 claim과 만료된 실행은 다르게 다뤄야 한다" ] } ], "reference": [ { "title": "CAS 튜플을 where 절에 전부 반복하고 update count를 답으로 쓴다", "slug": "cas-tuple-in-the-where-clause", "file": "owner-safe-state-machines/reference/reference-cas-tuple-in-the-where-clause.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "CAS 튜플과 update count가 답이 되는 구조", "lease가 만료 시각만 기록하고 소유자를 기록하지 않아 terminal state가 되돌려졌다", "native claim이 Version을 올리지 않아 충돌을 보고하지 않는 낙관적 잠금이 됐다" ] }, { "title": "digest는 길이 프레이밍하고 버전을 붙인다", "slug": "digest-must-be-length-framed-and-versioned", "file": "owner-safe-state-machines/reference/reference-digest-must-be-length-framed-and-versioned.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "transition digest가 누가와 언제만 덮고 무엇을 덮지 않아 다른 전이를 같다고 보고했다", "서명된 커서의 구조와 검증 순서" ] }, { "title": "만료된 claim과 만료된 실행은 다르게 다뤄야 한다", "slug": "expired-claim-and-expired-execution-differ", "file": "owner-safe-state-machines/reference/reference-expired-claim-and-expired-execution-differ.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "만료된 CLAIMED는 takeover하고 만료된 EXECUTING은 조정을 요구하도록 갈랐다", "모르는 것은 성공도 실패도 아닌 세 번째 결과여야 한다" ] }, { "title": "시간은 DB에서, 그리고 행을 잠근 다음에 읽는다", "slug": "read-the-clock-after-the-lock", "file": "owner-safe-state-machines/reference/reference-read-the-clock-after-the-lock.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "CAS 튜플을 where 절에 전부 반복하고 update count를 답으로 쓴다", "fenced lease — 만료 시각만으로는 부족한 이유" ] } ], "question": [ { "title": "V2 상태 기계 넷의 컨테이너 레인이 실행되지 않았다", "slug": "v2-state-machine-lanes-not-executed", "file": "owner-safe-state-machines/question/openquestion-v2-state-machine-lanes-not-executed.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "컨테이너가 필요한 특수 레인의 실제 결과를 실행으로 확인하지 않았다", "CAS 튜플과 update count가 답이 되는 구조", "만료된 CLAIMED는 takeover하고 만료된 EXECUTING은 조정을 요구하도록 갈랐다" ] } ], "decision": [ { "title": "capability는 스키마 적용과 사용 승인을 분리한다", "slug": "capability-separates-installation-from-activation", "file": "owner-safe-state-machines/decision/decision-capability-separates-installation-from-activation.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "capability_schema_registry — 스키마 적용과 사용 승인의 분리", "지원 등급은 추론이 아니라 선언이고 증거 없이는 올라가지 않는다" ] }, { "title": "상태 기계 구현은 Spring stereotype을 갖지 않는다", "slug": "state-machines-carry-no-stereotype", "file": "owner-safe-state-machines/decision/decision-state-machines-carry-no-stereotype.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "활성 트랜잭션 검사가 data source를 묻지 않아 다른 커넥션에서 커밋됐다", "꺼짐은 조건의 반복이 아니라 구조여야 한다", "Bean 애너테이션이 있다는 것은 조립 증거가 아니다" ] } ] } }, "query-and-pagination-models": { "topic": "query-and-pagination-models", "kinds": { "case": [], "concept": [ { "title": "자동설정이 참조하는 것은 58개 파일 중 둘이다", "slug": "adapter-inbound-graphql-c10", "file": "query-and-pagination-models/concept/concept-adapter-inbound-graphql-c10.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-graphql-c10", "adapter-inbound-graphql-c10-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-graphql-c10.txt" ], "relations": [] }, { "title": "durable-operation 게이트는 켤 수 없고 켜면 부팅이 실패한다", "slug": "adapter-inbound-web-c06", "file": "query-and-pagination-models/concept/concept-adapter-inbound-web-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c06" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c06.txt" ], "relations": [] }, { "title": "JpaRepositoryFragmentSupport는 CRUD가 아니라 실행 정책이다", "slug": "adapter-outbound-persistence-jpa-c27", "file": "query-and-pagination-models/concept/concept-adapter-outbound-persistence-jpa-c27.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c27" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c27.txt" ], "relations": [] }, { "title": "KeysetPredicateBuilder가 만드는 것은 사전식 술어다", "slug": "adapter-outbound-persistence-jpa-c28", "file": "query-and-pagination-models/concept/concept-adapter-outbound-persistence-jpa-c28.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c28" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c28.txt" ], "relations": [] }, { "title": "size + 1로 hasNext를 판정하고 COUNT를 없앤다", "slug": "adapter-outbound-persistence-jpa-c29", "file": "query-and-pagination-models/concept/concept-adapter-outbound-persistence-jpa-c29.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c29" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c29.txt" ], "relations": [] }, { "title": "application-core가 아는 유일한 프로젝트 의존은 shared-contract다", "slug": "application-core-c01", "file": "query-and-pagination-models/concept/concept-application-core-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "application-core-c01", "application-core-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/application-core-c01.txt" ], "relations": [ "legacy storage/notification compatibility surface의 제거 조건 추적" ] } ], "reference": [], "question": [], "decision": [] } }, "redis-command-admission": { "topic": "redis-command-admission", "kinds": { "case": [ { "title": "'\"build gate\"라 불리는 catalog drift 검사가 어디에서도 실행되지 않는다'", "slug": "a-build-gate-that-is-not-in-the-build", "file": "redis-command-admission/case/case-a-build-gate-that-is-not-in-the-build.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-build-gate-that-is-not-in-the-build" ], "evidence": [ "../../../final/evidence/raw/a-build-gate-that-is-not-in-the-build.txt" ], "relations": [ "산문이 선언한 게이트는 빌드에 있는 게이트가 아니다", "두 파일이 같은 검증기를 \"빌드를 실패시키는 것\"이라 적고, 어떤 빌드도 그것을 부르지 않는다", "서버 메타데이터가 명령의 정의이고 정책 파일은 허용 범위다" ] }, { "title": "startup probe가 production에서 한 번도 실행되지 않는다", "slug": "a-startup-probe-that-never-runs", "file": "redis-command-admission/case/case-a-startup-probe-that-never-runs.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-startup-probe-that-never-runs" ], "evidence": [ "../../../final/evidence/raw/a-startup-probe-that-never-runs.txt" ], "relations": [ "@Bean이 있다는 것은 조립 증거가 아니다", "시작 검증기가 도는지는 그 능력에 자동설정 루트가 있는지와 일치한다", "하위 시스템 전체가 미배선인데 그것을 켜는 플래그는 시작 검사를 수행한다" ] }, { "title": "의미 어댑터 다섯이 gateway를 직접 불러 admission 아홉 단계를 건너뛴다", "slug": "five-adapters-bypass-the-single-admission-point", "file": "redis-command-admission/case/case-five-adapters-bypass-the-single-admission-point.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "five-adapters-bypass-the-single-admission-point" ], "evidence": [ "../../../final/evidence/raw/five-adapters-bypass-the-single-admission-point.txt" ], "relations": [ "명령 카탈로그와 admission 아홉 단계", "단일 admission point는 우회 경로를 세어야 성립한다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다" ] }, { "title": "NOSCRIPT 복구가 다섯 벌이고 넷은 스크립트 레지스트리를 지나지 않는다", "slug": "five-copies-of-noscript-recovery", "file": "redis-command-admission/case/case-five-copies-of-noscript-recovery.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "five-copies-of-noscript-recovery" ], "evidence": [ "../../../final/evidence/raw/five-copies-of-noscript-recovery.txt" ], "relations": [ "같은 개념의 두 어휘가 공존하면 하나를 죽은 것으로 표시한다", "단일 admission point는 우회 경로를 세어야 성립한다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다" ] } ], "concept": [ { "title": "명령 카탈로그와 admission 아홉 단계", "slug": "redis-admission-stages", "file": "redis-command-admission/concept/concept-redis-admission-stages.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "redis-admission-stages", "redis-admission-stages-diagram" ], "evidence": [ "../../../final/evidence/raw/redis-admission-stages.txt" ], "relations": [ "의미 어댑터 다섯이 gateway를 직접 불러 admission 아홉 단계를 건너뛴다", "단일 admission point는 우회 경로를 세어야 성립한다", "분류되지 않은 명령은 fail-closed로 거부한다" ] } ], "reference": [ { "title": "단일 admission point는 우회 경로를 세어야 성립한다", "slug": "a-single-admission-point-must-count-its-bypasses", "file": "redis-command-admission/reference/reference-a-single-admission-point-must-count-its-bypasses.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "의미 어댑터 다섯이 gateway를 직접 불러 admission 아홉 단계를 건너뛴다", "명령 카탈로그와 admission 아홉 단계", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다" ] }, { "title": "서버 메타데이터가 명령의 정의이고 정책 파일은 허용 범위다", "slug": "server-metadata-defines-the-command", "file": "redis-command-admission/reference/reference-server-metadata-defines-the-command.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "명령 카탈로그와 admission 아홉 단계", "build gate라 불리는 catalog drift 검사가 어디에서도 실행되지 않는다", "분류되지 않은 명령은 fail-closed로 거부한다" ] } ], "question": [ { "title": "Redis 토폴로지 레인이 실행되지 않아 key spec 드리프트가 확인되지 않았다", "slug": "redis-topology-lane-not-executed", "file": "redis-command-admission/question/openquestion-redis-topology-lane-not-executed.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "build gate라 불리는 catalog drift 검사가 어디에서도 실행되지 않는다", "서버 메타데이터가 명령의 정의이고 정책 파일은 허용 범위다", "컨테이너가 필요한 특수 레인의 실제 결과를 실행으로 확인하지 않았다" ] } ], "decision": [ { "title": "분류되지 않은 명령은 fail-closed로 거부한다", "slug": "unclassified-commands-are-refused", "file": "redis-command-admission/decision/decision-unclassified-commands-are-refused.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "서버 메타데이터가 명령의 정의이고 정책 파일은 허용 범위다", "명령 카탈로그와 admission 아홉 단계", "의미 어댑터 다섯이 gateway를 직접 불러 admission 아홉 단계를 건너뛴다" ] } ] } }, "result-and-failure-algebra": { "topic": "result-and-failure-algebra", "kinds": { "case": [], "concept": [ { "title": "인증이 예외 변환 바깥에 있어도 진단이 새지 않는다", "slug": "adapter-inbound-grpc-c01", "file": "result-and-failure-algebra/concept/concept-adapter-inbound-grpc-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-grpc-c01", "adapter-inbound-grpc-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-grpc-c01.txt" ], "relations": [] }, { "title": "구독 경로가 guard를 건너뛰고 대신 세우는 검사", "slug": "adapter-outbound-cache-redis-c09", "file": "result-and-failure-algebra/concept/concept-adapter-outbound-cache-redis-c09.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-cache-redis-c09" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-cache-redis-c09.txt" ], "relations": [] }, { "title": "실패가 런타임이 아니라 빌드에서 발생한다", "slug": "domain-core-c03", "file": "result-and-failure-algebra/concept/concept-domain-core-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "domain-core-c03" ], "evidence": [ "../../../final/evidence/raw/domain-core-c03.txt" ], "relations": [] }, { "title": "public 시그니처에 나오는 타입은 api로 선언한다", "slug": "messaging-cloudevents-c08", "file": "result-and-failure-algebra/concept/concept-messaging-cloudevents-c08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-cloudevents-c08" ], "evidence": [ "../../../final/evidence/raw/messaging-cloudevents-c08.txt" ], "relations": [ "왕복이라 부르는 테스트는 무엇을 보존하지 않는지도 적는다", "문서가 범위를 제한하면 그 제한을 누가 강제하는지 같이 적는다" ] }, { "title": "커넥션을 요청하기 전에 거절하도록 고정한 테스트", "slug": "messaging-inbox-jdbc-postgresql-c07", "file": "result-and-failure-algebra/concept/concept-messaging-inbox-jdbc-postgresql-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-inbox-jdbc-postgresql-c07" ], "evidence": [ "../../../final/evidence/raw/messaging-inbox-jdbc-postgresql-c07.txt" ], "relations": [ "컬럼 폭은 애플리케이션 검증과 짝을 이룬다", "같은 안전 규칙은 한 공식과 한 강제 시점을 갖는다" ] }, { "title": "알 수 없는 실패의 기본값을 모호로 둔다", "slug": "messaging-pulsar-experimental-c01", "file": "result-and-failure-algebra/concept/concept-messaging-pulsar-experimental-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-pulsar-experimental-c01", "messaging-pulsar-experimental-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-pulsar-experimental-c01.txt" ], "relations": [] }, { "title": "검사의 위치와 키가 틀렸던 두 결함", "slug": "messaging-schema-api-c07", "file": "result-and-failure-algebra/concept/concept-messaging-schema-api-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-api-c07" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-api-c07.txt" ], "relations": [ "port 계약은 동시성 요구를 적는다", "도달성 판정은 단어가 아니라 import로 확인한다" ] }, { "title": "아는 척하지 않기 위해 던지는 자리와 삼키는 자리", "slug": "messaging-testkit-c06", "file": "result-and-failure-algebra/concept/concept-messaging-testkit-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-testkit-c06" ], "evidence": [ "../../../final/evidence/raw/messaging-testkit-c06.txt" ], "relations": [] }, { "title": "오래 돌 때만 드러나는 수명주기 결함 네 개", "slug": "messaging-transport-spi-c07", "file": "result-and-failure-algebra/concept/concept-messaging-transport-spi-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-transport-spi-c07" ], "evidence": [ "../../../final/evidence/raw/messaging-transport-spi-c07.txt" ], "relations": [ "멱등 종료를 보장하는 컴포넌트는 종료 이후의 등록도 정의한다", "같은 개념의 sentinel은 계층을 넘어 하나로 정한다" ] }, { "title": "추정하지 않는 두 경계 — 스위치 해석과 상태 투영", "slug": "shared-contract-c03", "file": "result-and-failure-algebra/concept/concept-shared-contract-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "shared-contract-c03" ], "evidence": [ "../../../final/evidence/raw/shared-contract-c03.txt" ], "relations": [] } ], "reference": [], "question": [], "decision": [] } }, "retention-and-unbounded-growth": { "topic": "retention-and-unbounded-growth", "kinds": { "case": [ { "title": "재생 저장소에 제거 경로가 없고, 형제 맵의 상한은 세션 경계 하나다", "slug": "a-replay-store-with-no-eviction-path", "file": "retention-and-unbounded-growth/case/case-a-replay-store-with-no-eviction-path.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-replay-store-with-no-eviction-path" ], "evidence": [ "../../../final/evidence/raw/a-replay-store-with-no-eviction-path.txt" ], "relations": [ "bounded 와 unbounded 오버로드를 나란히 둔 포트", "같은 안전 규칙은 하나의 공식과 하나의 강제 시점을 갖는다", "runtime_memberships를 먼저 읽고 심각도를 정한다" ] }, { "title": "cleanup 이 스스로 막겠다고 적은 장애를 일으키는 형태로 호출된다", "slug": "the-cleanup-that-causes-the-outage-it-prevents", "file": "retention-and-unbounded-growth/case/case-the-cleanup-that-causes-the-outage-it-prevents.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "the-cleanup-that-causes-the-outage-it-prevents" ], "evidence": [ "../../../final/evidence/raw/the-cleanup-that-causes-the-outage-it-prevents.txt" ], "relations": [ "bounded 와 unbounded 오버로드를 나란히 둔 포트", "두 형태를 나란히 내놓는 포트는 이미 안전하지 않은 쪽을 고른 것이다", "그 속성을 보일 수 없는 대역 위에서 통과한 테스트는 증인이 아니다" ] } ], "concept": [ { "title": "bounded 와 unbounded 오버로드를 나란히 둔 포트", "slug": "bounded-and-unbounded-side-by-side", "file": "retention-and-unbounded-growth/concept/concept-bounded-and-unbounded-side-by-side.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "bounded-and-unbounded-side-by-side", "bounded-and-unbounded-side-by-side-diagram" ], "evidence": [ "../../../final/evidence/raw/bounded-and-unbounded-side-by-side.txt" ], "relations": [ "두 형태를 나란히 내놓는 포트는 이미 안전하지 않은 쪽을 고른 것이다", "cleanup 이 스스로 막겠다고 적은 장애를 일으키는 형태로 호출된다", "같은 개념의 두 어휘가 공존하면 하나를 죽은 것으로 표시한다" ] } ], "reference": [ { "title": "그 속성을 보일 수 없는 대역 위에서 통과한 테스트는 증인이 아니다", "slug": "a-fake-that-cannot-show-the-property-is-not-a-witness", "file": "retention-and-unbounded-growth/reference/reference-a-fake-that-cannot-show-the-property-is-not-a-witness.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "cleanup 이 스스로 막겠다고 적은 장애를 일으키는 형태로 호출된다", "재개된 리드라이브가 옮기지 못한 메시지를 건너뛰고 성공으로 닫힌다", "배정 식별자 때문에 insert-first 청구가 UPSERT 가 되어 커밋된 결과를 덮었다" ] }, { "title": "두 형태를 나란히 내놓는 포트는 이미 안전하지 않은 쪽을 고른 것이다", "slug": "a-port-that-offers-both-forms-has-chosen-the-unsafe-one", "file": "retention-and-unbounded-growth/reference/reference-a-port-that-offers-both-forms-has-chosen-the-unsafe-one.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "bounded 와 unbounded 오버로드를 나란히 둔 포트", "cleanup 이 스스로 막겠다고 적은 장애를 일으키는 형태로 호출된다", "같은 개념의 두 어휘가 공존하면 하나를 죽은 것으로 표시한다" ] }, { "title": "같은 안전 규칙은 하나의 공식과 하나의 강제 시점을 갖는다", "slug": "one-formula-and-one-enforcement-point-per-safety-rule", "file": "retention-and-unbounded-growth/reference/reference-one-formula-and-one-enforcement-point-per-safety-rule.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "재생 저장소에 제거 경로가 없고, 형제 맵의 상한은 세션 경계 하나다", "순서 계약을 구현하는 것이 없고, 그것을 검증한다는 테스트는 enum 선언 순서만 본다", "문서의 수치는 세지 말고 파생하거나 게이트로 붙든다" ] } ], "question": [], "decision": [] } }, "runtime-contract-correctness": { "topic": "runtime-contract-correctness", "kinds": { "case": [ { "title": "애플리케이션이 넣은 재시도 정책이 한 번도 불리지 않고 작업만 두 번 돈다", "slug": "a05-f005-jparetrypolicy", "file": "runtime-contract-correctness/case/case-a05-f005-jparetrypolicy.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a05-f005-jparetrypolicy", "a05-f005-jparetrypolicy-probe" ], "evidence": [ "../../../final/evidence/raw/a05-f005-jparetrypolicy.txt", "../../../final/evidence/raw/a05-f005-jparetrypolicy-probe.txt" ], "relations": [ "재시도 구현이 둘이고 정교한 쪽을 아무도 호출하지 않는다", "재시도 단위는 statement가 아니라 유스케이스 전체다", "@Bean이 있다는 것은 조립 증거가 아니다" ] }, { "title": "하나의 상태 코드가 같은 메서드 안에서 두 답을 갖는다", "slug": "grpc-core-api-f04", "file": "runtime-contract-correctness/case/case-grpc-core-api-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-core-api-f04" ], "evidence": [ "../../../final/evidence/raw/grpc-core-api-f04.txt" ], "relations": [] }, { "title": "허용 태그 8개 중 둘은 값이 자유 문자열이고, 그중 하나는 bounded 열거형이 이미 존재한다", "slug": "grpc-observability-f03", "file": "runtime-contract-correctness/case/case-grpc-observability-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-observability-f03" ], "evidence": [ "../../../final/evidence/raw/grpc-observability-f03.txt" ], "relations": [] }, { "title": "반사 모드를 명시하면 서비스·역할 허용 목록이 조용히 하드코딩으로 바뀐다", "slug": "grpc-spring-boot-starter-f04", "file": "runtime-contract-correctness/case/case-grpc-spring-boot-starter-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-spring-boot-starter-f04" ], "evidence": [ "../../../final/evidence/raw/grpc-spring-boot-starter-f04.txt" ], "relations": [] }, { "title": "예외 승격이 에러 코드 문자열 접미사에 의존한다", "slug": "messaging-claim-check-f03", "file": "runtime-contract-correctness/case/case-messaging-claim-check-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-claim-check-f03" ], "evidence": [ "../../../final/evidence/raw/messaging-claim-check-f03.txt" ], "relations": [ "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "같은 튜닝 값이 두 계층에 있으면 어느 쪽이 이기는지 정한다" ] }, { "title": "MessagingRedactor가 상수 대신 문자열 리터럴을 쓴다", "slug": "messaging-core-api-f04", "file": "runtime-contract-correctness/case/case-messaging-core-api-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-core-api-f04" ], "evidence": [ "../../../final/evidence/raw/messaging-core-api-f04.txt" ], "relations": [] }, { "title": "구세대 전이 메서드가 신세대와 다른 행 상태를 남긴다", "slug": "messaging-outbox-jdbc-postgresql-f05", "file": "runtime-contract-correctness/case/case-messaging-outbox-jdbc-postgresql-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-outbox-jdbc-postgresql-f05" ], "evidence": [ "../../../final/evidence/raw/messaging-outbox-jdbc-postgresql-f05.txt" ], "relations": [] }, { "title": "maxBatches 가 하드코딩이고 현재는 의미가 없다", "slug": "messaging-outbox-jdbc-postgresql-f08", "file": "runtime-contract-correctness/case/case-messaging-outbox-jdbc-postgresql-f08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-outbox-jdbc-postgresql-f08" ], "evidence": [ "../../../final/evidence/raw/messaging-outbox-jdbc-postgresql-f08.txt" ], "relations": [] }, { "title": "죽은 매개변수 하나가 유일한 비기본값에서 NPE 를 낳는다", "slug": "messaging-spring-boot-starter-f03", "file": "runtime-contract-correctness/case/case-messaging-spring-boot-starter-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-spring-boot-starter-f03" ], "evidence": [ "../../../final/evidence/raw/messaging-spring-boot-starter-f03.txt" ], "relations": [ "검증기는 발행이 아니라 주입이 강제다" ] } ], "concept": [], "reference": [ { "title": "구성 오류는 한 예외 타입과 안정 코드로 보고한다", "slug": "messaging-kafka-share-experimental-f04", "file": "runtime-contract-correctness/reference/reference-messaging-kafka-share-experimental-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "\"등록\"이 아무것도 등록하지 않고 성공을 반환한다" ] }, { "title": "부팅 경로의 알고리즘 복잡도는 문서화한다", "slug": "messaging-policy-f05", "file": "runtime-contract-correctness/reference/reference-messaging-policy-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "재시도 엔진과 DLQ 조정자가 bean으로 만들어지고 주입되는 곳이 없다", "재시도와 DLQ 각각에 두 개의 구현이 있고 정본이 표시되지 않았다", "DLQ 메타데이터의 두 시각이 항상 같다" ] }, { "title": "CompletionStage를 반환하는 메서드는 동기적으로 던지지 않는다", "slug": "messaging-runtime-core-f05", "file": "runtime-contract-correctness/reference/reference-messaging-runtime-core-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "관측이 구현·호출부·주입 자리를 모두 갖추고도 출하에서 no-op이다", "소비 오케스트레이터가 조립되지 않는다", "선언된 content type과 실제 인코딩이 조용히 갈라질 수 있다" ] } ], "question": [], "decision": [] } }, "runtime-reachability-and-composition": { "topic": "runtime-reachability-and-composition", "kinds": { "case": [ { "title": "오타를 막는 근거만 남기고, 오타가 들어올 자리를 지웠다", "slug": "a05-f007-transactionprofileregistry", "file": "runtime-reachability-and-composition/case/case-a05-f007-transactionprofileregistry.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a05-f007-transactionprofileregistry-adr", "a05-f007-transactionprofileregistry" ], "evidence": [ "../../../final/evidence/raw/a05-f007-transactionprofileregistry-adr.txt", "../../../final/evidence/raw/a05-f007-transactionprofileregistry.txt" ], "relations": [ "재시도 구현이 둘이고 정교한 쪽을 아무도 호출하지 않는다", "legacy compatibility surface의 제거 조건을 세 가지로 고정한다", "같은 개념의 두 어휘가 공존하면 하나를 죽은 것으로 표시한다" ] }, { "title": "쿼리 이름을 SQL 로 옮기는 두 경로가 양쪽 끝만 있고 가운데가 없다", "slug": "a05-f018-sql", "file": "runtime-reachability-and-composition/case/case-a05-f018-sql.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a05-f018-sql" ], "evidence": [ "../../../final/evidence/raw/a05-f018-sql.txt" ], "relations": [ "@Bean이 있다는 것은 조립 증거가 아니다", "이름은 값이 아니라 registry key다", "카디널리티 경계를 타입으로 표현하기" ] }, { "title": "거부라고 적힌 처리가 폐기이고, 그 값을 읽는 시작 검사는 켤 방법이 없다", "slug": "a06-f003-change-streams-true", "file": "runtime-reachability-and-composition/case/case-a06-f003-change-streams-true.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a06-f003-change-streams-true", "a06-f003-change-streams-true-probe", "a06-f003-change-streams-true-shipped" ], "evidence": [ "../../../final/evidence/raw/a06-f003-change-streams-true.txt", "../../../final/evidence/raw/a06-f003-change-streams-true-probe.txt", "../../../final/evidence/raw/a06-f003-change-streams-true-shipped.txt" ], "relations": [ "하위 시스템 전체가 미배선인데 그것을 켜는 플래그는 시작 검사를 수행한다", "sanitize가 아니라 reject가 기본이다", "플래그는 고정 거짓이라 능력 검사를 끄지만, 조립 조건이 아니라서 소비자 빈은 그대로 생성된다" ] }, { "title": "통합 다리의 메타데이터 조립이 메타데이터 예산을 검사하지 않는다", "slug": "grpc-advanced-compat-f01", "file": "runtime-reachability-and-composition/case/case-grpc-advanced-compat-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-compat-f01" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-compat-f01.txt" ], "relations": [] }, { "title": "정책 목록의 가장 강한 성질을 이 저장소에서는 쓸 수 없다", "slug": "grpc-core-api-f01", "file": "runtime-reachability-and-composition/case/case-grpc-core-api-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-core-api-f01" ], "evidence": [ "../../../final/evidence/raw/grpc-core-api-f01.txt" ], "relations": [] }, { "title": "queueHighWatermark 는 요구되고 검증되지만 아무도 읽지 않는다", "slug": "grpc-observability-f01", "file": "runtime-reachability-and-composition/case/case-grpc-observability-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-observability-f01" ], "evidence": [ "../../../final/evidence/raw/grpc-observability-f01.txt" ], "relations": [] }, { "title": "clearAfterTask 는 합법 값이 하나뿐인 성분이고, 아무도 읽지 않는다", "slug": "grpc-policy-f07", "file": "runtime-reachability-and-composition/case/case-grpc-policy-f07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-policy-f07" ], "evidence": [ "../../../final/evidence/raw/grpc-policy-f07.txt" ], "relations": [] }, { "title": "빌더 경로에서 순서 규칙 넷 중 셋이 발화할 수 없다", "slug": "grpc-server-f03", "file": "runtime-reachability-and-composition/case/case-grpc-server-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-server-f03" ], "evidence": [ "../../../final/evidence/raw/grpc-server-f03.txt" ], "relations": [] }, { "title": "시작 검증기가 시작 시 실행되지 않는다", "slug": "grpc-spring-boot-starter-f01", "file": "runtime-reachability-and-composition/case/case-grpc-spring-boot-starter-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-spring-boot-starter-f01", "grpc-spring-boot-starter-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-spring-boot-starter-f01.txt" ], "relations": [] }, { "title": "default-unary-deadline 은 읽는 코드가 저장소에 없다", "slug": "grpc-spring-boot-starter-f03", "file": "runtime-reachability-and-composition/case/case-grpc-spring-boot-starter-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-spring-boot-starter-f03" ], "evidence": [ "../../../final/evidence/raw/grpc-spring-boot-starter-f03.txt" ], "relations": [] }, { "title": "계약 스위트 둘이 결과를 만드는 코드를 갖지 않는다", "slug": "grpc-testkit-f05", "file": "runtime-reachability-and-composition/case/case-grpc-testkit-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-testkit-f05" ], "evidence": [ "../../../final/evidence/raw/grpc-testkit-f05.txt" ], "relations": [] }, { "title": "TopologyManagementMode 가 어디에도 연결되어 있지 않다", "slug": "messaging-admin-api-f03", "file": "runtime-reachability-and-composition/case/case-messaging-admin-api-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-api-f03" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-api-f03.txt" ], "relations": [] }, { "title": "운영자용 표면 전체에 프로덕션 소비자가 없다", "slug": "messaging-admin-api-f04", "file": "runtime-reachability-and-composition/case/case-messaging-admin-api-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-api-f04" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-api-f04.txt" ], "relations": [] }, { "title": "messaging-policy 의존이 import 0건이다", "slug": "messaging-admin-api-f06", "file": "runtime-reachability-and-composition/case/case-messaging-admin-api-f06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-api-f06" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-api-f06.txt" ], "relations": [] }, { "title": "오케스트레이터가 어디에서도 실행되지 않는다", "slug": "messaging-admin-runtime-f03", "file": "runtime-reachability-and-composition/case/case-messaging-admin-runtime-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-runtime-f03", "messaging-admin-runtime-f03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-runtime-f03.txt" ], "relations": [] }, { "title": "public 인터페이스를 패키지 밖에서 구현할 수 없다", "slug": "messaging-admin-runtime-f04", "file": "runtime-reachability-and-composition/case/case-messaging-admin-runtime-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-runtime-f04" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-runtime-f04.txt" ], "relations": [] }, { "title": "선언된 의존 6개 중 3개가 import 0건", "slug": "messaging-admin-runtime-f09", "file": "runtime-reachability-and-composition/case/case-messaging-admin-runtime-f09.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-runtime-f09" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-runtime-f09.txt" ], "relations": [] }, { "title": "배포 아티팩트가 싣지만 아무도 부르지 않고, 다른 곳의 에러 메시지가 이 경로를 권한다", "slug": "messaging-claim-check-f01", "file": "runtime-reachability-and-composition/case/case-messaging-claim-check-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-claim-check-f01", "messaging-claim-check-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-claim-check-f01.txt" ], "relations": [ "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "같은 튜닝 값이 두 계층에 있으면 어느 쪽이 이기는지 정한다" ] }, { "title": "배포 아티팩트가 싣지만 아무도 부르지 않는다", "slug": "messaging-cloudevents-f02", "file": "runtime-reachability-and-composition/case/case-messaging-cloudevents-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-cloudevents-f02", "messaging-cloudevents-f02-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-cloudevents-f02.txt" ], "relations": [ "왕복이라 부르는 테스트는 무엇을 보존하지 않는지도 적는다", "문서가 범위를 제한하면 그 제한을 누가 강제하는지 같이 적는다" ] }, { "title": "bounded purge가 구현돼 있고 호출되지 않아, cleanup이 스스로 막겠다고 한 장애를 일으킨다", "slug": "messaging-inbox-jdbc-postgresql-f01", "file": "runtime-reachability-and-composition/case/case-messaging-inbox-jdbc-postgresql-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-inbox-jdbc-postgresql-f01", "messaging-inbox-jdbc-postgresql-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-inbox-jdbc-postgresql-f01.txt" ], "relations": [ "컬럼 폭은 애플리케이션 검증과 짝을 이룬다", "같은 안전 규칙은 한 공식과 한 강제 시점을 갖는다" ] }, { "title": "관측 구현이 조립되지 않고, 그 재료 둘만 bean으로 존재한다", "slug": "messaging-observability-f02", "file": "runtime-reachability-and-composition/case/case-messaging-observability-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-observability-f02", "messaging-observability-f02-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-observability-f02.txt" ], "relations": [ "타입이 문서화한 불변식은 타입이 강제한다" ] }, { "title": "정리 작업이 무제한 DELETE 를 쏘고, 그것을 막는 오버로드는 호출되지 않는다", "slug": "messaging-outbox-jdbc-postgresql-f01", "file": "runtime-reachability-and-composition/case/case-messaging-outbox-jdbc-postgresql-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-outbox-jdbc-postgresql-f01", "messaging-outbox-jdbc-postgresql-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-outbox-jdbc-postgresql-f01.txt" ], "relations": [] }, { "title": "두 릴레이 상호배제가 기동에서 강제되지 않는다", "slug": "messaging-outbox-jdbc-postgresql-f04", "file": "runtime-reachability-and-composition/case/case-messaging-outbox-jdbc-postgresql-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-outbox-jdbc-postgresql-f04", "messaging-outbox-jdbc-postgresql-f04-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-outbox-jdbc-postgresql-f04.txt" ], "relations": [] }, { "title": "능력 상수의 delayedDelivery 가 무조건 참이고, 그 지연을 제공할 토폴로지는 조립되지 않는다", "slug": "messaging-rabbit-f04", "file": "runtime-reachability-and-composition/case/case-messaging-rabbit-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-rabbit-f04" ], "evidence": [ "../../../final/evidence/raw/messaging-rabbit-f04.txt" ], "relations": [] }, { "title": "fencing token 경로가 실제 데이터베이스에 대해 실행되지 않는다", "slug": "messaging-reliability-api-f02", "file": "runtime-reachability-and-composition/case/case-messaging-reliability-api-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-reliability-api-f02", "messaging-reliability-api-f02-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-reliability-api-f02.txt" ], "relations": [ "계약만 담는 leaf도 계약의 거절 조건은 자기 레인에서 검증한다", "record의 `equals`를 좁히면 이유를 적는다", "호출 컨텍스트가 계약이면 그 컨텍스트를 검증할 수단을 함께 정한다" ] }, { "title": "관측이 구현·호출부·주입 자리를 모두 갖추고도 출하에서 no-op이다", "slug": "messaging-runtime-core-f01", "file": "runtime-reachability-and-composition/case/case-messaging-runtime-core-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-runtime-core-f01", "messaging-runtime-core-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-runtime-core-f01.txt" ], "relations": [ "만들어 두고 흘리지 않는 진단값은 진단이 아니다", "증가한다고 문서화한 값이 리터럴이면 그 사실을 적는다", "안정 코드는 운영자의 행동이 갈리는 지점마다 나눈다", "`CompletionStage`를 반환하는 메서드는 동기적으로 던지지 않는다" ] }, { "title": "소비 오케스트레이터가 조립되지 않는다", "slug": "messaging-runtime-core-f02", "file": "runtime-reachability-and-composition/case/case-messaging-runtime-core-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-runtime-core-f02", "messaging-runtime-core-f02-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-runtime-core-f02.txt" ], "relations": [ "만들어 두고 흘리지 않는 진단값은 진단이 아니다", "증가한다고 문서화한 값이 리터럴이면 그 사실을 적는다", "안정 코드는 운영자의 행동이 갈리는 지점마다 나눈다", "`CompletionStage`를 반환하는 메서드는 동기적으로 던지지 않는다" ] }, { "title": "포맷 독립 진화 규칙이 호출되지 않고, 그것이 막으려던 중복이 실제로 생겼다", "slug": "messaging-schema-api-f01", "file": "runtime-reachability-and-composition/case/case-messaging-schema-api-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-api-f01", "messaging-schema-api-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-api-f01.txt" ], "relations": [ "port 계약은 동시성 요구를 적는다", "도달성 판정은 단어가 아니라 import로 확인한다" ] }, { "title": "종료 시 자격증명 소거가 호출되지 않는다", "slug": "messaging-security-f04", "file": "runtime-reachability-and-composition/case/case-messaging-security-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-security-f04" ], "evidence": [ "../../../final/evidence/raw/messaging-security-f04.txt" ], "relations": [ "배선된 게이트는 자기 leaf 레인에서 검증한다", "같은 술어가 두 타입에 있으면 하나가 다른 하나를 부른다", "가변 필드로 상태 전이를 표현하면 가시성을 함께 정한다", "맵 갱신 함수 안에서 I/O를 하면 그 지연이 락 범위가 된다" ] }, { "title": "같은 자동 설정 안에서 검증기 하나만 감싸이지 않는다", "slug": "messaging-spring-boot-starter-f01", "file": "runtime-reachability-and-composition/case/case-messaging-spring-boot-starter-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-spring-boot-starter-f01", "messaging-spring-boot-starter-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-spring-boot-starter-f01.txt" ], "relations": [ "검증기는 발행이 아니라 주입이 강제다" ] }, { "title": "FaultController 의 5개 중 2개가 구현만 3벌 있고 호출부가 0건이다", "slug": "messaging-testkit-f01", "file": "runtime-reachability-and-composition/case/case-messaging-testkit-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-testkit-f01", "messaging-testkit-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-testkit-f01.txt" ], "relations": [] }, { "title": "1 MiB 한도가 PayloadPolicy 를 두고 리터럴로 재선언된다", "slug": "messaging-testkit-f04", "file": "runtime-reachability-and-composition/case/case-messaging-testkit-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-testkit-f04" ], "evidence": [ "../../../final/evidence/raw/messaging-testkit-f04.txt" ], "relations": [] }, { "title": "messaging-transport-spi 의존이 import 0건이다", "slug": "messaging-testkit-f05", "file": "runtime-reachability-and-composition/case/case-messaging-testkit-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-testkit-f05" ], "evidence": [ "../../../final/evidence/raw/messaging-testkit-f05.txt" ], "relations": [] }, { "title": "BrokerFailureMatrix.adapters() 는 호출부가 0건이다", "slug": "messaging-testkit-f06", "file": "runtime-reachability-and-composition/case/case-messaging-testkit-f06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-testkit-f06" ], "evidence": [ "../../../final/evidence/raw/messaging-testkit-f06.txt" ], "relations": [] }, { "title": "시작 검증기가 유일한 소비자인 설정 키 넷이 아무것도 게이트하지 않는다", "slug": "startup-validator-is-the-only-reader-of-four-keys", "file": "runtime-reachability-and-composition/case/case-startup-validator-is-the-only-reader-of-four-keys.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "startup-validator-is-the-only-reader-of-four-keys" ], "evidence": [ "../../../final/evidence/raw/startup-validator-is-the-only-reader-of-four-keys.txt" ], "relations": [ "시작 검증기가 시작 시 실행되지 않는다", "검증기는 발행이 아니라 주입이 강제다", "같은 자동 설정 안에서 검증기 하나만 감싸이지 않아 트랜잭션 조건이 검사되지 않는다" ] }, { "title": "같은 자동 설정 안에서 검증기 하나만 감싸이지 않아 트랜잭션 조건이 검사되지 않는다", "slug": "validator-declared-and-never-injected", "file": "runtime-reachability-and-composition/case/case-validator-declared-and-never-injected.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "validator-declared-and-never-injected" ], "evidence": [ "../../../final/evidence/raw/validator-declared-and-never-injected.txt" ], "relations": [ "시작 검증기가 유일한 소비자인 설정 키 넷이 아무것도 게이트하지 않는다", "검증기는 발행이 아니라 주입이 강제다", "능력 상수가 프로파일 조건보다 오래 살아서 중복 제거 없는 목적지가 가드를 통과한다" ] } ], "concept": [], "reference": [ { "title": "검증기는 발행이 아니라 주입이 강제다", "slug": "a-validator-is-enforced-by-injection", "file": "runtime-reachability-and-composition/reference/reference-a-validator-is-enforced-by-injection.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "같은 자동 설정 안에서 검증기 하나만 감싸이지 않아 트랜잭션 조건이 검사되지 않는다", "시작 검증기가 유일한 소비자인 설정 키 넷이 아무것도 게이트하지 않는다", "시작 검증기가 시작 시 실행되지 않는다" ] }, { "title": "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "slug": "messaging-claim-check-f04", "file": "runtime-reachability-and-composition/reference/reference-messaging-claim-check-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "배포 아티팩트가 싣지만 아무도 부르지 않고, 다른 곳의 에러 메시지가 이 경로를 권한다", "예외 승격이 에러 코드 문자열 접미사에 의존한다" ] }, { "title": "허용 의존 목록은 상한이므로 미사용을 잡지 않는다 — 그것을 잡으려면 별도 검사가 필요하다", "slug": "messaging-kafka-share-experimental-f02", "file": "runtime-reachability-and-composition/reference/reference-messaging-kafka-share-experimental-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "\"등록\"이 아무것도 등록하지 않고 성공을 반환한다" ] }, { "title": "만들어 두고 흘리지 않는 진단값은 진단이 아니다", "slug": "messaging-runtime-core-f07", "file": "runtime-reachability-and-composition/reference/reference-messaging-runtime-core-f07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "관측이 구현·호출부·주입 자리를 모두 갖추고도 출하에서 no-op이다", "소비 오케스트레이터가 조립되지 않는다", "선언된 content type과 실제 인코딩이 조용히 갈라질 수 있다" ] }, { "title": "배선된 게이트는 자기 leaf 레인에서 검증한다", "slug": "messaging-security-f07", "file": "runtime-reachability-and-composition/reference/reference-messaging-security-f07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "종료 시 자격증명 소거가 호출되지 않는다", "같은 TLS posture를 두 클래스가 다른 엄격도로 검사한다", "권한 거부가 `AUTHORIZATION`이 아니라 `CONFIGURATION`으로 기록된다" ] }, { "title": "허용 의존 목록은 상한이므로 미사용을 잡지 않는다", "slug": "messaging-spring-cloud-stream-bridge-f01", "file": "runtime-reachability-and-composition/reference/reference-messaging-spring-cloud-stream-bridge-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [] }, { "title": "등록을 받는 컴포넌트는 해제도 제공한다", "slug": "messaging-spring-cloud-stream-bridge-f05", "file": "runtime-reachability-and-composition/reference/reference-messaging-spring-cloud-stream-bridge-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [] } ], "question": [ { "title": "선언된 핸들러 계약이 배선된 것과 다르다", "slug": "messaging-core-api-f01", "file": "runtime-reachability-and-composition/question/openquestion-messaging-core-api-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [] }, { "title": "12개 예외가 선언만 되어 있다", "slug": "messaging-core-api-f03", "file": "runtime-reachability-and-composition/question/openquestion-messaging-core-api-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [] }, { "title": "형제 어댑터 넷이 구현하는 SPI를 이 leaf만 구현하지 않는다", "slug": "messaging-kafka-share-experimental-f03", "file": "runtime-reachability-and-composition/question/openquestion-messaging-kafka-share-experimental-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "허용 의존 목록은 상한이므로 미사용을 잡지 않는다 — 그것을 잡으려면 별도 검사가 필요하다", "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "에러 메시지가 지시하는 설정은 그 설정을 읽는 코드와 함께 존재해야 한다", "구성 오류는 한 예외 타입과 안정 코드로 보고한다" ] }, { "title": "출하 컨텍스트가 발행은 하고 소비는 하지 못한다", "slug": "messaging-policy-f02", "file": "runtime-reachability-and-composition/question/openquestion-messaging-policy-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "구성 오류는 한 예외 타입과 안정 코드로 보고한다", "저장소 밖 문서를 절 번호로 인용하지 않는다", "부팅 경로의 알고리즘 복잡도는 문서화한다" ] }, { "title": "dual-write의 답이라고 선언한 진입점에 구현이 없다", "slug": "messaging-reliability-api-f03", "file": "runtime-reachability-and-composition/question/openquestion-messaging-reliability-api-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "계약만 담는 leaf도 계약의 거절 조건은 자기 레인에서 검증한다", "record의 `equals`를 좁히면 이유를 적는다", "호출 컨텍스트가 계약이면 그 컨텍스트를 검증할 수단을 함께 정한다" ] }, { "title": "빈 registry로 조립되면 모든 메시지가 거절된다", "slug": "messaging-schema-json-f03", "file": "runtime-reachability-and-composition/question/openquestion-messaging-schema-json-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "실패 코드는 운영자의 다음 행동이 갈리는 지점마다 나눈다" ] } ], "decision": [] } }, "schema-and-data-contracts": { "topic": "schema-and-data-contracts", "kinds": { "case": [ { "title": "예외가 들고 있는 능력이 transient 라 역직렬화 뒤 사라진다", "slug": "grpc-advanced-bootstrap-f05", "file": "schema-and-data-contracts/case/case-grpc-advanced-bootstrap-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-bootstrap-f05" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-bootstrap-f05.txt" ], "relations": [] }, { "title": "비교 픽스처에 비교 대상이 없다", "slug": "grpc-advanced-edition-f01", "file": "schema-and-data-contracts/case/case-grpc-advanced-edition-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-edition-f01", "grpc-advanced-edition-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-edition-f01.txt" ], "relations": [] }, { "title": "픽스처의 메서드 경로가 서비스 × 메서드 교차곱이다", "slug": "grpc-codegen-f03", "file": "schema-and-data-contracts/case/case-grpc-codegen-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-codegen-f03" ], "evidence": [ "../../../final/evidence/raw/grpc-codegen-f03.txt" ], "relations": [] }, { "title": "직렬화 가능하다고 선언한 예외가 자기 내용을 직렬화하지 않는다", "slug": "grpc-core-api-f06", "file": "schema-and-data-contracts/case/case-grpc-core-api-f06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-core-api-f06" ], "evidence": [ "../../../final/evidence/raw/grpc-core-api-f06.txt" ], "relations": [] }, { "title": "직렬 스트림 기록기의 가장 오래된 것 버리기가 잘못된 메시지의 바이트를 뺀다", "slug": "grpc-policy-f03", "file": "schema-and-data-contracts/case/case-grpc-policy-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-policy-f03", "grpc-policy-f03-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-policy-f03.txt" ], "relations": [] }, { "title": "reserved 2 to 5; 범위가 개별 숫자로만 수집되어 RESERVED_HISTORY 오탐이 된다", "slug": "grpc-proto-contract-f01", "file": "schema-and-data-contracts/case/case-grpc-proto-contract-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-proto-contract-f01" ], "evidence": [ "../../../final/evidence/raw/grpc-proto-contract-f01.txt" ], "relations": [] }, { "title": "커밋 스키마 게이트가 파일 목록을 하드코딩한다", "slug": "grpc-proto-contract-f03", "file": "schema-and-data-contracts/case/case-grpc-proto-contract-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-proto-contract-f03" ], "evidence": [ "../../../final/evidence/raw/grpc-proto-contract-f03.txt" ], "relations": [] }, { "title": "열거형 안의 reserved 는 수집되지 않는다", "slug": "grpc-proto-contract-f04", "file": "schema-and-data-contracts/case/case-grpc-proto-contract-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-proto-contract-f04" ], "evidence": [ "../../../final/evidence/raw/grpc-proto-contract-f04.txt" ], "relations": [] }, { "title": "감사 sink 인터페이스가 사용처에서 다시 선언된다", "slug": "messaging-observability-f04", "file": "schema-and-data-contracts/case/case-messaging-observability-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-observability-f04" ], "evidence": [ "../../../final/evidence/raw/messaging-observability-f04.txt" ], "relations": [ "타입이 문서화한 불변식은 타입이 강제한다" ] }, { "title": "선언된 content type과 실제 인코딩이 조용히 갈라질 수 있다", "slug": "messaging-runtime-core-f03", "file": "schema-and-data-contracts/case/case-messaging-runtime-core-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-runtime-core-f03" ], "evidence": [ "../../../final/evidence/raw/messaging-runtime-core-f03.txt" ], "relations": [ "만들어 두고 흘리지 않는 진단값은 진단이 아니다", "증가한다고 문서화한 값이 리터럴이면 그 사실을 적는다", "안정 코드는 운영자의 행동이 갈리는 지점마다 나눈다", "`CompletionStage`를 반환하는 메서드는 동기적으로 던지지 않는다" ] }, { "title": "진화 판단이 두 곳에 있고 형태가 반대다", "slug": "messaging-schema-avro-f02", "file": "schema-and-data-contracts/case/case-messaging-schema-avro-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-avro-f02", "messaging-schema-avro-f02-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-avro-f02.txt" ], "relations": [ "모드 enum을 분기 조건으로 쓰면 각 분기에 테스트를 둔다", "컬렉션 순서가 계약이면 양쪽에서 같은 방향으로 적는다", "안정 코드는 판단 단위로 정하고 구현 단위로 정하지 않는다" ] }, { "title": "포맷 중립 payload 정책이, 자기 상수를 두고 JSON codec의 상수를 참조한다", "slug": "messaging-schema-json-f01", "file": "schema-and-data-contracts/case/case-messaging-schema-json-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-json-f01", "messaging-schema-json-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-json-f01.txt" ], "relations": [ "실패 코드는 운영자의 다음 행동이 갈리는 지점마다 나눈다" ] }, { "title": "registry 조회 로직이 세 codec에 복제돼 있다", "slug": "messaging-schema-protobuf-f04", "file": "schema-and-data-contracts/case/case-messaging-schema-protobuf-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-protobuf-f04" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-protobuf-f04.txt" ], "relations": [ "검증되지 않는 스키마 파일은 문서임을 파일 안에 적는다", "신뢰할 수 없는 입력 쪽 경계를 먼저 테스트한다" ] } ], "concept": [], "reference": [ { "title": "컬렉션 순서가 계약이면 양쪽에서 같은 방향으로 적는다", "slug": "messaging-schema-avro-f03", "file": "schema-and-data-contracts/reference/reference-messaging-schema-avro-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "진화 판단이 두 곳에 있고 형태가 반대다", "CI에서 돈다고 선언한 게이트를 부르는 CI가 없다" ] }, { "title": "안정 코드는 판단 단위로 정하고 구현 단위로 정하지 않는다", "slug": "messaging-schema-avro-f05", "file": "schema-and-data-contracts/reference/reference-messaging-schema-avro-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "진화 판단이 두 곳에 있고 형태가 반대다", "CI에서 돈다고 선언한 게이트를 부르는 CI가 없다" ] } ], "question": [ { "title": "dataschema가 채워질 경로가 없다", "slug": "messaging-cloudevents-f04", "file": "schema-and-data-contracts/question/openquestion-messaging-cloudevents-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "왕복이라 부르는 테스트는 무엇을 보존하지 않는지도 적는다", "문서가 범위를 제한하면 그 제한을 누가 강제하는지 같이 적는다" ] }, { "title": "protobuf-java 버전이 저장소에 셋이고 전역 정책이 없다", "slug": "messaging-schema-protobuf-f03", "file": "schema-and-data-contracts/question/openquestion-messaging-schema-protobuf-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "검증되지 않는 스키마 파일은 문서임을 파일 안에 적는다", "신뢰할 수 없는 입력 쪽 경계를 먼저 테스트한다" ] } ], "decision": [] } }, "schema-and-wire-models": { "topic": "schema-and-wire-models", "kinds": { "case": [], "concept": [ { "title": "스키마 해시의 생산자도 소비자도 빈이 없다", "slug": "adapter-inbound-graphql-c02", "file": "schema-and-wire-models/concept/concept-adapter-inbound-graphql-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-graphql-c02" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-graphql-c02.txt" ], "relations": [] }, { "title": "파싱·검증 실패의 와이어 형식은 이 플랫폼이 정하지 않는다", "slug": "adapter-inbound-graphql-c07", "file": "schema-and-wire-models/concept/concept-adapter-inbound-graphql-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-graphql-c07" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-graphql-c07.txt" ], "relations": [] }, { "title": "키를 요구하는 코드는 둘이고 서명하는 코드는 없다", "slug": "adapter-inbound-graphql-c11", "file": "schema-and-wire-models/concept/concept-adapter-inbound-graphql-c11.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-graphql-c11" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-graphql-c11.txt" ], "relations": [] }, { "title": "페이지네이션 어휘가 한 번도 컨트롤러에 붙어 본 적이 없다", "slug": "adapter-inbound-web-c08", "file": "schema-and-wire-models/concept/concept-adapter-inbound-web-c08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c08" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c08.txt" ], "relations": [] }, { "title": "어느 쪽이 정본인지 코드로 판정할 수 없다", "slug": "adapter-inbound-web-c10", "file": "schema-and-wire-models/concept/concept-adapter-inbound-web-c10.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c10" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c10.txt" ], "relations": [] }, { "title": "기여자가 커스터마이저에 도달하지 않아 스키마가 문서에 없다", "slug": "adapter-inbound-web-c11", "file": "schema-and-wire-models/concept/concept-adapter-inbound-web-c11.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c11" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c11.txt" ], "relations": [] }, { "title": "오류 형식이 세 벌이다", "slug": "adapter-inbound-websocket-c03", "file": "schema-and-wire-models/concept/concept-adapter-inbound-websocket-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-websocket-c03" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-websocket-c03.txt" ], "relations": [] }, { "title": "키를 요구하는 검증기가 없어서 잘못된 확인 신호도 없다", "slug": "adapter-inbound-websocket-c04", "file": "schema-and-wire-models/concept/concept-adapter-inbound-websocket-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-websocket-c04" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-websocket-c04.txt" ], "relations": [] }, { "title": "guard 아래에서는 명령 이름으로 위험을 다시 유도할 수 없다", "slug": "adapter-outbound-cache-redis-c07", "file": "schema-and-wire-models/concept/concept-adapter-outbound-cache-redis-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-cache-redis-c07" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-cache-redis-c07.txt" ], "relations": [] }, { "title": "R4인데 BLOCKED이 아닌 정책 파일은 읽히지 않는다", "slug": "adapter-outbound-cache-redis-c11", "file": "schema-and-wire-models/concept/concept-adapter-outbound-cache-redis-c11.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-cache-redis-c11" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-cache-redis-c11.txt" ], "relations": [] }, { "title": "파싱은 되지만 우리가 쓰지 않았을 형태를 전부 거부한다", "slug": "adapter-outbound-fileserver-c02", "file": "schema-and-wire-models/concept/concept-adapter-outbound-fileserver-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-fileserver-c02" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-fileserver-c02.txt" ], "relations": [] }, { "title": "검사할 수 없는 성분을 가진 본문은 재생 가능으로 인증되지 않는다", "slug": "adapter-outbound-httpclient-c03", "file": "schema-and-wire-models/concept/concept-adapter-outbound-httpclient-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-httpclient-c03" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-httpclient-c03.txt" ], "relations": [] }, { "title": "와이어 바이트와 디코드 바이트를 따로 세고, 읽는 도중에 상한을 건다", "slug": "adapter-outbound-httpclient-c06", "file": "schema-and-wire-models/concept/concept-adapter-outbound-httpclient-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-httpclient-c06", "adapter-outbound-httpclient-c06-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-httpclient-c06.txt" ], "relations": [] }, { "title": "구성이 끝난 뒤에는 스키마를 가져올 방법이 남아 있지 않다", "slug": "adapter-outbound-messaging-c01", "file": "schema-and-wire-models/concept/concept-adapter-outbound-messaging-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-messaging-c01", "adapter-outbound-messaging-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-messaging-c01.txt" ], "relations": [] }, { "title": "봉투를 쓰는 경로에 JSON 파서도 생성기도 없다", "slug": "adapter-outbound-messaging-c02", "file": "schema-and-wire-models/concept/concept-adapter-outbound-messaging-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-messaging-c02" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-messaging-c02.txt" ], "relations": [] }, { "title": "새 레코드를 추가하면 컴파일이 codec 갱신을 강제한다", "slug": "adapter-outbound-objectstorage-c04", "file": "schema-and-wire-models/concept/concept-adapter-outbound-objectstorage-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-objectstorage-c04" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-objectstorage-c04.txt" ], "relations": [] }, { "title": "다른 route의 identity로 만든 키는 파싱 단계에서 거부된다", "slug": "adapter-outbound-objectstorage-c06", "file": "schema-and-wire-models/concept/concept-adapter-outbound-objectstorage-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-objectstorage-c06" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-objectstorage-c06.txt" ], "relations": [] }, { "title": "자기가 만든 토큰을 자기가 거부하는 경계값", "slug": "adapter-outbound-persistence-jpa-c05", "file": "schema-and-wire-models/concept/concept-adapter-outbound-persistence-jpa-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c05", "adapter-outbound-persistence-jpa-c05-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c05.txt" ], "relations": [] }, { "title": "문서 상수와 같은 상수를 assert하는 test를 피한 이유", "slug": "adapter-outbound-persistence-jpa-c25", "file": "schema-and-wire-models/concept/concept-adapter-outbound-persistence-jpa-c25.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c25", "adapter-outbound-persistence-jpa-c25-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c25.txt" ], "relations": [] }, { "title": "V3와 V4는 registry revision을 올리지 않는다", "slug": "adapter-outbound-persistence-jpa-c45", "file": "schema-and-wire-models/concept/concept-adapter-outbound-persistence-jpa-c45.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c45" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c45.txt" ], "relations": [] }, { "title": "평문처럼 보이는 envelope를 DB constraint가 거부한다", "slug": "adapter-outbound-persistence-jpa-c49", "file": "schema-and-wire-models/concept/concept-adapter-outbound-persistence-jpa-c49.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c49" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c49.txt" ], "relations": [] }, { "title": "선언된 축이 컴파일되지 않으면 startup에서 거부된다", "slug": "adapter-outbound-persistence-mongo-c02", "file": "schema-and-wire-models/concept/concept-adapter-outbound-persistence-mongo-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-mongo-c02" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-mongo-c02.txt" ], "relations": [] }, { "title": "배선된 enforcer를 부르는 코드가 미배선이다", "slug": "adapter-outbound-persistence-mongo-c05", "file": "schema-and-wire-models/concept/concept-adapter-outbound-persistence-mongo-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-mongo-c05" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-mongo-c05.txt" ], "relations": [] }, { "title": "@Configuration을 게이팅하면 게이트를 공급하는 것을 게이팅한다", "slug": "adapter-outbound-persistence-mongo-c09", "file": "schema-and-wire-models/concept/concept-adapter-outbound-persistence-mongo-c09.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-mongo-c09" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-mongo-c09.txt" ], "relations": [] }, { "title": "임의 Object 대신 sealed 변수 대수를 쓴 이유", "slug": "application-core-c10", "file": "schema-and-wire-models/concept/concept-application-core-c10.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "application-core-c10", "application-core-c10-diagram" ], "evidence": [ "../../../final/evidence/raw/application-core-c10.txt" ], "relations": [ "legacy storage/notification compatibility surface의 제거 조건 추적" ] }, { "title": "재개 토큰 — 서명하고, 구분자를 봉인한다", "slug": "grpc-policy-c01", "file": "schema-and-wire-models/concept/concept-grpc-policy-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-policy-c01" ], "evidence": [ "../../../final/evidence/raw/grpc-policy-c01.txt" ], "relations": [] }, { "title": "서명 대상 객체가 존재한다는 것이 4-eyes 통과를 뜻한다", "slug": "messaging-admin-api-c03", "file": "schema-and-wire-models/concept/concept-messaging-admin-api-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-api-c03", "messaging-admin-api-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-api-c03.txt" ], "relations": [] }, { "title": "싣고 쓰지 않는다", "slug": "messaging-cloudevents-c01", "file": "schema-and-wire-models/concept/concept-messaging-cloudevents-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-cloudevents-c01", "messaging-cloudevents-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-cloudevents-c01.txt" ], "relations": [ "왕복이라 부르는 테스트는 무엇을 보존하지 않는지도 적는다", "문서가 범위를 제한하면 그 제한을 누가 강제하는지 같이 적는다" ] }, { "title": "런타임 classpath에는 오르고 어느 @Bean도 만들지 않는다", "slug": "messaging-cloudevents-c02", "file": "schema-and-wire-models/concept/concept-messaging-cloudevents-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-cloudevents-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-cloudevents-c02.txt" ], "relations": [ "왕복이라 부르는 테스트는 무엇을 보존하지 않는지도 적는다", "문서가 범위를 제한하면 그 제한을 누가 강제하는지 같이 적는다" ] }, { "title": "확장 이름이 봉투 필드명과 다른 이유", "slug": "messaging-cloudevents-c03", "file": "schema-and-wire-models/concept/concept-messaging-cloudevents-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-cloudevents-c03" ], "evidence": [ "../../../final/evidence/raw/messaging-cloudevents-c03.txt" ], "relations": [ "왕복이라 부르는 테스트는 무엇을 보존하지 않는지도 적는다", "문서가 범위를 제한하면 그 제한을 누가 강제하는지 같이 적는다" ] }, { "title": "두 방향 모두 시각이 없으면 거절한다", "slug": "messaging-cloudevents-c05", "file": "schema-and-wire-models/concept/concept-messaging-cloudevents-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-cloudevents-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-cloudevents-c05.txt" ], "relations": [ "왕복이라 부르는 테스트는 무엇을 보존하지 않는지도 적는다", "문서가 범위를 제한하면 그 제한을 누가 강제하는지 같이 적는다" ] }, { "title": "외부 데이터가 들어오는 유일한 진입점의 실패가 분류되지 않는다", "slug": "messaging-cloudevents-c06", "file": "schema-and-wire-models/concept/concept-messaging-cloudevents-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-cloudevents-c06" ], "evidence": [ "../../../final/evidence/raw/messaging-cloudevents-c06.txt" ], "relations": [ "왕복이라 부르는 테스트는 무엇을 보존하지 않는지도 적는다", "문서가 범위를 제한하면 그 제한을 누가 강제하는지 같이 적는다" ] }, { "title": "의존이 하나도 없고 나머지 24개 전부가 이것을 의존한다", "slug": "messaging-core-api-c02", "file": "schema-and-wire-models/concept/concept-messaging-core-api-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-core-api-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-core-api-c02.txt" ], "relations": [] }, { "title": "코드가 실제로 도는 네 지점", "slug": "messaging-core-api-c05", "file": "schema-and-wire-models/concept/concept-messaging-core-api-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-core-api-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-core-api-c05.txt" ], "relations": [] }, { "title": "Spring 주석 0개인 leaf가 배포 아티팩트에 실린다", "slug": "messaging-schema-api-c02", "file": "schema-and-wire-models/concept/concept-messaging-schema-api-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-api-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-api-c02.txt" ], "relations": [ "port 계약은 동시성 요구를 적는다", "도달성 판정은 단어가 아니라 import로 확인한다" ] }, { "title": "아무것도 실패하지 않고 잘못된 성공이 나온다", "slug": "messaging-schema-api-c03", "file": "schema-and-wire-models/concept/concept-messaging-schema-api-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-api-c03", "messaging-schema-api-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-api-c03.txt" ], "relations": [ "port 계약은 동시성 요구를 적는다", "도달성 판정은 단어가 아니라 import로 확인한다" ] }, { "title": "진화 검사 경로는 이 저장소에서 실행되지 않는다", "slug": "messaging-schema-api-c04", "file": "schema-and-wire-models/concept/concept-messaging-schema-api-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-api-c04" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-api-c04.txt" ], "relations": [ "port 계약은 동시성 요구를 적는다", "도달성 판정은 단어가 아니라 import로 확인한다" ] }, { "title": "형제 leaf가 implementation이고 이쪽이 api인 것이 규칙의 증거다", "slug": "messaging-schema-avro-c01", "file": "schema-and-wire-models/concept/concept-messaging-schema-avro-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-avro-c01" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-avro-c01.txt" ], "relations": [ "모드 enum을 분기 조건으로 쓰면 각 분기에 테스트를 둔다", "컬렉션 순서가 계약이면 양쪽에서 같은 방향으로 적는다", "안정 코드는 판단 단위로 정하고 구현 단위로 정하지 않는다" ] }, { "title": "소비자 없음과 membership 없음이 일치한다", "slug": "messaging-schema-avro-c02", "file": "schema-and-wire-models/concept/concept-messaging-schema-avro-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-avro-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-avro-c02.txt" ], "relations": [ "모드 enum을 분기 조건으로 쓰면 각 분기에 테스트를 둔다", "컬렉션 순서가 계약이면 양쪽에서 같은 방향으로 적는다", "안정 코드는 판단 단위로 정하고 구현 단위로 정하지 않는다" ] }, { "title": "틀린 스키마로 디코딩해도 실패하지 않는다", "slug": "messaging-schema-avro-c03", "file": "schema-and-wire-models/concept/concept-messaging-schema-avro-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-avro-c03", "messaging-schema-avro-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-avro-c03.txt" ], "relations": [ "모드 enum을 분기 조건으로 쓰면 각 분기에 테스트를 둔다", "컬렉션 순서가 계약이면 양쪽에서 같은 방향으로 적는다", "안정 코드는 판단 단위로 정하고 구현 단위로 정하지 않는다" ] }, { "title": "쓰기 스키마와 읽기 스키마를 둘 다 넘기는 경로", "slug": "messaging-schema-avro-c04", "file": "schema-and-wire-models/concept/concept-messaging-schema-avro-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-avro-c04" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-avro-c04.txt" ], "relations": [ "모드 enum을 분기 조건으로 쓰면 각 분기에 테스트를 둔다", "컬렉션 순서가 계약이면 양쪽에서 같은 방향으로 적는다", "안정 코드는 판단 단위로 정하고 구현 단위로 정하지 않는다" ] }, { "title": "크기 실패가 인코딩 실패로 접히지 않게 하는 재던지기", "slug": "messaging-schema-avro-c05", "file": "schema-and-wire-models/concept/concept-messaging-schema-avro-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-avro-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-avro-c05.txt" ], "relations": [ "모드 enum을 분기 조건으로 쓰면 각 분기에 테스트를 둔다", "컬렉션 순서가 계약이면 양쪽에서 같은 방향으로 적는다", "안정 코드는 판단 단위로 정하고 구현 단위로 정하지 않는다" ] }, { "title": "출하 구성의 codec registry에는 JSON 하나만 들어간다", "slug": "messaging-schema-json-c02", "file": "schema-and-wire-models/concept/concept-messaging-schema-json-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-json-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-json-c02.txt" ], "relations": [ "실패 코드는 운영자의 다음 행동이 갈리는 지점마다 나눈다" ] }, { "title": "인코딩 상한과 파서 상한이 하나의 값에서 나온다", "slug": "messaging-schema-json-c03", "file": "schema-and-wire-models/concept/concept-messaging-schema-json-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-json-c03" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-json-c03.txt" ], "relations": [ "실패 코드는 운영자의 다음 행동이 갈리는 지점마다 나눈다" ] }, { "title": "디코딩은 등록 클래스와 정확히 같은지를 본다", "slug": "messaging-schema-json-c04", "file": "schema-and-wire-models/concept/concept-messaging-schema-json-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-json-c04" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-json-c04.txt" ], "relations": [ "실패 코드는 운영자의 다음 행동이 갈리는 지점마다 나눈다" ] }, { "title": "소비자가 계약을 등록하려면 vendor 타입을 이름 불러야 한다", "slug": "messaging-schema-protobuf-c01", "file": "schema-and-wire-models/concept/concept-messaging-schema-protobuf-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-protobuf-c01" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-protobuf-c01.txt" ], "relations": [ "검증되지 않는 스키마 파일은 문서임을 파일 안에 적는다", "신뢰할 수 없는 입력 쪽 경계를 먼저 테스트한다" ] }, { "title": "계약 등록 실패가 시작 시점에 난다", "slug": "messaging-schema-protobuf-c04", "file": "schema-and-wire-models/concept/concept-messaging-schema-protobuf-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-protobuf-c04" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-protobuf-c04.txt" ], "relations": [ "검증되지 않는 스키마 파일은 문서임을 파일 안에 적는다", "신뢰할 수 없는 입력 쪽 경계를 먼저 테스트한다" ] }, { "title": "세 codec이 같은 문제를 라이브러리에 맞춰 다르게 푼다", "slug": "messaging-schema-protobuf-c05", "file": "schema-and-wire-models/concept/concept-messaging-schema-protobuf-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-protobuf-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-protobuf-c05.txt" ], "relations": [ "검증되지 않는 스키마 파일은 문서임을 파일 안에 적는다", "신뢰할 수 없는 입력 쪽 경계를 먼저 테스트한다" ] }, { "title": "실패의 종류가 바뀌면 운영자가 읽을 정보가 사라진다", "slug": "messaging-schema-protobuf-c07", "file": "schema-and-wire-models/concept/concept-messaging-schema-protobuf-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-protobuf-c07" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-protobuf-c07.txt" ], "relations": [ "검증되지 않는 스키마 파일은 문서임을 파일 안에 적는다", "신뢰할 수 없는 입력 쪽 경계를 먼저 테스트한다" ] }, { "title": "등급이 증거를 만들지 않고 증거가 등급을 만든다", "slug": "messaging-testkit-c03", "file": "schema-and-wire-models/concept/concept-messaging-testkit-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-testkit-c03" ], "evidence": [ "../../../final/evidence/raw/messaging-testkit-c03.txt" ], "relations": [] }, { "title": "digest는 고정하지만 validator 상호운용은 증명하지 않는다", "slug": "shared-contract-c04", "file": "schema-and-wire-models/concept/concept-shared-contract-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "shared-contract-c04" ], "evidence": [ "../../../final/evidence/raw/shared-contract-c04.txt" ], "relations": [] } ], "reference": [], "question": [], "decision": [] } }, "schema-ownership-and-capability-streams": { "topic": "schema-ownership-and-capability-streams", "kinds": { "case": [ { "title": "Flyway location customizer가 운영자가 바인딩한 값을 덮어썼다", "slug": "a-customizer-that-discarded-the-bound-property", "file": "schema-ownership-and-capability-streams/case/case-a-customizer-that-discarded-the-bound-property.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-customizer-that-discarded-the-bound-property" ], "evidence": [ "../../../final/evidence/raw/a-customizer-that-discarded-the-bound-property.txt" ], "relations": [ "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "독립 Flyway 스트림과 baseline version 0" ] }, { "title": "char(64)와 varchar(64) 불일치를 H2가 가리고 있었다", "slug": "h2-hid-a-column-type-mismatch", "file": "schema-ownership-and-capability-streams/case/case-h2-hid-a-column-type-mismatch.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "h2-hid-a-column-type-mismatch" ], "evidence": [ "../../../final/evidence/raw/h2-hid-a-column-type-mismatch.txt" ], "relations": [ "로컬이 다른 DB면 로컬 테스트는 다른 시스템에 대한 진술이다", "connection-timeout이 5s 문자열로 출하되어 prod와 dev 배포가 전부 시작에 실패했다" ] }, { "title": "messaging 마이그레이션 두 leaf가 같은 디렉터리에서 V2를 둘 만들었다", "slug": "messaging-migrations-collide-at-v2", "file": "schema-ownership-and-capability-streams/case/case-messaging-migrations-collide-at-v2.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-migrations-collide-at-v2" ], "evidence": [ "../../../final/evidence/raw/messaging-migrations-collide-at-v2.txt" ], "relations": [ "마이그레이션 스트림은 자기 history 테이블을 갖는다", "두 트리가 다 V1부터 번호를 매겨 공유 history가 하나를 건너뛸 수 있었다", "lease가 만료 시각만 기록하고 소유자를 기록하지 않아 terminal state가 되돌려졌다" ] }, { "title": "레지스트리 컬럼이 38자 경로에서 짧아 \"더 짧은 경로를 적는\" 우회를 유혹했다", "slug": "registry-column-too-short-for-its-own-path", "file": "schema-ownership-and-capability-streams/case/case-registry-column-too-short-for-its-own-path.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "registry-column-too-short-for-its-own-path" ], "evidence": [ "../../../final/evidence/raw/registry-column-too-short-for-its-own-path.txt" ], "relations": [ "독립 Flyway 스트림과 baseline version 0", "두 트리가 다 V1부터 번호를 매겨 공유 history가 하나를 건너뛸 수 있었다" ] }, { "title": "두 트리가 다 V1부터 번호를 매겨 공유 history가 하나를 건너뛸 수 있었다", "slug": "two-trees-both-numbered-from-v1", "file": "schema-ownership-and-capability-streams/case/case-two-trees-both-numbered-from-v1.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "two-trees-both-numbered-from-v1" ], "evidence": [ "../../../final/evidence/raw/two-trees-both-numbered-from-v1.txt" ], "relations": [ "독립 Flyway 스트림과 baseline version 0", "마이그레이션 스트림은 자기 history 테이블을 갖는다", "messaging 마이그레이션 두 leaf가 같은 디렉터리에서 V2를 둘 만들었다" ] } ], "concept": [ { "title": "독립 Flyway 스트림과 baseline version 0", "slug": "independent-flyway-streams", "file": "schema-ownership-and-capability-streams/concept/concept-independent-flyway-streams.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "independent-flyway-streams" ], "evidence": [ "../../../final/evidence/raw/independent-flyway-streams.txt" ], "relations": [ "두 트리가 다 V1부터 번호를 매겨 공유 history가 하나를 건너뛸 수 있었다", "마이그레이션 스트림은 자기 history 테이블을 갖는다", "capability_schema_registry — 스키마 적용과 사용 승인의 분리" ] } ], "reference": [ { "title": "적용된 마이그레이션의 checksum은 그것을 돌린 모든 배포에 대한 약속이다", "slug": "an-applied-checksum-is-a-promise", "file": "schema-ownership-and-capability-streams/reference/reference-an-applied-checksum-is-a-promise.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "char(64)와 varchar(64) 불일치를 H2가 가리고 있었다", "레지스트리 컬럼이 38자 경로에서 짧아 더 짧은 경로를 적는 우회를 유혹했다", "Repair는 모드가 아니라 운영자가 호출하는 작업이다" ] }, { "title": "마이그레이션 스트림은 자기 history 테이블을 갖는다", "slug": "each-stream-owns-its-history-table", "file": "schema-ownership-and-capability-streams/reference/reference-each-stream-owns-its-history-table.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "독립 Flyway 스트림과 baseline version 0", "두 트리가 다 V1부터 번호를 매겨 공유 history가 하나를 건너뛸 수 있었다", "messaging 마이그레이션 두 leaf가 같은 디렉터리에서 V2를 둘 만들었다" ] }, { "title": "로컬이 다른 DB면 로컬 테스트는 다른 시스템에 대한 진술이다", "slug": "local-with-a-different-db-is-a-different-system", "file": "schema-ownership-and-capability-streams/reference/reference-local-with-a-different-db-is-a-different-system.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "char(64)와 varchar(64) 불일치를 H2가 가리고 있었다", "connection-timeout이 5s 문자열로 출하되어 prod와 dev 배포가 전부 시작에 실패했다", "컨테이너가 필요한 특수 레인의 실제 결과를 실행으로 확인하지 않았다" ] } ], "question": [], "decision": [ { "title": "Flyway가 스키마를 소유하고 런타임 롤은 DDL 권한을 갖지 않는다", "slug": "flyway-owns-the-schema", "file": "schema-ownership-and-capability-streams/decision/decision-flyway-owns-the-schema.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "char(64)와 varchar(64) 불일치를 H2가 가리고 있었다", "적용된 마이그레이션의 checksum은 그것을 돌린 모든 배포에 대한 약속이다", "독립 Flyway 스트림과 baseline version 0" ] }, { "title": "Repair는 모드가 아니라 운영자가 호출하는 작업이다", "slug": "repair-is-not-a-mode", "file": "schema-ownership-and-capability-streams/decision/decision-repair-is-not-a-mode.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "적용된 마이그레이션의 checksum은 그것을 돌린 모든 배포에 대한 약속이다", "Flyway가 스키마를 소유하고 런타임 롤은 DDL 권한을 갖지 않는다" ] } ] } }, "security-and-trust-boundaries": { "topic": "security-and-trust-boundaries", "kinds": { "case": [ { "title": "프로파일이 선언한 여섯 값이 드라이버에 하나도 도달하지 않는다", "slug": "a06-f020-tls-stable", "file": "security-and-trust-boundaries/case/case-a06-f020-tls-stable.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a06-f020-tls-stable", "a06-f020-tls-stable-probe" ], "evidence": [ "../../../final/evidence/raw/a06-f020-tls-stable.txt", "../../../final/evidence/raw/a06-f020-tls-stable-probe.txt" ], "relations": [ "검증기가 운영에 TLS를 요구하고, 실제로 조립되는 생산자에는 그 설정이 없다", "@Bean이 있다는 것은 조립 증거가 아니다", "조립 결함을 판정하려면 조립하는 쪽을 먼저 읽어야 한다" ] } ], "concept": [ { "title": "off 계약의 두 절반과 리터럴 404를 피한 단언", "slug": "adapter-inbound-graphql-c01", "file": "security-and-trust-boundaries/concept/concept-adapter-inbound-graphql-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-graphql-c01" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-graphql-c01.txt" ], "relations": [] }, { "title": "security 패키지가 자기 안에서만 서로를 부른다", "slug": "adapter-inbound-web-c03", "file": "security-and-trust-boundaries/concept/concept-adapter-inbound-web-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c03", "adapter-inbound-web-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c03.txt" ], "relations": [] }, { "title": "publicPaths가 먼저 등록되어 제한 경로 규칙을 덮는다", "slug": "adapter-inbound-web-c04", "file": "security-and-trust-boundaries/concept/concept-adapter-inbound-web-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c04", "adapter-inbound-web-c04-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c04.txt" ], "relations": [] }, { "title": "지문이 길이 프레이밍 없이 구분자로만 만들어진다", "slug": "adapter-inbound-web-c07", "file": "security-and-trust-boundaries/concept/concept-adapter-inbound-web-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c07" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c07.txt" ], "relations": [] }, { "title": "절대 URI를 정화하지 않고 거부한다", "slug": "adapter-outbound-httpclient-c07", "file": "security-and-trust-boundaries/concept/concept-adapter-outbound-httpclient-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-httpclient-c07" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-httpclient-c07.txt" ], "relations": [] }, { "title": "TLS 실패가 CONNECT로 분류된 원인은 픽스처의 듀얼스택 호스트명이다", "slug": "adapter-outbound-httpclient-c09", "file": "security-and-trust-boundaries/concept/concept-adapter-outbound-httpclient-c09.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-httpclient-c09" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-httpclient-c09.txt" ], "relations": [] }, { "title": "unhealthy 조건 넷에 DRAINING이 없다", "slug": "adapter-outbound-notification-c04", "file": "security-and-trust-boundaries/concept/concept-adapter-outbound-notification-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-notification-c04" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-notification-c04.txt" ], "relations": [] }, { "title": "ObjectReference가 보장하는 route 구획", "slug": "adapter-outbound-objectstorage-c03", "file": "security-and-trust-boundaries/concept/concept-adapter-outbound-objectstorage-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-objectstorage-c03" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-objectstorage-c03.txt" ], "relations": [] }, { "title": "가드의 존재가 곧 테넌트 격리 보장은 아니다", "slug": "adapter-outbound-persistence-jpa-c53", "file": "security-and-trust-boundaries/concept/concept-adapter-outbound-persistence-jpa-c53.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c53" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c53.txt" ], "relations": [] }, { "title": "로그 마스킹은 PII 차단 보장을 복구하지 않는다", "slug": "adapter-outbound-support-c03", "file": "security-and-trust-boundaries/concept/concept-adapter-outbound-support-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-support-c03" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-support-c03.txt" ], "relations": [] }, { "title": "outbound 어댑터끼리는 support를 통해서만 공유한다", "slug": "adapter-outbound-support-c05", "file": "security-and-trust-boundaries/concept/concept-adapter-outbound-support-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-support-c05" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-support-c05.txt" ], "relations": [] }, { "title": "레지스트리 계약 테스트가 실제 파일을 읽어 대조한다", "slug": "app-bootstrap-c05", "file": "security-and-trust-boundaries/concept/concept-app-bootstrap-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "app-bootstrap-c05" ], "evidence": [ "../../../final/evidence/raw/app-bootstrap-c05.txt" ], "relations": [] }, { "title": "권한 판정과 객체 접근 판정을 분리한다", "slug": "application-core-c02", "file": "security-and-trust-boundaries/concept/concept-application-core-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "application-core-c02", "application-core-c02-diagram" ], "evidence": [ "../../../final/evidence/raw/application-core-c02.txt" ], "relations": [ "legacy storage/notification compatibility surface의 제거 조건 추적" ] }, { "title": "승격 게이트는 능력마다 따로 기록된 증거를 본다", "slug": "grpc-advanced-bootstrap-c03", "file": "security-and-trust-boundaries/concept/concept-grpc-advanced-bootstrap-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-bootstrap-c03" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-bootstrap-c03.txt" ], "relations": [] }, { "title": "Channelz는 유용해서 위험한 표면이다", "slug": "grpc-advanced-diagnostics-c01", "file": "security-and-trust-boundaries/concept/concept-grpc-advanced-diagnostics-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-diagnostics-c01", "grpc-advanced-diagnostics-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-diagnostics-c01.txt" ], "relations": [] }, { "title": "논리 RPC와 물리 시도와 스트림 수명주기를 구별한다", "slug": "grpc-observability-c01", "file": "security-and-trust-boundaries/concept/concept-grpc-observability-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-observability-c01", "grpc-observability-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-observability-c01.txt" ], "relations": [] }, { "title": "Advanced 의존 금지를 세 겹으로 강제한다", "slug": "grpc-spring-boot-starter-c01", "file": "security-and-trust-boundaries/concept/concept-grpc-spring-boot-starter-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-spring-boot-starter-c01", "grpc-spring-boot-starter-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-spring-boot-starter-c01.txt" ], "relations": [] }, { "title": "부팅된 애플리케이션에서 살아나는 타입은 둘뿐이다", "slug": "messaging-admin-api-c02", "file": "security-and-trust-boundaries/concept/concept-messaging-admin-api-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-api-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-api-c02.txt" ], "relations": [] }, { "title": "인가 실패와 프로그래밍 오류를 예외 타입으로 가른다", "slug": "messaging-admin-api-c05", "file": "security-and-trust-boundaries/concept/concept-messaging-admin-api-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-api-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-api-c05.txt" ], "relations": [] }, { "title": "자격증명은 연결 시도마다 해석된다", "slug": "messaging-rabbit-c02", "file": "security-and-trust-boundaries/concept/concept-messaging-rabbit-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-rabbit-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-rabbit-c02.txt" ], "relations": [] } ], "reference": [], "question": [], "decision": [] } }, "security-policy-enforcement": { "topic": "security-policy-enforcement", "kinds": { "case": [ { "title": "MongoRegexPolicy.forbidden()은 금지하지 않는다", "slug": "a06-f011-mongoregexpolicy-forbidden", "file": "security-policy-enforcement/case/case-a06-f011-mongoregexpolicy-forbidden.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a06-f011-mongoregexpolicy-forbidden-probe", "a06-f011-mongoregexpolicy-forbidden" ], "evidence": [ "../../../final/evidence/raw/a06-f011-mongoregexpolicy-forbidden-probe.txt", "../../../final/evidence/raw/a06-f011-mongoregexpolicy-forbidden.txt" ], "relations": [ "위험한 조합은 정책이 아니라 생성자가 거부하게 만든다", "sanitize가 아니라 reject가 기본이다", "접두사 시작 매칭은 시그니처에는 맞고 스니핑 패턴에는 맞지 않는다" ] }, { "title": "비밀 필드 검사가 스냅숏의 네 구획 중 하나에만 적용된다", "slug": "grpc-admin-f02", "file": "security-policy-enforcement/case/case-grpc-admin-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-admin-f02" ], "evidence": [ "../../../final/evidence/raw/grpc-admin-f02.txt" ], "relations": [] }, { "title": "마스킹이 IPv4 만 알고, 그 결과 \"마스킹되지 않은 주소\" 검사가 나머지 형태를 전부 통과시킨다", "slug": "grpc-advanced-diagnostics-f01", "file": "security-policy-enforcement/case/case-grpc-advanced-diagnostics-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-diagnostics-f01", "grpc-advanced-diagnostics-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-diagnostics-f01.txt" ], "relations": [] }, { "title": "금지 필드 검사가 키에만 적용되고 값에는 적용되지 않는다", "slug": "grpc-advanced-diagnostics-f02", "file": "security-policy-enforcement/case/case-grpc-advanced-diagnostics-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-diagnostics-f02" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-diagnostics-f02.txt" ], "relations": [] }, { "title": "정책의 자바독이 하지 않는 거부를 한다고 적고, 승격 승인이 두 곳에 따로 있다", "slug": "grpc-advanced-edition-f03", "file": "security-policy-enforcement/case/case-grpc-advanced-edition-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-edition-f03" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-edition-f03.txt" ], "relations": [] }, { "title": "RESOURCE_EXHAUSTED 매핑이 그 상태의 두 출처 중 하나만 가정한다", "slug": "grpc-core-api-f03", "file": "security-policy-enforcement/case/case-grpc-core-api-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-core-api-f03" ], "evidence": [ "../../../final/evidence/raw/grpc-core-api-f03.txt" ], "relations": [] }, { "title": "스트림 승인의 경계가 동시성 아래에서 새고, caller별 맵이 줄지 않는다", "slug": "grpc-policy-f01", "file": "security-policy-enforcement/case/case-grpc-policy-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-policy-f01", "grpc-policy-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-policy-f01.txt" ], "relations": [] }, { "title": "자격증명 회전이 비교 후 교체가 아니고, 배수 완료가 진행 중인 회전을 되돌릴 수 있다", "slug": "grpc-policy-f02", "file": "security-policy-enforcement/case/case-grpc-policy-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-policy-f02", "grpc-policy-f02-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-policy-f02.txt" ], "relations": [] }, { "title": "승인 제어기의 세 메서드가 원자적이지 않고, 큐 계수기를 되돌리는 경로가 없다", "slug": "grpc-server-f04", "file": "security-policy-enforcement/case/case-grpc-server-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-server-f04", "grpc-server-f04-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-server-f04.txt" ], "relations": [] }, { "title": "던져 버릴 비밀번호를 만들어 놓고 외부 프로세스의 명령줄에 싣는다", "slug": "grpc-testkit-f06", "file": "security-policy-enforcement/case/case-grpc-testkit-f06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-testkit-f06" ], "evidence": [ "../../../final/evidence/raw/grpc-testkit-f06.txt" ], "relations": [] }, { "title": "마스킹이 IPv4 만 알아서 검사가 나머지 주소 형태를 전부 통과시킨다", "slug": "ipv4-only-mask-passes-every-other-form", "file": "security-policy-enforcement/case/case-ipv4-only-mask-passes-every-other-form.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "ipv4-only-mask-passes-every-other-form" ], "evidence": [ "../../../final/evidence/raw/ipv4-only-mask-passes-every-other-form.txt" ], "relations": [ "위험한 조합은 정책이 아니라 생성자가 거부하게 만든다", "붉은 test를 제품 결함으로 잘못 읽었다", "문서끼리의 일치는 아무것도 증명하지 않는다" ] }, { "title": "계획 다이제스트가 승인 정규 형식과 다른 인코딩을 쓴다", "slug": "messaging-admin-api-f02", "file": "security-policy-enforcement/case/case-messaging-admin-api-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-api-f02" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-api-f02.txt" ], "relations": [] }, { "title": "VerifiedApproval 의 위조 방지가 package-private 에만 의존한다", "slug": "messaging-admin-api-f05", "file": "security-policy-enforcement/case/case-messaging-admin-api-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-api-f05" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-api-f05.txt" ], "relations": [] }, { "title": "같은 인가 실패 코드가 세 파일에 문자열 리터럴로 흩어져 있다", "slug": "messaging-admin-api-f07", "file": "security-policy-enforcement/case/case-messaging-admin-api-f07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-api-f07" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-api-f07.txt" ], "relations": [] }, { "title": "파괴적 작업의 승인만 위조 가능한 형태로 남아 있다", "slug": "messaging-admin-runtime-f01", "file": "security-policy-enforcement/case/case-messaging-admin-runtime-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-runtime-f01", "messaging-admin-runtime-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-runtime-f01.txt" ], "relations": [] }, { "title": "감사 싱크가 중복 선언되어 있고 레닥션 계약이 유실된다", "slug": "messaging-admin-runtime-f05", "file": "security-policy-enforcement/case/case-messaging-admin-runtime-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-runtime-f05" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-runtime-f05.txt" ], "relations": [] }, { "title": "격리 리플레이의 guard 우회가 dryRun 파라미터로 표현된다", "slug": "messaging-admin-runtime-f08", "file": "security-policy-enforcement/case/case-messaging-admin-runtime-f08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-runtime-f08" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-runtime-f08.txt" ], "relations": [] }, { "title": "자격증명 판정이 core-api보다 약하다", "slug": "messaging-observability-f05", "file": "security-policy-enforcement/case/case-messaging-observability-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-observability-f05" ], "evidence": [ "../../../final/evidence/raw/messaging-observability-f05.txt" ], "relations": [ "타입이 문서화한 불변식은 타입이 강제한다" ] }, { "title": "같은 TLS posture를 두 클래스가 다른 엄격도로 검사한다", "slug": "messaging-security-f01", "file": "security-policy-enforcement/case/case-messaging-security-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-security-f01", "messaging-security-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-security-f01.txt" ], "relations": [ "배선된 게이트는 자기 leaf 레인에서 검증한다", "같은 술어가 두 타입에 있으면 하나가 다른 하나를 부른다", "가변 필드로 상태 전이를 표현하면 가시성을 함께 정한다", "맵 갱신 함수 안에서 I/O를 하면 그 지연이 락 범위가 된다" ] }, { "title": "권한 거부가 AUTHORIZATION이 아니라 CONFIGURATION으로 기록된다", "slug": "messaging-security-f02", "file": "security-policy-enforcement/case/case-messaging-security-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-security-f02", "messaging-security-f02-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-security-f02.txt" ], "relations": [ "배선된 게이트는 자기 leaf 레인에서 검증한다", "같은 술어가 두 타입에 있으면 하나가 다른 하나를 부른다", "가변 필드로 상태 전이를 표현하면 가시성을 함께 정한다", "맵 갱신 함수 안에서 I/O를 하면 그 지연이 락 범위가 된다" ] } ], "concept": [], "reference": [ { "title": "맵 갱신 함수 안에서 I/O를 하면 그 지연이 락 범위가 된다", "slug": "messaging-security-f06", "file": "security-policy-enforcement/reference/reference-messaging-security-f06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "종료 시 자격증명 소거가 호출되지 않는다", "같은 TLS posture를 두 클래스가 다른 엄격도로 검사한다", "권한 거부가 `AUTHORIZATION`이 아니라 `CONFIGURATION`으로 기록된다" ] } ], "question": [ { "title": "ACL 매니페스트 전체가 쓰이지 않는다", "slug": "messaging-security-f03", "file": "security-policy-enforcement/question/openquestion-messaging-security-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "배선된 게이트는 자기 leaf 레인에서 검증한다", "같은 술어가 두 타입에 있으면 하나가 다른 하나를 부른다", "가변 필드로 상태 전이를 표현하면 가시성을 함께 정한다", "맵 갱신 함수 안에서 I/O를 하면 그 지연이 락 범위가 된다" ] } ], "decision": [] } }, "self-disclosure-grading": { "topic": "self-disclosure-grading", "kinds": { "case": [ { "title": "담금 임계값이 열거형에 없는 등급을 위해 쓰여 중간 등급으로 올라가는 것이 더 어려워졌다", "slug": "a-soak-threshold-written-for-a-grade-that-does-not-exist", "file": "self-disclosure-grading/case/case-a-soak-threshold-written-for-a-grade-that-does-not-exist.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-soak-threshold-written-for-a-grade-that-does-not-exist" ], "evidence": [ "../../../final/evidence/raw/a-soak-threshold-written-for-a-grade-that-does-not-exist.txt" ], "relations": [ "등급은 네 단계로 나누고 관측보다 높게 적지 않는다", "지원 등급은 추론이 아니라 선언이고 증거 없이는 올라가지 않는다", "이름이 검사한다고 말하는 것을 본문이 검사하지 않는 테스트 넷" ] }, { "title": "시작 검증기가 커서 서명 키를 요구하는데 그 키로 서명하는 코드가 없다", "slug": "a-startup-validator-that-requires-a-key-nothing-signs-with", "file": "self-disclosure-grading/case/case-a-startup-validator-that-requires-a-key-nothing-signs-with.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-startup-validator-that-requires-a-key-nothing-signs-with" ], "evidence": [ "../../../final/evidence/raw/a-startup-validator-that-requires-a-key-nothing-signs-with.txt" ], "relations": [ "등급표 13행 중 일곱을 스스로 강등하고 한 행만 관측과 어긋났다", "하위 시스템 전체가 미배선인데 그것을 켜는 플래그는 시작 검사를 수행한다", "커서에 서명하는 이유는 기밀성이 아니라 무결성이다" ] }, { "title": "build-only 등급이 90개 파일의 미조립을 오늘의 사고에서 면제한다", "slug": "build-only-exempts-ninety-files-from-todays-incident", "file": "self-disclosure-grading/case/case-build-only-exempts-ninety-files-from-todays-incident.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "build-only-exempts-ninety-files-from-todays-incident" ], "evidence": [ "../../../final/evidence/raw/build-only-exempts-ninety-files-from-todays-incident.txt" ], "relations": [ "runtime_memberships를 먼저 읽고 심각도를 정한다", "gRPC 플랫폼은 build-only로 두고 애플리케이션 도달 경로를 먼저 정한다", "등급표 13행 중 일곱을 스스로 강등하고 한 행만 관측과 어긋났다" ] }, { "title": "등급표 13행 중 일곱을 스스로 강등하고 한 행만 관측과 어긋났다", "slug": "seven-rows-downgraded-by-the-family-itself", "file": "self-disclosure-grading/case/case-seven-rows-downgraded-by-the-family-itself.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "seven-rows-downgraded-by-the-family-itself" ], "evidence": [ "../../../final/evidence/raw/seven-rows-downgraded-by-the-family-itself.txt" ], "relations": [ "네 단계 공시 등급 — modelled에서 production-verified까지", "등급은 네 단계로 나누고 관측보다 높게 적지 않는다", "시작 검증기가 커서 서명 키를 요구하는데 그 키로 서명하는 코드가 없다" ] } ], "concept": [ { "title": "네 단계 공시 등급 — modelled에서 production-verified까지", "slug": "four-grade-disclosure", "file": "self-disclosure-grading/concept/concept-four-grade-disclosure.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "four-grade-disclosure", "four-grade-disclosure-diagram" ], "evidence": [ "../../../final/evidence/raw/four-grade-disclosure.txt" ], "relations": [ "등급은 네 단계로 나누고 관측보다 높게 적지 않는다", "등급표 13행 중 일곱을 스스로 강등하고 한 행만 관측과 어긋났다", "능력 등급은 코드가 아니라 실행된 증거에서 파생한다" ] } ], "reference": [ { "title": "등급은 네 단계로 나누고 관측보다 높게 적지 않는다", "slug": "grades-may-understate-never-overstate", "file": "self-disclosure-grading/reference/reference-grades-may-understate-never-overstate.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "네 단계 공시 등급 — modelled에서 production-verified까지", "등급표 13행 중 일곱을 스스로 강등하고 한 행만 관측과 어긋났다", "능력 등급은 코드가 아니라 실행된 증거에서 파생한다" ] }, { "title": "runtime_memberships를 먼저 읽고 심각도를 정한다", "slug": "runtime-membership-decides-severity", "file": "self-disclosure-grading/reference/reference-runtime-membership-decides-severity.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "build-only 등급이 90개 파일의 미조립을 오늘의 사고에서 면제한다", "gRPC 플랫폼은 build-only로 두고 애플리케이션 도달 경로를 먼저 정한다", "Bean 애너테이션이 있다는 것은 조립 증거가 아니다" ] } ], "question": [], "decision": [ { "title": "능력 등급은 코드가 아니라 실행된 증거에서 파생한다", "slug": "grades-derive-from-executed-evidence", "file": "self-disclosure-grading/decision/decision-grades-derive-from-executed-evidence.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "네 단계 공시 등급 — modelled에서 production-verified까지", "증거 등급과 provenance — R1과 R2를 가르는 것", "지원 등급은 추론이 아니라 선언이고 증거 없이는 올라가지 않는다", "등급은 네 단계로 나누고 관측보다 높게 적지 않는다" ] } ] } }, "state-machines-and-ownership": { "topic": "state-machines-and-ownership", "kinds": { "case": [ { "title": "만료를 보는 청구와 시각을 읽지 않는 조회가 같은 행을 다르게 답한다", "slug": "a05-f020-inspect-claim", "file": "state-machines-and-ownership/case/case-a05-f020-inspect-claim.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a05-f020-inspect-claim", "a05-f020-inspect-claim-postgres" ], "evidence": [ "../../../final/evidence/raw/a05-f020-inspect-claim.txt", "../../../final/evidence/raw/a05-f020-inspect-claim-postgres.txt" ], "relations": [ "만료된 claim과 만료된 실행은 다르게 다뤄야 한다", "시간은 DB에서, 그리고 행을 잠근 다음에 읽는다", "전이 다섯 중 넷은 공용 판정을 쓰고 완료만 손으로 비교한다" ] }, { "title": "전이 다섯 중 넷은 공용 판정을 쓰고 완료만 손으로 비교한다", "slug": "a05-f021-complete-replayttl", "file": "state-machines-and-ownership/case/case-a05-f021-complete-replayttl.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a05-f021-complete-replayttl-postgres", "a05-f021-complete-replayttl" ], "evidence": [ "../../../final/evidence/raw/a05-f021-complete-replayttl-postgres.txt", "../../../final/evidence/raw/a05-f021-complete-replayttl.txt" ], "relations": [ "transition digest가 \"누가·언제\"만 덮고 \"무엇\"을 덮지 않아 다른 전이를 같다고 보고했다", "digest는 길이 프레이밍하고 버전을 붙인다", "만료를 보는 청구와 시각을 읽지 않는 조회가 같은 행을 다르게 답한다" ] }, { "title": "만료 조건이 연장에는 있고 확정에는 없다", "slug": "a05-f025-filequotaservice-commit", "file": "state-machines-and-ownership/case/case-a05-f025-filequotaservice-commit.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a05-f025-filequotaservice-commit", "a05-f025-filequotaservice-commit-postgres" ], "evidence": [ "../../../final/evidence/raw/a05-f025-filequotaservice-commit.txt", "../../../final/evidence/raw/a05-f025-filequotaservice-commit-postgres.txt" ], "relations": [ "조건부 update로 행을 claim하고 읽은 값으로 판단하지 않는다", "만료된 claim과 만료된 실행은 다르게 다뤄야 한다", "리스가 만료 시각만 기록하고 소유자를 기록하지 않아 최종 상태를 되돌릴 수 있었다" ] }, { "title": "reclaimExpiredClaim이 MAXIMUM_ATTEMPTS를 보지 않는다", "slug": "a05-f027-maximum-attempts", "file": "state-machines-and-ownership/case/case-a05-f027-maximum-attempts.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a05-f027-maximum-attempts", "a05-f027-maximum-attempts-reclaim" ], "evidence": [ "../../../final/evidence/raw/a05-f027-maximum-attempts.txt", "../../../final/evidence/raw/a05-f027-maximum-attempts-reclaim.txt" ], "relations": [ "만료된 claim과 만료된 실행은 다르게 다뤄야 한다", "fenced lease — 만료 시각만으로는 부족한 이유", "재시도 가능성은 멱등성과 실패 범주를 함께 봐야 정해진다" ] } ], "concept": [ { "title": "기계가 읽는 매니페스트와 사람이 읽는 등급표가 다르게 답한다", "slug": "adapter-inbound-graphql-c12", "file": "state-machines-and-ownership/concept/concept-adapter-inbound-graphql-c12.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-graphql-c12" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-graphql-c12.txt" ], "relations": [] }, { "title": "릴리스 게이트의 미배선은 정상이고 작성기의 호출자 부재는 다르다", "slug": "adapter-inbound-graphql-c13", "file": "state-machines-and-ownership/concept/concept-adapter-inbound-graphql-c13.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-graphql-c13" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-graphql-c13.txt" ], "relations": [] }, { "title": "캐시 헤더를 소유하는 것은 24줄 상수 두 개다", "slug": "adapter-inbound-web-c09", "file": "state-machines-and-ownership/concept/concept-adapter-inbound-web-c09.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c09" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c09.txt" ], "relations": [] }, { "title": "선언된 능력 열하나 중 켤 수 있는 것은 둘이다", "slug": "adapter-inbound-web-c16", "file": "state-machines-and-ownership/concept/concept-adapter-inbound-web-c16.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-web-c16" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-web-c16.txt" ], "relations": [] }, { "title": "릴리스 시점 도구라서 런타임 미배선이 정상이다", "slug": "adapter-inbound-websocket-c05", "file": "state-machines-and-ownership/concept/concept-adapter-inbound-websocket-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-websocket-c05" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-websocket-c05.txt" ], "relations": [] }, { "title": "한쪽에만 적용되는 변경이 구조적으로 불가능하다", "slug": "adapter-outbound-cache-redis-c08", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-cache-redis-c08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-cache-redis-c08", "adapter-outbound-cache-redis-c08-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-cache-redis-c08.txt" ], "relations": [] }, { "title": "뒤 단계일수록 비싸도록 검증 순서를 고정했다", "slug": "adapter-outbound-cache-redis-c10", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-cache-redis-c10.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-cache-redis-c10", "adapter-outbound-cache-redis-c10-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-cache-redis-c10.txt" ], "relations": [] }, { "title": "stateRevision은 정확히 하나씩만 증가한다", "slug": "adapter-outbound-fileserver-c03", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-fileserver-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-fileserver-c03", "adapter-outbound-fileserver-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-fileserver-c03.txt" ], "relations": [] }, { "title": "배타성이 필요한 쪽에만 OS 락을 둔다", "slug": "adapter-outbound-fileserver-c04", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-fileserver-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-fileserver-c04" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-fileserver-c04.txt" ], "relations": [] }, { "title": "잔여 경로 연산을 선언하고 identity 검사로 감싼다", "slug": "adapter-outbound-fileserver-c08", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-fileserver-c08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-fileserver-c08", "adapter-outbound-fileserver-c08-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-fileserver-c08.txt" ], "relations": [] }, { "title": "회전이 틈으로 관측되지 않게 만든 순서와 두 누수 이력", "slug": "adapter-outbound-httpclient-c02", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-httpclient-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-httpclient-c02" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-httpclient-c02.txt" ], "relations": [] }, { "title": "뒤 규칙이 앞 규칙의 금지를 되돌리지 못한다", "slug": "adapter-outbound-httpclient-c04", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-httpclient-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-httpclient-c04", "adapter-outbound-httpclient-c04-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-httpclient-c04.txt" ], "relations": [] }, { "title": "열린 타입은 페이로드로 받지 않는다", "slug": "adapter-outbound-messaging-c03", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-messaging-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-messaging-c03" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-messaging-c03.txt" ], "relations": [] }, { "title": "revision은 건너뛰지도 되돌아가지도 못한다", "slug": "adapter-outbound-objectstorage-c05", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-objectstorage-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-objectstorage-c05", "adapter-outbound-objectstorage-c05-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-objectstorage-c05.txt" ], "relations": [] }, { "title": "durable record가 비밀을 담지 않는다", "slug": "adapter-outbound-objectstorage-c07", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-objectstorage-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-objectstorage-c07" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-objectstorage-c07.txt" ], "relations": [] }, { "title": "내부 소비자 부재와 public 계약 필요성을 따로 묻는다", "slug": "adapter-outbound-persistence-jpa-c01", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c01" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c01.txt" ], "relations": [] }, { "title": "위험한 shape 자체를 표현하기 어렵게 만든다", "slug": "adapter-outbound-persistence-jpa-c03", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c03" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c03.txt" ], "relations": [] }, { "title": "설정으로 completion unknown을 다시 살릴 수 없다", "slug": "adapter-outbound-persistence-jpa-c06", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c06", "adapter-outbound-persistence-jpa-c06-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c06.txt" ], "relations": [] }, { "title": "이름 목록만 고정하고 의미는 고정하지 않는다", "slug": "adapter-outbound-persistence-jpa-c07", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c07" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c07.txt" ], "relations": [] }, { "title": "구현 클래스를 샘플링하지 않고 51개를 전부 읽었다", "slug": "adapter-outbound-persistence-jpa-c08", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c08" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c08.txt" ], "relations": [] }, { "title": "같은 leaf 안에 트랜잭션 모델이 둘 있다", "slug": "adapter-outbound-persistence-jpa-c09", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c09.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c09" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c09.txt" ], "relations": [] }, { "title": "commit exception을 rollback으로 가정하지 않는다", "slug": "adapter-outbound-persistence-jpa-c12", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c12.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c12" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c12.txt" ], "relations": [] }, { "title": "이미 소비한 시간을 트랜잭션 계층이 다시 주지 않는다", "slug": "adapter-outbound-persistence-jpa-c13", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c13.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c13" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c13.txt" ], "relations": [] }, { "title": "SQLSTATE만으로는 구분할 수 없어 phase가 필요하다", "slug": "adapter-outbound-persistence-jpa-c17", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c17.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c17" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c17.txt" ], "relations": [] }, { "title": "runbook이 지목하는 지표를 만드는 호출이 없다", "slug": "adapter-outbound-persistence-jpa-c19", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c19.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c19" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c19.txt" ], "relations": [] }, { "title": "Querydsl은 production runtimeClasspath에 들어오지 않는다", "slug": "adapter-outbound-persistence-jpa-c30", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c30.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c30" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c30.txt" ], "relations": [] }, { "title": "게이트 통과가 오히려 검증기의 한계를 보여 준다", "slug": "adapter-outbound-persistence-jpa-c34", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c34.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c34" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c34.txt" ], "relations": [] }, { "title": "40003이 UNKNOWN으로 강등되면서 조정 경로도 함께 사라진다", "slug": "adapter-outbound-persistence-jpa-c35", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c35.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c35" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c35.txt" ], "relations": [] }, { "title": "만료된 COMPLETED row를 inspect와 claim이 다르게 읽는다", "slug": "adapter-outbound-persistence-jpa-c36", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c36.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c36", "adapter-outbound-persistence-jpa-c36-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c36.txt" ], "relations": [] }, { "title": "SQL 식별자를 호출자가 조립하지 않는다", "slug": "adapter-outbound-persistence-jpa-c38", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c38.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c38" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c38.txt" ], "relations": [] }, { "title": "vendor migration 아홉을 실제 PostgreSQL에서 적용했다", "slug": "adapter-outbound-persistence-jpa-c39", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c39.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c39" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c39.txt" ], "relations": [] }, { "title": "재현에 쓴 레인과 복원까지 남긴 기록", "slug": "adapter-outbound-persistence-jpa-c40", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c40.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c40" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c40.txt" ], "relations": [] }, { "title": "보류한 항목과 보류한 이유", "slug": "adapter-outbound-persistence-jpa-c41", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c41.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c41" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c41.txt" ], "relations": [] }, { "title": "H2 idempotency와 V2 owner 필드", "slug": "adapter-outbound-persistence-jpa-c43", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c43.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c43" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c43.txt" ], "relations": [] }, { "title": "FIFO 정산은 기록된 적응이고 전제가 빠진 것이 문제다", "slug": "adapter-outbound-persistence-jpa-c46", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c46.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c46" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c46.txt" ], "relations": [] }, { "title": "만료 직후 takeover 전 창은 보이지만 계약이 그것을 금지하지 않는다", "slug": "adapter-outbound-persistence-jpa-c47", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c47.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c47" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c47.txt" ], "relations": [] }, { "title": "레지스트리는 V4에 멈춰 있고 매핑은 V10까지 의존한다", "slug": "adapter-outbound-persistence-jpa-c48", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c48.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c48" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c48.txt" ], "relations": [] }, { "title": "이 scope에서는 cross-tenant bypass를 확정하지 못했다", "slug": "adapter-outbound-persistence-jpa-c50", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c50.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c50" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c50.txt" ], "relations": [] }, { "title": "schema 값을 statement text에 붙이지 않고 set_config로 바인딩한다", "slug": "adapter-outbound-persistence-jpa-c52", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c52.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c52" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c52.txt" ], "relations": [] }, { "title": "이름이 말하는 것과 반환하는 것이 다른 helper", "slug": "adapter-outbound-persistence-jpa-c54", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c54.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c54" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c54.txt" ], "relations": [] }, { "title": "정규식 파서를 통과해도 Gradle이 다시 파싱한다", "slug": "adapter-outbound-persistence-jpa-c55", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c55.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c55" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c55.txt" ], "relations": [] }, { "title": "registry에서 task graph 한 방향만 검사한다", "slug": "adapter-outbound-persistence-jpa-c57", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c57.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c57" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c57.txt" ], "relations": [] }, { "title": "JVM 공유를 설계 근거로 내세웠지만 소비자 31곳 어디에도 없다", "slug": "adapter-outbound-persistence-jpa-c58", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-jpa-c58.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c58" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c58.txt" ], "relations": [] }, { "title": "취소된 stream은 성공도 실패도 기록하지 않는다", "slug": "adapter-outbound-persistence-mongo-c04", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-mongo-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-mongo-c04", "adapter-outbound-persistence-mongo-c04-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-mongo-c04.txt" ], "relations": [] }, { "title": "더 자주 갱신해도 고쳐지지 않는 문제라서 fencing을 얹는다", "slug": "adapter-outbound-persistence-mongo-c06", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-persistence-mongo-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-mongo-c06" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-mongo-c06.txt" ], "relations": [] }, { "title": "직접 참조 0이지만 broad component scan으로 도달한다", "slug": "adapter-outbound-support-c04", "file": "state-machines-and-ownership/concept/concept-adapter-outbound-support-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-support-c04" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-support-c04.txt" ], "relations": [] }, { "title": "효과가 없었다고 증명할 수 없으면 자동 재시도 권한을 주지 않는다", "slug": "application-core-c04", "file": "state-machines-and-ownership/concept/concept-application-core-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "application-core-c04", "application-core-c04-diagram" ], "evidence": [ "../../../final/evidence/raw/application-core-c04.txt" ], "relations": [ "legacy storage/notification compatibility surface의 제거 조건 추적" ] }, { "title": "efficiency lock이 correctness authority를 대체하지 않는다", "slug": "application-core-c05", "file": "state-machines-and-ownership/concept/concept-application-core-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "application-core-c05" ], "evidence": [ "../../../final/evidence/raw/application-core-c05.txt" ], "relations": [ "legacy storage/notification compatibility surface의 제거 조건 추적" ] }, { "title": "메타데이터와 물리 내용이 원자적이지 않다는 사실을 숨기지 않는다", "slug": "application-core-c09", "file": "state-machines-and-ownership/concept/concept-application-core-c09.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "application-core-c09" ], "evidence": [ "../../../final/evidence/raw/application-core-c09.txt" ], "relations": [ "legacy storage/notification compatibility surface의 제거 조건 추적" ] }, { "title": "도메인 내용이 아니라 도메인 모델링 계약을 소유한다", "slug": "domain-core-c01", "file": "state-machines-and-ownership/concept/concept-domain-core-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "domain-core-c01", "domain-core-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/domain-core-c01.txt" ], "relations": [] }, { "title": "헤지는 성공했을지도 모르는 호출에 대해 일어난다", "slug": "grpc-advanced-resilience-c01", "file": "state-machines-and-ownership/concept/concept-grpc-advanced-resilience-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-resilience-c01", "grpc-advanced-resilience-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-resilience-c01.txt" ], "relations": [] }, { "title": "손으로 적은 요구 목록은 갱신이 멈추는 쪽이다", "slug": "grpc-codegen-c01", "file": "state-machines-and-ownership/concept/concept-grpc-codegen-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-codegen-c01", "grpc-codegen-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-codegen-c01.txt" ], "relations": [] }, { "title": "위험한 조합은 정책이 아니라 생성자가 거부한다", "slug": "grpc-discovery-c01", "file": "state-machines-and-ownership/concept/concept-grpc-discovery-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-discovery-c01", "grpc-discovery-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-discovery-c01.txt" ], "relations": [] }, { "title": "record를 지나지 않는 쓰기가 있어서 제약을 DB에도 둔다", "slug": "grpc-operation-ledger-jpa-c01", "file": "state-machines-and-ownership/concept/concept-grpc-operation-ledger-jpa-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-operation-ledger-jpa-c01" ], "evidence": [ "../../../final/evidence/raw/grpc-operation-ledger-jpa-c01.txt" ], "relations": [] }, { "title": "같은 신원의 두 번째 청구가 같은 행을 겨냥한다", "slug": "grpc-operation-ledger-jpa-c02", "file": "state-machines-and-ownership/concept/concept-grpc-operation-ledger-jpa-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-operation-ledger-jpa-c02" ], "evidence": [ "../../../final/evidence/raw/grpc-operation-ledger-jpa-c02.txt" ], "relations": [] }, { "title": "서수 컬럼은 값이 끼어들면 모든 행을 조용히 바꾼다", "slug": "grpc-operation-ledger-jpa-c03", "file": "state-machines-and-ownership/concept/concept-grpc-operation-ledger-jpa-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-operation-ledger-jpa-c03", "grpc-operation-ledger-jpa-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-operation-ledger-jpa-c03.txt" ], "relations": [] }, { "title": "한 번에 전부 모아 실패한다", "slug": "grpc-spring-boot-starter-c02", "file": "state-machines-and-ownership/concept/concept-grpc-spring-boot-starter-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-spring-boot-starter-c02" ], "evidence": [ "../../../final/evidence/raw/grpc-spring-boot-starter-c02.txt" ], "relations": [] }, { "title": "런북을 나중에 쓰면 처음 만나는 사람이 새벽에 알아내야 한다", "slug": "grpc-testkit-c01", "file": "state-machines-and-ownership/concept/concept-grpc-testkit-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-testkit-c01" ], "evidence": [ "../../../final/evidence/raw/grpc-testkit-c01.txt" ], "relations": [] }, { "title": "실행 코드가 없어서 동시성 계약이 전부 문서다", "slug": "messaging-admin-api-c06", "file": "state-machines-and-ownership/concept/concept-messaging-admin-api-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-api-c06", "messaging-admin-api-c06-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-api-c06.txt" ], "relations": [] }, { "title": "승인이 처음에는 데이터였고 지금은 타입이다", "slug": "messaging-admin-api-c07", "file": "state-machines-and-ownership/concept/concept-messaging-admin-api-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-api-c07" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-api-c07.txt" ], "relations": [] }, { "title": "리드라이브는 재개하고 리플레이는 처음부터 다시 읽는다", "slug": "messaging-admin-runtime-c03", "file": "state-machines-and-ownership/concept/concept-messaging-admin-runtime-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-runtime-c03", "messaging-admin-runtime-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-runtime-c03.txt" ], "relations": [] }, { "title": "펜싱 토큰이 세 지점에서 작동한다", "slug": "messaging-admin-runtime-c06", "file": "state-machines-and-ownership/concept/concept-messaging-admin-runtime-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-runtime-c06", "messaging-admin-runtime-c06-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-runtime-c06.txt" ], "relations": [] }, { "title": "크래시와 복제본을 고려하지 않은 admin 평면", "slug": "messaging-admin-runtime-c07", "file": "state-machines-and-ownership/concept/concept-messaging-admin-runtime-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-runtime-c07" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-runtime-c07.txt" ], "relations": [] }, { "title": "위협은 실패가 아니라 잘못된 성공이다", "slug": "messaging-claim-check-c01", "file": "state-machines-and-ownership/concept/concept-messaging-claim-check-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-claim-check-c01", "messaging-claim-check-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-claim-check-c01.txt" ], "relations": [ "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "같은 튜닝 값이 두 계층에 있으면 어느 쪽이 이기는지 정한다" ] }, { "title": "싣고 쓰지 않는다", "slug": "messaging-claim-check-c02", "file": "state-machines-and-ownership/concept/concept-messaging-claim-check-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-claim-check-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-claim-check-c02.txt" ], "relations": [ "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "같은 튜닝 값이 두 계층에 있으면 어느 쪽이 이기는지 정한다" ] }, { "title": "보존이 생성자 불변식이고 삭제를 부르는 쪽이 없다", "slug": "messaging-claim-check-c03", "file": "state-machines-and-ownership/concept/concept-messaging-claim-check-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-claim-check-c03", "messaging-claim-check-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-claim-check-c03.txt" ], "relations": [ "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "같은 튜닝 값이 두 계층에 있으면 어느 쪽이 이기는지 정한다" ] }, { "title": "두 경로 모두 production에서 호출되지 않는다", "slug": "messaging-claim-check-c04", "file": "state-machines-and-ownership/concept/concept-messaging-claim-check-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-claim-check-c04" ], "evidence": [ "../../../final/evidence/raw/messaging-claim-check-c04.txt" ], "relations": [ "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "같은 튜닝 값이 두 계층에 있으면 어느 쪽이 이기는지 정한다" ] }, { "title": "만료와 불일치를 다른 카테고리로 가른다", "slug": "messaging-claim-check-c05", "file": "state-machines-and-ownership/concept/concept-messaging-claim-check-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-claim-check-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-claim-check-c05.txt" ], "relations": [ "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "같은 튜닝 값이 두 계층에 있으면 어느 쪽이 이기는지 정한다" ] }, { "title": "MessageDigest를 호출마다 새로 만드는 것이 옳다", "slug": "messaging-claim-check-c06", "file": "state-machines-and-ownership/concept/concept-messaging-claim-check-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-claim-check-c06" ], "evidence": [ "../../../final/evidence/raw/messaging-claim-check-c06.txt" ], "relations": [ "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "같은 튜닝 값이 두 계층에 있으면 어느 쪽이 이기는지 정한다" ] }, { "title": "테스트에서는 드물고 부하에서는 일상인 것", "slug": "messaging-claim-check-c07", "file": "state-machines-and-ownership/concept/concept-messaging-claim-check-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-claim-check-c07" ], "evidence": [ "../../../final/evidence/raw/messaging-claim-check-c07.txt" ], "relations": [ "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "같은 튜닝 값이 두 계층에 있으면 어느 쪽이 이기는지 정한다" ] }, { "title": "상태가 없다는 사실이 javadoc에는 적혀 있지 않다", "slug": "messaging-cloudevents-c07", "file": "state-machines-and-ownership/concept/concept-messaging-cloudevents-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-cloudevents-c07" ], "evidence": [ "../../../final/evidence/raw/messaging-cloudevents-c07.txt" ], "relations": [ "왕복이라 부르는 테스트는 무엇을 보존하지 않는지도 적는다", "문서가 범위를 제한하면 그 제한을 누가 강제하는지 같이 적는다" ] }, { "title": "무엇이 아닌가가 무엇인가만큼 중요하다", "slug": "messaging-core-api-c01", "file": "state-machines-and-ownership/concept/concept-messaging-core-api-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-core-api-c01", "messaging-core-api-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-core-api-c01.txt" ], "relations": [] }, { "title": "예약 네임스페이스를 봉투 필드와 헤더 전용으로 쪼갠다", "slug": "messaging-core-api-c03", "file": "state-machines-and-ownership/concept/concept-messaging-core-api-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-core-api-c03" ], "evidence": [ "../../../final/evidence/raw/messaging-core-api-c03.txt" ], "relations": [] }, { "title": "동시성 지점이 하나뿐이다", "slug": "messaging-core-api-c07", "file": "state-machines-and-ownership/concept/concept-messaging-core-api-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-core-api-c07" ], "evidence": [ "../../../final/evidence/raw/messaging-core-api-c07.txt" ], "relations": [] }, { "title": "검사가 없었던 게 아니라 잘못된 단위로 되어 있었다", "slug": "messaging-core-api-c08", "file": "state-machines-and-ownership/concept/concept-messaging-core-api-c08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-core-api-c08" ], "evidence": [ "../../../final/evidence/raw/messaging-core-api-c08.txt" ], "relations": [] }, { "title": "action 예외가 예약까지 함께 롤백시킨다", "slug": "messaging-inbox-jdbc-postgresql-c04", "file": "state-machines-and-ownership/concept/concept-messaging-inbox-jdbc-postgresql-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-inbox-jdbc-postgresql-c04" ], "evidence": [ "../../../final/evidence/raw/messaging-inbox-jdbc-postgresql-c04.txt" ], "relations": [ "컬럼 폭은 애플리케이션 검증과 짝을 이룬다", "같은 안전 규칙은 한 공식과 한 강제 시점을 갖는다" ] }, { "title": "일시적 인프라 문제가 재시도 불가로 분류된다", "slug": "messaging-inbox-jdbc-postgresql-c05", "file": "state-machines-and-ownership/concept/concept-messaging-inbox-jdbc-postgresql-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-inbox-jdbc-postgresql-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-inbox-jdbc-postgresql-c05.txt" ], "relations": [ "컬럼 폭은 애플리케이션 검증과 짝을 이룬다", "같은 안전 규칙은 한 공식과 한 강제 시점을 갖는다" ] }, { "title": "커넥션 조회가 새 커넥션을 열기 전에 검사가 돌아야 한다", "slug": "messaging-inbox-jdbc-postgresql-c06", "file": "state-machines-and-ownership/concept/concept-messaging-inbox-jdbc-postgresql-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-inbox-jdbc-postgresql-c06", "messaging-inbox-jdbc-postgresql-c06-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-inbox-jdbc-postgresql-c06.txt" ], "relations": [ "컬럼 폭은 애플리케이션 검증과 짝을 이룬다", "같은 안전 규칙은 한 공식과 한 강제 시점을 갖는다" ] }, { "title": "느린 메시지 하나가 그 파티션의 워터마크를 붙든다", "slug": "messaging-kafka-c02", "file": "state-machines-and-ownership/concept/concept-messaging-kafka-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-kafka-c02", "messaging-kafka-c02-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-kafka-c02.txt" ], "relations": [] }, { "title": "register가 아무것도 등록하지 않고 활성을 돌려준다", "slug": "messaging-kafka-share-experimental-c03", "file": "state-machines-and-ownership/concept/concept-messaging-kafka-share-experimental-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-kafka-share-experimental-c03", "messaging-kafka-share-experimental-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-kafka-share-experimental-c03.txt" ], "relations": [ "허용 의존 목록은 상한이므로 미사용을 잡지 않는다 — 그것을 잡으려면 별도 검사가 필요하다", "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "에러 메시지가 지시하는 설정은 그 설정을 읽는 코드와 함께 존재해야 한다", "구성 오류는 한 예외 타입과 안정 코드로 보고한다" ] }, { "title": "닫을 자원이 없어서 두 번 닫아도 무해하다", "slug": "messaging-kafka-share-experimental-c06", "file": "state-machines-and-ownership/concept/concept-messaging-kafka-share-experimental-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-kafka-share-experimental-c06" ], "evidence": [ "../../../final/evidence/raw/messaging-kafka-share-experimental-c06.txt" ], "relations": [ "허용 의존 목록은 상한이므로 미사용을 잡지 않는다 — 그것을 잡으려면 별도 검사가 필요하다", "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "에러 메시지가 지시하는 설정은 그 설정을 읽는 코드와 함께 존재해야 한다", "구성 오류는 한 예외 타입과 안정 코드로 보고한다" ] }, { "title": "seam은 중립이고 구현만 벤더에 묶인다", "slug": "messaging-observability-c01", "file": "state-machines-and-ownership/concept/concept-messaging-observability-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-observability-c01", "messaging-observability-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-observability-c01.txt" ], "relations": [ "타입이 문서화한 불변식은 타입이 강제한다" ] }, { "title": "Set 인스턴스를 락으로 쓰지만 외부 경합이 없다", "slug": "messaging-observability-c06", "file": "state-machines-and-ownership/concept/concept-messaging-observability-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-observability-c06" ], "evidence": [ "../../../final/evidence/raw/messaging-observability-c06.txt" ], "relations": [ "타입이 문서화한 불변식은 타입이 강제한다" ] }, { "title": "경계는 예산을 정확히 소비할 때만 경계다", "slug": "messaging-observability-c07", "file": "state-machines-and-ownership/concept/concept-messaging-observability-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-observability-c07" ], "evidence": [ "../../../final/evidence/raw/messaging-observability-c07.txt" ], "relations": [ "타입이 문서화한 불변식은 타입이 강제한다" ] }, { "title": "동시성 제어가 전부 데이터베이스에 있다", "slug": "messaging-outbox-jdbc-postgresql-c05", "file": "state-machines-and-ownership/concept/concept-messaging-outbox-jdbc-postgresql-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-outbox-jdbc-postgresql-c05", "messaging-outbox-jdbc-postgresql-c05-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-outbox-jdbc-postgresql-c05.txt" ], "relations": [] }, { "title": "모순은 부팅 실패여야 한다", "slug": "messaging-policy-c01", "file": "state-machines-and-ownership/concept/concept-messaging-policy-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-policy-c01", "messaging-policy-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-policy-c01.txt" ], "relations": [ "구성 오류는 한 예외 타입과 안정 코드로 보고한다", "저장소 밖 문서를 절 번호로 인용하지 않는다", "부팅 경로의 알고리즘 복잡도는 문서화한다" ] }, { "title": "거절이 전송 전에 끝나는 것이 설계의 핵심이다", "slug": "messaging-policy-c03", "file": "state-machines-and-ownership/concept/concept-messaging-policy-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-policy-c03", "messaging-policy-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-policy-c03.txt" ], "relations": [ "구성 오류는 한 예외 타입과 안정 코드로 보고한다", "저장소 밖 문서를 절 번호로 인용하지 않는다", "부팅 경로의 알고리즘 복잡도는 문서화한다" ] }, { "title": "제거 실패는 안전한 방향의 경합이다", "slug": "messaging-policy-c06", "file": "state-machines-and-ownership/concept/concept-messaging-policy-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-policy-c06" ], "evidence": [ "../../../final/evidence/raw/messaging-policy-c06.txt" ], "relations": [ "구성 오류는 한 예외 타입과 안정 코드로 보고한다", "저장소 밖 문서를 절 번호로 인용하지 않는다", "부팅 경로의 알고리즘 복잡도는 문서화한다" ] }, { "title": "반납이 획득보다 많으면 제한이 사라진다", "slug": "messaging-policy-c09", "file": "state-machines-and-ownership/concept/concept-messaging-policy-c09.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-policy-c09" ], "evidence": [ "../../../final/evidence/raw/messaging-policy-c09.txt" ], "relations": [ "구성 오류는 한 예외 타입과 안정 코드로 보고한다", "저장소 밖 문서를 절 번호로 인용하지 않는다", "부팅 경로의 알고리즘 복잡도는 문서화한다" ] }, { "title": "Outbox 하나로는 부족하다는 것을 타입이 직접 말한다", "slug": "messaging-reliability-api-c01", "file": "state-machines-and-ownership/concept/concept-messaging-reliability-api-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-reliability-api-c01", "messaging-reliability-api-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-reliability-api-c01.txt" ], "relations": [ "계약만 담는 leaf도 계약의 거절 조건은 자기 레인에서 검증한다", "record의 `equals`를 좁히면 이유를 적는다", "호출 컨텍스트가 계약이면 그 컨텍스트를 검증할 수단을 함께 정한다" ] }, { "title": "Outbox에 행을 쓰는 진입점이 없다", "slug": "messaging-reliability-api-c02", "file": "state-machines-and-ownership/concept/concept-messaging-reliability-api-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-reliability-api-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-reliability-api-c02.txt" ], "relations": [ "계약만 담는 leaf도 계약의 거절 조건은 자기 레인에서 검증한다", "record의 `equals`를 좁히면 이유를 적는다", "호출 컨텍스트가 계약이면 그 컨텍스트를 검증할 수단을 함께 정한다" ] }, { "title": "이 enum의 의미가 저장소 규칙 하나의 존재 이유다", "slug": "messaging-reliability-api-c03", "file": "state-machines-and-ownership/concept/concept-messaging-reliability-api-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-reliability-api-c03", "messaging-reliability-api-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-reliability-api-c03.txt" ], "relations": [ "계약만 담는 leaf도 계약의 거절 조건은 자기 레인에서 검증한다", "record의 `equals`를 좁히면 이유를 적는다", "호출 컨텍스트가 계약이면 그 컨텍스트를 검증할 수단을 함께 정한다" ] }, { "title": "Outbox에 행을 쓰는 진입점만 구현이 없다", "slug": "messaging-reliability-api-c04", "file": "state-machines-and-ownership/concept/concept-messaging-reliability-api-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-reliability-api-c04" ], "evidence": [ "../../../final/evidence/raw/messaging-reliability-api-c04.txt" ], "relations": [ "계약만 담는 leaf도 계약의 거절 조건은 자기 레인에서 검증한다", "record의 `equals`를 좁히면 이유를 적는다", "호출 컨텍스트가 계약이면 그 컨텍스트를 검증할 수단을 함께 정한다" ] }, { "title": "실패를 예외가 아니라 상태와 반환값으로 표현한다", "slug": "messaging-reliability-api-c05", "file": "state-machines-and-ownership/concept/concept-messaging-reliability-api-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-reliability-api-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-reliability-api-c05.txt" ], "relations": [ "계약만 담는 leaf도 계약의 거절 조건은 자기 레인에서 검증한다", "record의 `equals`를 좁히면 이유를 적는다", "호출 컨텍스트가 계약이면 그 컨텍스트를 검증할 수단을 함께 정한다" ] }, { "title": "전부 트랜잭션 계약인데 코드에는 트랜잭션이 없다", "slug": "messaging-reliability-api-c06", "file": "state-machines-and-ownership/concept/concept-messaging-reliability-api-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-reliability-api-c06", "messaging-reliability-api-c06-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-reliability-api-c06.txt" ], "relations": [ "계약만 담는 leaf도 계약의 거절 조건은 자기 레인에서 검증한다", "record의 `equals`를 좁히면 이유를 적는다", "호출 컨텍스트가 계약이면 그 컨텍스트를 검증할 수단을 함께 정한다" ] }, { "title": "전달 경로가 메시지 내용을 바꾸면 그것은 전달이 아니다", "slug": "messaging-reliability-api-c07", "file": "state-machines-and-ownership/concept/concept-messaging-reliability-api-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-reliability-api-c07" ], "evidence": [ "../../../final/evidence/raw/messaging-reliability-api-c07.txt" ], "relations": [ "계약만 담는 leaf도 계약의 거절 조건은 자기 레인에서 검증한다", "record의 `equals`를 좁히면 이유를 적는다", "호출 컨텍스트가 계약이면 그 컨텍스트를 검증할 수단을 함께 정한다" ] }, { "title": "전송이 없으면 조용히 반환하는 설치 경로", "slug": "messaging-runtime-core-c04", "file": "state-machines-and-ownership/concept/concept-messaging-runtime-core-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-runtime-core-c04" ], "evidence": [ "../../../final/evidence/raw/messaging-runtime-core-c04.txt" ], "relations": [ "만들어 두고 흘리지 않는 진단값은 진단이 아니다", "증가한다고 문서화한 값이 리터럴이면 그 사실을 적는다", "안정 코드는 운영자의 행동이 갈리는 지점마다 나눈다", "`CompletionStage`를 반환하는 메서드는 동기적으로 던지지 않는다" ] }, { "title": "지역 변수 하나만 람다가 복사해 캡처한다", "slug": "messaging-runtime-core-c06", "file": "state-machines-and-ownership/concept/concept-messaging-runtime-core-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-runtime-core-c06" ], "evidence": [ "../../../final/evidence/raw/messaging-runtime-core-c06.txt" ], "relations": [ "만들어 두고 흘리지 않는 진단값은 진단이 아니다", "증가한다고 문서화한 값이 리터럴이면 그 사실을 적는다", "안정 코드는 운영자의 행동이 갈리는 지점마다 나눈다", "`CompletionStage`를 반환하는 메서드는 동기적으로 던지지 않는다" ] }, { "title": "codec은 닫힌 registry에 대해서만 동작한다", "slug": "messaging-schema-api-c01", "file": "state-machines-and-ownership/concept/concept-messaging-schema-api-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-api-c01", "messaging-schema-api-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-api-c01.txt" ], "relations": [ "port 계약은 동시성 요구를 적는다", "도달성 판정은 단어가 아니라 import로 확인한다" ] }, { "title": "프로그래밍 오류를 MessagingException 밖에 둔다", "slug": "messaging-schema-api-c05", "file": "state-machines-and-ownership/concept/concept-messaging-schema-api-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-api-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-api-c05.txt" ], "relations": [ "port 계약은 동시성 요구를 적는다", "도달성 판정은 단어가 아니라 import로 확인한다" ] }, { "title": "의도적으로 스레드 안전하지 않은 타입이 하나 있다", "slug": "messaging-schema-api-c06", "file": "state-machines-and-ownership/concept/concept-messaging-schema-api-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-api-c06" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-api-c06.txt" ], "relations": [ "port 계약은 동시성 요구를 적는다", "도달성 판정은 단어가 아니라 import로 확인한다" ] }, { "title": "재사용 자리에 항상 null을 넘겨 공유 상태를 없앤다", "slug": "messaging-schema-avro-c06", "file": "state-machines-and-ownership/concept/concept-messaging-schema-avro-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-avro-c06" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-avro-c06.txt" ], "relations": [ "모드 enum을 분기 조건으로 쓰면 각 분기에 테스트를 둔다", "컬렉션 순서가 계약이면 양쪽에서 같은 방향으로 적는다", "안정 코드는 판단 단위로 정하고 구현 단위로 정하지 않는다" ] }, { "title": "메시지당 유지 메모리를 성능 테스트가 간접 확인한다", "slug": "messaging-schema-json-c06", "file": "state-machines-and-ownership/concept/concept-messaging-schema-json-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-json-c06" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-json-c06.txt" ], "relations": [ "실패 코드는 운영자의 다음 행동이 갈리는 지점마다 나눈다" ] }, { "title": "이 리프에서 발견된 문제가 상위 리프의 타입을 만들어냈다", "slug": "messaging-schema-json-c07", "file": "state-machines-and-ownership/concept/concept-messaging-schema-json-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-json-c07" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-json-c07.txt" ], "relations": [ "실패 코드는 운영자의 다음 행동이 갈리는 지점마다 나눈다" ] }, { "title": "나가는 의존이 하나도 없다", "slug": "messaging-schema-protobuf-c02", "file": "state-machines-and-ownership/concept/concept-messaging-schema-protobuf-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-protobuf-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-protobuf-c02.txt" ], "relations": [ "검증되지 않는 스키마 파일은 문서임을 파일 안에 적는다", "신뢰할 수 없는 입력 쪽 경계를 먼저 테스트한다" ] }, { "title": "평탄한 registry라 얕은 복사 문제가 없다", "slug": "messaging-schema-protobuf-c06", "file": "state-machines-and-ownership/concept/concept-messaging-schema-protobuf-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-schema-protobuf-c06" ], "evidence": [ "../../../final/evidence/raw/messaging-schema-protobuf-c06.txt" ], "relations": [ "검증되지 않는 스키마 파일은 문서임을 파일 안에 적는다", "신뢰할 수 없는 입력 쪽 경계를 먼저 테스트한다" ] }, { "title": "비밀은 참조로만 다루고 역할은 필드로 나눈다", "slug": "messaging-security-c01", "file": "state-machines-and-ownership/concept/concept-messaging-security-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-security-c01", "messaging-security-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-security-c01.txt" ], "relations": [ "배선된 게이트는 자기 leaf 레인에서 검증한다", "같은 술어가 두 타입에 있으면 하나가 다른 하나를 부른다", "가변 필드로 상태 전이를 표현하면 가시성을 함께 정한다", "맵 갱신 함수 안에서 I/O를 하면 그 지연이 락 범위가 된다" ] }, { "title": "한 경합에서 서로 다른 두 결함이 나왔다", "slug": "messaging-security-c03", "file": "state-machines-and-ownership/concept/concept-messaging-security-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-security-c03", "messaging-security-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-security-c03.txt" ], "relations": [ "배선된 게이트는 자기 leaf 레인에서 검증한다", "같은 술어가 두 타입에 있으면 하나가 다른 하나를 부른다", "가변 필드로 상태 전이를 표현하면 가시성을 함께 정한다", "맵 갱신 함수 안에서 I/O를 하면 그 지연이 락 범위가 된다" ] }, { "title": "시작 검증 호출 지점이 두 곳으로 갈린다", "slug": "messaging-security-c04", "file": "state-machines-and-ownership/concept/concept-messaging-security-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-security-c04" ], "evidence": [ "../../../final/evidence/raw/messaging-security-c04.txt" ], "relations": [ "배선된 게이트는 자기 leaf 레인에서 검증한다", "같은 술어가 두 타입에 있으면 하나가 다른 하나를 부른다", "가변 필드로 상태 전이를 표현하면 가시성을 함께 정한다", "맵 갱신 함수 안에서 I/O를 하면 그 지연이 락 범위가 된다" ] }, { "title": "종료 시 자격증명을 소거하는 코드가 없다", "slug": "messaging-security-c06", "file": "state-machines-and-ownership/concept/concept-messaging-security-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-security-c06" ], "evidence": [ "../../../final/evidence/raw/messaging-security-c06.txt" ], "relations": [ "배선된 게이트는 자기 leaf 레인에서 검증한다", "같은 술어가 두 타입에 있으면 하나가 다른 하나를 부른다", "가변 필드로 상태 전이를 표현하면 가시성을 함께 정한다", "맵 갱신 함수 안에서 I/O를 하면 그 지연이 락 범위가 된다" ] }, { "title": "거부목록이 실제로 뚫린 기록이 남아 있다", "slug": "messaging-security-c07", "file": "state-machines-and-ownership/concept/concept-messaging-security-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-security-c07" ], "evidence": [ "../../../final/evidence/raw/messaging-security-c07.txt" ], "relations": [ "배선된 게이트는 자기 leaf 레인에서 검증한다", "같은 술어가 두 타입에 있으면 하나가 다른 하나를 부른다", "가변 필드로 상태 전이를 표현하면 가시성을 함께 정한다", "맵 갱신 함수 안에서 I/O를 하면 그 지연이 락 범위가 된다" ] }, { "title": "등록된 핸들러를 해제하는 방법이 없다", "slug": "messaging-spring-cloud-stream-bridge-c06", "file": "state-machines-and-ownership/concept/concept-messaging-spring-cloud-stream-bridge-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-spring-cloud-stream-bridge-c06" ], "evidence": [ "../../../final/evidence/raw/messaging-spring-cloud-stream-bridge-c06.txt" ], "relations": [ "허용 의존 목록은 상한이므로 미사용을 잡지 않는다", "등록을 받는 컴포넌트는 해제도 제공한다", "함께 읽히는 두 맵은 한 값으로 묶는다", "에러 메시지가 지시하는 설정은 그 설정을 읽는 코드와 함께 존재해야 한다", "한 개념의 등록 상태를 두 객체가 나눠 갖지 않는다" ] }, { "title": "가변인데 공유되지 않아서 안전한 것들", "slug": "messaging-testkit-c07", "file": "state-machines-and-ownership/concept/concept-messaging-testkit-c07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-testkit-c07" ], "evidence": [ "../../../final/evidence/raw/messaging-testkit-c07.txt" ], "relations": [] }, { "title": "자기 자신을 검증하는 상수가 여섯 얼굴로 나타났다", "slug": "messaging-testkit-c08", "file": "state-machines-and-ownership/concept/concept-messaging-testkit-c08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-testkit-c08" ], "evidence": [ "../../../final/evidence/raw/messaging-testkit-c08.txt" ], "relations": [] }, { "title": "어댑터가 코덱도 한도도 스스로 고르지 않는다", "slug": "messaging-transport-spi-c01", "file": "state-machines-and-ownership/concept/concept-messaging-transport-spi-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-transport-spi-c01", "messaging-transport-spi-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-transport-spi-c01.txt" ], "relations": [ "멱등 종료를 보장하는 컴포넌트는 종료 이후의 등록도 정의한다", "같은 개념의 sentinel은 계층을 넘어 하나로 정한다" ] }, { "title": "회전은 변경이 아니라 교체다", "slug": "messaging-transport-spi-c03", "file": "state-machines-and-ownership/concept/concept-messaging-transport-spi-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-transport-spi-c03", "messaging-transport-spi-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-transport-spi-c03.txt" ], "relations": [ "멱등 종료를 보장하는 컴포넌트는 종료 이후의 등록도 정의한다", "같은 개념의 sentinel은 계층을 넘어 하나로 정한다" ] }, { "title": "선언된 종료 순서와 실제 종료 경로", "slug": "messaging-transport-spi-c04", "file": "state-machines-and-ownership/concept/concept-messaging-transport-spi-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-transport-spi-c04" ], "evidence": [ "../../../final/evidence/raw/messaging-transport-spi-c04.txt" ], "relations": [ "멱등 종료를 보장하는 컴포넌트는 종료 이후의 등록도 정의한다", "같은 개념의 sentinel은 계층을 넘어 하나로 정한다" ] }, { "title": "포기가 조용하지 않다는 것이 설계다", "slug": "messaging-transport-spi-c05", "file": "state-machines-and-ownership/concept/concept-messaging-transport-spi-c05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-transport-spi-c05" ], "evidence": [ "../../../final/evidence/raw/messaging-transport-spi-c05.txt" ], "relations": [ "멱등 종료를 보장하는 컴포넌트는 종료 이후의 등록도 정의한다", "같은 개념의 sentinel은 계층을 넘어 하나로 정한다" ] }, { "title": "두 자료구조가 다른 방식으로 보호되고 주석이 없다", "slug": "messaging-transport-spi-c06", "file": "state-machines-and-ownership/concept/concept-messaging-transport-spi-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-transport-spi-c06" ], "evidence": [ "../../../final/evidence/raw/messaging-transport-spi-c06.txt" ], "relations": [ "멱등 종료를 보장하는 컴포넌트는 종료 이후의 등록도 정의한다", "같은 개념의 sentinel은 계층을 넘어 하나로 정한다" ] } ], "reference": [], "question": [], "decision": [] } }, "state-ownership-and-concurrency": { "topic": "state-ownership-and-concurrency", "kinds": { "case": [ { "title": "SKIP LOCKED 로 잡은 조정 작업을 두 번째 연결이 그대로 받는다", "slug": "a05-f029-for-update-skip-locked", "file": "state-ownership-and-concurrency/case/case-a05-f029-for-update-skip-locked.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a05-f029-for-update-skip-locked", "a05-f029-for-update-skip-locked-probe" ], "evidence": [ "../../../final/evidence/raw/a05-f029-for-update-skip-locked.txt", "../../../final/evidence/raw/a05-f029-for-update-skip-locked-probe.txt" ], "relations": [ "조건부 update로 행을 claim하고 읽은 값으로 판단하지 않는다", "fenced lease — 만료 시각만으로는 부족한 이유", "CAS 튜플을 where 절에 전부 반복하고 update count를 답으로 쓴다" ] }, { "title": "recordApplied가 펜스를 비교하지 않아 밀려난 실행자가 원장을 차지한다", "slug": "a06-f013-recordapplied", "file": "state-ownership-and-concurrency/case/case-a06-f013-recordapplied.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a06-f013-recordapplied", "a06-f013-recordapplied-probe", "a06-f013-recordapplied-around" ], "evidence": [ "../../../final/evidence/raw/a06-f013-recordapplied.txt", "../../../final/evidence/raw/a06-f013-recordapplied-probe.txt", "../../../final/evidence/raw/a06-f013-recordapplied-around.txt" ], "relations": [ "fenced lease — 만료 시각만으로는 부족한 이유", "CAS 튜플을 where 절에 전부 반복하고 update count를 답으로 쓴다", "리스가 만료 시각만 기록하고 소유자를 기록하지 않아 최종 상태를 되돌릴 수 있었다" ] }, { "title": "배정 식별자 때문에 insert-first 청구가 UPSERT 가 되어 커밋된 결과를 덮었다", "slug": "assigned-id-turns-claim-into-upsert", "file": "state-ownership-and-concurrency/case/case-assigned-id-turns-claim-into-upsert.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "assigned-id-turns-claim-into-upsert" ], "evidence": [ "../../../final/evidence/raw/assigned-id-turns-claim-into-upsert.txt" ], "relations": [ "Atomic 타입의 존재는 원자성의 증거가 아니다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "커밋 증거 프레임을 두 주인이 pop해서 바깥 트랜잭션의 실패가 익명이 됐다" ] }, { "title": "배수 완료가 자기가 읽은 값으로 상태를 다시 써서 진행 중인 자격증명 회전을 되돌린다", "slug": "complete-drain-rolls-back-a-rotation", "file": "state-ownership-and-concurrency/case/case-complete-drain-rolls-back-a-rotation.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "complete-drain-rolls-back-a-rotation" ], "evidence": [ "../../../final/evidence/raw/complete-drain-rolls-back-a-rotation.txt" ], "relations": [ "Atomic 타입의 존재는 원자성의 증거가 아니다", "배정 식별자 때문에 insert-first 청구가 UPSERT가 되어 커밋된 결과를 덮었다", "재시도 안전은 증거로 결정된다" ] }, { "title": "배수 조정자가 가변이고 동기화가 없다", "slug": "grpc-admin-f03", "file": "state-ownership-and-concurrency/case/case-grpc-admin-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-admin-f03" ], "evidence": [ "../../../final/evidence/raw/grpc-admin-f03.txt" ], "relations": [] }, { "title": "깃발 홀더가 가변이고 동기화가 없다", "slug": "grpc-advanced-bootstrap-f03", "file": "state-ownership-and-concurrency/case/case-grpc-advanced-bootstrap-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-bootstrap-f03" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-bootstrap-f03.txt" ], "relations": [] }, { "title": "리졸버의 개정 가드가 비교 후 교체가 아니다", "slug": "grpc-advanced-resilience-f03", "file": "state-ownership-and-concurrency/case/case-grpc-advanced-resilience-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-resilience-f03", "grpc-advanced-resilience-f03-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-resilience-f03.txt" ], "relations": [] }, { "title": "체크포인트 전진이 ConcurrentMap 위의 확인 후 쓰기다", "slug": "grpc-advanced-streaming-f03", "file": "state-ownership-and-concurrency/case/case-grpc-advanced-streaming-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-streaming-f03" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-streaming-f03.txt" ], "relations": [] }, { "title": "rotate 가 비교 후 교체가 아니라 덮어쓰기다", "slug": "grpc-client-f01", "file": "state-ownership-and-concurrency/case/case-grpc-client-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-client-f01", "grpc-client-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-client-f01.txt" ], "relations": [] }, { "title": "비원자적 감소가 세대를 영구히 회수 불가로 만든다", "slug": "grpc-client-f02", "file": "state-ownership-and-concurrency/case/case-grpc-client-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-client-f02", "grpc-client-f02-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-client-f02.txt" ], "relations": [] }, { "title": "배수 목록의 순회가 동기화 밖에서 일어난다", "slug": "grpc-client-f03", "file": "state-ownership-and-concurrency/case/case-grpc-client-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-client-f03" ], "evidence": [ "../../../final/evidence/raw/grpc-client-f03.txt" ], "relations": [] }, { "title": "릴리스 버전 불변성이 프로세스 안에서만 성립한다", "slug": "grpc-codegen-f02", "file": "state-ownership-and-concurrency/case/case-grpc-codegen-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-codegen-f02" ], "evidence": [ "../../../final/evidence/raw/grpc-codegen-f02.txt" ], "relations": [] }, { "title": "목록으로 보고하는 검증기가 주소 수 0 에서 던진다", "slug": "grpc-discovery-f03", "file": "state-ownership-and-concurrency/case/case-grpc-discovery-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-discovery-f03" ], "evidence": [ "../../../final/evidence/raw/grpc-discovery-f03.txt" ], "relations": [] }, { "title": "markCommitted 는 던지고 markFailed 는 조용히 넘어간다", "slug": "grpc-operation-ledger-jpa-f02", "file": "state-ownership-and-concurrency/case/case-grpc-operation-ledger-jpa-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-operation-ledger-jpa-f02" ], "evidence": [ "../../../final/evidence/raw/grpc-operation-ledger-jpa-f02.txt" ], "relations": [] }, { "title": "완료 조정자가 요청 경로에서 동기화 없는 가변 리스트를 변경한다", "slug": "grpc-policy-f04", "file": "state-ownership-and-concurrency/case/case-grpc-policy-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-policy-f04", "grpc-policy-f04-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-policy-f04.txt" ], "relations": [] }, { "title": "스트림 수명 조정자의 배수 신호가 스레드를 건너면서 volatile 이 아니다", "slug": "grpc-policy-f05", "file": "state-ownership-and-concurrency/case/case-grpc-policy-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-policy-f05", "grpc-policy-f05-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-policy-f05.txt" ], "relations": [] }, { "title": "릴리스 게이트의 입력이 전부 호출자가 손으로 만드는 값이다", "slug": "grpc-testkit-f02", "file": "state-ownership-and-concurrency/case/case-grpc-testkit-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-testkit-f02" ], "evidence": [ "../../../final/evidence/raw/grpc-testkit-f02.txt" ], "relations": [] }, { "title": "저널의 itemsCompleted 단조성이 인터페이스 계약에 없다", "slug": "messaging-admin-runtime-f06", "file": "state-ownership-and-concurrency/case/case-messaging-admin-runtime-f06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-runtime-f06" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-runtime-f06.txt" ], "relations": [] }, { "title": "리플레이가 리스를 받지만 재개하지 않는다", "slug": "messaging-admin-runtime-f07", "file": "state-ownership-and-concurrency/case/case-messaging-admin-runtime-f07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-runtime-f07" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-runtime-f07.txt" ], "relations": [] }, { "title": "반환을 순번에 맞추는 조각이 production 에 없고, 시험이 그 자리를 스스로 메운다", "slug": "messaging-rabbit-f02", "file": "state-ownership-and-concurrency/case/case-messaging-rabbit-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-rabbit-f02", "messaging-rabbit-f02-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-rabbit-f02.txt" ], "relations": [] } ], "concept": [], "reference": [ { "title": "같은 튜닝 값이 두 계층에 있으면 어느 쪽이 이기는지 정한다", "slug": "messaging-claim-check-f02", "file": "state-ownership-and-concurrency/reference/reference-messaging-claim-check-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "배포 아티팩트가 싣지만 아무도 부르지 않고, 다른 곳의 에러 메시지가 이 경로를 권한다", "예외 승격이 에러 코드 문자열 접미사에 의존한다" ] }, { "title": "가변 필드로 상태 전이를 표현하면 가시성을 함께 정한다", "slug": "messaging-security-f08", "file": "state-ownership-and-concurrency/reference/reference-messaging-security-f08.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "종료 시 자격증명 소거가 호출되지 않는다", "같은 TLS posture를 두 클래스가 다른 엄격도로 검사한다", "권한 거부가 `AUTHORIZATION`이 아니라 `CONFIGURATION`으로 기록된다" ] }, { "title": "함께 읽히는 두 맵은 한 값으로 묶는다", "slug": "messaging-spring-cloud-stream-bridge-f04", "file": "state-ownership-and-concurrency/reference/reference-messaging-spring-cloud-stream-bridge-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [] }, { "title": "에러 메시지가 지시하는 설정은 그 설정을 읽는 코드와 함께 존재해야 한다", "slug": "messaging-spring-cloud-stream-bridge-f06", "file": "state-ownership-and-concurrency/reference/reference-messaging-spring-cloud-stream-bridge-f06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [] } ], "question": [], "decision": [] } }, "transaction-and-consistency-models": { "topic": "transaction-and-consistency-models", "kinds": { "case": [], "concept": [ { "title": "요청 경로에 있는 것은 stomp 패키지가 참조하는 것뿐이다", "slug": "adapter-inbound-websocket-c02", "file": "transaction-and-consistency-models/concept/concept-adapter-inbound-websocket-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-inbound-websocket-c02" ], "evidence": [ "../../../final/evidence/raw/adapter-inbound-websocket-c02.txt" ], "relations": [] }, { "title": "등록되지 않은 스크립트는 서버에 닿을 방법이 없다", "slug": "adapter-outbound-cache-redis-c13", "file": "transaction-and-consistency-models/concept/concept-adapter-outbound-cache-redis-c13.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-cache-redis-c13", "adapter-outbound-cache-redis-c13-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-cache-redis-c13.txt" ], "relations": [] }, { "title": "능력 어휘와 지원 등급과 실제 보고를 나눈다", "slug": "adapter-outbound-persistence-jpa-c02", "file": "transaction-and-consistency-models/concept/concept-adapter-outbound-persistence-jpa-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c02", "adapter-outbound-persistence-jpa-c02-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c02.txt" ], "relations": [] }, { "title": "두 트랜잭션 경계가 공존하고 문서만 어긋난다", "slug": "adapter-outbound-persistence-jpa-c10", "file": "transaction-and-consistency-models/concept/concept-adapter-outbound-persistence-jpa-c10.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c10" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c10.txt" ], "relations": [] }, { "title": "Spring stereotype이 있다고 runtime에 도달하지 않는다", "slug": "adapter-outbound-persistence-jpa-c11", "file": "transaction-and-consistency-models/concept/concept-adapter-outbound-persistence-jpa-c11.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c11" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c11.txt" ], "relations": [] }, { "title": "SQLSTATE가 retryable이라고 해서 use case를 다시 돌리지 않는다", "slug": "adapter-outbound-persistence-jpa-c14", "file": "transaction-and-consistency-models/concept/concept-adapter-outbound-persistence-jpa-c14.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c14" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c14.txt" ], "relations": [] }, { "title": "한 번의 물리 시도만 담당하고 재시도는 하지 않는다", "slug": "adapter-outbound-persistence-jpa-c15", "file": "transaction-and-consistency-models/concept/concept-adapter-outbound-persistence-jpa-c15.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c15" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c15.txt" ], "relations": [] }, { "title": "완료 불명과 되돌릴 수 없는 부작용에서는 재시도하지 않는다", "slug": "adapter-outbound-persistence-jpa-c16", "file": "transaction-and-consistency-models/concept/concept-adapter-outbound-persistence-jpa-c16.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c16" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c16.txt" ], "relations": [] }, { "title": "문서가 지목하는 조정 레코드를 쓰는 코드가 없다", "slug": "adapter-outbound-persistence-jpa-c18", "file": "transaction-and-consistency-models/concept/concept-adapter-outbound-persistence-jpa-c18.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c18" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c18.txt" ], "relations": [] }, { "title": "참조 수가 0이어도 스캔으로 도달한다", "slug": "adapter-outbound-persistence-jpa-c20", "file": "transaction-and-consistency-models/concept/concept-adapter-outbound-persistence-jpa-c20.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c20" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c20.txt" ], "relations": [] }, { "title": "이름이 비슷한 두 번역 계열의 출력 계약이 다르다", "slug": "adapter-outbound-persistence-jpa-c21", "file": "transaction-and-consistency-models/concept/concept-adapter-outbound-persistence-jpa-c21.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c21" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c21.txt" ], "relations": [] }, { "title": "adapter 오류 경계 쪽 번역기는 다른 출력을 낸다", "slug": "adapter-outbound-persistence-jpa-c22", "file": "transaction-and-consistency-models/concept/concept-adapter-outbound-persistence-jpa-c22.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c22" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c22.txt" ], "relations": [] }, { "title": "설치되는 bean 셋과 설치되지 않는 구현 셋", "slug": "adapter-outbound-persistence-jpa-c23", "file": "transaction-and-consistency-models/concept/concept-adapter-outbound-persistence-jpa-c23.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c23" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c23.txt" ], "relations": [] }, { "title": "쓰기 경로마다 트랜잭션 소유가 다르다", "slug": "adapter-outbound-persistence-jpa-c26", "file": "transaction-and-consistency-models/concept/concept-adapter-outbound-persistence-jpa-c26.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c26", "adapter-outbound-persistence-jpa-c26-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c26.txt" ], "relations": [] }, { "title": "중복 재생이 owner 검증보다 먼저 저장된 owner를 돌려준다", "slug": "adapter-outbound-persistence-jpa-c37", "file": "transaction-and-consistency-models/concept/concept-adapter-outbound-persistence-jpa-c37.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c37" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c37.txt" ], "relations": [] }, { "title": "여섯 package만 스캔하므로 같은 리프 안에서도 도달성이 다르다", "slug": "adapter-outbound-persistence-jpa-c42", "file": "transaction-and-consistency-models/concept/concept-adapter-outbound-persistence-jpa-c42.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c42", "adapter-outbound-persistence-jpa-c42-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c42.txt" ], "relations": [] }, { "title": "Stable 스캔 목록에 experimental package가 이미 들어 있다", "slug": "adapter-outbound-persistence-jpa-c51", "file": "transaction-and-consistency-models/concept/concept-adapter-outbound-persistence-jpa-c51.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-jpa-c51", "adapter-outbound-persistence-jpa-c51-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-jpa-c51.txt" ], "relations": [] }, { "title": "아직 쓰이지 않은 연산에도 같은 불변식이 성립하게 만든 순서", "slug": "adapter-outbound-persistence-mongo-c03", "file": "transaction-and-consistency-models/concept/concept-adapter-outbound-persistence-mongo-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "adapter-outbound-persistence-mongo-c03", "adapter-outbound-persistence-mongo-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/adapter-outbound-persistence-mongo-c03.txt" ], "relations": [] }, { "title": "예외가 발생했다는 것을 rollback으로 단순화하지 않는다", "slug": "application-core-c03", "file": "transaction-and-consistency-models/concept/concept-application-core-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "application-core-c03", "application-core-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/application-core-c03.txt" ], "relations": [ "legacy storage/notification compatibility surface의 제거 조건 추적" ] }, { "title": "승인이 마감보다 먼저이고 멱등이 검증보다 먼저다", "slug": "grpc-server-c01", "file": "transaction-and-consistency-models/concept/concept-grpc-server-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-server-c01", "grpc-server-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-server-c01.txt" ], "relations": [] }, { "title": "메커니즘 전체가 하나의 SQL 문장에 있다", "slug": "messaging-inbox-jdbc-postgresql-c01", "file": "transaction-and-consistency-models/concept/concept-messaging-inbox-jdbc-postgresql-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-inbox-jdbc-postgresql-c01" ], "evidence": [ "../../../final/evidence/raw/messaging-inbox-jdbc-postgresql-c01.txt" ], "relations": [ "컬럼 폭은 애플리케이션 검증과 짝을 이룬다", "같은 안전 규칙은 한 공식과 한 강제 시점을 갖는다" ] }, { "title": "starter가 셋을 만들고 InboxRepository는 그 목록에 없다", "slug": "messaging-inbox-jdbc-postgresql-c02", "file": "transaction-and-consistency-models/concept/concept-messaging-inbox-jdbc-postgresql-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-inbox-jdbc-postgresql-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-inbox-jdbc-postgresql-c02.txt" ], "relations": [ "컬럼 폭은 애플리케이션 검증과 짝을 이룬다", "같은 안전 규칙은 한 공식과 한 강제 시점을 갖는다" ] }, { "title": "두 오버로드가 있었고 호출되는 쪽이 틀린 쪽이었다", "slug": "messaging-inbox-jdbc-postgresql-c03", "file": "transaction-and-consistency-models/concept/concept-messaging-inbox-jdbc-postgresql-c03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-inbox-jdbc-postgresql-c03", "messaging-inbox-jdbc-postgresql-c03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-inbox-jdbc-postgresql-c03.txt" ], "relations": [ "컬럼 폭은 애플리케이션 검증과 짝을 이룬다", "같은 안전 규칙은 한 공식과 한 강제 시점을 갖는다" ] }, { "title": "모르는 것을 실패로 취급하지 않는다", "slug": "messaging-outbox-jdbc-postgresql-c01", "file": "transaction-and-consistency-models/concept/concept-messaging-outbox-jdbc-postgresql-c01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-outbox-jdbc-postgresql-c01", "messaging-outbox-jdbc-postgresql-c01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-outbox-jdbc-postgresql-c01.txt" ], "relations": [] }, { "title": "starter가 만들지 않는 셋은 애플리케이션이 직접 등록해야 한다", "slug": "messaging-outbox-jdbc-postgresql-c02", "file": "transaction-and-consistency-models/concept/concept-messaging-outbox-jdbc-postgresql-c02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-outbox-jdbc-postgresql-c02" ], "evidence": [ "../../../final/evidence/raw/messaging-outbox-jdbc-postgresql-c02.txt" ], "relations": [] }, { "title": "쓰기와 배출과 정리와 저널이 각각 다른 경로다", "slug": "messaging-outbox-jdbc-postgresql-c04", "file": "transaction-and-consistency-models/concept/concept-messaging-outbox-jdbc-postgresql-c04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-outbox-jdbc-postgresql-c04" ], "evidence": [ "../../../final/evidence/raw/messaging-outbox-jdbc-postgresql-c04.txt" ], "relations": [] }, { "title": "만들어졌지만 아무도 부르지 않는다를 이름 붙인 유일한 자리", "slug": "messaging-outbox-jdbc-postgresql-c06", "file": "transaction-and-consistency-models/concept/concept-messaging-outbox-jdbc-postgresql-c06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-outbox-jdbc-postgresql-c06" ], "evidence": [ "../../../final/evidence/raw/messaging-outbox-jdbc-postgresql-c06.txt" ], "relations": [] } ], "reference": [], "question": [], "decision": [] } }, "transaction-deadline-and-pool": { "topic": "transaction-deadline-and-pool", "kinds": { "case": [ { "title": "'connection-timeout: 5s가 모든 prod 배포를 시작 실패시켰고 local만 통과했다'", "slug": "a-five-second-string-that-broke-every-prod-deploy", "file": "transaction-deadline-and-pool/case/case-a-five-second-string-that-broke-every-prod-deploy.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-five-second-string-that-broke-every-prod-deploy-bind", "a-five-second-string-that-broke-every-prod-deploy" ], "evidence": [ "../../../final/evidence/raw/a-five-second-string-that-broke-every-prod-deploy-bind.txt", "../../../final/evidence/raw/a-five-second-string-that-broke-every-prod-deploy.txt" ], "relations": [ "로컬이 다른 DB면 로컬 테스트는 다른 시스템에 대한 진술이다", "validator가 요청을 서비스하지 않는 datasource를 검증하고 있었다" ] }, { "title": "validator가 요청을 서비스하지 않는 datasource를 검증하고 있었다", "slug": "a-validator-checking-the-wrong-datasource", "file": "transaction-deadline-and-pool/case/case-a-validator-checking-the-wrong-datasource.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-validator-checking-the-wrong-datasource", "a-validator-checking-the-wrong-datasource-run" ], "evidence": [ "../../../final/evidence/raw/a-validator-checking-the-wrong-datasource.txt", "../../../final/evidence/raw/a-validator-checking-the-wrong-datasource-run.txt" ], "relations": [ "connection-timeout: 5s가 모든 prod 배포를 시작 실패시켰고 local만 통과했다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "@Bean이 있다는 것은 조립 증거가 아니다" ] }, { "title": "REQUIRES_NEW가 바깥 커넥션을 핀한 채 새 커넥션을 딴다", "slug": "requires-new-pins-the-outer-connection", "file": "transaction-deadline-and-pool/case/case-requires-new-pins-the-outer-connection.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "requires-new-pins-the-outer-connection" ], "evidence": [ "../../../final/evidence/raw/requires-new-pins-the-outer-connection.txt" ], "relations": [ "REQUIRES_NEW의 커넥션 비용과 풀 사이징 제약", "풀 계약 레인이 실행되지 않아 포화 동작이 확인되지 않았다", "커밋 증거 단계 — NOT_STARTED에서 UNKNOWN까지" ] } ], "concept": [ { "title": "호출 예산에서 DB 로컬 타임아웃까지의 데드라인 전파", "slug": "deadline-propagation", "file": "transaction-deadline-and-pool/concept/concept-deadline-propagation.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "deadline-propagation", "deadline-propagation-diagram" ], "evidence": [ "../../../final/evidence/raw/deadline-propagation.txt" ], "relations": [ "데드라인은 호출 예산에서 시작해 세 단계로 좁힌다", "쓰기 트랜잭션에는 유한 타임아웃이 필수다", "세션 스코프 설정은 풀로 돌아간 커넥션에 남는다" ] }, { "title": "REQUIRES_NEW의 커넥션 비용과 풀 사이징 제약", "slug": "requires-new-connection-cost", "file": "transaction-deadline-and-pool/concept/concept-requires-new-connection-cost.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "requires-new-connection-cost" ], "evidence": [ "../../../final/evidence/raw/requires-new-connection-cost.txt" ], "relations": [ "REQUIRES_NEW가 바깥 커넥션을 핀한 채 새 커넥션을 딴다", "호출 예산에서 DB 로컬 타임아웃까지의 데드라인 전파", "풀 계약 레인이 실행되지 않아 포화 동작이 확인되지 않았다" ] } ], "reference": [ { "title": "데드라인은 호출 예산에서 시작해 세 단계로 좁힌다", "slug": "deadline-narrows-in-three-stages", "file": "transaction-deadline-and-pool/reference/reference-deadline-narrows-in-three-stages.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "호출 예산에서 DB 로컬 타임아웃까지의 데드라인 전파", "쓰기 트랜잭션에는 유한 타임아웃이 필수다", "재시도 가능성은 멱등성과 실패 범주를 함께 봐야 정해진다" ] }, { "title": "세션 스코프 설정은 풀로 돌아간 커넥션에 남는다", "slug": "session-scoped-settings-outlive-the-transaction", "file": "transaction-deadline-and-pool/reference/reference-session-scoped-settings-outlive-the-transaction.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "호출 예산에서 DB 로컬 타임아웃까지의 데드라인 전파", "connection-timeout이 5s 문자열로 출하되어 prod와 dev 배포가 전부 시작에 실패했다" ] }, { "title": "쓰기 트랜잭션에는 유한 타임아웃이 필수다", "slug": "write-transactions-need-a-finite-timeout", "file": "transaction-deadline-and-pool/reference/reference-write-transactions-need-a-finite-timeout.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "데드라인은 호출 예산에서 시작해 세 단계로 좁힌다", "커밋 모호성 판정은 넓혀도 좁혀도 해롭다" ] } ], "question": [ { "title": "풀 계약 레인이 실행되지 않아 포화 동작이 확인되지 않았다", "slug": "pool-contract-lane-not-executed", "file": "transaction-deadline-and-pool/question/openquestion-pool-contract-lane-not-executed.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "컨테이너가 필요한 특수 레인의 실제 결과를 실행으로 확인하지 않았다", "REQUIRES_NEW가 바깥 커넥션을 핀한 채 새 커넥션을 딴다", "certified라 불리던 레인이 threshold를 하나도 비교하지 않고 있었다" ] } ], "decision": [ { "title": "inRootWrite는 suspend하지 않고 fail-fast한다", "slug": "in-root-write-fails-fast", "file": "transaction-deadline-and-pool/decision/decision-in-root-write-fails-fast.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "REQUIRES_NEW의 커넥션 비용과 풀 사이징 제약", "트랜잭션 템플릿은 모드별로 미리 만들어 둔다", "트랜잭션 결과 대수 — 다섯 변형이 각각 답하는 질문" ] }, { "title": "트랜잭션 템플릿은 모드별로 미리 만들어 둔다", "slug": "templates-are-built-once-per-mode", "file": "transaction-deadline-and-pool/decision/decision-templates-are-built-once-per-mode.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "호출 예산에서 DB 로컬 타임아웃까지의 데드라인 전파", "Atomic 타입의 존재는 원자성의 증거가 아니다" ] } ] } }, "transport-and-provider-semantics": { "topic": "transport-and-provider-semantics", "kinds": { "case": [ { "title": "능력 상수가 프로파일 조건보다 오래 살아서 중복 제거 없는 목적지가 가드를 통과한다", "slug": "capability-constant-outlives-its-condition", "file": "transport-and-provider-semantics/case/case-capability-constant-outlives-its-condition.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "capability-constant-outlives-its-condition" ], "evidence": [ "../../../final/evidence/raw/capability-constant-outlives-its-condition.txt" ], "relations": [ "같은 자동 설정 안에서 검증기 하나만 감싸이지 않아 트랜잭션 조건이 검사되지 않는다", "지원 매트릭스가 코드와 반대를 말한다", "조용히 약해진 보증은 사고 전까지 동작하는 것과 구분되지 않는다" ] }, { "title": "자동 설정이 transport 를 읽지 않고 전송을 하드코딩한다", "slug": "grpc-spring-boot-starter-f02", "file": "transport-and-provider-semantics/case/case-grpc-spring-boot-starter-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-spring-boot-starter-f02" ], "evidence": [ "../../../final/evidence/raw/grpc-spring-boot-starter-f02.txt" ], "relations": [] }, { "title": "토폴로지 검증 스택이 두 벌이고 판정이 어긋난다", "slug": "messaging-admin-runtime-f02", "file": "transport-and-provider-semantics/case/case-messaging-admin-runtime-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-runtime-f02", "messaging-admin-runtime-f02-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-runtime-f02.txt" ], "relations": [] }, { "title": "실패한 리드라이브 항목의 사유가 어디에도 남지 않는다", "slug": "messaging-admin-runtime-f10", "file": "transport-and-provider-semantics/case/case-messaging-admin-runtime-f10.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-runtime-f10" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-runtime-f10.txt" ], "relations": [] }, { "title": "배치 metadata를 만들고 넘길 곳이 없다", "slug": "messaging-core-api-f02", "file": "transport-and-provider-semantics/case/case-messaging-core-api-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-core-api-f02", "messaging-core-api-f02-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-core-api-f02.txt" ], "relations": [] }, { "title": "SQL 실패가 재시도 불가로 분류된다", "slug": "messaging-inbox-jdbc-postgresql-f03", "file": "transport-and-provider-semantics/case/case-messaging-inbox-jdbc-postgresql-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-inbox-jdbc-postgresql-f03", "messaging-inbox-jdbc-postgresql-f03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-inbox-jdbc-postgresql-f03.txt" ], "relations": [ "컬럼 폭은 애플리케이션 검증과 짝을 이룬다", "같은 안전 규칙은 한 공식과 한 강제 시점을 갖는다" ] }, { "title": "천장에 닿아 일시정지된 파티션을 재개하는 경로가 없다", "slug": "messaging-kafka-f02", "file": "transport-and-provider-semantics/case/case-messaging-kafka-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-kafka-f02", "messaging-kafka-f02-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-kafka-f02.txt" ], "relations": [] }, { "title": "오염된 재시도 헤더가 격리되지 않고 무한 pause-and-seek 을 만든다", "slug": "messaging-kafka-f03", "file": "transport-and-provider-semantics/case/case-messaging-kafka-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-kafka-f03", "messaging-kafka-f03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-kafka-f03.txt" ], "relations": [] }, { "title": "시계를 주입받는 클래스가 한 곳에서만 벽시계를 읽는다", "slug": "messaging-kafka-f04", "file": "transport-and-provider-semantics/case/case-messaging-kafka-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-kafka-f04", "messaging-kafka-f04-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-kafka-f04.txt" ], "relations": [] }, { "title": "결함으로 판정된 메서드가 남아 있고, 실브로커 증명이 그것 위에서 돈다", "slug": "messaging-kafka-f05", "file": "transport-and-provider-semantics/case/case-messaging-kafka-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-kafka-f05" ], "evidence": [ "../../../final/evidence/raw/messaging-kafka-f05.txt" ], "relations": [] }, { "title": "등록\"이 아무것도 등록하지 않고 성공을 반환한다", "slug": "messaging-kafka-share-experimental-f01", "file": "transport-and-provider-semantics/case/case-messaging-kafka-share-experimental-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-kafka-share-experimental-f01", "messaging-kafka-share-experimental-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-kafka-share-experimental-f01.txt" ], "relations": [ "허용 의존 목록은 상한이므로 미사용을 잡지 않는다 — 그것을 잡으려면 별도 검사가 필요하다", "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "에러 메시지가 지시하는 설정은 그 설정을 읽는 코드와 함께 존재해야 한다", "구성 오류는 한 예외 타입과 안정 코드로 보고한다" ] }, { "title": "닫힌 전송의 거절이 영구 업무 실패로 분류된다", "slug": "messaging-nats-experimental-f02", "file": "transport-and-provider-semantics/case/case-messaging-nats-experimental-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-nats-experimental-f02" ], "evidence": [ "../../../final/evidence/raw/messaging-nats-experimental-f02.txt" ], "relations": [] }, { "title": "NatsJetStreamProfileValidator 를 부르는 곳이 javadoc 링크 하나뿐이다", "slug": "messaging-nats-experimental-f03", "file": "transport-and-provider-semantics/case/case-messaging-nats-experimental-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-nats-experimental-f03", "messaging-nats-experimental-f03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-nats-experimental-f03.txt" ], "relations": [] }, { "title": "재시도 엔진과 DLQ 조정자가 bean으로 만들어지고 주입되는 곳이 없다", "slug": "messaging-policy-f01", "file": "transport-and-provider-semantics/case/case-messaging-policy-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-policy-f01", "messaging-policy-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-policy-f01.txt" ], "relations": [ "구성 오류는 한 예외 타입과 안정 코드로 보고한다", "저장소 밖 문서를 절 번호로 인용하지 않는다", "부팅 경로의 알고리즘 복잡도는 문서화한다" ] }, { "title": "재시도와 DLQ 각각에 두 개의 구현이 있고 정본이 표시되지 않았다", "slug": "messaging-policy-f03", "file": "transport-and-provider-semantics/case/case-messaging-policy-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-policy-f03" ], "evidence": [ "../../../final/evidence/raw/messaging-policy-f03.txt" ], "relations": [ "구성 오류는 한 예외 타입과 안정 코드로 보고한다", "저장소 밖 문서를 절 번호로 인용하지 않는다", "부팅 경로의 알고리즘 복잡도는 문서화한다" ] }, { "title": "DLQ 메타데이터의 두 시각이 항상 같다", "slug": "messaging-policy-f04", "file": "transport-and-provider-semantics/case/case-messaging-policy-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-policy-f04" ], "evidence": [ "../../../final/evidence/raw/messaging-policy-f04.txt" ], "relations": [ "구성 오류는 한 예외 타입과 안정 코드로 보고한다", "저장소 밖 문서를 절 번호로 인용하지 않는다", "부팅 경로의 알고리즘 복잡도는 문서화한다" ] }, { "title": "닫힌 전송의 거절이 영구 업무 실패로 분류된다", "slug": "messaging-pulsar-experimental-f01", "file": "transport-and-provider-semantics/case/case-messaging-pulsar-experimental-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-pulsar-experimental-f01" ], "evidence": [ "../../../final/evidence/raw/messaging-pulsar-experimental-f01.txt" ], "relations": [] }, { "title": "확인 등급이 요구에서 파생되고, 그 요구를 뒷받침하는 강제는 목적지 종류 하나에만 걸린다", "slug": "messaging-rabbit-f01", "file": "transport-and-provider-semantics/case/case-messaging-rabbit-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-rabbit-f01" ], "evidence": [ "../../../final/evidence/raw/messaging-rabbit-f01.txt" ], "relations": [] }, { "title": "SCRAM 자격을 RabbitMQ 의 데모 기구로 조용히 매핑한다", "slug": "messaging-rabbit-f03", "file": "transport-and-provider-semantics/case/case-messaging-rabbit-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-rabbit-f03" ], "evidence": [ "../../../final/evidence/raw/messaging-rabbit-f03.txt" ], "relations": [] }, { "title": "pause 의 의미가 SPI 하나 뒤에서 두 브로커에 다르게 구현된다", "slug": "messaging-rabbit-f05", "file": "transport-and-provider-semantics/case/case-messaging-rabbit-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-rabbit-f05" ], "evidence": [ "../../../final/evidence/raw/messaging-rabbit-f05.txt" ], "relations": [] }, { "title": "Faults 내부클래스 57줄이 3개 모듈에 바이트 단위로 복제되어 있다", "slug": "messaging-testkit-f03", "file": "transport-and-provider-semantics/case/case-messaging-testkit-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-testkit-f03" ], "evidence": [ "../../../final/evidence/raw/messaging-testkit-f03.txt" ], "relations": [] } ], "concept": [], "reference": [ { "title": "에러 메시지가 지시하는 설정은 그 설정을 읽는 코드와 함께 존재해야 한다", "slug": "messaging-kafka-share-experimental-f06", "file": "transport-and-provider-semantics/reference/reference-messaging-kafka-share-experimental-f06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "\"등록\"이 아무것도 등록하지 않고 성공을 반환한다" ] }, { "title": "안정 코드는 운영자의 행동이 갈리는 지점마다 나눈다", "slug": "messaging-runtime-core-f04", "file": "transport-and-provider-semantics/reference/reference-messaging-runtime-core-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "관측이 구현·호출부·주입 자리를 모두 갖추고도 출하에서 no-op이다", "소비 오케스트레이터가 조립되지 않는다", "선언된 content type과 실제 인코딩이 조용히 갈라질 수 있다" ] }, { "title": "실패 코드는 운영자의 다음 행동이 갈리는 지점마다 나눈다", "slug": "messaging-schema-json-f02", "file": "transport-and-provider-semantics/reference/reference-messaging-schema-json-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "포맷 중립 payload 정책이, 자기 상수를 두고 JSON codec의 상수를 참조한다" ] }, { "title": "멱등 종료를 보장하는 컴포넌트는 종료 이후의 등록도 정의한다", "slug": "messaging-transport-spi-f02", "file": "transport-and-provider-semantics/reference/reference-messaging-transport-spi-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "드레인 마감 30초가 세 곳에서 독립적으로 결정된다" ] }, { "title": "같은 개념의 sentinel은 계층을 넘어 하나로 정한다", "slug": "messaging-transport-spi-f03", "file": "transport-and-provider-semantics/reference/reference-messaging-transport-spi-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "드레인 마감 30초가 세 곳에서 독립적으로 결정된다" ] } ], "question": [ { "title": "브로커 홉 추적기가 소비자를 갖지 않는다", "slug": "messaging-observability-f03", "file": "transport-and-provider-semantics/question/openquestion-messaging-observability-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "타입이 문서화한 불변식은 타입이 강제한다" ] }, { "title": "브리지의 바인더 쪽 절반이 없다", "slug": "messaging-spring-cloud-stream-bridge-f02", "file": "transport-and-provider-semantics/question/openquestion-messaging-spring-cloud-stream-bridge-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "허용 의존 목록은 상한이므로 미사용을 잡지 않는다", "등록을 받는 컴포넌트는 해제도 제공한다", "함께 읽히는 두 맵은 한 값으로 묶는다", "에러 메시지가 지시하는 설정은 그 설정을 읽는 코드와 함께 존재해야 한다", "한 개념의 등록 상태를 두 객체가 나눠 갖지 않는다" ] } ], "decision": [] } }, "verification-path-coverage": { "topic": "verification-path-coverage", "kinds": { "case": [ { "title": "rejectNewAdmission() 이 단계만 기록하고 아무것도 거절하지 않는다", "slug": "grpc-admin-f01", "file": "verification-path-coverage/case/case-grpc-admin-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-admin-f01", "grpc-admin-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-admin-f01.txt" ], "relations": [] }, { "title": "등급 재정의에 하한이 없어 \"켤 수 없다\" 는 등급이 켜질 수 있다", "slug": "grpc-advanced-bootstrap-f01", "file": "verification-path-coverage/case/case-grpc-advanced-bootstrap-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-bootstrap-f01" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-bootstrap-f01.txt" ], "relations": [] }, { "title": "capabilitiesDraggedAlong 은 독립성을 증명하지 않는다. 상수를 상수와 비교한다", "slug": "grpc-advanced-bootstrap-f04", "file": "verification-path-coverage/case/case-grpc-advanced-bootstrap-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-bootstrap-f04" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-bootstrap-f04.txt" ], "relations": [] }, { "title": "반응형 표면 두 타입은 테스트조차 없다", "slug": "grpc-advanced-compat-f02", "file": "verification-path-coverage/case/case-grpc-advanced-compat-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-compat-f02" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-compat-f02.txt" ], "relations": [] }, { "title": "저장소가 참조 프록시 설정을 갖고 있는데, 그것을 판정할 코드에 넣지 않는다", "slug": "grpc-advanced-compat-f03", "file": "verification-path-coverage/case/case-grpc-advanced-compat-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-advanced-compat-f03" ], "evidence": [ "../../../final/evidence/raw/grpc-advanced-compat-f03.txt" ], "relations": [] }, { "title": "Buf 수명주기 태스크 목록이 빌드와 대조되지 않는다. 테스트는 목록을 자기 자신과 비교한다", "slug": "grpc-codegen-f01", "file": "verification-path-coverage/case/case-grpc-codegen-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-codegen-f01" ], "evidence": [ "../../../final/evidence/raw/grpc-codegen-f01.txt" ], "relations": [] }, { "title": "sha256: 검사가 길이 15자 이상만 요구한다. 저장소 자신의 테스트가 32자 해시를 통과시킨다", "slug": "grpc-codegen-f04", "file": "verification-path-coverage/case/case-grpc-codegen-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-codegen-f04" ], "evidence": [ "../../../final/evidence/raw/grpc-codegen-f04.txt" ], "relations": [] }, { "title": "모듈 목록 테스트가 레지스트리와 목록을 붙들지 않는다", "slug": "grpc-core-api-f02", "file": "verification-path-coverage/case/case-grpc-core-api-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-core-api-f02" ], "evidence": [ "../../../final/evidence/raw/grpc-core-api-f02.txt" ], "relations": [] }, { "title": "두 아키텍처 규칙이 저장소 소스에 적용되지 않는다", "slug": "grpc-server-f01", "file": "verification-path-coverage/case/case-grpc-server-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-server-f01", "grpc-server-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-server-f01.txt" ], "relations": [] }, { "title": "네 레인이 check 에 붙지 않고, 이 가족을 이름으로 부르는 워크플로가 없다", "slug": "grpc-testkit-f01", "file": "verification-path-coverage/case/case-grpc-testkit-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-testkit-f01", "grpc-testkit-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-testkit-f01.txt" ], "relations": [] }, { "title": "고장 레인의 유일한 실소켓 시험이 자기가 관측한 것을 버리고 리터럴로 증거를 만든다", "slug": "grpc-testkit-f03", "file": "verification-path-coverage/case/case-grpc-testkit-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-testkit-f03", "grpc-testkit-f03-diagram" ], "evidence": [ "../../../final/evidence/raw/grpc-testkit-f03.txt" ], "relations": [] }, { "title": "호환성 표의 레인 이름과 빌드의 레인 이름이 서로 다른 집합이다", "slug": "grpc-testkit-f04", "file": "verification-path-coverage/case/case-grpc-testkit-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "grpc-testkit-f04" ], "evidence": [ "../../../final/evidence/raw/grpc-testkit-f04.txt" ], "relations": [] }, { "title": "DestructiveOperationGuard 의 두 분기가 문서에도 없고 테스트에도 없다", "slug": "messaging-admin-api-f01", "file": "verification-path-coverage/case/case-messaging-admin-api-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-admin-api-f01", "messaging-admin-api-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-admin-api-f01.txt" ], "relations": [] }, { "title": "상호운용을 위한 매퍼가 명세 준수 이벤트를 분류되지 않은 예외로 거절한다", "slug": "messaging-cloudevents-f01", "file": "verification-path-coverage/case/case-messaging-cloudevents-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-cloudevents-f01", "messaging-cloudevents-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-cloudevents-f01.txt" ], "relations": [ "왕복이라 부르는 테스트는 무엇을 보존하지 않는지도 적는다", "문서가 범위를 제한하면 그 제한을 누가 강제하는지 같이 적는다" ] }, { "title": "속성을 이름으로 주장하는 테스트가 그 속성을 보일 수 없는 fake 위에서 통과한다", "slug": "messaging-inbox-jdbc-postgresql-f02", "file": "verification-path-coverage/case/case-messaging-inbox-jdbc-postgresql-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-inbox-jdbc-postgresql-f02", "messaging-inbox-jdbc-postgresql-f02-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-inbox-jdbc-postgresql-f02.txt" ], "relations": [ "컬럼 폭은 애플리케이션 검증과 짝을 이룬다", "같은 안전 규칙은 한 공식과 한 강제 시점을 갖는다" ] }, { "title": "deduplicatedPublish 를 무조건 참으로 선언하는데 실제 중복 제거는 프로파일에 창이 있을 때만 일어난다", "slug": "messaging-nats-experimental-f01", "file": "verification-path-coverage/case/case-messaging-nats-experimental-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-nats-experimental-f01", "messaging-nats-experimental-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-nats-experimental-f01.txt" ], "relations": [] }, { "title": "경과 시간 회귀를 막으려는 어셈블이 항상 참이다", "slug": "messaging-nats-experimental-f04", "file": "verification-path-coverage/case/case-messaging-nats-experimental-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-nats-experimental-f04" ], "evidence": [ "../../../final/evidence/raw/messaging-nats-experimental-f04.txt" ], "relations": [] }, { "title": "배포되는 Debezium 설정이 수정 이전 버전이다", "slug": "messaging-outbox-jdbc-postgresql-f02", "file": "verification-path-coverage/case/case-messaging-outbox-jdbc-postgresql-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-outbox-jdbc-postgresql-f02", "messaging-outbox-jdbc-postgresql-f02-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-outbox-jdbc-postgresql-f02.txt" ], "relations": [] }, { "title": "역슬래시로 끝나는 헤더 값이 헤더 맵을 깨뜨린다", "slug": "messaging-outbox-jdbc-postgresql-f03", "file": "verification-path-coverage/case/case-messaging-outbox-jdbc-postgresql-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-outbox-jdbc-postgresql-f03", "messaging-outbox-jdbc-postgresql-f03-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-outbox-jdbc-postgresql-f03.txt" ], "relations": [] }, { "title": "한 인터페이스가 같은 전이의 두 세대를 갖고, 안전하지 않은 쪽에 @Deprecated가 없다", "slug": "messaging-reliability-api-f01", "file": "verification-path-coverage/case/case-messaging-reliability-api-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-reliability-api-f01", "messaging-reliability-api-f01-diagram" ], "evidence": [ "../../../final/evidence/raw/messaging-reliability-api-f01.txt" ], "relations": [ "계약만 담는 leaf도 계약의 거절 조건은 자기 레인에서 검증한다", "record의 `equals`를 좁히면 이유를 적는다", "호출 컨텍스트가 계약이면 그 컨텍스트를 검증할 수단을 함께 정한다" ] }, { "title": "배치 발행자가 CompletionStage 를 돌려주면서 동기 예외를 던진다", "slug": "messaging-spring-boot-starter-f05", "file": "verification-path-coverage/case/case-messaging-spring-boot-starter-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-spring-boot-starter-f05" ], "evidence": [ "../../../final/evidence/raw/messaging-spring-boot-starter-f05.txt" ], "relations": [ "검증기는 발행이 아니라 주입이 강제다" ] }, { "title": "항등식을 단언하는 테스트가 하나 있다", "slug": "messaging-testkit-f07", "file": "verification-path-coverage/case/case-messaging-testkit-f07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-testkit-f07" ], "evidence": [ "../../../final/evidence/raw/messaging-testkit-f07.txt" ], "relations": [] }, { "title": "드레인 마감 30초가 세 곳에서 독립적으로 결정된다", "slug": "messaging-transport-spi-f01", "file": "verification-path-coverage/case/case-messaging-transport-spi-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "messaging-transport-spi-f01" ], "evidence": [ "../../../final/evidence/raw/messaging-transport-spi-f01.txt" ], "relations": [ "멱등 종료를 보장하는 컴포넌트는 종료 이후의 등록도 정의한다", "같은 개념의 sentinel은 계층을 넘어 하나로 정한다" ] } ], "concept": [], "reference": [ { "title": "왕복이라 부르는 테스트는 무엇을 보존하지 않는지도 적는다", "slug": "messaging-cloudevents-f03", "file": "verification-path-coverage/reference/reference-messaging-cloudevents-f03.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "배포 아티팩트가 싣지만 아무도 부르지 않는다", "상호운용을 위한 매퍼가 명세 준수 이벤트를 분류되지 않은 예외로 거절한다" ] }, { "title": "leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다", "slug": "messaging-kafka-share-experimental-f05", "file": "verification-path-coverage/reference/reference-messaging-kafka-share-experimental-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "\"등록\"이 아무것도 등록하지 않고 성공을 반환한다" ] }, { "title": "계약만 담는 leaf도 계약의 거절 조건은 자기 레인에서 검증한다", "slug": "messaging-reliability-api-f04", "file": "verification-path-coverage/reference/reference-messaging-reliability-api-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "inbox 보존 규칙이 문서로만 있다", "포트가 bounded/unbounded purge 두 오버로드를 나란히 노출하고, 호출자가 무제한 쪽을 고른다", "fencing token 경로가 실제 데이터베이스에 대해 실행되지 않는다", "한 인터페이스가 같은 전이의 두 세대를 갖고, 안전하지 않은 쪽에 `@Deprecated`가 없다" ] }, { "title": "record의 equals를 좁히면 이유를 적는다", "slug": "messaging-reliability-api-f07", "file": "verification-path-coverage/reference/reference-messaging-reliability-api-f07.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "inbox 보존 규칙이 문서로만 있다", "포트가 bounded/unbounded purge 두 오버로드를 나란히 노출하고, 호출자가 무제한 쪽을 고른다", "fencing token 경로가 실제 데이터베이스에 대해 실행되지 않는다", "한 인터페이스가 같은 전이의 두 세대를 갖고, 안전하지 않은 쪽에 `@Deprecated`가 없다" ] }, { "title": "증가한다고 문서화한 값이 리터럴이면 그 사실을 적는다", "slug": "messaging-runtime-core-f06", "file": "verification-path-coverage/reference/reference-messaging-runtime-core-f06.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "관측이 구현·호출부·주입 자리를 모두 갖추고도 출하에서 no-op이다", "소비 오케스트레이터가 조립되지 않는다", "선언된 content type과 실제 인코딩이 조용히 갈라질 수 있다" ] }, { "title": "모드 enum을 분기 조건으로 쓰면 각 분기에 테스트를 둔다", "slug": "messaging-schema-avro-f04", "file": "verification-path-coverage/reference/reference-messaging-schema-avro-f04.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "진화 판단이 두 곳에 있고 형태가 반대다", "CI에서 돈다고 선언한 게이트를 부르는 CI가 없다" ] }, { "title": "검증되지 않는 스키마 파일은 문서임을 파일 안에 적는다", "slug": "messaging-schema-protobuf-f01", "file": "verification-path-coverage/reference/reference-messaging-schema-protobuf-f01.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "registry 조회 로직이 세 codec에 복제돼 있다" ] }, { "title": "신뢰할 수 없는 입력 쪽 경계를 먼저 테스트한다", "slug": "messaging-schema-protobuf-f02", "file": "verification-path-coverage/reference/reference-messaging-schema-protobuf-f02.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "registry 조회 로직이 세 codec에 복제돼 있다" ] }, { "title": "같은 술어가 두 타입에 있으면 하나가 다른 하나를 부른다", "slug": "messaging-security-f05", "file": "verification-path-coverage/reference/reference-messaging-security-f05.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "종료 시 자격증명 소거가 호출되지 않는다", "같은 TLS posture를 두 클래스가 다른 엄격도로 검사한다", "권한 거부가 `AUTHORIZATION`이 아니라 `CONFIGURATION`으로 기록된다" ] } ], "question": [], "decision": [] } }, "web-inbound-and-http-surface": { "topic": "web-inbound-and-http-surface", "kinds": { "case": [ { "title": "호출자 없이 들어온 메서드이고, 도달 불가라던 가지는 켜지면 반대로 답한다", "slug": "a14-f002-webproblemsanitizer-alreadysafe", "file": "web-inbound-and-http-surface/case/case-a14-f002-webproblemsanitizer-alreadysafe.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a14-f002-webproblemsanitizer-alreadysafe", "a14-f002-webproblemsanitizer-alreadysafe-branch" ], "evidence": [ "../../../final/evidence/raw/a14-f002-webproblemsanitizer-alreadysafe.txt", "../../../final/evidence/raw/a14-f002-webproblemsanitizer-alreadysafe-branch.txt" ], "relations": [ "adapter까지 있고 호출자가 없는 교정 경로", "소비자가 없는 fixture 셋", "runtime_memberships를 먼저 읽고 심각도를 정한다" ] }, { "title": "공개 경로가 관리 경로를 덮으면 제한 규칙이 건너뛰어지고, 그 겹침을 보는 것이 없다", "slug": "a14-f005-publicpaths-restrictedpathrule", "file": "web-inbound-and-http-surface/case/case-a14-f005-publicpaths-restrictedpathrule.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a14-f005-publicpaths-restrictedpathrule", "a14-f005-publicpaths-restrictedpathrule-chain", "a14-f005-publicpaths-restrictedpathrule-mgmtport" ], "evidence": [ "../../../final/evidence/raw/a14-f005-publicpaths-restrictedpathrule.txt", "../../../final/evidence/raw/a14-f005-publicpaths-restrictedpathrule-chain.txt", "../../../final/evidence/raw/a14-f005-publicpaths-restrictedpathrule-mgmtport.txt" ], "relations": [ "publicPaths가 먼저 등록되어 제한 경로 규칙을 덮는다", "단일 admission point는 우회 경로를 세어야 성립한다", "production 판정이 두 개의 리터럴 프로파일 이름에 걸려 있다", "runtime_memberships를 먼저 읽고 심각도를 정한다" ] }, { "title": "저장 금지와 조건부 읽기가 같은 응답에 실리고, 둘을 이으라고 만든 이름은 아무도 읽지 않는다", "slug": "a14-f010-no-store", "file": "web-inbound-and-http-surface/case/case-a14-f010-no-store.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a14-f010-no-store", "a14-f010-no-store-conditional" ], "evidence": [ "../../../final/evidence/raw/a14-f010-no-store.txt", "../../../final/evidence/raw/a14-f010-no-store-conditional.txt" ], "relations": [ "캐시 헤더를 소유하는 것은 24줄 상수 두 개다", "maxArrayElements가 선언만 되고 강제되지 않으며, 바이트 예산 백스톱도 없다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다", "내부 소비자 부재와 public 계약 필요성을 따로 묻는다", "runtime_memberships를 먼저 읽고 심각도를 정한다" ] }, { "title": "배열 원소 상한은 선언만 되고, 파서가 그것을 대신할 수단은 이 팩토리에서만 비어 있다", "slug": "a14-f011-maxarrayelements", "file": "web-inbound-and-http-surface/case/case-a14-f011-maxarrayelements.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a14-f011-maxarrayelements", "a14-f011-maxarrayelements-converter", "a14-f011-maxarrayelements-parser" ], "evidence": [ "../../../final/evidence/raw/a14-f011-maxarrayelements.txt", "../../../final/evidence/raw/a14-f011-maxarrayelements-converter.txt", "../../../final/evidence/raw/a14-f011-maxarrayelements-parser.txt" ], "relations": [ "저장 금지와 조건부 읽기가 같은 응답에 실리고, 둘을 이으라고 만든 이름은 아무도 읽지 않는다", "타입이 문서화한 불변식은 타입이 강제한다", "문서가 범위를 제한하면 그 제한을 누가 강제하는지 같이 적는다", "\"상한을 두고 읽는다\"는 본문 핸들러가 전부 읽은 뒤에 자른다" ] }, { "title": "선언된 Advanced 능력 열둘 중 속성 이름을 읽는 코드가 있는 것은 둘이다", "slug": "a14-f014-advanced", "file": "web-inbound-and-http-surface/case/case-a14-f014-advanced.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a14-f014-advanced", "a14-f014-advanced-switches" ], "evidence": [ "../../../final/evidence/raw/a14-f014-advanced.txt", "../../../final/evidence/raw/a14-f014-advanced-switches.txt" ], "relations": [ "그러나 R0 경계가 문서에만 있고 compile 경로에서 닫히지 않는다", "플랫폼 요청 컨텍스트가 서블릿에는 생산자가 없고, 리액티브에는 익명 액터로 고정되어 있다", "그 속성을 보일 수 없는 대역 위에서 통과한 테스트는 증인이 아니다", "선언 순서를 단언하는 테스트는 그 순서를 읽는 코드가 있을 때만 게이트다" ] }, { "title": "켜는 속성이라고 적힌 메서드가 어느 게이트도 쓰지 않는 이름을 돌려준다", "slug": "a14-f015-virtualthreadprofile-propertyname", "file": "web-inbound-and-http-surface/case/case-a14-f015-virtualthreadprofile-propertyname.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a14-f015-virtualthreadprofile-propertyname", "a14-f015-virtualthreadprofile-propertyname-bind" ], "evidence": [ "../../../final/evidence/raw/a14-f015-virtualthreadprofile-propertyname.txt", "../../../final/evidence/raw/a14-f015-virtualthreadprofile-propertyname-bind.txt" ], "relations": [ "선언된 Advanced 능력 열둘 중 속성 이름을 읽는 코드가 있는 것은 둘이다", "호출자 없이 들어온 메서드이고, 도달 불가라던 가지는 켜지면 반대로 답한다", "선언 순서를 단언하는 테스트는 그 순서를 읽는 코드가 있을 때만 게이트다" ] }, { "title": "라우트 게이트가 실물을 읽어 오는 한 조각만 아무도 만들지 않는다", "slug": "a14-f017-springmvcrouteinventorycollector", "file": "web-inbound-and-http-surface/case/case-a14-f017-springmvcrouteinventorycollector.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a14-f017-springmvcrouteinventorycollector", "a14-f017-springmvcrouteinventorycollector-run" ], "evidence": [ "../../../final/evidence/raw/a14-f017-springmvcrouteinventorycollector.txt", "../../../final/evidence/raw/a14-f017-springmvcrouteinventorycollector-run.txt" ], "relations": [ "운영 런북이 시작 검증기의 판정을 근거로 삼는데 그 검증기를 부르는 곳이 없다", "소비자가 없는 fixture 셋", "@Bean이 있다는 것은 조립 증거가 아니다" ] }, { "title": "운영 런북이 시작 검증기의 판정을 근거로 삼는데 그 검증기를 부르는 곳이 없다", "slug": "a14-f018-webplatformstartupvalidator", "file": "web-inbound-and-http-surface/case/case-a14-f018-webplatformstartupvalidator.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a14-f018-webplatformstartupvalidator", "a14-f018-webplatformstartupvalidator-run" ], "evidence": [ "../../../final/evidence/raw/a14-f018-webplatformstartupvalidator.txt", "../../../final/evidence/raw/a14-f018-webplatformstartupvalidator-run.txt" ], "relations": [ "라우트 게이트가 실물을 읽어 오는 한 조각만 아무도 만들지 않는다", "@Bean이 있다는 것은 조립 증거가 아니다", "시작 검증기가 도는지는 그 능력에 자동설정 루트가 있는지와 일치한다", "그러나 R0 경계가 문서에만 있고 compile 경로에서 닫히지 않는다" ] }, { "title": "플랫폼 요청 컨텍스트가 서블릿에는 생산자가 없고, 리액티브에는 익명 액터로 고정되어 있다", "slug": "analysis-finding-a14-f003", "file": "web-inbound-and-http-surface/case/case-analysis-finding-a14-f003.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a14-f003" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a14-f003.txt" ], "relations": [ "두 개의 outbox 중 하나만 조립되어 있다", "한쪽의 javadoc이 다른 쪽의 동작을 규탄한다", "픽스처가 생산자를 우회하면 게이트가 도는 것은 픽스처다" ] }, { "title": "프레임워크 자유 신원 모델과 교차 테넌트 가드가 프로덕션에서 한 번도 참조되지 않는다", "slug": "analysis-finding-a14-f004", "file": "web-inbound-and-http-surface/case/case-analysis-finding-a14-f004.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a14-f004" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a14-f004.txt" ], "relations": [ "플랫폼 요청 컨텍스트가 서블릿에는 생산자가 없고 리액티브에는 익명 액터로 고정되어 있다", "용량 보호 계층 전체가 자기 테스트 픽스처 안에서만 실행된다", "노출이 없는 것과 가드가 작동하는 것은 다르다" ] }, { "title": "용량 보호 계층 전체(41 main files)가 자기 테스트 픽스처 안에서만 실행된다", "slug": "analysis-finding-a14-f006", "file": "web-inbound-and-http-surface/case/case-analysis-finding-a14-f006.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a14-f006" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a14-f006.txt" ], "relations": [ "멱등 실행 계층과 durable-operation 표면이 픽스처에서만 조립된다", "플랫폼 요청 컨텍스트가 서블릿에는 생산자가 없고 리액티브에는 익명 액터로 고정되어 있다", "레인은 게이트가 올바른가를 증명하고 플랫폼이 게이트를 설치하는가는 묻지 않는다" ] }, { "title": "리액티브 전송에는 속도 제한 경로가 하나도 없다", "slug": "analysis-finding-a14-f007", "file": "web-inbound-and-http-surface/case/case-analysis-finding-a14-f007.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a14-f007" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a14-f007.txt" ], "relations": [ "용량 보호 계층 전체가 자기 테스트 픽스처 안에서만 실행된다", "동적 대상 DNS 핀 능력 검사가 블로킹 오버로드에만 있다", "속성은 받아들여지고 소비자는 없다" ] }, { "title": "멱등 실행 계층과 durable-operation 표면이 픽스처에서만 조립된다", "slug": "analysis-finding-a14-f008", "file": "web-inbound-and-http-surface/case/case-analysis-finding-a14-f008.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a14-f008" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a14-f008.txt" ], "relations": [ "용량 보호 계층 전체가 자기 테스트 픽스처 안에서만 실행된다", "플랫폼 요청 컨텍스트가 서블릿에는 생산자가 없고 리액티브에는 익명 액터로 고정되어 있다", "헤더를 받아들이는 것처럼 보이는 API가 그것을 지키지 않는다" ] }, { "title": "의미 지문이 길이 프레이밍 없이 구분자로 만들어진다", "slug": "analysis-finding-a14-f009", "file": "web-inbound-and-http-surface/case/case-analysis-finding-a14-f009.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a14-f009" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a14-f009.txt" ], "relations": [ "멱등 실행 계층과 durable-operation 표면이 픽스처에서만 조립된다", "구분자 이어붙이기는 길이 프레이밍으로 닫는다", "같은 문제를 다른 모듈에서는 닫았다" ] }, { "title": "이 leaf의 리액티브 절반 29개 파일은 어떤 출하 배포에서도 활성화될 수 없다", "slug": "analysis-finding-a14-f016", "file": "web-inbound-and-http-surface/case/case-analysis-finding-a14-f016.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a14-f016" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a14-f016.txt" ], "relations": [ "플랫폼 요청 컨텍스트가 서블릿에는 생산자가 없고 리액티브에는 익명 액터로 고정되어 있다", "리액티브 전송에는 속도 제한 경로가 하나도 없다", "조건은 참이 될 수 있어야 조건이다" ] }, { "title": "크로스 스택 게이트가 검증하는 조립은 픽스처의 조립이고, 플랫폼의 조립이 아니다", "slug": "analysis-finding-a14-f019", "file": "web-inbound-and-http-surface/case/case-analysis-finding-a14-f019.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a14-f019" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a14-f019.txt" ], "relations": [ "용량 보호 계층 전체가 자기 테스트 픽스처 안에서만 실행된다", "멱등 실행 계층과 durable-operation 표면이 픽스처에서만 조립된다", "능력이 올바른가와 플랫폼이 능력을 설치하는가는 다른 질문이다" ] } ], "concept": [], "reference": [], "question": [], "decision": [] } }, "websocket-and-realtime": { "topic": "websocket-and-realtime", "kinds": { "case": [ { "title": "연결 티켓·origin 정책·메시지 권한·연결 예산이 요청 경로 밖이고, 그중 일부는 STOMP 어댑터가 다른 방식으로 대체한다", "slug": "a17-f002-stomp", "file": "websocket-and-realtime/case/case-a17-f002-stomp.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a17-f002-stomp" ], "evidence": [ "../../../final/evidence/raw/a17-f002-stomp.txt" ], "relations": [ "프레임워크 자유 신원 모델과 교차 테넌트 가드가 프로덕션에서 한 번도 참조되지 않는다", "능력 프로퍼티 이름을 만드는 코드와 실제 게이트가 다른 접두사를 쓴다", "중복 장치를 찾으면 어느 쪽이 조립됐는지 먼저 확인한다" ] }, { "title": "능력 프로퍼티 이름을 만드는 코드와 실제 게이트가 다른 접두사를 쓴다", "slug": "analysis-finding-a17-f003", "file": "websocket-and-realtime/case/case-analysis-finding-a17-f003.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "analysis-finding-a17-f003" ], "evidence": [ "../../../final/evidence/raw/analysis-finding-a17-f003.txt" ], "relations": [ "속성 이름 메서드가 아무것도 게이트하지 않는 이름을 반환한다", "연결 티켓과 origin 정책과 메시지 권한과 연결 예산이 요청 경로 밖이고 일부는 다른 방식으로 대체된다", "운영자가 문서를 보고 설정하면 켜지지 않는다" ] } ], "concept": [], "reference": [], "question": [], "decision": [] } }, "what-a-gate-does-not-prove": { "topic": "what-a-gate-does-not-prove", "kinds": { "case": [ { "title": "패키지 카탈로그가 트리보다 아홉 개 적었고, 선언된 간선의 DAG 검사도 없었다", "slug": "a-catalog-nine-entries-short", "file": "what-a-gate-does-not-prove/case/case-a-catalog-nine-entries-short.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-catalog-nine-entries-short" ], "evidence": [ "../../../final/evidence/raw/a-catalog-nine-entries-short.txt" ], "relations": [ "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "@Bean이 있다는 것은 조립 증거가 아니다" ] }, { "title": "'\"certified\"라 불리던 레인이 threshold를 하나도 비교하지 않고 있었다'", "slug": "a-certifying-lane-that-compared-nothing", "file": "what-a-gate-does-not-prove/case/case-a-certifying-lane-that-compared-nothing.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-certifying-lane-that-compared-nothing" ], "evidence": [ "../../../final/evidence/raw/a-certifying-lane-that-compared-nothing.txt" ], "relations": [ "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "성능 측정은 릴리스 게이트에 넣지 않는다", "strict test lane — 발견하지 못하면 실패하는 레인" ] }, { "title": "릴리스 게이트가 읽는 증거를 아무도 생산하지 않는다", "slug": "a-release-gate-with-no-evidence-producer", "file": "what-a-gate-does-not-prove/case/case-a-release-gate-with-no-evidence-producer.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-release-gate-with-no-evidence-producer" ], "evidence": [ "../../../final/evidence/raw/a-release-gate-with-no-evidence-producer.txt", "../../../final/evidence/raw/tl-grpc-release-gate-no-producer.txt" ], "relations": [ "아무도 돌리지 않는 레인의 게이트는 마지막으로 돌린 사람이 본 것을 보고한다", "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "시작 검증기 13개 규칙이 유일한 조립 지점에서 호출되지 않는다" ] }, { "title": "다중 타깃 검증을 확인한다는 테스트가 다른 가드에 걸려 통과했다", "slug": "a-test-that-passed-on-the-wrong-guard", "file": "what-a-gate-does-not-prove/case/case-a-test-that-passed-on-the-wrong-guard.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a-test-that-passed-on-the-wrong-guard" ], "evidence": [ "../../../final/evidence/raw/a-test-that-passed-on-the-wrong-guard.txt" ], "relations": [ "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "계약 테스트는 어댑터가 실제로 돌리는 statement를 실행해야 한다" ] }, { "title": "상위 클래스까지 올라가는 탐색이 게터는 읽지 않는다", "slug": "a05-f012-identity", "file": "what-a-gate-does-not-prove/case/case-a05-f012-identity.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a05-f012-identity", "a05-f012-identity-probe" ], "evidence": [ "../../../final/evidence/raw/a05-f012-identity.txt", "../../../final/evidence/raw/a05-f012-identity-probe.txt" ], "relations": [ "접두사 시작 매칭은 시그니처에는 맞고 스니핑 패턴에는 맞지 않는다", "@Bean이 있다는 것은 조립 증거가 아니다" ] }, { "title": "널 검사가 술어 검사를 대신하고, 라이브러리는 널 아닌 조건 없음을 준다", "slug": "a05-f013-specificationpolicy-specification-unrestricted", "file": "what-a-gate-does-not-prove/case/case-a05-f013-specificationpolicy-specification-unrestricted.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a05-f013-specificationpolicy-specification-unrestricted", "a05-f013-specificationpolicy-specification-unrestricted-probe" ], "evidence": [ "../../../final/evidence/raw/a05-f013-specificationpolicy-specification-unrestricted.txt", "../../../final/evidence/raw/a05-f013-specificationpolicy-specification-unrestricted-probe.txt" ], "relations": [ "@Bean이 있다는 것은 조립 증거가 아니다", "접두사 시작 매칭은 시그니처에는 맞고 스니핑 패턴에는 맞지 않는다", "명령 카탈로그와 admission 아홉 단계" ] }, { "title": "게이트가 막겠다는 실패가 그 게이트 실행 안에서 일어나고, 단언은 그것을 보지 못한다", "slug": "a05-f014-collection-fetch-pagination", "file": "what-a-gate-does-not-prove/case/case-a05-f014-collection-fetch-pagination.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a05-f014-collection-fetch-pagination", "a05-f014-collection-fetch-pagination-probe", "a05-f014-collection-fetch-pagination-lane" ], "evidence": [ "../../../final/evidence/raw/a05-f014-collection-fetch-pagination.txt", "../../../final/evidence/raw/a05-f014-collection-fetch-pagination-probe.txt", "../../../final/evidence/raw/a05-f014-collection-fetch-pagination-lane.txt" ], "relations": [ "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "계약 테스트는 어댑터가 실제로 돌리는 statement를 실행해야 한다", "아무도 돌리지 않는 레인의 게이트는 마지막으로 돌린 사람이 본 것을 보고한다" ] }, { "title": "선택된 카드의 생산자 태스크가 지금 빌드를 실패시킨다", "slug": "a05-f033-jpa-flyway-migration", "file": "what-a-gate-does-not-prove/case/case-a05-f033-jpa-flyway-migration.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "a05-f033-jpa-flyway-migration", "a05-f033-jpa-flyway-migration-run", "a05-f033-jpa-flyway-migration-gate" ], "evidence": [ "../../../final/evidence/raw/a05-f033-jpa-flyway-migration.txt", "../../../final/evidence/raw/a05-f033-jpa-flyway-migration-run.txt", "../../../final/evidence/raw/a05-f033-jpa-flyway-migration-gate.txt" ], "relations": [ "아무도 돌리지 않는 레인의 게이트는 마지막으로 돌린 사람이 본 것을 보고한다", "마이그레이션 스트림은 자기 history 테이블을 갖는다", "컨테이너가 필요한 레인의 실제 결과를 실행으로 확인하지 않았다" ] }, { "title": "문서 계약 테스트의 단언 경계 밖에 발견된 드리프트 세 건이 전부 있었다", "slug": "doc-contract-test-boundary-predicted-the-drift", "file": "what-a-gate-does-not-prove/case/case-doc-contract-test-boundary-predicted-the-drift.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "doc-contract-test-boundary-predicted-the-drift" ], "evidence": [ "../../../final/evidence/raw/doc-contract-test-boundary-predicted-the-drift.txt" ], "relations": [ "문서와 상수가 서로 일치하는 것으로는 아무것도 증명되지 않는다", "빠뜨림이 통과가 되는 게이트는 게이트가 아니다" ] }, { "title": "이름이 검사한다고 말하는 것을 본문이 검사하지 않는 테스트 넷", "slug": "test-names-that-assert-what-their-bodies-do-not", "file": "what-a-gate-does-not-prove/case/case-test-names-that-assert-what-their-bodies-do-not.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "test-names-that-assert-what-their-bodies-do-not" ], "evidence": [ "../../../final/evidence/raw/test-names-that-assert-what-their-bodies-do-not.txt" ], "relations": [ "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "다중 타깃 검증을 확인한다는 테스트가 다른 가드에 걸려 통과했다", "산문이 선언한 게이트는 빌드에 있는 게이트가 아니다" ] }, { "title": "릴리스 레인이 매트릭스 세 버전 중 첫 번째만 돌리고 세 개를 커버로 기록했다", "slug": "three-versions-declared-one-executed", "file": "what-a-gate-does-not-prove/case/case-three-versions-declared-one-executed.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "three-versions-declared-one-executed" ], "evidence": [ "../../../final/evidence/raw/three-versions-declared-one-executed.txt" ], "relations": [ "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "컨테이너가 필요한 레인의 실제 결과를 실행으로 확인하지 않았다" ] }, { "title": "두 파일이 같은 검증기를 \"빌드를 실패시키는 것\"이라 적고, 어떤 빌드도 그것을 부르지 않는다", "slug": "two-files-name-a-build-gate-that-no-build-runs", "file": "what-a-gate-does-not-prove/case/case-two-files-name-a-build-gate-that-no-build-runs.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "two-files-name-a-build-gate-that-no-build-runs" ], "evidence": [ "../../../final/evidence/raw/two-files-name-a-build-gate-that-no-build-runs.txt" ], "relations": [ "산문이 선언한 게이트는 빌드에 있는 게이트가 아니다", "아무도 돌리지 않는 레인의 게이트는 마지막으로 돌린 사람이 본 것을 보고한다", "릴리스 게이트가 읽는 증거를 아무도 생산하지 않는다", "build gate라 불리는 catalog drift 검사가 어디에서도 실행되지 않는다" ] } ], "concept": [ { "title": "증거 등급과 provenance — R1과 R2를 가르는 것", "slug": "evidence-grades-and-provenance", "file": "what-a-gate-does-not-prove/concept/concept-evidence-grades-and-provenance.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "evidence-grades-and-provenance", "evidence-grades-and-provenance-diagram" ], "evidence": [ "../../../final/evidence/raw/evidence-grades-and-provenance.txt" ], "relations": [ "후보 증거는 통과해도 R1에 머무르고 R2는 별도 게이트가 판정한다", "아무도 돌리지 않는 레인의 게이트는 마지막으로 돌린 사람이 본 것을 보고한다", "strict test lane — 발견하지 못하면 실패하는 레인" ] }, { "title": "strict test lane — 발견하지 못하면 실패하는 레인", "slug": "strict-test-lane", "file": "what-a-gate-does-not-prove/concept/concept-strict-test-lane.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [ "strict-test-lane" ], "evidence": [ "../../../final/evidence/raw/strict-test-lane.txt" ], "relations": [ "아무것도 발견하지 못한 레인은 성공이 아니라 실패여야 한다", "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "인증 레인만 Docker 가드를 달지 않는다" ] } ], "reference": [ { "title": "계약 테스트는 어댑터가 실제로 돌리는 statement를 실행해야 한다", "slug": "a-contract-test-must-run-the-adapters-statement", "file": "what-a-gate-does-not-prove/reference/reference-a-contract-test-must-run-the-adapters-statement.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "다중 타깃 검증을 확인한다는 테스트가 다른 가드에 걸려 통과했다", "번역되지 않은 경합 예외가 재시도 코디네이터의 catch를 통째로 비껴갔다" ] }, { "title": "산문이 선언한 게이트는 빌드에 있는 게이트가 아니다", "slug": "a-gate-declared-in-prose-is-not-in-the-build", "file": "what-a-gate-does-not-prove/reference/reference-a-gate-declared-in-prose-is-not-in-the-build.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "두 파일이 같은 검증기를 빌드를 실패시키는 것이라 적고 어떤 빌드도 그것을 부르지 않는다", "아무도 돌리지 않는 레인의 게이트는 마지막으로 돌린 사람이 본 것을 보고한다", "시작 검증기가 네 설정 키의 유일한 소비자인데 시작 시 실행되지 않는다", "검증기는 발행이 아니라 주입이 강제다" ] }, { "title": "아무도 돌리지 않는 레인의 게이트는 마지막으로 돌린 사람이 본 것을 보고한다", "slug": "a-gate-nobody-runs-reports-the-last-run", "file": "what-a-gate-does-not-prove/reference/reference-a-gate-nobody-runs-reports-the-last-run.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "릴리스 게이트가 읽는 증거를 아무도 생산하지 않는다", "증거 등급과 provenance — R1과 R2를 가르는 것" ] }, { "title": "아무것도 발견하지 못한 레인은 성공이 아니라 실패여야 한다", "slug": "a-lane-that-discovers-nothing-must-fail", "file": "what-a-gate-does-not-prove/reference/reference-a-lane-that-discovers-nothing-must-fail.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "strict test lane — 발견하지 못하면 실패하는 레인", "빠뜨림이 통과가 되는 게이트는 게이트가 아니다" ] }, { "title": "문서와 상수가 서로 일치하는 것으로는 아무것도 증명되지 않는다", "slug": "agreement-between-documents-proves-nothing", "file": "what-a-gate-does-not-prove/reference/reference-agreement-between-documents-proves-nothing.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "문서 계약 테스트의 단언 경계 밖에 발견된 드리프트 세 건이 전부 있었다", "빠뜨림이 통과가 되는 게이트는 게이트가 아니다" ] }, { "title": "빠뜨림이 통과가 되는 게이트는 게이트가 아니다", "slug": "omission-that-passes-is-not-a-gate", "file": "what-a-gate-does-not-prove/reference/reference-omission-that-passes-is-not-a-gate.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "패키지 카탈로그가 트리보다 아홉 개 적었고, 선언된 간선의 DAG 검사도 없었다", "certified라 불리던 레인이 threshold를 하나도 비교하지 않고 있었다", "아무것도 발견하지 못한 레인은 성공이 아니라 실패여야 한다" ] } ], "question": [ { "title": "컨테이너가 필요한 레인의 실제 결과를 실행으로 확인하지 않았다", "slug": "container-lanes-not-executed", "file": "what-a-gate-does-not-prove/question/openquestion-container-lanes-not-executed.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [ "../../../final/evidence/raw/tl-platform-suite-results.txt" ], "relations": [ "커밋 모호성 계약 레인이 이 리비전에서 통과하는지 실행으로 확인되지 않았다", "아무도 돌리지 않는 레인의 게이트는 마지막으로 돌린 사람이 본 것을 보고한다", "릴리스 게이트가 읽는 증거를 아무도 생산하지 않는다" ] } ], "decision": [ { "title": "후보 증거는 통과해도 R1에 머무르고 R2는 별도 게이트가 판정한다", "slug": "candidate-evidence-stays-at-r1", "file": "what-a-gate-does-not-prove/decision/decision-candidate-evidence-stays-at-r1.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "증거 등급과 provenance — R1과 R2를 가르는 것", "문서와 상수가 서로 일치하는 것으로는 아무것도 증명되지 않는다" ] }, { "title": "인증 레인만 Docker 가드를 달지 않는다", "slug": "only-the-certification-lane-carries-no-docker-guard", "file": "what-a-gate-does-not-prove/decision/decision-only-the-certification-lane-carries-no-docker-guard.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "아무것도 발견하지 못한 레인은 성공이 아니라 실패여야 한다", "아무도 돌리지 않는 레인의 게이트는 마지막으로 돌린 사람이 본 것을 보고한다", "릴리스 게이트가 읽는 증거를 아무도 생산하지 않는다" ] }, { "title": "성능 측정은 릴리스 게이트에 넣지 않는다", "slug": "performance-measurement-is-not-a-release-gate", "file": "what-a-gate-does-not-prove/decision/decision-performance-measurement-is-not-a-release-gate.md", "readiness": "NEEDS_EVIDENCE", "status": "게시 전", "studioId": "", "assets": [], "evidence": [], "relations": [ "certified라 불리던 레인이 threshold를 하나도 비교하지 않고 있었다", "아무도 돌리지 않는 레인의 게이트는 마지막으로 돌린 사람이 본 것을 보고한다", "컨테이너가 필요한 특수 레인의 실제 결과를 실행으로 확인하지 않았다" ] } ] } } } }