Commit graph

165 commits

Author SHA1 Message Date
e206f4edbb
operserv: REDACT deletes a message by its msgid (draft/message-redaction), relayed server-sourced so no ircd oper privilege is needed
All checks were successful
CI / check (push) Successful in 4m6s
2026-07-18 01:23:37 +00:00
e6f05a3ede
protocol: learn channel-mode arity + prefix modes (incl custom Y/ojoin) from CAPAB CHANMODES; services MODE uses the authoritative set 2026-07-18 01:15:23 +00:00
d313ca3523
chanserv: LEVELS grants a capability (op/topic/invite/access) to an access tier and above, additive so it never locks anyone out 2026-07-18 01:05:58 +00:00
0c3e09ea00
operserv: SPAMFILTER — persisted content filters pushed to the ircd m_filter via metadata, re-asserted at burst
All checks were successful
CI / check (push) Successful in 3m56s
2026-07-18 00:04:24 +00:00
9908548978
chanserv: reuse echo_api chanmode_takes_param in the MODE extban gate instead of a less-complete local copy 2026-07-17 22:52:31 +00:00
8c77016aed
helpserv: HELP EXTBANS lists the network live extban set with a friendly example for each 2026-07-17 22:23:54 +00:00
77d09c4bdc
akick: accept a matching extban only the ircd knows (ircd-enforced +b), reject acting extbans with a clear reason 2026-07-17 22:01:32 +00:00
c990eb1e1e
extban: learn the ircd live set from CAPAB EXTBANS and validate AKICK/MODE against what it actually offers 2026-07-17 21:47:02 +00:00
da94142bad
chanserv: hold MODE ban/except/invex extbans to the [extban] enabled policy, matching AKICK 2026-07-17 21:33:00 +00:00
74a983467c
akick: match the server and fingerprint extbans from the SERVER name and ssl_cert metadata the s2s stream carries 2026-07-17 21:23:25 +00:00
f7c38cedad
chanserv: full AKICK extban registry, [extban] enabled gate, passive extbans pushed as channel bans for the ircd to enforce 2026-07-17 21:06:14 +00:00
426fc694a2
akick: match extbans (account/realname/realmask/unauthed) using the ident, real host and real name the UID carries but was discarding
All checks were successful
CI / check (push) Successful in 4m0s
2026-07-17 19:47:34 +00:00
bc4fada354
api: type GroupServ flags (GroupFlag/GroupFlags via a shared flag_set! macro); delete the stringly apply_flags
All checks were successful
CI / check (push) Successful in 4m0s
2026-07-17 18:47:08 +00:00
2a12ebd6e3
api: typed Flag/Flags bitset for channel access (mirrors Privs); level_caps resolves every level through it, collapsing 40 lines to 5
All checks were successful
CI / check (push) Successful in 4m0s
2026-07-17 18:30:45 +00:00
65323caaeb
chanserv: FLAGS maps sop/halfop presets to flag letters (oa=+ao), fixing privilege escalation when editing a HOP/SOP entry
All checks were successful
CI / check (push) Successful in 4m2s
2026-07-17 18:14:58 +00:00
f2ba876ce4
botserv: bots join +ao (protected admin + op), keeping op alongside protect
All checks were successful
CI / check (push) Successful in 3m53s
2026-07-17 17:11:25 +00:00
73467b91ca
botserv: bots join channels as protected admins (+a) so ordinary ops can't kick or deop them
All checks were successful
CI / check (push) Successful in 3m50s
2026-07-17 16:52:00 +00:00
2f6fd41465
chanserv: SOP protect tier over AOP (+ao), founder owner (+qo); resolve op access by capability not mode string
All checks were successful
CI / check (push) Successful in 3m59s
2026-07-17 15:43:16 +00:00
c8106035df
chanserv: give SOP/AOP/HOP/VOP four distinct access tiers matching Anope, classified by capability
All checks were successful
CI / check (push) Successful in 3m55s
2026-07-17 14:54:36 +00:00
f5c976eb56
api/gameserv: type email ExpiryTarget and chess Ending as enums (drop stringly returns)
All checks were successful
CI / check (push) Successful in 3m53s
2026-07-17 14:15:39 +00:00
2cdc7f820a
chanserv/nickserv: resolve access level via caps, so FLAGS-set roles list correctly in ALIST and AOP/SOP/VOP 2026-07-17 14:15:39 +00:00
7a5f1502a4
infoserv: type the news kind as an enum at the store boundary
All checks were successful
CI / check (push) Successful in 3m53s
2026-07-17 13:53:53 +00:00
ee95225eaf
operserv: OPER ADD rejects unknown privilege names instead of silently dropping them 2026-07-17 13:53:53 +00:00
ef34c04c8d
operserv: type the X-line kind as an enum at the command/store boundary, wire token in storage 2026-07-17 13:47:10 +00:00
2c8ba4460d
forbid: type the FORBID kind as an enum at the store boundary, string only in storage
All checks were successful
CI / check (push) Successful in 3m56s
2026-07-17 13:26:16 +00:00
cfe05481d6
gameserv: model the domain with enums (GameType/Side/Status/Outcome/Board), zero-alloc grid moves
All checks were successful
CI / check (push) Successful in 3m54s
2026-07-17 12:20:26 +00:00
108c15e95a
gameserv: ranked ladder rides StatServ's persisted counters, no separate store
All checks were successful
CI / check (push) Successful in 3m50s
2026-07-17 12:07:35 +00:00
b763eab9ed
gameserv: use the GamesServ nick, GameServ is reserved on the network
All checks were successful
CI / check (push) Successful in 3m51s
2026-07-17 11:51:35 +00:00
a7a37d1277
gameserv: server-authoritative ttt/c4/chess referee with ranked ladder
All checks were successful
CI / check (push) Successful in 3m56s
2026-07-17 11:24:13 +00:00
64b675e61f
operserv: REHASH reloads config live without a restart
All checks were successful
CI / check (push) Successful in 3m54s
2026-07-17 10:46:12 +00:00
75c6537532
standard replies: emit IRCv3 FAIL/WARN/NOTE for service errors, config-gated
All checks were successful
CI / check (push) Successful in 3m42s
2026-07-17 02:53:48 +00:00
fcca7ac12b
chanserv: channel seen checks channel membership, not global presence
All checks were successful
CI / check (push) Successful in 3m45s
2026-07-17 01:54:55 +00:00
66eb644a07
chanserv: channel-scoped seen with last message, replied in-channel
All checks were successful
CI / check (push) Successful in 3m47s
2026-07-17 01:41:47 +00:00
96654b5e5a
groupserv: gate channel access on the c flag, document !group
All checks were successful
CI / check (push) Successful in 3m43s
2026-07-17 01:00:27 +00:00
b87a0c56a2
services: label as network service in whois
All checks were successful
CI / check (push) Successful in 3m44s
2026-07-17 00:30:51 +00:00
952078aa7e services: configurable pseudo-client umodes
All checks were successful
CI / check (push) Successful in 3m43s
2026-07-17 00:01:24 +00:00
eaf3111917 whois: answer IDLE for pseudo-clients 2026-07-16 23:22:35 +00:00
9bdda721f3 keycard: redeem website login keycards over SASL 2026-07-16 22:27:59 +00:00
38d12cb0bb debugserv: live services activity feed 2026-07-16 22:27:35 +00:00
2f9790feac
auth: offload IDENTIFY + SASL PLAIN verify off the engine lock
All checks were successful
CI / check (push) Successful in 3m47s
Both ran scram verify_plain (~1s PBKDF2 at 1.2M iters) inline under the engine
lock, freezing the whole daemon per login. Add NetAction::DeferAuthenticate +
AuthThen continuation + ctx.defer_authenticate, mirroring DeferPassword: the
module/SASL path fetches the verifier cheaply and defers; the link layer runs
verify_plain on spawn_blocking, then Engine::complete_authenticate finishes the
login (IDENTIFY reuses the same ctx helpers, so its login/AJOIN/vhost/memo
side-effects are unchanged). Tests resolve the defer inline (cfg(test)). The
gRPC web-login path was already fixed; no login path stalls services now.
(GHOST/DROP/CERT/GROUP still verify inline but are rare account ops, not logins.)
2026-07-16 19:04:18 +00:00
2e92f75a90
chanserv: PEACE never blocks acting on yourself (self-deop)
All checks were successful
CI / check (push) Successful in 3m58s
!deop with no target deops the caller, but peace_blocks compared the target's
access rank to the caller's — equal for self — so PEACE refused it with 'you
can't act against someone with equal or higher access.' Exempt the self case
(target uid == caller uid) in peace_blocks: acting on yourself isn't acting
against anyone, so you can always drop your own status. Covers DEOP/DEVOICE and
the kick/ban paths too.
2026-07-16 17:59:00 +00:00
1f6a11dba2
statserv: persist per-channel activity across restart too
All checks were successful
CI / check (push) Successful in 3m49s
The earlier StatsSet fix persisted only the shared namespaced counters. The
per-channel BOTSTATS view (lines seen + top talkers, from /statserv #chan) lived
on the LiveChannel struct, which is rebuilt from each burst — so it reset to zero
on restart. Move it to a name-keyed Network.chan_activity map (independent of live
membership, seedable before the burst) and carry it in the StatsSet snapshot
(new serde-default `channels` field) alongside the counters. Reworded the
notice from 'seen this session' now that it persists.
2026-07-16 17:50:11 +00:00
8a9b6a37ca
botserv: op assigned bots on join; statserv: persist counters across restart
Some checks failed
CI / check (push) Failing after 3m48s
Problem 1: an assigned bot joined via IJOIN with no status mode, so it had no
+o. Join it with the 4-param IJOIN form (ts 1, mode o) so it's opped, matching
Anope's default bot modes (+o), and exempt bots from SECUREOPS/RESTRICTED so the
op is never stripped.

Problem 2: the shared stat counters lived only in memory, so a restart wiped
them. Snapshot them to the log (StatsSet event, folded into NetData + compaction)
periodically and on shutdown, and reseed the live registry from the log at
startup. Live gauges (online counts) stay re-derived, not stored.
2026-07-16 17:32:20 +00:00
d1685f7e53
inspircd: include membid in outbound IJOIN
All checks were successful
CI / check (push) Successful in 3m49s
Services IJOIN was ':<uid> IJOIN <chan>' with no membership id, but InspIRCd
requires <chan> <membid> (min 2 params). On link the ircd rejected the whole
server connection with 'Insufficient parameters' the moment a BotServ bot joined
its assigned channel, splitting services. Add a monotonic membid, matching how
InspIRCd itself sends IJOIN. Validated against a real InspIRCd 4 with production
data: full burst to ENDBURST, all bot IJOINs accepted, no split.
2026-07-16 16:36:19 +00:00
9d94dd5eb0
chanserv: support param mode locks (+f flood, +j joinflood)
Some checks failed
CI / check (push) Has been cancelled
Mode locks were char-only, so Anope FLOOD/JOINFLOOD locks were dropped on
migration. Carry a value per locked param-mode through the event log, MLOCK
parsing/display, drift enforcement, compaction, and the Anope importer, so a
migrated network keeps its flood protection verbatim.
2026-07-16 15:23:09 +00:00
61005f52f5
services: throttle emailed codes to stop RESEND/RESETPASS email-bombing
All checks were successful
CI / check (push) Successful in 3m46s
REGISTER was rate-limited but RESEND and RESETPASS weren't — anyone could
repeatedly request confirmation/reset codes for any account with an address
on file, flooding the victim's inbox and burning the service's sender
reputation. A per-account 60s cooldown (code_issue_wait, mirroring the vhost
request throttle) now gates both paths; guessing was already infeasible
(2^40 code + 5-try limit), so this closes the abuse, not an auth hole.
2026-07-16 10:41:52 +00:00
320a591ae3
engine: track the server tree so a hub SQUIT cascades
All checks were successful
CI / check (push) Successful in 3m50s
SQUIT arrives once for a splitting server (by SID), but a hub takes its
whole subtree with it — users behind downstream servers were left as stale
state. The parser now distinguishes a sourced downstream SERVER (tracked
with its parent) from the unsourced uplink handshake, the engine keeps the
SID->parent tree, and a SQUIT forgets every user across the departed
server's subtree. Tree is rebuilt each link. Wire formats verified against
the InspIRCd 4 m_spanningtree source.
2026-07-16 10:31:29 +00:00
4aff734340
engine: forget a split server's users on SQUIT
All checks were successful
CI / check (push) Successful in 3m47s
A netsplit is signalled once via SQUIT, not as a QUIT per user, so every
user behind the departed server lingered in services' state — stale
sessions, session-limit slots, and channel memberships. The parser now
surfaces ServerSplit and the engine forgets every uid carrying that
server's SID prefix, leaving other servers' users untouched.
2026-07-16 10:10:20 +00:00
63ecd79b12
engine: handle inbound KILL — forget users, reintroduce bots
KILL was never parsed, so a killed user lingered in services' state (stale
session, session-limit slot, channel membership) and a killed services bot
vanished for good. The parser now surfaces UserKilled; a killed real user is
forgotten like a QUIT (shared forget_user helper), while a killed bot is
dropped and reconciled so it is reintroduced and rejoins its channels.
2026-07-16 10:06:36 +00:00
7e868babc3
inspircd: restore logins from replayed accountname metadata
All checks were successful
CI / check (push) Successful in 3m45s
The inbound parser ignored METADATA entirely, so on a services netburst
(after a restart/relink) the ircd's replayed 'accountname' metadata was
dropped — every logged-in user looked logged out to services until they
re-identified, losing ChanServ access. Parse METADATA <uid> accountname
into a new AccountLogin event that restores account_of (empty = logout);
our own echoes and other keys are filtered.
2026-07-16 09:54:35 +00:00