@superblocksteam/telemetry 2.0.93 → 2.0.94-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/README.md +59 -44
  2. package/dist/browser/index.d.ts +2 -2
  3. package/dist/browser/resilient-exporter.d.ts.map +1 -1
  4. package/dist/browser/resilient-exporter.js.map +1 -1
  5. package/dist/common/contracts/tier2-traces.d.ts +62 -50
  6. package/dist/common/contracts/tier2-traces.d.ts.map +1 -1
  7. package/dist/common/contracts/tier2-traces.js +484 -138
  8. package/dist/common/contracts/tier2-traces.js.map +1 -1
  9. package/dist/common/guardrails.d.ts +2 -2
  10. package/dist/common/guardrails.d.ts.map +1 -1
  11. package/dist/common/guardrails.js +7 -7
  12. package/dist/common/guardrails.js.map +1 -1
  13. package/dist/common/log-sanitizer.d.ts +88 -0
  14. package/dist/common/log-sanitizer.d.ts.map +1 -1
  15. package/dist/common/log-sanitizer.js +304 -6
  16. package/dist/common/log-sanitizer.js.map +1 -1
  17. package/dist/common/resource.d.ts +4 -1
  18. package/dist/common/resource.d.ts.map +1 -1
  19. package/dist/common/resource.js +4 -2
  20. package/dist/common/resource.js.map +1 -1
  21. package/dist/common/trace-sanitizer.d.ts +82 -0
  22. package/dist/common/trace-sanitizer.d.ts.map +1 -0
  23. package/dist/common/trace-sanitizer.js +230 -0
  24. package/dist/common/trace-sanitizer.js.map +1 -0
  25. package/dist/index.d.ts +2 -1
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +16 -8
  28. package/dist/index.js.map +1 -1
  29. package/dist/lint/forbidden-attributes.d.ts +2 -2
  30. package/dist/lint/forbidden-attributes.d.ts.map +1 -1
  31. package/dist/lint/forbidden-attributes.js +41 -40
  32. package/dist/lint/forbidden-attributes.js.map +1 -1
  33. package/dist/lint/index.d.ts +1 -1
  34. package/dist/llmobs/index.d.ts +2 -2
  35. package/dist/llmobs/tier1-exporter.d.ts +2 -2
  36. package/dist/llmobs/tier1-exporter.d.ts.map +1 -1
  37. package/dist/llmobs/tier1-exporter.js +17 -14
  38. package/dist/llmobs/tier1-exporter.js.map +1 -1
  39. package/dist/llmobs/tier2-summarizer.d.ts.map +1 -1
  40. package/dist/llmobs/tier2-summarizer.js +10 -4
  41. package/dist/llmobs/tier2-summarizer.js.map +1 -1
  42. package/dist/node/exporters/resilient-exporter.d.ts +14 -0
  43. package/dist/node/exporters/resilient-exporter.d.ts.map +1 -1
  44. package/dist/node/exporters/resilient-exporter.js +8 -1
  45. package/dist/node/exporters/resilient-exporter.js.map +1 -1
  46. package/dist/node/index.d.ts +2 -1
  47. package/dist/node/index.d.ts.map +1 -1
  48. package/dist/node/index.js +7 -2
  49. package/dist/node/index.js.map +1 -1
  50. package/dist/node/init.d.ts.map +1 -1
  51. package/dist/node/init.js +61 -12
  52. package/dist/node/init.js.map +1 -1
  53. package/dist/node/log-processor.d.ts +41 -6
  54. package/dist/node/log-processor.d.ts.map +1 -1
  55. package/dist/node/log-processor.js +152 -61
  56. package/dist/node/log-processor.js.map +1 -1
  57. package/dist/node/metrics-client.d.ts.map +1 -1
  58. package/dist/node/metrics-client.js.map +1 -1
  59. package/dist/node/safe-logger.d.ts +55 -0
  60. package/dist/node/safe-logger.d.ts.map +1 -0
  61. package/dist/node/safe-logger.js +158 -0
  62. package/dist/node/safe-logger.js.map +1 -0
  63. package/dist/node/sanitizing-processor.d.ts +56 -0
  64. package/dist/node/sanitizing-processor.d.ts.map +1 -0
  65. package/dist/node/sanitizing-processor.js +124 -0
  66. package/dist/node/sanitizing-processor.js.map +1 -0
  67. package/dist/node/traced-socket.d.ts +47 -3
  68. package/dist/node/traced-socket.d.ts.map +1 -1
  69. package/dist/node/traced-socket.js +96 -19
  70. package/dist/node/traced-socket.js.map +1 -1
  71. package/dist/testing/in-memory-exporter.d.ts +3 -3
  72. package/dist/testing/in-memory-exporter.d.ts.map +1 -1
  73. package/dist/testing/in-memory-exporter.js +3 -1
  74. package/dist/testing/in-memory-exporter.js.map +1 -1
  75. package/dist/testing/index.d.ts +2 -2
  76. package/dist/types/index.d.ts +28 -1
  77. package/dist/types/index.d.ts.map +1 -1
  78. package/dist-esm/browser/index.d.ts +2 -2
  79. package/dist-esm/browser/index.js +2 -2
  80. package/dist-esm/browser/resilient-exporter.d.ts.map +1 -1
  81. package/dist-esm/browser/resilient-exporter.js.map +1 -1
  82. package/dist-esm/common/contracts/tier2-traces.d.ts +62 -50
  83. package/dist-esm/common/contracts/tier2-traces.d.ts.map +1 -1
  84. package/dist-esm/common/contracts/tier2-traces.js +480 -137
  85. package/dist-esm/common/contracts/tier2-traces.js.map +1 -1
  86. package/dist-esm/common/guardrails.d.ts +2 -2
  87. package/dist-esm/common/guardrails.d.ts.map +1 -1
  88. package/dist-esm/common/guardrails.js +9 -9
  89. package/dist-esm/common/guardrails.js.map +1 -1
  90. package/dist-esm/common/log-sanitizer.d.ts +88 -0
  91. package/dist-esm/common/log-sanitizer.d.ts.map +1 -1
  92. package/dist-esm/common/log-sanitizer.js +294 -5
  93. package/dist-esm/common/log-sanitizer.js.map +1 -1
  94. package/dist-esm/common/resource.d.ts +4 -1
  95. package/dist-esm/common/resource.d.ts.map +1 -1
  96. package/dist-esm/common/resource.js +3 -1
  97. package/dist-esm/common/resource.js.map +1 -1
  98. package/dist-esm/common/trace-sanitizer.d.ts +82 -0
  99. package/dist-esm/common/trace-sanitizer.d.ts.map +1 -0
  100. package/dist-esm/common/trace-sanitizer.js +226 -0
  101. package/dist-esm/common/trace-sanitizer.js.map +1 -0
  102. package/dist-esm/index.d.ts +2 -1
  103. package/dist-esm/index.d.ts.map +1 -1
  104. package/dist-esm/index.js +2 -1
  105. package/dist-esm/index.js.map +1 -1
  106. package/dist-esm/lint/forbidden-attributes.d.ts +2 -2
  107. package/dist-esm/lint/forbidden-attributes.d.ts.map +1 -1
  108. package/dist-esm/lint/forbidden-attributes.js +43 -42
  109. package/dist-esm/lint/forbidden-attributes.js.map +1 -1
  110. package/dist-esm/lint/index.d.ts +1 -1
  111. package/dist-esm/lint/index.js +1 -1
  112. package/dist-esm/llmobs/index.d.ts +2 -2
  113. package/dist-esm/llmobs/index.js +2 -2
  114. package/dist-esm/llmobs/tier1-exporter.d.ts +2 -2
  115. package/dist-esm/llmobs/tier1-exporter.d.ts.map +1 -1
  116. package/dist-esm/llmobs/tier1-exporter.js +18 -15
  117. package/dist-esm/llmobs/tier1-exporter.js.map +1 -1
  118. package/dist-esm/llmobs/tier2-summarizer.d.ts.map +1 -1
  119. package/dist-esm/llmobs/tier2-summarizer.js +10 -4
  120. package/dist-esm/llmobs/tier2-summarizer.js.map +1 -1
  121. package/dist-esm/node/exporters/resilient-exporter.d.ts +14 -0
  122. package/dist-esm/node/exporters/resilient-exporter.d.ts.map +1 -1
  123. package/dist-esm/node/exporters/resilient-exporter.js +8 -1
  124. package/dist-esm/node/exporters/resilient-exporter.js.map +1 -1
  125. package/dist-esm/node/index.d.ts +2 -1
  126. package/dist-esm/node/index.d.ts.map +1 -1
  127. package/dist-esm/node/index.js +2 -1
  128. package/dist-esm/node/index.js.map +1 -1
  129. package/dist-esm/node/init.d.ts.map +1 -1
  130. package/dist-esm/node/init.js +61 -12
  131. package/dist-esm/node/init.js.map +1 -1
  132. package/dist-esm/node/log-processor.d.ts +41 -6
  133. package/dist-esm/node/log-processor.d.ts.map +1 -1
  134. package/dist-esm/node/log-processor.js +151 -62
  135. package/dist-esm/node/log-processor.js.map +1 -1
  136. package/dist-esm/node/metrics-client.d.ts.map +1 -1
  137. package/dist-esm/node/metrics-client.js.map +1 -1
  138. package/dist-esm/node/safe-logger.d.ts +55 -0
  139. package/dist-esm/node/safe-logger.d.ts.map +1 -0
  140. package/dist-esm/node/safe-logger.js +154 -0
  141. package/dist-esm/node/safe-logger.js.map +1 -0
  142. package/dist-esm/node/sanitizing-processor.d.ts +56 -0
  143. package/dist-esm/node/sanitizing-processor.d.ts.map +1 -0
  144. package/dist-esm/node/sanitizing-processor.js +120 -0
  145. package/dist-esm/node/sanitizing-processor.js.map +1 -0
  146. package/dist-esm/node/traced-socket.d.ts +47 -3
  147. package/dist-esm/node/traced-socket.d.ts.map +1 -1
  148. package/dist-esm/node/traced-socket.js +96 -19
  149. package/dist-esm/node/traced-socket.js.map +1 -1
  150. package/dist-esm/testing/in-memory-exporter.d.ts +3 -3
  151. package/dist-esm/testing/in-memory-exporter.d.ts.map +1 -1
  152. package/dist-esm/testing/in-memory-exporter.js +4 -2
  153. package/dist-esm/testing/in-memory-exporter.js.map +1 -1
  154. package/dist-esm/testing/index.d.ts +2 -2
  155. package/dist-esm/testing/index.js +2 -2
  156. package/dist-esm/types/index.d.ts +28 -1
  157. package/dist-esm/types/index.d.ts.map +1 -1
  158. package/dist-esm/types/index.js +1 -1
  159. package/package.json +17 -18
