@glasstrace/sdk 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/async-context/index.cjs +15005 -0
  2. package/dist/async-context/index.cjs.map +1 -0
  3. package/dist/async-context/index.d.cts +174 -0
  4. package/dist/async-context/index.d.ts +174 -0
  5. package/dist/async-context/index.js +13 -0
  6. package/dist/{capture-error-Dzz7_-v4.d.ts → capture-error-BeuEXXJO.d.cts} +2 -2
  7. package/dist/{capture-error-C95zvSvF.d.cts → capture-error-D02pzB7q.d.ts} +2 -2
  8. package/dist/chunk-CL3OVHPO.js +23 -0
  9. package/dist/chunk-CL3OVHPO.js.map +1 -0
  10. package/dist/{chunk-WL6BXEJ5.js → chunk-DKV53A2C.js} +2 -2
  11. package/dist/{chunk-3PJP5Y3U.js → chunk-GWIEUBFR.js} +3 -3
  12. package/dist/{chunk-H57MQGNU.js → chunk-H6WJ63X2.js} +2 -2
  13. package/dist/{chunk-NN5YCETI.js → chunk-HD6JIFKN.js} +2 -2
  14. package/dist/{chunk-P45NZR4J.js → chunk-JHUNLPSS.js} +35 -1
  15. package/dist/{chunk-P45NZR4J.js.map → chunk-JHUNLPSS.js.map} +1 -1
  16. package/dist/{chunk-UQKI476D.js → chunk-M6EWJCAT.js} +2 -2
  17. package/dist/chunk-QHV7NFON.js +130 -0
  18. package/dist/chunk-QHV7NFON.js.map +1 -0
  19. package/dist/{chunk-M2TLX6NM.js → chunk-QXITSNYM.js} +3 -3
  20. package/dist/chunk-RQ5BIWDT.js +119 -0
  21. package/dist/chunk-RQ5BIWDT.js.map +1 -0
  22. package/dist/{chunk-JJL2M64Z.js → chunk-XEPC4NFL.js} +19 -10
  23. package/dist/chunk-XEPC4NFL.js.map +1 -0
  24. package/dist/cli/init.cjs +4 -4
  25. package/dist/cli/init.cjs.map +1 -1
  26. package/dist/cli/init.js +7 -7
  27. package/dist/cli/mcp-add.cjs +1 -1
  28. package/dist/cli/mcp-add.cjs.map +1 -1
  29. package/dist/cli/mcp-add.js +3 -3
  30. package/dist/cli/uninit.js +3 -3
  31. package/dist/cli/upgrade-instructions.cjs +1 -1
  32. package/dist/cli/upgrade-instructions.js +3 -3
  33. package/dist/cli/validate.cjs.map +1 -1
  34. package/dist/cli/validate.js +2 -2
  35. package/dist/{edge-entry-AWO70gje.d.ts → correlation-id-B_K8adD6.d.ts} +1 -1
  36. package/dist/{edge-entry-DaeG7D7S.d.cts → correlation-id-NAapJ5jn.d.cts} +1 -1
  37. package/dist/edge-entry.cjs +295 -26
  38. package/dist/edge-entry.cjs.map +1 -1
  39. package/dist/edge-entry.d.cts +5 -2
  40. package/dist/edge-entry.d.ts +5 -2
  41. package/dist/edge-entry.js +12 -3
  42. package/dist/index.cjs +55 -5
  43. package/dist/index.cjs.map +1 -1
  44. package/dist/{index.d-Dq33YwFT.d.cts → index.d-CkTf_boH.d.cts} +1 -1
  45. package/dist/{index.d-Dq33YwFT.d.ts → index.d-CkTf_boH.d.ts} +1 -1
  46. package/dist/index.d.cts +7 -4
  47. package/dist/index.d.ts +7 -4
  48. package/dist/index.js +6 -5
  49. package/dist/index.js.map +1 -1
  50. package/dist/middleware/index.cjs +15014 -0
  51. package/dist/middleware/index.cjs.map +1 -0
  52. package/dist/middleware/index.d.cts +183 -0
  53. package/dist/middleware/index.d.ts +183 -0
  54. package/dist/middleware/index.js +13 -0
  55. package/dist/middleware/index.js.map +1 -0
  56. package/dist/node-entry.cjs +55 -5
  57. package/dist/node-entry.cjs.map +1 -1
  58. package/dist/node-entry.d.cts +3 -3
  59. package/dist/node-entry.d.ts +3 -3
  60. package/dist/node-entry.js +8 -7
  61. package/dist/node-subpath.cjs.map +1 -1
  62. package/dist/node-subpath.d.cts +1 -1
  63. package/dist/node-subpath.d.ts +1 -1
  64. package/dist/node-subpath.js +3 -3
  65. package/dist/{source-map-uploader-XFUEVV7I.js → source-map-uploader-MMJ2WCL4.js} +3 -3
  66. package/dist/source-map-uploader-MMJ2WCL4.js.map +1 -0
  67. package/package.json +13 -1
  68. package/dist/chunk-JJL2M64Z.js.map +0 -1
  69. /package/dist/{source-map-uploader-XFUEVV7I.js.map → async-context/index.js.map} +0 -0
  70. /package/dist/{chunk-WL6BXEJ5.js.map → chunk-DKV53A2C.js.map} +0 -0
  71. /package/dist/{chunk-3PJP5Y3U.js.map → chunk-GWIEUBFR.js.map} +0 -0
  72. /package/dist/{chunk-H57MQGNU.js.map → chunk-H6WJ63X2.js.map} +0 -0
  73. /package/dist/{chunk-NN5YCETI.js.map → chunk-HD6JIFKN.js.map} +0 -0
  74. /package/dist/{chunk-UQKI476D.js.map → chunk-M6EWJCAT.js.map} +0 -0
  75. /package/dist/{chunk-M2TLX6NM.js.map → chunk-QXITSNYM.js.map} +0 -0
@@ -0,0 +1,174 @@
1
+ import { AttributeValue } from './common/Attributes';
2
+
3
+ /**
4
+ * Post-response async causality instrumentation for Glasstrace.
5
+ *
6
+ * Subpath: `@glasstrace/sdk/async-context`
7
+ *
8
+ * This module exposes {@link withAsyncCausality}, a continuation-
9
+ * passing wrapper that captures the active OTel `SpanContext` at call
10
+ * time and binds it to a callback. When the callback runs later
11
+ * (Next.js `after()`, queue dispatchers, webhook fire-and-forget),
12
+ * the wrapper opens a span linked to the originating trace via two
13
+ * channels:
14
+ *
15
+ * - An OTel `Link` to the captured `SpanContext` — the OTel-native
16
+ * pointer between two spans in different traces. Surfaces in
17
+ * standard OTel-aware UIs (Jaeger, Honeycomb, etc.) as a
18
+ * "follows from" relationship.
19
+ * - A `glasstrace.causal.post_response_async` attribute carrying
20
+ * the captured trace ID (32-char hex). Used by the product-side
21
+ * trace-summary transform (per DISC-1539's product handoff) to
22
+ * reconstruct ownership without resolving the Link. Two
23
+ * companion booleans
24
+ * (`glasstrace.causal.affects_http_status` and
25
+ * `glasstrace.causal.affects_http_duration`) document that the
26
+ * async work does NOT participate in the root request's outcome.
27
+ *
28
+ * Both channels are emitted together so the SDK is robust to
29
+ * downstream transforms that resolve causality through either form.
30
+ *
31
+ * Edge-runtime safety
32
+ * -------------------
33
+ * The wrapper is included in the SDK's edge bundle
34
+ * (`packages/sdk/src/edge-entry.ts`). Its closure imports only the
35
+ * OTel API, the protocol constants, and the
36
+ * `./optional-lifecycle.js` bridge — none of which reach into
37
+ * `node:*` built-ins or the `process` global. The F003 closure scan
38
+ * (`packages/sdk/scripts/check-edge-bundle.mjs`) enforces this on
39
+ * every build.
40
+ *
41
+ * Strategy: continuation-passing, NOT global ALS propagation
42
+ * ---------------------------------------------------------
43
+ * Per the SDK-046 brief §2.3: ALS continuity across Next.js `after()`
44
+ * is uncertain (the framework may schedule via `queueMicrotask`
45
+ * (preserves ALS) or via cross-tick scheduling (drops ALS)). Relying
46
+ * on ALS would couple the SDK to Next internals. Continuation-passing
47
+ * makes the causality explicit — the user wraps the callback they
48
+ * pass to `after()` / their queue, and the captured `SpanContext`
49
+ * travels with the closure regardless of how the framework schedules
50
+ * it.
51
+ *
52
+ * @module @glasstrace/sdk/async-context
53
+ */
54
+
55
+ /**
56
+ * INTERNAL — clears once-flags for unit tests; not part of the
57
+ * public surface.
58
+ */
59
+ declare function _resetForTesting(): void;
60
+ /**
61
+ * Options for {@link withAsyncCausality}.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * import { withAsyncCausality } from "@glasstrace/sdk/async-context";
66
+ * import { after } from "next/server";
67
+ *
68
+ * export async function POST(req: Request) {
69
+ * const result = await processRequest(req);
70
+ * after(
71
+ * withAsyncCausality(
72
+ * { name: "send-confirmation-email" },
73
+ * async () => sendEmail(result.userId),
74
+ * ),
75
+ * );
76
+ * return Response.json({ ok: true });
77
+ * }
78
+ * ```
79
+ */
80
+ interface WithAsyncCausalityOptions {
81
+ /**
82
+ * Span name for the async work. Required, non-empty string. Used as
83
+ * the OTel span name and appears in trace timelines. Names should
84
+ * be stable across runs (e.g., "send-confirmation-email",
85
+ * "enqueue-webhook-dispatch"); avoid embedding payload data in the
86
+ * name.
87
+ */
88
+ name: string;
89
+ /**
90
+ * Optional attributes attached to the span before the wrapped
91
+ * callback runs. Forwarded to OTel as-is via `span.setAttributes()`.
92
+ * The SDK does not redact, sanitize, or scan values here — callers
93
+ * MUST avoid placing tokens, credentials, or other sensitive data
94
+ * in `attributes`.
95
+ */
96
+ attributes?: Record<string, AttributeValue>;
97
+ }
98
+ /**
99
+ * Capture the active OTel `SpanContext` at call time, bind it to a
100
+ * callback, and return a continuation that will emit a
101
+ * causally-linked span when invoked.
102
+ *
103
+ * The returned continuation:
104
+ *
105
+ * 1. Detects the SDK's registration state. When the OTel API is
106
+ * still on the noop tracer, runs the wrapped callback directly
107
+ * and emits an `async:skipped_uninstalled` lifecycle event (at
108
+ * most once per process). No span is opened.
109
+ * 2. Otherwise opens a span named `options.name` as a NEW root
110
+ * span (not parented to the captured context — `after()` /
111
+ * queue dispatchers run outside the originating request's OTel
112
+ * context, so the async work belongs to a separate trace).
113
+ * 3. When a captured `SpanContext` exists with a valid trace ID,
114
+ * attaches:
115
+ * - an OTel `Link` to that `SpanContext` (the OTel-native
116
+ * form),
117
+ * - the `glasstrace.causal.post_response_async` attribute
118
+ * carrying the trace ID (the transform-readable form),
119
+ * - `glasstrace.causal.affects_http_status = false` and
120
+ * `glasstrace.causal.affects_http_duration = false`
121
+ * documenting that the async work does NOT participate in
122
+ * the root request's outcome.
123
+ * When no valid `SpanContext` was captured, none of these are
124
+ * emitted (per SDK-046's "missing or unknown evidence is
125
+ * preferable to guessed evidence" rule) and an
126
+ * `async:no_originating_context` lifecycle event fires (at
127
+ * most once per process).
128
+ * 4. Awaits the wrapped callback.
129
+ * 5. On a thrown error: normalizes the throwable; sets `ERROR`
130
+ * status with `recordException`; rethrows the original error
131
+ * verbatim.
132
+ * 6. On a successful return: leaves status `UNSET`.
133
+ * 7. Always ends the span.
134
+ *
135
+ * The continuation returns a Promise resolving to the callback's
136
+ * return value (Promise-or-value semantics: a sync callback's value
137
+ * is wrapped in `Promise.resolve()`).
138
+ *
139
+ * @param options - Span name and optional pre-start attributes.
140
+ * @param fn - The async callback to run later. May be sync or async;
141
+ * the wrapper always returns a Promise to give a consistent
142
+ * continuation shape regardless of `fn`'s synchronicity.
143
+ * @returns A continuation `() => Promise<T>` that, when invoked,
144
+ * emits the causally-linked span and runs `fn`.
145
+ *
146
+ * @example Next.js after() — typical use
147
+ * ```ts
148
+ * import { withAsyncCausality } from "@glasstrace/sdk/async-context";
149
+ * import { after } from "next/server";
150
+ *
151
+ * export async function POST(req: Request) {
152
+ * const result = await processRequest(req);
153
+ * after(
154
+ * withAsyncCausality(
155
+ * { name: "send-confirmation-email" },
156
+ * async () => sendEmail(result.userId),
157
+ * ),
158
+ * );
159
+ * return Response.json({ ok: true });
160
+ * }
161
+ * ```
162
+ *
163
+ * @example Queue dispatcher — capture before enqueue
164
+ * ```ts
165
+ * const dispatch = withAsyncCausality(
166
+ * { name: "process-webhook" },
167
+ * async () => handler(payload),
168
+ * );
169
+ * await queue.enqueue(dispatch);
170
+ * ```
171
+ */
172
+ declare function withAsyncCausality<T>(options: WithAsyncCausalityOptions, fn: () => Promise<T> | T): () => Promise<T>;
173
+
174
+ export { type WithAsyncCausalityOptions, _resetForTesting, withAsyncCausality };
@@ -0,0 +1,174 @@
1
+ import { AttributeValue } from './common/Attributes';
2
+
3
+ /**
4
+ * Post-response async causality instrumentation for Glasstrace.
5
+ *
6
+ * Subpath: `@glasstrace/sdk/async-context`
7
+ *
8
+ * This module exposes {@link withAsyncCausality}, a continuation-
9
+ * passing wrapper that captures the active OTel `SpanContext` at call
10
+ * time and binds it to a callback. When the callback runs later
11
+ * (Next.js `after()`, queue dispatchers, webhook fire-and-forget),
12
+ * the wrapper opens a span linked to the originating trace via two
13
+ * channels:
14
+ *
15
+ * - An OTel `Link` to the captured `SpanContext` — the OTel-native
16
+ * pointer between two spans in different traces. Surfaces in
17
+ * standard OTel-aware UIs (Jaeger, Honeycomb, etc.) as a
18
+ * "follows from" relationship.
19
+ * - A `glasstrace.causal.post_response_async` attribute carrying
20
+ * the captured trace ID (32-char hex). Used by the product-side
21
+ * trace-summary transform (per DISC-1539's product handoff) to
22
+ * reconstruct ownership without resolving the Link. Two
23
+ * companion booleans
24
+ * (`glasstrace.causal.affects_http_status` and
25
+ * `glasstrace.causal.affects_http_duration`) document that the
26
+ * async work does NOT participate in the root request's outcome.
27
+ *
28
+ * Both channels are emitted together so the SDK is robust to
29
+ * downstream transforms that resolve causality through either form.
30
+ *
31
+ * Edge-runtime safety
32
+ * -------------------
33
+ * The wrapper is included in the SDK's edge bundle
34
+ * (`packages/sdk/src/edge-entry.ts`). Its closure imports only the
35
+ * OTel API, the protocol constants, and the
36
+ * `./optional-lifecycle.js` bridge — none of which reach into
37
+ * `node:*` built-ins or the `process` global. The F003 closure scan
38
+ * (`packages/sdk/scripts/check-edge-bundle.mjs`) enforces this on
39
+ * every build.
40
+ *
41
+ * Strategy: continuation-passing, NOT global ALS propagation
42
+ * ---------------------------------------------------------
43
+ * Per the SDK-046 brief §2.3: ALS continuity across Next.js `after()`
44
+ * is uncertain (the framework may schedule via `queueMicrotask`
45
+ * (preserves ALS) or via cross-tick scheduling (drops ALS)). Relying
46
+ * on ALS would couple the SDK to Next internals. Continuation-passing
47
+ * makes the causality explicit — the user wraps the callback they
48
+ * pass to `after()` / their queue, and the captured `SpanContext`
49
+ * travels with the closure regardless of how the framework schedules
50
+ * it.
51
+ *
52
+ * @module @glasstrace/sdk/async-context
53
+ */
54
+
55
+ /**
56
+ * INTERNAL — clears once-flags for unit tests; not part of the
57
+ * public surface.
58
+ */
59
+ declare function _resetForTesting(): void;
60
+ /**
61
+ * Options for {@link withAsyncCausality}.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * import { withAsyncCausality } from "@glasstrace/sdk/async-context";
66
+ * import { after } from "next/server";
67
+ *
68
+ * export async function POST(req: Request) {
69
+ * const result = await processRequest(req);
70
+ * after(
71
+ * withAsyncCausality(
72
+ * { name: "send-confirmation-email" },
73
+ * async () => sendEmail(result.userId),
74
+ * ),
75
+ * );
76
+ * return Response.json({ ok: true });
77
+ * }
78
+ * ```
79
+ */
80
+ interface WithAsyncCausalityOptions {
81
+ /**
82
+ * Span name for the async work. Required, non-empty string. Used as
83
+ * the OTel span name and appears in trace timelines. Names should
84
+ * be stable across runs (e.g., "send-confirmation-email",
85
+ * "enqueue-webhook-dispatch"); avoid embedding payload data in the
86
+ * name.
87
+ */
88
+ name: string;
89
+ /**
90
+ * Optional attributes attached to the span before the wrapped
91
+ * callback runs. Forwarded to OTel as-is via `span.setAttributes()`.
92
+ * The SDK does not redact, sanitize, or scan values here — callers
93
+ * MUST avoid placing tokens, credentials, or other sensitive data
94
+ * in `attributes`.
95
+ */
96
+ attributes?: Record<string, AttributeValue>;
97
+ }
98
+ /**
99
+ * Capture the active OTel `SpanContext` at call time, bind it to a
100
+ * callback, and return a continuation that will emit a
101
+ * causally-linked span when invoked.
102
+ *
103
+ * The returned continuation:
104
+ *
105
+ * 1. Detects the SDK's registration state. When the OTel API is
106
+ * still on the noop tracer, runs the wrapped callback directly
107
+ * and emits an `async:skipped_uninstalled` lifecycle event (at
108
+ * most once per process). No span is opened.
109
+ * 2. Otherwise opens a span named `options.name` as a NEW root
110
+ * span (not parented to the captured context — `after()` /
111
+ * queue dispatchers run outside the originating request's OTel
112
+ * context, so the async work belongs to a separate trace).
113
+ * 3. When a captured `SpanContext` exists with a valid trace ID,
114
+ * attaches:
115
+ * - an OTel `Link` to that `SpanContext` (the OTel-native
116
+ * form),
117
+ * - the `glasstrace.causal.post_response_async` attribute
118
+ * carrying the trace ID (the transform-readable form),
119
+ * - `glasstrace.causal.affects_http_status = false` and
120
+ * `glasstrace.causal.affects_http_duration = false`
121
+ * documenting that the async work does NOT participate in
122
+ * the root request's outcome.
123
+ * When no valid `SpanContext` was captured, none of these are
124
+ * emitted (per SDK-046's "missing or unknown evidence is
125
+ * preferable to guessed evidence" rule) and an
126
+ * `async:no_originating_context` lifecycle event fires (at
127
+ * most once per process).
128
+ * 4. Awaits the wrapped callback.
129
+ * 5. On a thrown error: normalizes the throwable; sets `ERROR`
130
+ * status with `recordException`; rethrows the original error
131
+ * verbatim.
132
+ * 6. On a successful return: leaves status `UNSET`.
133
+ * 7. Always ends the span.
134
+ *
135
+ * The continuation returns a Promise resolving to the callback's
136
+ * return value (Promise-or-value semantics: a sync callback's value
137
+ * is wrapped in `Promise.resolve()`).
138
+ *
139
+ * @param options - Span name and optional pre-start attributes.
140
+ * @param fn - The async callback to run later. May be sync or async;
141
+ * the wrapper always returns a Promise to give a consistent
142
+ * continuation shape regardless of `fn`'s synchronicity.
143
+ * @returns A continuation `() => Promise<T>` that, when invoked,
144
+ * emits the causally-linked span and runs `fn`.
145
+ *
146
+ * @example Next.js after() — typical use
147
+ * ```ts
148
+ * import { withAsyncCausality } from "@glasstrace/sdk/async-context";
149
+ * import { after } from "next/server";
150
+ *
151
+ * export async function POST(req: Request) {
152
+ * const result = await processRequest(req);
153
+ * after(
154
+ * withAsyncCausality(
155
+ * { name: "send-confirmation-email" },
156
+ * async () => sendEmail(result.userId),
157
+ * ),
158
+ * );
159
+ * return Response.json({ ok: true });
160
+ * }
161
+ * ```
162
+ *
163
+ * @example Queue dispatcher — capture before enqueue
164
+ * ```ts
165
+ * const dispatch = withAsyncCausality(
166
+ * { name: "process-webhook" },
167
+ * async () => handler(payload),
168
+ * );
169
+ * await queue.enqueue(dispatch);
170
+ * ```
171
+ */
172
+ declare function withAsyncCausality<T>(options: WithAsyncCausalityOptions, fn: () => Promise<T> | T): () => Promise<T>;
173
+
174
+ export { type WithAsyncCausalityOptions, _resetForTesting, withAsyncCausality };
@@ -0,0 +1,13 @@
1
+ import {
2
+ _resetForTesting,
3
+ withAsyncCausality
4
+ } from "../chunk-RQ5BIWDT.js";
5
+ import "../chunk-CL3OVHPO.js";
6
+ import "../chunk-DQ25VOKK.js";
7
+ import "../chunk-JHUNLPSS.js";
8
+ import "../chunk-NSBPE2FW.js";
9
+ export {
10
+ _resetForTesting,
11
+ withAsyncCausality
12
+ };
13
+ //# sourceMappingURL=index.js.map
@@ -1,8 +1,8 @@
1
- import { G as GlasstraceEnvVars, f as GlasstraceOptions, A as AnonApiKey, g as SdkInitResponse, C as CaptureConfig, h as SdkHealthReport, I as ImportGraphPayload, i as SdkDiagnosticCode } from './index.d-Dq33YwFT.js';
1
+ import { G as GlasstraceEnvVars, h as GlasstraceOptions, A as AnonApiKey, i as SdkInitResponse, C as CaptureConfig, j as SdkHealthReport, I as ImportGraphPayload, f as SdkDiagnosticCode } from './index.d-CkTf_boH.cjs';
2
2
  import { ReadableSpan } from './export/ReadableSpan';
