---
id: WF-PFM-NOT-010
title: Submit an association communication request
trigger: A producer submits association e-mail alongside its business transaction.
product_area: platform
module: notifications
revision: 1
status: draft
design_intent: confirmed
origin: 'Andrew 2026-10-10: one S3 write inside the caller''s transaction, services-platform:docs/communications/architecture.md#18.12
  One S3 write inside the caller''s transaction (Andrew, 2026-10-10); queued-work standard, services-platform:docs/queued-work.md#5.
  A large or personal payload lives in S3 and the queue carries a pointer'
implementation_evidence: observed
inference: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
- CAP-PFM-NOT-017
- CAP-PFM-NOT-018
moves:
- STATE-PFM-NOT-010
crosses:
- SVC-PFM-NOT-communications
hops:
- n: 1
  actor_or_service: Submitting macroservice (inside its business transaction)
  action: Validate the entire communication envelope, payload size and addresses, purpose and template
    ownership; derive request identity and lane.
  anchor: '@rhythmsoftware/macroservice-communications:submitCommunicationRequest (0.11.0)'
  seam: sync
  on_failure: Reject malformed input before storage or key consumption.
  left_inconsistent: No accepted request work.
  observer: Caller validation response.
  provenance: test
  source: services-platform:modules/communications/tests/e2e/requests.e2e.spec.js#takes nothing for that
    request, so its key is still free
- n: 2
  actor_or_service: Submitting macroservice
  action: Write the complete request body to object storage while the producer transaction remains open.
  anchor: '@rhythmsoftware/macroservice-communications:submitCommunicationRequest'
  seam: sync
  on_failure: Fail the caller transaction; retry with the same idempotency key.
  left_inconsistent: A later rollback leaves an unreferenced object until the thirty-day expiry.
  observer: Caller error; no Platform outcome.
  provenance: documented
  source: services-platform:docs/communications/architecture.md#18.12 One S3 write inside the caller's
    transaction (Andrew, 2026-10-10)
- n: 3
  actor_or_service: Submitting macroservice
  action: Insert the object pointer through the producer capability and commit with the business change.
  anchor: services-platform:modules/communications/db/communication-request-submissions.table.ts
  seam: sync
  on_failure: Roll back the pointer with the caller transaction.
  left_inconsistent: The previously stored object can remain unreferenced.
  observer: Caller transaction result.
  provenance: test
  source: services-platform:modules/communications/tests/integration/db/communication-request-submissions.table.integration.spec.js#leaves
    no queue row behind when the caller’s transaction rolls back
- n: 4
  actor_or_service: Submitting macroservice
  action: Nudge communication dispatch after commit.
  anchor: '@rhythmsoftware/macroservice-communications:nudgeCommunicationsDispatcher'
  seam: event
  on_failure: Rely on minute dispatch if the nudge fails.
  left_inconsistent: Dispatch can wait for the next schedule.
  observer: Dispatcher metrics.
  provenance: observed
  source: services-platform:modules/communications/services/requests/submit-request.ts:realNudge
- n: 5
  actor_or_service: Communications dispatcher
  action: Claim oldest workspace pointers, publish to purpose lanes outside a transaction, delete acknowledgements
    and respect invocation time bounds.
  anchor: services-platform:modules/communications/services/dispatch/dispatch-communications.ts:dispatchCommunications
  seam: schedule
  on_failure: Retain refused work until its claim expires.
  left_inconsistent: Published work can repeat after a failed deletion; acceptance deduplicates it.
  observer: Dispatch counters and queue-age alarms.
  provenance: observed
  source: services-platform:modules/communications/services/dispatch/dispatch-communications.ts:dispatchCommunications
idempotency: The producer key selects the same stored request and queue pointer on retry.
concurrency: Pointer uniqueness and dispatch claims coordinate repeated submission and queue publication.
branches:
- HTTP and IAM callers use the same validated submission contract with their own transaction boundary.
waits:
- Scheduled dispatch recovers a missed post-commit nudge.
evidence:
- 'services-platform at ad3f6a65: modules/communications/services/requests/submit-request.ts; services/dispatch/{dispatch-communications,lanes,send-queue}.ts;
  db/communication-request-submissions.table.ts; docs/communications/architecture.md §18.1 to §18.8.'
controls: [TC-AVL-001, TC-AVL-004, TC-AVL-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-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-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]
---
# Submit an association communication request

## What It Does

A producer submits association e-mail alongside its business transaction.

## The Flow

```mermaid
flowchart TD
    h0["Validate the entire communication envelope, payload size and addresses, purpose and template ownership"]
    h1["Write the complete request body to object storage while the producer transaction remains open"]
    h0 --> h1
    h2["Insert the object pointer through the producer capability and commit with the business change"]
    h1 --> h2
    h3["Nudge communication dispatch after commit"]
    h2 --> h3
    h4["Claim oldest workspace pointers, publish to purpose lanes outside a transaction, delete acknowledgements and respec"]
    h3 --> h4
```

## When Something Fails

The hop rows identify each retry boundary, any state left behind and the available observer. The producer key selects the same stored request and queue pointer on retry. Pointer uniqueness and dispatch claims coordinate repeated submission and queue publication.

## Open Design Questions

HTTP and IAM callers use the same validated submission contract with their own transaction boundary. Scheduled dispatch recovers a missed post-commit nudge.
