ADR-0017: Slack chatter retention policy — Neon row lifecycle
- Status: Accepted · Legal Director sign-off: retention windows ratified with inline amendments on app_uninstalled fallback, content-performance data-type carve-out, and GDPR Chapter V trigger scope; full findings in Legal Review section below · Date: 2026-05-31 · Authored by: COO, Legal Director, Security Director (jointly)
- Related: ADR-0015 (Slack live chatter feed), ADR-0014 (Neon + Drizzle data layer), ADR-0016 (data-layer policy)
Note:
docs/slack-strategy.mdand Phase 1 item 13 reference this record as ADR-0016. That slot was taken by the data-layer policy committed the same day (2026-05-31). Renumbered to ADR-0017.docs/slack-strategy.mdrequires a follow-up edit to correct the cross-reference.
Context
ADR-0015 established that Slack messages are ingested into Neon (chatter_messages) via the Events API. It explicitly deferred the question of how long those rows are kept. Without a ratified retention policy:
- Neon storage grows unbounded.
- The legal obligation triggered by
app_uninstalled(delete all data within ~30 days per Slack ToS) has no documented enforcement path. - Phase 2 bot invitations are blocked —
docs/slack-strategy.mdmakes ADR-0016/0017 a Phase 1 prerequisite for all new bot invitations. - Cross-border data residency obligations cannot be scoped until the retention surface is defined.
The Principal approved provisional retention windows on 2026-05-31 (Q5 in docs/slack-strategy.md). Those windows are recorded here as the decision basis. Legal Director must formally review and sign off before this ADR moves from Draft to Accepted and before any Phase 2 bot invitation proceeds.
Options considered
Option A — No retention limit (keep all rows indefinitely).
Rejected. Unbounded Neon storage, unclear legal standing under GDPR Chapter V once a non-US learner joins, and no deletion path for app_uninstalled obligation.
Option B — Uniform retention window across all channels (e.g. 90 days). Rejected. Operational signals (#alerts, #deploys) have lower value after 90 days; governance and decision records (#governance, #decisions, #briefings) must survive 2 years minimum for audit and accountability purposes.
Option C — Per-channel-category windows with Archivist export gate for durable records. Chosen. Aligns window to the value lifetime of the content, satisfies the Principal’s governance needs, and provides a deletion-block mechanism for channels where export is required before rotation.
Decision
Retention windows for rows in chatter_messages are set per channel category as follows:
| Channel category | Channels | Neon retention window | Archivist export required before deletion |
|---|---|---|---|
| Operational | #alerts, #deploys, #content-performance ¹ | 90 days rolling | No |
| Incident lifecycle | #incidents | 2 years | Yes |
| Governance | #governance | Archive-before-rotation | Yes — hard dependency; deletion is blocked until Archivist confirms export complete |
| Decisions and briefings | #decisions, #briefings | 2 years | Yes |
| Transient incident channels | #inc-* | Deleted at resolution | Yes — Archivist export blocks deletion |
| Private / bot-excluded | #brand-approvals, #research-findings, #finance-alerts, #legal-compliance | N/A — not ingested | N/A |
¹ #content-performance data-type constraint (Legal Director amendment): The 90-day operational window applies to aggregate YouTube performance signals only (views, CTR, watch-time delivered via PubSubHubbub webhook). No learner-identifying data may enter this channel’s Neon rows. Any addition of a learner-identifying field to
chatter_messagesrows sourced from #content-performance constitutes learner data subject to Open Item 3 / the separate learner-voice ADR, and is blocked until that ADR is ratified.
Enforcement mechanism
Enforcement requires two schema additions not yet present in db/schema.ts:
channel_categorycolumn onchatter_channels— text enum identifying the retention class (operational|incident|governance|decisions_briefings|transient_incident). Engineering Director owns the Drizzle migration.archived_atcolumn onchatter_messages— nullable timestamp. Set by the Archivist export process. The DELETE job must checkarchived_at IS NOT NULLbefore deleting any row in a channel category where export is required.
Until these columns are migrated and populated, the deletion cron must not run. Engineering Director is responsible for confirming migration is complete and columns are populated before enabling the cron.
Deletion cron
A nightly Vercel cron job (or Neon pg_cron job) executes the following pattern:
-- Operational channels: delete without export gate
DELETE FROM chatter_messages
WHERE channel IN (
SELECT name FROM chatter_channels WHERE channel_category = 'operational'
)
AND ts < NOW() - INTERVAL '90 days';
-- Durable channels: delete only after Archivist export confirmed
DELETE FROM chatter_messages
WHERE channel IN (
SELECT name FROM chatter_channels
WHERE channel_category IN ('incident', 'governance', 'decisions_briefings')
)
AND ts < NOW() - INTERVAL '2 years'
AND archived_at IS NOT NULL;
-- Transient incident channels: delete at resolution, export required
-- Triggered by resolution event, not the nightly cron. Archivist export blocks deletion.
The nightly cron is a Phase 2 prerequisite. Engineering Director owns implementation and deployment. The cron runs only after the schema migration is complete and Legal Director has ratified this ADR.
app_uninstalled obligation
When the Slack app is uninstalled, all ingested messages must be deleted from Neon within approximately 30 days per Slack platform ToS (Section 3). The /api/slack/events handler must process the app_uninstalled event by scheduling or immediately executing a full DELETE FROM chatter_messages across all channels. Engineering Director owns implementation. Legal Director confirms the exact obligation and timeline.
Legal Director amendment (2026-05-31): The obligation is a maximum of 30 days; sooner is permissible and preferred. The current handler at intranet/src/pages/api/slack/events.ts (lines 297–307) deletes all rows from chatter_messages and chatter_channels immediately on receipt of the app_uninstalled event — this satisfies the obligation. However, the catch block ACKs the 200 even when the DELETE throws, meaning a failed deletion is silently treated as success. This is a gap. Engineering Director is required to implement a fallback verification mechanism: a periodic job (nightly Vercel cron or equivalent) that (a) checks current Slack app installation status and (b) if the app is uninstalled, confirms both tables are empty and re-executes the DELETE if any rows remain. This verification job must be in place before Phase 2 goes live. The fallback does not extend the 30-day window; it closes the failure-mode gap in the immediate deletion path.
Additionally, Usage Norm 13 (docs/slack-strategy.md) requires written disclosure to any non-Principal human who joins the workspace that their messages are mirrored to Neon. That disclosure must explicitly state that their messages will be deleted from Neon if the Slack app is uninstalled. This is a documentation obligation on the Principal (or PA) at the time of workspace invitation — not a product code change.
Legal Review — Legal Director findings (2026-05-31)
The following items were open at draft. All three are resolved below. This section is the Legal Director’s formal sign-off record.
Item 1 — GDPR Chapter V cross-border data transfer
Finding: Not currently in scope. Hard gate documented for first non-US onboarding event.
GDPR Chapter V governs transfers of personal data to third countries by a data controller or processor established in the EU/EEA, or when offering goods or services to, or monitoring the behavior of, data subjects in the EU/EEA (GDPR Articles 3(1) and 3(2)). The current facts are: the Principal is US-based; there is no EU/EEA establishment; the platform is single-user with no current offering to EU/EEA residents; the Slack workspace is an internal operational tool with no EU/EEA data subjects. Chapter V does not apply today.
(a) Retention window adjustment: No adjustment is required for current operations. The 90-day and 2-year windows are defensible under Article 5(1)(e) (storage limitation) — operational signals at 90 days, governance and decision records at 2 years are proportionate to legitimate internal operational purposes. Chapter V addresses transfer mechanism (geographic location and safeguards), not retention duration; Article 5(1)(e) minimization is what would touch duration, and these windows satisfy it.
(b) Neon us-east-1 region: Sufficient for current operations. No EU-region database is required as a pre-launch gate condition for Phase 2. The gate condition is the first non-US onboarding event (as stated in Q6).
© Minimum legal basis and safeguard for when the gate triggers: When a non-US user (either a learner on the platform or a non-Principal human joining the Slack workspace) joins and EU/EEA residency cannot be excluded, the following must be resolved before that onboarding proceeds:
- Applicable framework determination — confirm whether GDPR, UK GDPR, or another regime applies based on user geography.
- Transfer mechanism — the preferred mechanism is an adequacy decision if one covers the jurisdiction (e.g. US-EU Data Privacy Framework for US-based processors). Legal Director must verify at that time whether Neon participates in the DPF. If not, Standard Contractual Clauses (Module 2: Controller-to-Processor) are the fallback, and a Transfer Impact Assessment (TIA) is required before SCCs are executed. The Principal cannot proceed with EU/EEA onboarding on the assumption that the DPF covers Neon — that must be confirmed.
- Scope of trigger — the Q6 gate as stated in
docs/slack-strategy.mdcovers “first non-US learner.” This ADR extends that trigger: the same gate applies to any non-Principal human joining the Slack workspace, not only learners. The broader trigger must be reflected in the cross-border data residency ADR (the follow-on decision deferred in this ADR’s Consequences section). Legal Director and Engineering Director own that ADR jointly.
Required action before EU/EEA onboarding: Legal Director verifies DPF participation by Neon; if not confirmed, SCCs + TIA are required. Engineering Director documents Neon region in ADR-0014 or the follow-on cross-border ADR. This is a hard gate — no EU/EEA onboarding proceeds until the follow-on ADR is ratified.
Item 2 — app_uninstalled 30-day deletion obligation
Finding: Obligation confirmed. Immediate deletion satisfies the requirement. A fallback verification mechanism is required before Phase 2.
The Slack Platform Terms of Service (Section 3, “Your Customers’ Data”) require that upon app uninstallation, the app must promptly delete all workspace customer data in its possession. Slack’s published guidance specifies a maximum of 30 days. Deletion sooner than 30 days is permissible and is the preferred posture.
(a) Does immediate deletion satisfy the obligation? Yes. The current handler at intranet/src/pages/api/slack/events.ts (lines 297–307) deletes all rows from chatter_messages and chatter_channels immediately on receipt of app_uninstalled. Immediate deletion exceeds the 30-day obligation. The obligation is satisfied on the happy path.
(b) Is the handler sufficient, or is a fallback required? The handler is insufficient on its own. The catch block (lines 303–305) logs the error and the function returns HTTP 200 unconditionally — a failed DELETE is ACKed as success to Slack and is never retried. A database error during the delete would leave data in Neon with no automatic recovery path and no alert to the Principal. This is a compliance gap: the 30-day obligation runs from the uninstall event regardless of whether the application-layer delete succeeded.
Requirement for Engineering Director (Phase 2 prerequisite): Implement a periodic verification job — nightly cadence is sufficient — that (a) checks current Slack app installation status via the Slack API, and (b) if the app is uninstalled (status returns a revocation or absence of valid tokens), confirms COUNT(*) FROM chatter_messages is zero and re-executes the full DELETE if any rows remain. The job must emit a logged alert if rows are found after an uninstall event. This is a compliance requirement, not optional hardening.
© Documentation obligation: Usage Norm 13 (docs/slack-strategy.md) requires written disclosure to any non-Principal human joining the workspace that their messages are mirrored to Neon and surfaced on the KLMS intranet. That disclosure must explicitly state that their messages will be deleted from Neon if the Slack app is uninstalled. This is an obligation on the Principal (or PA) at the time of workspace invitation — not a product code change. The PA should maintain a template for this disclosure notice.
Item 3 — Learner-voice channel separate ADR gate
Finding: Gate correctly placed. No inadvertent learner data capture in this ADR, with one amendment required for #content-performance.
(a) Gate placement: The gate is correctly placed. No learner data should enter Neon under this ADR’s authority. The three elements that must be covered in a dedicated learner-data ADR before any learner-facing channel is admitted are: (1) lawful basis and consent mechanism for processing learner-generated content; (2) purpose limitation — what the data may be used for and what is prohibited; (3) retention window and deletion schedule specific to learner data, which may differ materially from the operational and governance windows in this ADR. This ADR’s retention windows do not apply to learner data and must not be construed as pre-authorizing any learner data collection.
(b) Does this ADR inadvertently capture learner data? One channel requires a carve-out. The #content-performance channel is classified as Operational (90-day rolling, no Archivist export required). The strategy document describes it as carrying aggregate YouTube performance signals (views, CTR, watch-time) delivered via PubSubHubbub — that is not learner data. However, the ADR as originally drafted contained no restriction on what data may flow through that channel. An inline amendment has been added to the retention table (footnote ¹ on the Operational row) specifying that the 90-day window applies to aggregate YouTube signals only, and that any learner-identifying field in chatter_messages rows sourced from #content-performance is subject to the learner-voice ADR gate. This amendment closes the gap without changing the retention window.
Consequences
Positive:
- Retention windows are ratified and documented, unblocking Phase 2 bot invitations once Legal Director signs off.
- Per-category windows align storage cost with content value: operational signals rotate at 90 days; governance and decisions records survive 2 years.
- The Archivist export gate ensures no durable record is lost to automated deletion before it is preserved.
- The
app_uninstalledobligation has a named owner and a documented enforcement path.
Negative / trade-offs:
- Two schema migrations (
channel_category,archived_at) are required before enforcement can begin. Until they land, the cron must not run. - The
archive-before-rotationpolicy for #governance has no hard deadline — it depends on the Archivist confirming export. If the Archivist process is not operational, rows will accumulate indefinitely rather than be silently deleted. - The
app_uninstalledfallback verification job (Legal Director requirement, Item 2) is a new Phase 2 prerequisite that was not present in the draft. Engineering Director owns implementation; it must be in place before Phase 2 goes live.
Follow-on decisions deferred:
- Learner-voice channel retention — requires a separate ADR (Legal Director leads).
- Cross-border data residency ADR — Engineering Director + Legal Director, triggered by first non-US learner.
- Outbound posting ADR — Engineering Director drafts, C-suite reviews, Principal approves (Phase 2 prerequisite).