Library · Conversations & archives / Games & interaction
Discord Activity Privacy Core
Decide what an activity policy permits, then minimize retained records and plan expiry.
Repository: CinvanaAI/discord-activity-privacy-core
Recorded synthetic example. Source with a complete offline example.
See the idea in action.
Two rejected decisions, one minimized record with no plaintext, a dry-run backfill plan, and one expired record ID.
One synthetic Discord message event and three policy states.
{
"input": {
"eventId": "event-1",
"guildId": "synthetic-guild",
"actorId": "synthetic-actor",
"channelId": "synthetic-channel",
"kind": "message_created",
"occurredAt": "2026-01-02T03:04:05Z",
"content": "This plaintext is deliberately not retained.",
"attachmentCount": 1
},
"disabled": {
"accepted": false,
"reasons": [
"archive-disabled",
"guild-not-allowed",
"actor-consent-missing",
"event-kind-not-allowed",
"pseudonym-key-too-short"
]
},
"missingConsent": {
"accepted": false,
"reasons": [
"actor-consent-missing"
]
},
"accepted": {
"accepted": true,
"record": {
"schemaVersion": 1,
"recordId": "b322de3f49c1771bd1dd76f8",
"guildRef": "9091e479600ff22e9c46d965",
"actorRef": "d005ed00a34cb9a806dceb82",
"channelRef": "648bf417ad9b2ca6a474b30f",
"kind": "message_created",
"occurredAt": "2026-01-02T03:04:05.000Z",
"attachmentCount": 1
}
},
"digestMode": {
"accepted": true,
"record": {
"schemaVersion": 1,
"recordId": "b322de3f49c1771bd1dd76f8",
"guildRef": "9091e479600ff22e9c46d965",
"actorRef": "d005ed00a34cb9a806dceb82",
"channelRef": "648bf417ad9b2ca6a474b30f",
"kind": "message_created",
"occurredAt": "2026-01-02T03:04:05.000Z",
"attachmentCount": 1,
"contentLength": 44,
"contentDigest": "1253cd8fee9dd61b032eb43d0f8c7ed318f4c6889940301a5f80ff359ef1da34"
}
},
"invalidRetentionBackfill": {
"status": "denied",
"reasons": [
"retention-out-of-bounds"
],
"operations": [],
"estimatedMaximumMessages": 0
},
"plaintextRetained": false,
"backfill": {
"status": "dry-run",
"reasons": [
"execution-not-requested"
],
"operations": [
{
"channelRef": "648bf417ad9b2ca6a474b30f",
"maxMessages": 100
}
],
"estimatedMaximumMessages": 100
},
"expiredRecords": [
"b322de3f49c1771bd1dd76f8"
],
"discordCalls": 0
}Try the example.
From the repository root, follow the dependency requirements in the README. This example uses supplied synthetic material.
npm ci npm run demo
Two rejected decisions, one minimized record with no plaintext, a dry-run backfill plan, and one expired record ID.
Complete setup and instructions ↗The interesting part.
Collection defaults off, requires both guild/actor consent, pseudonymizes references, and separates backfill planning from execution.
Where it came from.
A June 2025 TypeScript/Discord.js activity experiment.
June 2025 — Historical TypeScript/Discord.js source experiment; not the public continuation date. Source ↗
Reworks the concept around consent, minimized data, private targets and bounded dry-run-first work.
The raw historical implementation and its privacy defaults are not this public package.