Skip to content

chore(workflows): route the small workflows views through the facade - #108476

Open
mayteio wants to merge 4 commits into
posthog/workflows-seal-reverse-accessorsfrom
posthog/workflows-slice-3a-small-views
Open

mayteio wants to merge 4 commits into
posthog/workflows-seal-reverse-accessorsfrom
posthog/workflows-slice-3a-small-views

Conversation

@mayteio

@mayteio mayteio commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

Problem

  • Every workflows PR still runs the full backend suite, because products/workflows cannot turn on backend:contract-check while its views import internals directly.
  • This is slice 3a of #84402. It covers three of the four small views. Slice 3b covers hog_flow_template.py in a separate PR.
  • Nothing changes for users. The work removes 5 of the 38 ignore_imports entries that block the CI skip.

Refs #84402

Changes

Nothing changes for users. The API responses stay the same, and the only generated-type change is three new field descriptions.

  • Batch runs: the batch_jobs POST creates the row through a new facade function create_batch_job.
    • HogFlowBatchJobSerializer becomes a plain serializer with the same fields, so it no longer imports the model.
    • This is the riskiest part: it is a write path. The post_save dispatch to the plugin server stays on the model, unchanged.
  • Workflow task endpoint: it reads the owner through the existing get_workflow_owner_id and the daily caps through a new get_workflow_task_daily_limits.
    • A missing workflow still returns the same 422.
  • Scout run endpoint: it checks the workflow through a new workflow_exists.
  • JWT purposes: both endpoints get TASKS_CREATE_PURPOSE and WORKFLOW_SCOUT_RUN_PURPOSE through facade/service_jwt.py.
    • The constants stay in service_jwt.py, because Node and settings comments point at that path.
  • Batch run states: HogFlowBatchJobState moves to facade/enums.py, and HogFlowBatchJob.State is an alias of it.
    • The class keeps the same values, labels and derived OpenAPI name (HogFlowBatchJobStateEnum). makemigrations --check finds no change.
  • Mechanical: 5 entries deleted from pyproject.toml, and the new help_text shows up in api.schemas.ts and the MCP generated.ts.

The HogFlowBatchJob list, cancel and status paths in hog_flow.py stay as they are. Slice 7 covers them.

How did you test this code?

The change was tested manually on a local dev stack (backend, frontend, plugin server, Temporal), before and after, on the same data.

API comparison. A script sent the same 48 requests on master and on this branch, normalized the IDs and timestamps, and compared each response body. All 48 are identical. The requests cover batch create, list and cancel; the task endpoint with a real scoped JWT; the scout endpoint; and the template endpoints.

Batch, task and scout requests (status on both runs)
Request Status
Batch create (response shows created_by, filters snapshot, status: queued) 200
Batch create with a client-set status (stored as sent, same as master) 200
Batch create with variables as a string (accepted, same as master) 200
Batch create on a draft workflow 400
Batch list 200
Batch cancel (uses the enum in HogFlowBatchJobCancelResponseSerializer) 200
Task: workflow with no owner 422
Task: token for a workflow that does not exist 422
Task: body without a prompt 400
Task: scout-run token on the task endpoint 401
Task: workflow_task_rate_limit_per_day = 0 in team config 409 "paused for this workflow"
Task: workflow_task_team_rate_limit_per_day = 0 in team config 409 "paused for this project"
Scout: token for a workflow that does not exist 422
Scout: unknown scout name 404
Scout: task token on the scout endpoint 401

The two zero-cap cases prove that the daily caps come through the new facade read.

UI. Playwright drove the workflow editor for a batch-trigger workflow: Trigger, then "Run workflow", then the Invocations tab.

  • The POST returned 200, and the new run showed as "queued", created by "you", above the older runs.
  • The plugin server logged "Received hogflow batch invocation" for that run.
  • Nothing looks different from master.

Batch runs after a UI-triggered run

