This repository contains the code for a Rust implementation of the Phoenix Protocol, an infrastructure protocol built around the Messaging Layer Security (MLS) group messaging protocol.
The Phoenix Protocol aims to enable functionality commonly required by messaging applications while providing strong security and privacy guarantees. It allows federation between different servers and their connected clients.
For security, the protocol relies mainly on the strong security guarantees provided by the underlying MLS protocol. The authentication service required by the MLS protocol is a simple signature-based PKI.
The documentation including the full specification for the Phoenix Protocol can be found here.
The implementation spans client, server and test-specific components. It is split across multiple crates:
types
: Structs, Enums and utilities used by multiple other crates in this repository. This crate allows us to compile client and server components separately.backend
: Implements both the local and the federation part of the protocol logic on the server side. Inspired by the type-based verification design of the OpenMLS crate (on which bothcoreclient
andbackend
are built), verification of incoming messages is enforced using Rust's type system. Thebackend
is written to work with arbitrary storage providers. The crate itself provides an in-memory and a Postgres-based storage provider.server
: The server component that makes the logic implemented in thebackend
available to clients via a REST API. Beside the REST API, theserver
also supports web-sockets, which the backend can use to notify clients of new messages. Theserver
crate can be compiled into a binary that can be run to expose the HTTP endpoints. ADockerfile
is available to build a Docker image that contains the server binary.coreclient
: Implements the protocol logic of the client component. Thecoreclient
stores and manages a user's contacts, conversations, as well as the underlying MLS groups. It provides a high-level API to make use of the protocol in the context of a messaging application. Just like thebackend
, thecoreclient
uses a type-based message verification approach. The crate can be used to instantiate and persist (via Sqlite) multiple clients parallely.apiclient
: A shallow layer that thecoreclient
calls to interact with thebackend
via theserver
using HTTP(s).applogic
: A layer using cubits to expose the functionality of thecoreclient
to a UI client.app
: A UI client that usesapplogic
to provide a simple messaging application. The GUI is built using Flutter.test_harness
: Exclusively used for testing. Thetest_harness
contains a test framework to conduct integration tests and can be compiled into a binary for docker-based testing of the protocol's federation capabilities.
Setup Instructions (macOS)
Before starting, ensure you have the following tools installed:
- Clone the repository:
git clone https://github.com/phnx-im/infra
-
Install Rust
-
Install Flutter SDK
Verify your installation with:
flutter --version
Note: installing Flutter through VS Code may run into problems when using the
just
setup scripts later. You may need to separately install Flutter outside of VS Code in order to follow the rest of these instructions.
- Install required tools:
cargo install just flutter_rust_bridge_codegen sqlx-cli
just
: "is a handy way to save and run project-specific commands."flutter_rust_bridge_codegen
: "Flutter/Dart <-> Rust binding generator"sqlx-cli
: "SQLx's associated command-line utility for managing databases, migrations, and enabling "offline" mode withsqlx::query!()
and friends."
- Install Docker Desktop on Mac
- Generate Rust bridge code:
just frb-integrate
- Ensure that Docker is running. You can check your system tray or verify this on the CLI with:
docker info
If you see something like
ERROR: Cannot connect to the Docker daemon at unix:///Users/[YOUR_USERNAME]/.docker/run/docker.sock. Is the docker daemon running?
then Docker is not running.
- Initialize the database:
just init-db
If you see the error
error getting credentials - err: exec: "docker-credential-desktop": executable file not found in $PATH
, then you should verify if you are runningdocker-credential-osxkeychain
with the commanddocker-credential-osxkeychain version
.If that works, then you will need to edit your
~/.docker/config.json
. Replace the value of"credsStore"
with"osxkeychain"
, then re-runjust init-db
.If you see the error
Error response from daemon: Ports are not available: exposing port TCP 127.0.0.1:5432 -> 0.0.0.0:0: listen tcp 127.0.0.1:5432: bind: address already in use
, verify that you are not already running Postgres on port 5432. Some users may be using popular apps like Postgres.app which runs on this port by default. Simply stop your server and try again.
- Set up macOS requirements:
Install Xcode and accept the license
sudo xcodebuild -license
Install CocoaPods (requires recent Ruby version)
gem install cocoapods
Quick start:
cd app
flutter run -d macos
When prompted, use the domain name localhost
.
The Phoenix Protocol allows for communication between users across different
servers. To properly test federation-related functionalities, the test_harness
provides utilities to spin up multiple servers using Docker. Docker allows us to
approximate a real-world networking environments, where servers can discover
one-another using DNS and facilitate communication between their respective
clients across a network. The server
crate contains several federated test
scenarios that are run in this way.
Since the tests build fresh Docker images from the code and spin up multiple
containers, running them is somewhat slow. To make regular testing more
ergonomic, the --include-ignored
flag has to be used when running cargo test
on the server
crate. Note that Docker-based tests are run as part of the CI
whenever a pull request is made.
All crates in this repository are licensed under the AGPL 3.0. This README file is licensed under CC-BY 4.0.