Repository navigation
feat(integrations): add an email sender over MCP - #125535
Conversation
Reading a sending domain's DNS records and verifying it are both MCP tools, but creating the sender in the first place was not, so setting up email still began in the app. An agent asked to set up workflow email had to hand the person back to the UI for the first step and pick the thread up afterwards. integrations-email-create exposes the existing create endpoint for the email kind only: `kind` is dropped from the advertised schema and hardcoded in the handler, so the tool cannot make any other integration. The sender starts unverified, as it does from the app. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
😎 Merged successfully - details. |
|
Risk: Low · 2 low Since the last review the branch only merged master and regenerated the MCP schema files; the PR-authored delta is one comment line plus a behavior-identical extraction of the Slack channel-lookup budget helper, which introduces no new security surface. I re-checked the previously reported SES MAIL FROM paths in posthog/models/integration/email.py: verify() at lines 178/187 still passes the stored subdomain into set_identity_mail_from_domain (ses.py:706), and update_native_integration at line 152 still writes SES without the domain lock the create path takes at line 77 — both remain in the code unchanged by this increment. Sentinel reviewed |
There was a problem hiding this comment.
PostHog Review · Standard · reviewed 5f9257d: 1 Should fix.
See this review and its findings in PostHog Review. Comment @posthog review --deep for a Deep review. A Deep review takes longer and looks deeper than a Standard review.
🤖 CI report
|
| Function | Location | Complexity | Limit |
|---|---|---|---|
LegacyEmailSetupModal |
products/workflows/frontend/Channels/EmailSetup/EmailSetupModal.tsx:37 |
21 | 10 |
✅ 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.
✅ Comment density — 0% of added code lines are comments (1 of 236)
This section warns when comments are more than 3% of the code lines a PR adds, and alerts above 6%. Before agent-assisted PRs, the typical share was about 2%. Only full-line comments count. Docstrings, generated files, snapshots, migrations, and workflow files are left out.
Comments that restate the code, record how the change came about, or narrate the next line add noise for the next reader. Keep the comments that explain a reason the code cannot show, and remove the rest. See .agents/skills/writing-code-comments/SKILL.md for the house rules.
Files with the most added comment lines:
| File | Comment lines | Added lines |
|---|---|---|
posthog/api/integration.py |
1 | 1 |
This check does not block merging. It updates on every push and clears when the share drops.
⚠️ Bundle size — 🔺 +10.0 KiB (+0.0%)
Uncompressed size of every built .js bundle, compared against the base branch.
Total: 77.44 MiB · 🔺 +10.0 KiB (+0.0%)
| File | Size | Δ vs base |
|---|---|---|
posthog-app/_parent/products/signals/frontend/inbox/InboxScene.js |
538.9 KiB | 🔺 +9.0 KiB (+1.7%) |
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.03 MiB · 25 files | no change | █████████░ 90.1% 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 |
3.01 MiB · 625 files | no change | ██████████ 99.2% of 3.03 MiB |
authenticated shell (every logged-in page)src/scenes/AuthenticatedShell.tsx |
3.83 MiB · 1,228 files | no change | ██████████ 95.6% of 4.01 MiB |
dashboard scenesrc/scenes/dashboard/Dashboard.tsx |
7.61 MiB · 2,941 files | no change | ████████░░ 77.4% of 9.84 MiB |
today home pathsrc/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx |
4.70 MiB · 1,759 files | 🔺 +48 B (+0.0%) | ██████████ 95.4% of 4.93 MiB |
AI-first home pathsrc/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx |
6.00 MiB · 2,265 files | 🔺 +48 B (+0.0%) | ██████████ 95.7% of 6.27 MiB |
events scenesrc/scenes/activity/explore/EventsScene.tsx |
6.69 MiB · 2,519 files | no change | ███████░░░ 71.1% of 9.41 MiB |
web analytics scenesrc/scenes/web-analytics/WebAnalyticsScene.tsx |
7.71 MiB · 2,884 files | no change | ███████░░░ 73.5% of 10.49 MiB |
replay detail scenesrc/scenes/session-recordings/detail/SessionRecordingDetail.tsx |
6.91 MiB · 2,605 files | no change | █████████░ 85.0% of 8.13 MiB |
🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 products/product_analytics/frontend/insights/activityDescriptions 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/lib/logic/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/kea-test-utils/ 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
🟢 products/product_analytics/frontend/insights/activityDescriptions stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/kea-test-utils/ 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
🟢 src/layout/panel-layout/ProjectTree/menus/SessionReplayMenuItems.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/taxonomy/core-filter-definitions-by-group.json stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/navigation/projectNoticeLogic.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/navigation/ImpersonationNotice/ImpersonationNotice.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/cohorts/cohortSavedToast.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
🟢 products/subscriptions/frontend/components/Subscriptions/exportNudge/exportNudgeLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/billing/paymentEntryLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 products/conversations/frontend/components/SidePanel/sidepanelTicketsLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/zod/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/authentication/auth/loginLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/authentication/shared/passkeyLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/cohorts/CohortFilters/constants.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 products/persons/frontend/logics/personsLogic.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/surveys/constants.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/@tiptap/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/prosemirror- stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/re2js/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/react-markdown/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/Command/Command.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 packages/quill/packages/ 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
🟢 packages/quill/packages/quill/dist/ stays out of src/scenes/dashboard/Dashboard.tsx
🟢 node_modules/@tiptap/ stays out of src/scenes/dashboard/Dashboard.tsx
🟢 node_modules/prosemirror- stays out of src/scenes/dashboard/Dashboard.tsx
🟢 node_modules/marked/ stays out of src/scenes/dashboard/Dashboard.tsx
🟢 node_modules/frimousse/ stays out of src/scenes/dashboard/Dashboard.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/queries/web-analytics-validators.js stays out of src/scenes/dashboard/Dashboard.tsx
🟢 node_modules/re2js/ stays out of src/scenes/dashboard/Dashboard.tsx
🟢 node_modules/kea-test-utils/ stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/scenes/debug/HogDebug.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/queries/QueryEditor/QueryEditor.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 packages/quill/packages/quill/dist/ stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.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
🟢 packages/quill/packages/quill/dist/ 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/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
🟢 packages/quill/packages/quill/dist/ stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 node_modules/@tiptap/ stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 node_modules/prosemirror- stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 node_modules/marked/ stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 node_modules/frimousse/ stays out of src/scenes/activity/explore/EventsScene.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/queries/web-analytics-validators.js stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 node_modules/re2js/ stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 node_modules/kea-test-utils/ stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/queries/nodes/InsightViz/InsightViz.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/queries/nodes/DataVisualization/DataVisualization.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/queries/nodes/WebOverview/WebOverview.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/scenes/debug/HogDebug.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/queries/QueryEditor/QueryEditor.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 packages/quill/packages/quill/dist/ stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 node_modules/@tiptap/ stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 node_modules/prosemirror- stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 node_modules/marked/ stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 node_modules/frimousse/ stays out of src/scenes/web-analytics/WebAnalyticsScene.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/queries/validators.js stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 node_modules/re2js/ stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 node_modules/kea-test-utils/ stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 src/scenes/debug/HogDebug.tsx stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 src/queries/QueryEditor/QueryEditor.tsx stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 packages/quill/packages/quill/dist/ stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 node_modules/@tiptap/ stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 node_modules/prosemirror- stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 node_modules/marked/ stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.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
🟢 node_modules/re2js/ stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 node_modules/kea-test-utils/ stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 node_modules/d3/src/ 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.9 KiB | src/lib/utils/bootTiming.ts |
| 1.7 KiB | src/index.tsx |
| 1.7 KiB | ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js |
| 1.2 KiB | src/RootErrorBoundary.tsx |
| 1.1 KiB | src/lib/utils/deferredAppContext.ts |
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
| Size | File |
|---|---|
| 359.8 KiB | ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 224.1 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 |
| 105.7 KiB | src/products.tsx |
| 87.4 KiB | src/lib/api.ts |
| 68.7 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 |
| 28.6 KiB | src/lib/constants.tsx |
| 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 |
|---|---|
| 359.8 KiB | ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 224.1 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 |
| 105.7 KiB | src/products.tsx |
| 87.4 KiB | src/lib/api.ts |
| 68.7 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 |
| 32.5 KiB | src/lib/utils/eventUsageLogic.ts |
| 28.6 KiB | src/lib/constants.tsx |
Largest files eagerly shipped from src/scenes/dashboard/Dashboard.tsx
| Size | File |
|---|---|
| 359.8 KiB | ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 224.1 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 |
| 115.8 KiB | ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/surveys-preview.js |
| 111.3 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 105.7 KiB | src/products.tsx |
| 96.1 KiB | ../packages/quill/packages/components/dist/index.js |
| 87.4 KiB | src/lib/api.ts |
| 79.0 KiB | src/scenes/dashboard/dashboardLogic.tsx |
| 68.7 KiB | src/lib/lemon-ui/icons/icons.tsx |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
| Size | File |
|---|---|
| 359.8 KiB | ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 224.1 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 |
| 111.3 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 105.7 KiB | src/products.tsx |
| 87.4 KiB | src/lib/api.ts |
| 68.7 KiB | src/lib/lemon-ui/icons/icons.tsx |
| 68.5 KiB | ../products/posthog_ai/frontend/logics/runStreamLogic.ts |
| 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 |
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 |
|---|---|
| 359.8 KiB | ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 224.1 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 |
| 111.3 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 105.7 KiB | src/products.tsx |
| 87.4 KiB | src/lib/api.ts |
| 68.7 KiB | src/lib/lemon-ui/icons/icons.tsx |
| 68.5 KiB | ../products/posthog_ai/frontend/logics/runStreamLogic.ts |
| 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 |
| 41.7 KiB | src/scenes/hog-functions/sub-templates/sub-templates.ts |
Largest files eagerly shipped from src/scenes/activity/explore/EventsScene.tsx
| Size | File |
|---|---|
| 359.8 KiB | ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 224.1 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 |
| 111.3 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 105.7 KiB | src/products.tsx |
| 96.1 KiB | ../packages/quill/packages/components/dist/index.js |
| 87.4 KiB | src/lib/api.ts |
| 79.0 KiB | src/scenes/dashboard/dashboardLogic.tsx |
| 68.7 KiB | src/lib/lemon-ui/icons/icons.tsx |
| 68.5 KiB | ../products/posthog_ai/frontend/logics/runStreamLogic.ts |
Largest files eagerly shipped from src/scenes/web-analytics/WebAnalyticsScene.tsx
| Size | File |
|---|---|
| 359.8 KiB | ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 224.1 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 |
| 115.8 KiB | ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/surveys-preview.js |
| 111.3 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 105.7 KiB | src/products.tsx |
| 96.1 KiB | ../packages/quill/packages/components/dist/index.js |
| 87.4 KiB | src/lib/api.ts |
| 79.0 KiB | src/scenes/dashboard/dashboardLogic.tsx |
| 68.7 KiB | src/lib/lemon-ui/icons/icons.tsx |
Largest files eagerly shipped from src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
| Size | File |
|---|---|
| 359.8 KiB | ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 321.1 KiB | ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/rrweb.js |
| 224.1 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 |
| 111.3 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 105.7 KiB | src/products.tsx |
| 96.1 KiB | ../packages/quill/packages/components/dist/index.js |
| 87.4 KiB | src/lib/api.ts |
| 68.7 KiB | src/lib/lemon-ui/icons/icons.tsx |
| 68.5 KiB | ../products/posthog_ai/frontend/logics/runStreamLogic.ts |
Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479
✅ Frontend layers — no new upward imports, 0 removed
Static imports from a lower frontend layer into a higher one (layers, lowest first: kernel, shell, query, features). Compared with the base branch, so an import that a PR also adds to layer-baseline.txt still shows here. Sizes are the source bytes on the eager path of every logged-in page.
| Layer | Eager source bytes | Δ vs base |
|---|---|---|
| kernel | 2.98 MiB | no change |
| shell | 2.36 MiB | no change |
| query | 56.2 KiB | no change |
| features | 273.8 KiB | no change |
Download the interactive layer graph for this PR.
Posted automatically by check-layers
✅ Toolbar bundle — eager 2.43 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.43 MiB · 19 files | no change | ████░░░░░░ 42.4% of 5.72 MiB |
| Deferred (lazy) | 2.64 MiB · 44 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 |
|---|---|
| 967.6 KiB | dist/toolbar/toolbar-app-DPGLK7O2.css |
| 732.3 KiB | dist/toolbar/chunk-chunk-J5PBHNM7.js |
| 290.5 KiB | dist/toolbar/chunk-chunk-CBC3BDP6.js |
| 137.0 KiB | dist/toolbar/chunk-chunk-HTOXCPKS.js |
| 131.8 KiB | dist/toolbar/chunk-chunk-FQJO25M6.js |
| 75.7 KiB | dist/toolbar/toolbar-app-BQQKEFBC.js |
| 69.0 KiB | dist/toolbar/chunk-chunk-BFAXZMC5.js |
| 33.8 KiB | dist/toolbar/chunk-chunk-6EBAJOMK.js |
| 21.9 KiB | dist/toolbar/chunk-chunk-6Y3VU5HE.js |
| 6.8 KiB | dist/toolbar/chunk-chunk-RVLGRPCH.js |
Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile
✅ Dist folder size — 🔺 +101.0 KiB (+0.0%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 991.35 MiB · 🔺 +101.0 KiB (+0.0%)
ℹ️ MCP UI apps size — 35 app(s), 29918.4 KB JS
Built size of each MCP UI app (main.js + styles.css).
| App | JS | CSS |
|---|---|---|
| debug | 864.4 KB | 222.2 KB |
| explain-chart | 1143.1 KB | 222.2 KB |
| action | 793.1 KB | 222.2 KB |
| action-list | 855.4 KB | 222.2 KB |
| cohort | 792.1 KB | 222.2 KB |
| cohort-list | 854.4 KB | 222.2 KB |
| email-template | 792.0 KB | 222.2 KB |
| error-details | 797.0 KB | 222.2 KB |
| error-issue | 794.1 KB | 222.2 KB |
| error-issue-list | 856.6 KB | 222.2 KB |
| experiment | 852.5 KB | 222.2 KB |
| experiment-list | 856.2 KB | 222.2 KB |
| experiment-results | 854.4 KB | 222.2 KB |
| feature-flag | 854.8 KB | 222.2 KB |
| feature-flag-list | 858.5 KB | 222.2 KB |
| feature-flag-testing | 795.4 KB | 222.2 KB |
| inline-scan | 792.6 KB | 222.2 KB |
| insight-actors | 853.9 KB | 222.2 KB |
| llm-costs | 851.2 KB | 222.2 KB |
| session-recording | 794.4 KB | 222.2 KB |
| survey | 793.7 KB | 222.2 KB |
| survey-global-stats | 851.2 KB | 222.2 KB |
| survey-list | 856.1 KB | 222.2 KB |
| survey-stats | 851.2 KB | 222.2 KB |
| trace-span | 792.5 KB | 222.2 KB |
| trace-span-list | 855.3 KB | 222.2 KB |
| vision-observation-list | 854.5 KB | 222.2 KB |
| workflow | 792.4 KB | 222.2 KB |
| workflow-list | 854.8 KB | 222.2 KB |
| workflow-setup-status | 792.1 KB | 222.2 KB |
| query-results | 1114.5 KB | 222.2 KB |
| render-ui | 1218.8 KB | 222.2 KB |
| visual-review-snapshots | 797.0 KB | 222.2 KB |
| workflow-data-suggestions | 794.8 KB | 222.2 KB |
| workflow-sending-rules | 793.5 KB | 222.2 KB |
ℹ️ MCP agent API — agent-facing tool changes
What this PR changes for agents, from the tool schema snapshots and tool definitions.
Tools added (1): integrations-email-create
HostHog preview —
|
create_native_integration keys update_or_create on the sender address, so an address that already has a sender is overwritten and its config.verified is reset. On SES that stops a workflow sending from it until the domain is verified again. The tool is now annotated destructive, so a host that guards destructive calls asks first, and the description tells the caller to check integrations-list rather than call this to retry or amend a sender. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ting it create_native_integration keyed update_or_create on the sender address, so adding an address that already had a sender rewrote the row and reset config.verified. On SES that stops every workflow sending from it until the domain is verified again, and nothing told the caller it had happened. A duplicate address is now refused, which the app surfaces as the error on the add-sender form. Editing a sender already has its own endpoint, so the overwrite was reachable only by mistake. The MCP tool goes back to non-destructive, since it can no longer damage an existing sender. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…n upsert The duplicate check runs before the provider call, which takes seconds, so two creates for one address can both pass it. update_or_create then resolved the collision as an update, rewriting the winner's row and resetting its verified flag: the overwrite the check was added to stop. The row is now inserted, and the unique constraint on team, kind and integration_id settles the race. The early check stays so an obvious duplicate never reaches the provider. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
SES keeps one MAIL FROM per domain identity, shared by every sender on it and across the organization's projects. A second sender on an existing domain carried its own subdomain, defaulting to feedback, which repointed bounce handling for the senders already using that domain. A new sender on a domain that already has one now inherits its subdomain. The add-sender form passes the existing value when it knows it; the rule now holds wherever the sender is created from. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
PostHog Review · Standard · reviewed ccc95ab: 1 Should fix.
This is review round 3 on this pull request. When findings keep coming back in the same code, the approach is usually the problem. Before the next fix, check whether a different design would remove the whole class of findings.
…MAIL FROM Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
PostHog Review · Standard · reviewed 5c140ba: 1 Should fix.
This is review round 4 on this pull request. When findings keep coming back in the same code, the approach is usually the problem. Before the next fix, check whether a different design would remove the whole class of findings.
…side the org Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
PostHog Review · Standard · reviewed c79983f: 1 Should fix.
This is review round 5 on this pull request. When findings keep coming back in the same code, the approach is usually the problem. Before the next fix, check whether a different design would remove the whole class of findings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…its as before A second sender on a domain now takes the MAIL FROM subdomain SES uses for the identity, read through the workflows facade, instead of a stored row that can disagree with SES. Editing a sender goes back to the base behavior: it updates that one sender and no siblings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… wording Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…main Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-create-email-sender
- Take a per-domain advisory lock in create_native_integration, so two creates on one domain run in turn: a repeated address is refused before SES, and a new address takes the MAIL FROM SES now has. - Refresh the legacy setup form from the created sender, so Save sends the stored MAIL FROM and does not repoint SES for the domain. - Share the duplicate-sender message and narrow the serializer comment on upserts, which no longer holds for email. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Hold the domain lock on a second connection and check that a create on that domain waits, while a create on another domain goes through. - Tell the legacy setup modal's user that every sender on a domain shares one MAIL FROM subdomain, which is why the field can show the stored value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t changes The lock test now takes the lock through the same helper as the model, so the key cannot drift between them. The help text says that changing the MAIL FROM subdomain changes it for every sender on the domain. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Note 🤖 Claude Opus 5.5 responding on behalf of Michael Decisions from the takeover and its review rounds:
|
Names and tests carry the intent: lock_sender_domain, the duplicate refusal before the provider call, and the modal test for the stored MAIL FROM. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… docstring Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PostHog Review · Deep · reviewed
|
| Step | Status | Result |
|---|---|---|
| Prepare the diff | done | 11 files, 1 chunk |
| Pick perspectives | done | 4 perspectives |
| Run review passes | done | 2 issues (+1 blind-spot) |
| Merge overlapping findings | done | 3 → 3 |
| Validate findings | done | 0 kept, 3 dismissed |
| Publish | done | Nothing to post |
|
/trunk merge |
1 similar comment
|
/trunk merge |

Problem
An agent setting up workflow email cannot create the sender. A user interview named this handoff back to the app as where setup stalls.
In the app, re-adding an address reset the sender to unverified, and a second sender moved SES's bounce domain (MAIL FROM) for the others.
Warning
🟡 Merge risk: medium · two-way door (merge-risk rubric)
git revertthe merge commit.Changes
integrations-email-createlets an agent add an email sender, behind a flag.How did you test this code?
Test rationale: tests catch a tool body without
kind: 'email', an overwritten sender, a second sender ignoring SES, a dropped domain lock, and a stale Save.Release status
workflows-email-domain-agent-setup.Docs update
🤖 Agent context
Autonomy: Human-driven (agent-assisted). Built by meikelmosby; Michael directed the takeover.
Involvement: QA swarm (3 rounds and three final reads), review bots, live-run, UI walk and prod-shape proof.
Agent: Claude Code, Opus 5 and Opus 5.5
Skills:
/writing-tests,/writing-code-comments,/improving-drf-endpoints,/writing-pr-descriptionsMore context for AI agents
inject_bodyandexclude_params, so it creates only email senders.create_native_integrationis atomic and takespg_advisory_xact_lockon the domain; the serializer's transaction holds it through the SES calls.lib/apicalls; moving to generated clients is out of scope.configand becomes the onlyintegrations-email-createdefinition.create_native_integrationinposthog/models/integration/email.py, the only hunk on the live app path.integrations-email-create.LegacyEmailSetupModalcomplexity predates this PR, which changes one help string there. The bundle growth is in scenes this PR does not touch, such as feature flags and Transactional, from master commits after this branch's merge base (feat(flags): show rules v2 flags as an ordered rule flow #127839, feat(workflows): add trend charts to the transactional metrics tab #130558, feat(workflows): show email log activity on one collapsible rail #130597 and others).Earlier evidence (before the takeover)
A shadow run sent 15 API journeys through master's create path and this one. Edits and verifies matched; the 4 differing creates are the changes above.
🤖 Generated with Claude Code