rolla-node is a Rust implementation of a small, security-oriented, two-party ephemeral P2P messenger.
The project is designed around private direct communication, short-lived chat identities, minimal data retention, bounded protocol parsing, explicit state, and clear security boundaries.
rolla-nodeis under active development, has not been independently audited, and does not currently provide network anonymity or traffic-analysis resistance.
rolla-node is in early implementation.
Current implementation work is focused on Phase 1: Transport Abstraction and Two Local Nodes. The repository currently contains:
- a Cargo workspace;
- a
rolla-protocolcrate with protocol versioning and bounded frame encoding/decoding; - a
rolla-nodebinary crate with CLI commands for help, version, local TCP listen, and local TCP dial; - a minimal TCP path that sends one bounded test frame from
dialtolisten; - architecture, roadmap, threat-model, and deferred-scope documentation.
The current binary is not yet a usable messenger. Most security-sensitive capabilities described below are planned milestones, not completed features.
The long-term goal is a terminal-first v0.1.0 capable of private two-party communication with:
- one active chat per node process;
- per-chat cryptographic identities;
- signed limited-lifetime invitations;
- manual peer fingerprint verification;
- authenticated peer transport behind a transport abstraction;
- encrypted and signed message records;
- a Braided Message Log for verifiable message history;
- offline local writing and reconnect synchronization;
- encrypted local persistence;
- passphrase-protected key storage;
- fixed chat expiration and local cryptographic deletion;
- bounded parsing and validation of untrusted input.
The project deliberately starts with a narrow protocol instead of a general-purpose messaging platform.
The initial protocol is designed for exactly two participants:
Alice rolla-node <-> Bob rolla-node
The initial implementation is terminal-first and manages one active chat per process. Browser UI, multi-chat support, group chats, attachments, relays, Tor, universal NAT traversal, key ratcheting, and OS keychain integration are intentionally deferred.
The project aims to provide:
- message-content confidentiality through application-layer encryption;
- peer authentication through per-chat identities and fingerprint verification;
- tamper detection for accepted message records;
- rollback and equivocation detection relative to accepted checkpoints;
- no intentional plaintext message persistence;
- bounded handling of network-controlled input;
- explicit typed failures instead of silent repair.
These are design goals until implemented and tested in the relevant milestones.
rolla-node does not currently claim to protect against:
- a compromised endpoint;
- malware, screenshots, photographs, or manual copying;
- malicious peers retaining displayed plaintext;
- IP-address disclosure between direct peers;
- traffic timing or volume analysis;
- global passive adversaries;
- complete denial-of-service resistance;
- post-compromise security;
- Signal Double Ratchet guarantees;
- absolute anonymity.
The full threat model is documented in THREAT_MODEL.md.
The application protocol is not tied directly to one concrete transport. Bounded application frames are carried through a transport abstraction.
Phase 1 uses a simple direct TCP transport for local and LAN development. TCP is chosen first to establish the transport boundary and bounded frame handling before stronger transports are added. It does not provide confidentiality or protocol-fingerprint resistance by itself.
A later milestone may add a TLS/WebSocket-based transport to reduce reliance on a stable custom protocol fingerprint. This is separate from anonymity: direct peer connections still expose metadata such as IP addresses, ports, timing, packet sizes, and traffic volume.
Each chat is intended to use a fresh cryptographic identity. This avoids a permanent global username and reduces straightforward linkage between unrelated conversations.
Aliases are UI hints only. Peer authentication depends on full cryptographic identity material and manual fingerprint verification when identity authenticity matters.
The central protocol idea is the Braided Message Log.
Each participant owns and stores their own author log. Each message links to:
- the previous message by the same author;
- the latest accepted peer message observed by the author.
This creates two independently owned chains that can be reconstructed into one deterministic conversation view while preserving causal links, sequence validation, duplicate handling, rollback checks, and same-author conflict detection.
Detailed semantics are documented in BRAIDED_LOG.md.
The intended storage model keeps local plaintext off disk. A participant permanently stores only the data required for the declared behavior, including their own encrypted records, local state, encrypted keys, expiration state, and the latest accepted remote checkpoint.
The complete conversation is reconstructed from two independently owned logs while both peers can provide the required records.
The active milestone is defined in ROADMAP.md.
Current focus:
Phase 1 - Transport Abstraction and Two Local Nodes
Near-term work:
- keep protocol frame handling independent from concrete transport code;
- harden the direct TCP local/LAN transport;
- turn one-frame exchange into a bounded transport session;
- reject malformed, oversized, unsupported, and unexpected protocol input without panics.
Future milestones add invitations, per-chat identities, encrypted signed messages, the Braided Message Log, offline writing, storage, restart synchronization, expiration, and terminal usability.
Install a recent stable Rust toolchain with Rust 2024 edition support.
Run the required checks from the repository root:
cargo fmt --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspaceRun the current CLI:
cargo run -p rolla-node -- --help
cargo run -p rolla-node -- --version
cargo run -p rolla-node -- listen
cargo run -p rolla-node -- dial 127.0.0.1:9000 "hello"The listen command binds to 127.0.0.1 on an operating-system-assigned port, accepts one connection, reads one bounded frame, prints the payload when it is valid UTF-8, and exits.
The dial command connects to a known address, sends one bounded test frame containing the provided message, and exits.
crates/
├── rolla-protocol/
│ └── src/
│ ├── errors.rs
│ ├── frame.rs
│ ├── lib.rs
│ └── version.rs
└── rolla-node/
└── src/
├── cli.rs
├── main.rs
└── tcp.rs
rolla-protocol contains protocol-facing types such as versioning, frame kinds, bounded frame encoding, decoding, and typed protocol errors.
rolla-node contains the executable node, CLI, and transport/runtime work.
The detailed project documents are:
ARCHITECTURE.md- system boundaries, components, state ownership, key hierarchy, lifecycle, and decision register;BRAIDED_LOG.md- message-log model, causal links, validation rules, synchronization, and invariants;THREAT_MODEL.md- assets, adversaries, trust boundaries, assumptions, mitigations, and residual risks;ROADMAP.md- implementation phases, acceptance criteria, milestone scope, and deferred features.
rolla-node is developed around a few constraints:
- keep milestones small and testable;
- prefer explicit Rust types over loosely related primitives;
- validate cheap structural properties before expensive operations;
- keep externally influenced queues, frames, and allocations bounded;
- avoid custom cryptographic primitives;
- document security assumptions and non-goals honestly;
- connect protocol invariants to negative tests.
The project license has not yet been selected.