Skip to content

[codex] Add actor-scoped tracking payloads#2330

Open
WcaleNieWolny wants to merge 3 commits into
mainfrom
codex/tracking-v2-identifiers
Open

[codex] Add actor-scoped tracking payloads#2330
WcaleNieWolny wants to merge 3 commits into
mainfrom
codex/tracking-v2-identifiers

Conversation

@WcaleNieWolny
Copy link
Copy Markdown
Contributor

@WcaleNieWolny WcaleNieWolny commented May 22, 2026

Summary (AI generated)

  • Add tracking_version: 2 + org_id support to /private/events so new callers track the authenticated actor while preserving organization grouping.
  • Update CLI builder/onboarding/build telemetry and selected dashboard onboarding/usage events to send v2 org context instead of overloading user_id.
  • Use requested_by for delayed builder lifecycle and AI analysis events while keeping owner_org as the PostHog organization group.

Motivation (AI generated)

Capgo analytics currently mix person IDs and organization IDs in user_id, which makes it hard to answer whether the same human used the dashboard, CLI onboarding, and builder. A versioned payload keeps old clients compatible while allowing new CLI/frontend events to carry both actor and org context cleanly.

Business Impact (AI generated)

This improves funnel attribution across dashboard onboarding, CLI onboarding, builder uploads, build lifecycle, and AI build analysis. Better cross-product attribution should make onboarding drop-off and builder adoption easier to diagnose without breaking existing tracking clients.

Test Plan (AI generated)

  • bun lint
  • bun lint:backend
  • bunx vitest run tests/ai-analysis-telemetry.unit.test.ts tests/builder-onboarding-telemetry.unit.test.ts tests/builder-upload-telemetry.unit.test.ts tests/build-lifecycle-emit.unit.test.ts tests/build-ai-analyze.test.ts tests/build-start-log-token.test.ts
  • bun typecheck
  • bun run supabase:with-env -- bunx vitest run tests/events.test.ts could not be validated locally because this worktree has no Supabase DB container; all existing and new cases returned 503.

Generated with AI

Summary by CodeRabbit

  • Chores
    • Telemetry now reports organization-scoped identifiers and a new tracking_version (v2) for more consistent org-level analytics.
    • Tracking calls are gated to only send when organization context is available.
    • Backend now validates and authorizes v2 org-scoped events, enforcing access controls for org-linked telemetry.
    • Test suites and telemetry assertions updated to reflect the new v2 payload shape.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 52f49863-6b2c-4f1e-a77c-09a1d3e5f81f

📥 Commits

Reviewing files that changed from the base of the PR and between 11c2023 and 5a03153.

📒 Files selected for processing (12)
  • cli/src/build/onboarding/telemetry.ts
  • cli/test/test-onboarding-telemetry.mjs
  • src/components/dashboard/DemoOnboardingModal.vue
  • src/components/dashboard/InviteTeammateModal.vue
  • src/components/dashboard/StepsApp.vue
  • src/components/dashboard/StepsBuild.vue
  • src/components/dashboard/StepsBundle.vue
  • src/components/dashboard/TrialBanner.vue
  • src/pages/settings/organization/Plans.vue
  • src/pages/settings/organization/Usage.vue
  • supabase/functions/_backend/private/events.ts
  • tests/events.test.ts

📝 Walkthrough

Walkthrough

This PR introduces tracking payload v2 by shifting telemetry to organization-scoped identity (org_id) and adding tracking_version: 2 across CLI, frontend, backend, and tests; backend event processing is refactored to validate v2 org access and build/AI tracking separates requester identity from organization context.

Changes

Tracking Payload v2 with Organization-Scoped Identity

