observability-toolkit 1.8.2 → 1.8.5

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 (259) hide show
  1. package/README.md +60 -0
  2. package/dist/backends/index.d.ts +43 -0
  3. package/dist/backends/index.d.ts.map +1 -1
  4. package/dist/backends/index.js +41 -0
  5. package/dist/backends/index.js.map +1 -1
  6. package/dist/backends/index.test.d.ts +5 -0
  7. package/dist/backends/index.test.d.ts.map +1 -0
  8. package/dist/backends/index.test.js +156 -0
  9. package/dist/backends/index.test.js.map +1 -0
  10. package/dist/backends/local-jsonl-boolean-search.test.js +15 -12
  11. package/dist/backends/local-jsonl-boolean-search.test.js.map +1 -1
  12. package/dist/backends/local-jsonl-cache.test.d.ts +2 -0
  13. package/dist/backends/local-jsonl-cache.test.d.ts.map +1 -0
  14. package/dist/backends/local-jsonl-cache.test.js +295 -0
  15. package/dist/backends/local-jsonl-cache.test.js.map +1 -0
  16. package/dist/backends/local-jsonl-circuit-breaker.test.d.ts +2 -0
  17. package/dist/backends/local-jsonl-circuit-breaker.test.d.ts.map +1 -0
  18. package/dist/backends/local-jsonl-circuit-breaker.test.js +180 -0
  19. package/dist/backends/local-jsonl-circuit-breaker.test.js.map +1 -0
  20. package/dist/backends/local-jsonl-export.test.d.ts +2 -0
  21. package/dist/backends/local-jsonl-export.test.d.ts.map +1 -0
  22. package/dist/backends/local-jsonl-export.test.js +704 -0
  23. package/dist/backends/local-jsonl-export.test.js.map +1 -0
  24. package/dist/backends/local-jsonl-index.test.d.ts +2 -0
  25. package/dist/backends/local-jsonl-index.test.d.ts.map +1 -0
  26. package/dist/backends/local-jsonl-index.test.js +554 -0
  27. package/dist/backends/local-jsonl-index.test.js.map +1 -0
  28. package/dist/backends/local-jsonl-logs.test.d.ts +2 -0
  29. package/dist/backends/local-jsonl-logs.test.d.ts.map +1 -0
  30. package/dist/backends/local-jsonl-logs.test.js +612 -0
  31. package/dist/backends/local-jsonl-logs.test.js.map +1 -0
  32. package/dist/backends/local-jsonl-metrics.test.d.ts +2 -0
  33. package/dist/backends/local-jsonl-metrics.test.d.ts.map +1 -0
  34. package/dist/backends/local-jsonl-metrics.test.js +876 -0
  35. package/dist/backends/local-jsonl-metrics.test.js.map +1 -0
  36. package/dist/backends/local-jsonl-traces.test.d.ts +2 -0
  37. package/dist/backends/local-jsonl-traces.test.d.ts.map +1 -0
  38. package/dist/backends/local-jsonl-traces.test.js +1729 -0
  39. package/dist/backends/local-jsonl-traces.test.js.map +1 -0
  40. package/dist/backends/local-jsonl.d.ts +9 -0
  41. package/dist/backends/local-jsonl.d.ts.map +1 -1
  42. package/dist/backends/local-jsonl.js +348 -227
  43. package/dist/backends/local-jsonl.js.map +1 -1
  44. package/dist/backends/local-jsonl.test.js +290 -21
  45. package/dist/backends/local-jsonl.test.js.map +1 -1
  46. package/dist/backends/signoz-api-circuit-breaker.test.d.ts +6 -0
  47. package/dist/backends/signoz-api-circuit-breaker.test.d.ts.map +1 -0
  48. package/dist/backends/signoz-api-circuit-breaker.test.js +548 -0
  49. package/dist/backends/signoz-api-circuit-breaker.test.js.map +1 -0
  50. package/dist/backends/signoz-api-rate-limiter.test.d.ts +6 -0
  51. package/dist/backends/signoz-api-rate-limiter.test.d.ts.map +1 -0
  52. package/dist/backends/signoz-api-rate-limiter.test.js +389 -0
  53. package/dist/backends/signoz-api-rate-limiter.test.js.map +1 -0
  54. package/dist/backends/signoz-api-ssrf.test.d.ts +6 -0
  55. package/dist/backends/signoz-api-ssrf.test.d.ts.map +1 -0
  56. package/dist/backends/signoz-api-ssrf.test.js +216 -0
  57. package/dist/backends/signoz-api-ssrf.test.js.map +1 -0
  58. package/dist/backends/signoz-api-test-helpers.d.ts +80 -0
  59. package/dist/backends/signoz-api-test-helpers.d.ts.map +1 -0
  60. package/dist/backends/signoz-api-test-helpers.js +79 -0
  61. package/dist/backends/signoz-api-test-helpers.js.map +1 -0
  62. package/dist/backends/signoz-api.d.ts +16 -0
  63. package/dist/backends/signoz-api.d.ts.map +1 -1
  64. package/dist/backends/signoz-api.js +71 -9
  65. package/dist/backends/signoz-api.js.map +1 -1
  66. package/dist/backends/signoz-api.test.d.ts +9 -0
  67. package/dist/backends/signoz-api.test.d.ts.map +1 -1
  68. package/dist/backends/signoz-api.test.js +14 -1027
  69. package/dist/backends/signoz-api.test.js.map +1 -1
  70. package/dist/lib/cache.d.ts +47 -1
  71. package/dist/lib/cache.d.ts.map +1 -1
  72. package/dist/lib/cache.js +40 -3
  73. package/dist/lib/cache.js.map +1 -1
  74. package/dist/lib/circuit-breaker.d.ts +83 -0
  75. package/dist/lib/circuit-breaker.d.ts.map +1 -0
  76. package/dist/lib/circuit-breaker.js +125 -0
  77. package/dist/lib/circuit-breaker.js.map +1 -0
  78. package/dist/lib/circuit-breaker.test.d.ts +2 -0
  79. package/dist/lib/circuit-breaker.test.d.ts.map +1 -0
  80. package/dist/lib/circuit-breaker.test.js +263 -0
  81. package/dist/lib/circuit-breaker.test.js.map +1 -0
  82. package/dist/lib/constants-symlink.test.d.ts +12 -0
  83. package/dist/lib/constants-symlink.test.d.ts.map +1 -0
  84. package/dist/lib/constants-symlink.test.js +357 -0
  85. package/dist/lib/constants-symlink.test.js.map +1 -0
  86. package/dist/lib/constants.d.ts +43 -0
  87. package/dist/lib/constants.d.ts.map +1 -1
  88. package/dist/lib/constants.js +154 -24
  89. package/dist/lib/constants.js.map +1 -1
  90. package/dist/lib/constants.test.js +156 -7
  91. package/dist/lib/constants.test.js.map +1 -1
  92. package/dist/lib/edge-cases.test.d.ts +11 -0
  93. package/dist/lib/edge-cases.test.d.ts.map +1 -0
  94. package/dist/lib/edge-cases.test.js +634 -0
  95. package/dist/lib/edge-cases.test.js.map +1 -0
  96. package/dist/lib/error-sanitizer.d.ts.map +1 -1
  97. package/dist/lib/error-sanitizer.js +62 -26
  98. package/dist/lib/error-sanitizer.js.map +1 -1
  99. package/dist/lib/error-sanitizer.test.js +186 -0
  100. package/dist/lib/error-sanitizer.test.js.map +1 -1
  101. package/dist/lib/error-types.d.ts +54 -0
  102. package/dist/lib/error-types.d.ts.map +1 -0
  103. package/dist/lib/error-types.js +154 -0
  104. package/dist/lib/error-types.js.map +1 -0
  105. package/dist/lib/error-types.test.d.ts +2 -0
  106. package/dist/lib/error-types.test.d.ts.map +1 -0
  107. package/dist/lib/error-types.test.js +196 -0
  108. package/dist/lib/error-types.test.js.map +1 -0
  109. package/dist/lib/file-utils.test.js +3 -3
  110. package/dist/lib/file-utils.test.js.map +1 -1
  111. package/dist/lib/indexer.test.js +157 -24
  112. package/dist/lib/indexer.test.js.map +1 -1
  113. package/dist/lib/input-validator.d.ts +17 -0
  114. package/dist/lib/input-validator.d.ts.map +1 -1
  115. package/dist/lib/input-validator.fuzz.test.d.ts +12 -0
  116. package/dist/lib/input-validator.fuzz.test.d.ts.map +1 -0
  117. package/dist/lib/input-validator.fuzz.test.js +290 -0
  118. package/dist/lib/input-validator.fuzz.test.js.map +1 -0
  119. package/dist/lib/input-validator.js +62 -3
  120. package/dist/lib/input-validator.js.map +1 -1
  121. package/dist/lib/input-validator.test.js +129 -1
  122. package/dist/lib/input-validator.test.js.map +1 -1
  123. package/dist/lib/logger.d.ts +46 -0
  124. package/dist/lib/logger.d.ts.map +1 -0
  125. package/dist/lib/logger.js +81 -0
  126. package/dist/lib/logger.js.map +1 -0
  127. package/dist/lib/logger.test.d.ts +2 -0
  128. package/dist/lib/logger.test.d.ts.map +1 -0
  129. package/dist/lib/logger.test.js +122 -0
  130. package/dist/lib/logger.test.js.map +1 -0
  131. package/dist/lib/query-sanitizer.d.ts +51 -3
  132. package/dist/lib/query-sanitizer.d.ts.map +1 -1
  133. package/dist/lib/query-sanitizer.js +105 -31
  134. package/dist/lib/query-sanitizer.js.map +1 -1
  135. package/dist/lib/query-sanitizer.test.js +102 -1
  136. package/dist/lib/query-sanitizer.test.js.map +1 -1
  137. package/dist/lib/server-utils.d.ts +88 -0
  138. package/dist/lib/server-utils.d.ts.map +1 -0
  139. package/dist/lib/server-utils.js +173 -0
  140. package/dist/lib/server-utils.js.map +1 -0
  141. package/dist/lib/shared-schemas.d.ts +81 -0
  142. package/dist/lib/shared-schemas.d.ts.map +1 -0
  143. package/dist/lib/shared-schemas.js +80 -0
  144. package/dist/lib/shared-schemas.js.map +1 -0
  145. package/dist/lib/shared-schemas.test.d.ts +5 -0
  146. package/dist/lib/shared-schemas.test.d.ts.map +1 -0
  147. package/dist/lib/shared-schemas.test.js +106 -0
  148. package/dist/lib/shared-schemas.test.js.map +1 -0
  149. package/dist/lib/toon-encoder.d.ts +26 -0
  150. package/dist/lib/toon-encoder.d.ts.map +1 -0
  151. package/dist/lib/toon-encoder.js +61 -0
  152. package/dist/lib/toon-encoder.js.map +1 -0
  153. package/dist/lib/toon-encoder.test.d.ts +5 -0
  154. package/dist/lib/toon-encoder.test.d.ts.map +1 -0
  155. package/dist/lib/toon-encoder.test.js +85 -0
  156. package/dist/lib/toon-encoder.test.js.map +1 -0
  157. package/dist/server.d.ts +1 -49
  158. package/dist/server.d.ts.map +1 -1
  159. package/dist/server.js +154 -162
  160. package/dist/server.js.map +1 -1
  161. package/dist/server.test.js +198 -7
  162. package/dist/server.test.js.map +1 -1
  163. package/dist/test-helpers/env-utils.d.ts +87 -0
  164. package/dist/test-helpers/env-utils.d.ts.map +1 -0
  165. package/dist/test-helpers/env-utils.js +132 -0
  166. package/dist/test-helpers/env-utils.js.map +1 -0
  167. package/dist/test-helpers/file-utils.d.ts +67 -0
  168. package/dist/test-helpers/file-utils.d.ts.map +1 -1
  169. package/dist/test-helpers/file-utils.js +165 -2
  170. package/dist/test-helpers/file-utils.js.map +1 -1
  171. package/dist/test-helpers/fuzz-generators.d.ts +58 -0
  172. package/dist/test-helpers/fuzz-generators.d.ts.map +1 -0
  173. package/dist/test-helpers/fuzz-generators.js +216 -0
  174. package/dist/test-helpers/fuzz-generators.js.map +1 -0
  175. package/dist/test-helpers/index.d.ts +11 -0
  176. package/dist/test-helpers/index.d.ts.map +1 -0
  177. package/dist/test-helpers/index.js +30 -0
  178. package/dist/test-helpers/index.js.map +1 -0
  179. package/dist/test-helpers/memfs-utils.d.ts +181 -0
  180. package/dist/test-helpers/memfs-utils.d.ts.map +1 -0
  181. package/dist/test-helpers/memfs-utils.js +292 -0
  182. package/dist/test-helpers/memfs-utils.js.map +1 -0
  183. package/dist/test-helpers/memfs-utils.test.d.ts +5 -0
  184. package/dist/test-helpers/memfs-utils.test.d.ts.map +1 -0
  185. package/dist/test-helpers/memfs-utils.test.js +338 -0
  186. package/dist/test-helpers/memfs-utils.test.js.map +1 -0
  187. package/dist/test-helpers/mock-backends.d.ts +113 -2
  188. package/dist/test-helpers/mock-backends.d.ts.map +1 -1
  189. package/dist/test-helpers/mock-backends.js +199 -3
  190. package/dist/test-helpers/mock-backends.js.map +1 -1
  191. package/dist/test-helpers/mock-backends.test.d.ts +5 -0
  192. package/dist/test-helpers/mock-backends.test.d.ts.map +1 -0
  193. package/dist/test-helpers/mock-backends.test.js +368 -0
  194. package/dist/test-helpers/mock-backends.test.js.map +1 -0
  195. package/dist/test-helpers/race-condition-helpers.d.ts +85 -0
  196. package/dist/test-helpers/race-condition-helpers.d.ts.map +1 -0
  197. package/dist/test-helpers/race-condition-helpers.js +279 -0
  198. package/dist/test-helpers/race-condition-helpers.js.map +1 -0
  199. package/dist/test-helpers/schema-validators.d.ts +32 -0
  200. package/dist/test-helpers/schema-validators.d.ts.map +1 -0
  201. package/dist/test-helpers/schema-validators.js +125 -0
  202. package/dist/test-helpers/schema-validators.js.map +1 -0
  203. package/dist/test-helpers/test-data-builders.d.ts +260 -0
  204. package/dist/test-helpers/test-data-builders.d.ts.map +1 -0
  205. package/dist/test-helpers/test-data-builders.js +337 -0
  206. package/dist/test-helpers/test-data-builders.js.map +1 -0
  207. package/dist/test-helpers/test-data-builders.test.d.ts +2 -0
  208. package/dist/test-helpers/test-data-builders.test.d.ts.map +1 -0
  209. package/dist/test-helpers/test-data-builders.test.js +306 -0
  210. package/dist/test-helpers/test-data-builders.test.js.map +1 -0
  211. package/dist/test-helpers/tool-validators.d.ts +28 -0
  212. package/dist/test-helpers/tool-validators.d.ts.map +1 -0
  213. package/dist/test-helpers/tool-validators.js +71 -0
  214. package/dist/test-helpers/tool-validators.js.map +1 -0
  215. package/dist/tools/context-stats.d.ts +1 -0
  216. package/dist/tools/context-stats.d.ts.map +1 -1
  217. package/dist/tools/context-stats.js +9 -5
  218. package/dist/tools/context-stats.js.map +1 -1
  219. package/dist/tools/context-stats.test.js +24 -10
  220. package/dist/tools/context-stats.test.js.map +1 -1
  221. package/dist/tools/get-trace-url.js +2 -2
  222. package/dist/tools/get-trace-url.js.map +1 -1
  223. package/dist/tools/health-check.js +2 -2
  224. package/dist/tools/health-check.js.map +1 -1
  225. package/dist/tools/query-evaluations.d.ts +21 -18
  226. package/dist/tools/query-evaluations.d.ts.map +1 -1
  227. package/dist/tools/query-evaluations.js +33 -19
  228. package/dist/tools/query-evaluations.js.map +1 -1
  229. package/dist/tools/query-evaluations.test.js +60 -63
  230. package/dist/tools/query-evaluations.test.js.map +1 -1
  231. package/dist/tools/query-llm-events.d.ts +19 -15
  232. package/dist/tools/query-llm-events.d.ts.map +1 -1
  233. package/dist/tools/query-llm-events.js +31 -15
  234. package/dist/tools/query-llm-events.js.map +1 -1
  235. package/dist/tools/query-llm-events.test.js +277 -12
  236. package/dist/tools/query-llm-events.test.js.map +1 -1
  237. package/dist/tools/query-logs.d.ts +22 -22
  238. package/dist/tools/query-logs.d.ts.map +1 -1
  239. package/dist/tools/query-logs.js +9 -9
  240. package/dist/tools/query-logs.js.map +1 -1
  241. package/dist/tools/query-logs.test.js +19 -72
  242. package/dist/tools/query-logs.test.js.map +1 -1
  243. package/dist/tools/query-metrics.d.ts +14 -14
  244. package/dist/tools/query-metrics.d.ts.map +1 -1
  245. package/dist/tools/query-metrics.js +9 -9
  246. package/dist/tools/query-metrics.js.map +1 -1
  247. package/dist/tools/query-metrics.test.js +12 -25
  248. package/dist/tools/query-metrics.test.js.map +1 -1
  249. package/dist/tools/query-traces.d.ts +28 -28
  250. package/dist/tools/query-traces.d.ts.map +1 -1
  251. package/dist/tools/query-traces.js +18 -18
  252. package/dist/tools/query-traces.js.map +1 -1
  253. package/dist/tools/query-traces.test.js +58 -54
  254. package/dist/tools/query-traces.test.js.map +1 -1
  255. package/dist/tools/setup-claudeignore.js +7 -7
  256. package/dist/tools/setup-claudeignore.js.map +1 -1
  257. package/dist/tools/setup-claudeignore.test.js +4 -25
  258. package/dist/tools/setup-claudeignore.test.js.map +1 -1
  259. package/package.json +4 -2
