Skip to content

feat(messaging): add a single transactional email send endpoint - #123556

Merged
trunk-io[bot] merged 1 commit into
masterfrom
posthog/messaging-send-email-endpoint
Oct 27, 2026
Merged

trunk-io[bot] merged 1 commit into
masterfrom
posthog/messaging-send-email-endpoint

Conversation

@mayteio

@mayteio mayteio commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Why: the SDKs can call the final URL from their first release, and later send forms can extend the same endpoint.

Refs #120921

Changes

  • POST /api/projects/:project_id/messaging/send/email/ sends one transactional email from the template in template.id. The body is otherwise the same: to, identifiers.distinct_id, message_data, plus the Idempotency-Key header.
  • Auth, the workflows-transactional-email-api flag, the workflow access check, the refusal codes and the 202 response all match the template route.
  • Both routes go through one TransactionalEmailSendMixin, so a later fix applies to both.
  • Both routes use the same throttle scopes, so a caller can't double its rate limit by using both.
  • The transactional email api send event gains a route property (template or send_email), so adoption of the new route is measurable.
  • A send from code can be added later as another form of template, such as template: { key } with subject and html, without breaking template: { id }.
  • Mechanical: the regenerated messaging frontend types and MCP API types.

How did you test this code?

Test rationale: the existing send tests in test_transactional_email.py are extended to run on both routes: the workflow call and attribution, project secret key scopes, and the flag gate. A new parameterized test checks that the new route refuses an unknown template, another project's template, or a missing template, and never calls the pipeline. The new route takes the template ID from the body, so a lookup without team scoping would send another project's email. No existing test covers that.

Ran locally: test_transactional_email.py (59 pass), repo-wide mypy --cache-fine-grained ., ruff check, ruff format --check and hogli lint:tach.

Ran against a local stack (the workflows dev intent, maildev, and a sender with provider: maildev), with a project secret key:

Request Result
Send on /messaging_templates/{id}/send/ 202; the workflow ran and maildev received the email
Send on /messaging/send/email/ 202; the workflow ran and maildev received the email
Same Idempotency-Key again 202 with the first message_id and replayed: true
Unknown template.id 404
No template 400, attr: template
No key 401
Flag off, both routes 404

Release status

  • This change is behind a feature flag and is not available to users

Docs update

None in this repository. The transactional email docs page in PostHog/posthog.com#21564 switches to this endpoint once it merges.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Agent: PostHog Desktop (Claude Code), Claude Opus 5.5

  • Skills: /improving-drf-endpoints, /writing-tests, /writing-pr-descriptions.
  • Scope is the template form only, by request. Sends from code, cc/bcc, attachments and status lookup are left for the contract's owner to build on this endpoint.
  • The shared mixin carries a comment, not a docstring, because drf-spectacular published the docstring as the description of every template operation.
  • Duplicate search: no open PR adds this endpoint.
  • Public artifact: no session material is in the diff. All test data is invented.

🤖 Generated with Claude Code


Created with PostHog Desktop

@mayteio mayteio self-assigned this Oct 26, 2026
@trunk-io

trunk-io Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

😎 Stack merged successfully - details.

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

🤖 CI report

⚠️ Trunk lane — backend Python lane

This PR is assigned to the backend Python lane. It runs backend Python tests and may merge in parallel with PRs in other lanes.

✅ Complexity (TypeScript) — clean

Cyclomatic complexity above the limit in changed typescript files (10 for production files, 15 for test files). Warn only: worth simplifying when you next touch these functions.

✅ Duplication (Python) — clean

New Python code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

✅ Duplication (TypeScript) — clean

New TypeScript code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

✅ Bundle size — no change

Uncompressed size of every built .js bundle, compared against the base branch.

Total: 76.96 MiB · no change

No file changed by more than 1000 B.

Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report

⚠️ Eager graph — 1 over budget

How much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy import() / React.lazy chunks are not counted.

