Snapshot of the in-flight state that already existed, identically, in both this worktree and the main checkout before this session began: the initial HTTP Client platform implementation (previously untracked), the redis-lab removal, and the JPA / object-storage / notification integration work. Kept separate from this session's HTTP Client review response, which lands in the following commit, so the two bodies of work stay reviewable apart. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
adapter:outbound:objectstorage — design-decision reference
Object-storage driven adapter under
dev.caskeleton.adapter.outbound.objectstorage. It implements the semantic contracts in
dev.caskeleton.application.objectstorage and keeps provider keys, paths, SDK types, and control
records behind the application boundary.
The allowed production dependencies are owned by
src/config/architecture/modules.json. Module rules live in CLAUDE.md, the full design
in docs/superpowers/specs/2026-07-28-objectstorage-production-capability-design.md, and exact
evidence claims in docs/registries/object-storage-readiness.yaml.
Current readiness
Batch B implements the provider-neutral namespace/control kernel and
filesystem-local-dev managed single upload/download at R1. R1 means bounded local functional
evidence only:
- immutable streamed create with exact SHA-256 and exact version inspection;
- full/range bounded reads;
- strict canonical control-record codecs and single-process CAS;
- same-operation replay without invoking the producer again;
- restart/path/symlink/corruption/fault characterization;
- exactly-once selected-provider lifecycle.
It does not prove multi-node CAS, power-loss durability, production credentials/TLS/IAM/encryption, S3 response-loss behavior, or R2 readiness. Direct transfer, multipart, quarantine, retention, and production reconciliation cards remain R0.
Activation and routing
The canonical namespace is app.object-storage and is disabled by default. Enabling it requires an
explicit provider, exact provider version, logical destination, route token, binding/policy
revisions, and bounded sizes. Settings compile fully before any selected provider creates a
directory, client, thread, scheduler, or credential lookup.
filesystem-local-dev is rejected under prod/production. Normal composition contributes only
managed publication, inspection/transfer, retirement, and operation-resolution ports. Scanner and
privileged purge composition remain separate and empty; no direct-grant port is registered.
The local provider maps provider-neutral logical control keys to .record leaf files. This permits
object-store-valid pairs such as reference and reference/lifecycle without a filesystem
file/directory collision; callers and durable control records retain the canonical logical keys.
Legacy compatibility
ObjectStoragePort, StoredObject, and the old whole-byte[] filesystem/S3 adapters are deprecated
compatibility only. They preserve overwrite/raw-key semantics in an isolated namespace and never
back the new semantic ports.
- Preferred temporary activation:
app.object-storage.legacy.enabled=truewith an explicit backend and namespace. - Old
ca-skeleton.objectstorage.*properties remain an explicit legacy-only alias. - Mixing any old alias with canonical settings fails startup without echoing values.
- The sample
local/testprofiles explicitly opt into legacy filesystem storage until its consumer migration; no production profile receives a local fallback.
Provider and dependency scope
The AWS SDK v2 BOM stays module-scoped because Spring Boot does not manage
software.amazon.awssdk:*. The existing legacy S3/MinIO adapter remains characterized but is not a
canonical production provider and advances no S3 readiness card.
Verification
Focused contracts cover codecs/state machines, local provider behavior, fail-closed binding, composition side effects/lifecycle, routing replay/read behavior, and the readiness registry.
cd src
./gradlew :adapter:outbound:objectstorage:check --console=plain