@@ -0,0 +1,290 @@
1
+ /**
2
+ * Fuzzing tests for input validation (A2 Category 7)
3
+ *
4
+ * Tests input validation resilience against:
5
+ * - Random Unicode inputs
6
+ * - ReDoS patterns
7
+ * - SQL injection payloads
8
+ * - Path traversal payloads
9
+ * - Special number values
10
+ */
11
+ import { describe, it } from 'node:test';
12
+ import assert from 'node:assert';
13
+ import { validateLimit, validateDuration, validateDateRange, validateRegexPattern, validateInputSize, MAX_DURATION_MS, } from './input-validator.js';
14
+ import { generateRandomUnicodeString, generateRandomInteger, generateRandomDateString, getSqlInjectionPayloads, getPathTraversalPayloads, getSpecialNumbers, getControlCharacterStrings, getRedosPatterns, fuzz, } from '../test-helpers/fuzz-generators.js';
15
+ describe('input-validator fuzzing', () => {
16
+ describe('validateRegexPattern fuzzing', () => {
17
+ it('should handle random Unicode patterns without crashing', () => {
18
+ const results = fuzz(() => generateRandomUnicodeString(50), (input) => {
19
+ try {
20
+ validateRegexPattern(input);
21
+ }
22
+ catch {
23
+ // Expected - invalid patterns should throw
24
+ }
25
+ }, 100);
26
+ // Should complete without crashing (no unhandled exceptions)
27
+ assert.strictEqual(results.failed, 0, 'Should handle all Unicode inputs');
28
+ });
29
+ it('should reject ReDoS patterns', () => {
30
+ const patterns = getRedosPatterns();
31
+ for (const pattern of patterns) {
32
+ const start = Date.now();
33
+ try {
34
+ validateRegexPattern(pattern);
35
+ }
36
+ catch {
37
+ // Some patterns may be rejected for other reasons
38
+ }
39
+ const elapsed = Date.now() - start;
40
+ // Should not take more than 100ms (ReDoS protection)
41
+ assert.ok(elapsed < 100, `Pattern "${pattern}" took ${elapsed}ms - potential ReDoS`);
42
+ }
43
+ });
44
+ it('should handle nested groups safely', () => {
45
+ // Deeply nested groups
46
+ const depths = [5, 10, 15, 20];
47
+ for (const depth of depths) {
48
+ let pattern = '';
49
+ for (let i = 0; i < depth; i++)
50
+ pattern += '(';
51
+ pattern += 'x';
52
+ for (let i = 0; i < depth; i++)
53
+ pattern += ')';
54
+ const start = Date.now();
55
+ try {
56
+ validateRegexPattern(pattern);
57
+ }
58
+ catch {
59
+ // May throw for too many groups
60
+ }
61
+ const elapsed = Date.now() - start;
62
+ assert.ok(elapsed < 50, `Nested depth ${depth} took ${elapsed}ms`);
63
+ }
64
+ });
65
+ it('should handle mixed capturing and non-capturing groups', () => {
66
+ const patterns = [
67
+ '(?:a)(b)(?:c)(d)',
68
+ '((?:a)+)',
69
+ '(?:(a)+)',
70
+ '(?:(?:(?:a)))',
71
+ '((?:a)(?:b))(c)',
72
+ ];
73
+ for (const pattern of patterns) {
74
+ assert.doesNotThrow(() => validateRegexPattern(pattern), `Failed on: ${pattern}`);
75
+ }
76
+ });
77
+ });
78
+ describe('validateLimit fuzzing', () => {
79
+ it('should handle 1000 random integers', () => {
80
+ const results = fuzz(() => generateRandomInteger(-1000000, 1000000), (input) => {
81
+ const result = validateLimit(input);
82
+ // Result should always be between 1 and 1000
83
+ assert.ok(result >= 1 && result <= 1000, `Invalid result ${result} for input ${input}`);
84
+ }, 1000);
85
+ assert.strictEqual(results.failed, 0, 'All random integers should be handled');
86
+ });
87
+ it('should handle special number values', () => {
88
+ const special = getSpecialNumbers();
89
+ for (const num of special) {
90
+ const result = validateLimit(num);
91
+ // NaN gets clamped to 1 by Math.max(1, Math.min(NaN, 1000)) = Math.max(1, NaN) = NaN... but then compared
92
+ // Actually Math.max(1, NaN) = NaN, so we need to handle this
93
+ if (Number.isNaN(num)) {
94
+ // NaN handling: Math.max(1, Math.min(NaN, 1000)) might return NaN
95
+ // Document current behavior
96
+ assert.ok(typeof result === 'number', 'NaN should return a number');
97
+ }
98
+ else {
99
+ assert.ok(result >= 1 && result <= 1000, `Special value ${num} produced invalid result ${result}`);
100
+ }
101
+ }
102
+ });
103
+ });
104
+ describe('validateDuration fuzzing', () => {
105
+ it('should handle 1000 random positive numbers', () => {
106
+ const results = fuzz(() => generateRandomInteger(0, MAX_DURATION_MS * 2), (input) => {
107
+ const result = validateDuration(input, 'minDurationMs');
108
+ // Result should be clamped to [0, MAX_DURATION_MS]
109
+ assert.ok(result === undefined || (result >= 0 && result <= MAX_DURATION_MS), `Invalid result ${result} for input ${input}`);
110
+ }, 1000);
111
+ assert.strictEqual(results.failed, 0, 'All positive random values should be handled');
112
+ });
113
+ it('should reject negative numbers consistently', () => {
114
+ const negatives = [-1, -100, -1000, -Number.MAX_VALUE, -Infinity];
115
+ for (const neg of negatives) {
116
+ assert.throws(() => validateDuration(neg, 'minDurationMs'), /cannot be negative/, `Should reject negative: ${neg}`);
117
+ }
118
+ });
119
+ it('should handle NaN gracefully', () => {
120
+ // NaN behavior: NaN < 0 is false, so it passes the negative check
121
+ // Math.min(NaN, MAX) returns NaN
122
+ const result = validateDuration(NaN, 'minDurationMs');
123
+ // This documents current behavior - NaN passes through as NaN
124
+ // The test validates this behavior is consistent
125
+ assert.ok(Number.isNaN(result) || result === undefined || result >= 0, 'NaN handling');
126
+ });
127
+ it('should clamp Infinity to MAX_DURATION_MS', () => {
128
+ const result = validateDuration(Infinity, 'maxDurationMs');
129
+ assert.strictEqual(result, MAX_DURATION_MS, 'Infinity should be clamped');
130
+ });
131
+ it('should handle -0 correctly', () => {
132
+ const result = validateDuration(-0, 'minDurationMs');
133
+ // -0 passes the negative check because -0 < 0 is false
134
+ // Math.min(-0, MAX) returns -0
135
+ assert.ok(result === 0 || Object.is(result, -0), 'Should be 0 or -0');
136
+ // Both 0 and -0 are valid for duration
137
+ assert.ok(result !== undefined);
138
+ });
139
+ it('should handle Number.MAX_VALUE', () => {
140
+ const result = validateDuration(Number.MAX_VALUE, 'maxDurationMs');
141
+ assert.strictEqual(result, MAX_DURATION_MS, 'MAX_VALUE should be clamped');
142
+ });
143
+ it('should handle Number.MAX_SAFE_INTEGER', () => {
144
+ const result = validateDuration(Number.MAX_SAFE_INTEGER, 'minDurationMs');
145
+ assert.strictEqual(result, MAX_DURATION_MS, 'MAX_SAFE_INTEGER should be clamped');
146
+ });
147
+ it('should handle very small positive numbers', () => {
148
+ const result = validateDuration(0.0000001, 'minDurationMs');
149
+ assert.ok(result !== undefined && result >= 0 && result <= MAX_DURATION_MS);
150
+ });
151
+ it('should handle floating point edge cases', () => {
152
+ const result = validateDuration(86400000.000001, 'maxDurationMs');
153
+ // Should be clamped to MAX_DURATION_MS
154
+ assert.strictEqual(result, MAX_DURATION_MS);
155
+ });
156
+ });
157
+ describe('validateDateRange fuzzing', () => {
158
+ it('should handle 100 random date-like strings', () => {
159
+ let validCount = 0;
160
+ let invalidCount = 0;
161
+ for (let i = 0; i < 100; i++) {
162
+ const dateStr = generateRandomDateString();
163
+ try {
164
+ validateDateRange(dateStr, undefined);
165
+ validCount++;
166
+ }
167
+ catch {
168
+ invalidCount++;
169
+ }
170
+ }
171
+ // At least some should fail (random strings)
172
+ assert.ok(invalidCount > 0, 'Some random dates should be invalid');
173
+ });
174
+ it('should handle boundary year values', () => {
175
+ const boundaryYears = ['0000-01-01', '9999-12-31', '-001-01-01', '10000-01-01'];
176
+ for (const date of boundaryYears) {
177
+ try {
178
+ validateDateRange(date, date);
179
+ }
180
+ catch {
181
+ // Expected for invalid dates
182
+ }
183
+ // Should not throw unhandled exception
184
+ }
185
+ });
186
+ it('should handle SQL injection in date strings', () => {
187
+ const payloads = getSqlInjectionPayloads();
188
+ for (const payload of payloads) {
189
+ assert.throws(() => validateDateRange(payload, '2024-01-01'), /Invalid.*format/i, `Should reject SQL injection: ${payload.substring(0, 20)}...`);
190
+ }
191
+ });
192
+ });
193
+ describe('validateInputSize fuzzing', () => {
194
+ it('should handle input at exact boundary (65535, 65536, 65537 bytes)', () => {
195
+ // Just under limit
196
+ const under = { data: 'x'.repeat(65500) };
197
+ assert.doesNotThrow(() => validateInputSize(under));
198
+ // At limit (accounting for JSON overhead)
199
+ const at = { data: 'x'.repeat(65520) };
200
+ assert.doesNotThrow(() => validateInputSize(at));
201
+ // Over limit
202
+ const over = { data: 'x'.repeat(70000) };
203
+ assert.throws(() => validateInputSize(over), /exceeds maximum/);
204
+ });
205
+ it('should handle deeply nested objects', () => {
206
+ let obj = { value: 'x' };
207
+ for (let i = 0; i < 50; i++) {
208
+ obj = { nested: obj };
209
+ }
210
+ // Should handle deeply nested without stack overflow
211
+ assert.doesNotThrow(() => validateInputSize(obj));
212
+ });
213
+ it('should handle arrays with many elements', () => {
214
+ // Many small elements
215
+ const arr = Array.from({ length: 1000 }, (_, i) => ({ id: i }));
216
+ assert.doesNotThrow(() => validateInputSize(arr));
217
+ // Should throw when total size exceeds limit
218
+ const largeArr = Array.from({ length: 5000 }, (_, i) => ({ id: i, data: 'x'.repeat(20) }));
219
+ assert.throws(() => validateInputSize(largeArr), /exceeds maximum/);
220
+ });
221
+ it('should handle Unicode content correctly', () => {
222
+ // Unicode characters can be multiple bytes
223
+ // 🎉 is 4 bytes in UTF-8, need >65536 bytes total including JSON overhead
224
+ // JSON: {"emoji":"🎉🎉..."} adds ~12 bytes overhead
225
+ // Need: 65536 / 4 ≈ 16384 emoji, use 17000 to be safe
226
+ const unicode = { emoji: '🎉'.repeat(17000) };
227
+ assert.throws(() => validateInputSize(unicode), /exceeds maximum/);
228
+ });
229
+ it('should handle null bytes in strings', () => {
230
+ const withNulls = { data: 'test\x00hidden\x00data' };
231
+ assert.doesNotThrow(() => validateInputSize(withNulls));
232
+ });
233
+ });
234
+ describe('SQL injection resilience', () => {
235
+ it('should handle SQL injection payloads as regex patterns', () => {
236
+ const payloads = getSqlInjectionPayloads();
237
+ for (const payload of payloads) {
238
+ try {
239
+ validateRegexPattern(payload);
240
+ // If it doesn't throw, the pattern is valid regex (safe for our use)
241
+ }
242
+ catch {
243
+ // Expected - invalid regex
244
+ }
245
+ }
246
+ });
247
+ });
248
+ describe('path traversal resilience', () => {
249
+ it('should handle path traversal payloads as inputs', () => {
250
+ const payloads = getPathTraversalPayloads();
251
+ for (const payload of payloads) {
252
+ // These shouldn't crash the validators
253
+ try {
254
+ validateRegexPattern(payload);
255
+ }
256
+ catch {
257
+ // Expected for invalid patterns
258
+ }
259
+ // As date strings, should be rejected
260
+ assert.throws(() => validateDateRange(payload, '2024-01-01'), /Invalid.*format/i);
261
+ }
262
+ });
263
+ });
264
+ describe('control character handling', () => {
265
+ it('should handle control characters in inputs', () => {
266
+ const controlStrings = getControlCharacterStrings();
267
+ for (const str of controlStrings) {
268
+ try {
269
+ validateRegexPattern(str);
270
+ }
271
+ catch {
272
+ // May throw for invalid patterns
273
+ }
274
+ // Date validation should reject
275
+ assert.throws(() => validateDateRange(str, '2024-01-01'));
276
+ }
277
+ });
278
+ it('should handle null byte injection attempts', () => {
279
+ const nullBytePayloads = [
280
+ '2024-01-01\x00.evil',
281
+ 'error\x00hidden',
282
+ '\x00leading-null',
283
+ ];
284
+ for (const payload of nullBytePayloads) {
285
+ assert.throws(() => validateDateRange(payload, '2024-01-01'));
286
+ }
287
+ });
288
+ });
289
+ });
290
+ //# sourceMappingURL=input-validator.fuzz.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-validator.fuzz.test.js","sourceRoot":"","sources":["../../src/lib/input-validator.fuzz.test.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,7 @@ export const MAX_REGEX_LENGTH = 200;
13
13
  export const MAX_REGEX_GROUPS = 10;
