merge: integrate object storage production capability

This commit is contained in:
donghyeon-ka
2026-08-01 00:57:40 +09:00
445 changed files with 32429 additions and 796 deletions
@@ -1,13 +1,15 @@
# Object Storage Production Capability Deep Design
- 작성일: 2026-07-28
- 상태: 상세 설계 및 구현 계획 완료, 구현 미착수, R2 미구현
- 상태: Approval Gate A 승인 반영, Batch AD 및 Batch E pause checkpoint를 main에 통합, R2 미구현
- 독립 재리뷰: 완료 — 아키텍처 및 문서 실행성 blocker 0, high 0
- LLM Wiki capture: 정본 vault
`/home/donghyeon/workspace/ai-tool/llm-wiki-private/` 부재로 차단; 비정본 clone 대체 사용 안 함
- LLM Wiki capture: public vault
`raw/branch-notes/chore-main-worktree-capability-integration.md`에 main 통합 기록 완료
- 기준: Java 21, Spring Boot 4.0.0, Gradle 멀티모듈 Clean Architecture
- 대상 leaf: `adapter-outbound-objectstorage`
- 현재 구현 수준: whole-object `byte[]` 기반 local filesystem/S3-MinIO 예제, R0~R1 일부
- 현재 구현 수준: provider-neutral kernel + `filesystem-local-dev` managed single R1,
S3 managed/direct primitives, exact MinIO mutation profiles `UNSUPPORTED`,
legacy whole-object filesystem/S3-MinIO 격리
- 상위 문서:
[Production Capability Platform Design](2026-07-26-production-capability-platform-design.md)
- 구현 계획:
@@ -19,39 +21,100 @@
## 0. 구현 상태
2026-07-28 기준 구현된 범위는 다음뿐이다.
### Approval Gate A 결정 — 2026-07-29
사용자의 구현 계속 승인에 따라 Batch E의 public/sample 계약을 다음과 같이 고정한다.
- production scanner는 주장하지 않는다. 스캔 경계는 test fake만 제공하고 첫 sample
destination profile은 `integrity-verified-reference`로 한다.
- canonical surface는 additive
`POST /posters/{id}/imagePublications`와 별도 authorized GET status resource다. 저장소의
AIP-122 경로 규칙에 따라 collection segment에는 kebab-case를 사용하지 않는다.
POST는 항상 동일한 bounded `202` reservation을 반환하며 READY 결과를 같은 idempotency
response에 섞지 않는다.
- 정확한 full-file SHA-256은 canonical Base64 형식의 bounded multipart field로 받고 TX1 전에
semantic fingerprint에 포함한 뒤 staging 중 다시 검증한다.
- `Idempotency-Key`는 필수다. 첫 committed UploadIntent가 stable operation ID를 할당하며
generic idempotency reservation과 intent는 같은 TX1에서 원자적으로 commit한다.
- sample authorization은 기존 `poster:write` permission을 유지한다. 존재하지 않는 Poster
owner 속성을 발명하지 않는다.
- legacy `/posters/{id}/image`는 명시적 compatibility profile에서만 유지한다. canonical과
legacy controller는 동시에 활성화하지 않는다.
- 기존 `poster.image-attached`/`imageKey` 이벤트는 변경하거나 제거하지 않는다. canonical
흐름은 새 versioned V2 event를 사용하며 외부 zero-consumer를 주장하지 않는다.
- OpenAPI 승인은 새 publication/status surface에만 한정한다. 기존 DTO의 locator-shaped
필드는 compatibility window 동안 그대로 둔다.
- 통합 타임라인의 V8은 additive, forward-only다. V7 Poster schema의 `image_key`와 legacy
reader를 유지하고 canonical writer는
READY opaque reference만 기록한다. rollback은 구 binary가 additive columns를 무시하는
binary-only window이며 down migration이나 자동 object mutation은 없다.
2026-07-28 Batch D 체크포인트 기준 다음 범위가 구현되었다.
- `application-core`의 framework/provider-neutral object-storage identity, opaque reference,
bounded content callback, digest/range, request/receipt/outcome, capability requirement;
- managed, staged, direct single/multipart, scan-maintenance, purge-maintenance를 분리한 narrow port;
- 모든 mutation의 `ObjectOperationKey`, strict reference grammar/checksum, transient grant redaction;
- application contract의 framework/provider/transport/persistent-locator purity 검사;
- legacy port/receipt의 removal-boundary deprecation과 sample legacy import freeze;
- deterministic `data/v1`/`control/v1` namespace, reference/handle/fingerprint/policy codec,
operation epoch와 immutable route/policy snapshot;
- strict canonical JSON control envelope와 operation/manifest/reference/multipart record,
reserve/replay/conflict/pending-effect state kernel;
- bounded immutable local create, exact inspect/version, full/range transfer, conditional retire,
create resolution, symlink/path confinement, restrictive permissions와 single-process CAS;
- constructor-bound `app.object-storage` settings, compile-before-construction provider
contribution/assembler, destination/retained-route routers, disabled/unselected/invalid/close
side-effect matrix;
- explicit canonical legacy subgroup와 old alias isolation, sample local/test explicit activation;
- exact nine-card readiness registry. `filesystem-local-dev` managed single upload/download만 R1,
나머지는 R0;
- pinned AWS SDK `2.30.0` conditional/checksum/expected-owner API characterization과 explicit
`NettyNioAsyncHttpClient` policy/factory/lifecycle;
- exact AWS/MinIO binding, bounded async transport, managed S3 single/multipart/control primitives,
response-loss resolution, selected-only provider composition;
- durable direct single/multipart session and grant records, S3 presigner lifecycle, exact part
acknowledgement, completion/abort fences, terminal exact-version replay;
- digest-pinned MinIO contract/fault lanes and protected AWS compile-only lane. Exact MinIO는
create-only PUT/complete 조건을 무시하므로 managed/direct mutation profile을
`UNSUPPORTED`로 유지하며 readiness를 올리지 않는다.
증거는 [Batch A checkpoint](../../evidence/object-storage/batch-a-checkpoint.md),
[Batch B checkpoint](../../evidence/object-storage/batch-b-checkpoint.md),
[Batch C checkpoint](../../evidence/object-storage/batch-c-progress.md),
[Batch D checkpoint](../../evidence/object-storage/batch-d-checkpoint.md),
[Batch E pause checkpoint](../../evidence/object-storage/batch-e-pause-checkpoint.md)에 기록했다.
격리 브랜치에서는 private vault 경로를 잘못 선택해 capture가 차단됐지만, main 통합 작업은
사용자가 지정한 public vault의
`raw/branch-notes/chore-main-worktree-capability-integration.md`에 캡처했다.
legacy runtime 범위는 별도로 유지된다.
- `application-core`의 범용 `ObjectStoragePort`;
- caller가 지정한 raw key에 `byte[]`를 put/get/delete/exists하는 계약;
- local filesystem adapter;
- synchronous AWS SDK v2 `S3Client`를 사용하는 S3/MinIO adapter;
- 설정 한 개로 filesystem 또는 S3 backend를 선택하는 Spring composition;
- 명시적 legacy-only filesystem 또는 S3 Spring composition;
- filesystem unit test, mocked S3 unit test, Testcontainers MinIO integration test;
- module registry가 허용한 `application-core`, `shared-contract` 의존성.
아직 구현되지 않은 범위:
아직 구현되지 않은 runtime/provider 범위:
- streaming upload/download와 range read;
- immutable object reference와 version token;
- stable operation ID, request fingerprint, durable operation record;
- conditional create/update/delete와 unknown-outcome reconciliation;
- checksum 생성·전송·검증 계약;
- metadata/head 계약;
- staged upload, quarantine, scan, publication;
- presigned upload/download;
- multipart start/part/complete/abort/recovery;
- public presigned upload/download endpoint와 inbound authorization;
- R2 수준의 exhaustive multipart/direct response-loss·race·restart qualification;
- lifecycle, versioning, retention, legal hold 검증;
- production credential, encryption, TLS, expected-owner 정책;
- bounded timeout, connection pool, retry amplification, graceful shutdown;
- provider capability qualification과 exact readiness card;
- multi-node linearizable control CAS와 production unknown-outcome reconciliation;
- production credential, encryption, TLS, retention/Object Lock qualification;
- orphan/abandoned multipart/retired object reaper;
- database와 object storage 사이의 crash-safe workflow;
- 운영 metric, trace, audit, runbook;
- AWS sandbox fault/security evidence.
따라서 현재 MinIO round-trip test가 통과하더라도 S3 production readiness를 의미하지 않는다.
이 문서의 상태가 “상세 설계 완료”인 것은 구현, R2 qualification 또는 운영 준비 완료를
뜻하지 않는다.
Batch B의 R1은 exact local functional topology 증거다. Multi-node CAS, power-loss durability,
S3/MinIO qualification, R2 또는 운영 준비 완료를 뜻하지 않는다.
## 1. 설계 판정
@@ -3955,8 +4018,10 @@ authorization endpoint의 ephemeral response이며 stored object DTO에 영구
정본 구현 순서와 아래 결정의 현재 freeze/approval gate는
[Object Storage Production Capability Implementation Plan](../plans/2026-07-28-objectstorage-production-capability.md)에
기록한다. 계획 작성은 완료됐지만 모든 구현 task는 아직 미착수이며, 계획 승인이 public API,
scanner provider 또는 AWS/IaC 외부 변경 권한을 자동으로 부여하지 않는다.
기록한다. Tasks 124의 구현은 Batch E pause checkpoint까지 진행됐지만 Batch E 전체
combined/root gate는 아직 통과하지 않았다. Tasks 25–30은 미착수다. 이 구현 진행이나
계획 승인이 public API, scanner provider 또는 AWS/IaC 외부 변경 권한을 자동으로 부여하지
않는다.
구현 계획은 다음 결정을 task 단위로 명시해야 한다.