diff --git a/aidlc-docs/features/react-frontend/audit.md b/aidlc-docs/features/react-frontend/audit.md index ecf0642..63f1b9c 100644 --- a/aidlc-docs/features/react-frontend/audit.md +++ b/aidlc-docs/features/react-frontend/audit.md @@ -528,3 +528,15 @@ **Context**: Post-workflow follow-up (feature already marked Complete); continues the `feature/sentry_error_logging` branch. `pnpm run build`, `pnpm run lint` and `pnpm run test` re-verified successfully after the change. Changes not yet committed/pushed. --- + +## Post-Completion Follow-up: Sentry "Tunnel" Extended to Local Development + +**Timestamp**: 2026-07-25T15:45:00Z + +**User Input**: "Is het ook gefixt voor lokaal?" — followed by: "Ja voeg voor lokaal ook een tunnel toe". + +**AI Response**: "Added a `server.proxy` entry for `/sentry-tunnel` in `vite.config.ts`, forwarding to the same Sentry envelope endpoint as the reverse-proxy Pi's nginx tunnel (matching the org/project baked into the local `.env.local` DSN). Simplified `src/main.tsx`'s `tunnel` option from the previous `import.meta.env.DEV ? undefined : '/sentry-tunnel'` to an unconditional `'/sentry-tunnel'`, since `pnpm dev` now also has a matching proxy route — local testing no longer requires disabling the ad-blocker. Updated `monitoring-setup.md` to describe the tunnel as active in all environments (including local), and to flag that the org/project id must stay in sync across the nginx config, the Vite proxy target, and the configured DSN." + +**Context**: Post-workflow follow-up (feature already marked Complete); continues the `feature/sentry_error_logging` branch. `pnpm run build`, `pnpm run lint` and `pnpm run test` re-verified successfully after the change. Changes not yet committed/pushed. + +--- diff --git a/aidlc-docs/features/react-frontend/operations/monitoring/monitoring-setup.md b/aidlc-docs/features/react-frontend/operations/monitoring/monitoring-setup.md index 04fb196..17744e2 100644 --- a/aidlc-docs/features/react-frontend/operations/monitoring/monitoring-setup.md +++ b/aidlc-docs/features/react-frontend/operations/monitoring/monitoring-setup.md @@ -25,7 +25,7 @@ Both the console and Sentry are now active (original Question 3 resolved as a co - **Manual follow-up required**: create a free Sentry project (https://sentry.io) for this app, copy its DSN, and set it as the `VITE_SENTRY_DSN` repository variable in Gitea (Repository Settings → Actions → Variables). Until that variable is set, the build still succeeds and the site still works — Sentry reporting simply stays inactive. - Free tier limits (error volume, retention) are typically sufficient for a low-traffic marketing site. - **Not (yet) implemented, by explicit choice**: automatic source map upload (via `@sentry/vite-plugin`), which the official Sentry setup guide also recommends so stack traces show real source code instead of minified code. This requires a Sentry auth token/org/project as a new Gitea secret; deliberately left out of scope for now — revisit if readable production stack traces become a priority. -- **Ad-blocker mitigation via a Sentry "tunnel" (test/production only)**: requests straight to `*.ingest..sentry.io` are commonly blocked client-side by ad-blockers/privacy extensions (`ERR_BLOCKED_BY_CLIENT`), because they resemble third-party tracking. To avoid this in deployed environments, `Sentry.init()` sets `tunnel: '/sentry-tunnel'` (disabled — `undefined` — during local `pnpm dev`, where the ad-blocker itself is disabled instead, per earlier decision). The reverse-proxy Pi (`nginx/reverse-proxy-nginx.conf.example`) forwards that path server-side to Sentry's envelope endpoint, so the browser only ever talks to the first-party domain (e.g. `test.slpsoftware.nl`). This relies on full control over the reverse-proxy's nginx config, which is the case here (self-hosted on the user's own Raspberry Pi's) — it would not work on a third-party/shared host without reverse-proxy access. **Important**: the org-/project-id hardcoded in that nginx `location /sentry-tunnel` block must match whatever `VITE_SENTRY_DSN` is actually configured for that environment; update both together if the Sentry project/DSN ever changes. +- **Ad-blocker mitigation via a Sentry "tunnel" (all environments, including local)**: requests straight to `*.ingest..sentry.io` are commonly blocked client-side by ad-blockers/privacy extensions (`ERR_BLOCKED_BY_CLIENT`), because they resemble third-party tracking. To avoid this, `Sentry.init()` always sets `tunnel: '/sentry-tunnel'`. In deployed (test/production) environments, the reverse-proxy Pi (`nginx/reverse-proxy-nginx.conf.example`) forwards that path server-side to Sentry's envelope endpoint, so the browser only ever talks to the first-party domain (e.g. `test.slpsoftware.nl`). Locally (`pnpm dev`), the equivalent route is provided by Vite's own dev-server proxy (`server.proxy` in `vite.config.ts`), so no ad-blocker whitelisting/disabling is needed anymore for local testing either. This relies on full control over the reverse-proxy's nginx config, which is the case here (self-hosted on the user's own Raspberry Pi's) — it would not work on a third-party/shared host without reverse-proxy access. **Important**: the org-/project-id hardcoded in both the nginx `location /sentry-tunnel` block and the Vite `server.proxy` target must match whatever `VITE_SENTRY_DSN`/`.env.local` DSN is actually configured; update all together if the Sentry project/DSN ever changes. **Log level strategy**: only errors are logged (no verbose/info-level client logging) — this is a static site with no meaningful "business events" beyond page views, which are covered by analytics (see Dashboards below), not logging. diff --git a/src/main.tsx b/src/main.tsx index 5b98daa..76c4f07 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -22,11 +22,10 @@ if (sentryDsn) { enableLogs: true, // Ad-blockers/privacy extensions commonly block requests straight to *.ingest.sentry.io // (ERR_BLOCKED_BY_CLIENT), because it looks like third-party tracking. Routing through our - // own domain via a reverse-proxy "tunnel" avoids that (see nginx/reverse-proxy-nginx.conf.example). - // Only enabled for built (test/production) environments — local dev (`pnpm dev`) has no such - // proxy route available, so it keeps posting straight to Sentry (resolved by disabling the - // ad-blocker locally instead). - tunnel: import.meta.env.DEV ? undefined : '/sentry-tunnel', + // own domain via a "tunnel" avoids that: in built (test/production) environments this is + // handled by the reverse-proxy Pi (see nginx/reverse-proxy-nginx.conf.example); locally + // (`pnpm dev`) the equivalent proxy route is set up in vite.config.ts's `server.proxy`. + tunnel: '/sentry-tunnel', }); } diff --git a/vite.config.ts b/vite.config.ts index 9a1d7aa..a437210 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -10,6 +10,20 @@ export default defineConfig({ // Injected at build time, used as the Sentry `release` tag (see src/main.tsx). __APP_VERSION__: JSON.stringify(version), }, + server: { + proxy: { + // Mirrors the reverse-proxy Pi's "/sentry-tunnel" location (see + // nginx/reverse-proxy-nginx.conf.example) so the same tunnel path also + // works locally during `pnpm dev`, avoiding ad-blocker ERR_BLOCKED_BY_CLIENT + // errors when testing locally too (see src/main.tsx's Sentry.init tunnel option). + // LET OP: moet in sync blijven met de VITE_SENTRY_DSN uit .env.local. + '/sentry-tunnel': { + target: 'https://o4511795618185216.ingest.de.sentry.io', + changeOrigin: true, + rewrite: () => '/api/4511795622838352/envelope/', + }, + }, + }, test: { environment: 'jsdom', globals: true,