- File model + migration: file metadata, content lives in object storage
- IFileStorage port with local disk and S3-compatible (RustFS/MinIO) adapters
- POST /files, GET /files/:id/download, DELETE /files/:id
- MIME sniffed from content; only safe images served inline, nosniff header
- FileOwnerRegistry: owner modules register to grant visibility and keep
their files from GC; FileGcService removes orphaned files hourly
- TransformResponseInterceptor passes StreamableFile through
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>