The service pseudo-clients and the ircd protocol link sat flat at the
repo root, mixed in with the daemon core and the SDK. Move them all
under modules/ so the tree separates concerns cleanly: the daemon in
src/, the SDK every module links against in api/, and the loadable
modules — the pseudo-clients plus the protocol link — in modules/.
Workspace members, the daemon's per-crate dependency paths, and each
module's api path are updated to match; the docs follow. No code change.
KICK <#channel> DONTKICKVOICES <on|off> exempts voiced users from the
kickers. The network view now tracks +v the same way it tracks +o: a new
ChannelVoice event is parsed from FMODE +v/-v and from +v join prefixes,
and set_voice/is_voiced mirror set_op/is_op (voice is cleared on part and
quit). scan_ops generalised to scan_status for any status letter.
Also scrubbed third-party project name-drops from code comments.
Three brute-force / weak-secret gaps closed:
- REGISTER and SET PASSWORD now enforce a length range and reject a password
equal to the nick (Anope's minpasslen/not-nick rules), with tests.
- IDENTIFY is throttled per account: a few free tries then an exponential
backoff that clears on success, so a password can't be ground down. SASL had
a limiter; interactive login had none.
- Emailed confirm/reset codes go from 6 digits to 8 base32 chars (~40 bits) and
are burned after a few wrong guesses, closing a reset-code takeover window.
Throttle and code state are node-local and in-memory (not in the event log).