@glasstrace/sdk 1.15.1 → 1.17.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/README.md +118 -11
  2. package/dist/async-context/index.cjs +21 -2
  3. package/dist/async-context/index.cjs.map +1 -1
  4. package/dist/async-context/index.js +2 -2
  5. package/dist/{capture-error-03qDnC5v.d.cts → capture-error-B0txjNut.d.cts} +2 -2
  6. package/dist/{capture-error-CAfFUyIU.d.ts → capture-error-Dc01rYNR.d.ts} +2 -2
  7. package/dist/{chunk-ZIYT2Y4B.js → chunk-BJOZBAP7.js} +3 -3
  8. package/dist/{chunk-VMK2G6QR.js → chunk-CN5EP25B.js} +2 -2
  9. package/dist/{chunk-HMEHYSTS.js → chunk-EVX6D2TX.js} +2 -2
  10. package/dist/{chunk-T4ETJJSK.js → chunk-F2IPBTDJ.js} +133 -11
  11. package/dist/{chunk-T4ETJJSK.js.map → chunk-F2IPBTDJ.js.map} +1 -1
  12. package/dist/{chunk-XMD5OYD6.js → chunk-M3QGJUEI.js} +2 -2
  13. package/dist/{chunk-7LE2O4ZJ.js → chunk-MKT54VEH.js} +55 -6
  14. package/dist/{chunk-7LE2O4ZJ.js.map → chunk-MKT54VEH.js.map} +1 -1
  15. package/dist/{chunk-MP3QNDXQ.js → chunk-O7IJP2TQ.js} +2 -2
  16. package/dist/{chunk-F7A3QXCT.js → chunk-UOAG72NR.js} +2 -2
  17. package/dist/{chunk-6ST4QV7T.js → chunk-VEQX2YSQ.js} +3 -3
  18. package/dist/{chunk-LQZRGBN5.js → chunk-YKE6HJLW.js} +2 -2
  19. package/dist/cli/init.cjs +18 -5
  20. package/dist/cli/init.cjs.map +1 -1
  21. package/dist/cli/init.js +7 -7
  22. package/dist/cli/mcp-add.cjs +15 -2
  23. package/dist/cli/mcp-add.cjs.map +1 -1
  24. package/dist/cli/mcp-add.js +3 -3
  25. package/dist/cli/uninit.js +3 -3
  26. package/dist/cli/upgrade-instructions.cjs +1 -1
  27. package/dist/cli/upgrade-instructions.js +3 -3
  28. package/dist/cli/validate.cjs +14 -1
  29. package/dist/cli/validate.cjs.map +1 -1
  30. package/dist/cli/validate.js +2 -2
  31. package/dist/{correlation-id-YcfcqOru.d.ts → correlation-id-B9YYmoZw.d.ts} +1 -1
  32. package/dist/{correlation-id-CZ2bstzA.d.cts → correlation-id-CelUvw7j.d.cts} +1 -1
  33. package/dist/edge-entry.cjs +21 -2
  34. package/dist/edge-entry.cjs.map +1 -1
  35. package/dist/edge-entry.d.cts +2 -2
  36. package/dist/edge-entry.d.ts +2 -2
  37. package/dist/edge-entry.js +4 -4
  38. package/dist/import-graph-DBLGNjcI.d.cts +238 -0
  39. package/dist/import-graph-Dka_Fm7j.d.ts +238 -0
  40. package/dist/index.cjs +203 -12
  41. package/dist/index.cjs.map +1 -1
  42. package/dist/{index.d-BQIJ5Dvc.d.cts → index.d-3-cJoY8y.d.cts} +10 -2
  43. package/dist/{index.d-BQIJ5Dvc.d.ts → index.d-3-cJoY8y.d.ts} +10 -2
  44. package/dist/index.d.cts +102 -5
  45. package/dist/index.d.ts +102 -5
  46. package/dist/index.js +30 -5
  47. package/dist/index.js.map +1 -1
  48. package/dist/middleware/index.cjs +21 -2
  49. package/dist/middleware/index.cjs.map +1 -1
  50. package/dist/middleware/index.js +2 -2
  51. package/dist/node-entry.cjs +28 -8
  52. package/dist/node-entry.cjs.map +1 -1
  53. package/dist/node-entry.d.cts +4 -4
  54. package/dist/node-entry.d.ts +4 -4
  55. package/dist/node-entry.js +7 -7
  56. package/dist/node-subpath.cjs +27 -1
  57. package/dist/node-subpath.cjs.map +1 -1
  58. package/dist/node-subpath.d.cts +51 -235
  59. package/dist/node-subpath.d.ts +51 -235
  60. package/dist/node-subpath.js +16 -3
  61. package/dist/node-subpath.js.map +1 -1
  62. package/dist/{source-map-uploader-NUONOEJG.js → source-map-uploader-U7SLSKIZ.js} +3 -3
  63. package/dist/trpc/index.cjs +21 -2
  64. package/dist/trpc/index.cjs.map +1 -1
  65. package/dist/trpc/index.js +1 -1
  66. package/package.json +1 -1
  67. /package/dist/{chunk-ZIYT2Y4B.js.map → chunk-BJOZBAP7.js.map} +0 -0
  68. /package/dist/{chunk-VMK2G6QR.js.map → chunk-CN5EP25B.js.map} +0 -0
  69. /package/dist/{chunk-HMEHYSTS.js.map → chunk-EVX6D2TX.js.map} +0 -0
  70. /package/dist/{chunk-XMD5OYD6.js.map → chunk-M3QGJUEI.js.map} +0 -0
  71. /package/dist/{chunk-MP3QNDXQ.js.map → chunk-O7IJP2TQ.js.map} +0 -0
  72. /package/dist/{chunk-F7A3QXCT.js.map → chunk-UOAG72NR.js.map} +0 -0
  73. /package/dist/{chunk-6ST4QV7T.js.map → chunk-VEQX2YSQ.js.map} +0 -0
  74. /package/dist/{chunk-LQZRGBN5.js.map → chunk-YKE6HJLW.js.map} +0 -0
  75. /package/dist/{source-map-uploader-NUONOEJG.js.map → source-map-uploader-U7SLSKIZ.js.map} +0 -0
