autotel-schema 10.0.0 → 11.0.1

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.
package/dist/cli.cjs CHANGED
@@ -27,7 +27,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  }) : target, mod));
28
28
 
29
29
  //#endregion
30
- const require_snapshot = require('./snapshot-CyWGJaJT.cjs');
30
+ const require_snapshot = require('./snapshot-BJmrOlMK.cjs');
31
31
  const require_diff = require('./diff.cjs');
32
32
  let node_fs = require("node:fs");
33
33
  let node_path = require("node:path");
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as parseSnapshot } from "./snapshot-h8pb_Up_.js";
2
+ import { n as parseSnapshot } from "./snapshot-BFIxChH0.js";
3
3
  import { diffSnapshots, formatDiff, hasBreakingChanges } from "./diff.js";
4
4
  import { readFileSync } from "node:fs";
5
5
  import path from "node:path";
@@ -1,50 +1,51 @@
1
- //#region src/scenario.d.ts
1
+ //#region src/validate.d.ts
2
+ /** Severity of a contract violation. `error` = a breaking-shaped problem. */
3
+ type ViolationSeverity = 'error' | 'warning';
4
+ type ViolationCode = 'unknown_span' | 'unknown_attribute' | 'type_mismatch' | 'missing_required' | 'deprecated_attribute' | 'enum_violation';
5
+ /** A single discrepancy between an emitted span and the contract. */
6
+ interface SchemaViolation {
7
+ code: ViolationCode;
8
+ severity: ViolationSeverity;
9
+ spanName: string;
10
+ /** Attribute key involved, when the violation is attribute-scoped. */
11
+ attribute?: string;
12
+ message: string;
13
+ /** Nearest declared key, for likely typos (`unknown_attribute` only). */
14
+ suggestion?: string;
15
+ }
16
+ /** What an attribute can hold once a span has been emitted. */
17
+ type EmittedAttributeValue = string | number | boolean | null | undefined | Array<string | number | boolean | null | undefined>;
2
18
  /**
3
- * Scenario conformance a flow-level contract checked against collected spans.
4
- *
5
- * Where {@link ./contract} declares the *surface* of your telemetry (span
6
- * names + attributes), a scenario declares the *behaviour* of one exercised
7
- * flow: which events must fire, how many times, in what parent/child
8
- * topology, and — critically — **when the observation is complete**, because
9
- * for an async flow a missing event and an event that has not fired *yet* are
10
- * indistinguishable without a completion boundary.
11
- *
12
- * Checking a scenario yields one of three outcomes, not two:
13
- *
14
- * - `conformant` — the boundary closed and the signature satisfied the contract
15
- * - `non-conformant` required behaviour was missing or invalid (definitive)
16
- * - `incomplete` the boundary did not close within the observation budget;
17
- * infrastructure slowness is *not* reported as behavioural regression
18
- *
19
- * Absence is definitive only after closure (closed-world semantics). Excess
20
- * is definitive immediately: a `max` cardinality violation or an unexpected
21
- * error span fails the check even while the flow is still open.
22
- *
23
- * Undeclared events are **additive**: reported in `result.additions`, never a
24
- * failure — improving instrumentation must not break CI.
25
- *
26
- * The span input shape is structurally compatible with `SerializedSpan` from
27
- * `autotel/test-span-collector`, so a test can feed a collector's output
28
- * straight in. Like the rest of this package the module is dependency-free —
29
- * usable from vitest, a deferred reconciliation job, or a CLI alike.
30
- *
31
- * @example
32
- * ```ts
33
- * const result = await checkScenario(
34
- * contract.scenarios!['transfer.accept'],
35
- * () => collector.peekTrace(traceId),
36
- * { name: 'transfer.accept' },
37
- * );
38
- * if (result.outcome === 'non-conformant') throw new Error(formatScenarioResult(result));
39
- * ```
19
+ * A span as this package receives it for validation — just enough of one to
20
+ * check against a schema, which avoids a hard dependency on the OTel SDK.
21
+ */
22
+ interface EmittedSpan {
23
+ name: string;
24
+ attributes: Record<string, EmittedAttributeValue>;
25
+ }
26
+ interface ValidateOptions {
27
+ /** Report `unknown_span` for span names not in the contract. Default `false`. */
28
+ strictSpanNames?: boolean;
29
+ }
30
+ /**
31
+ * Validate one emitted span against the contract, returning every discrepancy.
32
+ * Order is deterministic: required-but-missing first, then per-attribute checks
33
+ * in attribute insertion order.
40
34
  */
35
+ declare function validateSpan(span: EmittedSpan, contract: TelemetryContract, options?: ValidateOptions): SchemaViolation[];
36
+ /** `true` when any violation is `error` severity. */
37
+ declare function hasErrors(violations: SchemaViolation[]): boolean;
38
+ /** One-line human/agent-readable rendering of a violation. */
39
+ declare function formatViolation(v: SchemaViolation): string;
40
+ //#endregion
41
+ //#region src/scenario.d.ts
41
42
  /** A finished span/event as the scenario checker sees it. */
