Skip to content

fix(tasks): verify sandbox compute source - #74491

Closed
adboio wants to merge 6 commits into
masterfrom
posthog-code/trusted-task-billing-provenance
Closed

fix(tasks): verify sandbox compute source#74491
adboio wants to merge 6 commits into
masterfrom
posthog-code/trusted-task-billing-provenance

Conversation

@adboio

@adboio adboio commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Problem

Task origin_product is useful attribution, but API clients can influence it. It now participates in sandbox billing decisions, so client assertions alone are not a safe trust boundary.

Changes

I separated task attribution from compute provenance:

  • Task.origin_product continues to describe the owning workflow. Generic PostHog Desktop creation is restricted to user_created, while the dedicated signal-report implementation endpoint stamps signal_report server-side.
  • TaskRun.compute_source records the authenticated surface that initiated cloud execution. SandboxSession snapshots it at provision or first warm-sandbox claim.
  • The initial source is posthog_desktop, derived only from known Desktop and mobile OAuth applications. Clients cannot submit it.
  • Origin mutation is rejected, signal-report implementation creation is idempotent, and loop classification is also snapshotted for stable historical billing.

An origin allowlist alone still trusts signal_report claims. Task-creation provenance also misses tasks created elsewhere and later run from Desktop. A billing-specific boolean would hide provenance and make additional trusted surfaces harder to represent.

Warning

Older clients that send signal_report through generic task creation receive an explicit update-required error. Current Desktop and mobile clients migrate in PostHog/code#3905.

How did you test this code?

  • Ruff lint and formatting
  • Focused mypy over the changed backend modules
  • Django migration consistency check
  • Added endpoint and ledger regressions for OAuth provenance, origin forgery and mutation, signal-report idempotency, warm claims, resumes, and immutable ledger attribution

Database-backed tests could not run locally because the configured Postgres hostname is unavailable in this environment. CI is the execution gate for those tests.

Automatic notifications

  • Publish to changelog?
  • Alert Sales and Marketing teams?

Docs update

No user-facing documentation change.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Codex implemented this with direct human design review. Repository guidance used included improving DRF endpoints, writing tests, and Django migrations. The design deliberately keeps origin_product as workflow attribution and adds a separate server-derived, run-level compute source.


Created with PostHog Code

@adboio adboio self-assigned this Jul 29, 2026
@trunk-io

trunk-io Bot commented Jul 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

Copy link
Copy Markdown
Contributor

Hey @adboio! 👋

It looks like your git author email on this PR isn't your @posthog.com address (adambowker98@gmail.com). Since you're on the PostHog team, it's worth pointing your local git author email at your @posthog.com address. Why it matters:

  • Consistent work identity in git history — internal tooling that attributes commits to team members keys off your @posthog.com address.
  • Keeps team contributions easy to tell apart from external community ones when scanning history.

You can fix it for this repo with:

git config user.email "you@posthog.com"

Or set it globally with git config --global user.email "you@posthog.com". No need to redo this PR — just a nudge for next time. 🙂

@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

🤖 CI report

Bundle size — no change

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

Total: 65.23 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.24 MiB · 22 files no change ███░░░░░░░ 27.6% of 4.51 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
8.10 MiB · 3,017 files no change ████████░░ 83.4% of 9.71 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/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers 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/RootErrorBoundary.tsx
912 B ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js
789 B src/scenes/ChunkLoadErrorBoundary.tsx
762 B src/index.tsx
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
281.6 KiB ../node_modules/.pnpm/posthog-js@1.407.7/node_modules/posthog-js/dist/rrweb.js
267.7 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
235.5 KiB src/taxonomy/core-filter-definitions-by-group.json
226.5 KiB ../node_modules/.pnpm/posthog-js@1.407.7/node_modules/posthog-js/dist/module.js
154.3 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
105.2 KiB src/lib/api.ts
94.0 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

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.18 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.18 MiB · 17 files no change ████░░░░░░ 38.2% of 5.72 MiB
Deferred (lazy) 2.07 MiB · 33 files no change n/a — loads on demand
Loader dist/toolbar.js 1.1 KiB no change █░░░░░░░░░ 5.8% of 19.5 KiB
Largest eagerly-shipped chunks
Size File
717.3 KiB dist/toolbar/toolbar-app-EF6PM3YW.css
546.0 KiB dist/toolbar/chunk-chunk-BL7J7KBQ.js
484.3 KiB dist/toolbar/chunk-chunk-CQF6YMXB.js
133.6 KiB dist/toolbar/chunk-chunk-TCJBN7XJ.js
131.8 KiB dist/toolbar/chunk-chunk-T5KY5WYR.js
71.0 KiB dist/toolbar/toolbar-app-GTMFZI2Y.js
69.0 KiB dist/toolbar/chunk-chunk-27JL52RE.js
35.6 KiB dist/toolbar/chunk-chunk-YXUTEZ43.js
20.9 KiB dist/toolbar/chunk-chunk-OJ6UIY6V.js
12.2 KiB dist/toolbar/chunk-chunk-PIK3PADE.js

Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile

