---
id: STATE-PFM-NOT-014
title: Association sender verification
object: DOM-PFM-NOT-005
product_area: platform
module: notifications
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
states:
- name: none
  meaning: No custom sender setting is available, so shared sending applies.
- name: pending
  meaning: The stored setting awaits provider verification and may precede identity creation.
- name: verified
  meaning: At least one configured identity is ready for custom sending.
- name: failed
  meaning: No configured identity is ready and at least one reports provider verification failure.
transitions:
- from: none
  to: pending
  trigger: Workspace setup requests a custom sender setting.
  guard: The strategy and required domain or address must be valid.
  side_effects:
  - Provisioning creates or adopts identities and records DNS instructions; initial setting creation is
    outside the examined scope.
  who: Workspace lifecycle participant
  provenance: unknown
  source: rhythm-v2-docs:specs/platform/notifications/FINDINGS.md:FND-PFM-NOT-049
- from: pending
  to: verified
  trigger: An HQ sender read refreshes provider verification.
  guard: At least one identity is ready to send.
  side_effects:
  - Record the first verification time without replacing an earlier one.
  who: Rhythm HQ sender read
  provenance: observed
  source: services-platform:modules/communications/services/sender-identity/provision-sender-identity.ts:refreshSenderIdentityVerification
- from: pending
  to: failed
  trigger: An HQ sender read finds failed verification.
  guard: No identity can send and at least one reports failure.
  side_effects: []
  who: Rhythm HQ reading the sender
  provenance: observed
  source: services-platform:modules/communications/services/sender-identity/provision-sender-identity.ts:verificationStateOf
- from: verified
  to: pending
  trigger: An HQ sender read finds verification no longer ready.
  guard: No identity can send and none reports failure.
  side_effects:
  - Preserve historical verification time and use shared sending.
  who: Rhythm HQ reading the sender
  provenance: observed
  source: services-platform:modules/communications/services/sender-identity/provision-sender-identity.ts:verificationStateOf
- from: verified
  to: none
  trigger: Workspace deletion removes the sender.
  guard: Remove provider identities and verify their absence before deleting the setting.
  side_effects:
  - Deletion also removes identities adopted from existing resources.
  who: Workspace lifecycle participant
  provenance: observed
  source: services-platform:modules/communications/services/sender-identity/provision-sender-identity.ts:purgeSenderIdentityIdentities
- from: failed
  to: verified
  trigger: An HQ sender read observes recovered verification.
  guard: At least one provider identity is ready to send.
  side_effects:
  - Refresh the check time and retain the first verification time.
  who: Rhythm HQ sender read
  provenance: observed
  source: services-platform:modules/communications/services/sender-identity/provision-sender-identity.ts:verificationStateOf
- from: failed
  to: pending
  trigger: An HQ sender read observes verification still awaiting completion.
  guard: No provider identity is ready or reports failed DKIM.
  side_effects:
  - Refresh the check time and retain the first verification time.
  who: Rhythm HQ sender read
  provenance: observed
  source: services-platform:modules/communications/services/sender-identity/provision-sender-identity.ts:verificationStateOf
- from: verified
  to: failed
  trigger: An HQ sender read observes provider verification failure.
  guard: No provider identity is ready and at least one reports failed DKIM.
  side_effects:
  - Refresh the check time and retain the first verification time.
  who: Rhythm HQ sender read
  provenance: observed
  source: services-platform:modules/communications/services/sender-identity/provision-sender-identity.ts:verificationStateOf
- from: pending
  to: none
  trigger: Workspace deletion removes the pending sender.
  guard: Provider identities must be removed and their absence verified.
  side_effects:
  - Adopted identities are included in deletion.
  who: Workspace lifecycle participant
  provenance: observed
  source: services-platform:modules/communications/services/sender-identity/provision-sender-identity.ts:purgeSenderIdentityIdentities
- from: failed
  to: none
  trigger: Workspace deletion removes the failed sender.
  guard: Provider identities must be removed and their absence verified.
  side_effects:
  - Adopted identities are included in deletion.
  who: Workspace lifecycle participant
  provenance: observed
  source: services-platform:modules/communications/services/sender-identity/provision-sender-identity.ts:purgeSenderIdentityIdentities
invalid:
- from: none
  to: verified
  why: Setup does not wait for DNS readiness; the verification refresh determines readiness.
- from: pending
  to: none
  why: Only the purge sequence removes a setting, including a pending or failed setting.
concurrency: Each workspace has one setting. Per-process sender caching delays selection changes by up
  to a minute. HQ sender reads refresh and write verification; no scheduled refresh is implemented.
evidence:
- 'services-platform at ad3f6a65: modules/communications/services/sender-identity/*.ts; db/communication-sender-identities.table.ts;
  modules/tenants/aws/api/tenants.routes.ts:getHqTenantEmailSender.'
---
# Association sender verification

## The Lifecycle

```mermaid
stateDiagram-v2
    state "none" as s0
    state "pending" as s1
    state "verified" as s2
    state "failed" as s3
    s0 --> s1
    s1 --> s2
    s1 --> s3
    s2 --> s1
    s2 --> s0
    s3 --> s2
    s3 --> s1
    s2 --> s3
    s1 --> s0
    s3 --> s0
```

## 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

Setup does not wait for DNS readiness; the verification refresh determines readiness. Only the purge sequence removes a setting, including a pending or failed setting.

## Concurrency and Timing

Each workspace has one setting. Per-process sender caching delays selection changes by up to a minute. HQ sender reads refresh and write verification; no scheduled refresh is implemented.