@@ -1,185 +1,531 @@
1
1
  "use strict";
2
2
  /**
3
- * Tier 2 Traces Contract
3
+ * Tier 2 Traces Contract (v0.2.0)
4
4
  *
5
- * This file defines the Tier 2 telemetry contract:
6
- * - Forbidden attributes (removed by Collector)
7
- * - Hashed attributes (pseudonymized by Collector)
8
- * - Dropped attributes (removed by Collector)
9
- * - Forbidden value patterns (for lint-time detection)
5
+ * Single source of truth for Tier 2 sanitized trace telemetry.
6
+ * Mirrors: engineering/projects/o11y-refactor/contracts/tier2-traces.v0.2.0.json
10
7
  *
11
- * ENFORCEMENT: The OTEL Collector handles runtime enforcement.
12
- * These definitions are used for:
13
- * - ESLint rules (static analysis at CI time)
14
- * - Development warnings (guardrails.ts)
8
+ * Used by:
9
+ * - trace-sanitizer (SDK: which spans/attributes to export)
10
+ * - lint/forbidden-attributes (ESLint)
11
+ * - guardrails (dev-time warnings)
15
12
  * - Collector config generation
16
13
  *
17
- * See: obs/otel-collector/config-tiered.yaml
18
- * Source of truth: engineering/projects/o11y-refactor/contracts/tier2-traces.v0.3.0.json
14
+ * "request handler *" is a local extension for Express instrumentation (not in JSON).
19
15
  */