@@ -43,6 +43,10 @@ declare const CaptureConfigSchema: z.ZodObject<{
43
43
  consoleErrors: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
44
44
  errorResponseBodies: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
45
45
  sideEffectEvidence: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
46
+ captureFidelity: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
47
+ strict: "strict";
48
+ full: "full";
49
+ }>>>;
46
50
  }, z.core.$strip>;
47
51
  type CaptureConfig = z.infer<typeof CaptureConfigSchema>;
48
52
  /** Developer-facing config for registerGlasstrace(). */
@@ -112,6 +116,10 @@ declare const SdkInitResponseSchema: z.ZodObject<{
112
116
  consoleErrors: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
113
117
  errorResponseBodies: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
114
118
  sideEffectEvidence: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
119
+ captureFidelity: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
120
+ strict: "strict";
121
+ full: "full";
122
+ }>>>;
115
123
  }, z.core.$strip>;
116
124
  subscriptionStatus: z.ZodString;
117
125
  linkedAccountId: z.ZodOptional<z.ZodString>;
@@ -284,7 +292,7 @@ type SideEffectSemanticFieldKey = SideEffectSemanticFieldStableCoreKey | string;
284
292
  * wire. The set is fixed by SCHEMA-036; new reasons require a
285
293
  * coordinated cross-repo bump.
286
294
  */
287
- declare const SIDE_EFFECT_OMISSION_REASONS: readonly ["pii", "secret", "raw_payload", "unsupported_key", "value_too_long", "not_emitted", "capture_disabled"];
295
+ declare const SIDE_EFFECT_OMISSION_REASONS: readonly ["pii", "secret", "raw_payload", "unsupported_key", "value_too_long", "not_emitted", "capture_disabled", "raw_timestamp", "unhashed_id", "non_finite"];
288
296
  /**
289
297
  * One of the allowlisted side-effect omission reasons.
290
298
  *
@@ -316,4 +324,4 @@ declare const SIDE_EFFECT_OPERATION_PHASES: readonly ["request", "post_response"
316
324
  */
317
325
  type SideEffectOperationPhase = (typeof SIDE_EFFECT_OPERATION_PHASES)[number];
318
326
 
319
- export { type AnonApiKey as A, type CaptureConfig as C, type GlasstraceEnvVars as G, type ImportGraphPayload as I, type SideEffectOperationKind as S, type SideEffectOperationStatus as a, type SideEffectOperationPhase as b, type SideEffectSemanticFieldKey as c, deriveSessionId as d, type SideEffectOmissionReason as e, type SideEffectSemanticFieldStableCoreKey as f, type SdkDiagnosticCode as g, type SessionId as h, isSideEffectSemanticFieldKey as i, type GlasstraceOptions as j, type SdkInitResponse as k, type SdkHealthReport as l, type SourceMapUploadResponse as m, type SourceMapManifestResponse as n };
327
+ export { type AnonApiKey as A, type CaptureConfig as C, type GlasstraceEnvVars as G, type ImportGraphPayload as I, type SideEffectOperationKind as S, type SideEffectOperationStatus as a, type SideEffectOperationPhase as b, type SideEffectSemanticFieldKey as c, deriveSessionId as d, type SideEffectOmissionReason as e, type SideEffectSemanticFieldStableCoreKey as f, type SourceMapUploadResponse as g, type SourceMapManifestResponse as h, isSideEffectSemanticFieldKey as i, type SdkDiagnosticCode as j, type SessionId as k, type GlasstraceOptions as l, type SdkInitResponse as m, type SdkHealthReport as n };
@@ -43,6 +43,10 @@ declare const CaptureConfigSchema: z.ZodObject<{
43
43
  consoleErrors: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
44
44
  errorResponseBodies: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
45
45
  sideEffectEvidence: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
46
+ captureFidelity: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
47
+ strict: "strict";
48
+ full: "full";
49
+ }>>>;
46
50
  }, z.core.$strip>;
47
51
  type CaptureConfig = z.infer<typeof CaptureConfigSchema>;
48
52
  /** Developer-facing config for registerGlasstrace(). */
@@ -112,6 +116,10 @@ declare const SdkInitResponseSchema: z.ZodObject<{
112
116
  consoleErrors: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
113
117
  errorResponseBodies: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
114
118
  sideEffectEvidence: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
119
+ captureFidelity: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
120
+ strict: "strict";
121
+ full: "full";
122
+ }>>>;
115
123
  }, z.core.$strip>;
116
124
  subscriptionStatus: z.ZodString;
