Reorganize protocol and pseudoclients into a modules/ tree

The core stays in src/; protocol and pseudoclients move to modules/,
pulled in with #[path].
This commit is contained in:
Jean Chevronnet 2026-07-12 10:31:09 +00:00
parent dbc45a0b6a
commit 677963924a
No known key found for this signature in database
11 changed files with 43 additions and 17 deletions

View file

@ -7,14 +7,19 @@ derived from any project's source.
## Design
- **`proto/`** the ircd link layer. A `Protocol` trait maps raw server-to-server
lines to and from a normalized `NetEvent`/`NetAction` model, so the engine never
touches a raw line and a new ircd is one new module. InspIRCd is the first.
- **`engine/`** the services engine: live network `state`, the account store, and
the `Service` trait. The store is event-sourced: every change is an `Event`
The core lives in `src/`; the pluggable parts live in `modules/` (see
`modules/README.md`).
- **`src/engine/`** the services engine: live network `state`, the account store,
and the `Service` trait. The store is event-sourced: every change is an `Event`
appended to a per-node log, and state is a fold over that log.
- **`gossip/`** node-to-node replication over the logs.
- **`services/`** the pseudo-clients: NickServ first, then ChanServ / OperServ.
- **`src/gossip.rs`** node-to-node replication over the logs.
- **`modules/protocol/`** the ircd link layer. A `Protocol` trait maps raw
server-to-server lines to and from a normalized `NetEvent`/`NetAction` model, so
the engine never touches a raw line and a new ircd is one new module. InspIRCd is
the first.
- **`modules/nickserv/`, `modules/chanserv/`** the pseudo-clients, one directory
each. OperServ and others follow the same shape.
## Replication

19
modules/README.md Normal file
View file

@ -0,0 +1,19 @@
# modules/
The pluggable parts of fedserv: one directory per protocol and per pseudoclient.
The core (engine, event log, gossip, link loop) stays in `../src/`.
```
modules/
protocol/ ircd link protocols (inspircd.rs)
nickserv/ NickServ pseudoclient
chanserv/ ChanServ pseudoclient
```
`src/main.rs` pulls each in with `#[path = "../modules/..."]`, so crate paths
stay flat (`crate::proto`, `crate::nickserv`, `crate::chanserv`).
## Naming
A service directory holds its pseudoclient file plus, as commands are split out,
one file per command with the service prefix: `ns_register.rs`, `cs_mode.rs`, etc.

View file

@ -542,7 +542,7 @@ impl RegLimiter {
#[cfg(test)]
mod tests {
use super::*;
use crate::services::nickserv::NickServ;
use crate::nickserv::NickServ;
fn plain(authzid: &[u8], authcid: &[u8], passwd: &[u8]) -> String {
let mut payload = Vec::new();
@ -934,7 +934,7 @@ mod tests {
// only the founder can drop.
#[test]
fn chanserv_register_info_drop() {
use crate::services::chanserv::ChanServ;
use crate::chanserv::ChanServ;
let path = std::env::temp_dir().join("fedserv-chanserv.jsonl");
let _ = std::fs::remove_file(&path);
let mut db = Db::open(&path, "42S");

View file

@ -1,6 +1,5 @@
//! SCRAM (RFC 5802 / RFC 7677) server side for SASL SCRAM-SHA-256 and
//! SCRAM-SHA-512. The stored verifier is byte-compatible with the rest of the
//! stack (Anope m_apiauth / Django): `v=1,i=,s=,sk=,sv=` where
//! SCRAM-SHA-512. Stored verifier format `v=1,i=,s=,sk=,sv=` where
//!
//! SaltedPassword = Hi(password, salt, i) (PBKDF2, dklen = hash len)
//! ClientKey = HMAC(SaltedPassword, "Client Key")

View file

@ -263,7 +263,7 @@ async fn send(tx: &mpsc::Sender<String>, msg: &Msg) -> Result<(), ()> {
mod tests {
use super::*;
use crate::engine::db::Db;
use crate::services::nickserv::NickServ;
use crate::nickserv::NickServ;
fn engine(origin: &str, tag: &str) -> (Shared, Outbound) {
let path = std::env::temp_dir().join(format!("fedserv-gossip-{tag}.jsonl"));

View file

@ -1,19 +1,24 @@
// Core lives in src/; pluggable modules live in ../modules/.
mod config;
mod engine;
mod gossip;
mod link;
#[path = "../modules/protocol/mod.rs"]
mod proto;
mod services;
#[path = "../modules/nickserv/nickserv.rs"]
mod nickserv;
#[path = "../modules/chanserv/chanserv.rs"]
mod chanserv;
use anyhow::Result;
use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH};
use tokio::sync::Mutex;
use chanserv::ChanServ;
use engine::Engine;
use nickserv::NickServ;
use proto::inspircd::InspIrcd;
use services::chanserv::ChanServ;
use services::nickserv::NickServ;
#[tokio::main]
async fn main() -> Result<()> {

View file

@ -1,2 +0,0 @@
pub mod chanserv;
pub mod nickserv;