Repository navigation
Add browser error capture and error-only session replay via same-origin Sentry tunnel - #909
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThis change adds browser Sentry initialization and error-only Session Replay, passes configuration through SSR metadata, forwards validated envelopes through a same-origin worker route, updates CSP for Replay workers, and documents the integration. ChangesBrowser Sentry integration
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Browser
participant SSR
participant SentryTunnel
participant Sentry
SSR->>Browser: Render kody:sentry configuration
Browser->>Browser: Initialize Sentry and capture client errors
Browser->>SentryTunnel: POST /sentry-tunnel envelope
SentryTunnel->>SentryTunnel: Validate size and DSN
SentryTunnel->>Sentry: Forward matching envelope
Sentry-->>SentryTunnel: Ingest response
SentryTunnel-->>Browser: Return delivery status
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
🔎 Preview deployed: https://kody-pr-909.kody-a99.workers.dev Worker: Mocks:
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/worker/client/sentry-config.ts`:
- Around line 27-32: Update the tunnel validation in the sentry configuration
parser to accept paths beginning with a single slash while rejecting
scheme-relative values beginning with “//”. Add regression coverage for the
rejected scheme-relative tunnel in
packages/worker/client/sentry-config.node.test.ts at lines 32-50 and the
existing parser tests, preserving valid same-origin path behavior.
In `@packages/worker/src/app/handlers/sentry-tunnel.ts`:
- Around line 26-29: Update the DSN parsing in the handler around dsnUrl and
projectId to split the pathname into segments, use only the final segment as the
project ID, and preserve preceding segments when constructing the Sentry
envelope URL. Keep empty-project validation intact and add a regression test
covering a DSN hosted under a base path such as /sentry/456.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 3f728266-5ade-479a-b042-f31b10464697
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (15)
docs/contributing/architecture/request-lifecycle.mddocs/contributing/environment-variables.mdpackages/worker/client/entry.tsxpackages/worker/client/sentry-client.tspackages/worker/client/sentry-config.node.test.tspackages/worker/client/sentry-config.tspackages/worker/package.jsonpackages/worker/src/app/handlers/sentry-tunnel.node.test.tspackages/worker/src/app/handlers/sentry-tunnel.tspackages/worker/src/app/router.tspackages/worker/src/app/routes.tspackages/worker/src/app/security-headers.tspackages/worker/src/app/ssr-document.tsxpackages/worker/src/app/ssr-render.tsxpackages/worker/tsconfig-worker.json
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 5bd1adf. Configure here.
| timeline: '/timeline', | ||
| timelineApi: '/timeline.json', | ||
| health: '/health', | ||
| sentryTunnel: post('/sentry-tunnel'), |
There was a problem hiding this comment.
Sentry tunnel hits write lease
Medium Severity
The new POST /sentry-tunnel route is treated like a mutating account write for signed-in users. Global createAccountWriteLeaseMiddleware runs on every POST except /account/delete, so authenticated browser envelopes can return 409 during account deletion, 503 when the lease is lost, or hold a D1 write lease for the entire upstream Sentry forward—including large error replay uploads—while anonymous POSTs skip the lease entirely.
Reviewed by Cursor Bugbot for commit 5bd1adf. Configure here.


What
Adds client-side Sentry with strict privacy defaults, completing the observability rollout (#905, #906, #908):
@sentry/browser):packages/worker/client/sentry-client.tsinitializes from akody:sentrymeta tag thatssr-document.tsxrenders whenSENTRY_DSNis configured (the DSN is a publishable client key). No-ops entirely when the tag is absent (local dev / tests). The hydration error listener inentry.tsxalso reports through it.replaysSessionSampleRate: 0,replaysOnErrorSampleRate: 1.0— nothing is recorded to Sentry during normal sessions; only the in-memory buffer around an error is uploaded.maskAllTextandblockAllMediaare set explicitly because Kody sessions contain personal-assistant content.POST /sentry-tunnelroute (packages/worker/src/app/handlers/sentry-tunnel.ts) forwards envelopes server-side, so the first-party CSP keepsconnect-src 'self'. Abuse-safe: the envelope header's DSN must exactly match the Worker's ownSENTRY_DSN(403 otherwise), bodies are capped at 10 MB, and the route 404s when no DSN is configured.worker-src 'self' blob:for replay's compression Web Worker (spawning a blob worker already requires script execution, whichscript-src 'self'still gates).tsconfig-worker.jsonincludesclient/sentry-config.ts(the SDK-free config module shared by SSR and client); docs updated inrequest-lifecycle.mdandenvironment-variables.md.Cost note
The client bundle grows from ~600 KB to ~850 KB minified (~75 KB gzip delta) — the Sentry CDN/lazy-load alternative is not available under
script-src 'self', so static bundling is the CSP-correct option.Verification
buffermode; a thrown error produced both the error-event envelope and the replay recording envelope through/sentry-tunnel(tunnel-envelopes: ['error_event', 'replay']); curl checks confirmed 403 on mismatched DSN and forward-attempt on match; CSP header includes the newworker-srcdirective.System recap — extends the app shell with client telemetry (medium risk)
Mode: recap · Base:
main@52b06b46· Head: branch tipClassification: extends — new route on the app surface, CSP directive addition, and a browser SDK in the client bundle; no data-model or MCP changes.
Primitives touched
app-uiapp-routerPOST /sentry-tunnelroutesecurity-headersworker-src 'self' blob:added to CSPSystem map
Browser errors flow from the client bundle through the same-origin tunnel into Sentry, keeping CSP locked.
Legend: green = composes (wiring only) · amber = extended by this PR · red = new primitive · gray = context (unchanged).
Invariants
Replay privacy: all text masked, all media blocked, no session recording without an error,
sendDefaultPii: false. The tunnel cannot proxy to arbitrary destinations (DSN allowlist of exactly one).Summary by CodeRabbit
New Features
/sentry-tunnelendpoint.Documentation
Bug Fixes
Tests
/sentry-tunnelforwarding behavior.