Skip to content

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

Open
mayteio wants to merge 1 commit into
masterfrom
posthog/messaging-send-email-endpoint
Open

mayteio wants to merge 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

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 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: e72a2c10-f145-4f7c-8754-a4fcc06a18be
@mayteio mayteio self-assigned this Oct 26, 2026
@trunk-io

trunk-io Bot commented Oct 26, 2026

Copy link
Copy Markdown

Merging to master in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

@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 — 🔺 +79.4 KiB (+0.1%)

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

Total: 76.93 MiB · 🔺 +79.4 KiB (+0.1%)

File Size Δ vs base
render-query/src/render-query/render-query.js 24.91 MiB 🔺 +46.5 KiB (+0.2%)
posthog-app/_parent/products/ai_observability/frontend/evaluations/EvaluationsScene.js 73.9 KiB 🟢 -12.0 KiB (-13.9%)
posthog-app/_parent/products/apm/frontend/ApplicationObservabilityScene.js 11.8 KiB 🔺 +11.8 KiB (new)
posthog-app/_parent/products/tracing/frontend/TracingScene.js 161.9 KiB 🟢 -10.0 KiB (-5.8%)
posthog-app/_parent/products/ai_observability/frontend/evaluations/AIObservabilityEvaluation.js 113.1 KiB 🔺 +8.7 KiB (+8.3%)
posthog-app/_parent/products/business_knowledge/frontend/scenes/playground/BusinessKnowledgePlaygroundScene.js 31.0 KiB 🔺 +8.3 KiB (+36.5%)
posthog-app/_parent/products/signals/frontend/inbox/InboxScene.js 512.2 KiB 🔺 +5.4 KiB (+1.1%)
posthog-app/src/scenes/experiments/Experiment.js 409.9 KiB 🔺 +2.6 KiB (+0.6%)
posthog-app/_parent/products/workflows/frontend/Broadcasts/BroadcastScene.js 122.2 KiB 🔺 +2.2 KiB (+1.8%)
posthog-app/src/layout/today/TodayAnalyticsSidebar.js 7.8 KiB 🔺 +2.1 KiB (+37.0%)
posthog-app/_parent/products/replay_vision/frontend/replay_scanners/ScannerEditorScene.js 82.1 KiB 🟢 -1.9 KiB (-2.2%)
posthog-app/src/scenes/onboarding/Onboarding.js 783.3 KiB 🔺 +1.6 KiB (+0.2%)
exporter/src/exporter/scenes/ExporterNotebookScene.js 3.90 MiB 🔺 +1.4 KiB (+0.0%)
posthog-app/_parent/products/ai_observability/frontend/offline-evaluations/OfflineScorerHistoryScene.js 19.5 KiB 🔺 +1.3 KiB (+7.4%)

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