Root Eager (shipped) Δ vs base Budget
entry (logged-out pages, app bootstrap)
src/index.tsx
1.00 MiB · 24 files no change █████████░ 87.8% of 1.14 MiB
logged-out boot: index + App + bootApp (preloaded by every page, including /login)
src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
2.97 MiB · 620 files no change ██████████ 97.9% of 3.03 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
7.49 MiB · 2,562 files no change ██████████ 100.0% of 7.50 MiB
dashboard scene
src/scenes/dashboard/Dashboard.tsx
9.94 MiB · 3,728 files no change ██████████ 99.3% of 10.01 MiB
today home path
src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
7.67 MiB · 2,655 files no change ██████████ 99.1% of 7.74 MiB
🟡 AI-first home path
src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
7.92 MiB · 2,648 files no change ██████████ 100.1% of 7.91 MiB
events scene
src/scenes/activity/explore/EventsScene.tsx
9.38 MiB · 3,510 files no change ██████████ 97.9% of 9.59 MiB
web analytics scene
src/scenes/web-analytics/WebAnalyticsScene.tsx
10.31 MiB · 3,756 files no change ██████████ 95.2% of 10.83 MiB
replay detail scene
src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
8.41 MiB · 3,087 files no change █████████░ 88.8% of 9.47 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/svg/ stays out of src/index.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/components/ stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/layout/navigation-3000/navigationLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/scenes/dashboard/dashboardLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/lemon-ui/LemonMarkdown/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/RichContentEditor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/CodeSnippet/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/taxonomy/core-filter-definitions-by-group.json stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 node_modules/zod/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/scenes/billing/billingLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/ProductEmptyState/productSetupPreloadLogic.ts stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 products/dashboards/frontend/widgets/previews/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 products/wizard/frontend/runs/WizardRunDetailsDrawer.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/TodayShell.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/TodayContextPanelFloating.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/TodaySidePanel.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/TodayTopBar.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/todayRailItems.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 zod/v4/locales/de.js stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/svg/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/components/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/session-recordings/playlist/SessionRecordingsPlaylist.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/scenes/web-analytics/tiles/WebAnalyticsTile.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/queries/validators.js stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/scenes/project-homepage/today/TodayReportPage.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/queries/Query/Query.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 packages/quill/packages/charts/ stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 products/posthog_ai/frontend/components/tool/widgets/VisualizationWidget.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 products/posthog_ai/frontend/components/tool/widgets/RecordingsWidget.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 src/queries/Query/Query.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 products/posthog_ai/frontend/api/primitives.ts stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 src/scenes/notebooks/Notebook/notebookLogic.ts stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 src/scenes/session-recordings/playlist/SessionRecordingsPlaylist.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/scenes/web-analytics/tiles/WebAnalyticsTile.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/queries/validators.js stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/scenes/web-analytics/LiveMetricsDashboard/LiveWebAnalyticsMetrics.tsx stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 products/product_analytics/frontend/insights/trends/WorldMap/countryVectors.tsx stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 src/scenes/settings/SettingsMap.tsx stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 @jspm/core/nodelibs/browser/fs stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx

