# 검증기 자바독이 적은 두 결함과 그 상쇄
  JpaDataSourceProfileValidator.java:11  * <p>It used to validate a different one. The bounds came from {@code JpaDataSourceSettings}, bound
  JpaDataSourceProfileValidator.java:12  * to {@code app.jpa-platform.datasource.*}, while the pool that serves requests is built from
  JpaDataSourceProfileValidator.java:13  * {@code spring.datasource.hikari.*} — one pool with two descriptions, and a validator can pass
  JpaDataSourceProfileValidator.java:14  * against the description that is not in use.
  JpaDataSourceProfileValidator.java:15  *
  JpaDataSourceProfileValidator.java:16  * <p>Worse, the parallel namespace appeared in no shipped YAML and no row of the env-key registry,
  JpaDataSourceProfileValidator.java:17  * so both of its fields were always null and {@code requirePoolBounds} would have thrown on every
  JpaDataSourceProfileValidator.java:18  * deployment. Nothing called it, so nothing failed. Two defects that cancelled each other out, and
  JpaDataSourceProfileValidator.java:19  * the reason the application started was the second one hiding the first.

# 그 병렬 네임스페이스가 src 안에 남아 있는 자리
  main · NotificationSmtpProviderConfig.java:48  * app.jpa-platform.datasource.*} validated a pool that {@code spring.datasource.hikari.*} had
  main · NotificationSmtpSettings.java:14  * paid for — {@code app.jpa-platform.datasource.*} validated a pool that {@code
  main · SmtpProviderRuntimeAssembler.java:40  * already paid for elsewhere — {@code app.jpa-platform.datasource.*} validated a pool that {@code
  main · JpaDataSourceProfileValidator.java:12  * to {@code app.jpa-platform.datasource.*}, while the pool that serves requests is built from
  test · JpaResolvedDataSourceValidationTest.java:22  * <p>{@code JpaDataSourceSettings} bound {@code app.jpa-platform.datasource.*} while the pool that
  test · JpaResolvedDataSourceValidationTest.java:57             .filter(path -> withoutJavaComments(read(path)).contains("app.jpa-platform.datasource"))
  main · KafkaMessagingAutoConfiguration.java:119    * repository has already paid for in {@code app.jpa-platform.datasource.*}, and the
  src 밖에서 이 문자열을 쓰는 파일과 줄 수 :
    docs/study/postgresql-jpa-walkthrough.ko.md:1
    docs/superpowers/plans/2026-08-15-wave2-module-on-path.md:4
    docs/superpowers/plans/evidence/2026-08-15-wave2-decisions.md:3
    docs/superpowers/specs/2026-08-15-five-adapter-runtime-remediation-review-design.md:1
    infra/jpa/postgres/README.md:1
  그중 운영자용 표에 살아 있는 줄 :
    infra/jpa/postgres/README.md:18:| `max_connections` | The number `app.jpa-platform.datasource.maximum-pool-size` must be sized against — across every instance, and allowing for 
  설정 파일(yml·yaml·properties)에서 : 0 건
  그중 주석이 아닌 줄 : main 0 건 · test 1 건 (test 쪽은 회귀 테스트의 검색 문자열)
  그것을 바인딩하던 JpaDataSourceSettings 클래스 : 0 건

# 옛 상한 검사 메서드 이름이 남아 있는 자리
  main · JpaDataSourceProfileValidator.java:17  * so both of its fields were always null and {@code requirePoolBounds} would have thrown on every
  test · JpaResolvedDataSourceValidationTest.java:26  * of its fields were always null — and {@code requirePoolBounds} throws on a null. Had anything
  test · JpaResolvedDataSourceValidationTest.java:29  * <p>Nothing did. {@code validateStable} and {@code requirePoolBounds} were reachable only from

# 지금 검증기가 읽는 것과 던지는 것
  JpaDataSourceProfileValidator.java:50   public void validateResolved(DataSource dataSource, boolean requirePostgreSql) {
  JpaDataSourceProfileValidator.java:51     Objects.requireNonNull(dataSource, "dataSource");
  JpaDataSourceProfileValidator.java:52     if (!requirePostgreSql) {
  JpaDataSourceProfileValidator.java:53       // Local development runs H2 by design, and PersistenceVendorProdSafetyValidator is what keeps
  JpaDataSourceProfileValidator.java:54       // that out of production. Demanding PostgreSQL here as well would refuse every laptop.
  JpaDataSourceProfileValidator.java:55       return;
  JpaDataSourceProfileValidator.java:56     }
  JpaDataSourceProfileValidator.java:57     try (Connection connection = dataSource.getConnection()) {
  JpaDataSourceProfileValidator.java:58       versionPolicy.requireStable(connection.getMetaData());
  JpaDataSourceProfileValidator.java:59     } catch (SQLException unreachable) {
  JpaDataSourceProfileValidator.java:60       throw new IllegalStateException(
  JpaDataSourceProfileValidator.java:61           "could not open a connection to validate the datasource: "
  JpaDataSourceProfileValidator.java:62               + unreachable.getMessage()
  JpaDataSourceProfileValidator.java:63               + ". A context that starts without this check reports healthy and fails on whoever "
  JpaDataSourceProfileValidator.java:64               + "sends the first request.",
  JpaDataSourceProfileValidator.java:65           unreachable);
  JpaDataSourceProfileValidator.java:66     }

# validateResolved 를 부르는 자리 전부
  main · PersistenceJpaRootAutoConfiguration.java:113     return () -> validator.validateResolved(dataSource, "postgresql".equalsIgnoreCase(vendor));
  test · JpaResolvedDataSourceValidationTest.java:82                     .validateResolved(pool, true))
  test · JpaResolvedDataSourceValidationTest.java:101     assertThatCode(() -> validator.validateResolved(h2, false))
  test · JpaResolvedDataSourceValidationTest.java:104     assertThatThrownBy(() -> validator.validateResolved(h2, true))

# 그 호출자가 붙는 조건과 출하 기본값
  PersistenceJpaRootAutoConfiguration.java:56 @AutoConfiguration
  PersistenceJpaRootAutoConfiguration.java:57 @ConditionalOnProperty(
  PersistenceJpaRootAutoConfiguration.java:58     prefix = "ca-skeleton.persistence-jpa",
  PersistenceJpaRootAutoConfiguration.java:59     name = "enabled",
  PersistenceJpaRootAutoConfiguration.java:60     havingValue = "true")
  PersistenceJpaRootAutoConfiguration.java:61 @Import({
  application.yml:364:    enabled: ${APP_PERSISTENCE_JPA_ENABLED:false}

# 직접 생성의 이유로 적힌 조건과, 그 조건의 현재 상태
  PersistenceJpaRootAutoConfiguration.java:95    * {@code @ConditionalOnBean(DataSource.class)} on a plain {@code @Configuration} imported by this
  PersistenceJpaRootAutoConfiguration.java:96    * root — a condition evaluated during configuration-class parsing, before the datasource bean
  PersistenceJpaRootAutoConfiguration.java:97    * definition is registered. That class therefore drops out silently in the real application,
  PersistenceJpaRootAutoConfiguration.java:98    * taking the whole JPA add-on layer with it. Depending on a bean from it would make this check
  PersistenceJpaRootAutoConfiguration.java:99    * disappear for the same reason the thing it checks disappeared. The condition-ordering defect is
  JpaPlatformRuntimeAutoConfiguration.java:57  * root, which already carries the master switch, so "is there a datasource" has been answered yes
  JpaPlatformRuntimeAutoConfiguration.java:58  * by the time it is parsed. A bean here that needs one takes it as a parameter, and a missing
  JpaPlatformRuntimeAutoConfiguration.java:59  * datasource with the switch on is then a loud failure — which is the outcome that was wanted,
  JpaPlatformRuntimeAutoConfiguration.java:60  * rather than the layer vanishing.
  JpaPlatformRuntimeAutoConfiguration.java:61  */
  JpaPlatformRuntimeAutoConfiguration.java:62 @org.springframework.context.annotation.Configuration(proxyBeanMethods = false)
  JpaPlatformRuntimeAutoConfiguration.java:63 @ConditionalOnClass(DataSource.class)
  JpaPlatformRuntimeAutoConfiguration.java:64 @ConditionalOnProperty(prefix = "app.jpa-platform", name = "addons-enabled", matchIfMissing = true)

# 그 호출자가 검증기를 어디서 얻는가
  PersistenceJpaRootAutoConfiguration.java:106   @Bean
  PersistenceJpaRootAutoConfiguration.java:107   public InitializingBean jpaResolvedDataSourceCheck(
  PersistenceJpaRootAutoConfiguration.java:108       DataSource dataSource, Environment environment) {
  PersistenceJpaRootAutoConfiguration.java:109     JpaDataSourceProfileValidator validator =
  PersistenceJpaRootAutoConfiguration.java:110         new JpaDataSourceProfileValidator(new PostgreSqlVersionPolicy());
  PersistenceJpaRootAutoConfiguration.java:111     String vendor =
  PersistenceJpaRootAutoConfiguration.java:112         environment.getProperty(PersistenceVendorSettings.VENDOR_PROPERTY, "postgresql").trim();
  PersistenceJpaRootAutoConfiguration.java:113     return () -> validator.validateResolved(dataSource, "postgresql".equalsIgnoreCase(vendor));
  PersistenceJpaRootAutoConfiguration.java:114   }

# 이 타입을 빈으로 정의하는 자리와, 그 빈을 주입받는 코드
  JpaPlatformAutoConfiguration 의 @Bean 개수 : 0
  JpaPlatformAutoConfiguration.java:19  * <p>Plain construction rather than Spring auto-configuration. This repository's rule is that
  JpaPlatformAutoConfiguration.java:20  * {@code app-bootstrap} owns composition, and an adapter leaf that auto-configured itself would
  JpaPlatformAutoConfiguration.java:48   /** The datasource product, version, and pool validator. */
  JpaPlatformAutoConfiguration.java:49   public JpaDataSourceProfileValidator dataSourceProfileValidator() {
  JpaPlatformAutoConfiguration.java:50     return new JpaDataSourceProfileValidator(new PostgreSqlVersionPolicy());
  JpaPlatformRuntimeAutoConfiguration.java:111   /** The datasource product, version and pool validator. */
  JpaPlatformRuntimeAutoConfiguration.java:112   @Bean
  JpaPlatformRuntimeAutoConfiguration.java:113   @ConditionalOnMissingBean
  JpaPlatformRuntimeAutoConfiguration.java:114   public JpaDataSourceProfileValidator jpaDataSourceProfileValidator(
  JpaPlatformRuntimeAutoConfiguration.java:115       JpaPlatformAutoConfiguration composition) {
  JpaPlatformRuntimeAutoConfiguration.java:116     return composition.dataSourceProfileValidator();
  JpaPlatformRuntimeAutoConfiguration.java:117   }
  파라미터나 필드로 받는 프로덕션 코드 : 0 건

# HikariPoolConstraintValidator 가 읽는 키와 그 빈, 그리고 풀 크기를 보는 다른 검증기
  HikariPoolConstraintValidator.java:18  static final String CONNECTION_TIMEOUT_KEY = "spring.datasource.hikari.connection-timeout";
  HikariPoolConstraintValidator.java:19  static final String VALIDATION_TIMEOUT_KEY = "spring.datasource.hikari.validation-timeout";
  HikariPoolConstraintValidator.java:20  static final String KEEPALIVE_TIME_KEY = "spring.datasource.hikari.keepalive-time";
  HikariPoolConstraintValidator.java:21  static final String MAX_LIFETIME_KEY = "spring.datasource.hikari.max-lifetime";
  HikariPoolConstraintValidator.java:22  static final String LEAK_DETECTION_KEY = "spring.datasource.hikari.leak-detection-threshold";
  RuntimeSafetyConfig.java:49   @Bean
  RuntimeSafetyConfig.java:50   HikariPoolConstraintValidator hikariPoolConstraintValidator(Environment environment) {
  RuntimeSafetyConfig.java:51     return new HikariPoolConstraintValidator(environment);
  maximum-pool-size 와 minimum-idle 을 실제로 검사하는 곳 :
  main · RuntimeNumericBoundsValidator.java:22               "spring.datasource.hikari.maximum-pool-size", "APP_DATASOURCE_POOL_MAX_SIZE", 1),
  main · RuntimeNumericBoundsValidator.java:26           new Bound("spring.datasource.hikari.minimum-idle", "APP_DATASOURCE_POOL_MIN_IDLE", 0),
  app-bootstrap 이 HikariCP 를 선언하는 구성 :
    build.gradle:140:    testImplementation 'com.zaxxer:HikariCP'
  그런데 runtimeClasspath 를 풀어 보면 :
    |    |    |    \--- com.zaxxer:HikariCP:7.0.2
    +--- com.zaxxer:HikariCP:{strictly 7.0.2} -> 7.0.2 (c)

# 그 부재를 고정하는 회귀 테스트
  test · JpaResolvedDataSourceValidationTest.java:45   @DisplayName("no production code binds the parallel namespace")
  test · JpaResolvedDataSourceValidationTest.java:46   void theParallelNamespaceIsGone() {
  test · JpaResolvedDataSourceValidationTest.java:70   @DisplayName("an unreachable database fails at startup, not at the first query")
  test · JpaResolvedDataSourceValidationTest.java:71   void anUnreachableDatabaseFailsAtStartup() {
  test · JpaResolvedDataSourceValidationTest.java:91   @DisplayName("the product check applies only where PostgreSQL is the selected vendor")
  test · JpaResolvedDataSourceValidationTest.java:92   void theProductCheckFollowsTheVendorSelector() {
  그 테스트가 훑는 범위 :
  JpaResolvedDataSourceValidationTest.java:115   private static Stream<Path> productionSources() {
  JpaResolvedDataSourceValidationTest.java:116     Path root = repositoryRoot().resolve("src");
  JpaResolvedDataSourceValidationTest.java:117     return Stream.of("app-bootstrap", "adapter/outbound/persistence-jpa")
  JpaResolvedDataSourceValidationTest.java:118         .map(root::resolve)
  JpaResolvedDataSourceValidationTest.java:119         .filter(Files::isDirectory)
  공허한 통과를 막는 단언과 주석 제거 :
  JpaResolvedDataSourceValidationTest.java:47     List<Path> sources = productionSources().toList();
  JpaResolvedDataSourceValidationTest.java:48 
  JpaResolvedDataSourceValidationTest.java:49     assertThat(sources)
  JpaResolvedDataSourceValidationTest.java:50         .as("a scan that reached no source would report every binding as absent")
  JpaResolvedDataSourceValidationTest.java:51         .isNotEmpty();
  JpaResolvedDataSourceValidationTest.java:52 
  JpaResolvedDataSourceValidationTest.java:53     // Comments are stripped: a sentence recording that the namespace was retired is the opposite of
  JpaResolvedDataSourceValidationTest.java:54     // the defect, which was a binder reading a namespace nothing supplied.
  JpaResolvedDataSourceValidationTest.java:55     List<String> offenders =
  JpaResolvedDataSourceValidationTest.java:56         sources.stream()
  JpaResolvedDataSourceValidationTest.java:57             .filter(path -> withoutJavaComments(read(path)).contains("app.jpa-platform.datasource"))
  JpaResolvedDataSourceValidationTest.java:58             .map(path -> path.getFileName().toString())
  JpaResolvedDataSourceValidationTest.java:59             .sorted()
  JpaResolvedDataSourceValidationTest.java:60             .toList();