117
125
  linkedAccountId: z.ZodOptional<z.ZodString>;
@@ -284,7 +292,7 @@ type SideEffectSemanticFieldKey = SideEffectSemanticFieldStableCoreKey | string;
284
292
  * wire. The set is fixed by SCHEMA-036; new reasons require a
285
293
  * coordinated cross-repo bump.
286
294
  */
287
- declare const SIDE_EFFECT_OMISSION_REASONS: readonly ["pii", "secret", "raw_payload", "unsupported_key", "value_too_long", "not_emitted", "capture_disabled"];
295
+ declare const SIDE_EFFECT_OMISSION_REASONS: readonly ["pii", "secret", "raw_payload", "unsupported_key", "value_too_long", "not_emitted", "capture_disabled", "raw_timestamp", "unhashed_id", "non_finite"];
288
296
  /**
289
297
  * One of the allowlisted side-effect omission reasons.
290
298
  *
@@ -316,4 +324,4 @@ declare const SIDE_EFFECT_OPERATION_PHASES: readonly ["request", "post_response"
316
324
  */
317
325
  type SideEffectOperationPhase = (typeof SIDE_EFFECT_OPERATION_PHASES)[number];
318
326
 
319
- export { type AnonApiKey as A, type CaptureConfig as C, type GlasstraceEnvVars as G, type ImportGraphPayload as I, type SideEffectOperationKind as S, type SideEffectOperationStatus as a, type SideEffectOperationPhase as b, type SideEffectSemanticFieldKey as c, deriveSessionId as d, type SideEffectOmissionReason as e, type SideEffectSemanticFieldStableCoreKey as f, type SdkDiagnosticCode as g, type SessionId as h, isSideEffectSemanticFieldKey as i, type GlasstraceOptions as j, type SdkInitResponse as k, type SdkHealthReport as l, type SourceMapUploadResponse as m, type SourceMapManifestResponse as n };
327
+ export { type AnonApiKey as A, type CaptureConfig as C, type GlasstraceEnvVars as G, type ImportGraphPayload as I, type SideEffectOperationKind as S, type SideEffectOperationStatus as a, type SideEffectOperationPhase as b, type SideEffectSemanticFieldKey as c, deriveSessionId as d, type SideEffectOmissionReason as e, type SideEffectSemanticFieldStableCoreKey as f, type SourceMapUploadResponse as g, type SourceMapManifestResponse as h, isSideEffectSemanticFieldKey as i, type SdkDiagnosticCode as j, type SessionId as k, type GlasstraceOptions as l, type SdkInitResponse as m, type SdkHealthReport as n };
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
- export { C as CorrelationIdRequest, G as GlasstraceSpanProcessor, S as SdkError, a as SessionManager, c as captureCorrelationId, g as getDateString, b as getOrigin } from './correlation-id-CZ2bstzA.cjs';
2
- export { F as FetchTarget, G as GlasstraceExporter, a as GlasstraceExporterOptions, I as InitClaimResult, R as ResolvedConfig, c as captureError, b as classifyFetchTarget, d as createGlasstraceSpanProcessor, g as getActiveConfig, e as getDiscoveryHandler, f as getLinkedAccountId, h as getOrCreateAnonKey, i as getStatus, j as isAnonymousMode, k as isProductionDisabled, l as isReady, m as loadCachedConfig, p as performInit, r as readAnonKey, n as readEnvVars, o as registerGlasstrace, q as resolveConfig, s as saveCachedConfig, t as sendInitRequest, w as waitForReady, u as withGlasstraceConfig } from './capture-error-03qDnC5v.cjs';
3
- import { S as SideEffectOperationKind, a as SideEffectOperationStatus, b as SideEffectOperationPhase, c as SideEffectSemanticFieldKey } from './index.d-BQIJ5Dvc.cjs';
4
- export { e as SideEffectOmissionReason, f as SideEffectSemanticFieldStableCoreKey, d as deriveSessionId, i as isSideEffectSemanticFieldKey } from './index.d-BQIJ5Dvc.cjs';
1
+ export { C as CorrelationIdRequest, G as GlasstraceSpanProcessor, S as SdkError, a as SessionManager, c as captureCorrelationId, g as getDateString, b as getOrigin } from './correlation-id-CelUvw7j.cjs';
2
+ export { F as FetchTarget, G as GlasstraceExporter, a as GlasstraceExporterOptions, I as InitClaimResult, R as ResolvedConfig, c as captureError, b as classifyFetchTarget, d as createGlasstraceSpanProcessor, g as getActiveConfig, e as getDiscoveryHandler, f as getLinkedAccountId, h as getOrCreateAnonKey, i as getStatus, j as isAnonymousMode, k as isProductionDisabled, l as isReady, m as loadCachedConfig, p as performInit, r as readAnonKey, n as readEnvVars, o as registerGlasstrace, q as resolveConfig, s as saveCachedConfig, t as sendInitRequest, w as waitForReady, u as withGlasstraceConfig } from './capture-error-B0txjNut.cjs';
3
+ import { S as SideEffectOperationKind, a as SideEffectOperationStatus, b as SideEffectOperationPhase, c as SideEffectSemanticFieldKey } from './index.d-3-cJoY8y.cjs';
4
+ export { e as SideEffectOmissionReason, f as SideEffectSemanticFieldStableCoreKey, d as deriveSessionId, i as isSideEffectSemanticFieldKey } from './index.d-3-cJoY8y.cjs';
5
5
  export { RequestMiddlewareFunction, TracedRequestMiddlewareOptions } from './middleware/index.cjs';
