You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
runtime-config: serve the client error-reporting DSN from the server — platform users consume a prebuilt console and cannot set build-time keys (replaces the just-shipped allowClientErrorReporting boolean) #12681
The shipped two-key gate (objectui #5559 + #5982, this repo's PR #11382) is: build-time VITE_SENTRY_DSNAND runtime telemetry.allowClientErrorReporting. That shape silently assumes the deployer builds the console. ObjectStack's users don't — they consume a prebuilt console, and after #5559 the prebuilt artifact deliberately carries no DSN. Consequence, stated plainly:
A self-hosting operator cannot enable client error reporting at all today — the runtime permission exists, but the source half is compiled-in and absent, and rebuilding the frontend is not a thing platform users do.
The maintainer's own SaaS can work around it (he controls the Vercel build), but only by configuring telemetry in two places (build panel + server env) — two knobs with two silent dead states ("permission on, no DSN" / "DSN in, permission off"), the same shape-class of quiet failure docs(pm-dispatch): 协调模型改版 —— 分诊/执行纵向拆分 + 一人一车道双射 + 登记表正文即真相 + 座位 Routine 化 (#5472) #5522 was about.
Ruled direction, and the shape the standing rules pick
The DSN is served by the operator's server at runtime — the direction is the maintainer's ruling above. The shape follows from the startup-stage no-gradualism rule (no dual paths, no grace windows; the boolean shipped days ago, is in an unreleased changeset, and no deployment consumes it):
/api/v1/runtime/config's telemetry payload carries the source itself: the DSN (plus a closed enumeration of the client knobs that must travel with it — PII opt-in, environment, sample rates — designed as one object, not scattered fields). The DSN's presence IS the grant: no DSN ⇒ reporting off. Fail-closed posture unchanged.
The server's knowledge source is operator env / RuntimeConfigPlugin config (name per repo convention, e.g. OS_TELEMETRY_SENTRY_DSN-shaped; the existing truthy-vocabulary strictness precedent applies — malformed value refused loudly at mount, never coerced).
The allowClientErrorReporting boolean is replaced, not paralleled — remove it in the same change (unreleased changeset superseded per changeset conventions; the content/docs/deployment/environment-variables.mdx row and packages/cloud-connection/README.md move with it, sync-guarded docs updated in the same PR).
objectui half: app-shell's runtime-config consumer reads the DSN object; initSentry() already runs after initRuntimeConfig() (test(service-sms): sms settings provider 表 ↔ transports 双向契约测试 (#5773) #5982 sequenced exactly this), so the delivery point exists. The VITE_SENTRY_DSN build-time source path retires (no-gradualism); the committed-telemetry-endpoint.test.ts ratchet stays — its job (nothing endpoint-shaped in the repo) is unchanged.
CSP note for the dev: the console CSP's connect-src allows https://*.sentry.io; a runtime-delivered DSN on a custom/self-hosted Sentry domain needs the CSP story stated in the docs, not silently broken.
Sequencing
objectui#6599 (in flight) rewrites apps/console/docs/error-tracking.md to describe the current two-key shape — correct to land first; this card updates that doc again to the server-delivered shape as part of its own change. Expected churn, accepted.
⚠️ Contract tier: this changes the accept/reject surface of a public endpoint's payload (/api/v1/runtime/config) — the standing contract-review tiering clause applies to construction and review.
Acceptance
A self-hosting operator enables client error reporting with server-side configuration only — one place, no frontend rebuild; unset ⇒ off, malformed ⇒ loud refusal at mount.
The boolean is gone from code, payload, docs, and pending changeset in the same change; no dual-spelling window.
Both repos' halves land coherently (cross-repo PRs referencing this card); docs (environment-variables.mdx, cloud-connection README, error-tracking.md) describe only the final shape.
Provenance: maintainer, 2026-08-27, PM chat (session
session_01DKWDdUJ2XNRESVVWUvcpnh), reviewing the #5522 (objectui) operating procedure. Verbatim, untranslated:The gap the ruling names
The shipped two-key gate (objectui #5559 + #5982, this repo's PR #11382) is: build-time
VITE_SENTRY_DSNAND runtimetelemetry.allowClientErrorReporting. That shape silently assumes the deployer builds the console. ObjectStack's users don't — they consume a prebuilt console, and after #5559 the prebuilt artifact deliberately carries no DSN. Consequence, stated plainly:Ruled direction, and the shape the standing rules pick
The DSN is served by the operator's server at runtime — the direction is the maintainer's ruling above. The shape follows from the startup-stage no-gradualism rule (no dual paths, no grace windows; the boolean shipped days ago, is in an unreleased changeset, and no deployment consumes it):
/api/v1/runtime/config'stelemetrypayload carries the source itself: the DSN (plus a closed enumeration of the client knobs that must travel with it — PII opt-in, environment, sample rates — designed as one object, not scattered fields). The DSN's presence IS the grant: no DSN ⇒ reporting off. Fail-closed posture unchanged.RuntimeConfigPluginconfig (name per repo convention, e.g.OS_TELEMETRY_SENTRY_DSN-shaped; the existing truthy-vocabulary strictness precedent applies — malformed value refused loudly at mount, never coerced).allowClientErrorReportingboolean is replaced, not paralleled — remove it in the same change (unreleased changeset superseded per changeset conventions; thecontent/docs/deployment/environment-variables.mdxrow andpackages/cloud-connection/README.mdmove with it, sync-guarded docs updated in the same PR).app-shell's runtime-config consumer reads the DSN object;initSentry()already runs afterinitRuntimeConfig()(test(service-sms): sms settings provider 表 ↔ transports 双向契约测试 (#5773) #5982 sequenced exactly this), so the delivery point exists. TheVITE_SENTRY_DSNbuild-time source path retires (no-gradualism); thecommitted-telemetry-endpoint.test.tsratchet stays — its job (nothing endpoint-shaped in the repo) is unchanged.connect-srcallowshttps://*.sentry.io; a runtime-delivered DSN on a custom/self-hosted Sentry domain needs the CSP story stated in the docs, not silently broken.Sequencing
apps/console/docs/error-tracking.mdto describe the current two-key shape — correct to land first; this card updates that doc again to the server-delivered shape as part of its own change. Expected churn, accepted./api/v1/runtime/config) — the standing contract-review tiering clause applies to construction and review.Acceptance
environment-variables.mdx, cloud-connection README, error-tracking.md) describe only the final shape.Refs: objectui#5522 (the saga card, closed by maintainer ruling 2026-08-27) · objectui#5559 · objectui#5982 · #10805 / PR #11382 · objectui#6599.