Files
Pamela Chia 2d0bcd4714 feat(telemetry): classify funnel creation errors (#47293)
## Summary

The KPI-3 friction dashboard needs to know *why* users hit errors on the
signup, project-creation, and org-creation funnels, not just that they
did. The existing `dashboard_error_created` event already fires for
these paths (10% sampled, with `$pathname`), but carries no reason:
~98.5% of events have no `errorType` and no property carries an error
message. This adds PII-safe classification computed client-side from a
controlled vocabulary, so raw error text never leaves the browser.
Validation errors (previously invisible, since they are inline form
errors that never raise a toast) are now captured on invalid submit.

## Changes

- Extend `dashboard_error_created` with `origin`, `errorCategory`,
`errorReason`, `errorCode`, and a `form` source value
- Add a pure, unit-tested classifier (`funnel-errors.ts`) and a
10%-sampled tracking hook (`use-track-funnel-error.ts`); the classifier
maps errors to stable slugs and emits only slugs + HTTP status, never
raw message text
- Classify signup errors (API failures + validation) in `SignUpForm`
- Classify project-creation errors (API failures, OrioleDB guard,
validation) in the new-project wizard
- Classify org-creation errors (API failures, payment/card declines,
confirm-subscription, validation) in `NewOrgForm`

## Testing

13 unit tests cover every classifier branch (validation / api / network
/ payment, status-code handling, message-pattern matching, and
fallbacks).

To verify on the Vercel preview (events are 10% sampled; set the sample
rate to 1 locally to observe each fire):
- Signup with a weak but non-empty password: `origin=signup,
source=form, errorCategory=validation, errorReason=password_invalid`
- Signup with an already-registered email: `origin=signup, source=toast,
errorCategory=api, errorReason=email_already_registered`
- New project with an empty name: `origin=project_creation, source=form,
errorReason=project_name_invalid`
- New org with an empty name: `origin=org_creation, source=form,
errorReason=org_name_missing`
- New org with a declined test card: `origin=org_creation,
errorCategory=payment`

PII: raw `error.message` is never sent; only controlled slugs and HTTP
status. Dashboard consumers must filter `origin IS NOT NULL` so these do
not collide with the generic toast events the global tracker still
emits.

## Linear

- fixes FE-3691


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added improved, categorized telemetry for signup, project creation,
and organization creation errors, including payment,
subscription-change, and validation failures.
* Extended dashboard error events with optional structured diagnostics
(origin, category, reason, and optional error code) and support for
form-origin reporting.

* **Bug Fixes**
* Improved project-creation handling to record a validation telemetry
event when an Oriole image is unavailable.
* Ensured payment-related and subscription-change failures are captured
consistently alongside existing user toasts.

* **Tests**
* Added unit tests covering API/network/validation/Stripe error
classification and reason mapping.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-25 20:56:23 +08:00
..