Skip to content

feat(monitoring): #45 consent-gated Sentry error monitoring (client-only, PII-scrubbed)#145

Merged
TortoiseWolfe merged 1 commit into
mainfrom
feat/45-sentry-monitoring
Jun 8, 2026
Merged

feat(monitoring): #45 consent-gated Sentry error monitoring (client-only, PII-scrubbed)#145
TortoiseWolfe merged 1 commit into
mainfrom
feat/45-sentry-monitoring

Conversation

@TortoiseWolfe

Copy link
Copy Markdown
Owner

What

Scaffolds Sentry error monitoring for the static-export app (issue #45). Client-only, consent-gated, PII-scrubbed, and inert until a DSN is configured — so it ships now and goes live with zero code change once NEXT_PUBLIC_SENTRY_DSN is set.

Why client-only

The app is output: 'export' (GitHub Pages). @sentry/nextjs / withSentryConfig / instrumentation.ts all require a Next server, so this uses @sentry/react (re-exports the browser SDK) and initializes purely on the client, mirroring the existing consent-gated GoogleAnalytics.

How it works

  • src/lib/monitoring/scrub.ts — pure, SDK-free PII scrubber used as beforeSend: redacts emails, JWTs, Bearer/access_token/refresh_token, sb-<ref>-auth-token keys, and whole-value-redacts message-body fields (content, plaintext_content, new_content, encrypted_content, password). 15 unit tests.
  • src/lib/monitoring/sentry.ts — idempotent initSentry (no-op without DSN / on SSR), closeSentry on consent withdrawal, guarded captureAppError. Replay + tracing disabled so the E2E-encrypted messaging UI is never recorded. 6 tests.
  • src/lib/monitoring/SentryMonitor/ — 5-file consent-gated client component; inits only after analytics consent, shuts down on withdrawal.
  • src/utils/error-handler.ts — single capture chokepoint in sendToService (ErrorBoundary already routes here → exactly one captureException per handled error). 2 tests.
  • layout.tsx — mounts <SentryMonitor/> beside <GoogleAnalytics/> and adds Sentry ingest hosts to the CSP connect-src (static export has no header CSP — without this, envelopes are silently blocked).
  • .env.example / deploy.yml / README.md — document NEXT_PUBLIC_SENTRY_DSN (build-time inlined, so wired into the deploy build env).

Going live (for the maintainer)

A DSN is a sentry.io connection string (not DNS, not derivable from the domain). Create a free Next.js project at sentry.io → copy the DSN from Client Keys (DSN) → set it in .env + add the NEXT_PUBLIC_SENTRY_DSN Actions secret. Monitoring then activates automatically (after the user grants analytics consent).

Verification

  • pnpm run type-checkpnpm run lint
  • pnpm run validate:structure ✅ (110/110)
  • 33 unit tests pass (scrub 15, sentry 6, SentryMonitor 5 + a11y 5, error-handler 2)
  • pnpm run build ✅ — compiles and prerenders with an empty DSN (Sentry no-ops) under static export

Closes #45.

🤖 Generated with Claude Code

…nly, PII-scrubbed)

Scaffolds Sentry error monitoring for the static-export app. Client-only
(@sentry/react, not @sentry/nextjs — withSentryConfig needs a Next server),
gated on analytics consent via ConsentContext (mirrors GoogleAnalytics), and
inert until NEXT_PUBLIC_SENTRY_DSN is set (empty DSN = no-op, so it ships now
and goes live with zero code change once a DSN is provided).

- src/lib/monitoring/scrub.ts — pure PII scrubber (emails, JWTs, Bearer/token
  k-v, sb-<ref>-auth-token keys; whole-value redaction of message bodies
  content/plaintext_content/new_content/encrypted_content/password). Used as
  beforeSend. 15 unit tests.
- src/lib/monitoring/sentry.ts — idempotent init (no-op without DSN/on SSR),
  closeSentry on consent withdrawal, guarded captureAppError. Replay + tracing
  disabled so the encrypted messaging UI is never recorded. 6 tests.
- src/lib/monitoring/SentryMonitor/ — 5-file consent-gated client component.
- src/utils/error-handler.ts — single capture chokepoint in sendToService
  (ErrorBoundary already routes here → exactly one captureException per error).
- layout.tsx mounts <SentryMonitor/> + adds Sentry ingest hosts to CSP
  connect-src (static export has no header CSP; envelopes would be blocked).
- .env.example / deploy.yml / README document NEXT_PUBLIC_SENTRY_DSN.

Closes #45.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@TortoiseWolfe TortoiseWolfe merged commit 8a53e9f into main Jun 8, 2026
17 checks passed
@TortoiseWolfe TortoiseWolfe deleted the feat/45-sentry-monitoring branch June 8, 2026 18:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Gap-Audit] 044 Error Handler Integrations: Sentry/LogRocket integration + PII scrubbing + session replay

2 participants