Skip to content

feat(subscriptions): add AI report context contract - #91428

Open
vdekrijger wants to merge 20 commits into
masterfrom
codex/ai-subscription-contexts-stack-v1
Open

feat(subscriptions): add AI report context contract#91428
vdekrijger wants to merge 20 commits into
masterfrom
codex/ai-subscription-contexts-stack-v1

Conversation

@vdekrijger

@vdekrijger vdekrijger commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Problem

People creating AI report subscriptions cannot save dashboards or insights as trusted context for later report generation.

This base layer defines the contract. #91787 adds execution, and #91788 adds the UI.

Changes

  • AI subscriptions can store up to three dashboard or insight contexts.
  • The API validates team ownership, access, and deletion state before replacing contexts atomically.
  • Historical deliveries expose only contexts the current viewer can access.
  • Database checks require exactly one target while keeping the context model extensible.
  • Generated frontend and MCP types mirror the serializer contract.
  • This layer has no visible UI change.

How did you test this code?

  • Model and API tests cover constraints, uniqueness, access control, concurrent replacement, and historical delivery access.
  • A disposable database migration test covered rollback, reapplication, and validated foreign keys.
  • OpenAPI generation, repository-wide mypy, and strict preflight completed locally.
  • Manual UI testing does not apply to this contract layer.

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

Automatic notifications

  • Publish to changelog?

Docs update

No public docs update. This contract is not user-visible until the final stack layer.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

  • Codex implemented the approved narrow contract and split it from execution and UI changes.
  • Skills: /django-migrations, /improving-drf-endpoints, /adopting-generated-api-types, /implementing-mcp-tools, /writing-tests, /running-ci-preflight, /writing-pr-descriptions, and /stacking-prs.
  • Public-artifact review found no customer-derived or private material.

@vdekrijger vdekrijger self-assigned this Aug 31, 2026
@trunk-io

trunk-io Bot commented Aug 31, 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 Aug 31, 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.

⚠️ Bundle size — 🔺 +30.8 KiB (+0.0%)

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

Total: 68.68 MiB · 🔺 +30.8 KiB (+0.0%)

File Size Δ vs base
posthog-app/src/scenes/AuthenticatedShell.js 239.6 KiB 🔺 +25.1 KiB (+11.7%)
posthog-app/src/scenes/experiments/Experiment.js 275.1 KiB 🔺 +5.3 KiB (+2.0%)

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.50 MiB · 22 files 🟢 -22 B (-0.0%) ███░░░░░░░ 33.2% of 4.51 MiB
logged-out boot: index + App + bootApp (preloaded by every page, including /login)
src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
5.24 MiB · 668 files 🔺 +199 B (+0.0%) █████████░ 93.1% of 5.63 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
7.66 MiB · 2,677 files 🟢 -549 B (-0.0%) █████████░ 87.3% of 8.77 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
🟢 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

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.0 KiB src/index.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
281.8 KiB ../node_modules/.pnpm/posthog-js@1.428.6_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
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
255.4 KiB src/taxonomy/core-filter-definitions-by-group.json
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
104.2 KiB src/lib/api.ts
79.0 KiB src/products.tsx
68.8 KiB src/lib/lemon-ui/icons/icons.tsx
62.8 KiB src/lib/utils/eventUsageLogic.ts
38.8 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
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
281.8 KiB ../node_modules/.pnpm/posthog-js@1.428.6_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
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
255.4 KiB src/taxonomy/core-filter-definitions-by-group.json
153.8 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
104.2 KiB src/lib/api.ts
95.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
79.0 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.29 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.29 MiB · 18 files no change ████░░░░░░ 40.0% of 5.72 MiB
Deferred (lazy) 2.11 MiB · 45 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
756.4 KiB dist/toolbar/toolbar-app-LA4JX7FS.css
608.8 KiB dist/toolbar/chunk-chunk-P3PF5T4P.js
484.7 KiB dist/toolbar/chunk-chunk-RPV3NYRJ.js
136.6 KiB dist/toolbar/chunk-chunk-6MQWLXON.js
131.8 KiB dist/toolbar/chunk-chunk-FDH2IBXT.js
72.2 KiB dist/toolbar/toolbar-app-VLT4VAGU.js
69.0 KiB dist/toolbar/chunk-chunk-TSAL54PB.js
35.6 KiB dist/toolbar/chunk-chunk-DTB5C7AH.js
21.0 KiB dist/toolbar/chunk-chunk-35CVENAR.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 — 🔺 +222.6 KiB (+0.0%)

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