6
6
  export { WithAsyncCausalityOptions } from './async-context/index.cjs';
7
7
  import './export/ReadableSpan';
@@ -71,6 +71,39 @@ interface RecordSideEffectInput {
71
71
  * omission counter.
72
72
  */
73
73
  fields?: Partial<Record<SideEffectSemanticFieldKey, string>>;
74
+ /**
75
+ * Optional value-fidelity scalars emitted on the off-summary
76
+ * `glasstrace.side_effect.scalar.*` channel. Keys must be camelCase
77
+ * ending in `Ms` / `Amount` / `Bytes` / `Ratio` / `Id` / `Value` /
78
+ * `Flag` (`Count` routes to the categorical `fields` channel instead).
79
+ * Values are native `number` / `boolean` / `string`.
80
+ *
81
+ * Under the default `strict` capture posture the SDK rejects raw
82
+ * wall-clock timestamps (a `Date`, or a raw epoch on a `*Ms` key) and
83
+ * unhashed `*Id` values at emit time — send bounded deltas as numbers,
84
+ * and pre-hash identifiers with `hashId` (`@glasstrace/sdk/node`). At
85
+ * most
86
+ * {@link MAX_SIDE_EFFECT_SCALARS_PER_OPERATION} scalars are recorded
87
+ * per call; rejected values route to the matching omission counter and
88
+ * the raw value never reaches the wire. The same key may also appear
89
+ * in `fields` — the two channels are distinct (selected by attribute
90
+ * prefix), so a categorical and a scalar facet can share a name.
91
+ */
92
+ scalars?: Record<string, unknown>;
93
+ /**
94
+ * Optional producer-asserted boolean relations (invariants) emitted on
95
+ * the categorical field channel. Keys must be camelCase ending in
96
+ * `Holds` (e.g. `timezonePreservedHolds`); values are real `boolean`s,
97
+ * coerced to `"true"`/`"false"` on the wire. A non-`Holds` key, a
98
+ * non-boolean value, or a key already attached by `fields` (a
99
+ * same-channel collision — `fields` wins) is dropped with the matching
100
+ * omission counter. Relations count against the same product-side
101
+ * per-operation field budget as `fields` (enforced at projection).
102
+ *
103
+ * Use {@link invariant} / {@link isNullInvariant} to compute the
104
+ * boolean from a comparison.
105
+ */
106
+ relations?: Record<string, boolean>;
74
107
  }
75
108
  /**
76
109
  * Record allowlisted side-effect evidence on the current active OTel
@@ -114,9 +147,73 @@ interface RecordSideEffectInput {
114
147
  * locale: "en-US",
115
148
  * timezone: "Europe/Paris",
116
149
  * },
150
+ * scalars: {
151
+ * // Bounded delta (not a wall-clock epoch) and a boolean flag.
152
+ * renderMs: 42,
153
+ * hadAttachmentFlag: false,
154
+ * },
117
155
  * });
118
156
  * ```
119
157
  */
120
158
  declare function recordSideEffect(input: RecordSideEffectInput): void;
121
159
 