20
16
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.FORBIDDEN_VALUE_PATTERNS = exports.ALWAYS_SAMPLE_SPANS = exports.TIER2_DROPPED_ATTRIBUTES = exports.TIER2_HASHED_ATTRIBUTES = exports.TIER2_FORBIDDEN_ATTRIBUTES = void 0;
17
+ exports.FORBIDDEN_VALUE_PATTERNS = exports.ALWAYS_SAMPLE_SPANS = exports.TIER2_DROPPED_ATTRIBUTES = exports.TIER2_HASHED_ATTRIBUTES = exports.TIER2_FORBIDDEN_ATTRIBUTES = exports.DROPPED_HIGH_CARDINALITY_ATTRIBUTES = exports.HASHED_TIER_2_SPAN_ATTRIBUTES = exports.FORBIDDEN_TIER_2_SPAN_ATTRIBUTES = exports.CLOUD_TRACE_CONTRACT = exports.TIER_2_TRACE_CONTRACT = void 0;
18
+ exports.getAttributeName = getAttributeName;
19
+ exports.getTraceContract = getTraceContract;
20
+ exports.getTraceSanitizerAttributeSets = getTraceSanitizerAttributeSets;
22
21
  exports.isForbiddenAttribute = isForbiddenAttribute;
23
22
  exports.isHashedAttribute = isHashedAttribute;
24
23
  exports.isDroppedAttribute = isDroppedAttribute;
25
24
  exports.containsForbiddenPattern = containsForbiddenPattern;
26
25
  exports.shouldAlwaysSample = shouldAlwaysSample;
26
+ const shared_1 = require("@superblocksteam/shared");
27
+ function getAttributeName(attr) {
28
+ return typeof attr === "string" ? attr : attr.name;
29
+ }
27
30
  /**
28
- * Attributes that are FORBIDDEN in Tier 2 telemetry.
29
- * These contain sensitive data that should never leave the customer's environment.
30
- * The Collector strips these entirely (not hashed, not present in Tier 2).
31
+ * Span patterns from tier2-traces.v0.2.0.json.
32
+ * Suffix wildcard only: "HTTP POST *" matches "HTTP POST /api/..." or "POST /api/...".
31
33
  */
