The old broken attachments/uploads show up as
[{file name}|attachment](/uploads/default/original/2X/6/{sha1 hash + extension}) in the post’s raw text. This gets cooked as href="/uploads/default/original/2X/6/{sha1 hash + extension}", which breaks file attachments, but not images.
Later working attachments appear as [{file name}|attachment](upload://{sha1 to base62 + extension}) and get cooked as href="/uploads/short-url/{sha1 to base62 + extension}.
I wrote a little ruby code to go through all the posts in the know problematic time period and replaced all the old upload urls with the newer version. I utilized the Upload model’s base62_sha1 function to convert the sha1 hash to the expected file name that discourse short urls are expecting.
This made the attachments work. Then I ran another rebake just to confirm the fix, and it seems to still be working. It seems like the problem just resided in Post.raw and didn’t have anything to do with Upload.