Dist folder size — 🔺 +18.4 KiB (+0.0%)

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

Total: 1367.94 MiB · 🔺 +18.4 KiB (+0.0%)

ℹ️ MCP UI apps size — 32 app(s), 17067.9 KB JS

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

App JS CSS
debug 599.5 KB 187.7 KB
action 457.8 KB 187.7 KB
action-list 564.3 KB 187.7 KB
cohort 456.8 KB 187.7 KB
cohort-list 563.3 KB 187.7 KB
email-template 456.6 KB 187.7 KB
error-details 472.4 KB 187.7 KB
error-issue 457.5 KB 187.7 KB
error-issue-list 564.2 KB 187.7 KB
experiment 561.5 KB 187.7 KB
experiment-list 565.1 KB 187.7 KB
experiment-results 563.2 KB 187.7 KB
feature-flag 567.1 KB 187.7 KB
feature-flag-list 570.9 KB 187.7 KB
feature-flag-testing 461.0 KB 187.7 KB
insight-actors 562.1 KB 187.7 KB
invite-email-preview 456.0 KB 187.7 KB
llm-costs 559.5 KB 187.7 KB
session-recording 458.6 KB 187.7 KB
session-summary 463.9 KB 187.7 KB
survey 458.4 KB 187.7 KB
survey-global-stats 562.2 KB 187.7 KB
survey-list 565.0 KB 187.7 KB
survey-stats 562.2 KB 187.7 KB
trace-span 457.2 KB 187.7 KB
trace-span-list 564.2 KB 187.7 KB
workflow 457.1 KB 187.7 KB
workflow-list 563.7 KB 187.7 KB
loops-review 461.2 KB 187.7 KB
query-results 746.7 KB 187.7 KB
render-ui 827.3 KB 187.7 KB
visual-review-snapshots 461.6 KB 187.7 KB
⚠️ Django migration SQL — 1 new migration to review

We've detected new migrations on this PR. Review the SQL output for each migration:

products/tasks/backend/migrations/0076_add_compute_source.py

BEGIN;
--
-- Add field compute_source to taskrun
--
ALTER TABLE "posthog_task_run" ADD COLUMN "compute_source" varchar(32) NULL;
--
-- Add field compute_source to sandboxsession
--
ALTER TABLE "posthog_task_sandbox_session" ADD COLUMN "compute_source" varchar(32) NULL;
--
-- Add field loop_internal to sandboxsession
--
ALTER TABLE "posthog_task_sandbox_session" ADD COLUMN "loop_internal" boolean NULL;
COMMIT;

Last updated: 2026-07-29 16:33 UTC (5a5f719)

Django migration risk — migration analysis complete

We've analyzed your migrations for potential risks.

Summary: 1 Safe | 0 Needs Review | 0 Blocked

✅ Safe

Brief or no lock, backwards compatible

tasks.0076_add_compute_source
  └─ #1 ✅ AddField
     Adding nullable field requires brief lock
     model: taskrun, field: compute_source
  └─ #2 ✅ AddField
     Adding nullable field requires brief lock
     model: sandboxsession, field: compute_source
  └─ #3 ✅ AddField
     Adding nullable field requires brief lock
     model: sandboxsession, field: loop_internal

📚 How to Deploy These Changes Safely

AddField:

This operation acquires a brief lock but doesn't rewrite the table.

Deployment uses lock timeouts with automatic retries, so lock contention will cause retries rather than connection pile-up.

Last updated: 2026-07-29 16:34 UTC (5a5f719)

@adboio adboio added the skip-inkeep-docs Use this label to skip an Inkeep docs PR in posthog.com label Jul 29, 2026 — with PostHog
@adboio adboio changed the title fix(tasks): verify sandbox billing provenance fix(tasks): verify sandbox compute source Jul 29, 2026
adboio added 4 commits July 29, 2026 12:21
Derive PostHog Code provenance from authenticated run actions and route signal report implementations through an idempotent server-owned creation path.

Generated-By: PostHog Code
Task-Id: e55f8ea4-cc41-4e76-ad48-896b396e95ce
Preserve a loop's internal classification on each sandbox session so historical compute billing cannot change when the loop changes.

Generated-By: PostHog Code
Task-Id: e55f8ea4-cc41-4e76-ad48-896b396e95ce
Generated-By: PostHog Code
Task-Id: e55f8ea4-cc41-4e76-ad48-896b396e95ce
@adboio
adboio force-pushed the posthog-code/trusted-task-billing-provenance branch from ca874ed to 7484578 Compare July 29, 2026 16:21
adboio added 2 commits July 29, 2026 12:21
Generated-By: PostHog Code
Task-Id: e55f8ea4-cc41-4e76-ad48-896b396e95ce
Generated-By: PostHog Code
Task-Id: e55f8ea4-cc41-4e76-ad48-896b396e95ce
@adboio adboio closed this Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-inkeep-docs Use this label to skip an Inkeep docs PR in posthog.com

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant