From 82b55e30843c700cfd384be064b4083e399c00af Mon Sep 17 00:00:00 2001 From: wtclaude Date: Tue, 1 Sep 2026 15:41:14 -0500 Subject: [PATCH] docs(site): /privacy tells the truth about engagement retention again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ENGAGEMENT.md Phase 14. The deploy-engagement entry in the collection inventory said "Kept until the operator removes them; nothing here expires on its own" and, in its detail, "the delivery log, the suppression list and the per-person rate limits have no retention sweep, so they are as long as the site is old". That was the true answer until Phase 14 landed a sweep, and it is the kind of sentence a Play reviewer reads. It now describes what the code does: a nightly sweep with an operator-settable horizon per table (180 days for the delivery log, 30 for the queue and the rate limits), and the two things that deliberately do NOT expire — an item still waiting to be sent, because it is a message the site still intends to deliver, and the suppression list, because ageing an entry out would mean mailing an address that already bounced. PLAY_DATA_SAFETY.md is unchanged and check:datasafety stays green: deploy-engagement is deployment-scoped, and the Play answers are generated from the app-scoped entries, because Play asks what the app collects rather than what a self-hosted deployment keeps. All ten checks green, 42 tests pass. Co-Authored-By: Claude --- src/data/collection.mjs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/data/collection.mjs b/src/data/collection.mjs index 85d3e76..2af9fb3 100644 --- a/src/data/collection.mjs +++ b/src/data/collection.mjs @@ -452,17 +452,24 @@ export const collected = [ 'operator can see what was suppressed without the list becoming a second address ' + 'book.', retention: { - summary: 'Kept until the operator removes them; nothing here expires on its own', + summary: + 'The delivery log is kept for a period the operator sets (180 days by default) and then ' + + 'swept; the suppression list does not expire', detail: - 'Stated plainly because it is the answer people assume the other way round: ' + - 'the delivery log, the suppression list and the per-person rate limits have no ' + - 'retention sweep, so they are as long as the site is old. Deleting an account ' + - 'detaches its rows from it rather than deleting them — a delivery history stops ' + - 'naming a person, and a suppressed address stays suppressed.', + 'A nightly sweep removes delivery-log entries, finished items from the send queue and the ' + + 'per-person rate-limit rows once they pass the horizon the operator has set for each — ' + + 'the defaults are 180 days for the log and 30 for the other two. Two things deliberately ' + + 'do not expire. An item still waiting to be sent is never swept however old it is, ' + + 'because it is a message the site still intends to deliver. And the suppression list is ' + + 'permanent by design: it records a standing decision to stop mailing an address, and ' + + 'ageing an entry out would mean mailing an address that already bounced or asked to be ' + + 'left alone. An operator can remove an entry from it deliberately, one at a time. ' + + 'Deleting an account detaches its rows from it rather than deleting them — a delivery ' + + 'history stops naming a person, and a suppressed address stays suppressed.', }, source: 'website server/db/schema.sql — engagement_sends, engagement_suppressions, ' + - 'notification_channel_prefs', + 'notification_channel_prefs; server/src/utils/engagementRetentionPrune.js', }, { id: 'deploy-game-data',