fix(retention): a tiny or brand-new retention value can't wipe a room (#298) #367

Merged
jared merged 1 commits from fix/retention-floor-grace into lotus 2026-10-16 22:48:19 -04:00
Owner

Fixes #298.

m.room.retention can be set to anything by anyone with state power. A fat-fingered max_lifetime: 1000 blanked the timeline for every Lotus user. For members with Enforce Message Retention on, the sweeper also redacted all their messages within a minute. The RETENTION_MIN_MS floor existed but was never applied.

Change

  • effectiveRetentionMs(): anything under 10 minutes counts as off. It's used by both the sweeper and the timeline's hiding.
  • 24 h deletion grace: the sweeper never deletes under a policy that's less than a day old. A mistake or a malicious change can be reverted before anything is lost. Local hiding of expired messages still applies at once.

Verified headless, with the issue's own repro (enforcement on, then max_lifetime: 1000):

  • Before: timeline blank, all 4 messages redacted.
  • After: all 4 messages stay visible, and none are redacted after 45 s.

Unit tests cover the floor and the grace window.

Not included: showing the room's retention in the header, the issue's third suggestion. It's a separate UI change.

tsc clean · unit tests pass · ESLint clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5

Fixes #298. `m.room.retention` can be set to anything by anyone with state power. A fat-fingered `max_lifetime: 1000` blanked the timeline for every Lotus user. For members with **Enforce Message Retention** on, the sweeper also **redacted all their messages within a minute**. The `RETENTION_MIN_MS` floor existed but was never applied. **Change** - `effectiveRetentionMs()`: anything **under 10 minutes counts as off**. It's used by both the sweeper and the timeline's hiding. - **24 h deletion grace:** the sweeper never deletes under a policy that's less than a day old. A mistake or a malicious change can be reverted before anything is lost. Local hiding of expired messages still applies at once. **Verified** headless, with the issue's own repro (enforcement on, then `max_lifetime: 1000`): - **Before:** timeline blank, all 4 messages redacted. - **After:** all 4 messages stay visible, and none are redacted after 45 s. Unit tests cover the floor and the grace window. **Not included:** showing the room's retention in the header, the issue's third suggestion. It's a separate UI change. `tsc` clean · unit tests pass · ESLint clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
jared added 1 commit 2026-10-16 21:37:23 -04:00
fix(retention): a tiny or brand-new retention value can't wipe a room (#298)
CI / Build & Quality Checks (pull_request) Successful in 2m3s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 27s
CI / Playwright smoke (e2e) (pull_request) Successful in 11m33s
8b2322f751
m.room.retention can be set to anything by anyone with state power. A
fat-fingered `max_lifetime: 1000` blanked the timeline for every Lotus
user and, for members with "Enforce Message Retention" on, the sweeper
redacted all their messages within a minute. The RETENTION_MIN_MS floor
existed but was never applied.

- effectiveRetentionMs(): anything under 10 min counts as off; used by
  getRoomRetentionMs (sweeper) and the timeline's hiding.
- The sweeper never deletes under a policy less than 24 h old, so a
  mistake or a malicious change can be reverted before anything is lost.
  (Local hiding of expired messages still applies at once.)

Verified headless (the issue's repro, enforcement on): after
max_lifetime 1000, all 4 messages stay visible and none are redacted
after 45 s (before: timeline blank, all 4 redacted). Unit tests for the
floor and the grace window.

Fixes #298

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
jared merged commit 0c5cf4109a into lotus 2026-10-16 22:48:19 -04:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/cinny#367