From b6557d6409fa97d5dde2f4d2614443ba6d1c8ea2 Mon Sep 17 00:00:00 2001 From: Paul Hitt Date: Fri, 28 Aug 2026 17:44:05 -0400 Subject: [PATCH] Re-tell the delivery key when a told peer writes unsealed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirror of the iOS change: the poll path un-marks a toldPeer whose message arrived unsealed — their copy of our key is gone, and the next send re-tells it. Same staleness class, and same cure, as the avatar marker. Co-Authored-By: Claude Fable 5 --- .../main/kotlin/io/flamenet/client/Conversations.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/client/src/main/kotlin/io/flamenet/client/Conversations.kt b/client/src/main/kotlin/io/flamenet/client/Conversations.kt index 40d215e..e3c6995 100644 --- a/client/src/main/kotlin/io/flamenet/client/Conversations.kt +++ b/client/src/main/kotlin/io/flamenet/client/Conversations.kt @@ -613,6 +613,19 @@ class Conversations( val fromUser = opened?.claimedFromUser ?: message.fromUser val content = Content.parse(plaintext) consumeControl(fromUser, content) + // 🔴 An UNSEALED message from a contact we have told our + // delivery key means their copy is gone — a reinstall wiped + // it. Sealing to us requires that key, and a peer who holds + // it seals everything. Un-mark them so the next send re-tells + // it; until then the relay sees their sender on every message + // they write us. Worst case: one redundant control envelope. + if (!sealed && fromUser != 0L) { + vault.loadDelivery()?.let { d -> + if (fromUser in d.toldPeers) { + vault.saveDelivery(d.copy(toldPeers = d.toldPeers - fromUser)) + } + } + } out += Received(message.id, fromUser, fromDevice, content, sealed = sealed, at = message.createdAt) } catch (_: Exception) {