feat: add JPA production capability
This commit is contained in:
@@ -0,0 +1,484 @@
|
||||
# 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 환경이 필요하다.
|
||||
Reference in New Issue
Block a user