Total: 1458.39 MiB · 🔺 +222.6 KiB (+0.0%)

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

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

App JS CSS
debug 600.0 KB 195.2 KB
action 458.2 KB 195.2 KB
action-list 564.9 KB 195.2 KB
cohort 457.2 KB 195.2 KB
cohort-list 563.8 KB 195.2 KB
email-template 457.0 KB 195.2 KB
error-details 472.9 KB 195.2 KB
error-issue 457.9 KB 195.2 KB
error-issue-list 564.7 KB 195.2 KB
experiment 562.0 KB 195.2 KB
experiment-list 565.6 KB 195.2 KB
experiment-results 567.1 KB 195.2 KB
feature-flag 567.6 KB 195.2 KB
feature-flag-list 571.4 KB 195.2 KB
feature-flag-testing 461.4 KB 195.2 KB
inline-scan 457.7 KB 195.2 KB
insight-actors 563.0 KB 195.2 KB
invite-email-preview 456.4 KB 195.2 KB
llm-costs 560.0 KB 195.2 KB
session-recording 459.0 KB 195.2 KB
survey 458.8 KB 195.2 KB
survey-global-stats 562.7 KB 195.2 KB
survey-list 565.5 KB 195.2 KB
survey-stats 562.7 KB 195.2 KB
trace-span 457.6 KB 195.2 KB
trace-span-list 564.7 KB 195.2 KB
vision-observation-list 563.9 KB 195.2 KB
workflow 457.5 KB 195.2 KB
workflow-list 564.2 KB 195.2 KB
loops-review 461.9 KB 195.2 KB
query-results 756.3 KB 195.2 KB
render-ui 839.5 KB 195.2 KB
visual-review-snapshots 462.0 KB 195.2 KB
Playwright — all passed

All tests passed.

View test results →

⚠️ Backend coverage — 96.0% of changed backend lines covered — 20 uncovered

🧪 Backend test coverage

Patch coverage — changed backend lines (products + core): ███████████████████░ 96.0% (590 / 610)

File Patch Uncovered changed lines
products/exports/backend/models/subscription.py 58.1% 52–53, 57–58, 258–259, 583, 585–588, 590–591
products/exports/backend/models/subscription_context.py 81.1% 29–30, 35–36, 41, 44, 53

