---
id: WF-CRM-ENT-001
title: Create a contact
trigger: >-
  A user submits the configured contact create form, or an integration requests
  a new contact.
product_area: crm
module: entities
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
inference: []
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
implements:
  - CAP-CRM-ENT-001
  - CAP-CRM-ENT-005
  - CAP-CRM-ENT-006
  - CAP-CRM-ENT-008
  - CAP-CRM-ENT-009
  - CAP-CRM-ENT-011
moves:
  - STATE-CRM-ENT-001
  - STATE-CRM-ENT-005
crosses:
  - SVC-CRM-ENT-entities
idempotency: >-
  The validated create fingerprint is stored with the chosen identity. Repeating
  that identity with a matching fingerprint returns the earlier contact,
  including competing attempts; a different fingerprint conflicts. Requests
  without a stable client identity have no retry recognition.
concurrency: >-
  Independent creates can still contend on shared spouse, email or organization
  resources. Number allocation uses a separate short transaction and leaves gaps
  on rollback. Organization locking serializes first-contact role assignment for
  competing joins.
hops:
  - 'n': 1
    actor_or_service: Console contact editor
    action: >-
      Collect the chosen type and configured form values, then send the client
      identity reserved for this creation intent.
    anchor: 'react-console:lib/contacts/record-operations.ts:useContactRecordOperations'
    seam: sync
    on_failure: >-
      On an ambiguous result, read that identity before offering another create
      attempt.
    left_inconsistent: No partial business write remains.
    observer: The creator sees form or recovery feedback.
    provenance: observed
    source: 'react-console:lib/contacts/live-operations.ts:liveContactOperations'
  - 'n': 2
    actor_or_service: CRM dispatcher and Entities route
    action: >-
      Validate application access, create permission and any duplicate override
      permission, then map the payload and reject submitted locks.
    anchor: 'services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes'
    seam: sync
    on_failure: >-
      Return field validation errors or an authorization refusal before
      persistence.
    left_inconsistent: No partial business write remains.
    observer: The caller receives the result.
    provenance: observed
    source: 'services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes'
  - 'n': 3
    actor_or_service: Entities create composition
    action: >-
      Check the supplied identity and validated fingerprint for a previously
      successful creation.
    anchor: >-
      services-crm:modules/entities/services/contacts/contact-create.ts:createRequestedContact
    seam: sync
    on_failure: >-
      A conflicting existing identity is refused; a recognized retry returns the
      prior contact.
    left_inconsistent: No partial business write remains.
    observer: The caller receives the result.
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/contacts/contact-create.integration.spec.js#answers
      the retry with the contact the first attempt made
  - 'n': 4
    actor_or_service: Data Quality duplicate guard
    action: >-
      Evaluate the workspace duplicate-block rules and require an authorized,
      explained override when blocked.
    anchor: >-
      services-crm:modules/duplicates/services/detection/duplicate-checks.ts:refuseBlockedDuplicateCreate
    seam: sync
    on_failure: >-
      Return duplicate candidates and override availability without creating the
      contact.
    left_inconsistent: No partial business write remains.
    observer: The duplicate dialog shows the refusal.
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/contacts/CRM-ACC-0042.spec.ts#CRM-ACC-0042
  - 'n': 5
    actor_or_service: Shared record-asset pipeline
    action: >-
      Prepare permanent copies for the photo and file-valued custom fields
      before opening the record transaction.
    anchor: >-
      services-crm:modules/entities/services/assets/entity-assets.ts:entityAssets
    seam: sync
    on_failure: Refuse invalid or failed asset preparation before saving the record.
    left_inconsistent: Prepared copies may remain until abandoned-asset cleanup.
    observer: Asset cleanup logs show deferred removal.
    provenance: test
    source: >-
      services-crm:modules/entities/tests/e2e/contacts.e2e.spec.js#answers 400
      for a photo whose upload is not there, naming the field that failed
  - 'n': 6
    actor_or_service: Entities persistence (one transaction)
    action: >-
      Prepare affiliations and default type, eligible roles and source links;
      normalize and validate values; allocate the number and insert the contact;
      persist spouse reciprocity, assets, children, default mappings, custom
      values and any override audit together.
    anchor: >-
      services-crm:modules/entities/services/persistence/contacts.ts:createContact
    seam: sync
    on_failure: Roll back the aggregate on failure and return the detected problems.
    left_inconsistent: 'An allocated number is spent, and prepared files may await cleanup.'
    observer: The caller receives the result.
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/persistence/contacts.integration.spec.js#keeps
      the number consumed when the transaction rolls back: a gap, never given
      back
  - 'n': 7
    actor_or_service: Database change capture
    action: >-
      Capture one aggregate contact event and revision for the changed
      transaction; a reciprocal spouse change has its own capture.
    anchor: 'services-crm:modules/entities/db/record-revisions.table.ts:recordRevisions'
    seam: sync
    on_failure: Missing required attribution prevents capture and rolls back creation.
    left_inconsistent: No partial business write remains.
    observer: Contact history exposes the committed revision.
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/persistence/contacts.history.integration.spec.js#writes
      exactly one revision, whatever the save touched
  - 'n': 8
    actor_or_service: Entities route
    action: 'After commit, request early dispatch of the captured events.'
    anchor: 'services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes'
    seam: event
    on_failure: Ignore a failed nudge and rely on scheduled dispatch.
    left_inconsistent: Post-commit reactions can be delayed.
    observer: Dispatcher logs show publication attempts.
    provenance: documented
    source: 'services-crm:docs/change-events.md#The pieces'
  - 'n': 9
    actor_or_service: CRM change-event consumers
    action: >-
      Run the registered compliance, region, search and duplicate reactions
      independently. Reconciliation handlers reread committed data; search
      receives event snapshots.
    anchor: 'services-crm:aws/crm.change-events.ts:crmChangeEventStreams'
    seam: queue
    on_failure: >-
      Retry failed handler messages through SQS and dead-letter after five
      receives.
    left_inconsistent: >-
      The contact persists while dependent compliance, region or search state
      may lag.
    observer: Consumer logs and the dead-letter queue identify failed handlers.
    provenance: documented
    source: 'services-crm:docs/change-events.md#7. Failures and recovery'