122
- export { type RecordSideEffectInput, SideEffectOperationKind, SideEffectOperationPhase, SideEffectOperationStatus, SideEffectSemanticFieldKey, recordSideEffect };
160
+ /**
161
+ * Producer-sugar for computing boolean relations to emit as `*Holds`
162
+ * side-effect evidence.
163
+ *
164
+ * These helpers turn a comparison into the boolean a producer passes to
165
+ * `recordSideEffect({ relations: { …Holds: invariant(a, "eq", b) } })`.
166
+ * They are pure (no I/O, no Node built-ins) and edge-safe, so they live
167
+ * on the root barrel. The operator set is intentionally minimal and
168
+ * fixed — six binary comparisons plus a separate unary null check — and
169
+ * is not a general expression DSL.
170
+ */
171
+ /**
172
+ * The six supported binary comparison operators. `isNull` is **not** an
173
+ * operator here — use {@link isNullInvariant} for the unary case.
174
+ */
175
+ type InvariantOp = "eq" | "neq" | "lt" | "lte" | "gt" | "gte";
176
+ /**
177
+ * Evaluate a binary comparison invariant and return the boolean result.
178
+ *
179
+ * Both operands are constrained to the same primitive type. `eq`/`neq`
180
+ * use strict equality; the ordering operators (`lt`/`lte`/`gt`/`gte`)
181
+ * use the language relational operators (numeric for numbers/bigints,
182
+ * lexical for strings). Intended for producing a `*Holds` relation, e.g.
183
+ * `invariant(emittedDurationMinutes, "eq", declaredDurationMinutes)`.
184
+ *
185
+ * Operands should be comparable primitives. `NaN` follows IEEE-754
186
+ * (unequal to everything; all orderings `false`), so screen `NaN` before
187
+ * asserting a relation. Passing a non-primitive (e.g. a `Symbol`, or an
188
+ * object with a throwing `valueOf`) to an ordering operator throws per
189
+ * JS semantics — the type signature prevents this for typed callers.
190
+ *
191
+ * @param left - The left operand.
192
+ * @param op - One of the six {@link InvariantOp} comparisons.
193
+ * @param right - The right operand (same primitive type as `left`).
194
+ * @returns The boolean result of `left <op> right`.
195
+ *
196
+ * @example
197
+ * recordSideEffect({
198
+ * kind: "calendar_link",
199
+ * operation: "invite.create",
200
+ * relations: {
201
+ * durationMatchesHolds: invariant(emittedMinutes, "eq", declaredMinutes),
202
+ * },
203
+ * });
204
+ */
205
+ declare function invariant<T extends number | string | bigint | boolean>(left: T, op: InvariantOp, right: T): boolean;
206
+ /**
207
+ * Unary null/undefined invariant — `true` when `value` is `null` or
208
+ * `undefined`. Kept separate from {@link invariant} because nullishness
209
+ * is a unary predicate, not a binary comparison (there is no `isNull`
210
+ * operator). Use for a `*Holds` relation asserting a value's absence,
211
+ * e.g. `relations: { recipientMissingHolds: isNullInvariant(recipient) }`.
212
+ *
213
+ * @param value - The value to test.
214
+ * @returns `true` when `value` is `null` or `undefined`, else `false`
215
+ * (falsy-but-present values like `0`, `""`, `false`, `NaN` are `false`).
216
+ */
217
+ declare function isNullInvariant(value: unknown): boolean;
218
+
219
+ export { type InvariantOp, type RecordSideEffectInput, SideEffectOperationKind, SideEffectOperationPhase, SideEffectOperationStatus, SideEffectSemanticFieldKey, invariant, isNullInvariant, recordSideEffect };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export { C as CorrelationIdRequest, G as GlasstraceSpanProcessor, S as SdkError, a as SessionManager, c as captureCorrelationId, g as getDateString, b as getOrigin } from './correlation-id-YcfcqOru.js';
2
- export { F as FetchTarget, G as GlasstraceExporter, a as GlasstraceExporterOptions, I as InitClaimResult, R as ResolvedConfig, c as captureError, b as classifyFetchTarget, d as createGlasstraceSpanProcessor, g as getActiveConfig, e as getDiscoveryHandler, f as getLinkedAccountId, h as getOrCreateAnonKey, i as getStatus, j as isAnonymousMode, k as isProductionDisabled, l as isReady, m as loadCachedConfig, p as performInit, r as readAnonKey, n as readEnvVars, o as registerGlasstrace, q as resolveConfig, s as saveCachedConfig, t as sendInitRequest, w as waitForReady, u as withGlasstraceConfig } from './capture-error-CAfFUyIU.js';
3
- import { S as SideEffectOperationKind, a as SideEffectOperationStatus, b as SideEffectOperationPhase, c as SideEffectSemanticFieldKey } from './index.d-BQIJ5Dvc.js';
4
- export { e as SideEffectOmissionReason, f as SideEffectSemanticFieldStableCoreKey, d as deriveSessionId, i as isSideEffectSemanticFieldKey } from './index.d-BQIJ5Dvc.js';
1
+ export { C as CorrelationIdRequest, G as GlasstraceSpanProcessor, S as SdkError, a as SessionManager, c as captureCorrelationId, g as getDateString, b as getOrigin } from './correlation-id-B9YYmoZw.js';
2
+ export { F as FetchTarget, G as GlasstraceExporter, a as GlasstraceExporterOptions, I as InitClaimResult, R as ResolvedConfig, c as captureError, b as classifyFetchTarget, d as createGlasstraceSpanProcessor, g as getActiveConfig, e as getDiscoveryHandler, f as getLinkedAccountId, h as getOrCreateAnonKey, i as getStatus, j as isAnonymousMode, k as isProductionDisabled, l as isReady, m as loadCachedConfig, p as performInit, r as readAnonKey, n as readEnvVars, o as registerGlasstrace, q as resolveConfig, s as saveCachedConfig, t as sendInitRequest, w as waitForReady, u as withGlasstraceConfig } from './capture-error-Dc01rYNR.js';
3
+ import { S as SideEffectOperationKind, a as SideEffectOperationStatus, b as SideEffectOperationPhase, c as SideEffectSemanticFieldKey } from './index.d-3-cJoY8y.js';
4
+ export { e as SideEffectOmissionReason, f as SideEffectSemanticFieldStableCoreKey, d as deriveSessionId, i as isSideEffectSemanticFieldKey } from './index.d-3-cJoY8y.js';
5
5
  export { RequestMiddlewareFunction, TracedRequestMiddlewareOptions } from './middleware/index.js';
6
6
  export { WithAsyncCausalityOptions } from './async-context/index.js';
7
7
  import './export/ReadableSpan';
