Repository navigation
feat(workflows): validate and provision sandbox email steps - #131840
Conversation
Add the email_sandbox integration kind with credentials as its only auth type, and the two tables the sandbox sender reads: a mirror of the shared SES tenant's sending status and a staff-set organization block. Nothing reads them yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds the email_sandbox step type and its server-side contract: an allowlisted config that cannot name a sender or delivery settings, an adoption flag for new steps with stored steps grandfathered, and a refusal in broadcasts, other products' workflows and templates. Adds the project's sandbox sender endpoints (status and provision), the minute poll that mirrors the sandbox SES tenant status, a staff admin for organization blocks, and the activation exclusion for workflows whose only messages go through the sandbox. Ordinary email steps can no longer newly pick a sender row that is not an email sender. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Keep the sandbox action type in the hog flow model module so the workflows facade stays off the Django startup import path. - Grandfather the wrong-kind sender rule only from the live workflow; a lenient web draft never raised it, so its draft value must not pass publish unchecked. - Compile sandbox Hog templates with the warehouse record alias when a warehouse table triggers the workflow. - Serialize the sender status DTO directly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 CI report
|
| File | Comment lines | Added lines |
|---|---|---|
products/workflows/backend/presentation/views/hog_flow.py |
8 | 76 |
This check does not block merging. It updates on every push and clears when the share drops.
✅ Bundle size — no change
Uncompressed size of every built .js bundle, compared against the base branch.
Total: 78.37 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 — 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.04 MiB · 25 files | no change | █████████░ 91.2% 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.03 MiB · 627 files | no change | ██████████ 100.0% of 3.03 MiB |
authenticated shell (every logged-in page)src/scenes/AuthenticatedShell.tsx |
3.86 MiB · 1,235 files | no change | ██████████ 96.4% of 4.01 MiB |
dashboard scenesrc/scenes/dashboard/Dashboard.tsx |
7.77 MiB · 2,997 files | no change | ████████░░ 79.0% of 9.84 MiB |
today home pathsrc/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx |
4.84 MiB · 1,859 files | no change | ██████████ 98.2% 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.06 MiB · 2,290 files | no change | ██████████ 96.7% of 6.27 MiB |
events scenesrc/scenes/activity/explore/EventsScene.tsx |
6.79 MiB · 2,557 files | no change | ███████░░░ 72.1% of 9.41 MiB |
web analytics scenesrc/scenes/web-analytics/WebAnalyticsScene.tsx |
7.85 MiB · 2,937 files | no change | ███████░░░ 74.8% of 10.49 MiB |
replay detail scenesrc/scenes/session-recordings/detail/SessionRecordingDetail.tsx |
6.97 MiB · 2,613 files | no change | █████████░ 85.7% 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 |
|---|---|
| 362.7 KiB | ../node_modules/.pnpm/posthog-js@1.447.12_@types+react@18.3.31_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 |
| 106.4 KiB | src/products.tsx |
| 87.7 KiB | src/lib/api.ts |
| 69.0 KiB | src/lib/lemon-ui/icons/icons.tsx |
| 42.7 KiB | ../node_modules/.pnpm/@dnd-kit+core@6.3.0_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 |
| 29.0 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 |
|---|---|
| 362.7 KiB | ../node_modules/.pnpm/posthog-js@1.447.12_@types+react@18.3.31_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 |
| 106.4 KiB | src/products.tsx |
| 87.7 KiB | src/lib/api.ts |
| 69.0 KiB | src/lib/lemon-ui/icons/icons.tsx |
| 42.7 KiB | ../node_modules/.pnpm/@dnd-kit+core@6.3.0_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.6 KiB | src/lib/utils/eventUsageLogic.ts |
| 29.0 KiB | src/lib/constants.tsx |
Largest files eagerly shipped from src/scenes/dashboard/Dashboard.tsx
| Size | File |
|---|---|
| 362.7 KiB | ../node_modules/.pnpm/posthog-js@1.447.12_@types+react@18.3.31_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 |
| 116.4 KiB | ../node_modules/.pnpm/posthog-js@1.447.12_@types+react@18.3.31_react@18.3.1/node_modules/posthog-js/dist/surveys-preview.js |
| 112.5 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 106.4 KiB | src/products.tsx |
| 98.2 KiB | ../packages/quill/packages/components/dist/index.js |
| 87.7 KiB | src/lib/api.ts |
| 78.8 KiB | src/scenes/dashboard/dashboardLogic.tsx |
| 69.0 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 |
|---|---|
| 362.7 KiB | ../node_modules/.pnpm/posthog-js@1.447.12_@types+react@18.3.31_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 |
| 112.5 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 106.4 KiB | src/products.tsx |
| 87.7 KiB | src/lib/api.ts |
| 69.0 KiB | src/lib/lemon-ui/icons/icons.tsx |
| 68.5 KiB | ../products/posthog_ai/frontend/logics/runStreamLogic.ts |
| 42.7 KiB | ../node_modules/.pnpm/@dnd-kit+core@6.3.0_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 |
|---|---|
| 362.7 KiB | ../node_modules/.pnpm/posthog-js@1.447.12_@types+react@18.3.31_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 |
| 112.5 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 106.4 KiB | src/products.tsx |
| 87.7 KiB | src/lib/api.ts |
| 69.0 KiB | src/lib/lemon-ui/icons/icons.tsx |
| 68.5 KiB | ../products/posthog_ai/frontend/logics/runStreamLogic.ts |
| 42.7 KiB | ../node_modules/.pnpm/@dnd-kit+core@6.3.0_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 |
|---|---|
| 362.7 KiB | ../node_modules/.pnpm/posthog-js@1.447.12_@types+react@18.3.31_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 |
| 112.5 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 106.4 KiB | src/products.tsx |
| 98.2 KiB | ../packages/quill/packages/components/dist/index.js |
| 87.7 KiB | src/lib/api.ts |
| 78.8 KiB | src/scenes/dashboard/dashboardLogic.tsx |
| 69.0 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 |
|---|---|
| 362.7 KiB | ../node_modules/.pnpm/posthog-js@1.447.12_@types+react@18.3.31_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 |
| 116.4 KiB | ../node_modules/.pnpm/posthog-js@1.447.12_@types+react@18.3.31_react@18.3.1/node_modules/posthog-js/dist/surveys-preview.js |
| 112.5 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 106.4 KiB | src/products.tsx |
| 98.2 KiB | ../packages/quill/packages/components/dist/index.js |
| 87.7 KiB | src/lib/api.ts |
| 78.8 KiB | src/scenes/dashboard/dashboardLogic.tsx |
| 69.0 KiB | src/lib/lemon-ui/icons/icons.tsx |
Largest files eagerly shipped from src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
| Size | File |
|---|---|
| 362.7 KiB | ../node_modules/.pnpm/posthog-js@1.447.12_@types+react@18.3.31_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 329.1 KiB | ../node_modules/.pnpm/posthog-js@1.447.12_@types+react@18.3.31_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 |
| 112.5 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 106.4 KiB | src/products.tsx |
| 98.2 KiB | ../packages/quill/packages/components/dist/index.js |
| 87.7 KiB | src/lib/api.ts |
| 69.0 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 | 3.00 MiB | no change |
| shell | 2.41 MiB | no change |
| query | 56.9 KiB | no change |
| features | 274.1 KiB | no change |
Download the interactive layer graph for this PR.
Posted automatically by check-layers
✅ Toolbar bundle — eager 2.44 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.44 MiB · 19 files | no change | ████░░░░░░ 42.7% 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 |
|---|---|
| 980.1 KiB | dist/toolbar/toolbar-app-N27Y2VQV.css |
| 738.4 KiB | dist/toolbar/chunk-chunk-IWQ5X2PG.js |
| 290.5 KiB | dist/toolbar/chunk-chunk-QRQPQULA.js |
| 137.6 KiB | dist/toolbar/chunk-chunk-JCO5XNTJ.js |
| 131.8 KiB | dist/toolbar/chunk-chunk-FQJO25M6.js |
| 75.7 KiB | dist/toolbar/toolbar-app-OEB77UQQ.js |
| 69.0 KiB | dist/toolbar/chunk-chunk-BFAXZMC5.js |
| 33.8 KiB | dist/toolbar/chunk-chunk-RDAX246Y.js |
| 21.9 KiB | dist/toolbar/chunk-chunk-63VUMQXG.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 — 🔺 +9.2 KiB (+0.0%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 1005.97 MiB · 🔺 +9.2 KiB (+0.0%)
ℹ️ MCP UI apps size — 35 app(s), 36997.7 KB JS
Built size of each MCP UI app (main.js + styles.css).
| App | JS | CSS |
|---|---|---|
| debug | 1067.1 KB | 224.2 KB |
| explain-chart | 1349.4 KB | 224.2 KB |
| action | 994.3 KB | 224.2 KB |
| action-list | 1058.0 KB | 224.2 KB |
| cohort | 993.3 KB | 224.2 KB |
| cohort-list | 1057.0 KB | 224.2 KB |
| email-template | 993.1 KB | 224.2 KB |
| error-details | 998.2 KB | 224.2 KB |
| error-issue | 995.2 KB | 224.2 KB |
| error-issue-list | 1059.2 KB | 224.2 KB |
| experiment | 1055.2 KB | 224.2 KB |
| experiment-list | 1058.8 KB | 224.2 KB |
| experiment-results | 1057.2 KB | 224.2 KB |
| feature-flag | 1057.4 KB | 224.2 KB |
| feature-flag-list | 1061.2 KB | 224.2 KB |
| feature-flag-testing | 996.5 KB | 224.2 KB |
| inline-scan | 993.8 KB | 224.2 KB |
| insight-actors | 1056.5 KB | 224.2 KB |
| llm-costs | 1053.8 KB | 224.2 KB |
| session-recording | 995.5 KB | 224.2 KB |
| survey | 994.9 KB | 224.2 KB |
| survey-global-stats | 1053.8 KB | 224.2 KB |
| survey-list | 1058.7 KB | 224.2 KB |
| survey-stats | 1053.8 KB | 224.2 KB |
| trace-span | 993.7 KB | 224.2 KB |
| trace-span-list | 1057.9 KB | 224.2 KB |
| vision-observation-list | 1057.1 KB | 224.2 KB |
| workflow | 993.6 KB | 224.2 KB |
| workflow-list | 1057.4 KB | 224.2 KB |
| workflow-setup-status | 993.3 KB | 224.2 KB |
| query-results | 1318.8 KB | 224.2 KB |
| render-ui | 1425.3 KB | 224.2 KB |
| visual-review-snapshots | 998.2 KB | 224.2 KB |
| workflow-data-suggestions | 996.0 KB | 224.2 KB |
| workflow-sending-rules | 994.6 KB | 224.2 KB |
ℹ️ MCP agent API — agent-facing tool changes
What this PR changes for agents, from the tool schema snapshots and tool definitions.
Tools changed (2):
| Tool | Params | Scopes | Annotations | Schema chars |
|---|---|---|---|---|
broadcasts-create |
20,088 -> 20,584 | |||
workflows-create |
20,088 -> 20,584 |
⚠️ Backend coverage — 95.0% of changed backend lines covered — 37 uncovered
🧪 Backend test coverage
Patch coverage — changed backend lines (products + core): ███████████████████░ 95.0% (772 / 809)
| File | Patch | Uncovered changed lines |
|---|---|---|
posthog/api/integration.py |
0.0% | 2979–2980, 3048–3049 |
products/workflows/backend/facade/api.py |
25.0% | 319–324 |
products/workflows/backend/facade/contracts.py |
28.6% | 1225–1229 |
products/workflows/backend/admin/sandbox_sender_organization_block_admin.py |
89.7% | 21, 25, 36 |
products/workflows/backend/tests/fakes/ses_endpoint.py |
89.9% | 20–23, 28–29, 84 |
products/cdp/backend/validation.py |
91.7% | 121–122, 168, 173 |
products/workflows/backend/providers/ses.py |
94.4% | 483 |
products/workflows/backend/services/sandbox_email/validation.py |
94.8% | 54, 62, 73, 77, 110 |
products/workflows/backend/services/sandbox_email/provisioning.py |
96.7% | 41 |
products/workflows/backend/presentation/views/workflow_email_sandbox.py |
97.7% | 77 |
🤖 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 111502720069175 -n patch-coverage), or the coverage-data block at the end of this comment.
Per-product line coverage (touched products)
| Product | Coverage | Lines |
|---|---|---|
platform_features |
██░░░░░░░░░░░░░░░░░░ 12.1% |
7 / 58 |
data_tools |
████████████░░░░░░░░ 57.6% |
95 / 165 |
warehouse_sources_queue |
█████████████░░░░░░░ 65.9% |
2,194 / 3,330 |
demo |
██████████████░░░░░░ 71.3% |
1,978 / 2,775 |
knowledge_writer |
████████████████░░░░ 77.7% |
1,409 / 1,813 |
batch_exports |
█████████████████░░░ 82.9% |
24,777 / 29,885 |
engineering_analytics |
█████████████████░░░ 85.6% |
12,515 / 14,615 |
ml_inference |
█████████████████░░░ 86.3% |
524 / 607 |
commands |
█████████████████░░░ 86.5% |
1,645 / 1,901 |
mcp_analytics |
██████████████████░░ 87.8% |
6,827 / 7,777 |
posthog_ai |
██████████████████░░ 88.2% |
4,514 / 5,116 |
apm |
██████████████████░░ 88.2% |
1,973 / 2,236 |
notebooks |
██████████████████░░ 88.6% |
15,594 / 17,599 |
dashboards |
██████████████████░░ 89.5% |
8,969 / 10,017 |
cohorts |
██████████████████░░ 90.7% |
9,866 / 10,883 |
warehouse_suggestions |
██████████████████░░ 90.7% |
4,264 / 4,700 |
actions |
██████████████████░░ 90.9% |
1,524 / 1,677 |
visual_review |
██████████████████░░ 90.9% |
10,634 / 11,698 |
data_warehouse |
██████████████████░░ 91.1% |
15,984 / 17,546 |
signals |
██████████████████░░ 91.2% |
112,460 / 123,292 |
cdp |
██████████████████░░ 91.4% |
10,896 / 11,920 |
today |
██████████████████░░ 91.5% |
4,136 / 4,521 |
canvas |
██████████████████░░ 91.5% |
8,559 / 9,351 |
tasks |
██████████████████░░ 91.6% |
86,248 / 94,204 |
autoresearch |
██████████████████░░ 91.6% |
12,203 / 13,318 |
data_modeling |
██████████████████░░ 91.7% |
12,686 / 13,831 |
streamlit_apps |
██████████████████░░ 92.0% |
3,200 / 3,478 |
alerts_platform |
██████████████████░░ 92.0% |
10,654 / 11,576 |
release |
██████████████████░░ 92.1% |
453 / 492 |
metrics |
██████████████████░░ 92.1% |
12,068 / 13,102 |
business_knowledge |
██████████████████░░ 92.2% |
10,900 / 11,824 |
review_hog |
██████████████████░░ 92.3% |
18,397 / 19,930 |
conversations |
██████████████████░░ 92.4% |
31,728 / 34,335 |
wizard |
██████████████████░░ 92.4% |
7,323 / 7,922 |
error_tracking |
███████████████████░ 92.5% |
20,976 / 22,675 |
slack_app |
███████████████████░ 92.6% |
25,544 / 27,600 |
early_access_features |
███████████████████░ 92.7% |
1,377 / 1,486 |
notifications |
███████████████████░ 92.8% |
1,230 / 1,326 |
legal_documents |
███████████████████░ 93.0% |
2,380 / 2,558 |
ai_training |
███████████████████░ 93.1% |
605 / 650 |
managed_warehouse |
███████████████████░ 93.2% |
15,792 / 16,947 |
alerts |
███████████████████░ 93.2% |
13,752 / 14,756 |
authorization |
███████████████████░ 93.2% |
850 / 912 |
webmcp |
███████████████████░ 93.3% |
277 / 297 |
stamphog |
███████████████████░ 93.3% |
11,443 / 12,265 |
web_analytics |
███████████████████░ 93.5% |
27,059 / 28,934 |
surveys |
███████████████████░ 93.6% |
7,847 / 8,388 |
exports |
███████████████████░ 93.7% |
4,474 / 4,777 |
approvals |
███████████████████░ 93.7% |
5,020 / 5,359 |
cross_project_dashboards |
███████████████████░ 93.7% |
867 / 925 |
context_layer |
███████████████████░ 93.9% |
4,075 / 4,342 |
messaging |
███████████████████░ 93.9% |
9,228 / 9,827 |
marketing_analytics |
███████████████████░ 93.9% |
22,429 / 23,882 |
mcp_store |
███████████████████░ 94.0% |
9,391 / 9,991 |
ai_gateway |
███████████████████░ 94.0% |
1,472 / 1,566 |
billing_alerts |
███████████████████░ 94.0% |
2,332 / 2,480 |
workflows |
███████████████████░ 94.1% |
30,351 / 32,270 |
annotations |
███████████████████░ 94.1% |
1,460 / 1,552 |
managed_migrations |
███████████████████░ 94.2% |
1,886 / 2,003 |
customer_analytics |
███████████████████░ 94.2% |
31,699 / 33,658 |
ai_observability |
███████████████████░ 94.3% |
38,322 / 40,635 |
access_control |
███████████████████░ 94.3% |
8,606 / 9,122 |
replay_vision |
███████████████████░ 94.4% |
33,432 / 35,422 |
logs |
███████████████████░ 94.4% |
20,533 / 21,748 |
reminders |
███████████████████░ 94.5% |
837 / 886 |
experiments |
███████████████████░ 95.0% |
47,368 / 49,882 |
warehouse_sources |
███████████████████░ 95.0% |
142,320 / 149,854 |
growth |
███████████████████░ 95.0% |
11,602 / 12,216 |
endpoints |
███████████████████░ 95.0% |
9,725 / 10,239 |
product_tours |
███████████████████░ 95.1% |
1,271 / 1,337 |
skills |
███████████████████░ 95.1% |
7,658 / 8,053 |
uptime_monitoring |
███████████████████░ 95.3% |
306 / 321 |
data_catalog |
███████████████████░ 95.7% |
4,750 / 4,965 |
tracing |
███████████████████░ 95.7% |
5,087 / 5,315 |
ui_customization |
███████████████████░ 95.7% |
714 / 746 |
subscriptions |
███████████████████░ 95.7% |
14,176 / 14,811 |
product_analytics |
███████████████████░ 95.8% |
31,450 / 32,836 |
feature_flags |
███████████████████░ 95.8% |
30,752 / 32,104 |
revenue_analytics |
███████████████████░ 95.9% |
1,877 / 1,958 |
aeo |
███████████████████░ 95.9% |
4,131 / 4,308 |
data_quality |
███████████████████░ 96.0% |
8,583 / 8,937 |
groups |
███████████████████░ 96.4% |
2,068 / 2,145 |
account_audits |
███████████████████░ 96.5% |
823 / 853 |
security |
███████████████████░ 96.8% |
1,597 / 1,650 |
pulse |
███████████████████░ 97.0% |
2,026 / 2,089 |
analytics_platform |
████████████████████ 98.0% |
2,962 / 3,022 |
field_notes |
████████████████████ 98.4% |
181 / 184 |
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.
⚠️ MCP snapshots — 2 updated (2 modified, 0 added, 0 deleted)
Snapshots: MCP unit test snapshots updated
Changes: 2 snapshots (2 modified, 0 added, 0 deleted)
What this means:
- Snapshots have been automatically updated to match current output
Next steps:
- Review the changes to ensure they're intentional
- If unexpected, investigate what caused the output to change
✅ Django migration risk — no migrations to analyze
No Django migrations need risk analysis.
❌ Hogbox preview — build failed
The preview didn't come up for commit b9fe013. See the build log for the failing step. It'll retry on the next push.
Previews are optional and never block merging. A failure here is often a hogland or tailnet hiccup rather than anything in your PR, so the check stays green and this section is the status.
There was a problem hiding this comment.
PostHog Review · Standard · reviewed 4a3ebff: 2 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.
|
React Doctor found no issues in the changed files. 🎉 Reviewed by React Doctor for commit |
A web draft save tolerates unfinished steps, so the sender-kind rule never ran there. The sender then reached the workflow's live actions and was grandfathered when it published. A wrong-kind sender is never an unfinished edit, so every save now refuses it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ership A sandbox email step now refuses a null recipient name, subject, preheader, text or HTML, which the sender's renderer cannot take. A test run's configuration override on a workflow another product owns is now refused like a save, because the ownership check reads the flow from the context. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A test run's configuration override could claim no owning product and send a sandbox step for a workflow another product owns. The owner is set on create and never changes, so the saved value now decides. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A web draft save with malformed function inputs crashed the sender-kind check before the serializer could tolerate them. The check now leaves such inputs to the serializer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Note Decision record for this PR, written by the agent that built it (Claude Code, claude-opus-5-5). Each line holds a call made in the agent session or a review round.
|
The draft sender check now reaches cdp through its presentation re-exports, as the facade contract requires. The tenant poll is marked exempt from the team scope audit, because its model is platform state with no team. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Not approved — this change needs a human reviewer.
Re-add the stamphog label to request another review once you have addressed this.
The author belongs to the workflows owning team, but @PostHog's substantive activation concern remains unfixed and has not been accepted by another reviewer. Resolve that thread and request review from @PostHog/team-workflows; Harley Alexander and Daniel Marchuk are suggested reviewers.
- Author wrote 10% of the modified lines and has 18 merged PRs in these paths (familiarity MODERATE).
- 1 of the 41 changed files are governed by
products/desktop/AGENT_APPROVALS.md. - @PostHog on products/workflows/backend/presentation/views/hog_flow.py: the activation concern remains unaddressed. With adoption enabled, the current serializer accepts active sandbox workflows, but nodejs/src/cdp/services/hogflows/hogflow-executor.service.ts has no sandbox action handler and throws for unsupported actions; no sandbox support exists in the Node checkout. The author's rollout explanation is not independent acceptance. Address this thread by preventing activation until runtime support is present, or obtain non-author acceptance of the rollout dependency before re-requesting.
Gate mechanics and policy version
| Gate | Result | |
|---|---|---|
| prerequisites | ✓ | all clear |
| deny-list | ✓ | no deny categories matched |
| size | ✓ | 623L, 22F substantive, 1553L/41F incl. docs/generated/snapshots — within ceiling |
| tier | ✓ | T1-agent / T1d-complex (1553L, 41F, cross-cutting, feat) |
| stamphog 2.7.0 | .stamphog/policy.yml @ 90cddf7 · reviewed head 90cddf7 |
Add WORKFLOWS_SANDBOX_EMAIL_RUNTIME_ENABLED, off by default. While it is off, a workflow holding an email_sandbox step can't go live through any live write (create, update, graph or email edit, publish) or run as a test. Draft saves still work. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…side Render compiled sandbox templates on the HogVM and assert the rendered email. Answer boto3's HTTP requests with a recording SESv2 fake, so the provisioning and tenant poll tests assert the stored rows and the requests SES received, not mocked SDK calls. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
😎 Stack merged successfully - details. |
The sandbox step tests checked the stored envelope for a missing bytecode key. They now send a hog step carrying another step's compiled bytecode and render what the server stored on the HogVM, through the validator and through the hog flows API. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…b-free tests" This reverts commit 1558d21.
Two provision requests that both miss the sender row no longer let the loser overwrite the winner's created_by: provisioning creates the row and, on a conflict, returns the row that won. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # products/workflows/backend/facade/api.py
There was a problem hiding this comment.
Approved.
The author belongs to the workflows owning team, but this cross-team change also touches shared validation and API contracts; the trusted context explicitly excludes the incomplete current-head review as assurance. Request review covering those shared changes from @PostHog/team-context-and-mcp and @PostHog/team-surfaces, with Harley Alexander or Daniel Marchuk as suggested reviewers, before re-requesting.
- Author wrote 9% of the modified lines and has 18 merged PRs in these paths (familiarity MODERATE).
- PostHog Review (Standard) reviewed the current head (no findings) but skipped 1 changed file, so it does not count as assurance.
- 1 of the 41 changed files are governed by
products/desktop/AGENT_APPROVALS.md.
Gate mechanics and policy version
| Gate | Result | |
|---|---|---|
| prerequisites | ✓ | all clear |
| deny-list | ✓ | no deny categories matched |
| size | ✓ | 658L, 23F substantive, 1853L/41F incl. docs/generated/snapshots — within ceiling |
| tier | ✓ | T1-agent / T1d-complex (1853L, 41F, cross-cutting, feat) |
| stamphog 2.7.0 | .stamphog/policy.yml @ b9fe013 · reviewed head b9fe013 |
|
/trunk merge |
|
🔒 Security review withheld — this PR was merged first — This PR was reviewed, but it merged before the review could post. Posting findings here would publish exploit detail against code that has already shipped, so nothing was posted to this PR. If the review had anything to report, the security team was notified directly. This message is posted whenever a review finishes after its PR merges, regardless of whether anything was found. |
Deploy status
This table shows the |
Problem
Replaces #128948, #129061, #130911, and parts of #129058 (the poll) and #129059 (the admin).
Caution
🔴 Merge risk: high · one-way door at merge: the
workflow_email_sandboxstatus and provision endpoints and theemail_sandboxstep type enter the public API schema and the workflows MCP toolstest_validation.py. No stored workflow step, single sender or rotation list, and no function points at a non-email row in either region: prod shape.email/verifyandPATCH email/now answer 400 for any row that isn't an email row, in both regions, live on deploy. On the base the same request crashed with a 500 and wrote nothing, so no caller loses a working path. Email rows pass as before. Live run A6, base vs head.typefilter now counts anemail_sandboxstep as messaging, so a workflow holding one lists under Messaging. The list's tag still calls it Automation until U1 (#131916) adds the step to the frontend messaging types. Only flagged teams can save such a step, and no stored workflow in either region holds one: prod shape. Uncovered: a mismatched tag, cosmetic.statusanswers whatever the flag says and writes nothing.provisionwrites oneemail_sandboxrow per team. The flag refuses it when off. Two requests that race keep the first creator: a concurrent live run, base vs head.SES_SANDBOX_TENANT_NAMEis set. Unset, it sends and writes nothing. Nothing reads the row yet. Live run G.workflows-sandbox-sendergates new sandbox steps and provisioning.WORKFLOWS_SANDBOX_EMAIL_RUNTIME_ENABLED(off by default) keeps them from going live or running as tests. An unsetSES_SANDBOX_TENANT_NAMEkeeps the poll off. The sender-kind rule, the runtime check and the activation query have none: live on deploy, fix forward.Rollout
WORKFLOWS_SANDBOX_EMAIL_RUNTIME_ENABLEDandSES_SANDBOX_TENANT_NAME. The flag turns on after that.Changes
email_sandboxstep behind the adoption flag. Stored steps stay editable without it.WORKFLOWS_SANDBOX_EMAIL_RUNTIME_ENABLEDis on. Activating it, publishing it, and test-running it return a 400, because the worker can't run the step yet.workflow_email_sandboxstatus and provision endpoints create the team's sender row without an SES call.This PR builds the parts outlined in blue: the email step's sender validation, the
email_sandboxstep type, and the provisioned sender row.How did you test this code?
Test rationale: each new test file covers one contract that no older test checks.
Evidence, tests and gaps
1c7edf5, four servers (head with the flag on and off, head with the runtime switch on, and the P1 base) and a local SESv2 stub:hog_flow.pylines are existing comments re-indented when the inputs context moved into a variable.test_workflow_email_sandbox.pyandtest_product_intent.pyrun theintegration.pyandfacade/api.pylines it lists as uncovered. The other gaps are guards for malformed input.test_sandbox_email_validation.py(no database): the allowlists, IDs, null and wrongly typed text, and completeness. Hog steps run their compiled templates on the HogVM and assert the rendered email, the warehouserecordalias included. A step sent with another step's bytecode still renders its own template.test_sandbox_email_steps.py: a hog step saved with forged bytecode renders its own template on the HogVM, the flag, grandfathering, product refusal on save and on a test run's override, and the sender-kind rule on publish and on a web draft save. The draft-only and web-draft cases are mutation-checked.test_sandbox_email_steps.py, runtime switch: create, activate and publish refused, both test-run forms refused, draft saves. Removing each of the three guards turns its own cases red.products/cdp/backend/test/test_validation.py: the sender-kind rule, and malformed draft inputs reaching the serializer instead of a 500.test_workflow_email_sandbox.py: provisioning makes one row and SES receives no request, through a recording SESv2 fake at boto3's HTTP layer. It also covers access control, and that a staff POST to the admin cannot forge or omit a block's creator. A request that loses the race between its lookup and its insert returns the winner's row and keeps the winner as creator; the previous code turns it red.test_sandbox_sender_tenant_state.py: every tenant state, failed reads, stale writes, and an unset tenant name, all through the same SESv2 fake, asserting the stored row and the requests SES received.test_ses_provider.pyandtest_message_assets.py. Both files pass alone and are untouched here.Release status
Docs update
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Agent: Claude Code, claude-opus-5-5
Skills:
/improving-drf-endpoints,/writing-tests,/writing-pr-descriptions,/merge-risk,/pr-description,/qa-swarm(design pass)Involvement: one design pass, a GPT-6.1 Sol full review and eight final reads, PostHog Review on each push, live runs, an admin UI walk, and a US and EU production-shape check.
More context for AI agents
email_sandboxto the frontend kind list, icon map, and messaging types, which aligns the list tag with the backendtypefilter.b9fe013merges master after N1 landed; only imports infacade/api.pyconflicted.bd7bad9keeps the first creator when provisioning races.51cd006reverts an unrelated warehouse test stub, which moves to its own PR.953fe2brenders a forged-bytecode step instead of checking the stored envelope.9cab2cdmerges master after feat(workflows): store the sandbox sender kind and state #131749 landed, with no conflicts.1c7edf5moves the sandbox tests outside in: rendered templates and a recording SESv2 fake.0e84119added the runtime setting, which every live write and the test-run endpoint check.products/cdp/backend/validation.pysender-kind rule;facade/api.pyactivation query;services/hog_flow_writes.pyruntime check.🤖 Generated with Claude Code