🤖 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 34262828335 -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
warehouse_sources_queue ██████░░░░░░░░░░░░░░ 29.1% 92 / 316
data_tools ████████████░░░░░░░░ 62.1% 90 / 145
demo ████████████░░░░░░░░ 62.1% 1,658 / 2,671
ai_gateway ███████████████░░░░░ 75.0% 9 / 12
batch_exports ████████████████░░░░ 79.9% 19,473 / 24,368
apm █████████████████░░░ 83.3% 1,234 / 1,481
wizard █████████████████░░░ 85.3% 2,779 / 3,259
cdp █████████████████░░░ 85.4% 4,349 / 5,094
signals █████████████████░░░ 85.5% 36,471 / 42,645
product_tours ██████████████████░░ 88.0% 1,312 / 1,491
notebooks ██████████████████░░ 88.5% 11,879 / 13,429
data_warehouse ██████████████████░░ 88.9% 12,824 / 14,424
business_knowledge ██████████████████░░ 89.2% 4,469 / 5,008
cohorts ██████████████████░░ 89.3% 7,565 / 8,468
dashboards ██████████████████░░ 89.6% 6,837 / 7,631
engineering_analytics ██████████████████░░ 90.1% 8,391 / 9,310
tasks ██████████████████░░ 90.3% 66,287 / 73,399
data_modeling ██████████████████░░ 90.4% 9,350 / 10,347
streamlit_apps ██████████████████░░ 90.7% 2,619 / 2,889
exports ██████████████████░░ 90.7% 9,245 / 10,189
managed_warehouse ██████████████████░░ 90.7% 9,417 / 10,378
alerts ██████████████████░░ 90.9% 5,242 / 5,765
links ██████████████████░░ 91.0% 192 / 211
mcp_analytics ██████████████████░░ 91.2% 4,411 / 4,837
conversations ██████████████████░░ 91.3% 21,777 / 23,859
canvas ██████████████████░░ 91.3% 5,033 / 5,514
visual_review ██████████████████░░ 91.7% 7,567 / 8,250
error_tracking ██████████████████░░ 92.0% 13,495 / 14,669
notifications ██████████████████░░ 92.5% 1,120 / 1,211
early_access_features ███████████████████░ 92.6% 1,331 / 1,438
managed_migrations ███████████████████░ 92.7% 1,576 / 1,700
slack_app ███████████████████░ 92.7% 12,684 / 13,676
surveys ███████████████████░ 93.1% 6,180 / 6,640
mcp_registry ███████████████████░ 93.2% 1,471 / 1,578
web_analytics ███████████████████░ 93.3% 19,324 / 20,706
stamphog ███████████████████░ 93.4% 6,543 / 7,009
context_layer ███████████████████░ 93.4% 2,615 / 2,801
mcp_store ███████████████████░ 93.5% 8,063 / 8,621
reminders ███████████████████░ 93.5% 477 / 510
marketing_analytics ███████████████████░ 93.5% 17,452 / 18,657
posthog_ai ███████████████████░ 93.6% 1,395 / 1,491
ai_observability ███████████████████░ 93.8% 18,255 / 19,463
approvals ███████████████████░ 93.9% 3,570 / 3,803
billing_alerts ███████████████████░ 94.1% 2,079 / 2,210
endpoints ███████████████████░ 94.2% 9,072 / 9,627
review_hog ███████████████████░ 94.3% 10,214 / 10,826
tracing ███████████████████░ 94.5% 2,726 / 2,885
legal_documents ███████████████████░ 94.7% 2,082 / 2,199
workflows ███████████████████░ 94.7% 11,801 / 12,455
autoresearch ███████████████████░ 95.0% 934 / 983
customer_analytics ███████████████████░ 95.1% 19,308 / 20,303
annotations ███████████████████░ 95.3% 804 / 844
product_analytics ███████████████████░ 95.3% 19,340 / 20,292
actions ███████████████████░ 95.4% 749 / 785
replay_vision ███████████████████░ 95.5% 22,817 / 23,886
skills ███████████████████░ 95.6% 5,536 / 5,791
experiments ███████████████████░ 95.6% 30,259 / 31,643
feature_flags ███████████████████░ 95.7% 20,361 / 21,270
access_control ███████████████████░ 95.8% 6,293 / 6,572
messaging ███████████████████░ 95.9% 3,680 / 3,839
growth ███████████████████░ 96.0% 7,728 / 8,053
logs ███████████████████░ 96.0% 13,950 / 14,532
revenue_analytics ███████████████████░ 96.3% 1,841 / 1,911
user_interviews ███████████████████░ 96.5% 2,651 / 2,747
warehouse_sources ███████████████████░ 97.2% 409,791 / 421,671
data_quality ████████████████████ 97.6% 4,229 / 4,335
analytics_platform ████████████████████ 98.2% 2,381 / 2,425
metrics ████████████████████ 98.2% 3,576 / 3,640
data_catalog ████████████████████ 98.4% 3,268 / 3,322
pulse ████████████████████ 98.4% 2,028 / 2,060
live_debugger ████████████████████ 99.2% 621 / 626
field_notes ████████████████████ 99.4% 167 / 168

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 SQL — 2 new migrations to review

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

products/exports/backend/migrations/0012_subscription_context.py

-- sqlmigrate failed for this migration (see the Validate migrations job log)