@@ -71,6 +71,39 @@ interface RecordSideEffectInput {
71
71
  * omission counter.
72
72
  */
73
73
  fields?: Partial<Record<SideEffectSemanticFieldKey, string>>;
74
+ /**
75
+ * Optional value-fidelity scalars emitted on the off-summary
76
+ * `glasstrace.side_effect.scalar.*` channel. Keys must be camelCase
77
+ * ending in `Ms` / `Amount` / `Bytes` / `Ratio` / `Id` / `Value` /
78
+ * `Flag` (`Count` routes to the categorical `fields` channel instead).
79
+ * Values are native `number` / `boolean` / `string`.
80
+ *
81
+ * Under the default `strict` capture posture the SDK rejects raw
82
+ * wall-clock timestamps (a `Date`, or a raw epoch on a `*Ms` key) and
83
+ * unhashed `*Id` values at emit time — send bounded deltas as numbers,
84
+ * and pre-hash identifiers with `hashId` (`@glasstrace/sdk/node`). At
85
+ * most
86
+ * {@link MAX_SIDE_EFFECT_SCALARS_PER_OPERATION} scalars are recorded
87
+ * per call; rejected values route to the matching omission counter and
88
+ * the raw value never reaches the wire. The same key may also appear
89
+ * in `fields` — the two channels are distinct (selected by attribute
90
+ * prefix), so a categorical and a scalar facet can share a name.
91
+ */
92
+ scalars?: Record<string, unknown>;
93
+ /**
94
+ * Optional producer-asserted boolean relations (invariants) emitted on
95
+ * the categorical field channel. Keys must be camelCase ending in
96
+ * `Holds` (e.g. `timezonePreservedHolds`); values are real `boolean`s,
97
+ * coerced to `"true"`/`"false"` on the wire. A non-`Holds` key, a
98
+ * non-boolean value, or a key already attached by `fields` (a
99
+ * same-channel collision — `fields` wins) is dropped with the matching
100
+ * omission counter. Relations count against the same product-side
101
+ * per-operation field budget as `fields` (enforced at projection).
102
+ *
103
+ * Use {@link invariant} / {@link isNullInvariant} to compute the
104
+ * boolean from a comparison.
105
+ */
106
+ relations?: Record<string, boolean>;
74
107
  }
75
108
  /**
76
109
  * Record allowlisted side-effect evidence on the current active OTel
@@ -114,9 +147,73 @@ interface RecordSideEffectInput {
114
147
  * locale: "en-US",
115
148
  * timezone: "Europe/Paris",
116
149
  * },
150
+ * scalars: {
151
+ * // Bounded delta (not a wall-clock epoch) and a boolean flag.
152
+ * renderMs: 42,
153
+ * hadAttachmentFlag: false,
154
+ * },
117
155
  * });
118
156
  * ```
119
157
  */
120
158
  declare function recordSideEffect(input: RecordSideEffectInput): void;
121
159
 
122
- export { type RecordSideEffectInput, SideEffectOperationKind, SideEffectOperationPhase, SideEffectOperationStatus, SideEffectSemanticFieldKey, recordSideEffect };
160
+ /**
161
+ * Producer-sugar for computing boolean relations to emit as `*Holds`
162
+ * side-effect evidence.
163
+ *
164
+ * These helpers turn a comparison into the boolean a producer passes to
165
+ * `recordSideEffect({ relations: { …Holds: invariant(a, "eq", b) } })`.
166
+ * They are pure (no I/O, no Node built-ins) and edge-safe, so they live
167
+ * on the root barrel. The operator set is intentionally minimal and
168
+ * fixed — six binary comparisons plus a separate unary null check — and
169
+ * is not a general expression DSL.
170
+ */
171
+ /**
172
+ * The six supported binary comparison operators. `isNull` is **not** an
173
+ * operator here — use {@link isNullInvariant} for the unary case.
174
+ */
175
+ type InvariantOp = "eq" | "neq" | "lt" | "lte" | "gt" | "gte";
176
+ /**
177
+ * Evaluate a binary comparison invariant and return the boolean result.
178
+ *
179
+ * Both operands are constrained to the same primitive type. `eq`/`neq`
180
+ * use strict equality; the ordering operators (`lt`/`lte`/`gt`/`gte`)
181
+ * use the language relational operators (numeric for numbers/bigints,
182
+ * lexical for strings). Intended for producing a `*Holds` relation, e.g.
183
+ * `invariant(emittedDurationMinutes, "eq", declaredDurationMinutes)`.
184
+ *
185
+ * Operands should be comparable primitives. `NaN` follows IEEE-754
186
+ * (unequal to everything; all orderings `false`), so screen `NaN` before
187
+ * asserting a relation. Passing a non-primitive (e.g. a `Symbol`, or an
188
+ * object with a throwing `valueOf`) to an ordering operator throws per
189
+ * JS semantics — the type signature prevents this for typed callers.
190
+ *
191
+ * @param left - The left operand.
192
+ * @param op - One of the six {@link InvariantOp} comparisons.
193
+ * @param right - The right operand (same primitive type as `left`).
194
+ * @returns The boolean result of `left <op> right`.
195
+ *
196
+ * @example
197
+ * recordSideEffect({
198
+ * kind: "calendar_link",
199
+ * operation: "invite.create",
200
+ * relations: {
201
+ * durationMatchesHolds: invariant(emittedMinutes, "eq", declaredMinutes),
202
+ * },
203
+ * });
204
+ */
205
+ declare function invariant<T extends number | string | bigint | boolean>(left: T, op: InvariantOp, right: T): boolean;
206
+ /**
207
+ * Unary null/undefined invariant — `true` when `value` is `null` or
208
+ * `undefined`. Kept separate from {@link invariant} because nullishness
209
+ * is a unary predicate, not a binary comparison (there is no `isNull`
210
+ * operator). Use for a `*Holds` relation asserting a value's absence,
211
+ * e.g. `relations: { recipientMissingHolds: isNullInvariant(recipient) }`.
212
+ *
213
+ * @param value - The value to test.
214
+ * @returns `true` when `value` is `null` or `undefined`, else `false`
215
+ * (falsy-but-present values like `0`, `""`, `false`, `NaN` are `false`).
216
+ */
217
+ declare function isNullInvariant(value: unknown): boolean;
218
+
219
+ export { type InvariantOp, type RecordSideEffectInput, SideEffectOperationKind, SideEffectOperationPhase, SideEffectOperationStatus, SideEffectSemanticFieldKey, invariant, isNullInvariant, recordSideEffect };
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  recordSideEffect,
11
11
  registerGlasstrace,
