leveva/src/command/sajoin.rs
leveva/src/command/sanick.rs
leveva/src/command/sapart.rs
===
===== leveva/src/command/samode.rs =====
(missing)
===== leveva/src/command/sajoin.rs =====
use crate::command::*;
use crate::UserMode;

/// `SAJOIN <nick> <channel>{,<channel>}` — leveva-native operator command: forcibly join a
/// **local** user to one or more channels, bypassing every join restriction (`+i` invite-only,
/// `+k` key, `+l` limit, `+b` ban, `+O` oper-only). The channel companion to
/// [`SAMODE`](crate::command::mode::samode) / [`SANICK`](crate::command::sanick::sanick).
///
/// - Not an IRC operator → `481 ERR_NOPRIVILEGES` (mirrors `KILL`).
/// - Missing target or channel → `461`; a malformed channel name → `403` (to the oper).
/// - Target nick not registered → `401`.
/// - The target is not on this server (a remote/mirrored user) → a server `NOTICE` to the
///   oper; leveva does not yet propagate a forced join across a link (documented scope).
/// - Success → the join runs through the **same** machinery as a client `JOIN`
///   ([`force_join`](crate::command::join::force_join)): the channel's other members get
///   `:nick!user@host JOIN #chan`, the linked network gets the `:<uid> JOIN`, and the forced
///   user's own connection receives its `JOIN` echo + topic + NAMES burst on its mailbox. The
///   oper receives no numeric on success (like `KILL`) — only the `403`/`461`/`401`/`481`
///   error replies come back to it. Joining a channel the user is already on is a silent
///   no-op.
pub(crate) fn sajoin(client: &Registered, msg: &Message, ctx: &ServerContext) -> Vec<Message> {
    if client.modes & (UserMode::Oper.bit() | UserMode::LocalOp.bit()) == 0 {
        return vec![no_privileges(ctx, &client.nick)];
    }
    let target = msg
        .params()
        .first()
        .map(String::as_str)
        .filter(|s| !s.is_empty());
    let chans = msg
        .params()
        .get(1)
        .map(String::as_str)
        .or(msg.trailing())
        .filter(|s| !s.is_empty());
    let (Some(target), Some(chans)) = (target, chans) else {
        return vec![need_more_params(ctx, &client.nick, "SAJOIN")];
    };

    let Some(uid) = ctx.registry.uid_of(target) else {
        return vec![no_such_nick(ctx, &client.nick, target)];
    };
    if !ctx.is_local_uid(&uid) {
        // Remote/mirrored target (P11 slice 183): validate each channel name for immediate oper
        // feedback (a malformed one → `403`, matching the local path), then route the valid set
        // to the target's home server, which runs its own `force_join` (whose `NJOIN` relay
        // carries the join network-wide). Success returns no numeric, like the local path / KILL.
        let mut replies = Vec::new();
        let valid: Vec<&str> = chans
            .split(',')
            .filter(|c| !c.is_empty())
            .filter(|c| {
                if ChanName::try_from(*c).is_err() {
                    replies.push(no_such_channel(ctx, &client.nick, c));
                    false
                } else {
                    true
                }
            })
            .collect();
        if !valid.is_empty() {
            crate::s2s::sajoin::propagate(ctx, &uid, &valid.join(","));
        }
        return replies;
    }
    let Some(rec) = ctx.registry.record_of(&uid) else {
        return vec![no_such_nick(ctx, &client.nick, target)]; // lost a race with a disconnect
    };
    let view = crate::command::join::registered_view(&rec);

    // Per channel: a bad name reports `403` to the oper; a good one force-joins the target
    // (the JOIN echo + NAMES land on the target's mailbox, the JOIN fans out to co-members).
    let mut replies = Vec::new();
    for chan in chans.split(',').filter(|c| !c.is_empty()) {
        if ChanName::try_from(chan).is_err() {
            replies.push(no_such_channel(ctx, &client.nick, chan));
            continue;
        }
        crate::command::join::force_join(ctx, &view, chan);
    }
    replies
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::command::testutil::*;

    /// An opered `alice` connection (the testutil fixture, plus `+o`).
    fn oper() -> Registered {
        let mut c = client();
        c.modes |= UserMode::Oper.bit();
        c
    }

    fn drive(ctx: &ServerContext, c: &Registered, line: &str) -> Vec<Message> {
        dispatch(&mut c.clone(), &Message::parse(line).unwrap(), ctx)
    }

    /// The gate (and its inverse): a non-operator's SAJOIN is `481` and joins nobody.
    #[test]
    fn sajoin_requires_oper() {
        let ctx = ctx();
        let _bob = claim_observed(&ctx, "bob");
        let r = drive(&ctx, &client(), "SAJOIN bob #rust");
        assert_eq!(codes(&r), &["481"]);
        assert!(
            !ctx.channels.is_member("#rust", &uid_for("bob")),
            "a gated SAJOIN joins nobody"
        );
    }

    /// Remote target (P11 slice 183): SAJOIN of a user on another server routes a server-sourced
    /// `ENCAP * SAJOIN <uid> <chans>` to the peer — no NOTICE, no numeric to the oper.
    #[test]
    fn sajoin_of_a_remote_user_routes_an_encap() {
        let ctx = ctx();
        let mut peer = link_observed_peer(&ctx);
        let (tx, _rx) = tokio::sync::mpsc::unbounded_channel();
        let rover = crate::ident::Uid::try_from("0XYZAAAAA").unwrap();
        ctx.registry
            .try_claim(&rover, "rover", "ru", "rh", "Rover", tx)
            .expect("fresh nick");

        let r = drive(&ctx, &oper(), "SAJOIN rover #a,#b");
        assert!(r.is_empty(), "no NOTICE, no numeric — routed across the link");
        let m = delivered(&mut peer);
        assert_eq!(m.command(), "ENCAP");
        assert_eq!(m.prefix(), Some("0ABC"));
        assert_eq!(m.params(), &["*", "SAJOIN", "0XYZAAAAA", "#a,#b"]);
    }

    /// Remote target with a malformed channel name: the bad name yields a `403` to the oper, and
    /// only the valid channels are routed onward (nothing is routed if none are valid).
    #[test]
    fn sajoin_of_a_remote_user_with_a_bad_channel_403s_and_routes_the_rest() {
        let ctx = ctx();
        let mut peer = link_observed_peer(&ctx);
        let (tx, _rx) = tokio::sync::mpsc::unbounded_channel();
        let rover = crate::ident::Uid::try_from("0XYZAAAAA").unwrap();
        ctx.registry
            .try_claim(&rover, "rover", "ru", "rh", "Rover", tx)
            .expect("fresh nick");

        let r = drive(&ctx, &oper(), "SAJOIN rover notachan,#good");
        assert_eq!(codes(&r), &["403"], "the bad channel name is reported to the oper");
        let m = delivered(&mut peer);
        assert_eq!(m.params(), &["*", "SAJOIN", "0XYZAAAAA", "#good"]);
        // Inverse: an all-bad channel set routes nothing.
        let r2 = drive(&ctx, &oper(), "SAJOIN rover alsobad");
        assert_eq!(codes(&r2), &["403"]);
        assert!(peer.try_recv().is_err(), "no valid channel → nothing routed");
    }

    /// Success: an oper forces a user into a channel; the target's mailbox gets its JOIN echo
    /// + NAMES, an existing member sees the JOIN, and membership is real.
    #[test]
    fn sajoin_forces_a_local_user_into_a_channel() {
        let ctx = ctx();
        let mut bob = claim_observed(&ctx, "bob");
        // carol already holds #rust (so there is a co-member to notify).
        let mut carol = claim_observed(&ctx, "carol");
        ctx.channels.join("#rust", &uid_for("carol"), 0);
        let r = drive(&ctx, &oper(), "SAJOIN bob #rust");
        assert!(r.is_empty(), "the oper gets no numeric on success");
        assert!(
            ctx.channels.is_member("#rust", &uid_for("bob")),
            "bob is now a member"
        );
        // bob's own mailbox: the JOIN echo (his mask) then the NAMES burst (353/366).
        let join = delivered(&mut bob);
        assert_eq!(join.command(), "JOIN");
        assert_eq!(join.prefix(), Some("bob!u@h"));
        assert_eq!(join.params(), &["#rust"]);
        let names: Vec<String> = std::iter::from_fn(|| bob.try_recv().ok())
            .filter_map(|e| match e {
                crate::registry::Envelope::Wire(b) => Some(
                    Message::parse(&String::from_utf8_lossy(&b))
                        .unwrap()
                        .command()
                        .to_string(),
                ),
                _ => None,
            })
            .collect();
        assert!(names.contains(&"353".to_string()) && names.contains(&"366".to_string()));
        // carol, the existing member, saw bob's JOIN.
        let m = delivered(&mut carol);
        assert_eq!(m.command(), "JOIN");
        assert_eq!(m.prefix(), Some("bob!u@h"));
        assert_eq!(m.params(), &["#rust"]);
    }

    /// The override is real: SAJOIN past `+i`/`+k`/`+l`/`+b` succeeds where a self-JOIN
    /// would be rejected — and the inverse, a normal JOIN by the same user, is refused.
    #[test]
    fn sajoin_overrides_invite_key_limit_ban() {
        let ctx = ctx();
        // carol owns #locked and seals it: +i, +k secret, +l 1 (full), +b *!*@h (bans bob).
        claim_and_join(&ctx, "carol", "#locked");
        let mut carol_cli = client();
        carol_cli.uid = uid_for("carol");
        carol_cli.nick = "carol".to_string();
        for line in [
            "MODE #locked +i",
            "MODE #locked +k secret",
            "MODE #locked +b *!*@h",
        ] {
            dispatch(&mut carol_cli, &Message::parse(line).unwrap(), &ctx);
        }
        let mut bob = claim_observed(&ctx, "bob"); // bob!u@h — matches the ban, has no invite/key
                                                   // Inverse boundary: bob's own JOIN is refused (invite-only fires first → 473).
        let self_join = drive(
            &ctx,
            &{
                let mut c = client();
                c.uid = uid_for("bob");
                c.nick = "bob".into();
                c.host = "h".into();
                c.user = "u".into();
                c
            },
            "JOIN #locked",
        );
        assert!(
            self_join.iter().all(|m| m.command() != "JOIN"),
            "a self-JOIN past +i is refused: {:?}",
            codes(&self_join)
        );
        assert!(!ctx.channels.is_member("#locked", &uid_for("bob")));
        // The override forces him in regardless.
        let r = drive(&ctx, &oper(), "SAJOIN bob #locked");
        assert!(r.is_empty());
        assert!(
            ctx.channels.is_member("#locked", &uid_for("bob")),
            "override beat +i/+k/+l/+b"
        );
        assert_eq!(delivered(&mut bob).command(), "JOIN");
    }

    /// Operand / lookup / name errors land on the oper, not the target.
    #[test]
    fn sajoin_operand_and_lookup_errors() {
        let ctx = ctx();
        let _bob = claim_observed(&ctx, "bob");
        assert_eq!(codes(&drive(&ctx, &oper(), "SAJOIN")), &["461"]);
        assert_eq!(codes(&drive(&ctx, &oper(), "SAJOIN bob")), &["461"]);
        assert_eq!(codes(&drive(&ctx, &oper(), "SAJOIN ghost #rust")), &["401"]);
        let r = drive(&ctx, &oper(), "SAJOIN bob notachannel");
        assert_eq!(codes(&r), &["403"]);
        assert!(!ctx.channels.is_member("notachannel", &uid_for("bob")));
    }

    /// Inverse / idempotence: SAJOIN onto a channel the user already holds is a silent
    /// no-op — no duplicate membership, nothing newly delivered about the join.
    #[test]
    fn sajoin_when_already_a_member_is_a_silent_noop() {
        let ctx = ctx();
        let mut bob = claim_observed(&ctx, "bob");
        ctx.channels.join("#rust", &uid_for("bob"), 0);
        let r = drive(&ctx, &oper(), "SAJOIN bob #rust");
        assert!(r.is_empty());
        assert!(ctx.channels.is_member("#rust", &uid_for("bob")));
        // Nothing delivered to bob for a join that did not happen.
        assert!(
            bob.try_recv().is_err(),
            "no echo for an already-member SAJOIN"
        );
    }
}
===== leveva/src/command/sapart.rs =====
use crate::command::*;
use crate::UserMode;

