Proof of concept mechanical port of ircnet/ircd to Rust as part of a bit about C being insecure for network services
0

Configure Feed

Select the types of activity you want to include in your feed.

ircd.rs / docs / claude-memory / leveva-next-step-s2s-completeness.md
54 kB

name: leveva-next-step-s2s-completeness description: "leveva P11: S2S + auth + full client surface DONE; the parity matrix toward P12 is UNDERWAY — slices 45 (channel-lifecycle inverses) + 46 (burst/netsplit teardown inverses) + 47 (WHO/WHOIS/WHOX) + 48 (CAP framework, IRCv3) + 49 (PASS + connection-password gate) + 50 (STATS k/K active k-lines) + 51 (IRCv3 multi-prefix) + 52 (live two-node link integration: two real leveva subprocesses, real CONNECT, PRIVMSG/TOPIC/MODE relay) + 53 (WebSocket transport via axum at /socket + the +W umode/WHOIS 320, first transport slice) DONE; remaining matrix areas = more registration edge cases (full I-line enforcement / class assignment) / more STATS letters (l/L/p/P/t/T/f/F/a/? — all need per-conn or live infra leveva lacks) / (LINKS/MAP network-mirror enumeration DONE in slice 88 — true tree, not flattened) / rehash-restart / iauth end-to-end / more IRCv3 caps. IRCv3 ACCOUNT track COMPLETE: slice 139 (account identity via ENCAP * SU → WHOIS 330 / WHO %a) + 140 (account-notify) + 141 (account-tag @account msg tag) + 142 (extended-join) DONE. The four originally-named matrix areas are ALL done now (45/46/47 + registration 49/99 + STATS 50/109) — that 'ask user' note is STALE. Slice 143 (2026-06-13) DONE = hunt_server target-resolution FUZZING (model-lockstep query_routing_proptest over VERSION/TIME/ADMIN/INFO/LUSERS/USERS/MOTD/STATS forward path incl. slice-110 remote-forward + own-name precedence + netsplit-revert; summon_proptest 411/445/402 + golden_summon; STATS idx-1 forward unit) — a confirm-and-lock parity slice, no bug. §4 fuzzing gaps now essentially closed; nearly every command has unit+golden+proptest. NEXT toward P12 = ask user: remaining IRCv3 caps (SASL the keystone — auth INTO the slice-139 account SoT; or utf8only/labeled-response/batch) vs the P12 deletion itself (delete ircd-common/ircd-rs once §7 def-of-done met)" metadata: node_type: memory type: project originSessionId: 90eead6b-cbcf-4bb0-bbbd-d299622cd3a6#

The leveva (P11) work is S2S-completeness — per the user (2026-06-09). After slice 34 (channel modes), the remaining in-scope msgtab rows are the server-to-server ones, so build those rather than more client/oper commands.

Slice 35 DONE (2026-06-09): ERROR/ENCAP/SDIE — the relay/notice cluster, in leveva/src/s2s/forward.rs (inbound_encap/inbound_sdie/inbound_error), wired into s2s::dispatch. ENCAP+SDIE onward-relay verbatim (msg.to_wire()) split-horizon via PeerLinks::broadcast; ERROR is absorbed (eprintln!). Key finding: m_encap/m_sdie are IRCnet placeholders (git 7c3931d1; m_sdie only sendto_serv_v(...); return 0;, no s_die()) → leveva's SDIE is a pure relay that does not kill the process; wiring it to control would be a divergence. golden_s2s_forward guards that regression.

