@superblocksteam/telemetry 2.0.173-next.4 → 2.0.174

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 (304) hide show
  1. package/dist/browser/console-logging.js +7 -2
  2. package/dist/browser/console-logging.js.map +1 -1
  3. package/dist/browser/early-console-buffer.js +14 -12
  4. package/dist/browser/early-console-buffer.js.map +1 -1
  5. package/dist/browser/index.js +41 -12
  6. package/dist/browser/index.js.map +1 -1
  7. package/dist/browser/init.d.ts +1 -1
  8. package/dist/browser/init.d.ts.map +1 -1
  9. package/dist/browser/init.js +52 -42
  10. package/dist/browser/init.js.map +1 -1
  11. package/dist/browser/instrumentations.js +15 -11
  12. package/dist/browser/instrumentations.js.map +1 -1
  13. package/dist/browser/logs.d.ts +1 -1
  14. package/dist/browser/logs.d.ts.map +1 -1
  15. package/dist/browser/logs.js +18 -11
  16. package/dist/browser/logs.js.map +1 -1
  17. package/dist/browser/metrics.js +12 -9
  18. package/dist/browser/metrics.js.map +1 -1
  19. package/dist/browser/resilient-exporter.d.ts +1 -1
  20. package/dist/browser/resilient-exporter.d.ts.map +1 -1
  21. package/dist/browser/resilient-exporter.js +12 -8
  22. package/dist/browser/resilient-exporter.js.map +1 -1
  23. package/dist/browser/sanitizer.js +6 -2
  24. package/dist/browser/sanitizer.js.map +1 -1
  25. package/dist/browser/traced-socket.js +18 -14
  26. package/dist/browser/traced-socket.js.map +1 -1
  27. package/dist/common/contracts/tier2-traces.js +44 -33
  28. package/dist/common/contracts/tier2-traces.js.map +1 -1
  29. package/dist/common/deployment-type.js +8 -5
  30. package/dist/common/deployment-type.js.map +1 -1
  31. package/dist/common/guardrails.js +38 -26
  32. package/dist/common/guardrails.js.map +1 -1
  33. package/dist/common/index.js +24 -8
  34. package/dist/common/index.js.map +1 -1
  35. package/dist/common/log-sanitizer.js +55 -37
  36. package/dist/common/log-sanitizer.js.map +1 -1
  37. package/dist/common/policy-evaluator.d.ts +1 -1
  38. package/dist/common/policy-evaluator.d.ts.map +1 -1
  39. package/dist/common/policy-evaluator.js +9 -5
  40. package/dist/common/policy-evaluator.js.map +1 -1
  41. package/dist/common/resource.js +25 -18
  42. package/dist/common/resource.js.map +1 -1
  43. package/dist/common/tier-hints.js +22 -12
  44. package/dist/common/tier-hints.js.map +1 -1
  45. package/dist/common/trace-sanitizer.js +10 -6
  46. package/dist/common/trace-sanitizer.js.map +1 -1
  47. package/dist/common/traced-socket-types.js +2 -1
  48. package/dist/common/traced-socket-types.js.map +1 -1
  49. package/dist/index.js +38 -6
  50. package/dist/index.js.map +1 -1
  51. package/dist/lint/forbidden-attributes.js +24 -19
  52. package/dist/lint/forbidden-attributes.js.map +1 -1
  53. package/dist/lint/index.js +8 -1
  54. package/dist/lint/index.js.map +1 -1
  55. package/dist/llmobs/index.js +9 -2
  56. package/dist/llmobs/index.js.map +1 -1
  57. package/dist/llmobs/tier1-exporter.js +12 -6
  58. package/dist/llmobs/tier1-exporter.js.map +1 -1
  59. package/dist/llmobs/tier2-summarizer.js +5 -1
  60. package/dist/llmobs/tier2-summarizer.js.map +1 -1
  61. package/dist/node/dynamic-attribute-processor.js +7 -2
  62. package/dist/node/dynamic-attribute-processor.js.map +1 -1
  63. package/dist/node/exporters/resilient-exporter.d.ts +1 -1
  64. package/dist/node/exporters/resilient-exporter.d.ts.map +1 -1
  65. package/dist/node/exporters/resilient-exporter.js +12 -8
  66. package/dist/node/exporters/resilient-exporter.js.map +1 -1
  67. package/dist/node/index.js +26 -7
  68. package/dist/node/index.js.map +1 -1
  69. package/dist/node/init.d.ts +3 -3
  70. package/dist/node/init.d.ts.map +1 -1
  71. package/dist/node/init.js +72 -66
  72. package/dist/node/init.js.map +1 -1
  73. package/dist/node/local-obs-mode.js +4 -1
  74. package/dist/node/local-obs-mode.js.map +1 -1
  75. package/dist/node/log-processor.d.ts +1 -1
  76. package/dist/node/log-processor.d.ts.map +1 -1
  77. package/dist/node/log-processor.js +55 -47
  78. package/dist/node/log-processor.js.map +1 -1
  79. package/dist/node/metrics-client.js +5 -1
  80. package/dist/node/metrics-client.js.map +1 -1
  81. package/dist/node/safe-logger.js +12 -8
  82. package/dist/node/safe-logger.js.map +1 -1
  83. package/dist/node/sanitizing-processor.d.ts +2 -2
  84. package/dist/node/sanitizing-processor.d.ts.map +1 -1
  85. package/dist/node/sanitizing-processor.js +10 -6
  86. package/dist/node/sanitizing-processor.js.map +1 -1
  87. package/dist/node/service-tracers.js +10 -7
  88. package/dist/node/service-tracers.js.map +1 -1
  89. package/dist/node/traced-socket.d.ts +3 -3
  90. package/dist/node/traced-socket.d.ts.map +1 -1
  91. package/dist/node/traced-socket.js +52 -48
  92. package/dist/node/traced-socket.js.map +1 -1
  93. package/dist/npm-registry/emitter.js +47 -34
  94. package/dist/npm-registry/emitter.js.map +1 -1
  95. package/dist/npm-registry/index.js +19 -3
  96. package/dist/npm-registry/index.js.map +1 -1
  97. package/dist/npm-registry/sanitize.js +27 -16
  98. package/dist/npm-registry/sanitize.js.map +1 -1
  99. package/dist/npm-registry/spans.js +12 -7
  100. package/dist/npm-registry/spans.js.map +1 -1
  101. package/dist/testing/in-memory-exporter.d.ts +1 -1
  102. package/dist/testing/in-memory-exporter.d.ts.map +1 -1
  103. package/dist/testing/in-memory-exporter.js +12 -6
  104. package/dist/testing/in-memory-exporter.js.map +1 -1
  105. package/dist/testing/index.js +15 -3
  106. package/dist/testing/index.js.map +1 -1
  107. package/dist/testing/metrics-capture.js +15 -12
  108. package/dist/testing/metrics-capture.js.map +1 -1
  109. package/dist/testing/test-init.js +31 -24
  110. package/dist/testing/test-init.js.map +1 -1
  111. package/dist/types/index.js +17 -1
  112. package/dist/types/index.js.map +1 -1
  113. package/dist/types/policy.js +24 -21
  114. package/dist/types/policy.js.map +1 -1
  115. package/dist-esm/browser/console-logging.d.ts +18 -0
  116. package/dist-esm/browser/console-logging.d.ts.map +1 -0
  117. package/dist-esm/browser/console-logging.js +27 -0
  118. package/dist-esm/browser/console-logging.js.map +1 -0
  119. package/dist-esm/browser/early-console-buffer.d.ts +49 -0
  120. package/dist-esm/browser/early-console-buffer.d.ts.map +1 -0
  121. package/dist-esm/browser/early-console-buffer.js +181 -0
  122. package/dist-esm/browser/early-console-buffer.js.map +1 -0
  123. package/dist-esm/browser/index.d.ts +18 -0
  124. package/dist-esm/browser/index.d.ts.map +1 -0
  125. package/dist-esm/browser/index.js +23 -0
  126. package/dist-esm/browser/index.js.map +1 -0
  127. package/dist-esm/browser/init.d.ts +100 -0
  128. package/dist-esm/browser/init.d.ts.map +1 -0
  129. package/dist-esm/browser/init.js +317 -0
  130. package/dist-esm/browser/init.js.map +1 -0
  131. package/dist-esm/browser/instrumentations.d.ts +67 -0
  132. package/dist-esm/browser/instrumentations.d.ts.map +1 -0
  133. package/dist-esm/browser/instrumentations.js +79 -0
  134. package/dist-esm/browser/instrumentations.js.map +1 -0
  135. package/dist-esm/browser/logs.d.ts +57 -0
  136. package/dist-esm/browser/logs.d.ts.map +1 -0
  137. package/dist-esm/browser/logs.js +80 -0
  138. package/dist-esm/browser/logs.js.map +1 -0
  139. package/dist-esm/browser/metrics.d.ts +29 -0
  140. package/dist-esm/browser/metrics.d.ts.map +1 -0
  141. package/dist-esm/browser/metrics.js +46 -0
  142. package/dist-esm/browser/metrics.js.map +1 -0
  143. package/dist-esm/browser/resilient-exporter.d.ts +43 -0
  144. package/dist-esm/browser/resilient-exporter.d.ts.map +1 -0
  145. package/dist-esm/browser/resilient-exporter.js +84 -0
  146. package/dist-esm/browser/resilient-exporter.js.map +1 -0
  147. package/dist-esm/browser/sanitizer.d.ts +35 -0
  148. package/dist-esm/browser/sanitizer.d.ts.map +1 -0
  149. package/dist-esm/browser/sanitizer.js +207 -0
  150. package/dist-esm/browser/sanitizer.js.map +1 -0
  151. package/dist-esm/browser/traced-socket.d.ts +102 -0
  152. package/dist-esm/browser/traced-socket.d.ts.map +1 -0
  153. package/dist-esm/browser/traced-socket.js +199 -0
  154. package/dist-esm/browser/traced-socket.js.map +1 -0
  155. package/dist-esm/common/contracts/tier2-traces.d.ts +116 -0
  156. package/dist-esm/common/contracts/tier2-traces.d.ts.map +1 -0
  157. package/dist-esm/common/contracts/tier2-traces.js +725 -0
  158. package/dist-esm/common/contracts/tier2-traces.js.map +1 -0
  159. package/dist-esm/common/deployment-type.d.ts +18 -0
  160. package/dist-esm/common/deployment-type.d.ts.map +1 -0
  161. package/dist-esm/common/deployment-type.js +27 -0
  162. package/dist-esm/common/deployment-type.js.map +1 -0
  163. package/dist-esm/common/guardrails.d.ts +132 -0
  164. package/dist-esm/common/guardrails.d.ts.map +1 -0
  165. package/dist-esm/common/guardrails.js +230 -0
  166. package/dist-esm/common/guardrails.js.map +1 -0
  167. package/dist-esm/common/index.d.ts +17 -0
  168. package/dist-esm/common/index.d.ts.map +1 -0
  169. package/dist-esm/common/index.js +17 -0
  170. package/dist-esm/common/index.js.map +1 -0
  171. package/dist-esm/common/log-sanitizer.d.ts +163 -0
  172. package/dist-esm/common/log-sanitizer.d.ts.map +1 -0
  173. package/dist-esm/common/log-sanitizer.js +745 -0
  174. package/dist-esm/common/log-sanitizer.js.map +1 -0
  175. package/dist-esm/common/policy-evaluator.d.ts +103 -0
  176. package/dist-esm/common/policy-evaluator.d.ts.map +1 -0
  177. package/dist-esm/common/policy-evaluator.js +196 -0
  178. package/dist-esm/common/policy-evaluator.js.map +1 -0
  179. package/dist-esm/common/resource.d.ts +79 -0
  180. package/dist-esm/common/resource.d.ts.map +1 -0
  181. package/dist-esm/common/resource.js +121 -0
  182. package/dist-esm/common/resource.js.map +1 -0
  183. package/dist-esm/common/tier-hints.d.ts +182 -0
  184. package/dist-esm/common/tier-hints.d.ts.map +1 -0
  185. package/dist-esm/common/tier-hints.js +199 -0
  186. package/dist-esm/common/tier-hints.js.map +1 -0
  187. package/dist-esm/common/trace-sanitizer.d.ts +82 -0
  188. package/dist-esm/common/trace-sanitizer.d.ts.map +1 -0
  189. package/dist-esm/common/trace-sanitizer.js +230 -0
  190. package/dist-esm/common/trace-sanitizer.js.map +1 -0
  191. package/dist-esm/common/traced-socket-types.d.ts +43 -0
  192. package/dist-esm/common/traced-socket-types.d.ts.map +1 -0
  193. package/dist-esm/common/traced-socket-types.js +16 -0
  194. package/dist-esm/common/traced-socket-types.js.map +1 -0
  195. package/dist-esm/index.d.ts +45 -0
  196. package/dist-esm/index.d.ts.map +1 -0
  197. package/dist-esm/index.js +56 -0
  198. package/dist-esm/index.js.map +1 -0
  199. package/dist-esm/lint/forbidden-attributes.d.ts +149 -0
  200. package/dist-esm/lint/forbidden-attributes.d.ts.map +1 -0
  201. package/dist-esm/lint/forbidden-attributes.js +210 -0
  202. package/dist-esm/lint/forbidden-attributes.js.map +1 -0
  203. package/dist-esm/lint/index.d.ts +9 -0
  204. package/dist-esm/lint/index.d.ts.map +1 -0
  205. package/dist-esm/lint/index.js +9 -0
  206. package/dist-esm/lint/index.js.map +1 -0
  207. package/dist-esm/llmobs/index.d.ts +22 -0
  208. package/dist-esm/llmobs/index.d.ts.map +1 -0
  209. package/dist-esm/llmobs/index.js +22 -0
  210. package/dist-esm/llmobs/index.js.map +1 -0
  211. package/dist-esm/llmobs/tier1-exporter.d.ts +146 -0
  212. package/dist-esm/llmobs/tier1-exporter.d.ts.map +1 -0
  213. package/dist-esm/llmobs/tier1-exporter.js +193 -0
  214. package/dist-esm/llmobs/tier1-exporter.js.map +1 -0
  215. package/dist-esm/llmobs/tier2-summarizer.d.ts +268 -0
  216. package/dist-esm/llmobs/tier2-summarizer.d.ts.map +1 -0
  217. package/dist-esm/llmobs/tier2-summarizer.js +652 -0
  218. package/dist-esm/llmobs/tier2-summarizer.js.map +1 -0
  219. package/dist-esm/node/dynamic-attribute-processor.d.ts +43 -0
  220. package/dist-esm/node/dynamic-attribute-processor.d.ts.map +1 -0
  221. package/dist-esm/node/dynamic-attribute-processor.js +74 -0
  222. package/dist-esm/node/dynamic-attribute-processor.js.map +1 -0
  223. package/dist-esm/node/exporters/resilient-exporter.d.ts +91 -0
  224. package/dist-esm/node/exporters/resilient-exporter.d.ts.map +1 -0
  225. package/dist-esm/node/exporters/resilient-exporter.js +132 -0
  226. package/dist-esm/node/exporters/resilient-exporter.js.map +1 -0
  227. package/dist-esm/node/index.d.ts +13 -0
  228. package/dist-esm/node/index.d.ts.map +1 -0
  229. package/dist-esm/node/index.js +13 -0
  230. package/dist-esm/node/index.js.map +1 -0
  231. package/dist-esm/node/init.d.ts +97 -0
  232. package/dist-esm/node/init.d.ts.map +1 -0
  233. package/dist-esm/node/init.js +359 -0
  234. package/dist-esm/node/init.js.map +1 -0
  235. package/dist-esm/node/local-obs-mode.d.ts +17 -0
  236. package/dist-esm/node/local-obs-mode.d.ts.map +1 -0
  237. package/dist-esm/node/local-obs-mode.js +19 -0
  238. package/dist-esm/node/local-obs-mode.js.map +1 -0
  239. package/dist-esm/node/log-processor.d.ts +132 -0
  240. package/dist-esm/node/log-processor.d.ts.map +1 -0
  241. package/dist-esm/node/log-processor.js +389 -0
  242. package/dist-esm/node/log-processor.js.map +1 -0
  243. package/dist-esm/node/metrics-client.d.ts +88 -0
  244. package/dist-esm/node/metrics-client.d.ts.map +1 -0
  245. package/dist-esm/node/metrics-client.js +205 -0
  246. package/dist-esm/node/metrics-client.js.map +1 -0
  247. package/dist-esm/node/safe-logger.d.ts +55 -0
  248. package/dist-esm/node/safe-logger.d.ts.map +1 -0
  249. package/dist-esm/node/safe-logger.js +154 -0
  250. package/dist-esm/node/safe-logger.js.map +1 -0
  251. package/dist-esm/node/sanitizing-processor.d.ts +67 -0
  252. package/dist-esm/node/sanitizing-processor.d.ts.map +1 -0
  253. package/dist-esm/node/sanitizing-processor.js +163 -0
  254. package/dist-esm/node/sanitizing-processor.js.map +1 -0
  255. package/dist-esm/node/service-tracers.d.ts +52 -0
  256. package/dist-esm/node/service-tracers.d.ts.map +1 -0
  257. package/dist-esm/node/service-tracers.js +78 -0
  258. package/dist-esm/node/service-tracers.js.map +1 -0
  259. package/dist-esm/node/traced-socket.d.ts +120 -0
  260. package/dist-esm/node/traced-socket.d.ts.map +1 -0
  261. package/dist-esm/node/traced-socket.js +334 -0
  262. package/dist-esm/node/traced-socket.js.map +1 -0
  263. package/dist-esm/npm-registry/emitter.d.ts +330 -0
  264. package/dist-esm/npm-registry/emitter.d.ts.map +1 -0
  265. package/dist-esm/npm-registry/emitter.js +546 -0
  266. package/dist-esm/npm-registry/emitter.js.map +1 -0
  267. package/dist-esm/npm-registry/index.d.ts +12 -0
  268. package/dist-esm/npm-registry/index.d.ts.map +1 -0
  269. package/dist-esm/npm-registry/index.js +12 -0
  270. package/dist-esm/npm-registry/index.js.map +1 -0
  271. package/dist-esm/npm-registry/sanitize.d.ts +174 -0
  272. package/dist-esm/npm-registry/sanitize.d.ts.map +1 -0
  273. package/dist-esm/npm-registry/sanitize.js +331 -0
  274. package/dist-esm/npm-registry/sanitize.js.map +1 -0
  275. package/dist-esm/npm-registry/spans.d.ts +61 -0
  276. package/dist-esm/npm-registry/spans.d.ts.map +1 -0
  277. package/dist-esm/npm-registry/spans.js +86 -0
  278. package/dist-esm/npm-registry/spans.js.map +1 -0
  279. package/dist-esm/package.json +1 -0
  280. package/dist-esm/testing/in-memory-exporter.d.ts +179 -0
  281. package/dist-esm/testing/in-memory-exporter.d.ts.map +1 -0
  282. package/dist-esm/testing/in-memory-exporter.js +250 -0
  283. package/dist-esm/testing/in-memory-exporter.js.map +1 -0
  284. package/dist-esm/testing/index.d.ts +9 -0
  285. package/dist-esm/testing/index.d.ts.map +1 -0
  286. package/dist-esm/testing/index.js +9 -0
  287. package/dist-esm/testing/index.js.map +1 -0
  288. package/dist-esm/testing/metrics-capture.d.ts +29 -0
  289. package/dist-esm/testing/metrics-capture.d.ts.map +1 -0
  290. package/dist-esm/testing/metrics-capture.js +71 -0
  291. package/dist-esm/testing/metrics-capture.js.map +1 -0
  292. package/dist-esm/testing/test-init.d.ts +80 -0
  293. package/dist-esm/testing/test-init.d.ts.map +1 -0
  294. package/dist-esm/testing/test-init.js +137 -0
  295. package/dist-esm/testing/test-init.js.map +1 -0
  296. package/dist-esm/types/index.d.ts +84 -0
  297. package/dist-esm/types/index.d.ts.map +1 -0
  298. package/dist-esm/types/index.js +7 -0
  299. package/dist-esm/types/index.js.map +1 -0
  300. package/dist-esm/types/policy.d.ts +92 -0
  301. package/dist-esm/types/policy.d.ts.map +1 -0
  302. package/dist-esm/types/policy.js +122 -0
  303. package/dist-esm/types/policy.js.map +1 -0
  304. package/package.json +17 -11
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Browser PII Sanitizing Processors
3
+ *
4
+ * Span and log processors that redact PII before export from the browser.
5
+ * Browser telemetry always runs in untrusted context, so aggressive sanitization
6
+ * is applied unconditionally.
7
+ *
8
+ * - SanitizingSpanProcessor: redacts sensitive span attributes and strips
9
+ * sensitive query params from URL attributes.
10
+ * - SanitizingLogProcessor: redacts sensitive log record attributes and
11
+ * replaces email-like patterns in log body text.
12
+ */
13
+ // ============================================================================
14
+ // Constants
15
+ // ============================================================================
16
+ const REDACTED = "[REDACTED]";
17
+ const REDACTED_EMAIL = "[REDACTED_EMAIL]";
18
+ /**
19
+ * Attribute key substrings that indicate sensitive values.
20
+ * Case-insensitive matching is applied.
21
+ */
22
+ const SENSITIVE_KEY_SUBSTRINGS = [
23
+ "email",
24
+ "token",
25
+ "secret",
26
+ "password",
27
+ "authorization",
28
+ "cookie",
29
+ "credential",
30
+ ];
31
+ /**
32
+ * Attribute key patterns (regex) for additional well-known sensitive keys
33
+ * not covered by simple substring matching (e.g. api_key, x-api-key).
34
+ */
35
+ const SENSITIVE_KEY_PATTERNS = [
36
+ /api[_\-.]?key/i,
37
+ /x[_\-.]?api[_\-.]?key/i,
38
+ ];
39
+ /**
40
+ * URL query parameter names that should be stripped.
41
+ * Exact (case-insensitive) match against param name.
42
+ */
43
+ const SENSITIVE_URL_PARAMS = [
44
+ "token",
45
+ "key",
46
+ "secret",
47
+ "password",
48
+ "code",
49
+ "state",
50
+ "auth",
51
+ ];
52
+ /** URL attribute keys that receive query-param sanitization. */
53
+ const URL_ATTRIBUTE_KEYS = new Set(["http.url", "url.full"]);
54
+ /** Regex matching email-like patterns in log body text. */
55
+ const EMAIL_PATTERN = /[\w.+-]+@[\w.-]+(\.\w+)?/g;
56
+ // ============================================================================
57
+ // Helpers
58
+ // ============================================================================
59
+ /**
60
+ * Returns true if the attribute key is sensitive and its value should be
61
+ * replaced with [REDACTED].
62
+ */
63
+ function isSensitiveKey(key, additionalPatterns) {
64
+ const lower = key.toLowerCase();
65
+ for (const substr of SENSITIVE_KEY_SUBSTRINGS) {
66
+ if (lower.includes(substr)) {
67
+ return true;
68
+ }
69
+ }
70
+ for (const pattern of SENSITIVE_KEY_PATTERNS) {
71
+ pattern.lastIndex = 0;
72
+ if (pattern.test(key)) {
73
+ return true;
74
+ }
75
+ }
76
+ for (const pattern of additionalPatterns) {
77
+ pattern.lastIndex = 0;
78
+ if (pattern.test(key)) {
79
+ return true;
80
+ }
81
+ }
82
+ return false;
83
+ }
84
+ /**
85
+ * Strips sensitive query parameters from a URL string.
86
+ * Sensitive param values are replaced with [REDACTED] (key is preserved).
87
+ */
88
+ function sanitizeUrl(url, additionalParams) {
89
+ const qIdx = url.indexOf("?");
90
+ if (qIdx === -1) {
91
+ return url;
92
+ }
93
+ const base = url.slice(0, qIdx);
94
+ const query = url.slice(qIdx + 1);
95
+ const sensitiveSet = new Set([
96
+ ...SENSITIVE_URL_PARAMS.map((p) => p.toLowerCase()),
97
+ ...additionalParams.map((p) => p.toLowerCase()),
98
+ ]);
99
+ const sanitizedParts = query.split("&").map((part) => {
100
+ const eqIdx = part.indexOf("=");
101
+ if (eqIdx === -1) {
102
+ return part;
103
+ }
104
+ const rawParamName = part.slice(0, eqIdx);
105
+ let paramName;
106
+ try {
107
+ paramName = decodeURIComponent(rawParamName).toLowerCase();
108
+ }
109
+ catch {
110
+ paramName = rawParamName.toLowerCase();
111
+ }
112
+ if (sensitiveSet.has(paramName)) {
113
+ return `${part.slice(0, eqIdx)}=${REDACTED}`;
114
+ }
115
+ return part;
116
+ });
117
+ return `${base}?${sanitizedParts.join("&")}`;
118
+ }
119
+ /**
120
+ * Sanitizes span/log attributes in-place. Sensitive keys get value [REDACTED];
121
+ * URL attributes get query-param sanitization.
122
+ */
123
+ function sanitizeAttributes(attributes, additionalKeyPatterns, additionalSensitiveParams) {
124
+ for (const key of Object.keys(attributes)) {
125
+ if (URL_ATTRIBUTE_KEYS.has(key)) {
126
+ const val = attributes[key];
127
+ if (typeof val === "string") {
128
+ attributes[key] = sanitizeUrl(val, additionalSensitiveParams);
129
+ }
130
+ // URL attributes are handled; skip further key-based check
131
+ continue;
132
+ }
133
+ if (isSensitiveKey(key, additionalKeyPatterns)) {
134
+ attributes[key] = REDACTED;
135
+ }
136
+ }
137
+ }
138
+ // ============================================================================
139
+ // SanitizingSpanProcessor
140
+ // ============================================================================
141
+ class SanitizingSpanProcessor {
142
+ additionalKeyPatterns;
143
+ additionalSensitiveParams;
144
+ constructor(config = {}) {
145
+ this.additionalKeyPatterns = config.additionalKeyPatterns ?? [];
146
+ this.additionalSensitiveParams = config.additionalSensitiveParams ?? [];
147
+ }
148
+ onStart(_span, _parentContext) {
149
+ // Nothing to do at start; sanitization occurs at end when attributes are final.
150
+ }
151
+ onEnd(span) {
152
+ // ReadableSpan.attributes is typed as Attributes (readonly in API), but
153
+ // in practice the SDK implementation uses a mutable object. We cast to
154
+ // allow in-place mutation, which avoids allocating a new span wrapper.
155
+ const attrs = span.attributes;
156
+ sanitizeAttributes(attrs, this.additionalKeyPatterns, this.additionalSensitiveParams);
157
+ }
158
+ async shutdown() { }
159
+ async forceFlush() { }
160
+ }
161
+ // ============================================================================
162
+ // SanitizingLogProcessor
163
+ // ============================================================================
164
+ class BrowserSanitizingLogProcessor {
165
+ additionalKeyPatterns;
166
+ constructor(config = {}) {
167
+ this.additionalKeyPatterns = config.additionalKeyPatterns ?? [];
168
+ }
169
+ onEmit(record, _context) {
170
+ // Sanitize attributes in-place
171
+ const attrs = record.attributes;
172
+ for (const key of Object.keys(attrs)) {
173
+ if (isSensitiveKey(key, this.additionalKeyPatterns)) {
174
+ attrs[key] = REDACTED;
175
+ }
176
+ }
177
+ // Redact email-like patterns in string body
178
+ if (typeof record.body === "string") {
179
+ EMAIL_PATTERN.lastIndex = 0;
180
+ record.body = record.body.replace(EMAIL_PATTERN, REDACTED_EMAIL);
181
+ }
182
+ }
183
+ async shutdown() { }
184
+ async forceFlush() { }
185
+ }
186
+ // ============================================================================
187
+ // Factory functions
188
+ // ============================================================================
189
+ /**
190
+ * Create a SpanProcessor that redacts PII from span attributes before export.
191
+ *
192
+ * @param config - Optional configuration for additional key patterns / URL params
193
+ * @returns A SpanProcessor suitable for use in a browser WebTracerProvider
194
+ */
195
+ export function createSanitizingSpanProcessor(config) {
196
+ return new SanitizingSpanProcessor(config);
197
+ }
198
+ /**
199
+ * Create a LogRecordProcessor that redacts PII from log records before export.
200
+ *
201
+ * @param config - Optional configuration for additional key patterns
202
+ * @returns A LogRecordProcessor suitable for use in a browser log provider
203
+ */
204
+ export function createSanitizingLogProcessor(config) {
205
+ return new BrowserSanitizingLogProcessor(config);
206
+ }
207
+ //# sourceMappingURL=sanitizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizer.js","sourceRoot":"","sources":["../../src/browser/sanitizer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Browser-side TracedSocket for WebSocket tracing.
3
+ *
4
+ * Wraps a WebSocket client (or any WebSocket-like object) and adds
5
+ * OpenTelemetry tracing. Designed to speak the same envelope protocol as the
6
+ * server-side TracedSocket so that distributed traces link correctly across
7
+ * the browser–server boundary.
8
+ *
9
+ * Envelope format (matches @superblocksteam/shared SocketRequest):
10
+ * outbound: { request: { method, id, traceparent?, tracestate?, ... } }
11
+ * inbound: { request: { method, id, traceparent?, tracestate?, ... } }
12
+ * { response: { id, ... } }
13
+ *
14
+ * Propagation uses the W3C Trace Context propagator registered globally by
15
+ * initBrowserTelemetry() (see browser/init.ts). The carrier is the
16
+ * `request` object itself — the same convention as the server side.
17
+ */
18
+ import { type Tracer } from "@opentelemetry/api";
19
+ import type { SocketMessageEnvelope } from "../common/traced-socket-types.js";
20
+ /** Minimal browser WebSocket surface needed by BrowserTracedSocket. */
21
+ export interface WebSocketLike {
22
+ readonly readyState: number;
23
+ close(code?: number, reason?: string): void;
24
+ send(data: string | ArrayBuffer): void;
25
+ addEventListener(type: string, listener: (event: unknown) => void): void;
26
+ removeEventListener(type: string, listener: (event: unknown) => void): void;
27
+ }
28
+ /** Configuration for BrowserTracedSocket. */
29
+ export interface BrowserTracedSocketConfig {
30
+ /**
31
+ * Tracer instance. When omitted the global tracer named
32
+ * "superblocks-ws" is used (requires initBrowserTelemetry() first).
33
+ */
34
+ tracer?: Tracer;
35
+ }
36
+ /**
37
+ * BrowserTracedSocket wraps a WebSocket and provides:
38
+ *
39
+ * 1. `decorateOutbound(msg)` — call this before sending any message.
40
+ * Injects traceparent/tracestate into msg.request so the server can
41
+ * extract the browser's active context.
42
+ *
43
+ * 2. `traceOutboundCall(method)` — wraps a client-initiated RPC call in a
44
+ * CLIENT span. Returns the span's end function.
45
+ *
46
+ * 3. `handleInbound(msg)` — call this when a message arrives from the server.
47
+ * Extracts the server's trace context and creates a SERVER span so that
48
+ * server-initiated pushes appear in the browser's trace.
49
+ *
50
+ * 4. `recordReconnect({ attempt })` — call this from the reconnect loop to
51
+ * create a ws.reconnect span.
52
+ *
53
+ * Lifecycle spans (ws.connect, ws.disconnect) are attached automatically via
54
+ * WebSocket open/close event listeners.
55
+ */
56
+ export declare class BrowserTracedSocket {
57
+ private readonly ws;
58
+ private readonly tracer;
59
+ private connectStartTime;
60
+ constructor(ws: WebSocketLike, config: BrowserTracedSocketConfig);
61
+ private readonly onOpen;
62
+ private readonly onClose;
63
+ /**
64
+ * Records a ws.reconnect span. Call this from the reconnect loop just
65
+ * before opening a new WebSocket, passing the attempt counter so it shows
66
+ * up as a span attribute.
67
+ */
68
+ recordReconnect({ attempt }: {
69
+ attempt: number;
70
+ }): void;
71
+ /**
72
+ * Injects W3C trace context into the message's request envelope.
73
+ * Call this on every outbound message before handing it to the transport.
74
+ *
75
+ * Mirrors the server-side TracedSocket.decorateToSend() behaviour so that
76
+ * the server can extract the browser's active context via propagation.extract.
77
+ */
78
+ decorateOutbound(message: SocketMessageEnvelope): SocketMessageEnvelope;
79
+ /**
80
+ * Creates a CLIENT span for a browser-initiated RPC call.
81
+ * Returns the span so the caller can end it after the response resolves.
82
+ *
83
+ * Usage:
84
+ * ```typescript
85
+ * const span = socket.traceOutboundCall("editor.runApi");
86
+ * const result = await socket.request("editor.runApi", params);
87
+ * span.end();
88
+ * ```
89
+ */
90
+ traceOutboundCall(method: string): import("@opentelemetry/api").Span;
91
+ /**
92
+ * Handles an inbound message from the server.
93
+ * - Extracts the server's trace context from the request envelope.
94
+ * - Creates a SERVER span as a child of the server's trace so that
95
+ * server-initiated pushes appear in the browser's distributed trace.
96
+ * - Response-only messages (no request field) are ignored.
97
+ */
98
+ handleInbound(message: SocketMessageEnvelope): void;
99
+ /** Remove lifecycle listeners. Call when tearing down the socket. */
100
+ dispose(): void;
101
+ }
102
+ //# sourceMappingURL=traced-socket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traced-socket.d.ts","sourceRoot":"","sources":["../../src/browser/traced-socket.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAML,KAAK,MAAM,EACZ,MAAM,oBAAoB,CAAC;AAM5B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAE9E,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;IACvC,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IACzE,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;CAC7E;AAED,6CAA6C;AAC7C,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAOD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,mBAAmB;IAK5B,OAAO,CAAC,QAAQ,CAAC,EAAE;IAJrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,gBAAgB,CAAqB;gBAG1B,EAAE,EAAE,aAAa,EAClC,MAAM,EAAE,yBAAyB;IAoBnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAwBrB;IAEF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAuBtB;IAEF;;;;OAIG;IACI,eAAe,CAAC,EAAE,OAAO,EAAE,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAoB9D;;;;;;OAMG;IACI,gBAAgB,CACrB,OAAO,EAAE,qBAAqB,GAC7B,qBAAqB;IAexB;;;;;;;;;;OAUG;IACI,iBAAiB,CAAC,MAAM,EAAE,MAAM;IAkBvC;;;;;;OAMG;IACI,aAAa,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI;IAgC1D,qEAAqE;IAC9D,OAAO,IAAI,IAAI;CAIvB"}
@@ -0,0 +1,199 @@
1
+ /**
2
+ * Browser-side TracedSocket for WebSocket tracing.
3
+ *
4
+ * Wraps a WebSocket client (or any WebSocket-like object) and adds
5
+ * OpenTelemetry tracing. Designed to speak the same envelope protocol as the
6
+ * server-side TracedSocket so that distributed traces link correctly across
7
+ * the browser–server boundary.
8
+ *
9
+ * Envelope format (matches @superblocksteam/shared SocketRequest):
10
+ * outbound: { request: { method, id, traceparent?, tracestate?, ... } }
11
+ * inbound: { request: { method, id, traceparent?, tracestate?, ... } }
12
+ * { response: { id, ... } }
13
+ *
14
+ * Propagation uses the W3C Trace Context propagator registered globally by
15
+ * initBrowserTelemetry() (see browser/init.ts). The carrier is the
16
+ * `request` object itself — the same convention as the server side.
17
+ */
18
+ import { ROOT_CONTEXT, SpanKind, context as otelCtx, propagation, trace, } from "@opentelemetry/api";
19
+ import { SEMATTRS_MESSAGING_DESTINATION_KIND, SEMATTRS_MESSAGING_SYSTEM, } from "@opentelemetry/semantic-conventions";
20
+ const MESSAGING_ATTRS = {
21
+ [SEMATTRS_MESSAGING_SYSTEM]: "ws",
22
+ [SEMATTRS_MESSAGING_DESTINATION_KIND]: "websocket",
23
+ };
24
+ /**
25
+ * BrowserTracedSocket wraps a WebSocket and provides:
26
+ *
27
+ * 1. `decorateOutbound(msg)` — call this before sending any message.
28
+ * Injects traceparent/tracestate into msg.request so the server can
29
+ * extract the browser's active context.
30
+ *
31
+ * 2. `traceOutboundCall(method)` — wraps a client-initiated RPC call in a
32
+ * CLIENT span. Returns the span's end function.
33
+ *
34
+ * 3. `handleInbound(msg)` — call this when a message arrives from the server.
35
+ * Extracts the server's trace context and creates a SERVER span so that
36
+ * server-initiated pushes appear in the browser's trace.
37
+ *
38
+ * 4. `recordReconnect({ attempt })` — call this from the reconnect loop to
39
+ * create a ws.reconnect span.
40
+ *
41
+ * Lifecycle spans (ws.connect, ws.disconnect) are attached automatically via
42
+ * WebSocket open/close event listeners.
43
+ */
44
+ export class BrowserTracedSocket {
45
+ ws;
46
+ tracer;
47
+ connectStartTime;
48
+ constructor(ws, config) {
49
+ this.ws = ws;
50
+ this.tracer = config.tracer ?? trace.getTracer("superblocks-ws", "0.0.0");
51
+ this.connectStartTime = performance.now();
52
+ this.ws.addEventListener("open", this.onOpen);
53
+ this.ws.addEventListener("close", this.onClose);
54
+ // If the WebSocket is already open (e.g. constructed after connectWebSocket
55
+ // resolves), the "open" event won't fire again. Fire onOpen immediately so
56
+ // the ws.connect lifecycle span is still recorded.
57
+ if (this.ws.readyState === 1 /* WebSocket.OPEN */) {
58
+ this.onOpen(undefined);
59
+ }
60
+ }
61
+ // ------------------------------------------------------------------
62
+ // Lifecycle handlers
63
+ // ------------------------------------------------------------------
64
+ onOpen = (_event) => {
65
+ try {
66
+ const durationMs = this.connectStartTime
67
+ ? performance.now() - this.connectStartTime
68
+ : undefined;
69
+ this.tracer.startActiveSpan("ws.connect", {
70
+ kind: SpanKind.CLIENT,
71
+ attributes: {
72
+ ...MESSAGING_ATTRS,
73
+ ...(durationMs !== undefined
74
+ ? { "ws.connect_duration_ms": durationMs }
75
+ : {}),
76
+ },
77
+ }, (span) => {
78
+ span.end();
79
+ });
80
+ }
81
+ catch (err) {
82
+ console.error("[TracedSocket] onOpen tracing error", err);
83
+ }
84
+ };
85
+ onClose = (event) => {
86
+ try {
87
+ const ev = event;
88
+ const code = ev.code ?? 1000;
89
+ const reason = ev.reason ?? "";
90
+ this.tracer.startActiveSpan("ws.disconnect", {
91
+ kind: SpanKind.CLIENT,
92
+ attributes: {
93
+ ...MESSAGING_ATTRS,
94
+ "ws.close_code": code,
95
+ "ws.close_reason": reason,
96
+ },
97
+ }, (span) => {
98
+ span.end();
99
+ });
100
+ }
101
+ catch (err) {
102
+ console.error("[TracedSocket] onClose tracing error", err);
103
+ }
104
+ };
105
+ /**
106
+ * Records a ws.reconnect span. Call this from the reconnect loop just
107
+ * before opening a new WebSocket, passing the attempt counter so it shows
108
+ * up as a span attribute.
109
+ */
110
+ recordReconnect({ attempt }) {
111
+ this.tracer.startActiveSpan("ws.reconnect", {
112
+ kind: SpanKind.CLIENT,
113
+ attributes: {
114
+ ...MESSAGING_ATTRS,
115
+ "ws.reconnect_attempt": attempt,
116
+ },
117
+ }, (span) => {
118
+ span.end();
119
+ });
120
+ }
121
+ // ------------------------------------------------------------------
122
+ // Outbound
123
+ // ------------------------------------------------------------------
124
+ /**
125
+ * Injects W3C trace context into the message's request envelope.
126
+ * Call this on every outbound message before handing it to the transport.
127
+ *
128
+ * Mirrors the server-side TracedSocket.decorateToSend() behaviour so that
129
+ * the server can extract the browser's active context via propagation.extract.
130
+ */
131
+ decorateOutbound(message) {
132
+ if (!message.request) {
133
+ return message;
134
+ }
135
+ // Skip if already injected (e.g. manual traceparent for testing)
136
+ if (message.request.traceparent || message.request.tracestate) {
137
+ return message;
138
+ }
139
+ propagation.inject(otelCtx.active(), message.request);
140
+ return message;
141
+ }
142
+ /**
143
+ * Creates a CLIENT span for a browser-initiated RPC call.
144
+ * Returns the span so the caller can end it after the response resolves.
145
+ *
146
+ * Usage:
147
+ * ```typescript
148
+ * const span = socket.traceOutboundCall("editor.runApi");
149
+ * const result = await socket.request("editor.runApi", params);
150
+ * span.end();
151
+ * ```
152
+ */
153
+ traceOutboundCall(method) {
154
+ return this.tracer.startActiveSpan(`WS CLIENT ${method}`, {
155
+ kind: SpanKind.CLIENT,
156
+ attributes: {
157
+ ...MESSAGING_ATTRS,
158
+ "ws.method": method,
159
+ },
160
+ }, (span) => span);
161
+ }
162
+ // ------------------------------------------------------------------
163
+ // Inbound
164
+ // ------------------------------------------------------------------
165
+ /**
166
+ * Handles an inbound message from the server.
167
+ * - Extracts the server's trace context from the request envelope.
168
+ * - Creates a SERVER span as a child of the server's trace so that
169
+ * server-initiated pushes appear in the browser's distributed trace.
170
+ * - Response-only messages (no request field) are ignored.
171
+ */
172
+ handleInbound(message) {
173
+ if (!message.request) {
174
+ return;
175
+ }
176
+ const method = message.request.method ?? "unknown";
177
+ const parentCtx = propagation.extract(ROOT_CONTEXT, message.request);
178
+ otelCtx.with(parentCtx, () => {
179
+ this.tracer.startActiveSpan(`WS SERVER ${method}`, {
180
+ kind: SpanKind.CONSUMER,
181
+ attributes: {
182
+ ...MESSAGING_ATTRS,
183
+ "ws.method": method,
184
+ },
185
+ }, (span) => {
186
+ span.end();
187
+ });
188
+ });
189
+ }
190
+ // ------------------------------------------------------------------
191
+ // Cleanup
192
+ // ------------------------------------------------------------------
193
+ /** Remove lifecycle listeners. Call when tearing down the socket. */
194
+ dispose() {
195
+ this.ws.removeEventListener("open", this.onOpen);
196
+ this.ws.removeEventListener("close", this.onClose);
197
+ }
198
+ }
199
+ //# sourceMappingURL=traced-socket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traced-socket.js","sourceRoot":"","sources":["../../src/browser/traced-socket.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Tier 2 Traces Contract (v0.6.0) — TypeScript mirror.
3
+ *
4
+ * THIS FILE IS A MIRROR, NOT THE SOURCE OF TRUTH. The canonical Tier 2 traces
5
+ * contract lives in the `engineering` repo:
6
+ * - engineering/projects/o11y-refactor/contracts/tier2-traces.v0.6.0.json (canonical contract)
7
+ * - engineering/projects/o11y-refactor/contracts/README.md (rationale, Versioning Policy, Review Checklist)
8
+ * Org-wide telemetry naming and the Tier 2 privacy boundary are documented in the
9
+ * `workspace` repo: workspace/docs/naming-conventions.md and the `observability`
10
+ * skill (.agents/skills/observability/SKILL.md).
11
+ *
12
+ * CHANGING TIER 2 BEHAVIOR (forbidden / hashed / dropped / allowed attributes):
13
+ * 1. Update the canonical JSON in `engineering` FIRST, as a NEW version, per the
14
+ * README Versioning Policy (breaking = MAJOR, additive = MINOR, docs = PATCH).
15
+ * 2. Propagate the SAME change to every mirror so they stay byte-for-byte aligned:
16
+ * - this file (TS SDK sanitizer / ESLint / guardrails)
17
+ * - orchestrator/pkg/telemetry/forbidden_attributes.go (Go SDK maps)
18
+ * - orchestrator/pkg/telemetry/contracts/tier2-traces.json (Go embedded; regenerate via
19
+ * orchestrator/scripts/sync-ts-telemetry-contracts.sh — do not hand-edit)
20
+ * Editing this file alone silently drifts from the contract and the other SDKs, which
21
+ * lets a re-cased or newly added attribute bypass the Tier 2 privacy boundary. Cross-surface
22
+ * parity is enforced by the orchestrator Go tests (TestForbiddenAttributesMatchTSContract,
23
+ * TestDroppedAttributesMatchTS).
24
+ *
25
+ * Used by: trace-sanitizer (which spans/attributes to export), lint/forbidden-attributes
26
+ * (ESLint), guardrails (dev-time warnings), and Collector config generation.
27
+ * "request handler *" is a local extension for Express instrumentation (not in the JSON).
28
+ */
29
+ import { DeploymentTypeEnum } from "@superblocksteam/shared";
30
+ export interface AttributeDefinition {
31
+ name: string;
32
+ allowedValues?: string[];
33
+ maxCardinality?: number;
34
+ type?: "string" | "number" | "boolean";
35
+ }
36
+ export type AllowedAttribute = string | AttributeDefinition;
37
+ export interface SpanDefinition {
38
+ name: string;
39
+ description?: string;
40
+ allowedAttributes: AllowedAttribute[];
41
+ alwaysSample?: boolean;
42
+ }
43
+ export declare function getAttributeName(attr: AllowedAttribute): string;
44
+ /**
45
+ * Span patterns from tier2-traces.v0.4.0.json.
46
+ * Suffix wildcard only: "HTTP POST *" matches "HTTP POST /api/..." or "POST /api/...".
47
+ */
48
+ export declare const TIER_2_TRACE_CONTRACT: SpanDefinition[];
49
+ /**
50
+ * Cloud trace contract: match-all span name ("*") so no spans are dropped by name.
51
+ * Attribute allowlist is not used when attributeAllowlistPassthrough is true.
52
+ */
53
+ export declare const CLOUD_TRACE_CONTRACT: SpanDefinition[];
54
+ /**
55
+ * Returns the trace contract (span definitions) for the given deployment type.
56
+ * Cloud: match-all so no traces are dropped by span name.
57
+ * Cloud-prem: Tier 2 contract (named spans only).
58
+ */
59
+ export declare function getTraceContract(deploymentType: DeploymentTypeEnum): SpanDefinition[];
60
+ /** Forbidden in Tier 2 (forbiddenAttributes in contract). Collector strips these entirely. */
61
+ export declare const FORBIDDEN_TIER_2_SPAN_ATTRIBUTES: string[];
62
+ /**
63
+ * Hashed (keyed HMAC) for Tier 2 (hashedAttributes in contract).
64
+ * v0.5.0 (AGENT-3255): per-user / per-session identifiers single out a natural
65
+ * person (pseudonymous personal data even as a UUID), so pseudonymize rather than
66
+ * forbid. This is the full contract hashedAttributes set: enduser.id, session.id,
67
+ * and the user-id variants. organization-id is intentionally NOT hashed (single
68
+ * customer org per cloud-prem deployment → pass-through).
69
+ * NOTE: with no hashConfig, TraceSanitizer.hashValue() emits "[redacted]", so
70
+ * these fail closed and never flow raw until an HMAC key is provisioned.
71
+ */
72
+ export declare const HASHED_TIER_2_SPAN_ATTRIBUTES: string[];
73
+ /**
74
+ * Dropped — high cardinality, no hash value (droppedAttributes in contract).
75
+ * The contract's dropped set also lists correlation/request/trace/execution ids,
76
+ * but those are dropped at the collector (and pass through at the SDK in
77
+ * pass-through mode); the SDK only hard-drops binding keys. v0.6.0 adds the
78
+ * dotted/kebab spellings of binding_keys for casing parity.
79
+ */
80
+ export declare const DROPPED_HIGH_CARDINALITY_ATTRIBUTES: string[];
81
+ export declare const TIER2_FORBIDDEN_ATTRIBUTES: Set<string>;
82
+ export declare const TIER2_HASHED_ATTRIBUTES: Set<string>;
83
+ export declare const TIER2_DROPPED_ATTRIBUTES: Set<string>;
84
+ /**
85
+ * Attribute sets and contract options used by TraceSanitizer.
86
+ * Allows different rules per deployment type (e.g. cloud vs cloud-prem).
87
+ */
88
+ export interface TraceSanitizerAttributeSets {
89
+ forbiddenAttributes: Set<string>;
90
+ droppedAttributes: Set<string>;
91
+ hashedAttributes: Set<string>;
92
+ /** Span definitions for name matching; cloud uses match-all ("*"). */
93
+ spanDefinitions: SpanDefinition[];
94
+ /** When true, span attributes are not filtered by allowedAttributes (pass-through). */
95
+ attributeAllowlistPassthrough: boolean;
96
+ }
97
+ /**
98
+ * Returns the Tier 2 trace attribute sets and contract options for the given deployment type.
99
+ * Cloud: relaxed policy (no attributes dropped/hashed), match-all span names, pass-through attributes.
100
+ * Cloud-prem: full Tier 2 contract (forbidden/dropped/hashed), named spans only, allowlist enforced.
101
+ */
102
+ export declare function getTraceSanitizerAttributeSets(deploymentType: DeploymentTypeEnum): TraceSanitizerAttributeSets;
103
+ /** Spans that should ALWAYS be sampled (samplingPolicy.alwaysSampleSpans in contract). */
104
+ export declare const ALWAYS_SAMPLE_SPANS: Set<string>;
105
+ /**
106
+ * Patterns that indicate forbidden content in attribute values (e.g. secrets in strings).
107
+ * No ^/$ anchors so they match secrets embedded anywhere.
108
+ * It's not used by TraceSanitizer, only in guardrails.
109
+ */
110
+ export declare const FORBIDDEN_VALUE_PATTERNS: RegExp[];
111
+ export declare function isForbiddenAttribute(name: string): boolean;
112
+ export declare function isHashedAttribute(name: string): boolean;
113
+ export declare function isDroppedAttribute(name: string): boolean;
114
+ export declare function containsForbiddenPattern(value: unknown): boolean;
115
+ export declare function shouldAlwaysSample(spanName: string): boolean;
116
+ //# sourceMappingURL=tier2-traces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tier2-traces.d.ts","sourceRoot":"","sources":["../../../src/common/contracts/tier2-traces.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAM7D,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;CACxC;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,mBAAmB,CAAC;AAE5D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;IACtC,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAE/D;AA0KD;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,cAAc,EA+TjD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,cAAc,EAEhD,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,cAAc,EAAE,kBAAkB,GACjC,cAAc,EAAE,CAQlB;AAMD,8FAA8F;AAC9F,eAAO,MAAM,gCAAgC,EAAE,MAAM,EAiEpD,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,6BAA6B,EAAE,MAAM,EAUjD,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mCAAmC,EAAE,MAAM,EAIvD,CAAC;AAMF,eAAO,MAAM,0BAA0B,aAEtC,CAAC;AACF,eAAO,MAAM,uBAAuB,aAAyC,CAAC;AAC9E,eAAO,MAAM,wBAAwB,aAEpC,CAAC;AASF;;;GAGG;AACH,MAAM,WAAW,2BAA2B;IAC1C,mBAAmB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACjC,iBAAiB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC/B,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,sEAAsE;IACtE,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,uFAAuF;IACvF,6BAA6B,EAAE,OAAO,CAAC;CACxC;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,cAAc,EAAE,kBAAkB,GACjC,2BAA2B,CAwB7B;AAMD,0FAA0F;AAC1F,eAAO,MAAM,mBAAmB,aAA2B,CAAC;AAE5D;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,UAYpC,CAAC;AAMF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAGhE;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE5D"}