Archive sentry-improvements, sync specs

Sync Sentry error tracking requirement (5 scenarios) to main
infrastructure spec. Archive completed change.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ullrich Schäfer 2026-03-25 03:13:36 +01:00
parent 9a904d9f69
commit 9d51fd6b36
No known key found for this signature in database
GPG key ID: A32FF691A0F752D9
6 changed files with 23 additions and 0 deletions

View file

@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-03-25

View file

@ -0,0 +1,38 @@
## Context
Both apps have basic Sentry (`@sentry/react` + `@sentry/node`) with source map uploads, release tracking, and environment tagging. Errors appear in Sentry but lack user/session context, making triage slow. Source maps are also served publicly.
## Goals / Non-Goals
**Goals:**
- Identify which user or session caused an error without guessing
- Route-level performance traces (not just page loads)
- Stop serving source maps to browsers
**Non-Goals:**
- Custom Sentry dashboards or alert rules (configure in Sentry UI)
- Server-side performance instrumentation beyond request handling
- Profiling integration
## Decisions
### D1: Set user context via Sentry.setUser in root loader
Journal's root loader already fetches the session user. Call `Sentry.setUser({ id, username })` on the client when authenticated, `Sentry.setUser(null)` when not. Done in root.tsx since it runs on every navigation.
### D2: Tag planner errors with session ID via Sentry.setTag
In `SessionView`, call `Sentry.setTag("session_id", sessionId)` on mount. This tags all subsequent errors with the active session.
### D3: Use reactRouterV7BrowserTracingIntegration
Sentry provides `Sentry.reactRouterV7BrowserTracingIntegration` which hooks into React Router's navigation to create route-aware spans. Replace the generic `browserTracingIntegration()` in both `entry.client.tsx` files. Requires passing `useEffect` and `useLocation` from react-router.
### D4: Hidden source maps via Vite config
Change `build.sourcemap` from `true` to `"hidden"`. This generates `.map` files for the Sentry plugin to upload but doesn't add `//# sourceMappingURL` comments to the bundles. Browsers won't request the map files. The Sentry plugin's `sourcemaps.filesToDeleteAfterUpload` option can also clean them from the build output.
## Risks / Trade-offs
- **D3 couples Sentry to React Router version** → Acceptable; we already depend on both. If we upgrade React Router, we upgrade the Sentry integration too.
- **D4 makes browser debugging harder in production** → Acceptable; errors go to Sentry with full source context. DevTools debugging in production was never a supported workflow.

View file

@ -0,0 +1,28 @@
## Why
Sentry is deployed but errors lack context — we don't know which user or session triggered them, route-level performance is invisible, and source maps are served to clients unnecessarily. These gaps make debugging harder and leak internal details.
## What Changes
- Set Sentry user context when a Journal user is authenticated (user ID, username)
- Tag Planner errors with the session ID for debugging
- Replace generic `browserTracingIntegration` with `reactRouterV7BrowserTracingIntegration` for route-aware performance traces
- Configure Vite to produce source maps as `hidden` (uploaded to Sentry but not referenced in the bundle, so browsers don't fetch them)
- Wrap server-side request handlers with Sentry error capturing for unhandled exceptions
## Capabilities
### New Capabilities
(None — this enhances the existing Sentry integration, no new behavioral capabilities.)
### Modified Capabilities
- `infrastructure`: Adding Sentry context enrichment and source map handling to the deployment pipeline
## Impact
- **Files**: `entry.client.tsx` (both apps), `entry.server.tsx` (journal), `server.ts` (planner), `vite.config.ts` (both apps), Journal root loader or layout
- **Dependencies**: No new packages — `@sentry/react` and `@sentry/node` already support all features
- **APIs**: No API changes
- **Security**: Source maps no longer served to clients (currently `.map` files are publicly accessible)

View file

@ -0,0 +1,24 @@
## MODIFIED Requirements
### Requirement: Sentry error tracking
The system SHALL enrich Sentry events with user and session context, use route-aware tracing, and prevent source maps from being served to clients.
#### Scenario: Journal error includes user context
- **WHEN** an authenticated Journal user triggers an error
- **THEN** the Sentry event SHALL include the user's ID and username
#### Scenario: Journal error without user context
- **WHEN** an unauthenticated visitor triggers an error
- **THEN** the Sentry event SHALL have no user context (Sentry.setUser(null))
#### Scenario: Planner error includes session ID
- **WHEN** an error occurs during a Planner session
- **THEN** the Sentry event SHALL include a `session_id` tag with the active session ID
#### Scenario: Route-level performance traces
- **WHEN** a user navigates between routes in either app
- **THEN** Sentry SHALL create a transaction span named after the route pattern (e.g., `/routes/:id`)
#### Scenario: Source maps not served to clients
- **WHEN** a client requests a `.map` file from the production server
- **THEN** the server SHALL return 404 (source maps are uploaded to Sentry during build, not shipped in the bundle)

View file

@ -0,0 +1,24 @@
## 1. User & Session Context
- [x] 1.1 Set Sentry user context (id, username) in Journal root loader/component when authenticated, clear when not
- [x] 1.2 Set Sentry `session_id` tag in Planner's SessionView on mount
## 2. Route-Aware Tracing
- [x] 2.1 Replace `browserTracingIntegration()` with `reactRouterV7BrowserTracingIntegration` in planner entry.client.tsx
- [x] 2.2 Replace `browserTracingIntegration()` with `reactRouterV7BrowserTracingIntegration` in journal entry.client.tsx
## 3. Source Map Hardening
- [x] 3.1 Change `build.sourcemap` from `true` to `"hidden"` in both vite.config.ts files
- [x] 3.2 Add `sourcemaps.filesToDeleteAfterUpload` to the Sentry Vite plugin config to clean up .map files after upload
## 4. Privacy Manifest
- [x] 4.1 Create `/privacy` route in Journal with a user-visible privacy manifest documenting: what Sentry collects (errors, traces, session replays), what the Planner does NOT collect, data retention, and third-party disclosure (Sentry)
- [x] 4.2 Add link to privacy manifest in Journal footer/home page
## 5. Verify
- [x] 5.1 Test locally: build, check no `.map` files remain in build output (or no sourceMappingURL in bundles)
- [x] 5.2 Test locally: trigger error in Journal while logged in, verify Sentry.setUser was called (check devtools)