Skip to content

PM-5449: Send manual phase change emails per recipient - #166

Merged
jmgasper merged 1 commit into
developfrom
PM-5449
Oct 9, 2026
Merged

jmgasper merged 1 commit into
developfrom
PM-5449

Conversation

@jmgasper

@jmgasper jmgasper commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

What was broken

When a challenge phase was manually closed or reopened from the review app, the phase change email listed every notified member in the To field, so each member could see the other members' email addresses. Autopilot phase change emails were not affected because autopilot already publishes one email event per recipient.

Root cause

Manual phase changes go through PATCH /challenges/:id/phases/:phaseId, which sends mail through helper.sendPhaseChangeNotification. That helper put the whole recipient list into a single external.action.email bus event. The email service then sends that event as one SendGrid message with all recipients in To.

PM-5763 (b362f1d, already on develop and master) changed ChallengePhaseService to call the helper once per recipient. However, the helper still merged any multi-recipient list into one shared email, so the privacy guarantee depended on every caller getting this right.

What was changed

  • helper.sendPhaseChangeNotification now publishes a separate external.action.email event for each recipient, with a single address in recipients. The privacy guarantee now applies where the email event is built, so callers cannot expose addresses.
  • A failed publish for one recipient is logged and the remaining recipients are still notified.
  • The helper's doc comment was updated to describe this.

Any added/updated tests

  • Added test/unit/phase-change-notification-helper.test.js. It loads the helper against a stubbed bus client and checks two things:
    • a multi-recipient call publishes one email event per recipient, each with exactly one address;
    • a failed publish for one recipient does not block the others.
  • Both tests fail against the previous helper and pass with this change.
  • Full unit run (placeholder DATABASE_URL, no local Postgres): 79 passing / 82 failing. Clean develop gives 77 / 82, so the only change is the 2 new passing tests. The 82 failures are pre-existing DB-backed hooks.
  • eslint (the repo lint script's globs) and nest build both pass.

🤖 Generated with Claude Code

What was broken

When a challenge phase was manually closed or reopened from the review app, the phase change email listed every notified member in the To field, so each member could see the other members' email addresses. Autopilot phase change emails were not affected because autopilot already publishes one email event per recipient.

Root cause

Manual phase changes go through PATCH /challenges/:id/phases/:phaseId, which sends mail through helper.sendPhaseChangeNotification. That helper put the whole recipient list into a single external.action.email bus event. The email service then sends that event as one SendGrid message with all recipients in To. PM-5763 changed ChallengePhaseService to call the helper once per recipient, but the helper still merged any multi-recipient list into one shared email.

What was changed

helper.sendPhaseChangeNotification now publishes a separate external.action.email event for each recipient, with a single address in recipients. This applies the privacy guarantee at the point where the email event is built, so callers cannot expose addresses. A failed publish for one recipient is logged and the remaining recipients are still notified. The helper's doc comment was updated to describe this.

Any added/updated tests

Added test/unit/phase-change-notification-helper.test.js. It loads the helper against a stubbed bus client and checks two things: a multi-recipient call publishes one email event per recipient, each with exactly one address, and a failed publish for one recipient does not block the others. Both tests fail against the previous helper and pass with this change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jmgasper
jmgasper merged commit 22e913f into develop Oct 9, 2026
5 checks passed
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