---
id: STATE-PFM-NOT-010
title: Communication request acceptance
object: DOM-PFM-NOT-005
product_area: platform
module: notifications
revision: 1
status: draft
design_intent: confirmed
origin: 'Andrew''s 2026-10-10 queued-work design for communications (acceptance moves behind the queue;
  the caller is told only that the request was received), services-platform:docs/communications/architecture.md#18.
  Rework 2026-10-10: queue pointers, S3 for request data and bodies, SQS owns retries'
implementation_evidence: observed
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
states:
- name: received
  meaning: Stored request content has a committed queue pointer but no processing outcome.
- name: accepted
  meaning: Rendering produced messages, each waiting to send or withheld.
- name: configuration blocked
  meaning: Missing or unsuitable content prevented message creation.
- name: suppressed
  meaning: Protection checks withheld every recipient.
- name: invalid
  meaning: Stored content or pointer validation failed and retained the problems.
transitions:
- from: received
  to: accepted
  trigger: The consumer processes a request without an outcome.
  guard: The pointer matches valid content, the rendering mode resolves usable content and at least one
    recipient can be rendered.
  side_effects:
  - Store rendered bodies before database commit.
  - Commit the request outcome and messages together.
  who: Notification processing worker (send consumer)
  provenance: test
  source: services-platform:modules/communications/tests/integration/lifecycle/contact-role-compliance-communication.integration.spec.js#accepts
    the request with the owner’s published version pinned
- from: received
  to: configuration blocked
  trigger: Content resolution cannot produce a usable version.
  guard: The request otherwise passes validation.
  side_effects:
  - Retain a staff-visible configuration reason.
  who: Notification processing worker
  provenance: test
  source: services-platform:modules/communications/tests/e2e/requests.e2e.spec.js#blocks a request that
    names no template, recording the reason staff can act on
- from: received
  to: suppressed
  trigger: Every recipient is excluded by protection checks.
  guard: No additional condition is imposed beyond its source state.
  side_effects:
  - Store withheld messages with their exclusion reasons.
  who: Notification processing worker
  provenance: observed
  source: services-platform:modules/communications/services/requests/accept-communication-request.ts:acceptResolved
- from: received
  to: invalid
  trigger: Stored content is absent, mismatched or invalid.
  guard: No additional condition is imposed beyond its source state.
  side_effects:
  - Prevent provider sending.
  who: Notification processing worker
  provenance: test
  source: services-platform:modules/communications/tests/integration/services/storage/communication-objects.integration.spec.js#refuses
    an object that names another tenant, which is what the grant cannot prevent
invalid:
- from: configuration blocked
  to: accepted
  why: Fixing a template does not reopen an existing blocked outcome.
- from: accepted
  to: invalid
  why: Redelivery resumes existing work without replacing the accepted outcome.
concurrency: Derived request identity prevents repeated acceptance; later receives resume sending existing
  messages. Submission validation failures neither write work nor consume the key, whereas stored-content
  failures produce an invalid processing outcome.
evidence:
- 'services-platform at ad3f6a65: modules/communications/services/requests/accept-communication-request.ts;
  services/dispatch/process-communication-request.ts; db/communication-requests.table.ts.'
---
# Communication request acceptance

## The Lifecycle

```mermaid
stateDiagram-v2
    state "received" as s0
    state "accepted" as s1
    state "configuration blocked" as s2
    state "suppressed" as s3
    state "invalid" as s4
    s0 --> s1
    s0 --> s2
    s0 --> s3
    s0 --> s4
```

## Transitions Explained

The transition rows describe stored state changes, their checks and their recorded effects. A queue receive, provider outcome and staff action can reach different lifecycle boundaries.

## What Cannot Happen

Fixing a template does not reopen an existing blocked outcome. Redelivery resumes existing work without replacing the accepted outcome.

## Concurrency and Timing

Derived request identity prevents repeated acceptance; later receives resume sending existing messages. Submission validation failures neither write work nor consume the key, whereas stored-content failures produce an invalid processing outcome.
