Status: implemented, pre-alpha
Retention defines how long this server offers message content for replay and cross-device synchronization. It is not a promise to erase copies already held by IRC clients, exports, backups, filesystem snapshots, or external processors.
Persisted channel messages and authenticated account-pair direct messages use separate, deliberately simple policy scopes:
| Content | Policy |
|---|---|
channel PRIVMSG or NOTICE |
the channel override, or the server channel default |
authenticated direct PRIVMSG or NOTICE |
one server-wide DM policy |
| direct message involving an anonymous endpoint | live-only, as today |
The generalized defaults are 90 days for channels and 180 days for durable direct messages. The first private deployment intends to give its default general room a shorter override of about 30 days, with the exact value left as deployment configuration. Annual planning rooms can select a longer finite period such as roughly 400 days without making every conversation an archive.
Users do not select individual or per-thread DM retention. A single operator-configured server policy avoids conflicting participant preferences and the misleading claim that one person's copy was deleted while the same plaintext remains stored for the other.
An operator defines the allowed channel range and whether indefinite retention is available at all. Within those bounds, an authenticated channel owner or operator may choose:
- live-only history;
- a finite duration suitable for ephemeral, ordinary, or long-cycle rooms;
- the server default by removing an override; or
- indefinite retention only when the server operator explicitly permits it.
The policy applies equally to public, keyed, and invite-only rooms. Content reset ignores every override and removes all server-owned content in its documented scope.
A message captures its effective expiration when accepted. Later policy changes apply to later messages and cannot silently lengthen the lifetime promised when existing content was posted. Pruned content cannot be restored. A separate confirmation-heavy shortening operation may eventually expire existing content immediately; it is not implemented yet. An ordinary retention edit is not also a hidden bulk deletion.
The current effective channel policy must be inspectable from an ordinary IRC client through a vendor command rather than a non-portable mode letter. Native clients show it before or upon joining. A policy change produces a visible channel notification so participants know the storage contract for later messages changed. The server-wide DM duration is disclosed during onboarding, in operator documentation, and through native clients; there is no private recipient preference to probe.
The implemented IRC surface is:
RETENTION #room
RETENTION #room DEFAULT
RETENTION #room LIVE
RETENTION #room <whole-days>
RETENTION #room INDEFINITE
The query is available to anyone who can see the channel; private channels stay
opaque to outsiders. Mutations require an authenticated, joined owner or
operator. Replies are machine-readable RETENTION lines, invalid requests use
bounded FAIL RETENTION responses, and successful changes emit a server
NOTICE to the room. RPL_ISUPPORT advertises RETENTION for discovery.
The server reads the finite defaults, owner-selectable bounds, indefinite
toggle, and prune cadence from the versioned [retention] configuration
section. The existing IRC_CHANNEL_RETENTION_DAYS, IRC_DM_RETENTION_DAYS,
IRC_CHANNEL_RETENTION_MIN_DAYS, IRC_CHANNEL_RETENTION_MAX_DAYS,
IRC_ALLOW_INDEFINITE_RETENTION, and IRC_RETENTION_PRUNE_INTERVAL_SECS
variables remain explicit overrides. Defaults are 90, 180, 1, 400, false, and
3600 respectively. See server configuration. After startup,
the first deployment can set its planned general-room policy with the command
RETENTION #general 30. This is durable room policy rather than a hard-coded
product exception.
Expiration covers persisted PRIVMSG and NOTICE bodies in channels and
durable DMs, including link text and ordinary CTCP-shaped payloads. Exact
direct DCC negotiation and registered-provider XDCC control are live-only and
never enter retained history. Expiration does not
automatically delete accounts, credentials, channels, current topics,
memberships, roles, bans, DM preferences, authority audit rows, or invitation
metadata governed by its own expiry.
When content expires, history queries skip it. A minimal event-envelope tombstone preserves the event ID, conversation ordering, and any live cursor anchor so an old read or delivery marker cannot create a replay gap. The implementation minimizes that envelope: sender attribution, message type, author presentation, body, and expiry are scrubbed. Tombstones retain only the event ID, conversation ID, offset, acceptance time, and structural pruned flag. They are cursor state, not replayable chat history.
Pruning runs before listeners bind and periodically while the process is live. A pruning failure is an operational failure rather than a silently broken privacy promise. SQLite secure deletion, WAL checkpointing, backups, and filesystem snapshot lifecycle remain distinct layers; logical expiration alone is not represented as forensic erasure.