Files
featherChat/warzone/docs/SERVER.md
Siavash Sameni 7b72f7cba5 feat: friend list, bot API, ETH addressing, deep links, docs overhaul
Tier 1 — New features:
- E2E encrypted friend list: server stores opaque blob (POST/GET /v1/friends),
  protocol-level encrypt/decrypt with HKDF-derived key, 4 tests
- Telegram Bot API compatibility: /bot/register, /bot/:token/getUpdates,
  sendMessage, getMe — TG-style Update objects with proper message mapping
- ETH address resolution: GET /v1/resolve/:address (0x.../alias/@.../fp),
  bidirectional ETH↔fp mapping stored on key registration
- Seed recovery: /seed command in TUI + web client
- URL deep links: /message/@alias, /message/0xABC, /group/#ops
- Group members with online status in GET /groups/:name/members

Tier 2 — UX polish:
- TUI: /friend, /friend <addr>, /unfriend <addr> with presence checking
- Web: friend commands, showGroupMembers() on group join
- Web: ETH address in header, clickable addresses (click→peer or copy)
- Bot: full WireMessage→TG Update mapping (encrypted base64, CallSignal,
  FileHeader, bot_message JSON)

Documentation:
- USAGE.md rewritten: complete user guide with all commands
- SERVER.md rewritten: full admin guide with all 50+ endpoints
- CLIENT.md rewritten: architecture, commands, keyboard, storage
- LLM_HELP.md created: 1083-word token-optimized reference for helper LLM

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 07:31:54 +04:00

15 KiB

Warzone Server -- Administration Guide

Version 0.0.21


1. Building

Local Build

From the workspace root:

# Debug
cargo build -p warzone-server

# Release (recommended for deployment)
cargo build -p warzone-server --release

Binary output: target/release/warzone-server.

Cross-Compile for Linux (x86_64)

The scripts/build-linux.sh script spins up a Hetzner Cloud VPS, builds Linux release binaries, and pulls them back to target/linux-x86_64/.

# Full pipeline: build + deploy to all production servers + destroy VM
./scripts/build-linux.sh --ship

# Step-by-step:
./scripts/build-linux.sh --prepare     # create VM, install deps, upload source
./scripts/build-linux.sh --build       # compile release binaries on the VM
./scripts/build-linux.sh --transfer    # download binaries to target/linux-x86_64/
./scripts/build-linux.sh --destroy     # delete the VM

# Or all three build steps at once (VM persists):
./scripts/build-linux.sh --all

Minimum Rust Version

Rust 1.75 or later (rust-version = "1.75" in Cargo.toml).


2. Running

Basic

# Defaults: bind 0.0.0.0:7700, data in ./warzone-data
./warzone-server

# Custom bind address and data directory
./warzone-server --bind 0.0.0.0:7700 --data-dir ./data

# With federation enabled
./warzone-server --federation federation.json

CLI Flags

Flag Short Default Description
--bind -b 0.0.0.0:7700 Address and port to listen on
--data-dir -d ./warzone-data Directory for the sled database
--federation -f (none) Path to federation JSON config file

Environment Variables

Variable Default Description
RUST_LOG warn (production) Log filter. Examples: info, warzone_server=debug, trace
WZP_RELAY_ADDR (none) WZP voice relay address advertised to clients

systemd Service

A production-ready unit file is provided at deploy/warzone-server.service:

[Unit]
Description=Warzone Messenger Server (featherChat)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=warzone
Group=warzone
WorkingDirectory=/home/warzone
ExecStart=/home/warzone/warzone-server --bind 0.0.0.0:7700 --data-dir /home/warzone/data --federation /home/warzone/federation.json
Restart=always
RestartSec=3
LimitNOFILE=65536

# Security hardening
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/home/warzone/data
PrivateTmp=yes

Environment=RUST_LOG=warn,warzone_server::federation=info

[Install]
WantedBy=multi-user.target

Install and enable:

sudo cp deploy/warzone-server.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now warzone-server

3. Configuration

Federation JSON

Enable federation by passing --federation <path> on startup. The config file specifies the local server identity, peer connection details, and a shared secret for authentication.

Format (see federation.example.json):

{
  "server_id": "alpha",
  "shared_secret": "change-me-to-a-long-random-string-shared-between-both-servers",
  "peer": {
    "id": "bravo",
    "url": "http://10.0.0.2:7700"
  },
  "presence_interval_secs": 5
}
Field Description
server_id Unique name for this server (e.g. "alpha")
shared_secret Pre-shared secret; must match on both sides
peer.id The remote server's server_id
peer.url HTTP base URL of the remote server
presence_interval_secs How often to broadcast online-user lists (default 5)