Layer / File(s) Summary
Type & contract extensions
cli/src/utils.ts, src/services/tracking.ts, supabase/functions/_backend/public/build/ai_analyze.ts, supabase/functions/_backend/utils/build_tracking.ts
Added optional org_id and tracking_version to tracking payload types; EmitAiAnalysisResultInput adds required userId; BuildRowForTracking adds required requested_by.
CLI telemetry payload updates
cli/src/ai/telemetry.ts, cli/src/build/credentials-command.ts, cli/src/build/onboarding/telemetry.ts, cli/src/build/request.ts, cli/src/build/telemetry.ts
CLI telemetry calls (AI analysis, credentials, onboarding, build requested/result, builder upload) now send org_id instead of user_id and include tracking_version: 2.
Frontend telemetry updates
src/components/dashboard/DemoOnboardingModal.vue, src/components/dashboard/InviteTeammateModal.vue, src/components/dashboard/StepsApp.vue, src/components/dashboard/StepsBuild.vue, src/components/dashboard/StepsBundle.vue, src/components/dashboard/TrialBanner.vue, src/pages/settings/organization/Plans.vue, src/pages/settings/organization/Usage.vue
Vue components derive org_id from current organization, guard sends on availability, include tracking_version: 2, and pass org context to pushEvent.
Backend /private/events v2 handling
supabase/functions/_backend/private/events.ts
Detect tracking_version: 2, accept org_id, refactor resolve logic to accept requested user/org, enforce org-scoped access (app.read + owner_org check or org.read), and inject org_id into tags for verified v2 events.
AI analysis tracking adjustments
supabase/functions/_backend/public/build/ai_analyze.ts
AI analyze handler now uses apikey.user_id as the tracking user_id for emit paths, conditionally sets tags.org_id when ownerOrg is present, and requires userId in emit inputs.
Build lifecycle requester & tagging
supabase/functions/_backend/public/build/start.ts, supabase/functions/_backend/public/build/status.ts, supabase/functions/_backend/triggers/cron_reconcile_build_status.ts, supabase/functions/_backend/utils/build_tracking.ts
Build handlers now select and forward requested_by in emitted build transition events; emitBuildTransitionEvent uses requested_by as user_id and includes org_id derived from owner_org in tags.
Test updates and new v2 event tests
tests/*, cli/test/*
Unit and integration tests updated to assert org_id and tracking_version: 2; fixtures extended with requested_by; new tests added for v2 org-scoped success and cross-org rejection.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Cap-go/capgo#2327: Overlapping changes to onboarding telemetry and related payload contract updates.
  • Cap-go/capgo#2287: Introduced builder onboarding telemetry that this PR updates to use org_id and tracking_version: 2.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description provides a comprehensive summary, motivation, and business impact. However, the Test Plan section is incomplete: one critical test suite (events.test.ts) was not validated locally due to environment limitations, and the checklist items are not completed as required by the template. Complete the checklist items in the description template, including code style verification, documentation updates (if applicable), and test coverage validation. Document the limitation with events.test.ts or resolve the Supabase container issue.
Docstring Coverage ⚠️ Warning Docstring coverage is 29.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: introducing actor-scoped tracking payloads with tracking_version 2 and org_id support across the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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

@WcaleNieWolny WcaleNieWolny marked this pull request as ready for review May 22, 2026 11:56
@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented May 22, 2026

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing codex/tracking-v2-identifiers (5a03153) with main (db5951f)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 11c2023830

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +145 to +147
const trackedBody = trackingV2
? { ...trackOptions, user_id: trackingUserId, tags: trackedTags }
: requestedUserId
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep org identity for onboarding-step-done events

For tracking_version: 2 requests, this branch rewrites user_id to the authenticated actor ID, but the existing onboarding path later treats trackedBody.user_id as an organization ID (orgs.id) when event === 'onboarding-step-done'. As a result, a valid v2 onboarding event (with org_id set) will look up the org using a user UUID, fail the .single() query, and return error_fetching_organization_or_app instead of tracking/sending Bento. This breaks the onboarding-done telemetry flow for v2 clients.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cli/src/build/onboarding/telemetry.ts (1)

82-88: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Migrate trackBuilderOnboardingAction to v2 payload fields as well.

trackBuilderOnboardingStep now uses org_id and tracking_version: 2, but trackBuilderOnboardingAction still sends user_id: input.orgId. This keeps org IDs overloaded into user_id and leaves onboarding action events on the old contract.

Suggested fix
   try {
     await sendEvent(input.apikey, {
       event: 'Builder Onboarding Action',
       channel: 'builder-onboarding',
       icon: '🧭',
       notify: false,
-      user_id: input.orgId,
+      org_id: input.orgId,
+      tracking_version: 2,
       tags,
     })
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/src/build/onboarding/telemetry.ts` around lines 82 - 88, The onboarding
action telemetry is still using the old payload field user_id and lacks the v2
marker; update trackBuilderOnboardingAction to mirror trackBuilderOnboardingStep
by renaming user_id: input.orgId to org_id: input.orgId and add
tracking_version: 2 to the payload, keeping the rest of the fields (event,
channel, icon, notify, tags) unchanged so the event uses the v2 contract.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/pages/settings/organization/Usage.vue`:
- Around line 46-47: The tracking event currently sets tracking_version: 2 while
org_id can be undefined (currentOrganization.value?.gid); update the code around
the sendEvent call (the call site that uses currentOrganization and
tracking_version) to only emit v2 events when a valid organization exists —
e.g., check that currentOrganization.value?.gid is truthy before calling
sendEvent or conditionally set tracking_version to 1/omit it when org_id is
missing; locate the sendEvent invocation that references currentOrganization and
adjust it to guard on currentOrganization.value?.gid (or branch to a fallback)
so v2 events are only sent with a valid org_id.

In `@supabase/functions/_backend/private/events.ts`:
- Around line 145-149: The trackingV2 branch incorrectly sets
trackedBody.user_id to the authenticated actor (trackingUserId) and later
onboarding enrichment treats that as an org ID; change trackedBody construction
so that when trackingV2 is true you include the authenticated actor as user_id
(trackingUserId) but also include the verified organization id under a separate
key (e.g., org_id: verifiedOrgId) so onboarding-step-done lookup uses org_id
instead of user_id; update any onboarding enrichment code that reads
trackedBody.user_id to read trackedBody.org_id for org lookups; adjust the
trackedBody creation in the branch that uses trackingV2 (and keep the existing
branches for requestedUserId/trackOptions) to include this org_id field.

In `@tests/events.test.ts`:
- Around line 54-78: The test labeled "tracks v2 events with actor user and
organization context" (and the other v2 event test in the same file) are using
it(...) but must use parallel tests; change the test declarations from it(...)
to it.concurrent(...) so both v2 event specs run in parallel; update the two
occurrences in tests/events.test.ts where the test descriptions mention "v2" or
"tracking_version: 2" to use it.concurrent instead of it.

---

Outside diff comments:
In `@cli/src/build/onboarding/telemetry.ts`:
- Around line 82-88: The onboarding action telemetry is still using the old
payload field user_id and lacks the v2 marker; update
trackBuilderOnboardingAction to mirror trackBuilderOnboardingStep by renaming
user_id: input.orgId to org_id: input.orgId and add tracking_version: 2 to the
payload, keeping the rest of the fields (event, channel, icon, notify, tags)
unchanged so the event uses the v2 contract.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d50b6188-8fdf-444f-aa2d-dded68c44657

📥 Commits

Reviewing files that changed from the base of the PR and between 2d18719 and 11c2023.

📒 Files selected for processing (29)
  • cli/src/ai/telemetry.ts
  • cli/src/build/credentials-command.ts
  • cli/src/build/onboarding/telemetry.ts
  • cli/src/build/request.ts
  • cli/src/build/telemetry.ts
  • cli/src/utils.ts
  • src/components/dashboard/DemoOnboardingModal.vue
  • src/components/dashboard/InviteTeammateModal.vue
  • src/components/dashboard/StepsApp.vue
  • src/components/dashboard/StepsBuild.vue
  • src/components/dashboard/StepsBundle.vue
  • src/components/dashboard/TrialBanner.vue
  • src/pages/settings/organization/Plans.vue
  • src/pages/settings/organization/Usage.vue
  • src/services/tracking.ts
  • supabase/functions/_backend/private/events.ts
  • supabase/functions/_backend/public/build/ai_analyze.ts
  • supabase/functions/_backend/public/build/request.ts
  • supabase/functions/_backend/public/build/start.ts
  • supabase/functions/_backend/public/build/status.ts
  • supabase/functions/_backend/triggers/cron_reconcile_build_status.ts
  • supabase/functions/_backend/utils/build_tracking.ts
  • tests/ai-analysis-telemetry.unit.test.ts
  • tests/build-ai-analyze.test.ts
  • tests/build-lifecycle-emit.unit.test.ts
  • tests/build-start-log-token.test.ts
  • tests/builder-onboarding-telemetry.unit.test.ts
  • tests/builder-upload-telemetry.unit.test.ts
  • tests/events.test.ts

Comment thread src/pages/settings/organization/Usage.vue Outdated
Comment on lines +145 to +149
const trackedBody = trackingV2
? { ...trackOptions, user_id: trackingUserId, tags: trackedTags }
: requestedUserId
? { ...trackOptions, user_id: trackingUserId }
: trackOptions
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use verified org ID (not actor ID) for onboarding org lookup in tracking v2

In tracking v2, user_id is the authenticated actor. The onboarding enrichment path still treats trackedBody.user_id as an org ID, which can fail org lookup and abort onboarding-step-done event processing.

Suggested fix
+  const onboardingOrgId = trackingV2 ? verifiedOrgId : trackedBody.user_id
-  if (trackedBody.user_id && appId && trackedBody.event === 'onboarding-step-done') {
+  if (onboardingOrgId && appId && trackedBody.event === 'onboarding-step-done') {
     onboardingBentoEvent = await Promise.all([
       supabase
         .from('orgs')
         .select('*')
-        .eq('id', trackedBody.user_id)
+        .eq('id', onboardingOrgId)
         .single(),
       supabase
         .from('apps')
         .select('*')
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/functions/_backend/private/events.ts` around lines 145 - 149, The
trackingV2 branch incorrectly sets trackedBody.user_id to the authenticated
actor (trackingUserId) and later onboarding enrichment treats that as an org ID;
change trackedBody construction so that when trackingV2 is true you include the
authenticated actor as user_id (trackingUserId) but also include the verified
organization id under a separate key (e.g., org_id: verifiedOrgId) so
onboarding-step-done lookup uses org_id instead of user_id; update any
onboarding enrichment code that reads trackedBody.user_id to read
trackedBody.org_id for org lookups; adjust the trackedBody creation in the
branch that uses trackingV2 (and keep the existing branches for
requestedUserId/trackOptions) to include this org_id field.

Comment thread tests/events.test.ts
Comment on lines +54 to +78
it('tracks v2 events with actor user and organization context', async () => {
const response = await fetch(`${BASE_URL}/private/events`, {
method: 'POST',
headers: {
capgkey: headers.Authorization,
},
body: JSON.stringify({
channel: 'test',
event: 'test_event_v2',
description: 'Testing v2 event tracking',
icon: '🧪',
notify: false,
org_id: ORG_ID,
tracking_version: 2,
tags: {
app_id: APPNAME_EVENT,
test: true,
},
}),
})

const data = await response.json() as { status: string }
expect(response.status).toBe(200)
expect(data.status).toBe('ok')
})
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n "^\s*it\(" tests/events.test.ts

Repository: Cap-go/capgo

Length of output: 824


Use it.concurrent for the two v2 event tests
In tests/events.test.ts, these cases are declared with it(...) but the repo requires it.concurrent() in tests/**/*.test.ts for parallel execution:

Suggested change
-  it('tracks v2 events with actor user and organization context', async () => {
+  it.concurrent('tracks v2 events with actor user and organization context', async () => {
@@
-  it('rejects v2 events for foreign organizations', async () => {
+  it.concurrent('rejects v2 events for foreign organizations', async () => {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/events.test.ts` around lines 54 - 78, The test labeled "tracks v2
events with actor user and organization context" (and the other v2 event test in
the same file) are using it(...) but must use parallel tests; change the test
declarations from it(...) to it.concurrent(...) so both v2 event specs run in
parallel; update the two occurrences in tests/events.test.ts where the test
descriptions mention "v2" or "tracking_version: 2" to use it.concurrent instead
of it.

@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant