Add Architecture page

Jean Chevronnet 2026-07-14 16:14:44 +00:00
parent bd4932ac64
commit d6ad4ed128

26
Architecture.md Normal file

@ -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).