14
14
  export const DEFAULT_LIMIT = 50;
15
15
  export const MAX_DURATION_MS = 86400000; // 24 hours
16
+ export const MAX_INPUT_SIZE_BYTES = 65536; // 64KB max total input size
16
17
  /**
17
18
  * Custom error class for input validation failures.
18
19
  * Provides structured error information for user-friendly error responses.
@@ -55,6 +56,10 @@ export function validateLimit(limit) {
55
56
  /**
56
57
  * Validate and clamp duration parameters.
57
58
  *
59
+ * Note: Zero is allowed and has specific behavior:
60
+ * - `minDurationMs: 0` matches all spans (no minimum filter)
61
+ * - `maxDurationMs: 0` matches no spans (nothing has zero duration)
62
+ *
58
63
  * @param duration - User-provided duration in milliseconds (undefined passes through)
59
64
  * @param field - Field name for error messages ('minDurationMs' or 'maxDurationMs')
60
65
  * @returns Clamped duration between 0 and MAX_DURATION_MS, or undefined if not provided
@@ -62,6 +67,7 @@ export function validateLimit(limit) {
62
67
  *
63
68
  * @example
64
69
  * validateDuration(undefined, 'minDurationMs') // returns undefined
70
+ * validateDuration(0, 'minDurationMs') // returns 0 (matches all spans)
65
71
  * validateDuration(5000, 'minDurationMs') // returns 5000
66
72
  * validateDuration(100000000, 'maxDurationMs') // returns 86400000 (clamped to max)
67
73
  * validateDuration(-10, 'minDurationMs') // throws: negative duration
@@ -80,6 +86,13 @@ export function validateDuration(duration, field) {
80
86
  /**
81
87
  * Parse a date string in YYYY-MM-DD format.
82
88
  * Returns null if the format is invalid.
89
+ *
90
+ * **Timezone Behavior**: Creates dates in the local timezone using `new Date(year, month, day)`.
91
+ * The returned Date represents midnight local time on the specified date.
92
+ * For UTC parsing, consider using `new Date(dateStr + 'T00:00:00Z')` instead.
93
+ *
94
+ * @param dateStr - Date string in YYYY-MM-DD format
95
+ * @returns Parsed Date in local timezone, or null if invalid
83
96
  */