Largest files eagerly shipped from src/index.tsx
Size File
126.8 KiB ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js
24.6 KiB ../node_modules/.pnpm/[email protected]/node_modules/buffer/index.js
6.3 KiB ../node_modules/.pnpm/[email protected]/node_modules/react/cjs/react.production.min.js
4.7 KiB ../node_modules/.pnpm/@[email protected]/node_modules/@jspm/core/nodelibs/browser/process.js
4.0 KiB ../node_modules/.pnpm/[email protected]/node_modules/scheduler/cjs/scheduler.production.min.js
1.7 KiB ../node_modules/.pnpm/[email protected]/node_modules/base64-js/index.js
1.6 KiB src/lib/utils/bootTiming.ts
1.6 KiB src/index.tsx
1.2 KiB src/RootErrorBoundary.tsx
949 B src/scenes/ChunkLoadErrorBoundary.tsx
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
Size File
322.9 KiB ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs
217.5 KiB ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js
126.8 KiB ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js
100.8 KiB src/products.tsx
86.1 KiB src/lib/api.ts
68.2 KiB src/lib/lemon-ui/icons/icons.tsx
41.9 KiB ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@dnd-kit/core/dist/core.esm.js
36.4 KiB ../node_modules/.pnpm/[email protected]_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js
27.0 KiB ../node_modules/.pnpm/[email protected]/node_modules/tailwind-merge/dist/bundle-mjs.mjs
24.6 KiB ../node_modules/.pnpm/[email protected]/node_modules/buffer/index.js
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
322.9 KiB ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs
286.4 KiB src/taxonomy/core-filter-definitions-by-group.json
239.9 KiB ../packages/quill/packages/quill/dist/index.js
217.5 KiB ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.8 KiB ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js
100.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@tiptap/core/dist/index.js
92.5 KiB ../node_modules/.pnpm/[email protected]/node_modules/prosemirror-view/dist/index.js
86.1 KiB src/lib/api.ts
Largest files eagerly shipped from src/scenes/dashboard/Dashboard.tsx
Size File
322.9 KiB ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs
286.4 KiB src/taxonomy/core-filter-definitions-by-group.json
239.9 KiB ../packages/quill/packages/quill/dist/index.js
217.5 KiB ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.8 KiB ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js
144.1 KiB ../packages/quill/packages/primitives/dist/index.js
126.8 KiB ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js
100.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@tiptap/core/dist/index.js
92.5 KiB ../node_modules/.pnpm/[email protected]/node_modules/prosemirror-view/dist/index.js
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
Size File
322.9 KiB ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs
286.4 KiB src/taxonomy/core-filter-definitions-by-group.json
239.9 KiB ../packages/quill/packages/quill/dist/index.js
217.5 KiB ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.8 KiB ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js
100.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@tiptap/core/dist/index.js
92.5 KiB ../node_modules/.pnpm/[email protected]/node_modules/prosemirror-view/dist/index.js
86.1 KiB src/lib/api.ts
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
Size File
322.9 KiB ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs
286.4 KiB src/taxonomy/core-filter-definitions-by-group.json
239.9 KiB ../packages/quill/packages/quill/dist/index.js
217.5 KiB ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.8 KiB ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js
144.1 KiB ../packages/quill/packages/primitives/dist/index.js
126.8 KiB ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js
100.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@tiptap/core/dist/index.js
92.5 KiB ../node_modules/.pnpm/[email protected]/node_modules/prosemirror-view/dist/index.js
Largest files eagerly shipped from src/scenes/activity/explore/EventsScene.tsx
Size File
322.9 KiB ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs
286.4 KiB src/taxonomy/core-filter-definitions-by-group.json
239.9 KiB ../packages/quill/packages/quill/dist/index.js
217.5 KiB ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.8 KiB ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js
144.1 KiB ../packages/quill/packages/primitives/dist/index.js
126.8 KiB ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js
100.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@tiptap/core/dist/index.js
92.5 KiB ../node_modules/.pnpm/[email protected]/node_modules/prosemirror-view/dist/index.js
Largest files eagerly shipped from src/scenes/web-analytics/WebAnalyticsScene.tsx
Size File
322.9 KiB ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs
286.4 KiB src/taxonomy/core-filter-definitions-by-group.json
239.9 KiB ../packages/quill/packages/quill/dist/index.js
217.5 KiB ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js
182.9 KiB src/queries/validators.js
153.8 KiB ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js
144.1 KiB ../packages/quill/packages/primitives/dist/index.js
126.8 KiB ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js
100.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@tiptap/core/dist/index.js
Largest files eagerly shipped from src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
Size File
322.9 KiB ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs
316.1 KiB ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/rrweb.js
286.4 KiB src/taxonomy/core-filter-definitions-by-group.json
239.9 KiB ../packages/quill/packages/quill/dist/index.js
217.5 KiB ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.8 KiB ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js
100.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@tiptap/core/dist/index.js
92.5 KiB ../node_modules/.pnpm/[email protected]/node_modules/prosemirror-view/dist/index.js

Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479

✅ Toolbar bundle — eager 2.30 MiB within budget

What the toolbar ships to customer pages, measured from the esbuild output (minified, post-tree-shake). The eager set is the entry plus everything statically imported from it — fetched before any feature runs; deferred chunks load lazily. The eager guardrail is 5.72 MiB. Each output file must also stay below 10 MB, where CloudFront stops compressing it. The module boundary is enforced separately by check-toolbar-graph.

