---
id: SVC-PFM-NOT-notifications
title: Notifications Service Module
product_area: platform
module: notifications
repository: services-platform
source_module: modules/notifications
revision: 1
status: draft
design_intent: proposed
implementation_evidence: partially-observed
inference: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
owns:
- DOM-PFM-NOT-003
does_not_own:
- Communications owns association templates, recipient mail and sender protection; future staff e-mail
  uses that delivery service.
- Eligibility owns responsibility changes and their producer integration.
- Security and workspace lifecycle own provisioning and its alert trigger; operational system scope uses
  the shared workspace store.
- Security owns accounts, roles, evaluated permissions and support access grants used for audience and
  support reads.
- Eligibility owns the bell’s attention presentation and the legacy attention redirect.
- Integrations owns customer chat connections, while Operations supplies job execution and partition maintenance.
operations:
- operation_id: getNotificationsHealth
  intent: Expose the API health and deployed build for operational checks.
  access: public
  permission: 'none: public route'
  realises: []
  published_to_submissions: 'not published: service health is an operational read without a submission
    binding.'
- operation_id: listMyNotifications
  intent: Page through the caller’s inbox by newest item, optionally restricting personal view, category
    or time.
  access: console
  permission: platform.notifications.use
  realises:
  - CAP-PFM-NOT-009
  published_to_submissions: 'not published: personal notice inspection belongs to the inbox service.'
- operation_id: getMyNotificationSummary
  intent: Return unread totals for applicable, unarchived personal notices and their categories.
  access: console
  permission: platform.notifications.use
  realises:
  - CAP-PFM-NOT-009
  published_to_submissions: 'not published: personal notice inspection belongs to the inbox service.'
- operation_id: getMyNotification
  intent: Return the caller’s notice, channel results and saved audience explanation.
  access: console
  permission: platform.notifications.use
  realises:
  - CAP-PFM-NOT-009
  - CAP-PFM-NOT-010
  published_to_submissions: 'not published: personal notice inspection belongs to the inbox service.'
- operation_id: markMyNotificationRead
  intent: Record that the caller has read a notice, preserving an existing read timestamp.
  access: console
  permission: platform.notifications.use
  realises:
  - CAP-PFM-NOT-009
  published_to_submissions: 'not published: read and archive changes organize the authenticated person’s
    inbox.'
- operation_id: markMyNotificationUnread
  intent: Clear the read mark on a notice belonging to the caller.
  access: console
  permission: platform.notifications.use
  realises:
  - CAP-PFM-NOT-009
  published_to_submissions: 'not published: read and archive changes organize the authenticated person’s
    inbox.'
- operation_id: archiveMyNotification
  intent: Move a personal notice out of ordinary inbox views and unread totals.
  access: console
  permission: platform.notifications.use
  realises:
  - CAP-PFM-NOT-009
  published_to_submissions: 'not published: read and archive changes organize the authenticated person’s
    inbox.'
- operation_id: unarchiveMyNotification
  intent: Return a personal archived item to ordinary inbox views.
  access: console
  permission: platform.notifications.use
  realises:
  - CAP-PFM-NOT-009
  published_to_submissions: 'not published: read and archive changes organize the authenticated person’s
    inbox.'
- operation_id: markAllMyNotificationsRead
  intent: Read all qualifying personal items, with optional category and creation-time cutoff.
  access: console
  permission: platform.notifications.use
  realises:
  - CAP-PFM-NOT-009
  published_to_submissions: 'not published: read and archive changes organize the authenticated person’s
    inbox.'
- operation_id: sendMyTestNotification
  intent: Submit a diagnostic notice addressed only to the signed-in person.
  access: console
  permission: platform.notifications.use
  realises:
  - CAP-PFM-NOT-009
  - CAP-PFM-NOT-002
  published_to_submissions: 'not published: test notice creation supports diagnosis of personal delivery.'
