Repository navigation
Conversation
The codebase scan already finds email-sending services such as Resend. Set them on the person as wizard_detected_email_providers and wizard_detected_email_provider_at, through $set on the `warehouse sources detected` event. A $set captured before login is set again at identify, so it reaches the person who uses the PostHog app. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Set the person properties when the scan is shared after login, so CI, headless, warehouse and self-driving runs set them too, and drop the pre-login replay in Analytics. Count Campaign Monitor, ConvertKit, beehiiv and Drip as email providers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Read the new account's user after provisioning and identify it, as the OAuth login does, so a signup run's events and the detected email providers land on its person. A failed read keeps the signup. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A login without a user, such as a signup whose user could not be read, has no person to set them on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Silthus
marked this pull request as ready for review
October 26, 2026 19:34
Author
|
Note 🤖 Claude Opus 5.5 responding on behalf of Michael
|
Silthus
marked this pull request as draft
October 28, 2026 04:28
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The Wizard's codebase scan already finds the email services a user's code sends through, such as Resend, SendGrid or Amazon SES. That fact stays in the scan and never reaches the person, so feature flags, surveys and the Workflows onboarding in the PostHog app can't tell that this user already sends email from their code.
With this PR, the logged-in person gets
wizard_detected_email_providers(the detected kinds, such as["Resend"]) andwizard_detected_email_provider_at(when the scan found them), on every program that scans: the default integration flow, interactive or CI,wizard warehouseandwizard self-driving. Awizard --signuprun now identifies the account it creates, so its events and these properties land on that account's person too.Impact
Pays into Grow Workflows through Started orgs (orgs that create their first workflow). Not measured yet: an insight in the internal project counts people with
wizard_detected_email_providersper week and how many of them reach Workflows, start its onboarding, create an email sender, or launch a workflow or broadcast. In scope: email, the Messaging category. Expected move: small, up. On its own this PR only adds the targeting signal; a follow-up such as a "We found Resend in your code" card in Workflows uses it. Run cost: n/a.Merge Danger
Note
🔵 Merge risk: low · one-way door (merge-risk rubric)
$unset.reportCodebaseScangains one call behind its existing consent, login and failed-scan checks, andAnalyticsgainssetPersonProperties. No existing event or$identifypayload changes.wizard --signupruns now callidentifyUserfor the new account, as OAuth logins already do, so their events merge onto that person instead of staying anonymous. A failed user read keeps the signup going.Changes
emailProviderPersonProperties(src/services/codebase-scan/email-providers.ts) reads the run's codebase scan and keeps the tool catalog kinds of email services:AwsSes,Beehiiv,BigMailer,Brevo,CampaignMonitor,ConvertKit,Drip,Elasticemail,EmailOctopus,Flexmail,Loops,Mailchimp,MailerLite,MailerSend,Mailgun,Mailjet,Plunk,Postmark,Resend,SendGrid,Shipmail,Smaily,SparkPost,Tinyemail. Kind names match PostHog's live/api/wizard/tool_catalog/.reportCodebaseScan, the one place a scan is cleared to leave the machine, sets both properties withanalytics.setPersonPropertieswhen it shares the scan: sharing granted, telemetry on, logged in with a known user, and the scan did not fail. A login without a user (a signup whose user read failed, or an API key withoutuser:read) has no person to set them on, so it sends nothing. The scan-share latch keeps it to once per run. Login identifies the user first, so the$setlands on the logged-in person. A scan with no email provider sends nothing, so the person keeps what an earlier run found.Analytics.setPersonPropertiessends posthog-node's$setevent on the run's identified id.askForProvisioningSignup(src/tui/auth/project-data.ts) reads the new account's user with the provisioned token, which already holdsuser:read, identifies it, and returns it as the login's user. Before, a signup run never identified anyone, so every event and the$setstayed on an anonymous person. A failed read is captured withcaptureExceptionand the signup continues unidentified.Test plan
Lane gate on
7e96c5d:pnpm typecheckgreen, prettier and eslint clean on the changed files, and the tests of every touched module (codebase-scan,detection,shared/utils,tui/auth, the integration, warehouse, self-driving programs and the program runner) green. Full gate on7e96c5d:pnpm lint(0 errors) andpnpm test(build plus the whole suite) green locally. CI: the Wiz scans pass; Build & Test, Semgrep and the commit check wait for a maintainer to approve workflows for this fork PR.Test seams:
reportCodebaseScan(store)on a CI session after a real scan of a temp project against the fixture catalog, with analytics mocked at@utils/analytics: a Resend + Stripe project, reported twice after login, sets["Resend"]and the scan time once; a Stripe-only project, a declined-sharing session, and a login without a user set nothing.Analyticsover a mockedposthog-nodeclient: afteridentifyUser,setPersonPropertiessets the properties on the identified id.getOrAskForProjectData({ signup: true })with provisioning and the API mocked: a successful signup identifies the new account and returns it as the login's user; a failed user read still returns the signed-up credentials, with no user.Proofs per qa-swarm
PROOF.md:7e96c5d), two runs of the real code with a fetch preload that logged each analytics request and answered it locally, so nothing reached the real project:logInwith the TUI's OAuth provider on a--signupsession, over real HTTP to a local server that answers the provisioning API and/api/users/@me/and serves the live tool catalog. Analytics sent$identifyon the new account's id, then$create_alias, then one$setwith["Resend"]on that id.reportCodebaseScan,SessionStoreandAnalyticsscanning a Next.js app with theresendpackage. A report before login sent nothing about the person; after login, three reports sent exactly one$seton the logged-in id.$setis a plain person update on the identified id, with no merge involved.Captured requests, signup live run on 7e96c5d (trimmed)
LLM context
Built by Claude Code (Opus 5.5) from a handoff in Michael's Workflows onboarding thread.
--signupruns identify the new account?wizard_detected_services?$seton the pre-loginwarehouse sources detectedevent, which only the interactive integration flow sends.$set, so the person keeps what an earlier run found.Involvement: no grilling rounds, no prototypes, a design pass, a cross-family review, a QA swarm panel (7 lenses across GPT-6.1 Sol and Opus 5.5, including the author's Team perspective) a narrow second round on its fixes, and two final reads, live-run proof captured.
🤖 Generated with Claude Code