84
97
  function parseDateString(dateStr) {
85
98
  const match = dateStr.match(/^(\d{4})-(\d{2})-(\d{2})$/);
@@ -162,7 +175,17 @@ export function validateDateRange(startDate, endDate) {
162
175
  }
163
176
  /**
164
177
  * Count the number of capture groups in a regex pattern.
165
- * Handles escaped parentheses and non-capturing groups.
178
+ * Handles escaped parentheses, character classes, and non-capturing groups.
179
+ *
180
+ * Correctly counts:
181
+ * - Regular capturing groups: (...)
182
+ * - Named capturing groups: (?<name>...)
183
+ *
184
+ * Does NOT count (non-capturing):
185
+ * - Non-capturing groups: (?:...)
186
+ * - Lookahead: (?=...), (?!...)
187
+ * - Lookbehind: (?<=...), (?<!...)
188
+ * - Flags: (?i), (?m), etc.
166
189
  */
167
190
  function countRegexGroups(pattern) {
168
191
  let count = 0;
@@ -189,13 +212,27 @@ function countRegexGroups(pattern) {
189
212
  if (inCharClass) {
190
213
  continue;
191
214
  }
192
- // Check for opening parenthesis that starts a capturing group
215
+ // Check for opening parenthesis that starts a group
193
216
  if (char === '(') {
194
- // Look ahead to check for non-capturing group (?:, (?=, (?!, (?<= etc.
195
217
  const next = pattern[i + 1];
196
218
  if (next !== '?') {
219
+ // Regular capturing group: (...)
197
220
  count++;
198
221
  }
222
+ else {
223
+ // Check for named capturing group: (?<name>...)
224
+ const afterQuestion = pattern[i + 2];
225
+ if (afterQuestion === '<') {
226
+ // Could be named group (?<name>...) or lookbehind (?<=...) / (?<!...)
227
+ const afterAngle = pattern[i + 3];
228
+ if (afterAngle !== '=' && afterAngle !== '!') {
229
+ // Named capturing group
230
+ count++;
231
+ }
232
+ // else: lookbehind assertion (non-capturing)
233
+ }
234
+ // else: non-capturing (?:), lookahead (?=, ?!), flags (?i), etc.
235
+ }
199
236
  }
200
237
  }
201
238
  return count;
@@ -242,4 +279,26 @@ export function validateRegexPattern(pattern) {
242
279
  export function isInputValidationError(error) {
243
280
  return error instanceof InputValidationError;
244
281
  }
282
+ /**
283
+ * Validate that total input size does not exceed MAX_INPUT_SIZE_BYTES.
284
+ * Prevents resource exhaustion from very large input payloads.
285
+ *
286
+ * @param input - The raw input object to validate
287
+ * @throws InputValidationError if input exceeds size limit
288
+ *
289
+ * @example
290
+ * validateInputSize(rawInput); // throws if > 64KB
291
+ */
292
+ export function validateInputSize(input) {
293
+ // Fast path: skip for primitives
294
+ if (input === null || input === undefined)
295
+ return;
296
+ if (typeof input !== 'object')
297
+ return;
298
+ const serialized = JSON.stringify(input);
299
+ const sizeBytes = Buffer.byteLength(serialized, 'utf8');
300
+ if (sizeBytes > MAX_INPUT_SIZE_BYTES) {
301
+ throw new InputValidationError(`Input size of ${sizeBytes} bytes exceeds maximum of ${MAX_INPUT_SIZE_BYTES} bytes (64KB).`, 'input', 'maxSize');
302
+ }
303
+ }
245
304
  //# sourceMappingURL=input-validator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"input-validator.js","sourceRoot":"","sources":["../../src/lib/input-validator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"input-validator.js","sourceRoot":"","sources":["../../src/lib/input-validator.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { describe, it } from 'node:test';
2
2
  import assert from 'node:assert';
3
- import { validateLimit, validateDuration, validateDateRange, validateRegexPattern, InputValidationError, isInputValidationError, MAX_LIMIT, MAX_DATE_RANGE_DAYS, MAX_REGEX_LENGTH, MAX_REGEX_GROUPS, DEFAULT_LIMIT, MAX_DURATION_MS, } from './input-validator.js';
3
+ import { validateLimit, validateDuration, validateDateRange, validateRegexPattern, validateInputSize, InputValidationError, isInputValidationError, MAX_LIMIT, MAX_DATE_RANGE_DAYS, MAX_REGEX_LENGTH, MAX_REGEX_GROUPS, DEFAULT_LIMIT, MAX_DURATION_MS, MAX_INPUT_SIZE_BYTES, } from './input-validator.js';
4
4
  describe('input-validator', () => {
5
5
  describe('validateLimit', () => {
6
6
  it('should return default limit when undefined', () => {
@@ -70,6 +70,71 @@ describe('input-validator', () => {
70
70
  assert.strictEqual(validateDuration(0, 'minDurationMs'), 0);
71
71
  assert.strictEqual(validateDuration(MAX_DURATION_MS, 'maxDurationMs'), MAX_DURATION_MS);
72
72
  });
73
+ // A2 Category 5: Duration Validation Edge Cases
74
+ describe('JavaScript special number handling (A2)', () => {
75
+ it('should clamp Number.MAX_VALUE to MAX_DURATION_MS', () => {
76
+ const result = validateDuration(Number.MAX_VALUE, 'maxDurationMs');
77
+ assert.strictEqual(result, MAX_DURATION_MS);
78
+ });
79
+ it('should clamp Number.MAX_SAFE_INTEGER to MAX_DURATION_MS', () => {
80
+ const result = validateDuration(Number.MAX_SAFE_INTEGER, 'minDurationMs');
81
+ assert.strictEqual(result, MAX_DURATION_MS);
82
+ });
83
+ it('should treat -0 as 0 without error', () => {
84
+ const result = validateDuration(-0, 'minDurationMs');
85
+ // -0 is not strictly equal to 0, but they compare equal
86
+ assert.ok(result === 0 || Object.is(result, -0), 'Result should be 0 or -0');
87
+ // Verify it passes the negative check (-0 < 0 is false)
88
+ assert.ok(result !== undefined);
89
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
90
+ assert.ok(result >= 0, '-0 should pass >= 0 check');
91
+ });
92
+ it('should handle NaN input', () => {
93
+ // NaN < 0 is false, so negative check passes
94
+ // Math.min(NaN, MAX_DURATION_MS) returns NaN
95
+ const result = validateDuration(NaN, 'minDurationMs');
96
+ // Document current behavior: NaN passes through
97
+ assert.ok(Number.isNaN(result), 'NaN should pass through (current behavior)');
98
+ });
99
+ it('should clamp Infinity to MAX_DURATION_MS', () => {
100
+ const result = validateDuration(Infinity, 'maxDurationMs');
101
+ assert.strictEqual(result, MAX_DURATION_MS);
102
+ });
103
+ it('should throw on -Infinity (negative)', () => {
104
+ assert.throws(() => validateDuration(-Infinity, 'minDurationMs'), /cannot be negative/);
105
+ });
106
+ it('should clamp large float to MAX_DURATION_MS', () => {
107
+ const result = validateDuration(86400000.000001, 'maxDurationMs');
108
+ assert.strictEqual(result, MAX_DURATION_MS);
109
+ });
110
+ it('should handle very small positive numbers', () => {
111
+ const result = validateDuration(0.0000001, 'minDurationMs');
112
+ assert.ok(result !== undefined && result >= 0);
113
+ assert.ok(result <= MAX_DURATION_MS);
114
+ });
115
+ it('should handle string coercion attempts', () => {
116
+ // TypeScript prevents this, but test runtime behavior
117
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
118
+ const result = validateDuration('1000', 'minDurationMs');
119
+ // String is truthy, so it passes undefined check
120
+ // Comparison with number uses type coercion
121
+ assert.ok(result !== undefined);
122
+ });
123
+ it('should handle 2^53 (beyond MAX_SAFE_INTEGER)', () => {
124
+ const result = validateDuration(2 ** 53, 'maxDurationMs');
125
+ assert.strictEqual(result, MAX_DURATION_MS);
126
+ });
127
+ it('should handle Number.EPSILON correctly', () => {
128
+ const result = validateDuration(Number.EPSILON, 'minDurationMs');
129
+ assert.ok(result !== undefined && result >= 0);
130
+ });
131
+ it('should handle near-zero negative that rounds to -0', () => {
132
+ // Very small negative that might round to -0
133
+ const result = validateDuration(1e-400, 'minDurationMs');
134
+ // 1e-400 underflows to 0 in IEEE 754
135
+ assert.strictEqual(result, 0);
136
+ });
137
+ });
73
138
  });
74
139
  describe('validateDateRange', () => {
75
140
  it('should parse valid date strings', () => {
@@ -237,6 +302,28 @@ describe('input-validator', () => {
237
302
  // Mix of real groups, non-capturing, and escaped
238
303
  assert.doesNotThrow(() => validateRegexPattern('(a)(?:b)\\(c\\)[d]'));
239
304
  });
305
+ it('should count named capturing groups', () => {
306
+ // Named groups (?<name>...) ARE capturing groups
307
+ assert.doesNotThrow(() => validateRegexPattern('(?<name>foo)'));
308
+ // Mix of named and regular groups
309
+ assert.doesNotThrow(() => validateRegexPattern('(?<first>a)(b)(?<third>c)'));
310
+ });
311
+ it('should throw when named groups exceed limit', () => {
312
+ // 11 named groups exceeds the limit of 10
313
+ const manyNamedGroups = '(?<a1>1)(?<a2>2)(?<a3>3)(?<a4>4)(?<a5>5)(?<a6>6)(?<a7>7)(?<a8>8)(?<a9>9)(?<a10>10)(?<a11>11)';
314
+ assert.throws(() => validateRegexPattern(manyNamedGroups), (err) => {
315
+ assert.strictEqual(err.field, 'pattern');
316
+ assert.strictEqual(err.constraint, 'maxGroups');
317
+ return true;
318
+ });
319
+ });
320
+ it('should not count lookbehind as capturing group', () => {
321
+ // (?<=...) and (?<!...) are NOT capturing groups
322
+ assert.doesNotThrow(() => validateRegexPattern('(?<=prefix)content'));
323
+ assert.doesNotThrow(() => validateRegexPattern('(?<!prefix)content'));
324
+ // Mix with actual capturing groups
325
+ assert.doesNotThrow(() => validateRegexPattern('(?<=pre)(capture)(?<!post)'));
326
+ });
240
327
  });
241
328
  describe('InputValidationError', () => {
242
329
  it('should have correct properties', () => {
@@ -273,6 +360,46 @@ describe('input-validator', () => {
273
360
  assert.strictEqual(isInputValidationError('string'), false);
274
361
  });
275
362
  });
363
+ describe('validateInputSize', () => {
364
+ it('should accept null and undefined', () => {
365
+ assert.doesNotThrow(() => validateInputSize(null));
366
+ assert.doesNotThrow(() => validateInputSize(undefined));
367
+ });
368
+ it('should accept primitives', () => {
369
+ assert.doesNotThrow(() => validateInputSize('string'));
370
+ assert.doesNotThrow(() => validateInputSize(123));
371
+ assert.doesNotThrow(() => validateInputSize(true));
372
+ });
373
+ it('should accept small objects', () => {
374
+ assert.doesNotThrow(() => validateInputSize({ key: 'value' }));
375
+ assert.doesNotThrow(() => validateInputSize({ a: 1, b: 2, c: 3 }));
376
+ });
377
+ it('should accept objects within size limit', () => {
378
+ // Create object with ~60KB of data (under 64KB limit)
379
+ const data = { content: 'x'.repeat(60000) };
380
+ assert.doesNotThrow(() => validateInputSize(data));
381
+ });
382
+ it('should throw when input exceeds size limit', () => {
383
+ // Create object with >64KB of data
384
+ const data = { content: 'x'.repeat(70000) };
385
+ assert.throws(() => validateInputSize(data), (err) => {
386
+ assert.strictEqual(err.field, 'input');
387
+ assert.strictEqual(err.constraint, 'maxSize');
388
+ assert.ok(err.message.includes('exceeds maximum'));
389
+ assert.ok(err.message.includes('64KB'));
390
+ return true;
391
+ });
392
+ });
393
+ it('should throw for large arrays', () => {
394
+ // Create array that exceeds size limit
395
+ const data = Array.from({ length: 10000 }, (_, i) => ({ id: i, value: 'x'.repeat(10) }));
396
+ assert.throws(() => validateInputSize(data), (err) => {
397
+ assert.strictEqual(err.field, 'input');
398
+ assert.strictEqual(err.constraint, 'maxSize');
399
+ return true;
400
+ });
401
+ });
402
+ });
276
403
  describe('constants', () => {
277
404
  it('should export expected constant values', () => {
278
405
  assert.strictEqual(MAX_LIMIT, 1000);
@@ -281,6 +408,7 @@ describe('input-validator', () => {
281
408
  assert.strictEqual(MAX_REGEX_GROUPS, 10);
282
409
  assert.strictEqual(DEFAULT_LIMIT, 50);
283
410
  assert.strictEqual(MAX_DURATION_MS, 86400000); // 24 hours
411
+ assert.strictEqual(MAX_INPUT_SIZE_BYTES, 65536); // 64KB
284
412
  });
285
413
  });
286
414
  });