Slice 36 DONE (2026-06-09): UMODE — remote user-mode propagation, in leveva/src/s2s/umode.rs. Outbound relay::local_umode emits :<uid> UMODE <nick> <diff> (masked to SEND_UMODES = all umodes except +O locop = oracle 61) from the slice-14 local umode handler; inbound umode::inbound_umode (reached by the UMODE verb AND a user-target MODE — dispatch MODE arm guards on is_s2s_channel) applies the masked diff to the RemoteUser::umodes mirror + registry record, then onward-relays split-horizon. No client fan-out (user modes aren't broadcast). Key divergence: the oracle emits MODE <nick> :<diff> (send_umode_out) while accepting UMODE; leveva standardises on emitting UMODE (the row) but accepts both forms on input. Tests: 9 unit + 3-property s2s_umode_proptest + golden_s2s_umode.

Slice 37 DONE (2026-06-09): multi-hop SERVER-behind-peer introduction — the SMASK prerequisite, built first by user decision (asked, chose "multi-hop SERVER first, then SMASK"). New leveva/src/s2s/server.rs handle_server parses :<announcing_sid> SERVER <name> <hopcount> <sid> <version> :<info> (the shape build_burst already emits), mirrors the server into Network with uplink = the DIRECT peer's Sid (NOT the announcing prefix — load-bearing: routing uplink_ofPeerLinks::route keys on directly-linked peers, and squit_subtree tears it down with the link), onward-relays verbatim split-horizon. Absorbs (not link-drop) on bad/colliding SID. Wired "SERVER" => into s2s::dispatch. Tests: 7 unit + 3-prop s2s_server_proptest + golden_s2s_server.

Slice 38 DONE (2026-06-09): SMASK — masked-server introduction, the LAST server-sourced msgtab row. New leveva/src/s2s/smask.rs handle_server parses :<announcing_sid> SMASK <sid> <version> (oracle m_smask, s_serv.c:533), the masked cousin of slice-37 SERVER: the masked server inherits the announcer's name (oracle serv->namebuf = sptr->name) + hopcount + 1, description = literal "Masked Server"; announcer resolved from the line prefix SID via Network (unknown announcer → dropped, SMASK-specific). uplink = the DIRECT peer (same load-bearing reason as slice 37). Version is required-present but NOT mirrored (RemoteServer has no version field, like SERVER). Absorbs (not link-drop) on bad/colliding SID. Wired "SMASK" => into s2s::dispatch. Tests: 8 unit + 3-prop s2s_smask_proptest + golden_s2s_smask.

✅ S2S-COMPLETENESS REACHED — every server-sourced msgtab row is now handled. No S2S row remains unported.

Slice 39 DONE (2026-06-09): native in-process authentication + ident — see [[iauth-subsumed-into-leveva]]. User chose to subsume iauth into leveva (not spawn a child over a socketpair). New leveva-iauth crate (Module trait + ModuleCtx/ModuleOutcome + AuthPipeline) + the ident (RFC 1413) module; the iauth block configures auth in-process (ident flag + timeout, child-config-path field dropped); ident runs concurrently with the NICK/USER handshake and folds into registration via the deferred-finalize seam (Session::pending_complete/resolve_auth, sync feed / async ident). ~user rule in registration::resolve_username. Restored a leveva-integration differential (first since wdhms2sec): leveva-iauth parser vs iauth-rs (now the auth oracle until P12).

Slice 40 DONE (2026-06-09): dnsbl subsumed into leveva-iauth + the 465 auth-deny gate — the FIRST denying module. leveva-iauth/src/dnsbl.rs (idiomatic rewrite of the faithful iauth-rs dnsbl): reverse IP→<rev>.<zone>, resolve via hickory-dns (the locked choice, hickory-resolver = 0.26, lazy shared TokioResolver) behind an injectable Resolver; deny iff paranoid || (reject && 127.0.0.x). Dropped the C hostlog cache (redundant under tokio) + use config order not C's reversed host_list (documented). Pipeline BoxArc (AuthPipeline: Vec<Arc<dyn Module>>, modules built once in from_config, dnsbl-first). AuthConfig gains modules + any() (keeps ident: bool for the ~ rule); defer decision keys on ctx.auth.any() so a dnsbl-only config still defers. The 465 gate: finalize_registration renders verdict.deny as 465+ERROR :Closing Link (reason default Denied access) — same uniform refusal as the K-line gate (C just exit_clients). Config: iauth { dnsbl { servers …; reject; paranoid; reason … } }, parse-time validated. Differential: leveva reversed_name vs iauth_rs::modules::dnsbl::build_name (made pub). Fuzz = proptest (stable toolchain → no cargo-fuzz/L3). golden_dnsbl boots an .invalid (NXDOMAIN) zone.

Slice 41 DONE (2026-06-09): socks + webproxy open-proxy probes subsumed into leveva-iauth — the two open-proxy denying modules (leveva-iauth/src/{socks,webproxy}.rs), idiomatic rewrites of the faithful mod_socks.c/mod_webproxy.c ports; deny an open proxy via the slice-40 465 gate. Same divergences as dnsbl: cache + STATS dropped, reject+port required at config time (no probe-only mode; megaparanoid ⇒ paranoid+bofh). socks collapses the SOCKS4→5 reconnect + careful SOCKS5b stages into one async flow; webproxy's careful mode keys on the server's own 020 banner (passed to WebProxy::new as a config-time constant, so ModuleCtx stays minimal — itsip/itsport/ourip/ourport only, NO ircd_name). Pure build_query/decide/resolve kept byte-identical to the oracle → leveva-integration proxy_differential (the oracle's pure fns + Ver/Raw/ProxyState/OPT_* made pub). build_auth_modules(iauth, ircd_name) pushes denying modules before ident. Tests: +20 lib unit (49 total) + proxy_proptest (6) + proxy_differential (6) + 7 config + golden_socks boot.

Slice 42 DONE (2026-06-09): prometheus-backed metrics + STATS m/STATS z — see [[leveva-prometheus-metrics]]. Replaced the leveva istat-analog (server::Counters, hand-rolled atomics) with a per-ServerContext prometheus::Registry in new leveva/src/metrics.rs (user instruction: "replace the istat counters with prometheus metrics"; user agreed the per-server — not global default — registry is justified for parallel test isolation). dispatch records each command (name+wire-bytes); implemented the two stubbed counter letters: STATS m212 per recorded command (sorted), STATS z → four 249 live-count debug lines. Still stubbed (no leveva state): l/L (per-link), p/P, t/T, f/F, k/K, a, ?.

Slice 44 DONE (2026-06-09): pipe external-program auth module — port of mod_pipe.c (oracle iauth-rs/src/modules/pipe.rs) into leveva-iauth/src/pipe.rs, the LAST denying module → dnsbl/socks/webproxy/pipe set complete. Spawns the configured program with itsip+itsport appended as separate argv entries (no shell — pure build_argv carries that security claim), reads one stdout byte via pure classify: N→Deny (465 gate), Y→allow (NoOpinion), else abstain. Security hardening over C: explicit argv, config-only command, stdin(null)+kill_on_drop. Config: iauth { pipe { program "…"; reason "…" } }, program required (no reject flag — pipe has no probe-only mode, unlike socks/webproxy). Order: after webproxy, before ident; any() auto-defers. Tests: 11 unit + 3 config + pipe_proptest (4) + golden_pipe boot. No differential (no pure oracle verdict fn). Finding: a write-then-exec temp-script arg test was ETXTBSY-flaky under parallel cargo test (sibling Command fork inherits the open write fd) → replaced by pure build_argv unit tests.

Slice 45 DONE (2026-06-09): channel-lifecycle PARITY — the first parity-matrix slice (user chose "Channel lifecycle parity"). leveva already had per-command happy-path channel coverage + the forward gates (475/474/473); slice 45 closes the inverses the command-cluster-port skill demands: -b unban / -i reopen / -k un-key, +l free-slot, INVITE one-shot re-gate (join→part→re-join 473 again), deop revokes MODE/KICK authority (482), kick→clean-rejoin (no stale @), recreate-after-last-part is fresh (331 + 324 +), QUIT removes membership everywhere. No bug found — parity confirmed. Boot-golden golden_channel_lifecycle.rs (7 tests) + gate-model fuzz channel_lifecycle_proptest.rs (2 props, 400 cases — first proptest to set modes and gate a JOIN). No leveva-integration differential (oracle channel fns are private/impure — match_differential still pins the glob matcher). Plan: docs/superpowers/plans/2026-06-09-p11-slice45-channel-lifecycle-parity.md.

Slice 46 DONE (2026-06-09): burst/netsplit PARITY — user chose "Burst / netsplit parity". The s2s/squit.rs::squit_subtree teardown core was already richly unit-tested (headline QUIT fan-out, multi-hop, NJOIN ghost sweep, idempotency); slice 46 added the unpinned inverses: two new squit unit tests (squit_leaf_keeps_the_peer_and_its_users = partial-subtree teardown, peer survives; reburst_after_split_is_clean = freed nick re-claimable + single fresh membership + no double-deliver), a NEW model-based fuzz s2s_netsplit_proptest.rs (random server forest behind a peer → SQUIT a random node → a pure uplink-fixpoint model predicts the doomed set, survivors, and exact QUIT multiset; 200 cases + a panic-freedom prop on handle_squit), and a NEW boot golden golden_s2s_netsplit.rs (3 tests: QUIT fan-out to a local co-member on drop, explicit SQUIT <leaf> spares the peer, clean re-burst). No bug — parity confirmed. Finding: NJOIN members are UIDs not nicks (:1ZZZ NJOIN #hub :1ZZZAAAAA); a first cut used the nick → the remote user silently never joined and the QUIT fan-out never fired (the exact happy-path-looks-fine trap the slice exists to catch). Plan: docs/superpowers/plans/2026-06-09-p11-slice46-burst-netsplit-parity.md.

Slice 47 DONE (2026-06-09): WHO / WHOIS / WHOX parity (FULL — a feature build, not just locking inverses). Implemented WHOX from scratch (leveva/src/command/who.rs): faithful parse_who_arg (legacy o opers-only filter + %fields[,token], ≤3-char token), 354 RPL_WHOSPCRPL emitted field-by-field in the oracle's FIXED who_one order (t c u i h s n f d l a o S U r) — field set AND order independent of typed order. Single-server divergences match the oracle constants: %i=host (no DNS split), %l=0, %a=0, %o=n/a. Advertised WHOX in ISUPPORT. Coupled remote-field fix (real bug, since S2S landed after WHO/WHOIS): a server_view/whois_server helper resolves a remote user's own server-name/hopcount/SID from the Network mirror (ctx.net.server(sid_of_uid(uid))) instead of hardcoding us/0 — for 352, 354 %s/%S/%d, AND WHOIS 312; plus the * oper flag in the status. Tests: 19 who.rs unit + whois remote-312 + isupport WHOX; goldens golden_whox + the REQUIRED golden_s2s_who (remote user via a peer → all fields name peer.test/hop 1/SID 1ZZZ, + the drop inverse); whox_proptest (field-order model). golden_s2s/golden_registration snapshots updated for the corrected remote 312 + the WHOX 005 token. No leveva-integration differential (oracle who/whois are unsafe/global-buffer). Plan: docs/superpowers/plans/2026-06-09-p11-slice47-who-whois-whox-parity.md.

Slice 49 DONE (2026-06-09): registration edge cases — PASS + the connection-password gate. PASS was entirely absent and allow{ password } blocks were parsed but never consulted. New pure registration::connection_password_ok(allows,user,host,supplied) (first matching rule decides; wrong+fallthrough defers; no matching passworded rule → default-allow — password gate only, NOT general I-line enforcement); Registration stores PASS (last-wins, bare PASS→461), carried via RegStep::Complete{pass}PendingComplete so it survives the CAP/auth deferred-finalize. session::finalize_registration runs the gate after username resolution, before the K-line gate → 464+ERROR close on mismatch. Post-reg PASS462. Bounded/deferred: I-line enforcement, class/restricted/kline_exempt assignment, CIDR allow masks, PASS→iauth forwarding. Tests: +9 registration unit / +7 session unit / golden_pass (3) / pass_proptest (3). See [[leveva-ircv3-track]] for the parallel IRCv3 track (slice 48).

Slice 50 DONE (2026-06-10): STATS completion — STATS k/K active k-lines (216). User chose "STATS completion". STATS k now reports the live KlineStore (the oracle tkconf temporary-ban list) via a pure kline_report(server,nick,entries,now) core in command/stats.rs — one 216 RPL_STATSKLINE per not-yet-expired ban, store order, ttl clamped non-negative. leveva models only temporary k-lines (laid by TKLINE; no KLINE command, no kconf), so STATS K is recognized but always empty; both echo their letter in 219 (not *). Wire: :srv 216 nick k <host> <user> <ttl> :<reason> (leveva-native; divergences: no class field, reason as trailing). Bounded to k/K — the other state letters (l/L/P/f need per-conn traffic counters ClientRecord lacks; p/t/T/r/?/a/d/hub/etc. have no leveva state) stay *. Tests: +6 stats unit / golden_stats+1 (+216-ttl canonicalizer mask) / stats_proptest+1 (active-filter model). No differential (impure oracle). Plan: docs/superpowers/plans/2026-06-10-p11-slice50-stats-klines.md.

Slice 51 DONE (2026-06-10): IRCv3 multi-prefix (first behavior cap). User chose the IRCv3 area. NAMES (353) / WHO (352 + WHOX 354 %f) / WHOIS (319) show all of a member's status sigils (@+) when the requester negotiates multi-prefix, only the highest otherwise. Core = MemberStatus::prefixes(multi) (channel.rs); the cap snapshot rides on Registered.caps: cap::ClientCaps (set at finalize, re-synced post-reg). leveva-native (no CAP in the oracle → no differential). See [[leveva-ircv3-track]] for the add-a-behavior-cap pattern. Tests: +6 lib unit / golden_multi_prefix / multi_prefix_proptest (+ the deliberate golden_cap LS-token snapshot updates). Plan: docs/superpowers/plans/2026-06-10-p11-slice51-multi-prefix.md.

Slice 52 DONE (2026-06-10): live two-node link integration (real subprocess relay). User-requested: the FIRST test that boots two real leveva binaries and links them (every prior S2S test drives a hand-coded Peer into the inbound accept side only). Closes the outbound-dial coverage gap: command::connectlink::requestmain::dial_servers2s::build_link_greeting, and a real leveva accepting a link from another real leveva. New harness helpers (tests/harness/mod.rs, additive): boot_two (boots both binaries under ONE held port lock — two boot_fixture calls deadlock on separate flock(LOCK_EX)), Client::connect_port, Client::wait_visible(nick) (polls WHOIS for 311 as the link-up barrier). Cross-linked fixtures node_a.kdl/node_b.kdl (symmetric send/accept passwords, oper has connect priv). tests/integration_two_node.rs: alice opers+CONNECTs on A, bob on B, both JOIN #live, assert PRIVMSG/TOPIC/MODE relay BOTH directions (B→A driven before +m moderation lands). Fuzz tests/link_greeting_proptest.rs (3 props): greeting roundtrips on matching passwords with conserved identity / mismatch always rejects / well-formed + panic-free under truncation. Parity gap FOUND (not fixed, separate slice): m_links still reports only me — unfit as a link-up probe, hence the WHOIS barrier. Plan: docs/superpowers/plans/2026-06-10-p11-slice52-live-two-node-link.md.

Slice 53 DONE (2026-06-10): WebSocket transport (IRCv3 websocket) — the first TRANSPORT slice. Browser clients connect over WebSocket served by axum at /socket; a nested websocket{} block on a listen{} port. Adds the leveva-native +W umode + WHOIS 320 (propagated network-wide). Full detail in [[leveva-ircv3-track]] (pure leveva::websocket helpers + leveva::websocket::server axum glue; tls.rs promoted to leveva::tls; end-to-end tokio-tungstenite golden). Also added HELP USER_MODES/CHANNEL_MODES topic pages ([[help-files-per-command]]).

P11 VERDICT (2026-06-10, survey): NEARLY COMPLETE. Every RFC 2812 / oracle msgtab client command is implemented and the Numeric enum is an effectively complete replies[] transcription. The one genuine client-command behavioral gap was PRIVMSG/NOTICE mask targetsCLOSED by slice 57 (operator-only $$<servermask>/$#<hostmask> + 413/414, command/mask.rs + command/message.rs + s2s/relay.rs; the 407/MAXPENALTY cap + canonize dedup follow-up is CLOSED by slice 87canonicalize_targets de-dups the comma list case-insensitively and the delivery loop caps at 5 distinct recipients, emitting 407 ERR_TOOMANYTARGETS over-cap (PRIVMSG) / silence (NOTICE); only the nick!user@host/user%host "Duplicate recipients" 407 stays out of scope as leveva has no such targets. No genuine client-command behavioral gap remains.). Remaining minor items: SUMMON→421 vs 445, no standalone UMODE verb (folded into MODE), STATS m doesn't count pre-reg commands. Out-of-scope verbs correctly 421. The big forward surface is the IRCv3 track ([[leveva-ircv3-track]]). Standing testing plan + native-boot capability: [[ircd-common-native-boot]] (docs/superpowers/specs/2026-06-10-leveva-testing-plan.md).

Slices 54–57 DONE (2026-06-10): 54 = eager auto-reop (+R), 55 = IRCv3 bot mode (+B), 56 = IRCv3 message-tags FOUNDATION (tags on the core Message type + the message-tags cap; the prerequisite that unblocks bot-tag/server-time/msgid/redaction/oper-tag) — both detailed in [[leveva-ircv3-track]]; 57 = PRIVMSG/NOTICE mask targets ($$/$# operator broadcast + 413/414, the last genuine client-command gap — see the VERDICT above). NEXT (clearest highest-leverage) = slice 58: message-tags BEHAVIOR (TAGMSG + client-only +tag relay with per-recipient cap gating + S2S + 417), which lights up the deferred bot tag and makes server-time/msgid thin follow-ons. Otherwise still ask-the-user among the matrix areas below.

Slice 65 DONE (2026-06-10): REHASH live-reloads the MOTD — the first rehash/restart matrix slice (user chose "rehash/restart"). DIE/RESTART/REHASH already existed; the gap was that REHASH only validated config and applied nothing live. Faithful to IRCnet rehash()read_motd(MPATH): an oper edits the MOTD file, REHASHes, and the next MOTD/welcome burst serves the new text. Mechanism — live MOTD in the control plane (ZERO ServerContext-literal churn, matching how control.rs routes DIE/RESTART): new MotdStore (ArcSwapOption + AtomicBool initialized, unit-tested on a fresh instance like ServerControl) + static LIVE_MOTD/MOTD_PATH in control.rs; main records the resolved --motd path + seeds LIVE_MOTD at boot; read sites (command/mod.rs MOTD + session.rs welcome burst) use the live store when initialized else fall back to ctx.motd (keeps the 44 ServerContext { motd: None } literals + every unit test untouched — the global stays uninit under cargo test); rehash.rs calls control::reload_motd() after the config validation. Divergences: MOTD-only hot-apply (opers/allows/classes still boot-immutable — each its own future slice); removed file → 422; bare \r survives (faithful, str::lines only strips \r\n). Tests: control units (incl. inverse seed(None) clears) + golden_rehash_motd (v1→rewrite→REHASH→v2→ truncate→REHASH→422, via additive harness boot_minimal_with_motd) + motd_reload_proptest (400 cases: load_motd_lines total/framed/fixed-point + reply-shape model). Plan: docs/superpowers/plans/2026-06-10-p11-slice65-rehash-motd.md.

Slice 82 DONE (2026-06-10): I-line (allow-block) admission enforcement + class assignment — the slice-49 registration deferral. registration::authorize_connection (returns Accepted(Admission{class,restricted,kline_exempt})/BadPassword/NoAuthorization) replaces the slice-49 password-only connection_password_ok: configured allow blocks are now a real admission gate (no matching I-line → 465 :No authorization line for your host); empty allows stays open (backward-compat — every bare ServerContext test relies on it; all 25 in-tree allow blocks use *@* so nothing breaks). The matched block's attributes take effect at session::finalize_registration: restricted+r, kline-exempt skips the K-line gate, and the class re-arms the keepalive ping-freq (the hand-off main.rs:156-159 anticipated; reads boot ctx.stats_conf.classes, no live-retune — slice-81 stance). Still deferred from the slice-49 list: CIDR allow masks (/24 — glob-only matching), per-class max-links/sendq/ per-host CIDR connection caps (no live connection-accounting infra), and require_ident/no_resolve/xline_exempt (carried in the model, not yet acted on). Tests: registration units (the 6 slice-49 tests rewritten to the 3-way verdict) + session units (465/restricted/kline-exempt/class, each with its inverse) + golden_iline.rs + iline_proptest.rs (vs an independent model). Plan: docs/superpowers/plans/2026-06-10-p11-slice82-iline-enforcement.md.

Slice 83 DONE (2026-06-10): REHASH live-reloads the allow (I-line) blocks. User chose "rehash → allows/listeners". Extends the slice-81 ConfStore (which hot-reloaded operator+class) to also carry the allow blocks, so REHASH hot-applies the slice-82 admission gate: ConfStore gains allows: ArcSwapOption<Vec<Allow>>; config_conf now returns the ConfBlocks type alias (operators, classes, allows); live_allows() global. Read sites prefer the live store when seeded else fall back to boot ctx.stats_conf.allows (the slice-81 live-or-ctx pattern): session::finalize_registration's authorize_connection gate AND STATS i. An oper edits an I-line on disk, REHASHes, the next connection is admitted/refused (465) per the edited rules — no restart. Listeners DEFERRED (documented divergence — live socket-rebind needs accept-task management leveva lacks; its own future slice); links/admin/ options/iauth unchanged. Finding: the no-MOTD welcome burst ends at 422, never 376 — the golden uses 001 RPL_WELCOME as the admit sentinel (the slice-81 golden silently eats a 5s read-timeout/register on the missing 376). Tests: control units (incl. inverse seed(.., empty) clears) + golden_rehash_iline.rs + extended rehash_conf_proptest.rs (3-tuple + allow-host model). Plan: docs/superpowers/plans/2026-06-10-p11-slice83-rehash-allows.md.

Slice 88 DONE (2026-06-11): LINKS / MAP network enumeration — true-to-oracle tree. Closed the parity gap slice 52 flagged (m_links/m_map reported only me despite the Network mirror tracking the whole topology since slices 31–87). User directive: no flattening — render the genuine multi-level tree. The crux: RemoteServer.uplink is the routing direct-peer (NOT the tree parent), so added a display-only RemoteServer.parent: Sid (the true tree parent = the announcing SERVER/SMASK line prefix), populated at the 3 real introduction sites (handshake.rs = our SID; server.rs = the :<announcing_sid> prefix; smask.rs = announcer) + ~20 test fixtures; routing/squit_subtree still key on uplink. New command/topology.rs: topology(ctx) enumerator (me first, remotes in Sid order, per-server user counts, orphan-reparents-to-root) + a pure map_lines() tree renderer faithful to dump_map's |-/ \- 4-char connector cells (visited-set cycle guard → every server emitted exactly once).links()shows each server's true upstream;map()nests behind-peer servers under their parent. **Single-server output byte-identical → zero snapshot churn.** Divergences:MAP sremote version*(unmirrored), Sid-sorted order, orphan→root. leveva- native (no differential —m_links/m_mapare impure). Tests: 22 lib unit (inverse SQUIT/mask /orphan/cycle) +golden_s2s_links_map.rs(real Peer bursts a behind-server → me→peer→leaf tree) +links_map_proptest.rs(400 cases: random forest, model-checked upstream + every- server-once + panic-freedom). Plan:docs/superpowers/plans/2026-06-11-p11-slice88-links-map-network-enumeration.md. (Note: this is the LINKS network-mirror enumerationgap named in this memory's description — now CLOSED.) *Pre-existing unrelated failure observed:*privmsg_proptest::delivery_is_well_formed_and_conserved` fails from a persisted regression seed (reproduces on clean master, untouched by slice 88).

Slice 89 DONE (2026-06-11): CIDR allow (I-line) host masks. User chose "CIDR allow masks" from the matrix. Closes the slice-49/82/83 deferral: allow block host masks now accept CIDR notation (*@10.0.0.0/24, *@2001:db8::/32) alongside globs. New pure leveva::cidr (parse_cidr/contains/cidr_match) is the single crate-wide CIDR matcher; matching::allow_host_matches splits the mask on the last @, glob-matches the user component and CIDR-or-glob-matches the host component (CIDR path only for addr/prefix → every existing *@*/glob mask byte-unchanged); authorize_connection admits/refuses (465) by network membership of the peer IP. Divergences: family must match (no v4-mapped-v6), malformed CIDR degrades to a non-matching glob, CIDR only matches IP hosts. Also consolidated websocket::proxy_trusted's private cidr_contains/prefix_match onto the shared module (−~35 lines). leveva-native (no differential). Gate: cidr/matching/registration units + golden_iline_cidr + cidr_proptest (400 cases vs an independent bit-shift model). Still deferred from the slice-49/82 list: per-class connection caps (max-links/sendq/per-host CIDR caps — no live connection-accounting infra) + require_ident/no_resolve/xline_exempt (carried in the model, not acted on). Plan: docs/superpowers/plans/2026-06-11-p11-slice89-cidr-allow-masks.md.

Slice 90 DONE (2026-06-11): IRCv3 setname. User chose "SETNAME" from the matrix, then gave docs/rfcs/ircv3/setname.md. The SETNAME :<realname> command + setname cap — a registered client (any, not oper-gated) changes its own realname (GECOS) live, the close cousin of slice-71 chghost but simpler: no non-cap reconnect fallback (spec forbids sending SETNAME to non-cap clients; a realname change needs no client refresh). New command/setname.rs

  • s2s/setname.rs (local_setname ENCAP broadcast / apply_encap_setname inbound / shared notify_co_members); cap::SETNAME + ClientCaps::setname; ident::REALLEN=50 + realname_valid; Registry::set_realname; isupport NAMELEN=50 (spec MUST); help/SETNAME.md. Validity invalid → FAIL SETNAME INVALID_REALNAME (spec-enabled stdreply, sent regardless of cap). Self-echo iff issuer has the cap; co-members notified only if they hold setname (+ extended-monitor watchers — the extended-monitor doc's "leveva has no setname" is now stale, only account-notify remains out of scope). leveva-native ENCAP * SETNAME carrier → no differential (oracle has no SETNAME). Tests: 18 lib unit + golden_setname + setname_proptest (3 props). Snapshot churn: setname on CAP LS + NAMELEN=50 in 005 (re-chunked, MONITOR→next line). Plan: docs/superpowers/plans/2026-06-11-p11-slice90-setname.md.

Slice 91 DONE (2026-06-11): REHASH hot-reloads the admin + connect (link) + options blocks. User chose "rehash links/admin/options blocks" from the matrix. Extends the slice-81/83 ConfStore (the ConfBlocks tuple type alias became a struct + 3 new fields: admin: ArcSwapOption<Admin>, links: ArcSwapOption<Vec<Connect>>, default_user_modes: ArcSwapOption<u32>) so REHASH hot-applies three more re-read blocks: the admin contact (read by ADMIN 256–259), the connect (link) blocks (read by STATS c 213 + the CONNECT target lookup find_link), and options { default-user-modes } (applied fresh at each registration finalize → the slice-72 connect MODE notice). main seeds the struct at boot; new global readers live_admin()/live_links()/live_default_user_modes(); read sites are live-or-ctx (the slice-81/83 STATS idiom, so unit tests + boot-seeded goldens see no churn). Deferred (documented): default-channel-modes (held by the live Channels table, stamped internally by channel.rs::join — needs retuning a runtime structure), the auto-connect dial loop (keeps the boot link set — only CONNECT/STATS c read live) + listeners (live socket-rebind, slice-83 stance), and the other options fields (auto-connect/split-min-*/connection-accept — no clean reloadable read site). leveva-native (no differential). Tests: control units (incl. inverse empty-seed clears) + golden_rehash_blocks (v1→rewrite admin/connect/dumodes→REHASH→v2→inverse back) + extended rehash_conf_proptest (admin/links/dumodes tracked in lockstep). Golden pitfall: the connect MODE notice arrives in the same TCP chunk as the welcome burst → read straight through to the MODE sentinel, don't consume 001 first. Plan: docs/superpowers/plans/2026-06-11-p11-slice91-rehash-admin-options-links.md. Rehash matrix now: opers/classes (81), allows (83), MOTD (65), admin/connect/default-user-modes (91); still boot-immutable: listeners, the dial loop, links/iauth config, default-channel-modes.

Slices 100–115 (2026-06-11) closed the testing-plan §3 differential matrix AND the §4 fuzzing-gaps list. The native cross-daemon skeleton differential now covers every command surface (100–111, 111 = the last undiffed surface, S2S inbound live-relay), and slices 112–115 backfilled the named §4 proptest gaps: 112 = nick-collision, 113 = post-registration gating (found+fixed a real CR-framing bug), 114 = VERSION, 115 = iauth registration-seam (native leveva — iauth_seam_proptest, the resolve_authfinalize_registration deferred-finalize gate fuzzed over random verdict × arrival order; headline = byte-identical output regardless of order). Slice 116 (2026-06-11) then closed the last non-nightly §4 item — the prometheus-output golden — by turning it into a real feature: a metrics { port; bind? } config block stands up an axum GET /metrics endpoint serving Counters::encode_text() (see [[leveva-prometheus-metrics]]), pinned by golden_metrics.rs (boot + raw-HTTP scrape) + metrics_endpoint_proptest.rs (3 props). The §4 "concrete fuzzing gaps" list is now fully closed. Slice 117 (2026-06-12) then closed the §4 lower-priority "features fuzzed but never boot-tested" tail for the client keepalive plane (heartbeat + ping): golden_keepalive.rs drives the real binary's keepalive over a live socket (client PING→PONG, server-PINGs-idle-client, ping-timeout ERROR + close, and the active-client-never-dropped inverse — the client twin of the existing golden_s2s_keepalive), plus a Session-layer keepalive_proptest pinning the wire+state contract the pure-core heartbeat_proptest never reached. Slice 118 (2026-06-12) landed the §4 "cargo-fuzz tier over Message::parse + the full Session::feed byte path" as its verifiable structured analogue (the libfuzzer tier needs a nightly toolchain → stays optional/P12): feed_framing_proptest.rs (5 props — never-panic/well-formed output, chunk-boundary reassembly invariance, the 512/8191 edges) + golden_recvq.rs, and found+fixed a real unbounded-self.buf DoS — the raw-TCP serve loop fed 4 KB chunks into an uncapped accumulation buffer (a client that never sent CR/LF grew it without bound), now bounded at MAX_INBOUND_LINE (tag budget + body = 8703) with a 417 + skip-to-terminator resync, faithful in spirit to dbuf_getmsg. The §4 concrete fuzzing gaps are now EXHAUSTED. Only the optional nightly cargo-fuzz tier (needs nightly; marked P12) remains. P11 is at its §7 definition-of-done; next is the deferred infra items (per-class connection caps, listener live-rebind, the auto-connect dial loop, default-channel-modes rehash — each needs live-accounting/accept-task infra leveva lacks) or P12 proper (delete ircd-common/ircd-rs). Ask the user.

Next P11 work — the parity matrix toward P12 is underway (45 = channels, 46 = burst/netsplit, 47 = WHO/WHOIS/WHOX, 48 = CAP/IRCv3, 49 = PASS/connection-password, 50 = STATS k/K, 51 = IRCv3 multi-prefix, 52 = live two-node link integration, 53 = WebSocket transport + +W, 54 = auto-reop, 55 = bot mode, 56 = message-tags foundation, 65 = rehash → live MOTD reload, 81 = rehash → live opers/classes, 83 = rehash → live allows/I-lines, 88 = LINKS/MAP network enumeration). Remaining matrix areas: rehash beyond opers/classes/allows (slices 81+83 hot-reload operator + class + allow blocks via a ConfStore global in control.rs — the slice-65 MotdStore pattern, read preferentially over the immutable boot ServerContext by OPER/STATS o/STATS y/STATS i + the registration I-line gate; still boot-immutable: listeners — needs live socket-rebind/accept-task infra — + links/admin/options/iauth, each its own slice), more registration edge cases (I-line enforcement + class assignment DONE slice 82, CIDR masks DONE slice 89; remaining = per-class connection caps + require_ident/no_resolve/xline_exempt — need live connection-accounting infra), the other STATS letters (l/L/p/P/t/T/f/F/a/? — each blocked on per-connection traffic counters or live infra leveva doesn't track yet; a deliberate non-trivial dependency, not a quick add), rehash/restart, iauth end-to-end, and more IRCv3 caps (userhost-in-names, message-tags, server-time, … — each its own slice per [[leveva-ircv3-track]]). Each is an independent slice with no single obvious order → ask the user which area next (as with slices 45–51). The end is P12: retire ircd-common/ircd-rs, leveva is the product.

Slice 136 DONE (2026-06-13): per-class connection caps — the long-deferred registration item (punted at 49/82/89). Built the live connection-accounting infra: new leveva::connlimit (pure check_admission decision + the per-ServerContext ConnLimits store with atomic try_admit/release + ConnTicket) + cidr::network_base. Enforces a matched class's max-links / max-local-per-host / max-local-per-user-host / cidr caps at session::finalize_registration (after the nick try_claim, before the class ping re-arm): a full cap undoes the claim and refuses with ERROR :Closing Link: <host> (<reason>) (no numeric — class-full isn't a ban); Session::release frees the ticket (Session.conn_ticket). 0 = unlimited; caps read the boot class set (slice-81 stance); ticket captures the pre-cloak host. Local clients only — server links/opers/remote users don't traverse finalize, so the network-wide max_global_* caps stay deferred (need to count the Network mirror) + require_ident/no_resolve/xline_exempt still carried-not-acted. leveva-native (no differential). Gate: connlimit/cidr/session units + golden_conn_limits + conn_limit_proptest (pure truth-table + stateful model fuzz). Remaining matrix: the other STATS letters (l/L/p/P/t/T/f/F — per-conn traffic counters), listener live-rebind, the auto-connect dial loop / default-channel-modes rehash, account/SASL infra (the last S2S-notify tag), or P12 proper. Ask the user.

Slice 137 DONE (2026-06-13): listener live-rebind on REHASH (user-chosen from the matrix above). Closes the last "deferred — needs live socket-rebind infra" note in control::rehash_config. New leveva::listeners module, split like control.rs: a pure plan(current, desired) -> RebindPlan { open, close, keep } over a normalized ListenerSpec (keyed (bind, port); same-key-identical → keep so connections survive, same-key-changed → close+open rebind, dedup-first-wins) + LiveListeners registry of accept-task AbortHandles (process-global for the server, fresh-instance for tests) + an install_rebinder/rehash seam so the binary injects the bind+spawn closure. main.rs factored per-listener bind+spawn into open_listener (sync std bind → from_std, callable from both async boot and the sync rehash closure), records each at boot, installs rebind_listeners (re-read config → plan → close removed → bind added, best-effort). command/rehash.rs calls listeners::rehash() beside the conf/MOTD reloads. Divergences: a rehash-added TLS port loads its cert but isn't added to the live cert watcher (later cert edit needs another REHASH); delayed listeners stay out of the desired set. leveva-native. Gate: 12 listeners units + golden_rehash_listeners (real binary: live add + remove + unchanged-survives) + listener_rebind_proptest. Remaining matrix: the STATS traffic letters (l/L/p/P/t/T/f/F), the auto-connect dial loop / default-channel-modes rehash, account/SASL infra (the last S2S-notify tag), or P12 proper. Ask the user.

Slice 138 DONE (2026-06-13): WHOIS shows the target's user modes (379 RPL_WHOISMODES) (WHO/WHOIS sweep; user asked "make WHOIS show the user modes for a user"). WHOIS <nick> emits :<srv> 379 <requester> <tnick> :is using modes +<modes> (rendered via the existing UserMode::render), placed after the 276 certfp block / before the 317/318 tail. Privacy-gated: only the target themselves (client.uid == rec.uid) or an operator (client.modes & (Oper|LocalOp)) sees it — a non-oper WHOISing another never sees their modes. leveva-native (IRCnet 2.11 has no 379); the WHOIS skeleton differential's self-WHOIS now documents the spliced-379 divergence (whois_core_agrees_modulo_leveva_379). Gate: whois units (self/oper-visible + non-oper-hidden inverse) + golden_whois_modes + whois_modes_proptest (render over the full UserMode bit space + privacy gate). Prep commit: leveva-integration native_oracle ServerContext was missing the slice-136 conn_limits field (pre-existing build break) → fixed first. Remaining matrix: the STATS traffic letters (l/L/p/P/t/T/f/F), the auto-connect dial loop / default-channel-modes rehash, account/SASL infra (the last S2S-notify tag), or P12 proper. Ask the user.

Slice 139 DONE (2026-06-13): services account identity via ENCAP * SU <uid> :<account> + WHOIS 330 / WHO %a — opened the account-notify / SASL matrix area. User directive: accounts are SERVER-DRIVEN ("service accounts should be set by a remote server broadcasting an ENCAP * SU <uid> :<account-name> command") — NOT client SASL (a service logs a client in and SUs it; client-side SASL is a later, larger slice). leveva keeps no account DB of its own. New ClientRecord.account: Option<String> + Registry::set_account (the read SoT — UNICK already mirrors remote users into the registry; no RemoteUser.account field — nothing reads it, deferred to burst-re-assertion to dodge 36 construction-site churn). New leveva/src/s2s/su.rs apply_encap_su (mirrors setname.rs): keyed on the <uid> PARAM (a service sets another user's login, unlike SETNAME/UMODE source-keyed), present+valid trailing = login / absent+empty = logout / invalid (account_valid: empty/SP/CR/LF/leading-:) = no-op; wired a Some("SU") arm into forward::inbound_encap (verbatim split-horizon relay intact). 330 RPL_WHOISACCOUNT (leveva-native de-facto charybdis code) after 313/before 320, not privacy-gated; WHO/WHOX %a now renders the account or 0. leveva-native (no differential). Gate: su/registry/forward/whois/ who units + golden_s2s_account + account_proptest. Follow-ons (the account behavior caps, framework-vs-behavior rule, see [[leveva-ircv3-track]]): account-notify (push :nick!u@h ACCOUNT <name>/ACCOUNT * to co-members on a SU-driven change), account-tag (@account on messages), extended-join (account in JOIN), the RemoteUser.account mirror + burst re-assertion, and client-side SASL. Plan: docs/superpowers/plans/2026-06-13-p11-slice139-account-identity-su.md.

Slice 144 DONE (2026-06-13): drop the IRCnet channel types &/!/+# only (user directive: "Remove &, !, and +-channels. They are an IRCNet specific thing not needed in Leveva"). CHANTYPES="#"; ident::validate_channel accepts only a # first char (others → BadPrefix). With +/! gone the modeless machinery they were the only users of is deleted: channel.rs::use_modes() removed, a channel creator is always a chanop, and the now-unreachable KickGate::NoChanModes / ApplyOutcome::NoChanModes variants + their 477 handler arms (kick.rs/mode.rs) are gone (Numeric::ErrNochanmodes stays in the table — it's a wire-code registry). The three S2S channel-sigil helpers (s2s/{mode,mod,relay}.rs) narrowed #&+!#; relay::local_join dropped its dead &-channel non-propagation skip. Fuzzing: new tests/chantypes_proptest.rs (512 cases) — #-bodies parse+round-trip; inverse, any &/!/+ name is BadPrefix regardless of body; arbitrary bytes never panic. Docs: rewrote help/CHANNEL_TYPES.md + fixed KICK/REOP_LIST help + 8 ISUPPORT golden snapshots. Plan: docs/superpowers/plans/2026-06-13-p11-slice144-drop-irc-net-channel-types.md. Gate: cargo test -p leveva green / clippy clean / workspace 0 warnings.

Slice 145 DONE (2026-06-13): per-connection traffic counters → STATS l/L (211) + t/T (249). User chose "STATS traffic letters" (the infrastructure-heavy matrix area)

  • "add fuzzing". Built the counter infra that was the long-standing blocker: new leveva/src/connstats.rs ConnStats (4 AtomicU64 + connected_at, lock-free), an Arc<ConnStats> shared between a connection's serve loop (the writer — counts every socket read/write via a count_sent closure) and the registry Entry (so STATS l on another task can read it). Registry::try_claim_with_stats + link_info() (the live finalize site passes the session's Arc; try_claim keeps its sig with a default to avoid churning ~8 call sites). STATS l/L → one 211 RPL_STATSLINKINFO per local client (pure link_report; sendq always 0 — unbounded mpsc; K=bytes/1024; local clients only); t/T → two leveva-native 249 :Traffic … lines from cumulative Counters traffic IntCounters (pure traffic_report). Still deferred (NOT traffic-blocked — different state): p/P (opers-online/listeners), f/F (fd table), a/?. Tests: connstats/registry/stats units
  • golden_stats_traffic + stats_traffic_proptest (5 props fuzzing the accumulator + render over arbitrary counters) + canonicalizer 211/249-Traffic masks + golden_metrics traffic-value mask. Plan: docs/superpowers/plans/2026-06-13-p11-slice145-conn-traffic-stats.md.

STATUS UPDATE: P12 IS DONE (2026-06-13) — the strangler is finished, ircd-common/ ircd-rs/iauth-rs/leveva-integration are DELETED. The description's "toward P12 / delete ircd-common" framing is now STALE — leveva is the standalone product; future work is plain feature slices in the P11 cadence (unit + boot-golden + proptest), NOT migration.

Slice 146 DONE (2026-06-13): the remaining STATS letters ?/P/a. ?249 per directly-linked server (<name> <S>S <U>U, multi-hop counts via a sid→uplink map); P (uppercase ONLY — p stays *) → 211 per live listener; a/A239 RPL_STATSIAUTH per configured auth module. The STATS surface is now complete; p/f/F + unmodeled config-block letters stay * as documented divergences. stats_topology_proptest fuzzes the ? counts over arbitrary spanning trees + golden_stats::stats_topology_queries.

Slice 147 DONE (2026-06-13): per-connection SendQ accounting + Max-SendQ backpressure kill (user chose it from a 4-way fork; "add fuzzing"). The unbounded mailbox is now bounded by a per-class sendq ceiling (else DEFAULT_SENDQ = 1 MiB) — ConnStats (the slice-145 Arc) gained sendq/sendq_peak/sendq_dead + sendq_admit/force_add/drain; the registry's 4 client-delivery sites account on enqueue, serve_client drains on dequeue; over-ceiling → one terminal ERROR :Closing Link: <host> (Max SendQ exceeded) eject then drop the rest (KILL/SAVE bypass). try_claim (remote/test, no draining loop) passes sendq_max = 0 = account-only. STATS l renders the live depth (was hardcoded 0). The write-side twin of the slice-118 recvq cap. Finding: every test fixture's cosmetic sendq 1000 was unenforceably tiny — bumped all to the shipped example's 512000 (surfaced+fixed a golden_s2s_mass_burst_drop overrun). Unit + sendq_proptest (3 model-lockstep props); no boot-golden (kill is socket-timing-dependent). Prep commit: slice-146's ?/P/a were never added to stats_proptest::is_recognized → latent RNG-flaky; fixed first.

Slice 148 DONE (2026-06-13): SendQ follow-ons — bounded socket writes + server-link SendQ accounting (user chose "SendQ follow-ons" from a 4-way fork; "add fuzzing"). The two items slice 147 deferred. Part A — bounded writes: new leveva::netio (WRITE_TIMEOUT = 60 s + write_bounded/flush_bounded, tokio::time::timeout over write_all/flush); both serve loops (serve_client, serve_linked_peer) route every steady-state write/flush through them, so a fully-wedged socket (peer not reading → write_all parks the whole select! task → the ping branch is unreachable) is now force-closed at the deadline instead of leaking the fd/task. Part B — server-link SendQ: PeerLink gained stats: Arc<ConnStats> (in PeerLink::new, sig unchanged); LinkEntry gained stats/sendq_max + a private enqueue (slice-147 admit/overflow/drop policy, overflow → one ERROR :Closing Link: <sid> (Max SendQ exceeded) eject → squit_subtree); the 4 PeerLinks send methods (route/route_tag_only/broadcast/ broadcast_tag_only) route through it, accounting the egress (post tag-strip) length; PeerLinks::link → account-only wrapper, new link_with_stats is the live path (main.rs:serve_linked_peer passes link.stats.clone() + DEFAULT_SERVER_SENDQ = 8 MiB, drains per dequeued frame). Divergences: ceiling is the constant not the connect-block class (per-connect resolution = follow-on; first-class pick would wrongly give a server the 512 KB users ceiling); registry-routed remote-user frames carry their own account-only stats (drain is saturating, so harmless). Tests: 3 netio units + netio_proptest (2); 5 links units + s2s_sendq_proptest (2 model-lockstep). Added tokio test-util dev-dep for start_paused. No boot-golden (timing-dependent), as slice 147. Plan: docs/superpowers/plans/2026-06-13-p11-slice148-sendq-followons.md.

Slice 154 DONE (2026-06-14): the last STATS state letters f/F + p — STATS SURFACE COMPLETE. f/F = the oracle report_fd fd/connection table: pure command::stats::fd_report → one 211 per registered connection over a new richer registry::connections() -> Vec<ConnInfo> (uid/nick/user/host/last_activity, sibling of link_info), oper-gated on OperPrivilege::Trace (the oracle's ACL_TRACE+MyConnect; denied → no body + 219 *, NOT 481). Renders only the tokio-available analogues — the connection UID stands in for the raw fd, local-listener/remote socket addresses dropped-not-faked, idle from last_activity. p (lowercase; uppercase P stays listeners) = recognized-but-always-empty like K (leveva has no aCPing/calculate_preference preference-pinging → never any 246). The gate rides a new stats_fd_ok: bool param threaded through the shared command::query_answer/stats (local dispatch passes has_privilege(Trace); the S2S hunt_server query path passes false — a remote requester is never a local-fd oper). leveva-native (no differential). Fuzz: fd_stats_proptest (256 cases: trace-oper body count + idle≥0 + the inverse non-oper-always-* gate). Only the unmodeled config-block letters (b/h/q/s/v/d/r/x) now stay * — there are no more STATS state letters to add.

Slice 155 DONE (2026-06-14): IRCv3 labeled-response (+ the batch framing dependency) — echo a command's inbound @label back on its direct reply (0→ACK, 1→tagged-in-place, ≥2→labeled-response BATCH). Pure leveva::labeled::wrap over the command::dispatch reply vector at the session seam; both labeled-response+batch advertised (gate = labeled_response, batch wired-but-not-read so a future batch slice adds more types). Direct-reply path only (async mailbox echo/fan-out out of scope). leveva-native. See [[leveva-ircv3-track]] for the full entry. Pitfall: I hallucinated the spec doc — the user had the real ircv3.net text and replaced it; implementation was already correct against it (incl. the PONG→ACK + WHOIS-batch examples).

NEXT = ask the user among: SASL (the IRCv3 keystone — client auth INTO the slice-139 account SoT), a dedicated batch slice (more batch types — the framing + batch cap now exist from slice 155), further SendQ hardening (a dedicated writer task / per-connect server sendq resolution / accounting the registry-routed remote-user sub-path on the peer's ceiling), or other IRCv3 caps. STATS is fully done (slice 154); labeled-response done (155) — do NOT re-offer them. Excluded set unchanged (SET/CLOSE/SUMMON/SERVICE).

This builds on the slice 31–34 S2S foundation: the leveva/src/s2s/ modtree (handshake/burst/unick/njoin/mode/save/eob/squit/relay/links) and the Network mirror in ServerContext. Each S2S slice follows the established P11 cadence — unit + boot golden + proptest; no leveva-integration differential (the oracle S2S handlers are impure, global-buffer, so there's no pure entry point to pin against), as with every recent slice.

Excluded — do NOT pick these: SET ([[set-not-required-leveva]]), CLOSE ([[close-not-required-leveva]]), SUMMON ([[summon-utmp-not-required]]), SERVICE/SQUERY/SERVLIST ([[leveva-service-is-client-services]]); and the oper-debug stats rows HAZH/DNS are low-value C-internal-stats — ask first.

Related: [[leveva-pivot-p9-retired]] (its stale "next concrete step" = the registration machine is long done), [[leveva-command-folder]], [[leveva-s2s-port-based-routing]].