---
id: STATE-ACC-PRD-004
title: Confirmation message setting
object: DOM-ACC-PRD-001
product_area: accounting
module: products
revision: 3
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
states:
- name: 'off'
  meaning: The selection requests no confirmation and claims no owned content.
- name: shared
  meaning: The selection names a shared workspace confirmation template.
- name: product-owned
  meaning: The product selects confirmation content stored under its ownership in Platform.
transitions:
- from: 'off'
  to: product-owned
  trigger: Supply owned confirmation content during product creation or replacement.
  guard: The kind must be sellable and Platform must accept template content and initial reply-to requirements.
  side_effects:
  - Platform saves independently before Accounting commits
  who: An HTTP caller authorized to create or update products
  provenance: test
  source: services-accounting:modules/products/tests/integration/services/persistence/products.features.integration.spec.js#saved
    its own template in Platform, owned by the product, once
- from: product-owned
  to: product-owned
  trigger: Resubmit owned content for merging.
  guard: Platform must accept the merged template.
  side_effects:
  - Keep omitted content fields
  - Avoid publishing an unchanged template
  who: An authorized HTTP product editor
  provenance: test
  source: services-accounting:modules/products/tests/integration/services/persistence/products.features.integration.spec.js#keeps
    one template, as its new version
- from: product-owned
  to: shared
  trigger: Switch an owned selection to a shared template.
  guard: A new shared choice must be active, unowned and in the correct workspace and purpose.
  side_effects:
  - Request owned-template clearing before local commit
  who: An authorized HTTP product editor
  provenance: test
  source: services-accounting:modules/products/tests/integration/services/persistence/products.features.integration.spec.js#clears
    the product’s own template when it switches to a shared one
- from: product-owned
  to: 'off'
  trigger: Explicitly disable owned confirmation.
  guard: The product must pass ordinary replacement checks.
  side_effects:
  - Request owned-template clearing before local commit
  who: An authorized HTTP product editor
  provenance: test
  source: services-accounting:modules/products/tests/integration/services/persistence/products.features.integration.spec.js#archives
    the product’s own template in Platform
- from: 'off'
  to: shared
  trigger: Select a shared confirmation template.
  guard: A new choice must pass purpose, ownership, workspace and activity checks.
  side_effects:
  - Save the shared template reference
  who: An authorized product caller or owning domain function
  provenance: test
  source: services-accounting:modules/products/tests/integration/services/persistence/products.features.integration.spec.js#names
    a shared template of the purpose
- from: shared
  to: 'off'
  trigger: Explicitly disable shared confirmation.
  guard: The product must pass its ordinary write checks.
  side_effects:
  - Clear the shared template reference
  who: An authorized product editor or owning domain function
  provenance: observed
  source: services-accounting:modules/products/services/persistence/products.ts:templateChangeOf
- from: shared
  to: product-owned
  trigger: Switch shared confirmation to owned content.
  guard: Platform must validate and accept the supplied template.
  side_effects:
  - Save owned content in Platform before local commit
  who: An authorized HTTP product editor
  provenance: observed
  source: services-accounting:modules/products/services/persistence/products.ts:templateChangeOf
invalid:
- from: 'off'
  to: product-owned
  why: Selling-feature validation refuses owned confirmation on unsellable kinds.
- from: shared
  to: shared
  why: New shared references require workspace, purpose, activity and ownership validation; a held reference
    skips new-selection checks.
concurrency: The product lock spans the Platform call and response reads. Independent remote commit can survive
  a lost answer, failed response assembly or failed Accounting commit.
invariants:
- INV-DOM-ACC-PRD-001-07
- INV-DOM-ACC-PRD-001-12
evidence:
- 'services-accounting at f47cb263: modules/products/services/persistence/products.ts (templateChangeOf, storedConfirmationEmail,
  featureColumns); services/confirmation-emails/confirmation-email-templates.ts (applyConfirmationTemplateChange,
  clearConfirmationTemplateOfDeletedProduct); services/persistence/communication-templates.ts; services/ports/communications.ts;
  docs/accounting/products.md (Features).'
- 'services-accounting at f47cb263: tests/integration/services/persistence/products.features.integration.spec.js.'
- 'react-console at baf6dae3: components/accounting-config/products/product-section-types.ts (confirmation
  section removed).'
---

# Confirmation message setting

## The Lifecycle

```mermaid
stateDiagram-v2
  [*] --> off
  off --> shared: choose shared confirmation
  off --> product_owned: supply owned content
  shared --> off: clear selection
  shared --> product_owned: supply owned content
  product_owned --> product_owned: merge content
  product_owned --> shared: choose shared and clear owned content
  product_owned --> off: clear owned selection
  product_owned --> [*]: delete product then attempt cleanup
```

## Transitions Explained

The product stores a confirmation selection for a purchase-time consumer. A shared selection names a workspace template; an owned selection uses content Platform stores for that product. HTTP replacement keeps an omitted selection, merges supplied owned content and requests clearing when leaving owned mode. Domain saving can retain an owned selection by omission, but cannot compose or clear that owned content.

## What Cannot Happen

Unsellable kinds reject confirmation settings. A newly selected shared template must belong to the correct workspace and purpose and have no record owner. The console currently exposes no confirmation controls. Sending the selected message belongs to the purchasing consumer.

## Concurrency and Timing

The product lock remains held while Platform answers and response data is read. A remote refusal aborts the local transaction. Platform success is not reversed if the response is lost, response assembly fails or Accounting cannot commit; no durable reconciliation is provided here.
