Federation overview
Federation lets independently operated Zentalk servers exchange messages, discover each other’s users, and route traffic across server boundaries while each operator keeps full control over their own data and users.
Two federation layers
Section titled “Two federation layers”Zentalk federates at two distinct layers. Both must be healthy for cross-server messaging to work end to end.
| Layer | Component | Transport | Purpose |
|---|---|---|---|
| API federation | zentalk-api |
HTTPS (mTLS in production) | Server registration, challenge/verify authentication, signed message delivery, user lookup |
| Node federation | zentalk-node (relay + mesh) |
libp2p (TCP, TLS 1.3/Noise) | Shared Kademlia DHT, distributed user directory, relay routing, delivery confirmation |
API layer
Section titled “API layer”Each API server holds an Ed25519 server identity. The server ID is cryptographically derived from the public key, so a peer cannot claim an ID it does not own — registration is rejected if the claimed ID does not match the key. The keypair is generated with federation-keygen and stored encrypted with a passphrase.
Servers authenticate to each other with a challenge/verify handshake, then exchange messages through a persistent inbox/outbox pipeline with retry, replay protection (nonce store), and per-server rate limiting.
Node layer
Section titled “Node layer”Relays and mesh nodes from all federated servers join a shared DHT (via a common bootstrap node). The node-level federation package (zentalk-node/pkg/federation) provides:
- Distributed user directory — user-to-home-server mappings stored encrypted in the DHT. DHT keys are derived with BLAKE2b (one-way), entries are ECDSA-signed (P-256) by the user’s own key — unlike server-to-server federation, which uses Ed25519 server identities — and privacy levels (
PUBLIC,CONTACTS_ONLY,PRIVATE) control discoverability. Entries expire after 7 days. - Anti-enumeration — lookup rate limiting (100 lookups per minute per IP), proof-of-work challenges for bulk lookups, honeypot entries, and automatic blocking of suspicious lookup patterns.
- Federated blocking, rate limiting, and delivery confirmation — cross-server enforcement of user blocks, per-peer quotas, and acknowledgement of relayed messages.
HTTP endpoint reference
Section titled “HTTP endpoint reference”All API-layer federation endpoints live under /api/federation. Endpoints marked Signed require the request-signing headers described below; /health and /status are exempt from authentication.
| Endpoint | Method | Auth | Purpose |
|---|---|---|---|
/api/federation/register |
POST | Registration payload signature | Register a peer server (ID, URL, public key, signed challenge) |
/api/federation/servers |
GET | Signed | List all known federated servers |
/api/federation/servers/{serverID} |
GET | Signed | Get details for one server |
/api/federation/auth/challenge |
POST | Signed | Issue a single-use authentication challenge for a server ID |
/api/federation/auth/verify |
POST | Signed | Verify a signed challenge response |
/api/federation/message |
POST | Signed | Receive a federated message (signature and forwarding chain verified, then queued to the inbox) |
/api/federation/users/lookup |
POST | Signed | Resolve a user address to its home server |
/api/federation/status |
GET | None | Federation status: enabled flag, server ID, known-server count |
/api/federation/health |
GET | None | Health check for peer monitoring |
Request signing
Section titled “Request signing”Every federation request except /register, /health, and /status must carry:
| Header | Content |
|---|---|
X-Server-ID |
The calling server’s ID |
X-Timestamp |
Unix timestamp (seconds); rejected if older than 5 minutes or more than 1 minute in the future |
X-Nonce |
Unique nonce; duplicates within the timestamp window are rejected as replay attacks |
X-Signature |
Base64 Ed25519 signature over timestamp + nonce + body |
The receiving server verifies the signature against the public key it recorded for that server ID at registration time.
Challenge/verify authentication
Section titled “Challenge/verify authentication”Registration and re-authentication use a challenge flow: the peer requests a challenge via /auth/challenge, signs it, and presents the signature to /auth/verify (or in the /register payload). With federation auth v2 enabled (ZENTALK_FEDERATION_AUTH_V2=true), challenges are server-issued, persisted, and consumed single-use — a peer cannot supply its own challenge value. The v2 registration payload additionally binds the server URL and public-key fingerprint into the signed data.
Legacy v1 peers (client-supplied challenge, legacy signature payload) are accepted only while the grace window is open. The grace window closes at the deadline configured by ZENTALK_FEDERATION_V1_DEADLINE (RFC 3339; default 2026-08-01T00:00:00Z), after which v1 authentication is rejected regardless of the v2 flag. V1 acceptances are counted in the zentalk_federation_auth_v1_grace_total metric so operators can monitor remaining v1 usage before cutover.
Trust model
Section titled “Trust model”Federation peers are authenticated at two layers:
- Application layer — per-peer Ed25519 public-key fingerprint pinning via
ZENTALK_FEDERATION_PEERS. Server IDs are derived from public keys, registration signatures prove key ownership, and every subsequent request is signature-verified against the pinned key. - Transport layer — mutual TLS with TLS 1.3 required and hot-reloadable certificates. Plaintext HTTP between federation peers is refused in production (
ZENTALK_REQUIRE_HTTPS=true). Outbound federation connections additionally support per-server certificate pinning (SHA-256 hashes of peer certificates); when unpinned connections are disallowed, connections to servers without pins are rejected.
Operators can also restrict the peer set explicitly with ZENTALK_ALLOWED_SERVER_IDS and ZENTALK_BLOCKED_SERVER_IDS.
Rate limits and bans
Section titled “Rate limits and bans”The federation middleware enforces per-server and per-IP limits. Violations accumulate into temporary bans with exponential backoff.
| Category | Limit | Window |
|---|---|---|
| Registration (per IP) | 5 | 1 hour |
| Message delivery | 50 | 1 minute |
| Server sync | 10 | 1 minute |
| Query/search | 20 | 1 minute |
| Default (other endpoints) | 30 | 1 minute |
| Ban trigger | Duration |
|---|---|
| 3 violations within 5 minutes | 15 minutes |
| 10 violations within 1 hour | 1 hour |
| Repeat offender | Previous duration × 2 per ban, capped at 24 hours |
Next steps
Section titled “Next steps”- Federation setup — generate keys, exchange fingerprints, configure mTLS, and bring up a federated pair.
- Environments and base URLs — where federation endpoints live per environment.
- REST API reference — the full API surface, including federation operations.
- Node binaries and ports — the relay, mesh, and bootstrap processes that carry node-level federation.
