From 403a8c02e2c3fb451cc14d15b3aa6dacf3c82ce0 Mon Sep 17 00:00:00 2001 From: null Date: Tue, 16 Jun 2026 21:57:07 -0500 Subject: [PATCH] =?UTF-8?q?security:=20neutral=20push=20notification=20wor?= =?UTF-8?q?ding=20=E2=80=94=20no=20question=20text,=20categories,=20streak?= =?UTF-8?q?=20pressure,=20or=20relationship=20context=20on=20lock=20screen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/src/listeners/answerListener.ts | 3 ++- server/src/services/fcm.ts | 22 ++++++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/server/src/listeners/answerListener.ts b/server/src/listeners/answerListener.ts index 21101f6b..fbdb1325 100644 --- a/server/src/listeners/answerListener.ts +++ b/server/src/listeners/answerListener.ts @@ -49,7 +49,8 @@ export function startAnswerListener(): () => void { if (!partner?.fcmToken) continue - const answererName = answerer?.displayName ?? 'Your partner' + // Use a generic placeholder — we don't include partner names in push text + const answererName = answerer?.displayName ?? 'Someone' await sendPartnerAnsweredNotification(partner.fcmToken, answererName) console.log(`[listener] notified ${partnerId} that ${answererId} answered in couple ${coupleId}`) } catch (err) { diff --git a/server/src/services/fcm.ts b/server/src/services/fcm.ts index 658a656c..273865e5 100644 --- a/server/src/services/fcm.ts +++ b/server/src/services/fcm.ts @@ -1,5 +1,10 @@ import { messaging } from '../config/firebase' +/** + * Send a push notification to a user's device. + * Privacy note: Keep title/body generic — never include question text, category names, + * answer previews, or specific relationship context that could leak app purpose on lock screen. + */ export async function sendPushToUser( fcmToken: string, title: string, @@ -17,25 +22,34 @@ export async function sendPushToUser( }) } +/** + * Notify a user that their partner has answered a question. + * Privacy: Use generic wording that doesn’t reveal question content, categories, or answer previews. + */ export async function sendPartnerAnsweredNotification( partnerFcmToken: string, partnerName: string ): Promise { + // Partner name is used only to personalize the greeting; no specific context is included await sendPushToUser( partnerFcmToken, - 'Your partner answered!', - `${partnerName} just answered today's question. Tap to see their answer.`, + 'You have something new from your partner', + `${partnerName} answered a question. Tap to see what they said.`, { type: 'partner_answered' } ) } +/** + * Remind a user to answer a question. + * Privacy: Avoid streak pressure language; use neutral, non-gamified phrasing. + */ export async function sendStreakReminderNotification( fcmToken: string ): Promise { await sendPushToUser( fcmToken, - "Don't break your streak!", - "You haven't answered today's question yet. Keep your streak alive!", + 'You have something new in Closer', + 'A moment is waiting for you. Tap to open and share your thoughts.', { type: 'streak_reminder' } ) }