Skip to content
Pug Network Docs Open the app

Architecture

Architecture

Pug Network is three cooperating layers. Each has a single responsibility, each can be reasoned about in isolation, and the encryption boundary lives above all three of them — nothing the server runs ever holds plaintext.

The three layers

          Browser A                          Browser B
          ┌──────────┐                       ┌──────────┐
          │ AES-GCM  │  encrypt              │ AES-GCM  │
          │ encrypt  │                       │ decrypt  │
          └────┬─────┘                       └────▲─────┘
               │                                   │
─── encryption boundary ─────────────────────── encryption boundary ───
               │  ciphertext                       │
               v                                   │
          ┌──────────────────────────────────────────────┐
          │   Realtime Gateway  (WebSocket relay only)    │
          └────────────────────┬─────────────────────────┘
                               │
                               v
          ┌──────────────────────────────────────────────┐
          │   Room Registry  (in-memory, TTL'd)           │
          └────────────────────▲─────────────────────────┘
                               │
                               │
          ┌──────────────────────────────────────────────┐
          │   HTTP / API  (serve client, create rooms)    │
          └──────────────────────────────────────────────┘

Per-layer responsibilities

Layer Responsibility JS implementation Go implementation
HTTP / API Serve client assets, issue PoW challenges, create rooms Express net/http + embed
Realtime gateway Bidirectional ciphertext relay between members Socket.IO Hand-rolled RFC 6455 subset
Room registry Membership, capacity, TTL, purge In-memory Map In-memory map + sync.Mutex

Domain model

Room

Member (connection)

Message event

Why this shape

The split is deliberate. Each layer holds the smallest amount of state it can possibly hold to do its job:

This is what allows the trust model to make absolute claims. There is no layer that could persist plaintext if it tried — none of them ever see plaintext, and none of them have a disk-backed store to write to. See Trust model for the consequences.