Open source / distributed messaging

Shared infrastructure.
Endpoint encryption.

EpochGrid combines NATS messaging infrastructure with MLS end-to-end group encryption. The fabric routes and stores messages. Devices hold the keys and read the content.

Project snapshot / 01
Transport
NATS + JetStream
Encryption
MLS via OpenMLS
Implementation
Rust · CLI + TUI

01 / Purpose

Why EpochGrid?

Separate the messaging fabric from the keys that make a conversation readable.

01

Infrastructure has a defined role

NATS handles routing and persistence. The metadata backend manages public identity and authorization state without decrypting chat. An invited service participant is a separate, readable endpoint.

02

Group state stays at the edge

OpenMLS manages cryptographic membership. Independent device keys and authenticated Welcome messages connect directory identity to the group.

03

Failure is part of the workflow

Durable inboxes, a ciphertext outbox and local transactions support offline catch-up and tested process restart boundaries.

02 / Implementation

A working, deliberately scoped system

Implemented

Identity and discovery

Independent keys, signed registration and enrollment, plus device revocation with broker exclusion and coordinated MLS removal.

Implemented

Encrypted group messages

Authenticated Welcome joining and MLS PrivateMessages, with coordinator-serialized membership changes.

Implemented

Durable delivery and history

JetStream ciphertext, retryable sends, local transcripts and offline catch-up.

Implemented

A persistent terminal client

Channel navigation, message composition, history, unread counts and automatic reconnect.

Implemented

Independent devices

Separate keys and state per device, explicit invitations and ordered membership catch-up.

Implemented

Device verification

Manual fingerprint comparison, persistent key-change warnings and a signed registration log with locally retained checkpoints.

Implemented

Encrypted identity recovery

Client-encrypted control credentials and trust evidence. Resuming messaging requires a fresh device and invitation; old chat keys and history are excluded.

Implemented

Delivery and read receipts

Encrypted device claims distinguish server acceptance, delivery and local presentation. Read is not proof of human attention.

Implemented

Replies, edits and reactions

Stable application IDs and authenticated, append-only relationships. Edits preserve original history.

Implemented

Explicit service participants

An invited MLS endpoint can answer status requests. It reads its joined conversation; the metadata backend does not.

Implemented

Dynamic admission

Canonical user/device enrollment and expiring Auth Callout grants. Full dynamic messaging integration remains in progress.

Implemented

Encrypted attachments

Client-encrypted files in NATS Object Store; metadata and keys inside MLS. Explicit authenticated saves, with size and retention limits.

Implemented describes repository code, not production readiness. The full messaging flow currently runs in the explicit static development fixture. Acceptance evidence (external) · Terminal client (external) · Verification and log limits (external) · Milestone status (external)

03 / Message path

One fabric. Distinct trust boundaries.

Content encryption, broker permissions and local storage provide different protections.

Message content is encrypted at the endpoints. Clients exchange MLS ciphertext through NATS and JetStream. A separate metadata backend manages public identities and authorization without chat keys. An explicitly invited service participant occupies the same plaintext boundary as a client endpoint. Files are encrypted in Object Store; their keys and metadata travel inside MLS. Receipts use a separate encrypted, non-durable Core NATS path. The broker sees routing and traffic metadata. This full message path runs in the static development fixture without TLS; dynamic messaging integration is still in progress.
Inspect the security layers →

04 / Foundations

A small set of substantial building blocks

RustShared core, CLI and service
NATSTransport and durable streams
OpenMLSGroup cryptographic state
SQLiteTransactional device storage
Roles, rationale and tradeoffs →

Build with the project

Start with the code. Help refine the boundaries.

Run the development flow, examine the threat model, or discuss a focused change with the maintainers.