This document describes the integration notification system: how notifications are produced, stored, polled, configured, and shown in the app.
- Notify users about meaningful integration events (GitHub/Jira/Confluence).
- Deduplicate events using provider-specific fingerprints.
- Support read/unread lifecycle and sorting for in-app notification center.
- Show native desktop notifications and route click actions back into app details.
- Keep polling scoped and configurable.
flowchart LR
scheduler[Notification scheduler] --> service[Notification service]
service --> registry[Notification definitions registry]
registry --> providers[Provider pollers]
providers --> dedupe[Fingerprint dedupe]
dedupe --> db[(notifications table)]
service --> desktop[Native desktop notifications]
desktop --> openEvt[notifications:open event]
db --> ipc[Notification IPC handlers]
ipc --> menu[Header notification center]
ipc --> settings[Settings notifications page]
- Scheduler:
electron/notifications/scheduler.ts - Polling + insertion orchestration:
electron/notifications/service.ts - Notification definitions and provider-specific polling:
electron/notifications/registry.ts - Desktop notification dispatch:
electron/notifications/desktop.ts - Event fanout for renderer updates/open actions:
electron/notifications/events.ts - IPC surface:
electron/ipc/notifications.ts
- Polling runs on an interval (
notifications_poll_interval_ms) with a default. - Polling target is the developer marked
is_current_user = 1. - Only notification definitions for active integrations are considered.
- Global enable/disable is controlled by
notifications_enabled.
A definition in registry.ts includes:
integration(e.g.github,jira)notificationType(stable identifier)label(settings display)defaultEnabledstrategymetadata (id,version)poll(developerId)to fetch candidate eventsfingerprint(event)to derive dedupe key
This keeps dedupe logic customizable per integration and notification type.
Migration: electron/db/schema.ts (v14).
Stores concrete delivered events:
iddeveloper_idintegrationnotification_typefingerprinttitle,bodypayload_jsonsource_urlstatus(new|read)event_updated_atcreated_atread_at
Deduplication is enforced by:
UNIQUE (developer_id, integration, notification_type, fingerprint)
Per notification-type settings:
integrationnotification_typeenabledfingerprint_strategy_jsonupdated_at
Component: src/components/notifications/NotificationCenter.tsx.
- Always-present bell icon in headers.
- Unread badge overlay.
- Dropdown list sorted by unread first, then most recent.
- Click item:
- marks notification read
- opens details modal
- Includes “Mark all read”.
Integrated in:
src/components/layout/TopBar.tsxsrc/components/layout/SettingsLayout.tsxsrc/components/layout/ReferenceLayout.tsx
Page: src/pages/settings/Notifications.tsx (/settings/notifications).
- Global notifications toggle.
- Poll interval control.
- Per-notification type enable/disable controls.
electron/ipc/notifications.ts provides:
notifications:listnotifications:getnotifications:mark-readnotifications:mark-all-readnotifications:unread-countnotifications:preferences:getnotifications:preferences:setnotifications:config:getnotifications:config:setnotifications:check-now
Renderer receives push events via preload:
notifications:open(desktop click -> open details)notifications:changed(refresh notification menu state)
- GitHub:
review_requested - GitHub:
github_stale_pr— open authored PRs with no reviews yet and age from last update past warn/danger thresholds (uses cached PRs; thresholds viapr_stale_warn_days/pr_stale_danger_days) - Jira:
assigned_or_watched_ticket_updated - Confluence:
page_activity
- Native notifications may appear as “Electron” in local dev; packaged builds use app bundle identity.
- Menu currently requests up to 50 notifications and uses internal scrolling for long lists.
- Fingerprint strategy metadata is persisted so strategy evolution can be managed safely over time.
Stale PR thresholds (pr_stale_warn_days / pr_stale_danger_days) are documented with other config keys in database.md. The dashboard PR list uses the same default ages (3d / 7d) for visual staleness; see metrics.md.
- Features — My Day / Reviews / command palette integration with notifications data