The rule that keeps this from making the product worse: the shorter
timer always wins. Without it a sender could defeat the recipient's
conversation timer by putting a long secs on every message — turning a
setting the recipient chose, on their own device, into something the
other party overrules.
🔴 pruneExpired returned early when the CONVERSATION had no timer, so a
timed message in an untimed thread would have been kept for ever — the
feature working on the sending phone and doing nothing on the receiving
one. Pruning is per message now.
⚠️ Content.text returns raw bytes with no envelope when it has nothing
to carry, so the timer had to join that decision or it would be dropped
and the message would live for ever.
The sender's own copy expires too: a timer that only cleared the
recipient's phone would leave the message with the person who set it.
Refs paulhitt/flamenet-messenger-ios#29
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>