pub enum Match {
Keyword {
patterns: Vec<String>,
normalize: Normalize,
},
Regex {
patterns: Vec<String>,
normalize: Normalize,
boundary_word: bool,
},
Link {
patterns: Vec<String>,
},
Repeat {
normalize: Normalize,
within_secs: Option<u64>,
},
Rate {
per_secs: u64,
},
Mentions {},
Cohort {
min: u32,
quiet_max: u32,
short_factor: u32,
thin_ratio: Option<Ratio>,
},
JoinBurst {
gap_secs: u64,
min: u32,
},
TenureLt {
secs: u64,
},
MessagesLte {
n: u32,
},
}Expand description
Phase-1 rule types. Each entry states its admissible scopes and basis; the validator rejects anything the spec does not define, so an undefined rule type can never evaluate as a silent no-op.
Variants§
Keyword
Bare pattern = token-anchored (the Scunthorpe guard); *word, word*,
*word* relax an edge; \* is a literal asterisk. No boundary field:
the grammar makes it redundant.
Regex
Link
Hits = distinct non-exempt registrable domains per message. Carries no span (its hit is a domain, not a text range).
Repeat
Window-only. Hits = occurrences of the most-repeated normalized text by that author; ties by the normalized key ascending.
within_secs bounds the count to the densest run inside that span, so
the rule measures a burst rather than a habit. Without it a daily “gm”
over a seven-day window counts as seven repeats, which is a regular, not
a spammer. A policy that sets it MUST declare requires: ["repeat_within"]
or an older engine ignores the field and convicts where a newer one
would not — the same policy_hash, two different verdicts.
Rate
Window-only. Half-open sliding window; candidate starts are the author’s own message timestamps.
Mentions
Hits = p-tags on the message. Inline @name is NOT a mention.
Cohort
Cross-account same-skeleton clustering. Whole-only, Heuristic.
JoinBurst
Densest run of joins within gap_secs; earliest wins on ties.
TenureLt
Member-plane aggravators: citation-less, immutably family-tagged.
MessagesLte
Implementations§
Source§impl Match
impl Match
pub fn type_name(&self) -> &'static str
Sourcepub fn basis(&self) -> Basis
pub fn basis(&self) -> Basis
Deterministic = byte-provable and replayable by anyone. Only these feed
proven, and only these may refuse.
Sourcepub fn admits(&self, scope: Scope) -> bool
pub fn admits(&self, scope: Scope) -> bool
Admissible scopes. A window-level quantity must not also declare per_message tiers, or both convictions enter the combinator and double-count one fact.
Sourcepub fn is_stateless(&self) -> bool
pub fn is_stateless(&self) -> bool
Can this rule judge ONE message on its own, with no history and no view of anyone else? Word filters and link blocks can; anything that counts across a window, or compares members to each other, cannot.
The split is what lets an ordinary member run moderation at all: their client checks its own drafts and the messages in front of it, while everything requiring historical state — repetition, rates, cohorts, tenure — belongs to an admin or a moderation bot, which has both the authority to act on it and the data to compute it honestly.
Sourcepub fn builtin_family(&self) -> Option<&'static str>
pub fn builtin_family(&self) -> Option<&'static str>
Built-in immutable family tag — the fresh-account proxies fold together so correlated signals never OR into an inflated score.
Sourcepub fn is_content_derived(&self) -> bool
pub fn is_content_derived(&self) -> bool
Cites content (so a conviction needs at least one citable citation), or is member-state (citation-less by nature).
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Match
impl<'de> Deserialize<'de> for Match
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for Match
impl StructuralPartialEq for Match
Auto Trait Implementations§
impl Freeze for Match
impl RefUnwindSafe for Match
impl Send for Match
impl Sync for Match
impl Unpin for Match
impl UnsafeUnpin for Match
impl UnwindSafe for Match
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more