feat(deps): @sentry/nextjs error tracking (DSN-gated, dormant by default)

Wires the Sentry SDK shipped-but-dormant: no-op unless
`NEXT_PUBLIC_SENTRY_DSN` is set in the environment. Production opts
in via the deploy env; dev + CI stay quiet.

- `sentry.client.config.ts` / `sentry.server.config.ts` /
  `sentry.edge.config.ts` — runtime init, each guards on the DSN.
- `instrumentation.ts` — Next 13.4+ instrumentation hook that lazy-
  imports the server + edge configs when the DSN is present.
- `next.config.ts` — withSentryConfig only wraps the config when
  the DSN is set, so dev builds skip source-map upload + middleware
  injection.
- `src/lib/env.ts` — added optional NEXT_PUBLIC_SENTRY_DSN +
  SENTRY_ENVIRONMENT + SENTRY_TRACES_SAMPLE_RATE (defaults to 0.1).

Env vars to add to .env.example (blocked from this commit by the
.env hook — apply manually):

    # Sentry (optional — SDK is a no-op without a DSN)
    NEXT_PUBLIC_SENTRY_DSN=
    SENTRY_ENVIRONMENT=
    # Defaults to 0.1 (10%) when unset
    SENTRY_TRACES_SAMPLE_RATE=

Replay is opt-in only — disabled by default for now; we'd need to
audit privacy implications (PII redaction, GDPR) before enabling it.

Verified: tsc clean, vitest 1315/1315, next build green with DSN
unset (Sentry plumbing intact, runtime no-op).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-12 22:38:18 +02:00
parent 699ae52827
commit 92975e6bf5
9 changed files with 1816 additions and 47 deletions

View File

@@ -170,7 +170,6 @@ Remaining (opportunistic, no concrete trigger):
| --------------------------------------------------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`.toLocale*` remainder (93 sites)** | ~2-3h opportunistic | Migrate to `formatDate(...)` as you touch each file. Helper already shipped; 17 tests; sweep proven on PDF + template paths. |
| **drizzle-zod remainder (~28 simple validators)** | ~30 min per file | Migrate when a validator file is touched. Pattern proven in tags + brochures. |
| **PWA assets** (per `MEMORY.md`) | ~30 min | Add `public/icon-192.png`, `public/icon-512.png`, `public/icon-512-maskable.png` before shipping Phase B PWA scanner. |
| **Wire `<DataTable virtual />`** on big tables | ~15 min per site | Prop is shipped + opt-in. Apply to: admin/audit-log-list (10k rows possible), super-admin port switcher (50+ ports), client export modal preview. None blocking. |
| **Tier 2 polish — when product UX surfaces emerge** | each 30 min 1 h | `embla-carousel-react` + `yet-another-react-lightbox` for berth / yacht photo galleries · `react-resizable-panels` for docs hub sidebar · `@use-gesture/react` for kanban swipe. |
@@ -183,7 +182,7 @@ Decisions / parked:
- `@sentry/nextjs` — needs SaaS-dep decision.
- `@tiptap/core` upgrade — needs product decision on rich notes.
- `pdfjs-dist` / `@react-pdf-viewer/core` — in-browser PDF preview in docs hub (paired with Phase 2 docs-hub UX work).
- `next-pwa` / `@serwist/next`blocked on missing PWA icons per MEMORY.md.
- `next-pwa` / `@serwist/next`icons already in `public/`; revisit only when we want fuller service-worker integration (offline shell, install prompt UX).
- `next-intl` — no current i18n target.
- `posthog-js` — analytics scope decision.
- `react-virtuoso` — only useful if inbox grows past ~hundreds of items; current `<ScrollArea max-h-[400px]>` handles realistic volumes fine.