/// `SAPART <nick> <channel>{,<channel>} [:reason]` — leveva-native operator command: forcibly
/// part a **local** user from one or more channels. The leave companion to
/// [`SAJOIN`](crate::command::sajoin::sajoin), completing the SA* oper-override family
/// ([`SAMODE`](crate::command::mode::samode) / [`SANICK`](crate::command::sanick::sanick)).
///
/// - Not an IRC operator → `481 ERR_NOPRIVILEGES` (mirrors `KILL`).
/// - Missing target or channel → `461`.
/// - Target nick not registered → `401`.
/// - The target is not on this server (a remote/mirrored user) → a server `NOTICE` to the
///   oper; leveva does not propagate a forced part across a link (documented scope).
/// - Success → the part runs through the **same** machinery as a client `PART`
///   ([`force_part`](crate::command::part::force_part)): the channel's other members get
///   `:nick!user@host PART #chan [:reason]`, the linked network gets the `:<uid> PART`, and
///   the forced user's own connection receives its `PART` echo on its mailbox. A channel that
///   does not exist → `403`, or one the target is not on → `442` — both **to the oper**. The
///   oper receives no numeric on a successful part (like `KILL`). The leave is a transparent
///   `PART` line, indistinguishable from the user's own part.
pub(crate) fn sapart(client: &Registered, msg: &Message, ctx: &ServerContext) -> Vec<Message> {
    if client.modes & (UserMode::Oper.bit() | UserMode::LocalOp.bit()) == 0 {
        return vec![no_privileges(ctx, &client.nick)];
    }
    let target = msg
        .params()
        .first()
        .map(String::as_str)
        .filter(|s| !s.is_empty());
    let chans = msg
        .params()
        .get(1)
        .map(String::as_str)
        .filter(|s| !s.is_empty());
    let (Some(target), Some(chans)) = (target, chans) else {
        return vec![need_more_params(ctx, &client.nick, "SAPART")];
    };
    let reason = msg.trailing().filter(|s| !s.is_empty());

    let Some(uid) = ctx.registry.uid_of(target) else {
        return vec![no_such_nick(ctx, &client.nick, target)];
    };
    if !ctx.is_local_uid(&uid) {
        // Remote/mirrored target (P11 slice 183): route the forced part to the target's home
        // server, which runs its own `force_part` (whose `PART` relay carries it network-wide).
        // No channel-name pre-check (the local path has none either); the oper gets no `403`/
        // `442` for a remote target — a documented divergence. Success returns no numeric.
        crate::s2s::sapart::propagate(ctx, &uid, chans, reason);
        return Vec::new();
    }
    let Some(rec) = ctx.registry.record_of(&uid) else {
        return vec![no_such_nick(ctx, &client.nick, target)]; // lost a race with a disconnect
    };
    let view = crate::command::join::registered_view(&rec);

    // Per channel: force the target out; any `403`/`442` is addressed to the oper (the actor),
    // the `PART` echo lands on the target's own mailbox.
    let mut replies = Vec::new();
    for chan in chans.split(',').filter(|c| !c.is_empty()) {
        if let Some(err) = crate::command::part::force_part(ctx, &view, &client.nick, chan, reason)
        {
            replies.push(err);
        }
    }
    replies
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::command::testutil::*;

    /// An opered `alice` connection (the testutil fixture, plus `+o`).
    fn oper() -> Registered {
        let mut c = client();
        c.modes |= UserMode::Oper.bit();
        c
    }

    fn drive(ctx: &ServerContext, c: &Registered, line: &str) -> Vec<Message> {
        dispatch(&mut c.clone(), &Message::parse(line).unwrap(), ctx)
    }

    /// The gate (and its inverse): a non-operator's SAPART is `481` and parts nobody.
    #[test]
    fn sapart_requires_oper() {
        let ctx = ctx();
        let _bob = claim_observed(&ctx, "bob");
        ctx.channels.join("#rust", &uid_for("bob"), 0);
        let r = drive(&ctx, &client(), "SAPART bob #rust");
        assert_eq!(codes(&r), &["481"]);
        assert!(
            ctx.channels.is_member("#rust", &uid_for("bob")),
            "a gated SAPART parts nobody"
        );
    }

    /// Success: an oper forces a user out of a channel; the target's mailbox gets its `PART`
    /// echo, an existing member sees the `PART`, membership is gone, the oper gets no numeric.
    #[test]
    fn sapart_forces_a_local_user_out_of_a_channel() {
        let ctx = ctx();
        let mut bob = claim_observed(&ctx, "bob");
        let mut carol = claim_observed(&ctx, "carol");
        ctx.channels.join("#rust", &uid_for("bob"), 0);
        ctx.channels.join("#rust", &uid_for("carol"), 0);
        let r = drive(&ctx, &oper(), "SAPART bob #rust");
        assert!(r.is_empty(), "the oper gets no numeric on success");
        assert!(
            !ctx.channels.is_member("#rust", &uid_for("bob")),
            "bob is no longer a member"
        );
        // bob's own mailbox: his PART echo (his mask).
        let part = delivered(&mut bob);
        assert_eq!(part.command(), "PART");
        assert_eq!(part.prefix(), Some("bob!u@h"));
        assert_eq!(part.params(), &["#rust"]);
        // carol, the remaining member, saw bob's PART.
        let m = delivered(&mut carol);
        assert_eq!(m.command(), "PART");
        assert_eq!(m.prefix(), Some("bob!u@h"));
        assert_eq!(m.params(), &["#rust"]);
    }

    /// The reason rides through to the `PART` trailing.
    #[test]
    fn sapart_carries_the_reason() {
        let ctx = ctx();
        let mut bob = claim_observed(&ctx, "bob");
        ctx.channels.join("#rust", &uid_for("bob"), 0);
        let r = drive(&ctx, &oper(), "SAPART bob #rust :be gone");
        assert!(r.is_empty());
        let part = delivered(&mut bob);
        assert_eq!(part.command(), "PART");
        assert_eq!(part.trailing(), Some("be gone"));
    }

    /// Operand / lookup / membership errors land on the **oper**, not the target, and leave
    /// the target's other memberships intact.
    #[test]
    fn sapart_errors_land_on_the_oper() {
        let ctx = ctx();
        let mut bob = claim_observed(&ctx, "bob");
        ctx.channels.join("#rust", &uid_for("bob"), 0);
        assert_eq!(codes(&drive(&ctx, &oper(), "SAPART")), &["461"]);
        assert_eq!(codes(&drive(&ctx, &oper(), "SAPART bob")), &["461"]);
        assert_eq!(codes(&drive(&ctx, &oper(), "SAPART ghost #rust")), &["401"]);
        // A channel that does not exist → 403 to the oper.
        assert_eq!(codes(&drive(&ctx, &oper(), "SAPART bob #nope")), &["403"]);
        // bob is not on #other → 442 to the oper.
        ctx.channels.join("#other", &uid_for("carol"), 0);
        assert_eq!(codes(&drive(&ctx, &oper(), "SAPART bob #other")), &["442"]);
        // Inverse: every failed SAPART left bob on #rust, and delivered him nothing.
        assert!(ctx.channels.is_member("#rust", &uid_for("bob")));
        assert!(bob.try_recv().is_err(), "no PART for a failed SAPART");
    }

    /// A remote/mirrored target (P11 slice 183): the forced part is routed to the home server as
    /// `:<sid> ENCAP * SAPART <uid> <chans> [:reason]` — no `NOTICE`, no numeric. The remote
    /// target's mirrored membership is untouched locally (the home server's `PART` relay reconciles
    /// it). With no peer linked the routed broadcast is a silent no-op.
    #[test]
    fn sapart_remote_target_routes_to_the_home_server() {
        let ctx = ctx();
        // A remote user is one whose UID carries a foreign SID prefix (≠ the local 0ABC), so
        // `is_local_uid` is false; it is `try_claim`ed into the same registry with no drained
        // mailbox, exactly as an S2S burst mirrors one.
        let remote = crate::ident::Uid::try_from("0XYZAAAAA").unwrap();
        ctx.registry
            .try_claim(&remote, "zane", "u", "h", "real", mb())
            .expect("free remote nick");
        ctx.channels.join("#rust", &remote, 0);
        let r = drive(&ctx, &oper(), "SAPART zane #rust :bye");
        assert!(r.is_empty(), "remote SAPART returns no numeric/NOTICE");
        assert!(
            ctx.channels.is_member("#rust", &remote),
            "the home server (not us) reconciles the remote target's membership"
        );
    }

    /// Remote target with a peer linked (P11 slice 183): the forced part is routed as a
    /// server-sourced `ENCAP * SAPART <uid> <chans> :reason` to the home server.
    #[test]
    fn sapart_of_a_remote_user_routes_an_encap() {
        let ctx = ctx();
        let mut peer = link_observed_peer(&ctx);
        let (tx, _rx) = tokio::sync::mpsc::unbounded_channel();
        let rover = crate::ident::Uid::try_from("0XYZAAAAA").unwrap();
        ctx.registry
            .try_claim(&rover, "rover", "ru", "rh", "Rover", tx)
            .expect("fresh nick");

        let r = drive(&ctx, &oper(), "SAPART rover #a,#b :bye");
        assert!(r.is_empty(), "no NOTICE, no numeric — routed across the link");
        let m = delivered(&mut peer);
        assert_eq!(m.command(), "ENCAP");
        assert_eq!(m.prefix(), Some("0ABC"));
        assert_eq!(m.params(), &["*", "SAPART", "0XYZAAAAA", "#a,#b"]);
        assert_eq!(m.trailing(), Some("bye"));
    }

    /// Forcing the last member out deletes the channel (the force path drives the same
    /// delete-on-empty as `PART`).
    #[test]
    fn sapart_of_the_last_member_deletes_the_channel() {
        let ctx = ctx();
        let _bob = claim_observed(&ctx, "bob");
        ctx.channels.join("#solo", &uid_for("bob"), 0);
        assert_eq!(ctx.channels.len(), 1);
        let r = drive(&ctx, &oper(), "SAPART bob #solo");
        assert!(r.is_empty());
        assert_eq!(ctx.channels.len(), 0, "empty channel removed");
    }
}

