---
id: DOM-PFM-NOT-004
title: Association E-mail Template
realises: CON-PFM-NOT-004
product_area: platform
module: notifications
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
owned_by: SVC-PFM-NOT-communications
readable_by: []
lifecycle: STATE-PFM-NOT-009
custom_fields: none
identity: A template has a time-ordered workspace identity and a stable purpose. Owned templates additionally
  identify their business record, with one active template per owner and purpose. Publication numbers
  increase within a template and a frozen content hash identifies its saved content.
attributes:
- name: purpose
  kind: reference
  required: true
  computed: false
  notes: The purpose defines available source records and merge fields, content responsibility, classification,
    channel, expiry and starter wording.
- name: name
  kind: text
  required: true
  computed: false
  notes: The bounded, trimmed name helps staff distinguish templates.
- name: draft content
  kind: collection
  required: true
  computed: false
  notes: Editable subject, HTML, optional plain text, sender display name, reply address and copy lists
    form the draft. Copy lists are canonical and allow ten addresses each.
- name: draft validation
  kind: collection
  required: false
  computed: false
  notes: Saved validation results identify draft problems and their locations. Saving incomplete content
    does not make it publishable.
- name: optimistic version
  kind: number
  required: true
  computed: false
  notes: Editors submit the version they read so a stale replacement cannot silently overwrite newer content.
- name: status
  kind: enum
  required: true
  computed: false
  notes: Active templates can be authored and resolved for sending; archived templates remain available
    by identity for history.
- name: owner
  kind: reference
  required: false
  computed: false
  notes: The owning object and record are assigned together at creation. Ordinary template operations
    cannot change this ownership.
- name: current version
  kind: reference
  required: false
  computed: false
  notes: The current publication reference is empty until content is first published.
- name: published versions
  kind: collection
  required: false
  computed: false
  notes: Publications preserve immutable content, sequence, hash, variable use, contract version, publisher
    and time.
- name: sender
  kind: reference
  required: true
  computed: false
  notes: The template records the Platform sender convention; final sending chooses the verified workspace
    address when available.
relationships:
- to: DOM-PFM-NOT-005
  cardinality: one version to many messages
  ownership: The communication message retains the publication reference; the template retains the publication
    after archiving.
  cross_service: false
- to: DOM-PFM-NOT-003
  cardinality: none
  ownership: Staff notice content and association template publications remain separate models without
    a current reference.
  cross_service: false
invariants:
- id: INV-DOM-PFM-NOT-004-01
  statement: A normal template send pins published content rather than the editable draft.
  enforced_at:
  - service
  - database
  provenance: test
  source: services-platform:modules/communications/tests/e2e/templates.e2e.spec.js#froze the draft as
    version 1, with the content hash and the variables it reads
- id: INV-DOM-PFM-NOT-004-02
  statement: Publication rejects content that fails the purpose’s variable, rendering and safety checks.
  enforced_at:
  - service
  provenance: test
  source: services-platform:modules/communications/tests/integration/lifecycle/contact-role-compliance-communication.integration.spec.js#refuses
    content that reads an undeclared variable and includes a file
- id: INV-DOM-PFM-NOT-004-03
  statement: Caller-rendered purposes reject association template creation.
  enforced_at:
  - api
  - service
  provenance: test
  source: services-platform:modules/communications/tests/integration/services/templates/caller-rendered-purposes.integration.spec.js#refuse
    a template for the caller-rendered purpose
- id: INV-DOM-PFM-NOT-004-04
  statement: A workspace has at most one active template for an owner and purpose; the unique owner index
    prevents duplicate first saves.
  enforced_at:
  - database
  - service
  provenance: observed
  source: services-platform:modules/communications/db/communication-templates.table.ts:communication_templates_owner_uidx
- id: INV-DOM-PFM-NOT-004-05
  statement: General authoring operations cannot assign a different purpose or owner to an existing template.
  enforced_at:
  - api
  - service
  provenance: test
  source: services-platform:modules/communications/tests/integration/services/templates/owned-templates.integration.spec.js#drops
    the purpose and the owner from the body before the operation sees them
- id: INV-DOM-PFM-NOT-004-06
  statement: Draft replacement guards the expected version in its update and rejects an archived row when
    read; publication checks state and optional expected version before locking, so concurrent archive
    or editing can invalidate its earlier check.
  enforced_at:
  - api
  - service
  provenance: observed
  source: services-platform:modules/communications/services/persistence/templates.ts:updateTemplateDraft;
    services-platform:modules/communications/services/persistence/templates.ts:publishTemplateDraft; services-platform:modules/communications/services/templates/template-publishing.ts:publishTemplate
- id: INV-DOM-PFM-NOT-004-07
  statement: The active-template limit is one hundred for each purpose in a workspace and excludes archived
    records.
  enforced_at:
  - service
  provenance: test
  source: services-platform:modules/communications/tests/integration/services/persistence/templates.integration.spec.js#refuses
    a template once the cap is filled with ACTIVE ones
- id: INV-DOM-PFM-NOT-004-08
  statement: Repeating a Marketing message-version save with identical content returns its publication;
    changed content for that published owner is refused.
  enforced_at:
  - service
  provenance: test
  source: services-platform:modules/communications/tests/integration/services/templates/message-version-templates.integration.spec.js#refuses
    different content for a message version that is published, as an illegal operation
- id: INV-DOM-PFM-NOT-004-09
  statement: Published versions are retained as history, with deletion reserved to the guarded workspace
    purge.
  enforced_at:
  - database
  provenance: observed
  source: services-platform:modules/communications/services/persistence/tenant-purges.ts
physical:
- communication_templates
- communication_template_versions
evidence:
- 'services-platform at ad3f6a65: modules/communications/db/communication-templates.table.ts, communication-template-versions.table.ts,
  communication-purposes.ts; services/persistence/templates.ts; services/templates/{template-content,template-publishing,owned-templates,message-version-templates,render-preview,test-send,readiness,resolution}.ts.'
- 'services-platform at ad3f6a65: docs/communications/architecture.md §6, §16.7, §19, §20, §22 (owned-template
  purposes) and the 2026-10-09 final acceptance.'
---
# Association E-mail Template

## What It Models

An association e-mail template supplies reusable wording for a declared communication purpose. Staff or an owning business record save content and publish snapshots. Normal sending uses a resolved publication; test sending can use the draft.

## Identity and Attributes

A template has a time-ordered workspace identity and a stable purpose. Owned templates additionally identify their business record, with one active template per owner and purpose. Publication numbers increase within a template and a frozen content hash identifies its saved content.

## Relationships

The communication message retains the publication reference; the template retains the publication after archiving. Staff notice content and association template publications remain separate models without a current reference.

## Invariants

The invariant rows identify the guarantees supported by the cited evidence and the layer enforcing each one. They retain implementation gaps rather than treating intended behavior as complete enforcement.

## How It Is Stored and Shared

The owner’s record save and Platform’s template save cross service boundaries. The cited architecture describes compensation, but this examination cannot verify the owning service’s implementation. Marketing rendering extensions still require product authority, and template editing audit remains undecided.

## Open Design Questions

The module findings retain unresolved authority, recovery and source-boundary questions affecting this object.
