From d6ad4ed128ac9348d4ca4fb4d2cbcc907a936622 Mon Sep 17 00:00:00 2001 From: Jean Chevronnet Date: Tue, 14 Jul 2026 16:14:44 +0000 Subject: [PATCH] Add Architecture page --- Architecture.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 Architecture.md diff --git a/Architecture.md b/Architecture.md new file mode 100644 index 0000000..ee3ab56 --- /dev/null +++ b/Architecture.md @@ -0,0 +1,26 @@ +# Architecture + +Echo is a small core plus a set of module crates. Three layers, each a clean boundary. + +## Protocol + +An ircd link implements the `Protocol` trait. It turns raw server-to-server lines into a normalized `NetEvent` vocabulary the engine understands, and turns the engine's `NetAction`s back into raw lines. The engine never sees a raw protocol line, so supporting another ircd is one new crate. InspIRCd is the first implementation, at `modules/protocol/inspircd`. + +## Engine + +The engine (`src/engine`) holds the live network view and the account and channel store, and routes a message addressed to a service into that service. It owns the parts a module must not touch: the append-only log, the gossip layer, and all credential material. + +A service reaches the engine through exactly two traits: + +- `NetView`, a read-only view of the live network: who is online, their nick and host, channel membership, who holds ops, last-seen times. +- `Store`, the account and channel store. Reads return credential-free views; writes are ordinary methods. A write committed here replicates like any other event, with no replication code in the service. + +## Store + +State is event-sourced. Every change is an `Event` appended to a per-node JSONL log, and the in-memory state is a fold over that log. One fold serves three paths: replay on restart, ingest from a peer, and compaction. Passwords are hashed with argon2id and SASL uses stored SCRAM verifiers, none of which is reachable through the `Store` trait. + +## Modules + +The pluggable parts are separate crates in a Cargo workspace, each depending only on the `echo-api` SDK and nothing else: not the engine, not the storage, not the network code. If a module compiles against `echo-api`, the core can run it. Services live under `modules/`, one crate per service; ircd links live under `modules/protocol/`. + +Each service crate follows one convention: `lib.rs` holds the struct and the command dispatcher, and every command lives in its own file. See [Writing a Module](Writing-a-Module).