4. Federation

Federation connects two Warzone servers over a persistent WebSocket so their users can communicate transparently.

How It Works

  • On startup, each server opens an outgoing WebSocket to its peer at /v1/federation/ws and authenticates with the shared secret.
  • The connection auto-reconnects on failure.
  • Presence (online fingerprints) is synced on the configured interval.
  • Messages to users on the remote server are forwarded automatically.

Federated Features

Feature Behavior
Key lookup proxy If a key bundle is not found locally, the server queries the peer
Message forwarding Messages addressed to a remote fingerprint are relayed over the WS
Alias resolution /v1/resolve/:address checks the peer if the alias is not local
Presence sync Each server broadcasts its online fingerprints to the peer

Two-Server Setup

Server A (alpha, e.g. mequ):

{
  "server_id": "alpha",
  "shared_secret": "s3cret-shared-between-both",
  "peer": { "id": "bravo", "url": "http://bravo-host:7700" },
  "presence_interval_secs": 5
}

Server B (bravo, e.g. kh3rad3ree):

{
  "server_id": "bravo",
  "shared_secret": "s3cret-shared-between-both",
  "peer": { "id": "alpha", "url": "http://alpha-host:7700" },
  "presence_interval_secs": 5
}

Both files use the same shared_secret. Each server's peer.id matches the other server's server_id.

Federation Status Endpoint

curl http://localhost:7700/v1/federation/status

Returns JSON with connection state, peer info, and presence data.


5. API Reference

All endpoints are prefixed with /v1. The web UI is served at /.

Notation

  • Auth = requires Authorization: Bearer <token> header (write routes).
  • Public = no authentication needed (read routes).

Health

Method Path Auth Description
GET /v1/health Public Health check; returns {"status":"ok"}

Keys

Method Path Auth Description
POST /v1/keys/register Public Register a pre-key bundle
POST /v1/keys/replenish Public Upload additional one-time pre-keys
GET /v1/keys/:fingerprint Public Fetch a key bundle (falls back to federation peer)
GET /v1/keys/list Public List all registered fingerprints
GET /v1/keys/:fingerprint/otpk-count Public Remaining one-time pre-key count
GET /v1/keys/:fingerprint/devices Public List devices for a fingerprint

Messages

Method Path Auth Description
POST /v1/messages/send Auth Send an encrypted message blob
GET /v1/messages/poll/:fingerprint Public Poll queued messages
DELETE /v1/messages/:id/ack Public Acknowledge (delete) a message

Groups

Method Path Auth Description
POST /v1/groups/create Auth Create a group
POST /v1/groups/:name/join Auth Join a group
POST /v1/groups/:name/send Auth Send a message to a group
POST /v1/groups/:name/leave Auth Leave a group
POST /v1/groups/:name/kick Auth Kick a member from a group
GET /v1/groups Public List all groups
GET /v1/groups/:name Public Get group details
GET /v1/groups/:name/members Public List members (includes online status)

Aliases

Method Path Auth Description
POST /v1/alias/register Auth Register a human-readable alias
POST /v1/alias/unregister Auth Remove your alias
POST /v1/alias/recover Auth Transfer alias to a new fingerprint
POST /v1/alias/renew Auth Renew alias expiry
POST /v1/alias/admin-remove Auth Admin-remove an alias
GET /v1/alias/resolve/:name Public Resolve alias to fingerprint
GET /v1/alias/list Public List all registered aliases
GET /v1/alias/whois/:fingerprint Public Reverse-lookup: fingerprint to alias

Calls (WZP)

Method Path Auth Description
POST /v1/calls/initiate Auth Start a 1:1 call
POST /v1/calls/:id/end Auth End an active call
POST /v1/calls/missed Auth Get missed calls for a fingerprint
POST /v1/groups/:name/call Auth Initiate a group call
GET /v1/calls/:id Public Get call details
GET /v1/calls/active Public List active calls

Devices

Method Path Auth Description
POST /v1/devices/:id/kick Auth Disconnect a specific device
POST /v1/devices/revoke-all Auth Disconnect all devices (optional keep one)
GET /v1/devices Auth List your connected devices

Presence

Method Path Auth Description
POST /v1/presence/batch Auth Batch-query presence for multiple fingerprints
GET /v1/presence/:fingerprint Public Check if a fingerprint is online

Friends

Method Path Auth Description
POST /v1/friends Auth Save friend list (encrypted blob)
GET /v1/friends Auth Retrieve saved friend list

Resolve