- operation_id: listNotificationHistory
  intent: Page through workspace notices with recipient facts and channel summaries.
  access: console
  permission: platform.notifications.manage
  realises:
  - CAP-PFM-NOT-011
  published_to_submissions: 'not published: administrative history exposes existing notification work.'
- operation_id: listNotificationRequests
  intent: Inspect processed requests, including outcomes that produced no personal item.
  access: console
  permission: platform.notifications.manage
  realises:
  - CAP-PFM-NOT-011
  published_to_submissions: 'not published: administrative history exposes existing notification work.'
- operation_id: getNotificationRequest
  intent: Inspect a processed request and the notices and deliveries it produced.
  access: console
  permission: platform.notifications.manage
  realises:
  - CAP-PFM-NOT-011
  - CAP-PFM-NOT-010
  published_to_submissions: 'not published: administrative history exposes existing notification work.'
- operation_id: getNotificationInstance
  intent: Inspect one workspace notice with its audience and channel explanation.
  access: console
  permission: platform.notifications.manage
  realises:
  - CAP-PFM-NOT-011
  - CAP-PFM-NOT-010
  published_to_submissions: 'not published: administrative history exposes existing notification work.'
- operation_id: getNotificationDelivery
  intent: Inspect a delivery’s recorded events and related notice and request.
  access: console
  permission: platform.notifications.manage
  realises:
  - CAP-PFM-NOT-011
  published_to_submissions: 'not published: administrative history exposes existing notification work.'
- operation_id: requestNotification
  intent: Accept a system publication through the same transactional submission helper used by producers.
  access: system
  permission: platform.notifications.publish
  realises:
  - CAP-PFM-NOT-002
  published_to_submissions: 'not published: publication requires a system caller and a domain-selected
    notification.'
- operation_id: cancelNotificationRequest
  intent: Submit withdrawal of a known request on behalf of a system caller.
  access: system
  permission: platform.notifications.publish
  realises:
  - CAP-PFM-NOT-002
  - CAP-PFM-NOT-006
  published_to_submissions: 'not published: publication requires a system caller and a domain-selected
    notification.'
- operation_id: listHqNotificationDefinitions
  intent: Inspect registered application definitions by application or status without returning content
    templates.
  access: system
  permission: hq.notifications.read
  realises:
  - CAP-PFM-NOT-001
  published_to_submissions: 'not published: the operation is an authorized support or operational tool.'
- operation_id: listHqTenantNotificationHistory
  intent: Read customer notice history after the service establishes an active workspace access grant.
  access: system
  permission: hq.notifications.read
  realises:
  - CAP-PFM-NOT-012
  published_to_submissions: 'not published: the operation is an authorized support or operational tool.'
- operation_id: listHqTenantNotificationRequests
  intent: Read customer request outcomes after the service establishes an active workspace access grant.
  access: system
  permission: hq.notifications.read
  realises:
  - CAP-PFM-NOT-012
  published_to_submissions: 'not published: the operation is an authorized support or operational tool.'
- operation_id: listHqNotificationDeadLetters
  intent: Inspect exhausted channel deliveries across operational workspaces without a customer grant
    check.
  access: system
  permission: hq.notifications.read
  realises:
  - CAP-PFM-NOT-012
  published_to_submissions: 'not published: the operation is an authorized support or operational tool.'
- operation_id: retryHqNotificationDelivery
  intent: Create fresh delivery work for an exhausted failure under the HQ operator permission.
  access: system
  permission: hq.notifications.operate
  realises:
  - CAP-PFM-NOT-012
  published_to_submissions: 'not published: the operation is an authorized support or operational tool.'
- operation_id: registerServiceNotifications (IAM function platform_notifications_registration)
  intent: Deploy an application manifest into the notification registry after complete validation and
    retire omitted definitions.
  access: internal
  permission: the platform-notifications-registration-invoke managed policy
  realises:
  - CAP-PFM-NOT-001
  published_to_submissions: 'not published: an application release registers its complete manifest.'
- operation_id: publishOrCancel (IAM function platform_notifications_request)
  intent: Accept IAM publication or cancellation through the notification request service.
  access: internal
  permission: the platform-notifications-request-invoke managed policy
  realises:
  - CAP-PFM-NOT-002
  published_to_submissions: 'not published: service callers submit work directly under their invocation
    authority.'
- operation_id: publishNotification and cancelNotification (producer library, in the producer's transaction)
  intent: Write notification publish or cancel transport rows within the producer’s business transaction.
  access: internal
  permission: the rhythm_notifications_submitter capability role (insert only, own workspace)
  realises:
  - CAP-PFM-NOT-002
  - CAP-PFM-NOT-014
  published_to_submissions: 'not published: the business owner publishes work inside its own transaction.'
- operation_id: nudgeNotificationsDispatcher (IAM invoke of platform_notifications_dispatcher)
  intent: Wake the workspace dispatcher after a producer commits notification work.
  access: internal
  permission: the platform-notifications-dispatcher-invoke managed policy
  realises:
  - CAP-PFM-NOT-002
  - CAP-PFM-NOT-008
  published_to_submissions: 'not published: the invocation wakes internal dispatch after commit.'
events: []
jobs:
- Notification dispatch runs each minute and after a nudge, with one reserved execution; it publishes
  due request and channel work and emits a silence heartbeat.
- The request processor consumes one queued item per invocation with up to four concurrent mappings.
- The chat processor sends queued channel work through the available adapter; only operational HQ Slack
  is deployed for chat.
- Nightly reconciliation schedules one durable job for each operational workspace at 03:40 UTC and monitors
  a two-day heartbeat gap.
- The text queue is declared, but no deployed text consumer receives its items.
integrations:
- system: Slack (Rhythm's own workspace)
  direction: outbound
  contract: Post Block Kit messages using the Platform-secret bot token and code-defined HQ channel mappings,
    with bounded rendered text.
- system: Amazon SQS
  direction: outbound and inbound
  contract: Request, chat and text transport queues allow eight receives and retain dead letters for fourteen
    days.
- system: Communications service module (planned)
  direction: outbound
  contract: The proposed personal e-mail adapter submits caller-rendered transactional mail and feeds
    provider outcomes back to the staff delivery.
consistency:
- rule: A business transaction commits its submission entry together with the producer’s change.
  kind: transactional
  compensation: Rollback removes the entry without separate compensation.
- rule: Request acceptance stores its outcome, recipient notices and channel work in one transaction.
  kind: transactional
  compensation: Queue redelivery finds the request identity; failed processing consumes receives until
    dead-lettering.
- rule: Audience selection and rendering occur asynchronously after publication.
  kind: eventual
  compensation: A minute schedule recovers a lost nudge, but cannot guarantee a one-minute delivery bound
    or recover every dead-lettered request.
- rule: Withdrawal eventually ends unsent channel work and marks affected notices inapplicable.
  kind: eventual
  compensation: Already submitted messages cannot be recalled; retirement currently follows a weaker settlement
    path.
- rule: Some delivery changes precede a separate notice-summary transaction.
  kind: eventual
  compensation: A failed summary refresh has no general repair for final deliveries.
- rule: Nightly reconciliation repairs bounded stuck and expired work.
  kind: eventual
  compensation: Ambiguous sends fail without resubmission; missing queued work is recreated and expired
    undispatched entries are recorded.
evidence:
- 'services-platform at ad3f6a65: modules/notifications/aws/api/notifications.routes.ts (22 routes including
  health); aws/logic/{notifications-functions,notifications-reconcile,notifications-registration}.lambda.ts;
  aws/resources/notifications-queues.sqs.ts; aws/platform.service.ts (notification permission groups).'
- 'services-platform at ad3f6a65: docs/notifications.md §2, §3, §5 to §7, §9, §10; docs/proposals/notifications/11-email.md
  §4 (staff e-mail through communications).'
controls: [TC-AVL-001, TC-AVL-004, TC-AVL-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-005, TC-AZ-006, TC-CHG-001, TC-CHG-002, TC-CHG-003, TC-CHG-004, TC-CHG-005, TC-CHG-006, TC-CHG-007, TC-CRY-001, TC-CRY-002, TC-CRY-003, TC-CRY-004, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-IAM-001, TC-IAM-002, TC-IAM-003, TC-IAM-004, TC-IAM-005, TC-IAM-006, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-MON-002, TC-MON-003, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-PRV-004, TC-SEC-001, TC-SEC-002, TC-SEC-003, TC-SEC-004, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-TEN-004, TC-VEN-001, TC-VEN-002, TC-VEN-003]
---
# Notifications Service Module

## What This Service Is For

Notifications lets applications announce changes to staff without choosing personal addresses or delivery channels. It maintains declarations, processed requests, personal inbox items and channel history.

## Boundary

Communications owns association templates, recipient mail and sender protection; future staff e-mail uses that delivery service. Eligibility owns responsibility changes and their producer integration. Security and workspace lifecycle own provisioning and its alert trigger; operational system scope uses the shared workspace store. Security owns accounts, roles, evaluated permissions and support access grants used for audience and support reads. Eligibility owns the bell’s attention presentation and the legacy attention redirect. Integrations owns customer chat connections, while Operations supplies job execution and partition maintenance.

## Operations in Words

Expose the API health and deployed build for operational checks.

Page through the caller’s inbox by newest item, optionally restricting personal view, category or time. Return unread totals for applicable, unarchived personal notices and their categories. Return the caller’s notice, channel results and saved audience explanation. Record that the caller has read a notice, preserving an existing read timestamp. Clear the read mark on a notice belonging to the caller. Move a personal notice out of ordinary inbox views and unread totals. Return a personal archived item to ordinary inbox views. Read all qualifying personal items, with optional category and creation-time cutoff. Submit a diagnostic notice addressed only to the signed-in person. Page through workspace notices with recipient facts and channel summaries. Inspect processed requests, including outcomes that produced no personal item. Inspect a processed request and the notices and deliveries it produced. Inspect one workspace notice with its audience and channel explanation. Inspect a delivery’s recorded events and related notice and request.

Accept a system publication through the same transactional submission helper used by producers. Submit withdrawal of a known request on behalf of a system caller. Inspect registered application definitions by application or status without returning content templates. Read customer notice history after the service establishes an active workspace access grant. Read customer request outcomes after the service establishes an active workspace access grant. Inspect exhausted channel deliveries across operational workspaces without a customer grant check. Create fresh delivery work for an exhausted failure under the HQ operator permission.

Deploy an application manifest into the notification registry after complete validation and retire omitted definitions. Accept IAM publication or cancellation through the notification request service. Write notification publish or cancel transport rows within the producer’s business transaction. Wake the workspace dispatcher after a producer commits notification work.

## Events and Jobs

The request and chat consumers work behind the scheduled dispatcher. Nightly reconciliation uses a durable state machine to handle ambiguity, expiry, lost work and retention. Text delivery has queue infrastructure but no deployed consumer. Operational heartbeats and channel-failure alarms expose failures to staff.

## Consistency Guarantees

Rollback removes the entry without separate compensation. Queue redelivery finds the request identity; failed processing consumes receives until dead-lettering. A minute schedule recovers a lost nudge, but cannot guarantee a one-minute delivery bound or recover every dead-lettered request. Already submitted messages cannot be recalled; retirement currently follows a weaker settlement path. A failed summary refresh has no general repair for final deliveries. Ambiguous sends fail without resubmission; missing queued work is recreated and expired undispatched entries are recorded.
