Skip to content

[CI] (1776c51) fastapi/fastapi3-ai-saas#2714

Closed
wizard-ci-bot[bot] wants to merge 1 commit into
mainfrom
wizard-ci-1776c51-fastapi-fastapi3-ai-saas
Closed

[CI] (1776c51) fastapi/fastapi3-ai-saas#2714
wizard-ci-bot[bot] wants to merge 1 commit into
mainfrom
wizard-ci-1776c51-fastapi-fastapi3-ai-saas

Conversation

@wizard-ci-bot

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

Copy link
Copy Markdown

Automated wizard CI run

Source: wizard-pr
Trigger ID: 1776c51
App: fastapi/fastapi3-ai-saas
App directory: apps/fastapi/fastapi3-ai-saas
Workbench branch: wizard-ci-1776c51-fastapi-fastapi3-ai-saas
Wizard branch: release-please--branches--main--components--wizard
Context Mill branch: main
PostHog (MCP) branch: master
Timestamp: 2026-07-10T23:22:22.370Z
Duration: 620.8s

YARA Scanner

✓ 112 tool calls scanned, 0 violations detected

No violations: ✓ 112 clean scans

@wizard-ci-bot

wizard-ci-bot Bot commented Jul 10, 2026

Copy link
Copy Markdown
Author

PR Evaluation Report

Summary

This PR integrates PostHog into a FastAPI AI SaaS application. It adds a shared PostHog client module, utility helpers for context-scoped event capture and user identification, and instruments 14 events across auth, generation, API key management, usage, and settings routes. The implementation uses the instance-based Posthog() constructor with environment-backed configuration.

Files changed Lines added Lines removed
12 +282 -9

Confidence score: 4/5 👍

  • new_password_length property is a security concern: Capturing the length of a user's new password in the password_changed event leaks password metadata that could aid brute-force attacks. Remove this property. [MEDIUM]
  • Missing .env.example update: The new POSTHOG_PROJECT_TOKEN, POSTHOG_HOST, and POSTHOG_DISABLED env vars are not documented in any .env.example or equivalent file. [MEDIUM]

File changes

Filename Score Description
app/config.py 5/5 Adds PostHog settings fields and migrates to SettingsConfigDict (Pydantic v2 pattern)
app/main.py 5/5 Imports PostHog client and calls shutdown() in lifespan teardown
app/posthog_client.py 5/5 New shared client with instance-based init, exception autocapture, and atexit registration
app/posthog_utils.py 5/5 Clean helper functions for context-scoped capture, user identification via set(), and exception capture
app/routers/api_keys.py 5/5 Captures api_key_created, api_key_revoked, and creation-blocked events with enriched properties
app/routers/auth.py 5/5 Captures signup, login, logout events with identify_user() calls on auth state changes
app/routers/generate.py 5/5 Captures content_generated, credit-blocked, and credits_viewed events
app/routers/pages.py 5/5 Captures dashboard_viewed with summary metrics
app/routers/settings.py 4/5 Captures settings_viewed, email_updated, password_changed — password_changed includes new_password_length
app/routers/usage.py 5/5 Captures usage_viewed with query parameters and result counts
requirements.txt 5/5 Adds posthog>=7.22.1
posthog-setup-report.md 5/5 Wizard setup report documenting events and next steps

App sanity check ✅

Criteria Result Description
App builds and runs Yes All imports resolve, no syntax errors, dependencies added correctly
Preserves existing env vars & configs Yes Existing settings preserved; Config inner class migrated to SettingsConfigDict with equivalent behavior, extra="ignore" added which is safe
No syntax or type errors Yes All code is syntactically valid Python
Correct imports/exports Yes All imports from posthog, app.config, app.models, app.posthog_client, app.posthog_utils are correct
Minimal, focused changes Yes Changes are focused on PostHog integration; minor cleanup of unused imports in generate.py and settings.py is acceptable
Pre-existing issues None No pre-existing issues observed

Issues

  • Missing .env.example documentation: The three new environment variables (POSTHOG_PROJECT_TOKEN, POSTHOG_HOST, POSTHOG_DISABLED) are not added to any .env.example file. Collaborators won't know which variables to set. [MEDIUM]

Other completed criteria

  • Build configuration is valid — posthog>=7.22.1 added correctly to requirements.txt
  • Existing app functionality preserved — no routes or logic removed
  • Config migration from inner Config class to SettingsConfigDict is the correct Pydantic v2 pattern

PostHog implementation ✅

Criteria Result Description
PostHog SDKs installed Yes posthog>=7.22.1 added to requirements.txt
PostHog client initialized Yes Instance-based Posthog() constructor in posthog_client.py with enable_exception_autocapture=True, atexit.register(posthog_client.shutdown), and lifespan shutdown
capture() Yes 14 meaningful capture() calls across all route files via the capture_user_event helper
identify() N/A Server-only app; uses posthog_client.set() correctly to set person properties (email, credits, is_active) on signup/login/email-update
Error tracking Yes enable_exception_autocapture=True in client constructor; capture_exception helper available in posthog_utils.py
Reverse proxy N/A Server-only app — reverse proxy not applicable

Issues

None.

Other completed criteria

  • API key loaded from environment variable via Pydantic Settings (posthog_project_token), not hardcoded
  • Host correctly configured via posthog_host setting, defaulting to https://us.i.posthog.com
  • Shutdown registered both via atexit and FastAPI lifespan teardown — belt-and-suspenders approach is good
  • Context API used correctly: new_context(client=posthog_client) with identify_context(str(user.id)) for request-scoped tracking
  • distinct_id uses str(user.id) — real database IDs, not fabricated values

PostHog insights and events ✅

Filename PostHog events Description
app/routers/auth.py signup_completed, login_succeeded, logout_completed Auth lifecycle with method, credits balance, and active status
app/routers/pages.py dashboard_viewed Dashboard load with generation counts, credits, API key count
app/routers/generate.py content_generated, generation_blocked_insufficient_credits, credits_viewed Core product action with type, credits used/remaining, prompt/result length
app/routers/api_keys.py api_key_created, api_key_revoked, api_key_creation_blocked_limit API key lifecycle with active counts
app/routers/usage.py usage_viewed Usage page view with date range and generation counts
app/routers/settings.py settings_viewed, email_updated, password_changed Account settings actions; email_updated tracks domain changes
app/posthog_utils.py capture_user_exception (helper) Exception capture helper using capture_exception with user context

Issues

  • new_password_length leaks password metadata: The password_changed event includes new_password_length, which reveals information about user password strength. This is a security-sensitive property that should be removed. [MEDIUM]

Other completed criteria

  • Events represent real user actions mapping to actual product flows (signup → generation → API key management)
  • Events enable product insights — signup-to-generation funnel, credit depletion trends, API key churn are all buildable
  • Events include rich contextual properties (generation_type, credits_used, credits_remaining, active_key_count, etc.)
  • No PII in event properties — email is set via posthog_client.set() on person profiles, not in capture() properties. Email domains (not full emails) are tracked in email_updated.
  • Event names are descriptive and consistently use snake_case with [noun]_[verb] pattern

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