Method Path Auth Description
GET /v1/resolve/:address Public Universal resolve: ETH address, alias, or fingerprint. Checks federation peer if not found locally.

WZP Voice Relay

Method Path Auth Description
GET /v1/wzp/relay-config Public Get the WZP relay address for voice calls

Federation

Method Path Auth Description
GET /v1/federation/status Public Federation connection status and peer info
GET /v1/federation/ws Internal WebSocket endpoint for server-to-server communication

Bot API

Method Path Auth Description
POST /v1/bot/register Auth Register a bot; returns an API token
GET /v1/bot/:token/getMe Token Bot identity info
POST /v1/bot/:token/getUpdates Token Long-poll for new messages (Telegram-compatible)
POST /v1/bot/:token/sendMessage Token Send a message as the bot (Telegram-compatible)

Bot tokens are scoped to the bot's fingerprint. The getUpdates and sendMessage endpoints follow the Telegram Bot API conventions so existing Telegram bot libraries can be adapted with minimal changes.


WebSocket

Path Description
/v1/ws/:fingerprint Real-time message delivery. Clients receive instant push of new messages.

Web UI

Path Description
/ Single-page WASM web client
/wasm/warzone_wasm.js WASM JavaScript bindings
/wasm/warzone_wasm_bg.wasm WASM binary

6. Database

The server uses sled (embedded key-value store). All data lives under the --data-dir directory.

Trees

Tree Purpose
keys Pre-key bundles (public keys only)
messages Queued encrypted message blobs
groups Group metadata and membership
aliases Human-readable alias mappings
tokens Authentication tokens (device sessions)
calls Call records (1:1 and group)
missed_calls Missed call notifications
friends Encrypted friend lists
eth_addresses Ethereum address to fingerprint mappings

Data Directory Structure

warzone-data/
  db                    # sled database file
  conf                  # sled config
  blobs/                # sled blob storage
  snap.*/               # sled snapshots

The entire directory should be treated as a unit for backup. Stop the server before copying, or use filesystem-level snapshots (LVM, ZFS, btrfs).


7. Security

Auth Middleware

All write (POST) endpoints require a bearer token in the Authorization header. Tokens are issued during key registration and tied to a fingerprint. Read (GET) endpoints are public.

Rate Limiting

  • 200 concurrent requests (tower ConcurrencyLimitLayer)
  • 5 WebSocket connections per fingerprint (multi-device cap)

Device Management

Users can list connected devices, kick individual devices, or revoke all sessions via the /v1/devices endpoints. The revoke-all endpoint accepts an optional keep_device_id to keep the current device active.

What the Server Can See

Data Visible
Message plaintext No (E2E encrypted blobs)
Sender/recipient fingerprints Yes
Message size and timing Yes
Public pre-key bundles Yes (public by design)
IP addresses Yes (from HTTP)

8. Monitoring

Logging

Control verbosity with RUST_LOG:

RUST_LOG=warn ./warzone-server              # production default
RUST_LOG=info ./warzone-server              # request-level logging
RUST_LOG=warzone_server=debug ./warzone-server  # server internals
RUST_LOG=trace ./warzone-server             # everything

With systemd:

journalctl -u warzone-server -f

Health Check

curl http://localhost:7700/v1/health

Federation Status

curl http://localhost:7700/v1/federation/status

Returns connection state, peer identity, and synced presence data.


9. Deploy Scripts

The scripts/build-linux.sh script handles the full build and deploy lifecycle via Hetzner Cloud VMs.

Key Commands

Command Description
--ship Full pipeline: build on VM, deploy to all production servers, destroy VM
--update-all Upload pre-built binaries to all production servers and restart
--update <user@host> Update a single production server
--status Check service status and federation on all production servers
--logs [user@host] Tail journalctl logs (defaults to first production server)

Typical Deploy Workflow

# One command: build, deploy everywhere, clean up
./scripts/build-linux.sh --ship

# Or step by step:
./scripts/build-linux.sh --all          # build (VM persists)
./scripts/build-linux.sh --update-all   # deploy binaries
./scripts/build-linux.sh --destroy      # clean up VM
./scripts/build-linux.sh --status       # verify

10. Backup and Recovery

Backup

systemctl stop warzone-server
cp -r /home/warzone/data /backup/warzone-$(date +%Y%m%d)
systemctl start warzone-server

Do not copy the sled directory while the server is running without filesystem-level snapshots.

Recovery

  1. Stop the server.
  2. Replace the data directory with the backup.
  3. Start the server.

Messages queued after the backup was taken are permanently lost. All messages are E2E encrypted and cannot be recovered from any other source.