Automated.

  • Two assertions added to test_post_hog_flow_batch_jobs_endpoint_creates_job: created_by and the filters snapshot. The response now comes from a contract rather than the model row, and no test checked those two fields.
  • No new facade tests. The existing endpoint tests already exercise each new function through the public API: the deleted-workflow scout test, test_team_config_overrides_daily_caps, and the batch create and list tests.
  • Also ran locally: lint-imports, hogli lint:tach, hogli product:lint workflows, repo-wide mypy, hogli build:openapi, the workflows test directories, test_workflow_tasks_api.py, and the pagination, timestamp and dataclass invariants.

Found on master, not changed here:

  • A workflow with a batch trigger cannot be saved as a template: the UI shows "Invalid trigger type".
  • PublicHogFlowTemplateViewSet.list sorts the cached global template list in place. After one public call, the list order changes for every later request in that process. Slice 3b fixes this.

Not checked: the MCP tools that call batch_jobs, beyond the regenerated types.

👉 Stay up-to-date with PostHog coding conventions for a smoother review.

Release status

  • No feature flag controls this change
  • This change is behind a feature flag and is not available to users
  • This change makes a previously flagged feature available to everyone

Automatic notifications

  • Publish to changelog?

Docs update

None. No user-facing behavior changes.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Agent: PostHog Desktop (Claude Code), Claude Opus 5.5 (claude-opus-5-5)

  • Skills invoked: /improving-drf-endpoints, /writing-dataclasses, /writing-tests, /writing-pr-descriptions. The isolating-product-facade-contracts skill and the slice plan in Isolate products/workflows for selective CI and move remaining team code out of posthog/ #84402 shaped the design.
  • Slice 3 is split into 3a (this PR, 5 entries) and 3b (template view, 3 entries), so the write-path rewrite of the template viewset does not block this one. Both PRs append to facade/enums.py and delete adjacent pyproject.toml lines. The second one to merge needs a trivial rebase.
  • No customer data or internal material was used. All manual-test data is local dev data.

Created with PostHog Desktop

