---
id: STATE-PFM-NOT-009
title: Association template and its published versions
object: DOM-PFM-NOT-004
product_area: platform
module: notifications
revision: 1
status: draft
design_intent: confirmed
origin: Andrew's 2026-10-09 decisions recorded in the final acceptance (association templates, draft and
  publish, the type owns its template), services-platform:docs/communications/architecture.md#2026-10-09
  — Final acceptance
implementation_evidence: observed
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
states:
- name: draft only
  meaning: The active template has editable content but no sendable version.
- name: published
  meaning: The active template has a frozen sendable version; draft changes do not affect sending.
- name: archived
  meaning: The template is unavailable for editing or new requests while its versions remain readable.
transitions:
- from: draft only
  to: published
  trigger: An author publishes, or an owning record saves its initial content.
  guard: The active-state and expected-version checks run before publication; validated content is frozen
    under a later numbering lock without rechecking those values.
  side_effects:
  - Freeze the first content version with its hash and used merge fields.
  - Point the template to that publication.
  who: Association communication administrator; the owning macroservice's save path
  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
- from: published
  to: published
  trigger: An author republishes or an owner saves changed content.
  guard: The same pre-transaction checks apply; identical owner content creates no publication.
  side_effects:
  - Freeze the next numbered version without altering earlier content.
  - Keep existing rendered messages pinned to their original versions.
  who: Association communication administrator; the owning macroservice
  provenance: test
  source: services-platform:modules/communications/tests/integration/services/templates/owned-templates.integration.spec.js#keeps
    every field the partial content left out
- from: published
  to: archived
  trigger: An author archives the template or its owner clears the setting.
  guard: Clearing is repeatable without another change.
  side_effects:
  - Exclude the template from active-purpose counts.
  - Block subsequent requests that require it.
  who: Association communication administrator; the owning macroservice
  provenance: test
  source: services-platform:modules/communications/tests/e2e/templates.e2e.spec.js#keeps it readable by
    id, because it is kept for history
- from: draft only
  to: archived
  trigger: An author archives an unpublished template or its owner clears it.
  guard: No additional condition is imposed beyond its source state.
  side_effects: []
  who: Association communication administrator; the owning macroservice
  provenance: observed
  source: services-platform:modules/communications/services/persistence/templates.ts:archiveTemplate
invalid:
- from: archived
  to: published
  why: Archived templates cannot be republished; an owner save creates another active template.
- from: published
  to: draft only
  why: Publishing history cannot be removed to restore a draft-only template.
concurrency: Draft replacement guards the expected version in its database update. The active-owner unique
  index resolves competing first creations. Marketing version storage returns identical content and refuses
  a changed publication for that message version. Publication checks state and optional expected version
  before locking and does not recheck them under the lock; owned draft changes can commit before publication.
evidence:
- 'services-platform at ad3f6a65: modules/communications/services/persistence/templates.ts; services/templates/{template-publishing,owned-templates,message-version-templates}.ts;
  db/communication-templates.table.ts.'
---
# Association template and its published versions

## The Lifecycle

```mermaid
stateDiagram-v2
    state "draft only" as s0
    state "published" as s1
    state "archived" as s2
    s0 --> s1
    s1 --> s1
    s1 --> s2
    s0 --> s2
```

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

Archived templates cannot be republished; an owner save creates another active template. Publishing history cannot be removed to restore a draft-only template.

## Concurrency and Timing

Draft replacement guards the expected version in its database update. The active-owner unique index resolves competing first creations. Marketing version storage returns identical content and refuses a changed publication for that message version. Publication checks state and optional expected version before locking and does not recheck them under the lock; owned draft changes can commit before publication.
