Repository navigation
feat(workflows): open entry-point broadcasts and workflows ready to send - #114807
Conversation
…nfiltered audiences
…missing-recipient-email # Conflicts: # products/workflows/frontend/Broadcasts/broadcastWizardLogic.test.ts # products/workflows/frontend/Broadcasts/broadcastWizardLogic.ts
|
😎 Stack merged successfully - details. |
🤖 CI report✅ Trunk lane — non-backend laneThis PR is assigned to the non-backend lane. It does not run backend Python tests and may merge in parallel with PRs in other lanes.
|
| Function | Location | Complexity | Limit |
|---|---|---|---|
EarlyAccessFeature |
products/early_access_features/frontend/EarlyAccessFeature.tsx:208 |
63 | 10 |
<anonymous> |
products/workflows/frontend/Workflows/workflowLogic.ts:3680 |
39 | 10 |
runSave |
products/workflows/frontend/Workflows/workflowLogic.ts:3233 |
37 | 10 |
saveWorkflowSuccess |
products/workflows/frontend/Workflows/workflowLogic.ts:4178 |
33 | 10 |
launchBroadcast |
products/workflows/frontend/Broadcasts/broadcastWizardLogic.ts:1638 |
27 | 10 |
WorkflowScene |
products/workflows/frontend/Workflows/WorkflowScene.tsx:62 |
26 | 10 |
toAudienceFilter |
products/workflows/frontend/Broadcasts/broadcastAudiencePrefill.ts:59 |
25 | 10 |
<anonymous> |
products/workflows/frontend/Broadcasts/broadcastWizardLogic.ts:1109 |
22 | 10 |
<anonymous> |
products/workflows/frontend/Broadcasts/broadcastWizardLogic.ts:1942 |
15 | 10 |
parseMessageDraftPrefill |
products/workflows/frontend/MessageAudience/messageDrafts.ts:98 |
13 | 10 |
setEmail |
products/workflows/frontend/Broadcasts/broadcastWizardLogic.ts:1424 |
12 | 10 |
saveName |
products/workflows/frontend/Broadcasts/broadcastWizardLogic.ts:1480 |
11 | 10 |
moveToDraft |
products/workflows/frontend/Broadcasts/broadcastWizardLogic.ts:1815 |
11 | 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 — 4% of added code lines are comments (23 of 523)
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 |
|---|---|---|
products/workflows/frontend/MessageAudience/messageDrafts.ts |
8 | 160 |
products/workflows/frontend/Broadcasts/broadcastWizardLogic.ts |
6 | 67 |
products/workflows/frontend/Workflows/workflowEmailPrefill.ts |
6 | 82 |
products/workflows/frontend/Workflows/workflowLogic.ts |
2 | 35 |
products/workflows/frontend/Broadcasts/broadcastWizardLogic.test.ts |
1 | 47 |
This check does not block merging. It updates on every push and clears when the share drops.
⚠️ Bundle size — 🔺 +4.9 KiB (+0.0%)
Uncompressed size of every built .js bundle, compared against the base branch.
Total: 75.83 MiB · 🔺 +4.9 KiB (+0.0%)
| File | Size | Δ vs base |
|---|---|---|
render-query/src/render-query/render-query.js |
24.36 MiB | 🔺 +13.5 KiB (+0.1%) |
posthog-app/_parent/products/workflows/frontend/TemplateLibrary/MessageTemplate.js |
22.1 KiB | 🟢 -9.7 KiB (-30.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 |
1002.2 KiB · 23 files | no change | █████████░ 85.5% 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.86 MiB · 615 files | no change | █████████░ 94.4% of 3.03 MiB |
authenticated shell (every logged-in page)src/scenes/AuthenticatedShell.tsx |
7.28 MiB · 2,511 files | 🔺 +13.0 KiB (+0.2%) | ██████████ 95.2% of 7.64 MiB |
dashboard scenesrc/scenes/dashboard/Dashboard.tsx |
9.52 MiB · 3,591 files | 🔺 +13.0 KiB (+0.1%) | █████████░ 92.4% of 10.30 MiB |
today home pathsrc/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx |
7.30 MiB · 2,521 files | 🔺 +13.0 KiB (+0.2%) | █████████░ 92.6% of 7.89 MiB |
events scenesrc/scenes/activity/explore/EventsScene.tsx |
9.11 MiB · 3,426 files | 🔺 +13.0 KiB (+0.1%) | █████████░ 92.2% of 9.88 MiB |
replay detail scenesrc/scenes/session-recordings/detail/SessionRecordingDetail.tsx |
11.90 MiB · 4,269 files | 🔺 +13.0 KiB (+0.1%) | ████████░░ 79.0% of 15.05 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
🟢 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
🟢 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/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
🟢 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
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.5 KiB | ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js |
| 3.9 KiB | ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js |
| 1.4 KiB | ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js |
| 1.3 KiB | src/RootErrorBoundary.tsx |
| 1.3 KiB | src/index.tsx |
| 912 B | ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js |
| 839 B | src/scenes/ChunkLoadErrorBoundary.tsx |
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
| Size | File |
|---|---|
| 317.7 KiB | ../node_modules/.pnpm/posthog-js@1.438.4_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 220.8 KiB | ../node_modules/.pnpm/@posthog+icons@0.38.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 |
| 101.5 KiB | src/products.tsx |
| 99.6 KiB | src/lib/api.ts |
| 69.0 KiB | src/lib/lemon-ui/icons/icons.tsx |
| 38.7 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 |
| 33.9 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/scenes/scenes.ts |
| 27.6 KiB | src/lib/constants.tsx |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
| Size | File |
|---|---|
| 317.7 KiB | ../node_modules/.pnpm/posthog-js@1.438.4_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 280.8 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.8 KiB | ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 153.7 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 |
| 113.0 KiB | ../packages/quill/packages/quill/dist/index.js |
| 101.5 KiB | src/products.tsx |
| 99.6 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 90.6 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/dashboard/Dashboard.tsx
| Size | File |
|---|---|
| 317.7 KiB | ../node_modules/.pnpm/posthog-js@1.438.4_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 280.8 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.8 KiB | ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 181.9 KiB | src/queries/validators.js |
| 153.7 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 |
| 113.0 KiB | ../packages/quill/packages/quill/dist/index.js |
| 101.5 KiB | src/products.tsx |
| 99.6 KiB | src/lib/api.ts |
| 93.3 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 |
|---|---|
| 317.7 KiB | ../node_modules/.pnpm/posthog-js@1.438.4_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 280.8 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.8 KiB | ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 153.7 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 |
| 113.0 KiB | ../packages/quill/packages/quill/dist/index.js |
| 101.5 KiB | src/products.tsx |
| 99.6 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 90.6 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/activity/explore/EventsScene.tsx
| Size | File |
|---|---|
| 317.7 KiB | ../node_modules/.pnpm/posthog-js@1.438.4_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 280.8 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.8 KiB | ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 181.9 KiB | src/queries/validators.js |
| 153.7 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 |
| 113.0 KiB | ../packages/quill/packages/quill/dist/index.js |
| 101.5 KiB | src/products.tsx |
| 99.6 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
Largest files eagerly shipped from src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
| Size | File |
|---|---|
| 317.7 KiB | ../node_modules/.pnpm/posthog-js@1.438.4_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 316.0 KiB | ../node_modules/.pnpm/posthog-js@1.438.4_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/rrweb.js |
| 280.8 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.8 KiB | ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 181.9 KiB | src/queries/validators.js |
| 153.7 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 |
| 113.0 KiB | ../packages/quill/packages/quill/dist/index.js |
| 101.5 KiB | src/products.tsx |
| 99.6 KiB | src/lib/api.ts |
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.24 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.24 MiB · 19 files | no change | ████░░░░░░ 39.2% of 5.72 MiB |
| Deferred (lazy) | 2.19 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 |
|---|---|
| 872.1 KiB | dist/toolbar/toolbar-app-2BT2CMPS.css |
| 661.9 KiB | dist/toolbar/chunk-chunk-7N2P2AVY.js |
| 259.6 KiB | dist/toolbar/chunk-chunk-LPBBQMMO.js |
| 138.9 KiB | dist/toolbar/chunk-chunk-PJ5QL3Y6.js |
| 131.8 KiB | dist/toolbar/chunk-chunk-FDH2IBXT.js |
| 75.2 KiB | dist/toolbar/toolbar-app-VMJBQ5YR.js |
| 69.0 KiB | dist/toolbar/chunk-chunk-TSAL54PB.js |
| 35.6 KiB | dist/toolbar/chunk-chunk-UJGIDH7X.js |
| 21.7 KiB | dist/toolbar/chunk-chunk-OV4LUCFT.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 — 🔺 +179.3 KiB (+0.0%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 1010.68 MiB · 🔺 +179.3 KiB (+0.0%)
✅ Hogbox preview — ready, open the preview
▶ Open the preview
| 🔑 Login | test@posthog.com / 12345678 (demo data) |
| 🧩 Running | this PR's backend and frontend, on the PostHog :master base |
| 🔗 Link | stable across rebuilds: a re-push swaps the box underneath, the URL stays |
| 🔒 Access | tailnet only (PostHog VPN) |
| 🛠️ Admin | inspect & debug state in hogland |
| 💤 Idle | sleeps after ~30 min idle (snapshot to S3, zero node cost) and wakes on your next visit in ~30s, behind a brief "waking up" screen |
commit d154209 · box box-ffac511d1c92 · ready in 1786s (push → usable) · build log · rebuilds on every push, torn down on close
|
Risk: No findings This increment hardens the email-draft prefill against template injection: entity names and URL-supplied draft text now have Liquid delimiters ( Sentinel reviewed |
There was a problem hiding this comment.
Not approved yet — waiting on the conditions below.
Re-add the stamphog label to request another review once you have addressed this.
The size gate refused this pull request. It has 4319 substantive changed lines across 13 files (4441 lines across 16 files including docs, generated files and snapshots), well over the 800-line ceiling for auto-review. Most of that comes from the large changes to workflowLogic.ts and hogFlowEditorLogic.tsx. The other gates (prerequisites, deny-list and tier) passed, so size is the only blocker.
The author can ask a human reviewer to look at it. They could also split it into smaller pull requests, for example the regenerated kea types and loadWorkflow return-type change on their own, then the new draft modules (messageDrafts.ts and workflowEmailPrefill.ts), then the broadcast and workflow entry-point wiring.
Gate mechanics and policy version
| Gate | Result | |
|---|---|---|
| prerequisites | ✓ | all clear |
| deny-list | ✓ | no deny categories matched |
| size | ✗ | too large for auto-review (4319L substantive in global — ceiling is 800L; 4319L, 13F total, 4441L/16F incl. docs/generated/snapshots) |
| tier | ✓ | T1-agent / T1d-complex (4441L, 16F, two-areas, feat) |
| stamphog 2.4.1 | .stamphog/policy.yml @ unknown · reviewed head 7e37ce1 |
👀 Auto-assigned reviewersThese soft owners were skipped because they only have minor changes here. Nothing blocks merge, so self-assign if you'd like a look:
Soft owners come from each directory's |
|
…logic types stay unchanged
|
✅ Visual changes approved by @dmarchuk — baseline updated in 3 changed. Install the Visual Review Chrome extension to see visual review results at the top of your pull requests. |
3 updated Run: 0cf01ab6-38e8-4b49-bad8-d0a88323a786 Co-authored-by: dmarchuk <8395106+dmarchuk@users.noreply.github.com>
A new stamphog review started for this PR — the fresh verdict replaces this approval.
|
/trunk merge |
A new stamphog review started for this PR — the fresh verdict replaces this approval.
|
/trunk merge |
…prefilled-start # Conflicts: # products/workflows/frontend/Broadcasts/broadcastWizardLogic.ts
A new stamphog review started for this PR — the fresh verdict replaces this approval.
There was a problem hiding this comment.
Approved.
The security-sensitive portion is owned by the author's workflows team, providing the policy's owning-team assurance path. No unresolved substantive review concerns or other refusal grounds were found; the discussion bot summary is not a current-head review.
- Author wrote 61% of the modified lines and has 33 merged PRs in these paths (familiarity MODERATE).
Gate mechanics and policy version
| Gate | Result | |
|---|---|---|
| prerequisites | ✓ | all clear |
| deny-list | ✓ | no deny categories matched |
| size | ✓ | 438L, 12F substantive, 580L/15F incl. docs/generated/snapshots — within ceiling |
| tier | ✓ | T1-agent / T1d-complex (580L, 15F, two-areas, feat) |
| stamphog 2.4.1 | .stamphog/policy.yml @ d154209 · reviewed head d154209 |
Problem
Changes
emailsearch param). The wizard fills the subject and body. With the project's default sender (feat(workflows): default email sender for new broadcasts and workflow emails #114682), it opens on Review.{{ person.properties.email }}. An event trigger gets the existing "One time" frequency ({person.id}, indefinitely), so someone who hits the error again gets no second email.messageDrafts.ts. Error tracking uses no issue text, because issue titles are technical. Early access uses the feature name and description. No LLM is involved. A later PR can swap in an AI draft at this one module.broadcast launchedgetsprefilled_email_edited, andbroadcast prefilled from linkgetshas_email.workflowLogicprops and logic key gainemailPrefill.More screenshots and a recording
Early access, one-time email, from the feature page to Review:
A feature name with HTML in it, shown as text:
Cohort link, and a draft with no usable sender, both open on Content:
Workflow from an error issue: frequency set to one time, and the draft in the visual editor:
How did you test this code?
Driven in a real browser (Playwright) on a local stack: this branch's frontend, a Django on a migrated clone of the dev database, and team 1 with four verified senders and a project default.
posthog_hogflowrowstatus=active,origin_product=broadcasts,from={"integrationId": 14}, the template subject, and adesignkey.workflows_hogflowbatchjobrow,status=queued.status=active,trigger_masking={"ttl": null, "hash": "{person.id}", "bytecode": [...]}, the email step'sfrom={"integrationId": 14}, and escaped HTML.POST /hog_flows/request was sent.<img src=x onerror=alert(1)> & co: no dialog fired, and the text shows literally in the subject, preview and visual editor.Reload, before and after
e06081e(early access link, reload at each step before Continue):/broadcasts/newbefore Continue is gone after a reload. That comes from saving only on Continue, and this PR does not change it.Liquid in entity names (fix after review):
{{ person.properties.email }},{% if true %}x{% endif %},{% endraw %}{{ event.event }},{{{ a }}} and {%- raw -%}andPlain é 🚀 name.formatLiquidInput, with globals holding a person email and an event name.messageDrafts.test.tscases fail (2 of 10).Not tested:
Test rationale:
messageDrafts.test.ts: catches unescaped entity names reaching the HTML or design, Liquid delimiters in a name or link running as a template, and a malformedemailparam being used. No test covered this module before.workflowEmailPrefill.test.ts: catches an event-triggered workflow losing its once-per-person frequency, and a template's own sender being overwritten.broadcastWizardLogic.test.ts, oneit.eachadded next to the existing link-prefill test: catches the wizard landing on the wrong step, or creating a draft when a link opens it.broadcastWizardLogic.test.ts, the existing link-prefill test now remounts the wizard on the same URL: catches a reload losing the prefill again.Release status
Docs update
None.
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Agent: Claude Code, Claude Opus 5.5 (1M context)
messageDrafts.tsoutput, with these templates as its fallback.loadWorkflowreturn type, which regenerated thousands of lines of kea types. The second commit keeps the type.🤖 Generated with Claude Code
https://claude.ai/code/session_01BR6LoqsDMB9Wfnftcy2KiG