apps/backend/src/lib/storage.ts issues real S3 presigned URLs in production but falls back to fakeUrl() in development — a string-templated URL never backed by an actual file. Nothing exercises the upload/download flow end-to-end locally. Build a real local-filesystem-backed object store for development implementing the same surface as ObjectStore (putObject/getObject/deleteObject/getPresignedPutUrl/getPresignedGetUrl), backed by files under a gitignored local directory and served through a local Express route.
Acceptance criteria:
- A local-disk object store implementation exists, matching
ObjectStore's shape, storing bytes under a gitignored local directory
- A local route serves GET/PUT against stored bytes so presigned URLs issued in development are real, working URLs
lib/storage.ts's isProduction() branch selects local-disk in dev/test and real S3 in production
- No Docker/MinIO required — the local store is pure Node
fs
fileCleanup.ts's hard-delete pass works correctly against the local store in dev
apps/backend/src/lib/storage.tsissues real S3 presigned URLs in production but falls back tofakeUrl()in development — a string-templated URL never backed by an actual file. Nothing exercises the upload/download flow end-to-end locally. Build a real local-filesystem-backed object store for development implementing the same surface asObjectStore(putObject/getObject/deleteObject/getPresignedPutUrl/getPresignedGetUrl), backed by files under a gitignored local directory and served through a local Express route.Acceptance criteria:
ObjectStore's shape, storing bytes under a gitignored local directorylib/storage.ts'sisProduction()branch selects local-disk in dev/test and real S3 in productionfsfileCleanup.ts's hard-delete pass works correctly against the local store in dev