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 / iauth-subsumed-into-leveva.md
3.0 kB

name: iauth-subsumed-into-leveva description: P11 slice 39+ — iauth is being subsumed into leveva as a native async leveva-iauth subcrate (no separate process / pipe protocol); locked design + the async-auth seam metadata: node_type: memory type: project originSessionId: fed77443-f8dd-486e-8e50-9635086fb05f#

User decision (2026-06-09): do NOT spawn iauth-rs as a child over a socketpair. The separate-process + <id> <category> <info> pipe protocol existed only to protect the C ircd's single-threaded select/poll loop from blocking DNS/ident/probe I/O — that motivation is gone under leveva's tokio. So iauth is subsumed into leveva as native async auth. This is PLAN.md's P12 ("fold/replace iauth-rs with leveva-native auth") pulled forward; the socketpair-spawn interim step is skipped as throwaway.

Locked structure: a new leveva-iauth workspace crate, idiomatic rewrite (not a verbatim copy of iauth-rs). Clean Module async trait + ModuleCtx/ModuleOutcome with no C baggage (no IauthMessage/ModuleStats/InstanceConfig). hickory-dns is the chosen DNS crate — lands with the dnsbl slice (ident needs no DNS). iauth-rs stays in the workspace as a differential oracle (it was the C-iauth port) and is deleted at P12.

Surprise: iauth-rs is already tokio-async (PLAN.md said mio — wrong); its 5 modules are async fn run. So modules transplant near-verbatim; only the IPC transport (protocol.rs/ircd_link.rs/engine.rs handle_ircd) is dropped.

The async seam (leveva::session::Session::feed is SYNC, ident is async): ident only needs IP+ports (known at accept), runs concurrently with the NICK/USER handshake. When registration completes AND ident is enabled, the session stashes pending_complete and emits nothing; serve_client pumps the spawned ident task into session.resolve_auth(verdict), which runs finalize (kline gate + UID + nick claim + welcome) with the resolved username. Either arrival order works (verdict stashed in the session). Ident not configured → finalize synchronously as today (so every existing golden is unchanged — minimal.kdl has no ident). Username rule: ident-confirmed(UNIX)→bare name; ident-attempted-no-answer→~name; ident-disabled→trust supplied (no ~). Seam at [[leveva-next-step-s2s-completeness]] follow-on. The remaining iauth modules (dnsbl/socks/webproxy/pipe — all deny-only) are later slices and DO need the 465/kill-from-auth path. DONE: dnsbl (slice 40), socks+webproxy (slice 41) — all via the 465 gate; only pipe (subprocess spawn) remains. Pattern for each rewrite: drop the C cache + STATS counters (tokio makes probes .await; cache never changed the deny decision), require the deny-opting config flag at parse (reject; no probe-only mode), keep the pure verdict fns byte-identical to the iauth-rs oracle for a leveva-integration differential. See [[leveva-next-step-s2s-completeness]].