Os anexos/carregamentos antigos e quebrados aparecem como
[{nome do arquivo}|attachment](/uploads/default/original/2X/6/{hash sha1 + extensão}) no texto bruto da postagem. Isso é processado como href="/uploads/default/original/2X/6/{hash sha1 + extensão}", o que quebra os anexos de arquivo, mas não as imagens.
Posteriormente, anexos funcionais aparecem como [{nome do arquivo}|attachment](upload://{sha1 para base62 + extensão}) e são processados como href="/uploads/short-url/{sha1 para base62 + extensão}.
Escrevi um pequeno código em Ruby para percorrer todas as postagens no período problemático conhecido e substituir todas as URLs de carregamento antigas pela versão mais recente. Utilizei a função base62_sha1 do modelo Upload para converter o hash sha1 no nome de arquivo esperado que as URLs curtas do Discourse aguardam.
Isso fez com que os anexos funcionassem. Em seguida, executei outro rebake apenas para confirmar a correção, e parece que ainda está funcionando. Parece que o problema residia apenas em Post.raw e não tinha nada a ver com Upload.