Federation & Friends¶
Foundation Protocol's federation layer connects multiple Host nodes; the friendship layer connects two entities across (or within) those hosts. Both are gated by self-presented identity, with cryptographic verification at the message layer.
Implementation: fp/core/wellknown.py, fp/host.py, fp/core/checkpoint.py (FriendRequestCheckPoint).
Host discovery — .well-known¶
When two hosts come into contact, each side exposes a .well-known document:
# fp/core/wellknown.py
class HostWellKnown(BaseModel):
name: str
uid: HostUid
url: str
public_entities: list[EntityCard] = Field(default_factory=list)
A .well-known contains:
- The host's identity (
name,uid,url) - The list of public entity cards the host advertises
It does not contain private host credentials, and the current implementation does not require the document itself to be signed by an external authority.
For a child host registering with a parent, the parent reads the child's .well-known and accepts the declared identity. This is best thought of as an identity claim, not an authentication credential. The boundary is documented explicitly under Known Gaps.
Friend request — first contact between two entities¶
Entities only accept most message kinds from peers already in their friends list (see Checkpoint Pipeline). Bootstrapping that relationship is the job of the FRIEND_REQUEST / FRIEND_ACCEPT / FRIEND_REJECT message family, handled by FriendRequestCheckPoint (fp/core/checkpoint.py).
The flow:
Alice Bob
│ │
│ FRIEND_REQUEST │
│ payload.sender_card = Alice.entity_card ───────►│
│ │
│ (Bob's mail.unseal extracts │
│ sender_card.sign_public_key │
│ and verifies signature) │
│ │
│ ├─► if Bob has an owner:
│ │ queue APPROVAL_REQUEST
│ │ to the owner
│ │
│ ├─► owner approves
│ │
│ FRIEND_ACCEPT │
│◄──────────── payload.sender_card = Bob.entity_card
│ │
│ Alice.add_friend(Bob) Bob.add_friend(Alice)
Two security-relevant properties:
-
The friend request itself is signed.
Mail.unsealverifies the signature using thesign_public_keyembedded inpayload.sender_card. So while the identity claim insender_cardis self-asserted, the binding between that claim and the message is cryptographic — a third party cannot forge a request that appears to come from a given sender card. -
Owner approval is supported. Entities with an
ownerfield can route friend requests throughCallOwnerMixin(fp/core/checkpoint.py) and pause the request as anAPPROVAL_REQUESTto the owner. The friendship is not established until the owner responds withAPPROVAL_RESPONSE. See Checkpoint Pipeline for the resume mechanics.
Friend list and storage¶
# fp/entity.py
def add_friend(self, card: EntityCard) -> None:
"""Store a friend's EntityCard, keyed by entity_uid."""
self.friends[card.entity_uid] = card
The friend list is just a dict from entity_uid to EntityCard. Every subsequent inbound message from that peer will be verified against the sign_public_key stored on the card.
What this gives you, and what it does not¶
| The runtime guarantees | The runtime does not yet guarantee |
|---|---|
| Sender of a friend request cannot be impersonated once you trust the card | The card itself is not an externally-attested credential |
| Every subsequent message from a friend is signature-verified | A host serving a .well-known is who it claims to be |
| Owner approval, if configured, is mandatory before friendship is recorded | Multi-party confirmation of friendship |
These boundaries are spelled out under Known Gaps.
Next: how every inbound message is gated — Checkpoint Pipeline.