3
3
  import { SpanExporter } from './export/SpanExporter';
4
4
  import { ExportResult } from './ExportResult';
5
- import { a as SessionManager } from './edge-entry-AWO70gje.js';
5
+ import { a as SessionManager } from './correlation-id-NAapJ5jn.cjs';
6
6
  import { SpanProcessor } from './SpanProcessor';
7
7
 
8
8
  /**
@@ -1,8 +1,8 @@
1
- import { G as GlasstraceEnvVars, f as GlasstraceOptions, A as AnonApiKey, g as SdkInitResponse, C as CaptureConfig, h as SdkHealthReport, I as ImportGraphPayload, i as SdkDiagnosticCode } from './index.d-Dq33YwFT.cjs';
1
+ import { G as GlasstraceEnvVars, h as GlasstraceOptions, A as AnonApiKey, i as SdkInitResponse, C as CaptureConfig, j as SdkHealthReport, I as ImportGraphPayload, f as SdkDiagnosticCode } from './index.d-CkTf_boH.js';
2
2
  import { ReadableSpan } from './export/ReadableSpan';
3
3
  import { SpanExporter } from './export/SpanExporter';
4
4
  import { ExportResult } from './ExportResult';
5
- import { a as SessionManager } from './edge-entry-DaeG7D7S.cjs';
5
+ import { a as SessionManager } from './correlation-id-B_K8adD6.js';
6
6
  import { SpanProcessor } from './SpanProcessor';
7
7
 
8
8
  /**
@@ -0,0 +1,23 @@
1
+ // src/optional-lifecycle.ts
2
+ var EMIT_BRIDGE = /* @__PURE__ */ Symbol.for("glasstrace.lifecycle.emit-bridge");
3
+ function _registerLifecycleEmitForBridge(emit) {
4
+ try {
5
+ const slot = { emit };
6
+ globalThis[EMIT_BRIDGE] = slot;
7
+ } catch {
8
+ }
9
+ }
10
+ function tryEmitLifecycleEvent(event, payload) {
11
+ try {
12
+ const slot = globalThis[EMIT_BRIDGE];
13
+ if (!slot) return;
14
+ slot.emit(event, payload);
15
+ } catch {
16
+ }
17
+ }
18
+
19
+ export {
20
+ _registerLifecycleEmitForBridge,
21
+ tryEmitLifecycleEvent
22
+ };
23
+ //# sourceMappingURL=chunk-CL3OVHPO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/optional-lifecycle.ts"],"sourcesContent":["/**\n * Edge-safe optional bridge to the SDK lifecycle event emitter.\n *\n * `./lifecycle.ts` imports `node:events` and is therefore excluded from\n * the F003 edge bundle (`packages/sdk/src/edge-entry.ts`,\n * `packages/sdk/scripts/check-edge-bundle.mjs`). Modules that need to\n * emit a lifecycle event AND need to ship in the edge bundle (e.g.,\n * `./middleware/index.ts`, `./async-context/index.ts`) cannot import\n * from `./lifecycle.ts` directly.\n *\n * This module is the bridge:\n *\n * - `lifecycle.ts` (Node-only) calls {@link _registerLifecycleEmitForBridge}\n * inside `initLifecycle()`. The registration writes the typed\n * `emitLifecycleEvent` reference to a `globalThis`-keyed slot.\n * - Edge-safe wrappers call {@link tryEmitLifecycleEvent}, which reads\n * the slot. When unset (edge runtime, or SDK not yet initialized),\n * the call is a clean no-op. When set, the call forwards to the\n * real emitter.\n *\n * This file imports nothing from `node:*` and reads no `process`\n * globals; it is admissible to the edge bundle by the F003 contract.\n *\n * The slot key uses `Symbol.for()` so the bridge survives module\n * re-evaluation (Turbopack HMR rebuilds, Webpack `next dev` rebuilds,\n * vitest module isolation). The same pattern is used by the OTel\n * context-manager guard at `./context-manager.ts:28` and the exporter\n * brand at `./coexistence.ts:31` — all three are per-isolate by V8\n * semantics, which is the correct boundary for this contract (a Node\n * worker thread or `vm.Context` is logically a fresh process).\n *\n * **Why not pass the emitter through the public wrapper API?** The\n * emitter is an internal SDK signal, not a user-facing knob. Keeping\n * it on a global slot rather than as a wrapper option preserves the\n * documented public surface (`tracedRequestMiddleware(options,\n * handler)`) and lets the lifecycle module take ownership of the\n * emit-once / event-key invariants without exposing them.\n */\n\n/** Process-wide brand used to look up the registered emit function. */\nconst EMIT_BRIDGE = Symbol.for(\"glasstrace.lifecycle.emit-bridge\");\n\n/**\n * Type of the registered emit function. Mirrors the signature of\n * `emitLifecycleEvent` from `./lifecycle.ts` but typed as `unknown`\n * here to keep this module free of any cross-import that would couple\n * the edge bundle to `node:events`.\n *\n * The lifecycle module casts to/from this type at the registration\n * site; consumers of {@link tryEmitLifecycleEvent} use the typed\n * overload that re-imposes the `SdkLifecycleEvents` constraint via a\n * second parameter alias.\n */\nexport type LifecycleEmitFn = (\n event: string,\n payload: Record<string, unknown>,\n) => void;\n\ninterface BridgeSlot {\n readonly emit: LifecycleEmitFn;\n}\n\n/**\n * INTERNAL — called by `./lifecycle.ts` during `initLifecycle()` to\n * register the emit function under the global slot. Calling twice is\n * idempotent: the latest registration wins. Never throws.\n */\nexport function _registerLifecycleEmitForBridge(\n emit: LifecycleEmitFn,\n): void {\n try {\n const slot: BridgeSlot = { emit };\n (globalThis as unknown as Record<symbol, BridgeSlot>)[EMIT_BRIDGE] = slot;\n } catch {\n // Defensive: writing to globalThis is observable; some constrained\n // sandboxes freeze it. The bridge falls back to silent no-op.\n }\n}\n\n/**\n * INTERNAL — called by `./lifecycle.ts` during\n * `resetLifecycleForTesting()` to clear the slot so a fresh test gets\n * a clean bridge state.\n */\nexport function _clearLifecycleEmitForBridge(): void {\n try {\n delete (globalThis as unknown as Record<symbol, unknown>)[EMIT_BRIDGE];\n } catch {\n // Defensive: see _registerLifecycleEmitForBridge.\n }\n}\n\n/**\n * Attempt to emit a lifecycle event through the registered bridge.\n *\n * - When the lifecycle module has registered the bridge (Node runtime\n * with `registerGlasstrace()` having run): forwards to\n * `emitLifecycleEvent(event, payload)`.\n * - When the bridge is unset (edge runtime — `lifecycle.ts` not in\n * closure; or pre-`initLifecycle()` race): no-op.\n *\n * Errors thrown by the registered emit function are swallowed —\n * instrumentation must never break a user request hook.\n */\nexport function tryEmitLifecycleEvent(\n event: string,\n payload: Record<string, unknown>,\n): void {\n try {\n const slot = (globalThis as unknown as Record<symbol, BridgeSlot | undefined>)[\n EMIT_BRIDGE\n ];\n if (!slot) return;\n slot.emit(event, payload);\n } catch {\n // Swallow — bridge failures are advisory, not fatal.\n }\n}\n"],"mappings":";AAwCA,IAAM,cAAc,uBAAO,IAAI,kCAAkC;AA2B1D,SAAS,gCACd,MACM;AACN,MAAI;AACF,UAAM,OAAmB,EAAE,KAAK;AAChC,IAAC,WAAqD,WAAW,IAAI;AAAA,EACvE,QAAQ;AAAA,EAGR;AACF;AA2BO,SAAS,sBACd,OACA,SACM;AACN,MAAI;AACF,UAAM,OAAQ,WACZ,WACF;AACA,QAAI,CAAC,KAAM;AACX,SAAK,KAAK,OAAO,OAAO;AAAA,EAC1B,QAAQ;AAAA,EAER;AACF;","names":[]}
@@ -2,7 +2,7 @@ import {
2
2
  AnonApiKeySchema,
3
3
  DevApiKeySchema,
4
4
  createAnonApiKey
5
- } from "./chunk-P45NZR4J.js";
5
+ } from "./chunk-JHUNLPSS.js";
6
6
  import {
7
7
  __require
8
8
  } from "./chunk-NSBPE2FW.js";