Metric Size Δ vs base Budget
Eager (shipped)
entry + static imports
2.30 MiB · 18 files no change ████░░░░░░ 40.2% of 5.72 MiB
Deferred (lazy) 2.11 MiB · 40 files no change n/a — loads on demand
Loader dist/toolbar.js 1.2 KiB no change █░░░░░░░░░ 6.0% of 19.5 KiB
Largest eagerly-shipped chunks
Size File
911.5 KiB dist/toolbar/toolbar-app-DUCPI2WS.css
694.6 KiB dist/toolbar/chunk-chunk-GZTRHRCK.js
259.9 KiB dist/toolbar/chunk-chunk-ONRHJSKR.js
131.8 KiB dist/toolbar/chunk-chunk-FDH2IBXT.js
130.4 KiB dist/toolbar/chunk-chunk-AME52YTL.js
74.8 KiB dist/toolbar/toolbar-app-VEELPFRX.js
69.0 KiB dist/toolbar/chunk-chunk-TSAL54PB.js
35.6 KiB dist/toolbar/chunk-chunk-KVA34CN3.js
21.7 KiB dist/toolbar/chunk-chunk-GOU3MNDU.js
6.8 KiB dist/toolbar/chunk-chunk-DV7IWQNF.js

Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile

✅ Dist folder size — 🔺 +3.0 KiB (+0.0%)

Total size of the built frontend/dist folder (all assets), compared against the base branch.

Total: 970.25 MiB · 🔺 +3.0 KiB (+0.0%)

ℹ️ MCP UI apps size — 35 app(s), 28999.8 KB JS

Built size of each MCP UI app (main.js + styles.css).

App JS CSS
debug 844.3 KB 211.1 KB
explain-chart 1004.9 KB 211.1 KB
action 767.7 KB 211.1 KB
action-list 835.3 KB 211.1 KB
cohort 766.7 KB 211.1 KB
cohort-list 834.3 KB 211.1 KB
email-template 766.6 KB 211.1 KB
error-details 771.6 KB 211.1 KB
error-issue 768.9 KB 211.1 KB
error-issue-list 836.8 KB 211.1 KB
experiment 832.4 KB 211.1 KB
experiment-list 836.1 KB 211.1 KB
experiment-results 835.0 KB 211.1 KB
feature-flag 834.7 KB 211.1 KB
feature-flag-list 838.4 KB 211.1 KB
feature-flag-testing 770.0 KB 211.1 KB
inline-scan 767.2 KB 211.1 KB
insight-actors 833.8 KB 211.1 KB
llm-costs 831.1 KB 211.1 KB
session-recording 769.0 KB 211.1 KB
survey 768.3 KB 211.1 KB
survey-global-stats 831.1 KB 211.1 KB
survey-list 836.0 KB 211.1 KB
survey-stats 831.1 KB 211.1 KB
trace-span 767.1 KB 211.1 KB
trace-span-list 835.2 KB 211.1 KB
vision-observation-list 834.4 KB 211.1 KB
workflow 767.1 KB 211.1 KB
workflow-list 834.7 KB 211.1 KB
workflow-setup-status 766.7 KB 211.1 KB
query-results 1087.6 KB 211.1 KB
render-ui 1186.5 KB 211.1 KB
visual-review-snapshots 771.6 KB 211.1 KB
workflow-data-suggestions 769.4 KB 211.1 KB
workflow-sending-rules 768.1 KB 211.1 KB
⚠️ Playwright — 1 flaky

🎭 Playwright report · View test results →

⚠️ 1 flaky test:

  • Can request password reset (chromium)

These issues are not necessarily caused by your changes.
Annoyed by this section? Help fix flakies and failures and it will go green!

⚠️ Backend coverage — 93.0% of changed backend lines covered — 7 uncovered

🧪 Backend test coverage

Patch coverage — changed backend lines (products + core): ███████████████████░ 93.0% (93 / 100)

File Patch Uncovered changed lines
products/messaging/backend/presentation/views/message_templates.py 89.7% 524–528, 610–611

🤖 Agents: add a test only if an uncovered line exposes a realistic regression that existing tests miss. Otherwise explain why no new test is needed under "How did you test this code?". Gap list: the patch-coverage artifact on this run (gh run download 260408068963570 -n patch-coverage), or the coverage-data block at the end of this comment.

