Files
document-haness/docs/clean-architecture-backend-template/tech-log-studio/self-disclosure-grading/case/case-a-startup-validator-that-requires-a-key-nothing-signs-with.md
T

9.1 KiB

kind, slug, title, topic, project, status, sourceRevision, rootTreeNode, evidenceCapturedOn, assets, evidence, source
kind slug title topic project status sourceRevision rootTreeNode evidenceCapturedOn assets evidence source
CASE a-startup-validator-that-requires-a-key-nothing-signs-with 시작 검증기가 커서 서명 키를 요구하는데 그 키로 서명하는 코드가 없다 self-disclosure-grading clean-architecture-backend-template 게시 전 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 case:a-startup-validator-that-requires-a-key-nothing-signs-with 2026-09-02
key file
a-startup-validator-that-requires-a-key-nothing-signs-with ../../../final/evidence/rendered/a-startup-validator-that-requires-a-key-nothing-signs-with.svg
../../../final/evidence/raw/a-startup-validator-that-requires-a-key-nothing-signs-with.txt
분석 문서는 inbound-graphql 어댑터 편 §24.1 이다. 서명하는 코드가 없다는 사실은 같은 문서 §23.2, 액추에이터 엔드포인트가 등록되지 않는다는 것은 §8.1, 매니페스트의 네 번째 신호는 §29.2 다. websocket 어댑터 편 §18.3 이 같은 형태의 재개 토큰 서명을 대조한다.

시작 검증기가 커서 서명 키를 요구하는데 그 키로 서명하는 코드가 없다

시작 검증기가 프로덕션에서 커서 서명 키를 요구하고, 그 검증기는 실제로 돈다. 그 키로 서명하는 코드는 없고, 서명될 커서도 아직 없다.

관계

  • 등급표 13행 중 일곱을 스스로 강등하고 한 행만 관측과 어긋났다 등급표가 이 능력을 모형 단계로 적고 있다.
  • 하위 시스템 전체가 미배선인데 그것을 켜는 플래그는 시작 검사를 수행한다 mongo 어댑터에서도 startup validator가 요구한 능력과 실제 조립된 실행 경로가 어긋났다.
  • 커서에 서명하는 이유는 기밀성이 아니라 무결성이다 이 커서 서명이 지키려는 성질이다.

문제

시작 검증기는 프로덕션 배포에서 cursor signing key가 없으면 기동을 거부한다. 오류 메시지는 서명되지 않은 cursor를 클라이언트가 수정할 수 있다는 위험을 설명한다.

이 검증기는 자동설정이 실제로 부른다.

결론

그 키를 소비하는 프로덕션 코드는 둘이다. 거절하는 검증기가 하나, 보고하는 액추에이터가 하나다. 뒤쪽을 만드는 코드는 아직 없다.

그 키로 서명하는 코드는 없다. 커서 코덱 쪽도 같다. 구현이 하나인데 만드는 프로덕션 코드가 없다.

서명될 커서도 아직 없다. 커넥션 조립기를 만드는 프로덕션 코드가 0 이고, 배포되는 스키마는 상태 확인 필드 하나다.

그런데 릴리스 게이트가 읽는 매니페스트는 이 능력을 안정 등급 승인 목록에 넣어 두었다.

문제는 능력이 미완인 상태 자체가 아니라, 실제 signing path가 없는데도 startup validator와 지원 신호가 이미 signing key를 필수 요건처럼 취급한다는 점이다.

닫는 것은 배선 결정이 아니라 설계 결정이다. 키링 팩토리는 키 재료를 인자로 받는데, 설정은 키 자체가 설정에 나타나지 않는다고 일부러 정해 두었다.

그때까지의 최소 조치는 요구를 남기고 문구를 사실에 맞추는 것이다. 테스트의 네 번째 케이스가 요구를 남기라고 못 박는다.

검증 환경

OpenJDK : 21.0.12 확인 방식 : 설정 소비 지점과 생성 지점의 계수, 배포 스키마 확인, 컨텍스트 테스트 확인 소스 수정 : x

재현 조건

  1. 시작 검증기가 프로덕션을 거절하는 조건과 문구를 읽고, 자동설정이 그것을 부르는 지점을 확인한다.
  2. 그 키 설정을 소비하는 프로덕션 코드를 세고, 그중 만들어지지 않는 것이 있는지 확인한다.
  3. 커서 코덱 구현체와 그것을 만드는 프로덕션 코드를 센다.
  4. 커넥션 조립기를 만드는 코드를 세고, 배포되는 스키마를 읽는다.
  5. 릴리스 게이트 매니페스트의 승인 목록을 확인한다.
  6. 부재를 고정하는 테스트와 요구를 남기라고 적은 케이스를 읽는다.

본문

프로덕션 배포에 커서 서명 키가 없으면 시작 검증기가 기동을 거절한다. 이유도 함께 적는다 — 서명되지 않은 커서는 클라이언트가 편집할 수 있다.

이 검증기는 발행만 되고 마는 종류가 아니다. 자동설정이 실제로 부른다.

