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