42
43
  interface ScenarioSpan {
43
44
  spanId: string;
44
45
  parentSpanId?: string;
45
46
  name: string;
46
47
  status: 'ok' | 'error' | 'unset';
47
- attributes?: Record<string, unknown>;
48
+ attributes?: Record<string, EmittedAttributeValue>;
48
49
  /** Epoch ms. Optional — used by {@link proposeScenario} to suggest budgets. */
49
50
  startTimeMs?: number;
50
51
  durationMs?: number;
@@ -301,4 +302,4 @@ declare function resolveAttributeSpec(contract: TelemetryContract, spanName: str
301
302
  /** Whether attributes outside the declared set are tolerated for a span. */
302
303
  declare function allowsAdditionalAttributes(contract: TelemetryContract, spanName: string): boolean;
303
304
  //#endregion
304
- export { validateScenarioSpec as A, ScenarioViolationCode as C, isScenarioClosed as D, formatScenarioResult as E, parseCardinality as O, ScenarioViolation as S, evaluateScenario as T, ScenarioOutcome as _, SpanSpec as a, ScenarioSpan as b, allowsAdditionalAttributes as c, Cardinality as d, CheckScenarioOptions as f, ScenarioEventSpec as g, ScenarioAddition as h, STABILITIES as i, proposeScenario as k, defineContract as l, EvaluateScenarioOptions as m, AttributeSpec as n, Stability as o, CompletionBoundary as p, AttributeType as r, TelemetryContract as s, ATTRIBUTE_TYPES as t, resolveAttributeSpec as u, ScenarioProposal as v, checkScenario as w, ScenarioSpec as x, ScenarioResult as y };
305
+ export { validateScenarioSpec as A, ScenarioViolationCode as C, isScenarioClosed as D, formatScenarioResult as E, ViolationCode as F, ViolationSeverity as I, formatViolation as L, EmittedSpan as M, SchemaViolation as N, parseCardinality as O, ValidateOptions as P, hasErrors as R, ScenarioViolation as S, evaluateScenario as T, ScenarioOutcome as _, SpanSpec as a, ScenarioSpan as b, allowsAdditionalAttributes as c, Cardinality as d, CheckScenarioOptions as f, ScenarioEventSpec as g, ScenarioAddition as h, STABILITIES as i, EmittedAttributeValue as j, proposeScenario as k, defineContract as l, EvaluateScenarioOptions as m, AttributeSpec as n, Stability as o, CompletionBoundary as p, AttributeType as r, TelemetryContract as s, ATTRIBUTE_TYPES as t, resolveAttributeSpec as u, ScenarioProposal as v, checkScenario as w, ScenarioSpec as x, ScenarioResult as y, validateSpan as z };
@@ -1,50 +1,51 @@
1
- //#region src/scenario.d.ts
1
+ //#region src/validate.d.ts
2
+ /** Severity of a contract violation. `error` = a breaking-shaped problem. */
3
+ type ViolationSeverity = 'error' | 'warning';
4
+ type ViolationCode = 'unknown_span' | 'unknown_attribute' | 'type_mismatch' | 'missing_required' | 'deprecated_attribute' | 'enum_violation';
5
+ /** A single discrepancy between an emitted span and the contract. */
6
+ interface SchemaViolation {
7
+ code: ViolationCode;
8
+ severity: ViolationSeverity;
9
+ spanName: string;
10
+ /** Attribute key involved, when the violation is attribute-scoped. */
11
+ attribute?: string;
12
+ message: string;
13
+ /** Nearest declared key, for likely typos (`unknown_attribute` only). */
14
+ suggestion?: string;
15
+ }
16
+ /** What an attribute can hold once a span has been emitted. */
17
+ type EmittedAttributeValue = string | number | boolean | null | undefined | Array<string | number | boolean | null | undefined>;
2
18
  /**
3
- * Scenario conformance a flow-level contract checked against collected spans.
4
- *
5
- * Where {@link ./contract} declares the *surface* of your telemetry (span
6
- * names + attributes), a scenario declares the *behaviour* of one exercised
7
- * flow: which events must fire, how many times, in what parent/child
8
- * topology, and — critically — **when the observation is complete**, because
9
- * for an async flow a missing event and an event that has not fired *yet* are
10
- * indistinguishable without a completion boundary.
11
- *
12
- * Checking a scenario yields one of three outcomes, not two:
13
- *
14
- * - `conformant` — the boundary closed and the signature satisfied the contract
15
- * - `non-conformant` required behaviour was missing or invalid (definitive)
16
- * - `incomplete` the boundary did not close within the observation budget;
17
- * infrastructure slowness is *not* reported as behavioural regression
18
- *
19
- * Absence is definitive only after closure (closed-world semantics). Excess
20
- * is definitive immediately: a `max` cardinality violation or an unexpected
21
- * error span fails the check even while the flow is still open.
22
- *
23
- * Undeclared events are **additive**: reported in `result.additions`, never a
24
- * failure — improving instrumentation must not break CI.
25
- *
26
- * The span input shape is structurally compatible with `SerializedSpan` from
27
- * `autotel/test-span-collector`, so a test can feed a collector's output
28
- * straight in. Like the rest of this package the module is dependency-free —
29
- * usable from vitest, a deferred reconciliation job, or a CLI alike.
30
- *
31
- * @example
32
- * ```ts
33
- * const result = await checkScenario(
34
- * contract.scenarios!['transfer.accept'],
35
- * () => collector.peekTrace(traceId),
36
- * { name: 'transfer.accept' },
37
- * );
38
- * if (result.outcome === 'non-conformant') throw new Error(formatScenarioResult(result));
39
- * ```
19
+ * A span as this package receives it for validation — just enough of one to
20
+ * check against a schema, which avoids a hard dependency on the OTel SDK.
21
+ */
22
+ interface EmittedSpan {
23
+ name: string;
24
+ attributes: Record<string, EmittedAttributeValue>;
25
+ }
26
+ interface ValidateOptions {
27
+ /** Report `unknown_span` for span names not in the contract. Default `false`. */
28
+ strictSpanNames?: boolean;
29
+ }
30
+ /**
31
+ * Validate one emitted span against the contract, returning every discrepancy.
32
+ * Order is deterministic: required-but-missing first, then per-attribute checks
33
+ * in attribute insertion order.
40
34
  */
35
+ declare function validateSpan(span: EmittedSpan, contract: TelemetryContract, options?: ValidateOptions): SchemaViolation[];
36
+ /** `true` when any violation is `error` severity. */
37
+ declare function hasErrors(violations: SchemaViolation[]): boolean;
38
+ /** One-line human/agent-readable rendering of a violation. */
39
+ declare function formatViolation(v: SchemaViolation): string;
40
+ //#endregion
41
+ //#region src/scenario.d.ts
41
42
  /** A finished span/event as the scenario checker sees it. */
42
43
  interface ScenarioSpan {
43
44
  spanId: string;
44
45
  parentSpanId?: string;
45
46
  name: string;
46
47
  status: 'ok' | 'error' | 'unset';
47
- attributes?: Record<string, unknown>;
48
+ attributes?: Record<string, EmittedAttributeValue>;
48
49
  /** Epoch ms. Optional — used by {@link proposeScenario} to suggest budgets. */
49
50
  startTimeMs?: number;
50
51
  durationMs?: number;
@@ -301,4 +302,4 @@ declare function resolveAttributeSpec(contract: TelemetryContract, spanName: str
301
302
  /** Whether attributes outside the declared set are tolerated for a span. */
302
303
  declare function allowsAdditionalAttributes(contract: TelemetryContract, spanName: string): boolean;
303
304
  //#endregion
304
- export { validateScenarioSpec as A, ScenarioViolationCode as C, isScenarioClosed as D, formatScenarioResult as E, parseCardinality as O, ScenarioViolation as S, evaluateScenario as T, ScenarioOutcome as _, SpanSpec as a, ScenarioSpan as b, allowsAdditionalAttributes as c, Cardinality as d, CheckScenarioOptions as f, ScenarioEventSpec as g, ScenarioAddition as h, STABILITIES as i, proposeScenario as k, defineContract as l, EvaluateScenarioOptions as m, AttributeSpec as n, Stability as o, CompletionBoundary as p, AttributeType as r, TelemetryContract as s, ATTRIBUTE_TYPES as t, resolveAttributeSpec as u, ScenarioProposal as v, checkScenario as w, ScenarioSpec as x, ScenarioResult as y };
305
+ export { validateScenarioSpec as A, ScenarioViolationCode as C, isScenarioClosed as D, formatScenarioResult as E, ViolationCode as F, ViolationSeverity as I, formatViolation as L, EmittedSpan as M, SchemaViolation as N, parseCardinality as O, ValidateOptions as P, hasErrors as R, ScenarioViolation as S, evaluateScenario as T, ScenarioOutcome as _, SpanSpec as a, ScenarioSpan as b, allowsAdditionalAttributes as c, Cardinality as d, CheckScenarioOptions as f, ScenarioEventSpec as g, ScenarioAddition as h, STABILITIES as i, EmittedAttributeValue as j, proposeScenario as k, defineContract as l, EvaluateScenarioOptions as m, AttributeSpec as n, Stability as o, CompletionBoundary as p, AttributeType as r, TelemetryContract as s, ATTRIBUTE_TYPES as t, resolveAttributeSpec as u, ScenarioProposal as v, checkScenario as w, ScenarioSpec as x, ScenarioResult as y, validateSpan as z };
@@ -1,4 +1,4 @@
1
- import { o as Stability, r as AttributeType, s as TelemetryContract } from "./contract-Ymh_Q37N.cjs";
1
+ import { o as Stability, r as AttributeType, s as TelemetryContract } from "./contract-CfOaZcD0.cjs";
2
2
  //#region src/attrs.d.ts
3
3
  /**
4
4
  * Wire constants for the schema contract — the keys autotel-schema reads from
@@ -1,4 +1,4 @@
1
- import { o as Stability, r as AttributeType, s as TelemetryContract } from "./contract-Ymh_Q37N.js";
1
+ import { o as Stability, r as AttributeType, s as TelemetryContract } from "./contract-CfOaZcD0.js";
2
2
  //#region src/attrs.d.ts
3
3
  /**
4
4
  * Wire constants for the schema contract — the keys autotel-schema reads from
package/dist/diff.cjs CHANGED
@@ -6,32 +6,32 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
6
6
  * six transitions are explicit and auditable — no silent fall-through. Same-
7
7
  * stability transitions are absent (no change to report).
8
8
  */
9
- const STABILITY_TRANSITIONS = {
10
- "stable->experimental": {
9
+ const STABILITY_TRANSITIONS = /* @__PURE__ */ new Map([
10
+ ["stable->experimental", {
11
11
  kind: "breaking",
12
12
  type: "stability_downgraded"
13
- },
14
- "stable->deprecated": {
13
+ }],
14
+ ["stable->deprecated", {
15
15
  kind: "additive",
16
16
  type: "deprecated"
17
- },
18
- "experimental->stable": {
17
+ }],
18
+ ["experimental->stable", {
19
19
  kind: "neutral",
20
20
  type: "stability_advanced"
21
- },
22
- "experimental->deprecated": {
21
+ }],
22
+ ["experimental->deprecated", {
23
23
  kind: "additive",
24
24
  type: "deprecated"
25
- },
26
- "deprecated->stable": {
25
+ }],
26
+ ["deprecated->stable", {
27
27
  kind: "neutral",
28
28
  type: "stability_advanced"
29
- },
30
- "deprecated->experimental": {
29
+ }],
30
+ ["deprecated->experimental", {
31
31
  kind: "breaking",
32
32
  type: "stability_downgraded"
33
- }
34
- };
33
+ }]
34
+ ]);
35
35
  function stabilityMessage(type, attribute, prev, next) {
36
36
  if (type === "deprecated") return `attribute "${attribute}" was deprecated${next.replacedBy ? ` (use "${next.replacedBy}")` : ""}`;
37
37
  if (type === "stability_downgraded") return `attribute "${attribute}" stability downgraded ${prev.stability} → ${next.stability}`;
@@ -85,7 +85,7 @@ function diffAttribute(diff, span, attribute, prev, next) {
85
85
  });
86
86
  }
87
87
  if (prev.stability !== next.stability) {
88
- const transition = STABILITY_TRANSITIONS[`${prev.stability}->${next.stability}`];
88
+ const transition = STABILITY_TRANSITIONS.get(`${prev.stability}->${next.stability}`);
89
89
  if (transition) push(diff, {
90
90
  ...transition,
91
91
  span,
package/dist/diff.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as diffSnapshots, i as SnapshotDiff, n as ChangeType, o as formatDiff, r as SnapshotChange, s as hasBreakingChanges, t as ChangeKind } from "./diff-CfvhW7ux.cjs";
1
+ import { a as diffSnapshots, i as SnapshotDiff, n as ChangeType, o as formatDiff, r as SnapshotChange, s as hasBreakingChanges, t as ChangeKind } from "./diff-B9GL_E28.cjs";
2
2
  export { ChangeKind, ChangeType, SnapshotChange, SnapshotDiff, diffSnapshots, formatDiff, hasBreakingChanges };
package/dist/diff.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as diffSnapshots, i as SnapshotDiff, n as ChangeType, o as formatDiff, r as SnapshotChange, s as hasBreakingChanges, t as ChangeKind } from "./diff-CAIC04O4.js";
1
+ import { a as diffSnapshots, i as SnapshotDiff, n as ChangeType, o as formatDiff, r as SnapshotChange, s as hasBreakingChanges, t as ChangeKind } from "./diff-DenUg42T.js";
2
2
  export { ChangeKind, ChangeType, SnapshotChange, SnapshotDiff, diffSnapshots, formatDiff, hasBreakingChanges };
package/dist/diff.js CHANGED
@@ -4,32 +4,32 @@
4
4
  * six transitions are explicit and auditable — no silent fall-through. Same-
5
5
  * stability transitions are absent (no change to report).
6
6
  */
7
- const STABILITY_TRANSITIONS = {
8
- "stable->experimental": {
7
+ const STABILITY_TRANSITIONS = /* @__PURE__ */ new Map([
8
+ ["stable->experimental", {
9
9
  kind: "breaking",
10
10
  type: "stability_downgraded"
11
- },
12
- "stable->deprecated": {
11
+ }],
12
+ ["stable->deprecated", {
13
13
  kind: "additive",
14
14
  type: "deprecated"
15
- },
16
- "experimental->stable": {
15
+ }],
16
+ ["experimental->stable", {
17
17
  kind: "neutral",
18
18
  type: "stability_advanced"
19
- },
20
- "experimental->deprecated": {
19
+ }],
20
+ ["experimental->deprecated", {
21
21
  kind: "additive",
22
22
  type: "deprecated"
23
- },
24
- "deprecated->stable": {
23
+ }],
24
+ ["deprecated->stable", {
25
25
  kind: "neutral",
26
26
  type: "stability_advanced"
27
- },
28
- "deprecated->experimental": {
27
+ }],
28
+ ["deprecated->experimental", {
29
29
  kind: "breaking",
30
30
  type: "stability_downgraded"
31
- }
32
- };
31
+ }]
32
+ ]);
33
33
  function stabilityMessage(type, attribute, prev, next) {
34
34
  if (type === "deprecated") return `attribute "${attribute}" was deprecated${next.replacedBy ? ` (use "${next.replacedBy}")` : ""}`;
35
35
  if (type === "stability_downgraded") return `attribute "${attribute}" stability downgraded ${prev.stability} → ${next.stability}`;
@@ -83,7 +83,7 @@ function diffAttribute(diff, span, attribute, prev, next) {
83
83
  });
84
84
  }
85
85
  if (prev.stability !== next.stability) {
86
- const transition = STABILITY_TRANSITIONS[`${prev.stability}->${next.stability}`];
86
+ const transition = STABILITY_TRANSITIONS.get(`${prev.stability}->${next.stability}`);
87
87
  if (transition) push(diff, {
88
88
  ...transition,
89
89
  span,
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_snapshot = require('./snapshot-CyWGJaJT.cjs');
3
- const require_processor = require('./processor-Gu8Yl_dS.cjs');
2
+ const require_snapshot = require('./snapshot-BJmrOlMK.cjs');
3
+ const require_processor = require('./processor-C9NmN0wQ.cjs');
4
4
  const require_diff = require('./diff.cjs');
5
5
 
6
6
  //#region src/completeness.ts
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { a as diffSnapshots, c as ContractSnapshot, d as contractToSnapshot, f as parseSnapshot, g as SchemaAttributeKey, h as SNAPSHOT_SPEC, i as SnapshotDiff, l as SnapshotAttribute, m as SCHEMA_ATTRS, n as ChangeType, o as formatDiff, p as serializeSnapshot, r as SnapshotChange, s as hasBreakingChanges, t as ChangeKind, u as SnapshotSpan } from "./diff-CfvhW7ux.cjs";
2
- import { A as validateScenarioSpec, C as ScenarioViolationCode, D as isScenarioClosed, E as formatScenarioResult, O as parseCardinality, S as ScenarioViolation, T as evaluateScenario, _ as ScenarioOutcome, a as SpanSpec, b as ScenarioSpan, c as allowsAdditionalAttributes, d as Cardinality, f as CheckScenarioOptions, g as ScenarioEventSpec, h as ScenarioAddition, i as STABILITIES, k as proposeScenario, l as defineContract, m as EvaluateScenarioOptions, n as AttributeSpec, o as Stability, p as CompletionBoundary, r as AttributeType, s as TelemetryContract, t as ATTRIBUTE_TYPES, u as resolveAttributeSpec, v as ScenarioProposal, w as checkScenario, x as ScenarioSpec, y as ScenarioResult } from "./contract-Ymh_Q37N.cjs";
3
- import { a as SchemaValidationSpanProcessor, c as createSchemaValidationProcessor, d as ValidateOptions, f as ViolationCode, g as validateSpan, h as hasErrors, i as SchemaValidationProcessorOptions, l as SchemaViolation, m as formatViolation, n as ReadableSpanLike, o as SpanLike, p as ViolationSeverity, r as SchemaProcessorMode, s as SpanProcessorLike, t as OtelContext, u as SpanShape } from "./processor-DVcsS6Rz.cjs";
1
+ import { a as diffSnapshots, c as ContractSnapshot, d as contractToSnapshot, f as parseSnapshot, g as SchemaAttributeKey, h as SNAPSHOT_SPEC, i as SnapshotDiff, l as SnapshotAttribute, m as SCHEMA_ATTRS, n as ChangeType, o as formatDiff, p as serializeSnapshot, r as SnapshotChange, s as hasBreakingChanges, t as ChangeKind, u as SnapshotSpan } from "./diff-B9GL_E28.cjs";
2
+ import { A as validateScenarioSpec, C as ScenarioViolationCode, D as isScenarioClosed, E as formatScenarioResult, F as ViolationCode, I as ViolationSeverity, L as formatViolation, M as EmittedSpan, N as SchemaViolation, O as parseCardinality, P as ValidateOptions, R as hasErrors, S as ScenarioViolation, T as evaluateScenario, _ as ScenarioOutcome, a as SpanSpec, b as ScenarioSpan, c as allowsAdditionalAttributes, d as Cardinality, f as CheckScenarioOptions, g as ScenarioEventSpec, h as ScenarioAddition, i as STABILITIES, j as EmittedAttributeValue, k as proposeScenario, l as defineContract, m as EvaluateScenarioOptions, n as AttributeSpec, o as Stability, p as CompletionBoundary, r as AttributeType, s as TelemetryContract, t as ATTRIBUTE_TYPES, u as resolveAttributeSpec, v as ScenarioProposal, w as checkScenario, x as ScenarioSpec, y as ScenarioResult, z as validateSpan } from "./contract-CfOaZcD0.cjs";
3
+ import { OtelContext, ReadableSpanLike, SchemaProcessorMode, SchemaValidationProcessorOptions, SchemaValidationSpanProcessor, SpanLike, SpanProcessorLike, createSchemaValidationProcessor } from "./processor.cjs";
4
4
  //#region src/completeness.d.ts
5
5
  /** The ten fields a GenAI trace is scored on. */
6
6
  declare const GENAI_COMPLETENESS_FIELDS: readonly ["llm_input", "llm_output", "model_name", "token_usage", "cost_usd", "latency_per_span", "tool_call_args", "tool_call_results", "span_tree", "span_count"];
@@ -66,4 +66,4 @@ declare function isHighCardinalityKey(contract: TelemetryContract, key: string):
66
66
  */
67
67
  declare const AGENT_SECURITY_TELEMETRY_CONTRACT: TelemetryContract;
68
68
  //#endregion
69
- export { AGENT_SECURITY_TELEMETRY_CONTRACT, ATTRIBUTE_TYPES, type AttributeSpec, type AttributeType, type Cardinality, type ChangeKind, type ChangeType, type CheckScenarioOptions, type CompletenessResult, type CompletionBoundary, type ContractSnapshot, type EvaluateScenarioOptions, type FieldScore, GENAI_COMPLETENESS_FIELDS, type GenAiCompletenessField, type OtelContext, type ReadableSpanLike, SCHEMA_ATTRS, SNAPSHOT_SPEC, STABILITIES, type ScenarioAddition, type ScenarioEventSpec, type ScenarioOutcome, type ScenarioProposal, type ScenarioResult, type ScenarioSpan, type ScenarioSpec, type ScenarioViolation, type ScenarioViolationCode, type SchemaAttributeKey, type SchemaProcessorMode, type SchemaValidationProcessorOptions, SchemaValidationSpanProcessor, type SchemaViolation, type SnapshotAttribute, type SnapshotChange, type SnapshotDiff, type SnapshotSpan, type SpanLike, type SpanProcessorLike, type SpanShape, type SpanSpec, type Stability, type TelemetryContract, type ValidateOptions, type ViolationCode, type ViolationSeverity, allowsAdditionalAttributes, checkScenario, contractToSnapshot, createSchemaValidationProcessor, defineContract, diffSnapshots, evaluateScenario, formatCompleteness, formatDiff, formatScenarioResult, formatViolation, hasBreakingChanges, hasErrors, highCardinalityKeys, isHighCardinalityKey, isScenarioClosed, parseCardinality, parseSnapshot, proposeScenario, resolveAttributeSpec, scoreGenAiCompleteness, serializeSnapshot, validateScenarioSpec, validateSpan };
69
+ export { AGENT_SECURITY_TELEMETRY_CONTRACT, ATTRIBUTE_TYPES, type AttributeSpec, type AttributeType, type Cardinality, type ChangeKind, type ChangeType, type CheckScenarioOptions, type CompletenessResult, type CompletionBoundary, type ContractSnapshot, type EmittedAttributeValue, type EmittedSpan, type EvaluateScenarioOptions, type FieldScore, GENAI_COMPLETENESS_FIELDS, type GenAiCompletenessField, type OtelContext, type ReadableSpanLike, SCHEMA_ATTRS, SNAPSHOT_SPEC, STABILITIES, type ScenarioAddition, type ScenarioEventSpec, type ScenarioOutcome, type ScenarioProposal, type ScenarioResult, type ScenarioSpan, type ScenarioSpec, type ScenarioViolation, type ScenarioViolationCode, type SchemaAttributeKey, type SchemaProcessorMode, type SchemaValidationProcessorOptions, SchemaValidationSpanProcessor, type SchemaViolation, type SnapshotAttribute, type SnapshotChange, type SnapshotDiff, type SnapshotSpan, type SpanLike, type SpanProcessorLike, type SpanSpec, type Stability, type TelemetryContract, type ValidateOptions, type ViolationCode, type ViolationSeverity, allowsAdditionalAttributes, checkScenario, contractToSnapshot, createSchemaValidationProcessor, defineContract, diffSnapshots, evaluateScenario, formatCompleteness, formatDiff, formatScenarioResult, formatViolation, hasBreakingChanges, hasErrors, highCardinalityKeys, isHighCardinalityKey, isScenarioClosed, parseCardinality, parseSnapshot, proposeScenario, resolveAttributeSpec, scoreGenAiCompleteness, serializeSnapshot, validateScenarioSpec, validateSpan };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { a as diffSnapshots, c as ContractSnapshot, d as contractToSnapshot, f as parseSnapshot, g as SchemaAttributeKey, h as SNAPSHOT_SPEC, i as SnapshotDiff, l as SnapshotAttribute, m as SCHEMA_ATTRS, n as ChangeType, o as formatDiff, p as serializeSnapshot, r as SnapshotChange, s as hasBreakingChanges, t as ChangeKind, u as SnapshotSpan } from "./diff-CAIC04O4.js";
2
- import { A as validateScenarioSpec, C as ScenarioViolationCode, D as isScenarioClosed, E as formatScenarioResult, O as parseCardinality, S as ScenarioViolation, T as evaluateScenario, _ as ScenarioOutcome, a as SpanSpec, b as ScenarioSpan, c as allowsAdditionalAttributes, d as Cardinality, f as CheckScenarioOptions, g as ScenarioEventSpec, h as ScenarioAddition, i as STABILITIES, k as proposeScenario, l as defineContract, m as EvaluateScenarioOptions, n as AttributeSpec, o as Stability, p as CompletionBoundary, r as AttributeType, s as TelemetryContract, t as ATTRIBUTE_TYPES, u as resolveAttributeSpec, v as ScenarioProposal, w as checkScenario, x as ScenarioSpec, y as ScenarioResult } from "./contract-Ymh_Q37N.js";
3
- import { a as SchemaValidationSpanProcessor, c as createSchemaValidationProcessor, d as ValidateOptions, f as ViolationCode, g as validateSpan, h as hasErrors, i as SchemaValidationProcessorOptions, l as SchemaViolation, m as formatViolation, n as ReadableSpanLike, o as SpanLike, p as ViolationSeverity, r as SchemaProcessorMode, s as SpanProcessorLike, t as OtelContext, u as SpanShape } from "./processor-TpuacLr5.js";
1
+ import { a as diffSnapshots, c as ContractSnapshot, d as contractToSnapshot, f as parseSnapshot, g as SchemaAttributeKey, h as SNAPSHOT_SPEC, i as SnapshotDiff, l as SnapshotAttribute, m as SCHEMA_ATTRS, n as ChangeType, o as formatDiff, p as serializeSnapshot, r as SnapshotChange, s as hasBreakingChanges, t as ChangeKind, u as SnapshotSpan } from "./diff-DenUg42T.js";
2
+ import { A as validateScenarioSpec, C as ScenarioViolationCode, D as isScenarioClosed, E as formatScenarioResult, F as ViolationCode, I as ViolationSeverity, L as formatViolation, M as EmittedSpan, N as SchemaViolation, O as parseCardinality, P as ValidateOptions, R as hasErrors, S as ScenarioViolation, T as evaluateScenario, _ as ScenarioOutcome, a as SpanSpec, b as ScenarioSpan, c as allowsAdditionalAttributes, d as Cardinality, f as CheckScenarioOptions, g as ScenarioEventSpec, h as ScenarioAddition, i as STABILITIES, j as EmittedAttributeValue, k as proposeScenario, l as defineContract, m as EvaluateScenarioOptions, n as AttributeSpec, o as Stability, p as CompletionBoundary, r as AttributeType, s as TelemetryContract, t as ATTRIBUTE_TYPES, u as resolveAttributeSpec, v as ScenarioProposal, w as checkScenario, x as ScenarioSpec, y as ScenarioResult, z as validateSpan } from "./contract-CfOaZcD0.js";
3
+ import { OtelContext, ReadableSpanLike, SchemaProcessorMode, SchemaValidationProcessorOptions, SchemaValidationSpanProcessor, SpanLike, SpanProcessorLike, createSchemaValidationProcessor } from "./processor.js";
4
4
  //#region src/completeness.d.ts
5
5
  /** The ten fields a GenAI trace is scored on. */
6
6
  declare const GENAI_COMPLETENESS_FIELDS: readonly ["llm_input", "llm_output", "model_name", "token_usage", "cost_usd", "latency_per_span", "tool_call_args", "tool_call_results", "span_tree", "span_count"];
@@ -66,4 +66,4 @@ declare function isHighCardinalityKey(contract: TelemetryContract, key: string):
66
66
  */
67
67
  declare const AGENT_SECURITY_TELEMETRY_CONTRACT: TelemetryContract;
68
68
  //#endregion
69
- export { AGENT_SECURITY_TELEMETRY_CONTRACT, ATTRIBUTE_TYPES, type AttributeSpec, type AttributeType, type Cardinality, type ChangeKind, type ChangeType, type CheckScenarioOptions, type CompletenessResult, type CompletionBoundary, type ContractSnapshot, type EvaluateScenarioOptions, type FieldScore, GENAI_COMPLETENESS_FIELDS, type GenAiCompletenessField, type OtelContext, type ReadableSpanLike, SCHEMA_ATTRS, SNAPSHOT_SPEC, STABILITIES, type ScenarioAddition, type ScenarioEventSpec, type ScenarioOutcome, type ScenarioProposal, type ScenarioResult, type ScenarioSpan, type ScenarioSpec, type ScenarioViolation, type ScenarioViolationCode, type SchemaAttributeKey, type SchemaProcessorMode, type SchemaValidationProcessorOptions, SchemaValidationSpanProcessor, type SchemaViolation, type SnapshotAttribute, type SnapshotChange, type SnapshotDiff, type SnapshotSpan, type SpanLike, type SpanProcessorLike, type SpanShape, type SpanSpec, type Stability, type TelemetryContract, type ValidateOptions, type ViolationCode, type ViolationSeverity, allowsAdditionalAttributes, checkScenario, contractToSnapshot, createSchemaValidationProcessor, defineContract, diffSnapshots, evaluateScenario, formatCompleteness, formatDiff, formatScenarioResult, formatViolation, hasBreakingChanges, hasErrors, highCardinalityKeys, isHighCardinalityKey, isScenarioClosed, parseCardinality, parseSnapshot, proposeScenario, resolveAttributeSpec, scoreGenAiCompleteness, serializeSnapshot, validateScenarioSpec, validateSpan };
69
+ export { AGENT_SECURITY_TELEMETRY_CONTRACT, ATTRIBUTE_TYPES, type AttributeSpec, type AttributeType, type Cardinality, type ChangeKind, type ChangeType, type CheckScenarioOptions, type CompletenessResult, type CompletionBoundary, type ContractSnapshot, type EmittedAttributeValue, type EmittedSpan, type EvaluateScenarioOptions, type FieldScore, GENAI_COMPLETENESS_FIELDS, type GenAiCompletenessField, type OtelContext, type ReadableSpanLike, SCHEMA_ATTRS, SNAPSHOT_SPEC, STABILITIES, type ScenarioAddition, type ScenarioEventSpec, type ScenarioOutcome, type ScenarioProposal, type ScenarioResult, type ScenarioSpan, type ScenarioSpec, type ScenarioViolation, type ScenarioViolationCode, type SchemaAttributeKey, type SchemaProcessorMode, type SchemaValidationProcessorOptions, SchemaValidationSpanProcessor, type SchemaViolation, type SnapshotAttribute, type SnapshotChange, type SnapshotDiff, type SnapshotSpan, type SpanLike, type SpanProcessorLike, type SpanSpec, type Stability, type TelemetryContract, type ValidateOptions, type ViolationCode, type ViolationSeverity, allowsAdditionalAttributes, checkScenario, contractToSnapshot, createSchemaValidationProcessor, defineContract, diffSnapshots, evaluateScenario, formatCompleteness, formatDiff, formatScenarioResult, formatViolation, hasBreakingChanges, hasErrors, highCardinalityKeys, isHighCardinalityKey, isScenarioClosed, parseCardinality, parseSnapshot, proposeScenario, resolveAttributeSpec, scoreGenAiCompleteness, serializeSnapshot, validateScenarioSpec, validateSpan };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { a as SNAPSHOT_SPEC, i as SCHEMA_ATTRS, n as parseSnapshot, r as serializeSnapshot, t as contractToSnapshot } from "./snapshot-h8pb_Up_.js";
2
- import { _ as validateScenarioSpec, a as validateSpan, c as allowsAdditionalAttributes, d as checkScenario, f as evaluateScenario, g as proposeScenario, h as parseCardinality, i as hasErrors, l as defineContract, m as isScenarioClosed, n as createSchemaValidationProcessor, o as ATTRIBUTE_TYPES, p as formatScenarioResult, r as formatViolation, s as STABILITIES, t as SchemaValidationSpanProcessor, u as resolveAttributeSpec } from "./processor-BPp_DewZ.js";
1
+ import { a as SNAPSHOT_SPEC, i as SCHEMA_ATTRS, n as parseSnapshot, r as serializeSnapshot, t as contractToSnapshot } from "./snapshot-BFIxChH0.js";
2
+ import { _ as validateScenarioSpec, a as validateSpan, c as allowsAdditionalAttributes, d as checkScenario, f as evaluateScenario, g as proposeScenario, h as parseCardinality, i as hasErrors, l as defineContract, m as isScenarioClosed, n as createSchemaValidationProcessor, o as ATTRIBUTE_TYPES, p as formatScenarioResult, r as formatViolation, s as STABILITIES, t as SchemaValidationSpanProcessor, u as resolveAttributeSpec } from "./processor-Cn0HNUvw.js";
3
3
  import { diffSnapshots, formatDiff, hasBreakingChanges } from "./diff.js";
4
4
 
5
5
  //#region src/completeness.ts
@@ -48,8 +48,8 @@ const COMPLETION_MODES = [
48
48
  */
49
49
  function validateScenarioSpec(name, spec) {
50
50
  const scope = `scenario "${name}"`;
51
- assert$1(spec.completion && typeof spec.completion === "object", `${scope} must declare a completion boundary`);
52
- assert$1(COMPLETION_MODES.includes(spec.completion.mode), `${scope} has invalid completion mode "${spec.completion.mode}"`);
51
+ assert$1(spec.completion !== void 0 && spec.completion !== null, `${scope} must declare a completion boundary`);
52
+ assert$1(COMPLETION_MODES.some((mode) => mode === spec.completion.mode), `${scope} has invalid completion mode "${spec.completion.mode}"`);
53
53
  const budget = spec.completion.mode === "externally-reconciled" ? spec.completion.reconciliationDeadlineMs : spec.completion.observationBudgetMs;
54
54
  assert$1(typeof budget === "number" && Number.isFinite(budget) && budget > 0, `${scope} completion budget must be a positive number of milliseconds`);
55
55
  switch (spec.completion.mode) {
@@ -62,7 +62,7 @@ function validateScenarioSpec(name, spec) {
62
62
  if (eventSpec.cardinality !== void 0) try {
63
63
  parseCardinality(eventSpec.cardinality);
64
64
  } catch (error) {
65
- throw new Error(`autotel-schema: ${scope} event "${event}": ${error.message}`);
65
+ throw new Error(`autotel-schema: ${scope} event "${event}": ${error instanceof Error ? error.message : String(error)}`);
66
66
  }
67
67
  if (eventSpec.status !== void 0) assert$1(eventSpec.status === "ok" || eventSpec.status === "error", `${scope} event "${event}" has invalid status "${eventSpec.status}"`);
68
68
  }
@@ -298,10 +298,10 @@ function proposeScenario(runs, options) {
298
298
  const scenario = {
299
299
  description: `Proposed from ${total} recorded run${total === 1 ? "" : "s"} of ${name} — review before committing`,
300
300
  completion,
301
- events,
302
- ...edges.length > 0 ? { edges } : {},
303
- ...optionalEdges.length > 0 ? { optionalEdges } : {}
301
+ events
304
302
  };
303
+ if (edges.length > 0) scenario.edges = edges;
304
+ if (optionalEdges.length > 0) scenario.optionalEdges = optionalEdges;
305
305
  validateScenarioSpec(name, scenario);
306
306
  return {
307
307
  scenario,
@@ -47,8 +47,8 @@ const COMPLETION_MODES = [
47
47
  */
48
48
  function validateScenarioSpec(name, spec) {
49
49
  const scope = `scenario "${name}"`;
50
- assert$1(spec.completion && typeof spec.completion === "object", `${scope} must declare a completion boundary`);
51
- assert$1(COMPLETION_MODES.includes(spec.completion.mode), `${scope} has invalid completion mode "${spec.completion.mode}"`);
50
+ assert$1(spec.completion !== void 0 && spec.completion !== null, `${scope} must declare a completion boundary`);
51
+ assert$1(COMPLETION_MODES.some((mode) => mode === spec.completion.mode), `${scope} has invalid completion mode "${spec.completion.mode}"`);
52
52
  const budget = spec.completion.mode === "externally-reconciled" ? spec.completion.reconciliationDeadlineMs : spec.completion.observationBudgetMs;
53
53
  assert$1(typeof budget === "number" && Number.isFinite(budget) && budget > 0, `${scope} completion budget must be a positive number of milliseconds`);
54
54
  switch (spec.completion.mode) {
@@ -61,7 +61,7 @@ function validateScenarioSpec(name, spec) {
61
61
  if (eventSpec.cardinality !== void 0) try {
62
62
  parseCardinality(eventSpec.cardinality);
63
63
  } catch (error) {
64
- throw new Error(`autotel-schema: ${scope} event "${event}": ${error.message}`);
64
+ throw new Error(`autotel-schema: ${scope} event "${event}": ${error instanceof Error ? error.message : String(error)}`);
65
65
  }
66
66
  if (eventSpec.status !== void 0) assert$1(eventSpec.status === "ok" || eventSpec.status === "error", `${scope} event "${event}" has invalid status "${eventSpec.status}"`);
67
67
  }
@@ -297,10 +297,10 @@ function proposeScenario(runs, options) {
297
297
  const scenario = {
298
298
  description: `Proposed from ${total} recorded run${total === 1 ? "" : "s"} of ${name} — review before committing`,
299
299
  completion,
300
- events,
301
- ...edges.length > 0 ? { edges } : {},
302
- ...optionalEdges.length > 0 ? { optionalEdges } : {}
300
+ events
303
301
  };
302
+ if (edges.length > 0) scenario.edges = edges;
303
+ if (optionalEdges.length > 0) scenario.optionalEdges = optionalEdges;
304
304
  validateScenarioSpec(name, scenario);
305
305
  return {
306
306
  scenario,
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_processor = require('./processor-Gu8Yl_dS.cjs');
2
+ const require_processor = require('./processor-C9NmN0wQ.cjs');
3
3
 
4
4
  exports.SchemaValidationSpanProcessor = require_processor.SchemaValidationSpanProcessor;
5
5
  exports.createSchemaValidationProcessor = require_processor.createSchemaValidationProcessor;
@@ -1,2 +1,71 @@
1
- import { a as SchemaValidationSpanProcessor, c as createSchemaValidationProcessor, i as SchemaValidationProcessorOptions, n as ReadableSpanLike, o as SpanLike, r as SchemaProcessorMode, s as SpanProcessorLike, t as OtelContext } from "./processor-DVcsS6Rz.cjs";
2
- export { OtelContext, ReadableSpanLike, SchemaProcessorMode, SchemaValidationProcessorOptions, SchemaValidationSpanProcessor, SpanLike, SpanProcessorLike, createSchemaValidationProcessor };
1
+ import { N as SchemaViolation, P as ValidateOptions, j as EmittedAttributeValue, s as TelemetryContract } from "./contract-CfOaZcD0.cjs";
2
+ //#region src/processor.d.ts
3
+ /** A ReadableSpan as this processor reads one, without a hard SDK dependency. */
4
+ interface ReadableSpanLike {
5
+ name: string;
6
+ attributes: Record<string, EmittedAttributeValue>;
7
+ }
8
+ interface SpanLike {
9
+ spanContext(): {
10
+ traceId: string;
11
+ spanId: string;
12
+ };
13
+ }
14
+ /**
15
+ * The parent context OTel hands a span processor. This package never reads it,
16
+ * and naming it here keeps the SpanProcessor signature matchable without taking
17
+ * a dependency on the SDK.
18
+ */
19
+ interface OtelContext {
20
+ getValue?: (key: symbol) => ContextValue;
21
+ }
22
+ /** Whatever OTel stored under a context key. This package never reads one. */
23
+ type ContextValue = object | string | number | boolean | undefined;
24
+ interface SpanProcessorLike {
25
+ onStart(span: SpanLike, parentContext: OtelContext): void;
26
+ onEnd(span: ReadableSpanLike): void;
27
+ shutdown(): Promise<void>;
28
+ forceFlush(): Promise<void>;
29
+ }
30
+ /** How the processor reacts to a contract violation. */
31
+ type SchemaProcessorMode = 'warn' | 'throw' | 'silent';
32
+ interface SchemaValidationProcessorOptions extends ValidateOptions {
33
+ contract: TelemetryContract;
34
+ /**
35
+ * `warn` (default): log each distinct violation once per interval.
36
+ * `throw`: throw on the first error-severity violation — for tests/CI only.
37
+ * `silent`: collect via `onViolation` without logging.
38
+ */
39
+ mode?: SchemaProcessorMode;
40
+ /** Called for every violation, before mode handling. */
41
+ onViolation?: (violation: SchemaViolation, span: ReadableSpanLike) => void;
42
+ /** Override the warn sink (defaults to `console.warn`). */
43
+ onWarn?: (message: string) => void;
44
+ /** Run even when `NODE_ENV === 'production'`. Default `false`. */
45
+ enabledInProduction?: boolean;
46
+ /** Throttle window for repeated identical warnings (ms). Default 60s. */
47
+ warnIntervalMs?: number;
48
+ }
49
+ /**
50
+ * Validates each ending span against a {@link TelemetryContract}. Bounded,
51
+ * deduplicated warnings; fail-open on any internal error.
52
+ */
53
+ declare class SchemaValidationSpanProcessor implements SpanProcessorLike {
54
+ private readonly opts;
55
+ private readonly enabled;
56
+ private readonly warnIntervalMs;
57
+ private readonly lastWarnAt;
58
+ private violationCount;
59
+ constructor(opts: SchemaValidationProcessorOptions);
60
+ /** Number of violations seen since startup (across all spans). */
61
+ get totalViolations(): number;
62
+ onStart(_span: SpanLike, _parentContext: OtelContext): void;
63
+ onEnd(span: ReadableSpanLike): void;
64
+ private handle;
65
+ private maybeWarn;
66
+ forceFlush(): Promise<void>;
67
+ shutdown(): Promise<void>;
68
+ }
69
+ declare function createSchemaValidationProcessor(opts: SchemaValidationProcessorOptions): SchemaValidationSpanProcessor;
70
+ //#endregion
71
+ export { ContextValue, OtelContext, ReadableSpanLike, SchemaProcessorMode, SchemaValidationProcessorOptions, SchemaValidationSpanProcessor, SpanLike, SpanProcessorLike, createSchemaValidationProcessor };
@@ -1,2 +1,71 @@
1
- import { a as SchemaValidationSpanProcessor, c as createSchemaValidationProcessor, i as SchemaValidationProcessorOptions, n as ReadableSpanLike, o as SpanLike, r as SchemaProcessorMode, s as SpanProcessorLike, t as OtelContext } from "./processor-TpuacLr5.js";
2
- export { OtelContext, ReadableSpanLike, SchemaProcessorMode, SchemaValidationProcessorOptions, SchemaValidationSpanProcessor, SpanLike, SpanProcessorLike, createSchemaValidationProcessor };
1
+ import { N as SchemaViolation, P as ValidateOptions, j as EmittedAttributeValue, s as TelemetryContract } from "./contract-CfOaZcD0.js";
2
+ //#region src/processor.d.ts
3
+ /** A ReadableSpan as this processor reads one, without a hard SDK dependency. */
4
+ interface ReadableSpanLike {
5
+ name: string;
6
+ attributes: Record<string, EmittedAttributeValue>;
7
+ }
8
+ interface SpanLike {
9
+ spanContext(): {
10
+ traceId: string;
11
+ spanId: string;
12
+ };
13
+ }
14
+ /**
15
+ * The parent context OTel hands a span processor. This package never reads it,
16
+ * and naming it here keeps the SpanProcessor signature matchable without taking
17
+ * a dependency on the SDK.
18
+ */
19
+ interface OtelContext {
20
+ getValue?: (key: symbol) => ContextValue;
21
+ }
22
+ /** Whatever OTel stored under a context key. This package never reads one. */
23
+ type ContextValue = object | string | number | boolean | undefined;
24
+ interface SpanProcessorLike {
25
+ onStart(span: SpanLike, parentContext: OtelContext): void;
26
+ onEnd(span: ReadableSpanLike): void;
27
+ shutdown(): Promise<void>;
28
+ forceFlush(): Promise<void>;
29
+ }
30
+ /** How the processor reacts to a contract violation. */
31
+ type SchemaProcessorMode = 'warn' | 'throw' | 'silent';
32
+ interface SchemaValidationProcessorOptions extends ValidateOptions {
33
+ contract: TelemetryContract;
34
+ /**
35
+ * `warn` (default): log each distinct violation once per interval.
36
+ * `throw`: throw on the first error-severity violation — for tests/CI only.
37
+ * `silent`: collect via `onViolation` without logging.
38
+ */
39
+ mode?: SchemaProcessorMode;
40
+ /** Called for every violation, before mode handling. */
41
+ onViolation?: (violation: SchemaViolation, span: ReadableSpanLike) => void;
42
+ /** Override the warn sink (defaults to `console.warn`). */
43
+ onWarn?: (message: string) => void;
44
+ /** Run even when `NODE_ENV === 'production'`. Default `false`. */
45
+ enabledInProduction?: boolean;
46
+ /** Throttle window for repeated identical warnings (ms). Default 60s. */
47
+ warnIntervalMs?: number;
48
+ }
49
+ /**
50
+ * Validates each ending span against a {@link TelemetryContract}. Bounded,
51
+ * deduplicated warnings; fail-open on any internal error.
52
+ */
53
+ declare class SchemaValidationSpanProcessor implements SpanProcessorLike {
54
+ private readonly opts;
55
+ private readonly enabled;
56
+ private readonly warnIntervalMs;
57
+ private readonly lastWarnAt;
58
+ private violationCount;
59
+ constructor(opts: SchemaValidationProcessorOptions);
60
+ /** Number of violations seen since startup (across all spans). */
61
+ get totalViolations(): number;
62
+ onStart(_span: SpanLike, _parentContext: OtelContext): void;
63
+ onEnd(span: ReadableSpanLike): void;
64
+ private handle;
65
+ private maybeWarn;
66
+ forceFlush(): Promise<void>;
67
+ shutdown(): Promise<void>;
68
+ }
69
+ declare function createSchemaValidationProcessor(opts: SchemaValidationProcessorOptions): SchemaValidationSpanProcessor;
70
+ //#endregion
71
+ export { ContextValue, OtelContext, ReadableSpanLike, SchemaProcessorMode, SchemaValidationProcessorOptions, SchemaValidationSpanProcessor, SpanLike, SpanProcessorLike, createSchemaValidationProcessor };
package/dist/processor.js CHANGED
@@ -1,3 +1,3 @@
1
- import { n as createSchemaValidationProcessor, t as SchemaValidationSpanProcessor } from "./processor-BPp_DewZ.js";
1
+ import { n as createSchemaValidationProcessor, t as SchemaValidationSpanProcessor } from "./processor-Cn0HNUvw.js";
2
2
 
3
3
  export { SchemaValidationSpanProcessor, createSchemaValidationProcessor };
@@ -40,9 +40,7 @@ function normalizeAttribute(spec) {
40
40
  return out;
41
41
  }
42
42
  function sortRecord(record) {
43
- const out = {};
44
- for (const key of Object.keys(record).toSorted()) out[key] = record[key];
45
- return out;
43
+ return Object.fromEntries(Object.keys(record).toSorted().map((key) => [key, record[key]]));
46
44
  }
47
45
  /**
48
46
  * Produce a deterministic, JSON-serializable snapshot from a contract. Keys are
@@ -41,9 +41,7 @@ function normalizeAttribute(spec) {
41
41
  return out;
42
42
  }
43
43
  function sortRecord(record) {
44
- const out = {};
45
- for (const key of Object.keys(record).toSorted()) out[key] = record[key];
46
- return out;
44
+ return Object.fromEntries(Object.keys(record).toSorted().map((key) => [key, record[key]]));
47
45
  }
48
46
  /**
49
47
  * Produce a deterministic, JSON-serializable snapshot from a contract. Keys are
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autotel-schema",
3
- "version": "10.0.0",
3
+ "version": "11.0.1",
4
4
  "description": "Your telemetry surface as a typed, versioned contract — declare the spans and attributes your service emits, validate live spans against them, and diff the surface across commits to catch breaking trace changes before they ship.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -44,7 +44,7 @@
44
44
  "author": "Jag Reehal <jag@jagreehal.com> (https://jagreehal.com)",
45
45
  "license": "Apache-2.0",
46
46
  "peerDependencies": {
47
- "autotel": "6.5.0"
47
+ "autotel": "7.0.1"
48
48
  },
49
49
  "peerDependenciesMeta": {
50
50
  "autotel": {
@@ -1,98 +0,0 @@
1
- import { s as TelemetryContract } from "./contract-Ymh_Q37N.cjs";
2
- //#region src/validate.d.ts
3
- /** Severity of a contract violation. `error` = a breaking-shaped problem. */
4
- type ViolationSeverity = 'error' | 'warning';
5
- type ViolationCode = 'unknown_span' | 'unknown_attribute' | 'type_mismatch' | 'missing_required' | 'deprecated_attribute' | 'enum_violation';
6
- /** A single discrepancy between an emitted span and the contract. */
7
- interface SchemaViolation {
8
- code: ViolationCode;
9
- severity: ViolationSeverity;
10
- spanName: string;
11
- /** Attribute key involved, when the violation is attribute-scoped. */
12
- attribute?: string;
13
- message: string;
14
- /** Nearest declared key, for likely typos (`unknown_attribute` only). */
15
- suggestion?: string;
16
- }
17
- /** Minimal emitted-span shape — avoids a hard dependency on the OTel SDK. */
18
- interface SpanShape {
19
- name: string;
20
- attributes: Record<string, unknown>;
21
- }
22
- interface ValidateOptions {
23
- /** Report `unknown_span` for span names not in the contract. Default `false`. */
24
- strictSpanNames?: boolean;
25
- }
26
- /**
27
- * Validate one emitted span against the contract, returning every discrepancy.
28
- * Order is deterministic: required-but-missing first, then per-attribute checks
29
- * in attribute insertion order.
30
- */
31
- declare function validateSpan(span: SpanShape, contract: TelemetryContract, options?: ValidateOptions): SchemaViolation[];
32
- /** `true` when any violation is `error` severity. */
33
- declare function hasErrors(violations: SchemaViolation[]): boolean;
34
- /** One-line human/agent-readable rendering of a violation. */
35
- declare function formatViolation(v: SchemaViolation): string;
36
- //#endregion
37
- //#region src/processor.d.ts
38
- /** Minimal ReadableSpan shape — matches OTel without a hard SDK dependency. */
39
- interface ReadableSpanLike {
40
- name: string;
41
- attributes: Record<string, unknown>;
42
- }
43
- interface SpanLike {
44
- spanContext(): {
45
- traceId: string;
46
- spanId: string;
47
- };
48
- }
49
- /** Opaque parent context — matches OTel SpanProcessor without importing it. */
50
- type OtelContext = unknown;
51
- interface SpanProcessorLike {
52
- onStart(span: SpanLike, parentContext: OtelContext): void;
53
- onEnd(span: ReadableSpanLike): void;
54
- shutdown(): Promise<void>;
55
- forceFlush(): Promise<void>;
56
- }
57
- /** How the processor reacts to a contract violation. */
58
- type SchemaProcessorMode = 'warn' | 'throw' | 'silent';
59
- interface SchemaValidationProcessorOptions extends ValidateOptions {
60
- contract: TelemetryContract;
61
- /**
62
- * `warn` (default): log each distinct violation once per interval.
63
- * `throw`: throw on the first error-severity violation — for tests/CI only.
64
- * `silent`: collect via `onViolation` without logging.
65
- */
66
- mode?: SchemaProcessorMode;
67
- /** Called for every violation, before mode handling. */
68
- onViolation?: (violation: SchemaViolation, span: ReadableSpanLike) => void;
69
- /** Override the warn sink (defaults to `console.warn`). */
70
- onWarn?: (message: string) => void;
71
- /** Run even when `NODE_ENV === 'production'`. Default `false`. */
72
- enabledInProduction?: boolean;
73
- /** Throttle window for repeated identical warnings (ms). Default 60s. */
74
- warnIntervalMs?: number;
75
- }
76
- /**
77
- * Validates each ending span against a {@link TelemetryContract}. Bounded,
78
- * deduplicated warnings; fail-open on any internal error.
79
- */
80
- declare class SchemaValidationSpanProcessor implements SpanProcessorLike {
81
- private readonly opts;
82
- private readonly enabled;
83
- private readonly warnIntervalMs;
84
- private readonly lastWarnAt;
85
- private violationCount;
86
- constructor(opts: SchemaValidationProcessorOptions);
87
- /** Number of violations seen since startup (across all spans). */
88
- get totalViolations(): number;
89
- onStart(_span: SpanLike, _parentContext: OtelContext): void;
90
- onEnd(span: ReadableSpanLike): void;
91
- private handle;
92
- private maybeWarn;
93
- forceFlush(): Promise<void>;
94
- shutdown(): Promise<void>;
95
- }
96
- declare function createSchemaValidationProcessor(opts: SchemaValidationProcessorOptions): SchemaValidationSpanProcessor;
97
- //#endregion
98
- export { SchemaValidationSpanProcessor as a, createSchemaValidationProcessor as c, ValidateOptions as d, ViolationCode as f, validateSpan as g, hasErrors as h, SchemaValidationProcessorOptions as i, SchemaViolation as l, formatViolation as m, ReadableSpanLike as n, SpanLike as o, ViolationSeverity as p, SchemaProcessorMode as r, SpanProcessorLike as s, OtelContext as t, SpanShape as u };
@@ -1,98 +0,0 @@
1
- import { s as TelemetryContract } from "./contract-Ymh_Q37N.js";
2
- //#region src/validate.d.ts
3
- /** Severity of a contract violation. `error` = a breaking-shaped problem. */
4
- type ViolationSeverity = 'error' | 'warning';
5
- type ViolationCode = 'unknown_span' | 'unknown_attribute' | 'type_mismatch' | 'missing_required' | 'deprecated_attribute' | 'enum_violation';
6
- /** A single discrepancy between an emitted span and the contract. */
7
- interface SchemaViolation {
8
- code: ViolationCode;
9
- severity: ViolationSeverity;
10
- spanName: string;
11
- /** Attribute key involved, when the violation is attribute-scoped. */
12
- attribute?: string;
13
- message: string;
14
- /** Nearest declared key, for likely typos (`unknown_attribute` only). */
15
- suggestion?: string;
16
- }
17
- /** Minimal emitted-span shape — avoids a hard dependency on the OTel SDK. */
18
- interface SpanShape {
19
- name: string;
20
- attributes: Record<string, unknown>;
21
- }
22
- interface ValidateOptions {
23
- /** Report `unknown_span` for span names not in the contract. Default `false`. */
24
- strictSpanNames?: boolean;
25
- }
26
- /**
27
- * Validate one emitted span against the contract, returning every discrepancy.
28
- * Order is deterministic: required-but-missing first, then per-attribute checks
29
- * in attribute insertion order.
30
- */
31
- declare function validateSpan(span: SpanShape, contract: TelemetryContract, options?: ValidateOptions): SchemaViolation[];
32
- /** `true` when any violation is `error` severity. */
33
- declare function hasErrors(violations: SchemaViolation[]): boolean;
34
- /** One-line human/agent-readable rendering of a violation. */
35
- declare function formatViolation(v: SchemaViolation): string;
36
- //#endregion
37
- //#region src/processor.d.ts
38
- /** Minimal ReadableSpan shape — matches OTel without a hard SDK dependency. */
39
- interface ReadableSpanLike {
40
- name: string;
41
- attributes: Record<string, unknown>;
42
- }
43
- interface SpanLike {
44
- spanContext(): {
45
- traceId: string;
46
- spanId: string;
47
- };
48
- }
49
- /** Opaque parent context — matches OTel SpanProcessor without importing it. */
50
- type OtelContext = unknown;
51
- interface SpanProcessorLike {
52
- onStart(span: SpanLike, parentContext: OtelContext): void;
53
- onEnd(span: ReadableSpanLike): void;
54
- shutdown(): Promise<void>;
55
- forceFlush(): Promise<void>;
56
- }
57
- /** How the processor reacts to a contract violation. */
58
- type SchemaProcessorMode = 'warn' | 'throw' | 'silent';
59
- interface SchemaValidationProcessorOptions extends ValidateOptions {
60
- contract: TelemetryContract;
61
- /**
62
- * `warn` (default): log each distinct violation once per interval.
63
- * `throw`: throw on the first error-severity violation — for tests/CI only.
64
- * `silent`: collect via `onViolation` without logging.
65
- */
66
- mode?: SchemaProcessorMode;
67
- /** Called for every violation, before mode handling. */
68
- onViolation?: (violation: SchemaViolation, span: ReadableSpanLike) => void;
69
- /** Override the warn sink (defaults to `console.warn`). */
70
- onWarn?: (message: string) => void;
71
- /** Run even when `NODE_ENV === 'production'`. Default `false`. */
72
- enabledInProduction?: boolean;
73
- /** Throttle window for repeated identical warnings (ms). Default 60s. */
74
- warnIntervalMs?: number;
75
- }
76
- /**
77
- * Validates each ending span against a {@link TelemetryContract}. Bounded,
78
- * deduplicated warnings; fail-open on any internal error.
79
- */
80
- declare class SchemaValidationSpanProcessor implements SpanProcessorLike {
81
- private readonly opts;
82
- private readonly enabled;
83
- private readonly warnIntervalMs;
84
- private readonly lastWarnAt;
85
- private violationCount;
86
- constructor(opts: SchemaValidationProcessorOptions);
87
- /** Number of violations seen since startup (across all spans). */
88
- get totalViolations(): number;
89
- onStart(_span: SpanLike, _parentContext: OtelContext): void;
90
- onEnd(span: ReadableSpanLike): void;
91
- private handle;
92
- private maybeWarn;
93
- forceFlush(): Promise<void>;
94
- shutdown(): Promise<void>;
95
- }
96
- declare function createSchemaValidationProcessor(opts: SchemaValidationProcessorOptions): SchemaValidationSpanProcessor;
97
- //#endregion
98
- export { SchemaValidationSpanProcessor as a, createSchemaValidationProcessor as c, ValidateOptions as d, ViolationCode as f, validateSpan as g, hasErrors as h, SchemaValidationProcessorOptions as i, SchemaViolation as l, formatViolation as m, ReadableSpanLike as n, SpanLike as o, ViolationSeverity as p, SchemaProcessorMode as r, SpanProcessorLike as s, OtelContext as t, SpanShape as u };