fix(analytics): address review findings on activation-funnel events

- app_opened now also fires on the consent-grant transition (modal Allow /
  Settings toggle), not just cold start with prior consent — the true first
  session was emitting nothing and session 2 got mislabeled is_first_open.
  trackAppOpened() is guarded once-per-JS-session so revoke->regrant cannot
  double-count.
- testConnection() takes a source ('onboarding' | 'edit_test') carried on
  connection_attempted/succeeded/failed so the funnel can filter out the
  edit screen's repeat-tester noise.
- Aborted runs no longer count: abortedSessions set (in sessions.ts, read by
  events.ts which already imports it — no new import cycle), marked after a
  successful abort call, cleared on busy, and checked on busy->idle for BOTH
  response_received and recordSuccessfulSession().
- Consent revocation now DROPS buffered events instead of flushing them:
  PostHog's optOut() only blocks new captures and shutdown() drains the queue
  over the network, so ConsentGatedPostHog overrides the public fetch()
  transport to answer with a synthetic 200 post-revoke — shutdown clears the
  persisted queue and timers with zero bytes leaving the device. Re-grant
  calls optIn() to clear the persisted SDK opt-out flag.
- classifyConnectionError extracted to pure analytics-classify.ts with
  node --test coverage (same pattern as store-review-policy).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NJKAQ6HAikWGQK7PGZ5Y4E
This commit is contained in:
engineer
2026-07-16 16:04:54 -07:00
parent 027c529ce5
commit c3cac2b8e5
9 changed files with 195 additions and 48 deletions

View File

@@ -84,6 +84,7 @@ export default function EditConnectionScreen() {
directory: directory.trim() || undefined,
username: username.trim() || undefined,
},
"edit_test",
password || undefined,
)

View File

@@ -80,6 +80,7 @@ export default function AddConnectionScreen() {
url: serverUrl,
username: username.trim() || undefined,
},
"onboarding",
password || undefined,
)
@@ -133,7 +134,7 @@ export default function AddConnectionScreen() {
// Advanced mode saves directly without a pre-flight health check (see
// useConnections.addConnection), so unlike quick-connect there is no
// success/failure signal to report here — only that an attempt was made.
track(AnalyticsEvent.ConnectionAttempted)
track(AnalyticsEvent.ConnectionAttempted, { source: "onboarding" })
setIsConnecting(true)
await addConnection(
{