# ca-skeleton.websocket 어댑터가 등록하는 인터셉터 둘
  AuthenticatedHandshakeInterceptor.java       34 줄
  WebSocketInboundAuthorizationInterceptor.java 53 줄
  stomp/WebSocketConfig.java:32 @ConditionalOnProperty(prefix = "ca-skeleton.websocket", name = "enabled", havingValue = "true")
  stomp/WebSocketConfig.java:36   private final AuthenticatedHandshakeInterceptor handshakeInterceptor =
  stomp/WebSocketConfig.java:37       new AuthenticatedHandshakeInterceptor();
  stomp/WebSocketConfig.java:40   private final WebSocketInboundAuthorizationInterceptor inboundAuthorization;
  stomp/WebSocketConfig.java:44     this.inboundAuthorization = new WebSocketInboundAuthorizationInterceptor(properties);
  stomp/WebSocketConfig.java:53         .addInterceptors(handshakeInterceptor)
  stomp/WebSocketConfig.java:58   public void configureClientInboundChannel(ChannelRegistration registration) {

# 같은 채널에 붙는 세 번째 인터셉터와 그 게이트
  advanced/stomp/StompSecurityInterceptor.java 96 줄
  advanced/stomp/StompConfiguration.java:24 @ConditionalOnProperty(
  advanced/stomp/StompConfiguration.java:25     prefix = "app.websocket-platform.advanced.stomp",
  advanced/stomp/StompConfiguration.java:26     name = "enabled",
  advanced/stomp/StompConfiguration.java:27     havingValue = "true")
  advanced/stomp/StompConfiguration.java:33   public StompConfiguration(StompProfile profile, StompSecurityInterceptor securityInterceptor) {
  advanced/stomp/StompConfiguration.java:35     this.securityInterceptor = securityInterceptor;
  advanced/stomp/StompConfiguration.java:39   public void configureClientInboundChannel(ChannelRegistration registration) {
  advanced/stomp/StompConfiguration.java:40     registration.interceptors(securityInterceptor);

# 이 모듈이 출하 런타임 그래프에 있는가
  app-bootstrap/build.gradle:196     // Explicit qualification-only composition. These projects remain absent from main
  app-bootstrap/build.gradle:197     // api/implementation/compileOnly/runtimeOnly and therefore from both shipped runtime graphs.
  app-bootstrap/build.gradle:198     conditionalTransportTestImplementation project(':adapter:inbound:graphql')
  app-bootstrap/build.gradle:199     conditionalTransportTestImplementation project(':adapter:inbound:grpc')
  app-bootstrap/build.gradle:200     conditionalTransportTestImplementation project(':adapter:inbound:websocket')
  websocket/CLAUDE.md:21 The module is absent from both shipped runtime compositions. Being registered and tested does not
  websocket/CLAUDE.md:22 activate it. A future composition must deliberately add the registered dependency and set
  websocket/CLAUDE.md:23 `ca-skeleton.websocket.enabled=true` with explicit safe origins.

# 정책 계층 — 네 패키지의 파일과 선언 형태와 줄 수
  security     WebSocketAuthenticationProfile.java    enum             57 줄
  security     WebSocketConnectionTicket.java         record           77 줄
  security     WebSocketOriginPolicy.java             final class      116 줄
  security     WebSocketTicketStore.java              interface        32 줄
  authz        MessageAuthorizationPolicy.java        final class      93 줄
  idempotency  CommandReconciliation.java             interface        84 줄
  idempotency  CommittedResultLedger.java             interface        61 줄
  idempotency  WebSocketCommandKey.java               record           40 줄
  idempotency  WebSocketCommandOutcome.java           enum             33 줄
  budget       WebSocketConnectionBudget.java         record           103 줄
  합계 10 파일

# 그 열 타입을 stomp 패키지가 참조하는가, 그리고 어디서 생성되는가
  CommandReconciliation              stomp참조=0  main생성=0  같은파일에@Bean있는main=0
  CommittedResultLedger              stomp참조=0  main생성=0  같은파일에@Bean있는main=0
  MessageAuthorizationPolicy         stomp참조=0  main생성=1  같은파일에@Bean있는main=0
  WebSocketAuthenticationProfile     stomp참조=0  main생성=0  같은파일에@Bean있는main=0
  WebSocketCommandKey                stomp참조=0  main생성=0  같은파일에@Bean있는main=0
  WebSocketCommandOutcome            stomp참조=0  main생성=0  같은파일에@Bean있는main=0
  WebSocketConnectionBudget          stomp참조=0  main생성=1  같은파일에@Bean있는main=0
  WebSocketConnectionTicket          stomp참조=0  main생성=0  같은파일에@Bean있는main=0
  WebSocketOriginPolicy              stomp참조=0  main생성=1  같은파일에@Bean있는main=1
  WebSocketTicketStore               stomp참조=0  main생성=0  같은파일에@Bean있는main=0

# 원문이 22 로 적은 수의 출처
  analysis/17:235:# Sub-scope 04 — `security` + `authz` + `idempotency` + `budget` + `error` + `observability` + `admin` + `release` (31 files, main 22 + test 9)
  security       4
  authz          1
  idempotency    4
  budget         1
  error          5
  observability  2
  admin          2
  release        3
  여덟 패키지 합계 22

# MessageAuthorizationPolicy 를 받는 자리와 그 받는 쪽의 생성자
  authz/MessageAuthorizationPolicy.java:26  public final class MessageAuthorizationPolicy {
  authz/MessageAuthorizationPolicy.java:39  public static MessageAuthorizationPolicy of(Map<WebSocketMessageType, Set<String>> requirements) {
  authz/MessageAuthorizationPolicy.java:57  public boolean permits(WebSocketMessageType type, Set<String> heldAuthorities) {
  authz/MessageAuthorizationPolicy.java:70  public boolean declares(WebSocketMessageType type) {
  authz/MessageAuthorizationPolicy.java:81  public java.util.List<WebSocketMessageType> undeclaredAmong(
  authz/MessageAuthorizationPolicy.java:90  public Map<WebSocketMessageType, Set<String>> requirements() {
  WebSocketPlatformStartupValidator.java:3 import dev.caskeleton.adapter.inbound.websocket.authz.MessageAuthorizationPolicy;
  WebSocketPlatformStartupValidator.java:56       MessageAuthorizationPolicy authorization,
  config/WebSocketPlatformStartupValidator.java:38  public WebSocketPlatformStartupValidator(boolean productionProfile) {
  config/WebSocketPlatformStartupValidator.java:53  public void validate(
  config/WebSocketPlatformStartupValidator.java:106  authorization.undeclaredAmong(
  WebSocketPlatformStartupValidatorTest.java:40       new WebSocketPlatformStartupValidator(true);
  WebSocketPlatformStartupValidatorTest.java:42       new WebSocketPlatformStartupValidator(false);

# 리프의 CLAUDE.md 가 적는 범위와 인바운드 정책 절 전체
  websocket/CLAUDE.md:15 - Opt-in STOMP over SockJS transport configuration and typed validation.
  websocket/CLAUDE.md:16 - HTTP-handshake principal enforcement and client-inbound STOMP destination authorization.
  websocket/CLAUDE.md:17 - Fixed client-safe STOMP `ERROR` mapping.
  websocket/CLAUDE.md:18 - Best-effort in-process event push through an explicit `LiveEventProjector` allowlist.
  websocket/CLAUDE.md:52 ## Inbound policy
  websocket/CLAUDE.md:53 
  websocket/CLAUDE.md:54 - The HTTP upgrade must already have a nonblank `Principal`; the adapter does not authenticate
  websocket/CLAUDE.md:55   credentials itself.
  websocket/CLAUDE.md:56 - STOMP `SUBSCRIBE` is allowed only for the configured broadcast destination.
  websocket/CLAUDE.md:57 - Authenticated `SEND` is allowed only below `/app/**`.
  websocket/CLAUDE.md:58 - Client `SEND` to `/topic/**` and other destinations is rejected.
  websocket/CLAUDE.md:59 - Every client-visible processing failure becomes the fixed
  websocket/CLAUDE.md:60   `WEBSOCKET_REQUEST_REJECTED` ERROR code with an empty payload.
