From 8b71d290f8bbb9adeee5889b1089a721196ac270 Mon Sep 17 00:00:00 2001 From: Till JS Date: Thu, 7 May 2026 01:55:07 +0200 Subject: [PATCH] feat(mana-auth): wire Glitchtip/Sentry error tracking via shared-error-tracking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First server-side error-tracking integration. Pattern mirrors the client-side one in apps/mana/apps/web/src/hooks.client.ts: - pull @mana/shared-error-tracking into mana-auth's deps (workspace pkg with @sentry/node + a no-op fallback when GLITCHTIP_DSN is unset) - call initErrorTracking() at the top of services/mana-auth/src/index.ts before the rest of the module body executes — this lets Sentry hook uncaughtException / unhandledRejection before any Hono handlers register - wrap app.onError so non-HTTPException throws also flow into captureException with path/method/query context. HTTPExceptions are intentional 4xx/422 and stay out of the issue list (otherwise every 401 from a stale session would page somebody at 3am) - compose: pass GLITCHTIP_DSN_MANA_PLATFORM through as GLITCHTIP_DSN per service so each container's events get tagged with serverName='mana-auth' DSN itself isn't in the repo; lives in .env.macmini on the Mac Mini and is referenced from the Glitchtip credentials doc. Co-Authored-By: Claude Opus 4.7 (1M context) --- docker-compose.macmini.yml | 4 ++++ services/mana-auth/package.json | 1 + services/mana-auth/src/index.ts | 25 ++++++++++++++++++++++++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/docker-compose.macmini.yml b/docker-compose.macmini.yml index edc3b87ae..3e74542b5 100644 --- a/docker-compose.macmini.yml +++ b/docker-compose.macmini.yml @@ -290,6 +290,10 @@ services: # returns 503 GRANT_NOT_CONFIGURED (graceful degrade). MANA_AI_PUBLIC_KEY_PEM: ${MANA_AI_PUBLIC_KEY_PEM:-} MANA_NOTIFY_URL: http://mana-notify:3013 + # Glitchtip error reporting (Phase 2d, 2026-05-07). DSN is the + # mana-platform project on glitchtip.mana.how; per-service env so + # each service ends up tagged with its serverName. + GLITCHTIP_DSN: ${GLITCHTIP_DSN_MANA_PLATFORM:-} MAX_DAILY_SIGNUPS: ${MAX_DAILY_SIGNUPS:-0} # Must be a superset of TRUSTED_ORIGINS in # services/mana-auth/src/auth/better-auth.config.ts. diff --git a/services/mana-auth/package.json b/services/mana-auth/package.json index f2426eb2f..feec90949 100644 --- a/services/mana-auth/package.json +++ b/services/mana-auth/package.json @@ -14,6 +14,7 @@ "dependencies": { "@better-auth/passkey": "^1.6.8", "@mana/shared-ai": "workspace:*", + "@mana/shared-error-tracking": "workspace:*", "@mana/shared-hono": "workspace:*", "@mana/shared-types": "workspace:*", "bcryptjs": "^3.0.2", diff --git a/services/mana-auth/src/index.ts b/services/mana-auth/src/index.ts index 2c525f67d..8b2981306 100644 --- a/services/mana-auth/src/index.ts +++ b/services/mana-auth/src/index.ts @@ -5,6 +5,17 @@ * Uses Better Auth natively (fetch-based handler, no Express conversion). */ +// Sentry/Glitchtip — must run before the rest of the module loads so +// uncaughtException + unhandledRejection get hooked. No-op when +// GLITCHTIP_DSN is unset (e.g. local dev). +import { initErrorTracking, captureException } from '@mana/shared-error-tracking'; +initErrorTracking({ + serviceName: 'mana-auth', + dsn: process.env.GLITCHTIP_DSN, + environment: process.env.NODE_ENV, + release: process.env.GIT_SHA, +}); + import { Hono } from 'hono'; import { cors } from 'hono/cors'; import { trimTrailingSlash } from 'hono/trailing-slash'; @@ -77,7 +88,19 @@ const missionGrantService = new MissionGrantService( const app = new Hono(); -app.onError(errorHandler); +app.onError((err, c) => { + // Surface non-HTTPException errors to Glitchtip with request context. + // HTTPException is intentional 4xx/422 etc. — not an "error" worth alerting on. + const isHttpException = err.constructor.name === 'HTTPException'; + if (!isHttpException) { + captureException(err, { + path: c.req.path, + method: c.req.method, + query: Object.fromEntries(new URL(c.req.url).searchParams), + }); + } + return errorHandler(err, c); +}); app.use('*', requestLogger()); // Defense-in-depth for clients that accidentally request the trailing-slash // form of a route (e.g. `/api/v1/me/onboarding/`). Hono's nested-router root