branches:
  - >-
    Inactive and deceased creation release primary email reservation and skip
    automatic roles; duplicate status retains active-status eligibility.
  - >-
    Future affiliations defer shared links and automatic-role work until
    eligible settlement.
waits: []
evidence:
  - >-
    services-crm at 7ea48a41: modules/entities/aws/api/contacts.routes.ts;
    services/contacts/contact-create.ts; services/persistence/contacts.ts
    (createContact, saveNewContact, insertContact);
    services/assets/entity-assets.ts;
    services/contacts/role-assignment/contact-role-assignment.ts;
    docs/entities-api.md (Retrying a create); docs/change-events.md.
  - >-
    react-console at da630758: lib/contacts/record-operations.ts,
    live-operations.ts; lib/api/write-safety.ts.
  - >-
    services-platform at ad3f6a65: docs/standards/record-write-contracts.md W5;
    docs/queued-work.md.
controls:
  - TC-AZ-001
  - TC-AZ-002
  - TC-AZ-003
  - TC-AZ-004
  - TC-AZ-006
  - TC-DAT-001
  - TC-DAT-002
  - TC-DAT-003
  - TC-IAM-001
  - TC-IAM-005
  - TC-IAM-006
  - TC-LOG-004
  - TC-LOG-005
  - TC-PI-001
  - TC-PI-002
  - TC-PI-003
  - TC-PI-005
  - TC-PRV-001
  - TC-PRV-002
  - TC-TEN-001
  - TC-TEN-002
  - TC-TEN-003
narrative:
  status: verified
  review: NARRATIVE-REVIEW-2026-10-23
