Uh oh!
There was an error while loading. Please reload this page.
docs(console): rewrite error-tracking guide for the two-key telemetry gate - #6601
Merged
Conversation
… gate `apps/console/docs/error-tracking.md` predated the #5522 fix chain and every load-bearing instruction in it contradicted the shipped design. Followed literally it told a reader to `pnpm add @sentry/react`, hand-roll `src/lib/sentry.ts`, and call it before React renders — bolting a second, ungated Sentry init onto an app that already has a gated one, which is exactly the "decision frozen at build time, no operator switch" shape #5522 removed. Rewritten to describe the system that exists: - Sentry is built in; the install + hand-rolled-init recipe is gone. - Enabling is the CONJUNCTION of two independent opt-ins: build-time `VITE_SENTRY_DSN` (plus the optional knobs mirrored from the authoritative comment block in `apps/console/.env.production`) AND the runtime permission `telemetry.allowClientErrorReporting`, granted server-side with `OS_TELEMETRY_CLIENT_ERROR_REPORTING_ENABLED` or `new RuntimeConfigPlugin({ allowClientErrorReporting: true })`. - The fail-closed contract stated once: either half missing => no reporting, silently, by design; every "cannot determine" state reads denied. - Ordering documented for host embedders: `initSentry()` must run after `initRuntimeConfig()` settles, because it memoizes its verdict. - "Option 2: Custom Error Boundary" removed. It was a second ungated exfiltration path presented as an alternative; replaced by the built-in `captureError()` / `setSentryUser()`, which route through the same gate, plus a pointer to the app-shell `ErrorBoundary` that already calls them. - Verification steps now check the half an operator can inspect from outside: `curl /api/v1/runtime/config | jq .telemetry`, then the vendor-sentry chunk, then a thrown test error. Two corrections beyond the card's table, both verified against the tree: - The CSP section was fabricated. It claimed the console "includes a Content Security Policy meta tag" whose default "already includes https://*.sentry.io in connect-src". `apps/console/index.html` sets no CSP meta tag and the doc was the only file in the repo mentioning CSP at all. Rewritten to say the console ships no CSP, and to give the connect-src a *hosting layer* would need. - `VITE_ENVIRONMENT` and `VITE_ERROR_ENDPOINT` had zero read sites anywhere in the tree; both are gone. Every env var the doc now names greps to a real read site (11/11 verified). The source-maps CI note is kept — `sourcemap: false` in `apps/console/vite.config.ts` is still accurate — with the release pinned to `VITE_SENTRY_RELEASE` so uploaded maps match the events.
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
os-zhuang
approved these changes
Aug 27, 2026
os-zhuang
left a comment
Contributor
There was a problem hiding this comment.
PM review (dispatching seat for #6599): read the full diff against the shipped implementation.
- Every instruction now describes the code that exists: the two-key gate (
resolveSentryGate), the fail-closed contract with all indeterminate states reading denied, the #5982 init-after-runtime-config ordering with the memoization trap spelled out, and the closed truthy vocabulary with loud refusal. - The dev's mechanical acceptance check (11/11 named variables grep to real read sites; the two ghosts
VITE_ENVIRONMENT/VITE_ERROR_ENDPOINTremoved) matches the card's acceptance criterion exactly. - Two corrections beyond the card, both verified measurements, both accepted: the old CSP section was fabricated (no CSP meta tag exists in
apps/console/index.html), and Option 2 was a second ungated exfiltration path — replaced with the gatedcaptureError/setSentryUserhelpers. - Heads-up recorded, not a blocker: objectstack#12681 (maintainer-ruled, queued) will move the DSN source server-side; this doc's runtime half gets updated again as part of that change. Landing the accurate current-shape doc first is the ruled sequencing.
Landing via the normal queue — apps/console/docs/** is not a governed surface.
Generated by Claude Code
os-zhuang
marked this pull request as ready for review
August 27, 2026 08:42
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#6599
apps/console/docs/error-tracking.mdpredated the #5522 fix chain. Followed literally it told a reader topnpm add @sentry/react, hand-rollsrc/lib/sentry.ts, and initialise before React renders — bolting a second, ungated Sentry init onto an app that already has a gated one, and reinstating the report-before-permission ordering that PR #5982 eliminated. Thecommitted-telemetry-endpoint.test.tsratchet would not have caught it: nothing gets committed, the init is just wrong.What changed
One file,
apps/console/docs/error-tracking.md(+156 / -131). No code, no dependencies, no changeset owed.VITE_SENTRY_DSN(plusVITE_SENTRY_SEND_DEFAULT_PII,VITE_SENTRY_ENABLED,VITE_SENTRY_ENVIRONMENT,VITE_SENTRY_RELEASE,VITE_SENTRY_TRACES_SAMPLE_RATE,VITE_SENTRY_REPLAY, mirrored from the authoritative comment block inapps/console/.env.production) AND the runtime permissiontelemetry.allowClientErrorReporting, granted withOS_TELEMETRY_CLIENT_ERROR_REPORTING_ENABLEDornew RuntimeConfigPlugin({ allowClientErrorReporting: true }), linked to the canonical row in objectstackcontent/docs/deployment/environment-variables.mdx.1/true/on/yes), the mount-time refusal of an unrecognised spelling, and theOS_CLOUD_URL=offinteraction that lowers a well-spelled grant to denied.initSentry()memoizes its verdict, so it must run afterinitRuntimeConfig()settles.captureError()/setSentryUser(), which route through the same gate and no-op when it denies, plus a pointer to the app-shellErrorBoundarythat already calls them.curl /api/v1/runtime/config | jq .telemetry, then the vendor-sentry chunk in the Network tab, then a thrown test error.Two corrections beyond the card table
Both found while verifying the doc against the tree, both in the same file:
https://*.sentry.ioin theconnect-srcdirective". Measured:apps/console/index.htmlsets no CSP meta tag, andgit grep -rlni "content-security-policy"over the repo excluding CHANGELOGs returns exactly one file — the doc itself. Rewritten to state the console ships no CSP, and to give theconnect-srca hosting layer would need.VITE_ENVIRONMENTandVITE_ERROR_ENDPOINThad zero read sites anywhere in the tree. Both removed.The source-maps CI note is kept —
sourcemap: falseatapps/console/vite.config.ts:702is still accurate — now with--releasepinned toVITE_SENTRY_RELEASEso uploaded maps match the events.Acceptance criteria
apps/console/docs/error-tracking.md. No changeset (check-changeset-presenceverdict: "No source of a released package changed in this range, so no changeset is owed.")VITE_SENTRY_DSN,VITE_SENTRY_ENABLED,VITE_SENTRY_SEND_DEFAULT_PII,VITE_SENTRY_ENVIRONMENT,VITE_SENTRY_RELEASE,VITE_SENTRY_TRACES_SAMPLE_RATE,VITE_SENTRY_REPLAY,VITE_APP_VERSION,VITE_SERVER_URLin objectui;OS_TELEMETRY_CLIENT_ERROR_REPORTING_ENABLED,OS_CLOUD_URLin objectstack).captureError,setSentryUser,ErrorBoundary) routes throughresolveSentryGate.Verification, at cca3b38
Gate union re-run after the final commit:
check:control-bytesOK (scanned 5451 tracked text file(s); skipped 85 binary)check:doc-fencesevery TypeScript block in 223 document(s) is fenced ts/tsx/typescriptcheck:shell-escape-residueOK (4/4 root(s) resolved ... 0 occurrence(s) outside a fence)check-changeset-presenceNo source of a released package changed in this rangecheck:control-bytesactually contains the edited file in its scan surface — it enumeratesgit ls-files, and the file is tracked (positive control run). The three documentation gates all root atcontent/docs(check:doc-fencesaddspackages/*/README.md) and do not descend intoapps/, so their green is real but says nothing about this file.eslintcannot judge it either: everyfiles:glob ineslint.config.jsis**/*.{ts,tsx}, so markdown is outside eslint entirely and a fullpnpm lintcould not change this verdict. That gap is recorded as #6600 (filed unassigned,finding) — not addressed here, out of scope for this card.This is a prose change to an operator guide with no mechanical checker; the substantive verification is the read-site audit above and the line-by-line check of every claim against
resolveSentryGate,runtime-config.ts,main.tsx,.env.production,vite.config.ts, and the objectstacktelemetry-posture.ts/runtime-config-plugin.ts.Refs: #5522 · PR #5559 · PR #5982 · objectstack#10805 · objectstack PR #11382 · objectstack-ai/cloud#1508
Generated by Claude Code