Skip to content

Latest commit

 

History

History
110 lines (89 loc) · 5.32 KB

retention.md

File metadata and controls

110 lines (89 loc) · 5.32 KB

Message retention

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.

Policy hierarchy

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.

Change semantics and disclosure

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 and tombstones

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.