@@ -8,12 +8,24 @@ import { createAnalytics } from '@hanzo/event';
88import { AnalyticsProvider , ErrorBoundary , useAnalytics , usePageview } from '@hanzo/event/react' ;
99import { setErrorReporter , type ErrorContext } from '@/lib/error-handling/error-logger' ;
1010
11- /** The ONE Hanzo Cloud telemetry front door — POST api.hanzo.ai/v1/event. Cloud
12- * fans the one batched stream out to the web (analytics), product (insights), and
13- * error (sentry) lenses; the client never sends the org — Cloud resolves the
14- * tenant server-side from the validated bearer (or the publishable key). */
11+ /** The Hanzo Cloud event-stream door — POST api.hanzo.ai/v1/event. The client
12+ * never sends the org; Cloud resolves the tenant server-side from the validated
13+ * bearer (or the publishable key).
14+ *
15+ * NOTE: this door does NOT fan out to sentry. An earlier comment here claimed
16+ * Cloud fanned the one stream into the error (sentry) lens — it does not, and
17+ * that mistaken belief is why this app reported zero errors to sentry.hanzo.ai.
18+ * A `type:'error'` event lands in the cloud event warehouse (readable via
19+ * GET /v1/errors); reaching sentry requires the DSN below. */
1520const HOST = 'https://api.hanzo.ai' ;
1621
22+ /** Hanzo-minted Sentry DSN for the `hanzo-app` project — the ERROR plane.
23+ * "https://<version>:<hmac>@<host>/v1/sentry/<projectId>". Publishable and
24+ * write-only, so it is safe in the bundle. Unset => the error plane is inert
25+ * (fail-safe: analytics keeps working, nothing throws). Set in the build env;
26+ * never committed. Mint: POST /v1/sentry/projects */
27+ const EVENT_DSN = process . env . NEXT_PUBLIC_HANZO_EVENT_DSN || undefined ;
28+
1729/** Optional publishable ingest key (pk_…) that lets LOGGED-OUT marketing/public
1830 * views emit accepted telemetry (pageviews + errors + unload beacons) — the key
1931 * HMAC-verifies to the org server-side, so anonymous events light up all three
@@ -53,7 +65,8 @@ function Identity() {
5365 * the bearer the @hanzo/iam SDK already holds — it emits pageviews, a stable-id
5466 * identify() once auth resolves, AND captures errors (auto: window.onerror +
5567 * unhandledrejection; React: the ErrorBoundary below; manual: errorLogger, wired
56- * through setErrorReporter). One client, one stream — errors are just events.
68+ * through setErrorReporter). One client, two planes: every captured error goes to
69+ * sentry.hanzo.ai as a Sentry envelope AND stays correlated on the event stream.
5770 * The token is read through a live ref so a single stable client survives token
5871 * refresh without re-initializing.
5972 */
@@ -71,6 +84,9 @@ export function AnalyticsRoot({ children }: { children: ReactNode }) {
7184 host : HOST ,
7285 getToken : ( ) => tokenRef . current ?? undefined ,
7386 ingestKey : INGEST_KEY ,
87+ // Error plane -> sentry.hanzo.ai. Inert (fail-safe) when the DSN is unset.
88+ dsn : EVENT_DSN ,
89+ environment : process . env . NODE_ENV ,
7490 // Consent gate: honor the browser Do-Not-Track signal.
7591 enabled : ! doNotTrack ( ) ,
7692 } ) ,
0 commit comments