12
12
  withGlasstraceConfig
13
- } from "./chunk-T4ETJJSK.js";
13
+ } from "./chunk-F2IPBTDJ.js";
14
14
  import {
15
15
  getStatus,
16
16
  isReady,
@@ -20,7 +20,7 @@ import {
20
20
  GlasstraceSpanProcessor,
21
21
  SdkError,
22
22
  captureCorrelationId
23
- } from "./chunk-HMEHYSTS.js";
23
+ } from "./chunk-EVX6D2TX.js";
24
24
  import "./chunk-CL3OVHPO.js";
25
25
  import "./chunk-DQ25VOKK.js";
26
26
  import "./chunk-YG3X7TUI.js";
@@ -31,7 +31,7 @@ import {
31
31
  performInit,
32
32
  saveCachedConfig,
33
33
  sendInitRequest
34
- } from "./chunk-6ST4QV7T.js";
34
+ } from "./chunk-VEQX2YSQ.js";
35
35
  import {
36
36
  isAnonymousMode,
37
37
  isProductionDisabled,
@@ -41,13 +41,36 @@ import {
41
41
  import {
42
42
  getOrCreateAnonKey,
43
43
  readAnonKey
44
- } from "./chunk-F7A3QXCT.js";
44
+ } from "./chunk-UOAG72NR.js";
45
45
  import {
46
46
  deriveSessionId,
47
47
  isSideEffectSemanticFieldKey
48
- } from "./chunk-7LE2O4ZJ.js";
48
+ } from "./chunk-MKT54VEH.js";
49
49
  import "./chunk-YIEXKQYP.js";
50
50
  import "./chunk-NSBPE2FW.js";
