# 가족 문서가 이 항목을 어떻게 들고 있는가
  messaging/CLAUDE.md:70:## application이 이 family에 도달하는 경로 (MSG-015, 미해결)
  messaging/CLAUDE.md:82:이것이 리뷰의 **MSG-015 (P0)** 이며 닫히지 않았다. 지금 안전한 이유는 설계가 아니라 기본값이다 —

# 두 스택의 설정 클래스와 생산자 빈
  bootstrap/messaging/KafkaSenderConfig.java:37 @Configuration(proxyBeanMethods = false)
  bootstrap/messaging/KafkaSenderConfig.java:38 @ConditionalOnProperty(name = "app.messaging.broker", havingValue = "kafka")
  bootstrap/messaging/KafkaSenderConfig.java:39 public class KafkaSenderConfig {
  bootstrap/messaging/KafkaSenderConfig.java:61   @Bean(name = "kafkaSeamProducer", destroyMethod = "close")
  bootstrap/messaging/KafkaSenderConfig.java:62   @ConditionalOnMissingBean(name = "kafkaSeamProducer")
  bootstrap/messaging/KafkaSenderConfig.java:63   public Producer<String, String> kafkaSeamProducer(KafkaAdapterSettings settings) {
  autoconfigure/KafkaMessagingAutoConfiguration.java:126    * @return the producer, closed with the context
  autoconfigure/KafkaMessagingAutoConfiguration.java:127    */
  autoconfigure/KafkaMessagingAutoConfiguration.java:128   @Bean(destroyMethod = "close")
  autoconfigure/KafkaMessagingAutoConfiguration.java:129   @ConditionalOnMissingBean
  autoconfigure/KafkaMessagingAutoConfiguration.java:130   public org.apache.kafka.clients.producer.Producer<byte[], byte[]> messagingKafkaProducer(
  autoconfigure/KafkaMessagingAutoConfiguration.java:131       org.springframework.core.env.Environment environment) {

# 플랫폼 쪽이 켜지는 사슬
  main · messaging/autoconfigure/MessagingPlatformRootAutoConfiguration.java:28 @ConditionalOnProperty(prefix = MessagingSettings.PREFIX, name = "enabled", havingValue = "true")
  main · messaging/autoconfigure/MessagingProviderSelection.java:48           "kafka", KafkaMessagingAutoConfiguration.class,

# broker 만 준 시험이 통과하는 이유 — 게이트 뒤 설정을 손으로 등록한다
  test · adapter/outbound/messaging/MessagingConfigTest.java:41         .withUserConfiguration(KafkaAdapterConfig.class)
  test · OptionalAdapterBeanGatingTest.java:59   private final ApplicationContextRunner runner =
  test · OptionalAdapterBeanGatingTest.java:60       new ApplicationContextRunner()
  test · OptionalAdapterBeanGatingTest.java:61           // Registered as a real auto-configuration entry, which is how the composition root
  test · OptionalAdapterBeanGatingTest.java:62           // reaches it: the HTTP Client platform's off state is a property of that entry, not of a
  test · OptionalAdapterBeanGatingTest.java:63           // hand-assembled subset of its children.
  test · OptionalAdapterBeanGatingTest.java:64           .withConfiguration(AutoConfigurations.of(HttpClientPlatformAutoConfiguration.class))
  test · OptionalAdapterBeanGatingTest.java:65           .withUserConfiguration(
  test · OptionalAdapterBeanGatingTest.java:66               OutboundSupportConfig.class,
  test · OptionalAdapterBeanGatingTest.java:67               MessagingConfig.class,
  test · OptionalAdapterBeanGatingTest.java:68               KafkaAdapterConfig.class,
  test · OptionalAdapterBeanGatingTest.java:69               NotificationConfig.class,
  test · OptionalAdapterBeanGatingTest.java:70               SlackNotificationAdapterConfig.class,
  두 시험이 컴포지션 루트를 쓰는가 :
    MessagingConfigTest.java                 CaSkeletonApplication 언급 0 건
    OptionalAdapterBeanGatingTest.java       CaSkeletonApplication 언급 0 건
  KafkaSenderConfig 가 그 슬라이스에 등록되는가 :
    MessagingConfigTest.java                 KafkaSenderConfig 언급 0 건
    OptionalAdapterBeanGatingTest.java       KafkaSenderConfig 언급 0 건

# 이 조합을 거르는 검증기가 있는가
  CapabilityDependencyValidator.java:64     }
  CapabilityDependencyValidator.java:65     if (relay && !outbox) {
  CapabilityDependencyValidator.java:66       violations.add(
  CapabilityDependencyValidator.java:67           "ca-skeleton.outbox.relay-enabled=true only starts the scheduler for a capability that is "
  CapabilityDependencyValidator.java:68               + "off; set ca-skeleton.outbox.enabled=true or turn the relay off.");
  CapabilityDependencyValidator.java:69     }
  CapabilityDependencyValidator.java:70     if (messaging && broker.isEmpty()) {
  CapabilityDependencyValidator.java:71       violations.add(
  CapabilityDependencyValidator.java:72           "app.messaging.enabled=true needs a transport; set app.messaging.broker to a registered "
  CapabilityDependencyValidator.java:73               + "broker id.");
  CapabilityDependencyValidator.java:74     }
  CapabilityDependencyValidator.java:75     if ("jdbc"
  CapabilityDependencyValidator.java:76             .equalsIgnoreCase(
  CapabilityDependencyValidator.java:77                 environment.getProperty(
  CapabilityDependencyValidator.java:78                     "ca-skeleton.capabilities.idempotency.provider", "disabled"))
  CapabilityDependencyValidator.java:79         && !jpa) {
  CapabilityDependencyValidator.java:80       violations.add(

# 운영 문서가 이 키를 무엇이라고 설명하는가
  docs/runbooks/outbox-publish-failed.md:26 ### Step 1 — 확인
  docs/runbooks/outbox-publish-failed.md:27 1. ERROR log에서 `OUTBOX_PUBLISH_FAILED` 라인 확인: `event_type`, `event_id`, `correlation_id`, `attempt_count` 추출
  docs/runbooks/outbox-publish-failed.md:28 2. broker 상태 확인: `APP_MESSAGING_BROKER` 값과 broker endpoint 가용성. 이 키는 활성화 스위치가
  docs/runbooks/outbox-publish-failed.md:29    아니라 **선택자**다 — messaging을 끄는 것은 `APP_MESSAGING_ENABLED=false`이고, 이 값을 비운다고
  docs/runbooks/outbox-publish-failed.md:30    messaging이 꺼지지는 않는다.
  docs/runbooks/outbox-publish-failed.md:31    - `APP_MESSAGING_BROKER`가 공백인 채로 relay가 켜져 있으면 **애플리케이션이 기동하지 않는다**
  docs/runbooks/outbox-publish-failed.md:32      (`OutboxRelayBrokerRequirementValidator`, MSG-024). 이 조합에서는 publish가 전부

# 출하 설정이 두 키를 어떻게 주는가
  compose-profile-contracts.json:170:        "APP_MESSAGING_ENABLED": "true",
  compose-profile-contracts.json:171:        "APP_MESSAGING_BROKER": "kafka",
  compose-profile-contracts.json:202:        "APP_MESSAGING_ENABLED": "true",
  compose-profile-contracts.json:203:        "APP_MESSAGING_BROKER": "kafka",
  compose-profile-contracts.json:604:        "APP_MESSAGING_ENABLED": "true",
  compose-profile-contracts.json:605:        "APP_MESSAGING_BROKER": "kafka",
  .env:38:APP_MESSAGING_BROKER=
  .env.example:229:APP_MESSAGING_BROKER=
  .env.example:299:APP_MESSAGING_ENABLED=false
  .env.local.example:20:APP_MESSAGING_ENABLED=false
  .env.local.example:21:APP_MESSAGING_BROKER=

# KafkaSenderConfig 가 조건에서 물러나는가
  KafkaSenderConfig.java:60    */
  KafkaSenderConfig.java:61   @Bean(name = "kafkaSeamProducer", destroyMethod = "close")
  KafkaSenderConfig.java:62   @ConditionalOnMissingBean(name = "kafkaSeamProducer")
  KafkaSenderConfig.java:63   public Producer<String, String> kafkaSeamProducer(KafkaAdapterSettings settings) {
  KafkaSenderConfig.java:64     Map<String, Object> config = new HashMap<>();
  KafkaSenderConfig.java:65     config.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, String.join(",", settings.brokers()));

# 이음매 설정 클래스 자신은 스캔 대상인가
  KafkaSenderConfig.java:1  package dev.caskeleton.bootstrap.messaging;
  AUTO_CONFIGURED_PACKAGES 가 bootstrap.messaging 을 제외하는가 : 0 건

# 이음매 쪽 생산자가 요구하는 설정 빈은 어디서 오는가
  main · adapter/outbound/messaging/kafka/KafkaAdapterConfig.java:19 @EnableConfigurationProperties(KafkaAdapterSettings.class)
  main · adapter/outbound/messaging/autoconfigure/MessagingBridgeRootAutoConfiguration.java:21 @ConditionalOnProperty(prefix = "app.messaging", name = "enabled", havingValue = "true")
  main · adapter/outbound/messaging/autoconfigure/MessagingBridgeRootAutoConfiguration.java:23 @Import({MessagingConfig.class, KafkaAdapterConfig.class})

# 그 설정 클래스가 컴포넌트 스캔으로 들어올 수 있는가
  CaSkeletonApplication.java:41 @ComponentScan(
  CaSkeletonApplication.java:42     basePackages = {
  CaSkeletonApplication.java:43       "dev.caskeleton.bootstrap",
  CaSkeletonApplication.java:44       "dev.caskeleton.adapter",
  CaSkeletonApplication.java:45       "dev.caskeleton.application",
  CaSkeletonApplication.java:46       "dev.caskeleton.domain",
  CaSkeletonApplication.java:47       "dev.caskeleton.shared"
  CaSkeletonApplication.java:48     },
  CaSkeletonApplication.java:49     excludeFilters = {
  CaSkeletonApplication.java:50       @ComponentScan.Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
  CaSkeletonApplication.java:51       @ComponentScan.Filter(
  CaSkeletonApplication.java:52           type = FilterType.CUSTOM,
  CaSkeletonApplication.java:53           classes = AutoConfigurationExcludeFilter.class),
  CaSkeletonApplication.java:54       @ComponentScan.Filter(
  CaSkeletonApplication.java:55           type = FilterType.REGEX,
  CaSkeletonApplication.java:56           pattern = CaSkeletonApplication.AUTO_CONFIGURED_PACKAGES)
  CaSkeletonApplication.java:57     })
  CaSkeletonApplication.java:100   static final String AUTO_CONFIGURED_PACKAGES =
  CaSkeletonApplication.java:101       "dev\\.caskeleton\\.bootstrap\\.autoconfigure\\..*"
  CaSkeletonApplication.java:105  + "|dev\\.caskeleton\\.adapter\\.outbound\\.messaging\\..*"
  ConfigurationPropertiesScan 목록에 adapter.outbound.messaging 이 있는가 :
    0 건

# broker=kafka 를 쓰는 시험마다 같은 파일이 enabled 를 주는가
  MessagingConfigTest.java                       broker=kafka 3 줄 · enabled= 0 줄
  OptionalAdapterBeanGatingTest.java             broker=kafka 1 줄 · enabled= 0 줄
  MessagingLiveRoundTripQualificationTest.java   broker=kafka 1 줄 · enabled= 1 줄
  MessagingStarterOffContractTest.java           broker=kafka 3 줄 · enabled= 7 줄
  enabled 를 한 줄도 주지 않는 파일의 시험 이름 :
    MessagingConfigTest.java:25  void blankBrokerBindsDisabledSentinelsCharacterization() {
    MessagingConfigTest.java:39  void selectedKafkaBrokerWithoutProjectSenderFailsStartupCharacterization() {
    MessagingConfigTest.java:54  void selectedBrokerIdMismatchFailsStartupCharacterization() {
    MessagingConfigTest.java:76  public void send(
    OptionalAdapterBeanGatingTest.java:77  void allOptionalAdaptersAreDisabledByDefaultAndTheAppStillStarts() {
    OptionalAdapterBeanGatingTest.java:114  void kafkaSelectedRegistersTheBrokerAndBindsTheRealPublishers() {
    OptionalAdapterBeanGatingTest.java:135  void slackWebhookEnabledContributesTheProviderAndRoutesBoundNotifications() {
    OptionalAdapterBeanGatingTest.java:153  void googleEmailEnabledContributesTheProviderAndRoutesBoundNotifications() {
    OptionalAdapterBeanGatingTest.java:170  void aRouteBindingToADisabledProviderFailsStartup() {
