# 주제: 네 인증 레인이 실제로 돌고 통과하지만, 그 결과를 릴리스 게이트에 먹이는 것이 없다 # revision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 # severity: P3 # ---- 먼저: 이 블록의 상태는 이미 정확히 문서화되어 있다 ---- # src/grpc/CLAUDE.md:74-86 "Runtime membership이 비어 있다는 것의 의미" # "registry의 모든 grpc:* leaf는 현재 runtime_memberships가 비어 있다. messaging:*가 처음 # 착지했을 때와 같은 상태다: # - **배포 아티팩트가 싣고 있지 않다.** build-only다. # - 애플리케이션에 배선하려면 registry의 runtime_memberships를 먼저 바꾸고 # verifyRuntimeModuleMembership을 통과시켜야 한다. # - **런타임에 있다는 것과 자격이 증명됐다는 것은 다르다.** 현재 in-process·Netty·fault lane은 # 실제로 실행되어 통과하지만, 실제 배포 환경에서의 soak·performance baseline은 없다. # **GrpcStableReleaseGate가 그 구분을 문서가 아니라 코드로 붙들고 있다.**" # src/grpc/CLAUDE.md:88-98 # "messaging:*의 MSG-015(bridge 부재)를 반복하지 않는 것이 이 family의 목표다." # "현재 adapter:inbound:grpc는 이 family에 의존하지 않는다 — registry의 allowed_dependencies를 # 보라. 배선은 별도 결정이며, 그때 registry edge와 브리지가 함께 들어간다." # => EVD-325 가 측정한 것은 전부 이 문서가 이미 말한 것이다. 드리프트가 아니라 확인이다. # ---- 네 레인을 실제로 돌렸다 ---- # command: ./gradlew :grpc:grpc-testkit:grpcInProcessContractTest :…:grpcNettyContractTest # :…:grpcFaultTest :…:grpcPerformanceTest --console=plain # exit: 0 (BUILD SUCCESSFUL, 4 executed) grpcInProcessContractTest tests=7 failures=0 grpcNettyContractTest tests=9 failures=0 <- 실제 HTTP/2 + TLS, ephemeral socket grpcFaultTest tests=9 failures=0 grpcPerformanceTest tests=1 failures=0 # 레인 정의(build.gradle): # grpc-inprocess "In-process contract lane: adapter, interceptor order, status, idempotency # replay. Never HTTP/2, TLS or transport-limit evidence." # grpc-netty "Real Netty lane: HTTP/2 on an ephemeral socket, TLS/mTLS, metadata and # message hard limits, GOAWAY, keepalive and drain." # grpc-fault "Fault-injection lane: connection loss at each evidence boundary, and the # classifier that refuses to infer NOT_SENT from an unobserved state." # grpc-performance (test 에서 제외) "…against a recorded baseline." # build.gradle 주석: # "A lane that discovers nothing fails, and none of them can serve an up-to-date result — # which is the property the split was protecting." # ---- 그러나 게이트는 레인 결과를 받지 않는다 ---- # GrpcStableReleaseGate.evaluate 시그니처: # public GrpcReleaseDecision evaluate( # GrpcReleaseEvidence evidence, # Map laneResults, <- **호출자가 손으로 넘긴다** # GrpcSchemaArtifactPublisher.PublishDecision schemaDecision) # # command: git grep -n "GrpcStableReleaseGate|laneResults" -- src # GrpcCompatibilityMatrix.java:76-84 missingResults(Map laneResults) # GrpcStableReleaseGateTest.java:16,18-19,136-137 <- 유일한 호출부, 테스트 # src/grpc/CLAUDE.md:82 <- 문서 언급 # => 프로덕션 호출부 0. 네 레인의 JUnit XML 을 읽어 laneResults 를 만드는 Gradle 태스크나 코드가 없다. # ---- messaging 과의 대비 ---- # messaging (EVD-318 에서 실행 확인): # messagingCertificationTest -> broker-certification-evidence.jsonl (커밋됨) # CertifiedEvidence.load() -> 매니페스트를 읽는다 # CompatibilityMatrix.Entry.hasLiveBrokerCertification() -> 매니페스트에서 **파생** # verifyMessagingCertificationEvidence -> 생산물 vs 커밋본 비교, 불일치면 빌드 실패 # => 닫힌 루프. CompatibilityMatrix javadoc: "an adapter cannot be promoted by editing a boolean" # # grpc: # 4개 레인 -> JUnit XML (build/test-results//) # ??? -> Map laneResults # GrpcStableReleaseGate.evaluate(...) <- 테스트만 호출 # => 열린 루프. laneResults 는 호출자가 편집할 수 있는 불리언 맵이다. # # 즉 messaging-testkit 이 명시적으로 고친 결함 형태 — # "an author added a line and the compatibility matrix … all believed it, on a machine that may # never have started a container" (CertifiedEvidence javadoc) # — 와 같은 모양이 grpc 쪽 게이트에 남아 있다. 다만 grpc 쪽은 레인이 실제로 돌고, # 아무도 게이트를 부르지 않으므로 잘못된 주장이 발행되지도 않는다. # ---- 판정 ---- # CLAUDE.md:82 의 "GrpcStableReleaseGate가 그 구분을 문서가 아니라 코드로 붙들고 있다" 는 # 절반만 참이다. 구분은 **타입으로** 붙들려 있다(GrpcEvidenceGrade, GrpcCompatibilityMatrix, # requireCertified). 그러나 그 타입에 실제 레인 결과를 넣는 코드가 없으므로, # 게이트는 아직 아무것도 붙들고 있지 않다.