32
- exports.TIER2_FORBIDDEN_ATTRIBUTES = new Set([
33
- // LLM/AI content
34
- 'llmobs.input',
35
- 'llmobs.output',
36
- 'prompt',
37
- 'code',
38
- 'tool_input',
39
- 'tool_output',
40
- // File content
41
- 'file_path',
42
- 'file_content',
43
- // Database content
44
- 'db.statement',
45
- 'db.query_text',
46
- 'db.query.text',
47
- // HTTP bodies and URLs
48
- 'http.request.body',
49
- 'http.response.body',
50
- 'url.full',
51
- 'url.query',
52
- 'http.url',
53
- 'http.target',
54
- // Resource identifiers (names are customer-specific)
55
- 'api-id',
56
- 'api_id',
57
- 'api-name',
58
- 'api_name',
59
- 'resource-id',
60
- 'resource_id',
61
- 'resource-name',
62
- 'resource_name',
63
- 'integration-id',
64
- 'integration_id',
65
- 'widget-type',
66
- 'branch',
67
- 'commit-id',
68
- 'commit_id',
69
- 'profile-id',
70
- 'profile_id',
71
- // Stack traces
72
- 'error.stack',
73
- 'exception.stacktrace',
74
- // Auth/secrets
75
- 'auth_token',
76
- 'api_key',
77
- 'authorization',
78
- 'cookie',
79
- 'x-api-key',
80
- ]);
34
+ exports.TIER_2_TRACE_CONTRACT = [
35
+ {
36
+ name: "HTTP GET *",
37
+ allowedAttributes: [
38
+ "http.method",
39
+ { name: "http.route", maxCardinality: 150 },
40
+ "http.status_code",
41
+ "http.response_content_length",
42
+ { name: "http.flavor", allowedValues: ["1.0", "1.1", "2.0", "3.0"] },
43
+ ],
44
+ },
45
+ {
46
+ name: "HTTP POST *",
47
+ allowedAttributes: [
48
+ "http.method",
49
+ { name: "http.route", maxCardinality: 150 },
50
+ "http.status_code",
51
+ "http.response_content_length",
52
+ "http.request_content_length",
53
+ { name: "http.flavor", allowedValues: ["1.0", "1.1", "2.0", "3.0"] },
54
+ ],
55
+ },
56
+ {
57
+ name: "HTTP PUT *",
58
+ allowedAttributes: [
59
+ "http.method",
60
+ { name: "http.route", maxCardinality: 150 },
61
+ "http.status_code",
62
+ "http.response_content_length",
63
+ "http.request_content_length",
64
+ ],
65
+ },
66
+ {
67
+ name: "HTTP DELETE *",
68
+ allowedAttributes: [
69
+ "http.method",
70
+ { name: "http.route", maxCardinality: 150 },
71
+ "http.status_code",
72
+ "http.response_content_length",
73
+ ],
74
+ },
75
+ {
76
+ name: "HTTP PATCH *",
77
+ allowedAttributes: [
78
+ "http.method",
79
+ { name: "http.route", maxCardinality: 150 },
80
+ "http.status_code",
81
+ "http.response_content_length",
82
+ "http.request_content_length",
83
+ ],
84
+ },
85
+ {
86
+ name: "request handler *",
87
+ allowedAttributes: [
88
+ "http.method",
89
+ { name: "http.route", maxCardinality: 150 },
90
+ "http.status_code",
91
+ "http.response_content_length",
92
+ "http.request_content_length",
93
+ { name: "http.flavor", allowedValues: ["1.0", "1.1", "2.0", "3.0"] },
94
+ "express.route",
95
+ ],
96
+ },
97
+ {
98
+ name: "WS SERVER *",
99
+ allowedAttributes: [
100
+ { name: "messaging.system", allowedValues: ["ws", "websocket"] },
101
+ { name: "messaging.destination_kind", allowedValues: ["websocket"] },
102
+ { name: "ws.handler", maxCardinality: 80 },
103
+ ],
104
+ },
105
+ {
106
+ name: "WS CLIENT *",
107
+ allowedAttributes: [
108
+ { name: "messaging.system", allowedValues: ["ws", "websocket"] },
109
+ ],
110
+ },
111
+ {
112
+ name: "WS HANDLER *",
113
+ allowedAttributes: [
114
+ { name: "messaging.system", allowedValues: ["ws", "websocket"] },
115
+ { name: "messaging.destination_kind", allowedValues: ["websocket"] },
116
+ ],
117
+ },
118
+ {
119
+ name: "api.execute",
120
+ alwaysSample: true,
121
+ allowedAttributes: [
122
+ { name: "view-mode", allowedValues: ["edit", "deployed", "preview"] },
123
+ {
124
+ name: "api.status",
125
+ allowedValues: ["success", "error", "timeout", "cancelled"],
126
+ },
127
+ { name: "api.type", allowedValues: ["api", "workflow", "scheduled_job"] },
128
+ { name: "api.step_count", type: "number" },
129
+ { name: "api.duration_ms", type: "number" },
130
+ { name: "remote", allowedValues: ["true", "false"] },
131
+ "otel.status_code",
132
+ "otel.status_description",
133
+ ],
134
+ },
135
+ {
136
+ name: "api.step",
137
+ allowedAttributes: [
138
+ { name: "step.type", maxCardinality: 50 },
139
+ { name: "step.status", allowedValues: ["success", "error"] },
140
+ { name: "step.duration_ms", type: "number" },
141
+ { name: "step.retry_count", type: "number" },
142
+ "otel.status_code",
143
+ ],
144
+ },
145
+ {
146
+ name: "api.block.*",
147
+ allowedAttributes: [
148
+ { name: "block.type", maxCardinality: 30 },
149
+ { name: "block.status", allowedValues: ["success", "error"] },
150
+ ],
151
+ },
152
+ {
153
+ name: "plugin.*",
154
+ allowedAttributes: [
155
+ { name: "plugin.name", maxCardinality: 80 },
156
+ {
157
+ name: "plugin.event",
158
+ allowedValues: ["execute", "test", "metadata", "pre_delete"],
159
+ },
160
+ { name: "plugin.result", allowedValues: ["succeeded", "failed"] },
161
+ { name: "plugin.duration_ms", type: "number" },
162
+ "otel.status_code",
163
+ ],
164
+ },
165
+ {
166
+ name: "db.*",
167
+ allowedAttributes: [
168
+ {
169
+ name: "db.system",
170
+ allowedValues: [
171
+ "postgresql",
172
+ "mysql",
173
+ "mssql",
174
+ "mongodb",
175
+ "redis",
176
+ "snowflake",
177
+ "bigquery",
178
+ "databricks",
179
+ "dynamodb",
180
+ "sqlite",
181
+ ],
182
+ },
183
+ {
184
+ name: "db.operation",
185
+ allowedValues: ["select", "insert", "update", "delete", "other"],
186
+ },
187
+ { name: "db.name", maxCardinality: 50 },
188
+ "otel.status_code",
189
+ ],
190
+ },
191
+ {
192
+ name: "llm.request",
193
+ allowedAttributes: [
194
+ {
195
+ name: "gen_ai.operation.name",
196
+ allowedValues: [
197
+ "chat",
198
+ "text_completion",
199
+ "embeddings",
200
+ "execute_tool",
201
+ "invoke_agent",
202
+ "generate_content",
203
+ ],
204
+ },
205
+ {
206
+ name: "gen_ai.system",
207
+ allowedValues: [
208
+ "openai",
209
+ "anthropic",
210
+ "aws.bedrock",
211
+ "azure.ai.openai",
212
+ "azure.ai.inference",
213
+ "gcp.gemini",
214
+ "gcp.vertex_ai",
215
+ "cohere",
216
+ "mistral_ai",
217
+ "deepseek",
218
+ "groq",
219
+ ],
220
+ },
221
+ {
222
+ name: "gen_ai.provider.name",
223
+ allowedValues: [
224
+ "openai",
225
+ "anthropic",
226
+ "aws.bedrock",
227
+ "azure.ai.openai",
228
+ "azure.ai.inference",
229
+ "gcp.gemini",
230
+ "gcp.vertex_ai",
231
+ "cohere",
232
+ "mistral_ai",
233
+ "deepseek",
234
+ "groq",
235
+ ],
236
+ },
237
+ { name: "gen_ai.request.model", maxCardinality: 50 },
238
+ { name: "gen_ai.response.model", maxCardinality: 50 },
239
+ "llm.provider",
240
+ "llm.model",
241
+ "llm.status",
242
+ {
243
+ name: "llm.error_category",
244
+ allowedValues: [
245
+ "none",
246
+ "rate_limit",
247
+ "context_length",
248
+ "content_filter",
249
+ "quota",
250
+ "network",
251
+ "timeout",
252
+ "auth_error",
253
+ "api_error",
254
+ "validation_error",
255
+ "aborted",
256
+ "unknown",
257
+ ],
258
+ },
259
+ "llm.duration_ms",
260
+ "gen_ai.usage.input_tokens",
261
+ "gen_ai.usage.output_tokens",
262
+ "llm.input_tokens",
263
+ "llm.output_tokens",
264
+ "llm.total_tokens",
265
+ "llm.reasoning_tokens",
266
+ "llm.cached_tokens",
267
+ "llm.cost_usd",
268
+ { name: "gen_ai.client.time_to_first_token", type: "number" },
269
+ { name: "llm.time_to_first_token_ms", type: "number" },
270
+ "gen_ai.response.finish_reasons",
271
+ "llm.finish_reason",
272
+ "otel.status_code",
273
+ ],
274
+ },
275
+ {
276
+ name: "llm.tool_call",
277
+ allowedAttributes: [
278
+ { name: "tool.name", maxCardinality: 50 },
279
+ { name: "tool.status", allowedValues: ["success", "error"] },
280
+ {
281
+ name: "tool.error_category",
282
+ allowedValues: [
283
+ "none",
284
+ "timeout",
285
+ "execution_error",
286
+ "validation_error",
287
+ "permission_denied",
288
+ "not_found",
289
+ "unknown",
290
+ ],
291
+ },
292
+ { name: "tool.duration_ms", type: "number" },
293
+ "otel.status_code",
294
+ ],
295
+ },
296
+ {
297
+ name: "ai.streamText",
298
+ allowedAttributes: [
299
+ "llm.provider",
300
+ "llm.model",
301
+ "llm.total_tokens",
302
+ "llm.step_count",
303
+ ],
304
+ },
305
+ {
306
+ name: "ai.streamText.step",
307
+ allowedAttributes: [
308
+ { name: "step.number", type: "number" },
309
+ {
310
+ name: "step.type",
311
+ allowedValues: ["text", "tool_call", "thinking", "reasoning"],
312
+ },
313
+ ],
314
+ },
315
+ {
316
+ name: "clark.session",
317
+ allowedAttributes: [
318
+ "session.duration_ms",
319
+ "session.step_count",
320
+ "session.llm_call_count",
321
+ "session.tool_call_count",
322
+ "session.total_tokens",
323
+ {
324
+ name: "session.outcome",
325
+ allowedValues: ["success", "error", "aborted"],
326
+ },
327
+ ],
328
+ },
329
+ {
330
+ name: "clark.debug_loop",
331
+ allowedAttributes: [
332
+ { name: "loop.iteration", type: "number" },
333
+ {
334
+ name: "loop.reason",
335
+ allowedValues: ["error_recovery", "validation_failure", "retry"],
336
+ },
337
+ { name: "loop.duration_ms", type: "number" },
338
+ ],
339
+ },
340
+ {
341
+ name: "grpc.*",
342
+ allowedAttributes: [
343
+ { name: "rpc.system", allowedValues: ["grpc"] },
344
+ { name: "rpc.service", maxCardinality: 50 },
345
+ { name: "rpc.method", maxCardinality: 100 },
346
+ { name: "rpc.grpc.status_code", type: "number" },
347
+ ],
348
+ },
349
+ {
350
+ name: "kafka.*",
351
+ allowedAttributes: [
352
+ { name: "messaging.system", allowedValues: ["kafka"] },
353
+ { name: "messaging.destination", maxCardinality: 50 },
354
+ {
355
+ name: "messaging.operation",
356
+ allowedValues: ["publish", "receive", "process"],
357
+ },
358
+ ],
359
+ },
360
+ {
361
+ name: "redis.*",
362
+ allowedAttributes: [
363
+ { name: "db.system", allowedValues: ["redis"] },
364
+ { name: "db.operation", maxCardinality: 30 },
365
+ ],
366
+ },
367
+ {
368
+ name: "fetch",
369
+ allowedAttributes: [
370
+ "http.method",
371
+ "http.status_code",
372
+ { name: "http.host", maxCardinality: 200 },
373
+ ],
374
+ },
375
+ {
376
+ name: "schedule.*",
377
+ allowedAttributes: [
378
+ {
379
+ name: "schedule.type",
380
+ allowedValues: ["cron", "interval", "one_time"],
381
+ },
382
+ {
383
+ name: "schedule.status",
384
+ allowedValues: ["success", "error", "skipped"],
385
+ },
386
+ ],
387
+ },
388
+ ];
81
389
  /**
82
- * Attributes that should be HASHED (pseudonymized) in Tier 2 telemetry.
83
- * The Collector replaces these with SHA256 hashes for privacy.
84
- * Hashes enable aggregate analysis without exposing plaintext identifiers.
85
- *
86
- * Mapping:
87
- * user-email, user.email, etc. → user.hash
88
- * organization-id, organization_id → organization.hash
89
- * application-id, application_id → application.hash
90
- * session.id → session.hash
91
- * enduser.id → enduser.pseudo.id
390
+ * Cloud trace contract: match-all span name ("*") so no spans are dropped by name.
391
+ * Attribute allowlist is not used when attributeAllowlistPassthrough is true.
92
392
  */