프로덕션이 요구하고, 운영자가 주고, 아무것도 서명하지 않는다

:::evidence key="a-startup-validator-that-requires-a-key-nothing-signs-with" alt="코드베이스에서 시작 검증기가 커서 서명 키 없이 프로덕션을 거절하는 문구와 그 검증기가 자동설정에서 실제로 불리는 지점, 그 키 설정을 소비하는 두 곳과 그중 액추에이터 엔드포인트를 만드는 코드 수, 커서 코덱 구현체 수와 그것을 만드는 코드 수, 커넥션 조립기를 만드는 코드 수와 배포되는 스키마 전체, 릴리스 게이트가 읽는 매니페스트의 승인 목록, 부재를 고정하는 테스트의 단언과 요구를 남기라고 적은 네 번째 케이스, 그리고 등급표가 이 능력에 매긴 등급을 뽑은 출력. 배포되는 스키마에 커서가 없고 서명 코덱을 만드는 코드도 0 이라는 것이 그 출력에 보인다." caption="검증기의 거절 문구와 실제 호출 · 소비 두 곳과 미조립 엔드포인트 · 코덱 생성 0 · 스키마는 _health 하나 · 매니페스트의 승인 · 요구를 남기라는 테스트" zoom="true" :::

그 키 설정을 읽는 프로덕션 코드는 둘이다. 없으면 거절하는 검증기와, 설정되었다고 보고하는 액추에이터 엔드포인트다.

뒤쪽은 아직 만들어지지 않는다. 그 엔드포인트를 생성하는 프로덕션 코드가 0 이고, 그 클래스의 javadoc 이 등록을 컴포지션 루트의 몫으로 남겨 두었다.

서명하는 코드는 없다. 커서 코덱 구현은 하나뿐이고, 그것과 키링을 만드는 프로덕션 코드가 0 이다.

서명될 커서 자체가 아직 없다

커넥션 조립기를 만드는 프로덕션 코드가 0 이다.

배포되는 스키마에는 상태 확인 필드 하나만 있다. 파일 주석은 모듈이 기능 없이도 독립 부팅되어야 하고 Spring for GraphQL은 빈 스키마로 시작할 수 없기 때문에 이 최소 필드를 둔다고 설명한다. 기능 타입 이름은 여기서 노출하지 않는다.

커서는 발급되지도 소비되지도 않는다. 검증기 문구가 막는다고 말한 상태는 지금 존재하지 않는다.

그런데 승인 신호는 이미 켜져 있다

릴리스 게이트가 읽는 능력 매니페스트가 있다. 안정 스타터에서 켜도 되는 능력의 목록이다.

서명 커서 커넥션이 그 목록에 들어 있다. 켜도 된다고 판정되고, 켜는 코드는 없다.

결함은 미완이 아니다

컨텍스트 테스트가 그 부재를 고정한다. 설정에 키가 담기는 것을 먼저 확인하고, 그다음 코덱 빈도 키링 빈도 없다는 것을 단언한다.

단언 문구가 판정을 적는다 — 아무것도 지키지 않는 키가 없다는 이유로 프로덕션이 기동을 거절하는 것은, 그 키를 아예 요구하지 않는 것보다 나쁘다.

같은 테스트가 두 번째 능력도 같은 방식으로 고정한다. 변이 멱등성 인터셉터가 어떤 설정에서도 참조되지 않는다. 등급표가 둘 다 모형 단계로 적어 두었다.

미완인 능력을 미완이라고 적는 것과, 미완인 능력에 대해 요구하고 승인해 주는 신호를 켜 두는 것은 다르다.

websocket 어댑터의 같은 형태는 결함이 아니다

websocket 어댑터에 재개 토큰 코덱과 키링이 있다. 이 둘도 조립되지 않는다.

차이는 하나다. websocket 어댑터에는 키를 요구하는 시작 검증기가 없다. 그래서 잘못된 확인 신호도 없다.

미배선은 양쪽이 같고 결함은 한쪽에만 있다. 결함을 만드는 것이 미완이 아니라 검증기라는 것을 그 대조가 보여 준다.

닫는 것은 배선이 아니라 설계다

키링 팩토리는 키 재료 자체를 인자로 받는다. 그런데 설정은 키 자체가 설정에 절대 나타나지 않는다고 일부러 정해 두었다.

키 재료가 어디서 오는지를 먼저 정해야 무엇을 어디에 붙일지가 정해진다.

그동안 할 수 있는 일이 없는 것은 아니다. 요구는 남기고 문구를 사실에 맞추면 된다.

테스트의 네 번째 케이스는 signing key 요구 자체를 제거하지 않는다. 빠진 것은 요청 경로의 signing 구현이며, 그 구현이 추가되면 ‘키만 요구하고 사용하지 않는다’는 앞의 불일치는 해소된다. 키가 없을 때 기동을 거부하는 검증은 그 이후에도 유지된다.

확인하지 못한 것

키 없이 기동해 거절을 재현해 보지는 않았다. 참조 계수를 이름 기반 정적 검색으로 냈기 때문에 리플렉션 조립 경로까지는 배제하지 못했다.