Skip to content

[CI] (gpt5-trial-2) next-js/15-pages-router-saas#2405

Closed
wizard-ci-bot[bot] wants to merge 1 commit into
mainfrom
wizard-ci-gpt5-trial-2-next-js-15-pages-router-saas
Closed

[CI] (gpt5-trial-2) next-js/15-pages-router-saas#2405
wizard-ci-bot[bot] wants to merge 1 commit into
mainfrom
wizard-ci-gpt5-trial-2-next-js-15-pages-router-saas

Conversation

@wizard-ci-bot

@wizard-ci-bot wizard-ci-bot Bot commented Jul 3, 2026

Copy link
Copy Markdown

Automated wizard CI run

Source: manual
Trigger ID: gpt5-trial-2
App: next-js/15-pages-router-saas
App directory: apps/next-js/15-pages-router-saas
Workbench branch: wizard-ci-gpt5-trial-2-next-js-15-pages-router-saas
Wizard branch: 1eb16c89a1ac295f0887a96381fff7314e999b05
Context Mill branch: main
PostHog (MCP) branch: master
Timestamp: 2026-07-03T16:22:43.129Z
Duration: 522.9s

YARA Scanner

✓ 84 tool calls scanned, 3 violations detected

  [BLOCKED] pii_in_capture_call (HIGH) — PostToolUse:Edit
  [BLOCKED] pii_in_capture_call (HIGH) — PostToolUse:Edit
  [BLOCKED] pii_in_capture_call (HIGH) — PostToolUse:Edit

No violations: ✓ 81 clean scans

⚠️ YARA violations detected — see report above

@wizard-ci-bot

wizard-ci-bot Bot commented Jul 3, 2026

Copy link
Copy Markdown
Author

PR Evaluation Report

Summary

This PR integrates PostHog into a Next.js 15 Pages Router SaaS app, adding both client-side (posthog-js via instrumentation-client.ts) and server-side (posthog-node via a factory function) tracking. It instruments auth flows, checkout, billing, team management, and account updates across ~13 files. While the event coverage is strong, there are notable gaps: email is used as distinct_id, posthog.reset() is missing on logout, error tracking is absent, no reverse proxy is configured, and .env.example is not updated.

Files changed Lines added Lines removed
14 +175 -0

Confidence score: 4/5 👍

  • Email used as distinct_id: posthog.identify(data.email) in login.tsx uses raw email as the distinct ID instead of a stable user ID (e.g., user.id). This causes fragmented person profiles and is explicitly flagged in PostHog best practices. The server-side events correctly use user.id.toString(), creating a mismatch. [CRITICAL]
  • No posthog.reset() on logout: header.tsx captures auth_signed_out but never calls posthog.reset(), so future events on shared devices remain linked to the logged-out user. [CRITICAL]
  • No error tracking: No captureException, no PostHogErrorBoundary, and no capture_exceptions: true in init config. [MEDIUM]
  • No reverse proxy configured: next.config.ts has no rewrites for PostHog, meaning client-side events are susceptible to ad blockers. [MEDIUM]
  • Missing defaults in posthog.init(): The instrumentation-client.ts init call omits the defaults option recommended by PostHog docs. [MEDIUM]

File changes

Filename Score Description
instrumentation-client.ts 3/5 Initializes posthog-js but missing defaults option
lib/posthog/server.ts 4/5 Clean server-side factory with correct flushAt/flushInterval settings
package.json 5/5 Both posthog-js and posthog-node added correctly
components/login.tsx 2/5 Good event coverage but uses email as distinct_id; YARA scanner blocked PII violations
components/header.tsx 2/5 Captures sign-out but missing posthog.reset()
pages/api/auth/sign-in.ts 4/5 Thorough server-side tracking with proper user.id as distinct_id
pages/api/stripe/create-checkout.ts 3/5 Good tracking but uses 'anonymous' as distinct_id for unauthenticated users
pages/api/stripe/webhook.ts 3/5 Uses Stripe customer ID as distinct_id which won't link to PostHog persons
pages/api/team/invite.ts 4/5 Clean server-side event capture
pages/api/team/remove-member.ts 4/5 Clean server-side event capture
pages/api/account/update.ts 4/5 Clean server-side event capture
pages/dashboard/index.tsx 4/5 Simple billing portal event
pages/pricing.tsx 4/5 Good checkout initiation event with properties
posthog-setup-report.md 2/5 Unnecessary file; claims sign-up events exist but sign-up.ts was never modified

App sanity check ⚠️

Criteria Result Description
App builds and runs Yes No syntax errors; PostHog SDK versions are valid
Preserves existing env vars & configs Yes Existing code untouched; PostHog additions are additive
No syntax or type errors Yes TypeScript is valid across all changed files
Correct imports/exports Yes posthog-js on client, posthog-node on server — correct separation
Minimal, focused changes No posthog-setup-report.md is unnecessary; report claims sign-up instrumentation that doesn't exist
Pre-existing issues None Base app appears functional