#[cfg(test)]
mod proptests {
    use crate::command::testutil::*;
    use crate::command::*;
    use crate::registry::Envelope;
    use crate::UserMode;
    use proptest::prelude::*;

    const CHAN_POOL: usize = 6;

    /// An opered `alice` (the actor for SAPART).
    fn oper() -> Registered {
        let mut c = client();
        c.modes |= UserMode::Oper.bit();
        c
    }

    /// Build a world where `victim` holds exactly the `joined` pool channels, plus a co-member
    /// `mate` on each (so a part has someone to notify and the channel is not deleted by the
    /// victim's own leave). Returns the ctx, the victim's `Registered` (mask-identical to its
    /// registry record), and the victim's mailbox receiver.
    fn world(
        joined: &std::collections::BTreeSet<usize>,
    ) -> (
        std::sync::Arc<ServerContext>,
        Registered,
        tokio::sync::mpsc::UnboundedReceiver<Envelope>,
    ) {
        let ctx = ctx();
        let vrx = claim_observed(&ctx, "victim");
        let _mate = claim_observed(&ctx, "mate");
        for &i in joined {
            let chan = format!("#c{i}");
            ctx.channels.join(&chan, &uid_for("victim"), 0);
            ctx.channels.join(&chan, &uid_for("mate"), 0);
        }
        let rec = ctx.registry.record_of(&uid_for("victim")).unwrap();
        let view = crate::command::join::registered_view(&rec);
        (ctx, view, vrx)
    }

