---
id: WF-PFM-NOT-014
title: Compose a record-owned template across services
trigger: An owning record creates, updates or clears its e-mail template setting.
product_area: platform
module: notifications
revision: 1
status: draft
design_intent: confirmed
origin: Andrew 2026-10-09 ("The type owns it; its API composes it"), services-platform:docs/communications/architecture.md#2026-10-09
  — Final acceptance
implementation_evidence: observed
inference: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
- CAP-PFM-NOT-016
moves:
- STATE-PFM-NOT-009
crosses:
- SVC-PFM-NOT-communications
hops:
- n: 1
  actor_or_service: Owning macroservice (CRM organization type save)
  action: Validate merged owned-template content with a dry run before the owner commits its record.
  anchor: services-platform:modules/communications/services/templates/owned-templates.ts:saveOwnedTemplate
  seam: sync
  on_failure: Reject the owner save when content validation fails.
  left_inconsistent: The dry run creates no template changes.
  observer: Owner-screen validation response.
  provenance: documented
  source: services-platform:docs/communications/architecture.md#16.7 A record composes a template it owns
- n: 2
  actor_or_service: Owning macroservice
  action: Commit the owner record using its own service boundary.
  anchor: FND-PFM-NOT-049
  seam: sync
  on_failure: Stop the composed save when the owner commit fails.
  left_inconsistent: Owner internals and compensation are outside examined scope.
  observer: Owner-screen result.
  provenance: unknown
  source: FND-PFM-NOT-049
- n: 3
  actor_or_service: Communications (IAM saveOwnedTemplate)
  action: Merge partial content onto the stored draft, validate it, create on first save and publish changed
    content; retain an identical publication.
  anchor: services-platform:modules/communications/services/templates/owned-templates.ts:saveOwnedTemplate
  seam: sync
  on_failure: Validation failure writes nothing; later save failures require the owner's documented compensation.
  left_inconsistent: Owner and template can disagree if save or compensation fails; template creation
    and publication use separate writes.
  observer: Owner logs and template versions.
  provenance: observed
  source: services-platform:modules/communications/tests/integration/services/templates/owned-templates.integration.spec.js#keeps
    every field the partial content left out; services-platform:modules/communications/services/templates/owned-templates.ts:mergeContent;
    services-platform:modules/communications/services/templates/owned-templates.ts:publishIfChanged
- n: 4
  actor_or_service: Communications (IAM clearOwnedTemplate)
  action: Archive the active owned template when its setting is cleared, preserving its versions.
  anchor: services-platform:modules/communications/services/templates/owned-templates.ts:clearOwnedTemplate
  seam: sync
  on_failure: Repeat the idempotent clear when needed.
  left_inconsistent: Until clear succeeds, the active owned template remains available.
  observer: Later requests report a missing usable template after successful clear.
  provenance: observed
  source: services-platform:modules/communications/services/templates/owned-templates.ts:clearOwnedTemplate
idempotency: Identical merged content retains its publication, and repeated clear retains archived history.
concurrency: The active-owner uniqueness constraint coordinates first creation; owner and template saves
  cross independent commit boundaries.
branches:
- The documented owner pattern validates first and compensates after a later template-save failure.
waits: []
evidence:
- 'services-platform at ad3f6a65: modules/communications/services/templates/{owned-templates,message-version-templates}.ts;
  services/requests/handle-invocation.ts; docs/communications/architecture.md §16.7 and §22 (owned-template
  purposes).'
controls: [TC-AVL-004, TC-AVL-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-CRY-001, TC-CRY-002, TC-CRY-003, TC-CRY-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-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-TEN-004, TC-VEN-001, TC-VEN-002, TC-VEN-003]
---
# Compose a record-owned template across services

## What It Does

An owning record creates, updates or clears its e-mail template setting.

## The Flow

```mermaid
flowchart TD
    h0["Validate merged owned-template content with a dry run before the owner commits its record"]
    h1["Commit the owner record using its own service boundary"]
    h0 --> h1
    h2["Merge partial content onto the stored draft, validate it, create on first save and publish changed content"]
    h1 --> h2
    h3["Archive the active owned template when its setting is cleared, preserving its versions"]
    h2 --> h3
```

## When Something Fails

The hop rows identify each retry boundary, any state left behind and the available observer. Identical merged content retains its publication, and repeated clear retains archived history. The active-owner uniqueness constraint coordinates first creation; owner and template saves cross independent commit boundaries.

## Open Design Questions

The documented owner pattern validates first and compensates after a later template-save failure.
