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
feat(observability): admin-gated per-request Server-Timing via X-OS-Debug-Timing (#2408) (#3163)
* feat(observability): admin-gated per-request Server-Timing via X-OS-Debug-Timing (#2408)
Adds the per-request gating from the perf-tuning design so an operator can pull
a single request's `Server-Timing` breakdown on a live environment without
turning the header on for every user.
Until now perf-tuning was global-only (`serverTiming` option / `OS_SERVER_TIMING`),
which discloses internal phase durations — a mild backend-fingerprinting surface
— to every caller. This wires up the second gating path the issue describes:
- **Disclosure gate** (`@objectstack/observability`): a request-scoped
`AsyncLocalStorage` gate, separate from the pure `PerfTiming` collector so the
collector keeps its "only measures, never decides to emit" invariant. Pinned
to a `Symbol.for` registry key like the collector store so the middleware
(which seeds it) and the dispatcher (which opens it) share one store across
ESM/CJS module copies.
- **Hono middleware**: always registered unless `serverTiming: false`. Runs the
collector when timing is global OR the request carries `X-OS-Debug-Timing: 1`;
emits the header only when the gate is open. Zero collector overhead (one
header read) when neither applies.
- **Dispatcher**: after resolving the execution context, opens the gate for
admin/service/system principals (`isSystem`, `principalKind` service/system,
posture PLATFORM_ADMIN/TENANT_ADMIN). Ordinary callers get no header even if
they send the debug header.
- **Env alias**: `OS_PERF_TIMING=1` now also enables global mode, matching the
issue's naming; `OS_SERVER_TIMING=true` still works.
Tests cover the gate primitive, the middleware's per-request/global/hard-off
paths, and the admin predicate. Existing global-mode behavior is unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011upHdyr5AnNc6dWAu63qxD
* docs(observability): document the admin-gated per-request Server-Timing path (#2408)
Updates the Server-Timing section for the new gating: the global mode
(`serverTiming` / `OS_SERVER_TIMING` / `OS_PERF_TIMING`) plus the per-request
`X-OS-Debug-Timing: 1` path that returns timing only to an admin/service
identity, and the `serverTiming: false` hard-off. Keeps the go-live checklist
in sync.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011upHdyr5AnNc6dWAu63qxD
* chore(changeset): perf-timing per-request gating (#2408)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011upHdyr5AnNc6dWAu63qxD
---------
Co-authored-by: Claude <noreply@anthropic.com>
0 commit comments