narrative_sources:
  - section: What It Does
    provenance: observed
    source: 'react-console:lib/contacts/record-operations.ts:useContactRecordOperations'
  - section: What It Does
    provenance: observed
    source: 'services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes'
  - section: What It Does
    provenance: observed
    source: >-
      services-crm:modules/entities/services/contacts/contact-create.ts:createRequestedContact
  - section: What It Does
    provenance: observed
    source: >-
      services-crm:modules/duplicates/services/detection/duplicate-checks.ts:refuseBlockedDuplicateCreate
  - section: What It Does
    provenance: observed
    source: >-
      services-crm:modules/entities/services/assets/entity-assets.ts:entityAssets
  - section: What It Does
    provenance: observed
    source: >-
      services-crm:modules/entities/services/persistence/contacts.ts:createContact
  - section: What It Does
    provenance: observed
    source: 'services-crm:modules/entities/db/record-revisions.table.ts:recordRevisions'
  - section: What It Does
    provenance: documented
    source: 'services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes'
  - section: What It Does
    provenance: documented
    source: 'services-crm:aws/crm.change-events.ts:crmChangeEventStreams'
  - section: What Starts It
    provenance: observed
    source: 'react-console:lib/contacts/record-operations.ts:useContactRecordOperations'
  - section: What Starts It
    provenance: observed
    source: 'services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes'
  - section: What Starts It
    provenance: observed
    source: >-
      services-crm:modules/entities/services/contacts/contact-create.ts:createRequestedContact
  - section: What Starts It
    provenance: observed
    source: >-
      services-crm:modules/duplicates/services/detection/duplicate-checks.ts:refuseBlockedDuplicateCreate
  - section: What Starts It
    provenance: observed
    source: >-
      services-crm:modules/entities/services/assets/entity-assets.ts:entityAssets
  - section: What Starts It
    provenance: observed
    source: >-
      services-crm:modules/entities/services/persistence/contacts.ts:createContact
  - section: What Starts It
    provenance: observed
    source: 'services-crm:modules/entities/db/record-revisions.table.ts:recordRevisions'
  - section: What Starts It
    provenance: documented
    source: 'services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes'
  - section: What Starts It
    provenance: documented
    source: 'services-crm:aws/crm.change-events.ts:crmChangeEventStreams'
  - section: The Flow
    provenance: observed
    source: 'react-console:lib/contacts/record-operations.ts:useContactRecordOperations'
  - section: The Flow
    provenance: observed
    source: 'services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes'
  - section: The Flow
    provenance: observed
    source: >-
      services-crm:modules/entities/services/contacts/contact-create.ts:createRequestedContact
  - section: The Flow
    provenance: observed
    source: >-
      services-crm:modules/duplicates/services/detection/duplicate-checks.ts:refuseBlockedDuplicateCreate
  - section: The Flow
    provenance: observed
    source: >-
      services-crm:modules/entities/services/assets/entity-assets.ts:entityAssets
  - section: The Flow
    provenance: observed
    source: >-
      services-crm:modules/entities/services/persistence/contacts.ts:createContact
  - section: The Flow
    provenance: observed
    source: 'services-crm:modules/entities/db/record-revisions.table.ts:recordRevisions'
  - section: The Flow
    provenance: documented
    source: 'services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes'
  - section: The Flow
    provenance: documented
    source: 'services-crm:aws/crm.change-events.ts:crmChangeEventStreams'
  - section: Hop by Hop
    provenance: observed
    source: 'react-console:lib/contacts/record-operations.ts:useContactRecordOperations'
  - section: Hop by Hop
    provenance: observed
    source: 'services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes'
  - section: Hop by Hop
    provenance: observed
    source: >-
      services-crm:modules/entities/services/contacts/contact-create.ts:createRequestedContact
  - section: Hop by Hop
    provenance: observed
    source: >-
      services-crm:modules/duplicates/services/detection/duplicate-checks.ts:refuseBlockedDuplicateCreate
  - section: Hop by Hop
    provenance: observed
    source: >-
      services-crm:modules/entities/services/assets/entity-assets.ts:entityAssets
  - section: Hop by Hop
    provenance: observed
    source: >-
      services-crm:modules/entities/services/persistence/contacts.ts:createContact
  - section: Hop by Hop
    provenance: observed
    source: 'services-crm:modules/entities/db/record-revisions.table.ts:recordRevisions'
  - section: Hop by Hop
    provenance: documented
    source: 'services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes'
  - section: Hop by Hop
    provenance: documented
    source: 'services-crm:aws/crm.change-events.ts:crmChangeEventStreams'
  - section: When Something Fails
    provenance: observed
    source: 'react-console:lib/contacts/record-operations.ts:useContactRecordOperations'
  - section: When Something Fails
    provenance: observed
    source: 'services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes'
  - section: When Something Fails
    provenance: observed
    source: >-
      services-crm:modules/entities/services/contacts/contact-create.ts:createRequestedContact
  - section: When Something Fails
    provenance: observed
    source: >-
      services-crm:modules/duplicates/services/detection/duplicate-checks.ts:refuseBlockedDuplicateCreate
  - section: When Something Fails
    provenance: observed
    source: >-
      services-crm:modules/entities/services/assets/entity-assets.ts:entityAssets
  - section: When Something Fails
    provenance: observed
    source: >-
      services-crm:modules/entities/services/persistence/contacts.ts:createContact
  - section: When Something Fails
    provenance: observed
    source: 'services-crm:modules/entities/db/record-revisions.table.ts:recordRevisions'
  - section: When Something Fails
    provenance: documented
    source: 'services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes'
  - section: When Something Fails
    provenance: documented
    source: 'services-crm:aws/crm.change-events.ts:crmChangeEventStreams'
  - section: Repeats and Races
    provenance: observed
    source: 'react-console:lib/contacts/record-operations.ts:useContactRecordOperations'
  - section: Repeats and Races
    provenance: observed
    source: 'services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes'
  - section: Repeats and Races
    provenance: observed
    source: >-
      services-crm:modules/entities/services/contacts/contact-create.ts:createRequestedContact
  - section: Repeats and Races
    provenance: observed
    source: >-
      services-crm:modules/duplicates/services/detection/duplicate-checks.ts:refuseBlockedDuplicateCreate
  - section: Repeats and Races
    provenance: observed
    source: >-
      services-crm:modules/entities/services/assets/entity-assets.ts:entityAssets
  - section: Repeats and Races
    provenance: observed
    source: >-
      services-crm:modules/entities/services/persistence/contacts.ts:createContact
  - section: Repeats and Races
    provenance: observed
    source: 'services-crm:modules/entities/db/record-revisions.table.ts:recordRevisions'
  - section: Repeats and Races
    provenance: documented
    source: 'services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes'
  - section: Repeats and Races
    provenance: documented
    source: 'services-crm:aws/crm.change-events.ts:crmChangeEventStreams'
  - section: What Is Observable
    provenance: observed
    source: 'react-console:lib/contacts/record-operations.ts:useContactRecordOperations'
  - section: What Is Observable
    provenance: observed
    source: 'services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes'
  - section: What Is Observable
    provenance: observed
    source: >-
      services-crm:modules/entities/services/contacts/contact-create.ts:createRequestedContact
  - section: What Is Observable
    provenance: observed
    source: >-
      services-crm:modules/duplicates/services/detection/duplicate-checks.ts:refuseBlockedDuplicateCreate
  - section: What Is Observable
    provenance: observed
    source: >-
      services-crm:modules/entities/services/assets/entity-assets.ts:entityAssets
  - section: What Is Observable
    provenance: observed
    source: >-
      services-crm:modules/entities/services/persistence/contacts.ts:createContact
  - section: What Is Observable
    provenance: observed
    source: 'services-crm:modules/entities/db/record-revisions.table.ts:recordRevisions'
  - section: What Is Observable
    provenance: documented
    source: 'services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes'
  - section: What Is Observable
    provenance: documented
    source: 'services-crm:aws/crm.change-events.ts:crmChangeEventStreams'
  - section: What It Does
    provenance: inferred
    source: >-
      react-console:lib/contacts/record-operations.ts:useContactRecordOperations;
      services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes;
      services-crm:modules/entities/services/contacts/contact-create.ts:createRequestedContact;
      services-crm:modules/duplicates/services/detection/duplicate-checks.ts:refuseBlockedDuplicateCreate;
      services-crm:modules/entities/services/assets/entity-assets.ts:entityAssets;
      services-crm:modules/entities/services/persistence/contacts.ts:createContact;
      services-crm:modules/entities/db/record-revisions.table.ts:recordRevisions;
      services-crm:modules/entities/aws/api/contacts.routes.ts:contactsRoutes;
      services-crm:aws/crm.change-events.ts:crmChangeEventStreams
    note: >-
      The explicitly labeled rationale interprets the existing transaction,
      transport and recovery boundaries; it is not a product decision.
  - section: Open Design Questions
    provenance: documented
    source: 'rhythm-v2-docs:specs/crm/entities/FINDINGS.md#Findings'
