Skip to content

feat(tasks): send slack dms for channel thread @-mentions#72087

Draft
adboio wants to merge 1 commit into
masterfrom
posthog-code/slack-mention-dms
Draft

feat(tasks): send slack dms for channel thread @-mentions#72087
adboio wants to merge 1 commit into
masterfrom
posthog-code/slack-mention-dms

Conversation

@adboio

@adboio adboio commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Problem

@-mentions in PostHog Code channel threads are pull-only today: they're indexed at write time (TaskThreadMessageMention) and surfaced in the client's Activity feed via a 60s poll, with no push notification of any kind. If you're not in the app, you don't find out someone needs you.

This adds an opt-in Slack DM when you're @-mentioned, reusing the team's existing Slack integration (raised in a project-bluebird channel task).

Changes

  • New products/tasks/backend/slack_mention_notifications.py: builds and sends the DM ("Ann mentioned you in #growth" + task title + quoted excerpt + "Open in PostHog" link to the cloud task page). Content is mrkdwn-escaped and truncated; mention tokens render as plain @Name.
  • Dispatch: a Celery task (products/tasks/backend/tasks.py, autodiscovered) fired via transaction.on_commit from _index_thread_message_mentions — the single choke point both human- and agent-authored messages already flow through. Best-effort end to end: one recipient's failure never blocks the others, and nothing can fail message creation.
  • Opt-in preference: new user-scoped CodeUserNotificationSettings model (default off), exposed at GET/POST /api/code/user_settings/ for the PostHog Code client. Recipients are resolved per team at send time (Integration kind slack), so the preference itself doesn't need team scoping.
  • SlackIntegration.lookup_user_id_by_email promoted onto the core helper (ported from the signals product's implementation) — uses users_lookupByEmail, which is already in the always-granted scope set along with chat:write, so no new Slack scopes or re-auth.
  • render_mention_tokens added to mentions.py (pattern switched to named groups, behavior-preserving).

Note

The preference defaults off and is only settable from the (flag-gated) PostHog Code settings UI, so there's no server-side flag check — an opt-in row is an explicit user signal. A companion PostHog Code PR adds the settings toggle.

How did you test this code?

Automated tests added (not run in this sandbox — no Django environment; CI will run them):

  • test_mentions.py: render_mention_tokens cases — catches the DM showing raw @[Name](email) tokens or mangling non-token text.
  • test_mention_slack_notifications.py: opt-in filtering (no row / disabled row → no DM), missing integration and missing Slack account guards, per-recipient failure isolation, agent-author + channel-less fallbacks, escaping/truncation.
  • test_channels_api.py: posting a mention dispatches exactly one DM through on_commit + eager Celery (catches the wiring being dropped); a Slack blow-up still returns 201; settings API defaults, upsert, per-user isolation, and auth.

ruff check and ruff format pass on all touched files. The migration was written by hand (mirrors sibling migrations, db_constraint=False on the user FK per the hot-table rule) — please verify makemigrations --check and hogli build:openapi output; I couldn't run either here.

Automatic notifications

  • Publish to changelog?
  • Alert Sales and Marketing teams?

Docs update

No docs under docs/ cover the mentions feed or Code notification settings yet.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Authored by Claude via a PostHog Code cloud task, directed by the assignee. Repo skills read before writing: /django-migrations, /improving-drf-endpoints, /writing-tests.

Decisions along the way: Celery over Temporal for the send (matches the main app's comment-mention precedent; Temporal here is the long-running-run machinery), cloud web URL over a posthog-code:// deep link (matches post_slack_update.py, works on mobile), a user-scoped opt-in model rather than reusing the signals SignalUserAutonomyConfig (different product, and mentions DM the user directly instead of posting to a chosen channel), and promoting the email→Slack-id lookup onto SlackIntegration because the signals implementation sits behind a product boundary.


Created with PostHog Code

When a thread message @-mentions org members, a Celery task (dispatched on commit from the existing mention-indexing choke point) DMs each mentioned user who opted in, via the team's Slack integration. Opt-in is a new per-user CodeUserNotificationSettings model exposed at /api/code/user_settings/ for the PostHog Code client.

Generated-By: PostHog Code
Task-Id: 69e0939c-e6e1-4efa-9d5e-771b88f03b5a
@adboio adboio self-assigned this Jul 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Hey @adboio! 👋

It looks like your git author email on this PR isn't your @posthog.com address (adambowker98@gmail.com). Since you're on the PostHog team, it's worth pointing your local git author email at your @posthog.com address. Why it matters:

  • Consistent work identity in git history — internal tooling that attributes commits to team members keys off your @posthog.com address.
  • Keeps team contributions easy to tell apart from external community ones when scanning history.

You can fix it for this repo with:

git config user.email "you@posthog.com"

Or set it globally with git config --global user.email "you@posthog.com". No need to redo this PR — just a nudge for next time. 🙂

adboio added a commit to PostHog/code that referenced this pull request Jul 17, 2026
Opt-in setting (default off) in the Slack settings section, gated behind the project-bluebird flag. Reads/writes the new /api/code/user_settings/ endpoint; delivery itself is backend-driven via the team's Slack integration (PostHog/posthog#72087).

Generated-By: PostHog Code
Task-Id: 69e0939c-e6e1-4efa-9d5e-771b88f03b5a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant