Defines typed, versioned notification templates with approved variables, channel-specific rendering, localization fallback, preview fixtures, escaping, and immutable evidence of what was sent.
Package status: reference context ready for human review. The contract and test scenarios are complete, but no claim is made that an adopting implementation has passed them.
Decision
Treat a template as compiled content with a typed input schema and immutable published version. Validate and render per channel, escape untrusted values by output context, and record the exact template version plus variable digest for delivery evidence.
Scope
- Template identity, schema, versions, lifecycle, variables, localization, channel variants, preview, approval, rendering, and evidence.
- Email, push, and in-product variants representing one notification intent.
- Content and rendering safeguards.
Outside this block
- Delivery retry policy or recipient preference classification.
- Allowing arbitrary executable template code or remote includes.
Contract
- A template version declares intent, channel, locale, variable schema, sensitivity, required links, and owning team.
- Only published immutable versions may be sent; edits create a new version.
- Variable access is allowlisted and typed; missing required or unexpected sensitive variables fail rendering.
- Escaping follows output context for text, HTML, URL components, and push payloads.
- Locale fallback is explicit and produces one complete channel variant, never a sentence assembled from mixed locales.
- Preview and snapshot fixtures cover long names, empty optional fields, RTL, hostile markup, and maximum payload sizes.
Implementation guidance
- Use a restricted template language without filesystem, network, or arbitrary code access.
- Build URLs from approved route IDs and typed parameters rather than template-authored origins.
- Generate plain-text email from an intentionally reviewed variant, not unreliable HTML stripping.
- Persist template ID/version, locale, channel, render outcome, and content digest; restrict access to rendered sensitive content.
Failure handling and safeguards
- If no valid locale fallback exists, stop delivery and report a render failure.
- If rendered output exceeds channel limits, fail or use an approved truncation variant without truncating security-critical action text.
- If a published version is withdrawn, queued messages follow the explicit cancel-or-pin policy.
Verification and operations
- Measure render failure by template/version/locale, fallback use, payload overflow, missing variables, and approval age.
- Snapshot-render every published locale/channel combination in CI.
- Review links, privacy classification, and unsubscribe or preference elements at publication.
The executable-looking examples in this package are fixtures and acceptance contracts. Run
python tools/validate.py from the collection root to check package structure and metadata; then
implement and execute the scenarios in the target repository.
Adoption assumptions
- Names and numeric values in
example.yamlare an adoption profile, not universal defaults. - The adopting team must map actors, data classes, error vocabulary, and ownership to its system.
References
- No external normative source is required; this package defines a project decision.