main
tag: launch-2026-06-01
tag: magicmirror-v0.1.1
tag: magicmirror-v0.3.0
tag: mnw-cli-v0.1.2
tag: mnw-cli-v0.1.3
tag: mnw-cli-v0.1.4
tag: pom-v0.4.1
tag: pom-v0.4.2
tag: pom-v0.4.3
tag: pom-v0.4.4
tag: pom-v0.4.5
tag: wam-v0.3.0
tag: wam-v0.3.1
Files
Commits
Tags
Notes
Issues
livechat: adopt universal clippy/lint baseline; warnings to zero
Renamed the misleadingly-underscored _permit field to permit (used_underscore_binding), by-value self on the Copy RateLimits method (trivially_copy_pass_by_ref), bound the error in a test panic (match_wild_err_arm).
clippy --all-targets clean, cargo fmt clean, tests green (57 passed+3 passed+2 passed+0 passed).
Co-Authored-By
Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5 files changed,
+49 insertions,
-19 deletions
26
26
[dev-dependencies]
27
27
serde_json = "1"
28
28
tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread", "sync", "time"] }
29
+
30
+
[lints.rust]
31
+
unused = "warn"
32
+
unreachable_pub = "warn"
33
+
34
+
[lints.clippy]
35
+
pedantic = { level = "warn", priority = -1 }
36
+
# Allow-list tuned from a measured breakdown across server/multithreaded/pter
37
+
# (2026-07-22). These are the high-churn / low-signal pedantic lints; everything
38
+
# else in `pedantic` stays a warning. Keep this block identical across repos.
39
+
module_name_repetitions = "allow"
40
+
# Doc lints — no docs-completeness push underway.
41
+
missing_errors_doc = "allow"
42
+
missing_panics_doc = "allow"
43
+
doc_markdown = "allow"
44
+
# Numeric casts — endemic and mostly intentional in size/byte math.
45
+
cast_possible_truncation = "allow"
46
+
cast_sign_loss = "allow"
47
+
cast_precision_loss = "allow"
48
+
cast_possible_wrap = "allow"
49
+
cast_lossless = "allow"
50
+
# Subjective structure/style nags — high churn, low signal.
51
+
must_use_candidate = "allow"
52
+
too_many_lines = "allow"
53
+
struct_excessive_bools = "allow"
54
+
similar_names = "allow"
55
+
items_after_statements = "allow"
56
+
single_match_else = "allow"
57
+
# Frequent false-positives in TUI/router-heavy code — added from the buckets breakdown.
58
+
match_same_arms = "allow"
59
+
unnecessary_wraps = "allow"
60
+
type_complexity = "allow"
129
129
.or_insert_with(|| broadcast::channel(self.inner.limits.room_buffer).0)
130
130
.subscribe();
131
131
132
-
Ok(Subscription {
133
-
rx,
134
-
room,
135
-
_permit: permit,
136
-
})
132
+
Ok(Subscription { rx, room, permit })
137
133
}
138
134
139
135
/// Rooms currently holding a channel. Diagnostics only.
152
148
self.inner
153
149
.rooms
154
150
.get(&room)
155
-
.map(|tx| tx.receiver_count())
156
-
.unwrap_or(0)
151
+
.map_or(0, |tx| tx.receiver_count())
157
152
}
158
153
}
159
154
223
218
pub struct Subscription {
224
219
rx: broadcast::Receiver<ChatEvent>,
225
220
room: RoomId,
226
-
_permit: ConnectionPermit,
221
+
permit: ConnectionPermit,
227
222
}
228
223
229
224
impl Subscription {
255
250
// this instant either keeps this channel or creates a fresh one after the
256
251
// removal. It cannot end up holding a receiver on a sender that has just
257
252
// been dropped from the map, which is the silent-dead-room failure.
258
-
self._permit
253
+
self.permit
259
254
.inner
260
255
.rooms
261
256
.remove_if(&self.room, |_, tx| tx.receiver_count() <= 1);
48
48
}
49
49
50
50
impl RateLimits {
51
-
fn refill_per_sec(&self) -> f64 {
51
+
fn refill_per_sec(self) -> f64 {
52
52
f64::from(self.sustain_per_min) / 60.0
53
53
}
54
54
}
220
220
let (u, r, t0) = (user(), room(), Instant::now());
221
221
222
222
assert!(rl.check(u, r, t0).is_allowed());
223
-
let long_later = t0 + Duration::from_secs(3600);
223
+
let long_later = t0 + Duration::from_hours(1);
224
224
225
225
for i in 0..3 {
226
226
assert!(rl.check(u, r, long_later).is_allowed(), "message {i}");
271
271
assert!(rl.check(u, r, t).is_allowed());
272
272
// Earlier than the bucket's last touch: elapsed saturates to zero rather
273
273
// than underflowing.
274
-
assert!(rl.check(u, r, t - Duration::from_secs(5)).is_allowed());
274
+
assert!(
275
+
rl.check(u, r, t.checked_sub(Duration::from_secs(5)).unwrap())
276
+
.is_allowed()
277
+
);
275
278
}
276
279
277
280
#[test]
285
288
rl.check(idle, r, t0);
286
289
assert_eq!(rl.bucket_count(), 2);
287
290
288
-
let later = t0 + Duration::from_secs(60);
291
+
let later = t0 + Duration::from_mins(1);
289
292
rl.check(busy, r, later);
290
293
291
294
assert_eq!(rl.evict_idle(later, Duration::from_secs(30)), 1);
15
15
use crate::error::ChatError;
16
16
17
17
/// Longest retention any room may request.
18
-
pub const MAX_AGE_CEILING: Duration = Duration::from_secs(30 * 24 * 60 * 60);
18
+
pub const MAX_AGE_CEILING: Duration = Duration::from_hours(720);
19
19
20
20
/// Most messages any room may hold.
21
21
pub const MAX_MESSAGES_CEILING: usize = 20_000;
61
61
/// messages.
62
62
pub fn forum_default() -> Self {
63
63
Self {
64
-
max_age: Duration::from_secs(7 * 24 * 60 * 60),
64
+
max_age: Duration::from_hours(168),
65
65
max_messages: 5_000,
66
66
}
67
67
}
70
70
/// messages. A creator may raise it, still bounded by the ceilings.
71
71
pub fn stream_default() -> Self {
72
72
Self {
73
-
max_age: Duration::from_secs(24 * 60 * 60),
73
+
max_age: Duration::from_hours(24),
74
74
max_messages: 5_000,
75
75
}
76
76
}
105
105
Err(ChatError::RetentionTooLong { .. })
106
106
));
107
107
assert!(matches!(
108
-
Retention::new(Duration::from_secs(60), MAX_MESSAGES_CEILING + 1),
108
+
Retention::new(Duration::from_mins(1), MAX_MESSAGES_CEILING + 1),
109
109
Err(ChatError::RetentionTooLong { .. })
110
110
));
111
111
}
122
122
Err(ChatError::RetentionTooShort)
123
123
));
124
124
assert!(matches!(
125
-
Retention::new(Duration::from_secs(60), 0),
125
+
Retention::new(Duration::from_mins(1), 0),
126
126
Err(ChatError::RetentionTooShort)
127
127
));
128
128
}
169
169
Ok(Some(ChatEvent::Gap)) => panic!("buffer was sized to make a gap impossible here"),
170
170
Ok(Some(_)) => received += 1,
171
171
Ok(None) => panic!("stable listener's room was closed out from under it"),
172
-
Err(_) => panic!("stable listener stopped receiving after {received} events"),
172
+
Err(e) => panic!("stable listener stopped receiving after {received} events: {e:?}"),
173
173
}
174
174
}
175
175