Description

Context

Two related cleanup items from the onboarding feature's team-review:

A. Outline doc accumulation, no retention (security WARNING) The 02:00 ET cron creates a new Outline document every day, indefinitely. After 12 months that's ~365 docs in the Community Digest collection, all titled "Community Digest — week of …" with overlapping 7-day windows. Collection becomes unsearchable; older docs drift past mental "this week" and become a discoverability surface for old aggregated activity.

B. outline_url NOT NULL semantics conflict (architecture WARNING) apps/signal-bot/database/060_community_rollups.sql declares outline_url TEXT NOT NULL, but community-rollup.ts writes outline_url: '' for no_activity and failed paths because no doc was actually created. The getLatestCommunityRollup query filters outline_url <> '' to compensate, but semantically it should be NULL.

Acceptance criteria

For (A) — choose one of two strategies and implement:

Option 1: Update-in-place (preferred) — keep one rolling "Community Digest" doc that's overwritten daily. URL stable, search bookmarked.

  • [ ] Track community_digest_doc_id in a single-row config table OR reuse daily_community_rollups with a is_canonical flag
  • [ ] On 02:00 cron: if a canonical doc exists, outlineClient.updateDocument(docId, newMarkdown); else create + flag canonical
  • [ ] Welcome flow continues to use getLatestCommunityRollup (now always returns the same canonical URL)

Option 2: Per-day docs with monthly archival

  • [ ] Keep current per-day creation
  • [ ] Monthly cron (e.g., 03:00 ET on day 1): archive (Outline documents.archive) all rollup docs older than 30 days
  • [ ] daily_community_rollups.archived_at column to track
  • [ ] Welcome flow unchanged

For (B):

  • [ ] New migration apps/signal-bot/database/061_outline_url_nullable.sql:
  ALTER TABLE daily_community_rollups ALTER COLUMN outline_url DROP NOT NULL;
  -- Backfill: any historical rows with empty string become NULL
  UPDATE daily_community_rollups SET outline_url = NULL WHERE outline_url = '';
  • [ ] Update getLatestCommunityRollup filter from outline_url <> '' to outline_url IS NOT NULL
  • [ ] Update persistRow to write null (not '') for non-success rows

Technical hints

  • Outline's documents.update API: https://www.getoutline.com/developers#tag/documents/POST/documents.update
  • Option 1 (update-in-place) is cheaper, avoids the doc-glut problem entirely, and keeps the welcome URL stable forever — recommended unless there's a specific reason to keep weekly snapshots
  • If you go Option 2, also add an admin command to manually archive an old rollup doc

--- *M-tier (100 pts + 40 merge_pr = 140). Combined cleanup; covers schema fix + retention. Half-day of work.*

Relevant files

No relevant files linked yet.

Hints

No hints yet.

Activity

No points have been awarded for this bounty yet.

Comments

No comments yet. Be the first to weigh in.

↑ Top