merge: integrate JPA production capability

# Conflicts:
#	.github/ci-gate-matrix.yml
#	.github/scripts/verify-gate-matrix.sh
#	.github/workflows/ci-quality-gates.yml
#	src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/transaction/SpringTransactionPort.java
This commit is contained in:
donghyeon-ka
2026-07-31 23:57:29 +09:00
142 changed files with 13206 additions and 325 deletions
+14 -5
View File
@@ -226,11 +226,11 @@ refresh 완료 전에 실패시킨다.
흔한 connection-timeout 5s/5000ms 와 같아지는 충돌을 해소). `keepalive-time < max-lifetime`(둘 다
있을 때; keepalive 가 lifetime 보다 길면 의미 없음). `leak-detection-threshold`는 0(비활성)이
아니라면 `>= 2000ms`(너무 작으면 정상 사용을 누수로 오탐).
- **모든 노브를 `String`으로 읽어 직접 파싱하는 방어적 처리.** `env-keys.yaml``connection-timeout`
기본값은 Duration 문자열 `5s`인데 `src/.env``30000`(ms)을 준다. `Environment#getProperty(...,
Long.class)``"5s"`에 호출하면 `ConversionFailedException`이 난다. 그래서 각 값을 `String`으로
읽어 `parseMillis`로 넘기고, `null`/blank 또는 plain-integer 가 아닌 값은 `null`(= 부재로 간주,
조용히 skip)로 처리한다. 덕분에 검증기가 형식 drift 값에 절대 죽지 않는다.
- **Spring Boot와 같은 Duration 문법을 검증한다.** `env-keys.yaml``connection-timeout`
기본값은 `5s`인데 `src/.env``30000`(ms)을 준다. resolved 값을 `String`으로 읽은 뒤
`DurationStyle`로 plain milliseconds, simple duration(`5s`)과 ISO-8601(`PT5S`)을 같은
milliseconds 계약으로 변환한다. present-but-invalid 값은 부재로 조용히 취급하지 않고 property
이름을 포함한 startup validation failure로 거절한다.
- **env 키가 아직 없는 노브는 "env key pending" 문구를 쓴다.** `connection-timeout` /
`max-lifetime``env-keys.yaml`에 등록돼 있고, greenfield 노브(validation-timeout, keepalive-time,
leak-detection-threshold)는 env 키가 없다. 없는 키 이름을 지어내는 대신 pending 문구를 메시지에 넣는다.
@@ -246,6 +246,15 @@ refresh 완료 전에 실패시킨다.
으로 한 번만 검사하고, 값이 *없으면* Spring Boot 기본(이 스켈레톤은 `application.yml`에서 OSIV off
가 기본)에 맡기며 *있는 `true`*만 거부한다.
### JpaSchemaSafetyValidator
- **Flyway를 production physical schema의 유일한 writer로 유지한다.** `prod` profile에서는
`spring.jpa.hibernate.ddl-auto``none` 또는 `validate`일 때만 허용한다. `update`, `create`,
`create-drop` 또는 그 밖의 값이면 `APP_DATASOURCE_DDL_AUTO`를 이름으로 포함한
`PROFILE_MISMATCH`로 부팅을 중단한다.
- **local 개발 편의와 production 권위를 분리한다.** non-prod profile의 `update`/`create`는 이
validator가 막지 않는다. prod profile 비교와 mode 비교는 대소문자를 무시해 `PROD`/`UPDATE`
같은 변형도 guard를 우회하지 못한다.
### RuntimeNumericBoundsValidator
- **고위험 숫자 노브(pool/thread 사이징)만 일부러 좁게 검증한다.** pool/connector 사이징 키는
Spring-native property(`spring.datasource.hikari.*`, `server.tomcat.*`)로 직결되고 `env-keys.yaml`