✅ Eager graph — within 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 🔺 +5.7 KiB (+0.6%) █████████░ 87.7% 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 🔺 +7.3 KiB (+0.2%) ██████████ 97.8% of 3.03 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
7.48 MiB · 2,558 files 🔺 +29.7 KiB (+0.4%) ██████████ 99.8% of 7.50 MiB
dashboard scene
src/scenes/dashboard/Dashboard.tsx
9.93 MiB · 3,725 files 🔺 +23.0 KiB (+0.2%) ██████████ 99.2% 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.66 MiB · 2,651 files 🔺 +32.7 KiB (+0.4%) ██████████ 99.0% 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.90 MiB · 2,643 files 🔺 +32.7 KiB (+0.4%) ██████████ 100.0% of 7.91 MiB
events scene
src/scenes/activity/explore/EventsScene.tsx
9.37 MiB · 3,508 files 🔺 +18.6 KiB (+0.2%) ██████████ 97.8% of 9.59 MiB
web analytics scene
src/scenes/web-analytics/WebAnalyticsScene.tsx
10.31 MiB · 3,755 files 🔺 +19.1 KiB (+0.2%) ██████████ 95.1% of 10.83 MiB
replay detail scene
src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
8.41 MiB · 3,087 files 🔺 +13.1 KiB (+0.2%) █████████░ 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/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
24.6 KiB ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js
6.3 KiB ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js
4.7 KiB ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js
4.0 KiB ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js
1.7 KiB ../node_modules/.pnpm/base64-js@1.5.1/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/posthog-js@1.438.23_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
217.5 KiB ../node_modules/.pnpm/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/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/@dnd-kit+core@6.0.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js
36.4 KiB ../node_modules/.pnpm/kea@4.0.0-pre.6_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js
27.0 KiB ../node_modules/.pnpm/tailwind-merge@2.2.2/node_modules/tailwind-merge/dist/bundle-mjs.mjs
24.6 KiB ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
322.9 KiB ../node_modules/.pnpm/posthog-js@1.438.23_@types+react@18.3.27_react@18.3.1/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/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.8 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
100.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js
92.5 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/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/posthog-js@1.438.23_@types+react@18.3.27_react@18.3.1/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/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.8 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
144.1 KiB ../packages/quill/packages/primitives/dist/index.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
100.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js
92.5 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/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/posthog-js@1.438.23_@types+react@18.3.27_react@18.3.1/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/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.8 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
100.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js
92.5 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/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/posthog-js@1.438.23_@types+react@18.3.27_react@18.3.1/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/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.8 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
144.1 KiB ../packages/quill/packages/primitives/dist/index.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
100.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js
92.5 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/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/posthog-js@1.438.23_@types+react@18.3.27_react@18.3.1/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/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.8 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
144.1 KiB ../packages/quill/packages/primitives/dist/index.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
100.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js
92.5 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/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/posthog-js@1.438.23_@types+react@18.3.27_react@18.3.1/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/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
182.9 KiB src/queries/validators.js
153.8 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
144.1 KiB ../packages/quill/packages/primitives/dist/index.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
100.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/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/posthog-js@1.438.23_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
316.1 KiB ../node_modules/.pnpm/posthog-js@1.438.23_@types+react@18.3.27_react@18.3.1/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/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.8 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
100.8 KiB src/products.tsx
94.5 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js
92.5 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/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 🔺 +6.2 KiB (+0.3%) ████░░░░░░ 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
909.9 KiB dist/toolbar/toolbar-app-IRKHFFP6.css
694.9 KiB dist/toolbar/chunk-chunk-6MTPPF75.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-SFCUI5FH.js
74.8 KiB dist/toolbar/toolbar-app-N45GYVDW.js
69.0 KiB dist/toolbar/chunk-chunk-TSAL54PB.js
35.6 KiB dist/toolbar/chunk-chunk-REHHFROD.js
21.7 KiB dist/toolbar/chunk-chunk-C4XR7ZDA.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 — 🔺 +1.71 MiB (+0.2%)

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

Total: 969.65 MiB · 🔺 +1.71 MiB (+0.2%)

ℹ️ MCP UI apps size — 34 app(s), 27969.1 KB JS

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

App JS CSS
debug 844.3 KB 209.1 KB
action 767.7 KB 209.1 KB
action-list 835.3 KB 209.1 KB
cohort 766.7 KB 209.1 KB
cohort-list 834.3 KB 209.1 KB
email-template 766.6 KB 209.1 KB
error-details 771.6 KB 209.1 KB
error-issue 768.9 KB 209.1 KB
error-issue-list 836.7 KB 209.1 KB
experiment 832.4 KB 209.1 KB
experiment-list 836.1 KB 209.1 KB
experiment-results 834.9 KB 209.1 KB
feature-flag 834.7 KB 209.1 KB
feature-flag-list 838.4 KB 209.1 KB
feature-flag-testing 770.0 KB 209.1 KB
inline-scan 767.2 KB 209.1 KB
insight-actors 833.8 KB 209.1 KB
llm-costs 831.1 KB 209.1 KB
session-recording 768.9 KB 209.1 KB
survey 768.3 KB 209.1 KB
survey-global-stats 831.1 KB 209.1 KB
survey-list 836.0 KB 209.1 KB
survey-stats 831.1 KB 209.1 KB
trace-span 767.1 KB 209.1 KB
trace-span-list 835.2 KB 209.1 KB
vision-observation-list 834.4 KB 209.1 KB
workflow 767.0 KB 209.1 KB
workflow-list 834.7 KB 209.1 KB
workflow-setup-status 766.7 KB 209.1 KB
query-results 1086.5 KB 209.1 KB
render-ui 1162.4 KB 209.1 KB
visual-review-snapshots 771.6 KB 209.1 KB
workflow-data-suggestions 769.4 KB 209.1 KB
workflow-sending-rules 768.0 KB 209.1 KB
✅ Playwright — all passed

All tests passed.

View test results →

⚠️ 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% 523–527, 609–610