products/exports/backend/migrations/0013_validate_subscription_context_team_fk.py

-- sqlmigrate failed for this migration (see the Validate migrations job log)

Last updated: 2026-09-08 18:29 UTC (4526025)

Django migration risk — migration analysis complete

We've analyzed your migrations for potential risks.

Summary: 0 Safe | 2 Needs Review | 0 Blocked

⚠️ Needs Review

May have performance impact

exports.0012_subscription_context
  └─ #1 ⚠️ AddField
     Adding NOT NULL field with callable default (list) - verify it's stable
     model: subscriptiondelivery, field: context_refs, default: list
  └─ #2 ✅ CreateModel
     Creating new table is safe
     model: SubscriptionContext
  └─ #3 ⚠️ AddForeignKeyNotValid: Unknown operation type: AddForeignKeyNotValid
  │
  └──> ℹ️  INFO:
       ℹ️  Skipped operations on newly created tables (empty tables
       don't cause lock contention).
exports.0013_validate_subscription_context_team_fk
  └─ #1 ⚠️ ValidateForeignKey: Unknown operation type: ValidateForeignKey

Last updated: 2026-09-08 18:29 UTC (4526025)

ClickHouse migration SQL — none

No ClickHouse migrations in the latest push.

@posthog

posthog Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Visual changes approved by @vdekrijger — baseline updated in 4ee9f23.

View this run in PostHog

6 new.

@vdekrijger
vdekrijger force-pushed the codex/ai-subscription-contexts-stack-v1 branch from c0fe275 to 733a6d8 Compare August 31, 2026 00:45
@trunk-io

trunk-io Bot commented Aug 31, 2026

Copy link
Copy Markdown

Static BadgeStatic BadgeStatic Badge

View Full Report ↗︎Docs

@vdekrijger
vdekrijger force-pushed the codex/ai-subscription-contexts-stack-v1 branch 2 times, most recently from 2cc97ae to 7d9c00a Compare August 31, 2026 01:34
@vdekrijger
vdekrijger force-pushed the codex/ai-subscription-contexts-stack-v1 branch from 4ee9f23 to eb7358a Compare August 31, 2026 16:07
@vdekrijger vdekrijger changed the title feat(subscriptions): add AI report contexts feat(subscriptions): add AI report context contract Aug 31, 2026
@vdekrijger
vdekrijger force-pushed the codex/ai-subscription-contexts-stack-v1 branch from eb7358a to 275ce18 Compare August 31, 2026 16:19
Comment thread ee/api/subscription.py Outdated
Comment thread ee/api/subscription.py Outdated
Comment thread ee/api/subscription.py Outdated
Comment thread ee/api/subscription.py
Comment thread ee/api/subscription.py
Comment thread products/exports/backend/migrations/0009_subscription_context.py Outdated
Comment thread products/exports/backend/migrations/0009_subscription_context.py Outdated
Comment thread products/exports/backend/migrations/0009_subscription_context.py Outdated
Comment thread products/product_analytics/backend/facade/api.py Outdated
Comment thread products/product_analytics/backend/logic.py
Comment thread ee/api/subscription.py
Comment thread ee/api/subscription.py
Comment thread ee/api/subscription.py Outdated
Comment thread ee/api/subscription.py Outdated
Comment thread ee/api/subscription.py
Comment thread products/exports/backend/models/subscription_context.py
Comment thread products/exports/backend/models/subscription.py Outdated
Comment thread products/exports/backend/migrations/0009_subscription_context.py Outdated
Comment thread posthog/models/activity_logging/activity_log.py
@vdekrijger vdekrijger added the reviewhog ($$$) Reviews pull requests before humans do label Sep 4, 2026
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

🦔 Hogbox preview · ✅ ready

▶ 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 4526025 · box box-eeda978a359c · ready in 1183s (push → usable) · build log · rebuilds on every push, torn down on close

@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested a review from a team September 4, 2026 14:52
@pr-assigner-resolver-posthog

Copy link
Copy Markdown

👀 Auto-assigned reviewers

These soft owners were skipped because they only have minor changes here. Nothing blocks merge, so self-assign if you'd like a look:

  • @PostHog/team-platform-features (posthog/models/owners.yaml)

Soft owners come from each directory's owners.yaml and each product's product.yaml (resolved nearest-file-wins). The locator after each owner is the file that decided it. Generated files and lockfiles are ignored when deciding ownership.

@greptile-apps

greptile-apps Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Security Review

Historical delivery access is intended to be checked against snapshotted context references, but production delivery creation leaves those references empty. Consequently, access is determined from the subscription's current contexts and can expose an older delivery after its restricted context is removed.

Prompt To Fix All With AI
### Issue 1
products/exports/backend/models/subscription.py:649
**Delivery context snapshot stays empty**

Production delivery creation never populates `context_refs`, so every delivery receives the empty-list default. If a restricted context is later removed from the subscription, the snapshot check cannot hide the historical delivery. Adding a restricted context can also hide older deliveries that never used it because the fallback checks the subscription's current contexts. Populate this field from the contexts used for the delivery when creating the record.

**How this was verified:** The production delivery creation path omits `context_refs`, while delivery authorization relies on that array to identify inaccessible snapshotted contexts.

### Issue 2
ee/api/subscription.py:1095-1098
**Obsolete contexts grow unbounded**

Replacement deletes only live context rows, so contexts whose targets were soft-deleted remain stored before up to three new rows are inserted. Repeated soft-deletion and replacement can therefore grow the collection without a bound, while the stored context and activity-reference sets exceed the advertised three-context contract. Remove obsolete rows during replacement or enforce the maximum across preserved and incoming rows.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "refactor(exports): simplify context targ..." | Re-trigger Greptile

Comment thread products/exports/backend/models/subscription.py Outdated
Comment thread ee/api/subscription.py
@vdekrijger vdekrijger added reviewhog ($$$) Reviews pull requests before humans do and removed reviewhog ($$$) Reviews pull requests before humans do labels Sep 4, 2026
@posthog

posthog Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

🦔 PostHog Review reviewed this pull request

Found 1 must fix, 2 should fix, 2 consider.

Published 5 findings (view the review).

Resolved comments: 1 fixed, 4 left for you · couldn't handle 1

@posthog

posthog Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

PostHog Review alpha 🦔 If you find any issues helpful - please reply "valid", "invalid", etc., for evaluation purposes 🙏

@posthog posthog 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.

PostHog Review

Found 1 must fix, 2 should fix, 2 consider.

Comment thread products/exports/backend/models/subscription.py Outdated
Comment thread products/exports/backend/models/subscription_context.py
Comment thread ee/api/subscription.py
Comment thread ee/api/subscription.py
Comment thread products/exports/backend/models/subscription_context.py Outdated
@posthog posthog Bot removed the reviewhog ($$$) Reviews pull requests before humans do label Sep 4, 2026
The new NOT NULL column had no Postgres default, so a worker still running
the previous image would omit it from its delivery INSERT and hit a
not-null violation until the rollout finished.

db_default lands a real `DEFAULT '{}'` on the column, and sqlmigrate
confirms Django no longer drops it after the ADD COLUMN.

Generated-By: PostHog Desktop
Task-Id: fc7c7475-0a06-4402-bc90-120e90bd5039
@github-actions
github-actions Bot requested a deployment to preview-pr-91428 September 4, 2026 16:21 In progress
Comment thread products/exports/backend/models/subscription.py
@veria-ai

veria-ai Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

PR overview

All previously flagged issues have been addressed. No open security concerns remain on this pull request.

Security review

No open security issues remain on this pull request.

Fixed/addressed: 1 · PR risk: 0/10

The blocked-tile subquery returns one row per tile. That was free while it
only fed IN clauses, which semi-join duplicates away, but the new
context-ref array repeats a dashboard reference once per blocked tile on
it.

Adding distinct caps that array at the team's dashboard count. The rows
the filter admits are unchanged: IN ignores duplicates, and so does array
overlap.

Generated-By: PostHog Desktop
Task-Id: fc7c7475-0a06-4402-bc90-120e90bd5039
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant