autotel 3.5.0 → 3.6.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 (92) hide show
  1. package/dist/{chunk-O4JZUCUE.js → chunk-66YJ66GG.js} +5 -158
  2. package/dist/chunk-66YJ66GG.js.map +1 -0
  3. package/dist/{chunk-Z6HRSM2Y.cjs → chunk-B7SWBE4P.cjs} +5 -5
  4. package/dist/{chunk-Z6HRSM2Y.cjs.map → chunk-B7SWBE4P.cjs.map} +1 -1
  5. package/dist/{chunk-DQEHQNQE.js → chunk-D4TM63S3.js} +3 -3
  6. package/dist/{chunk-DQEHQNQE.js.map → chunk-D4TM63S3.js.map} +1 -1
  7. package/dist/chunk-DCEDJQGG.js +28 -0
  8. package/dist/chunk-DCEDJQGG.js.map +1 -0
  9. package/dist/chunk-E6TERL5O.cjs +23 -0
  10. package/dist/chunk-E6TERL5O.cjs.map +1 -0
  11. package/dist/chunk-EE6CPXKH.cjs +164 -0
  12. package/dist/chunk-EE6CPXKH.cjs.map +1 -0
  13. package/dist/{chunk-GBFTC7Q7.cjs → chunk-EOFB7XCL.cjs} +6 -6
  14. package/dist/{chunk-GBFTC7Q7.cjs.map → chunk-EOFB7XCL.cjs.map} +1 -1
  15. package/dist/{chunk-Z7PW3KHL.cjs → chunk-FMTHVSYY.cjs} +4 -163
  16. package/dist/chunk-FMTHVSYY.cjs.map +1 -0
  17. package/dist/{chunk-VG2ABKJX.cjs → chunk-KYXZS3EA.cjs} +7 -7
  18. package/dist/{chunk-VG2ABKJX.cjs.map → chunk-KYXZS3EA.cjs.map} +1 -1
  19. package/dist/chunk-LVIPBYFE.js +157 -0
  20. package/dist/chunk-LVIPBYFE.js.map +1 -0
  21. package/dist/{chunk-NVGPMGI4.js → chunk-N25JDZSC.js} +3 -3
  22. package/dist/{chunk-NVGPMGI4.js.map → chunk-N25JDZSC.js.map} +1 -1
  23. package/dist/{chunk-AC5GNZKB.cjs → chunk-NENU7E6V.cjs} +5 -5
  24. package/dist/{chunk-AC5GNZKB.cjs.map → chunk-NENU7E6V.cjs.map} +1 -1
  25. package/dist/{chunk-URHPSJW2.js → chunk-QF7ARNUM.js} +3 -3
  26. package/dist/{chunk-URHPSJW2.js.map → chunk-QF7ARNUM.js.map} +1 -1
  27. package/dist/chunk-T5WRA76K.cjs +32 -0
  28. package/dist/chunk-T5WRA76K.cjs.map +1 -0
  29. package/dist/{chunk-YWCESU4Y.js → chunk-T7JO2TCP.js} +3 -3
  30. package/dist/{chunk-YWCESU4Y.js.map → chunk-T7JO2TCP.js.map} +1 -1
  31. package/dist/{chunk-O7JOKRN2.js → chunk-UIKYE2QZ.js} +3 -3
  32. package/dist/{chunk-O7JOKRN2.js.map → chunk-UIKYE2QZ.js.map} +1 -1
  33. package/dist/chunk-UNPLAVE7.js +21 -0
  34. package/dist/chunk-UNPLAVE7.js.map +1 -0
  35. package/dist/{chunk-FGNDN2FD.cjs → chunk-V7UBMJAB.cjs} +18 -18
  36. package/dist/{chunk-FGNDN2FD.cjs.map → chunk-V7UBMJAB.cjs.map} +1 -1
  37. package/dist/correlation-id.cjs +10 -9
  38. package/dist/correlation-id.js +2 -1
  39. package/dist/decorators.cjs +4 -3
  40. package/dist/decorators.cjs.map +1 -1
  41. package/dist/decorators.js +3 -2
  42. package/dist/decorators.js.map +1 -1
  43. package/dist/define-event-BL6Li7CM.d.ts +23 -0
  44. package/dist/define-event-ClP3T1Jx.d.cts +23 -0
  45. package/dist/event.cjs +6 -5
  46. package/dist/event.js +3 -2
  47. package/dist/functional.cjs +11 -10
  48. package/dist/functional.js +3 -2
  49. package/dist/http.cjs +3 -2
  50. package/dist/http.cjs.map +1 -1
  51. package/dist/http.js +2 -1
  52. package/dist/http.js.map +1 -1
  53. package/dist/index.cjs +86 -97
  54. package/dist/index.cjs.map +1 -1
  55. package/dist/index.d.cts +2 -21
  56. package/dist/index.d.ts +2 -21
  57. package/dist/index.js +16 -26
  58. package/dist/index.js.map +1 -1
  59. package/dist/messaging.cjs +7 -6
  60. package/dist/messaging.js +4 -3
  61. package/dist/semantic-helpers.cjs +8 -7
  62. package/dist/semantic-helpers.js +4 -3
  63. package/dist/validate.cjs +138 -0
  64. package/dist/validate.cjs.map +1 -0
  65. package/dist/validate.d.cts +129 -0
  66. package/dist/validate.d.ts +129 -0
  67. package/dist/validate.js +133 -0
  68. package/dist/validate.js.map +1 -0
  69. package/dist/validation-attributes.cjs +20 -0
  70. package/dist/validation-attributes.cjs.map +1 -0
  71. package/dist/validation-attributes.d.cts +40 -0
  72. package/dist/validation-attributes.d.ts +40 -0
  73. package/dist/validation-attributes.js +3 -0
  74. package/dist/validation-attributes.js.map +1 -0
  75. package/dist/webhook.cjs +5 -4
  76. package/dist/webhook.cjs.map +1 -1
  77. package/dist/webhook.js +3 -2
  78. package/dist/webhook.js.map +1 -1
  79. package/dist/workflow-distributed.cjs +5 -4
  80. package/dist/workflow-distributed.cjs.map +1 -1
  81. package/dist/workflow-distributed.js +3 -2
  82. package/dist/workflow-distributed.js.map +1 -1
  83. package/dist/workflow.cjs +8 -7
  84. package/dist/workflow.js +4 -3
  85. package/package.json +11 -1
  86. package/src/define-event.ts +2 -21
  87. package/src/stable-hash.ts +27 -0
  88. package/src/validate.test.ts +285 -0
  89. package/src/validate.ts +301 -0
  90. package/src/validation-attributes.ts +43 -0
  91. package/dist/chunk-O4JZUCUE.js.map +0 -1
  92. package/dist/chunk-Z7PW3KHL.cjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/validate.ts"],"names":["createCounter","VALIDATION_METRICS","VALIDATION_ISSUE_CAP","trace","VALIDATION_ATTR","createStructuredError","hashJson"],"mappings":"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","file":"validate.cjs","sourcesContent":["/**\n * Validation telemetry — connect runtime input validation (Zod or any\n * `safeParse` schema) to your traces and metrics at the boundaries where bad\n * data actually enters: HTTP bodies, events, messages.\n *\n * Today a `safeParse` failure either throws (no span, no metric, no alert) or\n * is silently swallowed in a handler. `defineValidator` makes the mismatch\n * **observable** — a `validation.*` span attribute set and a counter\n * incremented — with a per-validator `observe` vs `reject` mode:\n *\n * - `reject` (default): record telemetry, then throw a structured 400-shaped\n * error so the boundary can fail cleanly.\n * - `observe`: record telemetry, return the raw input so the handler continues\n * — useful for measuring real-world drift before you enforce it.\n *\n * **Not a security feature by default.** A malformed body is usually a bug or\n * version skew, not an attack. Validation telemetry is first-class on its own\n * metric; escalation to the security path is a deliberate opt-in via\n * {@link onValidationMismatch} (e.g. wired by `autotel-audit`), never automatic.\n *\n * **PII-safe by construction.** Only field *paths*, issue *codes*, and the\n * declared *type* are ever recorded — never the offending value, and never a\n * validator's error `message` (which routinely embeds the received value).\n */\n\nimport { trace } from '@opentelemetry/api';\nimport { createCounter } from './metric-helpers';\nimport { createStructuredError, type StructuredError } from './structured-error';\nimport { hashJson } from './stable-hash';\nimport type { SchemaLike } from './define-event';\nimport {\n VALIDATION_ATTR,\n VALIDATION_ISSUE_CAP,\n VALIDATION_METRICS,\n} from './validation-attributes';\n\nexport type { SchemaLike } from './define-event';\n\nexport type ValidationMode = 'observe' | 'reject';\nexport type ValidationSeverity = 'info' | 'warning' | 'error';\n\n/** A single failing field, stripped of any payload values. */\nexport interface ValidationIssue {\n /** Dotted field path, e.g. `items.0.price`. Never a value. */\n path: string;\n /** Issue code (e.g. Zod's `invalid_type`, `too_small`). Never a value. */\n code: string;\n /** Declared type/constraint summary, e.g. `string`. Never a received value. */\n expected?: string;\n}\n\n/** Everything the recorder needs — already PII-stripped by the caller. */\nexport interface ValidationMismatch {\n /** Contract id, e.g. `POST /orders` or `order.placed`. */\n name: string;\n boundary: string;\n mode: ValidationMode;\n issues: ValidationIssue[];\n hash?: string;\n severity?: ValidationSeverity;\n}\n\nlet mismatchCounter: ReturnType<typeof createCounter> | undefined;\nfunction counter(): ReturnType<typeof createCounter> {\n if (!mismatchCounter) {\n mismatchCounter = createCounter(VALIDATION_METRICS.mismatches, {\n description: 'Input payloads that did not match their declared shape',\n });\n }\n return mismatchCounter;\n}\n\ntype MismatchListener = (mismatch: ValidationMismatch) => void;\nconst listeners = new Set<MismatchListener>();\n\n/**\n * Register an explicit handler called on every recorded mismatch — the opt-in\n * seam for escalating to security events, a webhook, or a custom sink. There is\n * no automatic, package-presence-driven escalation: nothing fires here unless\n * you (or a package you wire up) register a handler.\n *\n * Multiple subscribers coexist: a package (e.g. `autotel-audit` bridging to\n * security events) and your own app code (a webhook, a logger) can both\n * register and all fire. Returns an unsubscribe fn that removes only this\n * handler; registering the same function twice is a no-op (Set semantics).\n */\nexport function onValidationMismatch(handler: MismatchListener): () => void {\n listeners.add(handler);\n return () => {\n listeners.delete(handler);\n };\n}\n\nconst truncate = (values: string[]): string =>\n values.slice(0, VALIDATION_ISSUE_CAP).join(',');\n\n/**\n * Record a validation mismatch as telemetry: `validation.*` attributes on the\n * active span (if any) and an increment on `autotel.validation.mismatches`.\n * Fail-open — never throws, so instrumentation can't break the boundary.\n */\nexport function recordValidationMismatch(mismatch: ValidationMismatch): void {\n try {\n const paths = mismatch.issues.map((i) => i.path).filter(Boolean);\n const codes = [...new Set(mismatch.issues.map((i) => i.code))];\n\n const span = trace.getActiveSpan();\n if (span) {\n span.setAttributes({\n [VALIDATION_ATTR.name]: mismatch.name,\n [VALIDATION_ATTR.boundary]: mismatch.boundary,\n [VALIDATION_ATTR.mode]: mismatch.mode,\n [VALIDATION_ATTR.issueCount]: mismatch.issues.length,\n [VALIDATION_ATTR.issuePaths]: truncate(paths),\n [VALIDATION_ATTR.issueCodes]: truncate(codes),\n ...(mismatch.hash ? { [VALIDATION_ATTR.hash]: mismatch.hash } : {}),\n ...(mismatch.severity\n ? { [VALIDATION_ATTR.severity]: mismatch.severity }\n : {}),\n });\n }\n\n try {\n counter().add(1, {\n boundary: mismatch.boundary,\n validation: mismatch.name,\n mode: mismatch.mode,\n });\n } catch {\n // meter not initialised yet — skip the count, keep the span attrs\n }\n\n // Dispatch to every subscriber with per-listener fault isolation: one\n // throwing subscriber must not starve its peers or break the boundary.\n // Set iteration tolerates concurrent (un)subscription safely.\n for (const listener of listeners) {\n try {\n listener(mismatch);\n } catch {\n // a misbehaving subscriber must not break the boundary or its peers\n }\n }\n } catch {\n // fail-open: telemetry must never break the validated boundary\n }\n}\n\n/**\n * Normalise an arbitrary validation error into PII-safe issues. Reads only\n * `path`, `code`, and (when it is a declared type name) `expected` — and never\n * `message`, `received`, or any value-bearing field. Understands the Zod shape\n * (`error.issues`) and a generic `error.errors` fallback; returns `[]` for\n * anything unrecognised.\n */\nexport function formatValidationIssues(error: unknown): ValidationIssue[] {\n const raw = extractRawIssues(error);\n return raw.map((issue) => toSafeIssue(issue));\n}\n\nfunction extractRawIssues(error: unknown): Array<Record<string, unknown>> {\n if (error && typeof error === 'object') {\n const candidate =\n (error as { issues?: unknown }).issues ??\n (error as { errors?: unknown }).errors;\n if (Array.isArray(candidate)) {\n return candidate.filter(\n (i): i is Record<string, unknown> => i !== null && typeof i === 'object',\n );\n }\n }\n return [];\n}\n\nfunction toSafeIssue(issue: Record<string, unknown>): ValidationIssue {\n const rawPath = issue.path;\n const path = Array.isArray(rawPath)\n ? rawPath.map(String).join('.')\n : typeof rawPath === 'string'\n ? rawPath\n : '';\n const code = typeof issue.code === 'string' ? issue.code : 'invalid';\n // `expected` is a declared type name in Zod (e.g. 'string'); safe. We never\n // read `received`/`message`/`value`, which can carry the offending payload.\n const expected =\n typeof issue.expected === 'string' ? issue.expected : undefined;\n return expected ? { path, code, expected } : { path, code };\n}\n\nexport interface DefineValidatorOptions<S> {\n /** Where validation runs. Defaults to `input`. */\n boundary?: string;\n /** `reject` (default): record then throw. `observe`: record then continue. */\n onMismatch?: ValidationMode;\n /** Project the schema to JSON Schema for a stable `validation.hash`. */\n toJsonSchema?: (schema: S) => unknown;\n severity?: ValidationSeverity;\n /** Build the error thrown in `reject` mode (defaults to a 400 structured error). */\n onReject?: (issues: ValidationIssue[], name: string) => Error;\n}\n\nexport type ValidatorResult<T> =\n | { success: true; data: T }\n | { success: false; issues: ValidationIssue[] };\n\nexport interface Validator<T> {\n readonly name: string;\n readonly mode: ValidationMode;\n /** Validate and record on failure; never throws. */\n safeParse(input: unknown): ValidatorResult<T>;\n /**\n * Validate, record on failure, then apply the mode: `reject` throws,\n * `observe` returns the raw input so the handler can continue.\n */\n parse(input: unknown): T;\n}\n\nfunction defaultRejectError(\n issues: ValidationIssue[],\n name: string,\n): StructuredError {\n return createStructuredError({\n name: 'ValidationError',\n status: 400,\n code: 'validation_failed',\n message: `Input for \"${name}\" did not match its declared shape.`,\n why: `${issues.length} field(s) failed validation: ${issues\n .map((i) => i.path || '(root)')\n .slice(0, VALIDATION_ISSUE_CAP)\n .join(', ')}.`,\n fix: 'Send a payload that matches the schema, or switch this validator to observe mode while you investigate.',\n // PII-safe: paths + codes only, no received values.\n details: { validation: name, issues },\n });\n}\n\n/**\n * Declare an expected input shape once and get a validator that records every\n * mismatch as telemetry.\n *\n * @example\n * ```ts\n * import { z } from 'zod';\n * import { defineValidator } from 'autotel/validate';\n *\n * const OrderBody = defineValidator('POST /orders', z.object({\n * items: z.array(z.object({ sku: z.string(), qty: z.number().int() })),\n * }), { boundary: 'http', toJsonSchema: (s) => z.toJSONSchema(s) });\n *\n * // reject mode (default): records + throws a 400-shaped structured error\n * const order = OrderBody.parse(req.body);\n *\n * // observe mode: records, returns the result, never throws\n * const result = OrderBody.safeParse(req.body);\n * if (!result.success) metrics.onDrift(result.issues);\n * ```\n */\nexport function defineValidator<T, S extends SchemaLike<T>>(\n name: string,\n schema: S,\n options: DefineValidatorOptions<S> = {},\n): Validator<T> {\n const mode = options.onMismatch ?? 'reject';\n const boundary = options.boundary ?? 'input';\n const hash = options.toJsonSchema\n ? hashJson(options.toJsonSchema(schema))\n : undefined;\n\n const record = (issues: ValidationIssue[]): void => {\n recordValidationMismatch({\n name,\n boundary,\n mode,\n issues,\n hash,\n severity: options.severity,\n });\n };\n\n return {\n name,\n mode,\n safeParse(input: unknown): ValidatorResult<T> {\n const parsed = schema.safeParse(input);\n if (parsed.success) return { success: true, data: parsed.data };\n const issues = formatValidationIssues(parsed.error);\n record(issues);\n return { success: false, issues };\n },\n parse(input: unknown): T {\n const parsed = schema.safeParse(input);\n if (parsed.success) return parsed.data;\n const issues = formatValidationIssues(parsed.error);\n record(issues);\n if (mode === 'reject') {\n throw options.onReject?.(issues, name) ?? defaultRejectError(issues, name);\n }\n // observe: continue with the raw input (documented type caveat)\n return input as T;\n },\n };\n}\n"]}
@@ -0,0 +1,129 @@
1
+ import { S as SchemaLike } from './define-event-ClP3T1Jx.cjs';
2
+ import './event-subscriber.cjs';
3
+
4
+ /**
5
+ * Validation telemetry — connect runtime input validation (Zod or any
6
+ * `safeParse` schema) to your traces and metrics at the boundaries where bad
7
+ * data actually enters: HTTP bodies, events, messages.
8
+ *
9
+ * Today a `safeParse` failure either throws (no span, no metric, no alert) or
10
+ * is silently swallowed in a handler. `defineValidator` makes the mismatch
11
+ * **observable** — a `validation.*` span attribute set and a counter
12
+ * incremented — with a per-validator `observe` vs `reject` mode:
13
+ *
14
+ * - `reject` (default): record telemetry, then throw a structured 400-shaped
15
+ * error so the boundary can fail cleanly.
16
+ * - `observe`: record telemetry, return the raw input so the handler continues
17
+ * — useful for measuring real-world drift before you enforce it.
18
+ *
19
+ * **Not a security feature by default.** A malformed body is usually a bug or
20
+ * version skew, not an attack. Validation telemetry is first-class on its own
21
+ * metric; escalation to the security path is a deliberate opt-in via
22
+ * {@link onValidationMismatch} (e.g. wired by `autotel-audit`), never automatic.
23
+ *
24
+ * **PII-safe by construction.** Only field *paths*, issue *codes*, and the
25
+ * declared *type* are ever recorded — never the offending value, and never a
26
+ * validator's error `message` (which routinely embeds the received value).
27
+ */
28
+
29
+ type ValidationMode = 'observe' | 'reject';
30
+ type ValidationSeverity = 'info' | 'warning' | 'error';
31
+ /** A single failing field, stripped of any payload values. */
32
+ interface ValidationIssue {
33
+ /** Dotted field path, e.g. `items.0.price`. Never a value. */
34
+ path: string;
35
+ /** Issue code (e.g. Zod's `invalid_type`, `too_small`). Never a value. */
36
+ code: string;
37
+ /** Declared type/constraint summary, e.g. `string`. Never a received value. */
38
+ expected?: string;
39
+ }
40
+ /** Everything the recorder needs — already PII-stripped by the caller. */
41
+ interface ValidationMismatch {
42
+ /** Contract id, e.g. `POST /orders` or `order.placed`. */
43
+ name: string;
44
+ boundary: string;
45
+ mode: ValidationMode;
46
+ issues: ValidationIssue[];
47
+ hash?: string;
48
+ severity?: ValidationSeverity;
49
+ }
50
+ type MismatchListener = (mismatch: ValidationMismatch) => void;
51
+ /**
52
+ * Register an explicit handler called on every recorded mismatch — the opt-in
53
+ * seam for escalating to security events, a webhook, or a custom sink. There is
54
+ * no automatic, package-presence-driven escalation: nothing fires here unless
55
+ * you (or a package you wire up) register a handler.
56
+ *
57
+ * Multiple subscribers coexist: a package (e.g. `autotel-audit` bridging to
58
+ * security events) and your own app code (a webhook, a logger) can both
59
+ * register and all fire. Returns an unsubscribe fn that removes only this
60
+ * handler; registering the same function twice is a no-op (Set semantics).
61
+ */
62
+ declare function onValidationMismatch(handler: MismatchListener): () => void;
63
+ /**
64
+ * Record a validation mismatch as telemetry: `validation.*` attributes on the
65
+ * active span (if any) and an increment on `autotel.validation.mismatches`.
66
+ * Fail-open — never throws, so instrumentation can't break the boundary.
67
+ */
68
+ declare function recordValidationMismatch(mismatch: ValidationMismatch): void;
69
+ /**
70
+ * Normalise an arbitrary validation error into PII-safe issues. Reads only
71
+ * `path`, `code`, and (when it is a declared type name) `expected` — and never
72
+ * `message`, `received`, or any value-bearing field. Understands the Zod shape
73
+ * (`error.issues`) and a generic `error.errors` fallback; returns `[]` for
74
+ * anything unrecognised.
75
+ */
76
+ declare function formatValidationIssues(error: unknown): ValidationIssue[];
77
+ interface DefineValidatorOptions<S> {
78
+ /** Where validation runs. Defaults to `input`. */
79
+ boundary?: string;
80
+ /** `reject` (default): record then throw. `observe`: record then continue. */
81
+ onMismatch?: ValidationMode;
82
+ /** Project the schema to JSON Schema for a stable `validation.hash`. */
83
+ toJsonSchema?: (schema: S) => unknown;
84
+ severity?: ValidationSeverity;
85
+ /** Build the error thrown in `reject` mode (defaults to a 400 structured error). */
86
+ onReject?: (issues: ValidationIssue[], name: string) => Error;
87
+ }
88
+ type ValidatorResult<T> = {
89
+ success: true;
90
+ data: T;
91
+ } | {
92
+ success: false;
93
+ issues: ValidationIssue[];
94
+ };
95
+ interface Validator<T> {
96
+ readonly name: string;
97
+ readonly mode: ValidationMode;
98
+ /** Validate and record on failure; never throws. */
99
+ safeParse(input: unknown): ValidatorResult<T>;
100
+ /**
101
+ * Validate, record on failure, then apply the mode: `reject` throws,
102
+ * `observe` returns the raw input so the handler can continue.
103
+ */
104
+ parse(input: unknown): T;
105
+ }
106
+ /**
107
+ * Declare an expected input shape once and get a validator that records every
108
+ * mismatch as telemetry.
109
+ *
110
+ * @example
111
+ * ```ts
112
+ * import { z } from 'zod';
113
+ * import { defineValidator } from 'autotel/validate';
114
+ *
115
+ * const OrderBody = defineValidator('POST /orders', z.object({
116
+ * items: z.array(z.object({ sku: z.string(), qty: z.number().int() })),
117
+ * }), { boundary: 'http', toJsonSchema: (s) => z.toJSONSchema(s) });
118
+ *
119
+ * // reject mode (default): records + throws a 400-shaped structured error
120
+ * const order = OrderBody.parse(req.body);
121
+ *
122
+ * // observe mode: records, returns the result, never throws
123
+ * const result = OrderBody.safeParse(req.body);
124
+ * if (!result.success) metrics.onDrift(result.issues);
125
+ * ```
126
+ */
127
+ declare function defineValidator<T, S extends SchemaLike<T>>(name: string, schema: S, options?: DefineValidatorOptions<S>): Validator<T>;
128
+
129
+ export { type DefineValidatorOptions, SchemaLike, type ValidationIssue, type ValidationMismatch, type ValidationMode, type ValidationSeverity, type Validator, type ValidatorResult, defineValidator, formatValidationIssues, onValidationMismatch, recordValidationMismatch };
@@ -0,0 +1,129 @@
1
+ import { S as SchemaLike } from './define-event-BL6Li7CM.js';
2
+ import './event-subscriber.js';
3
+
4
+ /**
5
+ * Validation telemetry — connect runtime input validation (Zod or any
6
+ * `safeParse` schema) to your traces and metrics at the boundaries where bad
7
+ * data actually enters: HTTP bodies, events, messages.
8
+ *
9
+ * Today a `safeParse` failure either throws (no span, no metric, no alert) or
10
+ * is silently swallowed in a handler. `defineValidator` makes the mismatch
11
+ * **observable** — a `validation.*` span attribute set and a counter
12
+ * incremented — with a per-validator `observe` vs `reject` mode:
13
+ *
14
+ * - `reject` (default): record telemetry, then throw a structured 400-shaped
15
+ * error so the boundary can fail cleanly.
16
+ * - `observe`: record telemetry, return the raw input so the handler continues
17
+ * — useful for measuring real-world drift before you enforce it.
18
+ *
19
+ * **Not a security feature by default.** A malformed body is usually a bug or
20
+ * version skew, not an attack. Validation telemetry is first-class on its own
21
+ * metric; escalation to the security path is a deliberate opt-in via
22
+ * {@link onValidationMismatch} (e.g. wired by `autotel-audit`), never automatic.
23
+ *
24
+ * **PII-safe by construction.** Only field *paths*, issue *codes*, and the
25
+ * declared *type* are ever recorded — never the offending value, and never a
26
+ * validator's error `message` (which routinely embeds the received value).
27
+ */
28
+
29
+ type ValidationMode = 'observe' | 'reject';
30
+ type ValidationSeverity = 'info' | 'warning' | 'error';
31
+ /** A single failing field, stripped of any payload values. */
32
+ interface ValidationIssue {
33
+ /** Dotted field path, e.g. `items.0.price`. Never a value. */
34
+ path: string;
35
+ /** Issue code (e.g. Zod's `invalid_type`, `too_small`). Never a value. */
36
+ code: string;
37
+ /** Declared type/constraint summary, e.g. `string`. Never a received value. */
38
+ expected?: string;
39
+ }
40
+ /** Everything the recorder needs — already PII-stripped by the caller. */
41
+ interface ValidationMismatch {
42
+ /** Contract id, e.g. `POST /orders` or `order.placed`. */
43
+ name: string;
44
+ boundary: string;
45
+ mode: ValidationMode;
46
+ issues: ValidationIssue[];
47
+ hash?: string;
48
+ severity?: ValidationSeverity;
49
+ }
50
+ type MismatchListener = (mismatch: ValidationMismatch) => void;
51
+ /**
52
+ * Register an explicit handler called on every recorded mismatch — the opt-in
53
+ * seam for escalating to security events, a webhook, or a custom sink. There is
54
+ * no automatic, package-presence-driven escalation: nothing fires here unless
55
+ * you (or a package you wire up) register a handler.
56
+ *
57
+ * Multiple subscribers coexist: a package (e.g. `autotel-audit` bridging to
58
+ * security events) and your own app code (a webhook, a logger) can both
59
+ * register and all fire. Returns an unsubscribe fn that removes only this
60
+ * handler; registering the same function twice is a no-op (Set semantics).
61
+ */
62
+ declare function onValidationMismatch(handler: MismatchListener): () => void;
63
+ /**
64
+ * Record a validation mismatch as telemetry: `validation.*` attributes on the
65
+ * active span (if any) and an increment on `autotel.validation.mismatches`.
66
+ * Fail-open — never throws, so instrumentation can't break the boundary.
67
+ */
68
+ declare function recordValidationMismatch(mismatch: ValidationMismatch): void;
69
+ /**
70
+ * Normalise an arbitrary validation error into PII-safe issues. Reads only
71
+ * `path`, `code`, and (when it is a declared type name) `expected` — and never
72
+ * `message`, `received`, or any value-bearing field. Understands the Zod shape
73
+ * (`error.issues`) and a generic `error.errors` fallback; returns `[]` for
74
+ * anything unrecognised.
75
+ */
76
+ declare function formatValidationIssues(error: unknown): ValidationIssue[];
77
+ interface DefineValidatorOptions<S> {
78
+ /** Where validation runs. Defaults to `input`. */
79
+ boundary?: string;
80
+ /** `reject` (default): record then throw. `observe`: record then continue. */
81
+ onMismatch?: ValidationMode;
82
+ /** Project the schema to JSON Schema for a stable `validation.hash`. */
83
+ toJsonSchema?: (schema: S) => unknown;
84
+ severity?: ValidationSeverity;
85
+ /** Build the error thrown in `reject` mode (defaults to a 400 structured error). */
86
+ onReject?: (issues: ValidationIssue[], name: string) => Error;
87
+ }
88
+ type ValidatorResult<T> = {
89
+ success: true;
90
+ data: T;
91
+ } | {
92
+ success: false;
93
+ issues: ValidationIssue[];
94
+ };
95
+ interface Validator<T> {
96
+ readonly name: string;
97
+ readonly mode: ValidationMode;
98
+ /** Validate and record on failure; never throws. */
99
+ safeParse(input: unknown): ValidatorResult<T>;
100
+ /**
101
+ * Validate, record on failure, then apply the mode: `reject` throws,
102
+ * `observe` returns the raw input so the handler can continue.
103
+ */
104
+ parse(input: unknown): T;
105
+ }
106
+ /**
107
+ * Declare an expected input shape once and get a validator that records every
108
+ * mismatch as telemetry.
109
+ *
110
+ * @example
111
+ * ```ts
112
+ * import { z } from 'zod';
113
+ * import { defineValidator } from 'autotel/validate';
114
+ *
115
+ * const OrderBody = defineValidator('POST /orders', z.object({
116
+ * items: z.array(z.object({ sku: z.string(), qty: z.number().int() })),
117
+ * }), { boundary: 'http', toJsonSchema: (s) => z.toJSONSchema(s) });
118
+ *
119
+ * // reject mode (default): records + throws a 400-shaped structured error
120
+ * const order = OrderBody.parse(req.body);
121
+ *
122
+ * // observe mode: records, returns the result, never throws
123
+ * const result = OrderBody.safeParse(req.body);
124
+ * if (!result.success) metrics.onDrift(result.issues);
125
+ * ```
126
+ */
127
+ declare function defineValidator<T, S extends SchemaLike<T>>(name: string, schema: S, options?: DefineValidatorOptions<S>): Validator<T>;
128
+
129
+ export { type DefineValidatorOptions, SchemaLike, type ValidationIssue, type ValidationMismatch, type ValidationMode, type ValidationSeverity, type Validator, type ValidatorResult, defineValidator, formatValidationIssues, onValidationMismatch, recordValidationMismatch };
@@ -0,0 +1,133 @@
1
+ import { VALIDATION_ATTR, VALIDATION_ISSUE_CAP, VALIDATION_METRICS } from './chunk-DCEDJQGG.js';
2
+ import { hashJson } from './chunk-UNPLAVE7.js';
3
+ import { createCounter } from './chunk-TQ5UWA7S.js';
4
+ import { createStructuredError } from './chunk-LVIPBYFE.js';
5
+ import './chunk-J5QENANM.js';
6
+ import './chunk-HA2WBOGQ.js';
7
+ import { trace } from '@opentelemetry/api';
8
+
9
+ var mismatchCounter;
10
+ function counter() {
11
+ if (!mismatchCounter) {
12
+ mismatchCounter = createCounter(VALIDATION_METRICS.mismatches, {
13
+ description: "Input payloads that did not match their declared shape"
14
+ });
15
+ }
16
+ return mismatchCounter;
17
+ }
18
+ var listeners = /* @__PURE__ */ new Set();
19
+ function onValidationMismatch(handler) {
20
+ listeners.add(handler);
21
+ return () => {
22
+ listeners.delete(handler);
23
+ };
24
+ }
25
+ var truncate = (values) => values.slice(0, VALIDATION_ISSUE_CAP).join(",");
26
+ function recordValidationMismatch(mismatch) {
27
+ try {
28
+ const paths = mismatch.issues.map((i) => i.path).filter(Boolean);
29
+ const codes = [...new Set(mismatch.issues.map((i) => i.code))];
30
+ const span = trace.getActiveSpan();
31
+ if (span) {
32
+ span.setAttributes({
33
+ [VALIDATION_ATTR.name]: mismatch.name,
34
+ [VALIDATION_ATTR.boundary]: mismatch.boundary,
35
+ [VALIDATION_ATTR.mode]: mismatch.mode,
36
+ [VALIDATION_ATTR.issueCount]: mismatch.issues.length,
37
+ [VALIDATION_ATTR.issuePaths]: truncate(paths),
38
+ [VALIDATION_ATTR.issueCodes]: truncate(codes),
39
+ ...mismatch.hash ? { [VALIDATION_ATTR.hash]: mismatch.hash } : {},
40
+ ...mismatch.severity ? { [VALIDATION_ATTR.severity]: mismatch.severity } : {}
41
+ });
42
+ }
43
+ try {
44
+ counter().add(1, {
45
+ boundary: mismatch.boundary,
46
+ validation: mismatch.name,
47
+ mode: mismatch.mode
48
+ });
49
+ } catch {
50
+ }
51
+ for (const listener of listeners) {
52
+ try {
53
+ listener(mismatch);
54
+ } catch {
55
+ }
56
+ }
57
+ } catch {
58
+ }
59
+ }
60
+ function formatValidationIssues(error) {
61
+ const raw = extractRawIssues(error);
62
+ return raw.map((issue) => toSafeIssue(issue));
63
+ }
64
+ function extractRawIssues(error) {
65
+ if (error && typeof error === "object") {
66
+ const candidate = error.issues ?? error.errors;
67
+ if (Array.isArray(candidate)) {
68
+ return candidate.filter(
69
+ (i) => i !== null && typeof i === "object"
70
+ );
71
+ }
72
+ }
73
+ return [];
74
+ }
75
+ function toSafeIssue(issue) {
76
+ const rawPath = issue.path;
77
+ const path = Array.isArray(rawPath) ? rawPath.map(String).join(".") : typeof rawPath === "string" ? rawPath : "";
78
+ const code = typeof issue.code === "string" ? issue.code : "invalid";
79
+ const expected = typeof issue.expected === "string" ? issue.expected : void 0;
80
+ return expected ? { path, code, expected } : { path, code };
81
+ }
82
+ function defaultRejectError(issues, name) {
83
+ return createStructuredError({
84
+ name: "ValidationError",
85
+ status: 400,
86
+ code: "validation_failed",
87
+ message: `Input for "${name}" did not match its declared shape.`,
88
+ why: `${issues.length} field(s) failed validation: ${issues.map((i) => i.path || "(root)").slice(0, VALIDATION_ISSUE_CAP).join(", ")}.`,
89
+ fix: "Send a payload that matches the schema, or switch this validator to observe mode while you investigate.",
90
+ // PII-safe: paths + codes only, no received values.
91
+ details: { validation: name, issues }
92
+ });
93
+ }
94
+ function defineValidator(name, schema, options = {}) {
95
+ const mode = options.onMismatch ?? "reject";
96
+ const boundary = options.boundary ?? "input";
97
+ const hash = options.toJsonSchema ? hashJson(options.toJsonSchema(schema)) : void 0;
98
+ const record = (issues) => {
99
+ recordValidationMismatch({
100
+ name,
101
+ boundary,
102
+ mode,
103
+ issues,
104
+ hash,
105
+ severity: options.severity
106
+ });
107
+ };
108
+ return {
109
+ name,
110
+ mode,
111
+ safeParse(input) {
112
+ const parsed = schema.safeParse(input);
113
+ if (parsed.success) return { success: true, data: parsed.data };
114
+ const issues = formatValidationIssues(parsed.error);
115
+ record(issues);
116
+ return { success: false, issues };
117
+ },
118
+ parse(input) {
119
+ const parsed = schema.safeParse(input);
120
+ if (parsed.success) return parsed.data;
121
+ const issues = formatValidationIssues(parsed.error);
122
+ record(issues);
123
+ if (mode === "reject") {
124
+ throw options.onReject?.(issues, name) ?? defaultRejectError(issues, name);
125
+ }
126
+ return input;
127
+ }
128
+ };
129
+ }
130
+
131
+ export { defineValidator, formatValidationIssues, onValidationMismatch, recordValidationMismatch };
132
+ //# sourceMappingURL=validate.js.map
133
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/validate.ts"],"names":[],"mappings":"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","file":"validate.js","sourcesContent":["/**\n * Validation telemetry — connect runtime input validation (Zod or any\n * `safeParse` schema) to your traces and metrics at the boundaries where bad\n * data actually enters: HTTP bodies, events, messages.\n *\n * Today a `safeParse` failure either throws (no span, no metric, no alert) or\n * is silently swallowed in a handler. `defineValidator` makes the mismatch\n * **observable** — a `validation.*` span attribute set and a counter\n * incremented — with a per-validator `observe` vs `reject` mode:\n *\n * - `reject` (default): record telemetry, then throw a structured 400-shaped\n * error so the boundary can fail cleanly.\n * - `observe`: record telemetry, return the raw input so the handler continues\n * — useful for measuring real-world drift before you enforce it.\n *\n * **Not a security feature by default.** A malformed body is usually a bug or\n * version skew, not an attack. Validation telemetry is first-class on its own\n * metric; escalation to the security path is a deliberate opt-in via\n * {@link onValidationMismatch} (e.g. wired by `autotel-audit`), never automatic.\n *\n * **PII-safe by construction.** Only field *paths*, issue *codes*, and the\n * declared *type* are ever recorded — never the offending value, and never a\n * validator's error `message` (which routinely embeds the received value).\n */\n\nimport { trace } from '@opentelemetry/api';\nimport { createCounter } from './metric-helpers';\nimport { createStructuredError, type StructuredError } from './structured-error';\nimport { hashJson } from './stable-hash';\nimport type { SchemaLike } from './define-event';\nimport {\n VALIDATION_ATTR,\n VALIDATION_ISSUE_CAP,\n VALIDATION_METRICS,\n} from './validation-attributes';\n\nexport type { SchemaLike } from './define-event';\n\nexport type ValidationMode = 'observe' | 'reject';\nexport type ValidationSeverity = 'info' | 'warning' | 'error';\n\n/** A single failing field, stripped of any payload values. */\nexport interface ValidationIssue {\n /** Dotted field path, e.g. `items.0.price`. Never a value. */\n path: string;\n /** Issue code (e.g. Zod's `invalid_type`, `too_small`). Never a value. */\n code: string;\n /** Declared type/constraint summary, e.g. `string`. Never a received value. */\n expected?: string;\n}\n\n/** Everything the recorder needs — already PII-stripped by the caller. */\nexport interface ValidationMismatch {\n /** Contract id, e.g. `POST /orders` or `order.placed`. */\n name: string;\n boundary: string;\n mode: ValidationMode;\n issues: ValidationIssue[];\n hash?: string;\n severity?: ValidationSeverity;\n}\n\nlet mismatchCounter: ReturnType<typeof createCounter> | undefined;\nfunction counter(): ReturnType<typeof createCounter> {\n if (!mismatchCounter) {\n mismatchCounter = createCounter(VALIDATION_METRICS.mismatches, {\n description: 'Input payloads that did not match their declared shape',\n });\n }\n return mismatchCounter;\n}\n\ntype MismatchListener = (mismatch: ValidationMismatch) => void;\nconst listeners = new Set<MismatchListener>();\n\n/**\n * Register an explicit handler called on every recorded mismatch — the opt-in\n * seam for escalating to security events, a webhook, or a custom sink. There is\n * no automatic, package-presence-driven escalation: nothing fires here unless\n * you (or a package you wire up) register a handler.\n *\n * Multiple subscribers coexist: a package (e.g. `autotel-audit` bridging to\n * security events) and your own app code (a webhook, a logger) can both\n * register and all fire. Returns an unsubscribe fn that removes only this\n * handler; registering the same function twice is a no-op (Set semantics).\n */\nexport function onValidationMismatch(handler: MismatchListener): () => void {\n listeners.add(handler);\n return () => {\n listeners.delete(handler);\n };\n}\n\nconst truncate = (values: string[]): string =>\n values.slice(0, VALIDATION_ISSUE_CAP).join(',');\n\n/**\n * Record a validation mismatch as telemetry: `validation.*` attributes on the\n * active span (if any) and an increment on `autotel.validation.mismatches`.\n * Fail-open — never throws, so instrumentation can't break the boundary.\n */\nexport function recordValidationMismatch(mismatch: ValidationMismatch): void {\n try {\n const paths = mismatch.issues.map((i) => i.path).filter(Boolean);\n const codes = [...new Set(mismatch.issues.map((i) => i.code))];\n\n const span = trace.getActiveSpan();\n if (span) {\n span.setAttributes({\n [VALIDATION_ATTR.name]: mismatch.name,\n [VALIDATION_ATTR.boundary]: mismatch.boundary,\n [VALIDATION_ATTR.mode]: mismatch.mode,\n [VALIDATION_ATTR.issueCount]: mismatch.issues.length,\n [VALIDATION_ATTR.issuePaths]: truncate(paths),\n [VALIDATION_ATTR.issueCodes]: truncate(codes),\n ...(mismatch.hash ? { [VALIDATION_ATTR.hash]: mismatch.hash } : {}),\n ...(mismatch.severity\n ? { [VALIDATION_ATTR.severity]: mismatch.severity }\n : {}),\n });\n }\n\n try {\n counter().add(1, {\n boundary: mismatch.boundary,\n validation: mismatch.name,\n mode: mismatch.mode,\n });\n } catch {\n // meter not initialised yet — skip the count, keep the span attrs\n }\n\n // Dispatch to every subscriber with per-listener fault isolation: one\n // throwing subscriber must not starve its peers or break the boundary.\n // Set iteration tolerates concurrent (un)subscription safely.\n for (const listener of listeners) {\n try {\n listener(mismatch);\n } catch {\n // a misbehaving subscriber must not break the boundary or its peers\n }\n }\n } catch {\n // fail-open: telemetry must never break the validated boundary\n }\n}\n\n/**\n * Normalise an arbitrary validation error into PII-safe issues. Reads only\n * `path`, `code`, and (when it is a declared type name) `expected` — and never\n * `message`, `received`, or any value-bearing field. Understands the Zod shape\n * (`error.issues`) and a generic `error.errors` fallback; returns `[]` for\n * anything unrecognised.\n */\nexport function formatValidationIssues(error: unknown): ValidationIssue[] {\n const raw = extractRawIssues(error);\n return raw.map((issue) => toSafeIssue(issue));\n}\n\nfunction extractRawIssues(error: unknown): Array<Record<string, unknown>> {\n if (error && typeof error === 'object') {\n const candidate =\n (error as { issues?: unknown }).issues ??\n (error as { errors?: unknown }).errors;\n if (Array.isArray(candidate)) {\n return candidate.filter(\n (i): i is Record<string, unknown> => i !== null && typeof i === 'object',\n );\n }\n }\n return [];\n}\n\nfunction toSafeIssue(issue: Record<string, unknown>): ValidationIssue {\n const rawPath = issue.path;\n const path = Array.isArray(rawPath)\n ? rawPath.map(String).join('.')\n : typeof rawPath === 'string'\n ? rawPath\n : '';\n const code = typeof issue.code === 'string' ? issue.code : 'invalid';\n // `expected` is a declared type name in Zod (e.g. 'string'); safe. We never\n // read `received`/`message`/`value`, which can carry the offending payload.\n const expected =\n typeof issue.expected === 'string' ? issue.expected : undefined;\n return expected ? { path, code, expected } : { path, code };\n}\n\nexport interface DefineValidatorOptions<S> {\n /** Where validation runs. Defaults to `input`. */\n boundary?: string;\n /** `reject` (default): record then throw. `observe`: record then continue. */\n onMismatch?: ValidationMode;\n /** Project the schema to JSON Schema for a stable `validation.hash`. */\n toJsonSchema?: (schema: S) => unknown;\n severity?: ValidationSeverity;\n /** Build the error thrown in `reject` mode (defaults to a 400 structured error). */\n onReject?: (issues: ValidationIssue[], name: string) => Error;\n}\n\nexport type ValidatorResult<T> =\n | { success: true; data: T }\n | { success: false; issues: ValidationIssue[] };\n\nexport interface Validator<T> {\n readonly name: string;\n readonly mode: ValidationMode;\n /** Validate and record on failure; never throws. */\n safeParse(input: unknown): ValidatorResult<T>;\n /**\n * Validate, record on failure, then apply the mode: `reject` throws,\n * `observe` returns the raw input so the handler can continue.\n */\n parse(input: unknown): T;\n}\n\nfunction defaultRejectError(\n issues: ValidationIssue[],\n name: string,\n): StructuredError {\n return createStructuredError({\n name: 'ValidationError',\n status: 400,\n code: 'validation_failed',\n message: `Input for \"${name}\" did not match its declared shape.`,\n why: `${issues.length} field(s) failed validation: ${issues\n .map((i) => i.path || '(root)')\n .slice(0, VALIDATION_ISSUE_CAP)\n .join(', ')}.`,\n fix: 'Send a payload that matches the schema, or switch this validator to observe mode while you investigate.',\n // PII-safe: paths + codes only, no received values.\n details: { validation: name, issues },\n });\n}\n\n/**\n * Declare an expected input shape once and get a validator that records every\n * mismatch as telemetry.\n *\n * @example\n * ```ts\n * import { z } from 'zod';\n * import { defineValidator } from 'autotel/validate';\n *\n * const OrderBody = defineValidator('POST /orders', z.object({\n * items: z.array(z.object({ sku: z.string(), qty: z.number().int() })),\n * }), { boundary: 'http', toJsonSchema: (s) => z.toJSONSchema(s) });\n *\n * // reject mode (default): records + throws a 400-shaped structured error\n * const order = OrderBody.parse(req.body);\n *\n * // observe mode: records, returns the result, never throws\n * const result = OrderBody.safeParse(req.body);\n * if (!result.success) metrics.onDrift(result.issues);\n * ```\n */\nexport function defineValidator<T, S extends SchemaLike<T>>(\n name: string,\n schema: S,\n options: DefineValidatorOptions<S> = {},\n): Validator<T> {\n const mode = options.onMismatch ?? 'reject';\n const boundary = options.boundary ?? 'input';\n const hash = options.toJsonSchema\n ? hashJson(options.toJsonSchema(schema))\n : undefined;\n\n const record = (issues: ValidationIssue[]): void => {\n recordValidationMismatch({\n name,\n boundary,\n mode,\n issues,\n hash,\n severity: options.severity,\n });\n };\n\n return {\n name,\n mode,\n safeParse(input: unknown): ValidatorResult<T> {\n const parsed = schema.safeParse(input);\n if (parsed.success) return { success: true, data: parsed.data };\n const issues = formatValidationIssues(parsed.error);\n record(issues);\n return { success: false, issues };\n },\n parse(input: unknown): T {\n const parsed = schema.safeParse(input);\n if (parsed.success) return parsed.data;\n const issues = formatValidationIssues(parsed.error);\n record(issues);\n if (mode === 'reject') {\n throw options.onReject?.(issues, name) ?? defaultRejectError(issues, name);\n }\n // observe: continue with the raw input (documented type caveat)\n return input as T;\n },\n };\n}\n"]}
@@ -0,0 +1,20 @@
1
+ 'use strict';
2
+
3
+ var chunkT5WRA76K_cjs = require('./chunk-T5WRA76K.cjs');
4
+
5
+
6
+
7
+ Object.defineProperty(exports, "VALIDATION_ATTR", {
8
+ enumerable: true,
9
+ get: function () { return chunkT5WRA76K_cjs.VALIDATION_ATTR; }
10
+ });
11
+ Object.defineProperty(exports, "VALIDATION_ISSUE_CAP", {
12
+ enumerable: true,
13
+ get: function () { return chunkT5WRA76K_cjs.VALIDATION_ISSUE_CAP; }
14
+ });
15
+ Object.defineProperty(exports, "VALIDATION_METRICS", {
16
+ enumerable: true,
17
+ get: function () { return chunkT5WRA76K_cjs.VALIDATION_METRICS; }
18
+ });
19
+ //# sourceMappingURL=validation-attributes.cjs.map
20
+ //# sourceMappingURL=validation-attributes.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"validation-attributes.cjs"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Validation telemetry wire constants — the single source of truth for the
3
+ * `validation.*` span attributes and the `autotel.validation.mismatches` metric
4
+ * emitted when an input payload (HTTP body, event, message) fails to match its
5
+ * declared shape.
6
+ *
7
+ * Dependency-free and side-effect-free by design (mirrors `security-schema.ts`):
8
+ * safe to import from anything that only needs the constant strings — a
9
+ * dashboard, a CLI, an alert rule — without pulling in the OpenTelemetry SDK.
10
+ *
11
+ * These keys are a public API for the agents that query your telemetry. Treat a
12
+ * rename here the way you'd treat a breaking change to any other contract.
13
+ */
14
+ declare const VALIDATION_ATTR: {
15
+ /** Contract id of the validated boundary, e.g. `POST /orders`, `order.placed`. */
16
+ readonly name: "validation.name";
17
+ /** Where validation ran: `http` | `event` | `message` | a custom label. */
18
+ readonly boundary: "validation.boundary";
19
+ /** `observe` (recorded, request continues) or `reject` (recorded, then failed). */
20
+ readonly mode: "validation.mode";
21
+ /** Stable hash of the declared shape, when a JSON-schema projection is given. */
22
+ readonly hash: "validation.hash";
23
+ /** `info` | `warning` | `error`. */
24
+ readonly severity: "validation.severity";
25
+ /** Number of failing fields. */
26
+ readonly issueCount: "validation.issue.count";
27
+ /** Comma-separated failing field paths (capped). Never contains values. */
28
+ readonly issuePaths: "validation.issue.paths";
29
+ /** Comma-separated distinct issue codes (capped). Never contains values. */
30
+ readonly issueCodes: "validation.issue.codes";
31
+ };
32
+ type ValidationAttributeKey = (typeof VALIDATION_ATTR)[keyof typeof VALIDATION_ATTR];
33
+ declare const VALIDATION_METRICS: {
34
+ /** Counter, labelled `{ boundary, validation, mode }`. */
35
+ readonly mismatches: "autotel.validation.mismatches";
36
+ };
37
+ /** Max field paths / codes stamped onto a span, to bound attribute size. */
38
+ declare const VALIDATION_ISSUE_CAP = 20;
39
+
40
+ export { VALIDATION_ATTR, VALIDATION_ISSUE_CAP, VALIDATION_METRICS, type ValidationAttributeKey };
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Validation telemetry wire constants — the single source of truth for the
3
+ * `validation.*` span attributes and the `autotel.validation.mismatches` metric
4
+ * emitted when an input payload (HTTP body, event, message) fails to match its
5
+ * declared shape.
6
+ *
7
+ * Dependency-free and side-effect-free by design (mirrors `security-schema.ts`):
8
+ * safe to import from anything that only needs the constant strings — a
9
+ * dashboard, a CLI, an alert rule — without pulling in the OpenTelemetry SDK.
10
+ *
11
+ * These keys are a public API for the agents that query your telemetry. Treat a
12
+ * rename here the way you'd treat a breaking change to any other contract.
13
+ */
14
+ declare const VALIDATION_ATTR: {
15
+ /** Contract id of the validated boundary, e.g. `POST /orders`, `order.placed`. */
16
+ readonly name: "validation.name";
17
+ /** Where validation ran: `http` | `event` | `message` | a custom label. */
18
+ readonly boundary: "validation.boundary";
19
+ /** `observe` (recorded, request continues) or `reject` (recorded, then failed). */
20
+ readonly mode: "validation.mode";
21
+ /** Stable hash of the declared shape, when a JSON-schema projection is given. */
22
+ readonly hash: "validation.hash";
23
+ /** `info` | `warning` | `error`. */
24
+ readonly severity: "validation.severity";
25
+ /** Number of failing fields. */
26
+ readonly issueCount: "validation.issue.count";
27
+ /** Comma-separated failing field paths (capped). Never contains values. */
28
+ readonly issuePaths: "validation.issue.paths";
29
+ /** Comma-separated distinct issue codes (capped). Never contains values. */
30
+ readonly issueCodes: "validation.issue.codes";
31
+ };
32
+ type ValidationAttributeKey = (typeof VALIDATION_ATTR)[keyof typeof VALIDATION_ATTR];
33
+ declare const VALIDATION_METRICS: {
34
+ /** Counter, labelled `{ boundary, validation, mode }`. */
35
+ readonly mismatches: "autotel.validation.mismatches";
36
+ };
37
+ /** Max field paths / codes stamped onto a span, to bound attribute size. */
38
+ declare const VALIDATION_ISSUE_CAP = 20;
39
+
40
+ export { VALIDATION_ATTR, VALIDATION_ISSUE_CAP, VALIDATION_METRICS, type ValidationAttributeKey };
@@ -0,0 +1,3 @@
1
+ export { VALIDATION_ATTR, VALIDATION_ISSUE_CAP, VALIDATION_METRICS } from './chunk-DCEDJQGG.js';
2
+ //# sourceMappingURL=validation-attributes.js.map
3
+ //# sourceMappingURL=validation-attributes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"validation-attributes.js"}
package/dist/webhook.cjs CHANGED
@@ -1,10 +1,11 @@
1
1
  'use strict';
2
2
 
3
3
  var chunk4P6ZOARG_cjs = require('./chunk-4P6ZOARG.cjs');
4
- var chunkFGNDN2FD_cjs = require('./chunk-FGNDN2FD.cjs');
4
+ var chunkV7UBMJAB_cjs = require('./chunk-V7UBMJAB.cjs');
5
5
  require('./chunk-OPPXYVEZ.cjs');
6
6
  require('./chunk-VQTCQKHQ.cjs');
7
- var chunkZ7PW3KHL_cjs = require('./chunk-Z7PW3KHL.cjs');
7
+ require('./chunk-FMTHVSYY.cjs');
8
+ var chunkEE6CPXKH_cjs = require('./chunk-EE6CPXKH.cjs');
8
9
  require('./chunk-R7QYGZUP.cjs');
9
10
  require('./chunk-QWW3E3JM.cjs');
10
11
  require('./chunk-CEAQK2QY.cjs');
@@ -157,7 +158,7 @@ function createParkingLot(config) {
157
158
  },
158
159
  traceCallback(callbackConfig) {
159
160
  return (fnFactory) => {
160
- return chunkFGNDN2FD_cjs.trace(
161
+ return chunkV7UBMJAB_cjs.trace(
161
162
  {
162
163
  name: callbackConfig.name,
163
164
  spanKind: api.SpanKind.SERVER
@@ -201,7 +202,7 @@ function createParkingLot(config) {
201
202
  const error = new Error(
202
203
  `Required parked context not found for key: ${correlationKey}`
203
204
  );
204
- chunkZ7PW3KHL_cjs.recordStructuredError(baseCtx, error);
205
+ chunkEE6CPXKH_cjs.recordStructuredError(baseCtx, error);
205
206
  throw error;
206
207
  }
207
208
  }