Repository navigation
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 throughhelper.sendPhaseChangeNotification. That helper put the whole recipient list into a singleexternal.action.emailbus 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
ChallengePhaseServiceto 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.sendPhaseChangeNotificationnow publishes a separateexternal.action.emailevent for each recipient, with a single address inrecipients. The privacy guarantee now applies where the email event is built, so callers cannot expose addresses.Any added/updated tests
test/unit/phase-change-notification-helper.test.js. It loads the helper against a stubbed bus client and checks two things:DATABASE_URL, no local Postgres): 79 passing / 82 failing. Cleandevelopgives 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) andnest buildboth pass.🤖 Generated with Claude Code