    /// Collect the `PART`-command lines (prefix + channel) from a slice of returned replies.
    fn part_lines(ms: &[Message]) -> Vec<(Option<String>, Vec<String>)> {
        ms.iter()
            .filter(|m| m.command() == "PART")
            .map(|m| {
                (
                    m.prefix().map(str::to_string),
                    m.params().iter().map(|p| p.to_string()).collect(),
                )
            })
            .collect()
    }

    /// Drain a mailbox into the same `PART`-line shape as [`part_lines`].
    fn mailbox_part_lines(
        rx: &mut tokio::sync::mpsc::UnboundedReceiver<Envelope>,
    ) -> Vec<(Option<String>, Vec<String>)> {
        let mut out = Vec::new();
        while let Ok(Envelope::Wire(b)) = rx.try_recv() {
            let m = Message::parse(&String::from_utf8_lossy(&b)).unwrap();
            if m.command() == "PART" {
                out.push((
                    m.prefix().map(str::to_string),
                    m.params().iter().map(|p| p.to_string()).collect(),
                ));
            }
        }
        out
    }

    proptest! {
        #![proptest_config(ProptestConfig::with_cases(256))]

        /// SAPART by an oper leaves the network in the identical state as the target PARTing
        /// those same channels itself — same residual membership across every pool channel,
        /// same delete-on-empty, same `PART` lines on the victim's connection — differing only
        /// in who issues it and where the replies are routed. And a SAPART from a channel the
        /// target is not on changes nothing. Never panics.
        #[test]
        fn sapart_equals_the_targets_own_part(
            joined in prop::collection::vec(0usize..CHAN_POOL, 0..8),
            parted in prop::collection::vec(0usize..CHAN_POOL, 0..8),
        ) {
            let joined: std::collections::BTreeSet<usize> = joined.into_iter().collect();
            let line = parted
                .iter()
                .map(|i| format!("#c{i}"))
                .collect::<Vec<_>>()
                .join(",");
            if line.is_empty() {
                return Ok(()); // a bare PART/SAPART is a 461 in both worlds — nothing to compare
            }

            // World A: the victim PARTs the subset itself (echoes return to it).
            let (ctx_a, victim, mut vrx_a) = world(&joined);
            let a_replies = dispatch(
                &mut victim.clone(),
                &Message::parse(&format!("PART {line} :bye")).unwrap(),
                &ctx_a,
            );

            // World B: an oper SAPARTs the victim from the same subset (echoes hit its mailbox).
            let (ctx_b, _victim_b, mut vrx_b) = world(&joined);
            let _b_replies = dispatch(
                &mut oper(),
                &Message::parse(&format!("SAPART victim {line} :bye")).unwrap(),
                &ctx_b,
            );

            // Residual membership identical across the whole pool.
            for i in 0..CHAN_POOL {
                let chan = format!("#c{i}");
                prop_assert_eq!(
                    ctx_a.channels.is_member(&chan, &uid_for("victim")),
                    ctx_b.channels.is_member(&chan, &uid_for("victim")),
                    "channel {} membership diverged", i
                );
            }
            // Delete-on-empty identical.
            prop_assert_eq!(ctx_a.channels.len(), ctx_b.channels.len());
            // The PART lines the victim sees are identical (A: its own replies; B: its mailbox).
            // Drain world A's mailbox too (it must hold no PART — the victim's echo came back as
            // a reply, not a delivery).
            prop_assert!(mailbox_part_lines(&mut vrx_a).is_empty());
            prop_assert_eq!(part_lines(&a_replies), mailbox_part_lines(&mut vrx_b));
        }
    }
}
===== leveva/src/command/sanick.rs =====
use crate::command::*;
use crate::UserMode;

