P11 slice 183 — SAJOIN / SAPART S2S propagation#
Date: 2026-06-15 Area: S2S notify-propagation arc (177 METADATA, 178 WALLOPS, 179 KILL, 180 metrics, 182 SANICK). Follow-on to: slice 182 (SANICK S2S), which named this explicitly:
route
ENCAP * SAJOIN/SAPARTto the home server, which runs its existing localforce_join/force_part(whose JOIN/NJOIN/PART S2S relay then propagates).
Problem#
SAJOIN <nick> <chan>{,<chan>} (slice — the SA* oper-override family) and
SAPART <nick> <chan>{,<chan>} [:reason] are local-target only: a remote/mirrored target
gets a server NOTICE ("not on this server") and nothing happens. Both handler docs admit
this is a documented scope limit, deferred behind the same stale "KILL-local scope" rationale
that slice 179 (KILL S2S) and slice 182 (SANICK S2S) have since closed. An oper should be able
to force a remote user into / out of a channel network-wide.
Mechanism — route to the home server, reuse the local force machinery#
Server-authoritative override → server-prefixed, rides ENCAP (slice-126 lesson: a bare
unknown verb SQUITs a stricter peer). Modeled exactly on s2s/sanick.rs:
:<our-sid> ENCAP * SAJOIN <target-uid> <chan>{,<chan>}
:<our-sid> ENCAP * SAPART <target-uid> <chan>{,<chan>} [:reason]
This pair is structurally simpler than SANICK: the home server's existing
force_join/force_part already relay the resulting JOIN/NJOIN/PART to all peers
(join_one emits the :<sid> NJOIN relay; part_one calls s2s::relay::local_part). So the
inbound apply just runs the local force machinery — the network converges from that relay, not
from the ENCAP (every other server no-ops the ENCAP, exactly like SANICK's NICK relay).
New modules (one per verb, matching the sanick.rs/su.rs convention)#
leveva/src/s2s/sajoin.rspropagate(ctx, uid, chans)— broadcast:<sid> ENCAP * SAJOIN <uid> <chans>to every peer (source = us → none excluded); no-op with no peers.chansis the already-comma-joined valid channel list (a single wire token).apply_encap_sajoin(_link, msg, ctx)— inbound: only the home server acts (uid local). Per channel:ChanName::try_fromok →command::join::force_join; invalid → skip (defensive — protects the home server from creating a malformed channel regardless of origin, mirroring the local handler's403guard). Transit / oper's own server: no-op. Does not relay (the callerforward::inbound_encaponward-relays theENCAPverbatim split-horizon).
leveva/src/s2s/sapart.rspropagate(ctx, uid, chans, reason)— broadcast:<sid> ENCAP * SAPART <uid> <chans> [:reason].apply_encap_sapart(_link, msg, ctx)— inbound: home server only. Per channel:command::part::force_part(its403/442error reply is discarded — the oper is not local on the home server). Transit: no-op.
Wiring#
leveva/src/s2s/forward.rs— addSome("SAJOIN") => super::sajoin::apply_encap_sajoin(...)andSome("SAPART") => super::sapart::apply_encap_sapart(...)to the interpreted-ENCAPmatch.leveva/src/s2s/mod.rs—pub mod sajoin; pub mod sapart;.leveva/src/command/sajoin.rs— the remote branch (!is_local_uid): replace theNOTICEwith per-channel name validation (403to the oper for a malformed name — immediate feedback, matching the local path) thens2s::sajoin::propagate(ctx, &uid, &valid_chans). Success returns no numeric (like the local path / KILL).461/401checks stay ahead of the locality branch.leveva/src/command/sapart.rs— the remote branch: replace theNOTICEwiths2s::sapart::propagate(ctx, &uid, chans, reason). No channel-name pre-check (the local path has none either; the home server'sforce_partvalidates). The oper gets no403/442for a remote target — a documented divergence.
Divergences (leveva-native — no oracle differential)#
- Single-uplink no-op — broadcast / onward-relay reaches ≤1 peer (standing
relaydivergence). - Remote SAPART gives no
403/442— membership state lives on the home server; the oper only learns of a461/401/malformed-channel(SAJOIN) failure, not "not on that channel". - Transparency — network-wide the effect is an ordinary
NJOIN/PART, indistinguishable from a normal join/part; no distinct SAJOIN/SAPART verb reaches clients.
TDD plan (tests first; inverse invariants + fuzz)#
s2s/sajoin.rs tests:
- home server: inbound
ENCAP * SAJOIN <local-uid> #a,#b→ target is a member of both, its own mailbox got the JOIN echo + NAMES, a co-member saw the JOIN. - inverse: a non-local (mirrored) uid → no-op (not a member anywhere).
- defensive: an invalid channel token is skipped; valid ones in the same line still join.
propagateemits the exactENCAP * SAJOINline; no-peerspropagateis a no-op.- fuzz
propagate_then_apply_joins_the_local_target: any set of valid channel names → round-trip joins the local target to all of them, never panics.
s2s/sapart.rs tests:
- home server: pre-join the local target to
#a,#b; inboundENCAP * SAPART <uid> #a,#b :bye→ target removed from both, echo on its mailbox, co-member saw the PART with the reason. - inverse: non-local uid → no-op (still a member); a channel the target is not on → no-op, no panic.
propagateemits the exact line incl. the reason trailing; no-peers no-op.- fuzz
propagate_then_apply_parts_the_local_target: round-trip parts the target from every channel it was on, never panics.
command/sajoin.rs (new): a remote target routes ENCAP * SAJOIN <uid> <chans> to the peer
(no NOTICE, no numeric); a malformed channel for a remote target → 403 to the oper + nothing
routed for it. command/sapart.rs (new): a remote target routes ENCAP * SAPART <uid> <chans> [:reason] to the peer (no NOTICE) — replacing the existing sapart_remote_target_gets_a_notice
assertion (now: routes, no NOTICE). Local suites stay green.
Gate#
cargo test -p leveva green; cargo clippy -p leveva --tests clean; cargo build --workspace
0 warnings. Record: PLAN.md P11 row bump, p11.md heredoc append, memory pointer update
(leveva-s2s-notify-propagation).