---

# Create a contact

## What It Does

Creation establishes one continuing person identity together with the information needed to use it: names, contact points, preferences, affiliations and permitted customer-defined values. For example, a coordinator adds Ruth Kim as a member-firm representative and expects the person, employer connection and initial responsibilities to describe the same committed result.

Our reading is that the sequence matters because validation, files, numbering and dependent projections cross different boundaries. The local aggregate can roll back as one unit; an allocated number or a prepared file has its own recovery behavior. A successful form submission establishes the contact, while search and region updates may still be pending.

## What Starts It

A membership coordinator submits the configured person form, or an integration calls contact creation. The submitted names, details and affiliations enter one creation request. A client identity can support recognized replay; an idless submission does not acquire that guarantee. Reaching the request boundary does not mean duplicate checks or persistence have succeeded.

## The Flow

The diagram shows the sequence and service seams. Each synchronous stage waits for its result, while captured-event, queue and scheduled stages can run after the originating request has returned. The hop descriptions below identify the write and failure boundary, so the last arrow must not be mistaken for one atomic transaction across every participant.

```mermaid
sequenceDiagram
  participant U as Creator
  participant C as CRM create workflow
  participant D as CRM database
  participant Q as Change queue
  U->>C: form values and stable create identity
  C->>C: recognize retry, check duplicates, prepare assets
  C->>D: persist aggregate with attribution
  D-->>C: commit contact, revision and event
  C-->>U: created contact
  C->>Q: request independent reactions
```

## Hop by Hop

### 1. Console contact editor

The editor turns the selected classification and configured fields into one creation intent. A reserved client identity connects an ambiguous response to a later read, so retry recovery can ask whether Ruth already exists before issuing another creation. The form holds the draft until the service confirms the result.

### 2. CRM dispatcher and Entities route

The dispatcher and route establish application reach and create authority before interpreting the business payload. They also evaluate the narrowly separate duplicate override grant. Field problems or an attempted lock assignment are reported before persistence, so an invalid form cannot partly establish the person.

### 3. Entities create composition

Create composition compares the supplied identity with the validated request fingerprint. Matching content can recover the contact already committed by a competing attempt; different content cannot silently adopt that earlier person. This stage is a synchronous replay check, not a search-based duplicate decision.

### 4. Data Quality duplicate guard

The duplicate guard asks Data Quality whether configured blocking conditions identify possible existing people. A refusal returns candidates and whether override is available. An override requires both authority and a reason, so recognizing a suspected duplicate remains distinguishable from establishing a different person deliberately.

### 5. Shared record-asset pipeline

The asset stage prepares permanent photo and file-valued custom-field copies before the record transaction. It supplies stable file references to the later write. This seam cannot be rolled back by deleting a database row, so abandoned copies require the asset cleanup mechanism if the remaining create fails.

### 6. Entities persistence (one transaction)

Persistence assembles and validates the contact aggregate in one transaction. It coordinates spouse reciprocity, typed details, affiliations, eligible responsibility assignments and selected shared defaults. Number allocation is independently spent, while owner and owned business values either commit together or disappear together on rollback.

### 7. Database change capture

Database capture builds the contact’s attributed revision and change event as part of creation. A spouse changed reciprocally receives a separate subject revision. Missing attribution therefore prevents the creation from committing rather than leaving a contact whose provenance cannot be reconstructed.