51
+
52
+ // src/side-effect/invariant.ts
53
+ function invariant(left, op, right) {
54
+ switch (op) {
55
+ case "eq":
56
+ return left === right;
57
+ case "neq":
58
+ return left !== right;
59
+ case "lt":
60
+ return left < right;
61
+ case "lte":
62
+ return left <= right;
63
+ case "gt":
64
+ return left > right;
65
+ case "gte":
66
+ return left >= right;
67
+ }
68
+ op;
69
+ return false;
70
+ }
71
+ function isNullInvariant(value) {
72
+ return value === null || value === void 0;
73
+ }
51
74
  export {
52
75
  GlasstraceExporter,
53
76
  GlasstraceSpanProcessor,
@@ -65,7 +88,9 @@ export {
65
88
  getOrCreateAnonKey,
66
89
  getOrigin,
67
90
  getStatus,
91
+ invariant,
68
92
  isAnonymousMode,
93
+ isNullInvariant,
69
94
  isProductionDisabled,
70
95
  isReady,
71
96
  isSideEffectSemanticFieldKey,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"sources":["../src/side-effect/invariant.ts"],"sourcesContent":["/**\n * Producer-sugar for computing boolean relations to emit as `*Holds`\n * side-effect evidence.\n *\n * These helpers turn a comparison into the boolean a producer passes to\n * `recordSideEffect({ relations: { …Holds: invariant(a, \"eq\", b) } })`.\n * They are pure (no I/O, no Node built-ins) and edge-safe, so they live\n * on the root barrel. The operator set is intentionally minimal and\n * fixed — six binary comparisons plus a separate unary null check — and\n * is not a general expression DSL.\n */\n\n/**\n * The six supported binary comparison operators. `isNull` is **not** an\n * operator here — use {@link isNullInvariant} for the unary case.\n */\nexport type InvariantOp = \"eq\" | \"neq\" | \"lt\" | \"lte\" | \"gt\" | \"gte\";\n\n/**\n * Evaluate a binary comparison invariant and return the boolean result.\n *\n * Both operands are constrained to the same primitive type. `eq`/`neq`\n * use strict equality; the ordering operators (`lt`/`lte`/`gt`/`gte`)\n * use the language relational operators (numeric for numbers/bigints,\n * lexical for strings). Intended for producing a `*Holds` relation, e.g.\n * `invariant(emittedDurationMinutes, \"eq\", declaredDurationMinutes)`.\n *\n * Operands should be comparable primitives. `NaN` follows IEEE-754\n * (unequal to everything; all orderings `false`), so screen `NaN` before\n * asserting a relation. Passing a non-primitive (e.g. a `Symbol`, or an\n * object with a throwing `valueOf`) to an ordering operator throws per\n * JS semantics — the type signature prevents this for typed callers.\n *\n * @param left - The left operand.\n * @param op - One of the six {@link InvariantOp} comparisons.\n * @param right - The right operand (same primitive type as `left`).\n * @returns The boolean result of `left <op> right`.\n *\n * @example\n * recordSideEffect({\n * kind: \"calendar_link\",\n * operation: \"invite.create\",\n * relations: {\n * durationMatchesHolds: invariant(emittedMinutes, \"eq\", declaredMinutes),\n * },\n * });\n */\nexport function invariant<T extends number | string | bigint | boolean>(\n left: T,\n op: InvariantOp,\n right: T,\n): boolean {\n switch (op) {\n case \"eq\":\n return left === right;\n case \"neq\":\n return left !== right;\n case \"lt\":\n return left < right;\n case \"lte\":\n return left <= right;\n case \"gt\":\n return left > right;\n case \"gte\":\n return left >= right;\n }\n // For well-typed callers `op` is `never` here, so this `satisfies`\n // enforces switch exhaustiveness at compile time (adding an\n // `InvariantOp` member without a case is a type error). The `return`\n // is the runtime fallback for an untyped (JS) caller passing an\n // out-of-domain op — it yields a `boolean`, never `undefined`.\n op satisfies never;\n return false;\n}\n\n/**\n * Unary null/undefined invariant — `true` when `value` is `null` or\n * `undefined`. Kept separate from {@link invariant} because nullishness\n * is a unary predicate, not a binary comparison (there is no `isNull`\n * operator). Use for a `*Holds` relation asserting a value's absence,\n * e.g. `relations: { recipientMissingHolds: isNullInvariant(recipient) }`.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is `null` or `undefined`, else `false`\n * (falsy-but-present values like `0`, `\"\"`, `false`, `NaN` are `false`).\n */\nexport function isNullInvariant(value: unknown): boolean {\n return value === null || value === undefined;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CO,SAAS,UACd,MACA,IACA,OACS;AACT,UAAQ,IAAI;AAAA,IACV,KAAK;AACH,aAAO,SAAS;AAAA,IAClB,KAAK;AACH,aAAO,SAAS;AAAA,IAClB,KAAK;AACH,aAAO,OAAO;AAAA,IAChB,KAAK;AACH,aAAO,QAAQ;AAAA,IACjB,KAAK;AACH,aAAO,OAAO;AAAA,IAChB,KAAK;AACH,aAAO,QAAQ;AAAA,EACnB;AAMA;AACA,SAAO;AACT;AAaO,SAAS,gBAAgB,OAAyB;AACvD,SAAO,UAAU,QAAQ,UAAU;AACrC;","names":[]}
@@ -15294,7 +15294,20 @@ var CaptureConfigSchema = external_exports.object({
15294
15294
  * client-side allowlist enforcement layered with the product's
15295
15295
  * storage-time filter as defense-in-depth.
15296
15296
  */
15297
- sideEffectEvidence: external_exports.boolean().optional().default(false)
15297
+ sideEffectEvidence: external_exports.boolean().optional().default(false),
15298
+ /**
15299
+ * Per-account value-fidelity capture posture (server-pushed).
15300
+ *
15301
+ * `strict` (default) is fail-closed: the SDK rejects raw wall-clock
15302
+ * timestamps and unhashed identifiers from the `scalar.*` channel at
15303
+ * emit time. `full` relaxes those rejections so raw magnitudes can be
15304
+ * surfaced — but only in conjunction with an explicit producer opt-in
15305
+ * (so a `full`-configured account still emits strict-shaped scalars
15306
+ * unless the producer also opts in). The operator owns this flag; it
15307
+ * is never derived from producer or request input. Absent on the wire
15308
+ * ⇒ `strict`.
15309
+ */
15310
+ captureFidelity: external_exports.enum(["strict", "full"]).optional().default("strict")
15298
15311
  });
15299
15312
  var SdkCachedConfigSchema = external_exports.object({
15300
15313
  response: external_exports.record(external_exports.string(), external_exports.unknown()),
@@ -15485,7 +15498,13 @@ var GLASSTRACE_ATTRIBUTE_NAMES = {
15485
15498
  SIDE_EFFECT_OMITTED_UNSUPPORTED_KEY: "glasstrace.side_effect.omitted.unsupported_key",
15486
15499
  SIDE_EFFECT_OMITTED_VALUE_TOO_LONG: "glasstrace.side_effect.omitted.value_too_long",
15487
15500
  SIDE_EFFECT_OMITTED_NOT_EMITTED: "glasstrace.side_effect.omitted.not_emitted",
15488
- SIDE_EFFECT_OMITTED_CAPTURE_DISABLED: "glasstrace.side_effect.omitted.capture_disabled"
15501
+ SIDE_EFFECT_OMITTED_CAPTURE_DISABLED: "glasstrace.side_effect.omitted.capture_disabled",
15502
+ // Value-fidelity scalar-channel omission reasons. Counts only; the
15503
+ // rejected raw value (timestamp, unhashed id, non-finite number) is
15504
+ // never echoed. Mirror the product omission enum verbatim.
15505
+ SIDE_EFFECT_OMITTED_RAW_TIMESTAMP: "glasstrace.side_effect.omitted.raw_timestamp",
15506
+ SIDE_EFFECT_OMITTED_UNHASHED_ID: "glasstrace.side_effect.omitted.unhashed_id",
15507
+ SIDE_EFFECT_OMITTED_NON_FINITE: "glasstrace.side_effect.omitted.non_finite"
15489
15508
  };
15490
15509
  var MAX_SOURCE_MAP_FILE_PATH_LENGTH = 512;
15491
15510
  var MAX_SOURCE_MAP_FILE_SIZE = 50 * 1024 * 1024;