System Overview
High-level components, state management structure, and end-to-end data flow in Wiltkey.
Overview
Wiltkey is a decentralized, ephemeral messaging app designed to minimize metadata and completely avoid long-term account state. The system consists of a Flutter Client (which stores key bytes and encrypted chat histories locally at rest) and a Go Blind Relay Server (which coordinates connections and queues, storing pending messages in Redis, Postgres, or Object Storage depending on payload size and system memory pressure, with zero long-term message retention).
Authentication is tied entirely to local cryptographic identity keypairs (Ed25519) swapped in person over BLE. The server acts as a blind mailbox. Messages are padded, encrypted using a local One-Time Pad, and routed either directly (if the recipient is online) or enqueued temporarily (up to 24 hours) in a Redis mailbox on the relay.
End-to-End Data Flow
Core Components
1. Client State Model (AppState)
The client uses a unified AppState singleton that implements ChangeNotifier. The class is split across multiple `part of 'state.dart'` extension files to prevent monolithic file growth. AppState handles WebSocket reconnection, local UI coordination, and lazy message pagination.
2. Database Layer (WiltkeyDatabase)
A unified SQLite database (wiltkey.db) managed by WiltkeyDatabase. It caches contacts and persists received messages. Plaintext message bodies are never written directly; they are either kept encrypted in transit (OTP ciphertext) or re-encrypted using the user's master key at rest.
3. Blind Relay Server
The Go relay server coordinates blind message forwarding. Clients authenticate their WebSocket sessions by solving an Ed25519 signature challenge. Under normal operations, offline messages (< 500 KB) are temporarily enqueued in a Redis mailbox. Large messages (≥ 500 KB) are offloaded to S3-compatible Object Storage with metadata tracked in Postgres. If the relay undergoes high memory pressure, it routes all offline queues to Postgres to protect server RAM. Large files are delivered reliably using client WebSocket acknowledgments before deletion.
Key Files & Symbols
| File Path | Symbol Name | Description |
|---|---|---|
wiltkey_client/lib/main.dart |
main() |
Initializes application binding, loads locale and themes, and starts the lock screen. |
wiltkey_client/lib/core/state.dart |
AppState |
Main singleton class coordinating connection, contact, and message state. |
wiltkey_server/main.go |
main() |
Starts the blind Go HTTP/WebSocket server and connects to the Redis backend. |
Gotchas & Edge Cases
If the client's configured relay (including optional local dev relays) is unreachable, the WebSocket client falls back to peer-advertised relays, and finally to the hardcoded default `https://api.wiltkey.org`. This creates a gap where a user's connection destination changes automatically without manual input.