V174: repair misclassified media rows (file_type / mime_type).
The corruption
Two writer defects, both since fixed at the write boundary
(Storage.store_file_in_buckets/7), left rows whose stored classification
contradicts what the file demonstrably is:
file_typepoisoned by the caller. The storage writer stored whateverfile_typethe call site claimed, unchecked. A live example: an external module's upload path hardcoded"image"while its picker accepted audio and video too — every.movand.mp3dropped on a board landed asfile_type: "image", and the media page trusts that column everywhere (broken<img>tiles, invisible to the video/audio filters, image variant processing run against a QuickTime file).mime_typeguessed from a map with no audio entries. The writer discarded the mime the caller observed and re-derived it from the extension via a hand-rolled map that knew no audio type at all, so every mp3/m4a/wav was stored — and served (file_controlleranswers with the instance's mime) — asapplication/octet-stream.
The repair
Same evidence-over-claim rule the write boundary now applies, in SQL:
- Rows (files AND file instances) whose mime is blank/octet-stream but
whose extension is in the known audio set get the real audio mime —
mirrors
Storage's@audio_mime_fallbacks. - Files whose (now-repaired) mime contradicts a generic
file_typetake the mime's classification — mirrorsStorage.determine_file_type/2's mime branch. Rows with no evidence (unknown mime) keep their claim, and non-generic system types ("tile") are never touched: internal machinery chose those deliberately and the classifier knows nothing about them.
Width/height/duration and missing variants are NOT backfilled here — the variant pipeline owns those, and re-queueing jobs is not a migration's business. A repaired row simply renders correctly from now on.
Down
Deliberately a no-op (marker stamp only). The pre-repair values were wrong, there is no record of which rows held them, and re-corrupting data is not a rollback anyone wants.