# Object Storage Batch B Checkpoint - Date: 2026-07-28 - Branch: `codex/objectstorage-production-capability` - Worktree: `/home/donghyeon/workspace/clean-architecture-backend-template-objectstorage` - Evidence grade: repository-local non-skipping unit/contract/application-context tests - Advanced cards: local managed single upload R1, local managed download R1 - R2 or production-provider readiness advanced: no ## Implemented scope - Added deterministic data/control namespaces, opaque reference/handle codecs, canonical request fingerprints, frozen binding/policy revisions, and bounded operation epochs. - Added six strict canonical JSON control-record families with fixed field order, outer SHA-256 envelopes, schema/size checks, corruption rejection, and checked-in golden digests. - Added provider-neutral publication, scan, reference, direct-session, multipart, and pending-effect state transitions with same-operation replay and conflicting-intent rejection. - Added a provider contract and `filesystem-local-dev` implementation with bounded streaming, immutable exclusive create, SHA-256 verification, exact inspect/version, full/range transfer, conditional retirement, create resolution, restrictive permissions, and path/symlink confinement. - Added single-process exact-version control CAS and restart/corruption/fault characterization. Logical control keys use `.record` physical leaves locally so object-store-valid prefix/leaf key pairs cannot collide as filesystem file/directory paths. - Added constructor-bound `app.object-storage` settings and compile-before-construction provider/destination/route/policy binding. The capability is disabled by default and `filesystem-local-dev` is rejected for `prod`/`production`. - Added disabled, unselected, invalid, selected-success, selected-construction-failure, close, legacy-only, and namespace-separated dual-run composition tests. - Added semantic routing evidence for publish, replay without producer invocation, inspect, full transfer, absent reference, and exact retained route lookup. - Added the exact nine-card readiness registry. Only local managed single upload/download are R1; direct, multipart, quarantine, retention, and production reconciliation remain R0. ## TDD and defect evidence Planned RED checks failed for the intentionally absent codec/kernel/provider/settings/readiness types before each implementation. Additional tests found and drove these corrections: - Local control keys may legally have both a leaf and a child in object storage, while a filesystem cannot have both `reference` and `reference/lifecycle`; local physical `.record` mapping fixed the collision without changing logical keys. - `ObjectInspectionPort.inspect` initially threw for an absent known-route reference; it now returns `Optional.empty()` while incomplete/corrupt evidence still fails closed. - The application purity test initially scanned its own test output after a full `check`; it now derives the production class root from a production contract type. - The general B7 ArchUnit rule initially classified objectstorage provider-internal SPI/control return values as public adapter responses. The existing negative fixture remains active, while a dedicated non-empty rule now checks the actual objectstorage `*Adapter` semantic boundaries. No skipped Docker or external-service test is used as Batch B readiness evidence. ## GREEN verification All commands ran from `src/` unless noted and completed with `BUILD SUCCESSFUL` after the documented RED/fix cycles: ```bash ./gradlew :adapter:outbound:objectstorage:verifyDependencyLocks --console=plain ./gradlew :adapter:outbound:objectstorage:test \ --tests '*ObjectNamespaceCodecTest' \ --tests '*ObjectRequestFingerprintCodecTest' \ --tests '*ObjectOperationEpochTest' --console=plain ./gradlew :adapter:outbound:objectstorage:test \ --tests '*ObjectControlRecordCodecTest' \ --tests '*ObjectOperationStateMachineTest' \ --tests '*ObjectOperationKernelTest' --console=plain ./gradlew :adapter:outbound:objectstorage:test \ --tests '*ObjectStorageProviderContract' \ --tests '*LocalDevObjectStorageProviderTest' \ --tests '*LocalDevObjectStorageRecoveryTest' --console=plain ./gradlew :adapter:outbound:objectstorage:test \ --tests '*ObjectStorageBindingCompilerTest' \ --tests '*ObjectStorageCapabilityConfigTest' \ --tests '*RoutingObjectStorageAdapterTest' --console=plain ./gradlew :adapter:outbound:objectstorage:test \ --tests '*ObjectStorageReadinessRegistryTest' --console=plain ./gradlew :sample-portfolio:test --console=plain ./gradlew :application-core:check \ :adapter:outbound:objectstorage:check --console=plain ./gradlew :app-bootstrap:test --tests '*CleanArchitectureTest' --console=plain ./gradlew verifyCleanArchitectureDependencies --console=plain ``` The final combined application/objectstorage checkpoint completed in 23 seconds. The focused Clean Architecture suite and dependency verification also passed. ## LLM Wiki capture The canonical vault required by repository policy, `/home/donghyeon/workspace/ai-tool/llm-wiki-private/`, and its parent `/home/donghyeon/workspace/ai-tool/` do not exist in this environment. Therefore the required `raw/branch-notes/codex-objectstorage-production-capability.md` and any derived raw documents could not be created or updated. No similarly named non-canonical clone was used. This exact access block is recorded in the plan/design status and at this Batch B boundary. ## Remaining gates and risks - `filesystem-local-dev` has no multi-node linearizability or power-loss durability evidence and is forbidden in production profiles. - The canonical S3/MinIO provider contribution, async bounded transport, provider qualification, response-loss fault tests, and protected AWS evidence are not implemented. - Direct grants, multipart, quarantine/scan, retention/legal hold, privileged purge, reapers, and production reconciliation remain R0. - The sample Poster workflow still uses the deprecated whole-`byte[]` port and transaction-coupled legacy choreography. It is explicitly activated only in sample local/test configuration. - External API/broker consumers and deployed legacy data remain uninspected, so Gate A still blocks destructive migration or legacy removal.