Issues

  • .env.example not updated: PostHog env vars (NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN, NEXT_PUBLIC_POSTHOG_HOST, POSTHOG_PROJECT_API_KEY, POSTHOG_HOST) are only in .env.local, not in .env.example. Collaborators won't know what to set. [MEDIUM]
  • Report claims false coverage: posthog-setup-report.md lists auth_sign_up_attempted, auth_sign_up_succeeded, auth_sign_up_failed events in pages/api/auth/sign-up.ts, but that file was never modified. [LOW]

Other completed criteria

  • App builds without errors introduced by the PR
  • Existing app code and configs are preserved
  • All import/export statements are correct (posthog-js client-side, posthog-node server-side)
  • Build configuration (package.json) is valid

PostHog implementation ⚠️

Criteria Result Description
PostHog SDKs installed Yes posthog-js@^1.396.6 and posthog-node@^5.39.4 in package.json
PostHog client initialized No instrumentation-client.ts initializes correctly but omits the defaults option recommended by docs
capture() Yes 14+ meaningful events across client and server
identify() No Uses raw email as distinct_id (posthog.identify(data.email)); server-side uses user.id.toString() — mismatched identity
Error tracking No No captureException, no error boundary, no capture_exceptions config
Reverse proxy No next.config.ts has no PostHog rewrites; client events exposed to ad blockers

Issues

  • Email as distinct_id: posthog.identify(data.email) in login.tsx uses the user's email as distinct_id. This creates fragmented person profiles since server-side events use user.id.toString(). Should use a stable user ID from the auth response. [CRITICAL]
  • Missing posthog.reset() on logout: header.tsx fires auth_signed_out but never calls posthog.reset(). On shared devices, future anonymous events will remain linked to the previous user. [CRITICAL]
  • No error tracking: No PostHogErrorBoundary, no captureException calls, and capture_exceptions is not set in the init config. [MEDIUM]
  • No reverse proxy: Full-stack Next.js app has no rewrites configured for PostHog endpoints, making client-side tracking vulnerable to ad blockers. [MEDIUM]
  • Missing defaults in init: posthog.init() in instrumentation-client.ts omits the defaults option that PostHog docs recommend for all new integrations. [MEDIUM]

Other completed criteria

  • API keys loaded from environment variables (not hardcoded)
  • API host correctly configured pointing to https://us.i.posthog.com
  • Server-side client uses correct flushAt: 1 and flushInterval: 0 pattern for Next.js API routes
  • Both client and server SDKs properly installed

PostHog insights and events ⚠️

Filename PostHog events Description
components/login.tsx auth_sign_in_attempted, auth_sign_up_attempted, auth_sign_in_failed, auth_sign_up_failed, auth_sign_in_succeeded, auth_sign_up_succeeded, auth_flow_error Full auth flow tracking with attempt/success/failure states; enables auth conversion funnel
components/header.tsx auth_signed_out Tracks user logout (but missing posthog.reset())
pages/api/auth/sign-in.ts auth_sign_in_failed, auth_sign_in_succeeded Server-side auth tracking with failure reasons
pages/api/stripe/create-checkout.ts checkout_session_created Tracks checkout creation with redirect context
pages/api/stripe/webhook.ts subscription_updated Tracks Stripe subscription changes with status
pages/api/team/invite.ts team_member_invited Tracks team invitations with role
pages/api/team/remove-member.ts team_member_removed Tracks member removal
pages/api/account/update.ts account_updated Tracks profile updates
pages/dashboard/index.tsx billing_portal_opened Tracks billing portal access
pages/pricing.tsx checkout_initiated Tracks checkout initiation with plan name

Issues

  • Duplicate event names across client/server: auth_sign_in_failed and auth_sign_in_succeeded are captured both client-side (login.tsx) and server-side (sign-in.ts), creating duplicate events for the same action. The client and server use different distinct_id values (email vs user.id), compounding the problem. [MEDIUM]
  • Webhook distinct_id uses Stripe customer ID: subscription_updated uses subscription.customer as distinct_id, which is a Stripe ID (e.g., cus_xxx) that won't match any PostHog person. Should use the team's owner user ID. [MEDIUM]

Other completed criteria

  • Events represent real user actions (auth, checkout, billing, team management)
  • Events enable product insights (auth conversion funnel, checkout flow, team activity trends)
  • Events include relevant contextual properties (reason, team_id, role, plan_name, etc.)
  • No PII in capture() event properties — emails and names are not sent as event properties
  • Event names are descriptive and use consistent snake_case convention

Reviewed by wizard workbench PR evaluator

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.

0 participants