@@ -164,7 +164,10 @@ serve = \req -> case req of
164164 where not (c.pubkey == pubkey && c.challenge == challenge)
165165 yield c
166166 set *sessions = if sigValid
167− then union sessions [{token: token, pubkey: pubkey, expiresAt: expiry}]
167+ then union (do
168+ s <- sessions
169+ where not (s.pubkey == pubkey)
170+ yield s) [{token: token, pubkey: pubkey, expiresAt: expiry}]
168171 else sessions
169172 set *presence = if sigValid
170173 then union
@@ -183,6 +186,7 @@ serve = \req -> case req of
183186 t <- now
184187 let token = extractToken authorization
185188 session <- atomic do
189+ pruneExpired t
186190 sessions <- *sessions
187191 yield (lookupSession sessions token t)
188192 case session of
@@ -193,6 +197,7 @@ serve = \req -> case req of
193197 let pending = do
194198 m <- messages
195199 where m.toKey == s.pubkey
200+ where m.timestamp > t - messageMaxAge
196201 yield {id: m.messageId, eventType: "message",
197202 payload: toJson {toKey: m.toKey, fromKey: m.fromKey,
198203 encryptedBlob: m.encryptedBlob,
@@ -203,23 +208,26 @@ serve = \req -> case req of
203208 SendMessage {to, encryptedBlob, timestamp, authorization, respond} -> do
204209 t <- now
205210 msgId <- genToken
211+ let clampedTs = if timestamp > t then t else timestamp
206212 status <- atomic do
207213 pruneExpired t
208214 sessions <- *sessions
209215 messages <- *messages
216+ presence <- *presence
210217 let session = lookupSession sessions (extractToken authorization) t
211218 set *messages = case session of
212219 Nothing {} -> messages
213220 Just {value: s} -> union messages
214221 [{messageId: msgId, toKey: to, fromKey: s.pubkey,
215− encryptedBlob: encryptedBlob, timestamp: t}]
222+ encryptedBlob: encryptedBlob, timestamp: clampedTs}]
216223 let online = case session of
217224 Nothing {} -> False {}
218225 Just {value: _} -> count (do
219− s <- sessions
220− where s.pubkey == to
221− where s.expiresAt > t
222− yield s) > 0
226+ p <- presence
227+ where p.pubkey == to
228+ where p.server == serverHost
229+ where p.expiresAt > t
230+ yield p) > 0
223231 let status = case session of
224232 Nothing {} -> "unauthorized"
225233 _ -> if online then "delivered" else "queued"
@@ -229,6 +237,7 @@ serve = \req -> case req of
229237 AckMessages {messageIds, authorization, respond} -> do
230238 t <- now
231239 ok <- atomic do
240+ pruneExpired t
232241 sessions <- *sessions
233242 messages <- *messages
234243 let session = lookupSession sessions (extractToken authorization) t
@@ -249,6 +258,7 @@ serve = \req -> case req of
249258 LookupPresence {pubkey, authorization, respond} -> do
250259 t <- now
251260 foundServer <- atomic do
261+ pruneExpired t
252262 sessions <- *sessions
253263 presence <- *presence
254264 let session = lookupSession sessions (extractToken authorization) t
@@ -278,20 +288,28 @@ serve = \req -> case req of
278288 let onlineEntries = do
279289 e <- events
280290 where e.eventType == "online"
281− yield {pubkey: e.pubkey, server: e.server, expiresAt: t + clampTtl e.ttl * 1000}
291+ where not (e.server == serverHost)
292+ yield {pubkey: e.pubkey, server: e.server, expiresAt: t + (clampTtl e.ttl) * 1000}
282293 let affectedKeys = do
283294 e <- events
295+ where not (e.server == serverHost)
284296 yield {pubkey: e.pubkey, server: e.server}
285− let deduped = do
286− e <- onlineEntries
287− where count (do
288− o <- onlineEntries
289− where o.pubkey == e.pubkey
290− where o.server == e.server
291− where o.expiresAt > e.expiresAt
292− yield o) == 0
293− yield e
297+ let deduped = fold (\acc e ->
298+ if count (do
299+ a <- acc
300+ where a.pubkey == e.pubkey
301+ where a.server == e.server
302+ where a.expiresAt >= e.expiresAt
303+ yield a) > 0
304+ then acc
305+ else union
306+ (do
307+ a <- acc
308+ where not (a.pubkey == e.pubkey && a.server == e.server)
309+ yield a)
310+ [e]) [] onlineEntries
294311 atomic do
312+ pruneExpired t
295313 presence <- *presence
296314 let cleaned = diff presence (do
297315 p <- presence
@@ -309,6 +327,7 @@ serve = \req -> case req of
309327 let authorized = verifyFederationAuth authorization
310328 let clampedTs = if timestamp > t then t else timestamp
311329 atomic do
330+ pruneExpired t
312331 messages <- *messages
313332 let exists = count (do
314333 m <- messages
@@ -324,9 +343,11 @@ serve = \req -> case req of
324343 respond {ok: authorized}
325344
326345 FederationAck {messageIds, originServer, authorization, respond} -> do
346+ t <- now
327347 let authorized = verifyFederationAuth authorization
328348 let validAck = authorized && originServer == serverHost
329349 atomic do
350+ pruneExpired t
330351 messages <- *messages
331352 set *messages = if validAck
332353 then diff messages (do