Commit graph

9 commits

Author SHA1 Message Date
253d4c2a2d
Add lazy inactivity-expiry for accounts and channels
Accounts and channels now carry a last-activity stamp and are dropped
once inactive past a configured threshold. A login stamps the account, a
join stamps the channel — both coalesced to at most one log entry per day
so routine traffic doesn't bloat the log, and stamps replicate so
activity on any node keeps a record alive network-wide.

Expiry is lazy in the proven style: a periodic pass computes it from the
stored stamps with no per-record timer, reusing the same relation the
vhost and suspension expiries use. The sweep spares operator accounts,
accounts with a live session, occupied channels, and anything an operator
has pinned with the new NOEXPIRE command (NickServ NOEXPIRE <account>,
ChanServ NOEXPIRE <#channel>, both Priv::Admin). Each expiry is announced
to the audit channel and clears the channel's +r.

Configured under [expire] (accounts_days / channels_days); a zero or
omitted field leaves that kind never expiring, and omitting the section
disables expiry entirely.
2026-07-14 00:02:36 +00:00
2fd5676ff2
Clippy sweep: clean across the workspace
- Box the oversized enum variants (Event::AccountRegistered, gossip
  Msg::Entry) so small events aren't sized to a full Account; serde is
  transparent so the wire/log format is unchanged.
- Use the configured server description in the SERVER line (it was
  hardcoded and the config field went unread).
- Derive the ChanServ SET label from the ChanSetting (drops toggle's 8th
  arg); rename inspircd from_us -> sourced.
- allow the two framework-idiom lints with rationale (tonic's Status in
  authorize; the guest-rename handler's inherent arg count).
- Auto-fixed map_or/contains/split_once style lints.
2026-07-13 23:30:51 +00:00
bddf13459d
Wire NickServ + ChanServ into the shared stats registry
nickserv.identify / nickserv.identify_fail and chanserv.register /
chanserv.drop are now recorded via ctx.count, so the Stats API reports
each module's own events, not just BotServ's.
2026-07-13 19:15:40 +00:00
cb081a2e95
chanserv: channel SUSPEND / UNSUSPEND (oper-gated)
Freezes a channel gated on Priv::Suspend: a typed Suspension on ChannelInfo
(event-logged, snapshotted, lazy expiry — same shape as the account one, no
Anope Extensible/Checker or expiry timer). While suspended, ChanServ refuses
all management (guards in require_op/require_founder and the founder-inline
SET/DROP/MLOCK), the engine skips Join enforcement (no auto-op/akick/entrymsg),
and suspending kicks everyone out; INFO shows it. parse_duration moved into the
SDK so both SUSPEND commands share it. Data + full-flow tests.
2026-07-13 04:17:17 +00:00
4600ee062c
chanserv: SET TOPICLOCK and KEEPTOPIC (topic subsystem)
Adds topic tracking: a TopicChange event (parsed from InspIRCd FTOPIC, our own
changes filtered by SID like FMODE) and a stored topic on the channel, folded
through the event log. TOPICLOCK reverts a topic change by a user without
op-level access back to the stored topic; KEEPTOPIC remembers the topic and
restores it when a registered channel is recreated. Both via the typed
ChanSettings path; shown in INFO. Parse + engine tests cover both.
2026-07-13 03:30:04 +00:00
d2c6448c6b
chanserv: SET SECUREOPS (strip ops from users without access)
When SECUREOPS is on, a user who gains channel-operator status without op-level
access is immediately deopped. Enforced in the engine's ChannelOp hook (manual
FMODE +o) and the Join hook (FJOIN prefix ops), sourced from ChanServ. Same
typed-settings path; shown in INFO; engine test covers on and off.
2026-07-13 03:14:43 +00:00
3bf6b2be77
chanserv: SET PEACE (block acting against equal-or-higher access)
PEACE stops a channel op from using ChanServ KICK/BAN/DEOP/DEVOICE against
someone whose access rank (founder>op>voice) is equal to or above their own.
Adds a typed access_rank on ChannelView and a peace_blocks guard in those
commands. Same typed-settings path as SIGNKICK/PRIVATE; shown in INFO.
2026-07-13 03:06:58 +00:00
75019c867a
chanserv: SET SIGNKICK and PRIVATE (typed channel settings)
Introduce a typed ChanSettings struct + ChanSetting enum for ChanServ's on/off
options instead of a bag of string flags, so a new option is one field and the
compiler proves every site handles it. First two, both functional: SIGNKICK
attributes ChanServ kicks with who requested them; PRIVATE hides the channel
from LIST. Folded through the event log like the other channel state (node-local,
no gossip), shown in INFO. One ChannelSettingsSet event, one Store method.
2026-07-13 02:54:46 +00:00
596630df53
modules: split services and the ircd link into external crates
nickserv, chanserv and the InspIRCd protocol move out of the binary into their
own workspace crates (fedserv-nickserv, fedserv-chanserv, fedserv-inspircd),
each depending only on fedserv-api. human_time and the branded account emails
move into the SDK crate so a module needs nothing from core; the engine keeps
its own inherent methods and builds emails via fedserv-api too. The bin now
constructs each module from its crate instead of an in-tree #[path] include.
Proves the SDK is self-sufficient: a third-party module is the same shape.
2026-07-13 01:33:56 +00:00