🤖 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 151746739253577 -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.3% 1,540 / 2,736
batch_exports ████████████████░░░░ 81.6% 22,900 / 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,785 / 8,785
warehouse_suggestions ██████████████████░░ 88.6% 3,047 / 3,438
mcp_registry ██████████████████░░ 89.0% 1,596 / 1,794
cohorts ██████████████████░░ 89.6% 8,568 / 9,559
product_tours ██████████████████░░ 89.7% 1,355 / 1,510
signals ██████████████████░░ 90.0% 88,828 / 98,662
tasks ██████████████████░░ 90.7% 79,896 / 88,111
managed_warehouse ██████████████████░░ 91.0% 12,251 / 13,458
data_warehouse ██████████████████░░ 91.1% 15,325 / 16,821
canvas ██████████████████░░ 91.2% 8,189 / 8,980
data_modeling ██████████████████░░ 91.4% 10,729 / 11,735
autoresearch ██████████████████░░ 91.4% 11,618 / 12,705
cdp ██████████████████░░ 91.5% 10,282 / 11,238
today ██████████████████░░ 91.6% 3,976 / 4,341
business_knowledge ██████████████████░░ 91.6% 10,017 / 10,934
metrics ██████████████████░░ 91.7% 10,627 / 11,590
slack_app ██████████████████░░ 91.7% 21,465 / 23,406
wizard ██████████████████░░ 91.7% 6,870 / 7,490
streamlit_apps ██████████████████░░ 91.9% 3,139 / 3,415
error_tracking ██████████████████░░ 92.0% 18,957 / 20,595
conversations ██████████████████░░ 92.2% 30,448 / 33,008
review_hog ██████████████████░░ 92.3% 17,915 / 19,413
early_access_features ███████████████████░ 92.6% 1,339 / 1,446
stamphog ███████████████████░ 92.6% 8,873 / 9,579
alerts_platform ███████████████████░ 92.7% 8,036 / 8,667
notifications ███████████████████░ 92.8% 1,216 / 1,310
alerts ███████████████████░ 92.9% 10,025 / 10,793
web_analytics ███████████████████░ 93.3% 26,068 / 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,256 / 31,128
messaging ███████████████████░ 94.0% 4,847 / 5,156
billing_alerts ███████████████████░ 94.0% 2,322 / 2,470
customer_analytics ███████████████████░ 94.1% 27,892 / 29,651
workflows ███████████████████░ 94.3% 24,527 / 26,012
logs ███████████████████░ 94.4% 19,281 / 20,429
replay_vision ███████████████████░ 94.4% 32,767 / 34,708
actions ███████████████████░ 94.7% 1,004 / 1,060
reminders ███████████████████░ 94.8% 760 / 802
experiments ███████████████████░ 94.8% 39,506 / 41,656
endpoints ███████████████████░ 94.9% 9,351 / 9,858
growth ███████████████████░ 94.9% 11,347 / 11,959
annotations ███████████████████░ 95.1% 1,095 / 1,151
skills ███████████████████░ 95.2% 7,630 / 8,015
access_control ███████████████████░ 95.5% 8,105 / 8,491
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,559 / 29,813
revenue_analytics ███████████████████░ 95.9% 1,877 / 1,958
data_quality ███████████████████░ 96.0% 8,561 / 8,915
tracing ███████████████████░ 96.4% 4,360 / 4,524
warehouse_sources ███████████████████░ 96.5% 479,076 / 496,432
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

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 PR adds a second transactional-email send route (POST /api/projects/:id/messaging/send/email/) by extracting the existing template-scoped send path into a shared TransactionalEmailSendMixin. The main risk — the template ID now comes from the request body instead of the URL — is guarded: the lookup is team-scoped (MessageTemplate.objects.get(team_id=team_id, ...)) and re-scoped inside send_transactional_email, and the new viewset inherits the same default permission stack, PSAK action gating, hog_flow:write scope requirement, feature-flag gate, and shared throttle scopes as the template route.

Sentinel reviewed dacf1b1 · Review settings

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

@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.

The disclosed API and security-sensitive changes have current-head independent review, owning-team authorship and STRONG familiarity. No unresolved substantive concerns or other refusal grounds were found.

  • Author wrote 99% of the modified lines and has 30 merged PRs in these paths (familiarity STRONG).
  • PostHog Review (Standard) reviewed the current head: no findings.
  • posthog[bot] reviewed the current head.
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 @ dacf1b1 · reviewed head dacf1b1

This branch has not been deployed

No deployments
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