@@ -659,4 +659,4 @@ export {
659
659
  writeMcpMarker,
660
660
  refreshGenericMcpConfigAtRuntime
661
661
  };
662
- //# sourceMappingURL=chunk-WL6BXEJ5.js.map
662
+ //# sourceMappingURL=chunk-DKV53A2C.js.map
@@ -5,10 +5,10 @@ import {
5
5
  isDevApiKey,
6
6
  readEnvLocalApiKey,
7
7
  writeAndFsyncTempSync
8
- } from "./chunk-WL6BXEJ5.js";
8
+ } from "./chunk-DKV53A2C.js";
9
9
  import {
10
10
  AnonApiKeySchema
11
- } from "./chunk-P45NZR4J.js";
11
+ } from "./chunk-JHUNLPSS.js";
12
12
  import {
13
13
  NEXT_CONFIG_NAMES
14
14
  } from "./chunk-NB7GJE4S.js";
@@ -917,4 +917,4 @@ export {
917
917
  writeShutdownMarker,
918
918
  runUninit
919
919
  };
920
- //# sourceMappingURL=chunk-3PJP5Y3U.js.map
920
+ //# sourceMappingURL=chunk-GWIEUBFR.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-DQ25VOKK.js";
4
4
  import {
5
5
  GLASSTRACE_ATTRIBUTE_NAMES
6
- } from "./chunk-P45NZR4J.js";
6
+ } from "./chunk-JHUNLPSS.js";
7
7
 
