@@ -226,7 +226,9 @@ type Session = {token: Text, pubkey: PubkeyHex, expiresAt: Timestamp, ip: Text}
226226-- `encryptedBlob` (the server cannot read it). `deliveredTo` records peers
227227-- that have already accepted a federated forward of this blob, so a later
228228-- presence re-announce of `toKey` doesn't trigger a duplicate delivery.
229−type Message = {toKey: PubkeyHex, encryptedBlob: BlobHex, receivedAt: Timestamp, deliveredTo: [ServerName]}
229+-- (Single-field record rows, not bare names: the Knot runtime cannot persist
230+-- a nested relation of scalars.)
231+type Message = {toKey: PubkeyHex, encryptedBlob: BlobHex, receivedAt: Timestamp, deliveredTo: [{server: ServerName}]}
230232-- Last-known location of a pubkey, either local (`server == serverHost`) or
231233-- learned from a peer via gossip. Multiple entries per pubkey are allowed.
232234type PresenceEntry = {pubkey: PubkeyHex, server: ServerName, expiresAt: Timestamp}
@@ -657,8 +659,8 @@ retryPendingForwards = do
657659 else x) (filter (\x -> not isDone x) cur)
658660 when success (do
659661 msgs <- *messages
660− *messages = map (\m -> if m.toKey == f.toKey && m.encryptedBlob == f.encryptedBlob && not elem server m.deliveredTo
661− then {m.toKey, m.encryptedBlob, m.receivedAt, deliveredTo: union m.deliveredTo [server]}
662+ *messages = map (\m -> if m.toKey == f.toKey && m.encryptedBlob == f.encryptedBlob && not any (\d -> d.server == server) m.deliveredTo
663+ then {m.toKey, m.encryptedBlob, m.receivedAt, deliveredTo: union m.deliveredTo [{server}]}
662664 else m) msgs)))))
663665
664666-- Forward queued messages to a server when a remote key comes online.
@@ -670,7 +672,7 @@ forwardQueuedToServer = \pubkey server -> atomic (do
670672 fwds <- *forwards
671673 let existing = count (filter (\f -> f.toServer == server) fwds)
672674 let budget = max 0 (maxForwardsPerServer - existing)
673− let candidates = filter (\m -> m.toKey == pubkey && not any (forwardMatches m.encryptedBlob server) fwds && not elem server m.deliveredTo) msgs
675+ let candidates = filter (\m -> m.toKey == pubkey && not any (forwardMatches m.encryptedBlob server) fwds && not any (\d -> d.server == server) m.deliveredTo) msgs
674676 let newFwds = map (\m -> {toServer: server, m.toKey, m.encryptedBlob, retries: 0}) (take budget (sortBy (\m -> m.receivedAt) candidates))
675677 *forwards = union fwds newFwds)
676678
@@ -897,8 +899,8 @@ forkForwardsTo = \to encryptedBlob servers -> forEach servers (\server -> when (
897899 fwds <- *forwards
898900 *forwards = filter (\x -> not same x) fwds
899901 msgs <- *messages
900− *messages = map (\m -> if m.toKey == to && m.encryptedBlob == encryptedBlob && not elem server m.deliveredTo
901− then {m.toKey, m.encryptedBlob, m.receivedAt, deliveredTo: union m.deliveredTo [server]}
902+ *messages = map (\m -> if m.toKey == to && m.encryptedBlob == encryptedBlob && not any (\d -> d.server == server) m.deliveredTo
903+ then {m.toKey, m.encryptedBlob, m.receivedAt, deliveredTo: union m.deliveredTo [{server}]}
902904 else m) msgs)))
903905
904906-- ============================================