Commit graph

196 commits

Author SHA1 Message Date
d6b681c972
Don't expire runtime-granted opers; preserve standalone kicker flags across compaction
All checks were successful
CI / check (push) Successful in 4m12s
2026-07-19 16:44:35 +00:00
d0c7cb6905
Exempt service bots from ChannelOp secureops and bound the last-seen map 2026-07-19 13:17:54 +00:00
23960adc83
Route every handle() early return through the shared tail so swept unbans and incident stamps aren't dropped 2026-07-19 04:44:11 +00:00
ad8a3fe065
Add loopback health and Prometheus metrics endpoint
All checks were successful
CI / check (push) Successful in 4m22s
2026-07-19 04:13:18 +00:00
a10662bbc6
engine: persist the incident ring (LOGSEARCH) across restarts via a periodic + on-shutdown snapshot event, mirroring stat-counter persistence
All checks were successful
CI / check (push) Successful in 3m44s
2026-07-19 00:46:14 +00:00
89ac01d0b0
nickserv/chanserv: catch styled/fullwidth look-alike names too, and add a [register] confusable_check toggle (REHASH-reloadable)
All checks were successful
CI / check (push) Successful in 3m48s
2026-07-19 00:15:08 +00:00
623750e638
dictserv: opt-in DICT (RFC 2229) lookup service — bots and /msg answer dict/define/thes/acronym/law/etc via dict.org off-reactor
All checks were successful
CI / check (push) Successful in 4m4s
2026-07-18 20:21:30 +00:00
e05c62c085
operserv: NOTIFY gains k/m/u/o flags and quit/part reasons; protocol carries kicker, mode-setter, oper-up, user modes
All checks were successful
CI / check (push) Successful in 4m1s
2026-07-18 19:18:17 +00:00
617d3c7966
operserv: NOTIFY feed uses labelled fields (IP/DNS/Account/Server) and Service:verb
All checks were successful
CI / check (push) Successful in 4m5s
2026-07-18 17:50:32 +00:00
4d327c3f47
operserv: NOTIFY lines carry real IP, rdns, login and origin server for the oper feed
All checks were successful
CI / check (push) Successful in 4m4s
2026-07-18 17:28:07 +00:00
8f19a94928
operserv: NOTIFY honours a config exclude list so relay/pylinked clients cannot flood the feed 2026-07-18 16:47:25 +00:00
c415117ec5
operserv: add NOTIFY oper watch list emitting matched-user events to the staff feed 2026-07-18 16:16:06 +00:00
86b1aae686
engine: rate-limit anonymous service commands so a bot cannot spam a service in a loop 2026-07-18 05:02:40 +00:00
6429b82fc4
nickserv: SET SNOTICE — opt-in server-notice-style service replies (*** NickServ: ...) sourced from the server instead of the pseudoclient
All checks were successful
CI / check (push) Successful in 3m47s
2026-07-18 03:40:22 +00:00
c64c3820a7
protocol: verify echos pseudoclients request servprotect (+k, by name from CAPAB USERMODES) so they cannot be killed by operators; warn if service_modes lacks it
All checks were successful
CI / check (push) Successful in 3m45s
2026-07-18 02:41:03 +00:00
2f70b0c133
protocol: verify echo ircd module dependencies from CAPAB MODULES at link, warning per-feature if one is missing rather than failing silently
All checks were successful
CI / check (push) Successful in 3m49s
2026-07-18 02:22:43 +00:00
0ca06247f8
protocol: read CASEMAPPING from CAPAB and verify it matches echos ascii identity folding, warning on mismatch instead of silently desyncing
All checks were successful
CI / check (push) Successful in 4m31s
2026-07-18 01:58:49 +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
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
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
47dfa76fd5
engine: a takeover keeps the account's founded channels (the account still exists) — only a genuine drop or expiry releases them
Some checks failed
CI / check (push) Failing after 3m56s
2026-07-17 20:23:51 +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
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
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
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
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
1fb3615b7e
auth: warn on unknown [[oper]] privilege names instead of silently dropping them
All checks were successful
CI / check (push) Successful in 3m53s
2026-07-17 12:45:41 +00:00
e3b83f4a92
operserv: REHASH announces the reload in the log channel via DebugServ
All checks were successful
CI / check (push) Successful in 4m1s
2026-07-17 11:02:29 +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
f2774f13fe
services: all pseudo-clients join a configurable channel (default #services)
All checks were successful
CI / check (push) Successful in 3m39s
2026-07-17 01:23:18 +00:00
657154e268
services: assigned bot fronts channel modes, not chanserv
All checks were successful
CI / check (push) Successful in 3m41s
2026-07-17 01:17:29 +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
eaf3111917 whois: answer IDLE for pseudo-clients 2026-07-16 23:22:35 +00:00
a60a6df19d debugserv: sourced auth feed, drop icons 2026-07-16 23:08:30 +00:00
38d12cb0bb debugserv: live services activity feed 2026-07-16 22:27:35 +00:00
6c403c01b0 services: configurable pseudo-client host 2026-07-16 19:15:48 +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
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
90167dd46f
db: persist jupes across restart (event-source them)
All checks were successful
CI / check (push) Successful in 3m50s
A fold-parity property test caught it: jupes were plain in-memory Db fields
that logged no event, so after any services restart every juped server was
silently un-juped and could relink. Moved jupes into NetData (like akills/
forbids/groups) and event-sourced them with JupeAdded/JupeRemoved (Local
scope), so a jupe now replays from the log. Adds the round-trip property test
(live state == replayed state) as a permanent guard against this bug class.
2026-07-16 10:56:22 +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
e5e04b4130
engine: reintroduce a killed service agent
All checks were successful
CI / check (push) Successful in 3m46s
A KILL of a services pseudo-client only reintroduced BotServ bots; a killed
core agent (NickServ, ChanServ, …) fell through to the forget-user path and
stayed off the network until a services restart. UserKilled now recognises an
agent by its fixed uid and re-emits its introduction, so an oper can't KILL
services down.
2026-07-16 10:16:48 +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
a9a3408de0
engine: a kicked services bot rejoins its assigned channel
A PART/KICK of a bot uid updated channel membership but not bot_channels,
so reconcile still believed the bot was present and never rejoined it — an
op could evict a services bot for good. The Part handler now drops the stale
membership and reconciles, so a bot assigned to the channel comes right back.
2026-07-16 10:03:00 +00:00