Repository navigation
Conversation
A message template gets a code key unique per team, an owner, a source and a content hash, so code can upload and lock a template by key. Part 1 of 3 of PostHog#118924. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 24, 2026
This was referenced Nov 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Moved here from part 1 of 3 of #118924, closed on 2026-10-25 so this fork stack is the only copy. It opens upstream again after review.
Problem
Engineers, and the coding agents working for them, keep transactional emails as HTML files in their repository and want PostHog to send them (spec). A message template has nowhere to record that code owns it: no key code can name it by, no owner, no source file and no content hash. This part adds the columns, so the API part above can use them.
Merge Danger
Warning
🟡 Merge risk: medium · one-way door: the columns and the index stay after a revert, unused (merge-risk rubric)
posthog_messagetemplate.0009adds nullable columns only, so it does not rewrite the table.0010builds the unique(team, key)index concurrently, for templates that are not deleted.workflows-transactional-email-api.Changes
key,managed_by(guiorcode, null meaninggui),source_repository,source_path,source_ref,content_hashandsuperseded_content_hashes.TemplateManagedBylives in the facade contracts, so the API and the frontend share one owner enum.superseded_content_hasheshas its readers and writers in the API part above (thetemplate_supersededwarning).How did you test this code?
Test rationale:
test_message_template_key.pydrives the database seam: a duplicate key in one team fails, the same key in another team passes, and a deleted template's key can be reused. A unique index that ignoreddeleted, or one missing the team, fails it.makemigrations messaging --check --dry-runon this head (ab6174d3f9d): "No changes detected in app 'messaging'".987b927630e, which holds this head unchanged, on a migrated clone of the local test database. The seed stored a template with the keypassword-reset, which then sent by key throughPOST messaging/send/email/and was delivered (case 02).987b927630e, all green: pytest 1764, CDP jest 3690 (1 skipped), cdp-api serial 288, frontend jest 84, ClickHouse migration tests 460, MCP 5035, repo-wide mypy, nodejs and frontendtsc, and the HCL check.Release status
Docs update
None in this part. The beta docs page
/docs/workflows/transactional-email-apiships separately on posthog.com (Silthus/posthog#475).🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Agent: Claude Code, Claude Opus 5.5 (
claude-opus-5-5) wrote the code and the split. Reviews by GPT-6.1 Sol and Claude Opus 5.5./django-migrations,/tdd,/writing-tests,qa-swarm,/writing-pr-descriptions.example.com.Decisions
The decisions for this change live on #118924. The split adds one:
Open: should
managed_bydefault toguiinstead of null for a template made in PostHog? It changes stored data and the read contract, which PostHog#120921 and the generated types state as "guior null" (➡️ keep null: it is documented, and a later backfill toguiis additive).Involvement: QA swarm design pass and round 1 (review and team lanes GPT-6.1 Sol high, fresh eyes Claude Opus 5.5 high). Round 1 found nothing to fix in this part, so no round 2 or final read ran on it. Live run captured at the stack top.
🤖 Generated with Claude Code