d3chat Federation Protocol
Source of truth:
d3chat/backend/app/federation/inbox.pyd3chat/backend/app/federation/client.pyd3chat/backend/app/federation/discovery.pyd3chat/backend/app/federation/handlers.pyd3chat/backend/app/federation/relay.pyd3chat/backend/app/crypto/signing.py
Protocol Objectives
Federation in d3chat provides:
- cross-server channel/user interoperability
- signed request authenticity
- replay resistance
- duplicate-event suppression
- bounded-abuse controls on peer traffic
It is designed as a signed event relay protocol over HTTP, not a distributed consensus system.
Server Identity and Discovery
Well-known endpoint
Every server exposes:
GET /.well-known/d3chat-serverReturns:
domainsigning_key_publicapi_base_urlprotocol_version
Discovery flow
When a server needs unknown peer metadata:
- query local
serverstable - if absent/stale, fetch well-known over HTTPS (fallback HTTP for development)
- cache and persist peer metadata
Discovery is cached in-memory with TTL and persisted in database.
Request Signing Model
Signature payload
Signing payload is:
METHOD + "\n" + PATH + "\n" + TIMESTAMP + "\n" + SHA256(BODY)Signed with Ed25519 private key. Signature is base64-encoded.
Required headers
X-D3Chat-OriginX-D3Chat-TimestampX-D3Chat-Signature
Verification steps (inbound)
- validate required headers
- parse and validate timestamp
- enforce replay window
- enforce per-origin rate limit
- discover origin server and fetch verify key
- verify signature over canonical payload
Replay and Dedup Semantics
Replay window
Requests are rejected if timestamp exceeds ±5 minute window.
Event dedup
Each event carries event_id. Inbound handler uses Redis SET NX with TTL (24h) to suppress duplicates.
Federation Endpoints
POST /federation/inbox
Single event ingress route for all event types.
General event envelope:
{ "event_id": "<unique-id>", "origin_server": "chat.example.com", "timestamp": "<iso8601-or-compatible>", "type": "message.relay", "...": "event-specific payload"}GET /federation/user-lookup?username=<name>
Signed lookup endpoint for remote servers to resolve local users.
Response example:
{ "found": true, "username": "alice", "user_id": "<uuid>", "server_domain": "chat.example.com"}Event Types and Handling
channel.invite
Behavior:
- resolves local invitee
- resolves/creates remote inviter user
- creates federated channel if missing
- adds memberships
- publishes
channel.newto invitee websocket topic
message.relay
Behavior:
- resolves/creates remote sender
- verifies channel existence and sender membership
- inserts message row with origin metadata
- publishes local
message.new
sender_key.distribute
Behavior:
- upserts sender key for remote device/channel
- publishes
sender_key.newevent for local clients to refetch keys
channel.join / channel.leave
Behavior:
- mutates membership state for remote user in local channel context
Outbound Relay Behavior
Message relay
On local message creation in federated channel:
- compute remote server list from remote members
- construct signed event payload
- POST to remote inbox with timeout
Sender key relay
On sender-key distribution in federated channel:
- emit signed
sender_key.distributeto remote peers
Invite relay
When adding remote user to local channel:
- emit signed
channel.inviteto remote user’s server
Reliability and Failure Model
Expected failures
- remote server unreachable
- signature rejection due to clock drift or stale keys
- partial peer fanout success
Current behavior
- logs failures and returns boolean success on sender side
- no durable retry queue in current implementation
For stronger delivery guarantees, production operators may add deferred retry queues and idempotency tracking outside current baseline.
Security and Abuse Controls
- origin-level request rate limits on inbox path
- replay window enforcement
- explicit signature verification against discovered peer key
- event dedup to suppress replayed payload effects
Residual risk areas:
- peer key rotation handling maturity
- long network partitions without retry queue
- deployment misconfiguration (clock skew, TLS termination issues)
Mobile Client Implications
Clients do not sign federation directly, but must correctly handle resulting cross-server effects:
- remote users appearing via lookup
- federated channel flags
- relay-originated messages and sender-key updates
- eventual consistency timing across peers
Recommended client strategy:
- treat realtime events as hints
- re-fetch authoritative channel/message slices on reconnect
- tolerate duplicate or reordered relay arrivals using id dedup and created_at ordering