Skip to content

feat(data-warehouse): add Intercom and HubSpot as self-driving inbox sources - #72535

Merged
talyn-app[bot] merged 7 commits into
masterfrom
tom/inbox-oauth-sources
Jul 21, 2026
Merged

feat(data-warehouse): add Intercom and HubSpot as self-driving inbox sources#72535
talyn-app[bot] merged 7 commits into
masterfrom
tom/inbox-oauth-sources

Conversation

@Gilbert09

Copy link
Copy Markdown
Member

Problem

Intercom and HubSpot were deferred from the initial self-driving inbox batch
(#72378) because their warehouse sources are OAuth-only and connecting OAuth
sources in the Code app looked like it needed bespoke per-source setup forms. It doesn't — the
Code app now connects OAuth sources generically (PostHog/code#3613), so these two can land.

Changes

Adds Intercom and HubSpot as signal sources (both record kind ticket):

  • HubSpot (tickets): flat table → shared make_flat_emitter (id hs_object_id,
    subject/content, createdate).
  • Intercom (conversations): bespoke emitter — the opening message lives in the source
    JSON blob and created_at is a Unix epoch, so it JSONExtractStrings the body and wraps the
    partition cursor in fromUnixTimestamp(...). Flagged in-module to verify the stored types on
    the first real sync.

Plus: two SignalSourceProduct enum values (one migration, 0065), contract variants,
registry entries, and parametrized test coverage.

Also corrects the adding-inbox-sources skill. The old guidance said OAuth sources need a
bespoke setup form (clone LinearSetup) and ~5 per-kind integration/router files. That's stale:
DynamicSourceSetup renders oauth/oauth-account-select generically and the connect flow is
started by a generic kind-parameterized integration router (PostHog/code#3613), so an OAuth
source is now the same one-registry-entry change as a credential source.

How did you test this?

  • pytest products/signals/backend/emission/tests/ (registry + schema-validation suites) — 235
    passing, including the two new sources in the parametrized registry/contract test.
  • makemigrations --check — clean. ruff check/format — clean.

Not done: no real warehouse sync, so Intercom's unix-timestamp/JSON-body handling is best-effort
(flagged in-module).

Stacking

Stacked on #72378 (base tom/inbox-tier1-sources); migration 0065 follows 0064 there. Merge
after #72378. The Code inbox wiring for these two is a separate code PR and depends on the
generic-OAuth enabler (PostHog/code#3613).

@github-actions

Copy link
Copy Markdown
Contributor

Hey @Gilbert09! 👋

It looks like your git author email on this PR isn't your @posthog.com address (owerstom@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. 🙂

@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested a review from a team July 21, 2026 11:07
Comment thread products/signals/backend/emission/registry.py
@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

🤖 CI report

⚠️ Bundle size — 🔺 +38 B (+0.0%)

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

Total: 64.48 MiB · 🔺 +38 B (+0.0%)

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.23 MiB · 22 files no change ███░░░░░░░ 28.7% of 4.29 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
8.19 MiB · 2,999 files no change █████████░ 88.5% of 9.25 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.3 KiB ../node_modules/.pnpm/posthog-js@1.404.1/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.8 KiB src/taxonomy/core-filter-definitions-by-group.json
223.4 KiB ../node_modules/.pnpm/posthog-js@1.404.1/node_modules/posthog-js/dist/module.js
167.1 KiB src/queries/validators.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
106.0 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
93.2 KiB ../packages/quill/packages/quill/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

Dist folder size — 🔺 +781 B (+0.0%)

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

Total: 1354.43 MiB · 🔺 +781 B (+0.0%)

⚠️ Backend coverage — 34.0% of changed backend lines covered — 45 uncovered

🧪 Backend test coverage

Patch coverage — changed backend lines (products + core): ███████░░░░░░░░░░░░░ 34.0% (24 / 69)

File Patch Uncovered changed lines
products/signals/backend/emission/registry.py 0.0% 139–140, 205–206
products/signals/backend/emission/hubspot_tickets.py 0.0% 9–12, 14, 24
products/signals/backend/emission/intercom_conversations.py 0.0% 12–13, 15, 17–19, 21, 23, 25, 35, 38–41, 44–54, 56–57, 60–62, 67–69, 71, 88

🤖 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 29854835854 -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
batch_exports ████████░░░░░░░░░░░░ 39.6% 8,414 / 21,244
demo ███████████░░░░░░░░░ 56.2% 1,497 / 2,663
warehouse_sources_queue ████████████░░░░░░░░ 59.2% 148 / 250
tasks █████████████░░░░░░░ 66.4% 26,566 / 40,009
data_tools ██████████████░░░░░░ 70.0% 63 / 90
ai_gateway ███████████████░░░░░ 75.0% 9 / 12
signals ████████████████░░░░ 78.9% 20,132 / 25,508
data_modeling ████████████████░░░░ 80.0% 4,834 / 6,045
cdp ████████████████░░░░ 80.7% 3,118 / 3,864
wizard █████████████████░░░ 84.8% 935 / 1,102
notebooks █████████████████░░░ 85.3% 7,266 / 8,522
agent_platform █████████████████░░░ 86.4% 3,807 / 4,405
actions █████████████████░░░ 86.6% 717 / 828
cohorts █████████████████░░░ 87.0% 4,303 / 4,945
product_tours ██████████████████░░ 87.9% 1,303 / 1,482
exports ██████████████████░░ 88.4% 6,943 / 7,853
engineering_analytics ██████████████████░░ 88.9% 5,507 / 6,196
business_knowledge ██████████████████░░ 89.0% 4,391 / 4,936
conversations ██████████████████░░ 89.2% 16,508 / 18,509
dashboards ██████████████████░░ 89.3% 5,928 / 6,640
visual_review ██████████████████░░ 89.4% 5,818 / 6,505
mcp_analytics ██████████████████░░ 89.7% 2,663 / 2,969
alerts ██████████████████░░ 89.9% 4,054 / 4,508
error_tracking ██████████████████░░ 90.1% 9,761 / 10,832
early_access_features ██████████████████░░ 90.1% 1,031 / 1,144
streamlit_apps ██████████████████░░ 90.4% 2,501 / 2,767
slack_app ██████████████████░░ 90.6% 8,989 / 9,926
links ██████████████████░░ 90.6% 183 / 202
marketing_analytics ██████████████████░░ 90.8% 11,514 / 12,684
stamphog ██████████████████░░ 91.0% 3,993 / 4,387
product_analytics ██████████████████░░ 91.3% 5,786 / 6,337
mcp_store ██████████████████░░ 91.9% 4,257 / 4,634
data_warehouse ███████████████████░ 92.6% 19,175 / 20,715
ai_observability ███████████████████░ 92.7% 14,758 / 15,926
notifications ███████████████████░ 92.7% 1,031 / 1,112
web_analytics ███████████████████░ 92.9% 13,853 / 14,913
workflows ███████████████████░ 92.9% 5,648 / 6,077
surveys ███████████████████░ 93.0% 5,724 / 6,157
posthog_ai ███████████████████░ 93.2% 1,325 / 1,421
approvals ███████████████████░ 93.3% 3,395 / 3,640
reminders ███████████████████░ 93.4% 468 / 501
managed_migrations ███████████████████░ 93.8% 1,220 / 1,300
tracing ███████████████████░ 93.9% 2,635 / 2,805
legal_documents ███████████████████░ 94.1% 1,568 / 1,667
endpoints ███████████████████░ 94.1% 8,606 / 9,143
messaging ███████████████████░ 94.3% 2,682 / 2,845
revenue_analytics ███████████████████░ 94.5% 3,598 / 3,809
skills ███████████████████░ 94.5% 2,893 / 3,061
review_hog ███████████████████░ 94.6% 6,808 / 7,193
logs ███████████████████░ 95.4% 9,935 / 10,416
experiments ███████████████████░ 95.7% 24,469 / 25,569
growth ███████████████████░ 95.8% 2,952 / 3,083
replay_vision ███████████████████░ 96.0% 14,397 / 14,996
annotations ███████████████████░ 96.2% 732 / 761
feature_flags ███████████████████░ 96.3% 16,311 / 16,940
user_interviews ███████████████████░ 96.5% 2,639 / 2,735
warehouse_sources ███████████████████░ 96.8% 303,312 / 313,423
access_control ███████████████████░ 96.8% 851 / 879
customer_analytics ███████████████████░ 97.3% 7,780 / 7,999
data_catalog ███████████████████░ 97.4% 2,345 / 2,407
analytics_platform ████████████████████ 98.0% 2,102 / 2,145
metrics ████████████████████ 98.2% 2,491 / 2,536
pulse ████████████████████ 98.4% 2,017 / 2,049
live_debugger ████████████████████ 99.2% 613 / 618
field_notes ████████████████████ 99.4% 158 / 159

Report-only. Patch coverage = changed backend lines covered vs origin/master. Sorted lowest first.
Known gaps: lines covered only by Temporal tests show as uncovered; core line numbers may drift if master changed the same file.

⚠️ MCP snapshots — 3 updated (3 modified, 0 added, 0 deleted)

Snapshots: MCP unit test snapshots updated

Changes: 3 snapshots (3 modified, 0 added, 0 deleted)

What this means:

  • Snapshots have been automatically updated to match current output

Next steps:

  • Review the changes to ensure they're intentional
  • If unexpected, investigate what caused the output to change

Review snapshot changes →

⚠️ Django migration SQL — 1 new migration to review

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

products/signals/backend/migrations/0065_alter_signalsourceconfig_source_product.py

BEGIN;
--
-- Alter field source_product on signalsourceconfig
--
-- (no-op)
COMMIT;

Last updated: 2026-07-21 17:57 UTC (8117b0f)

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

signals.0065_alter_signalsourceconfig_source_product
  └─ #1 ⚠️ AlterField
     Field alteration may cause table locks or data loss (check if changing type or constraints)
     model: signalsourceconfig, field: source_product, field_type: CharField

Last updated: 2026-07-21 17:57 UTC (8117b0f)

…sources

Add the two OAuth-connected support sources deferred from the initial
inbox-sources batch, now that the Code app connects OAuth sources
generically.

- HubSpot (`tickets` → ticket): flat table, uses the shared emitter
  factory (id `hs_object_id`, `subject`/`content`, `createdate`).
- Intercom (`conversations` → ticket): bespoke emitter — the opening
  message lives in the `source` JSON blob and `created_at` is a Unix
  epoch, so it JSON-extracts the body and wraps the partition cursor in
  fromUnixTimestamp (verify the stored type on first sync).

Adds the two SignalSourceProduct enum values (one migration), contract
variants, registry entries, and parametrized test coverage.

Also corrects the adding-inbox-sources skill: OAuth sources no longer
need a bespoke setup form or a per-kind integration service/router.
DynamicSourceSetup renders `oauth`/`oauth-account-select` generically and
the connect flow is started by the generic `integration` router, so an
OAuth source is the same one-registry-entry change as a credential source.
@Gilbert09
Gilbert09 force-pushed the tom/inbox-oauth-sources branch from 9f08c0a to 1bc3a54 Compare July 21, 2026 17:03
Generated-By: PostHog Code
Task-Id: 7f82f613-b489-484f-90c6-ac67e9b0d10b
@github-actions

github-actions Bot commented Jul 21, 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 8117b0f · box box-a4ac1cb68e1f · ready in 1106s (push → usable) · build log · rebuilds on every push, torn down on close

@github-actions
github-actions Bot requested a deployment to preview-pr-72535 July 21, 2026 17:03 In progress
@github-actions
github-actions Bot requested a deployment to preview-pr-72535 July 21, 2026 17:08 In progress
Generated-By: PostHog Code
Task-Id: 7f82f613-b489-484f-90c6-ac67e9b0d10b
@github-actions
github-actions Bot requested a deployment to preview-pr-72535 July 21, 2026 17:11 In progress
@talyn-app
talyn-app Bot enabled auto-merge (squash) July 21, 2026 17:17
@tests-posthog
tests-posthog Bot disabled auto-merge July 21, 2026 17:18
@talyn-app
talyn-app Bot enabled auto-merge (squash) July 21, 2026 17:18
@github-actions
github-actions Bot requested a deployment to preview-pr-72535 July 21, 2026 17:18 In progress
Generated-By: PostHog Code
Task-Id: 7f82f613-b489-484f-90c6-ac67e9b0d10b
Generated-By: PostHog Code
Task-Id: 7f82f613-b489-484f-90c6-ac67e9b0d10b
@talyn-app
talyn-app Bot merged commit 2191593 into master Jul 21, 2026
253 checks passed
@talyn-app
talyn-app Bot deleted the tom/inbox-oauth-sources branch July 21, 2026 18:19
@deployment-status-posthog

deployment-status-posthog Bot commented Jul 21, 2026

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-07-21 18:58 UTC Run
prod-us ✅ Deployed 2026-07-21 19:24 UTC Run
prod-eu ✅ Deployed 2026-07-21 19:23 UTC Run

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.

2 participants