An originator could misfile the answer to its own lookup as transit, so discovery reported "requests went unanswered" while the replies were in fact arriving and being reverse-path forwarded to a peer. A request is flooded to every tree peer whose bloom filter claims the target. At a high fill ratio a false positive sends a copy out into the wider network, which can circulate it back to the originator. On arrival `classify_request` applied its only identity test, `target == my_addr`, which a lookup we originated never satisfies, so the copy was recorded in `recent_requests` as an ordinary transit entry keyed on our own `request_id`. When the target answered, `classify_response` consulted `recent_requests` first, matched that entry, and relayed our own answer to the peer that looped the request. The pending lookup was never satisfied, the ladder retried with a fresh id, and the same race repeated. The `None` arm's reasoning — "not a request we transited, so it claims to answer one of ours" — held only while our own ids stayed out of the dedup cache, and nothing enforced that. `resp_unsolicited` pinned at zero while `resp_received == resp_forwarded` was the tell: control never reached the originator arm. Affected nodes showed `resp_accepted` at 1 of 291. It is a race, not a hard failure: when the genuine reply beats the looped copy the cache is still clean and the lookup succeeds. It bites hardest at the junction between a quiet subtree and a dense public network, where a lookup for a descendant goes both correctly downward and outward through a false positive, and the wide network returns it first. Two changes close it, on both sides of the invariant: - `classify_response` tests the pending lookups before `recent_requests`. A response naming a target with a lookup outstanding, carrying an id that lookup issued, is ours whatever the dedup cache holds. The id is fresh 64-bit randomness per attempt and the target signs over it, so an id we never issued still cannot match and the replay properties the `Unsolicited` arm protects are unchanged. - `classify_request` drops a request whose id a pending lookup for that target issued, rather than recording it. Our own id never enters the transit cache, so a duplicate reply cannot be misrouted after we accept the first, and the returning copy is not forwarded a second time. The guard keys on the id, so another node's lookup for the same target still transits normally. Verified against the reported deployment: discovery now completes where it previously exhausted the four-attempt ladder.
FIPS Documentation
FIPS (Free Internetworking Peering System) is a self-organizing encrypted mesh network built on Nostr identities, capable of operating over arbitrary transports — local networks, the public internet, Tor, Bluetooth, or point-to-point links — without central infrastructure.
With FIPS, your machine becomes a node in the mesh with a self-generated cryptographic identity. There are two ways to deploy it.
As an overlay on top of existing IP networks, FIPS lets your node reach any other FIPS node wherever it sits — behind a NAT, on a different ISP, on a phone over cellular, on a laptop with only Bluetooth in range, or behind a Tor onion. The mesh forwards IPv6 traffic transparently and end-to-end encrypted, with no central VPN concentrator or coordinating server.
From the ground up over raw Ethernet, WiFi, or Bluetooth, FIPS provides a complete permissionless network without any pre-existing IP infrastructure, ISP, or DNS. Any node that joins the link gets routable IPv6 addresses, peer discovery, and a path to every other node automatically.
Either way, existing networking software runs over it unchanged: SSH, HTTP servers, file transfer, anything IPv6-native works the same way it would on a local network.
New to FIPS? Start with the Getting Started guide.
Documentation Sections
Tutorials
If you are starting from scratch and want a guided path to a working mesh, go here.
How-To Guides
If you have a specific task in mind — enabling a feature, deploying a component, diagnosing a problem — go here.
Reference
If you need to look up wire formats, configuration keys, command flags, or counter inventories, go here.
Design
If you want to understand how the mesh self-organizes, why FIPS makes the choices it does, or how the pieces fit together, go here.
Releases
If you want the notes for a particular version — what changed, what broke, and what to do about it on upgrade — go here.