Add ReportServ, wired into the audit trail

Any user can REPORT <nick|#channel> <reason>; filing is rate-limited per
reporter. Reports are an event-sourced, federated queue operators review
with LIST / VIEW / CLOSE / DEL. The interconnection: because a filed report
is an event, the engine's audit feed already announces it to the staff
channel and records it in the searchable action log — so OperServ
LOGSEARCH finds a report by any word in it, tying reports into the same
trail as bans, kicks, and everything else. Opt-in (add "reportserv").
This commit is contained in:
Jean Chevronnet 2026-07-14 04:02:51 +00:00
parent 8d495a948e
commit 5b023c22a4
No known key found for this signature in database
9 changed files with 346 additions and 9 deletions

View file

@ -510,6 +510,17 @@ pub struct NewsView {
pub ts: u64,
}
// An abuse report held by ReportServ.
#[derive(Debug, Clone)]
pub struct ReportView {
pub id: u64,
pub reporter: String,
pub target: String,
pub reason: String,
pub ts: u64,
pub open: bool,
}
#[derive(Debug, Clone)]
pub struct BotView {
pub nick: String,
@ -788,6 +799,12 @@ pub trait Store {
fn news_add(&mut self, kind: &str, text: &str, setter: &str) -> u64;
fn news_del(&mut self, id: u64) -> bool;
fn news(&self, kind: &str) -> Vec<NewsView>;
// Abuse reports (ReportServ). `report_file` is rate-limited (None = too soon).
fn report_file(&mut self, reporter: &str, target: &str, reason: &str) -> Option<u64>;
fn report_close(&mut self, id: u64) -> bool;
fn report_del(&mut self, id: u64) -> bool;
fn reports(&self, open_only: bool) -> Vec<ReportView>;
fn report(&self, id: u64) -> Option<ReportView>;
// Runtime operator grants (OperServ OPER), merged with config opers. `expires`
// is an absolute unix time (None = permanent); opers_list hides expired ones.
fn oper_grant(&mut self, account: &str, privs: Vec<String>, expires: Option<u64>);