feat(leveva): D-lines (DLINE/UNDLINE) — IP-level operator bans (P11 slice 284)
charybdis-style D-lines, the IP/CIDR sibling of the temporary K-line family
(slices 281–283): `DLINE <duration> <ip/cidr> [:reason]` bans a raw IP or CIDR
block, `UNDLINE <ip/cidr>` lifts it. Built as a near-clone of the K-line plane
keyed on a single IP/CIDR `mask` (matched with the CIDR-aware
`matching::host_component_matches`) instead of `user@host`.
- `dline.rs`: `DlineStore` mirrors `KlineStore` (Vec+Mutex, NOCASE dedup,
`find_active`, same `database {}` SQLite write-through + boot reload as slice
282); `Dline::covers` = `host_component_matches`. Reuses the kline duration
grammar/clock/clamp.
- `command/dline.rs`: `dline`/`undline` mirror `tkline`/`untkline` (461→481 gate,
empty/`*` mask → Incorrect format, no success reply); `reap_matching_ip` ejects
local matching clients by `orighost` (real connect IP), skipping remote +
`kline-exempt`. New `OperPrivilege::Dline` (bit 0x400000).
- `session.rs`: registration gate checked before the K-line gate, matching the
pre-cloak connect IP → 465+ERROR+REJ snomask, never counted/claimed.
- `s2s/dline.rs`+`forward.rs`+`burst.rs`: `ENCAP * DLINE`/`UNDLINE` propagation
(server-prefixed, remaining-seconds, slice-281 KLINE shape) + burst
re-assertion.
- `stats.rs`: `STATS d` → `250 RPL_STATSDLINE` via `dline_report`.
- `server.rs`: `ctx.dlines` opens against the same `database {}` file (persists
across restart); boot test + inverse extended.
- help `DLINE.md`/`UNDLINE.md` + COMMANDS allowlist.
Tests (TDD, inverse invariants, mandated fuzzing): unit+proptest per module;
`tests/golden_dline.rs` (real binary, `dline.kdl` fixture) and
`tests/dline_proptest.rs` (6 properties incl. model-lockstep registration gate
over `Session::feed`). leveva-native, no oracle differential.
`cargo test -p leveva` green (2530 lib); clippy clean; workspace 0 warnings.
feat(leveva): learn the SASL mechanism list from services (ENCAP * MECHLIST) (P11 slice 299)
A linked SASL services agent announces its mechanisms via
`:<svcSID> ENCAP * MECHLIST :<comma-list>`; leveva learns the list, advertises
it (client-facing `sasl=` cap value + `908 RPL_SASLMECHS`) instead of the
hardcoded `PLAIN,EXTERNAL`, and relays whichever advertised mechanism a client
picks — faithful charybdis transparent relay (special-casing only EXTERNAL for
the CertFP; an unadvertised mechanism → 908+904, never relayed).
- sasl.rs: pure fuzzed `parse_mechlist`; `Mechanism` reworked
`{Plain,External,Other(Box<str>)}` with `from_advertised`/`name`/`is_external`.
- s2s/links.rs: PeerLinks learned-mechlist store, cleared when the last sasl
agent unlinks.
- s2s/mechlist.rs (new): `apply_encap_mechlist`, dispatched in forward.rs's
interpret-and-onward-relay block (broadcast, like SU).
- cap.rs: `apply`/`ls`/`req` `sasl_available: bool` → `sasl_mechs: Option<&str>`.
- session.rs: AUTHENTICATE gate uses `from_advertised`; 908 lists the advertised
set; relay_start takes &Mechanism.
leveva-native (the C 2.11 oracle predates SASL). Tests cover the happy path and
every inverse invariant (unadvertised rejected, all-junk keeps the prior list,
unlink clears, default fallback) + 2 proptests.
feat(leveva): learn the SASL mechanism list from services (ENCAP * MECHLIST) (P11 slice 299)
A linked SASL services agent announces its mechanisms via
`:<svcSID> ENCAP * MECHLIST :<comma-list>`; leveva learns the list, advertises
it (client-facing `sasl=` cap value + `908 RPL_SASLMECHS`) instead of the
hardcoded `PLAIN,EXTERNAL`, and relays whichever advertised mechanism a client
picks — faithful charybdis transparent relay (special-casing only EXTERNAL for
the CertFP; an unadvertised mechanism → 908+904, never relayed).
- sasl.rs: pure fuzzed `parse_mechlist`; `Mechanism` reworked
`{Plain,External,Other(Box<str>)}` with `from_advertised`/`name`/`is_external`.
- s2s/links.rs: PeerLinks learned-mechlist store, cleared when the last sasl
agent unlinks.
- s2s/mechlist.rs (new): `apply_encap_mechlist`, dispatched in forward.rs's
interpret-and-onward-relay block (broadcast, like SU).
- cap.rs: `apply`/`ls`/`req` `sasl_available: bool` → `sasl_mechs: Option<&str>`.
- session.rs: AUTHENTICATE gate uses `from_advertised`; 908 lists the advertised
set; relay_start takes &Mechanism.
leveva-native (the C 2.11 oracle predates SASL). Tests cover the happy path and
every inverse invariant (unadvertised rejected, all-junk keeps the prior list,
unlink clears, default fallback) + 2 proptests.
feat(leveva): LINKS/MAP enumerate the true network tree via RemoteServer.parent (P11 slice 88)
m_links/m_map hardcoded single-server output despite the Network mirror tracking
the whole topology since slices 31-87 (the gap slice 52 flagged). Both now enumerate
the mirror as the oracle does, rendering the genuine multi-level tree (no flattening,
per the user).
RemoteServer.uplink is the routing direct-peer, not the tree parent; the oracle prints
serv->up->name (the real spanning-tree edge). So add a display-only RemoteServer.parent
(the true tree parent = the announcing SERVER/SMASK line prefix), populated at the three
real introduction sites (handshake = our SID, server.rs = the :announcing_sid prefix,
smask = announcer) + ~20 test fixtures. Routing/squit_subtree still key on uplink.
New command/topology.rs: topology() 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 ' |- '/' `- ' connector cells with a visited-set cycle guard so
every server renders exactly once. links() shows each server's true upstream; map()
nests behind-peer servers under their parent. Single-server output is byte-identical
(zero existing-snapshot churn). Divergences: MAP s remote version '*' (unmirrored),
Sid-sorted order, orphan->root reparenting.
feat(leveva): +z operwall user mode + OPERWALL command (charybdis UMODE_OPERWALL) — P11 slice 252
The oper-only sibling of +w/WALLOPS: an operator broadcasts OPERWALL to every
+z operator network-wide. Closes one of the named remaining charybdis umodes.
A near-exact mirror of the slice-178 WALLOPS machinery (command/operwall.rs +
s2s/operwall.rs).
- +z (letter "z", bit 0x10000, FLAGS_OPERWALL): oper-gated to set like +s
(non-oper +z silently ignored, -z always allowed); purely local, NOT in
SEND_UMODES (the OPERWALL command propagates and each server fans to its own
local +z — diverges from +w, which is in SEND_UMODES only for oracle
faithfulness).
- OPERWALL <text>: oper-only (481), 461 on empty, fans :mask OPERWALL :text to
local +z, propagates :<uid> OPERWALL :text; inbound fans is_local_uid-gated +
split-horizon relay.
- mode.rs UserMode::Operwall (+ is_operwall predicate); umode_diff/RENDERED;
004 umode literal +z; help/OPERWALL.md + USER_MODES.md row.
- The mode.rs round-trip test also moved off "z" as its unknown example to ">".
Tests: command/operwall.rs + s2s/operwall.rs units (mirror wallops), +z oper-gate
units, golden_operwall.rs (+z oper receives, -z oper and -z sender do not),
operwall_proptest.rs (delivery decided by +z alone). 5 welcome-burst snapshots
gain the z letter.
cargo test -p leveva green; clippy clean; build --workspace 0 warnings.
feat(leveva): user mode +C no-CTCP (P11 slice 306)
Port charybdis extensions/umode_noctcp.c to a leveva user mode +C: a
self-settable umode that refuses CTCP queries (other than ACTION) sent to the
user as a PRIVMSG, replying 531 ERR_CANNOTSENDTOUSER :+C set. NOTICE, CTCP
replies, and ACTION always pass. The recipient-side private-message counterpart
of the channel +C (slice 220), reusing the fuzzed channel::is_blocked_ctcp.
Pure seams mode::is_noctcp + mode::noctcp_user_blocks (the composite gate
decision), enforced home-server-local on both the local command/message.rs path
and the inbound-S2S s2s/relay::inbound_message path (new noctcp_reject_remote
routes 531 to the sender's uplink, the +R 248->249 split precedent). The bit
still propagates (slice-254 "no local-only umodes"), so WHOIS shows +C. Bit
0x80000, numeric 531; umode_diff/RENDERED/004-literal/snapshot wiring per the
user-mode checklist.
Tests: mode seam units, command self-settable + inverse, message gate +
inverses, s2s inbound + inverses, golden_noctcp_umode, noctcp_umode_proptest
(5 props). 5 welcome snapshots regenerated (004 gains C).
feat(leveva): learn the SASL mechanism list from services (ENCAP * MECHLIST) (P11 slice 299)
A linked SASL services agent announces its mechanisms via
`:<svcSID> ENCAP * MECHLIST :<comma-list>`; leveva learns the list, advertises
it (client-facing `sasl=` cap value + `908 RPL_SASLMECHS`) instead of the
hardcoded `PLAIN,EXTERNAL`, and relays whichever advertised mechanism a client
picks — faithful charybdis transparent relay (special-casing only EXTERNAL for
the CertFP; an unadvertised mechanism → 908+904, never relayed).
- sasl.rs: pure fuzzed `parse_mechlist`; `Mechanism` reworked
`{Plain,External,Other(Box<str>)}` with `from_advertised`/`name`/`is_external`.
- s2s/links.rs: PeerLinks learned-mechlist store, cleared when the last sasl
agent unlinks.
- s2s/mechlist.rs (new): `apply_encap_mechlist`, dispatched in forward.rs's
interpret-and-onward-relay block (broadcast, like SU).
- cap.rs: `apply`/`ls`/`req` `sasl_available: bool` → `sasl_mechs: Option<&str>`.
- session.rs: AUTHENTICATE gate uses `from_advertised`; 908 lists the advertised
set; relay_start takes &Mechanism.
leveva-native (the C 2.11 oracle predates SASL). Tests cover the happy path and
every inverse invariant (unadvertised rejected, all-junk keeps the prior list,
unlink clears, default fallback) + 2 proptests.
feat(leveva): +l locops + LOCOPS command, and make all user modes global — P11 slice 254
Part A — +l locops user mode + LOCOPS command (charybdis UMODE_LOCOPS), the
local-server sibling of +z/OPERWALL: an oper broadcasts to +l users on the
originating server only; the command never crosses a link. Oper-gated to set,
letter 'l' (bit 0x40000). New command/locops.rs + golden_locops.rs +
locops_proptest.rs. The last named standard charybdis umode — surface complete.
Part B — leveva has NO local-only user modes (product decision). SEND_UMODES is
now every UserMode::ALL bit (self-maintaining const loop), so +O/+x/+s/+g/+G/+D/
+R/+Q/+z/+l all propagate and a remote WHOIS shows them. Verified safe: the burst
already rendered the full unmasked set, and a user's host is always carried
explicitly (UNICK field / ENCAP CHGHOST), never recomputed from the +x bit, so
+x cannot double-apply the cloak (+x now emits both UMODE +x and ENCAP CHGHOST).
Enforcement unchanged: caller-id (+g/+G) and +R stay gated on the target's home
server — the ACCEPT list lives only there and is not propagated, so those S2S
gates are the actual enforcement, not redundant re-checks, and are kept.
- mode.rs: UserMode::LocOps + is_locops(); doc sweep (bit propagates, enforcement
is server-local)
- command/mode.rs: 'l' in the oper-gated arm + umode_diff; +x test asserts both frames
- s2s/umode.rs: SEND_UMODES = every umode; exclusion test -> carries-every-mode
- snotice.rs / s2s/relay.rs: stale 'not in SEND_UMODES' comments corrected
- help/LOCOPS.md + USER_MODES +l row; 004 umode list -> ...zSl (6 snapshots)
- golden_s2s_umode rewritten (demonstrates +D now propagating)