···9090| **P8 — Delete the C + retire the oracle harness ✅ DONE** (per-sub-phase: [`PLAN-P8-progress.md`](PLAN-P8-progress.md) + [`docs/progress-log/p8.md`](docs/progress-log/p8.md)) | remaining C (the ~25 variadic sender trampolines + residual data globals) + `ircd-sys` C build + `ircd-golden` (L2) + `ircd-testkit`/`cref_*` archives (L1) + the frozen reference‑C tree | With all C _logic_ already Rust (P7 exit), delete the last C: replace the variadic sender trampolines with a non‑variadic Rust sender API at every call site (faithful `wire!`/`reply_one!`/`format!` first; leveva typed messages adopted alongside the IRC senders), drop the residual data globals via the data‑symbol seam (bindgen `extern` decls resolve to `#[no_mangle]` Rust defs at link), then drop **all** C compilation from `ircd-sys` (no more `cc::Build`), retire the differential harness (`cref_*`/L1 `ircd-testkit`/`ircd-golden` L2 can no longer be built once the oracle is gone), and **migrate the load‑bearing tests into `ircd-common`** as self‑contained Rust tests (own fixtures, no `cref_` oracle). **Progress (P8a–P8r — full entries in the progress logs):** **every variadic sender trampoline is now Rust** (P8a–P8m, incl. the keystones `sendto_one`/`sendto_flag`/`esendto_*`), and the five data‑global `.o`s are dropped outright (`s_auth.o` iauth globals P8n, `send.o` P8o, `s_bsd.o` `local[]`/`highest_fd`/… P8p, `ircd.o` `me`/`client`/timers/… P8q). **P8r dropped the last C‑logic TU `support.o`** — `dgets`/`make_isupport` ported to Rust + the `ipv6string`/`minus_one` data globals defined as `#[no_mangle]` statics (`snprintf_append` is dead in Rust — WHOX is field‑by‑field — so it died with the `.o`; `irc_sprintf` is deleted not ported, in P11). **Every ircd C TU is now Rust:** the link set holds only the generated `version.o` + the L1 harness's `ctruth.o`. **P8s migrated all 115 L1 `cref_` differentials into self‑contained `ircd-common` `insta` snapshot tests** (drive only the Rust port via `link_anchor()`, no oracle; soundness via the capture chain) — the suite is green + 0 warnings. **P8t ported the last *generated* C TU `version.c` to Rust** (`ircd-common/src/version.rs`): the data globals `generation`/`creation`/`pass_version`/`infotext`/`isupport` are now `#[no_mangle]` statics via the data‑symbol seam — `generation`/`creation` sourced from crate metadata at build time (`CARGO_PKG_VERSION` + an `ircd-common/build.rs` UTC build stamp), `pass_version`/`infotext` copied verbatim. `version.c.SH` generation + the `version.o` compile/archive are gone from `ircd-sys/build.rs`; `libircd_c.a` now holds **only** the L1 harness `ctruth.o`. (`creation` is now genuinely build‑time volatile, so the golden canonicalizer masks RPL_CREATED 003, matching the existing 371 Birth‑Date rule.) **P8u (FINAL) retired the oracle.** Ran the differential suite a last time green — L1 `ircd-testkit` all pass; L2 `ircd-golden` 86 pass + only the documented reference‑C‑garbage `s_serv_stats` flake (where Rust is the *correct* side) — then **dropped all C compilation** from `ircd-sys/build.rs`: the `make` object build, the `cref_*`/`ctruth.o`/`res.o` recompiles, the `libircd_c.a` archive, and the whole‑archive link + `-lz`/`-lm`/`-lcrypt` (none needed by Rust — `pow` resolves from glibc 2.29+). `build.rs` now only runs `configure` + bindgen over the C *headers* (the struct view `ircd-common` still uses until P9–P12) and expands the install‑path Makefile vars. `ircd-testkit` (L1) + `ircd-golden` (L2) are `exclude`d from the workspace (mothballed, git‑recoverable); the `ctruth.c`/`layout.rs` drift‑net is deleted. **The workspace is now 100% Rust — zero C TUs compiled.** **P8v (literal end of C) deleted the C *source tree* itself + retired `ircd-sys`:** froze the generated `bindings.rs` into a committed `ircd-common/src/bindings.rs` (a self‑alias `extern crate self as ircd_sys;` keeps every `ircd_sys::bindings::*` path resolving, zero src churn) + the install‑path consts as literals, then deleted `ircd-sys`, the mothballed `ircd-testkit`/`ircd-golden` oracle crates, the `iauth-rs` C‑iauth differential, and **all** C source (`common/ ircd/ iauth/ support/ contrib/ cbuild/ configure .clang-format* clangformat.yml`). `ircd-rs` calls `ircd_common::ircd::c_ircd_main` directly. **Not one line of C remains in the repo.** | **MET. Final differential run green; oracle mothballed; `cargo build --workspace` 0 warnings links pure Rust; `cargo test --workspace` 695 pass / 0 fail (P8v; was 698 before deleting the C‑oracle tests); the `ircd-common` snapshot tests carry the reference‑C correctness forward. C source tree deleted — repo is 100% Rust at the file level.** |
9191| **P9 — std‑library cleanup ❌ RETIRED (2026‑06‑08)** | — (was: whole Rust tree) | **Skipped by decision — superseded by the `leveva` greenfield.** P9 assumed an *in‑place* idiomatic transformation of the mechanical port (`MyMalloc`/`MyFree`→`Box`/`Vec`, `dbuf` freelist→owned, raw `libc`→`std`/`nix`, `[c_char;N]`→`[u8;N]`). Because the idiomatic end‑state is now a separate greenfield crate (`leveva`), `ircd-common` is throwaway code (the oracle, deleted at parity), so polishing it earns nothing. Nothing was implemented; the row is kept for provenance. | n/a — retired. |
9292| **P10 — `leveva` greenfield foundations 🔶 IN PROGRESS** ([`docs/progress-log/p10.md`](docs/progress-log/p10.md)) | new `leveva` crate (lib) + `leveva-integration` differential tests | The idiomatic‑Rust product, built from scratch (not transformed from the port). **Done so far:** RFC 1459 case‑folding (`casemap`); typed identifier strings (`IrcStr`/`IrcString` + `Nick`/`ChanName`/`Uid`/`Sid`/`Cid`/`ServerName`/`UserName`/`HostName` validating newtypes via `ident_newtype!`); `Message`/`MessageBuilder`; the full `Numeric` reply/error enum (184 codes, discriminant = wire code); a generic safe `patricia` trie; glob `matching`; `mode`; KDL `config` (model/parse/password/privilege); `rustls`/`tokio` `tls` endpoint with hot reload; `ident`. The async boot path (`main.rs`) binds listeners + watches certs but currently drops accepted connections — no protocol layer yet. Idiomatic Rust allowed everywhere; pulls real crates (tokio/rustls/kdl/nom/clap). | `cargo test -p leveva` green + clippy clean per module; `leveva-integration` pins each greenfield reimplementation against `ircd-common` (the oracle) within their shared domain (documented divergences asserted explicitly). |
9393-| **P11 — `leveva` protocol layer → feature parity 🔶 IN PROGRESS** ([`docs/progress-log/p11.md`](docs/progress-log/p11.md)) | `leveva` (client/server state machine + handlers) | The bulk of the remaining work: the connection + registration state machine (`NICK`/`USER` → `001`–`004`/`375`–`376` welcome burst), command handlers (JOIN/PRIVMSG/MODE/KICK/TOPIC/WHO/WHOIS/…), channels, the S2S link/burst protocol (UID‑based: UNICK/NJOIN/SAVE/EOB), and spawning `iauth-rs` over a socketpair. Each slice is built idiomatically (owned per‑connection state, typed identifiers end‑to‑end, `Result`/`thiserror`, `format!`/typed builders — **no** `sprintf`/global `buf`), tested by leveva's own boot‑level golden snapshot + proptest fuzzing, and **differentially pinned against `ircd-common`** (structural skeleton + documented divergences, since leveva emits a clean modern burst rather than a byte copy). **Done (32 slices) — full per‑slice detail in [`docs/progress-log/p11.md`](docs/progress-log/p11.md):** (1) connection + registration + welcome burst; (2) post‑registration dispatch; (3) shared client registry (nick uniqueness / `433`); (4) message delivery (per‑connection mailbox; `PRIVMSG`/`NOTICE`); (5) channels (`JOIN`/`PART` + fan‑out + `NICK`/`QUIT` relay); (6) UID identity (`UidGenerator`; UID‑keyed membership); (7) channel metadata (creation TS + `TOPIC`); (8) channel modes (`MODE` + op model + `+nmtipsklovb`); (9) `KICK`; (10) `INVITE` (`+i` one‑shot tokens); (11) `NAMES`/`LIST` (+ `+s`/`+p` visibility); (12) `WHOIS`; (13) `WHO` — this last preceded by splitting the `command.rs` monolith into a `command/` folder (one client handler per file, tests local); (14) **user modes** (`MODE <nick>` → `+i`/`+w` with `send_umode` echo + `221`/`501`/`502`), a config‑driven default user mode (`default-user-modes`, default `+iw`) seeded at registration, and `+i` invisible wired into the `WHO` user sweeps; (15) **`AWAY`** (`306`/`305`, the server‑managed `+a` bit) with the away message stored in the shared registry record + the three observers wired — PRIVMSG `301` to the sender (not NOTICE), WHO `G`/`H` flag, WHOIS `301` after `312`; (16) **`OPER`** (operator login) — authenticate `OPER <name> <password>` against the configured `operator` blocks (name IRC‑fold + `user@host` mask glob + `Password::verify`, the new pure‑Rust `pwhash` crypt path for hashed credentials), granting `+o`/`+O` with a `MODE` echo + `381`, mirrored into the registry so WHOIS shows `313` (after the `301` away slot); the `491`‑vs‑`464` split (no O‑line vs wrong password); (17) **`WALLOPS`** (operator broadcast) — `WALLOPS <text>` from an operator (`+o`/`+O`) fans `:nick!user@host WALLOPS :text` to every connected `+w` user (consuming the `UserMode::Wallops` bit that has existed since slice 14 with no consumer); non‑oper → `481`, no text → `461`. Deliberate divergence from the IRCnet 2.11 oracle (whose `m_wallops` `msgtab` row routes *client* WALLOPS to `m_nop` — it is server‑sourced only there): leveva adopts the RFC 2812 §4.7 / modern‑ircd oper‑issued form, documented; (18) **ping‑timeout keepalive** (the server‑side half of PING/PONG) — a new pure [`heartbeat`](leveva/src/heartbeat.rs) module (`Heartbeat`/`Beat`/`evaluate`) drives the IRCnet 2.11 `check_pings` policy: an idle connection is pinged once (`PING :<server>`) at one `ping-freq` and dropped (`ERROR :Closing Link: (Ping timeout)` + a `QUIT :Ping timeout` relayed to channel co‑members) if still silent at `2·ping-freq`; any inbound line (incl. the client's `PONG`) resets the timer; `ping-freq 0` disables it. The interval is the connection's **class `ping-freq`** (`heartbeat::default_ping_freq(&classes)`); since leveva does not yet match `allow → class`, every client uses the default (first) class, documented. Wired into `Session` (`start_heartbeat`/`record_activity`/`check_ping`, injected‑time so it stays pure/deterministic) and a third `select!` arm in the `main.rs` serve loop. No pure oracle entry point exists (the C `check_pings` walks `local[]` with global sender buffers) → no `leveva-integration` test; verified by unit + injected‑time session tests + a 2‑property `heartbeat_proptest` schedule fuzzer + a live boot (`ping-freq 1`: PING then timeout; answering PONG survives). (19) **`KILL`** (operator forced disconnect) — `KILL <nick> <comment>` from an operator (`+o`/`+O`) forcibly disconnects a **local** client: the victim receives `:<killer> KILL <victim> :<killerhost>!<killer> (<comment>)` + `ERROR :Closing Link: …`, then its serve loop closes and relays `QUIT :Local Kill by <killer> (<comment>)` to channel co‑members (faithful to the oracle's local‑oper `exit_client` comment, which leaves `FLAGS_KILLED` unset so the channel QUIT fires); non‑oper → `481`, missing target/comment → `461`, target = server → `483`, unknown nick → `401`. This is the first leveva command that **forces another connection to close**, so it introduces the cross‑connection control plane: the per‑connection mailbox payload becomes `Envelope::{Wire,Eject}` (the eject rides the same `mpsc` so it can never overtake queued wire frames), `Registry::eject_uid` queues the disconnect, and `Session::force_close` records the kill reason for `release()`'s QUIT relay. Out of scope (documented): the local‑oper server‑notice (`SCH_KILL`) broadcast, `FLAGS_KILLED`/S2S propagation, `+O` remote kill, WHOWAS kill‑chasing. No pure oracle entry point (the C `m_kill` calls `exit_client`/global sender buffers) → no `leveva-integration` test; verified by unit + injected‑state session tests + a 2‑property `kill_proptest` (privilege/outcome + per‑victim eject conservation + arbitrary‑bytes panic‑freedom) + a boot golden (`golden_kill`). (20) **`USERHOST`/`ISON`** (the two RFC "query a list of nicks" commands, ported as a pair) — `USERHOST` answers a single `302 RPL_USERHOST` listing up to **five** resolvable nicks as `<nick>[*]=<sign><user>@<host>` (`*` iff oper `+o`/`+O`, sign `-` iff away `+a`, else `+`), faithful to the oracle `m_userhost`'s 5‑token cap and byte layout; `ISON` answers a single `303 RPL_ISON` echoing exactly the online subset in query order as canonical (fold‑resolved) nicks, dropping absent names and stopping before the wire budget overflows (the oracle's `BUFSIZE‑4` early break). Both flatten middle params + trailing to one token stream (`a b` ≡ `:a b`) and emit `461` with no parameter. Documented divergence: leveva emits a single `302` line (the oracle re‑heads on `BUFSIZE` fill, unreachable under the 5‑nick cap within 512 bytes). No pure oracle entry point (both call `sendto_one` into global buffers) → no `leveva-integration` differential; verified by unit (with inverses: away→back sign round‑trip, quit makes a nick disappear, the 6th present user dropped by the cap) + a 3‑property `userhost_ison_proptest` (online‑subset‑in‑order model for ISON, first‑five‑resolvable model for USERHOST, arbitrary‑query panic‑freedom + wire‑budget) + a boot golden (`golden_userhost_ison`). (21) **`WHOWAS`** (nick‑history query) — a new pure [`whowas`](leveva/src/whowas.rs) module (bounded newest‑first ring) records a vacated identity on every `NICK`‑change and disconnect; `WHOWAS <nicklist> [count] [target]` answers `314`+`312` per matched entry (newest first, capped at `count`), `406` on a miss, one closing `369`, `431` with no nick. Divergences: no server routing/remote‑cap (single‑server), and the `312` time renders as unix **seconds** (leveva's wire‑time convention, like `333`). No pure oracle entry point → no `leveva-integration` test; verified by unit (store + handler, with inverses) + a session integration test (disconnect→WHOWAS finds it) + a 3‑property `whowas_proptest` (newest‑first model, comma‑list structure, arbitrary‑query panic‑freedom) + a boot golden (`golden_whowas`); (22) **`TIME`/`ADMIN`/`INFO`** (server‑information query commands, ported as a pure read‑only trio) — `TIME`→a single `391` (time as unix **seconds**, leveva's wire convention), `ADMIN`→the `256`/`257`/`258`/`259` block from a new `ServerContext.admin` config field (`423` when empty, unreachable since the `admin` block is mandatory), `INFO`→leveva's own `371`* description block (with `On-line since <created>`) then `374`; all three reach client+oper columns (no oper gate) and ignore the single‑server `hunt_server` target arg; verified by unit + a `golden_time_admin_info` boot golden + a 4‑property `server_query_proptest` (the canonicalizer gained a `391`‑seconds + `On-line since` mask); (23) **`LINKS`/`MAP`** (server‑topology query commands, ported as a read‑only pair) — on single‑server leveva the network is one node, so `LINKS`→one `364 RPL_LINKS` (this server as its own upstream, hopcount `0`, SID + description; empty description → `(Unknown Location)`) then `365 RPL_ENDOFLINKS`, and `MAP`→`018 RPL_MAPSTART`/one `015 RPL_MAP`/`017 RPL_MAPEND`, with the trailing literal `s` selecting the verbose `dump_map_sid` variant (header `Server users SID version`; the `015` body carries `<name> <users> <sid> <version>`). An optional server `<mask>` filters the (single) server by glob against its name — a non‑match drops the `364`/`015`, leaving just the terminator block. Documented divergences (single‑server): `LINKS`'s three‑arg `<remote> <mask>` remote‑forward form (`hunt_server`) can't resolve elsewhere with no peers, so leveva drops the remote target and answers locally using the second token as the mask; no `RPL_TRYAGAIN` flood throttle; `MAP` draws no tree connectors (no children) and never shows the `s`‑variant "bursting" annotation. No `leveva-integration` differential (`m_links`/`m_map` `sendto_one` into global buffers — no pure oracle entry point, as with every recent slice); verified by unit (each command + the inverse non‑matching‑mask suppression + the empty‑description branch) + a 3‑property `server_topology_proptest` (LINKS = optional `364`‑iff‑mask‑matches then one `365`; MAP = `018`/optional `015`/`017` with the verbose header keyed on a trailing `s`; arbitrary args/nick panic‑freedom + no stray numerics) + a boot golden (`golden_links_map`); (24) **`STATS`** (config‑introspection query) — `STATS <letter> [<target>]` dumps the parsed config blocks one numeric per block, closed by a `219 RPL_ENDOFSTATS` echoing the selector char (`*` for bare/unknown, faithful to the oracle's default‑arm downgrade). The selector is the **first char** of the first arg (oracle `parv[1][0]`), case‑insensitive; the `<target>` `hunt_server` arg is dropped (single server). leveva maps the **config‑introspection** letters directly onto its KDL config: `o`→`243` per `operator`, `y`→`218` per `class`, `i`→`215` per `allow`, `c`→`213` per `connect`, `u`→`242` uptime. A new bundled `ServerContext.stats_conf` ([`StatsConf`](leveva/src/server.rs): classes/allows/links + a boot `Instant`) carries the data (operators stay the top‑level field `OPER` already consumes; `STATS o` reads them there). Documented divergences (clean modern burst): named class instead of a numeric id + per‑host limits as separate params (not the oracle's `%d.%d` packing) + live‑links `0`; no oper/I‑line privilege‑flag trailer + port `0`; the **state‑dependent** letters the oracle implements but leveva has no state for (`m`/`l`/`p`/`t`/`?`/`f`/`z`/`k`/`a`) produce no body, just the terminator. No `leveva-integration` differential (`m_stats` `sendto_one` into global buffers — no pure oracle entry point). Verified by unit (each letter + the **inverse** empty‑config‑yields‑terminator‑only, the `O`/`o` case echo, first‑char‑only selector, ignored target) + a 3‑property `stats_proptest` (terminator always last/singular with the modeled selector char; recognized‑letter body count = configured‑block count; arbitrary args/nick panic‑freedom + only STATS numerics) + a boot golden (`golden_stats`, with the `242` uptime masked by the canonicalizer; `minimal.kdl` gained a `connect` block to exercise `STATS c`); (25) **`DIE`/`RESTART`/`REHASH`** (the oper control‑plane trio) — the first leveva commands that act on the **whole process**, introducing a server **control plane** ([`leveva/src/control.rs`](leveva/src/control.rs): a process‑global `ServerControl` = `Notify` + latching `AtomicU8` + `request`/`wait`/`pending`) — the process‑level analogue of slice 19's per‑connection eject plane. Faithful to the oracle `m_die`/`m_restart`/`m_rehash` `msgtab` gate (`{ m_nop, m_nopriv, m_<cmd>, m_nop, m_unreg }`: a non‑oper → `m_nopriv`/`481`; an oper → the handler, which re‑gates on `is_allowed(ACL_DIE|RESTART|REHASH)` → also `481` without the flag). This slice **consumes the dormant `OperPrivilege` machinery** (parsed since slice 16, unused like `UserMode::Wallops` before slice 17): `command::Registered` gains a `privileges` set, populated from the matched block on a successful `OPER`, and each control command gates on its `OperPrivilege` (a non‑oper's empty set ⇒ `481`, reproducing both oracle arms in one check). `DIE`/`RESTART` share `shutdown_all`: **eject every registered client** (issuer included) with `:<me> NOTICE <nick> :Server (Terminating\|Restarting). <nick>[<user>@<host>]` as the eject wire (reusing `eject_uid`, relaying `Server died`/`Server Restarting` as the channel QUIT), then `control::request(Die\|Restart)` — no in‑band reply; `main`'s top‑level `select!` (now `ctrl_c → Die` ∥ `control::wait() → action`) drains the ejects over a 200 ms grace then exits (`Die`) or `reexec()`s the binary (`Restart`, `CommandExt::exec` + `CLOEXEC` sockets re‑bind cleanly). `REHASH` replies `382 RPL_REHASHING <nick> <config‑basename> :Rehashing` and re‑reads/validates the on‑disk config (`control::rehash_config`). Documented divergences: `killer` as `<nick>[<user>@<host>]`; single‑server (no server‑link `ERROR` branch); `RESTART`'s re‑exec is review‑covered (decision unit‑tested), not golden‑tested, as the C port treated `restart()`; `REHASH` only validates the re‑read (applying it to the immutable‑per‑boot `ServerContext` is deferred; TLS certs already hot‑reload); no `SCH_NOTICE`; KILL/WALLOPS still gate on the oper bit only. No `leveva-integration` differential (all three `sendto_*`/`s_die`/`restart` into globals — no pure oracle entry point). Verified by unit (control struct 8; die/restart/rehash 3 each w/ inverses: non‑oper 481, oper‑without‑priv 481, privileged ejects/382; OPER stores the set) + a 3‑property `control_proptest` (gate = 481 iff lacking the privilege; DIE/RESTART eject‑conservation = exactly the registered set once each; arbitrary‑args panic‑freedom ⊆ {382,481}) + a boot golden (`golden_control`: mortal 481, oper 382, oper DIE → NOTICE then server exit) + live boots (DIE→EOF→exit; RESTART→re‑exec→port re‑bind); (26) **`TRACE`** (connection introspection, oper‑gated) — `TRACE [<target>]` reports the connections this server sees. The first command whose **output set depends on the requester's operator privilege**: it consumes the dormant `OperPrivilege::Trace` (the C `ACL_TRACE`, parsed since slice 16). With no target (or a target case‑folding to this server) it walks the registry (folded‑nick order) emitting one `205 RPL_TRACEUSER`/`204 RPL_TRACEOPERATOR` per **visible** client then `262 RPL_TRACEEND`; the oracle's report‑everything visibility gate applies — an ordinary client other than the requester shows **only** to a requester holding `Trace`, while self + operators are always shown. A target naming a registered nick yields one **ungated** trace line + a `262` naming the target (so a non‑oper's `TRACE bob` shows bob even though the sweep hides him); an unresolvable target → `402 ERR_NOSUCHSERVER`. Documented divergences (single‑server): the class field is the configured class **name** not the oracle's numeric id (the `STATS y` divergence) and is always the default (first) class (no `allow → class` yet); leveva's registry holds only *registered* clients so `203 RPL_TRACEUNKNOWN` + the server‑link `200`/`206` lines never appear; wildcard/SID target matching is dropped (the only server is us, matched by exact folded name). No `leveva-integration` differential (`m_trace` `reply_one!` into global buffers — no pure oracle entry point). Verified by unit (8 — non‑oper sweep = self+opers w/ the inverse bob‑absent; oper sweep = everyone w/ inverse bob‑present; targeted bob shown to a non‑oper; targeted oper = `204`; unknown = `402`; class name; `262` names server‑for‑sweep / target‑for‑target) + a 3‑property `trace_proptest` (sweep = exactly the modeled‑visible set `{self}∪{opers}∪(ACL_TRACE?all:∅)` in order then one `262`; target resolves to sweep / `[line,262]` / `[402]`; arbitrary args panic‑free ⊆ trace numerics) + a boot golden (`golden_trace`: mortal sweep hides bob, post‑`OPER` sweep shows both; `minimal.kdl`'s operator gained the `trace` privilege, additive); (27) **`ETRACE`** (extended local‑person trace, oper‑gated) — `ETRACE [<target>]` is the full‑column sibling of slice‑26 `TRACE`: unlike `TRACE` the **whole command** is oper‑gated (the oracle `m_etrace` gates on `my_client(sptr) && is_allowed(sptr, ACL_TRACE)`; both arms — non‑oper *and* oper‑without‑`trace` — go to `m_nopriv`), so a requester without `OperPrivilege::Trace` → `481` with no trace lines, and there is **no** per‑client visibility gate (the command being privileged, every local person is reported unconditionally). No target → one `708 RPL_ETRACEFULL` per registered client (folded‑nick order); a target naming a registered person → one `708` for it (an unresolvable target → no `708`); always closes with one `759 RPL_ETRACEEND` naming server + version. The `708` carries the full columns `<Oper\|User> <class> <nick> <user> <host> <ip> - - :<realname>`. Documented divergences (single‑server, clean modern burst): leveva emits the **canonical numeric `708`** where the oracle's `replies[708]` literally formats `709` on the wire (a long‑standing reference quirk — constant `RPL_ETRACEFULL == 708` but the message text says `709`); the class field is the configured class **name** not the oracle's numeric id (the `STATS y`/`TRACE` divergence), always the default (first) class; the `ip` column equals the `host` column because leveva's registry stores no separate numeric IP — the `host` already *is* the peer IP (no rDNS yet); the two XLINE columns are the `-` `-` literals (XLINE off in the oracle too). No `leveva-integration` differential (`m_etrace` `reply_one!` into global buffers — no pure oracle entry point). Verified by unit (8 — non‑oper → `481`/no lines, oper‑without‑`trace` → `481`, privileged sweep = one `708` per person + `759` w/ the **inverse** a quit removes that person's `708`, full‑column assertion incl. `host==ip`, `Oper`/`User` label, targeted‑present → `[708,759]`, targeted‑absent → `[759]` only, the `759` names server+version) + a 3‑property `etrace_proptest` (gate‑then‑sweep = `[481]` unprivileged else one `708` per person folded then one `759`; target resolves to `[708,759]`/`[759]`; arbitrary args/nick/privilege panic‑free ⊆ `{481,708,759}`) + a boot golden (`golden_etrace`: mortal `ETRACE` → `481`, post‑`OPER` `ETRACE` → `708` for alice+bob + `759`; reuses `minimal.kdl`'s `trace`‑privileged operator, no fixture change); (28) **`TKLINE`/`UNTKLINE`** (the temporary K‑line control‑plane — an oper bans/unbans a `user@host` glob mask for a bounded time) — the first leveva command that **persists shared ban state and gates connection admission**. A new pure [`kline`](leveva/src/kline.rs) module carries a `KlineStore` (owned `Vec<Kline>` behind a `Mutex`, glob masks matched via leveva's own `matching`, absolute unix‑second expiry passed in so the store reads no clock) bundled into a new `ServerContext.klines` field; `parse_duration` is a from‑scratch reimplementation of the C `wdhms2sec` duration grammar (`w`/`d`/`h`/`m`/`s` units, a trailing bare number = minutes, `i32`‑wrapping arithmetic, bad char → not‑ok with the retained partial), and — being a **pure** function with a faithful oracle twin — it **restores a `leveva-integration` differential** (`wdhms2sec_differential.rs`, pinning leveva ↔ `ircd_common::s_conf::wdhms2sec` over a fuzz corpus within the documented no‑overflow domain), the first since the run of impure introspection slices. `TKLINE <dur> <user@host> [:reason]` is param‑gated (min‑args `461` before privilege, faithful to the oracle `msgtab` order) then oper‑gated on `OperPrivilege::Tkline`, lays/refreshes the ban, and **reaps** every connected client the mask covers via slice‑19's `eject_uid` plane (`:<server> 465 :You (<umask>@<hmask>) are banned from this server: <reason>` + `ERROR :Closing Link: … (Kill line active: <reason>)`, relaying `QUIT :Kill line active: <reason>` to channel co‑members); `UNTKLINE <user@host>` lifts it; a malformed mask/duration → `NOTICE :T/UNTKLINE: Incorrect format`. The ban also **refuses a matching client at registration** ([`session.rs`](leveva/src/session.rs) consults `find_active` in the `Complete` arm → `465` + `ERROR`, never counted/claimed). Documented divergences (single‑server, clean modern burst): no `SCH_TKILL` server‑notice/`&NOTICES` feedback to the issuer (so a successful `TKLINE` makes no in‑band reply, like `KILL`/`DIE`); no `=user` auth‑targeting (stripped, treated as a plain glob — leveva has no separate `auth` field); no CIDR `match_ipmask` special‑casing or `USERLEN+HOSTLEN` length cap (host matched purely as a glob); no `FLAGS_EXEMPT` K‑line exemption yet (every match reaped). Verified by unit (kline 11: the `wdhms2sec` grammar incl. bad‑char/partial + store add/find/remove/expire/refresh with inverses; tkline 9: `461`‑before‑`481`, non‑oper `481` lays nothing, the five incorrect‑format cases, store‑on‑success, reap **with the inverse** a non‑matching host is untouched, untkline round‑trip; session 2: a klined client is refused + an unmatched client registers normally despite a kline) + a 4‑property `kline_proptest` (param‑then‑privilege gate; reap conservation = exactly the mask‑covered set ejected once each; TKLINE→UNTKLINE empties the store; arbitrary args/nick/privilege panic‑free ⊆ `{461,481,NOTICE}`) + the `wdhms2sec` differential + a boot golden (`golden_tkline`: a mortal `TKLINE`→`481`, a malformed mask→`NOTICE`, an oper `TKLINE bobby@*` reaps `bob` (ident `bobby`) with `465`+`ERROR` while the issuer `alice` (ident `alice`) survives a PING round‑trip, then `mallory` reconnecting with ident `bobby` is refused at registration with `465`; `minimal.kdl`'s operator gained the `tkline` privilege, additive); (29) **`HELP`/`USERS`** (the last two pure single‑server info queries, ported as a pair) — `HELP`→one `:<server> NOTICE <nick> :<CMD>` per command **leveva implements** (a hand‑maintained `command::HELP_COMMANDS` list), faithful to the oracle `m_help` *shape* (a NOTICE per command, no terminator, no param requirement) but diverging on *content* (leveva lists its own ~38 handlers, not the oracle's full 66‑row `msgtab` of S2S/services/debug rows it has no handler for); `USERS`→`265 RPL_LOCALUSERS`/`266 RPL_GLOBALUSERS`, faithful to the oracle `send_users` under the locked `USERS_SHOWS_UTMP`‑off config (exactly those two count lines — no utmp `392`/`393`/`394`, no `446`). The `265`/`266` pair is extracted as `registration::local_global_users` so `USERS` and the tail of `LUSERS` cannot drift. Both are pure, client‑reachable (no oper gate), and ignore their args (HELP's are unused; USERS's is a no‑op `hunt_server` target). No `leveva-integration` differential (`m_help`/`send_users` `reply_one!`/`sendto` into global buffers — no pure oracle entry point). Verified by unit (help 3 — the NOTICE dump + arg‑ignoring + the **inverse** `commands_are_all_implemented` honesty check: every advertised name dispatches to a real handler, never `421`; users 3 — `265`/`266` shape + the **`USERS`==`LUSERS`‑tail** pin + arg‑ignoring) + a 3‑property `help_users_proptest` (HELP = one NOTICE per `HELP_COMMANDS` in order to the requester; USERS = exactly `[265,266]` with counts matching the live counters; arbitrary args/nick panic‑free, never `421`) + a boot golden (`golden_help_users`: register alice → HELP NOTICE dump + USERS `265`/`266`, counts deterministic at one user so no canonicalizer change); (30) **`HELP` embedded per‑command help pages** (evolving slice 29's HELP) — `HELP` now serves plain‑text help pages embedded from `leveva/help/` via **`rust-embed`** (`HelpFiles`): bare `HELP`→`help/index.md`, `HELP <CMD>`→`help/<CMD>.md` (the topic is upper‑folded + sanitized to `[A-Z0-9]`, so a path‑traversal/junk argument simply misses), an unknown/unhelped command→a single not‑found `NOTICE`; each page is delivered as `:<server> NOTICE <nick> :<line>` wrapped in a `*** <label> ***`/`*** End of help ***` header/footer. In release the `.md` files are baked into the binary; in debug `rust-embed` reads them from disk (relative to `CARGO_MANIFEST_DIR`) so help text edits need no recompile. **39 command pages + an index** were authored — the 5 seed pages (index/JOIN/PART/PRIVMSG/OPER/HELP) by hand, the other 34 by an **ultracode multi‑agent workflow** (one agent per command grounding its page in the real handler source, then an adversarial accuracy/style review pass). Two test invariants enforce the convention *adding a command means adding its help page*, both directions: `shipped_help_files_name_real_commands` (no orphan page) and `every_command_has_a_help_page` (every command in the canonical `COMMANDS` list ships a page; `NICK` added to that list). Faithful to the oracle `m_help` *delivery* (plain `NOTICE`s, no terminator numeric, no param requirement); divergent on *content* (leveva's own pages, not a `msgtab` name dump). Verified by unit (help **8** — bare→index, `HELP <CMD>`→its file, case‑fold, the not‑found inverse, the path‑traversal rejection, the honesty + both completeness invariants) + the reworked 4‑property `help_users_proptest` (HELP arbitrary topic → NOTICEs to the requester, never `421`; a junk first‑token → single not‑found; USERS `[265,266]`; arbitrary panic‑freedom) + the updated `golden_help_users` boot golden; (31) **server‑to‑server (S2S) link protocol** — the UID‑based IRCnet 2.11 burst on `server‑only` listeners: a new `leveva/src/s2s/` modtree (`network`/`handshake`/`unick`/`njoin`/`mode`/`save`/`eob`/`squit` + `PeerLink`/`MemberPrefix`), a `Network` mirror in `ServerContext` (`BTreeMap<Uid,RemoteUser>`, netsplit = SID‑prefix `range` drain), PASS/SERVER handshake against `connect{}` blocks, inbound + outbound burst (UNICK/NJOIN/MODE/SAVE/EOB/EOBACK), and `SQUIT`/abrupt‑drop teardown (+ an oper `SQUIT` command). Built by an ultracode multi‑agent workflow, then 3 adversarial‑review bugs fixed (NJOIN‑only ghost member survived SQUIT; UNICK‑collision stale mirror nick; NJOIN `.` placeholder wire/parse mismatch). Verified by unit + `golden_s2s` boot golden + 7‑property `s2s_proptest` (no pure‑oracle entry point → no `leveva‑integration` differential). Full detail in [`docs/progress-log/p11.md`](docs/progress-log/p11.md); (32) **`CONNECT`** (operator‑initiated **outbound** server link — the active counterpart to slice 31's passive accept) — a new outbound‑link plane ([`leveva/src/link.rs`](leveva/src/link.rs): a global `mpsc` queue of `OutboundLink`, the multi‑shot sibling of slice 25's `control` plane) bridges the pure handler to `main`'s dial task. `CONNECT <server> [<port> [<remote>]]` consumes the dormant `OperPrivilege::ConnectLocal`; its pure `connect_decision` ladder = min‑params `461` → privilege `481` → remote‑routing `402` (single‑server can't forward) → resolution (unknown/already‑linked → a `NOTICE`) → port (0/non‑numeric → a `NOTICE`) → dial (`*** Connecting to <name>[<host>].<port>` NOTICE + an `OutboundLink` queued). `main`'s `serve_server` was refactored into a side‑agnostic `read_link_handshake` + a shared `serve_linked_peer` post‑establishment lifecycle, with a new `dial_server` that `TcpStream::connect`s the peer, sends our `PASS`/`SERVER` greeting **first** (`s2s::build_link_greeting`), validates the reply through the same reader, and bursts. Documented divergences (single‑server): no remote routing (`connect-remote` stays dormant); plain‑TCP only (TLS‑outbound deferred); leveva NOTICE phrasing, no `SCH_NOTICE`/in‑band confirmation. No pure‑oracle entry point → no `leveva‑integration` differential; verified by unit (connect 10 incl. inverses + link 1) + a 3‑property `connect_proptest` + a `golden_connect` boot golden (an oper `CONNECT peer.test` dials a fake peer listener, which receives the active greeting + full burst + EOB) + a `help/CONNECT.md` page. Each slice is unit‑tested + boot‑golden + proptest‑fuzzed, and — where a pure oracle entry point exists — differentially pinned against `ircd-common`. | Per‑slice: leveva boots and serves the slice; leveva golden snapshot + proptest green; the `leveva-integration` differential agrees with `ircd-common` on the shared skeleton with divergences asserted. Across the eventual matrix: registration, channels, WHO/WHOIS/WHOX, OPER/STATS, server burst, netsplit, rehash, restart; iauth end‑to‑end. |
9393+| **P11 — `leveva` protocol layer → feature parity 🔶 IN PROGRESS** ([`docs/progress-log/p11.md`](docs/progress-log/p11.md)) | `leveva` (client/server state machine + handlers) | The bulk of the remaining work: the connection + registration state machine (`NICK`/`USER` → `001`–`004`/`375`–`376` welcome burst), command handlers (JOIN/PRIVMSG/MODE/KICK/TOPIC/WHO/WHOIS/…), channels, the S2S link/burst protocol (UID‑based: UNICK/NJOIN/SAVE/EOB), and spawning `iauth-rs` over a socketpair. Each slice is built idiomatically (owned per‑connection state, typed identifiers end‑to‑end, `Result`/`thiserror`, `format!`/typed builders — **no** `sprintf`/global `buf`), tested by leveva's own boot‑level golden snapshot + proptest fuzzing, and **differentially pinned against `ircd-common`** (structural skeleton + documented divergences, since leveva emits a clean modern burst rather than a byte copy). **Done (33 slices) — full per‑slice detail in [`docs/progress-log/p11.md`](docs/progress-log/p11.md):** (1) connection + registration + welcome burst; (2) post‑registration dispatch; (3) shared client registry (nick uniqueness / `433`); (4) message delivery (per‑connection mailbox; `PRIVMSG`/`NOTICE`); (5) channels (`JOIN`/`PART` + fan‑out + `NICK`/`QUIT` relay); (6) UID identity (`UidGenerator`; UID‑keyed membership); (7) channel metadata (creation TS + `TOPIC`); (8) channel modes (`MODE` + op model + `+nmtipsklovb`); (9) `KICK`; (10) `INVITE` (`+i` one‑shot tokens); (11) `NAMES`/`LIST` (+ `+s`/`+p` visibility); (12) `WHOIS`; (13) `WHO` — this last preceded by splitting the `command.rs` monolith into a `command/` folder (one client handler per file, tests local); (14) **user modes** (`MODE <nick>` → `+i`/`+w` with `send_umode` echo + `221`/`501`/`502`), a config‑driven default user mode (`default-user-modes`, default `+iw`) seeded at registration, and `+i` invisible wired into the `WHO` user sweeps; (15) **`AWAY`** (`306`/`305`, the server‑managed `+a` bit) with the away message stored in the shared registry record + the three observers wired — PRIVMSG `301` to the sender (not NOTICE), WHO `G`/`H` flag, WHOIS `301` after `312`; (16) **`OPER`** (operator login) — authenticate `OPER <name> <password>` against the configured `operator` blocks (name IRC‑fold + `user@host` mask glob + `Password::verify`, the new pure‑Rust `pwhash` crypt path for hashed credentials), granting `+o`/`+O` with a `MODE` echo + `381`, mirrored into the registry so WHOIS shows `313` (after the `301` away slot); the `491`‑vs‑`464` split (no O‑line vs wrong password); (17) **`WALLOPS`** (operator broadcast) — `WALLOPS <text>` from an operator (`+o`/`+O`) fans `:nick!user@host WALLOPS :text` to every connected `+w` user (consuming the `UserMode::Wallops` bit that has existed since slice 14 with no consumer); non‑oper → `481`, no text → `461`. Deliberate divergence from the IRCnet 2.11 oracle (whose `m_wallops` `msgtab` row routes *client* WALLOPS to `m_nop` — it is server‑sourced only there): leveva adopts the RFC 2812 §4.7 / modern‑ircd oper‑issued form, documented; (18) **ping‑timeout keepalive** (the server‑side half of PING/PONG) — a new pure [`heartbeat`](leveva/src/heartbeat.rs) module (`Heartbeat`/`Beat`/`evaluate`) drives the IRCnet 2.11 `check_pings` policy: an idle connection is pinged once (`PING :<server>`) at one `ping-freq` and dropped (`ERROR :Closing Link: (Ping timeout)` + a `QUIT :Ping timeout` relayed to channel co‑members) if still silent at `2·ping-freq`; any inbound line (incl. the client's `PONG`) resets the timer; `ping-freq 0` disables it. The interval is the connection's **class `ping-freq`** (`heartbeat::default_ping_freq(&classes)`); since leveva does not yet match `allow → class`, every client uses the default (first) class, documented. Wired into `Session` (`start_heartbeat`/`record_activity`/`check_ping`, injected‑time so it stays pure/deterministic) and a third `select!` arm in the `main.rs` serve loop. No pure oracle entry point exists (the C `check_pings` walks `local[]` with global sender buffers) → no `leveva-integration` test; verified by unit + injected‑time session tests + a 2‑property `heartbeat_proptest` schedule fuzzer + a live boot (`ping-freq 1`: PING then timeout; answering PONG survives). (19) **`KILL`** (operator forced disconnect) — `KILL <nick> <comment>` from an operator (`+o`/`+O`) forcibly disconnects a **local** client: the victim receives `:<killer> KILL <victim> :<killerhost>!<killer> (<comment>)` + `ERROR :Closing Link: …`, then its serve loop closes and relays `QUIT :Local Kill by <killer> (<comment>)` to channel co‑members (faithful to the oracle's local‑oper `exit_client` comment, which leaves `FLAGS_KILLED` unset so the channel QUIT fires); non‑oper → `481`, missing target/comment → `461`, target = server → `483`, unknown nick → `401`. This is the first leveva command that **forces another connection to close**, so it introduces the cross‑connection control plane: the per‑connection mailbox payload becomes `Envelope::{Wire,Eject}` (the eject rides the same `mpsc` so it can never overtake queued wire frames), `Registry::eject_uid` queues the disconnect, and `Session::force_close` records the kill reason for `release()`'s QUIT relay. Out of scope (documented): the local‑oper server‑notice (`SCH_KILL`) broadcast, `FLAGS_KILLED`/S2S propagation, `+O` remote kill, WHOWAS kill‑chasing. No pure oracle entry point (the C `m_kill` calls `exit_client`/global sender buffers) → no `leveva-integration` test; verified by unit + injected‑state session tests + a 2‑property `kill_proptest` (privilege/outcome + per‑victim eject conservation + arbitrary‑bytes panic‑freedom) + a boot golden (`golden_kill`). (20) **`USERHOST`/`ISON`** (the two RFC "query a list of nicks" commands, ported as a pair) — `USERHOST` answers a single `302 RPL_USERHOST` listing up to **five** resolvable nicks as `<nick>[*]=<sign><user>@<host>` (`*` iff oper `+o`/`+O`, sign `-` iff away `+a`, else `+`), faithful to the oracle `m_userhost`'s 5‑token cap and byte layout; `ISON` answers a single `303 RPL_ISON` echoing exactly the online subset in query order as canonical (fold‑resolved) nicks, dropping absent names and stopping before the wire budget overflows (the oracle's `BUFSIZE‑4` early break). Both flatten middle params + trailing to one token stream (`a b` ≡ `:a b`) and emit `461` with no parameter. Documented divergence: leveva emits a single `302` line (the oracle re‑heads on `BUFSIZE` fill, unreachable under the 5‑nick cap within 512 bytes). No pure oracle entry point (both call `sendto_one` into global buffers) → no `leveva-integration` differential; verified by unit (with inverses: away→back sign round‑trip, quit makes a nick disappear, the 6th present user dropped by the cap) + a 3‑property `userhost_ison_proptest` (online‑subset‑in‑order model for ISON, first‑five‑resolvable model for USERHOST, arbitrary‑query panic‑freedom + wire‑budget) + a boot golden (`golden_userhost_ison`). (21) **`WHOWAS`** (nick‑history query) — a new pure [`whowas`](leveva/src/whowas.rs) module (bounded newest‑first ring) records a vacated identity on every `NICK`‑change and disconnect; `WHOWAS <nicklist> [count] [target]` answers `314`+`312` per matched entry (newest first, capped at `count`), `406` on a miss, one closing `369`, `431` with no nick. Divergences: no server routing/remote‑cap (single‑server), and the `312` time renders as unix **seconds** (leveva's wire‑time convention, like `333`). No pure oracle entry point → no `leveva-integration` test; verified by unit (store + handler, with inverses) + a session integration test (disconnect→WHOWAS finds it) + a 3‑property `whowas_proptest` (newest‑first model, comma‑list structure, arbitrary‑query panic‑freedom) + a boot golden (`golden_whowas`); (22) **`TIME`/`ADMIN`/`INFO`** (server‑information query commands, ported as a pure read‑only trio) — `TIME`→a single `391` (time as unix **seconds**, leveva's wire convention), `ADMIN`→the `256`/`257`/`258`/`259` block from a new `ServerContext.admin` config field (`423` when empty, unreachable since the `admin` block is mandatory), `INFO`→leveva's own `371`* description block (with `On-line since <created>`) then `374`; all three reach client+oper columns (no oper gate) and ignore the single‑server `hunt_server` target arg; verified by unit + a `golden_time_admin_info` boot golden + a 4‑property `server_query_proptest` (the canonicalizer gained a `391`‑seconds + `On-line since` mask); (23) **`LINKS`/`MAP`** (server‑topology query commands, ported as a read‑only pair) — on single‑server leveva the network is one node, so `LINKS`→one `364 RPL_LINKS` (this server as its own upstream, hopcount `0`, SID + description; empty description → `(Unknown Location)`) then `365 RPL_ENDOFLINKS`, and `MAP`→`018 RPL_MAPSTART`/one `015 RPL_MAP`/`017 RPL_MAPEND`, with the trailing literal `s` selecting the verbose `dump_map_sid` variant (header `Server users SID version`; the `015` body carries `<name> <users> <sid> <version>`). An optional server `<mask>` filters the (single) server by glob against its name — a non‑match drops the `364`/`015`, leaving just the terminator block. Documented divergences (single‑server): `LINKS`'s three‑arg `<remote> <mask>` remote‑forward form (`hunt_server`) can't resolve elsewhere with no peers, so leveva drops the remote target and answers locally using the second token as the mask; no `RPL_TRYAGAIN` flood throttle; `MAP` draws no tree connectors (no children) and never shows the `s`‑variant "bursting" annotation. No `leveva-integration` differential (`m_links`/`m_map` `sendto_one` into global buffers — no pure oracle entry point, as with every recent slice); verified by unit (each command + the inverse non‑matching‑mask suppression + the empty‑description branch) + a 3‑property `server_topology_proptest` (LINKS = optional `364`‑iff‑mask‑matches then one `365`; MAP = `018`/optional `015`/`017` with the verbose header keyed on a trailing `s`; arbitrary args/nick panic‑freedom + no stray numerics) + a boot golden (`golden_links_map`); (24) **`STATS`** (config‑introspection query) — `STATS <letter> [<target>]` dumps the parsed config blocks one numeric per block, closed by a `219 RPL_ENDOFSTATS` echoing the selector char (`*` for bare/unknown, faithful to the oracle's default‑arm downgrade). The selector is the **first char** of the first arg (oracle `parv[1][0]`), case‑insensitive; the `<target>` `hunt_server` arg is dropped (single server). leveva maps the **config‑introspection** letters directly onto its KDL config: `o`→`243` per `operator`, `y`→`218` per `class`, `i`→`215` per `allow`, `c`→`213` per `connect`, `u`→`242` uptime. A new bundled `ServerContext.stats_conf` ([`StatsConf`](leveva/src/server.rs): classes/allows/links + a boot `Instant`) carries the data (operators stay the top‑level field `OPER` already consumes; `STATS o` reads them there). Documented divergences (clean modern burst): named class instead of a numeric id + per‑host limits as separate params (not the oracle's `%d.%d` packing) + live‑links `0`; no oper/I‑line privilege‑flag trailer + port `0`; the **state‑dependent** letters the oracle implements but leveva has no state for (`m`/`l`/`p`/`t`/`?`/`f`/`z`/`k`/`a`) produce no body, just the terminator. No `leveva-integration` differential (`m_stats` `sendto_one` into global buffers — no pure oracle entry point). Verified by unit (each letter + the **inverse** empty‑config‑yields‑terminator‑only, the `O`/`o` case echo, first‑char‑only selector, ignored target) + a 3‑property `stats_proptest` (terminator always last/singular with the modeled selector char; recognized‑letter body count = configured‑block count; arbitrary args/nick panic‑freedom + only STATS numerics) + a boot golden (`golden_stats`, with the `242` uptime masked by the canonicalizer; `minimal.kdl` gained a `connect` block to exercise `STATS c`); (25) **`DIE`/`RESTART`/`REHASH`** (the oper control‑plane trio) — the first leveva commands that act on the **whole process**, introducing a server **control plane** ([`leveva/src/control.rs`](leveva/src/control.rs): a process‑global `ServerControl` = `Notify` + latching `AtomicU8` + `request`/`wait`/`pending`) — the process‑level analogue of slice 19's per‑connection eject plane. Faithful to the oracle `m_die`/`m_restart`/`m_rehash` `msgtab` gate (`{ m_nop, m_nopriv, m_<cmd>, m_nop, m_unreg }`: a non‑oper → `m_nopriv`/`481`; an oper → the handler, which re‑gates on `is_allowed(ACL_DIE|RESTART|REHASH)` → also `481` without the flag). This slice **consumes the dormant `OperPrivilege` machinery** (parsed since slice 16, unused like `UserMode::Wallops` before slice 17): `command::Registered` gains a `privileges` set, populated from the matched block on a successful `OPER`, and each control command gates on its `OperPrivilege` (a non‑oper's empty set ⇒ `481`, reproducing both oracle arms in one check). `DIE`/`RESTART` share `shutdown_all`: **eject every registered client** (issuer included) with `:<me> NOTICE <nick> :Server (Terminating\|Restarting). <nick>[<user>@<host>]` as the eject wire (reusing `eject_uid`, relaying `Server died`/`Server Restarting` as the channel QUIT), then `control::request(Die\|Restart)` — no in‑band reply; `main`'s top‑level `select!` (now `ctrl_c → Die` ∥ `control::wait() → action`) drains the ejects over a 200 ms grace then exits (`Die`) or `reexec()`s the binary (`Restart`, `CommandExt::exec` + `CLOEXEC` sockets re‑bind cleanly). `REHASH` replies `382 RPL_REHASHING <nick> <config‑basename> :Rehashing` and re‑reads/validates the on‑disk config (`control::rehash_config`). Documented divergences: `killer` as `<nick>[<user>@<host>]`; single‑server (no server‑link `ERROR` branch); `RESTART`'s re‑exec is review‑covered (decision unit‑tested), not golden‑tested, as the C port treated `restart()`; `REHASH` only validates the re‑read (applying it to the immutable‑per‑boot `ServerContext` is deferred; TLS certs already hot‑reload); no `SCH_NOTICE`; KILL/WALLOPS still gate on the oper bit only. No `leveva-integration` differential (all three `sendto_*`/`s_die`/`restart` into globals — no pure oracle entry point). Verified by unit (control struct 8; die/restart/rehash 3 each w/ inverses: non‑oper 481, oper‑without‑priv 481, privileged ejects/382; OPER stores the set) + a 3‑property `control_proptest` (gate = 481 iff lacking the privilege; DIE/RESTART eject‑conservation = exactly the registered set once each; arbitrary‑args panic‑freedom ⊆ {382,481}) + a boot golden (`golden_control`: mortal 481, oper 382, oper DIE → NOTICE then server exit) + live boots (DIE→EOF→exit; RESTART→re‑exec→port re‑bind); (26) **`TRACE`** (connection introspection, oper‑gated) — `TRACE [<target>]` reports the connections this server sees. The first command whose **output set depends on the requester's operator privilege**: it consumes the dormant `OperPrivilege::Trace` (the C `ACL_TRACE`, parsed since slice 16). With no target (or a target case‑folding to this server) it walks the registry (folded‑nick order) emitting one `205 RPL_TRACEUSER`/`204 RPL_TRACEOPERATOR` per **visible** client then `262 RPL_TRACEEND`; the oracle's report‑everything visibility gate applies — an ordinary client other than the requester shows **only** to a requester holding `Trace`, while self + operators are always shown. A target naming a registered nick yields one **ungated** trace line + a `262` naming the target (so a non‑oper's `TRACE bob` shows bob even though the sweep hides him); an unresolvable target → `402 ERR_NOSUCHSERVER`. Documented divergences (single‑server): the class field is the configured class **name** not the oracle's numeric id (the `STATS y` divergence) and is always the default (first) class (no `allow → class` yet); leveva's registry holds only *registered* clients so `203 RPL_TRACEUNKNOWN` + the server‑link `200`/`206` lines never appear; wildcard/SID target matching is dropped (the only server is us, matched by exact folded name). No `leveva-integration` differential (`m_trace` `reply_one!` into global buffers — no pure oracle entry point). Verified by unit (8 — non‑oper sweep = self+opers w/ the inverse bob‑absent; oper sweep = everyone w/ inverse bob‑present; targeted bob shown to a non‑oper; targeted oper = `204`; unknown = `402`; class name; `262` names server‑for‑sweep / target‑for‑target) + a 3‑property `trace_proptest` (sweep = exactly the modeled‑visible set `{self}∪{opers}∪(ACL_TRACE?all:∅)` in order then one `262`; target resolves to sweep / `[line,262]` / `[402]`; arbitrary args panic‑free ⊆ trace numerics) + a boot golden (`golden_trace`: mortal sweep hides bob, post‑`OPER` sweep shows both; `minimal.kdl`'s operator gained the `trace` privilege, additive); (27) **`ETRACE`** (extended local‑person trace, oper‑gated) — `ETRACE [<target>]` is the full‑column sibling of slice‑26 `TRACE`: unlike `TRACE` the **whole command** is oper‑gated (the oracle `m_etrace` gates on `my_client(sptr) && is_allowed(sptr, ACL_TRACE)`; both arms — non‑oper *and* oper‑without‑`trace` — go to `m_nopriv`), so a requester without `OperPrivilege::Trace` → `481` with no trace lines, and there is **no** per‑client visibility gate (the command being privileged, every local person is reported unconditionally). No target → one `708 RPL_ETRACEFULL` per registered client (folded‑nick order); a target naming a registered person → one `708` for it (an unresolvable target → no `708`); always closes with one `759 RPL_ETRACEEND` naming server + version. The `708` carries the full columns `<Oper\|User> <class> <nick> <user> <host> <ip> - - :<realname>`. Documented divergences (single‑server, clean modern burst): leveva emits the **canonical numeric `708`** where the oracle's `replies[708]` literally formats `709` on the wire (a long‑standing reference quirk — constant `RPL_ETRACEFULL == 708` but the message text says `709`); the class field is the configured class **name** not the oracle's numeric id (the `STATS y`/`TRACE` divergence), always the default (first) class; the `ip` column equals the `host` column because leveva's registry stores no separate numeric IP — the `host` already *is* the peer IP (no rDNS yet); the two XLINE columns are the `-` `-` literals (XLINE off in the oracle too). No `leveva-integration` differential (`m_etrace` `reply_one!` into global buffers — no pure oracle entry point). Verified by unit (8 — non‑oper → `481`/no lines, oper‑without‑`trace` → `481`, privileged sweep = one `708` per person + `759` w/ the **inverse** a quit removes that person's `708`, full‑column assertion incl. `host==ip`, `Oper`/`User` label, targeted‑present → `[708,759]`, targeted‑absent → `[759]` only, the `759` names server+version) + a 3‑property `etrace_proptest` (gate‑then‑sweep = `[481]` unprivileged else one `708` per person folded then one `759`; target resolves to `[708,759]`/`[759]`; arbitrary args/nick/privilege panic‑free ⊆ `{481,708,759}`) + a boot golden (`golden_etrace`: mortal `ETRACE` → `481`, post‑`OPER` `ETRACE` → `708` for alice+bob + `759`; reuses `minimal.kdl`'s `trace`‑privileged operator, no fixture change); (28) **`TKLINE`/`UNTKLINE`** (the temporary K‑line control‑plane — an oper bans/unbans a `user@host` glob mask for a bounded time) — the first leveva command that **persists shared ban state and gates connection admission**. A new pure [`kline`](leveva/src/kline.rs) module carries a `KlineStore` (owned `Vec<Kline>` behind a `Mutex`, glob masks matched via leveva's own `matching`, absolute unix‑second expiry passed in so the store reads no clock) bundled into a new `ServerContext.klines` field; `parse_duration` is a from‑scratch reimplementation of the C `wdhms2sec` duration grammar (`w`/`d`/`h`/`m`/`s` units, a trailing bare number = minutes, `i32`‑wrapping arithmetic, bad char → not‑ok with the retained partial), and — being a **pure** function with a faithful oracle twin — it **restores a `leveva-integration` differential** (`wdhms2sec_differential.rs`, pinning leveva ↔ `ircd_common::s_conf::wdhms2sec` over a fuzz corpus within the documented no‑overflow domain), the first since the run of impure introspection slices. `TKLINE <dur> <user@host> [:reason]` is param‑gated (min‑args `461` before privilege, faithful to the oracle `msgtab` order) then oper‑gated on `OperPrivilege::Tkline`, lays/refreshes the ban, and **reaps** every connected client the mask covers via slice‑19's `eject_uid` plane (`:<server> 465 :You (<umask>@<hmask>) are banned from this server: <reason>` + `ERROR :Closing Link: … (Kill line active: <reason>)`, relaying `QUIT :Kill line active: <reason>` to channel co‑members); `UNTKLINE <user@host>` lifts it; a malformed mask/duration → `NOTICE :T/UNTKLINE: Incorrect format`. The ban also **refuses a matching client at registration** ([`session.rs`](leveva/src/session.rs) consults `find_active` in the `Complete` arm → `465` + `ERROR`, never counted/claimed). Documented divergences (single‑server, clean modern burst): no `SCH_TKILL` server‑notice/`&NOTICES` feedback to the issuer (so a successful `TKLINE` makes no in‑band reply, like `KILL`/`DIE`); no `=user` auth‑targeting (stripped, treated as a plain glob — leveva has no separate `auth` field); no CIDR `match_ipmask` special‑casing or `USERLEN+HOSTLEN` length cap (host matched purely as a glob); no `FLAGS_EXEMPT` K‑line exemption yet (every match reaped). Verified by unit (kline 11: the `wdhms2sec` grammar incl. bad‑char/partial + store add/find/remove/expire/refresh with inverses; tkline 9: `461`‑before‑`481`, non‑oper `481` lays nothing, the five incorrect‑format cases, store‑on‑success, reap **with the inverse** a non‑matching host is untouched, untkline round‑trip; session 2: a klined client is refused + an unmatched client registers normally despite a kline) + a 4‑property `kline_proptest` (param‑then‑privilege gate; reap conservation = exactly the mask‑covered set ejected once each; TKLINE→UNTKLINE empties the store; arbitrary args/nick/privilege panic‑free ⊆ `{461,481,NOTICE}`) + the `wdhms2sec` differential + a boot golden (`golden_tkline`: a mortal `TKLINE`→`481`, a malformed mask→`NOTICE`, an oper `TKLINE bobby@*` reaps `bob` (ident `bobby`) with `465`+`ERROR` while the issuer `alice` (ident `alice`) survives a PING round‑trip, then `mallory` reconnecting with ident `bobby` is refused at registration with `465`; `minimal.kdl`'s operator gained the `tkline` privilege, additive); (29) **`HELP`/`USERS`** (the last two pure single‑server info queries, ported as a pair) — `HELP`→one `:<server> NOTICE <nick> :<CMD>` per command **leveva implements** (a hand‑maintained `command::HELP_COMMANDS` list), faithful to the oracle `m_help` *shape* (a NOTICE per command, no terminator, no param requirement) but diverging on *content* (leveva lists its own ~38 handlers, not the oracle's full 66‑row `msgtab` of S2S/services/debug rows it has no handler for); `USERS`→`265 RPL_LOCALUSERS`/`266 RPL_GLOBALUSERS`, faithful to the oracle `send_users` under the locked `USERS_SHOWS_UTMP`‑off config (exactly those two count lines — no utmp `392`/`393`/`394`, no `446`). The `265`/`266` pair is extracted as `registration::local_global_users` so `USERS` and the tail of `LUSERS` cannot drift. Both are pure, client‑reachable (no oper gate), and ignore their args (HELP's are unused; USERS's is a no‑op `hunt_server` target). No `leveva-integration` differential (`m_help`/`send_users` `reply_one!`/`sendto` into global buffers — no pure oracle entry point). Verified by unit (help 3 — the NOTICE dump + arg‑ignoring + the **inverse** `commands_are_all_implemented` honesty check: every advertised name dispatches to a real handler, never `421`; users 3 — `265`/`266` shape + the **`USERS`==`LUSERS`‑tail** pin + arg‑ignoring) + a 3‑property `help_users_proptest` (HELP = one NOTICE per `HELP_COMMANDS` in order to the requester; USERS = exactly `[265,266]` with counts matching the live counters; arbitrary args/nick panic‑free, never `421`) + a boot golden (`golden_help_users`: register alice → HELP NOTICE dump + USERS `265`/`266`, counts deterministic at one user so no canonicalizer change); (30) **`HELP` embedded per‑command help pages** (evolving slice 29's HELP) — `HELP` now serves plain‑text help pages embedded from `leveva/help/` via **`rust-embed`** (`HelpFiles`): bare `HELP`→`help/index.md`, `HELP <CMD>`→`help/<CMD>.md` (the topic is upper‑folded + sanitized to `[A-Z0-9]`, so a path‑traversal/junk argument simply misses), an unknown/unhelped command→a single not‑found `NOTICE`; each page is delivered as `:<server> NOTICE <nick> :<line>` wrapped in a `*** <label> ***`/`*** End of help ***` header/footer. In release the `.md` files are baked into the binary; in debug `rust-embed` reads them from disk (relative to `CARGO_MANIFEST_DIR`) so help text edits need no recompile. **39 command pages + an index** were authored — the 5 seed pages (index/JOIN/PART/PRIVMSG/OPER/HELP) by hand, the other 34 by an **ultracode multi‑agent workflow** (one agent per command grounding its page in the real handler source, then an adversarial accuracy/style review pass). Two test invariants enforce the convention *adding a command means adding its help page*, both directions: `shipped_help_files_name_real_commands` (no orphan page) and `every_command_has_a_help_page` (every command in the canonical `COMMANDS` list ships a page; `NICK` added to that list). Faithful to the oracle `m_help` *delivery* (plain `NOTICE`s, no terminator numeric, no param requirement); divergent on *content* (leveva's own pages, not a `msgtab` name dump). Verified by unit (help **8** — bare→index, `HELP <CMD>`→its file, case‑fold, the not‑found inverse, the path‑traversal rejection, the honesty + both completeness invariants) + the reworked 4‑property `help_users_proptest` (HELP arbitrary topic → NOTICEs to the requester, never `421`; a junk first‑token → single not‑found; USERS `[265,266]`; arbitrary panic‑freedom) + the updated `golden_help_users` boot golden; (31) **server‑to‑server (S2S) link protocol** — the UID‑based IRCnet 2.11 burst on `server‑only` listeners: a new `leveva/src/s2s/` modtree (`network`/`handshake`/`unick`/`njoin`/`mode`/`save`/`eob`/`squit` + `PeerLink`/`MemberPrefix`), a `Network` mirror in `ServerContext` (`BTreeMap<Uid,RemoteUser>`, netsplit = SID‑prefix `range` drain), PASS/SERVER handshake against `connect{}` blocks, inbound + outbound burst (UNICK/NJOIN/MODE/SAVE/EOB/EOBACK), and `SQUIT`/abrupt‑drop teardown (+ an oper `SQUIT` command). Built by an ultracode multi‑agent workflow, then 3 adversarial‑review bugs fixed (NJOIN‑only ghost member survived SQUIT; UNICK‑collision stale mirror nick; NJOIN `.` placeholder wire/parse mismatch). Verified by unit + `golden_s2s` boot golden + 7‑property `s2s_proptest` (no pure‑oracle entry point → no `leveva‑integration` differential). Full detail in [`docs/progress-log/p11.md`](docs/progress-log/p11.md); (32) **`CONNECT`** (operator‑initiated **outbound** server link — the active counterpart to slice 31's passive accept) — a new outbound‑link plane ([`leveva/src/link.rs`](leveva/src/link.rs): a global `mpsc` queue of `OutboundLink`, the multi‑shot sibling of slice 25's `control` plane) bridges the pure handler to `main`'s dial task. `CONNECT <server> [<port> [<remote>]]` consumes the dormant `OperPrivilege::ConnectLocal`; its pure `connect_decision` ladder = min‑params `461` → privilege `481` → remote‑routing `402` (single‑server can't forward) → resolution (unknown/already‑linked → a `NOTICE`) → port (0/non‑numeric → a `NOTICE`) → dial (`*** Connecting to <name>[<host>].<port>` NOTICE + an `OutboundLink` queued). `main`'s `serve_server` was refactored into a side‑agnostic `read_link_handshake` + a shared `serve_linked_peer` post‑establishment lifecycle, with a new `dial_server` that `TcpStream::connect`s the peer, sends our `PASS`/`SERVER` greeting **first** (`s2s::build_link_greeting`), validates the reply through the same reader, and bursts. Documented divergences (single‑server): no remote routing (`connect-remote` stays dormant); plain‑TCP only (TLS‑outbound deferred); leveva NOTICE phrasing, no `SCH_NOTICE`/in‑band confirmation. No pure‑oracle entry point → no `leveva‑integration` differential; verified by unit (connect 10 incl. inverses + link 1) + a 3‑property `connect_proptest` + a `golden_connect` boot golden (an oper `CONNECT peer.test` dials a fake peer listener, which receives the active greeting + full burst + EOB) + a `help/CONNECT.md` page; (33) **steady‑state S2S command relay** — relaying commands between linked servers *after* the burst, both directions. A new [`s2s::PeerLinks`](leveva/src/s2s/links.rs) routing table (`Sid`→peer mailbox) on `ServerContext.peers` — registered/unlinked by `serve_linked_peer`, now a `select!` loop that drains the peer mailbox to the socket in steady state — is the spine; `ServerContext::is_local_uid` gates channel fan‑out to **local** members only (a remote member is reached once by the relay, never by a per‑member client‑form mailbox push). **Outbound** ([`s2s::relay`](leveva/src/s2s/relay.rs) `local_*`): a local client's JOIN/PART/PRIVMSG‑NOTICE/TOPIC/KICK/MODE/NICK/QUIT is emitted UID‑prefixed to every peer (a remote‑nick message routed to that user's uplink only; `+o`/`+v` params rendered as UIDs), wired into the eight handlers + `Session::release`. **Inbound** (`s2s::dispatch` post‑burst): a peer's `JOIN/PART/PRIVMSG/NOTICE/TOPIC/KICK/NICK/QUIT` is applied to local state, fanned out to local members in client form (the `:nick!user@host` source resolved from the network mirror), and onward‑relayed to other peers (split‑horizon, never back to the origin); `MODE` keeps applying via `s2s::mode` and, post‑burst, also fans out via `after_mode` (UID member‑params translated back to display nicks). New helpers `Channels::set_topic_as_server` (no `+t` gate) + `squit::quit_one_remote_user`. Documented single‑uplink divergences (the onward‑relay is spine‑correct but a no‑op with one peer; clean `:<uid> JOIN` steady‑state form; no channel‑TS arbitration; no client numerics to a server). No pure‑oracle entry point → no `leveva-integration` differential; verified by unit (links 5 + relay 14, with inverses) + a 3‑property `relay_proptest` (outbound one‑frame‑per‑peer conservation; inbound split‑horizon; inbound forward‑to‑other‑peers exactly once) + a `golden_s2s_relay` boot golden (bidirectional relay through the real binary). Each slice is unit‑tested + boot‑golden + proptest‑fuzzed, and — where a pure oracle entry point exists — differentially pinned against `ircd-common`. | Per‑slice: leveva boots and serves the slice; leveva golden snapshot + proptest green; the `leveva-integration` differential agrees with `ircd-common` on the shared skeleton with divergences asserted. Across the eventual matrix: registration, channels, WHO/WHOIS/WHOX, OPER/STATS, server burst, netsplit, rehash, restart; iauth end‑to‑end. |
9494| **P12 — Retire the mechanical port; `leveva` is the product** | delete `ircd-common`/`ircd-rs` + C‑era `iauth-rs` scaffolding; workspace = `leveva` | Once `leveva` is at parity (P11 green across the matrix), run the differential suite a final time, then **delete the mechanical port** (`ircd-common`, `ircd-rs`) and fold/replace `iauth-rs` with leveva‑native auth. The `leveva-integration` oracle tests retire with their oracle; the load‑bearing characterizations carry forward as self‑contained `leveva` tests. Workspace becomes just `leveva` (+ any sub‑crates it wants). This is the literal end of the strangler — same lifecycle the C tree had at P8. | Final differential run green; `ircd-common`/`ircd-rs` deleted; `cargo test -p leveva` carries the behavioral guarantees forward; minimal `unsafe`; clean clippy. |
95959696---
···21212121convention; `CONNECT` added to `COMMANDS`). **Gate:** `cargo test -p leveva` 719 passed /
212221220 failed; clippy `-p leveva --all-targets` clean; `cargo fmt -p leveva --check` clean;
21232123`cargo build --workspace` 0 warnings.
21242124+21252125+## Slice 33 — steady-state S2S command relay (2026-06-09)
21262126+21272127+**Goal (user-requested).** Relay commands between linked servers in steady state (after the
21282128+burst/`EOB`): messages, channel joins/parts, mode changes, topic changes, kicks, nick
21292129+changes, quits — both **outbound** (a local client's action → linked peers) and **inbound**
21302130+(a peer's relayed line → local clients + onward to other peers). Slices 31/32 built the link
21312131+protocol (handshake + burst + SQUIT) and outbound `CONNECT`, but the serve loop held the peer
21322132+mailbox open without ever routing to it in steady state, and no local handler could reach a
21332133+peer. This slice closes both gaps.
21342134+21352135+**The spine.**
21362136+- [`s2s::PeerLinks`](../../leveva/src/s2s/links.rs) — a process-shared `BTreeMap<Sid,
21372137+ UnboundedSender<Envelope>>` of the **directly-linked** peers, on `ServerContext.peers`.
21382138+ `link`/`unlink` on establishment/teardown; `route(sid, wire)` to one uplink;
21392139+ `broadcast(except, wire)` to all peers except an origin (split-horizon). Registered in
21402140+ `main::serve_linked_peer` once the handshake completes, unlinked on drop.
21412141+- `ServerContext::is_local_uid(uid)` — a UID is local iff its 4-char SID prefix is ours. The
21422142+ load-bearing fan-out rule: a channel's membership mixes local + remote UIDs, so client-form
21432143+ fan-out (`deliver_uid`) must reach **only local members** — a remote member is reached once
21442144+ by the peer relay, never by a per-member mailbox push (which would send a client-form line
21452145+ to the peer socket, wrong direction + wrong format). Every broadcasting handler
21462146+ (message/join/part/topic/kick/mode/nick + `Session::release`) gained the `&& is_local_uid`
21472147+ filter alongside its relay call.
21482148+- `serve_linked_peer` became a `select!` loop (socket read ∥ mailbox recv), so frames other
21492149+ connections route to the peer are written to its socket in steady state — the burst now
21502150+ rides the same mailbox path and is drained by the same loop.
21512151+21522152+**Outbound** — [`s2s::relay`](../../leveva/src/s2s/relay.rs) `local_*` builders emit the
21532153+UID-prefixed S2S form to every peer (`broadcast`, no origin): `local_join`, `local_part`,
21542154+`local_topic`, `local_kick` (victim by UID), `local_quit`, `local_nick`,
21552155+`local_channel_message`, `local_channel_mode` (renders `+o`/`+v` params as **UIDs** via
21562156+`render_modes_uid`), and `route_message_to_remote` (a PRIVMSG/NOTICE to a remote nick → routed
21572157+to that user's uplink only). Each early-returns when no peers are linked, so a single-server
21582158+boot pays nothing. `message.rs` now resolves a nick target to local-deliver / remote-route /
21592159+`401` instead of the old `deliver_nick`-or-`401`.
21602160+21612161+**Inbound** — `s2s::dispatch` gained the post-burst relay verbs `JOIN/PART/PRIVMSG/NOTICE/
21622162+TOPIC/KICK/NICK/QUIT` (`NJOIN` stays burst-only; a *single* live join is `JOIN`). Each
21632163+`inbound_*` applies to local state, fans the **client form** (`:nick!user@host VERB …`,
21642164+source resolved from the network mirror) out to local members or the target local nick, and
21652165+onward-relays the original UID-form line to every *other* peer (split-horizon). `MODE` keeps
21662166+applying via `s2s::mode` and, once `!link.bursting`, also fans out + onward-relays via
21672167+`after_mode` (translating UID member-params back to display nicks for local clients). New
21682168+helpers: `Channels::set_topic_as_server` (no membership/`+t` gate) and
21692169+`squit::quit_one_remote_user` (single-user teardown, reusing the SQUIT path).
21702170+21712171+**Divergences (documented).** Single-uplink topology — the onward-relay is spine-correct but,
21722172+with one peer, a no-op; per-server membership routing + multi-peer loop avoidance are out of
21732173+scope. Steady-state joins relay as `:<uid> JOIN <chan>` (clean form). No channel-TS
21742174+arbitration. No client numerics to a server (an unappliable relayed line is dropped silently).
21752175+21762176+**Verification.** No pure-oracle entry point (every C path drives `sendto_*`/global buffers)
21772177+→ no `leveva-integration` differential. Verified by:
21782178+- **Unit** — `s2s::links` (5: route/unlink/broadcast/split-horizon/relink, with inverses) +
21792179+ `s2s::relay` (14: every outbound builder + every inbound verb, with inverses — join↔part,
21802180+ nick rename, quit teardown, member-UID→nick translation, malformed-line drops).
21812181+- **Proptest** — `relay_proptest` (3: outbound conservation = one frame per peer; inbound
21822182+ panic-freedom + split-horizon = origin never echoed; inbound forwarding to other peers
21832183+ exactly once).
21842184+- **Boot golden** — `golden_s2s_relay`: `alice` (local) + `rover` (remote behind a scripted
21852185+ peer) share `#hub`; alice's PRIVMSG/TOPIC reach the peer UID-prefixed, rover's PRIVMSG/PART
21862186+ reach alice in client form.
21872187+21882188+Gate: `cargo build -p leveva` 0 warnings; the touched lib (612) + `golden_s2s` +
21892189+`golden_s2s_relay` + `relay_proptest` + `s2s_proptest` + `s2s_pseudoserver` + the affected
21902190+local goldens/proptests all green.
···11+# P11 slice 33 — steady-state S2S command relay
22+33+**Goal.** Relay commands between linked servers in steady state (after the burst/EOB):
44+messages (PRIVMSG/NOTICE), channel joins/parts, channel mode changes, topic changes,
55+kicks, nick changes, and quits — both **outbound** (a local client's action → linked
66+peers) and **inbound** (a peer's relayed line → local clients + onward to other peers).
77+88+Slices 31/32 built the link protocol (handshake + burst + SQUIT) and outbound `CONNECT`.
99+The serve loop held the peer mailbox open but **never routed to it** in steady state, and
1010+no local handler could reach a peer. This slice closes that gap.
1111+1212+## The spine (prerequisite)
1313+1414+- `s2s::PeerLinks` — a process-shared `BTreeMap<Sid, UnboundedSender<Envelope>>` of the
1515+ **directly-linked** peers, on `ServerContext.peers`. `link`/`unlink` on
1616+ establishment/teardown; `route(sid, wire)` to one uplink; `broadcast(except, wire)` to
1717+ all peers except the origin (split-horizon).
1818+- `ServerContext::is_local_uid(uid)` — a UID is local iff its 4-char SID prefix is ours.
1919+ Channel fan-out must deliver the **client form** only to *local* members; remote members
2020+ are reached once, by relaying the **S2S form** to their uplink — never by pushing a
2121+ client-form line onto the peer mailbox per remote member.
2222+- `serve_linked_peer` becomes a `select!` loop (socket read ∥ mailbox recv), so frames
2323+ other connections route to the peer are written to its socket in steady state.
2424+2525+## Outbound (local client → peers) — `s2s::relay` builders
2626+2727+Each relays a UID-prefixed line to all peers (`except = None`): `local_join`, `local_part`,
2828+`local_message` (channel → broadcast; remote nick → route to uplink), `local_topic`,
2929+`local_channel_mode` (renders `+o/+v` params as **UIDs**), `local_nick`, `local_quit`.
3030+Wired into the local handlers (message/join/part/mode/topic/kick/nick) + `Session::release`.
3131+3232+## Inbound (peer → local + onward) — `s2s::dispatch` post-EOB
3333+3434+`JOIN/PART/PRIVMSG/NOTICE/TOPIC/KICK/NICK/QUIT` prefixed by a remote UID: apply to local
3535+state, fan out re-prefixed with the source `nick!user@host` to **local** members (or the
3636+target local nick), and onward-relay the original line to peers `except` the origin. `MODE`
3737+keeps applying via `s2s::mode` and, post-burst, also fans out + onward-relays.
3838+3939+## Divergences (documented)
4040+4141+- Steady-state single joins relay as `:UID JOIN <chan>` (clean form); `NJOIN` stays
4242+ burst-only. No channel-TS arbitration. No per-server membership tracking for relay — a
4343+ channel message is broadcast to **every** peer (correct for single-uplink leveva).
4444+- No pure-oracle entry point (every path drives `sendto_*`/global buffers in the C oracle)
4545+ → no `leveva-integration` differential; verified by unit + proptest + boot golden.
4646+4747+## Test gate
4848+4949+Unit tests (links + relay, with inverses) + a `relay_proptest` (panic-freedom, split-horizon,
5050+per-peer conservation) + a `golden_s2s_relay` boot golden exercising both directions, all
5151+green; `cargo build -p leveva` 0 warnings.