Slice 3a of the workflows isolation (#84402). The batch job serializer, the workflow task endpoint and the scout run endpoint read models and service_jwt through the facade, so their five presentation ignore_imports entries go.

- facade: workflow_exists, get_workflow_task_daily_limits, create_batch_job, and a service_jwt re-export.
- HogFlowBatchJobState moves to facade/enums; HogFlowBatchJob.State aliases it, so the OpenAPI enum name and the migration state stay the same.
- HogFlowBatchJobSerializer becomes a plain serializer with the same fields; the batch_jobs POST creates the row through the facade.

Generated-By: PostHog Desktop
Task-Id: 70ada836-ee92-46ed-8d45-d080b4590fa2
@mayteio mayteio self-assigned this Sep 29, 2026
@trunk-io

trunk-io Bot commented Sep 29, 2026

Copy link
Copy Markdown

Merging to master in this repository is managed by Trunk.

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

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

@github-actions

github-actions Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

🤖 CI report

⚠️ Trunk lane — backend Python lane

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

✅ Complexity (TypeScript) — clean

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

✅ Duplication (Python) — clean

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

✅ Duplication (TypeScript) — clean

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

✅ Bundle size — no change

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

Total: 68.97 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.58 MiB · 22 files no change █████████░ 85.8% of 1.84 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.52 MiB · 629 files no change █████████░ 87.4% of 4.03 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
7.35 MiB · 2,339 files no change █████████░ 88.1% of 8.34 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 [object Object] 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/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.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/index.tsx
1.3 KiB src/RootErrorBoundary.tsx
912 B ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js
854 B src/scenes/ChunkLoadErrorBoundary.tsx
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
Size File
301.8 KiB ../node_modules/.pnpm/posthog-js@1.434.14_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
216.9 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
100.5 KiB src/lib/api.ts
88.5 KiB src/products.tsx
69.4 KiB src/lib/lemon-ui/icons/icons.tsx
40.1 KiB src/lib/utils/eventUsageLogic.ts
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.4 KiB src/scenes/scenes.ts
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
301.8 KiB ../node_modules/.pnpm/posthog-js@1.434.14_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
272.3 KiB src/taxonomy/core-filter-definitions-by-group.json
216.9 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
100.5 KiB src/lib/api.ts
98.8 KiB ../packages/quill/packages/quill/dist/index.js
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
88.5 KiB src/products.tsx

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.16 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.16 MiB · 19 files no change ████░░░░░░ 37.8% of 5.72 MiB
Deferred (lazy) 2.10 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
805.5 KiB dist/toolbar/toolbar-app-ZATDHZQQ.css
651.7 KiB dist/toolbar/chunk-chunk-7ZORLPSY.js
259.4 KiB dist/toolbar/chunk-chunk-2FGAEFTI.js
138.3 KiB dist/toolbar/chunk-chunk-UA3V2PCC.js
131.8 KiB dist/toolbar/chunk-chunk-FDH2IBXT.js
75.2 KiB dist/toolbar/toolbar-app-SD4VQXWA.js
69.0 KiB dist/toolbar/chunk-chunk-TSAL54PB.js
35.6 KiB dist/toolbar/chunk-chunk-63EWNJRZ.js
21.0 KiB dist/toolbar/chunk-chunk-F5GDSM5D.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 — no change

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

Total: 947.79 MiB · no change

ℹ️ MCP UI apps size — 33 app(s), 17633.1 KB JS

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

App JS CSS
debug 597.9 KB 199.2 KB
action 454.1 KB 199.2 KB
action-list 564.2 KB 199.2 KB
cohort 453.1 KB 199.2 KB
cohort-list 563.2 KB 199.2 KB
email-template 452.9 KB 199.2 KB
error-details 469.6 KB 199.2 KB
error-issue 454.5 KB 199.2 KB
error-issue-list 564.8 KB 199.2 KB
experiment 561.3 KB 199.2 KB
experiment-list 564.9 KB 199.2 KB
experiment-results 566.3 KB 199.2 KB
feature-flag 566.8 KB 199.2 KB
feature-flag-list 570.5 KB 199.2 KB
feature-flag-testing 457.3 KB 199.2 KB
inline-scan 453.6 KB 199.2 KB
insight-actors 562.3 KB 199.2 KB
invite-email-preview 452.3 KB 199.2 KB
llm-costs 559.3 KB 199.2 KB
session-recording 455.3 KB 199.2 KB
survey 454.7 KB 199.2 KB
survey-global-stats 561.9 KB 199.2 KB
survey-list 564.9 KB 199.2 KB
survey-stats 561.9 KB 199.2 KB
trace-span 453.5 KB 199.2 KB
trace-span-list 564.1 KB 199.2 KB
vision-observation-list 563.3 KB 199.2 KB
workflow 453.4 KB 199.2 KB
workflow-list 563.5 KB 199.2 KB
loops-review 457.8 KB 199.2 KB
query-results 774.1 KB 199.2 KB
render-ui 858.1 KB 199.2 KB
visual-review-snapshots 457.9 KB 199.2 KB
⚠️ Playwright — 2 flaky

🎭 Playwright report · View test results →

⚠️ 2 flaky tests:

  • Logout in another tab results in logout in the current tab too (chromium)
  • Creating a SQL insight with a variable and overriding it on a dashboard (chromium)

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

⚠️ Backend coverage — 91.0% of changed backend lines covered — 11 uncovered

🧪 Backend test coverage

Patch coverage — changed backend lines (products + core): ██████████████████░░ 91.0% (117 / 128)

File Patch Uncovered changed lines
products/workflows/backend/presentation/views/workflow_tasks.py 28.6% 225–226, 326–328
products/workflows/backend/facade/api.py 66.7% 145, 150–152, 308
products/workflows/backend/providers/twilio.py 80.0% 51

🤖 Agents: add a test covering the lines above, or note why under "How did you test this code?". Machine-readable gap list: the patch-coverage artifact on this run (gh run download 36607323005 -n patch-coverage), or the coverage-data block at the end of this comment.

Per-product line coverage (touched products)
Product Coverage Lines
warehouse_sources_queue ██░░░░░░░░░░░░░░░░░░ 10.5% 187 / 1,777
platform_features ██░░░░░░░░░░░░░░░░░░ 12.1% 7 / 58
demo ███████████░░░░░░░░░ 52.8% 1,411 / 2,673
data_tools ████████████░░░░░░░░ 61.2% 90 / 147
ai_gateway ███████████████░░░░░ 75.0% 9 / 12
aeo ███████████████░░░░░ 76.3% 617 / 809
batch_exports ████████████████░░░░ 81.3% 21,543 / 26,502
apm █████████████████░░░ 84.1% 1,306 / 1,553
cdp ██████████████████░░ 88.2% 4,545 / 5,155
ml_inference ██████████████████░░ 88.4% 509 / 576
mcp_analytics ██████████████████░░ 89.2% 5,038 / 5,651
product_tours ██████████████████░░ 89.3% 1,331 / 1,491
dashboards ██████████████████░░ 89.5% 6,904 / 7,714
data_warehouse ██████████████████░░ 90.0% 14,027 / 15,589
notebooks ██████████████████░░ 90.2% 15,297 / 16,964
signals ██████████████████░░ 90.2% 57,838 / 64,097
cohorts ██████████████████░░ 90.4% 8,420 / 9,316
streamlit_apps ██████████████████░░ 90.8% 2,684 / 2,956
managed_warehouse ██████████████████░░ 91.0% 10,252 / 11,263
tasks ██████████████████░░ 91.1% 75,525 / 82,874
data_modeling ██████████████████░░ 91.4% 10,554 / 11,543
exports ██████████████████░░ 91.6% 9,680 / 10,562
engineering_analytics ██████████████████░░ 91.7% 11,032 / 12,030
ai_training ██████████████████░░ 92.2% 356 / 386
business_knowledge ██████████████████░░ 92.2% 7,684 / 8,330
conversations ███████████████████░ 92.5% 28,734 / 31,062
early_access_features ███████████████████░ 92.6% 1,332 / 1,439
managed_migrations ███████████████████░ 92.7% 1,581 / 1,705
visual_review ███████████████████░ 92.8% 9,247 / 9,969
stamphog ███████████████████░ 92.8% 8,109 / 8,742
canvas ███████████████████░ 92.8% 6,873 / 7,405
approvals ███████████████████░ 93.0% 3,974 / 4,271
mcp_registry ███████████████████░ 93.1% 1,670 / 1,794
notifications ███████████████████░ 93.2% 1,145 / 1,229
error_tracking ███████████████████░ 93.2% 16,359 / 17,547
surveys ███████████████████░ 93.3% 6,571 / 7,040
slack_app ███████████████████░ 93.4% 13,995 / 14,989
autoresearch ███████████████████░ 93.6% 8,481 / 9,061
context_layer ███████████████████░ 93.9% 3,415 / 3,638
web_analytics ███████████████████░ 94.0% 21,815 / 23,218
alerts ███████████████████░ 94.0% 8,569 / 9,114
billing_alerts ███████████████████░ 94.1% 2,094 / 2,226
mcp_store ███████████████████░ 94.4% 8,940 / 9,472
ai_observability ███████████████████░ 94.5% 24,473 / 25,896
workflows ███████████████████░ 94.6% 15,282 / 16,157
wizard ███████████████████░ 94.7% 6,150 / 6,496
reminders ███████████████████░ 94.8% 760 / 802
review_hog ███████████████████░ 95.0% 11,507 / 12,119
endpoints ███████████████████░ 95.1% 9,206 / 9,681
annotations ███████████████████░ 95.1% 817 / 859
customer_analytics ███████████████████░ 95.2% 25,636 / 26,938
legal_documents ███████████████████░ 95.2% 2,311 / 2,427
marketing_analytics ███████████████████░ 95.3% 19,566 / 20,528
posthog_ai ███████████████████░ 95.3% 2,488 / 2,610
experiments ███████████████████░ 95.4% 32,457 / 34,020
actions ███████████████████░ 95.5% 756 / 792
logs ███████████████████░ 95.5% 15,399 / 16,130
data_catalog ███████████████████░ 95.6% 4,402 / 4,606
tracing ███████████████████░ 95.6% 3,536 / 3,699
replay_vision ███████████████████░ 95.6% 27,675 / 28,939
growth ███████████████████░ 95.7% 11,228 / 11,734
messaging ███████████████████░ 95.8% 3,798 / 3,963
skills ███████████████████░ 95.8% 6,972 / 7,274
product_analytics ███████████████████░ 96.0% 28,470 / 29,647
access_control ███████████████████░ 96.3% 7,113 / 7,386
revenue_analytics ███████████████████░ 96.4% 1,876 / 1,946
user_interviews ███████████████████░ 96.5% 2,867 / 2,971
feature_flags ███████████████████░ 96.5% 25,588 / 26,509
warehouse_sources ███████████████████░ 97.3% 458,450 / 471,303
data_quality ████████████████████ 97.6% 7,587 / 7,774
links ████████████████████ 97.9% 234 / 239
security ████████████████████ 98.0% 1,286 / 1,312
metrics ████████████████████ 98.0% 4,084 / 4,166
analytics_platform ████████████████████ 98.3% 2,784 / 2,833
pulse ████████████████████ 98.5% 2,046 / 2,078
live_debugger ████████████████████ 99.2% 626 / 631
field_notes ████████████████████ 99.4% 172 / 173

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.

✅ Django migration risk — migration analysis complete

We've analyzed your migrations for potential risks.

Summary: 0 Safe | 1 Needs Review | 0 Blocked

⚠️ Needs Review

May have performance impact

workflows.0027_seal_reverse_accessors
  └─ #1 ⚠️ AlterField
     Field alteration may cause table locks or data loss (check if changing type or constraints)
     model: hogflow, field: created_by, field_type: ForeignKey
  └─ #2 ⚠️ AlterField
     Field alteration may cause table locks or data loss (check if changing type or constraints)
     model: hogflow, field: team, field_type: ForeignKey
  └─ #3 ⚠️ AlterField
     Field alteration may cause table locks or data loss (check if changing type or constraints)
     model: hogflowbatchjob, field: created_by, field_type: ForeignKey
  └─ #4 ⚠️ AlterField
     Field alteration may cause table locks or data loss (check if changing type or constraints)
     model: hogflowbatchjob, field: team, field_type: ForeignKey
  └─ #5 ⚠️ AlterField
     Field alteration may cause table locks or data loss (check if changing type or constraints)
     model: hogflowrevision, field: created_by, field_type: ForeignKey
  └─ #6 ⚠️ AlterField
     Field alteration may cause table locks or data loss (check if changing type or constraints)
     model: hogflowrevision, field: team, field_type: ForeignKey
  └─ #7 ⚠️ AlterField
     Field alteration may cause table locks or data loss (check if changing type or constraints)
     model: hogflowschedule, field: team, field_type: ForeignKey
  └─ #8 ⚠️ AlterField
     Field alteration may cause table locks or data loss (check if changing type or constraints)
     model: hogflowtemplate, field: created_by, field_type: ForeignKey
  └─ #9 ⚠️ AlterField
     Field alteration may cause table locks or data loss (check if changing type or constraints)
     model: hogflowtemplate, field: team, field_type: ForeignKey
  └─ #10 ⚠️ AlterField
     Field alteration may cause table locks or data loss (check if changing type or constraints)
     model: teamworkflowsconfig, field: team, field_type: OneToOneField
  └─ #11 ⚠️ AlterField
     Field alteration may cause table locks or data loss (check if changing type or constraints)
     model: workflowproposal, field: resolved_by, field_type: ForeignKey
  └─ #12 ⚠️ AlterField
     Field alteration may cause table locks or data loss (check if changing type or constraints)
     model: workflowproposal, field: team, field_type: ForeignKey

Last updated: 2026-09-29 18:49 UTC (7275666)

@greptile-apps

greptile-apps Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Retrigger

[Medium risk] Refactors batch job creation through a new service layer.

The PR appears safe to merge; batch creation adds one avoidable User query per request.

Reviews (1) · Last reviewed commit: "chore(workflows): route the small workfl..."

Comment thread products/workflows/backend/services/batch_jobs.py
@mayteio mayteio added the reviewhog ($$$) Reviews pull requests before humans do label Sep 29, 2026
@posthog

posthog Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

🦔 PostHog Review reviewed this pull request

Nothing worth raising this time. Enjoy the moment:

The dancing man in the red room from Twin Peaks

Resolved comments: 1 declined

@coderabbitai

coderabbitai Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: PostHog/posthog/.coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: 237ea54d-b414-4081-9e4f-146e1ba3b71b

📥 Commits

Reviewing files that changed from the base of the PR and between 27d0544 and fe0ee6f.

⛔ Files ignored due to path filters (1)
  • products/workflows/frontend/generated/api.schemas.ts is excluded by !**/generated/**
📒 Files selected for processing (3)
  • products/workflows/backend/facade/api.py
  • products/workflows/backend/models/hog_flow_batch_job/hog_flow_batch_job.py
  • services/mcp/src/api/generated.ts

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 10 remain after this review.


📝 Walkthrough

Walkthrough

The workflow facade adds workflow lookup and task daily-limit helpers, batch-job contracts, and a shared batch-job state enum. Batch-job creation now uses a service function and returns a workflow contract. Presentation views use facade helpers for batch-job creation, workflow validation, and task limits. The batch-job response test checks the creator ID and trigger filters.

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to fe0ee

The workflow owner fallback and batch-job response retain their prior behavior. No actionable PR-introduced risk remains, so the change is mergeable subject to normal checks.

Security Architecture Review

Security architecture risk: 🔵 Low · up to fe0ee

The reviewed paths retain the existing workflow access checks, batch-run controls, and dispatch behavior. No introduced security issue was established, but the change affects a mass-send write path and some downstream behavior remains unverified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • observed — A batch POST can initiate a mass-send workflow, but the handler first obtains the access-checked workflow, requires ACTIVE status, and requires audience confirmation for agent event sources. It supplies the authenticated user ID and stored workflow filters rather than accepting caller-supplied dispatch filters.

Trust Boundaries and Controls

  • observed — The new scout workflow-existence helper checks both team and workflow ID. The callback obtains those IDs from the authenticated service identity and token, not from the request body.

Resilience and Maintainability Implications

  • inferred — The changed creation route still relies on the model receiver for dispatch and propagates dispatch failure. Neither the new service nor the inspected receiver establishes creation-level idempotency; the evidence does not show that this PR introduced that limitation.
🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The description includes all required sections and clearly explains the problem, changes, testing, release status, documentation status, and agent involvement. It also reports known limitations and te…
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
products/workflows/backend/presentation/views/hog_flow.py (1)

6818-6831: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Make hog_flow response-only.

The endpoint derives the workflow ID from the URL and passes it directly to create_batch_job. The current writable field therefore adds a redundant required property to the POST OpenAPI request schema, although the server accepts requests without it. Keep the field in responses, but remove the merge:

Suggested fix
-    hog_flow = serializers.UUIDField(source="hog_flow_id", help_text="ID of the workflow this batch run belongs to.")
+    hog_flow = serializers.UUIDField(
+        source="hog_flow_id",
+        read_only=True,
+        help_text="ID of the workflow this batch run belongs to.",
+    )
-            serializer = HogFlowBatchJobSerializer(data={**request.data, "hog_flow": hog_flow.id})
+            serializer = HogFlowBatchJobSerializer(data=request.data)

Regenerate any OpenAPI-derived client types after changing the request schema.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: PostHog/posthog/.coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: afd86cc4-963d-4ce8-a9cb-1cf6e21f38a2

📥 Commits

Reviewing files that changed from the base of the PR and between 83c4096 and 27d0544.

⛔ Files ignored due to path filters (1)
  • products/workflows/frontend/generated/api.schemas.ts is excluded by !**/generated/**
📒 Files selected for processing (13)
  • products/workflows/backend/facade/api.py
  • products/workflows/backend/facade/contracts.py
  • products/workflows/backend/facade/enums.py
  • products/workflows/backend/facade/service_jwt.py
  • products/workflows/backend/models/hog_flow_batch_job/hog_flow_batch_job.py
  • products/workflows/backend/presentation/views/hog_flow.py
  • products/workflows/backend/presentation/views/hog_flow_batch_job.py
  • products/workflows/backend/presentation/views/workflow_scout_runs.py
  • products/workflows/backend/presentation/views/workflow_tasks.py
  • products/workflows/backend/services/batch_jobs.py
  • products/workflows/backend/tests/api/test_hog_flow.py
  • pyproject.toml
  • services/mcp/src/api/generated.ts
💤 Files with no reviewable changes (1)
  • pyproject.toml

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.

@posthog posthog Bot removed the reviewhog ($$$) Reviews pull requests before humans do label Sep 29, 2026
@trunk-io

trunk-io Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Static Badge   Static Badge   Static Badge

Failed Test Failure Summary Logs
Dashboards › Creating a SQL insight with a variable and overriding it on a dashboard The test expected an element to not be visible, but it was visible. Logs ↗︎
Auth › Logout in another tab results in logout in the current tab too The test failed because a specific element did not appear within the 30-second timeout. Logs ↗︎

View Full Report ↗︎ ⋅ Docs

@mayteio mayteio added the stamphog Request AI approval (no full review) label Sep 29, 2026
@mayteio
mayteio marked this pull request as ready for review September 29, 2026 17:27
@mayteio
mayteio requested a review from a team as a code owner September 29, 2026 17:27
@github-actions

github-actions Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

🦔 Hogbox preview · ❌ build failed

The preview didn't come up for commit 7275666. 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 comment is the status.

stamphog[bot]

This comment was marked as outdated.

@stamphog
stamphog Bot dismissed their stale review September 29, 2026 17:46

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

@mayteio
mayteio changed the base branch from master to posthog/workflows-seal-reverse-accessors September 29, 2026 17:47

@stamphog stamphog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Approved.

Behavior-preserving refactor inside the workflows product, written by an owning-team author. It has manual before/after API comparison, an added test assertion, and no unresolved reviewer concerns. The only pyproject.toml change removes import-linter ignore entries.

  • Author wrote 49% of the modified lines and has 19 merged PRs in these paths (familiarity MODERATE).
  • 👍 on the PR from greptile-apps[bot].
Gate mechanics and policy version
Gate Result
prerequisites ✓ all clear
deny-list ✓ no deny categories matched
size ✓ 243L, 11F substantive, 253L/14F incl. docs/generated/snapshots — within ceiling
tier ✓ T1-agent / T1c-medium (253L, 14F, two-areas, chore)
stamphog 2.3.1 .stamphog/policy.yml @ fe0ee6f · reviewed head fe0ee6f

This branch had an error being deployed

1 failed deployment
preview-pr-108476 — 72756666 Deployed Sep 29, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stamphog Request AI approval (no full review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant