# Object Storage Phase 0 Inventory - Captured: 2026-07-28 - Branch: `codex/objectstorage-production-capability` - Scope: repository-local source, tests, configuration, migrations, and documentation - Evidence grade: repository-local only; deployed data, broker subscribers, and external REST consumers were not inspected ## Commands ```bash rg -n 'application\.storage|ObjectStoragePort|StoredObject|ca-skeleton\.objectstorage|file://|s3://' \ src docs rg -n 'image_key|posters/.*/image' src/sample-portfolio rg -n 'poster\.image-attached|StoredObjectResponse|PosterResponse|imageKey' \ src/sample-portfolio docs ``` The commands completed successfully in the isolated worktree. Results are classified below. Documentation hits in the Object Storage design/plan describe the migration and are not runtime consumers. The `s3://bucket/key-1` fixture in `IdempotencyStoreAdapterTest` belongs to the generic idempotency response-reference test and is not an Object Storage legacy-port consumer. ## Repository-local runtime inventory | Contract/data | Producer | Repository-local consumers | Classification | | --- | --- | --- | --- | | `ObjectStoragePort` / `StoredObject` | `application-core/application/storage` | filesystem and S3 adapters, `UploadPosterImageUseCase`, `PosterController`/`PosterWebMapper` | legacy runtime contract | | `ca-skeleton.objectstorage.*` | `ObjectStorageSettings` / `ObjectStorageConfig` | sample runtime through its objectstorage runtime dependency | legacy runtime configuration | | `file://` receipt | `FilesystemObjectStorageAdapter` | `StoredObjectResponse.location` through `PosterWebMapper` | public legacy locator | | `s3://bucket/key` receipt | `S3ObjectStorageAdapter` | `StoredObjectResponse.location` through `PosterWebMapper` | public legacy locator | | `/posters/{id}/image` | `PosterController` | repository tests and the generated/public HTTP contract | legacy inbound API | | `StoredObjectResponse` | `PosterController` / `PosterWebMapper` | HTTP caller, with `key`, `size`, `contentType`, and `location` | legacy response DTO | | `PosterResponse.imageKey` | `PosterWebMapper` | list/get/create/update/publish/archive HTTP responses | legacy general response field | | `poster.image-attached` | `PosterEventPublisher` | no subscriber found in this repository | versionless broker event; external consumers unknown | | `poster.image-attached.imageKey` | `PosterImageAttached` and publisher JSON | no subscriber found in this repository | raw locator-shaped event field | | `poster.image_key` | Flyway V6, `PosterEntity`, persistence mapper | `Poster` aggregate and repository adapter | stored-data schema | | `posters/{id}/image` key | `UploadPosterImageUseCase` | aggregate `imageKey`, event payload, DB row, HTTP response | deterministic overwriteable legacy key | ## Executable characterization The following tests pin the current behavior without approving it as the target design: - `LegacyObjectStorageBehaviorTest` - caller-selected keys overwrite; - `get` returns `Optional` and materializes the whole object; - receipts expose `file://` and `s3://` locators. - `LegacyObjectStorageConfigTest` - missing backend configuration selects filesystem; - context creation creates the filesystem directory before the first write; - `autoCreateBucket=true` probes and creates a missing bucket during S3 bean construction. - `LegacyPosterImageUploadCharacterizationTest` - remote storage is called while `TransactionPort.inWrite` is active; - the controller calls `MultipartFile.getBytes`; - the response exposes raw key and provider location; - Poster deletion leaves the legacy object untouched. ## External inventory gap and Gate A Repository search does not prove that the following have no deployed consumers: - `POST /posters/{id}/image`; - `StoredObjectResponse.key` and `.location`; - `PosterResponse.imageKey`; - broker event type `poster.image-attached` and its `imageKey` payload; - rows already stored in `poster.image_key`; - filesystem/S3 objects already written under `posters/{id}/image`. No deployed database, object namespace, access log, API client catalog, broker consumer group, schema registry, or owning team approval was inspected. Therefore removal, in-place field rename, event payload replacement, or legacy-object deletion remains blocked. Approval Gate A must obtain owner and consumer evidence and choose an additive/versioned migration contract.