93
- exports.TIER2_HASHED_ATTRIBUTES = new Set([
94
- // User identity (hashed to user.hash)
95
- 'user-email',
96
- 'user.email',
97
- 'user_email',
98
- 'user.id',
99
- 'enduser.email',
100
- // Organization identity (hashed to organization.hash)
101
- 'organization-id',
102
- 'organization_id',
103
- // Application identity (hashed to application.hash)
104
- 'application-id',
105
- 'application_id',
106
- // Session/enduser identity
107
- 'session.id',
108
- 'enduser.id',
109
- ]);
393
+ exports.CLOUD_TRACE_CONTRACT = [
394
+ { name: "*", allowedAttributes: [] },
395
+ ];
110
396
  /**
111
- * Attributes that should be DROPPED entirely in Tier 2.
112
- * These are correlation IDs that don't provide operational value.
397
+ * Returns the trace contract (span definitions) for the given deployment type.
398
+ * Cloud: match-all so no traces are dropped by span name.
399
+ * Cloud-prem: Tier 2 contract (named spans only).
113
400
  */
114
- exports.TIER2_DROPPED_ATTRIBUTES = new Set([
115
- 'correlation-id',
116
- 'correlation_id',
117
- 'request-id',
118
- 'request_id',
119
- 'trace-id',
120
- 'execution_id',
121
- 'binding_keys',
122
- ]);
401
+ function getTraceContract(deploymentType) {
402
+ switch (deploymentType) {
403
+ case shared_1.DeploymentTypeEnum.CLOUD:
404
+ return exports.CLOUD_TRACE_CONTRACT;
405
+ case shared_1.DeploymentTypeEnum.CLOUD_PREM:
406
+ default:
407
+ return exports.TIER_2_TRACE_CONTRACT;
408
+ }
409
+ }
410
+ // ---------------------------------------------------------------------------
411
+ // Forbidden / hashed / dropped attribute names (v0.2.0 JSON)
412
+ // ---------------------------------------------------------------------------
413
+ /** Forbidden in Tier 2 (forbiddenAttributes in contract). Collector strips these entirely. */
414
+ exports.FORBIDDEN_TIER_2_SPAN_ATTRIBUTES = [
415
+ "llmobs.input",
416
+ "llmobs.output",
417
+ "prompt",
418
+ "code",
419
+ "tool_input",
420
+ "tool_output",
421
+ "file_path",
422
+ "file_content",
423
+ "db.statement",
424
+ "db.query_text",
425
+ "db.query.text",
426
+ "http.request.body",
427
+ "http.response.body",
428
+ "url.full",
429
+ "url.query",
430
+ "http.url",
431
+ "http.target",
432
+ "user-email",
433
+ "user.email",
434
+ "user_email",
435
+ "enduser.email",
436
+ "api-name",
437
+ "api_name",
438
+ "resource-name",
439
+ "resource_name",
440
+ "widget-type",
441
+ "branch",
442
+ "error.stack",
443
+ "exception.stacktrace",
444
+ "auth_token",
445
+ "api_key",
446
+ "authorization",
447
+ "cookie",
448
+ "x-api-key",
449
+ ];
450
+ /** Hashed (keyed HMAC) for Tier 2 (hashedAttributes in contract). */
451
+ exports.HASHED_TIER_2_SPAN_ATTRIBUTES = [];
452
+ /** Dropped — high cardinality, no hash value (droppedAttributes in contract). */
453
+ exports.DROPPED_HIGH_CARDINALITY_ATTRIBUTES = ["binding_keys"];
454
+ // ---------------------------------------------------------------------------
455
+ // Set views (for lint, guardrails: fast .has() lookup)
456
+ // ---------------------------------------------------------------------------
457
+ exports.TIER2_FORBIDDEN_ATTRIBUTES = new Set(exports.FORBIDDEN_TIER_2_SPAN_ATTRIBUTES);
458
+ exports.TIER2_HASHED_ATTRIBUTES = new Set(exports.HASHED_TIER_2_SPAN_ATTRIBUTES);
459
+ exports.TIER2_DROPPED_ATTRIBUTES = new Set(exports.DROPPED_HIGH_CARDINALITY_ATTRIBUTES);
460
+ // ---------------------------------------------------------------------------
461
+ // Per-deployment attribute sets (for trace-sanitizer)
462
+ // ---------------------------------------------------------------------------
463
+ /** Empty set used for cloud (relaxed policy: no drop, no hash, no forbidden). */
464
+ const EMPTY_ATTRIBUTE_SET = new Set();
123
465
  /**
124
- * Spans that should ALWAYS be sampled (never dropped by rate limiting).
466
+ * Returns the Tier 2 trace attribute sets and contract options for the given deployment type.
467
+ * Cloud: relaxed policy (no attributes dropped/hashed), match-all span names, pass-through attributes.
468
+ * Cloud-prem: full Tier 2 contract (forbidden/dropped/hashed), named spans only, pass-through attributes.
125
469
  */
126
- exports.ALWAYS_SAMPLE_SPANS = new Set([
127
- 'api.execute',
128
- ]);
470
+ function getTraceSanitizerAttributeSets(deploymentType) {
471
+ const spanDefinitions = getTraceContract(deploymentType);
472
+ const attributeAllowlistPassthrough = true;
473
+ switch (deploymentType) {
474
+ case shared_1.DeploymentTypeEnum.CLOUD:
475
+ return {
476
+ forbiddenAttributes: EMPTY_ATTRIBUTE_SET,
477
+ droppedAttributes: EMPTY_ATTRIBUTE_SET,
478
+ hashedAttributes: EMPTY_ATTRIBUTE_SET,
479
+ spanDefinitions,
480
+ attributeAllowlistPassthrough,
481
+ };
482
+ case shared_1.DeploymentTypeEnum.CLOUD_PREM:
483
+ default:
484
+ return {
485
+ forbiddenAttributes: exports.TIER2_FORBIDDEN_ATTRIBUTES,
486
+ droppedAttributes: exports.TIER2_DROPPED_ATTRIBUTES,
487
+ hashedAttributes: exports.TIER2_HASHED_ATTRIBUTES,
488
+ spanDefinitions,
489
+ attributeAllowlistPassthrough,
490
+ };
491
+ }
492
+ }
493
+ // ---------------------------------------------------------------------------
494
+ // Always-sample and value patterns (v0.2.0 samplingPolicy + lint-time)
495
+ // ---------------------------------------------------------------------------
496
+ /** Spans that should ALWAYS be sampled (samplingPolicy.alwaysSampleSpans in contract). */
497
+ exports.ALWAYS_SAMPLE_SPANS = new Set(["api.execute"]);
129
498
  /**
130
- * Patterns that indicate forbidden content in attribute values.
131
- * Used for secondary filtering when attribute names aren't explicit.
132
- *
133
- * IMPORTANT: Patterns should NOT use ^ and $ anchors so they match
134
- * secrets embedded anywhere in a string (e.g., in query params, headers).
499
+ * Patterns that indicate forbidden content in attribute values (e.g. secrets in strings).
500
+ * No ^/$ anchors so they match secrets embedded anywhere.
501
+ * It's not used by TraceSanitizer, only in guardrails.
135
502
  */
