Repository navigation
A friend request stays answerable for 30 days, across restarts - #49
Merged
Merged
Conversation
An acceptance is honoured only while the requester still has the matching outgoing entry, and that entry lived 10 minutes (2 x handshakeMaxAge), in memory only. People accept friend requests when they see them, often hours later, and by then the requester had forgotten asking: the accept (direct or relayed) was dropped as "unsolicited", the peer trusted the requester but not the other way round, and the requester showed the friend as waiting forever. A restart in between lost it the same way. Outgoing requests now live outgoingRequestTTL, which is the peer's pendingHandshakeTTL (30 days), are saved in trust.json with the trusted, pending and revoked state and restored on load (expired ones dropped), and are bounded at maxOutgoingRequests (4096, oldest forgotten first). Every removal goes through dropOutgoingLocked, which marks the state for saving, so a cancelled, rejected or completed request does not come back after a restart. The reaper test that encoded the old 10-minute rule now checks the new boundary; new tests cover an acceptance hours later (direct and relayed), a restart in between, a cancelled request across a restart, and the bound. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
An acceptance is honoured only while the requester still has the matching outgoing entry, and that entry lived 10 minutes (
2 × handshakeMaxAge), in memory only. People accept friend requests when they see them, often hours later. By then the requester had forgotten asking, so the accept was dropped as "unsolicited": the peer trusted the requester, but not the other way round, and the requester showed the friend as waiting forever. A restart in between lost the request the same way.Seen in production on Pilot Cloud on 2026-10-08: a request was accepted hours after it was sent and stayed "Waiting" until it was sent again. The peer then auto-accepted it, because it already trusted the requester.
Change
outgoingRequestTTL= the peer'spendingHandshakeTTL(30 days).trust.jsonalongside the trusted, pending and revoked state, and restored on load. Expired ones are dropped.maxOutgoingRequests(4096); the oldest is forgotten first.dropOutgoingLocked, which marks the state for saving, so a cancelled, rejected or completed request doesn't come back after a restart.Tests
zz_outgoing_lifetime_test.gocovers:go test -race ./...andgo vetare clean.🤖 Generated with Claude Code