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]].