136
503
  exports.FORBIDDEN_VALUE_PATTERNS = [
137
- // JWT tokens (anywhere in string)
138
- // Header (eyJ...) and payload (eyJ...) must be base64url encoded JSON
139
- // Signature can be any length (even short for test tokens)
140
504
  /eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]+/,
141
- // API keys (sk-/pk- prefix patterns with word boundaries)
142
505
  /\b(sk|pk)-[a-zA-Z0-9]{32,}\b/,
143
- // Bearer tokens (anywhere in string)
144
506
  /Bearer\s+[A-Za-z0-9._-]{20,}/,
145
- // PEM blocks (anywhere in string)
146
507
  /-----BEGIN\s+(RSA\s+)?(PRIVATE|PUBLIC)\s+KEY-----/,
147
- // AWS access key IDs
148
508
  /\bAKIA[A-Z0-9]{16}\b/,
149
- // GitHub tokens
150
509
  /\b(ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{36,}\b/,
151
- // Generic API key patterns (key=value or key:value with long alphanumeric)
152
510
  /\b(api[_-]?key|apikey|secret[_-]?key|access[_-]?token)[=:]\s*[A-Za-z0-9_-]{20,}\b/i,
153
511
  ];
154
- /**
155
- * Check if an attribute name is forbidden in Tier 2.
156
- */
512
+ // ---------------------------------------------------------------------------
513
+ // Helpers (for lint, guardrails)
514
+ // ---------------------------------------------------------------------------
157
515
  function isForbiddenAttribute(name) {
158
516
  return exports.TIER2_FORBIDDEN_ATTRIBUTES.has(name);
159
517
  }
160
- /**
161
- * Check if an attribute should be hashed in Tier 2.
162
- */
163
518
  function isHashedAttribute(name) {
164
519
  return exports.TIER2_HASHED_ATTRIBUTES.has(name);
165
520
  }
166
- /**
167
- * Check if an attribute should be dropped in Tier 2.
168
- */
169
521
  function isDroppedAttribute(name) {
170
522
  return exports.TIER2_DROPPED_ATTRIBUTES.has(name);
171
523
  }
172
- /**
173
- * Check if a value contains forbidden patterns (like tokens, keys).
174
- */
175
524
  function containsForbiddenPattern(value) {
176
- if (typeof value !== 'string')
525
+ if (typeof value !== "string")
177
526
  return false;
178
- return exports.FORBIDDEN_VALUE_PATTERNS.some(pattern => pattern.test(value));
527
+ return exports.FORBIDDEN_VALUE_PATTERNS.some((pattern) => pattern.test(value));
179
528
  }
180
- /**
181
- * Check if a span should always be sampled.
182
- */
183
529
  function shouldAlwaysSample(spanName) {
184
530
  return exports.ALWAYS_SAMPLE_SPANS.has(spanName);
185
531
  }