Per-product line coverage (touched products)
Product Coverage Lines
demo ███████████░░░░░░░░░ 56.4% 1,542 / 2,736
batch_exports ████████████████░░░░ 81.6% 22,899 / 28,059
engineering_analytics █████████████████░░░ 85.0% 11,463 / 13,482
commands █████████████████░░░ 85.5% 1,618 / 1,893
mcp_analytics █████████████████░░░ 86.2% 5,720 / 6,638
posthog_ai ██████████████████░░ 87.9% 4,296 / 4,886
notebooks ██████████████████░░ 88.5% 15,330 / 17,321
dashboards ██████████████████░░ 88.6% 7,800 / 8,800
mcp_registry ██████████████████░░ 89.0% 1,596 / 1,794
warehouse_suggestions ██████████████████░░ 89.2% 3,275 / 3,672
cohorts ██████████████████░░ 89.6% 8,568 / 9,559
product_tours ██████████████████░░ 89.7% 1,355 / 1,510
signals ██████████████████░░ 90.0% 89,147 / 99,033
tasks ██████████████████░░ 90.7% 80,114 / 88,335
managed_warehouse ██████████████████░░ 91.0% 12,251 / 13,458
data_warehouse ██████████████████░░ 91.1% 15,326 / 16,822
canvas ██████████████████░░ 91.2% 8,189 / 8,980
autoresearch ██████████████████░░ 91.4% 11,618 / 12,705
data_modeling ██████████████████░░ 91.5% 10,755 / 11,758
cdp ██████████████████░░ 91.5% 10,282 / 11,238
today ██████████████████░░ 91.6% 3,976 / 4,341
business_knowledge ██████████████████░░ 91.6% 10,242 / 11,177
metrics ██████████████████░░ 91.7% 10,627 / 11,590
slack_app ██████████████████░░ 91.7% 21,647 / 23,601
wizard ██████████████████░░ 91.7% 6,870 / 7,490
streamlit_apps ██████████████████░░ 91.9% 3,139 / 3,415
error_tracking ██████████████████░░ 92.1% 19,004 / 20,643
conversations ██████████████████░░ 92.3% 30,540 / 33,101
review_hog ██████████████████░░ 92.3% 17,915 / 19,413
stamphog ███████████████████░ 92.6% 8,869 / 9,579
early_access_features ███████████████████░ 92.6% 1,339 / 1,446
alerts_platform ███████████████████░ 92.8% 8,192 / 8,830
notifications ███████████████████░ 92.8% 1,217 / 1,311
alerts ███████████████████░ 92.9% 10,061 / 10,831
web_analytics ███████████████████░ 93.3% 26,075 / 27,943
cross_project_dashboards ███████████████████░ 93.4% 880 / 942
surveys ███████████████████░ 93.4% 6,941 / 7,429
exports ███████████████████░ 93.6% 4,166 / 4,452
approvals ███████████████████░ 93.7% 4,994 / 5,331
context_layer ███████████████████░ 93.8% 3,981 / 4,244
mcp_store ███████████████████░ 93.9% 9,188 / 9,784
marketing_analytics ███████████████████░ 93.9% 21,234 / 22,605
ai_observability ███████████████████░ 94.0% 29,391 / 31,266
billing_alerts ███████████████████░ 94.0% 2,322 / 2,470
messaging ███████████████████░ 94.1% 5,012 / 5,329
customer_analytics ███████████████████░ 94.1% 27,901 / 29,660
workflows ███████████████████░ 94.3% 24,695 / 26,180
logs ███████████████████░ 94.4% 19,309 / 20,457
replay_vision ███████████████████░ 94.4% 32,837 / 34,772
actions ███████████████████░ 94.7% 1,004 / 1,060
reminders ███████████████████░ 94.8% 760 / 802
experiments ███████████████████░ 94.8% 40,350 / 42,564
endpoints ███████████████████░ 94.9% 9,369 / 9,875
growth ███████████████████░ 94.9% 11,348 / 11,960
annotations ███████████████████░ 95.1% 1,095 / 1,151
skills ███████████████████░ 95.2% 7,630 / 8,015
access_control ███████████████████░ 95.4% 8,106 / 8,493
subscriptions ███████████████████░ 95.6% 13,601 / 14,228
data_catalog ███████████████████░ 95.7% 4,713 / 4,927
product_analytics ███████████████████░ 95.8% 29,875 / 31,195
feature_flags ███████████████████░ 95.8% 28,730 / 29,983
revenue_analytics ███████████████████░ 95.9% 1,877 / 1,958
data_quality ███████████████████░ 96.0% 8,561 / 8,915
tracing ███████████████████░ 96.3% 4,404 / 4,572
warehouse_sources ███████████████████░ 96.5% 481,271 / 498,684
account_audits ███████████████████░ 96.7% 770 / 796
pulse ███████████████████░ 97.1% 2,023 / 2,083
analytics_platform ████████████████████ 98.0% 2,828 / 2,885
groups ████████████████████ 98.2% 1,838 / 1,871

