---
id: WF-PFM-NOT-003
title: Turn one request into recipient notices
trigger: A request worker receives publication work.
product_area: platform
module: notifications
revision: 1
status: draft
design_intent: confirmed
origin: D-04 (audiences resolved by Platform at dispatch, 200-person cap), Andrew 2026-10-21 17:15 ET,
  services-platform:docs/proposals/notifications/23-decisions.md#D-04. Audiences, not addresses, and the
  200-person cap; PLAT-M23 plan scope (collapse, supersede, expiry), approved 2026-10-21 18:05 ET
implementation_evidence: observed
inference: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
- CAP-PFM-NOT-003
- CAP-PFM-NOT-004
- CAP-PFM-NOT-005
- CAP-PFM-NOT-006
- CAP-PFM-NOT-007
- CAP-PFM-NOT-008
moves:
- STATE-PFM-NOT-002
- STATE-PFM-NOT-003
- STATE-PFM-NOT-005
crosses:
- SVC-PFM-NOT-notifications
hops:
- n: 1
  actor_or_service: Request consumer
  action: Check whether the derived request identity already has an outcome.
  anchor: services-platform:modules/notifications/services/orchestration/orchestrate-request.ts
  seam: queue
  on_failure: Return failed processing for queue redelivery.
  left_inconsistent: No partial database write.
  observer: Duplicate-work logs and dispatcher nudge.
  provenance: test
  source: services-platform:modules/notifications/tests/integration/services/orchestration/orchestrate-request.integration.spec.js#recognizes
    a redelivered item by its record, writes nothing more and nudges the dispatcher
- n: 2
  actor_or_service: Request consumer
  action: Resolve an active definition and check cancellation, deadline and earliest processing time.
  anchor: services-platform:modules/notifications/services/orchestration/orchestrate-request.ts
  seam: sync
  on_failure: Record terminal rejection outcomes; defer future work or create a fresh delayed copy near
    exhaustion.
  left_inconsistent: Future work remains queued without an outcome.
  observer: Request outcome in History.
  provenance: test
  source: services-platform:modules/notifications/tests/integration/services/orchestration/orchestrate-request.integration.spec.js#gives
    back a request that is not due yet, writing nothing, never processing it early
- n: 3
  actor_or_service: Request consumer
  action: Validate submitted data against the registered schema.
  anchor: services-platform:modules/notifications/templates.ts:newAjv
  seam: sync
  on_failure: Record an invalid outcome with field-level problems.
  left_inconsistent: No notice is created.
  observer: Request validation details.
  provenance: observed
  source: services-platform:modules/notifications/services/orchestration/orchestrate-request.ts
- n: 4
  actor_or_service: Request consumer with Security and Eligibility reads
  action: Resolve current audience membership, exclusions and actor removal; enforce the two-hundred limit
    and active customer-workspace user boundary.
  anchor: services-platform:modules/notifications/services/orchestration/resolve-audience.ts
  seam: sync
  on_failure: Record invalid or empty-audience outcomes with isolation details.
  left_inconsistent: No partial recipient notices.
  observer: History and audience warnings.
  provenance: test
  source: services-platform:modules/notifications/tests/integration/services/orchestration/resolve-audience.integration.spec.js#changes
    the people when the responsibility is reassigned between the publish and the dispatch
- n: 5
  actor_or_service: Request consumer
  action: Within one transaction, insert the outcome, acquire sorted folding locks, and reuse, fold or
    render each recipient notice with its language, time zone and channel resolution.
  anchor: services-platform:modules/notifications/services/persistence/instances.ts:lockFoldIdentities
  seam: sync
  on_failure: Roll back and let the queue retry.
  left_inconsistent: No partially committed notice set.
  observer: Request, notice and skip metrics.
  provenance: test
  source: services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#folds
    ten requests dispatched at the same moment into one notification of collapsed count nine
- n: 6
  actor_or_service: Request consumer
  action: Persist immediate console delivery, milestone or unsupported skips, and available queued channels
    with work rows; redact declared links from stored data.
  anchor: services-platform:modules/notifications/services/orchestration/channel-resolution.ts:resolveChannels
  seam: sync
  on_failure: Roll back orchestration and retry the item.
  left_inconsistent: No partially committed delivery set.
  observer: Channel delivery counters.
  provenance: test
  source: services-platform:modules/notifications/tests/integration/services/orchestration/orchestrate-request.integration.spec.js#writes
    the console delivery delivered at once and records every other supported channel as not available
    until its milestone
- n: 7
  actor_or_service: Request consumer
  action: Apply occurrence replacement within acceptance, commit the new work, and nudge queued delivery
    dispatch.
  anchor: services-platform:modules/notifications/services/orchestration/orchestrate-request.ts
  seam: sync
  on_failure: Roll back acceptance on transactional failure; scheduled dispatch recovers a lost nudge.
  left_inconsistent: Committed work can wait for scheduled dispatch.
  observer: New and superseded notices in the inbox.
  provenance: test
  source: services-platform:modules/notifications/tests/integration/services/orchestration/cancel-and-supersede.integration.spec.js#supersedes
    the earlier request of a definition whose scope is the occurrence, and tells the person the new one
idempotency: Derived request and occurrence identities prevent repeated acceptance and duplicate recipient
  notices.
concurrency: Up to four items process concurrently; sorted transaction-scoped folding locks serialize
  matching identities, with hash collisions causing only extra waiting.
branches:
- System audiences follow the reserved-workspace alert path.
- Cancellation items follow withdrawal processing.
waits:
- Future-dated work waits until its earliest processing time.
evidence:
- 'services-platform at ad3f6a65: modules/notifications/services/orchestration/*.ts; services/persistence/{instances,deliveries,requests,recipients}.ts;
  docs/notifications.md §6.'
controls: [TC-AVL-001, TC-AVL-004, TC-AVL-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-CHG-001, TC-CHG-002, TC-CHG-003, TC-CHG-004, TC-CHG-005, TC-CHG-006, 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-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-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-PRV-004, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-TEN-004, TC-VEN-001, TC-VEN-002, TC-VEN-003]
---
# Turn one request into recipient notices

## What It Does

A request worker receives publication work.

## The Flow

```mermaid
flowchart TD
    h0["Check whether the derived request identity already has an outcome"]
    h1["Resolve an active definition and check cancellation, deadline and earliest processing time"]
    h0 --> h1
    h2["Validate submitted data against the registered schema"]
    h1 --> h2
    h3["Resolve current audience membership, exclusions and actor removal"]
    h2 --> h3
    h4["Within one transaction, insert the outcome, acquire sorted folding locks, and reuse, fold or render each recipient "]
    h3 --> h4
    h5["Persist immediate console delivery, milestone or unsupported skips, and available queued channels with work rows"]
    h4 --> h5
    h6["Apply occurrence replacement within acceptance, commit the new work, and nudge queued delivery dispatch"]
    h5 --> h6
```

## When Something Fails

The hop rows identify each retry boundary, any state left behind and the available observer. Derived request and occurrence identities prevent repeated acceptance and duplicate recipient notices. Up to four items process concurrently; sorted transaction-scoped folding locks serialize matching identities, with hash collisions causing only extra waiting.

## Open Design Questions

System audiences follow the reserved-workspace alert path. Cancellation items follow withdrawal processing. Future-dated work waits until its earliest processing time.
