485 lines
20 KiB
Markdown
485 lines
20 KiB
Markdown
# JPA/PostgreSQL Production Capability Implementation Plan
|
||
|
||
> 상태: Phase 0~3 기반과 Phase 4의 idempotency/outbox polling/inbox 후보 구현 및 전체
|
||
> local/real PostgreSQL 검증을 마쳤다. 검증을 통과한 항목은 `implemented-candidate`이며
|
||
> immutable 운영 evidence가 없는 항목을 R2로 승격하지 않는다. Phase 5~7은 외부 topology와
|
||
> policy prerequisite가 없어 `not-implemented`를 유지한다.
|
||
|
||
- 작성일: 2026-07-28
|
||
- 구현 branch: `codex/jpa-production-capability`
|
||
- worktree:
|
||
`/home/donghyeon/workspace/clean-architecture-backend-template-jpa`
|
||
- 시작 revision: `b3add0162df8d4a0a11e749e514901defe0a62a3`
|
||
- 설계 원본:
|
||
`/home/donghyeon/workspace/clean-architecture-backend-template/docs/superpowers/specs/2026-07-28-jpa-production-capability-design.md`
|
||
- 설계 SHA-256:
|
||
`c02eaef2a193a6ca66f4814087cc4d6bce723509aec251f40ea7b029046fd234`
|
||
|
||
설계 문서는 `main` worktree의 untracked 사용자 변경이므로 stage/commit/copy하지 않는다. 구현
|
||
중에는 위 절대 경로와 hash를 승인된 정본 snapshot으로 사용한다. 정본이 바뀌면 hash drift를
|
||
먼저 보고하고 해당 task의 설계를 재검토한다.
|
||
|
||
## 1. 목표와 완료 경계
|
||
|
||
목표는 JPA/PostgreSQL leaf의 각 capability를 독립적으로 구현·검증하는 것이다.
|
||
|
||
```text
|
||
truthful baseline
|
||
-> transaction/failure/deadline
|
||
-> entity/query discipline
|
||
-> migration/lifecycle/security
|
||
-> owner-safe reliability
|
||
-> optional replica
|
||
-> optional tenant/coordination
|
||
-> R3 rehearsal
|
||
```
|
||
|
||
한 phase의 unit test 통과를 전체 JPA R2로 확대하지 않는다. card가 R2가 되려면 설계 §31.3의
|
||
prerequisite, real PostgreSQL task, zero-skip sentinel과 immutable evidence manifest를 모두
|
||
충족해야 한다.
|
||
|
||
현재 구현 작업의 완료 경계는 다음과 같다.
|
||
|
||
1. 독립 worktree와 계획이 존재한다.
|
||
2. Phase 0의 SQLState, Duration, OSIV/DDL, machine-readable readiness baseline이
|
||
fail-closed한다.
|
||
3. named transaction policy, absolute deadline, PostgreSQL local timeout, phase-aware outcome,
|
||
bounded serialization/deadlock retry가 구현된다.
|
||
4. PostgreSQL 16 real test source set에서 lifecycle/security/migration/transaction/
|
||
aggregate/query가 무-skip로 실행된다.
|
||
5. owner-safe idempotency V2, immutable outbox storage V2, polling delivery V2, same-store
|
||
inbox가 독립 migration stream과 real PostgreSQL concurrency test를 가진다.
|
||
6. 외부 CDC, replica, tenant/RLS, R3는 토폴로지/evidence 없이 선택하거나 R2로 광고하지 않는다.
|
||
7. 전체 test/check와 Wiki capture 결과를 기록한다.
|
||
|
||
## 2. 공통 구현 규칙
|
||
|
||
- `src/config/architecture/modules.json`의 19개 leaf와 edge를 유지한다.
|
||
- `domain-core`에는 Spring/JPA/JDBC/PostgreSQL type을 추가하지 않는다.
|
||
- application contract에는 framework-neutral Java type만 둔다.
|
||
- transaction boundary는 application use case가 `TransactionPort`로 소유한다.
|
||
- controller/repository/mapper/configuration에 business policy를 두지 않는다.
|
||
- PostgreSQL 전용 code/import는 persistence-jpa leaf의 `.postgresql` package에 둔다.
|
||
- 동작 변경은 failing test를 먼저 확인한 뒤 최소 production code를 작성한다.
|
||
- applied Flyway V1/V3/V4/V5는 수정하지 않는다.
|
||
- agent는 stage/commit/amend/push하지 않는다.
|
||
- 다른 worktree의 dirty/untracked 변경을 복사하거나 되돌리지 않는다.
|
||
|
||
worktree 생성 직후 `src/gradlew.bat`는 CRLF blob과 checkout/attribute line-ending
|
||
normalization 차이 때문에 dirty로 표시된다. 비교 결과 의미 있는 텍스트 변경은 없지만 raw
|
||
worktree hash와 HEAD blob hash는 EOL 표현 때문에 다르다. targeted restore로도 사라지지 않는
|
||
known baseline drift이므로 구현 diff와 완료 판정에서 분리하고 stage하지 않는다.
|
||
|
||
## 3. Phase 0 — Truthful baseline과 contract freeze
|
||
|
||
### Task 0.1 SQLState mapping duplicate fail-fast
|
||
|
||
상태: 2026-07-28 구현 및 focused/architecture 검증 완료.
|
||
|
||
소유 leaf: `adapter-outbound-persistence-jpa`
|
||
|
||
파일:
|
||
|
||
- 수정:
|
||
`src/adapter/outbound/persistence-jpa/src/test/java/dev/caskeleton/adapter/outbound/persistence/failure/PersistenceExceptionTranslatorTest.java`
|
||
- 수정:
|
||
`src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/failure/PersistenceExceptionTranslator.java`
|
||
- 필요 시 수정:
|
||
`src/adapter/outbound/persistence-jpa/README.md`
|
||
|
||
TDD:
|
||
|
||
1. 서로 다른 두 `SqlStateErrorMapping`이 같은 exact SQLState에 같은
|
||
`OperationalError`를 등록해도 constructor가 실패하는 test를 작성한다.
|
||
2. 같은 SQLState에 서로 다른 `OperationalError`를 등록하면 실패하는 test를 작성한다.
|
||
3. error message가 raw SQL, credential, endpoint 없이 duplicate SQLState와 mapping
|
||
contributor type을 식별하는지 검증한다.
|
||
4. focused test를 실행해 RED를 확인한다.
|
||
5. `putAll`을 explicit merge로 바꾸고 first/duplicate provenance를 보존한다.
|
||
6. null mapping/map/key/value와 `08*` pseudo-entry를 fail-fast할지 현재 SPI 계약에 맞춰
|
||
validation test를 추가한다. 이 세부 계약은 범위를 키우지 않고 constructor invariant로
|
||
한정한다.
|
||
7. focused test를 GREEN으로 만든다.
|
||
|
||
검증:
|
||
|
||
```bash
|
||
cd src
|
||
./gradlew :adapter:outbound:persistence-jpa:test \
|
||
--tests 'dev.caskeleton.adapter.outbound.persistence.failure.PersistenceExceptionTranslatorTest' \
|
||
--console=plain
|
||
./gradlew :adapter:outbound:persistence-jpa:test --console=plain
|
||
./gradlew verifyCleanArchitectureDependencies --console=plain
|
||
```
|
||
|
||
### Task 0.2 Duration/OSIV/DDL production safety
|
||
|
||
상태: 2026-07-28 strict Duration와 prod DDL guard 구현 완료. OSIV guard는 기존 구현을
|
||
재사용하고 함께 회귀 검증했다.
|
||
|
||
소유 leaf:
|
||
|
||
- `app-bootstrap`: runtime settings/startup validator
|
||
- `adapter-outbound-persistence-jpa`: typed provider settings가 필요할 때만
|
||
|
||
선행 조사 파일:
|
||
|
||
- `src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/runtime/HikariPoolConstraintValidator.java`
|
||
- `src/app-bootstrap/src/test/java/dev/caskeleton/bootstrap/runtime/HikariPoolConstraintValidatorTest.java`
|
||
- `src/app-bootstrap/src/main/resources/application.yml`
|
||
- `src/app-bootstrap/CLAUDE.md`
|
||
|
||
TDD:
|
||
|
||
1. `5s`, `PT5S`, millisecond number의 canonical/legacy 허용 matrix를 test로 고정한다.
|
||
2. invalid/unknown Duration을 skip하지 않고 startup failure로 만드는 RED를 확인한다.
|
||
3. `spring.jpa.open-in-view=true`를 거절한다.
|
||
4. production profile의 `ddl-auto=update|create|create-drop`을 거절한다.
|
||
5. local/sample compatibility를 별도 test로 유지한다.
|
||
|
||
검증:
|
||
|
||
```bash
|
||
cd src
|
||
./gradlew :app-bootstrap:test \
|
||
--tests 'dev.caskeleton.bootstrap.runtime.HikariPoolConstraintValidatorTest' \
|
||
--console=plain
|
||
./gradlew :app-bootstrap:test --tests '*CleanArchitectureTest' --console=plain
|
||
./gradlew verifyEnvKeys --console=plain
|
||
```
|
||
|
||
### Task 0.3 Machine-readable readiness baseline
|
||
|
||
상태: 2026-07-28 구현 및 mutation/registry 검증 완료.
|
||
|
||
파일:
|
||
|
||
- 추가: `src/config/jpa/readiness-cards.yaml`
|
||
- 수정: `src/build.gradle`
|
||
- 추가: persistence-jpa readiness registry parser/validation tests
|
||
|
||
구현:
|
||
|
||
1. 설계 §31.3의 15 card와 7 owned migration stream을 exact key로 옮긴다.
|
||
2. unknown/missing card, duplicate task, cycle, missing prerequisite, duplicate
|
||
location/history를 fail-closed한다.
|
||
3. 현재 구현되지 않은 task/card는 `not-implemented`로 유지한다.
|
||
4. 존재하지 않는 target task를 통과 증거로 만들지 않는다.
|
||
5. registry structural verification task를 `check`의 architecture policy chain에 연결하되
|
||
real PostgreSQL readiness를 거짓으로 통과시키지 않는다.
|
||
|
||
## 4. Phase 1 — Transaction/failure/deadline foundation
|
||
|
||
상태: 2026-07-28 application contract, Spring executor, local timeout, phase-aware outcome,
|
||
bounded retry/backoff 후보 구현 완료. commit fault injection과 immutable R2 manifest는 남아 있다.
|
||
|
||
### Task 1.1 Additive application transaction contract
|
||
|
||
소유 leaf: `application-core`
|
||
|
||
예상 파일:
|
||
|
||
- 추가: `transaction/TransactionPolicy.java`
|
||
- 추가: `transaction/CallBudget.java`
|
||
- 추가: `transaction/OperationId.java`
|
||
- 추가: `transaction/TransactionOutcome.java`
|
||
- 추가: `transaction/PolicyTransactionPort.java`
|
||
- 수정: `transaction/TransactionPort.java`
|
||
- tests: 같은 package의 pure unit tests
|
||
|
||
계약:
|
||
|
||
- 기존 `inWrite`, `inRead`, `inNew` source compatibility 유지
|
||
- named write policy는 stable operation ID 요구
|
||
- legacy facade는 non-replayable/uncorrelated policy로 격리
|
||
- absolute deadline과 finite timeout intersection
|
||
- core에는 Spring `TransactionDefinition`/`DurationStyle`을 노출하지 않음
|
||
|
||
### Task 1.2 Spring policy executor와 propagation ownership
|
||
|
||
소유 leaf: `adapter-outbound-persistence-jpa`
|
||
|
||
예상 파일:
|
||
|
||
- 수정: `transaction/SpringTransactionPort.java`
|
||
- 추가: `transaction/SpringPolicyTransactionPort.java`
|
||
- 추가: transaction phase/outcome collaborator
|
||
- tests: unit + real PostgreSQL task
|
||
|
||
검증:
|
||
|
||
- REQUIRED physical owner와 participant 구분
|
||
- REQUIRES_NEW depth/capacity admission
|
||
- read/write route mismatch fail-fast
|
||
- commit callback ordering
|
||
- locale 없는 `toLowerCase()` 제거
|
||
|
||
### Task 1.3 Deadline와 PostgreSQL local timeout
|
||
|
||
- Hikari acquisition은 fixed pool timeout으로 유지
|
||
- action 시작 전 remaining budget pre-gate
|
||
- first statement 전 `SET LOCAL statement_timeout`, `lock_timeout`
|
||
- transaction/statement/lock rounding boundary test
|
||
- pool wait 뒤 total budget overshoot negative test
|
||
|
||
### Task 1.4 Phase-aware failure/retry
|
||
|
||
- operation/query executor를 모든 production persistence path에 연결
|
||
- constraint name allowlist
|
||
- begin/action/flush/commit/after-completion phase 분류
|
||
- `COMMIT_INDETERMINATE`는 blind retry 금지
|
||
- pre-commit + replay-safe + budget 조건에서만 whole-transaction retry
|
||
|
||
## 5. Phase 2 — Entity/query discipline
|
||
|
||
상태: production template에 임의 business aggregate를 추가하지 않고 sample의 기존 entity/
|
||
mapper/query discipline을 실제 PostgreSQL aggregate CAS와 query-plan fixture로 검증했다.
|
||
|
||
### Task 2.1 Aggregate persistence baseline
|
||
|
||
- domain aggregate와 persistence entity 분리
|
||
- mapper round-trip과 invariant failure test
|
||
- optimistic version/expected-version conflict
|
||
- audit creation carry-forward와 bulk DML guard
|
||
- bounded persistence-context batch
|
||
|
||
### Task 2.2 Purpose-built query model
|
||
|
||
- application projection `*QueryPort`
|
||
- allowlisted query ID
|
||
- max page/IN bound와 signed/versioned keyset cursor
|
||
- N+1 statement budget
|
||
- native/JDBC query는 `.postgresql` package
|
||
- representative `EXPLAIN` invariant task
|
||
|
||
## 6. Phase 3 — Migration/lifecycle/security
|
||
|
||
상태: legacy V1/V3/V4/V5/V6 adoption, independent core stream, PostgreSQL 16 lifecycle/security/
|
||
migration/transaction/aggregate/query candidate task와 content-addressed manifest producer 구현
|
||
완료. TLS verify-full/role/redaction, pool lifecycle, fresh/interrupted/rolling migration,
|
||
transaction concurrency/fault dimension을 실제 PostgreSQL과 transport test로 채웠다. clean CI
|
||
provenance와 외부 restore rehearsal이 없으면 R2/R3 aggregation은 계속 fail-closed한다.
|
||
|
||
### Task 3.1 Legacy adoption과 independent streams
|
||
|
||
- legacy V1/V3/V4/V5 checksum/object fingerprint
|
||
- `capability_schema_registry`
|
||
- explicit target stream version-0 adoption command
|
||
- core/optional history table ownership
|
||
- fresh/LEGACY_ADOPTED/interrupted paths
|
||
- old/target dual authority rejection
|
||
|
||
### Task 3.2 Real PostgreSQL qualification source set
|
||
|
||
canonical tasks:
|
||
|
||
```text
|
||
postgresqlLifecycleIntegrationTest
|
||
postgresqlSecurityBaselineIntegrationTest
|
||
postgresqlMigrationIntegrationTest
|
||
postgresqlTransactionIntegrationTest
|
||
postgresqlAggregateIntegrationTest
|
||
postgresqlQueryIntegrationTest
|
||
verifyJpaPrimaryFoundationEvidence
|
||
```
|
||
|
||
Docker/Testcontainers가 없으면 R2 lane은 skip이 아니라 fail이다. local optional task와 evidence
|
||
producer를 분리한다.
|
||
|
||
구현된 evidence task:
|
||
|
||
```text
|
||
verifyJpaEvidenceHarnessContract
|
||
generateJpaEvidenceManifests
|
||
verifyJpaCandidateEvidence
|
||
verifyJpaPrimaryFoundationEvidence
|
||
```
|
||
|
||
candidate task는 11개 active card의 exact JUnit selector, zero-skip count, source/이미지/의존성
|
||
version과 prerequisite manifest ID를 SHA-256 filename manifest로 남긴다. primary task는
|
||
`-PjpaEvidenceProfile=r2`, clean revision, CI job/artifact metadata, 모든 base dimension과
|
||
prerequisite R2를 추가로 요구한다.
|
||
|
||
### Task 3.3 Lifecycle/security
|
||
|
||
- migration/runtime role 분리
|
||
- trusted schema/search_path, `PUBLIC CREATE`/`TEMP` revoke
|
||
- TLS verify-full profile
|
||
- startup/readiness/shutdown/quiesce
|
||
- bounded/redacted metric/trace/log
|
||
- restore/forward-recovery runbook
|
||
|
||
## 7. Phase 4 — Owner-safe same-store reliability
|
||
|
||
상태: idempotency V2, outbox storage V2, polling delivery V2, inbox V1은 각각
|
||
`implemented-candidate`. 네 stream 모두 fresh-disabled/first-enable/disable/re-enable/
|
||
interrupted-recovery의 non-destructive lifecycle을 실제 PostgreSQL에서 검증한다. CDC는 external
|
||
messaging prerequisite가 없어 `not-implemented`다.
|
||
|
||
독립 implementation slice:
|
||
|
||
1. `jpa-idempotency-owner-safe-v2`
|
||
2. `jpa-outbox-storage-v2`
|
||
3. `jpa-outbox-polling-delivery-v2` 또는 `jpa-outbox-cdc-retention-v1`
|
||
4. `jpa-inbox-same-store-v1`
|
||
|
||
각 slice는 자기 migration stream/task/manifest를 가진다.
|
||
|
||
outbox storage 구현은:
|
||
|
||
- V3 `outbox_event`를 수정하지 않음
|
||
- `outbox_publication_control_v2`
|
||
- `outbox_publication_cutover_v2`
|
||
- `outbox_event_identity_v2`
|
||
- `outbox_event_log_v2`
|
||
- polling 선택 시에만 `outbox_delivery_v2`
|
||
- fresh/legacy genesis sentinel
|
||
- legacy mutation trigger/ACL fence
|
||
- paused old writer와 cutover barrier test
|
||
|
||
를 포함한다.
|
||
|
||
## 8. Phase 5–7
|
||
|
||
상태: 선택된 replica topology, tenant mode/RLS policy, target-like backup/failover environment가
|
||
없으므로 registry에서 `not-implemented`를 유지한다. 로컬 단일 PostgreSQL 테스트를 해당
|
||
운영 보장의 대체 evidence로 사용하지 않는다.
|
||
|
||
### Phase 5 — Primary/replica
|
||
|
||
- 별도 pool/route context
|
||
- explicit `ReadConsistency`
|
||
- endpoint-bound lag evidence
|
||
- strong/RYW primary default
|
||
- failover authority reconciliation
|
||
|
||
### Phase 6 — Tenant/RLS와 JDBC coordination
|
||
|
||
- tenant-prefixed unique/FK/query
|
||
- missing context fail-closed
|
||
- optional FORCE RLS
|
||
- runtime role bypass negative test
|
||
- JDBC coordination은 `EFFICIENCY_ONLY`
|
||
|
||
### Phase 7 — R3
|
||
|
||
- target-like load/capacity
|
||
- failover, rolling migration, certificate rotation
|
||
- backup/PITR restore
|
||
- outbox/idempotency/inbox reconciliation
|
||
- measured RPO/RTO와 operator game day
|
||
|
||
## 9. 공통 verification ladder
|
||
|
||
변경 leaf focused test부터 실행한다.
|
||
|
||
```bash
|
||
cd src
|
||
./gradlew :application-core:test --console=plain
|
||
./gradlew :adapter:outbound:persistence-jpa:test --console=plain
|
||
./gradlew :app-bootstrap:test --tests '*CleanArchitectureTest' --console=plain
|
||
./gradlew verifyCleanArchitectureDependencies --console=plain
|
||
./gradlew verifyPublicPathSnapshot --console=plain
|
||
./gradlew verifyEnvKeys --console=plain
|
||
```
|
||
|
||
전체 `test`/`check`와 real PostgreSQL task는 해당 phase가 경계를 실제로 변경하거나 required
|
||
task를 추가한 시점에 실행한다. 실행하지 못한 명령은 이유와 남은 위험을 branch-note와 최종
|
||
응답에 기록한다.
|
||
|
||
## 10. Wiki capture
|
||
|
||
각 의미 있는 slice가 끝날 때 실제 vault의 branch-note:
|
||
|
||
```text
|
||
raw/branch-notes/codex-jpa-production-capability.md
|
||
```
|
||
|
||
에 다음을 누적한다.
|
||
|
||
- design hash와 plan path
|
||
- 변경 파일/decision ID
|
||
- RED/GREEN/architecture command와 결과
|
||
- 실패/차단/known baseline drift
|
||
- evidence grade와 아직 R2가 아닌 이유
|
||
- 실제 파생 raw interview/blog/error 판단
|
||
|
||
canonical 문서는 별도 요청 전 생성하지 않는다.
|
||
|
||
## 11. 최종 실행 결과
|
||
|
||
2026-07-28:
|
||
|
||
- `./gradlew :sample-portfolio:test --console=plain`
|
||
→ 성공, 176 tests.
|
||
- `./gradlew test --console=plain`
|
||
→ 성공, 1m 59s.
|
||
- PostgreSQL readiness task 10개
|
||
(`lifecycle`, `security`, `migration`, `transaction`, `aggregate`, `query`, `idempotency`,
|
||
`outbox-storage`, `outbox-polling`, `inbox`)
|
||
→ 성공, 49s. XML 합계 23 tests, `skipped=0`, `failures=0`, `errors=0`.
|
||
- `./gradlew check --console=plain`
|
||
→ 성공, 2m 9s, 209 actionable tasks. 같은 실행에서 root architecture policy,
|
||
Checkstyle, Spotless, SpotBugs와 custom PostgreSQL source set 검증을 통과했다.
|
||
- `./gradlew verifyCleanArchitectureDependencies verifyPublicPathSnapshot verifyEnvKeys
|
||
verifyJpaReadinessRegistry --console=plain`
|
||
→ 성공. 19개 leaf edge, 1개 public path, 113 env keys, exact 15 cards/7 streams 검증.
|
||
- `git diff --check`
|
||
→ 진단 없음.
|
||
- `./gradlew :adapter:outbound:persistence-jpa:verifyJpaPrimaryFoundationEvidence --console=plain`
|
||
→ 기존 unconditional sentinel을 제거했다. content-addressed candidate manifest를 검증한 뒤
|
||
candidate profile과 observability, TLS/role/redaction, fresh/interrupted/rolling migration,
|
||
transaction concurrency 누락을 card별 blocker로 보고 R2를 차단한다.
|
||
- `./gradlew :adapter:outbound:persistence-jpa:verifyJpaCandidateEvidence --console=plain`
|
||
→ 성공, active card 11개 manifest 생성. PostgreSQL 23 tests와 primary base aggregation
|
||
7 tests 모두 zero-skip이고 content hash/prerequisite link를 검증했다.
|
||
- `bash .github/scripts/verify-gate-matrix.sh`
|
||
→ 성공, 21 gates verified. PR candidate evidence job과 conditional R2 workflow가 registry에
|
||
반영됐다.
|
||
- CI metadata를 주입한
|
||
`verifyJpaPrimaryFoundationEvidence -PjpaEvidenceProfile=r2`
|
||
→ PostgreSQL 23 tests와 r2-profile manifest 11개 생성 뒤 의도된 실패, 1m 21s.
|
||
`worktree-is-dirty`, observability, TLS/roles/redaction, migration
|
||
fresh/interrupted/rolling, transaction concurrency를 실제 blocker로 보고했다.
|
||
- `./gradlew test --console=plain`
|
||
→ 성공, 15s, 78 tasks up-to-date. 직전 evidence lane에서 persistence/app test는 강제
|
||
재실행했다.
|
||
- `./gradlew check verifyPublicPathSnapshot verifyDependencyLocks --console=plain`
|
||
→ 성공, 9s, 230 actionable tasks(37 executed, 193 up-to-date).
|
||
|
||
전체 test에서 발견한 sample Flyway 회귀는 independent `V1` stream을 broad
|
||
`classpath:db/migration`으로 합친 문제와 production/sample `V6` 충돌이었다. sample slice를
|
||
legacy PostgreSQL location으로 한정하고 disposable poster migration을 `V7`로 이동했다. 세부
|
||
재현·해결 기록은 Wiki
|
||
`raw/errors/flyway-independent-stream-broad-root-collision-2026-07-28.md`에 남겼다.
|
||
|
||
2026-07-29 completion pass:
|
||
|
||
- primary foundation의 pool lifecycle/observability, TLS verify-full/role/redaction,
|
||
fresh/interrupted/rolling migration, transaction concurrency/fault evidence를 추가했다.
|
||
- idempotency/outbox storage/outbox polling/inbox 네 독립 stream에
|
||
fresh-disabled/first-enable/disable/re-enable/interrupted-recovery 실제 PostgreSQL
|
||
lifecycle test를 추가했다.
|
||
- `./gradlew :adapter:outbound:persistence-jpa:verifyJpaCandidateEvidence --console=plain`
|
||
→ **BUILD SUCCESSFUL in 1m 55s**. 11개 manifest 모두 `missing=none`, zero-skip.
|
||
PostgreSQL producer 38 tests와 web redaction support 2 tests가 실행됐으며 primary
|
||
aggregation은 20 tests다.
|
||
- `./gradlew test --console=plain`
|
||
→ **BUILD SUCCESSFUL in 55s**, 78 actionable tasks.
|
||
- `./gradlew check verifyPublicPathSnapshot verifyDependencyLocks --console=plain`
|
||
→ 포맷과 test fixture SQL construction을 수정한 뒤 **BUILD SUCCESSFUL in 12s**,
|
||
231 actionable tasks. 19 leaf architecture, Checkstyle, Spotless, SpotBugs, dependency lock,
|
||
env/readiness/public-path gate를 통과했다.
|
||
- CI 메타데이터 형식만 주입한
|
||
`verifyJpaPrimaryFoundationEvidence -PjpaEvidenceProfile=r2`
|
||
→ **의도된 BUILD FAILED in 2m 6s**. missing evidence는 없고 root blocker는
|
||
`worktree-is-dirty`; 다른 blocker는 prerequisite R2 전파뿐이다.
|
||
- `bash .github/scripts/verify-gate-matrix.sh`
|
||
→ **OK**, 21 gates/21 verified.
|
||
- `git diff --check`
|
||
→ 진단 없음.
|
||
|
||
현재 환경에서 선택된 Phase 0~4 후보의 로컬 구현·검증은 완료됐다. R2 승격은 사람의
|
||
commit/push, clean revision에서의 retained CI artifact가 필요하고, R3는 target-like
|
||
backup/failover/load/operator rehearsal 환경이 필요하다.
|