|
Some checks failed
CI / Lint (push) Has been cancelled
CI / Build Test (stage-tamagotchi) (push) Has been cancelled
CI / Build Test (stage-tamagotchi-godot) (push) Has been cancelled
CI / Build Test (stage-web) (push) Has been cancelled
CI / Build Test (ui-loading-screens) (push) Has been cancelled
CI / Build Test (ui-transitions) (push) Has been cancelled
CI / Unit Test (push) Has been cancelled
CI / Type Check (push) Has been cancelled
CI / Check Provenance (push) Has been cancelled
Cloudflare Pages (Auth UI) / Deploy - ui-server-auth (push) Has been cancelled
Cloudflare Workers / Deploy - stage-web (push) Has been cancelled
Update Nix pnpmDeps Hash / update (push) Has been cancelled
## What Closes the three structural gaps in AIRI's product analytics: the signup surface had zero instrumentation, the payment funnel had no terminator in PostHog, and SPA route changes emitted no pageviews. Also adds semantic events for character cards, desktop-only features, and data-maintenance actions. ## User paths - User signs up / logs in / verifies email / resets password / links OAuth / deletes account → each step now emits a PostHog event from `apps/ui-server-auth` (previously fully uninstrumented), with `identify()` wired on session load so anonymous funnel events merge into the user person. - User pays via Stripe → webhook writes `product_events` as before, and the product-events service now forwards `payment_completed` (plus signup and subscription lifecycle facts) to PostHog via posthog-node `captureImmediate`, keyed by the Better Auth user id → the `checkout_started → payment_completed` funnel closes end-to-end. Per-request LLM/TTS volume is explicitly not forwarded. - User navigates between routes in any surface (web / desktop / pocket / docs) → `$pageview` + `$pageleave` fire per route change via the posthog-js `defaults: '2025-05-24'` preset in the shared `posthog.config.ts`. - User creates / imports / duplicates / edits a ccv3 card, switches stage background, runs destructive data actions (export / import / clear chats, reset providers, wipe app data), or uses desktop differentiators (Spotlight send, widget windows, in-app updater, MCP server management, pairing QR) → dedicated low-cardinality events. ## Notable decisions - Server forwarding defaults on: `POSTHOG_PROJECT_KEY` defaults to the shared browser-safe phc_* project key; set it to an empty string to disable. Postgres `product_events` remains the source of truth. - Cross-surface events (`oauth_callback_failed`, account lifecycle) share one stage vocabulary exported from stage-ui so the two emitters cannot drift silently. - Events captured right before full-page navigation use `sendBeacon` so they survive the redirect (checkout, OAuth consent handoff, login redirect). - Removed dead wrappers (`trackSignup`, `trackFirstModelSelected`, `trackModelChanged`) that duplicated live event streams under second names. ## How tested - `pnpm -F @proj-airi/server exec vitest run src/services/domain/product-events.test.ts` — 6 passed, covering the forwarding allowlist, the `user_signed_up → signup_completed` mapping, non-forwarded per-request actions, and a throwing sink not failing the webhook path nor losing the DB row. - stage-ui suites (`use-analytics`, `use-linked-accounts`, exports contract) — 22 passed, including new account/card/data/desktop event assertions. - Real transport smoke: posthog-node `captureImmediate` against `us.i.posthog.com` with the production key resolved in 1380ms (one `server_forwarding_smoke_test` event left in the project; filter by event name). - Browser-tested pageviews: `VITE_ENABLE_POSTHOG=true` dev build, two `history.pushState` route changes each produced a `$pageview` with `$pathname`, `navigation_type: pushState`, previous-page dwell time, and the `surface` super property; batched POST to `us.i.posthog.com/e/` returned 200. Note: posthog-js drops events from automated browsers (`navigator.webdriver`) by default — the verification session bypassed the bot filter locally; production config is untouched. - Typecheck and lint pass for server, stage-ui, stage-pages, stage-web, stage-tamagotchi, ui-server-auth. Full verification record: `apps/server/docs/ai-context/verifications/posthog-forwarding-and-pageview.md` ## Follow-ups (not in this PR) - Bot channel usage stats (Discord / Telegram) once they route through server-runtime counters. - Main-process desktop events (tray menu, global shortcut fire) need renderer relay plumbing. - Confirm `payment_completed` arrives in PostHog after the first real Stripe payment post-deploy. https://claude.ai/code/session_01Q1yGavkQ1P41YhTWE4XKex |
||
|---|---|---|
| .. | ||
| docs | ||
| drizzle | ||
| otel | ||
| production/railway | ||
| scripts | ||
| sql | ||
| src | ||
| tests/verifications | ||
| .env | ||
| CLAUDE.md | ||
| docker-compose.otel.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| drizzle.config.ts | ||
| instrumentation.ts | ||
| package.json | ||
| railway.toml | ||
| README.md | ||
| tsconfig.json | ||
| vitest.config.ts | ||
@proj-airi/server
HTTP and WebSocket backend for AIRI. This app owns auth, billing, chat synchronization, gateway forwarding, and server-side observability export.
What It Does
- Serves the Hono-based API and WebSocket endpoints.
- Uses Postgres as the source of truth for users, billing, and durable state.
- Uses Redis for cache, KV, Pub/Sub, and Streams.
- Forwards GenAI requests to the configured upstream gateway and records billing from usage.
- Exports traces, metrics, and logs through OpenTelemetry.
How To Use It
Install dependencies from the repo root and run scoped commands:
pnpm -F @proj-airi/server typecheck
pnpm -F @proj-airi/server exec vitest run
pnpm -F @proj-airi/server build
For local observability infrastructure, use:
docker compose -f apps/server/docker-compose.otel.yml up -d
AUTH_UI_URL
apps/ui-server-auth is deployed separately from the server image. The API server still owns the historical /auth/* entrypoints and redirects them to AUTH_UI_URL.
Default:
AUTH_UI_URL=https://accounts.airi.build/ui
Set this when previewing or deploying auth UI to a different Cloudflare URL.
ADMIN_UI_URL
The admin UI is deployed from the standalone proj-airi repository. The API server still owns the historical /admin/* entrypoints and redirects them to ADMIN_UI_URL.
Default:
ADMIN_UI_URL=https://admin.airi.build
Set this when previewing or deploying admin UI to a different Cloudflare URL.
ADDITIONAL_TRUSTED_ORIGINS (LAN / Capacitor dev)
When the mobile dev server uses a non-localhost origin (for example https://10.x.x.x:5273 from cap copy ios / capacitor.config.json), set ADDITIONAL_TRUSTED_ORIGINS in apps/server/.env.local to a comma-separated list of exact origins (parsed and normalized at startup). Example:
ADDITIONAL_TRUSTED_ORIGINS=https://10.0.0.129:5273,https://198.18.0.1:5273
Restart the API server after changing this variable.