Skip to content

PROD : OUT-4000 | Filter out email notifications according to iu notification preference - #1396

Merged
arpandhakal merged 5 commits into
productionfrom
main
Jul 23, 2026
Merged

PROD : OUT-4000 | Filter out email notifications according to iu notification preference#1396
arpandhakal merged 5 commits into
productionfrom
main

Conversation

@arpandhakal

Copy link
Copy Markdown
Collaborator

No description provided.

arpandhakal and others added 4 commits July 21, 2026 17:44
…n preference

Complete OUT-3929 IU email gating now that Copilot exposes
GET /v1/internal-users/:id/notification-settings.

Hybrid gating, split by send path:
- Single emails: attach the resolved notificationSettingId on the body
  so the platform gates the send (re-enabled in NotificationService).
- Grouped summaries: read the recipient IU's prefs and drop events for
  categories whose email is disabled before composing the summary
  (filterEventsForIuPreferences), fail-open on read error.

- add CopilotAPI.getInternalUserNotificationSettings (not cached; live pref)
- add InternalUserNotificationSettingsSchema
- add iuEmailPreference helpers (disabledEmailSettingIds, isIuEmailGloballyOff)
- tests for the helpers and the flush filter; flip obsolete ungated guard

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Only treat email as globally enabled when emailSettings is explicitly
"active" (case-insensitive, trimmed). Any other value — a different
disabled string, unexpected casing, or a missing field — is treated as
not activated, so a global opt-out is never bypassed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…isableEmail

emailSettings "not_active" does NOT mean the IU receives no email — a test
IU with emailSettings=not_active still expects (and should get) comment
emails. Gating on it suppressed every grouped IU email for that IU. The
reliable signal is the per-category disableEmail flag, so gate on that alone.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-preference

OUT-4000 |  Filter out email notifications according to iu notification preference
@linear-code

linear-code Bot commented Jul 23, 2026

Copy link
Copy Markdown

OUT-4000

@vercel

vercel Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tasks-app Ready Ready Preview, Comment Jul 23, 2026 4:07pm

Request Review

@vercel

vercel Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Deployment failed with the following error:

Deploying Serverless Functions to multiple regions is restricted to the Pro and Enterprise plans.

Learn More: https://vercel.link/multiple-function-regions

@greptile-apps

greptile-apps Bot commented Jul 23, 2026

Copy link
Copy Markdown

Greptile Summary

This PR enables Internal User notification-setting IDs and filters buffered grouped-email events using live IU preferences.

  • Resolves and attaches category setting IDs during notification creation and buffering.
  • Adds a Copilot API method and schemas for reading an IU's notification preferences.
  • Filters disabled categories before replaying individual emails or composing grouped summaries.
  • Adds unit coverage for setting extraction, filtering, and preference-read failures.

Confidence Score: 3/5

This PR should not merge until preference-read failures stop delivering emails that recipients explicitly disabled.

The new catch path converts any exhausted Copilot or response-validation failure into an ungated send, after which the affected buffer rows are marked sent and deleted.

src/jobs/notifications/flush-grouped-email.ts

Important Files Changed

Filename Overview
src/jobs/notifications/flush-grouped-email.ts Adds live preference filtering, but its fail-open error path delivers opted-out email and permanently consumes the buffered events.
src/app/api/notification/notification.service.ts Re-enables IU setting-ID resolution and propagates the resolved ID to immediate and buffered notification payloads.
src/utils/CopilotAPI.ts Adds the retried Copilot request used to retrieve an IU's current notification preferences.
src/types/common.ts Defines the response schema for per-surface and per-category IU notification preferences.
src/app/api/notification/iuEmailPreference.ts Extracts setting IDs for categories whose email surface is disabled.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[NotificationService resolves category setting ID] --> B[Buffer grouped email event]
  B --> C[Grouped-email flush]
  C --> D[Read IU notification preferences]
  D -->|Success| E[Remove disabled categories]
  D -->|Failure| F[Return all events unfiltered]
  E --> G{Events remaining?}
  F --> G
  G -->|One| H[Replay individual email]
  G -->|Multiple| I[Send grouped summary]
  G -->|None| J[Send nothing]
  H --> K[Mark sent and delete rows]
  I --> K
Loading

Reviews (1): Last reviewed commit: "Merge branch 'production' into main" | Re-trigger Greptile

Comment on lines +107 to +113
} catch (e) {
logger.error('flush-grouped-email: failed to read IU prefs; sending ungated', {
recipientIuId,
error: serializeError(e),
})
return events
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Preference failures bypass email opt-outs

When the Copilot preference request fails for an IU with disabled email categories, this catch returns every event unfiltered, causing opted-out emails to be sent before their buffer rows are marked sent and deleted.

Knowledge Base Used: Notifications flow: from task/comment event to delivered notification

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will create another pr for this.

@arpandhakal
arpandhakal merged commit 4150ef1 into production Jul 23, 2026
2 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