8
8
  // src/errors.ts
9
9
  var SdkError = class extends Error {
@@ -102,4 +102,4 @@ export {
102
102
  GlasstraceSpanProcessor,
103
103
  captureCorrelationId
104
104
  };
105
- //# sourceMappingURL=chunk-H57MQGNU.js.map
105
+ //# sourceMappingURL=chunk-H6WJ63X2.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createBuildHash
3
- } from "./chunk-P45NZR4J.js";
3
+ } from "./chunk-JHUNLPSS.js";
4
4
 
5
5
  // src/import-graph.ts
6
6
  import * as fs from "node:fs/promises";
@@ -175,4 +175,4 @@ export {
175
175
  extractImports,
176
176
  buildImportGraph
177
177
  };
178
- //# sourceMappingURL=chunk-NN5YCETI.js.map
178
+ //# sourceMappingURL=chunk-HD6JIFKN.js.map
@@ -13894,6 +13894,40 @@ var GLASSTRACE_ATTRIBUTE_NAMES = {
13894
13894
  ELEMENT_FINGERPRINT: "glasstrace.element.fingerprint",
13895
13895
  ELEMENT_CONFIDENCE: "glasstrace.element.confidence",
13896
13896
  TAB_ID: "glasstrace.tab.id",
13897
+ // Causal evidence (SDK-046 / DISC-1537 + DISC-1539).
13898
+ //
13899
+ // The SDK emits `glasstrace.causal.*` attributes on spans that
13900
+ // carry instrumentation-time evidence about a span's relationship
13901
+ // to its owning request trace. Two families are defined here:
13902
+ //
13903
+ // - `MIDDLEWARE_FOR_REQUEST` — middleware-ownership marker. Set
13904
+ // on a middleware-only span by `tracedRequestMiddleware()` from
13905
+ // `@glasstrace/sdk/middleware`. Carries the originating
13906
+ // request's normalized path so the product-side trace-summary
13907
+ // transform can link the middleware span to the owning HTTP
13908
+ // request trace even when the middleware runs in an edge
13909
+ // runtime that does not propagate AsyncLocalStorage parents.
13910
+ //
13911
+ // - `POST_RESPONSE_ASYNC` — post-response async marker. Set on a
13912
+ // span emitted from inside `withAsyncCausality()` from
13913
+ // `@glasstrace/sdk/async-context`. Carries the originating
13914
+ // request's trace ID (32-character hex) captured at the call
13915
+ // site so async work scheduled via Next.js `after()`, queues,
13916
+ // or webhooks can be linked back to its originating request.
13917
+ // Companion booleans `CAUSAL_AFFECTS_HTTP_STATUS` /
13918
+ // `CAUSAL_AFFECTS_HTTP_DURATION` document whether the async
13919
+ // work participates in the root request's outcome (default
13920
+ // `false` — non-outcome async work).
13921
+ //
13922
+ // Wire keys live under the `glasstrace.causal.*` namespace so they
13923
+ // are namespace-distinct from `glasstrace.error.*`,
13924
+ // `glasstrace.http.*`, `glasstrace.trpc.*`, and the side-effect
13925
+ // family below. Adding these constants is a `@glasstrace/protocol`
13926
+ // minor bump; existing entries are untouched.
13927
+ CAUSAL_MIDDLEWARE_FOR_REQUEST: "glasstrace.causal.middleware_for_request",
13928
+ CAUSAL_POST_RESPONSE_ASYNC: "glasstrace.causal.post_response_async",
13929
+ CAUSAL_AFFECTS_HTTP_STATUS: "glasstrace.causal.affects_http_status",
13930
+ CAUSAL_AFFECTS_HTTP_DURATION: "glasstrace.causal.affects_http_duration",
13897
13931
  // Side-effect evidence (SDK-049 / SCHEMA-036).
13898
13932
  // Top-level operation attributes attached to the active span when a
13899
13933
  // side-effect is recorded via `recordSideEffect()`. The wire-string
@@ -14258,4 +14292,4 @@ export {
14258
14292
  SIDE_EFFECT_OPERATION_STATUSES,
14259
14293
  SIDE_EFFECT_OPERATION_PHASES
14260
14294
  };
14261
- //# sourceMappingURL=chunk-P45NZR4J.js.map
14295
+ //# sourceMappingURL=chunk-JHUNLPSS.js.map