### 8. Entities route

The route requests an early dispatch after commit. It does not reopen the successful creation if the request to dispatch fails. The durable event remains available to scheduled publication, separating the response to the coordinator from the time dependent services receive the change.

### 9. CRM change-event consumers

Independent consumer messages let compliance, region, search and duplicate reactions succeed or retry separately. Some handlers reread current committed data; search uses the captured snapshot contract. The person already exists while these projections catch up, and one handler’s retry is not another creation.

## When Something Fails

### Hop 1 — Console contact editor

The failure boundary is: On an ambiguous result, read that identity before offering another create attempt. The remaining work or data is: No partial business write remains. The creator sees form or recovery feedback.

### Hop 2 — CRM dispatcher and Entities route

The failure boundary is: Return field validation errors or an authorization refusal before persistence. The remaining work or data is: No partial business write remains. The caller receives the result.

### Hop 3 — Entities create composition

The failure boundary is: A conflicting existing identity is refused; a recognized retry returns the prior contact. The remaining work or data is: No partial business write remains. The caller receives the result.

### Hop 4 — Data Quality duplicate guard

The failure boundary is: Return duplicate candidates and override availability without creating the contact. The remaining work or data is: No partial business write remains. The duplicate dialog shows the refusal.

### Hop 5 — Shared record-asset pipeline

The failure boundary is: Refuse invalid or failed asset preparation before saving the record. The remaining work or data is: Prepared copies may remain until abandoned-asset cleanup. Asset cleanup logs show deferred removal.

### Hop 6 — Entities persistence (one transaction)

The failure boundary is: Roll back the aggregate on failure and return the detected problems. The remaining work or data is: An allocated number is spent, and prepared files may await cleanup. The caller receives the result.

### Hop 7 — Database change capture

The failure boundary is: Missing required attribution prevents capture and rolls back creation. The remaining work or data is: No partial business write remains. Contact history exposes the committed revision.

### Hop 8 — Entities route

The failure boundary is: Ignore a failed nudge and rely on scheduled dispatch. The remaining work or data is: Post-commit reactions can be delayed. Dispatcher logs show publication attempts. A later attempt can be required; the scheduling or publication boundary does not establish an immediate user-visible completion.

### Hop 9 — CRM change-event consumers

The failure boundary is: Retry failed handler messages through SQS and dead-letter after five receives. The remaining work or data is: The contact persists while dependent compliance, region or search state may lag. Consumer logs and the dead-letter queue identify failed handlers. This failure is downstream of committed input; operators investigate its own delivery rather than treating the caller’s original save as failed.

## Repeats and Races

The supplied contact identity and validated fingerprint provide replay recognition. A matching retry returns the earlier committed person, while changed content under that identity conflicts. An idless request lacks that replay recognition. After an uncertain response, this contract does not establish a reliable identity-based retry for that request; staff must inspect saved records rather than assume another create will be recognized.

Creates can contend on spouse pairs, primary email or destination organizations. Organization locking coordinates first-contact roles under simultaneous joins. The separately allocated number can leave a gap after rollback; this is not evidence that a missing contact once committed. Prepared files also have a cleanup boundary independent of replay.

## What Is Observable

The creator sees form or recovery feedback. The caller receives the result. The duplicate dialog shows the refusal. Asset cleanup logs show deferred removal. Contact history exposes the committed revision. Dispatcher logs show publication attempts. Consumer logs and the dead-letter queue identify failed handlers.

The person or initiating caller sees the synchronous result at its own boundary. Captured history establishes committed local changes; logs, durable job state and queue outcomes explain remaining work. A successful database change, accepted downstream request and completed delivery are different observations and must be investigated through the component that owns each one.

## Open Design Questions

Replay recognition applies to contact creation and depends on a stable identity and matching fingerprint. It is not a generic guarantee for organization or catalogue creation. Dedicated browser proof of all ambiguous-response recovery remains limited by the existing acceptance findings; the design explains the built recovery path without claiming a complete delivery guarantee.
