Appearance
Storage Media Parity Smoke
Scope
This opt-in smoke supports P3-002 by comparing a real legacy media asset read with the native document-service read path. It is read-only: it fetches legacy metadata/content, fetches native content, compares byte hashes, and writes artifacts for review.
The smoke does not change the default gateway route table and does not create, update, or delete media assets.
Modes
STORAGE_PARITY_NATIVE_MODE=asset-id: compare legacy/api/storage/media-assets/{id}/contentwith native/v1/storage/media-assets/{id}/content.STORAGE_PARITY_NATIVE_MODE=storage-key: read the legacy detail payload, extractstorageKey, and compare original legacy content with native/v1/storage/objects/content?storageKey=.... This helps prove object-store byte parity before native media metadata backfill exists.STORAGE_PARITY_NATIVE_MODE=gateway: compare legacy direct content with gateway/api/storage/media-assets/{id}/contentwhile the gateway usesdeploy/gateway/routes.storage-native-localhost-example.json.STORAGE_PARITY_NATIVE_MODE=auto: try native asset-id content first, then fall back to storage-key for theoriginalvariant.
Required Runtime
Start these processes before live mode:
- legacy API, default
LEGACY_API_BASE_URL=http://localhost:4001 document-service, defaultDOCUMENT_BASE_URL=http://localhost:8097- optional API gateway, default
GATEWAY_BASE_URL=http://localhost:8085 - shared object storage reachable by both legacy and native services
For gateway mode, start the gateway with:
bash
GATEWAY_ROUTE_TABLE=deploy/gateway/routes.storage-native-localhost-example.jsonCompose route-table proof uses the sibling table:
bash
GATEWAY_ROUTE_TABLE=deploy/gateway/routes.storage-native-example.jsonThat Compose-facing v2 table is strict: it does not contain a broad /api fallback and does not expose the legacy single-PUT presigned write route.
Run
Static self-test:
bash
cd go-platform
STORAGE_PARITY_SELF_TEST=1 make test-storage-media-parityLive original-byte parity:
bash
cd go-platform
STORAGE_PARITY_MEDIA_ASSET_ID=<legacy-media-asset-id> \
STORAGE_PARITY_AUTHORIZATION='Bearer <token>' \
STORAGE_PARITY_ORGANIZATION_ID=<org-id> \
STORAGE_PARITY_NATIVE_MODE=auto \
make test-storage-media-parityLive image variant parity when native media metadata exists:
bash
STORAGE_PARITY_MEDIA_ASSET_ID=<image-media-asset-id> \
STORAGE_PARITY_AUTHORIZATION='Bearer <token>' \
STORAGE_PARITY_ORGANIZATION_ID=<org-id> \
STORAGE_PARITY_NATIVE_MODE=asset-id \
STORAGE_PARITY_VARIANTS=original,trim,formula \
make test-storage-media-parityAssertions
The smoke fails unless:
- legacy media detail returns
2xx - each requested legacy content variant returns
2xx - the matching native content path returns
2xx - SHA-256 hashes match for each compared variant
- in gateway mode, the native response includes
X-Hoctapaz-Gateway-Route: storage
Artifacts are written under output/storage-media-parity-* by default and include raw response bodies, headers, media summary, and parity-report.json.
Browser Proof Gate
This smoke proves HTTP/media byte parity; it is not browser UI proof by itself. Before public storage route promotion, the owning slice must add a named browser smoke that opens a real import/question/document page through the frontend, loads media through the gateway, and verifies browser-observed storage route headers plus rendered media artifacts.
Minimum browser proof:
- frontend started with API calls pointed at
api-gateway - gateway started with the matching non-default storage route table
document-serviceand shared object storage reachable- browser observes the expected
X-Hoctapaz-Gateway-Routefor a storage read - rendered image/document content is non-empty and matches the media asset or storage-key fixture under test
- artifacts are written under
output/playwright/
Rollback
Switch GATEWAY_ROUTE_TABLE back to deploy/gateway/routes.json, remove the native storage route entry, or set it to legacy_proxy. This smoke does not mutate runtime data.