---
id: TST-PFM-NOT-026
title: templates
kind: api-lifecycle
product_area: platform
module: notifications
revision: 1
status: draft
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
repository: services-platform
files:
  - modules/communications/tests/e2e/templates.e2e.spec.js
implements:
  - ATS-PFM-NOT-016-02
  - ATS-PFM-NOT-016-03
  - ATS-PFM-NOT-016-05
  - ATS-PFM-NOT-016-06
  - ATS-PFM-NOT-016-07
  - ATS-PFM-NOT-016-11
  - ATS-PFM-NOT-016-12
environment: local
implementation_state: implemented
latest_result: not-run
latest_run_at: null
latest_run_ref: null
conformance: not-verified
estimated_minutes: 5
isolation: >-
  Suite-owned records in the prepared integration workspaces; seeded workspace
  identities remain shared fixtures.
assertion_bindings:
  - scenario: ATS-PFM-NOT-016-02
    suite: TST-PFM-NOT-026
    assertions:
      - >-
        services-platform:modules/communications/tests/e2e/templates.e2e.spec.js#does
        not offer a purpose its caller renders, which has no template to edit
      - >-
        services-platform:modules/communications/tests/e2e/templates.e2e.spec.js#describes
        the records the purpose offers a template, from the registry
  - scenario: ATS-PFM-NOT-016-03
    suite: TST-PFM-NOT-026
    assertions:
      - >-
        services-platform:modules/communications/tests/e2e/templates.e2e.spec.js#refuses
        a body with no name as 400
      - >-
        services-platform:modules/communications/tests/e2e/templates.e2e.spec.js#refuses
        a purpose Rhythm does not know as 400, naming it
      - >-
        services-platform:modules/communications/tests/e2e/templates.e2e.spec.js#saves
        a draft that does not validate, recording why it cannot be published
  - scenario: ATS-PFM-NOT-016-05
    suite: TST-PFM-NOT-026
    assertions:
      - >-
        services-platform:modules/communications/tests/e2e/templates.e2e.spec.js#refuses
        a stale version as 409
      - >-
        services-platform:modules/communications/tests/e2e/templates.e2e.spec.js#refuses
        editing an archived template as 409
      - >-
        services-platform:modules/communications/tests/e2e/templates.e2e.spec.js#refuses
        publishing an archived template as 409
  - scenario: ATS-PFM-NOT-016-06
    suite: TST-PFM-NOT-026
    assertions:
      - >-
        services-platform:modules/communications/tests/e2e/templates.e2e.spec.js#says
        the draft does not validate
  - scenario: ATS-PFM-NOT-016-07
    suite: TST-PFM-NOT-026
    assertions:
      - >-
        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
      - >-
        services-platform:modules/communications/tests/e2e/templates.e2e.spec.js#answers
        200 for the second publish, numbering it 2
      - >-
        services-platform:modules/communications/tests/e2e/templates.e2e.spec.js#points
        the template at the version published last
      - >-
        services-platform:modules/communications/tests/e2e/templates.e2e.spec.js#leaves
        the published version untouched when the draft changes afterwards
      - >-
        services-platform:modules/communications/tests/e2e/templates.e2e.spec.js#refuses
        publishing a draft that does not validate as 400
  - scenario: ATS-PFM-NOT-016-11
    suite: TST-PFM-NOT-026
    assertions:
      - >-
        services-platform:modules/communications/tests/e2e/templates.e2e.spec.js#rendered
        the draft rather than a version, with sample data
  - scenario: ATS-PFM-NOT-016-12
    suite: TST-PFM-NOT-026
    assertions:
      - >-
        services-platform:modules/communications/tests/e2e/templates.e2e.spec.js#refuses
        an address that is neither a test mailbox nor the caller’s own as 403
      - >-
        services-platform:modules/communications/tests/e2e/templates.e2e.spec.js#marks
        the stored subject as a test
evidence:
  - 'services-platform:modules/communications/tests/e2e/templates.e2e.spec.js'
  - The file and referenced assertion titles exist at the pinned commit.
dependency_evidence:
  - >-
    Real: the dispatcher, the route table, signed-context verification, the
    authorization evaluation, the handlers, the
  - >-
    PostgreSQL with row-level security on. Doubled: nothing but the signing key,
    which is this run's own — no SES or send
  - >-
    queue double is needed, because no route sends (`tests/e2e/support.js`).
    Never doubled: the dispatcher, the route table,
---

# templates

## Verification Boundary

This suite exercises the local services and prepared PostgreSQL database. API lifecycle cases use signed test contexts through the real route handler; they do not invoke the deployed gateway.

## What This Suite Proves

Its cases exercise expose only association-editable purposes; validate template fields while retaining unfinished drafts; reject stale drafts and archived edits; report unsafe and invalid content locations; freeze published content across later edits; preview through the delivery renderer without sending.

The registered scenario bindings identify the assertions this executable file contributes. They retain individual test references so that a composite scenario does not become a claim of complete execution by one file.

## What It Does Not Prove

Local outcomes do not prove deployed queues, external provider acceptance, production credentials or complete browser behavior. No fresh execution or conformance result is claimed.

## Real Dependencies and Test Doubles

The communication fixtures use real PostgreSQL and module logic. Shared support records queue and transport calls and stores objects in memory; sender provisioning substitutes a provider identity store. Signed API contexts replace the authorizer key in API suites.

## Must Not Be Doubled

Database constraints, workspace policy, state guards and the service operation under test must remain real. Recording a provider or queue call must not replace the submission, claim or outcome logic being checked.