Report-only. Patch coverage = changed backend lines covered vs origin/master. Sorted lowest first.
Known gaps: lines covered only by Temporal tests show as uncovered; core line numbers may drift if master changed the same file.

@mayteio mayteio added the posthog-review Run a Standard PostHog Review label Oct 26, 2026

@posthog posthog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PostHog Review · Standard · reviewed dacf1b1: no findings.

This Standard review started from the posthog-review label. Comment @posthog review --deep for a Deep review, or @posthog help to see all commands.

@posthog posthog Bot removed the posthog-review Run a Standard PostHog Review label Oct 26, 2026
@trunk-io

trunk-io Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Static Badge   Static Badge   Static Badge

Failed Test Failure Summary Logs
Password Reset › Can request password reset The test timed out after 90 seconds while running the beforeEach setup hook. Logs ↗︎
ReportContextMenu routes the dismiss submenu's note button through the dialog instead of applying it The expected element was not found in the document. Logs ↗︎

View Full Report ↗︎ ⋅ Docs

mayteio commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

@PostHog review --deep

@mayteio
mayteio marked this pull request as ready for review October 27, 2026 10:43
@mayteio mayteio added the stamphog Request AI approval (no full review) label Oct 27, 2026 — with PostHog
@parameterai

parameterai Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Risk: No findings

This increment adds the recipient_unreachable refusal code to the 202/422 mapping on the shared transactional-email send path, updates the OpenAPI response descriptions, and regenerates the MCP API types. No security issues found: the template lookup stays team-scoped, the PSAK action gate (psak_allowed_actions = ["email"]) and key-to-project binding still hold, both send routes share one throttle scope set, and the permission stack (APIScopePermission, AccessControlPermission, TeamMemberAccessPermission) is retained by TeamAndOrgViewSetMixin.get_permissions despite the viewset's own permission_classes = [IsAuthenticated].

Sentinel reviewed b4f7f6d · Review settings

@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested a review from a team October 27, 2026 10:44
stamphog[bot]

This comment was marked as outdated.

mayteio commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

/trunk merge

POST /api/projects/:project_id/messaging/send/email/ sends a transactional email from the template named in the body as template.id, with the same request fields, auth, flag, checks, idempotency and error codes as /messaging_templates/:id/send/. Both routes share one send path and one set of rate-limit scopes. The send event records which route a send came from.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

Generated-By: PostHog Desktop
Task-Id: e72a2c10-f145-4f7c-8754-a4fcc06a18be
@mayteio
mayteio force-pushed the posthog/messaging-send-email-endpoint branch from dacf1b1 to b4f7f6d Compare October 27, 2026 17:24
@stamphog
stamphog Bot dismissed their stale review October 27, 2026 17:24

A new stamphog review started for this PR — the fresh verdict replaces this approval.

@stamphog stamphog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved.

Risky API and send-path changes have owning-team authorship and STRONG familiarity assurance, with added tests and no outstanding substantive concerns. The listed bot reviews are historical rather than current-head reviews.

  • Author wrote 99% of the modified lines and has 30 merged PRs in these paths (familiarity STRONG).
Gate mechanics and policy version
Gate Result
prerequisites ✓ all clear
deny-list ✓ no deny categories matched
size ✓ 274L, 2F substantive, 488L/7F incl. docs/generated/snapshots — within ceiling
tier ✓ T1-agent / T1d-complex (488L, 7F, two-areas, feat)
stamphog 2.6.1 .stamphog/policy.yml @ b4f7f6d · reviewed head b4f7f6d

mayteio commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

/trunk merge

@trunk-io

trunk-io Bot commented Oct 27, 2026

Copy link
Copy Markdown

This PR is already queued as a stacked merge. Cancel it first to re-submit.

@trunk-io
trunk-io Bot merged commit f231f8b into master Oct 27, 2026
281 of 285 checks passed
@trunk-io
trunk-io Bot deleted the posthog/messaging-send-email-endpoint branch October 27, 2026 19:16
@deployment-status-posthog

deployment-status-posthog Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-10-27 19:49 UTC Run
prod-us ✅ Deployed 2026-10-27 20:13 UTC Run
prod-eu ✅ Deployed 2026-10-27 20:15 UTC Run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stamphog Request AI approval (no full review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant