feat(mana-auth): wire Glitchtip/Sentry error tracking via shared-error-tracking

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) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-05-07 01:55:07 +02:00
parent dd2e609545
commit 8b71d290f8
3 changed files with 29 additions and 1 deletions

View file

@ -290,6 +290,10 @@ services:
# returns 503 GRANT_NOT_CONFIGURED (graceful degrade). # returns 503 GRANT_NOT_CONFIGURED (graceful degrade).
MANA_AI_PUBLIC_KEY_PEM: ${MANA_AI_PUBLIC_KEY_PEM:-} MANA_AI_PUBLIC_KEY_PEM: ${MANA_AI_PUBLIC_KEY_PEM:-}
MANA_NOTIFY_URL: http://mana-notify:3013 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} MAX_DAILY_SIGNUPS: ${MAX_DAILY_SIGNUPS:-0}
# Must be a superset of TRUSTED_ORIGINS in # Must be a superset of TRUSTED_ORIGINS in
# services/mana-auth/src/auth/better-auth.config.ts. # services/mana-auth/src/auth/better-auth.config.ts.

View file

@ -14,6 +14,7 @@
"dependencies": { "dependencies": {
"@better-auth/passkey": "^1.6.8", "@better-auth/passkey": "^1.6.8",
"@mana/shared-ai": "workspace:*", "@mana/shared-ai": "workspace:*",
"@mana/shared-error-tracking": "workspace:*",
"@mana/shared-hono": "workspace:*", "@mana/shared-hono": "workspace:*",
"@mana/shared-types": "workspace:*", "@mana/shared-types": "workspace:*",
"bcryptjs": "^3.0.2", "bcryptjs": "^3.0.2",

View file

@ -5,6 +5,17 @@
* Uses Better Auth natively (fetch-based handler, no Express conversion). * 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 { Hono } from 'hono';
import { cors } from 'hono/cors'; import { cors } from 'hono/cors';
import { trimTrailingSlash } from 'hono/trailing-slash'; import { trimTrailingSlash } from 'hono/trailing-slash';
@ -77,7 +88,19 @@ const missionGrantService = new MissionGrantService(
const app = new Hono(); 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()); app.use('*', requestLogger());
// Defense-in-depth for clients that accidentally request the trailing-slash // 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 // form of a route (e.g. `/api/v1/me/onboarding/`). Hono's nested-router root