autotel 3.5.0 → 3.7.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.
- package/dist/attribute-redacting-processor-DtTS9xxh.d.cts +175 -0
- package/dist/attribute-redacting-processor-DtTS9xxh.d.cts.map +1 -0
- package/dist/attribute-redacting-processor-DtTS9xxh.d.ts +175 -0
- package/dist/attribute-redacting-processor-DtTS9xxh.d.ts.map +1 -0
- package/dist/attribute-redacting-processor.cjs +374 -33
- package/dist/attribute-redacting-processor.cjs.map +1 -1
- package/dist/attribute-redacting-processor.d.cts +2 -207
- package/dist/attribute-redacting-processor.d.ts +2 -207
- package/dist/attribute-redacting-processor.js +368 -2
- package/dist/attribute-redacting-processor.js.map +1 -1
- package/dist/attributes-D3etyRVc.cjs +713 -0
- package/dist/attributes-D3etyRVc.cjs.map +1 -0
- package/dist/attributes-ksn4HVbd.js +600 -0
- package/dist/attributes-ksn4HVbd.js.map +1 -0
- package/dist/attributes.cjs +21 -85
- package/dist/attributes.d.cts +2 -20
- package/dist/attributes.d.ts +2 -20
- package/dist/attributes.js +3 -5
- package/dist/auto.cjs +50 -28
- package/dist/auto.cjs.map +1 -1
- package/dist/auto.d.cts +1 -2
- package/dist/auto.d.ts +1 -2
- package/dist/auto.js +49 -23
- package/dist/auto.js.map +1 -1
- package/dist/business-baggage.cjs +357 -13
- package/dist/business-baggage.cjs.map +1 -1
- package/dist/business-baggage.d.cts +106 -139
- package/dist/business-baggage.d.cts.map +1 -0
- package/dist/business-baggage.d.ts +106 -139
- package/dist/business-baggage.d.ts.map +1 -0
- package/dist/business-baggage.js +357 -2
- package/dist/business-baggage.js.map +1 -1
- package/dist/canonical-log-line-processor--RlFDHhm.cjs +377 -0
- package/dist/canonical-log-line-processor--RlFDHhm.cjs.map +1 -0
- package/dist/canonical-log-line-processor-BcRuAdRk.d.ts +147 -0
- package/dist/canonical-log-line-processor-BcRuAdRk.d.ts.map +1 -0
- package/dist/canonical-log-line-processor-DbBQT5vY.js +366 -0
- package/dist/canonical-log-line-processor-DbBQT5vY.js.map +1 -0
- package/dist/canonical-log-line-processor-xvjMgtpF.d.cts +147 -0
- package/dist/canonical-log-line-processor-xvjMgtpF.d.cts.map +1 -0
- package/dist/config.cjs +118 -22
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.cts +33 -45
- package/dist/config.d.cts.map +1 -0
- package/dist/config.d.ts +33 -45
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +116 -3
- package/dist/config.js.map +1 -1
- package/dist/correlated-events-Bzh5y-UB.js +28 -0
- package/dist/correlated-events-Bzh5y-UB.js.map +1 -0
- package/dist/correlated-events-kSwLo3mi.cjs +34 -0
- package/dist/correlated-events-kSwLo3mi.cjs.map +1 -0
- package/dist/correlation-id.cjs +11 -53
- package/dist/correlation-id.d.cts +6 -5
- package/dist/correlation-id.d.cts.map +1 -0
- package/dist/correlation-id.d.ts +6 -5
- package/dist/correlation-id.d.ts.map +1 -0
- package/dist/correlation-id.js +3 -16
- package/dist/db.cjs +244 -209
- package/dist/db.cjs.map +1 -1
- package/dist/db.d.cts +28 -26
- package/dist/db.d.cts.map +1 -0
- package/dist/db.d.ts +28 -26
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +243 -207
- package/dist/db.js.map +1 -1
- package/dist/decorators.cjs +39 -65
- package/dist/decorators.cjs.map +1 -1
- package/dist/decorators.d.cts +10 -37
- package/dist/decorators.d.cts.map +1 -0
- package/dist/decorators.d.ts +10 -37
- package/dist/decorators.d.ts.map +1 -0
- package/dist/decorators.js +38 -63
- package/dist/decorators.js.map +1 -1
- package/dist/define-event-CreknLm3.d.ts +25 -0
- package/dist/define-event-CreknLm3.d.ts.map +1 -0
- package/dist/define-event-HZRizPwz.d.cts +25 -0
- package/dist/define-event-HZRizPwz.d.cts.map +1 -0
- package/dist/drain-pipeline.cjs +111 -9
- package/dist/drain-pipeline.cjs.map +1 -1
- package/dist/drain-pipeline.d.cts +27 -32
- package/dist/drain-pipeline.d.cts.map +1 -0
- package/dist/drain-pipeline.d.ts +27 -32
- package/dist/drain-pipeline.d.ts.map +1 -0
- package/dist/drain-pipeline.js +111 -2
- package/dist/drain-pipeline.js.map +1 -1
- package/dist/enrichers.cjs +59 -66
- package/dist/enrichers.cjs.map +1 -1
- package/dist/enrichers.d.cts +15 -13
- package/dist/enrichers.d.cts.map +1 -0
- package/dist/enrichers.d.ts +15 -13
- package/dist/enrichers.d.ts.map +1 -0
- package/dist/enrichers.js +58 -65
- package/dist/enrichers.js.map +1 -1
- package/dist/event-Dlqr4ZNL.cjs +778 -0
- package/dist/event-Dlqr4ZNL.cjs.map +1 -0
- package/dist/event-_58ryBjh.js +761 -0
- package/dist/event-_58ryBjh.js.map +1 -0
- package/dist/event-subscriber-D1XLkPzi.d.cts +223 -0
- package/dist/event-subscriber-D1XLkPzi.d.cts.map +1 -0
- package/dist/event-subscriber-D1XLkPzi.d.ts +223 -0
- package/dist/event-subscriber-D1XLkPzi.d.ts.map +1 -0
- package/dist/event-subscriber.cjs +0 -6
- package/dist/event-subscriber.d.cts +2 -221
- package/dist/event-subscriber.d.ts +2 -221
- package/dist/event-subscriber.js +1 -3
- package/dist/event-testing-BqRnI0z4.d.cts +106 -0
- package/dist/event-testing-BqRnI0z4.d.cts.map +1 -0
- package/dist/event-testing-CfFs3to2.d.ts +106 -0
- package/dist/event-testing-CfFs3to2.d.ts.map +1 -0
- package/dist/event-testing.cjs +93 -17
- package/dist/event-testing.cjs.map +1 -1
- package/dist/event-testing.d.cts +2 -110
- package/dist/event-testing.d.ts +2 -110
- package/dist/event-testing.js +91 -2
- package/dist/event-testing.js.map +1 -1
- package/dist/event.cjs +5 -36
- package/dist/event.d.cts +295 -340
- package/dist/event.d.cts.map +1 -0
- package/dist/event.d.ts +295 -340
- package/dist/event.d.ts.map +1 -0
- package/dist/event.js +3 -20
- package/dist/exporters.cjs +12 -16
- package/dist/exporters.d.cts +86 -111
- package/dist/exporters.d.cts.map +1 -0
- package/dist/exporters.d.ts +86 -111
- package/dist/exporters.d.ts.map +1 -0
- package/dist/exporters.js +4 -4
- package/dist/filtering-span-processor-B8R8B7Uk.d.cts +59 -0
- package/dist/filtering-span-processor-B8R8B7Uk.d.cts.map +1 -0
- package/dist/filtering-span-processor-B8R8B7Uk.d.ts +59 -0
- package/dist/filtering-span-processor-B8R8B7Uk.d.ts.map +1 -0
- package/dist/filtering-span-processor.cjs +49 -9
- package/dist/filtering-span-processor.cjs.map +1 -1
- package/dist/filtering-span-processor.d.cts +2 -80
- package/dist/filtering-span-processor.d.ts +2 -80
- package/dist/filtering-span-processor.js +49 -2
- package/dist/filtering-span-processor.js.map +1 -1
- package/dist/functional-BGkT8J-h.js +1265 -0
- package/dist/functional-BGkT8J-h.js.map +1 -0
- package/dist/functional-C4CzoVrX.cjs +1312 -0
- package/dist/functional-C4CzoVrX.cjs.map +1 -0
- package/dist/functional.cjs +11 -56
- package/dist/functional.d.cts +96 -97
- package/dist/functional.d.cts.map +1 -0
- package/dist/functional.d.ts +96 -97
- package/dist/functional.d.ts.map +1 -0
- package/dist/functional.js +3 -19
- package/dist/http.cjs +276 -175
- package/dist/http.cjs.map +1 -1
- package/dist/http.d.cts +17 -37
- package/dist/http.d.cts.map +1 -0
- package/dist/http.d.ts +17 -37
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +275 -173
- package/dist/http.js.map +1 -1
- package/dist/index-CX0aG1Uh.d.ts +708 -0
- package/dist/index-CX0aG1Uh.d.ts.map +1 -0
- package/dist/index-DIWZFKUS.d.cts +708 -0
- package/dist/index-DIWZFKUS.d.cts.map +1 -0
- package/dist/index.cjs +1050 -1184
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +401 -570
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +401 -570
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +913 -725
- package/dist/index.js.map +1 -1
- package/dist/init-CNp-ee80.d.cts +1157 -0
- package/dist/init-CNp-ee80.d.cts.map +1 -0
- package/dist/init-Ch6t7MNI.js +1015 -0
- package/dist/init-Ch6t7MNI.js.map +1 -0
- package/dist/init-DJQOdVlN.d.ts +1157 -0
- package/dist/init-DJQOdVlN.d.ts.map +1 -0
- package/dist/init-DvapOXCc.cjs +1092 -0
- package/dist/init-DvapOXCc.cjs.map +1 -0
- package/dist/instrumentation.cjs +159 -185
- package/dist/instrumentation.cjs.map +1 -1
- package/dist/instrumentation.d.cts +42 -40
- package/dist/instrumentation.d.cts.map +1 -0
- package/dist/instrumentation.d.ts +42 -40
- package/dist/instrumentation.d.ts.map +1 -0
- package/dist/instrumentation.js +158 -183
- package/dist/instrumentation.js.map +1 -1
- package/dist/logger-BauSUhUv.d.cts +313 -0
- package/dist/logger-BauSUhUv.d.cts.map +1 -0
- package/dist/logger-BauSUhUv.d.ts +313 -0
- package/dist/logger-BauSUhUv.d.ts.map +1 -0
- package/dist/logger.cjs +225 -25
- package/dist/logger.cjs.map +1 -1
- package/dist/logger.d.cts +2 -348
- package/dist/logger.d.ts +2 -348
- package/dist/logger.js +204 -4
- package/dist/logger.js.map +1 -1
- package/dist/messaging-adapters.cjs +292 -187
- package/dist/messaging-adapters.cjs.map +1 -1
- package/dist/messaging-adapters.d.cts +28 -66
- package/dist/messaging-adapters.d.cts.map +1 -0
- package/dist/messaging-adapters.d.ts +28 -66
- package/dist/messaging-adapters.d.ts.map +1 -0
- package/dist/messaging-adapters.js +291 -185
- package/dist/messaging-adapters.js.map +1 -1
- package/dist/messaging-testing.cjs +306 -372
- package/dist/messaging-testing.cjs.map +1 -1
- package/dist/messaging-testing.d.cts +194 -223
- package/dist/messaging-testing.d.cts.map +1 -0
- package/dist/messaging-testing.d.ts +194 -223
- package/dist/messaging-testing.d.ts.map +1 -0
- package/dist/messaging-testing.js +305 -371
- package/dist/messaging-testing.js.map +1 -1
- package/dist/messaging.cjs +757 -35
- package/dist/messaging.cjs.map +1 -1
- package/dist/messaging.d.cts +603 -644
- package/dist/messaging.d.cts.map +1 -0
- package/dist/messaging.d.ts +603 -644
- package/dist/messaging.d.ts.map +1 -0
- package/dist/messaging.js +756 -20
- package/dist/messaging.js.map +1 -1
- package/dist/metric-helpers.cjs +27 -27
- package/dist/metric-helpers.cjs.map +1 -1
- package/dist/metric-helpers.d.cts +4 -2
- package/dist/metric-helpers.d.cts.map +1 -0
- package/dist/metric-helpers.d.ts +4 -2
- package/dist/metric-helpers.d.ts.map +1 -0
- package/dist/metric-helpers.js +24 -4
- package/dist/metric-helpers.js.map +1 -1
- package/dist/metric-testing-DXdK3-Q3.d.ts +106 -0
- package/dist/metric-testing-DXdK3-Q3.d.ts.map +1 -0
- package/dist/metric-testing-MxvzChDp.d.cts +106 -0
- package/dist/metric-testing-MxvzChDp.d.cts.map +1 -0
- package/dist/metric-testing.cjs +93 -17
- package/dist/metric-testing.cjs.map +1 -1
- package/dist/metric-testing.d.cts +2 -110
- package/dist/metric-testing.d.ts +2 -110
- package/dist/metric-testing.js +91 -2
- package/dist/metric-testing.js.map +1 -1
- package/dist/metric.cjs +306 -22
- package/dist/metric.cjs.map +1 -1
- package/dist/metric.d.cts +170 -198
- package/dist/metric.d.cts.map +1 -0
- package/dist/metric.d.ts +170 -198
- package/dist/metric.d.ts.map +1 -0
- package/dist/metric.js +277 -7
- package/dist/metric.js.map +1 -1
- package/dist/node-require-DF5QBX6z.cjs +99 -0
- package/dist/node-require-DF5QBX6z.cjs.map +1 -0
- package/dist/node-require-Db1oDpLj.js +88 -0
- package/dist/node-require-Db1oDpLj.js.map +1 -0
- package/dist/operation-context-C-2hmmtP.js +59 -0
- package/dist/operation-context-C-2hmmtP.js.map +1 -0
- package/dist/operation-context-n4_obUwq.cjs +70 -0
- package/dist/operation-context-n4_obUwq.cjs.map +1 -0
- package/dist/parse-error.cjs +55 -9
- package/dist/parse-error.cjs.map +1 -1
- package/dist/parse-error.d.cts +12 -10
- package/dist/parse-error.d.cts.map +1 -0
- package/dist/parse-error.d.ts +12 -10
- package/dist/parse-error.d.ts.map +1 -0
- package/dist/parse-error.js +55 -2
- package/dist/parse-error.js.map +1 -1
- package/dist/pretty-console-exporter-CMzlrRNg.cjs +232 -0
- package/dist/pretty-console-exporter-CMzlrRNg.cjs.map +1 -0
- package/dist/pretty-console-exporter-DqKl_q9z.js +227 -0
- package/dist/pretty-console-exporter-DqKl_q9z.js.map +1 -0
- package/dist/processors.cjs +13 -17
- package/dist/processors.d.cts +3 -171
- package/dist/processors.d.ts +3 -171
- package/dist/processors.js +4 -4
- package/dist/register.cjs +35 -6
- package/dist/register.cjs.map +1 -1
- package/dist/register.d.cts +1 -2
- package/dist/register.d.ts +1 -2
- package/dist/register.js +36 -3
- package/dist/register.js.map +1 -1
- package/dist/registry-DfXA3R1L.js +184 -0
- package/dist/registry-DfXA3R1L.js.map +1 -0
- package/dist/registry-JZg2J3RZ.cjs +334 -0
- package/dist/registry-JZg2J3RZ.cjs.map +1 -0
- package/dist/sampling-CR0Va1VB.d.ts +351 -0
- package/dist/sampling-CR0Va1VB.d.ts.map +1 -0
- package/dist/sampling-DfYhDJij.d.cts +351 -0
- package/dist/sampling-DfYhDJij.d.cts.map +1 -0
- package/dist/sampling.cjs +452 -60
- package/dist/sampling.cjs.map +1 -1
- package/dist/sampling.d.cts +2 -379
- package/dist/sampling.d.ts +2 -379
- package/dist/sampling.js +441 -5
- package/dist/sampling.js.map +1 -1
- package/dist/security-schema.cjs +65 -46
- package/dist/security-schema.cjs.map +1 -1
- package/dist/security-schema.d.cts +23 -26
- package/dist/security-schema.d.cts.map +1 -0
- package/dist/security-schema.d.ts +23 -26
- package/dist/security-schema.d.ts.map +1 -0
- package/dist/security-schema.js +64 -45
- package/dist/security-schema.js.map +1 -1
- package/dist/semantic-conventions-FhSxv-bK.d.cts +32 -0
- package/dist/semantic-conventions-FhSxv-bK.d.cts.map +1 -0
- package/dist/semantic-conventions-FhSxv-bK.d.ts +32 -0
- package/dist/semantic-conventions-FhSxv-bK.d.ts.map +1 -0
- package/dist/semantic-conventions.cjs +15 -26
- package/dist/semantic-conventions.cjs.map +1 -1
- package/dist/semantic-conventions.d.cts +2 -29
- package/dist/semantic-conventions.d.ts +2 -29
- package/dist/semantic-conventions.js +12 -3
- package/dist/semantic-conventions.js.map +1 -1
- package/dist/semantic-helpers.cjs +440 -38
- package/dist/semantic-helpers.cjs.map +1 -1
- package/dist/semantic-helpers.d.cts +38 -45
- package/dist/semantic-helpers.d.cts.map +1 -0
- package/dist/semantic-helpers.d.ts +38 -45
- package/dist/semantic-helpers.d.ts.map +1 -0
- package/dist/semantic-helpers.js +438 -19
- package/dist/semantic-helpers.js.map +1 -1
- package/dist/span-name-normalizer-8ZOGJuwv.d.cts +70 -0
- package/dist/span-name-normalizer-8ZOGJuwv.d.cts.map +1 -0
- package/dist/span-name-normalizer-8ZOGJuwv.d.ts +70 -0
- package/dist/span-name-normalizer-8ZOGJuwv.d.ts.map +1 -0
- package/dist/span-name-normalizer.cjs +95 -17
- package/dist/span-name-normalizer.cjs.map +1 -1
- package/dist/span-name-normalizer.d.cts +2 -94
- package/dist/span-name-normalizer.d.ts +2 -94
- package/dist/span-name-normalizer.js +93 -2
- package/dist/span-name-normalizer.js.map +1 -1
- package/dist/stable-hash-BNTMrmdB.cjs +28 -0
- package/dist/stable-hash-BNTMrmdB.cjs.map +1 -0
- package/dist/stable-hash-Cg5cT34Q.js +23 -0
- package/dist/stable-hash-Cg5cT34Q.js.map +1 -0
- package/dist/structured-error-9--cxBay.js +143 -0
- package/dist/structured-error-9--cxBay.js.map +1 -0
- package/dist/structured-error-CHg7DoIQ.cjs +178 -0
- package/dist/structured-error-CHg7DoIQ.cjs.map +1 -0
- package/dist/tail-sampling-processor.cjs +26 -13
- package/dist/tail-sampling-processor.cjs.map +1 -1
- package/dist/tail-sampling-processor.d.cts +11 -23
- package/dist/tail-sampling-processor.d.cts.map +1 -0
- package/dist/tail-sampling-processor.d.ts +11 -23
- package/dist/tail-sampling-processor.d.ts.map +1 -0
- package/dist/tail-sampling-processor.js +27 -6
- package/dist/tail-sampling-processor.js.map +1 -1
- package/dist/test-span-collector.cjs +70 -72
- package/dist/test-span-collector.cjs.map +1 -1
- package/dist/test-span-collector.d.cts +25 -43
- package/dist/test-span-collector.d.cts.map +1 -0
- package/dist/test-span-collector.d.ts +25 -43
- package/dist/test-span-collector.d.ts.map +1 -0
- package/dist/test-span-collector.js +69 -70
- package/dist/test-span-collector.js.map +1 -1
- package/dist/testing.cjs +389 -278
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +39 -62
- package/dist/testing.d.cts.map +1 -0
- package/dist/testing.d.ts +39 -62
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +386 -265
- package/dist/testing.js.map +1 -1
- package/dist/trace-context-Cijqoi6e.d.cts +212 -0
- package/dist/trace-context-Cijqoi6e.d.cts.map +1 -0
- package/dist/trace-context-Cijqoi6e.d.ts +212 -0
- package/dist/trace-context-Cijqoi6e.d.ts.map +1 -0
- package/dist/trace-helpers.cjs +634 -54
- package/dist/trace-helpers.cjs.map +1 -1
- package/dist/trace-helpers.d.cts +17 -49
- package/dist/trace-helpers.d.cts.map +1 -0
- package/dist/trace-helpers.d.ts +17 -49
- package/dist/trace-helpers.d.ts.map +1 -0
- package/dist/trace-helpers.js +624 -3
- package/dist/trace-helpers.js.map +1 -1
- package/dist/tracer-provider.cjs +227 -16
- package/dist/tracer-provider.cjs.map +1 -1
- package/dist/tracer-provider.d.cts +5 -4
- package/dist/tracer-provider.d.cts.map +1 -0
- package/dist/tracer-provider.d.ts +5 -4
- package/dist/tracer-provider.d.ts.map +1 -0
- package/dist/tracer-provider.js +227 -2
- package/dist/tracer-provider.js.map +1 -1
- package/dist/track-3HY4NGV-.cjs +1212 -0
- package/dist/track-3HY4NGV-.cjs.map +1 -0
- package/dist/track-nsKVy-pj.js +1111 -0
- package/dist/track-nsKVy-pj.js.map +1 -0
- package/dist/validate.cjs +201 -0
- package/dist/validate.cjs.map +1 -0
- package/dist/validate.d.cts +105 -0
- package/dist/validate.d.cts.map +1 -0
- package/dist/validate.d.ts +105 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +197 -0
- package/dist/validate.js.map +1 -0
- package/dist/validation-attributes.cjs +45 -0
- package/dist/validation-attributes.cjs.map +1 -0
- package/dist/validation-attributes.d.cts +33 -0
- package/dist/validation-attributes.d.cts.map +1 -0
- package/dist/validation-attributes.d.ts +33 -0
- package/dist/validation-attributes.d.ts.map +1 -0
- package/dist/validation-attributes.js +41 -0
- package/dist/validation-attributes.js.map +1 -0
- package/dist/webhook.cjs +286 -255
- package/dist/webhook.cjs.map +1 -1
- package/dist/webhook.d.cts +157 -192
- package/dist/webhook.d.cts.map +1 -0
- package/dist/webhook.d.ts +157 -192
- package/dist/webhook.d.ts.map +1 -0
- package/dist/webhook.js +285 -253
- package/dist/webhook.js.map +1 -1
- package/dist/workflow-distributed.cjs +498 -411
- package/dist/workflow-distributed.cjs.map +1 -1
- package/dist/workflow-distributed.d.cts +163 -173
- package/dist/workflow-distributed.d.cts.map +1 -0
- package/dist/workflow-distributed.d.ts +163 -173
- package/dist/workflow-distributed.d.ts.map +1 -0
- package/dist/workflow-distributed.js +497 -409
- package/dist/workflow-distributed.js.map +1 -1
- package/dist/workflow.cjs +405 -39
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +78 -131
- package/dist/workflow.d.cts.map +1 -0
- package/dist/workflow.d.ts +78 -131
- package/dist/workflow.d.ts.map +1 -0
- package/dist/workflow.js +403 -20
- package/dist/workflow.js.map +1 -1
- package/dist/yaml-config-B3dQ82GR.cjs +272 -0
- package/dist/yaml-config-B3dQ82GR.cjs.map +1 -0
- package/dist/yaml-config.cjs +5 -24
- package/dist/yaml-config.d.cts +30 -64
- package/dist/yaml-config.d.cts.map +1 -0
- package/dist/yaml-config.d.ts +30 -64
- package/dist/yaml-config.d.ts.map +1 -0
- package/dist/yaml-config.js +226 -7
- package/dist/yaml-config.js.map +1 -1
- package/package.json +14 -4
- package/src/define-event.ts +2 -21
- package/src/index.ts +3 -0
- package/src/request-logger.test.ts +53 -1
- package/src/request-logger.ts +58 -0
- package/src/stable-hash.ts +27 -0
- package/src/validate.test.ts +287 -0
- package/src/validate.ts +307 -0
- package/src/validation-attributes.ts +43 -0
- package/dist/attributes.cjs.map +0 -1
- package/dist/attributes.js.map +0 -1
- package/dist/chunk-2ZKEORFN.cjs +0 -14
- package/dist/chunk-2ZKEORFN.cjs.map +0 -1
- package/dist/chunk-3QXBFGKP.js +0 -344
- package/dist/chunk-3QXBFGKP.js.map +0 -1
- package/dist/chunk-454CH4OV.js +0 -744
- package/dist/chunk-454CH4OV.js.map +0 -1
- package/dist/chunk-4A53YIAX.js +0 -180
- package/dist/chunk-4A53YIAX.js.map +0 -1
- package/dist/chunk-4IFSYQVX.js +0 -337
- package/dist/chunk-4IFSYQVX.js.map +0 -1
- package/dist/chunk-4P6ZOARG.cjs +0 -33
- package/dist/chunk-4P6ZOARG.cjs.map +0 -1
- package/dist/chunk-55ER2KD5.js +0 -228
- package/dist/chunk-55ER2KD5.js.map +0 -1
- package/dist/chunk-5ZN622AO.js +0 -73
- package/dist/chunk-5ZN622AO.js.map +0 -1
- package/dist/chunk-6S5RUKU3.cjs +0 -347
- package/dist/chunk-6S5RUKU3.cjs.map +0 -1
- package/dist/chunk-6UQRVUN3.js +0 -222
- package/dist/chunk-6UQRVUN3.js.map +0 -1
- package/dist/chunk-7552UTQW.js +0 -11
- package/dist/chunk-7552UTQW.js.map +0 -1
- package/dist/chunk-7EQ4G4SI.cjs +0 -146
- package/dist/chunk-7EQ4G4SI.cjs.map +0 -1
- package/dist/chunk-7SAWIN74.js +0 -285
- package/dist/chunk-7SAWIN74.js.map +0 -1
- package/dist/chunk-A4E5AQFK.js +0 -30
- package/dist/chunk-A4E5AQFK.js.map +0 -1
- package/dist/chunk-AC5GNZKB.cjs +0 -344
- package/dist/chunk-AC5GNZKB.cjs.map +0 -1
- package/dist/chunk-ALPYR2GC.js +0 -1061
- package/dist/chunk-ALPYR2GC.js.map +0 -1
- package/dist/chunk-BZHG5IZ4.js +0 -73
- package/dist/chunk-BZHG5IZ4.js.map +0 -1
- package/dist/chunk-CEAQK2QY.cjs +0 -32
- package/dist/chunk-CEAQK2QY.cjs.map +0 -1
- package/dist/chunk-CMHVQR6P.js +0 -170
- package/dist/chunk-CMHVQR6P.js.map +0 -1
- package/dist/chunk-CU6IDACR.cjs +0 -224
- package/dist/chunk-CU6IDACR.cjs.map +0 -1
- package/dist/chunk-DPSA4QLA.js +0 -344
- package/dist/chunk-DPSA4QLA.js.map +0 -1
- package/dist/chunk-DQEHQNQE.js +0 -795
- package/dist/chunk-DQEHQNQE.js.map +0 -1
- package/dist/chunk-ESLWRGAG.cjs +0 -92
- package/dist/chunk-ESLWRGAG.cjs.map +0 -1
- package/dist/chunk-ESMHTKLJ.cjs +0 -206
- package/dist/chunk-ESMHTKLJ.cjs.map +0 -1
- package/dist/chunk-FGNDN2FD.cjs +0 -1242
- package/dist/chunk-FGNDN2FD.cjs.map +0 -1
- package/dist/chunk-FU6R566Y.cjs +0 -236
- package/dist/chunk-FU6R566Y.cjs.map +0 -1
- package/dist/chunk-GBFTC7Q7.cjs +0 -837
- package/dist/chunk-GBFTC7Q7.cjs.map +0 -1
- package/dist/chunk-GYR5K654.js +0 -91
- package/dist/chunk-GYR5K654.js.map +0 -1
- package/dist/chunk-HA2WBOGQ.js +0 -57
- package/dist/chunk-HA2WBOGQ.js.map +0 -1
- package/dist/chunk-HT5JQKN2.js +0 -118
- package/dist/chunk-HT5JQKN2.js.map +0 -1
- package/dist/chunk-INJD3G4K.cjs +0 -340
- package/dist/chunk-INJD3G4K.cjs.map +0 -1
- package/dist/chunk-IOYFAFHJ.cjs +0 -95
- package/dist/chunk-IOYFAFHJ.cjs.map +0 -1
- package/dist/chunk-J5QENANM.js +0 -87
- package/dist/chunk-J5QENANM.js.map +0 -1
- package/dist/chunk-J7VGRIAJ.js +0 -64
- package/dist/chunk-J7VGRIAJ.js.map +0 -1
- package/dist/chunk-KFOHQK7X.js +0 -144
- package/dist/chunk-KFOHQK7X.js.map +0 -1
- package/dist/chunk-KIL5CUN6.js +0 -31
- package/dist/chunk-KIL5CUN6.js.map +0 -1
- package/dist/chunk-LITNXTTT.js +0 -3
- package/dist/chunk-LITNXTTT.js.map +0 -1
- package/dist/chunk-M3LFHHTN.cjs +0 -764
- package/dist/chunk-M3LFHHTN.cjs.map +0 -1
- package/dist/chunk-NEIB3TLD.cjs +0 -360
- package/dist/chunk-NEIB3TLD.cjs.map +0 -1
- package/dist/chunk-NVAI5CCN.cjs +0 -39
- package/dist/chunk-NVAI5CCN.cjs.map +0 -1
- package/dist/chunk-NVGPMGI4.js +0 -95
- package/dist/chunk-NVGPMGI4.js.map +0 -1
- package/dist/chunk-NZ72VDNY.cjs +0 -4
- package/dist/chunk-NZ72VDNY.cjs.map +0 -1
- package/dist/chunk-O4JZUCUE.js +0 -1174
- package/dist/chunk-O4JZUCUE.js.map +0 -1
- package/dist/chunk-O7JOKRN2.js +0 -833
- package/dist/chunk-O7JOKRN2.js.map +0 -1
- package/dist/chunk-OPPXYVEZ.cjs +0 -131
- package/dist/chunk-OPPXYVEZ.cjs.map +0 -1
- package/dist/chunk-Q4EULJQY.js +0 -35
- package/dist/chunk-Q4EULJQY.js.map +0 -1
- package/dist/chunk-QWW3E3JM.cjs +0 -178
- package/dist/chunk-QWW3E3JM.cjs.map +0 -1
- package/dist/chunk-R7QYGZUP.cjs +0 -1075
- package/dist/chunk-R7QYGZUP.cjs.map +0 -1
- package/dist/chunk-RUPKBKUF.js +0 -352
- package/dist/chunk-RUPKBKUF.js.map +0 -1
- package/dist/chunk-SEO6NAQT.js +0 -14
- package/dist/chunk-SEO6NAQT.js.map +0 -1
- package/dist/chunk-T4B5LB6E.cjs +0 -66
- package/dist/chunk-T4B5LB6E.cjs.map +0 -1
- package/dist/chunk-TC5ZPWM4.cjs +0 -289
- package/dist/chunk-TC5ZPWM4.cjs.map +0 -1
- package/dist/chunk-TQ5UWA7S.js +0 -26
- package/dist/chunk-TQ5UWA7S.js.map +0 -1
- package/dist/chunk-URHPSJW2.js +0 -339
- package/dist/chunk-URHPSJW2.js.map +0 -1
- package/dist/chunk-UY3UYPBZ.cjs +0 -77
- package/dist/chunk-UY3UYPBZ.cjs.map +0 -1
- package/dist/chunk-VG2ABKJX.cjs +0 -100
- package/dist/chunk-VG2ABKJX.cjs.map +0 -1
- package/dist/chunk-VH77IPJN.cjs +0 -358
- package/dist/chunk-VH77IPJN.cjs.map +0 -1
- package/dist/chunk-VQTCQKHQ.cjs +0 -17
- package/dist/chunk-VQTCQKHQ.cjs.map +0 -1
- package/dist/chunk-WGWSHJ2N.js +0 -38
- package/dist/chunk-WGWSHJ2N.js.map +0 -1
- package/dist/chunk-WJH6IYU2.cjs +0 -32
- package/dist/chunk-WJH6IYU2.cjs.map +0 -1
- package/dist/chunk-YREV3LGG.cjs +0 -61
- package/dist/chunk-YREV3LGG.cjs.map +0 -1
- package/dist/chunk-YTXEZ4SD.cjs +0 -77
- package/dist/chunk-YTXEZ4SD.cjs.map +0 -1
- package/dist/chunk-YWCESU4Y.js +0 -1233
- package/dist/chunk-YWCESU4Y.js.map +0 -1
- package/dist/chunk-Z6HRSM2Y.cjs +0 -799
- package/dist/chunk-Z6HRSM2Y.cjs.map +0 -1
- package/dist/chunk-Z7PW3KHL.cjs +0 -1198
- package/dist/chunk-Z7PW3KHL.cjs.map +0 -1
- package/dist/chunk-ZNMBW67B.cjs +0 -40
- package/dist/chunk-ZNMBW67B.cjs.map +0 -1
- package/dist/correlation-id.cjs.map +0 -1
- package/dist/correlation-id.js.map +0 -1
- package/dist/event-subscriber.cjs.map +0 -1
- package/dist/event-subscriber.js.map +0 -1
- package/dist/event.cjs.map +0 -1
- package/dist/event.js.map +0 -1
- package/dist/exporters.cjs.map +0 -1
- package/dist/exporters.js.map +0 -1
- package/dist/functional.cjs.map +0 -1
- package/dist/functional.js.map +0 -1
- package/dist/init-DIowiiCh.d.ts +0 -1167
- package/dist/init-j-A1zI16.d.cts +0 -1167
- package/dist/processors.cjs.map +0 -1
- package/dist/processors.js.map +0 -1
- package/dist/trace-context-DbGKd1Rn.d.cts +0 -213
- package/dist/trace-context-DbGKd1Rn.d.ts +0 -213
- package/dist/utils-BahBCFtJ.d.cts +0 -712
- package/dist/utils-CLKwaUlG.d.ts +0 -712
- package/dist/yaml-config.cjs.map +0 -1
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { trace } from '@opentelemetry/api';
|
|
3
|
+
|
|
4
|
+
const counterAdd = vi.hoisted(() => vi.fn());
|
|
5
|
+
vi.mock('./metric-helpers', () => ({
|
|
6
|
+
createCounter: () => ({ add: counterAdd }),
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
defineValidator,
|
|
11
|
+
recordValidationMismatch,
|
|
12
|
+
formatValidationIssues,
|
|
13
|
+
onValidationMismatch,
|
|
14
|
+
type ValidationMismatch,
|
|
15
|
+
} from './validate';
|
|
16
|
+
import { VALIDATION_ATTR } from './validation-attributes';
|
|
17
|
+
|
|
18
|
+
/** A fake `SchemaLike` so tests don't depend on Zod. */
|
|
19
|
+
function schema<T>(
|
|
20
|
+
decide: (
|
|
21
|
+
input: unknown,
|
|
22
|
+
) => { success: true; data: T } | { success: false; error: unknown },
|
|
23
|
+
) {
|
|
24
|
+
return { safeParse: decide };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** A Zod-shaped error whose message/received embed a secret value. */
|
|
28
|
+
const SECRET = '123-45-6789';
|
|
29
|
+
const zodLikeError = {
|
|
30
|
+
issues: [
|
|
31
|
+
{
|
|
32
|
+
path: ['user', 'ssn'],
|
|
33
|
+
code: 'invalid_type',
|
|
34
|
+
expected: 'string',
|
|
35
|
+
received: SECRET, // value — must never escape
|
|
36
|
+
message: `Expected string, received ${SECRET}`, // value — must never escape
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
let setAttributes: ReturnType<typeof vi.fn>;
|
|
42
|
+
|
|
43
|
+
beforeEach(() => {
|
|
44
|
+
setAttributes = vi.fn();
|
|
45
|
+
vi.spyOn(trace, 'getActiveSpan').mockReturnValue({
|
|
46
|
+
setAttributes,
|
|
47
|
+
} as never);
|
|
48
|
+
counterAdd.mockClear();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
afterEach(() => {
|
|
52
|
+
vi.restoreAllMocks();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
describe('formatValidationIssues — PII guard', () => {
|
|
56
|
+
it('keeps only path, code, and declared type — never values or messages', () => {
|
|
57
|
+
const issues = formatValidationIssues(zodLikeError);
|
|
58
|
+
expect(issues).toEqual([
|
|
59
|
+
{ path: 'user.ssn', code: 'invalid_type', expected: 'string' },
|
|
60
|
+
]);
|
|
61
|
+
// The secret must not appear anywhere in the serialized output.
|
|
62
|
+
expect(JSON.stringify(issues)).not.toContain(SECRET);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('handles a generic { errors: [...] } shape', () => {
|
|
66
|
+
const issues = formatValidationIssues({
|
|
67
|
+
errors: [{ path: ['a'], code: 'custom' }],
|
|
68
|
+
});
|
|
69
|
+
expect(issues).toEqual([{ path: 'a', code: 'custom' }]);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('returns [] for unrecognised errors', () => {
|
|
73
|
+
expect(formatValidationIssues(new Error('boom'))).toEqual([]);
|
|
74
|
+
expect(formatValidationIssues()).toEqual([]);
|
|
75
|
+
expect(formatValidationIssues('nope')).toEqual([]);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('defaults a missing code and root path', () => {
|
|
79
|
+
expect(formatValidationIssues({ issues: [{}] })).toEqual([
|
|
80
|
+
{ path: '', code: 'invalid' },
|
|
81
|
+
]);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe('recordValidationMismatch', () => {
|
|
86
|
+
const mismatch: ValidationMismatch = {
|
|
87
|
+
name: 'POST /orders',
|
|
88
|
+
boundary: 'http',
|
|
89
|
+
mode: 'reject',
|
|
90
|
+
issues: [
|
|
91
|
+
{ path: 'a', code: 'invalid_type' },
|
|
92
|
+
{ path: 'b', code: 'too_small' },
|
|
93
|
+
{ path: 'c', code: 'invalid_type' },
|
|
94
|
+
],
|
|
95
|
+
hash: 'abc123',
|
|
96
|
+
severity: 'warning',
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
it('sets validation.* attributes on the active span', () => {
|
|
100
|
+
recordValidationMismatch(mismatch);
|
|
101
|
+
expect(setAttributes).toHaveBeenCalledWith(
|
|
102
|
+
expect.objectContaining({
|
|
103
|
+
[VALIDATION_ATTR.name]: 'POST /orders',
|
|
104
|
+
[VALIDATION_ATTR.boundary]: 'http',
|
|
105
|
+
[VALIDATION_ATTR.mode]: 'reject',
|
|
106
|
+
[VALIDATION_ATTR.issueCount]: 3,
|
|
107
|
+
[VALIDATION_ATTR.issuePaths]: 'a,b,c',
|
|
108
|
+
[VALIDATION_ATTR.issueCodes]: 'invalid_type,too_small', // deduped
|
|
109
|
+
[VALIDATION_ATTR.hash]: 'abc123',
|
|
110
|
+
[VALIDATION_ATTR.severity]: 'warning',
|
|
111
|
+
}),
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('increments the mismatch counter with boundary/validation/mode labels', () => {
|
|
116
|
+
recordValidationMismatch(mismatch);
|
|
117
|
+
expect(counterAdd).toHaveBeenCalledWith(1, {
|
|
118
|
+
boundary: 'http',
|
|
119
|
+
validation: 'POST /orders',
|
|
120
|
+
mode: 'reject',
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('skips span attributes when there is no active span (fail-open)', () => {
|
|
125
|
+
vi.spyOn(trace, 'getActiveSpan').mockReturnValue();
|
|
126
|
+
expect(() => recordValidationMismatch(mismatch)).not.toThrow();
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('never throws even if the span sink throws', () => {
|
|
130
|
+
setAttributes.mockImplementation(() => {
|
|
131
|
+
throw new Error('span boom');
|
|
132
|
+
});
|
|
133
|
+
expect(() => recordValidationMismatch(mismatch)).not.toThrow();
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
describe('onValidationMismatch', () => {
|
|
138
|
+
const mismatch = (name: string): ValidationMismatch => ({
|
|
139
|
+
name,
|
|
140
|
+
boundary: 'event',
|
|
141
|
+
mode: 'observe',
|
|
142
|
+
issues: [],
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// The listener registry is module-global; track every unsubscribe so a test
|
|
146
|
+
// can't leak a subscriber into the next one.
|
|
147
|
+
const cleanups: Array<() => void> = [];
|
|
148
|
+
const register = (handler: (m: ValidationMismatch) => void) => {
|
|
149
|
+
const off = onValidationMismatch(handler);
|
|
150
|
+
cleanups.push(off);
|
|
151
|
+
return off;
|
|
152
|
+
};
|
|
153
|
+
afterEach(() => {
|
|
154
|
+
while (cleanups.length > 0) cleanups.pop()!();
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('invokes a registered listener and can unsubscribe', () => {
|
|
158
|
+
const seen: ValidationMismatch[] = [];
|
|
159
|
+
const off = register((m) => seen.push(m));
|
|
160
|
+
recordValidationMismatch(mismatch('x'));
|
|
161
|
+
expect(seen).toHaveLength(1);
|
|
162
|
+
off();
|
|
163
|
+
recordValidationMismatch(mismatch('y'));
|
|
164
|
+
expect(seen).toHaveLength(1); // not called after unsubscribe
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('delivers each mismatch to every simultaneous subscriber', () => {
|
|
168
|
+
// The real case: autotel-audit registers a security bridge while the app
|
|
169
|
+
// registers its own webhook/logger — both must fire.
|
|
170
|
+
const audit: string[] = [];
|
|
171
|
+
const webhook: string[] = [];
|
|
172
|
+
register((m) => audit.push(m.name));
|
|
173
|
+
register((m) => webhook.push(m.name));
|
|
174
|
+
|
|
175
|
+
recordValidationMismatch(mismatch('POST /login'));
|
|
176
|
+
|
|
177
|
+
expect(audit).toEqual(['POST /login']);
|
|
178
|
+
expect(webhook).toEqual(['POST /login']);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('unsubscribes each subscriber independently', () => {
|
|
182
|
+
const a: string[] = [];
|
|
183
|
+
const b: string[] = [];
|
|
184
|
+
const offA = register((m) => a.push(m.name));
|
|
185
|
+
register((m) => b.push(m.name));
|
|
186
|
+
|
|
187
|
+
recordValidationMismatch(mismatch('first'));
|
|
188
|
+
offA(); // remove only A
|
|
189
|
+
recordValidationMismatch(mismatch('second'));
|
|
190
|
+
|
|
191
|
+
expect(a).toEqual(['first']); // A stopped after unsubscribe
|
|
192
|
+
expect(b).toEqual(['first', 'second']); // B keeps firing
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('isolates faults: a throwing subscriber neither throws nor starves peers', () => {
|
|
196
|
+
const survivor: string[] = [];
|
|
197
|
+
register(() => {
|
|
198
|
+
throw new Error('subscriber boom');
|
|
199
|
+
});
|
|
200
|
+
register((m) => survivor.push(m.name));
|
|
201
|
+
|
|
202
|
+
expect(() => recordValidationMismatch(mismatch('z'))).not.toThrow();
|
|
203
|
+
expect(survivor).toEqual(['z']); // the healthy subscriber still fired
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('treats a re-registered identical handler as a single subscription', () => {
|
|
207
|
+
const seen: string[] = [];
|
|
208
|
+
const handler = (m: ValidationMismatch) => seen.push(m.name);
|
|
209
|
+
register(handler);
|
|
210
|
+
register(handler); // Set semantics → still one
|
|
211
|
+
recordValidationMismatch(mismatch('once'));
|
|
212
|
+
expect(seen).toEqual(['once']);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
describe('defineValidator', () => {
|
|
217
|
+
const ok = schema<{ a: number }>(() => ({ success: true, data: { a: 1 } }));
|
|
218
|
+
const bad = schema<{ a: number }>(() => ({
|
|
219
|
+
success: false,
|
|
220
|
+
error: zodLikeError,
|
|
221
|
+
}));
|
|
222
|
+
|
|
223
|
+
it('reject mode (default): records then throws a 400 structured error', () => {
|
|
224
|
+
const v = defineValidator('POST /orders', bad, { boundary: 'http' });
|
|
225
|
+
expect(v.mode).toBe('reject');
|
|
226
|
+
try {
|
|
227
|
+
v.parse({ user: { ssn: SECRET } });
|
|
228
|
+
throw new Error('should have thrown');
|
|
229
|
+
} catch (error) {
|
|
230
|
+
const e = error as { status?: number; code?: string; message: string };
|
|
231
|
+
expect(e.status).toBe(400);
|
|
232
|
+
expect(e.code).toBe('validation_failed');
|
|
233
|
+
// even the thrown error must not leak the value
|
|
234
|
+
expect(JSON.stringify({ m: e.message })).not.toContain(SECRET);
|
|
235
|
+
}
|
|
236
|
+
expect(setAttributes).toHaveBeenCalled();
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it('observe mode: records then returns the raw input (no throw)', () => {
|
|
240
|
+
const v = defineValidator('order.placed', bad, {
|
|
241
|
+
boundary: 'event',
|
|
242
|
+
onMismatch: 'observe',
|
|
243
|
+
});
|
|
244
|
+
const raw = { user: { ssn: SECRET } };
|
|
245
|
+
expect(v.parse(raw)).toBe(raw);
|
|
246
|
+
expect(setAttributes).toHaveBeenCalledWith(
|
|
247
|
+
expect.objectContaining({ [VALIDATION_ATTR.mode]: 'observe' }),
|
|
248
|
+
);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it('returns parsed data and records nothing on success', () => {
|
|
252
|
+
const v = defineValidator('ok', ok);
|
|
253
|
+
expect(v.parse({})).toEqual({ a: 1 });
|
|
254
|
+
expect(setAttributes).not.toHaveBeenCalled();
|
|
255
|
+
expect(counterAdd).not.toHaveBeenCalled();
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it('safeParse returns a discriminated result and never throws', () => {
|
|
259
|
+
const v = defineValidator('POST /orders', bad);
|
|
260
|
+
const result = v.safeParse({});
|
|
261
|
+
expect(result.success).toBe(false);
|
|
262
|
+
if (!result.success) {
|
|
263
|
+
expect(result.issues[0]).toEqual({
|
|
264
|
+
path: 'user.ssn',
|
|
265
|
+
code: 'invalid_type',
|
|
266
|
+
expected: 'string',
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
it('honors a custom onReject error builder', () => {
|
|
272
|
+
const v = defineValidator('x', bad, {
|
|
273
|
+
onReject: () => new Error('custom reject'),
|
|
274
|
+
});
|
|
275
|
+
expect(() => v.parse({})).toThrow('custom reject');
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it('emits a stable validation.hash when toJsonSchema is provided', () => {
|
|
279
|
+
const v = defineValidator('x', bad, {
|
|
280
|
+
toJsonSchema: () => ({ type: 'object' }),
|
|
281
|
+
});
|
|
282
|
+
v.safeParse({});
|
|
283
|
+
const attrs = setAttributes.mock.calls[0][0];
|
|
284
|
+
expect(typeof attrs[VALIDATION_ATTR.hash]).toBe('string');
|
|
285
|
+
expect(attrs[VALIDATION_ATTR.hash]).toHaveLength(64); // sha256 hex
|
|
286
|
+
});
|
|
287
|
+
});
|
package/src/validate.ts
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation telemetry — connect runtime input validation (Zod or any
|
|
3
|
+
* `safeParse` schema) to your traces and metrics at the boundaries where bad
|
|
4
|
+
* data actually enters: HTTP bodies, events, messages.
|
|
5
|
+
*
|
|
6
|
+
* Today a `safeParse` failure either throws (no span, no metric, no alert) or
|
|
7
|
+
* is silently swallowed in a handler. `defineValidator` makes the mismatch
|
|
8
|
+
* **observable** — a `validation.*` span attribute set and a counter
|
|
9
|
+
* incremented — with a per-validator `observe` vs `reject` mode:
|
|
10
|
+
*
|
|
11
|
+
* - `reject` (default): record telemetry, then throw a structured 400-shaped
|
|
12
|
+
* error so the boundary can fail cleanly.
|
|
13
|
+
* - `observe`: record telemetry, return the raw input so the handler continues
|
|
14
|
+
* — useful for measuring real-world drift before you enforce it.
|
|
15
|
+
*
|
|
16
|
+
* **Not a security feature by default.** A malformed body is usually a bug or
|
|
17
|
+
* version skew, not an attack. Validation telemetry is first-class on its own
|
|
18
|
+
* metric; escalation to the security path is a deliberate opt-in via
|
|
19
|
+
* {@link onValidationMismatch} (e.g. wired by `autotel-audit`), never automatic.
|
|
20
|
+
*
|
|
21
|
+
* **PII-safe by construction.** Only field *paths*, issue *codes*, and the
|
|
22
|
+
* declared *type* are ever recorded — never the offending value, and never a
|
|
23
|
+
* validator's error `message` (which routinely embeds the received value).
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { trace } from '@opentelemetry/api';
|
|
27
|
+
import { createCounter } from './metric-helpers';
|
|
28
|
+
import {
|
|
29
|
+
createStructuredError,
|
|
30
|
+
type StructuredError,
|
|
31
|
+
} from './structured-error';
|
|
32
|
+
import { hashJson } from './stable-hash';
|
|
33
|
+
import type { SchemaLike } from './define-event';
|
|
34
|
+
import {
|
|
35
|
+
VALIDATION_ATTR,
|
|
36
|
+
VALIDATION_ISSUE_CAP,
|
|
37
|
+
VALIDATION_METRICS,
|
|
38
|
+
} from './validation-attributes';
|
|
39
|
+
|
|
40
|
+
export type { SchemaLike } from './define-event';
|
|
41
|
+
|
|
42
|
+
export type ValidationMode = 'observe' | 'reject';
|
|
43
|
+
export type ValidationSeverity = 'info' | 'warning' | 'error';
|
|
44
|
+
|
|
45
|
+
/** A single failing field, stripped of any payload values. */
|
|
46
|
+
export interface ValidationIssue {
|
|
47
|
+
/** Dotted field path, e.g. `items.0.price`. Never a value. */
|
|
48
|
+
path: string;
|
|
49
|
+
/** Issue code (e.g. Zod's `invalid_type`, `too_small`). Never a value. */
|
|
50
|
+
code: string;
|
|
51
|
+
/** Declared type/constraint summary, e.g. `string`. Never a received value. */
|
|
52
|
+
expected?: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Everything the recorder needs — already PII-stripped by the caller. */
|
|
56
|
+
export interface ValidationMismatch {
|
|
57
|
+
/** Contract id, e.g. `POST /orders` or `order.placed`. */
|
|
58
|
+
name: string;
|
|
59
|
+
boundary: string;
|
|
60
|
+
mode: ValidationMode;
|
|
61
|
+
issues: ValidationIssue[];
|
|
62
|
+
hash?: string;
|
|
63
|
+
severity?: ValidationSeverity;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let mismatchCounter: ReturnType<typeof createCounter> | undefined;
|
|
67
|
+
function counter(): ReturnType<typeof createCounter> {
|
|
68
|
+
if (!mismatchCounter) {
|
|
69
|
+
mismatchCounter = createCounter(VALIDATION_METRICS.mismatches, {
|
|
70
|
+
description: 'Input payloads that did not match their declared shape',
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return mismatchCounter;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
type MismatchListener = (mismatch: ValidationMismatch) => void;
|
|
77
|
+
const listeners = new Set<MismatchListener>();
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Register an explicit handler called on every recorded mismatch — the opt-in
|
|
81
|
+
* seam for escalating to security events, a webhook, or a custom sink. There is
|
|
82
|
+
* no automatic, package-presence-driven escalation: nothing fires here unless
|
|
83
|
+
* you (or a package you wire up) register a handler.
|
|
84
|
+
*
|
|
85
|
+
* Multiple subscribers coexist: a package (e.g. `autotel-audit` bridging to
|
|
86
|
+
* security events) and your own app code (a webhook, a logger) can both
|
|
87
|
+
* register and all fire. Returns an unsubscribe fn that removes only this
|
|
88
|
+
* handler; registering the same function twice is a no-op (Set semantics).
|
|
89
|
+
*/
|
|
90
|
+
export function onValidationMismatch(handler: MismatchListener): () => void {
|
|
91
|
+
listeners.add(handler);
|
|
92
|
+
return () => {
|
|
93
|
+
listeners.delete(handler);
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const truncate = (values: string[]): string =>
|
|
98
|
+
values.slice(0, VALIDATION_ISSUE_CAP).join(',');
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Record a validation mismatch as telemetry: `validation.*` attributes on the
|
|
102
|
+
* active span (if any) and an increment on `autotel.validation.mismatches`.
|
|
103
|
+
* Fail-open — never throws, so instrumentation can't break the boundary.
|
|
104
|
+
*/
|
|
105
|
+
export function recordValidationMismatch(mismatch: ValidationMismatch): void {
|
|
106
|
+
try {
|
|
107
|
+
const paths = mismatch.issues.map((i) => i.path).filter(Boolean);
|
|
108
|
+
const codes = [...new Set(mismatch.issues.map((i) => i.code))];
|
|
109
|
+
|
|
110
|
+
const span = trace.getActiveSpan();
|
|
111
|
+
if (span) {
|
|
112
|
+
span.setAttributes({
|
|
113
|
+
[VALIDATION_ATTR.name]: mismatch.name,
|
|
114
|
+
[VALIDATION_ATTR.boundary]: mismatch.boundary,
|
|
115
|
+
[VALIDATION_ATTR.mode]: mismatch.mode,
|
|
116
|
+
[VALIDATION_ATTR.issueCount]: mismatch.issues.length,
|
|
117
|
+
[VALIDATION_ATTR.issuePaths]: truncate(paths),
|
|
118
|
+
[VALIDATION_ATTR.issueCodes]: truncate(codes),
|
|
119
|
+
...(mismatch.hash ? { [VALIDATION_ATTR.hash]: mismatch.hash } : {}),
|
|
120
|
+
...(mismatch.severity
|
|
121
|
+
? { [VALIDATION_ATTR.severity]: mismatch.severity }
|
|
122
|
+
: {}),
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
counter().add(1, {
|
|
128
|
+
boundary: mismatch.boundary,
|
|
129
|
+
validation: mismatch.name,
|
|
130
|
+
mode: mismatch.mode,
|
|
131
|
+
});
|
|
132
|
+
} catch {
|
|
133
|
+
// meter not initialised yet — skip the count, keep the span attrs
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Dispatch to every subscriber with per-listener fault isolation: one
|
|
137
|
+
// throwing subscriber must not starve its peers or break the boundary.
|
|
138
|
+
// Set iteration tolerates concurrent (un)subscription safely.
|
|
139
|
+
for (const listener of listeners) {
|
|
140
|
+
try {
|
|
141
|
+
listener(mismatch);
|
|
142
|
+
} catch {
|
|
143
|
+
// a misbehaving subscriber must not break the boundary or its peers
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
} catch {
|
|
147
|
+
// fail-open: telemetry must never break the validated boundary
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Normalise an arbitrary validation error into PII-safe issues. Reads only
|
|
153
|
+
* `path`, `code`, and (when it is a declared type name) `expected` — and never
|
|
154
|
+
* `message`, `received`, or any value-bearing field. Understands the Zod shape
|
|
155
|
+
* (`error.issues`) and a generic `error.errors` fallback; returns `[]` for
|
|
156
|
+
* anything unrecognised.
|
|
157
|
+
*/
|
|
158
|
+
export function formatValidationIssues(error: unknown): ValidationIssue[] {
|
|
159
|
+
const raw = extractRawIssues(error);
|
|
160
|
+
return raw.map((issue) => toSafeIssue(issue));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function extractRawIssues(error: unknown): Array<Record<string, unknown>> {
|
|
164
|
+
if (error && typeof error === 'object') {
|
|
165
|
+
const candidate =
|
|
166
|
+
(error as { issues?: unknown }).issues ??
|
|
167
|
+
(error as { errors?: unknown }).errors;
|
|
168
|
+
if (Array.isArray(candidate)) {
|
|
169
|
+
return candidate.filter(
|
|
170
|
+
(i): i is Record<string, unknown> =>
|
|
171
|
+
i !== null && typeof i === 'object',
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return [];
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function toSafeIssue(issue: Record<string, unknown>): ValidationIssue {
|
|
179
|
+
const rawPath = issue.path;
|
|
180
|
+
const path = Array.isArray(rawPath)
|
|
181
|
+
? rawPath.map(String).join('.')
|
|
182
|
+
: typeof rawPath === 'string'
|
|
183
|
+
? rawPath
|
|
184
|
+
: '';
|
|
185
|
+
const code = typeof issue.code === 'string' ? issue.code : 'invalid';
|
|
186
|
+
// `expected` is a declared type name in Zod (e.g. 'string'); safe. We never
|
|
187
|
+
// read `received`/`message`/`value`, which can carry the offending payload.
|
|
188
|
+
const expected =
|
|
189
|
+
typeof issue.expected === 'string' ? issue.expected : undefined;
|
|
190
|
+
return expected ? { path, code, expected } : { path, code };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export interface DefineValidatorOptions<S> {
|
|
194
|
+
/** Where validation runs. Defaults to `input`. */
|
|
195
|
+
boundary?: string;
|
|
196
|
+
/** `reject` (default): record then throw. `observe`: record then continue. */
|
|
197
|
+
onMismatch?: ValidationMode;
|
|
198
|
+
/** Project the schema to JSON Schema for a stable `validation.hash`. */
|
|
199
|
+
toJsonSchema?: (schema: S) => unknown;
|
|
200
|
+
severity?: ValidationSeverity;
|
|
201
|
+
/** Build the error thrown in `reject` mode (defaults to a 400 structured error). */
|
|
202
|
+
onReject?: (issues: ValidationIssue[], name: string) => Error;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export type ValidatorResult<T> =
|
|
206
|
+
| { success: true; data: T }
|
|
207
|
+
| { success: false; issues: ValidationIssue[] };
|
|
208
|
+
|
|
209
|
+
export interface Validator<T> {
|
|
210
|
+
readonly name: string;
|
|
211
|
+
readonly mode: ValidationMode;
|
|
212
|
+
/** Validate and record on failure; never throws. */
|
|
213
|
+
safeParse(input: unknown): ValidatorResult<T>;
|
|
214
|
+
/**
|
|
215
|
+
* Validate, record on failure, then apply the mode: `reject` throws,
|
|
216
|
+
* `observe` returns the raw input so the handler can continue.
|
|
217
|
+
*/
|
|
218
|
+
parse(input: unknown): T;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function defaultRejectError(
|
|
222
|
+
issues: ValidationIssue[],
|
|
223
|
+
name: string,
|
|
224
|
+
): StructuredError {
|
|
225
|
+
return createStructuredError({
|
|
226
|
+
name: 'ValidationError',
|
|
227
|
+
status: 400,
|
|
228
|
+
code: 'validation_failed',
|
|
229
|
+
message: `Input for "${name}" did not match its declared shape.`,
|
|
230
|
+
why: `${issues.length} field(s) failed validation: ${issues
|
|
231
|
+
.map((i) => i.path || '(root)')
|
|
232
|
+
.slice(0, VALIDATION_ISSUE_CAP)
|
|
233
|
+
.join(', ')}.`,
|
|
234
|
+
fix: 'Send a payload that matches the schema, or switch this validator to observe mode while you investigate.',
|
|
235
|
+
// PII-safe: paths + codes only, no received values.
|
|
236
|
+
details: { validation: name, issues },
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Declare an expected input shape once and get a validator that records every
|
|
242
|
+
* mismatch as telemetry.
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```ts
|
|
246
|
+
* import { z } from 'zod';
|
|
247
|
+
* import { defineValidator } from 'autotel/validate';
|
|
248
|
+
*
|
|
249
|
+
* const OrderBody = defineValidator('POST /orders', z.object({
|
|
250
|
+
* items: z.array(z.object({ sku: z.string(), qty: z.number().int() })),
|
|
251
|
+
* }), { boundary: 'http', toJsonSchema: (s) => z.toJSONSchema(s) });
|
|
252
|
+
*
|
|
253
|
+
* // reject mode (default): records + throws a 400-shaped structured error
|
|
254
|
+
* const order = OrderBody.parse(req.body);
|
|
255
|
+
*
|
|
256
|
+
* // observe mode: records, returns the result, never throws
|
|
257
|
+
* const result = OrderBody.safeParse(req.body);
|
|
258
|
+
* if (!result.success) metrics.onDrift(result.issues);
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
export function defineValidator<T, S extends SchemaLike<T>>(
|
|
262
|
+
name: string,
|
|
263
|
+
schema: S,
|
|
264
|
+
options: DefineValidatorOptions<S> = {},
|
|
265
|
+
): Validator<T> {
|
|
266
|
+
const mode = options.onMismatch ?? 'reject';
|
|
267
|
+
const boundary = options.boundary ?? 'input';
|
|
268
|
+
const hash = options.toJsonSchema
|
|
269
|
+
? hashJson(options.toJsonSchema(schema))
|
|
270
|
+
: undefined;
|
|
271
|
+
|
|
272
|
+
const record = (issues: ValidationIssue[]): void => {
|
|
273
|
+
recordValidationMismatch({
|
|
274
|
+
name,
|
|
275
|
+
boundary,
|
|
276
|
+
mode,
|
|
277
|
+
issues,
|
|
278
|
+
hash,
|
|
279
|
+
severity: options.severity,
|
|
280
|
+
});
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
return {
|
|
284
|
+
name,
|
|
285
|
+
mode,
|
|
286
|
+
safeParse(input: unknown): ValidatorResult<T> {
|
|
287
|
+
const parsed = schema.safeParse(input);
|
|
288
|
+
if (parsed.success) return { success: true, data: parsed.data };
|
|
289
|
+
const issues = formatValidationIssues(parsed.error);
|
|
290
|
+
record(issues);
|
|
291
|
+
return { success: false, issues };
|
|
292
|
+
},
|
|
293
|
+
parse(input: unknown): T {
|
|
294
|
+
const parsed = schema.safeParse(input);
|
|
295
|
+
if (parsed.success) return parsed.data;
|
|
296
|
+
const issues = formatValidationIssues(parsed.error);
|
|
297
|
+
record(issues);
|
|
298
|
+
if (mode === 'reject') {
|
|
299
|
+
throw (
|
|
300
|
+
options.onReject?.(issues, name) ?? defaultRejectError(issues, name)
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
// observe: continue with the raw input (documented type caveat)
|
|
304
|
+
return input as T;
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
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
|
+
|
|
15
|
+
export const VALIDATION_ATTR = {
|
|
16
|
+
/** Contract id of the validated boundary, e.g. `POST /orders`, `order.placed`. */
|
|
17
|
+
name: 'validation.name',
|
|
18
|
+
/** Where validation ran: `http` | `event` | `message` | a custom label. */
|
|
19
|
+
boundary: 'validation.boundary',
|
|
20
|
+
/** `observe` (recorded, request continues) or `reject` (recorded, then failed). */
|
|
21
|
+
mode: 'validation.mode',
|
|
22
|
+
/** Stable hash of the declared shape, when a JSON-schema projection is given. */
|
|
23
|
+
hash: 'validation.hash',
|
|
24
|
+
/** `info` | `warning` | `error`. */
|
|
25
|
+
severity: 'validation.severity',
|
|
26
|
+
/** Number of failing fields. */
|
|
27
|
+
issueCount: 'validation.issue.count',
|
|
28
|
+
/** Comma-separated failing field paths (capped). Never contains values. */
|
|
29
|
+
issuePaths: 'validation.issue.paths',
|
|
30
|
+
/** Comma-separated distinct issue codes (capped). Never contains values. */
|
|
31
|
+
issueCodes: 'validation.issue.codes',
|
|
32
|
+
} as const;
|
|
33
|
+
|
|
34
|
+
export type ValidationAttributeKey =
|
|
35
|
+
(typeof VALIDATION_ATTR)[keyof typeof VALIDATION_ATTR];
|
|
36
|
+
|
|
37
|
+
export const VALIDATION_METRICS = {
|
|
38
|
+
/** Counter, labelled `{ boundary, validation, mode }`. */
|
|
39
|
+
mismatches: 'autotel.validation.mismatches',
|
|
40
|
+
} as const;
|
|
41
|
+
|
|
42
|
+
/** Max field paths / codes stamped onto a span, to bound attribute size. */
|
|
43
|
+
export const VALIDATION_ISSUE_CAP = 20;
|
package/dist/attributes.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"attributes.cjs"}
|
package/dist/attributes.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"attributes.js"}
|
package/dist/chunk-2ZKEORFN.cjs
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// src/semantic-conventions.ts
|
|
4
|
-
function httpRequestHeaderAttribute(name) {
|
|
5
|
-
return `http.request.header.${name.toLowerCase()}`;
|
|
6
|
-
}
|
|
7
|
-
function httpResponseHeaderAttribute(name) {
|
|
8
|
-
return `http.response.header.${name.toLowerCase()}`;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
exports.httpRequestHeaderAttribute = httpRequestHeaderAttribute;
|
|
12
|
-
exports.httpResponseHeaderAttribute = httpResponseHeaderAttribute;
|
|
13
|
-
//# sourceMappingURL=chunk-2ZKEORFN.cjs.map
|
|
14
|
-
//# sourceMappingURL=chunk-2ZKEORFN.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/semantic-conventions.ts"],"names":[],"mappings":";;;AAQO,SAAS,2BAA2B,IAAA,EAAsB;AAC/D,EAAA,OAAO,CAAA,oBAAA,EAAuB,IAAA,CAAK,WAAA,EAAa,CAAA,CAAA;AAClD;AAEO,SAAS,4BAA4B,IAAA,EAAsB;AAChE,EAAA,OAAO,CAAA,qBAAA,EAAwB,IAAA,CAAK,WAAA,EAAa,CAAA,CAAA;AACnD","file":"chunk-2ZKEORFN.cjs","sourcesContent":["import {\n HTTPAttributes,\n ServiceAttributes,\n URLAttributes,\n} from './attributes/registry';\n\nexport { HTTPAttributes, ServiceAttributes, URLAttributes };\n\nexport function httpRequestHeaderAttribute(name: string): string {\n return `http.request.header.${name.toLowerCase()}`;\n}\n\nexport function httpResponseHeaderAttribute(name: string): string {\n return `http.response.header.${name.toLowerCase()}`;\n}\n"]}
|