The migration sweep converted permanent conversations, messages, and shares to
the forced (ephemeral) window but left File records untouched. Files use a
retention-scoped expiredAt that application code sweeps (getExpiredFiles only
returns files whose own expiredAt is set), so uploads from migrated chats kept
expiredAt: null and lingered in storage after the conversation and messages
TTL out.
Add capConversationFiles and cap each converted conversation's files to the
same per-conversation deadline in sweepForcedRetention (and thread the File
model through the migration). Files with no expiration or a later one are set
to the deadline; files already expiring sooner are preserved. Scoped by
conversationId alone since File.user is an ObjectId rather than the string user
id the other cascades filter on. Under ephemeral retention every
conversation-scoped file is meant to expire, so no persistent-agent-file
exclusion is needed here.