/// `SANICK <nick> <newnick>` — leveva-native operator command: forcibly rename a **local**
/// user, the nick-side companion to [`SAMODE`](crate::command::mode::samode) /
/// [`SAJOIN`](crate::command::sajoin::sajoin).
///
/// - Not an IRC operator → `481 ERR_NOPRIVILEGES` (mirrors `KILL`).
/// - Missing target or new nick → `461`.
/// - Target nick not registered → `401`; the new nick is malformed → `432`; the new nick is
///   already held by another client → `433` (registry untouched).
/// - The target is on **another** server (a remote/mirrored user) → the rename is routed across
///   the link as `:<our-sid> ENCAP * SANICK <uid> <newnick>` (P11 slice 182,
///   [`crate::s2s::sanick`]); the target's home server performs it and the resulting `NICK` change
///   propagates network-wide. A network-wide nick collision is rejected here with `433`; success
///   yields no numeric (like `KILL`).
/// - Success → the rename goes through the **same** machinery as a client `NICK`
///   ([`apply_local_nick_change`]): WHOWAS files the old identity, the client-form
///   `:<oldmask> NICK <new>` reaches the target's channel co-members + linked peers, and the
///   MONITOR offline/online pair fires. The target's own connection is updated via an
///   [`Envelope::ForceNick`](crate::registry::Envelope::ForceNick), so its session adopts the
///   new nick and writes the `NICK` line. The oper receives no numeric (like `KILL`) — it
///   observes the change through any shared channel.
pub(crate) fn sanick(client: &Registered, msg: &Message, ctx: &ServerContext) -> Vec<Message> {
    if client.modes & (UserMode::Oper.bit() | UserMode::LocalOp.bit()) == 0 {
        return vec![no_privileges(ctx, &client.nick)];
    }
    let target = msg
        .params()
        .first()
        .map(String::as_str)
        .filter(|s| !s.is_empty());
    let raw_new = msg
        .params()
        .get(1)
        .map(String::as_str)
        .or(msg.trailing())
        .filter(|s| !s.is_empty());
    let (Some(target), Some(raw_new)) = (target, raw_new) else {
        return vec![need_more_params(ctx, &client.nick, "SANICK")];
    };

    let Some(uid) = ctx.registry.uid_of(target) else {
        return vec![no_such_nick(ctx, &client.nick, target)];
    };
    let new = match Nick::try_from(raw_new) {
        Ok(n) => n.to_string(),
        Err(_) => {
            return vec![Message::builder(Numeric::ErrErroneousnickname)
                .prefix(&ctx.name)
                .param(&client.nick)
                .param(raw_new)
                .trailing("Erroneous nickname")
                .build()]
        }
    };
    if !ctx.is_local_uid(&uid) {
        // Remote target (P11 slice 182): route a server-sourced `ENCAP * SANICK` so the user's
        // HOME server performs the rename via its own local NICK machinery (whose `:<uid> NICK`
        // relay then carries it network-wide). Pre-check a network-wide collision here so the oper
        // gets immediate `433` feedback; the home server's `try_rename` is the authoritative final
        // check. A case-only change onto the *target's own* current nick is not a collision.
        if ctx.registry.uid_of(&new).is_some_and(|holder| holder != uid) {
            return vec![Message::builder(Numeric::ErrNicknameinuse)
                .prefix(&ctx.name)
                .param(&client.nick)
                .param(&new)
                .trailing("Nickname is already in use")
                .build()];
        }
        crate::s2s::sanick::propagate(ctx, &uid, &new);
        return Vec::new(); // no numeric on success, like KILL — the change shows network-wide
    }
    let Some(rec) = ctx.registry.record_of(&uid) else {
        return vec![no_such_nick(ctx, &client.nick, target)]; // lost a race with a disconnect
    };

    match ctx.registry.try_rename(&uid, &new) {
        Err(ClaimError::InUse) => vec![Message::builder(Numeric::ErrNicknameinuse)
            .prefix(&ctx.name)
            .param(&client.nick)
            .param(&new)
            .trailing("Nickname is already in use")
            .build()],
        Ok(()) => {
            let nick_msg = crate::command::nick::apply_local_nick_change(
                ctx,
                &uid,
                &rec.nick,
                &rec.user,
                &rec.host,
                &rec.realname,
                &new,
            );
            // Force the target's own connection to adopt the new nick and write the line.
            ctx.registry
                .force_nick_uid(&uid, nick_msg.to_wire(), new.clone());
            Vec::new()
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::command::testutil::*;
    use crate::registry::Envelope;

    /// An opered `alice` connection (the testutil fixture, plus `+o`).
    fn oper() -> Registered {
        let mut c = client();
        c.modes |= UserMode::Oper.bit();
        c
    }

    fn drive(ctx: &ServerContext, c: &Registered, line: &str) -> Vec<Message> {
        dispatch(&mut c.clone(), &Message::parse(line).unwrap(), ctx)
    }

    /// The gate (and its inverse): a non-operator's SANICK is `481` and renames nobody.
    #[test]
    fn sanick_requires_oper() {
        let ctx = ctx();
        let mut bob = claim_observed(&ctx, "bob");
        let r = drive(&ctx, &client(), "SANICK bob eve");
        assert_eq!(codes(&r), &["481"]);
        // Inverse: bob keeps his nick and his mailbox is untouched.
        assert!(ctx.registry.contains("bob"));
        assert!(!ctx.registry.contains("eve"));
        assert!(bob.try_recv().is_err());
    }

    /// Success: an oper renames a local user; the registry moves, the target's session is
    /// forced (ForceNick), and a co-member sees the client-form NICK with the old mask.
    #[test]
    fn sanick_renames_a_local_user_and_forces_the_session() {
        let ctx = ctx();
        let mut bob = claim_observed(&ctx, "bob");
        let mut carol = claim_observed(&ctx, "carol");
        ctx.channels.join("#rust", &uid_for("bob"), 0);
        ctx.channels.join("#rust", &uid_for("carol"), 0);
        let r = drive(&ctx, &oper(), "SANICK bob robert");
        assert!(r.is_empty(), "the oper gets no numeric");
        // Registry moved; the UID is stable.
        assert!(ctx.registry.contains("robert"));
        assert!(!ctx.registry.contains("bob"), "old nick freed");
        assert_eq!(ctx.registry.nick_of(&uid_for("bob")).unwrap(), "robert");
        // bob's own connection is force-renamed (control envelope, not a plain wire frame).
        match bob.try_recv().expect("bob got a ForceNick") {
            Envelope::ForceNick { new, wire } => {
                assert_eq!(new, "robert");
                let line = String::from_utf8_lossy(&wire);
                assert!(
                    line.contains(":bob!u@h NICK robert"),
                    "old mask source: {line}"
                );
            }
            other => panic!("expected ForceNick, got {other:?}"),
        }
        // carol, a co-member, sees the client-form NICK with bob's OLD mask.
        let m = delivered(&mut carol);
        assert_eq!(m.command(), "NICK");
        assert_eq!(m.prefix(), Some("bob!u@h"));
        assert_eq!(m.params(), &["robert"]);
        // The vacated nick is filed into WHOWAS.
        assert_eq!(ctx.whowas.lookup("bob", 0).len(), 1);
    }

    /// Missing operand → 461; an unknown target → 401; a malformed new nick → 432.
    #[test]
    fn sanick_operand_and_lookup_errors() {
        let ctx = ctx();
        let _bob = claim_observed(&ctx, "bob");
        assert_eq!(codes(&drive(&ctx, &oper(), "SANICK")), &["461"]);
        assert_eq!(codes(&drive(&ctx, &oper(), "SANICK bob")), &["461"]);
        assert_eq!(
            codes(&drive(&ctx, &oper(), "SANICK ghost newnick")),
            &["401"]
        );
        let r = drive(&ctx, &oper(), "SANICK bob 1bad");
        assert_eq!(codes(&r), &["432"]);
        assert_eq!(r[0].params(), &["alice", "1bad"]);
        assert!(ctx.registry.contains("bob"), "a 432 renames nobody");
    }

    /// Remote target (slice 182): SANICK of a user on another server routes a server-sourced
    /// `ENCAP * SANICK <uid> <newnick>` to the peer — no NOTICE, no numeric to the oper.
    #[test]
    fn sanick_of_a_remote_user_routes_an_encap() {
        let ctx = ctx();
        let mut peer = link_observed_peer(&ctx);
        // A user resident behind the peer (mirrored into the registry, UID under a foreign SID).
        let (tx, _rx) = tokio::sync::mpsc::unbounded_channel();
        let rover = Uid::try_from("0XYZAAAAA").unwrap();
        ctx.registry
            .try_claim(&rover, "rover", "ru", "rh", "Rover", tx)
            .expect("fresh nick");

        let r = drive(&ctx, &oper(), "SANICK rover rocky");
        assert!(r.is_empty(), "no NOTICE, no numeric — routed across the link");
        let m = delivered(&mut peer);
        assert_eq!(m.command(), "ENCAP");
        assert_eq!(m.prefix(), Some("0ABC"));
        assert_eq!(m.params(), &["*", "SANICK", "0XYZAAAAA", "rocky"]);
    }

    /// Remote target whose new nick is already held network-wide → `433` to the oper, and nothing
    /// is routed to the peer.
    #[test]
    fn sanick_of_a_remote_user_onto_a_taken_nick_is_433() {
        let ctx = ctx();
        let mut peer = link_observed_peer(&ctx);
        let (tx, _rx) = tokio::sync::mpsc::unbounded_channel();
        let rover = Uid::try_from("0XYZAAAAA").unwrap();
        ctx.registry
            .try_claim(&rover, "rover", "ru", "rh", "Rover", tx)
            .expect("fresh nick");
        let _carol = claim_observed(&ctx, "carol");

        let r = drive(&ctx, &oper(), "SANICK rover carol");
        assert_eq!(codes(&r), &["433"]);
        assert!(peer.try_recv().is_err(), "a collision routes nothing");
        // Inverse: rover keeps its nick.
        assert_eq!(ctx.registry.nick_of(&rover).unwrap(), "rover");
    }

    /// The override does not invent nick slots: SANICK onto a nick another client already
    /// holds is `433`, and nothing moves.
    #[test]
    fn sanick_onto_a_taken_nick_is_433() {
        let ctx = ctx();
        let _bob = claim_observed(&ctx, "bob");
        let _carol = claim_observed(&ctx, "carol");
        let r = drive(&ctx, &oper(), "SANICK bob carol");
        assert_eq!(codes(&r), &["433"]);
        // Inverse: both nicks survive on their original UIDs.
        assert_eq!(ctx.registry.nick_of(&uid_for("bob")).unwrap(), "bob");
        assert_eq!(ctx.registry.nick_of(&uid_for("carol")).unwrap(), "carol");
    }
}
